diff --git a/.gitignore b/.gitignore
index b137d67..568c479 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,8 @@
-# Ignore
-.directory
-*.pyc
-*.zip
-*.sh
-# Not Ignore
-!create_zip_plugin.sh
-
+# Ignore
+.directory
+*.pyc
+*.zip
+*.sh
+# Not Ignore
+!create_zip_plugin.sh
+
diff --git a/LICENSE b/LICENSE
index d6a9326..c0f8284 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,340 +1,340 @@
-GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- {signature of Ty Coon}, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
-
+GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ {description}
+ Copyright (C) {year} {fullname}
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ {signature of Ty Coon}, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
diff --git a/README.md b/README.md
index 97ff18d..29b83cd 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,24 @@
-
-[mapbiomas_logo]: https://k6f2r3a6.stackpathcdn.com/wp-content/uploads/2018/04/C%C3%B3pia-de-mapbiomas_IV%C6%92_a-01.png
-
-![][mapbiomas_logo]
-[MapBiomas](http://mapbiomas.org/)
-
-# MapBiomas Collection Plugin QGIS
-
-This plugin lets you get collection of mapping from MapBiomas Project.
-
-## Author
-Luiz Motta
-
-## Changelog
-- 2020-03-25
-Changed Docwidget to WidgetProvider(legend)
-- 2019-09-05
-Add set for collection layer
-- 2019-08-30
-Update metadata and added collection number
-- 2019-08-29
-Start of plugin
+
+[mapbiomas_logo]: https://k6f2r3a6.stackpathcdn.com/wp-content/uploads/2018/04/C%C3%B3pia-de-mapbiomas_IV%C6%92_a-01.png
+
+![][mapbiomas_logo]
+[MapBiomas](http://mapbiomas.org/)
+
+# MapBiomas Collection Plugin QGIS
+
+This plugin lets you get collection of mapping from MapBiomas Project.
+
+## Author
+Luiz Motta, Luiz Cortinhas
+
+## Changelog
+- 2020-11-26
+Updated to new Map Server and SLD style
+- 2020-03-25
+Changed Docwidget to WidgetProvider(legend)
+- 2019-09-05
+Add set for collection layer
+- 2019-08-30
+Update metadata and added collection number
+- 2019-08-29
+Start of plugin
diff --git a/__init__.py b/__init__.py
index 0c01001..b1be37d 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,70 +1,69 @@
-# -*- coding: utf-8 -*-
-"""
-/***************************************************************************
-Name : MapBiomas Collection
-Description : This plugin lets you get collection of mapping from MapBiomas Project(http://mapbiomas.org/).
-Date : August, 2019
-copyright : (C) 2019 by Luiz Motta
-email : motta.luiz@gmail.com
-
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-"""
-__author__ = 'Luiz Motta'
-__date__ = '2019-08-28'
-__copyright__ = '(C) 2019, Luiz Motta'
-__revision__ = '$Format:%H$'
-
-
-import os
-
-from qgis.PyQt.QtCore import QObject, pyqtSlot
-from qgis.PyQt.QtGui import QIcon
-from qgis.PyQt.QtWidgets import QAction
-
-from .mapbiomascollection import MapBiomasCollection
-
-def classFactory(iface):
- return MapbiomasCollectionPlugin( iface )
-
-class MapbiomasCollectionPlugin(QObject):
- def __init__(self, iface=None):
- super().__init__()
- self.iface = iface
- self.name = u"&MapbiomasCollection"
- self.mbc = MapBiomasCollection( iface )
-
- def initGui(self):
- name = "Mapbiomas Collection"
- about = 'Add a MapBiomas collection'
- icon = QIcon( os.path.join( os.path.dirname(__file__), 'mapbiomas.svg' ) )
- self.action = QAction( icon, name, self.iface.mainWindow() )
- self.action.setObjectName( name.replace(' ', '') )
- self.action.setWhatsThis( about )
- self.action.setStatusTip( about )
- self.action.triggered.connect( self.run )
-
- self.iface.addToolBarIcon( self.action )
- self.iface.addPluginToMenu( self.name, self.action )
-
- self.mbc.register()
-
- def unload(self):
- self.iface.removeToolBarIcon( self.action )
- self.iface.removePluginMenu( self.name, self.action )
- del self.action
- if not self.mbc:
- del self.mbc
-
- @pyqtSlot()
- def run(self):
- self.mbc.run()
+# -*- coding: utf-8 -*-
+"""
+/***************************************************************************
+Name : MapBiomas Collection
+Description : This plugin lets you get collection of mapping from MapBiomas Project(http://mapbiomas.org/).
+Date : August, 2020
+copyright : (C) 2019 by Luiz Motta, Updated by Luiz Cortinhas (2020)
+email : motta.luiz@gmail.com, luiz.cortinhas@solved.eco.br
+
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+"""
+__author__ = 'Luiz Cortinhas, Luiz Motta'
+__date__ = '2021-02-11'
+__copyright__ = '(C) 2021, Luiz Cortinhas (Fork: 2019, Luiz Motta)'
+__revision__ = '$Format:%H$'
+
+import os
+
+from qgis.PyQt.QtCore import QObject, pyqtSlot
+from qgis.PyQt.QtGui import QIcon
+from qgis.PyQt.QtWidgets import QAction
+
+from .mapbiomascollection import MapBiomasCollection
+
+def classFactory(iface):
+ return MapbiomasCollectionPlugin( iface )
+
+class MapbiomasCollectionPlugin(QObject):
+ def __init__(self, iface=None):
+ super().__init__()
+ self.iface = iface
+ self.name = u"&MapbiomasCollection"
+ self.mbc = MapBiomasCollection( iface )
+
+ def initGui(self):
+ name = "Mapbiomas Collection"
+ about = 'Add a MapBiomas collection'
+ icon = QIcon( os.path.join( os.path.dirname(__file__), 'mapbiomas.svg' ) )
+ self.action = QAction( icon, name, self.iface.mainWindow() )
+ self.action.setObjectName( name.replace(' ', '') )
+ self.action.setWhatsThis( about )
+ self.action.setStatusTip( about )
+ self.action.triggered.connect( self.run )
+
+ self.iface.addToolBarIcon( self.action )
+ self.iface.addPluginToMenu( self.name, self.action )
+
+ self.mbc.register()
+
+ def unload(self):
+ self.iface.removeToolBarIcon( self.action )
+ self.iface.removePluginMenu( self.name, self.action )
+ del self.action
+ if not self.mbc:
+ del self.mbc
+
+ @pyqtSlot()
+ def run(self):
+ self.mbc.run()
\ No newline at end of file
diff --git a/create_zip_plugin.sh b/create_zip_plugin.sh
index 87e2dde..c014263 100755
--- a/create_zip_plugin.sh
+++ b/create_zip_plugin.sh
@@ -1,12 +1,10 @@
-#!/bin/bash
-plugin_dir=$( basename $( pwd ) )
-if [ -f "./$plugin_dir.zip" ]; then
- rm "./$plugin_dir.zip"
-fi
-mkdir "./$plugin_dir"
-cp *.py "./$plugin_dir"
-for item in metadata.txt LICENSE mapbiomas.svg *.json; do cp "./$item" "./$plugin_dir"; done
-zip -r $plugin_dir $plugin_dir
-rm -r $plugin_dir
-#
-kdialog --msgbox "Zip file created: "$plugin_dir".zip"
+#/bin/bash
+plugin_dir=$( basename $( pwd ) )
+if [ -f "./$plugin_dir.zip" ]; then
+ rm "./$plugin_dir.zip"
+fi
+mkdir "./$plugin_dir"
+cp *.py "./$plugin_dir"
+for item in metadata.txt LICENSE mapbiomas.svg *.json; do cp "./$item" "./$plugin_dir"; done
+zip -r $plugin_dir $plugin_dir
+rm -r $plugin_dir
\ No newline at end of file
diff --git a/mapbiomas.svg b/mapbiomas.svg
index df304f3..54c39d9 100644
--- a/mapbiomas.svg
+++ b/mapbiomas.svg
@@ -1,59 +1,59 @@
-
-
+
+
diff --git a/mapbiomascollection.py b/mapbiomascollection.py
index 1382443..9228f15 100644
--- a/mapbiomascollection.py
+++ b/mapbiomascollection.py
@@ -1,346 +1,423 @@
-import os, time, json
-import urllib.parse
-
-from osgeo import gdal
-
-from qgis.PyQt.QtCore import (
- Qt, QSettings, QLocale,
- QObject, pyqtSlot, pyqtSignal
-)
-from qgis.PyQt.QtWidgets import (
- QWidget, QPushButton,
- QSlider, QLabel,
- QTreeWidget, QTreeWidgetItem,
- QVBoxLayout, QHBoxLayout
-)
-from qgis.PyQt.QtGui import (
- QColor, QPixmap, QIcon
-)
-
-from qgis.core import (
- QgsApplication, Qgis, QgsProject,
- QgsRasterLayer,
- QgsTask
-
-)
-from qgis.gui import QgsGui, QgsMessageBar, QgsLayerTreeEmbeddedWidgetProvider
-
-
-class MapBiomasCollectionWidget(QWidget):
- @staticmethod
- def getUrl(url, version, year, l_class_id):
- l_strClass = [ str(item) for item in l_class_id ]
- paramsWms = 'IgnoreGetFeatureInfoUrl=1&IgnoreGetMapUrl=1&crs=EPSG:3857&dpiMode=7&format=image/png&layers=coverage&styles='
- paramsQuote = f"map=wms/v/{version}/classification/coverage.map"
- paramsQuote = f"{paramsQuote}&layers=coverage&transparent=true&version=1.1.1&territory_id=10"
- paramsQuote = urllib.parse.quote( f"{paramsQuote}&year={year}&classification_ids=" )
- paramClassification = ','.join( l_strClass )
- return f"{paramsWms}&url={url}?{paramsQuote}{paramClassification}"
-
- def __init__(self, layer, data):
- def getYearClasses():
- def getYear():
- values = [ item for item in paramsSource if item.find('year=') > -1 ]
- return self.maxYear if not len( values ) == 1 else int( values[0].split('=')[1] )
-
- def getClasses():
- values = [ item for item in paramsSource if item.find('classification_ids=') > -1 ]
- return [1,10,14,22,26,27] \
- if not len( values ) == 1 \
- else [ int( item ) for item in values[0].split('=')[1].split(',') ]
-
- paramsSource = urllib.parse.unquote( self.layer.source() ).split('&')
- return getYear(), getClasses()
-
- def setGui(classes):
- def createLayoutYear():
- lytYear = QHBoxLayout()
- lblTitleYear = QLabel( 'Year:', self )
- lblYear = QLabel( str( self.year ), self )
- lytYear.addWidget( lblTitleYear )
- lytYear.addWidget( lblYear )
- return lytYear, lblYear
-
- def createLayoutSlider():
- def createButtonLimit(limitYear, sFormat, objectName):
- label = sFormat.format( limitYear )
- pb = QPushButton( label, self )
- width = pb.fontMetrics().boundingRect( label ).width() + 7
- pb.setMaximumWidth( width )
- pb.setObjectName( objectName )
- return pb
-
- def createSlider():
- slider = QSlider( Qt.Horizontal, self )
- #slider.setTracking( False ) # Value changed only released mouse
- slider.setMinimum( self.minYear )
- slider.setMaximum( self.maxYear )
- slider.setSingleStep(1)
- slider.setValue( self.year )
- interval = int( ( self.maxYear - self.minYear) / 10 )
- slider.setTickInterval( interval )
- slider.setPageStep( interval)
- slider.setTickPosition( QSlider.TicksBelow )
- return slider
-
- lytSlider = QHBoxLayout()
- pbMin = createButtonLimit( self.minYear, "{} <<", 'minYear' )
- lytSlider.addWidget( pbMin )
- slider = createSlider()
- lytSlider.addWidget( slider )
- pbMax = createButtonLimit( self.maxYear, ">> {}", 'maxYear' )
- lytSlider.addWidget( pbMax )
- return lytSlider, slider, pbMin, pbMax
-
- def createTree(classes):
- def populateTreeJson(classes, itemRoot):
- def createIcon(color):
- color = QColor( color['r'], color['g'], color['b'] )
- pix = QPixmap(16, 16)
- pix.fill( color )
- return QIcon( pix )
-
- def createItem(itemRoot, name, class_id, flags, icon):
- # WidgetItem
- item = QTreeWidgetItem( itemRoot )
- item.setText(0, name )
- item.setData(0, Qt.UserRole, class_id )
- checkState = Qt.Checked if class_id in self.l_class_id else Qt.Unchecked
- item.setCheckState(0, checkState )
- item.setFlags( flags )
- item.setIcon(0, icon )
- return item
-
- flags = itemRoot.flags() | Qt.ItemIsUserCheckable
- for k in classes:
- class_id = classes[ k ]['id']
- icon = createIcon( classes[ k ]['color'] )
- itemClass = createItem( itemRoot, k, class_id, flags, icon )
- if 'classes' in classes[ k ]:
- populateTreeJson( classes[ k ]['classes'], itemClass )
-
- tree = QTreeWidget( self )
- tree.setSelectionMode( tree.NoSelection )
- tree.setHeaderHidden( True )
- itemRoot = QTreeWidgetItem( tree )
- itemRoot.setText(0, 'Classes')
- populateTreeJson( classes, itemRoot )
- return tree, itemRoot
-
- lytYear, lblYear = createLayoutYear()
- lytSlider, slider, pbMin, pbMax = createLayoutSlider( )
- tree, itemClasses = createTree( classes )
- itemClasses.setExpanded( True )
- # Layout
- lyt = QVBoxLayout()
- lyt.addLayout( lytYear )
- lyt.addLayout( lytSlider )
- lyt.addWidget( tree )
- msgBar = QgsMessageBar(self)
- lyt.addWidget( msgBar )
- self.setLayout( lyt )
-
-
- return {
- 'msgBar': msgBar,
- 'lblYear': lblYear,
- 'slider': slider,
- 'pbMin': pbMin,
- 'pbMax': pbMax,
- 'tree': tree,
- 'itemClasses': itemClasses
- }
-
- super().__init__()
- self.layer = layer
- self.version = data['version']
- self.url = data['url']
- self.minYear = data['years']['min']
- self.maxYear = data['years']['max']
-
- self.project = QgsProject.instance()
- self.root = self.project.layerTreeRoot()
-
- self.year, self.l_class_id = getYearClasses() # Depend self.maxYear
- self.valueYearLayer = self.year
-
- r = setGui( data['classes'] )
- self.msgBar = r['msgBar']
- self.lblYear = r['lblYear']
- self.slider = r['slider']
- self.pbMin = r['pbMin']
- self.pbMax = r['pbMax']
- self.tree = r['tree']
- self.itemClasses = r['itemClasses']
-
- # Connections
- self.slider.valueChanged.connect( self.on_yearChanged )
- self.slider.sliderReleased.connect( self.on_released )
- self.pbMin.clicked.connect( self.on_limitYear )
- self.pbMax.clicked.connect( self.on_limitYear )
- self.tree.itemChanged.connect( self.on_classChanged )
-
- def _uploadSource(self):
- def checkDataSource():
- url = self.getUrl( self.url, self.version, self.year, self.l_class_id )
- name = f"Collection {self.version} - {self.year}"
- args = [ url, name, self.layer.providerType() ]
- layer = QgsRasterLayer( *args )
- if not layer.isValid():
- msg = f"Error server {self.url}"
- return { 'isOk': False, 'message': msg }
- args += [ self.layer.dataProvider().ProviderOptions() ]
- return { 'isOk': True, 'args': args }
-
- self.setEnabled( False )
- r = checkDataSource()
- if not r['isOk']:
- self.msgBar.pushMessage( r['message'], Qgis.Critical, 4 )
- self.setEnabled( True )
- return
- self.layer.setDataSource( *r['args'] ) # The Widget will be create agai
-
- @pyqtSlot()
- def on_released(self):
- if self.valueYearLayer == self.year:
- return
-
- self._uploadSource()
-
- @pyqtSlot(int)
- def on_yearChanged(self, value):
- if value == self.year:
- return
-
- self.yearChanged = True
- self.year = value
- self.lblYear.setText( str( value ) )
- if not self.slider.isSliderDown(): # Keyboard
- self.valueYearLayer = self.year
- self._uploadSource()
-
- @pyqtSlot(bool)
- def on_limitYear(self, checked):
- year = self.maxYear if self.sender().objectName() == 'maxYear' else self.minYear
- if year == self.year:
- return
-
- self.year = year
- self.lblYear.setText( str( self.year ) )
- self.valueYearLayer = self.year
- self._uploadSource()
-
- @pyqtSlot(QTreeWidgetItem, int)
- def on_classChanged(self, item, column):
- value = item.data( column, Qt.UserRole)
- status = item.checkState( column ) == Qt.Checked
- f = self.l_class_id.append if status else self.l_class_id.remove
- f( value )
- self._uploadSource()
-
-
-class LayerMapBiomasCollectionWidgetProvider(QgsLayerTreeEmbeddedWidgetProvider):
- def __init__(self, data):
- super().__init__()
- self.data = data
-
- def id(self):
- return 'mapbiomascollection'
-
- def name(self):
- return "Layer MapBiomas Collection"
-
- def createWidget(self, layer, widgetIndex):
- return MapBiomasCollectionWidget( layer, self.data )
-
- def supportsLayer(self, layer):
- if not layer.providerType() == 'wms':
- return False
- source = urllib.parse.unquote( layer.source() ).split('&')
- host = f"url={self.data['url']}?map=wms/v/{self.data['version']}/classification/coverage.map"
- l_url = [ item for item in source if item.find( host ) > -1 ]
- return len( l_url ) > 0
-
-
-class MapBiomasCollection(QObject):
- MODULE = 'MapBiomasCollection'
- def __init__(self, iface):
- def getConfig():
- def existLocaleConfig():
- overrideLocale = QSettings().value('locale/overrideFlag', False, type=bool)
- locale = QLocale.system().name() if not overrideLocale else QSettings().value('locale/userLocale', '')
- name = f_name.format( locale=locale )
- fileConfig = os.path.join( dirname, name )
- if os.path.exists( fileConfig ):
- return { 'isOk': True, 'fileConfig': fileConfig }
- return { 'isOk': False }
-
- f_name = "mapbiomascollection_{locale}.json"
- dirname = os.path.dirname(__file__)
- r = existLocaleConfig()
- if r['isOk']:
- fileConfig = r['fileConfig']
- else:
- name = f_name.format( locale='en_US')
- fileConfig = os.path.join( dirname, name )
-
- with open(fileConfig) as json_file:
- data = json.load(json_file)
- return data
-
- super().__init__()
- self.msgBar = iface.messageBar()
- self.root = QgsProject.instance().layerTreeRoot()
- self.taskManager = QgsApplication.taskManager()
- self.data = getConfig()
- self.widgetProvider = None
-
- def register(self):
- self.widgetProvider = LayerMapBiomasCollectionWidgetProvider( self.data )
- registry = QgsGui.layerTreeEmbeddedWidgetRegistry()
- if not registry.provider( self.widgetProvider.id() ) is None:
- registry.removeProvider( self.widgetProvider.id() )
- registry.addProvider( self.widgetProvider )
-
- def run(self):
- def createLayer(task, year, l_class_id):
- args = ( self.data['url'], self.data['version'], year, l_class_id )
- url = MapBiomasCollectionWidget.getUrl( *args )
- return ( url, f"Collection {self.data['version']} - {year}", 'wms' )
-
- def finished(exception, result=None):
- self.msgBar.clearWidgets()
- if not exception is None:
- msg = f"Error: Exception: {exception}"
- self.msgBar.pushMessage( self.MODULE, msg, Qgis.Critical, 4 )
- return
- layer = QgsRasterLayer( *result )
- if not layer.isValid():
- source = urllib.parse.unquote( layer.source() ).split('&')
- url = [ v for v in source if v.split('=')[0] == 'url' ][0]
- msg = f"Error server: Get {url}"
- self.msgBar.pushCritical( self.MODULE, msg )
- return
-
- project = QgsProject.instance()
- totalEW = int( layer.customProperty('embeddedWidgets/count', 0) )
- layer.setCustomProperty('embeddedWidgets/count', totalEW + 1 )
- layer.setCustomProperty(f"embeddedWidgets/{totalEW}/id", self.widgetProvider.id() )
- project.addMapLayer( layer )
- root = project.layerTreeRoot()
- ltl = root.findLayer( layer )
- ltl.setExpanded(True)
-
- msg = f"Adding layer collection from {self.data['url']}"
- msg = f"{msg}(version {self.data['version']})..."
- self.msgBar.pushMessage( self.MODULE, msg, Qgis.Info, 0 )
- # Task
- args = {
- 'description': self.MODULE,
- 'function': createLayer,
- 'year': 2018,
- 'l_class_id': [1, 10, 14, 22, 26, 27],
- 'on_finished': finished
- }
- task = QgsTask.fromFunction( **args )
- self.taskManager.addTask( task )
+import os, time, json
+import urllib.parse
+import warnings
+from osgeo import gdal
+
+from qgis.PyQt.QtCore import (
+ Qt, QSettings, QLocale,
+ QObject, pyqtSlot, pyqtSignal
+)
+from qgis.PyQt.QtWidgets import (
+ QWidget, QPushButton,
+ QSlider, QLabel,
+ QTreeWidget, QTreeWidgetItem,
+ QVBoxLayout, QHBoxLayout
+)
+from qgis.PyQt.QtGui import (
+ QColor, QPixmap, QIcon
+)
+
+from qgis.core import (
+ QgsApplication, Qgis, QgsProject,
+ QgsRasterLayer,
+ QgsTask
+
+)
+from qgis.gui import QgsGui, QgsMessageBar, QgsLayerTreeEmbeddedWidgetProvider
+#https://production.mapserver.mapbiomas.org/wms/coverage.map?service=WMS&request=GetMap&layers=coverage&styles=&format=image%2Fpng&transparent=true&version=1.3.0&territory_ids=96&year=2019&class_tree_node_ids=28%2C36%2C50%2C51%2C52%2C35%2C29%2C37%2C38%2C41%2C40%2C39%2C30%2C43%2C42%2C54%2C56%2C55%2C57%2C53%2C44%2C31%2C45%2C46%2C47%2C34%2C32%2C49%2C48%2C33&width=256&height=256&srs=EPSG%3A3857&maxZoom=19&minZoom=4&bbox=-5635549.221409475,-1252344.2714243263,-5009377.085697311,-626172.1357121632
+
+class MapBiomasCollectionWidget(QWidget):
+ classRef = {1:{'color':'129912','parent':0,'status':False},
+ 2:{'color':'1F4423','parent':1,'status':False},
+ 3:{'color':'006400','parent':2,'status':False},
+ 4:{'color':'32CD32','parent':2,'status':False},
+ 5:{'color':'687537','parent':2,'status':False},
+ 6:{'color':'000000','parent':0,'status':False},
+ 7:{'color':'000000','parent':0,'status':False},
+ 8:{'color':'000000','parent':0,'status':False},
+ 9:{'color':'935132','parent':1,'status':False},
+ 10:{'color':'BBFCAC','parent':0,'status':False},
+ 11:{'color':'45C2A5','parent':10,'status':False},
+ 12:{'color':'B8AF4F','parent':10,'status':False},
+ 13:{'color':'BDB76B','parent':10,'status':False},
+ 14:{'color':'FFFFB2','parent':0,'status':False},
+ 15:{'color':'FFD966','parent':14,'status':False},
+ 16:{'color':'000000','parent':0,'status':False},
+ 17:{'color':'000000','parent':0,'status':False},
+ 18:{'color':'E974ED','parent':14,'status':False},
+ 19:{'color':'D5A6BD','parent':18,'status':False},
+ 20:{'color':'C27BA0','parent':19,'status':False},
+ 21:{'color':'FFEFC3','parent':14,'status':False},
+ 22:{'color':'EA9999','parent':0,'status':False},
+ 23:{'color':'DD7E6B','parent':22,'status':False},
+ 24:{'color':'af2a2a','parent':22,'status':False},
+ 25:{'color':'FF99FF','parent':22,'status':False},
+ 26:{'color':'0000FF','parent':0,'status':False},
+ 27:{'color':'D5D5E5','parent':0,'status':False},
+ 28:{'color': '000000','parent':0,'status':False},
+ 29:{'color':'FF8C00','parent':10,'status':False},
+ 30:{'color':'8A2BE2','parent':22,'status':False},
+ 31:{'color':'29EEE4','parent':26,'status':False},
+ 32:{'color':'968c46','parent':10,'status':False},
+ 33:{'color':'0000FF','parent':26,'status':False},
+ 34:{'color':'000000','parent':0,'status':False},
+ 35:{'color':'000000','parent':0,'status':False},
+ 36:{'color':'f3b4f1','parent':18,'status':False},
+ 37:{'color':'000000','parent':0,'status':False},
+ 38:{'color':'000000','parent':0,'status':False},
+ 39:{'color':'c59ff4','parent':19,'status':False},
+ 40:{'color':'000000','parent':0,'status':False},
+ 41:{'color':'e787f8','parent':19,'status':False}}
+ @staticmethod
+ def getParentColor(item):
+ if item['parent'] == 0 and item['status'] == False:
+ return 'FFFFFF'
+ if item['status']:
+ return item['color']
+ else:
+ return MapBiomasCollectionWidget.getParentColor(MapBiomasCollectionWidget.classRef[item['parent']])
+
+ @staticmethod
+ def getUrl(url, version, year, l_class_id):
+ l_strClass = [ str(item) for item in l_class_id ]
+ for item in MapBiomasCollectionWidget.classRef.keys():
+ MapBiomasCollectionWidget.classRef[item]['status'] = False
+ for item in l_class_id:
+ MapBiomasCollectionWidget.classRef[item]['status'] = True
+ #ENV Percorredor!
+ env = 'env='
+ for item in MapBiomasCollectionWidget.classRef.keys():
+ classID = item
+ color = MapBiomasCollectionWidget.getParentColor(MapBiomasCollectionWidget.classRef[item])
+ env = env + f'{classID}:{color};'
+ #env=1:00FF00;2:triangle;3:12
+ #crs=EPSG:3857&dpiMode=7&format=image/png&layers=mapbiomas&styles&url=http://azure.solved.eco.br:8080/geoserver/solved/wms
+ paramsWms = f'IgnoreGetFeatureInfoUrl=1&IgnoreGetMapUrl=1&service=WMS&styles=solved:mapbiomas_legend&request=GetMap&format=image/png8&layers=mapbiomas_{year}&crs=EPSG:4326'
+ #'IgnoreGetFeatureInfoUrl=1&IgnoreGetMapUrl=1&crs=EPSG:3857&dpiMode=7&format=image/png&layers=coverage&styles='
+ paramsQuote = f""
+ paramsQuote = f"{paramsQuote}&transparent=true&version=1.1.1"
+ paramsQuote = urllib.parse.quote( f"{paramsQuote}&exceptions=application/vnd.ogc.se_inimage&years={year}&{env}&classification_ids=" )# a ordem importa
+ paramClassification = ','.join( l_strClass )
+ msg = f"{paramsWms}&url={url}?{paramsQuote}{paramClassification}"
+ #warnings.warn(msg)
+ return f"{paramsWms}&url={url}?{paramsQuote}{paramClassification}"
+
+ def __init__(self, layer, data):
+ def getYearClasses():
+ def getYear():
+ values = [ item for item in paramsSource if item.find('years=') > -1]
+ return self.maxYear if not len( values ) == 1 else int( values[0].split('=')[1] )
+
+ def getClasses():
+ values = [ item for item in paramsSource if item.find('classification_ids=') > -1 ]
+ warnings.warn(str(values))
+ if (not len( values ) == 1) or (values[0] == 'classification_ids='):
+ return []
+ else :
+ return [ int( item ) for item in values[0].split('=')[1].split(',') ]
+
+ paramsSource = urllib.parse.unquote( self.layer.source() ).split('&')
+ return getYear(), getClasses()
+
+ def setGui(classes):
+ def createLayoutYear():
+ lytYear = QHBoxLayout()
+ lblTitleYear = QLabel( 'Year:', self )
+ lblYear = QLabel( str( self.year ), self )
+ lytYear.addWidget( lblTitleYear )
+ lytYear.addWidget( lblYear )
+ return lytYear, lblYear
+
+ def createLayoutSlider():
+ def createButtonLimit(limitYear, sFormat, objectName):
+ label = sFormat.format( limitYear )
+ pb = QPushButton( label, self )
+ width = pb.fontMetrics().boundingRect( label ).width() + 7
+ pb.setMaximumWidth( width )
+ pb.setObjectName( objectName )
+ return pb
+
+ def createSlider():
+ slider = QSlider( Qt.Horizontal, self )
+ #slider.setTracking( False ) # Value changed only released mouse
+ slider.setMinimum( self.minYear )
+ slider.setMaximum( self.maxYear )
+ slider.setSingleStep(1)
+ slider.setValue( self.year )
+ interval = int( ( self.maxYear - self.minYear) / 10 )
+ slider.setTickInterval( interval )
+ slider.setPageStep( interval)
+ slider.setTickPosition( QSlider.TicksBelow )
+ return slider
+
+ lytSlider = QHBoxLayout()
+ pbMin = createButtonLimit( self.minYear, "{} <<", 'minYear' )
+ lytSlider.addWidget( pbMin )
+ slider = createSlider()
+ lytSlider.addWidget( slider )
+ pbMax = createButtonLimit( self.maxYear, ">> {}", 'maxYear' )
+ lytSlider.addWidget( pbMax )
+ return lytSlider, slider, pbMin, pbMax
+
+ def createTree(classes):
+ def populateTreeJson(classes, itemRoot):
+ def createIcon(color):
+ color = QColor( color['r'], color['g'], color['b'] )
+ pix = QPixmap(16, 16)
+ pix.fill( color )
+ return QIcon( pix )
+
+ def createItem(itemRoot, name, class_id, flags, icon):
+ # WidgetItem
+ item = QTreeWidgetItem( itemRoot )
+ item.setText(0, name )
+ item.setData(0, Qt.UserRole, class_id )
+ checkState = Qt.Checked if class_id in self.l_class_id else Qt.Unchecked
+ item.setCheckState(0, checkState )
+ item.setFlags( flags )
+ item.setIcon(0, icon )
+ return item
+
+ flags = itemRoot.flags() | Qt.ItemIsUserCheckable
+ for k in classes:
+ class_id = classes[ k ]['id']
+ icon = createIcon( classes[ k ]['color'] )
+ itemClass = createItem( itemRoot, k, class_id, flags, icon )
+ if 'classes' in classes[ k ]:
+ populateTreeJson( classes[ k ]['classes'], itemClass )
+
+ tree = QTreeWidget( self )
+ tree.setSelectionMode( tree.NoSelection )
+ tree.setHeaderHidden( True )
+ itemRoot = QTreeWidgetItem( tree )
+ itemRoot.setText(0, 'Classes')
+ populateTreeJson( classes, itemRoot )
+ return tree, itemRoot
+
+ lytYear, lblYear = createLayoutYear()
+ lytSlider, slider, pbMin, pbMax = createLayoutSlider( )
+ tree, itemClasses = createTree( classes )
+ itemClasses.setExpanded( True )
+ # Layout
+ lyt = QVBoxLayout()
+ lyt.addLayout( lytYear )
+ lyt.addLayout( lytSlider )
+ lyt.addWidget( tree )
+ msgBar = QgsMessageBar(self)
+ lyt.addWidget( msgBar )
+ self.setLayout( lyt )
+
+
+ return {
+ 'msgBar': msgBar,
+ 'lblYear': lblYear,
+ 'slider': slider,
+ 'pbMin': pbMin,
+ 'pbMax': pbMax,
+ 'tree': tree,
+ 'itemClasses': itemClasses
+ }
+
+ super().__init__()
+ self.layer = layer
+ self.version = data['version']
+ self.url = data['url']
+ self.minYear = data['years']['min']
+ self.maxYear = data['years']['max']
+
+ self.project = QgsProject.instance()
+ self.root = self.project.layerTreeRoot()
+
+ self.year, self.l_class_id = getYearClasses() # Depend self.maxYear
+ self.valueYearLayer = self.year
+
+ r = setGui( data['classes'] )
+ self.msgBar = r['msgBar']
+ self.lblYear = r['lblYear']
+ self.slider = r['slider']
+ self.pbMin = r['pbMin']
+ self.pbMax = r['pbMax']
+ self.tree = r['tree']
+ self.itemClasses = r['itemClasses']
+
+ # Connections
+ self.slider.valueChanged.connect( self.on_yearChanged )
+ self.slider.sliderReleased.connect( self.on_released )
+ self.pbMin.clicked.connect( self.on_limitYear )
+ self.pbMax.clicked.connect( self.on_limitYear )
+ self.tree.itemChanged.connect( self.on_classChanged )
+
+ def _uploadSource(self):
+ def checkDataSource():
+ url = self.getUrl( self.url, self.version, self.year, self.l_class_id )
+ print('URL:')
+ print(url)
+ name = f"Collection {self.version} - {self.year}"
+ print('name:')
+ print(name)
+ args = [ url, name, self.layer.providerType() ]
+ layer = QgsRasterLayer( *args )
+ if not layer.isValid():
+ msg = f"Error server {self.url}"
+ return { 'isOk': False, 'message': msg }
+ args += [ self.layer.dataProvider().ProviderOptions() ]
+ return { 'isOk': True, 'args': args }
+
+ self.setEnabled( False )
+ r = checkDataSource()
+ if not r['isOk']:
+ self.msgBar.pushMessage( r['message'], Qgis.Critical, 4 )
+ self.setEnabled( True )
+ return
+ self.layer.setDataSource( *r['args'] ) # The Widget will be create agai
+
+ @pyqtSlot()
+ def on_released(self):
+ if self.valueYearLayer == self.year:
+ return
+
+ self._uploadSource()
+
+ @pyqtSlot(int)
+ def on_yearChanged(self, value):
+ if value == self.year:
+ return
+
+ self.yearChanged = True
+ self.year = value
+ self.lblYear.setText( str( value ) )
+ if not self.slider.isSliderDown(): # Keyboard
+ self.valueYearLayer = self.year
+ self._uploadSource()
+
+ @pyqtSlot(bool)
+ def on_limitYear(self, checked):
+ year = self.maxYear if self.sender().objectName() == 'maxYear' else self.minYear
+ if year == self.year:
+ return
+
+ self.year = year
+ self.lblYear.setText( str( self.year ) )
+ self.valueYearLayer = self.year
+ self._uploadSource()
+
+ @pyqtSlot(QTreeWidgetItem, int)
+ def on_classChanged(self, item, column):
+ value = item.data( column, Qt.UserRole)
+ color = item.data( column, Qt.UserRole)
+ status = item.checkState( column ) == Qt.Checked
+ f = self.l_class_id.append if status else self.l_class_id.remove
+ f( value )
+ self._uploadSource()
+
+
+class LayerMapBiomasCollectionWidgetProvider(QgsLayerTreeEmbeddedWidgetProvider):
+ def __init__(self, data):
+ super().__init__()
+ self.data = data
+
+ def id(self):
+ return 'mapbiomascollection'
+
+ def name(self):
+ return "Layer MapBiomas Collection"
+
+ def createWidget(self, layer, widgetIndex):
+ return MapBiomasCollectionWidget( layer, self.data )
+
+ def supportsLayer(self, layer):
+ if not layer.providerType() == 'wms':
+ return False
+ source = urllib.parse.unquote( layer.source() ).split('&')
+ print('Here')
+ host = f"url={self.data['url']}?map=wms/v/{self.data['version']}/classification/coverage.map"
+ print(host)
+ #warnings.warn(host)
+ l_url = [ item for item in source if item.find( host ) > -1 ]
+ return len( l_url ) > 0
+
+
+class MapBiomasCollection(QObject):
+ MODULE = 'MapBiomasCollection'
+ def __init__(self, iface):
+ def getConfig():
+ def existLocaleConfig():
+ overrideLocale = QSettings().value('locale/overrideFlag', False, type=bool)
+ locale = QLocale.system().name() if not overrideLocale else QSettings().value('locale/userLocale', '')
+ name = f_name.format( locale=locale )
+ fileConfig = os.path.join( dirname, name )
+ if os.path.exists( fileConfig ):
+ return { 'isOk': True, 'fileConfig': fileConfig }
+ return { 'isOk': False }
+
+ f_name = "mapbiomascollection_{locale}.json"
+ dirname = os.path.dirname(__file__)
+ r = existLocaleConfig()
+ if r['isOk']:
+ fileConfig = r['fileConfig']
+ else:
+ name = f_name.format( locale='en_US')
+ fileConfig = os.path.join( dirname, name )
+
+ with open(fileConfig) as json_file:
+ data = json.load(json_file)
+ return data
+
+ super().__init__()
+ self.msgBar = iface.messageBar()
+ self.root = QgsProject.instance().layerTreeRoot()
+ self.taskManager = QgsApplication.taskManager()
+ self.data = getConfig()
+ self.widgetProvider = None
+
+ def register(self):
+ self.widgetProvider = LayerMapBiomasCollectionWidgetProvider( self.data )
+ registry = QgsGui.layerTreeEmbeddedWidgetRegistry()
+ if not registry.provider( self.widgetProvider.id() ) is None:
+ registry.removeProvider( self.widgetProvider.id() )
+ registry.addProvider( self.widgetProvider )
+
+ def run(self):
+ def createLayer(task, year, l_class_id):
+ args = ( self.data['url'], self.data['version'], year, l_class_id )
+ #warnings.warn( self.data['url'])
+ url = MapBiomasCollectionWidget.getUrl( *args )
+ #warnings.warn(url)
+ return ( url, f"Collection {self.data['version']} - {year}", 'wms' )
+
+ def finished(exception, result=None):
+ self.msgBar.clearWidgets()
+ if not exception is None:
+ msg = f"Error: Exception: {exception}"
+ self.msgBar.pushMessage( self.MODULE, msg, Qgis.Critical, 4 )
+ return
+ layer = QgsRasterLayer( *result )
+ if not layer.isValid():
+ source = urllib.parse.unquote( layer.source() ).split('&')
+ url = [ v for v in source if v.split('=')[0] == 'url' ][0]
+ msg = f"!!!Error server: Get {url}"
+ self.msgBar.pushCritical( self.MODULE, msg )
+ return
+
+ project = QgsProject.instance()
+ totalEW = int( layer.customProperty('embeddedWidgets/count', 0) )
+ layer.setCustomProperty('embeddedWidgets/count', totalEW + 1 )
+ layer.setCustomProperty(f"embeddedWidgets/{totalEW}/id", self.widgetProvider.id() )
+ project.addMapLayer( layer )
+ root = project.layerTreeRoot()
+ ltl = root.findLayer( layer )
+ ltl.setExpanded(True)
+
+ msg = f"Adding layer collection from {self.data['url']}"
+ msg = f"{msg}(version {self.data['version']})..."
+ self.msgBar.pushMessage( self.MODULE, msg, Qgis.Info, 0 )
+ # Task
+ args = {
+ 'description': self.MODULE,
+ 'function': createLayer,
+ 'year': 2017,
+ 'l_class_id': [1, 10, 14, 22, 26, 27],
+ 'on_finished': finished
+ }
+ task = QgsTask.fromFunction( **args )
+ self.taskManager.addTask( task )
diff --git a/mapbiomascollection_en_US.json b/mapbiomascollection_en_US.json
index 9aa37d4..091c5bc 100644
--- a/mapbiomascollection_en_US.json
+++ b/mapbiomascollection_en_US.json
@@ -1,62 +1,69 @@
-{
- "version": "4.1",
- "url": "http://workspace.mapbiomas.org/wms",
- "years": { "min": 1985, "max": 2018},
- "classes": {
- "Florestry": {
- "id": 1, "color": { "r": 18, "g": 153, "b": 18 },
- "classes": {
- "Natural Forest": {
- "id": 2, "color": { "r": 31, "g": 68, "b": 35 },
- "classes": {
- "Forest Formation": { "id": 3, "color": { "r": 39, "g": 78, "b": 19 } },
- "Savanna Formation ": { "id": 4, "color": { "r": 50, "g": 205, "b": 50 } },
- "Mangrove": { "id": 5, "color": { "r": 104, "g": 117, "b": 55 } }
- }
- },
- "Forest Plantation": { "id": 9, "color": { "r": 147, "g": 81, "b": 50 } }
- }
- },
- "Non Forest Natural Formation": {
- "id": 10, "color": { "r": 187, "g": 252, "b": 172 },
- "classes": {
- "Wetland": { "id": 11, "color": { "r": 69, "g": 194, "b": 165 } },
- "Grassland": { "id": 12, "color": { "r": 184, "g": 175, "b": 79 } },
- "Salt Flat": { "id": 32, "color": { "r": 150, "g": 140, "b": 70 } },
- " Rocky Outcrop": { "id": 29, "color": { "r": 255, "g": 140, "b": 0 } },
- " Other Non Forest Natural Formation": { "id": 13, "color": { "r": 189, "g": 183, "b": 107 } }
- }
- },
- "Farming": {
- "id": 14, "color": { "r": 255, "g": 255, "b": 178 },
- "classes": {
- "Pasture": { "id": 15, "color": { "r": 255, "g": 217, "b": 102 } },
- "Agriculture": {
- "id": 18, "color": { "r": 233, "g": 116, "b": 237 },
- "classes": {
- "Annual and Perennial Crop": { "id": 19, "color": { "r": 213, "g": 166, "b": 189 } },
- "Semi-perennial Crop": { "id": 20, "color": { "r": 194, "g": 123, "b": 160 } }
- }
- },
- "Mosaic of Agriculture and Pasture": { "id": 21, "color": { "r": 255, "g": 239, "b": 195 } }
- }
- },
- "Non vegetated area": {
- "id": 22, "color": { "r": 234, "g": 153, "b": 153 },
- "classes": {
- "Beach and Dune": { "id": 23, "color": { "r": 221, "g": 126, "b": 107 } },
- "Urban Infrastructure": { "id": 24, "color": { "r": 175, "g": 42, "b": 42 } },
- "Mining": { "id": 30, "color": { "r": 138, "g": 43, "b": 226 } },
- "Other Non Vegetated Area": { "id": 25, "color": { "r": 255, "g": 153, "b": 255 } }
- }
- },
- "Water": {
- "id": 26, "color": { "r": 0, "g": 0, "b": 255 },
- "classes": {
- " River, Lake and Ocean": { "id": 33, "color": { "r": 0, "g": 0, "b": 255 } },
- "Aquaculture": { "id": 31, "color": { "r": 41, "g": 238, "b": 228 } }
- }
- },
- "Non Observed": { "id": 27, "color": { "r": 213, "g": 213, "b": 229 } }
- }
-}
+{
+ "version": "4.1",
+ "url": "http://azure.solved.eco.br:8080/geoserver/solved/wms",
+ "years": { "min": 1985, "max": 2019},
+ "classes": {
+ "Florestry": {
+ "id": 1, "color": { "r": 18, "g": 153, "b": 18 },
+ "classes": {
+ "Natural Forest": {
+ "id": 2, "color": { "r": 31, "g": 68, "b": 35 },
+ "classes": {
+ "Forest Formation": { "id": 3, "color": { "r": 39, "g": 78, "b": 19 } },
+ "Savanna Formation ": { "id": 4, "color": { "r": 50, "g": 205, "b": 50 } },
+ "Mangrove": { "id": 5, "color": { "r": 104, "g": 117, "b": 55 } }
+ }
+ },
+ "Forest Plantation": { "id": 9, "color": { "r": 147, "g": 81, "b": 50 } }
+ }
+ },
+ "Non Forest Natural Formation": {
+ "id": 10, "color": { "r": 187, "g": 252, "b": 172 },
+ "classes": {
+ "Wetland": { "id": 11, "color": { "r": 69, "g": 194, "b": 165 } },
+ "Grassland": { "id": 12, "color": { "r": 184, "g": 175, "b": 79 } },
+ "Salt Flat": { "id": 32, "color": { "r": 150, "g": 140, "b": 70 } },
+ " Rocky Outcrop": { "id": 29, "color": { "r": 255, "g": 140, "b": 0 } },
+ " Other Non Forest Natural Formation": { "id": 13, "color": { "r": 189, "g": 183, "b": 107 } }
+ }
+ },
+ "Farming": {
+ "id": 14, "color": { "r": 255, "g": 255, "b": 178 },
+ "classes": {
+ "Pasture": { "id": 15, "color": { "r": 255, "g": 217, "b": 102 } },
+ "Agriculture": {
+ "id": 18, "color": { "r": 233, "g": 116, "b": 237 },
+ "classes": {
+ "Temporary Crop ": {
+ "id": 19, "color": { "r": 213, "g": 166, "b": 189 },
+ "classes": {
+ "Soybean": { "id": 39, "color": { "r": 197, "g": 159, "b": 244 }},
+ "Suggar Cane": { "id": 20, "color": { "r": 194, "g": 123, "b": 160 }},
+ "Other Temporary Crops ": { "id": 41, "color": { "r": 231, "g": 135, "b": 248 }}
+ }
+ },
+ "Perennial Crop": { "id": 36, "color": { "r": 243, "g": 180, "b": 241 } }
+ }
+ },
+ "Mosaic of Agriculture and Pasture": { "id": 21, "color": { "r": 255, "g": 239, "b": 195 } }
+ }
+ },
+ "Non vegetated area": {
+ "id": 22, "color": { "r": 234, "g": 153, "b": 153 },
+ "classes": {
+ "Beach and Dune": { "id": 23, "color": { "r": 221, "g": 126, "b": 107 } },
+ "Urban Infrastructure": { "id": 24, "color": { "r": 175, "g": 42, "b": 42 } },
+ "Mining": { "id": 30, "color": { "r": 138, "g": 43, "b": 226 } },
+ "Other Non Vegetated Area": { "id": 25, "color": { "r": 255, "g": 153, "b": 255 } }
+ }
+ },
+ "Water": {
+ "id": 26, "color": { "r": 0, "g": 0, "b": 255 },
+ "classes": {
+ " River, Lake and Ocean": { "id": 33, "color": { "r": 0, "g": 0, "b": 255 } },
+ "Aquaculture": { "id": 31, "color": { "r": 41, "g": 238, "b": 228 } }
+ }
+ },
+ "Non Observed": { "id": 27, "color": { "r": 213, "g": 213, "b": 229 } }
+ }
+}
diff --git a/mapbiomascollection_pt_BR.json b/mapbiomascollection_pt_BR.json
index ce1c686..9c5bce5 100644
--- a/mapbiomascollection_pt_BR.json
+++ b/mapbiomascollection_pt_BR.json
@@ -1,62 +1,68 @@
-{
- "version": "4.1",
- "url": "http://workspace.mapbiomas.org/wms",
- "years": { "min": 1985, "max": 2018},
- "classes": {
- "Floresta": {
- "id": 1, "color": { "r": 18, "g": 153, "b": 18 },
- "classes": {
- "Floresta Natural": {
- "id": 2, "color": { "r": 31, "g": 68, "b": 35 },
- "classes": {
- "Formação Florestal": { "id": 3, "color": { "r": 39, "g": 78, "b": 19 } },
- "Formação Savanica": { "id": 4, "color": { "r": 50, "g": 205, "b": 50 } },
- "Mangue": { "id": 5, "color": { "r": 104, "g": 117, "b": 55 } }
- }
- },
- "Floresta Plantada": { "id": 9, "color": { "r": 147, "g": 81, "b": 50 } }
- }
- },
- "Formação Natural não Florestal": {
- "id": 10, "color": { "r": 187, "g": 252, "b": 172 },
- "classes": {
- "Área Úmida Natural não Florestal": { "id": 11, "color": { "r": 69, "g": 194, "b": 165 } },
- "Formação Campestre": { "id": 12, "color": { "r": 184, "g": 175, "b": 79 } },
- "Apicum": { "id": 32, "color": { "r": 150, "g": 140, "b": 70 } },
- "Afloramento Rochoso": { "id": 29, "color": { "r": 255, "g": 140, "b": 0 } },
- "Outra Formação Natural não Florestal": { "id": 13, "color": { "r": 189, "g": 183, "b": 107 } }
- }
- },
- "Agropecuária": {
- "id": 14, "color": { "r": 255, "g": 255, "b": 178 },
- "classes": {
- "Pastagem": { "id": 15, "color": { "r": 255, "g": 217, "b": 102 } },
- "Agricultura": {
- "id": 18, "color": { "r": 233, "g": 116, "b": 237 },
- "classes": {
- "Cultura Anual e Perene": { "id": 19, "color": { "r": 213, "g": 166, "b": 189 } },
- "Cultura Semi-Perene": { "id": 20, "color": { "r": 194, "g": 123, "b": 160 } }
- }
- },
- "Mosaico de Agricultura e Pastagem": { "id": 21, "color": { "r": 255, "g": 239, "b": 195 } }
- }
- },
- "Área não vegetada": {
- "id": 22, "color": { "r": 234, "g": 153, "b": 153 },
- "classes": {
- "Praia e Duna": { "id": 23, "color": { "r": 221, "g": 126, "b": 107 } },
- "Infraestrutura Urbana": { "id": 24, "color": { "r": 175, "g": 42, "b": 42 } },
- "Mineração": { "id": 30, "color": { "r": 138, "g": 43, "b": 226 } },
- "Outra Área não Vegetada": { "id": 25, "color": { "r": 255, "g": 153, "b": 255 } }
- }
- },
- "Corpos D'água": {
- "id": 26, "color": { "r": 0, "g": 0, "b": 255 },
- "classes": {
- "Rio, Lago e Oceano": { "id": 33, "color": { "r": 0, "g": 0, "b": 255 } },
- "Aquicultura": { "id": 31, "color": { "r": 41, "g": 238, "b": 228 } }
- }
- },
- "Não observado": { "id": 27, "color": { "r": 213, "g": 213, "b": 229 } }
- }
-}
+{
+ "version": "5.0",
+ "url": "http://azure.solved.eco.br:8080/geoserver/solved/wms",
+ "years": { "min": 1985, "max": 2019},
+ "classes": {
+ "Floresta": {
+ "id": 1, "color": { "r": 18, "g": 153, "b": 18 },
+ "classes": {
+ "Floresta Natural": {
+ "id": 2, "color": { "r": 31, "g": 68, "b": 35 },
+ "classes": {
+ "Formação Florestal": { "id": 3, "color": { "r": 39, "g": 78, "b": 19 } },
+ "Formação Savanica": { "id": 4, "color": { "r": 50, "g": 205, "b": 50 } },
+ "Mangue": { "id": 5, "color": { "r": 104, "g": 117, "b": 55 } }
+ }
+ },
+ "Floresta Plantada": { "id": 9, "color": { "r": 147, "g": 81, "b": 50 } }
+ }
+ },
+ "Formação Natural não Florestal": {
+ "id": 10, "color": { "r": 187, "g": 252, "b": 172 },
+ "classes": {
+ "Área Úmida Natural não Florestal": { "id": 11, "color": { "r": 69, "g": 194, "b": 165 } },
+ "Formação Campestre": { "id": 12, "color": { "r": 184, "g": 175, "b": 79 } },
+ "Apicum": { "id": 32, "color": { "r": 150, "g": 140, "b": 70 } },
+ "Afloramento Rochoso": { "id": 29, "color": { "r": 255, "g": 140, "b": 0 } },
+ "Outra Formação Natural não Florestal": { "id": 13, "color": { "r": 189, "g": 183, "b": 107 } }
+ }
+ },
+ "Agropecuária": {
+ "id": 14, "color": { "r": 255, "g": 255, "b": 178 },
+ "classes": {
+ "Pastagem": { "id": 15, "color": { "r": 255, "g": 217, "b": 102 } },
+ "Agricultura": {
+ "id": 18, "color": { "r": 233, "g": 116, "b": 237 },
+ "classes": {
+ "Lavoura Temporária ": {
+ "id": 19, "color": { "r": 213, "g": 166, "b": 189 },
+ "classes": {
+ "Soja": { "id": 39, "color": { "r": 197, "g": 159, "b": 244 }},
+ "Cana": { "id": 20, "color": { "r": 194, "g": 123, "b": 160 }},
+ "Outras Lavouras Temporárias": { "id": 41, "color": { "r": 231, "g": 135, "b": 248 }}
+ }
+ }
+ }},
+ "Lavoura Perene": { "id": 36, "color": { "r": 243, "g": 180, "b": 241 } },
+ "Mosaico de Agricultura e Pastagem": { "id": 21, "color": { "r": 255, "g": 239, "b": 195 } }
+ }
+ },
+ "Área não vegetada": {
+ "id": 22, "color": { "r": 234, "g": 153, "b": 153 },
+ "classes": {
+ "Praia e Duna": { "id": 23, "color": { "r": 221, "g": 126, "b": 107 } },
+ "Infraestrutura Urbana": { "id": 24, "color": { "r": 175, "g": 42, "b": 42 } },
+ "Mineração": { "id": 30, "color": { "r": 138, "g": 43, "b": 226 } },
+ "Outra Área não Vegetada": { "id": 25, "color": { "r": 255, "g": 153, "b": 255 } }
+ }
+ },
+ "Corpos D'água": {
+ "id": 26, "color": { "r": 0, "g": 0, "b": 255 },
+ "classes": {
+ "Rio, Lago e Oceano": { "id": 33, "color": { "r": 0, "g": 0, "b": 255 } },
+ "Aquicultura": { "id": 31, "color": { "r": 41, "g": 238, "b": 228 } }
+ }
+ },
+ "Não observado": { "id": 27, "color": { "r": 213, "g": 213, "b": 229 } }
+ }
+}
diff --git a/metadata.txt b/metadata.txt
index 8fd49bf..2e714bd 100644
--- a/metadata.txt
+++ b/metadata.txt
@@ -1,32 +1,34 @@
-[general]
-name: MapBiomas Collection
-description: This plugin lets you get collection of mapping from MapBiomas Project(http://mapbiomas.org/).
-about:This plugin add layers(WMS) of collection from MapBiomas.
-
-version:1.0
-qgisMinimumVersion:3.10
-
-author:Luiz Motta
-email:motta.luiz@gmail.com
-
-category:Web
-
-tags:MapBiomas
-
-homepage:https://github.com/lmotta/mapbiomascollection/wiki
-tracker:https://github.com/lmotta/mapbiomascollection/issues
-repository:https://github.com/lmotta/mapbiomascollection
-
-icon:mapbiomas.svg
-
-experimental:False
-deprecated:False
-
-changelog: 1.0(2020-03-25)
- Changed Docwidget to WidgetProvider(legend)
- - 0.3(2019-09-05)
- Add set for collection layer
- - 0.2(2019-08-30)
- Update metadata and added collection number
- - 0.1(2019-08-29)
- Start of plugin
+[general]
+name: MapBiomas Collection
+description: This plugin lets you get collection of mapping from MapBiomas Project(http://mapbiomas.org/).
+about:This plugin add layers(WMS) of collection from MapBiomas.
+
+version:1.1
+qgisMinimumVersion:3.10
+
+author:Luiz Motta, Luiz Cortinhas
+email:motta.luiz@gmail.com, luiz.cortinhas@solved.eco.br
+
+category:Web
+
+tags:MapBiomas
+
+homepage:https://github.com/lmotta/mapbiomascollection/wiki
+tracker:https://github.com/lmotta/mapbiomascollection/issues
+repository:https://github.com/lmotta/mapbiomascollection
+
+icon:mapbiomas.svg
+
+experimental:False
+deprecated:False
+
+changelog: - 1.2(2020-10-28) added 2018 and 2019
+ - 1.1(2020-10-28) Mapbiomas changed from Geoserver to MapServer
+ - 1.0(2020-03-25)
+ Changed Docwidget to WidgetProvider(legend)
+ - 0.3(2019-09-05)
+ Add set for collection layer
+ - 0.2(2019-08-30)
+ Update metadata and added collection number
+ - 0.1(2019-08-29)
+ Start of plugin