├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── Utils.py
├── __init__.py
├── icon.png
├── image_analyzer.py
├── img
└── sample.gif
├── magic_wand.py
├── magic_wand_dockwidget.py
├── magic_wand_dockwidget_base.ui
├── metadata.txt
├── polygon_maker.py
├── resources.py
└── resources.qrc
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kanahiro/MagicWand/b6db7d557625aa323f90a106b38d53b179cca6e8/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | __pycache__/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MagicWand
2 | QGIS plugin to make polygon easily and automatically by analyzing MapCanvas.
3 |
4 | # Sample
5 | 
6 |
7 | # Usage
8 | - Set Accuracy and Color Threshold, and Click mapcanvas where you want to make polygon.
9 | - Single Mode enable you make ONE polygon around where you clicked.
10 | - Higher Accuracy needs longer time.
11 | - To make polygon apropriately, it is better adjust Saturation highly.
12 |
13 | # Contact
14 | kanahiro.iguchi@gmail.com
--------------------------------------------------------------------------------
/Utils.py:
--------------------------------------------------------------------------------
1 | from qgis.core import *
2 | from qgis.gui import *
3 | from qgis.PyQt.QtCore import QPoint
4 |
5 | class ClickTool(QgsMapTool):
6 | def __init__(self, iface, callback):
7 | QgsMapTool.__init__(self,iface.mapCanvas())
8 | self.iface = iface
9 | self.callback = callback
10 | self.canvas = iface.mapCanvas()
11 | self.drugging = False
12 | return None
13 |
14 | def canvasPressEvent(self,e):
15 | self.drugging = True
16 | point = QPoint(e.pos().x(),e.pos().y())
17 | self.callback(point)
18 | return None
19 | '''
20 | def canvasMoveEvent(self,e):
21 | if self.drugging == False:
22 | return None
23 | point = QPoint(e.pos().x(),e.pos().y())
24 | self.callback(point)
25 | return None
26 |
27 | def canvasReleaseEvent(self,e):
28 | point = QPoint(e.pos().x(),e.pos().y())
29 | self.callback(point)
30 | self.drugging = False
31 | return None
32 | '''
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | /***************************************************************************
4 | Magicwand
5 | A QGIS plugin
6 | Auto-making Polygon by MapCanvas
7 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
8 | -------------------
9 | begin : 2019-07-14
10 | copyright : (C) 2019 by Kanahiro Iguchi
11 | email : https://twitter.com/kigchi999
12 | git sha : $Format:%H$
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | This script initializes the plugin, making it known to QGIS.
24 | """
25 |
26 |
27 | # noinspection PyPep8Naming
28 | def classFactory(iface): # pylint: disable=invalid-name
29 | """Load Magicwand class from file Magicwand.
30 |
31 | :param iface: A QGIS interface instance.
32 | :type iface: QgsInterface
33 | """
34 | #
35 | from .magic_wand import Magicwand
36 | return Magicwand(iface)
37 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kanahiro/MagicWand/b6db7d557625aa323f90a106b38d53b179cca6e8/icon.png
--------------------------------------------------------------------------------
/image_analyzer.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | class ImageAnalyzer:
4 | def __init__(self, image):
5 | self.image = image
6 |
7 | def to_ndarray(self, resize_multiply):
8 | scaled_img = self.resize(self.image, resize_multiply).convertToFormat(4)
9 |
10 | width = scaled_img.width()
11 | height = scaled_img.height()
12 |
13 | ptr = scaled_img.constBits()
14 | ptr.setsize(scaled_img.byteCount())
15 | arr_rgba = np.array(ptr).reshape(height, width, 4)
16 | arr_rgb = np.delete(arr_rgba, 3, 2)
17 | return arr_rgb
18 | #arr_rgb structure
19 | #img = x1y1 x2y1 ... xny1
20 | # x1y2 x2y2 ... xny2
21 | # ...
22 | # x1yn x2yn ... xnyn
23 | #then ndarray is [[x1y1, x2y1 ... xny1],
24 | # [x1y2, x2y2 ... xny2],
25 | # [x1yn, x2yn ... xnyn]]
26 | #xnyn = [blue, green, red]
27 |
28 | def resize(self, image, resize_multiply):
29 | scaled_img = image.scaled(int(image.width() * resize_multiply), int(image.height() * resize_multiply))
30 | return scaled_img
31 |
32 | def to_binary(self, point, resize_multiply=0.2, threshold=50):
33 | red, green, blue = self.get_rgb(point)
34 | img_ndarray = self.to_ndarray(resize_multiply)
35 | abs_ndarray = abs(img_ndarray - [blue, green, red])
36 | sum_ndarray = abs_ndarray.sum(axis=2)
37 | max_ndarray = abs_ndarray.max(axis=2)
38 | true_index = sum_ndarray + max_ndarray*0.5 < threshold
39 | return true_index
40 |
41 | def get_rgb(self, point):
42 | pixelColor = self.image.pixelColor(point.x(), point.y())
43 | red_value = pixelColor.red()
44 | green_value = pixelColor.green()
45 | blue_value = pixelColor.blue()
46 | return (red_value, green_value, blue_value)
--------------------------------------------------------------------------------
/img/sample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kanahiro/MagicWand/b6db7d557625aa323f90a106b38d53b179cca6e8/img/sample.gif
--------------------------------------------------------------------------------
/magic_wand.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication, Qt, QSize
4 | from qgis.PyQt.QtGui import QIcon, QImage, QPainter
5 | from qgis.PyQt.QtWidgets import QAction, QMessageBox
6 | from qgis.core import QgsProject, QgsMapLayer, QgsRectangle, QgsPoint, QgsMultiBandColorRenderer, QgsRaster, QgsMapSettings, QgsMapRendererCustomPainterJob
7 | # Initialize Qt resources from file resources.py
8 | from .resources import *
9 |
10 | # Import the code for the DockWidget
11 | from .magic_wand_dockwidget import MagicwandDockWidget
12 | import os.path
13 |
14 | from .Utils import ClickTool
15 | from .image_analyzer import ImageAnalyzer
16 | from .polygon_maker import PolygonMaker
17 |
18 |
19 | class Magicwand:
20 | """QGIS Plugin Implementation."""
21 |
22 | def __init__(self, iface):
23 | """Constructor.
24 |
25 | :param iface: An interface instance that will be passed to this class
26 | which provides the hook by which you can manipulate the QGIS
27 | application at run time.
28 | :type iface: QgsInterface
29 | """
30 | # Save reference to the QGIS interface
31 | self.iface = iface
32 |
33 | self.canvas = iface.mapCanvas()
34 |
35 | # initialize plugin directory
36 | self.plugin_dir = os.path.dirname(__file__)
37 |
38 | # initialize locale
39 | locale = QSettings().value('locale/userLocale')[0:2]
40 | locale_path = os.path.join(
41 | self.plugin_dir,
42 | 'i18n',
43 | 'Magicwand_{}.qm'.format(locale))
44 |
45 | if os.path.exists(locale_path):
46 | self.translator = QTranslator()
47 | self.translator.load(locale_path)
48 | QCoreApplication.installTranslator(self.translator)
49 |
50 | # Declare instance attributes
51 | self.actions = []
52 | self.menu = self.tr(u'&Magic Wand')
53 | # TODO: We are going to let the user set this up in a future iteration
54 | self.toolbar = self.iface.addToolBar(u'Magicwand')
55 | self.toolbar.setObjectName(u'Magicwand')
56 |
57 | #print "** INITIALIZING Magicwand"
58 |
59 | self.pluginIsActive = False
60 | self.dockwidget = None
61 |
62 | self.output_layer = None
63 |
64 |
65 | # noinspection PyMethodMayBeStatic
66 | def tr(self, message):
67 | """Get the translation for a string using Qt translation API.
68 |
69 | We implement this ourselves since we do not inherit QObject.
70 |
71 | :param message: String for translation.
72 | :type message: str, QString
73 |
74 | :returns: Translated version of message.
75 | :rtype: QString
76 | """
77 | # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
78 | return QCoreApplication.translate('Magicwand', message)
79 |
80 |
81 | def add_action(
82 | self,
83 | icon_path,
84 | text,
85 | callback,
86 | enabled_flag=True,
87 | add_to_menu=True,
88 | add_to_toolbar=True,
89 | status_tip=None,
90 | whats_this=None,
91 | parent=None):
92 | """Add a toolbar icon to the toolbar.
93 |
94 | :param icon_path: Path to the icon for this action. Can be a resource
95 | path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
96 | :type icon_path: str
97 |
98 | :param text: Text that should be shown in menu items for this action.
99 | :type text: str
100 |
101 | :param callback: Function to be called when the action is triggered.
102 | :type callback: function
103 |
104 | :param enabled_flag: A flag indicating if the action should be enabled
105 | by default. Defaults to True.
106 | :type enabled_flag: bool
107 |
108 | :param add_to_menu: Flag indicating whether the action should also
109 | be added to the menu. Defaults to True.
110 | :type add_to_menu: bool
111 |
112 | :param add_to_toolbar: Flag indicating whether the action should also
113 | be added to the toolbar. Defaults to True.
114 | :type add_to_toolbar: bool
115 |
116 | :param status_tip: Optional text to show in a popup when mouse pointer
117 | hovers over the action.
118 | :type status_tip: str
119 |
120 | :param parent: Parent widget for the new action. Defaults None.
121 | :type parent: QWidget
122 |
123 | :param whats_this: Optional text to show in the status bar when the
124 | mouse pointer hovers over the action.
125 |
126 | :returns: The action that was created. Note that the action is also
127 | added to self.actions list.
128 | :rtype: QAction
129 | """
130 |
131 | icon = QIcon(icon_path)
132 | text = "Magic Wand"
133 | action = QAction(icon, text, parent)
134 | action.triggered.connect(callback)
135 | action.setEnabled(enabled_flag)
136 |
137 | if status_tip is not None:
138 | action.setStatusTip(status_tip)
139 |
140 | if whats_this is not None:
141 | action.setWhatsThis(whats_this)
142 |
143 | if add_to_toolbar:
144 | self.toolbar.addAction(action)
145 |
146 | if add_to_menu:
147 | self.iface.addPluginToVectorMenu(
148 | self.menu,
149 | action)
150 |
151 | self.actions.append(action)
152 |
153 | return action
154 |
155 |
156 | def initGui(self):
157 | """Create the menu entries and toolbar icons inside the QGIS GUI."""
158 |
159 | icon_path = ':/plugins/magic_wand/icon.png'
160 | self.add_action(
161 | icon_path,
162 | text=self.tr(u''),
163 | callback=self.run,
164 | parent=self.iface.mainWindow())
165 |
166 | #--------------------------------------------------------------------------
167 |
168 | def onClosePlugin(self):
169 | """Cleanup necessary items here when plugin dockwidget is closed"""
170 |
171 | #print "** CLOSING Magicwand"
172 |
173 | # disconnects
174 | self.dockwidget.closingPlugin.disconnect(self.onClosePlugin)
175 |
176 | # remove this statement if dockwidget is to remain
177 | # for reuse if plugin is reopened
178 | # Commented next statement since it causes QGIS crashe
179 | # when closing the docked window:
180 | # self.dockwidget = None
181 |
182 | self.pluginIsActive = False
183 |
184 |
185 | def unload(self):
186 | """Removes the plugin menu item and icon from QGIS GUI."""
187 |
188 | #print "** UNLOAD Magicwand"
189 |
190 | for action in self.actions:
191 | self.iface.removePluginVectorMenu(
192 | self.tr(u'&Magic Wand'),
193 | action)
194 | self.iface.removeToolBarIcon(action)
195 | # remove the toolbar
196 | del self.toolbar
197 |
198 | #--------------------------------------------------------------------------
199 |
200 | #actions on mapcanvas clicked
201 | def click_action(self, point):
202 | mapSettings = self.iface.mapCanvas().mapSettings()
203 | image = self.make_image(mapSettings)
204 | image_analyzer = ImageAnalyzer(image)
205 | #get slider value
206 | resize_multiply = self.dockwidget.accuracy_slider.value() / 100
207 | threshold = 100 - self.dockwidget.threshold_slider.value()
208 | bin_index = image_analyzer.to_binary(point, resize_multiply, threshold)
209 |
210 | polygon_maker = PolygonMaker(self.iface.mapCanvas(), bin_index)
211 | project_crs = QgsProject.instance().crs()
212 | single_mode = self.dockwidget.single_mode.isChecked()
213 | selected_layer_id = self.dockwidget.layerComboBox.currentData()
214 |
215 | polygon_maker.make_polygons(point, crs=project_crs, single_mode=single_mode, layer_id=selected_layer_id)
216 |
217 | selected_index = self.dockwidget.layerComboBox.currentIndex()
218 | self.reload_combo_box()
219 | self.dockwidget.layerComboBox.setCurrentIndex(selected_index)
220 | self.canvas.refreshAllLayers()
221 |
222 | return
223 |
224 | #make and return QImage from MapCanvas
225 | def make_image(self, mapSettings):
226 | image = QImage(mapSettings.outputSize(), QImage.Format_RGB32)
227 | p = QPainter()
228 | p.begin(image)
229 | mapRenderer = QgsMapRendererCustomPainterJob(mapSettings, p)
230 | mapRenderer.start()
231 | mapRenderer.waitForFinished()
232 | p.end()
233 | return image
234 |
235 | def enable_magicwand(self):
236 | ct = ClickTool(self.iface, self.click_action)
237 | self.previous_map_tool = self.iface.mapCanvas().mapTool()
238 | self.iface.mapCanvas().setMapTool(ct)
239 |
240 | def init_sliders(self):
241 | self.dockwidget.accuracy_slider.setMinimum(20)
242 | self.dockwidget.accuracy_slider.setMaximum(100)
243 | self.dockwidget.accuracy_slider.setSingleStep(20)
244 | self.dockwidget.accuracy_slider.setValue(60)
245 |
246 | self.dockwidget.threshold_slider.setMinimum(10)
247 | self.dockwidget.threshold_slider.setMaximum(90)
248 | self.dockwidget.threshold_slider.setSingleStep(10)
249 | self.dockwidget.threshold_slider.setValue(50)
250 |
251 | def reload_combo_box(self):
252 | self.dockwidget.layerComboBox.clear()
253 | self.dockwidget.layerComboBox.addItem('===New Layer===',0)
254 | layers = QgsProject.instance().mapLayers()
255 | for key, layer in layers.items():
256 | if layer.type() == QgsMapLayer.VectorLayer:
257 | #key is ID of each layers
258 | self.dockwidget.layerComboBox.addItem(layer.name(),key)
259 |
260 | def run(self):
261 | """Run method that loads and starts the plugin"""
262 |
263 | if not self.pluginIsActive:
264 | self.pluginIsActive = True
265 |
266 | #print "** STARTING Magicwand"
267 |
268 | # dockwidget may not exist if:
269 | # first run of plugin
270 | # removed on close (see self.onClosePlugin method)
271 | if self.dockwidget == None:
272 | # Create the dockwidget (after translation) and keep reference
273 | self.dockwidget = MagicwandDockWidget()
274 |
275 | # connect to provide cleanup on closing of dockwidget
276 | self.dockwidget.closingPlugin.connect(self.onClosePlugin)
277 |
278 | # show the dockwidget
279 | self.iface.addDockWidget(Qt.TopDockWidgetArea, self.dockwidget)
280 | self.dockwidget.show()
281 |
282 | ct = ClickTool(self.iface, self.click_action)
283 | self.previous_map_tool = self.iface.mapCanvas().mapTool()
284 | self.iface.mapCanvas().setMapTool(ct)
285 |
286 | self.dockwidget.enable_button.clicked.connect(self.enable_magicwand)
287 |
288 | QgsProject.instance().layersAdded.connect(self.reload_combo_box)
289 | QgsProject.instance().layersRemoved.connect(self.reload_combo_box)
290 | self.reload_combo_box()
291 | self.init_sliders()
--------------------------------------------------------------------------------
/magic_wand_dockwidget.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import os
4 |
5 | from qgis.PyQt import QtGui, QtWidgets, uic
6 | from qgis.PyQt.QtCore import pyqtSignal
7 |
8 | FORM_CLASS, _ = uic.loadUiType(os.path.join(
9 | os.path.dirname(__file__), 'magic_wand_dockwidget_base.ui'))
10 |
11 |
12 | class MagicwandDockWidget(QtWidgets.QDockWidget, FORM_CLASS):
13 |
14 | closingPlugin = pyqtSignal()
15 |
16 | def __init__(self, parent=None):
17 | """Constructor."""
18 | super(MagicwandDockWidget, self).__init__(parent)
19 | # Set up the user interface from Designer.
20 | # After setupUI you can access any designer object by doing
21 | # self., and you can use autoconnect slots - see
22 | # http://doc.qt.io/qt-5/designer-using-a-ui-file.html
23 | # #widgets-and-dialogs-with-auto-connect
24 | self.setupUi(self)
25 |
26 | def closeEvent(self, event):
27 | self.closingPlugin.emit()
28 | event.accept()
29 |
--------------------------------------------------------------------------------
/magic_wand_dockwidget_base.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MagicwandDockWidgetBase
4 |
5 |
6 |
7 | 0
8 | 0
9 | 342
10 | 119
11 |
12 |
13 |
14 | Magic Wand
15 |
16 |
17 |
18 | -
19 |
20 |
21 | Enable
22 |
23 |
24 |
25 | -
26 |
27 |
28 | Fast
29 |
30 |
31 |
32 | -
33 |
34 |
35 | Accuracy
36 |
37 |
38 |
39 | -
40 |
41 |
42 | Color Threshold
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Ambiguous
50 |
51 |
52 |
53 | -
54 |
55 |
56 | Qt::Horizontal
57 |
58 |
59 |
60 | -
61 |
62 |
63 | Qt::Horizontal
64 |
65 |
66 |
67 | -
68 |
69 |
70 | Precise
71 |
72 |
73 |
74 | -
75 |
76 |
77 | Single Mode
78 |
79 |
80 |
81 | -
82 |
83 |
84 | Strict
85 |
86 |
87 |
88 | -
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/metadata.txt:
--------------------------------------------------------------------------------
1 | # This file contains metadata for your plugin.
2 |
3 | # This file should be included when you package your plugin.# Mandatory items:
4 |
5 | [general]
6 | name=Magic Wand
7 | qgisMinimumVersion=3.0
8 | description=Auto-making Polygon by MapCanvas
9 | version=1.3.2
10 | author=Kanahiro Iguchi
11 | email=kanahiro.iguchi@gmail.com
12 |
13 | about=QGIS plugin to make polygon easily and automatically by analysing MapCanvas.
14 |
15 | tracker=https://github.com/Kanahiro/MagicWand/issues
16 | repository=https://github.com/Kanahiro/MagicWand
17 | # End of mandatory metadata
18 |
19 | # Recommended items:
20 |
21 | hasProcessingProvider=no
22 | # Uncomment the following line and add your changelog:
23 | # changelog=
24 |
25 | # Tags are comma separated with spaces allowed
26 | tags=python
27 |
28 | homepage=https://kiguchi999.hatenablog.com/
29 | category=Vector
30 | icon=icon.png
31 | # experimental flag
32 | experimental=False
33 |
34 | # deprecated flag (applies to the whole plugin, not just a single version)
35 | deprecated=False
36 |
37 | # Since QGIS 3.8, a comma separated list of plugins to be installed
38 | # (or upgraded) can be specified.
39 | # Check the documentation for more information.
40 | # plugin_dependencies=
41 |
42 | Category of the plugin: Raster, Vector, Database or Web
43 | # category=
44 |
45 | # If the plugin can run on QGIS Server.
46 | server=False
47 |
48 |
--------------------------------------------------------------------------------
/polygon_maker.py:
--------------------------------------------------------------------------------
1 | from qgis.core import QgsProject, QgsRectangle, QgsVectorLayer, QgsFeature, QgsGeometry, QgsCoordinateTransform
2 | import processing
3 | import numpy as np
4 |
5 | class PolygonMaker:
6 | def __init__(self, canvas, bin_index):
7 | self.bin_index = bin_index
8 | self.map_canvas = canvas
9 | self.size_multiply = self.map_canvas.width() / self.bin_index.shape[1]
10 | self.minimum_area = self.make_rect(0,0, self.size_multiply).area()
11 | self.noise_multiply = 40
12 |
13 | def make_polygons(self, point, crs, single_mode=False, layer_id=None):
14 | rects = self.make_rects()
15 | rects_layer = self.make_layer_by(rects, crs)
16 |
17 | dissolved_layer = processing.run('qgis:dissolve', {'INPUT':rects_layer,'OUTPUT':'memory:'})['OUTPUT']
18 | single_part_layer = processing.run('qgis:multiparttosingleparts', {'INPUT':dissolved_layer,'OUTPUT':'memory:'})['OUTPUT']
19 | single_features = single_part_layer.getFeatures()
20 |
21 | if single_mode:
22 | for feature in single_features:
23 | if feature.geometry().contains(self.map_canvas.getCoordinateTransform().toMapPoint(point.x(), point.y())):
24 | single_features = [feature]
25 | break
26 |
27 | denoised_features = self.noise_reduction(single_features, self.noise_multiply)
28 | denoised_layer = self.make_layer_by(denoised_features, crs)
29 | cleaned_layer = processing.run('qgis:deleteholes', {'INPUT':denoised_layer, 'MIN_AREA':self.minimum_area * self.size_multiply * self.noise_multiply, 'OUTPUT':'memory:'})['OUTPUT']
30 | cleaned_features = cleaned_layer.getFeatures()
31 |
32 | #output layer
33 | output = QgsVectorLayer('Polygon?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', 'magic_wand', 'memory')
34 | if layer_id:
35 | output = QgsProject.instance().mapLayer(layer_id)
36 |
37 | output_provider = output.dataProvider()
38 | output_provider.addFeatures(cleaned_features)
39 |
40 | QgsProject.instance().addMapLayer(output)
41 |
42 | #make rectangle geometry by pointXY on Pixels
43 | def make_rect(self, x, y, size_multiply, count=0):
44 | pointTopLeft = self.map_canvas.getCoordinateTransform().toMapPoint(x * size_multiply, y * size_multiply)
45 | pointBottomRight = self.map_canvas.getCoordinateTransform().toMapPoint((x + count + 1) * size_multiply, (y + 1) * size_multiply)
46 |
47 | geo = QgsGeometry.fromRect(QgsRectangle(pointTopLeft.x(), pointTopLeft.y(), pointBottomRight.x(), pointBottomRight.y()))
48 | return geo
49 |
50 | def make_rects(self):
51 | #make 2d array including only TRUE pixel index
52 | #true_points[0]:y axis indexes
53 | #true_points[1]:x axis indexes
54 | true_points = np.where(self.bin_index)
55 |
56 | #rectangle making sequence
57 | geos = []
58 | #when neighbor pixel also true, incliment this count
59 | connectedCount = 0
60 | for i in range(len(true_points[0])):
61 | #skip loops same number to the count
62 | if connectedCount > 0:
63 | connectedCount = connectedCount - 1
64 | continue
65 |
66 | x = true_points[1][i]
67 | y = true_points[0][i]
68 |
69 | #when the final loop
70 | if i >= len(true_points[0]) - 1:
71 | geos.append(self.make_rect(x, y, self.size_multiply))
72 | break
73 |
74 | #calculate connectedCount
75 | while true_points[1][i + connectedCount + 1] - true_points[1][i + connectedCount] == 1:
76 | connectedCount = connectedCount + 1
77 | if i + connectedCount + 1 >= len(true_points[0]) - 1:
78 | break
79 |
80 | geos.append(self.make_rect(x, y, self.size_multiply, connectedCount))
81 |
82 | rects = []
83 | for geo in geos:
84 | rect = QgsFeature()
85 | rect.setGeometry(geo)
86 | rects.append(rect)
87 | return rects
88 |
89 | def make_layer_by(self, features, crs):
90 | features_layer = QgsVectorLayer('Polygon?crs=' + crs.authid() + '&field=MYNYM:integer&field=MYTXT:string', 'magic_wand', 'memory')
91 | features_layer_provider = features_layer.dataProvider()
92 | features_layer_provider.addFeatures(features)
93 | return features_layer
94 |
95 | def noise_reduction(self, features, noise_multiply, torel_multiply=2.5):
96 | output = []
97 | torelance = self.map_canvas.mapUnitsPerPixel() * torel_multiply * self.size_multiply ** 0.6
98 | for feature in features:
99 | if feature.geometry().area() < self.minimum_area * noise_multiply:
100 | continue
101 | output_geo = feature.geometry().simplify(torelance)
102 | output_feature = QgsFeature()
103 | output_feature.setGeometry(output_geo)
104 | output.append(output_feature)
105 |
106 | return output
--------------------------------------------------------------------------------
/resources.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Resource object code
4 | #
5 | # Created by: The Resource Compiler for PyQt5 (Qt v5.9.6)
6 | #
7 | # WARNING! All changes made in this file will be lost!
8 |
9 | from PyQt5 import QtCore
10 |
11 | qt_resource_data = b"\
12 | \x00\x00\x0c\x14\
13 | \x89\
14 | \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
15 | \x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
16 | \x00\x00\x0b\xdb\x49\x44\x41\x54\x78\x5e\xed\x9d\x7f\xac\x5c\x45\
17 | \x15\xc7\xcf\xb9\xfb\x2a\xbc\xdd\x06\x2a\x69\xc5\x54\x21\x44\xf9\
18 | \x91\x48\x4c\x2d\x82\x11\x8a\xb2\x60\xdb\xd7\x3b\xb3\x6b\x5a\xda\
19 | \xa7\x62\x82\x02\xa2\xd4\x04\x14\xa8\x28\x3f\xfe\x40\xff\x90\x20\
20 | \xa8\x68\xa2\x52\x0c\x88\x28\x6a\xe3\x93\x40\xfa\x76\x66\xf7\xbd\
21 | \xf6\xc9\xca\x0f\x21\x28\x15\xd1\x98\x58\xc1\x20\xfe\xd1\xb4\xd8\
22 | \x8a\xa9\xef\x99\x47\xf7\xdd\x63\xa6\xdc\x85\xed\x76\xdf\xdb\x7b\
23 | \xe7\xde\x9d\xbd\x77\xef\xdc\x7f\xda\xe4\xcd\x39\x67\xe6\x7c\x3f\
24 | \x77\xee\xdc\xb9\xb3\x33\x08\xf6\xca\x74\x06\x30\xd3\xad\xb7\x8d\
25 | \x07\x0b\x40\xc6\x21\xb0\x00\x58\x00\x32\x9e\x81\x8c\x37\xdf\xf6\
26 | \x00\x16\x80\x8c\x67\x20\xe3\xcd\xb7\x3d\x40\x0c\x00\x94\xcb\xe5\
27 | \xa5\x07\x0f\x1e\x6c\xd4\xeb\xf5\x57\x63\x70\x67\xd4\x85\x05\x20\
28 | \x62\xba\x8b\xc5\xe2\x50\x3e\x9f\x7f\x19\x11\xbd\xe9\xe9\xe9\x53\
29 | \xea\xf5\x7a\x23\xa2\x4b\xa3\xe6\x16\x80\x88\xe9\x2e\x95\x4a\x45\
30 | \x22\x7a\x54\xb9\xf1\x3c\xef\xfc\x6a\xb5\xfa\x64\x44\x97\x46\xcd\
31 | \x2d\x00\x11\xd3\xcd\x39\xff\x3a\x00\xdc\xac\xdc\x10\xd1\x57\xa5\
32 | \x94\x5f\x8b\xe8\xd2\xa8\xb9\x05\x20\x62\xba\x19\x63\xcf\x20\xe2\
33 | \x39\x3e\x00\x4f\x4a\x29\xcf\x8f\xe8\xd2\xa8\xb9\x05\x20\x42\xba\
34 | \x8b\xc5\xe2\x92\x7c\x3e\x7f\x00\x11\x0f\xe7\x91\x88\x1a\x8d\x46\
35 | \x63\xc9\xe4\xe4\xe4\x74\x04\xb7\x46\x4d\x2d\x00\x11\xd2\xed\xba\
36 | \xee\x26\xc7\x71\xc6\x5a\x5d\x78\x9e\xf7\xd1\x6a\xb5\x3a\x1e\xc1\
37 | \xad\x51\x53\x0b\x40\x84\x74\x73\xce\x7f\x08\x00\x9f\x6d\x75\x41\
38 | \x44\xdf\x97\x52\x5e\x1d\xc1\xad\x51\x53\x0b\x80\x66\xba\x5d\xd7\
39 | \x3d\x06\x11\xf7\x21\xe2\x71\x6d\x2e\xf6\x7b\x9e\xf7\x8e\x6a\xb5\
40 | \x3a\xab\xe9\xda\xa8\x99\x05\x40\x33\xdd\x8c\xb1\x9b\x10\xf1\xb6\
41 | \x79\xcc\x6f\x14\x42\x7c\x43\xd3\xb5\x51\x33\x0b\x80\x46\xba\x5d\
42 | \xd7\x2d\x3b\x8e\xf3\x08\x00\x38\x9d\xcc\xd5\x60\x10\x11\xd7\x0b\
43 | \x21\x84\x86\x7b\xa3\x26\x16\x80\x10\xe9\x76\x5d\xf7\xdd\x8e\xe3\
44 | \x6c\x26\xa2\x2d\xcd\x91\xff\x02\xe6\x1e\x11\xdd\x41\x44\xf7\x56\
45 | \xab\xd5\x17\x43\x84\x31\x5a\xd4\x02\xb0\x40\xba\x8b\xc5\xe2\xe2\
46 | \xe1\xe1\xe1\x0b\x1d\xc7\x59\x4b\x44\x6b\x11\xf1\x74\x1d\x75\x88\
47 | \x68\x37\x22\x4e\x10\xd1\x64\x2e\x97\xfb\xf5\xf8\xf8\xf8\x8c\x8e\
48 | \x9f\x5e\xd8\x58\x00\xda\xb2\x3a\x32\x32\x72\xe6\xd0\xd0\xd0\x7a\
49 | \x25\x38\x00\x9c\x87\x88\x43\x71\x26\x9e\x88\x0e\x01\xc0\x6f\x01\
50 | \x60\xc2\xf3\xbc\x5f\xd4\x6a\xb5\x97\xe2\xf4\x1f\xd6\x97\x05\xa0\
51 | \x25\x63\xa3\xa3\xa3\x6f\x99\x99\x99\x51\x77\x67\x2e\x6c\x22\x75\
52 | \xca\x13\xd1\x2b\x33\x33\x33\xcb\xfb\xf9\x01\xc9\x02\xd0\xa6\x1c\
53 | \xe7\xfc\x2e\x00\xf8\x1c\x00\xe4\x75\x44\x0d\x61\x33\x43\x44\x0f\
54 | \x49\x29\x3f\x15\xc2\x26\xf6\xa2\x16\x80\x0e\x29\xf5\x7b\x82\x55\
55 | \xfe\x73\x5f\x3d\xff\x57\x06\x18\xf4\x2d\x28\x0e\x11\x11\x22\xee\
56 | \x52\xe3\x00\xc7\x71\x26\xf7\xec\xd9\xf3\xe4\xb3\xcf\x3e\xab\x1e\
57 | \x07\x7d\xbd\x2c\x00\x01\xd2\xef\xba\xee\x32\x44\x5c\x83\x88\x2e\
58 | \x00\x6c\x04\x80\xe1\x00\x66\xaa\xc8\xff\x00\xe0\x21\x00\x10\x8d\
59 | \x46\x63\x72\x62\x62\xe2\x40\x40\x3b\x63\xc5\x22\x01\xc0\x39\xbf\
60 | \x99\x88\x4e\x22\xa2\x6b\xd3\x32\xf3\x15\x35\xb3\x3e\x0c\xdb\x11\
61 | \xf1\x83\x0b\xf9\x22\xa2\xa7\x67\x67\x67\x4b\x53\x53\x53\xfb\xa3\
62 | \xc6\xec\xa5\xbd\x36\x00\xfe\x3b\xf1\x0b\x7e\xe5\x2e\x11\x42\x6c\
63 | \xeb\x65\x45\x93\xe4\xbb\x58\x2c\x1e\x5b\x28\x14\x9e\x06\x80\x15\
64 | \x9d\xea\x45\x44\xcf\xef\xdd\xbb\xf7\xec\x24\x74\xf1\xdd\xf2\xa6\
65 | \x0d\x00\x63\xec\x2a\x44\xdc\xaa\x02\x10\xd1\x7d\x52\xca\x2b\xbb\
66 | \x05\x1b\xa4\xbf\xfb\xaf\x8b\x7f\xee\xd4\x26\xcf\xf3\xce\xac\x56\
67 | \xab\x7f\x49\x43\x7b\xb5\x01\xe0\x9c\xab\xcf\xa0\x9b\x7c\x00\xfe\
68 | \x29\xa5\x3c\x39\x0d\x0d\x8e\xb3\x8e\x8c\xb1\x27\x10\x71\x55\xab\
69 | \x4f\x22\x7a\x4c\x4a\x79\x41\x9c\x71\x7a\xe9\x4b\x17\x00\xe4\x9c\
70 | \xab\x01\xcd\x92\x66\xe5\x1a\x8d\xc6\x69\x13\x13\x13\xcd\x47\x42\
71 | \x2f\xeb\x9c\x18\xdf\x8c\xb1\x1b\x10\xf1\x8e\x36\x00\xae\x97\x52\
72 | \xaa\x57\xc9\x54\x5c\x5a\x00\x70\xce\xdf\x0f\x00\xbf\x6f\x6b\xf8\
73 | \xe7\xa5\x94\x87\x1f\x09\x59\xb9\x5c\xd7\x5d\xe9\x38\xce\xae\xb6\
74 | \xf6\xbe\x57\x08\xd1\xf1\xd1\x90\xc4\xbc\xe8\x02\xf0\x15\x00\xb8\
75 | \xbd\x0d\x00\x35\xa9\x71\xf8\x91\x90\xa5\x8b\x73\xfe\xef\x66\x4f\
76 | \x48\x44\xfb\xa4\x94\x27\xa6\xa9\xfd\xba\x00\xec\x00\x80\xd5\x6d\
77 | \x0d\x7d\x55\x08\x71\x82\x1a\x13\xf6\x3b\x01\x6a\xa9\x76\xa5\x52\
78 | \xa9\x9b\xa8\x07\x63\x6c\x1b\x22\x7e\xdc\x1f\x0b\xfd\x44\x4a\xf9\
79 | \x69\x13\x71\xe3\x8a\x11\x1a\x00\xd7\x75\x8f\xf3\x57\xc2\x1c\xd3\
80 | \x5e\x09\x22\xba\x40\x4a\xf9\x58\x5c\x95\xd3\xf1\xc3\x18\xbb\x0c\
81 | \x11\xef\x27\xa2\x1f\x4b\x29\x2f\xd7\xf1\x11\xc6\x86\x73\xfe\x19\
82 | \x00\xb8\xd7\xb7\xb9\x54\x08\xf1\x60\x18\xfb\x7e\x97\x0d\x0d\x00\
83 | \x63\xec\x0b\x88\xf8\xdd\x79\x2a\xfe\xa0\x10\xe2\xd2\x7e\x35\xaa\
84 | \x29\x7e\x33\xbe\x09\x08\xd6\xae\x5d\x7b\xd2\xa2\x45\x8b\x5e\x56\
85 | \x31\x0f\x1d\x3a\x74\xe2\xe4\xe4\xe4\xbe\x7e\xb5\x5f\x27\x6e\x28\
86 | \x00\xfc\xc9\x1f\x35\xf8\x7b\x63\xf4\xdf\x36\x0e\x68\x38\x8e\xb3\
87 | \xaa\x52\xa9\x3c\xa3\x53\x99\x28\x36\xed\xe2\x9b\x84\x80\x73\x7e\
88 | \x0b\x00\x34\xd2\xb2\x0c\xac\x35\xcf\x81\x01\xe0\x9c\xbf\x0b\x00\
89 | \xd4\x4f\xa0\xba\xbd\xef\xab\xbb\xe1\x42\x21\xc4\xdf\xa3\x08\x1a\
90 | \xc6\x76\x3e\xf1\x4d\x42\x10\xa6\xbe\x49\x2a\xdb\x15\x00\xff\xc7\
91 | \x8f\x1f\x43\xc4\xef\x01\xc0\x5b\x03\x56\x5e\x7d\x53\xbf\x75\x7a\
92 | \x7a\x7a\x6b\xbd\x5e\xff\x6f\x40\x1b\xad\x62\xdd\xc4\xb7\x10\x2c\
93 | \x9c\xd6\x8e\x00\xa8\xa5\x50\xf9\x7c\xbe\x88\x88\xea\x53\xe8\x06\
94 | \x44\x7c\xa7\x96\x3a\x00\x07\x89\xe8\x61\xb5\xfa\x65\x76\x76\x76\
95 | \x22\xee\x0f\x23\x41\xc5\xb7\x10\xcc\xaf\x5e\x13\x00\x35\xb3\x77\
96 | \x56\xcb\xf7\xef\x55\x88\xb8\x48\x53\xf4\x8e\x66\xea\x7b\x38\x00\
97 | \x3c\x87\x88\x93\x9e\xe7\x4d\x2e\x5e\xbc\xf8\x89\xb1\xb1\xb1\xd7\
98 | \x74\x63\x84\x15\xdf\x42\xd0\x39\xd3\xc8\x18\xfb\x22\x22\xde\x1a\
99 | \xa2\x7b\xd7\xd5\xac\xdd\x4e\x7d\x2b\xaf\xe5\xf3\xf9\x4f\x84\x05\
100 | \x41\x57\x7c\x0b\xc1\xd1\xd2\x29\x00\xf6\x20\xe2\xdb\xe3\x52\x35\
101 | \xac\x9f\x46\xa3\xb1\x7c\x62\x62\x62\x4f\x50\xbb\xa8\xe2\x5b\x08\
102 | \x8e\xcc\xb4\xea\xfa\xcf\x03\x80\x6b\x88\x48\x3d\xf3\x4d\x81\xa0\
103 | \xb6\x52\x51\x1b\x29\xa8\x79\x83\xc0\xeb\x08\xe2\x12\xdf\x42\xf0\
104 | \x26\x04\x47\x0c\x02\xfd\x57\xbd\x0f\x01\xc0\x87\x01\x40\xfd\x7b\
105 | \x5a\xd0\x3b\x73\xa1\x72\x44\xa4\xee\xf0\xc7\x89\xe8\xf1\x5c\x2e\
106 | \xf7\x78\xa5\x52\x79\x3e\xec\x94\x71\xdc\xe2\x5b\x08\x5e\xcf\xc0\
107 | \x82\xaf\x81\xfe\xf2\xa7\x8b\x01\xe0\x3a\x44\x3c\x23\x0c\x0c\xea\
108 | \xc3\x08\x00\xfc\xc0\xf3\xbc\x6d\xb5\x5a\xed\xaf\x61\x6c\xdb\xcb\
109 | \xf6\x4a\x7c\x0b\x41\x17\x00\x5a\x84\x50\x8f\x8a\x2d\x44\x74\x5b\
110 | \x90\xb7\x03\xb5\x28\x62\x68\x68\xa8\xb4\x7d\xfb\xf6\x83\x51\x84\
111 | \x57\xb6\xbd\x16\x3f\xeb\x10\x74\x9d\x08\x6a\x15\x90\x31\xf6\x49\
112 | \x44\xfc\x59\x97\xee\xbe\xb2\x77\xef\xde\x8b\xe3\x5a\x0f\x67\x0a\
113 | \x00\x00\x78\x40\x08\x71\x59\x54\x60\xd3\x66\x1f\x0a\x00\xd5\x38\
114 | \xce\xf9\x2f\x01\x60\x74\x9e\x86\xfe\xed\xc0\x81\x03\x2b\x9e\x7a\
115 | \xea\x29\xf5\x8a\x17\xdb\x65\x00\x82\x4c\x8a\xdf\x75\x0c\xd0\x49\
116 | \x41\xd7\x75\x57\x39\x8e\xf3\xc4\x3c\xea\x5e\x27\x84\xf8\x4e\x6c\
117 | \xca\xb7\x38\xea\x21\x04\x99\x15\x5f\x0b\x00\xbf\x17\x50\x3f\x77\
118 | \x56\x1f\x87\x8e\xb8\x1c\xc7\x59\x36\x3e\x3e\xfe\xaf\x5e\x00\xd0\
119 | \xa3\xf1\x40\xa6\xc5\xd7\x06\x80\x31\xb6\x15\x11\xaf\x6a\x15\x9a\
120 | \x88\xfe\x20\xa5\x3c\xab\x57\xe2\x37\xfd\xc6\xd8\x13\x64\x5e\x7c\
121 | \x6d\x00\x38\xe7\x6a\x0c\xa0\xc6\x02\x6f\x5c\x44\x74\xa7\x94\xf2\
122 | \xcb\xbd\x06\x20\xa6\x9e\xc0\x8a\xef\x0b\x15\x7a\x10\xe8\x3f\x02\
123 | \xd4\x67\xe1\x23\x7e\xe7\xe6\x79\xde\x48\xb5\x5a\x9d\x34\x01\x40\
124 | \x44\x08\x42\x8b\xbf\x7a\xf5\xea\xe3\x77\xee\xdc\xf9\x1f\x53\x6d\
125 | \x33\x19\x47\x0b\x00\x5f\x80\x5d\x88\xb8\x52\xfd\x5f\xed\x89\x43\
126 | \x44\x8b\x4d\xff\x3e\x50\xe3\x71\x10\x5a\x7c\x7f\x33\x48\xb5\x10\
127 | \xe6\xf9\xb4\x2d\xf8\x0c\x02\x92\x36\x00\x9c\xf3\x3b\x01\xe0\x4b\
128 | \x3e\x00\x8f\x4a\x29\x2f\x0a\x12\x30\xee\x32\x21\x20\xd0\x16\x1f\
129 | \x11\xdf\xe7\xb7\x33\x75\xab\x7e\xbb\xe5\x5b\x1b\x00\xc6\xd8\x3a\
130 | \x44\xac\xfa\x01\x6e\x11\x42\xcc\xb7\x65\x5a\xb7\x3a\x44\xfe\x7b\
131 | \x00\x08\x22\x8b\xdf\xac\x24\x11\x0d\x14\x04\xda\x00\x94\xcb\xe5\
132 | \xfc\xdc\xdc\xdc\x4b\x88\xb8\x0c\x00\xfa\xfe\x6b\x98\x05\x20\x88\
133 | \x4d\xfc\x41\x84\x40\x1b\x00\x95\x8c\x75\xeb\xd6\x9d\x92\xcb\xe5\
134 | \xce\x11\x42\x1c\xb1\x5f\x6e\xe4\x5b\x5a\xd3\x41\x07\x08\x62\x17\
135 | \xbf\x15\x82\x42\xa1\x70\xc5\xd8\xd8\xd8\x9c\x66\x75\x13\x61\x16\
136 | \x09\x80\x44\xb4\xa0\xad\x12\x2d\x10\xf4\x4c\xfc\x96\x90\x0f\xe7\
137 | \xf3\xf9\xd1\x34\x43\x30\x70\x00\x28\x71\x74\x7e\x1a\xd6\x1c\xed\
138 | \x37\x07\x7c\x21\xe0\x4e\x35\x04\x03\x09\x40\x08\xf1\x0e\x17\x8d\
139 | \x20\x7e\x33\x54\x6a\x21\xc8\x3c\x00\x31\x88\x9f\x6a\x08\x32\x0d\
140 | \x40\x8c\xe2\xa7\x16\x82\xcc\x02\xd0\x03\xf1\x53\x09\x41\x26\x01\
141 | \xe8\xa1\xf8\xa9\x83\x20\x73\x00\x18\x10\x3f\x55\x10\x64\x0e\x00\
142 | \xd7\x75\xd7\x3b\x8e\xa3\x7e\xaf\xd8\xf3\xcb\xdf\x0b\x38\xd1\xdb\
143 | \xe6\x64\x0e\x00\xa5\x3a\x63\x4c\x6d\x62\xf1\x40\xd4\xfd\x7f\x03\
144 | \x12\x94\xe8\x57\xc4\x4c\x02\x60\x21\x78\x13\xdd\xcc\x02\x60\x21\
145 | \x78\x1d\x82\x4c\x03\x60\x21\xb0\x00\x1c\xbe\x0b\xb2\x3c\x26\xc8\
146 | \x7c\x0f\xd0\x7c\x1a\x66\x15\x02\x0b\x40\xcb\x50\x3e\x8b\x10\x58\
147 | \x00\x8e\x5e\x4f\x90\xa9\x57\x44\x0b\x40\x87\x97\xf9\x2c\xf5\x04\
148 | \x16\x80\x79\x66\x73\xb2\x02\x81\x05\x60\x81\xe9\xbc\x2c\x40\x60\
149 | \x01\xe8\x32\x9f\x3b\xe8\x10\x58\x00\x02\x4c\xe8\x0f\x32\x04\xa9\
150 | \x05\x80\x31\x76\x23\x00\x9c\x61\x62\x4b\xf8\x41\x9e\x2c\x4a\x2d\
151 | \x00\x9c\xf3\xdd\x44\x74\x32\x11\x1d\x6f\xea\x37\x89\x83\xd8\x13\
152 | \xa4\x12\x80\x72\xb9\x7c\xb2\xe7\x79\xff\x50\x77\xe6\xdc\xdc\xdc\
153 | \xea\x5a\xad\x36\x15\xa0\x27\x8f\xa5\xc8\xa0\x41\x90\x4a\x00\x38\
154 | \xe7\x57\x00\xc0\x7d\x4a\x51\x22\xba\x5d\x4a\x79\x53\x2c\xea\x06\
155 | \x74\x32\x48\x10\xa4\x12\x00\xc6\xd8\xcf\x11\xf1\x12\x1f\x80\xdf\
156 | \x49\x29\x3f\x10\x50\xbb\xd8\x8a\x0d\x0a\x04\xa9\x03\x40\x9d\x5f\
157 | \x50\x28\x14\xd4\xce\xa3\x4b\x7d\x00\x28\x97\xcb\xbd\xad\x97\x7b\
158 | \x13\xcd\x47\xcd\x20\x40\x90\x3a\x00\x18\x63\x9b\x11\xf1\xee\x36\
159 | \x51\x6e\x10\x42\x7c\x33\xb6\xdb\x3b\x84\x23\x1f\x82\x1f\x21\xe2\
160 | \x50\x08\x33\xdd\xa2\xb1\x2f\x2f\x4b\x15\x00\x8c\xb1\xb3\x11\xf1\
161 | \x37\x00\x90\x6f\xcb\xe0\x6b\x44\xb4\x51\x4a\x59\xd1\xcd\x6c\x14\
162 | \x3b\xb5\xd0\x14\x11\xc7\xd2\x08\x41\x2a\x00\x70\x5d\xf7\x3d\x8e\
163 | \xe3\x5c\x4e\x44\xd7\x20\xe2\x51\xc7\xd5\x35\x1f\x05\xea\xb8\x38\
164 | \xb5\x3f\xb1\x10\x42\x9d\xe6\x69\xf4\xfc\xc2\xb4\x42\x90\x48\x00\
165 | \x5c\xd7\x55\x47\xd4\x5c\x84\x88\x1f\x41\x44\x75\x40\xe5\xf2\x90\
166 | \x77\xe8\x7e\x22\xaa\x23\xe2\x14\x11\x4d\x49\x29\x77\x87\xb4\xd7\
167 | \x2a\x9e\x46\x08\x12\x07\x80\xeb\xba\x9b\x1c\xc7\x89\x75\xc3\x09\
168 | \x22\xba\x4b\x4a\x79\xbd\x96\xaa\x21\x8d\xd2\x06\x41\x12\x01\x50\
169 | \x5d\xfc\x26\x75\xf7\x03\xc0\x1a\xdd\x03\xab\x88\xe8\x15\x75\xcc\
170 | \x9d\xea\x05\x00\x60\x4c\x08\xa1\xce\xf8\x35\x72\xa5\x09\x82\xc4\
171 | \x01\xd0\xae\xd0\xc8\xc8\xc8\xa9\x43\x43\x43\xea\xf4\xb2\x2b\x9b\
172 | \xdb\xd2\x2d\xa0\xe2\x0b\x9e\xe7\x6d\x25\xa2\x1d\xb5\x5a\xed\x4f\
173 | \xa6\xc7\x01\xad\xf5\x4a\x0b\x04\x89\x07\xa0\x35\xa9\x9c\xf3\x6b\
174 | \x01\xe0\x5b\x00\xe0\x74\x80\xe0\x6e\x21\xc4\xd5\x00\xe0\x19\xb9\
175 | \xcd\x03\x04\xe9\x03\x04\xa1\x0f\xe0\x4a\x15\x00\x2a\xe7\x8c\x31\
176 | \x75\x7a\xc9\xb7\xdb\xf2\xbf\x53\x08\xb1\x26\x80\x26\xc6\x8b\x98\
177 | \x84\x40\xf5\x7c\x85\x42\xa1\x14\xe6\x14\xb6\xd4\x01\x50\x2c\x16\
178 | \x8f\x2d\x14\x0a\x6a\x9b\xda\xe1\xa6\x9a\x6a\x5f\x9f\x4a\xa5\xf2\
179 | \x47\xe3\xea\x06\x0c\x98\x64\x08\x52\x07\x80\xdf\x0b\x48\x44\x74\
180 | \xfd\xf7\xff\x17\xa5\x94\xa7\x06\xd4\xa2\x6f\xc5\x92\x0a\x41\x2a\
181 | \x01\x70\x5d\x77\x8b\xe3\x38\x87\xa7\x7e\x89\xe8\x1e\x29\xe5\xe6\
182 | \xbe\x29\x1b\x22\x70\x12\x21\x48\x25\x00\xa5\x52\x69\x05\x11\x3d\
183 | \xa7\x72\xef\x79\xde\x68\xb5\x5a\xfd\x55\x08\x1d\xfa\x5a\x34\x69\
184 | \x10\xa4\x12\x00\xa5\x20\xe7\xfc\x00\x11\x2d\x99\x99\x99\x39\xa1\
185 | \x5e\xaf\xab\x83\x28\x53\x73\x25\x09\x82\xd4\x02\xc0\x18\xbb\x1f\
186 | \x11\x4f\x17\x42\xac\x4a\x8d\xf2\x2d\x15\x4d\x0a\x04\xa9\x05\xe0\
187 | \xdc\x73\xcf\x1d\xce\xe7\xf3\xf9\xb8\x8f\xa4\x37\x09\x53\x12\x20\
188 | \x48\x2d\x00\x26\x85\xea\x65\xac\x7e\x43\x60\x01\xe8\xa5\xba\x01\
189 | \x7d\xf7\x13\x02\x0b\x40\x40\x91\x7a\x5d\xac\x5f\x10\x58\x00\x7a\
190 | \xad\x6c\x08\xff\xfd\x80\xc0\x02\x10\x42\x20\x13\x45\x19\x63\x1b\
191 | \x11\xd1\xc8\xbc\x06\x11\x3d\x62\x01\x30\xa1\x6a\xc8\x18\x26\x7a\
192 | \x02\x22\x9a\x45\xc4\x92\x05\x20\xa4\x38\xa6\x8a\xf7\x12\x82\xa6\
193 | \xf8\x42\x88\x9d\x16\x00\x53\x8a\x6a\xc4\xe9\x05\x04\xad\xe2\xab\
194 | \x2a\x59\x00\x34\x84\x31\x69\x12\x27\x04\xed\xe2\x5b\x00\x4c\x2a\
195 | \x19\x21\x56\x1c\x10\x74\x12\xdf\x02\x10\x41\x14\xd3\xa6\x51\x20\
196 | \x98\x4f\x7c\x0b\x80\x69\x15\x23\xc6\xd3\x81\x60\x21\xf1\x2d\x00\
197 | \x11\x05\xe9\x87\x79\x18\x08\xba\x89\x6f\x01\xe8\x87\x82\x31\xc4\
198 | \x0c\x02\x41\x10\xf1\x2d\x00\x31\x88\xd1\x2f\x17\x0b\x41\x10\x54\
199 | \x7c\x0b\x40\xbf\xd4\x8b\x29\x6e\x27\x08\xc2\x88\x6f\x01\x88\x49\
200 | \x88\x7e\xba\x69\x85\x20\xac\xf8\x16\x80\x7e\x2a\x17\x63\xec\x52\
201 | \xa9\xb4\xc1\xf3\xbc\x9f\x02\xc0\x06\x29\xe5\x8e\x30\xae\xed\x4c\
202 | \x60\x98\x6c\x25\xb8\x6c\xb9\x5c\x5e\xaa\xb3\x4d\x8e\x05\x20\xc1\
203 | \xa2\x9a\xa8\x9a\x05\xc0\x44\x96\x13\x1c\xc3\x02\x90\x60\x71\x4c\
204 | \x54\xcd\x02\x60\x22\xcb\x09\x8e\x61\x01\x48\xb0\x38\x26\xaa\x66\
205 | \x01\x30\x91\xe5\x04\xc7\xb0\x00\x24\x58\x1c\x13\x55\xfb\x3f\x5e\
206 | \xdc\xa5\x83\xe1\xdb\x27\x05\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
207 | \x42\x60\x82\
208 | "
209 |
210 | qt_resource_name = b"\
211 | \x00\x07\
212 | \x07\x3b\xe0\xb3\
213 | \x00\x70\
214 | \x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\
215 | \x00\x0a\
216 | \x0f\x98\xbb\xe4\
217 | \x00\x6d\
218 | \x00\x61\x00\x67\x00\x69\x00\x63\x00\x5f\x00\x77\x00\x61\x00\x6e\x00\x64\
219 | \x00\x08\
220 | \x0a\x61\x5a\xa7\
221 | \x00\x69\
222 | \x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
223 | "
224 |
225 | qt_resource_struct_v1 = b"\
226 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
227 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
228 | \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
229 | \x00\x00\x00\x2e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
230 | "
231 |
232 | qt_resource_struct_v2 = b"\
233 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
234 | \x00\x00\x00\x00\x00\x00\x00\x00\
235 | \x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
236 | \x00\x00\x00\x00\x00\x00\x00\x00\
237 | \x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
238 | \x00\x00\x00\x00\x00\x00\x00\x00\
239 | \x00\x00\x00\x2e\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
240 | \x00\x00\x01\x6c\x4d\x2b\xaa\x38\
241 | "
242 |
243 | qt_version = QtCore.qVersion().split('.')
244 | if qt_version < ['5', '8', '0']:
245 | rcc_version = 1
246 | qt_resource_struct = qt_resource_struct_v1
247 | else:
248 | rcc_version = 2
249 | qt_resource_struct = qt_resource_struct_v2
250 |
251 | def qInitResources():
252 | QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
253 |
254 | def qCleanupResources():
255 | QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
256 |
257 | qInitResources()
258 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icon.png
4 |
5 |
6 |
--------------------------------------------------------------------------------