pax_global_header00006660000000000000000000000064131150203670014510gustar00rootroot0000000000000052 comment=7173a9f0cf4dd5cb1f3f85ef44bd2acad89463d3 qdirstat-1.4/000077500000000000000000000000001311502036700132075ustar00rootroot00000000000000qdirstat-1.4/.gitignore000066400000000000000000000000261311502036700151750ustar00rootroot00000000000000Makefile .qmake.stash qdirstat-1.4/LICENSE000066400000000000000000000431771311502036700142300ustar00rootroot00000000000000 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. qdirstat-1.4/README.md000066400000000000000000001133741311502036700144770ustar00rootroot00000000000000# QDirStat Qt-based directory statistics: KDirStat without any KDE -- from the author of the original KDirStat. (c) 2015-2017 Stefan Hundhammer Target Platforms: Linux, BSD, Unix-like systems License: GPL V2 Updated: 2017-06-04 ## Overview QDirStat is a graphical application to show where your disk space has gone and to help you to clean it up. This is a Qt-only port of the old Qt3/KDE3-based KDirStat, now based on the latest Qt 5. It does not need any KDE libs or infrastructure. It runs on every X11-based desktop on Linux, BSD and other Unix-like systems. QDirStat has a number of new features compared to KDirStat. To name a few: - Multi-selection in both the tree and the treemap. - Unlimited number of user-defined cleanup actions. - Properly show errors of cleanup actions (and their output, if desired). - File categories (MIME types) and their treemap color are now configurable. - Exclude rules for directories are easily configurable. - Desktop-agnostic; no longer relies on KDE or any other specific desktop. See section _New Features_ for more details. ## Screenshots [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-main-win.png) _Main window screenshot - notice the multi-selection in the tree and the treemap_ [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-file-type-stats.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-cleanup-output.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-column-config.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-locating-file-types.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-cleanup-config.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-mime-config.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-exclude-rules-config.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-histogram.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-histogram-options.png) [](https://raw.githubusercontent.com/shundhammer/qdirstat/master/screenshots/QDirStat-stats-help.png) _Full-size images and descriptions on the [Screenshots Page](https://github.com/shundhammer/qdirstat/blob/master/screenshots/README.md)_ ----------------------- ## Latest News **Latest stable release: V1.4** - 2017-06-04 **New stable release: V1.4** It's about time to ship all those latest changes. - 2017-06-04 Fixed problem with directories that have read, but not execute permissions thanks to _slodki_: In that case, you'd get a warning in the log for every entry in such a directory, and it would get the wrong icon (a locked folder) and null values for all fields. Now checking for execute and read permission of the directory in advance and not even trying to read any contents (because the values would be bogus anyway). - 2017-05-31 Fixed [GitHub Issue #61](https://github.com/shundhammer/qdirstat/issues/61): Files and directories with UTF-8 special characters in the name not read correctly when built with Qt 4.x This happened only when QDirStat was built against Qt 4.x, but that is the default for NHellFire's PPA, so this affects all Ubuntu users who installed QDirStat from that PPA. Thanks to _slodki_ who pointed this problem out! - 2017-05-12 Checked code with [Coverity](https://scan.coverity.com/) Coverity offers free static code analysis for Open Source projects. This is really an outstanding tool, and it does a really thorough analysis. You might be glad to hear that while it complained about some minor things, there was not a single issue that would have been user relevant (let alone any security problems - there were none). Still, I did my best to fix the small complaints it had, and now we are down to zero outstanding defects reported by Coverity in QDirStat's 130,000 lines of code. - 2017-04-21 More consistency between file type and size statistics Like the new file size statistics window, the older file type statistics window now uses the currently selected directory (in the tree view), not always the tree's toplevel directory. If nothing is selected, it still uses the toplevel directory. That means that F3 no longer toggles that window, but re-populates it with the currently selected directory instead. This is consistent with the F2 view. Of course, the "Locate Files by Type" window now is also restricted to that subtree which actually gives it better functionality if you know that you want to locate files only there. This means that you can now select a subdirectory in the tree, open the file type statistics for it (F3 key), then select any filename extension (suffix) in that window and then open the file size statistics (F2 key) for that file type in that subtree. Previously, you would have to start QDirStat to show only that directory, then open the file type statistics window (F3), then the file size statistics window (F2) from there. - 2017-04-14 _Let's do some real statistics_ It's been a while since the last official news here, but I wasn't idle during that time: ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram.png) This is a whole new kind of statistics in QDirStat showing how file sizes are distributed. You can start that for any selected directory (menu _View_ -> _File Size Statistics_ or F2) or from the _File Type Statistics" window if you select any filename suffix (extension) there and then _File Type_ -> _Size Statistics_ (or F2). In the latter case, you can see how large all your photos (.jpg), your videos (.mp4) or whatever are. This new statistics window deals with a lot of things you might have come to hate at school or at university, and which your math teacher or your statistics professor never explained in a way that mere mortals can understand, so I added those explanations as a bonus. There is a landing page for that in that new window: ![File Size Help](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-stats-help.png) Or you might use [this](https://github.com/shundhammer/qdirstat/tree/master/doc/stats) as a starting point. Everybody thinking "I have no clue what this is all about", please have a look at the [Median, Quartiles and Percentiles Explained](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md) document to convince yourself that really **everybody** can easily understand this. I also opened a [GitHub issue to discuss this](https://github.com/shundhammer/qdirstat/issues/60); comments are welcome. - 2017-03-10 Filling the gaps in the treemap [GitHub issue #58](https://github.com/shundhammer/qdirstat/issues/58) shows that users feel under-informed when there are grey areas in the treemap. The explanation is simple: Treemap tiles are only displayed when they have at least a certain minimum size (by default 3 pixels). Otherwise the treemap just gets cluttered with tiny things that don't show any information whatsoever. The remaining space is taken by its parent directory's tile. They were rendered just flat grey which makes their boundaries against each other invisible, thus giving the impression that there is nothing. So I experimented with visible borders, but that completely destroyed the visual impression of the treemap because those borders were everywhere. Fill patterns also didn't help: They were just ugly, and there was no way to tell where one directory tile ends and where the next one starts. Then I tried gradients. The first impression was good, but then I found that it was hard to tell which item was a (now over-emphasized) directory and which one a large file. Locating large files deep inside the directory hierarchy is the major strong point of the treemap visualization, so I wouldn't want to give that up. After playing a bit with the gradient parameters (toning it down and giving it just a little blueish tint) I ended up with this: ![Using Gradients](https://cloud.githubusercontent.com/assets/11538225/23812600/7e769e48-05db-11e7-820c-2a6f70916403.png) I think this is a good compromise. Of course this is configurable: Edit `~/.config/QDirStat/QDirStat.conf`: [Treemaps] ... DirGradientEnd=#707080 DirGradientStart=#606070 ... UseDirGradient=true Beware that QSettings sorts the entries alphabetically, so the start is after the end (how philosophical...). ------------------------ - 2017-03-05 **New stable release: V1.3** _See [DevHistory.md](https://github.com/shundhammer/qdirstat/blob/master/doc/DevHistory.md) for older entries._ ## History This is just a rough summary. For more details, see [DevHistory.md](https://github.com/shundhammer/qdirstat/blob/master/doc/DevHistory.md) - 2017-06-04 New stable release: V1.4 - 2017-03-05 New stable release: V1.3 - 2017-01-03 New stable release: V1.2 - 2016-10-31 New stable release: V1.1-Pumpkin - 2016-05-16 First stable release: V1.0 - 2016-04-08 Beta 3 release - 2016-03-20 Beta 2 release - 2016-02-06 Beta 1 release - 2015-11-28 QDirStat project start: Ported from the old KDE 3 KDirStat - Predecessor: KDE 3 **KDirStat** - 2006-06-01 KDirStat 2.5.3: The last KDE3 based version. - 2003: Bernhard Seifert wrote **WinDirStat** based on the KDirStat idea of coupling a tree view and a treemap and providing cleanup actions. - 2003-01-05 KDirStat 2.3.3: Treemaps - 2002-02-25 KDirStat 2.0.0: Complete rewrite for KDE 2 / Qt 2 - 2000-01-21 KDirStat 0.86 for KDE 1 announced: First public version. ## WinDirStat and QDirStat I keep reading articles and user forum comments about QDirStat being a "nice Linux port of WinDirStat". Well, nothing could be further from the truth: **WinDirStat is a Windows port of KDirStat**, the predecessor of QDirStat. So it's the other way round: **The Linux version was there first**, and somebody liked it so much that he wrote a Windows version based on that idea. That's a rare thing; usually people port Windows originals to Linux. See also https://windirstat.net/background.html and the WinDirStat "About" dialog. ## QDirStat and K4DirStat K4DirStat is a port to KDE 4 / Qt 4 of my old KDE 3 / Qt 3 KDirStat. QDirStat is independent of that; it is based on the old KDE 3 KDirStat directly. ## Motivation / Rant After having used KDE since its early days (since about 1998), I didn't like the direction any more that KDE has been taking. I loved KDE 1, KDE 2, KDE 3. When KDE 4 came along, it took me a long time to try to adopt it, and when I did, I moved back to KDE 3 after a short while, then tried again with the next release, moved back again -- several times. I really tried to like it, but whenever I thought I tamed it to meet my requirements, a new version came along that introduced yet another annoyance. To name a few: - A lot of things that used to be user configurable in KDE 3 are not configurable anymore, and when you approach the KDE 4/5 developers about that, they will tell you that this is intentional, and they do not intend to bring those config options back. Well, thanks a lot; this is the Apple approach where they think they know what is good for you, and you are just too stupid. - Konqueror as the old central tool is as good as dead. It's still there as an alternate file manager (for those who find it), but the primary one is the dumbed-down Dolphin that I consider unusable: It's only useful for complete newbies, not for power users. The web browser part of Konqueror is so outdated that you can't do much with it with most modern web sites, so the great integration of web and local file manager that was the major strong point of Konqueror (and thus KDE) no longer exists. - I don't like the fact that I can't simply put icons on my desktop any more -- no, I have to create a plasmoid first as a container, and those things keep doing weird stuff that drives every user crazy. With one false move of your mouse, it might be gone, change shape, move to another place or whatever. - I also don't like the desktop search that eats resources like there is no tomorrow (disk space, disk I/O, CPU usage) and that for all practical purposes you can't get rid of. - I don't like the fact that the mail client relies on that MySQL based framework called _Akonadi_ that is not only resource-hungry, but also so fragile that I had to use the _akonadiconsole_ lots of times just to bring it back to life. Seriously, if I as a Linux system developer have a hard time doing that, what is a normal user expected to do? - Activities vs. multiple desktops. I tried to use both, but they don't integrate well. The desktops previewer is far inferior to the old one from KDE3: Only monochrome rectangles, no real preview. The activities plasmoid keeps rearranging my carefully placed and named activities at random. WTF?! - Everything is so fragmented that not even the naming is clear anymore. What used to be KDE is now a jumble of the KF Framework, the KF libs, the KF apps and the Plasma desktop. Yeah, great job, folks; people used to know what KDE stood for. Nobody knows what the hell all those components are, and neither does anybody care anymore. You paved your way to oblivion with buzzwords. Great marketing strategy for gaining more visibility! Then the next generation KDE arrived, _Plasma 5_. When I was force-migrated to it at work with the _SUSE Tumbleweed_ rolling release, the experience was so bad that I moved to the _Xfce_ Desktop. Now every time I started my own KDirStat, it started about a dozen KDE processes along with it -- processes that it needs only for minor things like loading icons or translations. I really don't need or want that. So it was time to make KDirStat self-sufficient; it never used that much of all the KDE infrastructure anyway. Time to make a pure Qt-based and self-sufficient QDirStat. And while I was at it, I took the chance to add some features that I had wanted for a long time, yet I had never gotten myself to start working on: - Multi-selection in the directory tree so you can delete several files at once. - Remove limitations like having only a fixed number of user-defined cleanup actions. - Properly show the output of cleanup actions, in particular when they reported errors. - Make treemap colors configurable: Use custom colors and match them to user-defined filename extensions. - Move away from the arcane KDE build system: Back with KDE 1/2/3 it was the _Autotools_ with custom KDE extensions that only a handful people in the world really understood (I was not among them), later _CMake_ which is little better, just differently confusing. Yes, there is a Qt4 / Qt5 port of KDirStat called K4DirStat. K4DirStat is an independent project that started when I had not worked on the old KDirStat for a long time (my last KDirStat release had been in mid-2006). QDirStat is based on that same code from the 2006 KDirStat. It's an 80% rewrite using a lot of newer Qt technologies. And there was a lot of cleaning up that old code base that had been long overdue. ## New Features - Multi-selection: - Both views (the tree and the treemap) now support _extended_ selection, i.e. you can select more than one item. This was the most requested feature for the last KDirStat. Now you can select more than one item at the same time to move it to the trash can, to directly delete it or whatever. - Tree view: - Shift-click: Select a range of items. - Ctrl-Click: Select an additional item or deselect a selected one. - Treemap: - Ctrl-Click: Select an additional item or deselect a selected one. - The current item is highlighted with a red rectangle, all other selected ones with a yellow rectangle. If the current item is not also selected, it has a dotted red outline. - Proper output of cleanup actions with different colors for the commands that are executed, for their output and for error messages (see screenshot above). That output window can be configured to always open, to open after a certain (configurable) timeout, or only if there are error mesages -- or not at all, of course. If things go wrong, you can kill the external command started by the cleanup action from there. You can zoom in and out (increase or decrease the font size) as you like. - File type statistics window. WinDirStat has it, and users wanted it in QDirStat, too. Since filename extensions (suffixes) don't have as much semantics in Linux/Unix systems as they do in Windows, many files are categorized as "Other". This is a known limitation, but it's a limitation of the whole concept of using suffixes to categorize files by type. And no, checking file headers for magic byte sequences like the "file" command does is not an option here; QDirStat would have to do that for (at least) all the 30,000+ files typically listed under the "Other" category. So we'll have to live with that limitation. - Locate files by file type window. If you double-click on any of the filename extensions (suffixes) in the file type statistics window, you will get another window that lists all the directories that contain files of that type including the number and total size of those files. You can double-click each of those lines, and that directory will open in the main window with the files of that type preselected so you can start cleanup actions like moving them to trash or converting them to a better format (.bmp -> .png) immediately. - File size statistics window with histogram, percentiles, buckets and a lot of documentation that everybody should be able to understand. Even if (or, better yet, in particular if) your math teacher or statistics professor never explained it properly, please have a lot at it. - New macros to use in cleanup actions: - %d : Directory name with full path. For directories, this is the same as %p. For files, this is their parent directory's %p. - %terminal : Terminal window application of the current desktop; one of "konsole", "gnome-terminal", "xfce4-terminal", "lxterminal", "eterm". The fallback is "xterm". - %filemanager : File manager application of the current desktop; one of "konqueror", "nautilus", "thunar", "pcmanfm". The fallback is "xdg-open". - Which desktop is used is determined by the _$XDG_CURRENT_DESKTOP_ environment variable. Users can override this with the _$QDIRSTAT_DESKTOP_ environment variable, so you can get, say, the Xfce terminal or file manager despite currently running KDE if you set export QDIRSTAT_DESKTOP="Xfce" - Of course, you can still simply use your favourite file manager if you simply change %filemanager in the default "Open File Manager Here" cleanup action to the command to start it. - You can now select the shell to use for the cleanup commands: - $SHELL (the user's login shell) - using the same environment, syntax and wildcard etc. behaviour of the shell the user is used to. - /bin/bash for well-defined behaviour for wildcards etc. - /bin/sh as a last resort (which might be a simplistic _dash_ on Ubuntu). - Mouse actions in the treemap window: - Left click: Select item and make it the current item. - Right click: Open the context menu with cleanup actions and more. - Ctrl+Left click: Add item to selection or toggle selection. - Middle click: Select the current item's parent. Cycle back at toplevel. - Double click left: Zoom treemap in. - Double click middle: Zoom treemap out. - Mouse wheel: Zoom treemap in or out. - You can configure what columns to display in the tree view and in which order. The only thing that is fixed is the "Name" column which is always there and always the first (leftmost). Use the context menu in the tree header to unlock column widths. Drag columns to the left or right to change their order. - Exclude rules are now greatly simplified. They no longer always get the entire path to match which requires quite complex regexps; by default, they only get the last path component -- i.e., no longer "/work/home/sh/src/qdirstat/src/.git", but only ".git". You can now even tell the exclude rule to use a simplified syntax: "FixedString" or "Wildcard" in addition to the normal "RegExp". The old behaviour (matching against the full path) is still available, though. - Configuration dialog for exclude rules -- see screenshots. - Subvolume detection for Btrfs. Btrfs subvolumes are just ordinary mount points, so normally QDirStat would stop scanning there, leaving a large part of a Btrfs partition unaccounted for. But for each mount point found while scanning a directory tree, QDirStat checks /proc/mounts or /etc/mtab if it has the same device name as its parent directory, and if yes, considers it a subvolume and continues scanning. - Actions to go one directory level higher or to the toplevel: Context menu and menu "Go To" -> "Up One Level" or "Toplevel". This is useful if you clicked on a file in the treemap that is deep down in some subdirectory, and you want to know what subdirectory that is: Simply click "Go Up" twice (the first click will get you to the pseudo subdirectory, the second one to the real one). - Open all tree branches up to a certain level and close all other ones: Menu "View" -> "Expand Tree To Level" -> "Level 0" ... "Level 9". - The total sum of the selected items (subtrees) is displayed in the status line if more than one item is selected. - Icons are now compiled into the source thanks to Qt's resource system; now it's just one binary file, and nothing will go missing. No more dozens of little files to handle. - The build system is now Qt's _QMake_. I got rid of that _AutoTools_ (Automake, Autoconf, Libtool) stuff that most developers find intimidating with its crude M4 macro processor syntax. QMake .pro files are so much simpler, and they do the job just as well. And no, it will definitely never be _CMake_: I don't like that thing at all. It's just as much as a PITA as the AutoTools, just not as portable, no usable documentation, it's changing all the time, and those out-of-source builds are a royal PITA all on their own with constantly having to change back and forth between source and build directories. - QDirStat now has its own log file. It now logs to `/tmp/qdirstat-$USER/qdirstat.log` (where $USER is your Linux user name). No more messages on stdout that either clobber the shell you started the program from or that simply go missing. - No longer depending on dozens of KDE libs and a lot of KDE infrastructure; it now only requires Qt which is typically installed anyway on a Linux / BSD / Unix machine with any X11 (graphical) desktop. - It should still compile and work with Qt4. We now have a contributor who is very interested in that (Michael Matz), so it should be possible to maintain this compatibility. - Slow down display update from 333 millisec (default) to 3 sec (default) with `qdirstat --slow-update` or `qdirstat -s`. The slow update interval can be customized in `~/.config/QDirStat/QDirStat.conf`: ``` [DirectoryTree] SlowUpdateMillisec = 3000 ``` ## Old Features Features ported from the old KDirStat: - Fast and efficient directory reading. - Not crossing file system boundaries by default so you can see what eats up all the disk space on your root file system without getting distorted numbers due to all the other file systems that are mounted there. If you absolutely wish, you can use "Continue reading at mount point" from the context menu or from the "File" menu -- or configure QDirStat to always read across file systems. - Efficent memory usage. A modern Linux root file system has well over 500,000 objects (files, directories, symlinks, ...) and well over 40,000 directories. This calls for minimalistic C++ objects to represent each one of them. QDirStat / KDirStat do their best to minimize that memory footprint. - Hierarchical tree view that displays accumulated sums in each branch, together with a percent bar so you can see at a glimpse how the subdirectories compare with each other. - All numbers displayed human readable -- e.g., 34.4 MB instead of 36116381 Bytes. - Each tree level uses another color for that percent bar so you can easily compare subdirectories even if some of them are opened in the tree. - If a directory has files and subdirectories, all files in that subdirectory are grouped into a pseudo directory (called _dot entry_ in the QDirStat sources) so you can compare the disk usage of files on that directory level with the subdirectories. - Displaying the latest modification time of any object in each branch. You can instantly see in what subdirectory where any changes lately. You can sort by this column, of course. - Treemap display. Treemaps are a way to visualize hierarchical data structures, invented by Ben Shneiderman. Basically, the hierarchy is flattened and each level grouped in a rectangle, inside which it is again subdivided in rectangles. The area of each rectangle corresponds to the size of each item or subdirectory. For the purposes of QDirStat, it is enough to know that a large blob corresponds to a large file; you can instantly see where large ISOs or movies are. - You can zoom the treemap in and out (Ctrl + / Ctrl - / mouse wheel / menu / tool bar) to see more details of directories that are otherwise dominated by larger ones. - You can move the boundary between treemap and tree view up and down as you like. You can also get rid of the treemap completely (menu "Treemap" -> "Show Treemap" or F9 key) - Treemap and tree list view communicate. Select an item in one view, and it is also selected in the other. If you click on that large blob in the treemap, it is located in the tree view, all branches up to its directory are opened, and the tree view scrolls to that item. - Cleanup actions. Once you know what is consuming the disk space, you can start cleanup actions from within QDirStat to reclaim disk space - or to investigate further if you can safely delete a file. You can create your own cleanup actions (as many as you like), and there are some predefined ones: - Open file manager here. This will start a file manager in the directory of the current item. QDirStat tries its best to guess the name of the relevant file manager application for the current desktop, based on the $XDG_CURRENT_DESKTOP environment variable. You can override this with the $QDIRSTAT_DESKTOP environment variable. - Open terminal window here. In most cases, this is much easier than to navigate to that directory with 'cd' in an already open terminal window and using tab-completion numerous times. As with the file manager application, QDirStat tries its best to guess the name of the relevant terminal window application for the current desktop. - Move to trash bin. QDirStat has its own implementation of the XDG trash specification. - Delete immediately. - Compress: Create a compressed tar archive from a directory and then delete the directory. - Delete junk files: Backup files left behind by editors, core dumps. - All predefined cleanup actions are fully configurable, of course. You can change any of them, disable them, or delete them. - You can copy the complete path of the selected file or directory to the system clipboard and paste it to another application. - Reading and writing cache files: - This is mostly meant for remote servers in some server room somewhere: Rather than installing the Qt and X11 runtime environment and running QDirStat over remote X (ssh with X forwarding), you can run the supplied _qdirstat-cache-writer_ Perl script on the server, copy the resulting cache file to your desktop machine and view the content there with QDirStat. - For large directories (archives etc.) that don't change that much, you can also generate a QDirStat cache file (either with the Perl script or with QDirStat itself) and save it to that corresponding directory. If QDirStat finds a file .qdirstat.cache.gz in a directory, it checks if the toplevel directory in that cache file is the same as the current directory, and if it is, it uses the cache file for that directory rather than reading all subdirectories from disk. If you or the users that machine use QDirStat often, this might take a lot of I/O load from the server. - If you use the '-l' option of the qdirstat-cache-writer script, it uses the long file format with a complete path for each entry, so you can use the _zgrep_ command with it as a replacement for the _locate_ command. - The KDirStat / QDirStat file format is well documented and very simple. It seems to be used by a number of admins and some backup software. See also the specification in the doc/ directory: https://github.com/shundhammer/qdirstat/blob/master/doc/cache-file-format.txt - You can specify a cache file to read directly at the command line: ``` qdirstat --cache cache-file ``` - Other command line options: See ``` qdirstat --help ``` ## Features that are Gone (Compared with the old KDirStat) - KPacman: That was that PacMan animation wile reading directory reading. This is gone now. KPacMan looked out of place pretty soon after it got to KDirStat due to Qt styles doing fancy rendering of widget backgrounds with gradients etc. I know that it does have its fans, but it's unrealistic to get this back without breaking the menu bar rendering. - KioDirReadJob: Network-transparent directory reading for network protocols like FTP, HTTP, Fish (ssh-based). This depended on KDE's KIO slaves, so this functionality is gone now without KDE. That's a pity, but this is a little price to be paid to avoid the rest of the hassle with using the KDE libs. - KFeedback: That was that form where users could tell their opinion about KDirstat. But that was not used that often anyway - not nearly enough to justify the effort that has gone into that part. And the KDE usability people, like usability people generally tend to do, first discussed that to death and then decided they didn't want anything like that in general in KDE applications. So be it. - KActivityTracker: That was a supporting class for KFeedback that kept track of how much a user was using the program and after a while (when it was determined that it made sense) asked if the user wouldn't like to give his feedback about the program. Don't you all just hate those dumbass web designers who tell you to do a survey how much you like their grand web page before you even had a chance to look at it? Shove a pop-up up your face covering the stuff you are interesting in with their self-loving marketing bullshit? -- KActivityTracker was made to avoid exactly this: Ask the user only once you know that he actually used the program for a while. ## MacOS X Compatibility I was amazed to find that it doesn't take more than the normal "qmake" and then "make" to build QDirStat for MacOS X. We (Sonja Krause-Harder and I) did some basic testing, and it seems to work. The cleanups may need some adaptation, but this is something that might even be configured by the user. If anybody wants to give it a try, download Qt for MacOS X, install it, open a shell window, search the _qmake_ command: find . -name qmake Add this to your $PATH, then do the normal qmake make Not sure how well "make install" works, though. **_Be advised that QDirStat on MacOS X is purely experimental at this stage._** There is no support. If you try this, you are on your own. Even more so than with the other platforms, you will have to make sure that your Qt build environment is set up correctly. _There be dragons._ ;-) ### Architecture maintainer wanted for QDirStat for MacOS X If you are a developer with some prior C++ and Qt knowledge on the MacOS X platform and you'd like to see QDirStat working there, please consider joining the team. ## Windows Compatibility None for the forseeable future. Directory reading might be quite easy to replace for Windows; we don't have that problem with devices and crossing filesystems on that platform. But the cleanups might be a challenge, "move to trash" works completely differently, and we'd need an installer for a Windows version. So, for the time being, use [WinDirStat](https://windirstat.info/) instead. WinDirStat is a close relative to the KDirStat family anyway; the author had liked KDirStat on Linux so much that he decided to write a Windows clone and called it WinDirStat. ## Ready-made Packages ### openSUSE / SUSE Linux Enterprise QDirStat packages for: - openSUSE Tumbleweed - openSUSE Leap 42.2 - openSUSE Leap 42.1 - openSUSE 13.2 - SUSE Linux Enterprise (SLE) 12 SP2 - SUSE Linux Enterprise (SLE) 12 SP1 - SUSE Linux Enterprise (SLE) 12 Download page for the [**latest stable release**](https://software.opensuse.org/download/package?project=home:shundhammer:qdirstat-stable&package=qdirstat) Download page for the [**current development version** (git master)](https://software.opensuse.org/download/package?project=home:shundhammer:qdirstat-git&package=qdirstat) Since this version is in development, it may be not quite as stable and reliable as the latest official stable release, although the QDirStat developers try their best to keep it as stable as possible. ### Ubuntu See Nathan Rennie-Waldock's [**QDirStat PPA**](https://launchpad.net/~nathan-renniewaldock/+archive/ubuntu/qdirstat) ## Building ### Build Environment Make sure you have a working Qt 5 build environment installed. This includes: - C++ compiler (gcc recommended) - Qt 5 runtime environment - Qt 5 header files - libz (compression lib) runtime and header file If anything doesn't work, first of all **make sure you can build any of the simple examples supplied with Qt**, e.g. the [calculator example](http://doc.qt.io/qt-5/qtwidgets-widgets-calculator-example.html). #### Ubuntu Install the required packages for building: sudo apt-get install build-essential qtbase5-dev zlib1g-dev Dependent packages will be added automatically. Recommended packages for developers: sudo apt-get install qttools5-dev-tools qtbase5-doc qtbase5-doc-html qtbase5-examples See also http://askubuntu.com/questions/508503/whats-the-development-package-for-qt5-in-14-04 If you also have a Qt4 development environment installed, select the desired one via _qtchooser_: sudo apt-get install qtchooser export QT_SELECT="qt5" #### SUSE Install the required packages for building: sudo zypper install -t pattern devel_C_C++ sudo zypper install libQt5Widgets-devel libqt5-qttools zlib-devel If you also have a Qt4 development environment installed, make sure that the Qt5 version of 'qmake' is the first in your $PATH: export PATH=/usr/lib64/qt5/bin:$PATH ### Compiling Open a shell window, go to the QDirStat source directory, then enter these commands: qmake make ### Installing sudo make install or su -c make install ## Contributing See file [Contributing.md](https://github.com/shundhammer/qdirstat/blob/master/doc/Contributing.md) and [GitHub-Workflow.md](https://github.com/shundhammer/qdirstat/blob/master/doc/GitHub-Workflow.md) ## To Do See file [TODO.md](https://github.com/shundhammer/qdirstat/blob/master/doc/TODO.md) ## Troubleshooting ### Can't Move a Directory to Trash See file [Troubleshooting.md](https://github.com/shundhammer/qdirstat/blob/master/doc/Troubleshooting.md) ## Reference ### Original KDirStat Home page: http://kdirstat.sourceforge.net/ Sources: https://github.com/shundhammer/kdirstat ### K4Dirstat Home page: https://bitbucket.org/jeromerobert/k4dirstat/wiki/Home Sources: https://bitbucket.org/jeromerobert/k4dirstat/src ### WinDirStat (for Windows) Home page: https://windirstat.info/ ### XDG Trash Spec http://standards.freedesktop.org/trash-spec/trashspec-1.0.html ## Reviews ### YouTube [Spatry: _Quick Look: QDirStat_](https://www.youtube.com/watch?v=ysm4-x_5ftI) ## Code Analysis Tools [QDirStat at Coverity](https://scan.coverity.com/projects/qdirstat?tab=overview) Coverity Scan Build Status ## Misc http://moo.nac.uci.edu/~hjm/HOWTO_move_data.html#qdirstat http://moo.nac.uci.edu/~hjm/kdirstat/kdirstat-for-clusters.html qdirstat-1.4/debian/000077500000000000000000000000001311502036700144315ustar00rootroot00000000000000qdirstat-1.4/debian/changelog000066400000000000000000000002501311502036700163000ustar00rootroot00000000000000qdirstat (0.86~beta1-1~precise) precise; urgency=low * Initial release. -- Nathan Rennie-Waldock Sat, 27 Feb 2016 16:59:43 +0000 qdirstat-1.4/debian/compat000066400000000000000000000000021311502036700156270ustar00rootroot000000000000008 qdirstat-1.4/debian/control000066400000000000000000000013711311502036700160360ustar00rootroot00000000000000Source: qdirstat Maintainer: Nathan Rennie-Waldock Section: utils Priority: extra Build-Depends: debhelper (>= 8), zlib1g-dev, libqt5-dev | libqt4-dev Homepage: https://github.com/shundhammer/qdirstat Package: qdirstat Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: graphical disk usage display with cleanup facilities QDirStat (Qt Directory Statistics) is a small utility program that sums up disk usage for directory trees, very much like the Unix 'du' command. It displays the disk space used up by a directory tree, both numerically and graphically. It is network transparent (i.e., you can use it to sum up FTP servers), and comes with predefined and user configurable cleanup actions. qdirstat-1.4/debian/copyright000066400000000000000000000015041311502036700163640ustar00rootroot00000000000000This package was debianized by Nathan Rennie-Waldock on 2016-02-27 License: 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. qdirstat-1.4/debian/rules000077500000000000000000000000351311502036700155070ustar00rootroot00000000000000#!/usr/bin/make -f %: dh $@ qdirstat-1.4/debian/source/000077500000000000000000000000001311502036700157315ustar00rootroot00000000000000qdirstat-1.4/debian/source/format000066400000000000000000000000141311502036700171370ustar00rootroot000000000000003.0 (quilt) qdirstat-1.4/doc/000077500000000000000000000000001311502036700137545ustar00rootroot00000000000000qdirstat-1.4/doc/Building.md000066400000000000000000000001621311502036700160320ustar00rootroot00000000000000# Building QDirStat See [main document] (https://github.com/shundhammer/qdirstat/blob/master/README.md#building) qdirstat-1.4/doc/Contributing.md000066400000000000000000000156401311502036700167530ustar00rootroot00000000000000# Contributing to QDirStat Contributions are welcome. Please follow the rules and guide lines in this document: ## Guide Lines Use the same style as the existing code. Indentation is 4 blanks. One tab is 8 blanks. Do not indent with single tabs for each indentation level and thus fuck up everybody else's editor. Letting the editor automatically replace 8 blanks with a tab is okay, but indentation level is still 4 blanks. Brace style is braces **always** on a new line. Use blanks after opening and before closing parentheses: if ( someCondition ) { doSomething( arg1, arg2 ) } **No** K&R style indentation: if (someCondition) { // WRONG!!! doSomething(arg1, arg2) // WRONG!!! } Use blank lines liberally. No Rubocop-style code. Use CamelCase for classes and camelCase for variables. Do not use snake_case. Prefix member variables with an underscore: _someValue. Prefix its setter with Set...(), use only the name (someValue()) for the getter, **Not** getSomeValue(): private: SomeType _someValue; // member variable public: const & SomeType someValue() const; // getter void setSomeValue( const SomeType & newValue ); // setter Use a const reference for the setter parameter and the getter return type for nontrival data types (everything beyond a pointer or an int etc.), and the type directly otherwise. Use your common sense. Use Qt types whereever possible. Do not introduce types that are also available in a Qt version. In particular, do not use STL or Boost types unless there is no other reasonable way. For Qt dialogs, use Qt Designer forms whenever possible. I know that many Qt developers don't like Qt Designer (typically based on bad experiences years back), but it's really worthwhile to use it. This avoids having tons of dumb boilerplate code just for creating widget trees. ### Documenting Classes and their Methods Document classes and their methods in their header file. Document them immediately. If you don't do it right away, it will never happen. Don't wait for somebody else to do that for you - nobody will be willing to do the inconvenient part of the job for you. Undocumented stuff will mercilessly be rejected. In my 30+ years of programming I came to the conclusion that it helps immensely to write down a function name in the header file and **immediately** write its documentation: - What does it do? (Do not just repeat the function name! **Explain** what it does!) - What are the parameters? - What does it return? - In particular for functions returning bool: Which case returns 'true', which case returns 'false'? - What happens in fringe cases? (returning NULL pointer?) - If the function creates any objects: Who owns them? - Does the function transfer ownership of any objects it gets pointers to (as parameters) to itself or wherever? If you do that right, you might as well leave the implementation to somebody else. **Do not** insert any doc template without content before each function. This is worse than no documentation at all: Everybody has to wade through tons of useless empty forms that don't contain any content whatsoever. Been there. Done that. Hated it. Be careful when copying and pasting documentation from some other place. Misleading documentation is worse than no documentation at all. ### Legalese in the Sources **Do not** copy 30+ lines of legalese bullshit into any source file. One line in the header like License: GPL V2 - see file LICENSE is plenty. Seriously, what are those people thinking who put all that legalese into source files? Sure, they listened to spineless corporate lawyers who just want to make sure. But those lawyers are not going to have that crap smack up their faces every time they open a file for editing. We developers do. You lawyers out there, can you hear me? **This crap is in the way! Nobody wants to read that!** It's in the way of people trying to do their jobs! We could construct a harassment case from this! ### The GitHub Workflow See separate document [GitHub-Workflow.md](https://github.com/shundhammer/qdirstat/blob/master/doc/GitHub-Workflow.md) ### Getting Help for Contributors - Use the Qt reference documentation. - Install and study carefully the available Qt examples for reference. - Read the (extensive!) documentation in the QDirStat header files. - Use Stack Overflow. - Use Google. - Make sure you can build a basic Qt program. - Make sure you have the compiler and other developer tools set up correctly. - Make sure you have the relevant -devel (SUSE) or -dev (Ubuntu/Debian) packages installed. If you did all of the above (and only then!) and still couldn't figure out what's wrong: - Use IRC (#qdirstat on irc.freenode.net; fallback: contact HuHa in #yast on freenode IRC) - Write a mail It is a matter of professional courtesy to first use what is freely available on the web before you consume somebody else's time and expertise. It is utterly rude to let somebody else point you to the exact part of the Qt documentation you couldn't be bothered to read. Does this sound unfriendly? Well, maybe - but: Been there, done that, got the fucking T-shirt -- countless times. This is not how I want to spend my spare time. There are some people who keep arguing that "it takes hours for me to read through all the documentation, whereas you as an expert can give me the right answer within a minute". Well, yes, it might only take a minute to write the answer in IRC, but then that newbie won't learn anything except that it pays off to disturb people rather than learn for himself. And reading the documentation is always a good investment of time; it is never wasted. In the process of searching for an answer you will come across many things you hadn't known - and that might just be useful for your next question. Plus, it will take the expert that one or two minutes to write the answer to IRC - and then **15-20 minutes to recover from the interrupt**, to restore the fragile buildings in his mind he needs to solve the problem he was originally working on. Please keep in mind that every such interrupt will cost 20-30 minutes of time on average, and a working day only has 16-24 such time slots; and those experts tend to be in high demand on many different communication channels (IRC, personal mail, mailing lists, bugzilla, phone, people walking into the office). So, should you join the project as a newbie? If you have patience, self-discipline and are willing to learn (which includes reading the Qt documentation first), and, most importantly, if you are willing to stay with the project and not let some unfortunate guy clean up half-ready stuff, yes. Just keep in mind that others are doing this because (a) it's fun for them and/or (b) because they want that piece of software to be successful. Educating newbies and cleaning up after them is very low on most developers' list of fun things to do. They still do it, but it's painful for them. Please help minimizing that pain. qdirstat-1.4/doc/Debugging-Tips.md000066400000000000000000000021151311502036700171050ustar00rootroot00000000000000# QDirStat Debugging Tips ## Problem: Directory reading is too fast to debug anything ### Symptom Only the very first time, reading a large directory like / takes long enough to experiment with anything in the tree widget. Any subsequent time, it's just too fast - one or two seconds, and *bam* it's finished already. ### Reason The Linux kernel has become incredibly good at caching directory information, and today's PCs have so much RAM that the kernel tends to use a large amount of it as cache - files, inodes, dentries (directories). Once a directory is read, it remains in the cache for a long time, so the speedup upon a subsequent read is enormous. ### Fix / Workaround Drop the kernel caches (as root): su - echo 3 > /proc/sys/vm/drop_caches or echo 3 | sudo tee /proc/sys/vm/drop_caches ("sudo echo 3 > /proc/sys/vm/drop_caches" would NOT work because your non-root shell would do the I/O redirection, so it would not have sufficient privileges) ### Reference http://unix.stackexchange.com/questions/87908/how-do-you-empty-the-buffers-and-cache-on-a-linux-system qdirstat-1.4/doc/DevHistory.md000066400000000000000000001306171311502036700164060ustar00rootroot00000000000000# QDirStat Development History This is more verbose than a traditional change log, thus the unusual name of this file. See the README.md file for the latest news: https://github.com/shundhammer/qdirstat/blob/master/README.md ## QDirStat History - 2017-03-05 **New stable release: V1.3** - 2017-02-27 Implemented [GitHub issue #30](https://github.com/shundhammer/qdirstat/issues/30): When hovering over a treemap tile, display the full path and the total size of that element in the status bar. When the hover ends (when the mouse cursor leaves the treemap tile), display the current selection again in the status bar. - 2017-02-24 Improved logging: More secure and automatically log-rotating. QDirStat now uses its own log directory `/tmp/qdirstat-$USER` (where `$USER` is your user name; the numeric user ID is now only used if the user name cannot be obtained). It no longer keeps one single log file growing, but starts a new one each time it is started. 3 old logs are kept; any older ones are deleted. The permissions for that directory are set up in a pretty restrictive way (0700, i.e. `rwx------`) when it is created. If it already exists, QDirStat checks the owner and creates a new one with a random name if it is owned by anyone else than the user who started QDirStat. [sh @ balrog] ~ 68 % ls -ld /tmp/qdirstat-sh drwx------ 2 sh sh 4096 Feb 24 18:29 /tmp/qdirstat-sh [sh @ balrog] ~ 69 % ls -l /tmp/qdirstat-sh total 16 -rw-rw-r-- 1 sh sh 2067 Feb 24 18:29 qdirstat-00.old -rw-rw-r-- 1 sh sh 2067 Feb 24 18:07 qdirstat-01.old -rw-rw-r-- 1 sh sh 2067 Feb 24 18:07 qdirstat-02.old -rw-rw-r-- 1 sh sh 2067 Feb 24 18:29 qdirstat.log For anybody regularly watching the log file this means they will now have to use `tail -F qdirstat.log` rather than `tail -f` since the latter does not realize when the file it watches is renamed and a new one is created under the same name. - 2017-02-23 Fixed [GitHub issue #24](https://github.com/shundhammer/qdirstat/issues/24): During directory reading, subdirectories would get out of sync when opening a tree branch. It looks like QDirStat's tree display was a bit too dynamic for the concepts of the underlying Qt classes (QTreeView / QAbstractItemModel): During reading, QDirStat would sort the tree by the number of pending read jobs. That number is constantly changing, so the sort order would also constantly need to change. This is very hard to do properly with the limitations those underlying classes impose; basically it would require a reset of all the data the QTreeView keeps, thus making it forget things like its current scrollbar position or which tree branches were expanded or collapsed. That would make the user interface pretty much unusable. So the fix for this is to not sort by read jobs, but by directory names instead since they don't change all the time. The user can still sort by any other column, but that sort is a momentary thing that might become invalid moments later as data (accumulated sizes, number of child items) are updated. Everybody please notice that **this is a known limitation** and any complaints about that will flatly be rejected. The alternative would be to not allow the user to sort at all during directory reading, and that is certainly a lot less desirable. - 2017-02-22 - @flurbius contributed a patch to switch the main window layout from tree view above and treemap below to side-by-side (Menu _Treemap_ -> _Treemap as Side Panel_). - Added new document [GitHub-Workflow.md](https://github.com/shundhammer/qdirstat/blob/master/doc/GitHub-Workflow.md) explaining how to work with GitHub and Git to contribute to QDirStat. - 2017-02-20 Locating files by type from the _File Type Statistics_ window ![Locating FilesWindow](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-locating-file-types.png) You can now locate files with a specific filename extension directly: - You select a file type (a filename extension) in the "File Type Statistics" window. - You click "Locate" or you double-click the item. - The "Locate Files" window opens. - You click a directory there. - In the main window, the branch for that directory opens, and all matching files are selected in the tree view and in the treemap. - You can now directly start cleanup actions for those files. See also [GitHub issue #48](https://github.com/shundhammer/qdirstat/issues/48). - 2017-02-18 New document: [QDirStat for Servers](https://github.com/shundhammer/qdirstat/blob/master/doc/QDirStat-for-Servers.md) describing how to use QDirStat and the `qdirstat-cache-writer` script on headless (no X server, no X libs) servers. - 2017-02-17 _File Type Statistics_ window merged to Git master Latest screenshot: ![File Type Statistics Window Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-file-type-stats.png) **Limitations:** Since filename extensions (suffixes) don't have as much semantics in Linux/Unix systems as they do in Windows, many files are categorized as "Other". This is a known limitation, but it's a limitation of the whole concept of using suffixes to categorize files by type. And no, checking file headers for magic byte sequences like the "file" command does is not an option here; QDirStat would have to do that for (at least) all the 30,000+ files typically listed under the "Other" category. So we'll have to live with that limitation. Next thing to come: Locating files with a specific suffix from there. See [GitHub issue #48](https://github.com/shundhammer/qdirstat/issues/48). - 2017-02-12 Working on a _File Type Statistics_ window People who know WinDirStat inevitably want that _File Type_ view in QDirStat, too. I was really reluctant to do that because I didn't quite see the point; in WinDirStat, it serves mostly as a legend to the treemap colors since they are constantly changing in WinDirStat: The file type that consumes most disk space always gets color #1, the next-most color #2 etc., so it depends which directory you scan what color each file type gets. In QDirStat, the colors are stable; they are predefined and configurable in the _MIME Type Categories_ configuration dialog. And as most of you probably know, filename extensions have a much stricter meaning in Windows than on Linux/Unix systems; Linux people get very creative when it comes to using dots in filenames. Sometimes those dots delimit a filename's extension (suffix) from its base name, sometimes they are used for entirely different purposes. Anyway, there was one user who was insistent enough to make me reconsider, and I did some experimenting this weekend, and now we have an (albeit still experimental) **File Type Statistics** view. So far, that code lives in a Git branch, but I think it will stabilize in the next one or two weeks, so I will merge it to Git master. See the whole discussion with more screenshots at [GitHub issue #45](https://github.com/shundhammer/qdirstat/issues/45) - 2017-01-03 **New stable release: V1.2** _Upgrading to this release is highly recommended for Btrfs users:_ If you used QDirStat to scan a Btrfs partition, any subvolumes of that partition were not scanned (see [GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39)). Btrfs subvolumes were treated just like ordinary mount points (which, to all intents and purposes, they are). So you might have wondered why the _df_ command shows your 40 GB root filesystem as 97% full, yet QDirStat shows only about 7 GB. The rest might be hidden in subvolumes. QDirStat stops reading at mount points - which only makes sense because normally you want to know what eats up the disk space on that one partition that is filling up, not on any others like /home that are mounted there. Unfortunately, a Btrfs subvolume is also just another mount point, and QDirStat would stop reading there, too - at /var/log, at /var/spool, at /var/lib/libvirt etc.; a typical Btrfs root filesystem has about a dozen subvolumes, and all files in them were disregarded by QDirStat. This is now fixed: Despite Btrfs doing its best to make this difficult (using one single privileged system call for all its functionality, including simple info calls), QDirStat now detects if a mount point is a Btrfs subvolume and continues reading if it is. QDirStat uses /proc/mounts (or, if this is not available, /etc/mtab) to find this out. This is fixed in the _qdirstat-cache-writer_ script, too. - 2016-12-11 Bernhard Walle contributed some patches for MacOS X support. Thanks, Bernhard! - 2016-12-09 Fixed Perl (_qdirstat-cache-writer_) part of [GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39): QDirStat doesn't scan Btrfs subvolumes The _qdirstat-cache-writer_ script now also checks the device names of a mount point and its parent directory, not only their major/minor device numbers; so now it will not stop at Btrfs subvolumes while scanning. That script uses a more simplistic approach than QDirStat itself: It invokes the _df_ command with that path and parses its output. If the path contains very weird special characters, this may fail, in which case that directory (which at that point is already known to have a different device major/minor number than its parent) is considered a filesystem boundary, and that branch is not scanned. - 2016-12-08 Fixed C++ (QDirStat binary) part of [GitHub issue #39](https://github.com/shundhammer/qdirstat/issues/39): QDirStat doesn't scan Btrfs subvolumes This was a bit of a challenge since the relevant Btrfs commands to obtain any useful information about subvolumes all require root privileges, and I really wouldn't want to scare users off by prompting for a _sudo_ password. QDirStat now fetches the information from /proc/mounts (or /etc/mtab if /proc/mounts is unavailable) and does some heuristics (which are not completely fool proof) to check if a potential mount point is still on the same device. That means that it will no longer treat a Btrfs subvolume as an ordinary mount point where it stops reading by default, but it just continues. On the other hand, another Btrfs mounted into the current file system is of course treated as a normal mount point. See also the corresponding [GitHub issue](https://github.com/shundhammer/qdirstat/issues/39) for details. The Perl _qdirstat-cache-writer_ still has the old behaviour, i.e. it still stops at a subvolume mount point. This will be addressed next. - 2016-12-07 Fixed [GitHub issue #40](https://github.com/shundhammer/qdirstat/issues/40): Crash without useful error message when no display available When ssh'ing without -X to a remote machine and starting QDirStat there, it would just dump core and not issue any meaningful message. The fatal error message was only in the log file: ` :0 (): QXcbConnection: Could not connect to display` Now this message is also repeated on stderr, and in this particular case ("Could not connect to display"), it does not dump core any more, but just exits with error code 1. - 2016-12-06 **Warning to Btrfs users** (Fixed as of 2012-12-09) If you use QDirStat to scan a Btrfs partition, [any subvolumes of that partition are not scanned](https://github.com/shundhammer/qdirstat/issues/39): Btrfs subvolumes are treated just like ordinary mount points (which, to all intents and purposes, they are). So you might wonder why the _df_ command shows your 40 GB root filesystem as 97% full, yet QDirStat shows only about 7 GB. The rest might be hidden in subvolumes. QDirStat stops reading at mount points - which only makes sense because normally you want to know what eats up the disk space on that one partition that is filling up, not on any others like /home that are mounted there. Unfortunately, a Btrfs subvolume is also just another mount point, and QDirStat will stop reading there, too - at /var/log, at /var/spool, at /var/lib/libvirt etc.; a typical Btrfs root filesystem has about a dozen subvolumes, and all files in them are currently disregarded by QDirStat. You can of course click on "Continue reading at mount point" individually in QDirStat's directory tree for each one of them, but that's tedious. I am working on a solution. One approach would be to check if the current filesystem is Btrfs and list its subvolumes, but the Btrfs developers in their infinite wisdom decided that `btrfs subvolume list ` is a privileged operation, so QDirStat would have to use `sudo` with it and prompt for the root password (at which point I as a user would terminate the program and not use it any more). **This is broken by design.** A simple info command like that should not require root privileges. - 2016-10-31 (Halloween) **New stable release: V1.1-Pumpkin** It's about time for another official release to get the accumulated fixes and small changes out into the world. Since today is Halloween, this release shall be named _Pumpkin_ (as in the unforgettable Charlie Brown's _Great Pumpkin_). The last stable release, V1.0, was in mid-May (2016-05-16). Since then, there were 5 bug fixes and one small feature (the config file split up into independent parts so admins can provide presets to their users without overwriting the complete configuration), all described in greater detail below. - 2016-10-23 - Fixed [GitHub issue #32](https://github.com/shundhammer/qdirstat/issues/32): %p does not escape single quotes properly If you have a file name like `Don't do this.txt` (with a quote character in the name), the shell used when executing a cleanup action with this would complain about unmatched single quotes. QDirStat had always escaped such single quotes, but not the way common shells (Bash, Zsh) expect it: They don't want a backslash in front of that embedded single quote. Rather, you need to terminate the string with a single quote, escape the embedded quote with a backslash (or put it into double quotes), and then re-open the old string with another single quote. Thus, `'Don't do this'` becomes `'Don'\''t do this'`. This is certainly not what most people expect. I just wonder how much other software is out there that does it the intuitive (yet wrong) way: Just escape the single quote with a backslash (`'Don\'t do this'`). Of course, such file names should be avoided entirely, but you can't help some slightly broken MP3 ripper program doing it, so it needs to be handled correctly. - Fixed [GitHub issue #31](https://github.com/shundhammer/qdirstat/issues/31): Segfault with cleanup action while reading directories Now disabling cleanups that have a refresh policy other than "No Refresh" while directory reading is in progress; otherwise the re-read when the cleanup action has finished clashes with the directory read already in progress. This is not an optimal solution, but a very pragmatic one; the optimal solution might queue updates and execute them after the main read is done. - Fixed [GitHub issue #33](https://github.com/shundhammer/qdirstat/issues/33): Added command line option `--slow-update` (or `-s`) for slow remote X connections. - 2016-08-12 - Fixed [GitHub issue #23](https://github.com/shundhammer/qdirstat/issues/23): The internal cache writer would sometimes generate incorrect cache files because of buggy URL escaping resulting in an empty file name and thus invalid cache file syntax. This affected file names with colons (which is weird, but legal). One of these days I'm going to throw out all that QUrl stuff and replace the few things that I need with something that actually works consistently and not just under optimum conditions. - 2016-08-10 - Fixed [GitHub issue #22](https://github.com/shundhammer/qdirstat/issues/22): Cache files containing the root file system would not display correctly or segfault under certain conditions. This is now fixed. - Added "Refresh All" action to the main window tool bar. I had consciously avoided that because it's just too tempting to re-read the complete directory tree rather than think about what actually might have changed and then refresh just that, but it has become so common to use that action in web browsers that I found myself missing that more and more. And re-reading is not that expensive on today's mainstream PCs. - 2016-07-02 - Fixed [GitHub issue #21](https://github.com/shundhammer/qdirstat/issues/21): When started from a desktop menu, i.e. without any command line parameters, QDirStat would not prompt for a directory to read, but read the current directory (typically the user's home directory) right away. - More graceful handling for nonexisting paths specified on the commmand line: It now no longer just throws an exception right after starting the program (which looks like a crash to the unwary user), but posts an error popup instead and then asks for a directory to read. - 2016-06-29 - V1.01 (Development version) - Split up config file into four separate ones below ~/.config/QDirStat: - QDirStat.conf - QDirStat-cleanup.conf - QDirStat-exclude.conf - QDirStat-mime.conf This should make it much easier for site administrators to provide their own site-wide cleanup actions, exclude rules, or MIME categories. I did this with this in mind: http://moo.nac.uci.edu/~hjm/kdirstat/kdirstat-for-clusters.html Here, they describe how users should overwrite their KDirStat config file with one provided by the site admin so all users have those carefully crafted cleanup actions. But that also means that all other settings get lost each time there is a change in any of those commands, and users have to update that config file again. With the latest change, it is now possible to only replace the cleanup action config (QDirStat-cleanup.conf) and leave everything else untouched. Notice that this is far from a perfect solution; all cleanup actions the user added himself still get lost. But doing this perfectly might pretty quickly become an overengineered solution that would be hard to understand for everybody. As for migration from previous single-file configurations, QDirStat does that automatically: It reads the single file and moves the respective parts where they belong. No need to bother with any migration scrips or anything like that. - 2016-05-16 **First stable release: V1.0** After 3 months of Beta phase and 3 Beta releases, here is finally the official first stable release of QDirStat: Version 1.0. In terms of source code, there were very little changes from the last Beta (0.98-Beta3 from 2016-04-08) and no real code change (only the version number increased) from the last check-in from 2016-04-11. This version can really be considered stable in the truest sense of the word. It was not rushed out the door, and there were no hectic last minute changes. It is well tested, and the community had ample opportunity to report any problems. - 2016-04-11 - _buxit_ reported [GitHub issue #16](https://github.com/shundhammer/qdirstat/issues/16) and contributed the fix for it shortly afterwards: When clicking in the treemap, the corresponding item in the tree view was not always scrolled into the visible area. Now it is. - 2016-04-08 - Beta 3 - Fixed [GitHub issue #15](https://github.com/shundhammer/qdirstat/issues/15): After a cleanup action is executed that needs refreshing the affected subtree, the parent directory is selected, which is intentional so the user's focus is not thrown off completely. There was a bug when you selected an item in the treemap afterwards, that change was not correctly propagated to the internal selection model: The parent directory remained selected (which was wrong), and the newly selected item was just added to the selection, i.e. that item and (typically) its parent directory was selected. When a potentially dangerous cleanup operation was now started, it would affect not only that item, but also the directory; and, worse, that directory often went out of the visible scope of the tree view. Yes, the confirmation popup would ask for both of them, but you all know how quickly users click away those popups without really reading them. This bug is now fixed. - Improved the confirmation popup. Now highlighting directories much more if there is a "mixed" selection, i.e., both directories and non-directories are selected at the same time: ![New cleanup confirmation popup] (https://cloud.githubusercontent.com/assets/11538225/14390476/8b022c9a-fdb7-11e5-8eef-a5ba304d3bab.png) - 2016-03-20 - Beta 2 Beta 1 has now been out for 6 weeks, and I have not received one single bug report during that time. Maybe it's just business as usual, and people just keep waiting for others to do the testing, while they themselves are waiting for a stable release. Well, okay, so let them have their way: The current code is now officially V0.92 Beta 2. And it won't be another 6 weeks; the next versions will come a lot more quickly. Once V1.0 final is out, any bug reports will have to wait until there is time to work on them. So, folks, use those Betas wisely. BTW those who actually did test it will find that QDirStat is a lot more stable even in Beta 1 than other pieces of software in their official final release. - 2016-02-27 - Debian / Ubuntu packaging contributed by Nathan Rennie-Waldock. He also made a PPA repository available for various Ubuntu versions - see [Ubuntu packages](https://github.com/shundhammer/qdirstat#ubuntu) below. - 2016-02-06 - Added tab for exclude rules configuration to the config dialog (see screenshot above). That's it: That was the last missing major feature. **I hereby declare QDirStat to be Beta.** _Please use the GitHub issue tracker for any bug reports._ - Exclude rules can now optionally match against the full path again. I had changed this for just the directory name without the path by default, which makes regexps a lot simpler. You can now select the old behaviour, too, if you wish. This is configurable in the exclude rules tab of the config dialog. - Made the config file format of the new view header columns human readable and editable. The first version from yesterday used the native format of Qt's QHeaderView -- a QByteArray in hex encoding. This was a sorry excuse for a settings format - not usable for anybody, not legible, much less editable. Trolls, WTF? Pretty and usable formats everywhere else, and a glorified (well, not even glorified) hexdump here? I hope some admins who might want to provide ready-made config files for their users will appreciate that. If not, this is just for consistency's sake; I want to be able to read and edit my config file as I like, even without any graphical config dialogs. - The tree view now uses "middle eliding" for texts that don't fit into a column. It used to elide at the end of the text, but that's not necessarily useful for long file names; they often differ only at the end with lots of text at the start in common. So, now it's no longer "VeryLongTextBlurb...", but "VeryLongTe...foo.o" if anything needs to be cut off. Of course, this makes most sense with the new column width modes, otherwise your column will simply be resized wide enough to fit everything in. - 2016-02-05 - Extended the context menu of the tree view header columns -- see latest screenshot above. The configuration is now saved and restored when entering the program. You can move the columns around (i.e. change their order), hide columns, and choose between automatic column width ("auto size") or setting it manually ("interactive size") for each column individually or for all columns at once. - You can now read a cache file directly from the command line: ```` qdirstat --cache cache-file ```` - Fixed GitHub issue #9: [qdirstat-cache-writer creates broken cache file if some directory lacks Exec flag] (https://github.com/shundhammer/qdirstat/issues/9) - Fixed GitHub issue #10: [incorrect handling of sparse files with 0 allocated blocks] (https://github.com/shundhammer/qdirstat/issues/10) - 2016-02-02 - Fixed a bug where directory names with a colon ":" were cut off when reading a cache file, thus all files and directories below that point could not find their parent directory, so that complete branch was cut off. - Much improved performance for treemaps of large directory trees: Now not rebuilding the treemap immediately when the user resizes the window or drags the splitter dividing the main window, but just scheduling an update in 200 milliseconds. If another rebuild is requested during this time, the previous one is discarded. The net effect is that the treemap now is rebuilt only once, not for every pixel size change of the treemap subwindow, so the application remains responsive during dragging the splitter or resizing the main window. - 2016-02-01 - Fixed GitHub issue #6: [NullPointerException when reading cache file] (https://github.com/shundhammer/qdirstat/issues/6) The DirTreeModel and the DirCacheReader were somewhat out of sync with regard to which directory is ready for display in the tree view. - 2016-01-30 - Added a context menu for the tree view header. It's still very limited, but you can now turn off auto-resizing of the tree columns for the current session. - Added a .desktop file so QDirStat should now show up in the menu of the major desktop environments (KDE, GNOME, Xfce, Unity, ...) and in their file managers' "Open With" menus when you right-click a directory. - 2016-01-29 - Since the missing tabs in the config dialog will also have a list of things at the left and details of the one current item of those things at the right, I tried to move out the common part of this as a base class. Since the things those config tabs manage have different types, I tried a C++ template class. But **it turns out that in this year 2016 Qt's moc still does not support templates. WTF?!** - 21:00 (Grrrr) Okay, I found a workaround, albeit a pretty ugly one: Work with void pointers and forced type casts. Yuck. That's being bombed back to the early 1990s - we had to do this kind of stuff back with OSF/Motif in plain C all the time. Type safety was unknown back then; you could get all kinds of nasty surprises by casting pointers slightly wrong, and the compiler had no chance (even if it hadn't been that crappy SunOS C compiler, but a decent GCC) to catch any of this. 25 years later, and we are still stuck with that kind of stone age programming - just because some tool never got ported to the 21st century. Sigh. Yet another day of develpment completely wasted due to insufficiencies of underlying tools. Just great. I am getting fed up with this. - 2016-01-22 - Improved usability of refreshing the tree after cleanup actions: They used to leave the tree behind with nothing selected, the branch the user just worked in closed (which is natural since it needed to be re-read from disk) and scrolled to another position - maximum disorientation for the user. Now the parent directory is selected, giving at least some hint where the action took place. It's not optimal yet, but much better than before. - Improved usability of the tree widget: When an item in the treemap is selected, all other branches in the tree are now collapsed before the new branch is opened. But this required working around some design flaws in the underlying _QTreeView_ class. **Rant:** Trolls, didn't it ever occur to you that if you are _constantly_ using that _d->expandedIndexes_ from _QTreeViewPrivate_ in the _QTreeView_ public class, derived widgets might need that information, too? There is **no way** to access the currently expanded items other than cheating in some creative way. Seriously, I am not going to duplicate that bookkeeping with the _expanded()_ and _collapsed()_ signals, always being off by some items or not getting the information that items were removed (or listen to half a dozen more signals for even more advanced bookkeeping). If a widget class cannot provide that kind of elementary information to its derived classes, it's poorly designed. Period. - 2016-01-18 - Applied Qt4 compatibility patches from Michael Matz. The only nontrivial issue was a thin wrapper around QProcess to make it store the program to execute and its arguments in the constructor and use those later with a plain start() without any more arguments. - 2016-01-16 - The MIME categories and the corresponding treemap colors can now be configured - see screenshot above. Yes, this is a real treemap widget as a preview for the colors, complete with a demo directory tree with a random number of files with random sizes (i.e. it looks different for each invocation). That part was the last major feature that was missing; now it's only little stuff that's left (still quite a number of it, though). - Treemap colors are now no longer fixed; there is now a rules engine called MimeCategorizer. It uses a new class MimeCategory that groups MIME types (by filename, not by magic numbers in the file) into broad categories like "Documents", "Videos", "Music", "Images". Each of these categories has a list of filename extensions that belong to it (".mp4", ".wmv", ".mov" etc. for "Videos", for example). The categorizer uses a very fast lookup map for the vast majority of the rules (simple file extensions), but it can also use more powerful wildcards wherever you like them. - The log file is now created per user: It's now /tmp/qdirstat-$UID.log, which for most Linux home users (with only one user account on the machine) is typically /tmp/qdirstat-1000.log . - 2016-01-15 - Added new macros for use within cleanups: %terminal and %filemanager. They are expanded to the terminal window or file manager application, respectively, of the current desktop (KDE, GNOME, Xfce, ...). I just wasted four hours (that could have been put to better use adding missing features - grrrr) because KDE's konsole misbehaves in every way possible (leading today's WTF count with 3): - It won't let me start it in the background from within QDirStat; it simply exits. I tried all kinds of command line arguments (--nofork, --hold), I tried to wrap it into a subshell, into the _nohup_ command - nothing helped. WTF? - It exits when QDirStat exits. Well, since it won't let me start it in the background, that's not too surprising. Still, if it does its own fork(), WTF? - It doesn't give a damn about the current directory you start it from, it needs its --workdir command line argument. WTF? - Added %d macro for cleanups: This is the directory name with full path. For directories, this is the same as %p. For files, this is their parent directory's %p. - %terminal : Terminal window application of the current desktop; one of - konsole - gnome-terminal - xfce4-terminal - lxterminal - eterm - xterm (fallback) - %filemanager : File manager application of the current desktop; one of - konqueror - nautilus - thunar - pcmanfm - xdg-open (fallback) - Which desktop is used is determined by the _$XDG_CURRENT_DESKTOP_ environment variable. Currently supported: - KDE - GNOME - Unity - Xfce - Lxde - Enlightenment (no clue how to start its file manager, though - using xdg-open here) - Users can override this with the _$QDIRSTAT_DESKTOP_ environment variable, so you can get, say, the Xfce terminal or file manager despite currently running KDE if you set export QDIRSTAT_DESKTOP="Xfce" - Of course, you can still simply use your favourite file manager if you simply use its command instead of %filemanager in the default "Open File Manager Here" cleanup action. - Added new standard cleanup actions: - Git clean. Start "git clean -dfx" in the current item's directory. This is relevant for developers or for people who regularly build software from Git repositories. - Clear directory contents. This removes everything inside a directory, but leaves the directory itself intact. ~/.thumbnails or browser cache directories are typical candidates for this with their ever-growing content: You probably want to keep the directory, but get rid of everything inside it. - Redefined the semantics of the _file manager_ cleanup action: It no longer tries to open files with the corresponding application depending on MIME type, it now always opens a file manager in that directory (which can open the file in its app if you want that). It's now also renamed to "open file manager here". If you still want the old behaviour, you can easily add your own cleanup action with the "xdg-open %p" command. - Added "Troubleshooting" section in this document. - Cleanup actions that have an icon are now added to the tool bar. Right now, only some of the predefined actions have an icon. There is currently no way for the user to specify an icon for a cleanup action. - 2016-01-13 Added "move to trash", this time as a normal action in the "Edit" menu, the toolbar and the context menus. This is a real implementation of the XDG Trash specification. It does not rely on outside tools that might or might not be available. - 2016-01-12 We have a first MacOS X port! Sonja Krause-Harder volunteered to install a Qt development environment (11 GB! Yikes!) on her MacBook. I would have expected some changes, but a simple "qmake; make" just did the job. Amazing! -- The major challenge was to find where "qmake" gets installed in that MacOS Qt environment. - 2016-01-10 Went through the old KDirStat changelog and found a few bugs that I had fixed there -- and promptly repeated with the new QDirStat: - Disable cleanups while reading directories. This would result in a segfault. - No longer showing the path of the current directory being read. This sped up reading /usr on my machine from 9.5 sec to 1.5 sec (!). - 2016-01-09 Cleaned up this README.md file. It had grown much too long. - 2016-01-08 Cleanups are now configurable - see screenshot. - Cleanup actions can now be added, deleted, and moved up or down the list. There is no longer a hard limit to the number of cleanup actions; create as many as you like. Of course, your screen size is still the limit for those menus. ;-) - In addition to the old cleanup parameters, you can now configure the output window behaviour. The default is "show after timeout" with a timeout of half a second. This may sound pretty short, but I started with 3 seconds and found that it felt sluggish. A modern PC can get a lot of things done in half a second; yet waiting for more than that feels like an eternity. So if any action takes longer than that, an output window pops up. Of course, if there is any error, it pops up anyway. - You can now configure the shell to use. I was weighing the pros and cons of always using either /bin/sh or the user's login shell, and I found that there is no killer argument in favour or against either option. For example, I use the _zsh_, and while it's a great interactive shell, it did give me problems for that "remove junk files" cleanup: "rm -f *.o *.bak *~" -- when any of the wildcards cannot be expanded because there is no such file, it complains. Okay, you can wrap the whole command in "/bin/bash -c", but that's yet another indirection, so now you can configuare /bin/bash for that particular cleanup action. On the other hand, for some things I might want my original shell environment, so I do want my login shell by default. This is now the default behaviour: Try $SHELL (the user's login shell), and if that environment variable is not set or whatever is set there is not executable, it falls back to /bin/bash and then /bin/sh. And you can still enter your own in an editable combo box (but not "ruby" or "perl" because the "-c" option is still added automatically). - 2016-01-05 I admit I had never really liked the way the output of cleanup actions was typically hidden. Most of the times I couldn't care less, but sometimes there were error messages that mostly went unnoticed - such as no permissions to convert a directory into a compressed tarball. Now we have something new: A process watcher window that looks very much like a terminal window. The commands and their output are displayed there: Normal output (stdout) in amber, error output (stderr) in red. It will be configurable for each individual cleanup action if this window is desired: You can choose to always open it, to not open it at all -- or to have it automatically open when there is any output on stderr. And there is also a checkbox to automatically close it when the cleanup process finishes successfully. This is all not 100% perfect yet, but it works quite well already. - 2016-01-04 Cleanups are back. They still need some work, and you'll have to edit the config file in ~/.config/QDirStat/QDirStat.conf to configure anything, but they work. - 2016-01-03 We are getting nearer to the target: - Settings are read from and written to the settings file in all relevant places. This includes what columns to display and their order. See section 'Settings' below. - Refreshing the selected tree branch, continuing reading at mount points and at excluded directories now works. - Context menus are back. I am somewhat proud of the way my new ActionManager handles that with Qt introspection to avoid duplicating stuff: I wanted to keep the QActions in the Qt Designer file. That ActionManager keeps a pointer to the MainWindow that is the parent of all those QActions, and attached views can search that widget tree for action names (yes, that works only if you keep those QObject names tidy - which I am doing anyway). - Found some more icons for those actions. - Exclude rules are now greatly simplified. They no longer get the entire path to match which requires quite complex regexps, they only get the last path component - i.e., no longer "/work/home/sh/src/qdirstat/src/.git", but only ".git". You can now even tell the exclude rule to use a simplfied syntax: "FixedString" or "Wildcard" in addition to the normal "RegExp". - Still missing (this list is getting considerably shorter): - Cleanups - Settings dialog - 2016-01-01 New Year release - Added mouse operations to the treemap. Some where there in the old kdirstat (but I guess not many users knew about them), some are new: - Left click: Select item and make it the current item. - Ctrl+Left click: Add item to selection or toggle selection. - Middle click: Select the current item's parent. Cycle back at toplevel. - Double click left: Zoom treemap in. - Double click middle: Zoom treemap out. - Mouse wheel: Zoom treemap in or out. - Reliably sort by pending read jobs while reading. - Fixed crashes if wildly clicking in the tree while reading. Yes, I know... "Doctor, it hurts when I do that!" - "Then don't do that." - 2015-12-31 New Year's Eve release - Added the URL of the current item in the status bar at the bottom of the main window. If more than one item is selected, it displays the total sum of all selected items there. - Treemap zoom in / out / zoom reset works. The treemap now automatically zooms out if an item outside its current scope is clicked in the tree view. - Added more menu and toolbar actions and icons for many of them. - The treemap's red "current item" rectangle is now stippled instead of a solid line if the current item is not also selected (users can do that with ctrl-click). - Added "about" dialogs for the program and the used Qt version. - 2015-12-30 Treemap rendering now works as expected, and selecting items (including multi-selection with shift-click and ctrl-click in the tree view and ctrl-click in the treemap view) works. It was a bit of a challenge to avoid Qt signal ping-pong between the selection model object and the two views. - 2015-12-28 Treemaps are back. It's not perfect yet, but the basic rendering works. I admit I was somewhat scared of that part, but the transition from Qt3 QCanvas to QGraphicsScene / QGraphicsView went much smoother than I had expected. I am very glad I don't have to dig deep into the math again with those cushioned treemaps; that part worked completely unchanged. :-) - 2015-12-27 The tree view now supports _extended_ selection, i.e. you can shift-click to select a range of items or ctrl-click to select or deselect individual items. This was the most requested feature for the last KDirStat. This means you can now select more than one item at once to move it to the trash can etc. (once cleanup actions are back). - 2015-12-25 Christmas release - Sorting is now done internally in the DirTreeModel, and it's blazingly fast. It uses lazy sorting - postponing sorting until the last possible moment for each tree branch. Maybe the branch will never get visible, and then it doesn't need to be sorted at all. The QSortProxyModel is gone. - Reading cache files finally works again. It was quite some hassle to find all the places where the invisible root item that is required for the QTreeView / QAbstractItemModel make a difference. I hope now I caught all of them. - Fixed some bugs that resulted in segfaults. Well, it's a development version. Such things happen. - Removed the section about K4DirStat in this README.md; that information was outdated. It turns out I hadn't looked at the most recent sources of K4DirStat - that was entirely my own stupidity. My apologies. Since right now I don't have an informed opinion about K4DirStat, I preferred to remove that section entirely for the time being. Looks like K4DirStat is indeed ported to Qt5 now. - 2015-12-20 First usable preview version - see screenshot above. It's still pretty rough, and sorting via the QSortProxyModel seems to be awfully slow once a number of tree branches were ever opened. Looks like I'll have to do that myself, too. - 2015-12-18 Found the crippling bugs that made the DirTreeModel do crazy things. None of the Qt classes proved to be helpful to find that - they just happily do the crazy things. That's what I call poor design. Now there is a first working QDirStat with a useful display tree, including icons (but no percentage bar graph yet). - 2015-12-07 First working DirTreeModel -- still minimalistic, but working. - 2015-12-06 Created tree model based on QAbstractItemModel. Compiles, but dumps core so far. - 2015-12-05 Imported and ported directory tree data classes. Hammered through the compiler, but nothing usable so far. - 2015-11-28 QDirStat project is being set up. Nothing usable so far. ## KDirStat KDirStat is the predecessor to QDirStat. QDirStat is an 80% rewrite of the KDE3 based KDirStat. KDirStat home page: http://kdirstat.sourceforge.net/ Sources: https://github.com/shundhammer/kdirstat ### KDirStat History _(Incomplete list, just highlighting important releases)_ - 2006-06-01 KDirStat 2.5.3: The last KDE3 based version. - 2006-01-08 KDirStat 2.5.2: - New: Read and write cache files - 2005-02-22 KDirStat 2.4.4 - New: Handle hard links and sparse files - 2003-01-30 KDirStat 2.3.5 - New: colored treemap - 2003-01-05 KDirStat 2.3.3 - New: Treemaps (monochrome only) - Communication between treemap and tree list view: Select an item in one view, and it is automatically selected in the other one, too. - 2002-02-25 KDirStat 2.0.0 - Complete rewrite for KDE 2 / Qt 2 - Doing internal caching and (very) lazy creating of QListViewItems for improved performance and resource consumption - 2000-01-21 KDirStat 0.86 for KDE 1 announced -- the first public version. qdirstat-1.4/doc/GitHub-Workflow.md000066400000000000000000000267111311502036700172770ustar00rootroot00000000000000# GitHub Workflow for Open Source Projects (c) 2017 Stefan Hundhammer License: GNU Free Documentation License This is the workflow used for Open Source projects like QDirStat and YaST. Some of this is mandated by the tools used (git, GitHub), some of it is just best practices. ## Overview Even though GitHub hosts the original source code repositories for those projects, you don't work directly in them. Rather, you create your own forked repository (your _fork_), work in that one, and when you finished something you want to contribute to the original repository (called _upstream_), you create a pull request. That pull request is reviewed by the owner of the original project or by or senior team members. They might ask you for changes if anything in your pull request does not meet the project's quality criteria or violates the coding style. In that case, you add more commits to the pull request, and it is reviewed again etc. until everybody is satisfied and it is either merged (which is the normal case) or it is finally rejected (which is a very rare thing). When your changes are merged, you pull or rebase your fork against _upstream_ again so it is up to date, and then you can freely work on new things. One holy rule is that **upstream master always has to work**, even between official releases. This is much easier to achieve when everybody works in their own fork, preferably in their own branch of their own fork. ## Initial Setup - If you don't have one yet, create a user account at [GitHub](https://www.github.com). - Make sure to upload your ssh key to your GitHub account. [More info...](https://help.github.com/articles/connecting-to-github-with-ssh/) - Log in at GitHub. - Fork the original (upstream) repository to your GitHub account. You now have your own repo with that name. **But it does not automatically sync itself with the upstream repo** as others commit changes there after you forked; you have to do that manually (see below). - In a shell on your working machine (preferably Linux), clone your forked repo to that machine: cd ~/src git clone -o mine git@github.com:kilroy/qdirstat.git Where _kilroy_ is your GitHub user name which is part of the URL of that fork. **Make sure to use the "git@github" URL**, not the "https://" URL: The https URL is only useful for pulling (i.e. for read-only access), not for pushing (i.e. for read-write access). Since you also want to commit changes to that repo, you need read-write access. _mine_ is the name of that _remote_. The default would be _origin_, but that might lead to confusion because we'll add _upstream_ in a moment, so there will be two remotes. If you have the same distinct name for all your forks, your life will be considerably easier. You might also call it the same as your user name (_kilroy_) here. Just make sure you use the same one for all your repos. You now have an entry like this in your `.git/config` file in that newly cloned repo: [remote "mine"] url = git@github.com:kilroy/qdirstat.git fetch = +refs/heads/*:refs/remotes/kilroy/* - Add the original repo (_upstream_) as another _remote_ so you can pull / fetch from there to keep your fork up to date: git remote add upstream git@github.com:shundhammer/qdirstat.git You now have two _remote_ entries in your `.git/config`: [remote "mine"] url = git@github.com:kilroy/qdirstat.git fetch = +refs/heads/*:refs/remotes/kilroy/* [remote "upstream"] url = git@github.com:shundhammer/qdirstat.git fetch = +refs/heads/*:refs/remotes/huha/* You can also check this with this command: git remote -v mine git@github.com:kilroy/qdirstat.git (fetch) mine git@github.com:kilroy/qdirstat.git (push) upstream git@github.com:shundhammer/qdirstat.git (fetch) upstream git@github.com:shundhammer/qdirstat.git (push) Notice there is no _origin_ as would be the default if we hadn't used `-o mine` during `git clone`. If you forgot that, you can always rename a remote later (this affects only your working copy, not the repo on the GitHub server): git remote rename origin mine - Make sure your user name and e-mail address are up to date and valid in your `$HOME/.gitconfig`: [user] name = Kilroy Taylor email = kilroy@mydomain.com You can also use separate user names and e-mail addresses for different projects; simply edit .git/config in that project and add a `[user]` section there. That name and that e-mail address will be recorded for each commit you make, so this is where your karma points go and how you will be known to the community. So choose that name wisely. Real names are preferred, albeit not enforced. ## Common Tasks ### Working in Your Fork Your fork is yours. You can do there whatever you like. But if you want to contribute to the upstream project, you should follow some simple rules: - Keep your fork in sync with upstream as good as possible (see next section about rebasing). - Work in a feature branch for everything you do. This makes your life much easier when a pull request takes some time to get accepted: You can quickly switch between the pull request and add some more changes there to satisfy the reviewers and the next feature you might already be working on. - Prefix your branches with your user name so you can easily tell them apart form any upstream branches. Example: You plan to work on a _transmogrify_ feature. So you start from _master_, create a branch for that and check it out: git checkout master git branch kilroy-transmogrify git checkout kilroy-transmogrify Now work in that branch and commit your changes there. Don't forget to push it to your GitHub fork every once in a while: git push mine kilroy-transmogrify At some point, prepare a pull request to get your changes upstream. But before you do that, you should rebase your branch so it is in sync with upstream (except for your changes, of course). ### Rebasing (Updating Your Fork) As mentioned before, when you fork a repo at GitHub, this will not automatically update itself. As new commits are added to the upstream repo, your fork will increasingly get out of date, so you have to update it on a regular basis. There are two methods: `pull` and `fetch` / `rebase`. As long as you don't do any changes in your fork, there is no noticable difference; but when you work in your fork, i.e. when you commit changes there, `fetch` / `rebase` is highly recommended to keep the "railway yard" of parallel branches with merge and fork points in the `gitk` display to a minimum. First, get the data from the remote server (GitHub): git fetch --all **Make sure to use `--all`, not `-a`** which is something different (yes, this is a common, stupid, unnecessary pitfall of that git command). If that command remains silent, there was no change, so everything was still up to date. If it reports something like remote: Counting objects: 21, done. remote: Compressing objects: 100% (21/21), done. ... it did fetch some changes. Notice that the changes are only in the `.git/` subdirectory so far; they are not applied to your source tree yet. Now **make sure you don't have any pending changes** anymore. Check with git status If it reports any pending changes, you can choose to commit them or to _stash_ them, i.e. put them into temporary storage: git stash you can later retrieve them with git stash pop Now rebase. Typically, you want to do that based on the _master_ branch of _upstream_: git rebase upstream/master This basically checks where you branched off your working copy, then temporarily takes away your commits from that point on, then applies the commits from upstream that have accumulated in the meantime. As a last step, it tries to apply your commits on top of all that. Since git commits are basically little more than patches (diffs) on top of patches, this may or may not work flawlessly. If you are lucky, your commits still apply cleanly, and you are set: You successfully rebased your repo. If any of your commits does not apply cleanly, you will have to resolve merge conflicts and afterwards call git rebase --continue to get to the next commit. When all is done, you can push the result to your fork. Since the rebase caused the parent SHAs of your commits to change, you will need to force-push; this is normal and expected. git push -f mine master or git push -f mine branch-name if you were working in a branch. ### Preparing a Pull Request for Upstream When you have some changes you would like to get upstream (to contribute to the upstream project), you create a _Pull Request_. To do that, make sure those changes are in a separate branch. If you worked on a separate feature branch like recommended earlier in this document, you can simply use that one as the branch for the pull request. But remember to stop working on new features in that branch. As soon as you use a branch for a pull request, you only commit changes there that were requested by the reviewers. Before creating a pull request, rebase your branch against upstream/master once more and make sure to push your changes (even the latest ones) to your fork: git fetch --all git rebase upstream/master git push mine kilroy-transmogrify After that, go to your fork in the GitHub web UI, select your branch and click "New Pull Request". Fill the form with a meaningful description of your changes and send it off. Now you will have to wait for feedback from the upstream project owner. In the meantime, you will probably want to continue working on more things. Remember to leave the pull request branch alone during that time; create a new one for your next changes. It is perfectly okay to base that new branch on the last one that has now become a pull request: git branch kilroy-hyperforble git checkout kilroy-hyperforble ...(work in that branch...) When you get feedback about your pull request from your reviewers, you might have to add some more changes to the pull request branch. So switch to that branch (stash or commit any pending changes to your new working branch during that time): git checkout kilroy-transmogrify ...(add requested fixes)... git commit -am "Added code review changes" git push mine kilroy-transmogrify Remember that despite the fact that your branch has become a pull request, it is still hosted in your fork (_mine_) rather than upstream, so you still have to push to your fork, not to upstream (which you probably can't anyway because of insufficient permissions). After that, switch back to your working branch and continue working there: git checkout kilroy-hyperforble git stash pop # if you stashed any changes ### Updating Your Fork After Your PR is Merged Remember that after your pull request has been merged, _upstream/master_ has changed, so make sure to fetch and rebase: git fetch --all git checkout master git rebase upstream/master There should be no conflicts (provided you are only working in branches - which you should). Don't forget to push the new master to your fork, too: git push mine master No `-f` or `--force` needed here either if you only work in branches. ## Further Reading https://guides.github.com/activities/contributing-to-open-source/ https://guides.github.com/ https://www.atlassian.com/git/tutorials/merging-vs-rebasing https://www.udacity.com/course/how-to-use-git-and-github--ud775 qdirstat-1.4/doc/Installing.md000066400000000000000000000001661311502036700164050ustar00rootroot00000000000000# Installing QDirStat See [main document] (https://github.com/shundhammer/qdirstat/blob/master/README.md#installing) qdirstat-1.4/doc/QDirStat-for-Servers.md000066400000000000000000000173171311502036700202150ustar00rootroot00000000000000# QDirStat for Servers ## Executive Summary QDirStat can be used for headless (no X server, no X libs) servers: It comes with a Perl script qdirstat-cache-writer that can collect data on the server. You just have to copy the data file from the server to your desktop machine where you can view the data with the normal QDirStat application. ## Server-Side System Requirements - Perl - Some command to copy files to your desktop machine: scp, ftp or whatever ## One-time Server Setup Copy the qdirstat-cache-writer script to the server. You can find that script in scripts/ in the QDirStat source directory or in /usr/bin when you installed QDirStat as a binary package. Alternatively, you can fetch it directly from GitHub: ssh root@myserver cd /usr/local/bin wget https://github.com/shundhammer/qdirstat/blob/master/scripts/qdirstat-cache-writer By all means, have a look inside to convince yourself that there is no malicious code. It's a very simple script. ## Collecting Data on the Server Side Like QDirStat itself, qdirstat-cache-writer limits its operation to one filesystem. It does not by default descend into mounted filesystems. It scans Btrfs subvolumes, though. For each filesystem you wish to collect data from, create a qdirstat cache file: sudo qdirstat-cache-writer / myserver-root.cache.gz sudo qdirstat-cache-writer /var myserver-var.cache.gz sudo qdirstat-cache-writer /srv myserver-srv.cache.gz ... You should invoke the script with root permissions (thus sudo) to make sure you can read all the directories. The first parameter is the starting point of the directory scan, typically that filesystem's mount point. The last parameter is the name of the output file. The default is .qdirstat.cache.gz which is useful for desktop machines, but not for servers, so it is recommended to explicitly specify a name here. You might consider collecting those data in a nightly cron job. ## Transfer Data to Your Desktop Machine scp "root@myserver:~/tmp/*.cache.gz" ~/tmp ## View Data on Your Desktop Machine qdirstat --cache ~/tmp/myserver-root.cache.gz or qdirstat -c ~/tmp/myserver-root.cache.gz or start qdirstat and use "Read Cache File..." from the "File" menu. ## Limitations You cannot use QDirStat's built-in cleanup operations, of course; they'd still run on your desktop machine instead of your server. There is also no indication that your are seeing the contents of a cache file rather than data collected live from your local system, so be careful what you are doing. ## Security Concerns Don't give a cache file to somebody you wouldn't trust to read all directories on that server with root permissions. Don't even make it easily available to such persons. If the directory contents include sensitive information, treat the cache file with the same degree of confidentiality as you would the original directory on the server. ## Why Not Use QDirStat over Remote X? You can do that as well, of course. But that means you'll need at least the X11 libs and the Qt libs (Qt 5 by default) on the server. And you need to install QDirStat on the server, too. Also notice that with the advent of Qt 5, remote X has become very slow with Qt applications: Qt 5 no longer uses Xlib / X protocol primitives for painting (XDrawRectangle etc.), but renders into a pixel buffer and transfers that pixel buffer. While this is a considerable speedup for local X, it is pretty slow for remote X. To ease that pain a little, QDirStat has a --slow-update (or -s) command line option which is intended for remote X: ssh -X myserver qdirstat --slow-update This makes QDirStat update its display only every 3 seconds rather than the default 333 milliseconds during directory reading. This interval can be configured in `~/.config/QDirStat/QDirStat.conf` : [DirectoryTree] SlowUpdateMillisec = 3000 ## Looking Into a Cache File A cache file is a gzipped text file, so it can be viewed with `zless`: [qdirstat 1.0 cache file] # Generated by qdirstat-cache-writer # Do not edit! # # Type path size mtime D /var 4096 0x53cef170 # Device: /dev/sda6 L run 4 0x54bbf0e3 L lock 9 0x54bbf0e3 D /var/cache 4096 0x58125237 D /var/cache/dictionaries-common 4096 0x53ceef0a F hunspell.db 188 0x53ceef0a F ispell-dicts-list.txt 0 0x53ceef0a F wordlist.db 267 0x53cef022 F ispell.db 188 0x53ceef0a F jed-ispell-dicts.sl 881 0x53cef024 F aspell.db 741 0x53cef024 F sqspell.php 366 0x53cef024 F emacsen-ispell-default.el 173 0x53ceef0a F emacsen-ispell-dicts.el 897 0x53cef024 D /var/cache/cracklib 4096 0x53ceef8b F cracklib_dict.pwi 22972 0x53ceef8b F cracklib_dict.hwm 1024 0x53ceef8b F src-dicts 104 0x53ceef8b F cracklib_dict.pwd 412618 0x53ceef8b D /var/cache/cups 4096 0x58a842ad F job.cache 992 0x58a842ad F ppd-updates 271 0x567b004a The file format is described in detail in [cache-file-format.txt] (https://github.com/shundhammer/qdirstat/blob/master/doc/cache-file-format.txt). In short, each line contains one entry for a file, directory, or symlink. - The first field is the type: 'D' for directory, 'F' for file, 'L' for symlink. - The second field is the name; for directories, that's always the full path, for files, the path can be omitted. - The third field is the size of the object (not including any child objects). - The fourth field is the mtime in hex (seconds since 1970-01-01 00:00:00). ## Long file format qdirstat-cache-writer -l /var /tmp/var.cache.gz zless /tmp/var.cache.gz [qdirstat 1.0 cache file] # Generated by qdirstat-cache-writer # Do not edit! # # Type path size mtime D /var 4096 0x53cef170 # Device: /dev/sda6 L /var/run 4 0x54bbf0e3 L /var/lock 9 0x54bbf0e3 D /var/cache 4096 0x58125237 D /var/cache/dictionaries-common 4096 0x53ceef0a F /var/cache/dictionaries-common/hunspell.db 188 0x53ceef0a F /var/cache/dictionaries-common/ispell-dicts-list.txt 0 0x53ceef0a F /var/cache/dictionaries-common/wordlist.db 267 0x53cef022 F /var/cache/dictionaries-common/ispell.db 188 0x53ceef0a F /var/cache/dictionaries-common/jed-ispell-dicts.sl 881 0x53cef024 F /var/cache/dictionaries-common/aspell.db 741 0x53cef024 F /var/cache/dictionaries-common/sqspell.php 366 0x53cef024 F /var/cache/dictionaries-common/emacsen-ispell-default.el 173 0x53ceef0a F /var/cache/dictionaries-common/emacsen-ispell-dicts.el 897 0x53cef024 D /var/cache/cracklib 4096 0x53ceef8b F /var/cache/cracklib/cracklib_dict.pwi 22972 0x53ceef8b F /var/cache/cracklib/cracklib_dict.hwm 1024 0x53ceef8b F /var/cache/cracklib/src-dicts 104 0x53ceef8b F /var/cache/cracklib/cracklib_dict.pwd 412618 0x53ceef8b D /var/cache/cups 4096 0x58a842ad F /var/cache/cups/job.cache 992 0x58a842ad F /var/cache/cups/ppd-updates 271 0x567b004a The only difference is that all entries are always specified with their full path. That makes the file a bit larger, but now you can use it as a substitute for the `locate` command: zgrep cracklib /tmp/var.cache.gz ## Cache Files on Desktop Machines See [scripts/README.md] (https://github.com/shundhammer/qdirstat/blob/master/scripts/README.md) qdirstat-1.4/doc/TODO.md000066400000000000000000000052341311502036700150470ustar00rootroot00000000000000# QDirStat To Do List This is roughly ordered by priority. ** See also the GitHub issue tracker! ** ## Ready-made Packages for SUSE and Ubuntu - Write a .control file for Ubuntu .deb packages - Use the openSUSE build service to create .deb packages ## General ### Translations - Add translation stuff. Setting up the Qt translator classes is easy enough. The translation file(s) will probably also end up in the resource file to avoid being dependent on external files (they can always go missing). - Check out available web services for Open Source translations. - Once translations are there, definitely add config option to "force English". As much as translations are welcomed, I do not agree to translate everything to death, in particular when the English term is much more widely used. This happens a lot in German translations. I don't want to be at the mercy of the German translator; I want to be able to use my original English texts -- without switching my entire desktop and shell environment to English or the POSIX locale. ## Some Time in the Future ### Reports? - Format selected items in useful format and export to clipboard / to file? - Text, CSV, YaML? ### Config Dialog - General parameters config page - postponed for the time being. There are currently not enough worthwhile parameters to be configured. - Config dialog page for OutputWindow colors - Find a better way to get objects like CleanupCollection and MimeCategorizer to the respective config pages; the main window shouldn't need to know that much about the internal structure of those pages. - Create a subclass for things common to all the config pages: - setup() - apply() - discardChanges() ### Treemap Parameters Add config page for at least some of them? Not sure if all those crazy treemap parameters need to be user configurable. They are pretty much expert-only, and most of them look pretty scary to normal people. I might leave them in the config file, but most likely anybody who really wants to change any of them will need to use his favourite editor. ### MacOS X Support - Find out how to package a MacOS app - Find a volunteer for a MacOS X platform maintainer ### Windows Support **Postponed to the very far future** - Create DirReadJob subclass that strictly uses Qt classes (QFileInfo) and no POSIX system calls - Find out how to package a windows app - Installer ## Unclassified / Undecided ### Support for non-UTF-8 Locales See also [Github Issue #19] (https://github.com/shundhammer/qdirstat/issues/19) Dropped. People who need that should finally try to arrive in the 21st century and use UTF-8 like the civilized part of the world. qdirstat-1.4/doc/Troubleshooting.md000066400000000000000000000061761311502036700174770ustar00rootroot00000000000000 ## Troubleshooting ### Can't Move a Directory to Trash QDirStat does not copy entire directory trees to the trash directory in your home directory. It tries its best to copy single files there, but for anything larger, it strictly sticks to the XDG trash specification. So, if you have a separate /home partition (which is strongly recommended for a lot of reasons), you cannot move a directory from /tmp to trash because that would mean to move a directory across file systems -- from /tmp/somewhere to your ~/.local/share/Trash . But there is an easy workaround. It's described in the XDG trash spec, but here is a simple recipe what you can do: Create a dedicated trash directory on the toplevel (mount point) of that file system. If it is mounted at /data, do this: cd /data sudo mkdir .Trash sudo chmod 01777 .Trash Permissions '01777' means "rwx for all plus sticky bit". The sticky bit for a directory means that only the owner of a file can remove it. The sticky bit is required for security reasons and by the XDG trash spec (it's also required by the spec that applications like QDirStat refuse to use that trash directory it if it is not set). Now you can move directory trees from /data/somewhere to the trash with QDirStat. It will end up in /data/.Trash/1000/files/somewhere (if 1000 is your numerical user ID which is common in Linux for the first created user). Your desktop's native trash application (your trash icon on the desktop and the file manager window you get when you click on it) should show it, and you can empty the trash from there. In Xfce, this works out of the box. KDE might need a forced refresh (press F5) in that window. For USB sticks, this explicit toplevel .Trash directory is usually not necessary: If you have write permission on its toplevel directory, QDirStat will (again in compliance to the XDG trash specification) create a trash directory .Trash-1000 in its toplevel directory which is the fallback if there is no .Trash directory there. This would also happen automatically on /data and / if you had write permission there -- which is, however, very uncommon. What the major desktops (KDE, GNOME, Xfce) usually do with their native file managers is to recursively copy the entire directory tree to your home trash directory and then remove the original. Not only is this time-consuming and wasteful (copy stuff before deleting?!), it might also be error-prone if that directory tree contains symlinks, sockets or even just sparse files; and permissions and timestamps (mtime, ctime, not to mention atime) might or might not be the same as before. This might become a problem if you decide to restore that directory tree from the trash. I thought about emulating this behaviour, but this basically means to reimplement large parts of what the _rsync_ command does (calling _rsync_ from within QDirStat might not be such a good idea - what if it's not available or anything goes wrong?), and frankly, I don't want to do that - in particular not for something that typically gets deleted shortly afterwards anyway upon "empty trash". So, if you have this problem, please use the .Trash directory workaround described above. qdirstat-1.4/doc/cache-file-format.txt000066400000000000000000000161611311502036700177700ustar00rootroot00000000000000 The QDirStat Cache File Format ================================ Author: Stefan Hundhammer Updated: 2016-01-09 QDirStat can read cache files in either gzip or plain text (uncompressed) format. The file format is line oriented. Empty lines as well as lines with a '#' character as their first non-whitespace character are ignored. To generate a cache file, you can use QDirstat ("File" -> "Write Cache File") or the supplied qdirstat-cache-writer script in the scripts/ directory of the QDirStat sources. Example: [qdirstat 1.0 cache file] # Do not edit! # # Type path size mtime D /work/home/sh/kde/kdirstat 159 0x43aea3d3 F ChangeLog 19288 0x43ae9a3b F .cvsignore 207 0x41c194f3 F stamp-h1 23 0x43ae9d73 F acinclude.m4 357171 0x43ae9d52 F Makefile.am 1237 0x43ad58a0 F config.h 5460 0x43ae9977 D /work/home/sh/kde/kdirstat/kdirstat 549 0x43aea73b F .cvsignore 108 0x3b7bda58 F kcleanupcollection.cpp 7615 0x41a3322d F kdirstatapp.cpp 24254 0x43aea372 F kdirtree.cpp 33083 0x43adc843 F kdirstatsettings.cpp 30519 0x3e39540c F kdirtreeiterators.cpp 7191 0x3e1ad131 F ktreemapview.cpp 17100 0x3f93ee7b D /work/home/sh/kde/kdirstat/kdirstat/.libs 24 0x43ae9900 D /work/home/sh/kde/kdirstat/kdirstat/.deps 504 0x43aea73a F ktreemaptile.Po 18074 0x43ae99a0 F kdirtree.Po 18134 0x43aea0ba D /work/home/sh/kde/kdirstat/kdirstat/pics 144 0x43ae9d72 F hi32-action-symlink.png 1141 0x3c0b5152 F Makefile.am 59 0x41a47537 D /work/home/sh/kde/kdirstat/kdirstat/pics/CVS 64 0x41c194fc F Entries 447 0x41c194fc F Repository 23 0x41c194fb F Root 54 0x41c194fb D /work/home/sh/kde/kdirstat/kdirstat/CVS 64 0x434657ca F Entries 2020 0x434657ca F Repository 18 0x41c194f8 F Root 54 0x41c194f8 (End of example) Header ====== The first line ( "[qdirstat 1.0 cache file]" ) is a header identifying the file format. Future versions of QDirStat may or may not check the version number (the second word of the header line) to make sure the file format is compatible with that particular version of QDirStat. For compatibility reasons, QDirStat will recognize both "qdirstat" and "kdirstat" as file format keywords. Data Lines ========== The data lines are separated into fields by whitespace (blanks or tabs). Fields are not surrounded by single or double quotes. The maximum line length is 1024 bytes. Mandatory fields are: - Type - Path or name - Size - MTime (time of last modification) After those mandatory fields there may be optional fields in this order: - "blocks:" followed by a field with the number of blocks - "links:" followed by a field with the number of links The identifiers of those optional fields ("blocks:", "links:") are case insensitive. Fields ====== Type ---- Any of: "F" plain file "D" directory "L" (symbolic) link "BlockDev" block device i-node "CharDev" character device i-node "FIFO" FIFO (named pipe) "Socket" socket The type field is case insensitive. Path or Name ------------ Either an absolute path (starting with "/") or only a base name relative to the last preceding full path in the file. Directory entries are required to have an absolute path. Entries for plain files, symlinks, or special files (devices, FIFOs, sockets) may have an absolute or a relative path. Hint: To save some disk space with relative paths, it makes sense to list the plain files in a directory first and then descend into any subdirectories when writing a cache file. Paths and names are URL-encoded, i.e. any character (in particular whitespace) that might otherwise be some kind of delimiter is specified as its hex code with preceding "%": with blank -> with%20blank with%percent -> with%25percent Take special care for blanks, tabs, newlines, and percent characters. It does not hurt to escape a few more characters than would strictly be neccessary. As for encoding, unfortunately this is one big mess. 7 bit ASCII works alright, but if there are any special characters, everything depends on the locale in which the user created a file. There is no standard for file name encodings in file systems; special characters may come in all kinds of flavours - in Latin-1 (ISO-8859-1), Latin-2, UTF-8, Japanese, Korean, Chinese, whatever. In an ideal world, the file system would take care about this and normalize file names with non-ASCII (7 bit) characters, but that doesn't happen. So if one user uses, say, Latin-1 and another uses UTF-8, a file system may have files with different encodings for each file name. Worse yet, the same (special, i.e. non-7-bit-ASCII) character will be be stored in different character representations for different file names. Those character representations is what readdir() returns. There is no way to tell in which encoding a name may come, so there is also no way to convert it to a well-defined standard encoding like, say, UTF-8. So what gets stored in the cache file is the same byte sequence as returned by readdir(). Those names encoded in something other than the current locale of KDE where QDirStat is running will of course be displayed with garbage letters, but this cannot be helped. This is just the same as when the name is read directly from the file system with readdir(). Bad luck. Size ---- The entry's size (st_size in struct stat as returned by lstat() ). Note: This is the entry's own size, not the accumulated size of all children! This size is given in bytes. It may also have a trailing unit (directly following the number, without whitespace): - "K" for kB (1024 bytes) - "M" for MB (1024 kB) - "G" for GB (1024 MB) The size is always specified in integer numbers, never in fractional numbers. So if it cannot be divided by a bigger unit without a fractional part, use the next-lower unit that fits without fraction. Examples: 1024 -> 1K 1025 -> 1025 (NOT 1.01K or something like this!) 8589934592 -> 8G 8589934593 -> 8589934593 (bad luck) MTime ------ The entry's last modification time as time_t, i.e., in seconds since 1970-01-01 00:00:00. May be specified in hex (with preceding 0x) or decimal. Blocks ------ If a file is a sparse file (and only then) it has a "blocks:" field. This is the content of the st_blocks field of struct stat as returned by lstat(): The number of disk blocks actually allocated. This number multiplied by the block size may be less than what st_size returns; in this case that file is considered to be a "sparse" file or a file with "holes". A block size of 512 bytes is assumed. Example: blocks: 17 This file has 17*512 bytes allocated. Links ----- If a non-directory entry has more than one hard link, the entry has a "links:" field indicating the number of hard links: links: 7 qdirstat-1.4/doc/doc.pro000066400000000000000000000004741311502036700152500ustar00rootroot00000000000000# qmake .pro file for qdirstat/doc TEMPLATE = app TARGET = $(nothing) doc.files = *.txt *.md ../*.md ../LICENSE # Ubuntu / Debian pkg doc path doc.path = /usr/share/doc/qdirstat exists( /usr/share/doc/packages ) { # SUSE pkg doc path doc.path = /usr/share/doc/packages/qdirstat } INSTALLS += doc qdirstat-1.4/doc/stats/000077500000000000000000000000001311502036700151125ustar00rootroot00000000000000qdirstat-1.4/doc/stats/Buckets-Table.md000066400000000000000000000032131311502036700200600ustar00rootroot00000000000000# The Buckets Table ![Buckets Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-buckets-table.png) This shows the _buckets_ of the histogram as a table. It is the same information you can get when hovering over the histogram bars. For a histogram, files are put into _buckets_, i.e. they are classified by their size: Files of similar sizes are put into the same bucket, and the histogram shows how many files there are in each bucket. Columns from left to right: - Bucket number. How many buckets there are depends on the number of data points, i.e. the total number of files. QDirStat uses the [Rice Rule](https://en.wikipedia.org/wiki/Histogram#Rice_Rule) to determine the number of buckets so there is a reasonable number of data elements in each bucket. If there are too many buckets, many of them won't have any data, and the others will have very similar numbers, so it would be hard to make any sense of the histogram. QDirStat uses a maximum of 100 buckets so each bucket is still wide enough to be well visible and clickable. - The start value of the bucket, i.e. the minimum file size for a file to be put into that bucket. - The end value of the bucket, i.e. the maximum file size for a file to be put into that bucket. The end value of this bucket is also the start value for the next one. - The number of files in that bucket. This is what the histogram displays. ------------------------ ## Navigation [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/File-Size-Histogram.md000066400000000000000000000163321311502036700211630ustar00rootroot00000000000000# QDirStat's File Size Histogram _This explains the histogram itself. The overflow ("cut off") area is described in a [separate document](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md), and the histogram options in [yet another separate document](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md)._ ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram.png) ## How to Get this Window 1. In QDirStat's tree view, select a directory, then menu _View_ -> _File Size Statistics_ or hit the F2 key. 2. In QDirStat's _File Type Statistics_, open a file type category, then select a filename suffix (e.g. `*.jpg`), then open the _File Type_ menu button and select _Size Statistics_ or hit the F2 key. ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-jpg-work.png) _Histogram showing only .jpg files in that directory_ ## Histogram Panel Content This histogram displays the distribution of file sizes in the selected directory (see window heading). If a filename suffix ("*.jpg" or similar) is displayed, it is restricted to files of that type. ### The Colored Heading Values From left to right, you see - The first quartile (Q1) of the file sizes - The median of the file sizes - The third quartile (Q3) of the file sizes - The total number of files in the histogram, i.e. the sum of all bucket values. If the terms _median_, _quartile_, _percentile_ don't mean anything to you, you might want to read the [intro document where they are explained](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md). ### The Histogram The horizontal (x) axis shows the file sizes, the vertical axis the bucket values, i.e. the number of files in each bucket (in each size interval). The vertical axis might be linear (if labeled just with **n**) or logarithmic (if labeled with **log2(n)**) with a base 2 logarithm. ![Logarithmic scale](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-log-scale.png) _Histogram with logarithmic scale_ The same principle still applies: The higher a bar, the more files are in a bucket. But it's no longer a linear relationship between the bars; a bar that is just slightly higher might have double the data points if a logarithmic scale is used. Use tooltips to find out the true numbers. ### What is it Good For? - You can see the vast amount of very small files on a Linux system. - You can see the sizes of your MP3s, of your videos, of your photos and maybe make educated decisions about them. - You might use that information for optimizations for very special servers. Back a long time ago, news servers were notorious for creating a large number of very small files. Some http servers might be similar. Some database servers might be completely different. - Filesystem developers might find that information useful for optimizing or fine-tuning parameters. - You might want to compare the data from your Windows partition to your Linux partition. You **will** notice differences. - You might be just curious. - Information is power. Use your imagination what to do with it. ### Tooltips You can get a tooltip for each histogram item (bars or percentile marker) if you hover the mouse over it. Sometimes you might have to click into the window first so it gets focus. A tooltip looks like this: Bucket #20: 707 Files 1.6 MB .. 1.7 MB You can get the same information for all buckets at once by switching to the _Buckets_ page in that dialog. ### The Markers Markers for Q1, the median and Q3 are superimposed over the histogram: They are the colored vertical lines. Their respective color is the same as in the heading above the histogram. At the right, there are some more grey markers; they show some percentiles at the border of the histogram. They are useful to get an idea how much the percentiles are spaced out in that area. Typically, the last few percentiles are very wide, i.e. the data points in that area are very widely spaced. You could say "the air gets thinner" the more you get away from the center part. ### Histogram Boundaries It is very common for file sizes on a real life filesystem to be vastly different: You might have a large number of tiny files, and you might also have a couple of ISOs or videos of 2 GB each. Put into the same histogram, this looks like this: ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P100.png) This histogram does not really give away any useful information: You can see that the vast majority of files is at the left side, and then there are wide stretches of file sizes that don't appear anywhere in that directory tree (where all the gaps are), and then there are some very large files in the 2 GB area. This is not very useful. This is why QDirStat by default uses some heuristics to determine useful boundaries for the histogram: It uses the _interquartile distance_ (Q3 - Q1) and adds some generous distance to the left and to the right of Q1 and Q3: leftBoundary = Q1 - 3 * (Q3 - Q1) rightBoundary = Q3 + 3 * (Q3 - Q1) (maxed out at minValue (P0) and maxValue (P100), of course) But in our extreme example (which is actually quite common), even if we leave just one percentile out and display the histogram from P0 to P99, it becomes much more useful: ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P99.png) As you can see, the right boundary is still at 8 MB, and the "interesting" area between Q1 and Q3 is still pretty much crammed together at the left, but now at least we can make some sense of it all (notice that it's using a logarithmic vertical scale, so it's not nearly as evenly distributed as you might think). Percentile data for reference: ![Extreme Percentiles](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-extreme.png) ### Why Not Use a Logarithmic Scale There, Too? This is a tempting idea, but it would make the histogram display either incorrect or very difficult to interpret: By definition, the area of each bar corresponds to its numeric value (to the number of files in that bucket). By using a logarithmic scale there, too, the width (!) of the bars would have to get logarithmic, too: This would mean very fat bars on the left and very thin bars on the right. If there are extreme differences like in this example, the right bars would degenerate into thin lines, and even that would be technically wrong because they would need to have sub-pixel widths. Remember that we are comparing ranges of some few bytes with gigabytes; that's a factor 1024\*1024\*1024 difference. It's just not feasible to display that. So the more pragmatic approach is to cut off at a sensible limit. ---------------------------------- ## Navigation [Next: The Overflow Area](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/Histogram-Options.md000066400000000000000000000034441311502036700210270ustar00rootroot00000000000000# Histogram Options in QDirStat's File Size Histogram When you click on the `Options >>` button below the histogram, some interactive controls become visible: ![Histogram Options](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-options.png) Here you can change the left and right boundary of the histogram. Typically, the left boundary is P0 (percentile #0, the minimum file size), but the right boundary is below P100 (percentile #100, the maximum file size). As explained in the [file size histogram article](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md), QDirStat automatically determines a useful values for both boundaries. But that's just heuristics, and the value might not always be the optimal one. So here you have the tool to experiment with better values: Use the sliders or the _spin boxes_ below them to change the start and end percentile. Notice you can't cut off above Q1 or below Q3: That part of the histogram will always remain visible. If you set the end percentile to P100, the overflow ("Cut off") panel will disappear. This is normal and intentional since in that situation nothing is cut off. The _Auto_ button resets both to the automatically calculated values: leftBoundary = Q1 - 3 * (Q3 - Q1) rightBoundary = Q3 + 3 * (Q3 - Q1) (maxed out at minValue (P0) and maxValue (P100), of course) Hit `<< Options` again to close the histogram controls. ------------------------------ ## Navigation [Next: The Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Percentiles-Table.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/Histograms-in-General.md000066400000000000000000000115641311502036700215420ustar00rootroot00000000000000# Histograms in General (c) 2017 Stefan Hundhammer License: GNU Free Documentation License ## Quick Overview A histogram is a graphical representation of data: The data are grouped into _buckets_ (or _bins_) of intervals (usually of equal width), and bars are drawn to show how many data points fall into each bucket. The higher the bar, the more data are in a bucket. From the resulting graphics you can easily see if data points are concentrated in any area, if there are any peaks, and how data are distributed. ## Detailed Explanation ### Number of Buckets First you need to determine the number of buckets to use. This is not anything as easy as it may sound: Too many buckets, and you will end up with many buckets without any data, leaving gaps in the graphics; and at the same time the buckets that do have data will have very few of them which makes any comparison between them difficult. If you have too few buckets, it is very likely that many data will be concentrated in very few of them, which leaves you with the bars for those few buckets being huge in comparison with the others. Again, it makes analysis of the resulting histogram very difficult. There are a number of formulas to calculate a reasonable number of buckets. QDirStat uses the [Rice Rule](https://en.wikipedia.org/wiki/Histogram#Rice_Rule). It uses a maximum of 100 buckets so the resulting histogram bars don't degenerate to very thin lines, but remain well visible and also clickable. ### Buckets vs. Percentiles All buckets have the same width, while percentiles typically have very different widths. Each percentile interval (the interval between a percentile and the previous one) always has the same number of data points (by definition, each of them has 1/100 of the data points). ### Histogram Bars Each histogram bar corresponds to one bucket. In normal histograms, the height of each bar shows the number of data points in the bucket. _There are also histograms where the buckets have different widths; in that case, it is not the height, but the area of the histogram bar that corresponds to the number of data points. But that is hard to interpret, so that kind of histogram shall be disregarded here._ Notice that unlike with bar graphs, there are no gaps between histogram bars: This is because of the way the buckets are defined. The end point of one bucket is also the start point of the next bucket; this is how each possible data point can be unambiguously put into one bucket. If you see any gaps in a histogram, you are seeing an empty bucket (or possibly multiple empty buckets). ### Method Scenario: We measured 1000 data points. The minimum measured value is 100, the maximum 200. According to the Rice Rule, we need `2 * 1000^(1/3) = 20` buckets. The range we need to display is `max - min = 200 - 100 = 100`. The bucket width is `range / bucketCount = 100 / 20 = 5`. So we get those buckets: | Bucket # | Start | End | | -------: | ----: | --: | | 1 | 100 | 105 | | 2 | 105 | 110 | | 3 | 110 | 115 | | 4 | 115 | 120 | | .. | ... | ... | | .. | ... | ... | | 18 | 185 | 190 | | 19 | 190 | 195 | | 20 | 195 | 200 | How to handle the boundaries for its bucket is open to definition. A practicable definition would be to check for `start <= x < end`. Then we go through all data and determine the bucket where each data point belongs. For that bucket, we increment its counter by one. | Data Value | Bucket # | | ---------: | -------: | | 118 | 4 | | 187 | 18 | | 101 | 1 | | 119 | 4 | | ... | ... | | ... | ... | Notice that the data don't need to be sorted for that. Finally, we determine the maximum counter of all buckets; this is the maximum for the vertical scale. Then we can begin drawing the histogram bars. ## ### ###### ######### ## ############ #### ##################### --------------------- 1 5 10 15 20 Bucket No. ---> In this example, we have two clearly defined peaks: One around bucket #9, and another one around bucket #17. Notice how the histogram shows information even without knowing anything about the vertical scale; just the relative sizes of the bars against each other are enough. It does help, though, to mark the horizontal (x) axis to get any idea where the peaks or valleys are. ## Reference https://en.wikipedia.org/wiki/Histogram (Much better readable than the Wikipedia article about percentiles) ---------------------------------- ## Navigation [Next: The File Size Histogram](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/Median-Percentiles.md000066400000000000000000000234071311502036700211120ustar00rootroot00000000000000# Median, Quartiles and Percentiles Explained (c) 2017 Stefan Hundhammer License: GNU Free Documentation License ## Motivation _"Do not trust any statistics you did not fake yourself."_ (Joseph Goebbels, often wrongly attributed to Winston Churchill) This is the instant reply some moron will ALWAYS bring up whenever anybody begins talking about statistics, thus instantly discrediting whatever facts were brought up. But all that does is to make any intelligent discussion (that is, any fact-based discussion) virtually impossible, replacing hard facts with mere sentiments. While there might be some virtue to something meteorologists call "perceived temperature" (because it takes the wind chill factor into account), "perceived facts" are completely worthless. Yet they seem to rule the day in a society where it is considered chic to state "I've always been bad at math" (and nobody replies "you should be ashamed of yourself"). But important decisions should be based on facts, not on feelings. That's where statistics come into play; and that's when average people feel overwhelmed rather than informed. What is all that stuff? Everybody knows what an average value is, but what is a median, what are percentiles? And who cares anyway? It's actually very simple. It doesn't take a math genius to understand; every average (here we go again!) person can do that. Just read on. ## The Farmers of Dairyville Dairyville is a fictional village with a number of farmers; some small ones with only very few cows, most with a pretty medium-sized number, and there is also that big large corporation Agricorp, Inc. with a lot of cows: #1 Collins 1 cow #2 Myers 2 cows #3 Davis 12 cows #4 Thompson 12 cows #5 Fletcher 14 cows #6 Allen 15 cows #7 Brown 16 cows #8 Eliott 16 cows #9 Robinson 17 cows #10 Jones 18 cows #11 Simpson 38 cows #12 Agricorp, Inc. 400 cows Total 561 cows The average is 561 / 12 = 46.75. But that does not describe any of the farmers well; worse, that average is a meaningless number: It does not fit any of the normal farmers, much less the big Agricorp, Inc. corporation. Why this is so is obvious in this case: That big Agricorp, Inc. is greatly distorting the result. There must be a better way to do this; one that actually makes a meaningful statement about the typical farmer of Dairyville. Well, there is. It is called the median. ## The Median The median is a value determined by putting all the data in a sorted list and then choosing the middle point. It is the point where as many data points are below as there are above. #1 Collins 1 cow #2 Myers 2 cows #3 Davis 12 cows #4 Thompson 12 cows #5 Fletcher 14 cows #6 Allen 15 cows ------------------------------ Median #7 Brown 16 cows #8 Eliott 16 cows #9 Robinson 17 cows #10 Jones 18 cows #11 Simpson 38 cows #12 Agricorp, Inc. 400 cows In our example the data are already conveniently sorted and numbered, so we just have to pick the middle point from the 12 data points: Between #6 and #7, i.e. between farmer Allen and farmer Brown, between 15 and 16 cows, i.e. 15.5 cows. If you look at the data, that is a much more accurate description of the typical Dairyville farmer. Better yet, if you were to take Agricorp out of the calculation, you'd end up with a very similar number: Then the median would be at #6, farmer Allen, with 15 cows. No big change (from the previous 15.5). On the other hand, the average would change from 46.75 to 14.63 - quite a drastic change. If you were to disregard the very small farms #1 and #2, the median would be 16, no matter if Agricorp were still in the table or not. The median is a very useful measure; it is very stable against weird "outliers" (outlying data points very far from the center), unlike the average. This is why the median is typically used for professional statistics of any kind; never again let anyone fool you into believing that "the average income in our country is only so high because of a few billionaires who greatly distort the statistics". That is a flat-out lie. The pros use the median, and the billionaires don't make a difference at all. If you watch closely, the pros always talk about the "median household income", never about the "average household income" because that would indeed be a meaningless number. It's just the media who tend to misquote it and change it from "median" to "average" because they think that makes it easier to understand. ## Quartiles The concept goes further. Now that we know what the median is, can we make any more meaningful statements about the typical Dairyville farmer? We can. Let's just cut the list in half at the median and apply the same principle again: Lower half: #1 Collins 1 cow #2 Myers 2 cows #3 Davis 12 cows ----------------------------- 1st Quartile #4 Thompson 12 cows #5 Fletcher 14 cows #6 Allen 15 cows Upper half: #1 Brown 16 cows #2 Eliott 16 cows #3 Robinson 17 cows ----------------------------- 3rd Quartile #4 Jones 18 cows #5 Simpson 38 cows #6 Agricorp, Inc. 400 cows Voila, we just cut our farmer population into quarters. The dividing points (the medians of the lower and upper halves) are called the "first quartile" and the "third quartile". The second quartile technically exists, but it is much better known for its other name: The median. In more advanced statistics, the segment between the 1st quartile (Q1) and the 3rd quartile (Q3) is considered the most important part of the data. The value difference between them is called the "interquartile distance"; in our example, this would be 17.5 - 12 = 7.5. This is an important number for a lot of things, such as deciding where and how to leave out data in certain types of graphical representations such as "box plots": They typically cut off outlying data points beyond 1.5 * (Q3-Q1) on either side so the graphics remain meaningful. In our example, that would mean to cut off below Q1 - 1.5 * 7.5 = 0.75 and above Q3 + 1.5 * 7.5 = 28. That would mean that farmer Collins would still be in the graph, but Agricorp and farmer Simpson would not. ## n-Quantiles, Deciles and Percentiles In a mathematical sense, the concept is easy to generalize; it is called "n-quantiles" where "n" is the number of segments after the division. So, the median would be the 2-quantile, the quartiles would be 4-quantiles. When used with n = 10, they are called "deciles"; with n = 100, they are called "percentiles". And the percentiles are the most useful and come most natural to us modern people who are used to think in terms of percent. Dairyville has not enough farms to come up with a useful percentile table; with a full one, that is. But just think about it: The median is the middle point of the percentiles, i.e. the 50th percentile (P50); the first quartile is the 25th percentile (P25), the third quartile the 75th percentile (P75): #1 Collins 1 cow #2 Myers 2 cows #3 Davis 12 cows ------------------------------ P25 (Q1) #4 Thompson 12 cows #5 Fletcher 14 cows #6 Allen 15 cows ------------------------------ P50 (Median) #7 Brown 16 cows #8 Eliott 16 cows #9 Robinson 17 cows ------------------------------ P75 (Q3) #10 Jones 18 cows #11 Simpson 38 cows #12 Agricorp, Inc. 400 cows Notice that strictly speaking, there is no P100, and no P0. But it is useful to extend the concept a little further, and define P100 the maximum of the data and P0 the minimum, so the percentiles (even if only very few of them can be calculated with only 12 data points) can serve to completely describe the data set: ------------------------------ P0 (Min) #1 Collins 1 cow #2 Myers 2 cows #3 Davis 12 cows ------------------------------ P25 (Q1) #4 Thompson 12 cows #5 Fletcher 14 cows #6 Allen 15 cows ------------------------------ P50 (Median) #7 Brown 16 cows #8 Eliott 16 cows #9 Robinson 17 cows ------------------------------ P75 (Q3) #10 Jones 18 cows #11 Simpson 38 cows #12 Agricorp, Inc. 400 cows ------------------------------ P100 (Max) **Notice:** The percentiles/quartiles/median are the **dividing points**, not the interval at either of their sides. ## Further Reading Read the full description that is no doubt mathematically correct, but utterly incomprehensible and thus useless to the normal human here: https://en.wikipedia.org/wiki/Quantile https://en.wikipedia.org/wiki/Median https://en.wikipedia.org/wiki/Quartile (This bunch of uselessness is why I wrote this document) ## Disclaimer No animals (or farmers) were harmed in the making of this. We'd like to thank the farmers and cows of Dairyville and the Dairyville chamber of commerce for their kind cooperation. ;-) ## Navigation [Next: Histograms in General](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histograms-in-General.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/Overflow-Area.md000066400000000000000000000115621311502036700201120ustar00rootroot00000000000000# The Overflow Area in QDirStat's File Size Histogram Since QDirStat in most cases does not display the full data range, but rather cuts off at a sensible point, it displays a special panel next to the histogram when it does that as a reminder that you are not seeing the complete data set. ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram.png) In the above case, it's pretty harmless: The overflow ("Cut off") panel shows that a small part of the data was cut off: Percentile P99 to P100. Remember that each percentile contains by definition 1/100 of all data points (in this case: of all files), so in this case it's just 1% of all data points that were cut off; in this example, 292 files. But the histogram still shows the remaining 99%, 28838 files total (this is the rightmost / black value above the histogram). The upper pie chart shows that information graphically. It's no big deal, really. But P99..P100 in this case means cutting off from 5 MB to 31.1 MB, so it's a really wide part of the x axis that gets cut off; to show that all, it would need to be more than 6 times as wide. If scaled to the same window width, that would mean that the meaningful part of the histogram would only be 1/6 of the total width with vast areas of emptiness to its right. That's _why_ that part was cut off. But even though it's only 1% of all files, those files together account for 8.4% of the disk space in that directory tree: 3.3 GB total. This is what the lower pie chart shows. Again, this is not really significant, much less for the purpose of file size distribution which this window is all about. But it's a reminder not to just disregard those few files - because they are **big**. ## A More Extreme Example _Oh PacMan, where art thou?_ _...and why art thou red?_ ![Red PacMan](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-log-scale.png) Going one directory level up, we get this histogram, and this is an entirely different matter: The heuristics for determining the histogram boundaries decided on displaying P0 to P87. This does make sense in order to have the most important part of the distribution between Q1 (P25) and Q3 (P75) in view. But on the other hand, it cuts off 13% of all files (13 percentiles), the range between 2 MB and 2 GB. That's three magnitudes (1024) of difference in file size. The red slice of the upper pie chart is considerably bigger than in the previous example. For the accumulated size of those files that were cut off, it means that they now contribute to 88.1% of the total disk space in that directory tree (the red part of the pie charts is always the part that is cut off), by far dwarfing the accumulated sizes of those files that are displayed in the histogram. Again, this may or may not bother you; it depends on what information exactly you are looking for in the histogram. But this is where you might want to decide to show just a little more of the data range by opening the histogram options and moving the sliders. Moving the _End Percentile_ slider to P99 in this case gets you this: ![Histogram with P99](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P99.png) OK, that did put things a bit more into proportion - at the price that the most important part of the data, Q1 .. Q3, has now become a lot less visible: It now has 1/4 of its previous display size (since the right boundary is now at 8 MB from the previous 2 MB). Still, the remaining 1% of the files that were cut off contribute to 62% of the total disk space: The red slice is still the dominant one, albeit no longer quite as much as before. _PacMan opened its mouth for us._ ;-) But going full hog and moving the _End Percentile_ slider all the way to P100 is not helpful, either: ![Histogram with P100](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P100.png) Duh. There is no longer an overflow panel since now nothing is cut off, but the histogram is pretty worthless: We can now see that there are some files in the 2 GB range, but the core of the histogram (Q1..Q3) has now degenerated to some 5 pixels wide with colored lines. All we can see in this histogram is that there is a lot of little stuff on the left, then it peters out for a wide stretch, and there is another peak on the right. Notice, though, that due to the logarithmic vertical scale that peak is not nearly as high as it appears: It's just 18 files (!) in comparison to bucket #1 (the peak at the very left) with 98206 files. ----------------------------- ## Navigation [Next: Histogram Options](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/Percentiles-Table.md000066400000000000000000000042471311502036700207450ustar00rootroot00000000000000# The Percentiles Table ![Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-table.png) This table shows the percentiles of the file size statistics. If you don't know what percentiles are, please read the [percentiles documentation](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md) first. Columns from left to right: - Percentile number (P0 .. P100). - Percentile value. This is the file size where that percentile is. Remember that percentiles are the dividing point, not an interval. Percentile P10 is the point where 10% of all data points are below, 90% are above. - The name of the percentile if there is any special name: | Percentile | Name | |------------|------------------| | P0 | Min | | P25 | 1. Quartile (Q1) | | P50 | Median | | P75 | 3. Quartile (Q3) | | P100 | Max | - The accumulated sum of all data points (of all files) between the the previous percentile and this one. If you wonder how many data points (files) fall into any interval between the previous percentile and this one: That's always 1/100 of the total number of data points (files). This is why this is not listed in the table; that would be the same number for each percentile. This table shows either all or only the interesting percentiles. Use the combo box at the top right to switch between those two views. Interesting percentiles in the context of this table are those with a special name (see above), those with a number that can be divided (without remainder) by 5, and a few around the extremes (min and max). ![Full Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-table-full.png) _Full percentiles table_ ---------------------------- ## Navigation [Next: The Buckets Table](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Buckets-Table.md) [Up: Statistics Top Page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/README.md000077700000000000000000000000001311502036700210402Statistics.mdustar00rootroot00000000000000qdirstat-1.4/doc/stats/Statistics.md000066400000000000000000000020311311502036700175620ustar00rootroot00000000000000# Statistics in QDirStat ## Statistics Basics ### Median, Quartiles and Percentiles Explained https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Median-Percentiles.md ### Histograms in General https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histograms-in-General.md ----------------------------- ## QDirStat File Size Statistics ### The File Size Histogram https://github.com/shundhammer/qdirstat/blob/master/doc/stats/File-Size-Histogram.md ### The Overflow Area https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Overflow-Area.md ### Histogram Options https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Histogram-Options.md ### The Percentiles Table https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Percentiles-Table.md ### The Buckets Table https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Buckets-Table.md ---------------------------------- ## Navigation [Top: QDirStat Home Page](https://github.com/shundhammer/qdirstat/blob/master/README.md) qdirstat-1.4/doc/stats/stats.pro000066400000000000000000000004741311502036700167770ustar00rootroot00000000000000# qmake .pro file for qdirstat/doc/stats TEMPLATE = app TARGET = $(nothing) doc.files = *.txt *.md # Ubuntu / Debian pkg doc path doc.path = /usr/share/doc/qdirstat/stats exists( /usr/share/doc/packages ) { # SUSE pkg doc path doc.path = /usr/share/doc/packages/qdirstat/stats } INSTALLS += doc qdirstat-1.4/qdirstat.pro000066400000000000000000000003051311502036700155620ustar00rootroot00000000000000# Toplevel qmake .pro file. Create a Makefile from this with # # qmake # # Then build the program with # # make TEMPLATE = subdirs CONFIG += ordered SUBDIRS = src scripts doc doc/stats qdirstat-1.4/qdirstat.pro.user000066400000000000000000000476601311502036700165560ustar00rootroot00000000000000 ProjectExplorer.Project.ActiveTarget 0 ProjectExplorer.Project.EditorSettings true false true Cpp CppGlobal QmlJS QmlJSGlobal 2 UTF-8 false 4 false true 1 true 0 true 2 8 true 1 true false true true ProjectExplorer.Project.PluginSettings ProjectExplorer.Project.Target.0 Desktop Desktop {888b365f-2bde-4794-8b79-baa82c8a4ec2} 0 0 0 true qmake QtProjectManager.QMakeBuildStep false false false true Make Qt4ProjectManager.MakeStep -w -r false 2 Build ProjectExplorer.BuildSteps.Build true Make Qt4ProjectManager.MakeStep -w -r true clean 1 Clean ProjectExplorer.BuildSteps.Clean 2 false Release Qt4ProjectManager.Qt4BuildConfiguration 0 true 1 0 Deploy ProjectExplorer.BuildSteps.Deploy 1 Deploy locally ProjectExplorer.DefaultDeployConfiguration 1 false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 src Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/src/src.pro ~/src src/src.pro false false 3768 true false false false true false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 doc Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/doc/doc.pro doc/doc.pro false false 3768 false true false false true false false false false true 0.01 10 true 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 scripts Qt4ProjectManager.Qt4RunConfiguration:/work/home/sh/src/qdirstat/scripts/scripts.pro scripts/scripts.pro false false 3768 false true false false true 3 ProjectExplorer.Project.TargetCount 1 ProjectExplorer.Project.Updater.EnvironmentId {69a2b64a-6740-4d76-a751-dfd1210c7360} ProjectExplorer.Project.Updater.FileVersion 15 qdirstat-1.4/screenshots/000077500000000000000000000000001311502036700155475ustar00rootroot00000000000000qdirstat-1.4/screenshots/QDirStat-buckets-table.png000066400000000000000000003347331311502036700225100ustar00rootroot00000000000000PNG  IHDRsBIT|d pHYs+ IDATxwx93RHBI &*UAEł 뽶kEE &$-3s~Bz}NfsvvϞ=sB!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!BD *cnۄB!C)W7&u' K0B!uA }8.B!ꢿ8u!yluCB!u\V/ {?n%W@~~yЅB!DK)O,^r`{!^S8ȦvjkB!MIvS3blǘҨ1&by^E`/;^3EJketϺ][j'}[!(f$KRҁ"=J(7)܈R8n !B]fBpPH:hmc\+i³\cbxAxQcB"%\,xE9[Y|kiB?NktUZ)e-myZAeZc}ZR*B!v]+Ԗkk< W'ƫjP|\z*tQ}*SQҕVQRZj RWp>= sY(ϑ IB!Ӷ11㳌]3F˃3q++]7V<+GPa$FMǫBP1ꛍM:euϐ^SSHG[*^Yv,bk[i\eE|ڲN4F2 !Bm>ܨ֖q^|h|!pmM",@Q=<ATkaRWMiKbPʲ2Gi )EEHYn,jR,VZ/2QyB!;rPm Ƶ3D]1\c Ƶ|~2jʌyg\-;^r0%49f7%gz9Wc\v ںԵ6cҕ*ISrMLYVq,mK_mX,hVZy>(ҁڎElӶ);s[Ƶ- )۲X^!B7ZuReј)ӎ\ϯ}5ʆ|giXJ<-TPHH+ /hׂVf{[?Oѣs0DJYZ)RTE[&Ok(JOF);i8Vڧ4:V>eE1~gl JR<k7v]1J^PaEiE[֛.ŧpl-$jģLh i2V-B!11 k۳\=x~\S1s]ei5~"[F0,W~OOi2IX*C|'t*'f !B 5nsklmY F1ѾVQex11WiO; 2F🙷B8NuazYW <JŔ¯BEJ)[Yq4hmllle{-cBRu++QW+R !BӶm{3nL9ј1^ժL*؞8ZaYߏr=ܨR2/Ϻƥy6ZYJ=GiWZiKa<|>§Q^,U8EJY]z ;NϢXN,ms#FCÄ^Z X-["!y$%'S\TĺkˣQÆ|ڗB!DUXڶoGF(p=23Yt)v:k{ÍET:?,Ytoܸ<{2w\.o!h4J^A!]u#9>hp8L,!FIiЀ.ݺS9Djsb1J]SczQY:ub„ ̟? Nzةciw] Zl/'s:U>yK憵4JmL֭Xj%͚6òLB5˗/ƛnb 7\I'L˖--<|MfΜEqq1קSǎ 08tFfw|L֭ӼY3:,;Xn>h99zVZ=]Iz: ľu]6fѽa2xGmtu]CRRmC9cMҷCj5uvYiicҍ1|]A#!5 |ꪫ8s Rnڂ+*.&#.Y[K&AINJ͗&@y~HKM\niEJJ pZcCO$)kV/ ;dyg9񤓈#̚9‚u 'WmYzz:V2ׯۥqb_WT\L |>edffҠaF?Fcb=48t҈Y=;*7װmN og[x%&ťBQ ߌ9^s ~mwxɒګ,^dN?{hY`^}mZbxvءdge8{e,]}C0kl- 0:u3v,_ kז^K֭kls޽;}P<"/'~3g2sL6dƌ~[olrtܙAРAKxu[Fx<x!ޝ8+W2YtiٲwN~6eƍoƍ9÷Z;99yw!%9KˊqZh=Lii .nh484IoٳCjS3_urssi[+{Ͻzۭٳ~v75W]8 :Ǝ˄w&2QD]A}sUC:@AA~;Rp3Y~= yNPsPw]"ϏmћtRڶk[HLHuٓA],%>V0$.悂7k _$c.{bBqq|BD"aJ쭏',]>c}7[q;y/ָ Oz!#GY5@&|̛;ƍPVWgګO+q-Z ]ҏݺFyac͚{5l@aA׮醏HJyՐ7_ؗGOdAS׌9_cƌaȐ![a5g 1Ǒ`.ʟ}>7igu1}Ņ7N?SO>QcPWJСs]|Gt<@v 'XWe%Z v2f͚QX~;ߥ^BGaԹpvm[C6m8x7Uh$L4Ő5W_M޽Ϊ\nvsHM2 fȐ!u] {nWQV)S~ǟb /pqs!])[sssYgkFѫW/RRcRA1enݺr+߿p8R^8!)cwH80k826`,W HdRB:uxz֭ɓ-oc ݺtᗩ2}4Oɓ0]x|(͚5qh4ʣ SO'?/ DQzpg C7 1dO?2uxAN;T׹~ZFg&??߷<]U︃]ҽ{7=RRRvh 6hբŅ=[[}Q$&b1Gù /֊H$C9dHcqqUWS^2oO@qQhtj[a/%Ӿ][F~n׆at)w~+Oe>OvF >{#~bz(#p$e_Β+=W\QakV.MV\q|'4l؈>dۼ4b$~v+y3~u$|)y[_q]ƿ3y `2;q~'rQG/S0p+Wڡmm_\ض;T q=h4RѾ}{֮^NAA^2ذa9y9d[͛cƒ֘1ƒMnݮ=t֍˖FXj9mڶ>}1cǏsN}{2Fީu~Կk< fͬ|3eT/qmo,8̘1z}x !wc+ӡC~{̝͢ys+1C62Yr9x[q'3m46썕[jeYL?ھ͛KnjF)eú5_6ݓmі%KpNJ%O*o]2k]ĸ:0}ھiӦ|>̙ӵT䐹b[>bhGNneՖib![ú+O)%gcV^x!/֕˖x]QTƿq!?KÍ?]ZlS&ߧ|hE`U֤$f)Ĝ~X,)S}6))X B-׻7<,[u?2n/**o?/^̲e;n:c?~-_+G% MyK]^?@FF -^c55̘2j;VbƌS.{ʫ&1!ѣ{{+ >>o9sc䦛o#GTۯ֚p$ʓO>E^^ 4{1lw{A/SXXHzz:nm!GUs3~㠃"ĢLZ[~liӦQ\\9d[]j{[Y;'+|fϞS벝X1۝:C:jux.S~+hVmQVʲ݈6O1?b`A/dLF'JL}cû8_ wM#<(G4a㠁nz>< ; GRFl0v੧@pȘmX,ƺXl)EEEt7tmac.IiێM+AZmŋm6BVm().$7;:̪K+iքЦyoyŋRi$$$VNF͡ |x4kW$~RoQ'k AF$Ƕm\ǡ 5xOJBX֟ggeT}4i֜@ ,[@ HM}~<%;+fYb24iւx֬X۶iڢKC)E aw IDAT6PW9P+CűkF,"mbU5Ҧm[7nL$! aK/'^!R|Ff<7Q^kTr)ܘ*e8^쨭brc"Z~1/Pa̴ǤL_!*ejl6w=;Oos|>͚GFFVdy$$$n \FB%ouj5+W{zpV~1dgfu2+ͩ+|+٘áҒmDXlieHU˗U[h՞nSZgɂyiXvVYUCElmsƬ,VXQ-onrw쳯` 47é;2|H΃ w`mӰAh޼9pqm{MRv !BԂ=Ca o:jw&NB!Bl>1.B!ߏu!B! B!BAԅB!$ !BQIPB!.B!v% !BQIPB!.B!D Uμ;r-}{2'Y=ە<$3kwD;q\Y=̞7zVM~xL}y1//BA!BMgPf5pVϳ=4sJ ڟFúsTd,g7UUxyg>:Bo7r6=3{5\߁8Kq*vǴ$ڵS+?|q3U~tWwʧ0_^YLx/\KB!jW7`OAIaq&'qÐ*ٓ}kcQ+(oyy֦M9 0qԙsR{.1Q6zO!E˦\\09;A Ɍia nJ`/~B!޷_uCq [@[:,cY.4o|k<\ q5 >:I7s5Dx %qc&~¯͏.wt[^#c_ˇe }wN|Gà<0W?auMzz/._te]bcs?a~hw[yL8>MIz7z >;Lbs>lnt*M}Uz>Zz$ORV2G\BR :+%n(x=kN+^bX輦ކBs_q(on͔]yqc]ﲪљĕɞԜ.k"Vqwx78oRtï:ˣIqiRw3S ӺrF{5CO'Y3Y^bHx2/34O[3eUӦq2n_#BԪME1_ uza]v5mX@{z^yKckCX}g.hYhvp^g]M~-`bfYpv~ OOŤ{d!E$V먧y4N|0#d-͆ùⴅ6y5= )mu-9ZM2dLÄO_hc^-O=VOdzc~^?D6c4L޾nYotGޒ x(<<97P  8vx~3<Nhڜbu3 ǝK|&}5gЈtO87|rաq5NŽi5LDX9o#H^b ĚS4{9vbVm 8^Jǟ}%]*ڟڀC= %jTgx>ow5}LJ~9Q~Jꉗ9t?yPW>9ga]8OKOb3{l<*Wn/1OA~ykFݻŌ~m~?FC/sY/X+BuP.~6 nVI,Ц`.:5 ,1~8gSj3e,R֢9]8^ >H>_w!+auG+>C*n3[4?$WMC 䆩l՘'I_qoH9CqbkpAL93ǟQ_MdM8pd7YXx.sKM,0\FMZӬQ;{ B:tqJ<Ǥ 0o[N!Mӱr2_LjsP85|IR~&4tyYݼzVw#c~p$)]ٶнH4rՁqʪX!ܶusrdjWĢ_ⳋI-ϦM Lܩ?bF6'|- |lLѡ\,/9!ƔcHe@8'r XwdO7'>Q zz$y4^\_,ˢz@|2 S>P?#yEBAݐϾЗmn0+%W]$RN}|%f я3kt˺{!/2K#AT ;/烪dnĥzPңEt{t<$ДxǤne1m(^0 UU\LlG;;waydaV VKn}6Ndz P+y^tH^(`5iN GZF0%R<ˏA윶Ր1fN땴)P!Zt.ZLyY>3:7[ׄWɓ>.9xӐ+M,M睷rrڟo`wJS<<Yd,aW^4R֦2fS$(&Np1^݃L^MWvz[cg (ɊH =ꖿ)E*̬u/My4kg9.#kF42|?99̙[mc|!4aMĢ\پ=S /O@CjؚvPi'ڲ 霝0'?føք!z FZNNDRCSjZu*tαts4'5 `+T 硫kDC`UxZظzS3{ZmÆϟ[ХM#5Gof;H3NM9C9硼t>~kցh.kʢV7hJyLy~SRҡI"*k%Y+СF+˘ iXZZcb, Ki %x-vQ$~.U (ڝNoU:9(epMP:Ɩ4FX6!Ў̺k{:Ҿc3乵)/TM7!?ym!φ5v J#v?]4‡·6dl{9Gbq//M$v&tU=_ikNҽ!6%ޏ9wPZGhUyA<9߿OS[ NmMl#_׃hbK<jϖꚸ6_dŐ8.w9]yƥ$gUEf9NAzc7_hLÎ.lS4lۀ÷K1i٣_q4lP>yy|>v_sʵr[<^x,?ٕ}O bnKOc|$.oԉ䣎n_]\ŵG!wx/x{&K/jnEk5_\`R:rʵѷ}hL\7I_ϻhsL_.ݓ ަeTtq|1t>3q9oֱ6D; {oeZFӱ?[;#ҕ7\ɍmFսz<ǻMiԅ3^ŧ6Py: j8:ȕ_BqXmS>PfS|kB!*pQc*;tV'Tt]VϧV Em,rem,ic8^NAdu}K w~j\pFL1M-صk#}z'Z|{vw!ba6M69]rݨMWT.+p`Gmżss@qxQ7 cEh=&u>f*]Jgң.Kpm&u"!snLB!ĮKPbs:ǝW E0PNJ!BI(ˋy㋷B!I=B!uu!B! B!BAԅB!~P3!BQ~PB!oHgbzRg5hPĄD7oW7E!aԅ؇^?gR #CŶcVYC& !;d Q\\W7e@\(Dirc_\\gu.9#s?!2gddÁ;*R<ϰr2V\I 㽷T999=Wn<䒜U΁ 4I.2UG8_ݜm۴jӖ?ΡÁmxE~218NZj9p)B!2u`6pX^Vq|۷/j9BuW,{ck?![/{ԅH+b_#A]}1ȼ;@B};E/xSfenBo3<~r>ZL7W6'sGADZ/fYk.z2Wd6/z/xoڶWmv!;B:.9YLf tg <Pq}+3as%DdUYiZ{ӓ==H`Jgx;jcKqpb+T1e1]iәcs# c۵mԵцkm cVQ3OCzrGBQWՁQҺF:qaq}gGZ||;{e򆝍=~oB]iW΄]hmlx '݃(p,|,]Cb:&^v oZ3=t=v뱽qnaR8nb6nέ<#+DcC+V|oikJt]۟3:%acěu9\V?.z _ڂ_2n>=X|3z{;ɖK/;|>+Qz^>NjCfqq.N]FƆ⏼/;*ϟ~oցLh8.g/}?i/̈́1e[y{hsE\}u/7L7?V|:wH.|tazF2<t|W`/ ~ Ϗ 8[]_U]?ʺ^g g9Mfe/[˷ W1˘z_2G_A+y+~=ӎ/m"Z.=8äc5G\(0Y2W\|)؈~ M?!:˔x|~>H=R8}ln['Ps#ԛ>E}y.=b'؂Sxr½+cU{K9 #3w wɔ3ESoUoE[IqK9S7CDY9 ~)Mhܾ WE["n5s4*,)Y)'vE.L? uJUyZlٖ:>SÆ-,'Oo^>Pm o0mBC&zY/__tMSO$T^cs~lWDxVT{"8oF7ZZ+h$V>іrSEsX˱)V^uiV)X(ݰ&sy(B%I֝ #%畨hq(MomaGcb &h)B>3pV#WX $yE5:O>oEku]SiqnJ,qZ,saO]K_I2\,n6zh^ IDATɇ]nǢ9q$^5H>SۧuH|T"A}^ID1LƞI&v/4?Z$c9w:׸x2 ;~9}ɉǚPj1Dw[5.}&~ /Ȇ=r~л{:=:]u7cku [ cB~f igɖlUh0*p(/|qjL6oR&?xi`jAZd9J5cڅ߮qE,<SI|;*h[.7"'75qWV #v qkūdĤx~8v'9x\%x^lxtA0t`;G __OV5rY wO?N6Y{ꦹO#?%F|I>hN\ !Ȓd֗{e&pb^OB7xgs`S$FFr$&Bj7[~:f\g,s:qZ=_XSкYp.ZU.OJg3>FubXT`J>Yf/W iʈfN@AgгSi/^k!Mxw'sf'HZtLv|4|"kNn=ѵoŗJ?%1hG8Sfc: teO µhvwJ{[~w/*9NϺ\Ty]ë+6˴/[(2g]ޖ-WuXP9zHyZIgjU{Oiڕwy[,R=0kMIN@xnЁ?Q {.C'ZdD H*{ +k 5(Jxncob8,VUX-zŪx)djSm@'YU:4 wTQTc~3-jJ:[:q ];ڽ+9_م|m<>#?my6lْ%lYm`2ʜSnL?WLƌoNxk_~,Q5N!\yg}guS9'D;X+jBa$iF"X4SStfqs1n뚩kz]3D3""1aΛ{E>GGݥfR؍Dl55tLļò  4FB!x^[Zjov?7!;H6ts| X!q~eDapB<$Qu>hU24^EywbLV!xϝ{Oz>>l`Ym!JHB\KUn-nN/B!, !B$QB!I.B! D]!B$B!.Hu!B!\$B!B,}ã;znB!HGzu3 O>W? DDDMye8FEFfvBc}o .цaF L7L4&֮g:IC3 ! qB H)5{ODX2.AuR#&j[^$qB!\$H(2M3%ɔHB%!B$Q'uЂ,dbĠgz[y=Yzʉi:91e꽿 ڿBGc2m'di&ɧ`4,L 3-)rZ5NNo0w@agWqx4*G=D;>>uoqH},}g׼N㷷\W֔)?t]mdpBx4 |:SMrIkԓ0g1XN (i:ޢ`k&I5MVQS7MVX&Ҥ02>i`-35$v I+%0B}X /9[$Q'&Fv^ݲNy| A/6)3AדQ8/'/`ݟ9xNфҾVɱY{]sleH]qcĜfcSH5N2s^;4ՆŢ\0?^}\ O(nN:GZX$X%)kZP=+~5|k_4S٫%ɦj&&[pрwQُ,B|&uI^OPhS_ ʗ Ol g赝'`kᩥ/&q֜14v?,~Зj>? q"_0 LZa\ !x:π9aLr((3 =(0c5Rrr,OXLGv/DrNВw3WVS5R˓y\≟GG&ax5/D$ۊãP!wsJ\nQQ߇BGN||׭KN>}L$ꩲXJXŬ X* GYw|:ЀqS\VL/=';>MqC:c`uCSeO&y f^3#wZֻ_!f17kʅ/>jZ9du Gak_jUc)esv{6jyn>lގ:2{aF%aXN; z|7Wo=h3z nn?8t~FÃV.= SŌF! 0αiT m {?|ڕr~[lNhߕ=t˔=Xj:as%yPf+z!v,F_kZD̘m|3Ǹ*lۅ/e>!$Q>{e/e ~;С^yH/9|bZԯ| ClV<^‘$-&][Tx᛿ 4үrVbAi4{"89vzlL?0ᵍ˾ ]we}Pvm ]4 K\'TRJfq`(:W'$$R:i;1pIGY2r>%͓9m>[P1:d<3Em7X* ͆-uʝŌj4uIWXUUQU7!UR7h;]&UWfgy@io0;tE-ނ;1}>\ B 򉺫>+nX2rp© pFNqW=_9#wt(8oمGRMy)NrV*A5Rwo<}囃&/HUˏ'.f5, J4?h0ljyL%G̝>rv0o}8x$s ={hݾCÈُE )V-k64MC*ް+oO;8۝gmb^ZY3S+7IBF6_Bt|ڙ_fa^:5/$/K.ԕ'v>TB!#uˆ!nG &z|,>T7/CLuI1[$Q[In2+UaOp'*~Tf0c{<֭(~JEK0]XcxX#9|8guT/2SŌU!]KyCtq+̬Gٿ~E׿ _IOόb)\[4ywѷ(Rw˂݅;S;mcݬ2ʔTXJ7J43:9+6T~/gI/{6W^w{6H+}"BdI]s>0o]vʚSkq) OHN;4)8J嚉_.G:4gunݝn+;6_ٶu=3Nϗ` ^%<;qqӡ QNĮNhؠAҴ .%Xsi?!DfOa]Pq qhW^wx.S !x ǟlN|սӌ6T.] 0I8%y;uE3 z!G 㶥-^>x{g/(*SDJ֩xY[w-3Hgۯ<_Q4ހ᳖|Ŋ5} 9@q#R;O\Ȗ)GV#^37kVdrJ(RbŪ16S}sZ_$vJLT +:q'jRe,8<'{ѡ~vZLbwbƥt? 9Jo\$qz><B!2II){1R`;lɑ?1mOv7qNNdXd O0pFocإژ7a>Lji985ֵ34V-Ka f- ߙaBur^~Huؿ\Kwާ8p3 tv$&D狧]uS'w}f6m̦M+VJ~dg *xiK||>.h&̛-%0.s 쾈E9sxQc9X)e|o1Npm0'P HYD.g υy͖oө-ů)R.՞ίƥ3[w^h[4[$!JȼНhH]7n;rS#Yv}J,@XhaA?ߙ+iQ(?a"oԶnZxBWVmv%|I ͟O1`m-3WHkP :?ug!mϨIɗߤFΗ  |wou(Lz2q}$I /QP>B Qo}9**(^}iKvo*x˔IuGC4u/2PRaϴx5 IDAT!Rb&rlX^Ua(t4;}ұ Ҕ܄b#@Pz2uץD4'4>B tˉD5”q<:PTJ*Kicȿ CB({'L{l.9 V!x4"!qB!\$@V-3t Γ۝?r#+Q.4BdEԨ !B#:2B!p=2=B!.Hu!B!\ /B!HB!.Hzԑu!BzG]!B$x9U}n#M(B<$Q'%#9 KeQtߦ m`BR+_DF2Ql:fe ^;HJMāy61!$=OA x="#g-Uyƌ>CYt=IGY2r>%͓9Mؒ{ 2fTg,gvrm; ͆-uwxEbq`j5ͺ$.GBUUTUMHզ Ŏd\ƅѯ#rceH޴;c0W',^^2w`,FUX/_:MNQW[M 7iĥ_@Ԫ1|3=jE6-FnGj-/ay G6/r/7v\W!P2MiVAAxͶ4Y8x$s ={5naDG"O߉?qA Toؕlh36 /,-KBF6_BtB((IJs©`,=~G%f£|)r#u\OBF,]k>"q49]ڏt2hQv<=zi_1j÷XSX W6&n<ۍw_{sN!⁓D1b1!Rq[uF߬Y*QHƠث2OYi͊*P-6h2)'jRehGI̞̯@qKp\nOp`Wy+)f>ԍ_k}WˑF>&pp7%j]#G3 z!G 깥zZ: UQ=Wה !IӼEׇדݶ8^ʭo >ٽ[6if6mZ2V*#F?KUH[[qA3qFogo,yqgdŔ-șK'sfM){Tu'pf6wMjfFʢ%r&>Khx..rvhbtr {UUߤcL#bt۞n2 Н8Ϋ/1履yJɱrNC~6*ӉSSFHT3 Iƥ{;͟wtu1ĸq*}ӲiLB!2BͼI%(6.CwiNtӸ2Wv_|}//>xmyہ (2exPv?3i݋$Fz { aƞ 3cRb +DY#m@m;mw 1CO&2q8Z [N$FkPP%#~cֈ\9Ѭ{>  ,4eG -s=;Ҷםh͸|G|KO"o+Ŗ9mƱ/ ~" z2;* (+FH.\>?J)\E !x<[?i^y^VQEQsK<&xaqOjѓ-VKX$մTjL=ɪ:ys|(w["SkG!Ga*IԁZf̝';FV\h!Ȋ$Q QB!.Fudu!BzdzF!B!\$B!B )}AJ_B!u!B!\#=B!HB!.Hu%sT{o/ݔGQ!xINJKF.v\(LH2SDOLeI܁8#φ*(7kbR㫥{ґiwĽ_i ?AbI̦/r< i7} MVj*~:B6[7~Cי% -w{HRp7r8EpB3($Lhu+&'+ KN}w6

ync}ٷo;3{~m4)_Dѿq_VS]{2ߤ%af^F,c2^wRdv/ӈZ'zK64{BDQ=_gsW~o_Mh٣dבJݱزSQoZ~͌1X܁/@|0#ݍ*X6lŚ/KfɋUa6qX0ZF.2ˑPUUUyR)uv#*RlR< +8 Q( ^#(w.M8"eniE{bAn!$`כ>+Urcz)z kOAbqLE^zBnU`]=lVcQ;!Wȍj![p dhIԅB<D={oMu"4$l{H_=m(Ce(iB,;wI,?S!$,=~}~؅V`N|4.Dld*TIcDZe(B;}, RE0EIt2L3;RוY| Q6^E&w8jQpWnMKTٌޣfOk̏H$fV? 1o[s[_W_+BKhx.uvZq;u DӜ8I͵?׿H>k ԡY9_,|"Np>-3bv nG{^T cGTF)6OgL.qt/6vblڼM+'RRVmǣO$]&k-hZ( 6r(ui7Y(~U %BdIԁ^7DēyyC^(]62R#r8FD.XДÂS)l16{bҔO[zvmI;9&bnLu)5OdNpB#@AJHT)Ly9t& yLb~@Xh7Ls6- ,kΥЈu)] EK6m#LQlU Qdk&SIso8mɘg .uazGEv__|//~^8lV<}|`Q" t2uPw=,e/BU^e}LToWY,Bd{3+k 5(Jxncob8,VUX-zŪx)djSm@'YU:4 wTQTc~3-j[G!H4o2C`< 0BBC!DV$:`HB!p1# !B#3 !B$QB!I R"B!\w1ǿsf&"ADdĖF,o jiڊV-Umڪ.T*}Uk#ƾ/%D"[ddf HЈu=Wՙs9y>!B-Y6K0,u)t}/=:/!)Y2$ca[m$A }"sdGUf]ט#NMa1bg]ér۱uix|*v!j2Flc`){aQ77O[V:sr8*Nx-gg:'ghD.X&uuB$DQű;P#1#9 ;vmH`9/<\qrۧ4Ji28|ζK`S2[brDN*yȟpxo|18hPjƺsj.BcX6֊( {7굣%dҳwчkԑ~.JhIj>c zfУ˳O(퉛ż(] w8aE1vLK3vw/Ap~rGwNu(ξ IDATR+Nή%K!%zA9h{ËU]hn^Zǰ&f=gwb?ݒep~ ̐kiO/{ 5D ;&Od0gG\/+1؞FX;LM;BHŦfw%+*7xyc4Nty[?dH; /L2wNQ$+TvW]G3b [e/SZ&o}B%37*!O$Yi-f_ ۜ=) t#%pxk,aq{6oGN߳@Vs!B&ͷAHdjf f#mRpuQIKfr%E#0q8'6Uf浯jwkEi;~>-}ʥ9cCJXЀj>s:JdM7J+3ĭϿʥG)x0cdžf VoOzQĕˬ$?^χeTN>y9 #N>+gexh¹|<` ?F0 Uu!OY-n#D|XQU@ާP)v8@WFfq :\kb֤P| UT~ ųo= NG5GC ?+壅~֫Hٰiwaˊ8ʨ F]f&nzO]G?uk^{g*s4Qn0} $G| 3~;I38Wt6ǚ3y]E;:Nzٯ' 97Ry_^[˯nzHVKeZnm n+C2D̎"U'BDsl֟"zΙ -3f)OP`8ҕڕ&,ާτ T9<]w(V1bhO&wԛLUULbVPi S U/+9x!Myk,V/#,WR̘>^hSqfCNL9gXx?q4x6:mQTNiۍ7;gDKTs͙~۸- jԋ3hcJ7ױ !OR3{6WKhl&' `ЙJI8]i$BpEcy@8?=AM/%ۿ̘iQ*nI`ӷX)Cݗ`x#;%sh,ܘQ0RwHϞȾzy ݮ$2g R}O@31jҦ4 " ]X܅dxH$i(~mo[~|> t5|[5wOcGk8p Ūm˦>)qSϘGǂ!qB!Iԁ;u,-;/qh!xIR.B!IԑuԅB!D#3 !BQI.B!D$/HB!(zuIB!ēGfԑu!BQ<3B!BBt^fŢoQTͶ=ncv$Z3eI>GY~܁j>AtJ?@;~Sm |LTg'߸{:]*Э?sB!D":7j%ٰi#6md7`gx+R:oޘڕR_z#7(yG&E0˻Y14E<ϾևR H'vTNw~%7RY":p:4긲c&WA;\B!KC105SN-'R$]ʫx*tiL:Mη,9xw4C *D_4e2vLE`~&>$_Vc6=1\-;T+9IaMB #zKKY4JiVzMLQ 喾t`XуR˄õyT5{ȼx9u+u<^?B!3ٞ2 hչ#U*9cCJXЀj>s:Jd7J+3ĭϿʥG)x0cdžf VoOɺJF `pfOl!k_ ֔\5{v|ZN\H"͜ƕۙX⚶#4E9$8d$q7tMoYp V[*W Q#sܓy-?$B<$Q@gr|7jb7`šRh]̘w !{CԠj@ !YSl˦vn.s&| )6A+T81 #MR5\Jj?@j&&kNJT{S1˿Eʟy{c&o@4 =SҧIUn ~-E4zֲ U*x ,. ?؀=CCE sQ'gy9дONct7Nw4(:Aot:a4hzbTVM1.à88)Qo\WA箷S<:S+%[5?b{햭Щz}VG^z $?OY#`ħf8vUhIyDwU*f>׬XVm=a<8> ˗ѨIcl6jf/swjR֊^uiW= ,z=^}x;1BgS/4e[zY5kWUdEb@IOSUU5!ӠS-EXu6Uooђ5flV[UʹmICs+-bAGt=[+ *|<B!xH\9B!Cu O!B! 5BD]<$OB!HuQ&B!.fR!B! QGfuB!HfԅB!($QP&ǧgQ`/c,׃b.c !Dҗlz3?|ܜ7]IlRSjL|y &=AZXyM+güXim_Q(5tVÆӘ +^f|4-bOزm6=YǬ8c~N)LbJo|Qr5AOX7bzvLtOMhˤ|BnBG$猺 N|O_}oL3ܔ;nGhP^x [$m ^'WO}JY:te߼1+ӿHF F#fPtJ!4i=g3Ϥ*(׎ؗY8v4< *CqWgԤMIY/ 5%#Įm;d pu"6@xyGr-nYc1fR,CJq{y{\NÒX@qT\ l܌AqnףΙ*{ѺneL%p-@SmuΊ/A,抓+Ž}(CI7(B<$QOV}dUkOMS1\(Y6B^PGK8 DN:5 %ߏ6i>s,-glVO˰4l՛md= ؋>M|sI$lb{ban]׃ks*a},,M8rr vڥ1<0 4*18bfJ߉ь< wݍA|WLިB<ERg/V.jqi(^x%]{0Ԭ$lOVp-;r~7]_,ۖͮ:liWH(IO&ѤÈcc H_C vq2o4L>0#*ɺB'ج|L.]z`*]:0׵chRد@if^5n- )ͼo;+#xs3Ϛ_=UèTޔ{o}^ =y=ϊohjí7/F\͆Mؼk[Vq\WFmxoc,|U3g6~ǀ ~0 Jo{Oc44%#ŋHoَjg'}WC"neug/ZO%af/]:֒-=Ϳ-X+-`KX`sAb]yzD#5fvwR7!W7s}j"SfGZ'=B'}atvA3GxŌ v%yՆ_{-E<FӲ= W1`êI6UmˏA7p/VSH8[d0oAJ>h ҤLne7i8^ayЮu wm% oQg:3Z62AmG3볒5kuz]pqqխ8>ѮQ~!xQ%iϼ}.ahR?R.$:j e+ߺDZ LtɧӇӰbbe%pZ*ֲySͤ]9sd\l3^ECZX,T-V[ D/ŲW &k>N\H"͜ƕۙ&Z IDATX⚶#4#Q.CzSjVI*Ca\j*G}17S\fb믻žE+q} AfVccP'$Z#ɨ\*zh4g.u|8Ưiy1SX e/8j6k łŪfn#V.==J?ѯłb%ƕkt W0^ئGUI2u!O QaNJ-RzִbD8&E-}^FӇkFSolpj&&~9G.e,Mku˙'3Ty|YǺ!Aے94tn(SKԠDuZ <]On.s&|k u 03MΫ&mzLcZ %ߣ ZQB"ͻV r qQxnٮpdDKJXlSгqW( t0Kr= ۏ#g0}=>Y~m45_w1ؙiZx){tEl莯.ףe 5vw e2l`Dg9ʱ8Rc Di y9L&Bd<]߯c'*|Н2*nFAiPtzޖ7\uz-hFŨb]AqpR+ި((]oxuWJL1Yl{޲u:uBUUԫ_/_aȢag7S2{]iR/vy+.=>!PYO_ja徬X?!x\\FMcTUT5?_MCٸn=›g4^˻4oG;ElElT/flR (ijf0dtEf-Zf٬jK61ɢuPc΢yEE,]:ݿ[X]?EXLB!G !BFu ~:Q'BǑ$@^ B!,I$B!cHV=B!uHʗ#B!.IX]Am._ B'ꅐ٬߉x B|qy B}=taB!)z!ؼisbBq%r#Z.ףBQHةchA|y/CFC!Hu@u!BQH.B!YG]!B"Hu!B! )}AJ_B!D̨K-B! ֣aʌ:2.B!G`F]!B'$, #M(B<$Q'0[^dߦ6~&_*7oWf =5 Kk^e/5??gB^=O_Ʉɟ&`d<^G(y 1V5f&nڢ6&~Z)3qpBL&L4 smHBK wv9XGF֖0 ?ӻMs(8I9o2w-o[/{ƻ1gI؟x4K;~&LA57Q#x$#~LXw] B!D#}Q=ջ=?1ٵ-Jt|!:ȏ]$Qp"tL<dz[<۳3]Сۏ{:]*Э?%Ǘ x(c1aϾfSt^CSEdPI"^O)KC ݃O~Y#1D_ƈm 53YVq} xk1=O&:sR3{*=[ ;Z=G1n;ĉ<8p2I\)pf .ߏHd?5.fʣq 0$d_;Z6¾xƞ1*xG!(hs?3:ƆM˾c4+AΨѶwT++ֿ5IBvn31>#֝nY?vbݨʎ^֧5cfw|@w#'Uw$,1I%Щ.BcX6z( `wï^;{`_Bf!%g<*Q7g'yQ^%p:gtE뺕1põx{NݿqrsR9Jb&'E#uhT.ƿ0i˔uZ\%)f>䡿Y|#^AQK;ž8jwwF(*oT1:R,\r0KB8 ! ,z)sڇY8K.KȩlӇVԢ[IC;\w;{м꠬*ӕ +Q,1YÙ=&y]rfoڎOK¼4u8&bc̗ 稑uZaf}f4ʢG53T\pq)vX :Ϛg&VNfpJDE%j"8:c~Z:윝 *zB!xɌ:`Z e?Cp(߫Fm?wZz,KЪw#s۴dϞMZU,nOec?~ 2W?+壅~֫i7s56mb=lY1q]"PLS`tg=*_FXs&J#5fvwR#GK8>G'RHΙQ$(85/ٞǟf@}#%K:G޽b^梑;B'WP/6 0aSZ/g1 Tjh12uVٞTPE;:V<)W]cjɺ.u4w SVT\.z35{qVٟB'$ꀦ^H7ڴ .,j2Q3q'NNÒ Vvs^b_yjeέJdpO߲Xv**z#,^'gT4[*/bXGLᣘ;ړ]0?UgcytcgCYU}^n!fج$^R !hD Qh.l`kU9䶞[ϴ*jۊ8v s<˧icdMY'+O׼T~Atx|OG]uF˜ ,?HNZoHIxq^ @V-+ڦU ΚbX6+e b\P*]3&ez܊qs2bttX1׬[F!Z)\̣ccmL5 Qa.-Fʴ]x Ie8gm덨SF,r,k Nr+{QϏomڄi^͹pB!i % ṯJQgw;fޠe :W`04Q1*FjaP7j. s)zuL8+mlFNPջ:rW8Μ 9nTw?"W7OKhն#qpBZ|4f**]M4,](z.X@zJzhMhtmeլ]UQm]%=MUV LNb,VEKlz;UYmvV5f9&YjY4h9R׳RYmzB!xHT9B!xD<$B!ByT!B"HfMԅB!D#3B!BA !BQI `k !BQ|^6zB!D0l޴\tI88 BQHةchA|y/CFC!Hu@u!BQH.B!YQ!B"Hu!B! )}AJ_B!D#3B! T'jeFQB!Ę !BQI.LOmAϢ0?<$B!ēHuJ_ ̠W[&dB~߰H2*0b2g lۜKEFjZL&L[hwai̅Ut8ݛǘ5);i#wCM&DŽ}w_*8I9ѯZ.:Xevx!&L5?J\R^wB"ǚ]rkozٔv]éR יBDQYCVStl̚^u;^9A b^.텻W Ι*{ѺneL%p-@Smlq-ó>Vy BGs<Bw퐵Tb I1?q=UEQ0ػWͽ/!žKјi}TwSsm*f4QC{2s^4GŕhDwۯD{DׇRk4֝: ,煇3NxƳX)ւ/ 3"vLE`~&>$`Vc6=1\?(G-ؗW^ I`dVAiU\7)qN/Ο]Q&=go[1I(!~YOcic˫ӥ1u4;߲ BD>9{la24sY-KIA<ٲy1_.a8{[Fz>zy`MK=̬O6N;rȩlӇe*W윝 *yk9z/qT3SH7cRpuQIKޘhȥٰ}=s޳燷ƲR-! ~c/ZgWsB!Oufi.4"fqT-} ^kaBkC#5fvwR#뇮qdlh ]ଫ?+壅~֫i7s56mb=lY1q]b!|"qZz,KЪw#nL+ػT׳I4puagދt;H!9睉Ir控w^۞s%lD'Uۃ$pB!DQ#}H;NzzV/?dce)=YJy\*Іn[/g1 Tjh12uVٞTPs:|Mb$o&u̎qpq b%1ӽE$9_Kr`.:r)]>_&38'jU(/&o3GSYB+`+خƱ|5j8FPVѠfQeF]!Iu@,߹5_aFt=hB0Bfi6DˤӸzf?K5:rWjL~,,+}xqAٺ}oEy~k~@-_:eX6PbXZl6 518b ўL217jVI*Ca\wA^b_yj9Kn!fج$^Ru{V9-g łŚDާτgc:ΙdBV"B%j(]hkK/J7E5ԵR%(RBbn,DI9?J1_j<|yLG=`7}ïOi'+?~й&t2~Ώ'I`Ǟq2^\B;$7 Z&G3teϔ sQL3~S7׾Y5'59O{_~aRT8jT6L?zwi-c፯W^Ɇ3}ư`_F~ATpֱ:5YTB@Q,R1goz~ogIW#FMDM%lf?BWLi1{]muG[!ޡo 2khP,v&4$8߈DZaլAp8PÇ|$g2P)a*NP9ss8g83jv5\;tC3; irsjSsfizHwլzI K/,CE\Z%7}S}m2VD!BA\?Q/.R@!B܅$QB!äB!B Q RB!.FfԅB!pA !BႤЮcv!B!Jmq6B!A~}Ros/J;ıdHB#:%:T[4V>Ɨ;!BC!ĝHu@u!Bb$QGQB!GgB!I.B! E!ns;d2.B! udF]!BQB!I.n\lGq$B!HuJ_Js+N9x 5"f#vO |/fQ6mU lؖ(2 IDATA֑LМ bۼNL1mp3i)lBs8.}:&GpSS0o =OXtZ'#q ؖz6Nk7o3mK^IF``s+Gvn7*F.0]v0]h=t)8 iK!Hw9~>}fMi;`<ˍ[E1ߨ/ٿgc!?!P$%ߒٽyuk=OG^6;9&Espf,IbۼVJ$qJ2K;=H{iORR:m2a~ mLc]#!w`>@r ``?Ac}߱1W#oqѕz_>;pC.OF<"A!p5-~[KcDrnm3͓lR'6B˹|]Q>]jQFxr+B|g|Kۼ4?Lϳ1y᫴^iD&R{/ayZ^q\q2gv}Kr`R!2F`v Nj;#.N%sv@[ |%{pל@[ 8~9@ 1la96D.UF$vߢB!\$a  |YߥPb߭Z_0q/Nɷ]YN4(Yzne@yr,:6/k=u?v㍳Y8//vvwnLp AszM\Z+jĽǖa m~,es|7IoBߙsIM;NJhn3SEgGSph,=8[`I0lΝshbr%}j+iS-?fTԽˈYℌtreU!w!I =yK8C#W3oq~^IRebFtX¿_~eFv+%~@ .m*>v) 2/ܮ22Zk&e<׿Uw-t[;ٺf,z3.8ޛ0d#\d:*/OfpX+>@8~ eLp34^ً{#_7ޗ^ăG,U ϙEφ5XvOxCO3ꆧ'v( Zۉ{h\L6 ^ &FNIۡqB!K- aB^?>֍f`,~߂ .xr-WݜLpjgemr U{Ű!&^cHviVOonedR2'׬9/=FP>؏xl <3s+XQ4Ž2P< |,#|#9[$e>g:np-k;}jfOjyGզ_ǚxu?CC K6e6/͛tfo/6 Xh9ESj XagIW#FMDM%lf?KⅯ~r^X-f<}.cF5 "~wV9Q;Q6gO#iZ%y{Nރ DZ%Y]kT=ދ<ty+E:?OԡNp(-c2>^U:j]igOhCH@ 3o?DLCD`Ɣ"Y2&~ϔBӍ-a΋FMR=I(n&#׬*&ək2+^̱ EP-UkUj&ᩢzV䦖3)F9äSkݺ{FGşq6kzCa +'c޶POvO/zp 6d qB!DԨ !B#:B!p=<B!.Hu!B!\ /B!ȌB! D̨#3B!ȌB!.Huqrdf;ۏVw&qB!FWR[R8<@[;q\uLُ6m3%1s捡Gc4l?IWKu2mgܜmvgBx^Ø[QTDs׏VA6muyJ̤uL4C%>ݑ*gٛOf#DXy0F"q{ؒ U.B!ĝKbh63sHi׌N.-3FFHD3Z˜m')I#%}e?I{K9Ȅ11r~moweȎ`,M}h v0Bu~" ~"<^IVJ$qJ2şZ^XӇ;ؿ[f }Jn s~2=n ;CcZ,.t~|7$3%|8?Nf88qO9Vg<XB!ĝMuQ7Ry/F:Կ̈g+H~ml',LB/u-%?b6Zgؘ֍ HY_9q睷Ҥ?^T G!0}̈r'^U ZFIWhxN\zZUUTUM`NDewJn>]t5|EY TSV0Qqoz}*Hv7d/](|\KpfQcAu+G("8,+bre%Tr]xB!p\-5L\8UJwٌOys˿L"fgHZ q1l0_ﬣƙ]ߒ\;C X~%LjS "=_cɞ4M/aj]_ _UewBiD&Z ~Ú1OnjN$:BY*Ѥs8Wl")]Cwr`rtQbbr8^=pl[, < ƣBqs#7$'7*֯E$R){"[1=߉Y?ٞ(+svQ@禓v531kasueN}@7HY1S`^~a;;7fv t'*,&z69z19],eT瞌[|H8}:.{[mvv'oUɔu )J6cS=YB!ĝNf(vӝ:!|:/~OҰ~8ޛ0d#\d:*/OfpX+>@8~ eLp34^ً{#_7ޗ^ă[3/ -j-mY4#lởwuX<&g/Quh;^`U-=4VM&kAf+:NjhgfUȑlŔctQwq,r4*쟝B!ĝNE lK82 ݜ_bHuCC`?yw3sS4BqLF&UaCL15&x{{[}m.ɸ%POqTjO.D3v><߷{O@.MiF1{QhXW)w8wOZ޸Oz?DPmbc~y B!ĝNu0tc^?5^|¯U<ν{ٱ};۶og02bE۰:ÁiNp俨P(ڃ竭f4]N]CiYUfxgz&G7bމt]`R=}*$1$SMrRѝ^14fnty^<0= { "&ՙg=. QN{bO1߾UѰDՅX=Za^vȏ;LwbT4_xB!2y3Elbq{>ɓX>;JS#F歲ҹ}M(E]S,^wq+b2f@KYC wg(MpP 3+ejv 45XǼPF72'LTh=E/iZ!^ȥXL-b!(Mރb%B^5i5.\֫_D\K-պ0Іj4z'.ft_T4NĜijĽ֎5k^557k.폽Ǔ!թBsX1QbV8q8{O;^O7 ^~z[Q(Benϟa\:/*5JHe$5ۢ&\&gɬx)&3b6LբZ4CcVeTժ{,ZZΤ Z~RhfBw^{m5:]/7дY";lbtxvH#etyoeA jՇ=h =܃{ݰ~zGn/h߱ӭmNpBqZ*Zju0.}} dMqiYUIJKy*\A&+1g8 3W?ۍ:zӡ\0fg]`5+CwMq:40&7f85g:NtQ'ĨGgke՗b? V#<#Ɨ;!BC!ĝHu@u!Bb$QGQB!GgB!I.B! J_n~Y!BW#3B!B`Fu!BjdF]!B$r92~r[8 !w#I+})ͭi)lBs8un7*F.0]:`u@[U")8E|<|6 Zʃ7o~&}q o?iO`/j>j~EmU:Ke !VL`o޳ax\ CڅCޑf0DlF+o܂Kıa8R1gmBhTkv; JzyԬ;clT !;I^ ff34"9W7n1c4hUnI{iOR#c1z§3v$@'9Z ezv2ƴY|HwzO2c_2ɇaJdv_dJU$;ΡC |1}^&>n ^#$o {|#l$&`n|z;_n$;C4`)=׽| f텏$DZرC4kpLj~< ,ٚ@#t`!w#I)fFK4S 9^IOd}n_gԵ8ċ#xE§džw lEpE/zWzT*r{ӻW)WE{!{~B3Z4jM- [9DFkHLBw2Lݛ RX2& fKfV$-ɉn^w5‹cTtr8n ';%AyUw*G3>r~u}[+Ʊ8ɖ4Ud%va d`j٪WezP{UJB!<\-5_+yEc G)wNK!< !3H[Xk0,h9+6;R9q9IM:Ҩ|1 9N<J$_i[؞ADo9/DD#kp,+?-ua!SߙB.-(é=+keQP 9K[8WBqWo[)qesaJ/[9;V/&'v?Oܓ~xٕɏ#^'Et*jם;u}JO,*Ž,;Y8 6婣ŝGEp:N^Kkh),Jrnocl(F.Px!5-wEv?cE0O.]F'ܗNn Ngv=4{*>r^;C?Tɉx,CU+^ !>9t~c 0_D|:&) 'P׃XU ~u;rk(pAflQSIV ̬*݁9r㼘u _.k&e<׿U/nl޲~5cԓ76)d~u#hR Tߎ}>gg^^ud',|QPj814uj5L?%q,nl(VjͧO'iؙ6йKyQ^x8>/Qp$7%/B!7'a]N0س{MA>T!Bt{̨d2.B!\̨ !B$Q7Q.GfٸouWnkG!n$:OV2rH9Wl}Wp㛌\:!!ڪp -~;b.@[U;dEqz >ב@(ve[gBƴ'Z5Rq*A+82nb`-Y!1Hё*#Y4ѪVsڹĎG )vA枏6Jl|=M"S0{Kg`^XKt[H:+eb`zC<>cs>hrcχh$=8No^IfK&/Liq y FbzbOfH`o5*)wQW'NNIܟ3e.!w%I)fFK4S c?Wgx|a%XX83L ͬ^IZ6F3</j>>ϩptNvJTTfH}L=D&kMnW#ĝ̹|ݽ lډȀN-8Q1]bV \@t~(HKO9 㨥q8N򱠺Ndi Iwlxi>oVWwשKeY" ł_XWFd2%SBqrDV}6o@f eTp_x':GP/ iك.cxH2OD4y6{ Dz#[9<`z1ctH0)B^p@Bé=i%Ui~ڟgcWiUٽDV#-q "(tr8iL㖝yTΕcwoIƏ}DO!R{/ay/hGK%tgM$kTl\NR4*o=ĸ_fSl'7~qϿba\OlIG!6 30-5='iTM~do<*Uʹ.їf£dd@OaSԴ ܩ Yާ= cnS?LS׎;AQo1lgw"VLYesC;'RFuxMJ4(˟oV(-ɽzB39t~cbߜLրgg^^u!}',|QPj814uj5L?%62 f"^s[PZ0miF6ow?d뚱xLPMULsj 5?gOYFMQrE*VEDnx>]w,xop.G$vfVQ9q^L:O;Auh;^`U-=4VM&w_μ,MBq?%DH`ɿư-2Wqj`Ɖ`V=4Իb^}R{ۍ ]$%ʗQ>)jS+ 1˗G 3zz퍏olw/'͢^B( Y,l -95+}KQ74c=7[>HyG M]=@.MiF1{QhXW0T/,R BzpKͩKʄ_BqD07]/X.76y=R~=N=ԣۙz~&'v"KSќ8駣0rO[ R3dcǂ1`O^T ƞ X%5É44F9m[7rL K\CMr߳dd<h]T, :mē^c8uSxmvpѣkܻ۷mvJ S(#Vn`Z-/q8ipAVY:3ۗX=VNS/W3s7a+ 'u,&N bm -GhJ-Ĝɿ%B^5i5.\%cqNfٻBjR7i5s%"?Nδ=,ՙC]'V6o¸@~~]yaûjko\{'CS#0cly/=,պ0Іj4z'.ft_T@!ޡo 2.Q!?øt^T4jJ(IjEq3YMfU1M\YRLfgl,Ehj-ǬZ˨UC0Y OK*>&7I1&/Dkݺ{FG_9oiEw,`GN]03/{cr^Q]% ٰ~zؾ[ wtqۻx'܃Bܩ-YLxӉaٽ6m#=^UM,[d2P^S?4s\n7NrvwM9׬ݡ;4L#pܜԜn;=F5kxbFT랭b?-r3ZB!wIԁ[ZB!WD|S!B" !BdF0dJ]!BQB!I.B! @s^B!BOK~ܩi7 !B!'-ߕzkV~Qmމ$%C(BIԁ.Qq%@>6d qB!DԨ !B#:B!p=<B!.Hu!B!\ /B!ȌB!8qm̨#3B!w_++W%3B!hHyQ,IMˑh6n?[ݕۚQ!(Iide^($䕾V2rH9Wl}Wp*{lW32򻠧nb`-٠!1n W~6^H:kŶԳ nNpZm !VL`owg%|Pz?J*]p8Y4ѪV̸'iޫD5kݶ/1d_A֑LМ Ky,!O:uVwXC;FLf4fvrgdk/="H!RrK#p#hz'!)DLs86'?x)P1|?v5RgZ`۪DС^>/{f`?Ac}߱1WCߟ4=97TuRÎ 7@7HwzO2c_2ɇaJdv_0')_tgcp!eSw(wG^6;9&EspfDru!%IJ_n#W7Ry/F:ԿG5?o>^|Ų O}:E3L ͬ*WV-fTLW7Q8ċ#XlR#ĝ̹|ݽ lډȀN-LO凩svdF<^{|9PhْF/c*kiG- vEխu"HKH8Q<IR'vY" ł_XWFd2%SBQa.߀PG!9@P`e¯BEi)64h~±+3 N4nٙN\-i1\BK!< !kHJ/r懩yv}=&/|V FZEQ~8P!m<5I+!-ua!SߙBhj\5J4HJظ&iT a{,h&N=]kY{=OBxrk*V*?ƅHIBQۥEg, bv"#ӏG_«xWAf?6#R9b}8o&< ,UU|8Jt,_3^*|J%Cq3x?~!B2M0_[OY>v0 SC俘nOy{޽PF)Yn?Yg[s*rPl>Xs=_w7CJLP~Rݎow (,6hFu^E`\ʓjAw9V3`P$""v:tt(i 庌cٸ22_o ^X=$sI)*BZUɖtgH':ΝQ"?p9oq4UehAZQ~Tמދ@v_lN͉.㍪҈.Op12Q"* 9qDDV|'$:`y/Y i伾@h~;O&LMLy?֊ ݲ]&%IJkKP0H}?;N)'ޙk}xINea9 ;lݱ-6a&6,KK.vlU=f ˎʧxhNn v)BUg z)l8g.8ojܽ xrt<f5%0k '30M䄕\"F l(Ӆ.]y]#yO,'{ӣSUD{!½Hdֹ,4 .t4{tJig8q>Jn-!;9iXan5j'MɚloC^jGfezR_oaTZgfm ,US9i0Sw͏ ..~x٬c~EXQי>2>7;.Np2E8Z5ڍ%D&F(s,|t8jLh[ t#iT (x=_cޜ/}2mPॵf=VɀkwqD G<^pڍ=Cnŗ/Oal/٠;;Ja{?*,EAk3g/B!ڵGMrԙ;Ӫ*EϴX?b3lVbSmM3UhVGU4 oUQT/%[3ش%F;a i۾}Ytuc^?AF% $9~_MqIG=ӼcgZWeK}<"gcЬe{Ǣp B IDATQT͝5^uL$n{7ng{U0wl]'bxRotS9gg yH]y+jza8=5 Lb ݥY<]f[os#8.-^5p{'ǔYp}Q"mO}1\\j3ZOcֻcpԧHH5ri7q.CQnaaMtYce\3' Se%B;$yNalC:x"IZ4zԉr'H&x8>e=o'*^X0z&rF÷m$[.N'kϦ^mfxa>9YJI<"s}P0LGbyF oP ~Km}KPq'UUQU?hTf3 SKw`iPT+6¢pv~;|PrR?kLC~y35 qԒ8ILG`CjvI͡cMGk(E1۵80`R:494B!Z bjP^rY3ư˴W8saj-|v:ì)Zǟ}v.f5[Nyl/Yio03$V#i:6%աNo|SGb1;-zD^MKogۇ&WyT5<:]Waβg<lIyƩmk9X%iiaQ Ʈh΃B!܆$IŽgdE`d&s6 >BWsP<:9u~דaqw>pdd ??H;i:4oʚg9neOy{޽Pm5ӯ[Yxޟu5<)( N[}L!n4w봵'ckV&Cr4-KI_k.{8 _j̈́FӞ:5v0+Ng*6?_J)U>:Ԃ?ϛH!Is l"O:rmQy\n{8Wu)kEQ^{{/iJy\=%H!s}^_jy/C[WwҲqS7nNoD[*-:d3}knSx,H L:֘Q&Ӕ)ϢZ_lGZA^xCsr SY/ H".v* eU371cX0_v}W$nad-]~xٙ1Y0*~۶lbæMlذGxRfkxFeו}\G RPb igNAS:qT}+P_ L=H5Co@s4 C7/{ щ>En4m m%!+ n:ٳia\hbbɇ xbbK&Gf?_dhJBG3=3FL?MoB_1b7攗}qZFamv]zT}ʽUS9i0 :<Q3W21ӻNjάJդEL|&V:&+~>-RDA^RrM R~koO'LUk3y\3jGJ-x2|1)]#OOvhu__~h\b>(>U5q|8o$?/NbRϪH]!ڵGMrԙ;Ӫ*EϴX?b3lVbSmM3UhVGU4 oUQT/%[3ش%>D #3moH˨S7U j7W%܍.aPU39w6 Kds8=8c8sFR[Q NfZe .2SLk;udY+wn9§(7\z,%5䳵H!B $Qn!B!n$ B!BB!w"ԅB!B!nHu!B!ܐL}4=hB!0HoA!B+HBsqB(8 B~$QڴoW͛=GGBQI2G]!B Q8 !Bw#gB! I.B! z2E!B !BᆤTԅB!B!nHuq erh|bo&qB!D50co1^hLݎ#>?ZIv %_8Yj3ׄPOcֻcpԧHH5nn]_wtb1:q4]luZGqiw,p_nfRr;[ ;/|q31:ƞԍ|Bjg3gxqثس_-9ʹxEగc iB!;9yN Kشq ״<yiO b} ķ/R3=i3.]ڨX=qmE2;؞YIKqtgx!XlD4Kryf*{f=:o,O-nK #B؜d~JG,Vۥɚy3Nвg]JX4Z_'5$KRj5B6ū<1VDyX eB!;D=5hSx;(6+VEuaj-|v:ì$.ȷ{1ex'{$^<2LI63K= xp1oP'@>h(dyO^ag*C76aH7:p3C[vs=ȫqmәatkt@ygoGfxpsv">͇q3BNq;ѪSxMiLl}x&ur2x"# QOG]YeIZ|&jNre im? k8Grkuvtӽ6;ֵ=aB?JӐ™geiƪgKbB’/'$'eb5exz`Zlk}^sC+voCbas挓_$A6m) ՅBkI+5L ~oZ%}8xŗOƬ (6|,PԯP Տc%v&cdeЩTz5xM#}7i[9Zw>}2&йf%i2-w?KS߲R5{=A^ (wM"kՔY~C39E>&cyQrL~5$fk>9bl,LcwXػt e0f 2+ws[UtuP=D֊;i.9Hz!Q!HOyzt8R)^A}y[حBZUjJF#e+UZκjSŜVOmftX <2M[Zt$~ܗ>y\neuDzqeeJnKb1]d0sn<)Pf+YmQQ5|nƪf벟yD jUZDuq_7ٔ f 'VF ^y$-{>Cò٪5P+c?cB!DNnD!7ͼo[tׅMsX z)l2>7;/$Nf'ByB+VF$x˂G=7DVzPlBk^D ?~x\G3uZ}yʄVZ"aG^s@6g~lntw'm=5GG>Nxy^XIا3``yo/7Q5" FNFB>nyivQu&6eδj3-VOX մTjLGUQU/ b3}UT?K x 6-jO+';}27lmF޳s/]FݘObPl*n4v "=I_}φ'qa#fcvBr >ű hֲտ=^QcQ8!(ΚITn:i=7ʳZ;{6]B%E7NrF4N󜁑V4pzjVp.å)KxSx蚩kzfdN;e 3,slKPR>YH;_v. !B;$&B!܍$ B!BT!B7$uB!p3RQB! I.B!/u!B! $ꀮiB!$O~*>.(>"c8 !GuMv߼s |m|( q !E$!sԅB!(%QxB!ĝE(B!D]!B7$S_/B!HE]!B7$u.B!܏TԅB!pC[(C3|{(5Bq'D/}Bcva:Nj˕Ȗo^u=}Dz'׎$uW4q܆b˔آ{9x%$7nn]geXs gaF+ǐtsdV7rt_2I;OONأ1f;-寄7C;"G+z}9jS.PBܑ$Qσvb giă״13OۜyE 1uDvĹϷ٧,߹-DU NMew嵞qLôakH u焫 ޟ/;mTGl!&su}~zWjEi$/ҟ?>=*|mCm}KP< (B":yT-T߅A%F͡~_>ϻ[Ww;ڊqc?tѼD5W|UuuiпxcѼ/O`j\Leԡ=G_tԋ@?*ԡˋI?N'4SI7Gxƥ1X=qmE2;؞G[P,V6[b<'hٳ.%,ٚea᰹T/~9c7gyE6Am=)3wzWW~ 8r#(6S A)cB!܋$yATṛK|i5֚@|})Y>[@VV‡awP;̊K4%4@QȖ(('.$YyIꞩ ؄!mxh6drh|-lۋgF1z4 !HڷMIu[ܶ05: ۛ##Ø="}zӸ8Of佔XU/9}DV4@N8^%<X!pKxD-q}^OXA5;?spKd&aG0m5oepatn:AeiưgK?8KdʟA֔!Ka tת !:Y. TAL8vqq2umhOqYg4_85Slve@bǘq$a30xZ628Ű^D#3)A?s|[7KrW㘝IZ|&jλK?RB!XRQt͕b&$iYۖ IDATdŔmzws>}惏j>דaqw>pdd ŋʽ&2#|4Q3ac1ƪ?.\ 5\nOy{޽Pl5ӯ[Yxޟu5ݬY8\ǖ1qս<ݬ9љGY8t*C .*vy>iG'Wg _}Ӌz1S6ݸ/PBq璿/hS(œ=sbfNdž=CU˂*WMmަ_H[W}ii.GVET籏15xMɹl6?o>2x0V#W(eƕa\!|(9|' ${ӵI3Ɠr7ތt~˞аDEDPZ ~Ng bNh6JDE{{;[wY93`P$""v:ttO{OmftX _.&*4.Bݕ!/7)24݂LacWbpt&k;Q=)c/qf+ dY,AzfRNf'ByB+VF$^fpF~W^peS6<B{?*,EAk3g#/$WQ-A~x٬c'E8Yq'ng#$B">X6K۵kX%<3AM)/wUU,Vi*~ŪgجŦTf6<2zi髢^JC (fiQK|Z9铉Y|Za#m۷0򞝻|2u~jڍ`U vK 93m~ҋUN~r3鲥 >ű hֲտ=^QcQ8!(ΚITn:i=7ʳZ;{6]Bp L)Ti30RtrފfNOp5Ӫ.e4EwiOb]3uMOЌLݩ{'^aƾ㘥vcΙVQnZ+S_`)y:-l[BB!($Q n:B!Cun B!B$T!B7u݅чB!pI'u!B!ܐ$B!B!R4= !BQ$QtM B!$Q~ZS8vAYI Q!p?mڷ+͞#_w^k FQ\h!($Q .B!܌$sԅB!3 !B$QB! dB!p?RQB! IE !B#u!B!ܐ$& ߅mM(B܉$Q'kKa."cc8ZՍ92{9/J;ZʧO'n'Wq؛!s#GCe >[9z< 6ߖW3%-%My38b?[Ϥǟ|d|$(xU><ɐbxƟ?Oٞ0l>47C(f3I>O[e~'JK4B"K*QQR~z 1Ynei}-/VVQXmlY5 geϺȞda᰹T/Ξ$MgY^mFPd[vOeݤ^gZj>ʏuC6SI7GxPUUUzۊFev=1©G3wѠXT/J۔G}<80`R:4%|rq4βyǜ7WF_#<ҁDݫTe*W(E_1|)R{f]V~xP:B!D%z%j !R V¢u?UhK^\6FFd{Q38;ّo#ũx2#ŲE}f`hh/7Ptd^<4ޠagHڷMIu[-8z`=_p*A%,9׌'qjZV #qZEqTkB+9y'vp8:zJ>zaV\RV`^k 'AT4 Mds]ך,z9b˔syrq429t_a´ռuѹ[.$jP=7ٳ#^ /lw?Xy6wgB9d]!Gs1t #69Ճb SCx)x:>m*^~!>G_MuݩXB!DQ%zA1ϳg"2aNHgi ^){X<>@TDժ0tֽPz/.fDTsR2J GW0w}(jTK }~N:D9B.X6 CW͙돿?%ӘM297JqD;ɯKqODFUlUiD'XX)Q &g;gjYPT%[|$V 2G]!Iu4^ m3ۙԟMc:|7,m=@pWS jl۲ 6aގRY4QJYBx.N༮'ѓѩjt #ة,?xW;veӅ}.KK.vrzco3eڗzEiF֢9I: /W!k5JaOf` +EtPD"v7I6]LR΃kgq8ZРw cF*WM`ұƴjj%8ARGy|8kaAlJ8L48ӮU|$SBqD35a`^مnfo9l܆G{\ 3?Ofo7:UzDP%_~A{߽"FߵDȳͨs`LAA쇗͊o@>W=e~c*3|t'ZZ<+QXLdbpn2uR)7Tby5z}ټX#*8~H݊ {hLbҳU̫gqPL1meB+u7gQO u}5Tj֌ZLV@AqaɈ<N*#487ͤB!L7W2K۵kX%<3AM)/wUU,Vi*~ŪgجŦTf6<2zi髢^JC (fiQK|vݙS'1~~Fڶoa=;weԍz*֫Fc0(;21c:3Xt}!ϱ[f-[ø8cBjDUc&qxq<۫gS:\N(9nM匞i19#Ew)筨i 'X32\KStft)n5Stԝw,f;Yj7>LWS_`)y<+eB!#Ht!B!9I)<B!-!B!ܐTSJB!w.B!D]!B7$S_MyB!B&I]!!BqIԁT}.]P}Eǂ!qB!܏$@ yםQ(B!"IC !B7#:u!B;B!pC !Bd 2E!B !BᆤTԅB!B!nHuq erh|bo&qB!D501vrW-o-$LzvUkܗ1+mf 6OLYmj6{i F8w12E7{/Ysڍv;{( {$vo FZMd`Ǩi_aä]v'oKè1&Nd\ 36uZcaI!3K/r8AʾŌz1Qv;th'/f&qQ祝,=B/4Q!($Qσvb giăW603kTӫ 1uRɳ ?]8CLI8x²oF`{#KXC3sp~V^1g~[o }fxa>9YJI<"snr7LO΃Lg޽i/b^ƨҸhfuG\:֪zs+tVWby+:/i7bń2ÖVVQXmlY5 geϺhٽŢzQަ<@ƁY w/ߝ+7ҡQDdy0SI7Gx#*bQ`{b&R ֒8ILG`CjvI͡dP*UJW `ʄ%84J#<%)G2! JN}fcM4uBة@[>U#v8g͠,,7ʷRvbO޺4R3igeU׆ v`etXDi_fu& b/Ѧ?t]qotVwSތ{wb3s/3M6/7G@M㯯r2O1 ;uRp)S#;u;5̗5 ܜ .&f,]vo>bܑPϱ~dWoN>.D O/|i<`"#}VQÓ39(O7Tq#4*hJg5</viYxtG!A$_yS^z4OZ}mϡEkyһʉĵJ˲y~r?{?E+w6mw%kЈ;/fl?fIWoqqnKv٬ZKz~"]9~tֈ& &*7S|2a("g - n zI7V&u˹aGs97bPF%Ϧr,WnLc/B!ă{޺^imk}9W#1cL$υU}O?gKS_4M)͞/%|ͪl)n{L ̉>JcYq*8Z*>Sݩ;Q\}|e"3oT5M]T+{vಸ٩WNc[#4t{&geܤY$ar7R3d懕Ә]zcNuWf^ELg'K5 G ڐo>Xʏh]4Z UL9p1|X'N_wgiھ%gҩ' vB٨鬎MAgms/D07ݜB!C΋nǮPU 6AKv'^A5l)ٵ'ܪWt?|jqs%N2+G^m^33\_^;` np6~C |l"ِӞ%Xv8=,_~Yt(Zo%S0*P*u"fm! R4A*sU-XL1u+>&’4kɻ\TJHLƔ/ާ#&v/ui$3|Z[)#̊,D@`peꩴ)'̛הP?xux3T(BFRF\xM|G=дGn۲MqvEL!ͬ/W+mYȍ|6ݹ" ;ap t:h떭<3>џӡsxB IDATcB՚U֪uvt]<ѶM+5WӴ|.xʉQvѮ.s˚Um ,M:L9&flM5m٦v]حv4^%P?^(z< ?]-5ZVwE/^SB!':PB!3$QB!⯒IB!p@_Q/j.%u!B`.B!D]!BC_j/|u!B!$]U.!BqIԁow}[mn|IQ!p<zDk{kWGם Q.4B<$Q4.B!$I/&,oQ/km Q#L m%<G#,bş{t+gvfDi %cSE- z% ڽ47m XlvqAZhMLekqLĬy<8X{N}ddB$Pcx]`abhٜn)lMƴ2b.濻ô~kGN$l+?@p*ߔg8zt?˟/ڧGu&7ThGD>cG;=ymOm~b㜈YO3~ s}U/}WhHBbҵ%ϧ'C1y :Sv$ި!Yy2;6fFw8o5^SzGt'3lpV0J*',;9;X5Oe_hd_wˑqأ12'V1!Eu KRY_}M[Ȉ[K~&ؾ{_w&T) #> ѯm=Q10{Odp/B!?$0C&uju_w|Iri⃓o<,_͏ШkGm'!MEm- :ShJ0jim~@{Z>PIp]eonnA] 7Ɠz7wL­^mJ Qh=͎ noi׉<{wFMxeBYp!2ԪLN>]:/!B4J7_M|{|ANơ5̎C4r +g6oƈFw#QI#%2fV^I>7tpsws^qr#%5<-0KGA B! R쪭Ehh7~MZQr6H*l`& 2Rɶ忯"cȮ,(!Ɲ"))=}_]3\q>~40>+KyƠ+xxRҷ7#d`*NAzNZ ;Tnu~8gTpu+3]nc]|S 7NuFyЯ&$CM uGlv?mIHPC.ΤZ8^}m}l|' *;v f7܌PiVFU< p8 debǚwɛ+Y8|_5[!5)Q,B#_b|Zu7{JU\]Q6okFTt7a0yPirYCuF>仅"aUOq 1+'8[Ms^ T;w"_$]oF\=īdi,ү]6Ē^ >:V,'c(Avy? JH$Y(wgqb8z~`bªIthġhp.GF J޳+Ϧr,WnL*dz\xZ.`u)yH !OurhKsj-j{J:KAxWQP+Q1֭sY=3{ײthnҬgk~9VRNiHxu1b':t+YX3/rr"&ϳѥZk-X{%71w@ۡ 惥f=E3`Z-bi+'0DgޔdjVR"eq)8%}׀9s.p<,)okL8և]*b㨥sd D|KѬjaSw8bN^E29}KζS-O\ >QYj$i^``}otr}͔ÉVnfj2?B$@ӀwXt;vՆh~asK$%ƕ,+We |Za~sU-XL1u+>&’4kɻ\TJHLƔ/ާ#&v/@1c-[*ܲ3zOZɩ[9c6#URNcX/۝T/od^T?w_/IGvs:Ĝgo= o!b߿m !1e>---at5RXMlfd髷$7lMzweD`-h:`*gr=o9;-Cs%I/&,o?B!DѓD@9w%D&4oз\v0aޘ<ބ'h9{nô~kGN$l+?@6%ĤkK"=OOc@'8tu&IQCdvm3Vqj|#supxOĉ|>4Q^ /z 3KʸS]Bw?y)\I6Ro 6?B:7Yy>di!.5D[8rIba@8ޠ}\H^ױ&,;9;X5OeߵGq (Ge^fF!D*ꚍ&j ٲcn㕗==/O%wظk'o*ym2b(qSBߑx?`̘'B* ksXA'G|(>) PJT 8KzV_r)GiOc)B<$Q/~*|qQ^+*^ kS 'ykkH ~fHGh5#붓R۶F_| Yv=$(ƓEL­^mJ vg fP>Z>ITRw75|:(e{~Wis\=y_ʔ^-hذ5^)BE/>>: 8}7'@Mf{q}E{˽5㱗 gzPBlL29׷gV"usj2^k\RP !x(Fzb '|k2ظ|89m(s=Q58QVYHע}3x)mj}|fmm2oer%ئ =>f t'fGڡv9区ۧ1"E]@&eK9ډ/ug=%oheU׆lRP3.rG"i_xNMOg֒]x%9ˮE8d27ֹ99DWZ"w%!7Q# ;1A\:!.$&Jzm*PljY@:/멭5ǽΑ;=>6nY琞nNyn#.^nJf.OhQEb$B!:XrLw~|fv5+b 2R俯"cȮ,(!Ɲ"))=}_]yD~5%tyX6;Ƕ$$!gvd-}}q-Эodc\\11aGǎcXw3XMjTNb $SIB}9Z.pFe&P^dB'𭡺^ТGm2}5(:ށA8#9k6~?r*x)((Sȹ, ݞəkY:$%}׀9s.p<,)VRNokL8և]*&Z*>JnTKćYifæ NHW,mb$z̛4-wQ&!zER,gFc$%eM'9n33F/T?|6Q)~˗д{wtM+|t-[iܤq+j&tsrcaw"w,=U?GД~ßw8![lm{ BmKmKGe\,-X¦p`6 mv ܐ=}eSnn?Kyk1F*8YČvFICNIT iS˚b@S>V qAMfۨ`-X'zweD`-h:`*gq̺3;f3]n:aBc)B<$Q/P]c6 3e=}#կbӬ7ѷ5M5Fwg6q8R4@WlސlwuIrRPN#׷OLba@\>g8q(*MR IDATԀ:SLYaqč)'1ϧ'C1(svMXԜq,/Ut2CPgnOd>d8+Of1!Au k6.s" 7lfƏໍW^ZF|ֵm f|ka3S+Š/D̰-w7bLaCy$r!{.PyQu,< gi8|9o[h6cgAfLycR }G.=/)s( `rĿq@rQ .4'>,b#pۏ:>4iӂ+v,j*'Zi8A^f'BDz7qNMx0ftw59s,}Jl#xTF66ErH"YqtXF;ܨ\-cB!$11֏V;4ދc8~%nnp.G Xob:-Il?UQ5hzTΓL^ʔ^-hذ5^)PI\Ӭ^_Yw . GӲs>*؛Nx?GnnAk͏ШkGm'!MEm- :ST!19jdv7ח^_\LH= .;TZ5bcfxR6BXdz?E#=15Fd-^iIyβk<r*YjnsckCx5%r\z*=B R9cĥ#OgTwXۦ}>o sBڊ[sl)GX;Ec'ݳU]KA͸?}[MáLZu& b/MQ/U0rƑ;=>6nY琞nNyF\HIFǙmcOMw2avj#3 !xIEXrLw~|۷tH+x&{}Vv,RtS}SƇnpPQ(˕L w;ӹNRvY1wz R nN[3]nc]|S 7NuFyP:_M zI<49֏ʂm)9ك'Յ;c~a00bc_<ڱe]Q6okFTt7a0yPirYwc1W;~&5WFAlv[D$A]aG`(Avy? JH$Y(BqͿhŭQLxa Jao;-w}.EC#1ɲP~pz*>~xtnaC9R2XȦBvqR9Wrj2?> idYH9|]+(R\}|e"3o4-wQ&!zER,ggaq%}׀6l6v͎nY_;[⨸WNc[#4t{&gePo5GZse޽2ꌎʜ̸}e:6՞IҶ9̽wy ?KJ[a|_` !(Iԁ+NBޘDPwtՆhh:hڵZ- >!VŨ{U}X~sԟFT&0 ȝΞzcҠz ByaU6#W2fdў%Xv8=wnڲ!Au  b0b,+fpJ6Jd`*U$rUD"B Y"L!qF=1sUn{f8;/F~/6%$2?:N6G Zߣcp%*12W|LAh0{P닏.f^x0`%p5%T*/^]:%%k«R'33;rϔBӽM7%9Cp9 g UObt1)h1 ɞm6FbV̪Au6).n⢢ͺ⡸NѠF{UR"R/_B=ѽG4ѹ۶lq_b=ɵ! rβz@>IylH=uVџӡsxBcB՚U֪uvt]<ѶM+5WN\Q(ؓ>QvѮ.s˚Um ,M:L9&flM5m٦v]حv4^%P?^(z)B!DѐB!p@RQt) !B#u!B!$B!B8 [B!8IUB!7Dv׷ϋıhHB#:ЭGDvu|y/BBC!ăHu@1B!ܒ# !B#3 !B$QB!dB!p}KglgV3b:,w4GAO{1s6BL˱x\1b'_ dv߾}G9r|G 7JόcTkU2K!xxHNuFEzNdl1|Kˈu T<=ͤؼ5O,{a"׊/D̰-w7bLaCy$r!{.Vf &3fŘEld}Q3c7TIԯ^_|2[57.v@QE.;ā䜢x S>,[ٸ!sfٳcm!&2 ixCjD>cNr,qXp-CK'wf8ʄw`*Y%Plʔr~4xϵ$%UDM>_jAK's$ڄ\)=?̀NfㄧXrnh-t2wBdz?E#=15Ԕx~*Fd-^iIyβk<r*Y*:Il2oer%Ъ3x)mj}|fꄥ3#"\DZ|XVPkCy)bG/W.i5 ܜ .f,]vo>"h埢8F9yh9g(IcOXFi(ǑOyt8^g0˛2m?@ۑmbƻF^e"W,-ߠWk1B!'1NVfv{TK?Jk %T}OqZRwjcu2dYZO7kc~+GټݏQ݄A=xuOf2Plcv߉|t팸{WXj_lV%;U=Ł?*ٯo5[.Zϩ&x/ΊKZۀߓ {kӱx'JŃ:(gADaJ'TFZ~$k#U9!X9~^ tE#-n ڈe kP -ۨh;L]C,駎N5S3Ǫ]bߧQx MM[S@Maٰkvt{ϪZ'TF/c}4@qD*XGeiL]ӡ'+ors{Ld|MIij%5q.\":;u{\ٱlT-Nh;!|Ѭٻh?Lמ5T UU:k1˝LG1mR:9e7 t{Mclgٹe]&Ӛŕ_;|hw3?,~@vls?s[*mI,c޽ٻWDyr!_GO؅B<|$Qr-*1坄1 U:aKo&v=w] oQ<!$:-Fm5|ܫ2yGEwpS5u뭻9˫M L󏎓 `O ,;;|¹*,\D̺La)d"=cY13PڵjNTH@ԉEr,Kѩu bm¿V&J̔!:ǴVU |iY>-\&&odp@zvF`@e^|ɪfXBP(vq 4ǻhX_2ӣ vq|Ur"ѧ]93 +S qJ`ų$ޝWQ{H4"TX bAK"E j]jֺRnG@ ["& ;!۝s~$`B@܄&w3ܐ|gM߹OIL~/Ler.kӺenQjĉ %a CA4vRP8(m(F܈oq%a7!u|Lb(b]7I Ź Bm`CnZlٲyT9~DK.wΘ6ӻ̼|ڒF3(ae{q#ۢӧMʫ̩HND>}kz^]c]8jqt8JZ%=z]7 8c_^qހW4u!Φ j6b`-*487xx~(޳6 (7Ѡ8H٣ZkMcs'[qZU_*jHޣ{YWm3Äu FXI:OCCh Ua6d %"""""1H/uD| """" %Y}̩'Uuxh("""G:Kru&}lQ F=""""cuEDDD$hyFD]DDDD$HQE]DDDD$*""""{TQA1]Ent"kz*""""L'Z[[mssΤEFW&>&\1̌}_nÛ5o1! 3 _Zۉz3\߻Íu 渟1H"(l}=O\Mq,_Ug;90df47󰝱5~un,G[q#rɴ 3#z9VKxrNs?>ËׂHR^(#7gv7Nweڒ`<5 8ݲO&JqHȦȧ6Dxc͔r#7,_:'Neyi@۞WsoF ~[Xi7{-Wj@)KYJ/_̤;x8+}j,piG,].>'[*!Zq~`%챟Ѯs:\qt4<2tR}9;~Ĉ`i1?H?<,\<ѿy:JkADD(Qض!̉o7f'p7]?eģ9w ӘL|KNEM=8#5Gf?r-nH8)3#]f<{?&6&]9lBdѼ,'7# Q/#=pƽ'@?qօ~uq]p|*弦 ݶlPIJYff5">B_F}W#:I,/,z:lscܚc9iR%Q~< iM DԳ j@JJڝ^#:LzE$Z]ùZҬA2陜oY7[KSY7)-20)7nB4LTlJ/oAcSvCiE[[\, 4ϏC᪏A:zCܡ[O ix[9Y^e,n&{RY]2HqRqM8yyD+84yeNcW۱ uRP-_yYh}LkЊFc#T lEkNάDD䰤!<7liB;FԼussk*M.Lt;$_n7dCv M1sSx,z$锶׹EvuMAFBwqWf7)}OfuiCRr{$6o)'ܐ:ȫMSҗ";B:Si93՚7fX LW_(eHݧB^%(߽ţ}M[sh) 8{䳼x {.^^u(q$h%KbrUTK3p7\|MW_ePƴoyb&W %v+B139k?ǜ8j wAޢ{8RRp{\ G@B풖5kS^b։[%߱G'\Դt{2n(/xas֞zuDR,߽̓7"kK\R Ͽ&/ g$MV IDATO|=%T"Qv6_oHDz]z K~L^nL>ԥvHHN%55ؓA0nBJcr>whP|C&{m3*ϩ׆_]#?;QG[6K%c௟_GgѿL-""rPX[fضd"w0s)U㕞Wy1yoJ?9=/᳼L}~=,s|}L` |,@F:~_z D7.bڸH>- €—2eļ2cHFϻy<3O_ZKn)b36Т$Ÿ yǾZ VqdLX?(O.;9 1ɉдͼLt5/VV/fEiqѴ8%'\q9nZOǞN2z cv(_PDDDDbu`>ɓ}̺Hq<4GأD%9:krq燀>6Ш qԅEJuK-X[:ZG]DDDDbgAJEDDDDbZ_P니UEDDDDb*ꨢ.""""GuT uUEDDDS g֭ƘmssΤEFW&cl<ÈZќ3?Ê@V/?8޻̌d^7mwnY陫)볃-F8YdfKK*>'cN. qͣol2]Xealя:עF>?u%b:J+eWy!ٽ][:p wc{LIc؆~/UCߧt^8{~l 3 h}M騟챟Ѯs:@)KYJ/_̤;x8+?*wq'Ҁ=1O#TajS|g}|җJY`يʶJ6O8Ԃ=9Yb>;z""r8RNumCsoʹO2 n~,K w7(\㺦!F+n wY9*-?"M730Zj47ﻪA!$Nbyazʆ>=u]u ǧyz_kymz:8BIW;+3P2=Ԯ8ggX?h MRH?&K_ȶk'!)B,K8)Lziݪ9말T/Mqdf4Nés1J+$Ԓf IN~n&}e4w} \GJ nK^Z^N--iw fΚ1g$37/uqŬ~q{tK [/._tSqIHI~fpΕ5d xy1%""RuWy\0Wdo'OsAf~  zv.端 :5!n?;Gb`'"!9T7&cO_¸ WEq,?f{uL^.,m) *ڠDD䰤; _=;沬tBluw |ł%%0@J1l </"vqoͻg,H~8G)~.U39J$Y <Ӻ*`&ʶ2yZ\|$ 1|y`qcK{xKh4~&l{8.pDl䓗rIh9ȾAMٺTDDOJԩla+/~ٱ? {a42㈫Z$JJb7.Ԕz+z@;;GR~Uo8y❫yRCO?ǃ2ɒ~*1>BƬ]qtR2j*FgQ/#.  㡪H-D"t=W82eFNIDDDDJԁjOQZ{gI_QjUI]DDDR?UEDDDDbu/.DDDDDvD=kv9uj.R QDD$(Q~}INڄ\z[cES'ORG]hH]D0QD.""""G3 %"""""1H/EDDDDb*"""""1HuTQأH D]n9|^պcbxΙ wd*>[nB 23%P25~udf4'9lms}=O\Mq,_){7ɘ2Kpy\,۾#0%9;/Inj 23s3\U\bR4VV\ﮊׂHR^(#7gv7NweڒɅew[;o l|lC2GDжU<0)z*9L8DS0n 챟Ѯs:@)KYJ/_̤;x8+88!: g_-iW1Ob5/Da"ΟM^waqao͟߇oz+V٨l]7g59,)Qض!̉o7f'p7]? 64>3g}Y游)߽gd樴JMr9]iلzH#:I,/K¼yeCWs㺮뺄S{0(sڎoL 4*:gYݒMvxl q|t^/L ۖ~f]h<6,\H}'V@.پp1=Hݦ!<7liB?F9* z6uP'ys6I#w\QD}b]ܕi. l-nJӫa8Z{O٤qj)Z1;o\o@z`(ٺyeW/ ="""u! +k)^5G^yV\3Ո$~8v_ŀcuKZ@ξQ^άa_cfpXS¶>krwTzV#*]wղ8bVMe=h{9Rt^2:-'BhA!wE%""%Kwo 4aJ)p M915MҰI&/[I3)^~w_ DB$$JZdtɠK7q!(BGŒw/IحưfЫ7n0boNvp<76׶IĈ{p[?Ӎ""rXRNU` ^y%%c̎` &5~:ߣлUX{S%vw|w{q!cV]xCO?ǃ2ɒ~*1BqܝҕQVKwׄ/wBұss㡞H-D"t=WKjǁjVQN)""""^WCDDDD:`UR9ԂOuD]DDDD$ """" %@5=](QfϚ]cN<ǬCCq=Jԁ__S6!}VuɓC.Q""R)QzEDDD$ԂD:""""k;>GVnGADD(QPus_呛3g2wm. 翹3nt>_ ׿OB[#2?) i@۞W0O]øi?3 ~~Fs,e+Y|1nhL༪l e(~'pmݠgX\XAZlg׆M䳯Ŵ?p'l)ZVN`ɸu:K~EApﹻHD *cۆ0'xiSdptXl'/2ucp|՚*7yt}fU&p {s',VO 9\}{.O%t@ԣm\x d4J%a+_{N[_m *1>>qFchB1\:B}֗]+[Ȓ\pr32۳ lT.""%%qhuAvjI$grZdol-M+i妋QTݚV:{0(sڎoL 4*:gYݒMvxl3l[1uMzoS8dI]:Ҩx]@?~ W}v"""1&!<7liagW.lt7_}n+UjW!]uW?gS4rɥ/Ew,f]oyl<՗h$qyr5Rh=~|AFL>&g^r4FKX/K_DDD=&@[ {oȥmsE֎ C^26қz~%Q.r&̺h O9Gb`'"!9T7&cO_¸ ϊ4aۗs͠W9n+xjQm!_9^zpm7QΚ w]HKOaԏSb?QV-ȝ7L%c\qJ#B; v9qPzI6< <7;5Xo >&Wz|#gڌc>6cLeŇL$!_GM>A'U]RGϢ1Gyl{t]k)B/f|Z1m$ԖuJDDle+SN^O>¸$ŀ#o`;wK-1sh74 SƲqjKDFuӹcä~g,~Tv;bԳ r&Ý+796'T<f/t˞[pY0&>0boNv>\*~q姍遄˘>:&̻3Nܸ< Im8g1SH=o×u*r[K,),cvO^͠8oA_яr굤oʃZPs׈%߱=:?~:|ąYu ю>tF&K*nLjcz4D튣ҕQV~_KtN^C>?HzEB {tp']xGV%@ܱ*""""ub=EDDDDD$UUEDDDDbu.DDDDDvD=kv9uj.R QDD$(Q~}INڄ\z[cES'ORG]hĮ,[ kK?f҂;W1%TduZ1kBIDATb`a Ɩ.m|U:p1D."""RՌ1uSZPN(-Kg1wK6`v8GƹD|_@`JMڛ ڦ4Mӹ@wv=?ʤ+zZ5vJP e  o;˹7-Nf8+E'.J]'PIqB$q#u#Ǖ݄$M1MvqS'-69 ܐmh0Ïw%SǍi*""""RzCGpm,Fa ㉱}4B'ѭ!.> Ld5\{WjMrrK'"""" S|j^ٕ#Bk˾o X-+gȱmϏ=72Ϡg]y~Cc1|/n63j9]*>=CL62l՗Co-4hTV1V: غul2+9z.Du7#ewYݸVg4|lrNjDiҙ+Z3g"Up~uH'&`|MG6ky͎"5;[K5l!}x&<:[B 2d%dYĆcog;N%oуbcx:+Qr[_Gp/OY^4-E1. b֮foI UMM%qhJy%wgSd^ڂ=&֛ΨQVQ?[5{fukGHu:/%""""1~~8W~@zzJP."""RSRX`;'GT1 ZSJEDDDb1g~[jz:Bzz}RRR9rl۲fvh(Q5=:딓O)Z{yEDDD:^I Ì(,""""eICX2uclڊ.Rf}cB]vi}V1_Q W;""""֗*P(""""a_.bj}R (""""a_.{R 6bnk9""""RS*GO/""""RʴK-1cZEDDDd*/zbj-+kAYz8Z $Z7`=SrX߆5.!놭!;z+C9e[cgXqå9iXX߂_gn$6[>~v޶Oz߳(...4lc Z9k AY?1R<+fޢ?w""""" 7͎kbAkL`uL:Kb |;r0# 'dž|l(bm( JOb6q||Ƿ~8QESO꼍1ĦyK>^o+ vS`pu|;>`BNXlKsP`KsY/MwTQ!I;E$gS-0jZomJ08&ń" d\EܐhԳEa#lBn([v\8a'k=|[lq LS{('!s2a7bLYxք-ZkLijlQT6ieϟ]e"Omg[]N26[cmȖXum؍h \ |kGFM!׷a8zn1&WUړn<EZ滾-6.%DmZn|k\7݈qc 5qdžl`RlləO\.u;m!Y;lqq%:!k6wc ^k¾5w,n |Qu]Z%֚'q!:o96-r}[1ELQ 5c65gMUԋ ZS]yMqټ̍wrW\SKʑlQN|n\$ Ž A}'ϋ"APdp 6 \(dMqb9I]bBhNԸ[B`PȏgPFxL` &[[ZSRnll4Fr-0wo&=$$mbi;ܵ%ߵNkLĚPl`uDn 9qC! )v#vJQ."""" [[wCה&X/0!?Θ  5_ZY Anm/OoOPhٌ%aȺyq]uZY PqCa;%d}Fl/b6g'?d1;ZEJz`B~ua Ni1TbiblƲV6l{>Q/קPk#q%1^¸oPu uǍXUE]DDDD~&d zҍ LiwC8?ZXgu J[ۤ8 V˷=7u CxQ׉KI2օ" Sb:ab;M3q'LHu9h[acx5cc,IPdM2gZkBѾmMbu D}@ٕE2$n_e&) Nq :DCu$?'l1uƅ|銈1K/ l"q>E6(6p1Wd1$A`|S86?Uj/;9Orv8ypZ7YY-J8)87 i!7놊}Ǎ$:r'畄݈* s0Ǻ8=Y9ycnZcn5J{ңxZز$=!l5&( hk`R"ɏm=:YM_=Tm/p(Z_v]Tn ?$C>CBإ" \8N(Hqq#ƅ/pܸ8;j{%qz6.701 A-qgۻݶ(3CQW EMP ~>e o.$@s8s'%9@J Hk/#};Ft}By7U&$[yi_00PNB$ u`fZI!:8b郰i=a9Ei=/fޭyOǏ?;Mҭ+0_IiVB1YL 0 ii6o#Jq(=E2tSyU~eqI[.}!֯v)@VB6Ra6,d6Kl" B߬HcK<V[e\&%i>>]vtHHR]ZG$T pwzݽފ~~t몋tHҍ.]K]Kn璴-St頑.#ԥtl.L^_>%I:{rR]:~K uZK;.i7ڥu:Υ[]:JK .pUMKG qB{pρ~p1|'a\aIENDB`qdirstat-1.4/screenshots/QDirStat-cleanup-config.png000066400000000000000000002545671311502036700226630ustar00rootroot00000000000000PNG  IHDR|-=sBIT|d pHYs+ IDATxwx93ɦ@ )ұaCE"v^;({`CPQW^ MPmf$ v3sLI9 B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!F}]jM!P*Te JB!$`(T!b ݶ^Z!סۄaC}> &ӊ0ڧ B!5-cY0X/!Blc0}!ڎc\0;[b <7`ϸ;^rl+LhmCꞥd|.T;կ.q-MTJ[P㔲\;bUm\(hmO~і-8RZYJ}J!bwFWRq8s0ZY"ۨ8Om|c xxe"LLp} JJl0E5ƚ&Ge5X\:YJ[)rv#]ETY>lRgi,=vҠ6hGy+Bq\<<-Gte^D[ D= r1klgl2b#q uZkxTŴTw?n}G?*Z#kXJJ|(QZkcbv4lxo׶\3gllWZRB!v2~xj5e^4і=Gٖ]:4z81~vSJN*/UkTg+mYw+,T}>\ׯ-~Q16~c6RB!v13նXbtDk\7- 8&jYF=@y_y֖-c+mW~OOi2IX*av&q:ٍFDB! χ^y5,PUqDܨh_T2r訫 kp 2FW|\jaLjҁl+QJWg",8666=m1(R v_<x52B!AmuԴםϔc]Va4 ~)Frm ,i3./g/wO ?EW4U`Kԋ9J2QJJkm,c+IJP&vvMk3c{Z=fC([U!kRtx+c>IaOʶS`yZiA{J)G;hy6ZYJ=GiWZiKa<|(/R*18JYڄ_-Xn4mwF1z 9x) } h¢bm݊PJzK+1d_%KۣB!f{|׉8KYV:=ܝIg\HLiu@)RRS923NJr~^H!D-1w\=(L|_We[f O>˖-sN< F~qcU9晧uV*ۛ`)R߯CСCa: FVuސM` jmG(%7 jYfĉ,YVo߾t:ꨊe>S^}5,"1!-[rqI'U,ި8Ӧf~?M4sᤓN{[nw^ގ?O vyL`" ."Ygə={؇ޟH6xs^j=Q~ j%U] y|c̜1N;y};T95V |qh:|8p yGä`ǰv!tHo+,*nj=,Ph$R#XR\¢B}=F ΄Թ C<̏ӦU,'A&Ͽ8]s/T,רQ#y]վ8̚5zs{>1opP\RR\Ll,]ږX<0x03ǟpǝ~gۓaGy@˖-j8eO LzF_zzqxݺ^Ue~~I"pE |s%lKQiϯx4hЀ^⣩F}ڍs9b-2uyGnnGvL(Xn<,87JgP'1QnJ0_)ܔ-܂FqKll,PBIt:z<]3OgoNte˘7o}^Laa;wK.@sJ'zٳg3{l9y7Yho&K.CkMǎIMM%++(9묳/~뮻(ؔO4KNvi̤?ɓO-ki߾úuIoؐsϡK(..aܹSSS+ y9s&uexgxxC~||$^bM̙xl3z`dd' Ҭ!\3ڷottΕg̜رcYz pFB!.s1w~;Laڵ4o֌;=8+EmU5!ȣ)))+[WUvNNNEl9qͥ~Z]nڴi=C.I3 $֩< @f$&&xr/[N.v".R֮^EQa!P‚M\m~w'p}1ܥ C ONC_co3q,\YGW/W`ʫ1a|iNB4%&tmW|hn:q]g̸7tg<,yQwbbcX~=Ç?F3{1/xQ9g@1(fm2WvEZ)|8N8aUK/q}QR\\ZV0yɧh$}cG2Okitͼ3a͚5U#G5`[Tcǒ<{6`P(L||" r?D88 Fy>f E^ GD"aEF"{TUky8.,^4֭0u=.`T&spՀPJ՚\r@niP:6s,onq);(gbZs}),Y4P(X5XEl }@~!ѤIJJJlݰa` 5a9˖.QڪR쨻SN$&&G1cN[l+l^F͛7n;+=Zk,YRe*msRrrr+WܶLzyuSX2?gt钊,3y̝;kͣE˖}o`.MdՕÚtT sِ]#e/k!KZPKׂy{\vi{,^ hެy%&B`sX]֤$c}̘9@HGl 3fCJJ2z1ːCO;ndffرL<A$uq^V1o^oO.}W^ò/w 5k'9%c=vS\ Q/o̓nI3>~qp5x/? Gv7g٫Wdݚ5fe*^1նjeh)k"VmVʲݰ6O1?l8c3 cUu-eKygt;5FqxqT:n#ssxh^_oU6<\y{FY6eKPPP@C6 IDATaÆCabbcXŒeHSq]^!$ ֯OLl \bڶiZѕZe_뺄B! *n.!Y f-[QWqQ2)ul\)*{]Ew?&&Mu].Z@LL, 7\iԤ)+/Y/ubY6Tyzy֫O Қh$BA~9+yzIeۄC!׭%X]Xjs{M\f-[)? uhވNSeY 7!>!'_᪫> &t:Io5%%%D"a2W4l܄x<ϣ`S>8 -[~jpV,[R/ߠ!hl˫x;d1vO6mKg68{޼K`64?}mtu#^2yeKYILL-c7*`U/=c߼EKV8O#-۶iP͝CvrNʏuU?&c Fʎ8m 8G!Ctr炜69~BTjmK*HJ.cB!āTcRr܅Bt,/?#ssX*B!UjmH5(^#c^Ku\`+_:7\Cdc X&==M]WڐZݿSqE{*Fk{9#0b4b+Ioye&wz*Zt#RvmYӦ]{_rg jמ6ݟeaeM|>->[M2Zi٭'&Z]0g} _E{8׿Z@ntk`Er 70`nBv΍ w&"1O!uWDW1i}3ǯ?O?:m9:U܌D;-SR9EMM3t8v^1kR[)FisgdB7b*gMD Pķ#w ipB?j,3?3fRq6R|(eߠ5Sw|{"^{MהSc?ˮjipQԵGc,23אScS8E}b9sFoU0/7M/kաùY> :Adw|LzMVUL߮ #G3qE|0.kr~w#E {`~6?Ms=mx93>gmYVG\՗ŸG}OLcCEӏ9krq{%|~Fp2|3uwЊZJۼ'Ovu }Sϡ]¶f3O>N*UBˇimv*Gמ >Ijs{˼jZ E ?`|\߳5>kL~Wٗd  &U˫wLbŸօ>$'gM;AGX4+n72=<regѶNՕwrΔ:$%X(+]1+ x=Vet1I4>R{zxtNn6^IyiF'wޝڎۯ;I균eʮG@'g~u_W@$[qLzl۟5'e7}7y&va' $+ >nO Y&b h P/BB=u ekLwК*R[gt,uqM ض-7yG9$BE2wrxOˏ(a`PG e]a+6Vt|. ţM,d^(^٩28>1M"3XQqX춗1Y5Qdk6bۈVU~Ҏ]GO꧑\q$'lO[߭]L&%'rmԚ[W9$n[ 8T6%uAoŽV )qځn! ~w&kJmM%4x8GUi=֑sFY?CpC4lH| )E^:I߼vb#cֳăT)u"^VgO;62/J^񰛝L4KO#?J7+]=g_ؘ.O'lgzY7iN}.d6=vR3&)[ W78q @C}t£OOҼM,z;:0M踣 t?owB6*R ׄ g ࡘ'4co?fV˖+hs5$7y> LA2sD+?R6~avJVb :7w7q|dT26ٜR%|?u;^z4լi,OOnJL\f3kRE1³˝G紾'5U]@\Es 8s촮O3ڍ^^'YPmvs2#+mIHLN# {t;x\)?UܮTޱryocXG$vo՝W.cd9&^ghX4A2:J2k~9^B8O'='6hǦƲr#%^Ձ+Φ|@NqV\r(<,n}$$&RN3];V[ =Pρ f{x _>{bnR"ycp:,zB9'9mQTn졗1j̙{*:իGݶݹ|؇䂉w}\pzP=.JSXa۪q\q}IlKHn4]Y%ײ1ݟ)C8j\r~}̵HGRڑ\: >-kTN7;5ne,lr(R1pBZ=Ra~/p+jYM``Uڸ/o73hxy,x'OJ69< _I[oPķSͪh)>|4wL̗CO~u_8N[un2-n},cCQhL}y46:BBu(%!W>d-IMXKfN7Jб/)=OBOQ9X:  Y|0 6׫ќozoCw^fƩsLεکriy<;n  NI.!bp0kz"eǒTD;?lXys;->^=N`?)N=Zs~c\J6d<wpGԟpw>$v.y:M[Mn!Nowg'b^ K(o'oMu $2?f;;Se;:< Aƚ"xHIBT~~ݕR'sГj+Ufpzs#QsϨ*JK?n17nb*>~`ӤfVI<O|ЯR]TN 晞\m=gy~I-{jǠg1rɝ |qT38~Ski7wf *f<ʧ>ga\4wv]I/[Mb5 9Ik6O%Igنee[1h<3F;2G<%z+nJ 'pƅW3=cy~qϼkIvi_G]_O) ;3B;_2;aI u甞}M;dq׿$'fEj-|p^V[7>ʜaopIv+=U>~JIC8<@ѸaGN>|74No8#sg4NMcΧg|1 \KqMk;*bbEc^'ra⧿ׄc{]ƈ{O⠷{鍩XP+CuOX+lˍXJT}|ڧ}>pa[i,ID,k)SXދGDd^D%g;@z\s6?\=([Z޻ѳ'Nr}rѴ~L~80lcvsV~8}]!hm޸ '*F\/d6yxnT`b/vV^ԋzQGQNJBZ~1qCn jm-ZIC6ZS.Ƙjv5%gBq"Wƿw BUkCjg519w_Cb%r0? 'p5/pGהa0BT!D5|4=zBQNZRKo>q函;]Z'99.tBwHHB1fjEv@~~g}.)~B! BzsǙNs:C5C,wt̖d%RJ H ODtT-tB @ze#H!D9';33 psQܹI1!/M 86x׀Z$IIIzzS+WRaoxyOt x~ߍlKeIBܩ=JJAvH;D Izxi, Z2{ tps4$:385$Nn`ɇchޏm7L+m IDAT?;J#8\@+TEyd!,,k^ ڵPb/#1Yz-0bcbY $888{[\9-tHbtm9ˮ BN*$A)G6/&#o~"vO_Gn S4Zr1qѲgQ#>un`GzTfY'?yOQGjRkb? @0tׁbzpAɔYg2k,)Yd Ll_7v(ɺxxixp;U^scbAqK9 }Vb6hm)U,5HVw.N0u@jK㶣m՝( ޵|$VcpܝHg7,2][QzƭcTy6-:F`%f|5K@baVI՛I.߫qV0LfǸ=иu~ޘ鄮*%IH2軝? {^;_Μ Q7c×tk׌.3`qXy8EԂQ)0AAJ?*OPҔD@1WQ)0w7GkRg{W:zhV+&Mh4fI_C4Wn&J| <ڊg .-M׫=Zwap,)zVGX ?G߇ۄSOzsߣcuo<#ME`< BAj&Gz4/j t 4ۢOÏֲ5?5i5Se*&#Yq7@ԎSXl6 GYyLQI8>Pl&-#1ƄqOhUMq #su:íU3kesssfH?~v,عKXfW[ǠHkq˨_(=ygUXFg`ݨά(;ӦάΩ, yWc Kneջӹ˱A᧪ c-: nǦXIII̙3͛7yf^yz葃7Dʥ$kKӭIn !㛭vq /AE{btl2J`ʢ5lXin)IӮ>lXu;oYM>UzǨd^|ݘi;‰Sjf̨e\ B"L)QD⍷1SǷF .h?e@X-m׃qXM}|:ōȒmy%{Լɔ|k-!Z ZjKj)|}}3j}I?쩜_7xa+IԢߘ 6,9q4kcez/;"Ht|&Y'YR##Dzp>>MԽ:nZ@2R~=GcXzzJ6^1'#^K_,݌q}_C'!tP 6/||^D84/TErIJҶsԣkd: $o@RǦ/{aȐ!L2̻ ӑ/}ʭc,YC4TԎk Wq6IҸ"@d ƙ( rRӫXٕlg@܈$-~5LOsZA'9yI$ 5aapx/و;D'bshli{(EW;AݨOҠׁ9݊91t1>|O;'ǽ!%1iJJ8v:~T%;:u#a"meKz9ZWen,Π3.6ߍAU0}p)3.ez9̥0+`M'ҵ8^:9:\ͮãS7VA{ڹo:>z_)U%dOc֪?gL G1:+;Z ld[4'cD*fDsP߾!g9'ր+.Dvfjq{$1X(倷|,DYJcn` ?[Ly_dYfذa9iӦa04iR/F[$r# qsڕUo|$$qz׆|4/ªۮW9 -`ïXwkѻA$~JeG O4c5%z`cMOGs} |=[CRP4v˃mx;})ھ]aD,*(Dn=ĩ9yr`) J:Dj}i3O|NG~,U)񤺗2*׶ӯrR1'oTqldP/~O=w]z¤1(!l5]wFyӱb>|Ft %l`MMc9nW Mַjy䧾}{̘1/^<TR/o-,ʶ?m^:=\CaE(\FcWbӟ8UD?1k<4N zG-lqIswp)ތ%%+'NeCAoA#dO)wMhm|h7Uf7=0Ti{ZR+v M<5fP%*%qQْ0 m}'j$d*t`) bYl-q3jl&`[tW;xVWS&NfNft77o֝{ih2:My:|MXwZZ{yiᥢޫM8SBy+bh4 i3G{+RBy\\Iqrrb̚5?o,3+?d MJxoq hO`(ۋً[9}ٛIW}߀ kYwH>^U%jxxzPݻ"F"oT^]+ "]K(:$Vc0ieIXM itVd,tlk'˶FˮIuU5Lo_j>DٳwtAQOǖxwρ%kmqfqW΃YX.ͦi0w 򔭅ܒҤY,^:=255( ICFd;4Fd.!t+WҡSjmh|KNN +1lSU}Cc[ĸqI+SS'O2;?{Urc9fQlwksaefԾ I6jjqK\{Rr.#tZv:sAx&$I"55QoufP?K[59ڠqT~||$~HK:OK:r zqz6$KzE$Zqd< 8b˧ wVԩކq+ϓU-Aӡiuhd-:Ks5% ʝ w @YG܆fұ Tj0M+&ҩ$dOGu >h$!3Iwa&tAs#P0LfǸ=иu~ޘϰO'toV /IB*ސA$<=,YGxON#]FԞ PI$,!GXa Ѽ,~$%7֟ۢOÏֲ5?5i5Se*&#Yq7ԎSXl6 GYy-7WI8>Pl&-#1ƄqGw2kl%kS2tm878cVpq Y‹`vu z;qƽ.~9@v+UaX]jiK u:AXSocFco1N̸~p'*9ʀ\[Wȯ㰚=t(%nA=0KD dJ5e{͂-5R9;n }_VE1AlXr;Q[ z$|udTʸ5ؕx. SI&˻:B=))Ou_Ęl(VFWuzlm){q|]2ݽ.yy9K# jE`蓚 O"LVxIw;d̀#{F!2<%GCed[N;C!- ʧ r%VT GQJ*ѡ9c-ݻPR±ЁT >m7wIZlm2Cb1d[g\lRڠOK'cw32sR ]\ BoW?pJM>¸Qy9H"nA 5+jԍ%[jUϬc|L,+X9gx5hJUЯY)lݯGg7(;Z ld[4'7h18~/sFA't%2r>vQ-*e?/ߘBGK{d"v˃ml;+m߮JÏA-lI$9b=o(k8N5Wu_ ~K)%_ŜDՋR]AIy?JX^{iDEjΜ9}[n/yzyJ%?AhA#d`~5&6U: fnTJgk|Ւw\;&@CNv6PC+*-`{AX^ C~]DEVƈrCՔv͘_ no֝(yy|5gNIuvݻ >s +k Bѓ`Us HH.ʩ:ILZYh5VF+9H5]U5:Y',>]+ɲŠѩ2l+9iFR]U>Rz0VJ={ѩK%4lJ7zX"YݽFgfڔ.ÒҤY,ݳLe1 Q9%~AUUPXVJ!YR 4d%Wl. ܞ,>X B#TADUG3r:֨`IB$5ɨ0ʉO=Y!  PHyzP$I̘7q6> ¿(,Ɋƚl3P`IE$Frm7_ଡImyӬ\6?n3azg<~W(̄.hcIPH<1Nes0?I$-=+k>'^K(_ip*]mߡ\V 5(ʕX.Aɵ/6NQ|y?M$v w|KHj2'2'^%5IJtNB6!t%RA"Gp94D 蝊$z71J:sjI[*$qd~RMiUl(dh_^,a5,.]Ԥ.'|saDEۓ< I*7E$C)7+1A֍̊9mQҐ,Օ7ytfŞ=2kqtưi1(?G IDATǞP a_?v^ƪ871g vY‹`vu zDQI&;/$2?֤0 )p^]Xp“2awn^偫Y s^ݑmq_hk8mӝ=V_'inޘƍ3gqD \jvlo]ڌTT4jSbJ):|Ra J3f4+[dk6irI!ؿ;ᢓ y\n$$ .rpL9l j ?s-ƴ՗_BLX"bf : XCR)DfҗvTt!IZegP@+(GtTȈl?sƧ WM HF֯qbD/-_LtD -tc\C&U~KRŐZn}ޛ̓]":M>{ξ8%0es82>lӝS,Oҕ*]DZLOi<ʍ ˻PçrdǜbF;KނŐO;uu|wfE*EUH l ~9H} L D@~Sngi KvbڷM)=KNkq N%)/Ƕ&^#P2NޭPAK__͉\KINì8x5^`23.6?$ tENr@JewݙٌhD g 1W8eץOQ|9/Ι_GLzS=){Ӏ8%f9A8U|">B뜻*bP rP%\u 'IMʁ`e)fW'GtIVtTq[<;/o5m+υbJ$䄳 Ś:oҋ}u"@dvRm3UK|(o?.kᓾO=YˮBA%dOc֪?gL G1:'B_mܟ*o7O h??PIKo7v 4h-b7y'k_q oΥ[~a Y_fvSxi9/b_O#!9Tf̟ 3ٽˠ{5˧F)w@ < OH˦d[/ X;eƆ`L `%5NNN:#{ z:ǻv_ޭ e;eK:[1f%9f+>|%׸o֫ou=)sUyqV(|W+Oj!5.cGXSIu/I w;dTүm_/ :` u~?K2/4f [{h]jz~Fo:BVJşgɆdWi:*vꞟ?X9Wf^O-MEɏánGRt{y )@2=^׉cnP/R]d q ~6q:ޓ Ҳ CeMqZZOߊxwgɆm`C/xXc~ŘP~T(`[r+{YTRؔ¿h!\8u$|YTEuTRTD `I8osK; l D\l\;%x=v[R:׃;m t6e# F B%TAR]" C hAA  EWAAL|sOAک Tj<+YO1L[YAquv] kwٵQ>troA (_gϲv*# 8#^P.R UA2/_ s"3Dsœp$ʴ"vKH?'$[qLgj1"IF*weH;+Hj@,,YG.I8WĄgH|*a1ݶT2JHˉ,<9' 8b˧ wVԩކq+ϓ,*AAxD~yo"NJ;iѦ?qGLʁL; u Q7X+=r$1S4s}D: 9E~坚nX.ΧO50E!jH1aw\Ap{'p(Y^=}Hr~wxⅭtycذD GbG|ګ2lrfR;r˔|k-!Z Z), 3%fɈ;d^ %[T@IȖf2.$^Ntƛri> W=u+TCOst ZnwǠcW t.{WDZi4J9h/m]+ɲŠѩ2l+9iFR]U>#0sdD8V5۳wtAQOǖxwN -Y+M5-bJTT4..h4wA(V+n3}eY˩[vh4xiUMI J,%iSS%Ƣ֤bVjhljjj-ɚf5$T`h\.5b B~3qy^[ͼH֬ı}X-FA(@UTAgG!%t F~xQ@>9oI?׵*GIFʿ97^4>AxD*BҙUcN7^ڵe Gr!(T4<-RF j׋6dtڷ̘`*z0ҊFqH;*`ʯo6>@k˙,=L돧Šxj!T}dd,6/]џߧ} lؾKi4mFLUW-`ꂞcp]'0 IJy|~OBChoQsCc;u_utv*>3ݻv ^TLQX6k&?,CU Ř~)atvot)~AGԤ d;ζ]ذT`Oz2[׉8=:a;ztIJO3>z*S\; e{5{jSnF?7߮qGsd<qq3ܻ㗴ػl{o Z@,ƻW_YwýG1KZ[1[T%7"B9y C,wRe\etZ0(3%:.Uth} t[vkDI& D 5T^qrq>*w% dкUq!J>eS3HhBZÉP 5rMdE^Yt&}e\=툉N wa QXyc;/o5m+~qAq k*Wq6 QA(thgNħ!$.9Ĩ m3$I{HWPRwh܅W=SĥHHç': x7.fKXN36H[N̻7# <"HĜN ?w='xمT0R^'o?/Q%2/+1?B:Zwl D*PLbc؛`GǺnk UITp>d&ư%FO׋YF$[ь-=HKbcL}h&F~i.'OA0Yq;`jALAAԤ>B> Z-q9FAA >Bڅ˴p " UP{yl P,Yn]gOtdTAE)Oo/\](_8\TAglp0FktQA;u$Ξ\]"E 'ݎ]] Aկ5 E$bD, QE%՝0toS6 ]Hǹæ3dzLN3ߝ1 f,s4>wTo/Zp!s@W %A)AjAtuiXӒ8f]}1|&Jpͦ4L&ӝe/pKn  9R"ȲƈK@sd.e좦u`4: -YG.I8WĄgHTߚ]X.uug'ɞJޡw{տ霝\:ߜ'P0LfǸ=иu~ޘմlߐ:p9q7t:Yܟ@/]Ih5_ǑQ ^J8KF^4xg. PT 5$[ʼޕFlh3(qЊodq3 gh\J˜X%|t^CS8v!y6&Rڵ=vi67d= /2vV1h!2Š'yP;|ΚIyNʧ _3V3e\vb9uHĂwv6bd"l\=<4txAȱlnrKaeVnI=6 fx$aшr6R2DrAl“hbS,ѻ27Z$#ڎOb6_\͗%qOO- bÒg 4yӄAݫ$#eC81;($\grbǓ:}חW15~g.?3!H݃5xp(R JK[kq-S$! C HHBiΙsȲ3sevw~̑% e:U }NRal zAec؈~?NZjC)e;/=Ǧ0DpgQz% a8`*?tz1eDd8M|RI .Kf `̊!AӷN>' ƯZE%1FIS? !e"7y`9;\j۽()Vjh\c՗-aZ$>"(Fx/_zbz]ͥ\ H$p-0HjmV?TXAxA®aR`7ùsGg/jiBk="/XӇshlFs(JgV_j׋ 'g42 ҽXpz%;qO|gDyvSP".+) I)3J֟kPvfd^Ŝ<䗡y:f Z IW$FLBmdN&#Y?:̸)-ԝI^Yq՛Yx{S Sެܒy(Kf([s aP>'So&eOWjL1Z֧U [Cn1~"QRaZ66jy nK%,=2dY"!&ЦYqk3k"L>$=ވ+C#!pjYc>9΢ %aL+j$5xؿEӾv [A-ߤUF}vrxTO3ԡSo¡vR +˞3oףM|Sr9|'X3eE L ТCKN]c'A}"Ɉ,#2jcslsv.bˆռ\*.!In0!͙#/m_I¦T;rXa[DZxI'S.IY,/]yMNɁ"cӞF֎Ih6U"3'(;}я=I܋ -'?ѣ}d|vTY%^ߋ}wp.lspf|+(`ݭ#hk5;wP $[Iiq/A.ݐIK'rx[}c~a9s͝9M__o7k>ث19^3*rzZ1?^͞͸Ih8ܔK[b^?s)q?5+M{Wk"@I(݋=bD iғe3#-|Uv2b~ݶjTQxuLטW҂+iԑ^ҜIyֆ5E7p)݂ ~-;laoǪ\F<N_byt%msq.%QK56)Q"9k$ir%yXߣHan߾{c'G)Gg'l(oߥI6w‘0"taY]iBA+`E6?vkHwLht KUz,CWfޞ&}\XʐET6of. ۩js ԪѰ+k`~Uup3<2jWp|b\_D$ T۱2ǡ7^^anDfSFCX1u_mi?\g.} Nפijk؜eYFv:E̸ؕh.K,GVy7l,qA HRMa.Rd2lf>k:r;ySd5&Vdl>s)  d@٠=! GLen[0 $"á@أ\:җR[@`̊!A 5 JƖ<`&p%&7ynYfVyp3 &.-x́Dr)Ȕ=UsT!~c @ŵXvgPD]E(}Uz6BhT-Y]BGI "$<^#i/Ñ$(`>Z2)9qM3[c[/T]4.˖ܰN0H|NEϜ(;&t0hHPYcc$TA>m"H*C"pb#:jP=u#wߺzDBqi-ZjVPtG'"!+W} ϛ$\/ϭd y4Yzԭ2υkeb~즋 8ٕJtT6 ~y\Vlsܺ.ݜ5K4ӌ x..È1a_AmIREL.oNp2H$T!`~ۖ#= }A&NeDQP6]1V>LM!P;բs;w0 ˄&fJᮃφAI"*:F*3gBdyhrR dyT''JTP9:G|uSQԊS*cZ@ZL5k>>ׅ|uYaPA~L%J[7h >.*||4YLSw^e91(YC!gfd0hJڂ?`Qԝakb٭tUO˩wuF<ĭ~w 4GC,=K6evI? _jc*KxpiC3G|# ƻ[) {[_aE/M*$t&6x׀)ᯓXbd -G±b  Apq{#Th ԕ*?x}߿3?t>AmD*UL{ntl/Vk|~C`궼_˚H VykXn$;ӛ?M% wzza[L>O9mح82jxȁx}=GGocq6.1eRkФTsc2JX He-jEc\ 'L؎]qvN T(^Nk՚p\Jb(WYaWveg{"AD.X23$$I¡R{FAb950%-/eꑣdIK)jfS ro֐1kzⷬ>^,o@QP&_I UU!Lcb1I=P)t_ZeƬYӥ9!%QN ];b1op3*2;wkPJKzğ` - dNoQvs`?V\%1);vzjOAeO&>掩xghL>4e*8 5clǯAm2b3 dl?OHkX80kإ&"t~^S$@e]Vٶ.Y]YX"%KI~㊏ڄxVJy),ṲC^c+SSlJ=)vڗL::zSELe5VjӦ}.%ϫ Lͣ8;?A!G LY='uet?alr8H6햛ľgY6=U͑$sJǦZQK ωlZ>[g#v{(NmlmVL?yq6r%[P\BrLi{K}%:yUAV{/0?3y-<=oS Z)ޕS_#V%E 1soM ݎMFںb_x9ُ 2X:]X/l׎Ry)ڏlo/`tlY r bOC#u<=l9PbGD$:ByL lbe͋#YF@rr' ҨVVXZ`Cޱ_r9wJ$SHo?18ghgBL{E'L$ cY=ʶ$5+DFR[QqzY7U'EM>h͝p$ e^?Yd91K`R7l~BJ~BNƧZ.d ؖ`n(D_Z\Ѣ* cЅ Kw2JuAnUqҼȠlOmVcsnnZݑe^tONZ|;nf2YO]+8mۅ.PJd7s܉ඞ}ij#Kt櫦XE0 OV;Q[HHHPxhQcᒟM5W,޳6'C2[Ol` _%ē80ǫGt>;ʓ0uv?ؗ 0%,KuKvPˬD}1M,Y Mp|j<\N&XY֓2BM2IXu<Ǫ/[r#S! 8I|-AM#MF&eHӌ61}r{ fcHI°~MH1<ɺytR {c6zɭ5cvA)Է/L\4o1_n%P;7`|ݑu\q*X*rguܴ߇iSb]Wk;TnH<^A}eKDϞ_!RߠvHe+}ReS\RmJ~*Kݹ=?{fR'sj&I7ߐ-؈H{l.iщ :+ +A[J9֫K}?z $<#4oA,UYCIfy IDATnFMiUq%(7tszQ52AzJ]dGo>T[TQo7[SGY/!+Vٲ0MϠi Φu4L>5E /)kuiM_M^}+"uͥɠ?#N !7͚i_lK4-ͤ3+S':Ngx" *LŁtOƦTglګZyuizҼfv{;E glwrô1ٞV^xIDbBnqt~#E:y߱l $sn4 ϢϝG 5ZάcK( zm.AO,=-fQ<Ȕܭ'rP6lM0͚- ׎* ٱ4mlzSGChؼ+c]V|EradQT*Fh2uJӭÌa )9*ψmK)w{8T2Q0-܇_v%MȡQy4۽$xOl)/GdɍyݎoH.I oL[uS0Gew\YuN silBeބE0jK9q?RB#!1j- {@#KXz4dҳDdq0ƭ9cz0( Ɠ7≹ _5ΏZ(؁MBowoGAk1Rk9(GN{rF2RLղR*d)$ڠY3%e3Y6ѡ4 R6UFJ2TÜg}vߓЮC%}O/߫i,R>kРQÏly$ [[T*1S /^ϳgQ899f^YVufC,g.QqGϠ}^[GKЦTF2 WW;B?PJ$Ueo_NȚ,ԙ!,*4ߚ  dIi71ĝgE|0$g2;wK,;[͹>8+.owaYq0[$kdN4ڗgoe9G 1bz=}U9EzLB@@CTÞ'tP2s=ՠ%J'|aN}5.ɘ|+j?;z{㔱_1Vʏ m~7g_.,YX!TA,G2kÖd\ WXE oYSsb%s/WчO%l͢oѳ7ӏngLS w72j Z9|?y'#o9Յsr7x7,+ŚC$#[ع.%0i7c#~<ʺ\+ԥ)yjYB wY#WÉD !']Q M:eXƠ'u+ .\YGjOwSFyzAs"JOy $OVi}W2H*Y`\&^M xȤ^y#grXziMVXeZޝ/A B /b$^㪪n\^}dW?tm{5Զ9*tQTl^t 4-xZާ.U6ũU<ĠO ;5YaW .vޗ5ɗiU+ѭW#JB8a$X8e<$cyA_<6dC!w3l%.S\,tE8rX`goeFƢh~x-;ѝLS9Rk@Vu^oo$&[{ײjA.#ebdH)[ SCBmb=^`jDK#kq?}5:Xh,Q"nGV#:x`%CGY8&5fhГ:9º5+wM iʤ'_jAKRAއ˵5 Bd]Ja\FWh~әX`c6|zGw;BT }gi%`_7`cvo Iҵ<Rj*cLY9:B =(RN{\șp8=MR$}l0.M*F - >и&@׬̕ a_Y˘՗f[h´lL',5]Q`kR{$U G5I~2g<9! 24ՁXfԜ󄴧x6斖XY8R{ >_!boeӮ nJ2&"ђ̓A8˄m{`l J1! &V%-!E]NŨ( D?A@ƪT'Fa[D&+g\H"cY‹siu" J"O=I<KsTCYs$%!~LT ipߙ<[0uTRǬ/M_Qt|}B Ivp7E@r/7en]HALvSZ%spIA%83ցpÔAJ4e_S{[b~왗lM4  dM ˀjƸwCSЫG_&fTc8ivI̼% y‡Jl@ɻxhs3Ks4׾E^W7\sjT}73mr٢MYxt٥Vyp)Xgy0ť<=7U;H\AntfIT9$ÛӱlSɐ%*gX䲇Ծ'Ffhʵ(~d._IJGs-5򼜳VƺpU gu2א^gLq9ܒ&^@}eL7WkO»x;Ǚ&g}tz̘Jn8n43 `Hݯ}䰢H9 VHe2MV˒J'ԒR4jJ#kd k@gMdDb,ddKDVv*`gPsƷ{^!'](Jط_xW1¿khШNFTAA);(}tђ*  |rD*O҅[U_Mّpq{#T,B%ޞAkywAzͣQ˥<'?W TA2$g2;wK,;ժ4J4f0lTɒ+./4ɫrRftwڬ ^N>{U )ޚFD N>fz]]\i.N3N /JU$VgZ~[$ulw{ilkpߋ6]""} ѧ?4] Ye 3-]Y7fXOBxxM:S(g4O^?j{J{V$YzgW2Sb;7ZMw)p9JS{" 1wNPqoEjHxSNԨ;쯰;n˛;-P̅@Bsnv"~hwGK  d>Ənq5QCqs勵2cX:F])Vw =T* h^7xnGZWw؝l==gv4+u}.LyuS6+Z2hYÎ2uLnK6ij+$I\WJcXG(/HO=Zfs4F;}l Um'$Mk>|?cϓ BM!g/8SDU.KA;Aqjûgѫ+.:Q1wc7[ݍKǐ%iWgz$k\T_G/ZOA˽ؔ&75r3-W19?Ze9\{q&}~1+.9(ɡRkФTsc2ĽMi<;2$#Mq(ZNM+$eXϫ%TA,R&_I UU!Lcb1I=P魅ye$OaƙG?ֺhH#[ёӄ鸿b/fXr+쳏q)${czO?C@ +D+f=s$ūLfڹ5\N~)7!PS}v|j Nuaڒl՞;"h#_EZBbT͑" n O4XFǺw IJvq!ҬZpz5&4dơ {oNDПI 1?eơB2 t*2&O O| $sJ^j+g;x-a} Vw׊eA4:.dZ5Rҋtd˳LHT86O?JǗ8 e ۢΰ>U U!d۪12ۏ:wǧ30v/qh?퇴ImM!1q3{Q~_<ر*cIȩ<(߾=J. nra"#gڠ4oͰ1 @kߒEڴOb$$rp}ͽ`;dFhpb&nǽ՚)Jҹ1TyVS͋bQaZUIEhTނ/8mٯ,TH%;ʘIG'E<筫S֊n\9V扫]tV%q01/NVz1KF~EJ*5OkdA4^Je]v^k3FYd?¿'U!48V=Pb0oX =%ng_ۍg\'͔#̪G`+Rנ4v[r/E!1)Do75qr剕Dƒpt5IM!1$CZvY_I$Ij[˗8g$*` ;;bڝ[=<(0Et63ҕ3ܯ''!G֭f3<ȵkZ'jIU;xYٻ(ʽߙ-4R i (M:Av,( H(bTTЋ"-H̼l$>^s 3<3/mXq@KdǼ4&y+vR&߆tn?N}/d*Mmq_ز.W ,6rr.׶ȏaz-Vwe>|!3nXU׫xף7*wՆH=n̸%k9[1OSӄ8ƻOr1J-+X2.[2-nɬͻqCBJP ZůBZ#BQ/ sZ,`߇Nvj2lq˻az᱊/BI߿0C&ōʵ<8q$vbE\%;VU?0;V`jiI'د37ƫ8uWYG,Y:zigh:63EsXYtݑJќAu781z~yuz ¼-6prpsy0g-l)۰&V-$4NqCw٬H{X8&$Vk*cݻ;:0qd%pl>bE++m;d3֧cuwW@w }]0g9i:RГGکS^KZ[Or[Yd_ z\cRx+Qki '0,Q>mTޏζ̨(تwsa{y}zPcKOCZxzrLd7joez]]x@ ȈtRqU;% #~Q"PꇢDeQ*YfrUd6ivYVLf-b6LբZj5Ǭ&oR ä/>,V1)[mo櫯4tXNf/K׻%/&ScD988sm#-&Bi)TtuUćkұCbo2\%yS4=A3$ͮ'F9 3jVg9l0͊éhaɪ9 ͩeY]F5[]3A1֭-pidE)`T{"!(>Խ`5T׃|6!vG׻*>JQX7"/ڱe'!(%U!B;RB!DSBLB!T*B!n4RB!D#!U!B;RB!D#!U!SKHB!厄T!BQHHB!厄T!BQHHB!厄T!BQHHB!厄T!BQHHB!厄T!BQHHB!厄T!BQHHB!厄T!BQj\ !BTUCB!HHB!zW@!"%%DҼMWFB! *!Э{m]!t !nX>>>%ZDb`Zq|{=e+wI: z>W2PQ)ʗ?sJBBcX!1(@1dctYx{qVz|;l~qsg51{D^j_FSDL |:6G:'cԠxկqt54ńI-S9}?dy8N:Wt,rq5)D%-BQVTUU1Pco/|;{fZtM&DDpH>=88śF]ҷgqqڎ=oݝ-n,t)L!eKb:G|]\.D2؝,f8j8IoGT~!&oK>_կ;^D'K'Y1yza [IAK=sp{0k/mPzZ28˭vY0"u q^\$ZӃnQH=-cgnvꉾ4 À'Y[F/<'iW8왑tFp;m92Jw8>Ӛk6`F +{.7acmFpH+>?]EeBҒ*eAҁ-l0w|$C߯k f}ydx}:=lܷ߭~鱜H,~KM<<5 Eyvc?̀u;YfIY 73z 'Gdž'fʬ ĺcYM^21-3r3?̷CWr[-й,߿ΰ卑 xڝMt!tQZ_̽iUxW',ijn)^:ӽb=|h՟ǦVO?ٌQ8GL|xp;IQ8-nT)y bh.|L? QObyQ;fR#e,]2IY{CDޒBQ&RL$۵UDt?|U-8K~˴ @ł_{x讽qB'FskuoLXC[g"fxVTBZ3$fin~ĊNU,zI=gQPݫih>ŝyԉa}ojku՛Ȩt ]OmNiu9śL) p*M~>5uL(Hk1Ɓ3ؑI[dQQ=kenLy+KY=GmJQ*E$❧"GEȧw5b۩eBQm ׳2 !iIB2CX{ (-xٟe`vsbI>9C򂅁=;Ӊ v{[q~kS;x~q&+}7c1gOL6 bɰ^ZS h)&+f{EMiϝ{a^烕;Yb:~4c £/;H9 b,?~L+:|)@p:CC%.!Λٷw]Y¹ts6x*xQ{EKdǼ4&o7;)ݮcU{L劄T!(#f/*y`nBs89w[ڠß] UL 8d&  -YDo_#^!lۋ4Lx>7W[u#Ь=JNZibZx'[}+}i{Nţ8%$QiNڧȩ`{P-!N^_Obkr2ۗB($ !?$!T!ʞB!厄T!BQHHB!厄T!BQHHB!厄T!BQTZ!B T!Bq*B! B!ܑ*B! B!ܑ*B!B\EJJJyRB$!UqCJII[%?JBq1Bܰ|||.L&~dzsqvQD!Ҕ̦:WMOdvLޚ72 BQ3fиqcCpHoOJG#  pi?xpsGvU⚪*8t#33իo#i[ mTӕ]y v;Shd+i):S"-gD#~O8LbTS *2kh8kmّU$ qIHBB<#hٳ,Y>cL:?30 ZԥVnmO>{'QdT͘-, T~__ #8)= N,O'>a;r0,:uRx>@ơ,X=nMjzǾaHq8ϬEBnLk3%` ם^/bg'XQL$'w>݋.-|LkƯȂ5hMt~~߾3.c"'fw!a9ySs۱l[8a][FIYg/>z q\ݟmxVg䞱C/ӹ\>[>4Gs^ڪ($ !nx,X;w__r-0hРbdpUdIVﶏe_uhk[9.3[^6./V;'>zaC8gOogxr m8{8{<%xl].CwIчBz^1)Oʇ&k/kCXĬn|ld=^ ۬Y.vxJoZ=ɧG>icg><؊#~l<̙'RG6rNg11gz6|z<~s8u>ӄƎcVk}|{!>~?K[ "(. B֭[yy饗p8L27xU-ǤիܸG=7 NS#XJի'`Jej' 4Nf\fWra!@#(l4dGS-ϲlG3 2c|}fןpB vpΪADGhyur2 l?/!FSRjbniusm[__[8LoXwgrH;;Nb]~Bg\1F09f ~:$:0 ~cзqb~ìx`|9x$|;/LCR~w;9] MA-+pQ1ʪP^zFs4!jNA?SqNRn`"E/ (6 B7of޼yL>p%cpWM?*yW_{X12vl=FpݻxV̝TYV+O-ۛ#yz1,bsFYs"kv }3?Lk|[BOY{/|@ըAZ=8a];bշ5SLoÃJ^op2[KH]*ZgfL7 SSiٳn~֙hNHH+FhGh{ LLxhu:Vp#ODWQ}FvEE>fU(Vn7l&⭘Zl,E8 NkYy͉n^*jS|LVߤI |AFXtc{nN+oW_3hR!V-_Fn]w5J$66??_L+4g%*ͪtVO!E4SR%몪׮c.d2P9)zS4=A3$ͮ'F9 3jVg9l0͊éhaɪ9 ͩeY]F5[]3A1֭-pOE) ؊1qBT0Y!6*FHB2ִy]|!aE>s5BR: *SB!ܑ*B!ʝrReΔB!čGƤ !J$''[&U?"ʤdX0 *֔$TwwWk!{DTL2DH-bʻ)i(4H#M ģBTEE l^QKWo(wckw{vnnz,b)BWr)!UQ.ÁðlqgDU=s d(fÑ_dq%]UBrOBjHHB]n` ]3#q((h {#4;֑mnzRz tJWU%($LBߚ {M(9GqQqhq6 P׸ ՚_N)tk\Z䲝c`Zq|iEyn<P)^#_˭5+S|,LƳ)~ C"TBױg&j/YJ*(Cǥl"532 tC4 9՛ l:_5 97GU̬8%/-rl tSAOxYrJZIÑsZϽ\qd:ϓ>4'S/\~S^XNtXM IDATq |uƣυc]?.?Sxo(5k?`L C'lGs|܀KE^N\OT!Dev-7'@4/];(q836ݩb Yn&*\[>4}N>`kM(Gң8Z>J5|6zc,,;O)6B[vERs_t #/ 6)|?+9[H=NtH=Bܕќz*|qJ(ƺLH 1!ĄS|?!ǞG_)xlC&~%An]/e[R^DGGiצ某*(@Kjo> 6O;t[%#Hla.)SUTUC=j7yUrsޓ0r gm'cZ3~F̘Axeo&zV?,|miŽX{nk9~c6%v]귉d{{I??cΈv?ؙ,1Q~ Ogamxo+ChqzIw=1{4 #^L${^ }~cvDTMNCcZr53nEn{=[Q,'\w+5ZʓILL)!DXfB`Tݏ9> ő˟tp*ur=[$¶N sGA̗O2`;oYHݷG>ǯӣt,й,YvU-D~],e $0i&5<29YFM^%Cϟf,a$s欆[^/XMO濱G0oΗOMϏѭ'ȍ;n?CnņdXԁ㰯q =.SAMܾh1͙ OO92d M<ГmW$OFwn^{yU30\M-NmfKm a|(ۡVRdx|?z{toM}0j@0Y*AhIl}>kz[P##>X|8gO3]zOqbέqr#oهl}?޼"_GJu`0N||}<œ>-7N-`I?̤ڳ~Tq!eDL@Ibۂ^`g:'d#9T)us.3 -=qҘxc'%uLř\_z݌-rnjV]^AyoOP-9=,jfr Lbl7_&gQE$MFg,=o&]6⯻fo!1 X?&JIΛOw1MW)wO P9;NJݬVOj| pCZw$*#^˂$CdƝ\ &='1f lAsfw<8uah W@[~0Yq#SseeU|qȦь;Umh; pM?u䷋;29ckCFC:f_?ܕrTln98r^ӧ=ʌO@%JLhR2**eIHB`NME)q4.^۶mdy^T݄Gp0rohųxQA=?ǛyXdL.+XrZ /mJ\T|k,;Qi8 wr2 ?lWSmT"X2m 2>:Z*^D}t qM{U WzL{3yO#1(u znπn~'P/P< ^B^G݀2Ž<<;S1jBDGW7UgB嶈c(OϻnDty>+WbZ~~=ttb닷z>m5g*NI ]imԹg׳d#迣9T qf"?x~^ĩK. yeb)\ tW(uSL~]-Fu.~z}M&1t G,;/~8LGuΛONe}: iIaذ{/ѻO "t8z?޼!8]XŌrv[Ԋ_fR?%*UɢXM6ݬ*&I̊b2k9a4T 89f桪6'bxުM1YUb&5\lݶkoAC 'čmetzWnn6Bjll~~Lk𿅖-@/*' q}G! 2L|~=.B*AW\WUM|v-;/v} )Jfדl#UGOJ5+S׳ݜz6fEwT40 d՜ԲNݮeki-Ғ*PVWL|{>쀫#An1)*֒INvMl-O$ !*^pHXŜ=}U]81i97^iA8A7\c"$ !*_ g Ǣɾ bR+1TyϖT!D"7*DEP޳y($ !*k/N ( qyk@KIHBʁHNN&.6L R"E\vk/K&12ߢbu}{ !$ !JD*Tk-ˮ#7M\*! B-#yT+w\~t !čABT 9Áq, 7?P6?zb\ZZP !UQ*n_Ri.,'7`;d$ahܘ05셛Oš!U !UQ*a\Rθ?95zé gJoXN==GAx^}qn(Bqc*(םΏKuG.~ 5 ST M] Mdgfqxxx/cVU!n r9!D^`ɶ`5OW@ sobYYXvAVQNG~r'!!V-%UQ*~꺮cHw8ura蚁(vrjjM5*BkCBTt]ϿNi(4H^m 0 TTCq7X$سps]BQHHBQ{^54ͮdο;)JEA!S780rBT!DByㆁYMaz)Mqߩ%%`hNPLT1RB!rReEoUUⅽr ߠǜpM*N5rgXeaq^Vb]J!č@f !J^l6V SpRM)T]Rs7T t]f !p*(#by;9Ih4P}ÑVZ7n^|QUrBB<^>$_c={!0tꉽFs #6e(Ÿ-BT!DNjLPhul1G8rpzN%?.P%U!T!DE!ϗw L YX,BUdB\RsNnV+nV+}sEn'B䒐*(1rɸRUP&]O B!W"!U!'W}"Ŀ BNҖ)4g'K!ˋnYץrva\pם BJrOrֽo;c>8?Hn%܇C/뉠>0N_E|FU/#Aⓐ*96GrNyHr8cJO- }C!W1f# fL`Ԡa܅;5qtS}c#4?̟Bu >k(lR`1 yNQH]$6;f8>]30xْtQ1IP$ !%ַӖdջ7EyVJAOЖ?h~kC|X}f0!,30H{Oo&.?E~],eZUdˉ,sa[M: 7Q sWQtZF9*F>@{ʟl|n/& aKi(V6L8OSB`|P2[h&Y~NHC.RU[2dj/vDtޘۀ ߊʖF`!* T!@ų֭?cS8cۆaU<ձ:Gzj;[=;.Ԋ~,gC:@MasN} >huZ8HB"( A"JSŎڰ\WW(**(M{  $!uwHBI. 9ٳ+̼{3k&1t`GC9{$O^K]ْs[D3ttf)LY<*lMXպTߔHQt SjSNP/"ǟ݌mdoF$Ci\3Ξ +Ԡf6fdlaSZꨴi>e:o^?6 Ju+|Ϛurgotf~XT 11%:ۦBXd6%'eԢbYU:QZ*"rxciӥ1_Vk21śs$R>{؝ղ/?n uK_LkSWL7%Neipرp2XO)HZ~( F'/9ݛ5C9}6vvK<8.|rCsz`071 ;9H>uw_lCå\Ix7ǎiϽcҗrf|m~-啾u )e+ H z9"囂jP=;9VӚXrVQ>+ ږq<^+x\x|@H`apDؑv +{,Sxۙ뺇k~G^Rei\3hpqc²nFlߞLJ1x<."GW&۷%1j(F])8vmmg&ЩQx[&Z1.'47[{Yps\w<~aO0N yN7u+0Ֆa&N`_xUOԣREDD䔥REDD䔦REDD䔧|REDDDPP 6GXODDDqS IDATf7M﹭_0F<}>܄p_̾9@6}3t rTD+DDpٳt 7vzMmF$nǻ75ϑrudu[5]g=˦9o Ȭ_>oZ'n䢠Z$"O䫧%7yVԌMxX{ FVVuw0{C_sϓsY z_*gr?O/0pY$wi8)qӹ0s_G/H fb#ޗ_=3jоs%XЋ9k4o yI0'3kpφꍇ~.p%koL6xS^t֦mKֺzǥO!?xey~TfcpιgvDJAA|SH;⇙ӭab".m%Wsdz8/=҉&w&-: /qwSJ1\x=@AGPvN s|-hFBޘOs<T,`0_o}^GO0%d-{[d˯y2!1/8 |[6}6{&m$5ڟ?/dLf/iE׼3IKJ!jT+.y*Rڙ}zxPoUOcCj- ϣƹǿm! ;qZ(&_Y:otmFPmj LzXJKZo9rY'p-\0#n6KI|Rvnр&Y\{ooZ;hgğ;4,OuҲcZ^)vXbI&9dm+T?4CQ>v8FZޱ9.~c],O٭mksc=-m*yqsعO1^ÈWKVr DyZ U]\O+wuTܚ۰iZR痰;f߇^ B҆ :?m:˞je, ssusStVe3{6{zv @6Gbc١p%7c4+[3ϫ/3䏙9cMB_39+m 9Q r v(U %9"rMj8[(%'eԢh֥Lܹ.Έ%^MϼsH;\CK4Z(jq#xl3H3?yy$ݫy[Â'i,2{wd^7vң;ϖ08+_c"ꆂU6~Bn0*UrH\zHCyNg*ysP7=tl'O=7 ;N!]I΄{6oo-aղ/?n uK_LkS%uU{֟E8vD5]^%C!UDV70fνX#Ι\rZ<hDPӇ=%}+Z7ڻU:ĈV;]=.\5I|;U8?d| g ٟ{wkUi8/ukI)vEXΜ֑֟&{p[ѩK r;b #㑏9V헵cs孜_:_aecyomBS4ӑZa' MIW4ԉI;T))ׯ?vrs56嬶|V'-yV:>l \V#0+bWXر/4NkG {c>u \Ad6~XzQ"۷'SR OMY<=QWC.EB\lߖĨQ=ztY78&.mM@BGP96{WGOwc]N1i.nx\7'47k~xB&8'`p'?;x+szǯljq3s |q *IIJe\7 &^Mmb{ط>_}\B+%?C\ RNI/"Rl۶0 .1?r0]9Y)KfƆOu]kWxgZ7jJ|7R70v/P1N_Č8m &нLǐ4YΩ;mkptL=W\u1Ōj-E0.UVdOr 9g3j*/s^JXa9E'gocgކ}NWr{;ȫ 6n%}9> {tUmyۊ-!IpQH94=={жg^{>5RqJ/m<0n9/8…\}gU'ܶBհ&m:_&NpI[4kGP|3~ѫzg ɅW~;d#zĝ;NYIKi T:$ٸ;گfabnf}>䬪>#hxYc>YcТK]@V %{8l LuHv9m;&ѴכMLdIFA/o ^% [rB0+y&o0ƢBs8Aelkr5h9o&r ƮDہl3_|JUxvl`ݦ2I ruQv} Jڵ4h!IpQH9hxɓ'ݜE-!"ik+[Ex;R8~7][3W bֽĴa@ו|K2.~8t" fwIԮXNlZx ˿5(B;!&,rt6oNX߾UvukC \ZND̝杫 AJ X%?.uT˵~0 Dc T@ЃZ9wLغsr8C iɜLvvD-19ss~gv>Ud1D4~iv]䋪\sq]B D}ΌpZ\7e%LgiԎuY1ua4*u@̴1_â's{nמv]֝358ULyo=qu8Wėfw)?U mȥWظ`X{]VQ^w`M 8/bkC29~]eMoB1x^25f{/}59|Hg7xsUme\yg/&QsC"LV TL*v`Yk⃹=ye̜6MgXfL*lq1VM4;d^ꄺIrǤִ"q1N{*PV5".&S15hoZ_COssIxUmcZߛRu\DᱰV9__8v'5(Ju.wKZҠiW^QN#Z-շ{ލmҌoI͝!ޯ3p%MXdnR=벎I=De.{.QZԨs7ƏtɟTn0:}^f̅x:To˭Uc]TQ]:f$_Mu{BNK'#8n4 KFsUkvŸZvhݹ : 'pz%;;o-.F^57`䃯k Q`\v9 4S.e@(,Ÿ3i]qsVH7Z|2+\Js00^ͱڔΎY!0Ox׶<^Z}/`lBrvX {|&ƎìhO]cc>hwԝ;pKgܟۿ?{;L:k . r2?n,=z^X(ۓT)Q~0;s hsWCuBN| O˯)_w*S&ony4Kw2xq]t9]uqmQ= :Cjnq[ل $txT[R*ܷ&f;cr]nIsq3Nj97y^~78쐀8~S'2 Smf"K%[V/h1 d9v&m # ja;T"T7 ̸hxa,6 ""PQC~;g>~MO|BL5*iL|r. AOE^}oLxSH9DC.O0ge3`4(T@CcԋZ[ÂB֏ST)Vʕ*Uƶmʕ+uST)VLt --xb\eĔuST)V Yj5 ]]erJDШQòn*""ԤIntFDDDDBTSM9XW!UDDDDBT :ZJDDiud e{JY7E丩Wh4WM"REDXk֮#443۶+릈g~7R:gbMԯ[8*)PHCؓ=zu3DJ-N;3ǩ5R*""%~)ό떸lߺ-E'UDDDN:%I,8DJK!UDDDN:uznoypԠ"""rqٯ3r$~=#GzI{^˻iREDJ)w>ʺ%"rcM|I0`!--'|1\REDFM,+#;Q%HN?y|9;d{e5CORѲ!gkYXe sq:%x!="%CEHd¸%Խm~_+ovu7?īZ0y4M{'{,:>}k¥i/s{t<+WbT<&o`}5lc Ճ'!~O]R/.(eh3Y}Q nYx4mmK!'dN}k:Nߖ{m]R>Ms 2wWIE, 90Ժ[]S⿯Y;q1dxk{}L_qqV~!L5%.\?U5xizeϤz_΢`X6q{&, t8JS!א+& nXVmUw] ?ԓ<Ğ2K?@`D9ءDG;/6xf_W3acs.}ҋイ|a׳vv2]fz?]aEhs6L7inI榎`[ء׬.:RԓZiL1Nᅿ-oV&&do'4'ms3)IRH[2R顰~hl%&YS;$dWn.ii*F([,:W>G&ӕwԱq>]{b}C஻ҭv6Ǐ7kFBW&%1V%D='5( ժQF/jt46UIJ"Áh;$תGE,O!8ed7؟z uij g6 8ic\VlH=hCsL>Zx%+#j¥71|wWSBErh֯A0^$WҞQc%⇈HjُRͩ+ٕg8Ndْ-d{: IDATs3k!//&1vDZU񟑼THbμ"AՐG&}ìux!uK7}z $1gf.'__Um0le.7 =+̔UC<MEpٽ|lH%;,Uxٵwc| ,͋me.4ޙ,榲qFj)e81cg;-cǎ+NKP+#"'++%7/{A4~.\qϛ1c7F:6iFӫ$[<ymBB!d~v/a=7˕w']ҠQn?.^>j]:_^'ڇ ?o..X~ʐs)vEpٳb"_يDTkzЩRq!C`篼uKg=V2#c^^;7[_K#]5W>1] n䣯Tx^ʣn&W'SqVZ jbk4&5oHxͱڔΎY!0Ox׶<^Z}/`lBrvX {|&ƎìhO]ccajݻvNsLq#O5k97=/,fT9ٙ{N@ʷ[o+E0qatB ~zG} "y'{ӣGҥҭ+`\טV^sn]l}t!5u7qqG^ٶ=|6a :վTk+Mwc]N1i.nx\7'47k~xB&8'`p'gZ.wXU|M*g<8tyǰfb#rz nLe57V_L'SXg΅L՞;@0 ;0!^;mp=>acGaV'ĮLecpWݻvGuܟۿ?{O5k97=/,fTs䑖ٙ{͂ pѾ%#"ҥҭ+`\b)4c]ߠ8&.mM@BG~۶TUh9XQ눈N!UD6m\M(5-kVaKDT*""Q0`4oJDDD!UDDDDN9 """"tREDDD$(HQH9Ŕy """"tREDDD$(HQH*""""AG!UDDDDBT : """"tREDDD$}H-c+CzREDDD$(HQH*""""AG!UDDDD """RٶT1,12cYX1-Yb """"%o=C*t>רBH DFFӏz{q zYI`*""""AG!UDDDDBT :8%"""R{Xzu-3U\ j2h!)TknKK.1`@s.I-5TRp]HHuC~Oc=nn1""""tREDDD$蔃!.YJjj*۷Ur4oODDxo,\[&L,2naUBKesiˏ~̚ŲKiޢ1ݯrضm6oZj1kpv.Hrnǎ{LKDŽv)*|},REĒomfȉOy}<eݜ.HͰikx7eV}XUlC=/"RҋKON!UDJeY=flro$,,*HT) T'8\pr%8H*""{)H\2ƀm NX9l=l | "R*ƸP!Ų@v~H5yY ަ!"oLN LV2d&brv&BDdez vR;.kZTKvCYT])ؐ<!9^"pY "R*k*곻A?K$g`yozj|+/v"""*"d0-*::6jC4=Qq\A!UDJI=Se;vv;kr7pa]f]v5z-^l]ݥEDD 1"a󏉉ٙ QrVmAji&+v"""*"Télx 4iS؃z( -QN{7znc "R*[t*;:q=;愽nzQHRq1sTQ':oK:a%"W\=QF)D4qJDJ`ӱ,h┈mIU99}H4 S9 5,P%JY<)TO>ARE$T\/¸.>&Ÿ.زx"RN)\4&UDJVܱJlTE˖dǞ  'f~C鑖;qL-/&Ĩ@90jj*"rgu1C|tVEWsǰTRPP=9ǻ@z>/T+ֱe{^.mRQJrH?{ED7c=嗜MPg0U3jw[͞"˷V|+WA%QW찆s0-L t~">_T2Z>i*H;>Iw2`rLت1X,/as0 6,Ȅ!^/v LǢOU/t/|A o obPk;T]9ԣԓ*"b )`|?aT@NN!u8 ঐ*"b\ş&QZUQuOv[WDDRP ^ "R*1-Ÿ`#9TS9:i#c̡{DXYXDDʂj)!UD1.!1.n.}z""eEA5hvq ݿ3{g"q;}̒4IM(&ZYT@UP 7}Ī,l,4M4s?&[ۤL<=qw8Thrh AXīS´o~NI%r@Yz D4 {4rd=vp*wa}Ā+zx&u8F\(IDDRh@E%9qB:/>RO[a=^x&}ƍ c̖>JDD;T"eNjѣV VOSu)cR(!}3p8wX`Ҕq\+ s5T"Vᯠ* ':[+~c7y?+DDԩC* +De}R oB[}o" ;cfWDDW!ʒ@!-|jjQ9loA[!xDDԁ!Fp.,},k%JRFnD=`L+Z{4n5ϝ*{_fC*[F,|9m6-`s 1z_#cd2Y*\EDEU!"d)9T7R7nXߟEfF46Ƭٳ|ѣzd28."佇cbs`@TvcR7a ը.u3C*T"""L%JDDDDe!C*T""""*;zTk7Q%!n+uheH3CDDDD!M """SDDDDTvR}HvUOXeRhÐJDDDDegX'"nkҵnJEsr'4m˖ -ZemѨQwy)_+C*0u͐d5}}0ԔEh~Ewzz%Nsl-] xCnce0i^_f[ZRW[qݙAD*`Dy0.<]O~9mpBUa{swٯ~d DD3o@PkLxKK : -Z3z?~k%cH%"TU~5͋`aB1 c7~7}auR*PEa R!hXQp!Jl;VlOV',U7 f鬤vƍ;{VR+?0_8UϭS^>M uhau]xnu}^v~gۺk3~t |Ċy Y]Phǹ~g}jQsWa竀TT~Gp݅鵨ŔO^Z BoݯT"a,_I-7h~8{ŧp-A._柇<\{:B "Ⱦ~?EvIDATwҹXq{bo S֯Oߌ[qkqݪwyൿovUq58ek0G :ܚw⾗+0wЎΫүT"aLDJ+.=ݹIn|*|Kq D:@as+_vC Jv)hzĠUUw`3,~uX/3.ƻ?x nm3qG?3ˆ'| 8#qY\G%U 8b?\ԆmR~ '4V!Hv4¹^5fřGi/1sX{Oo?;8#pgwY ^6#1퀓qD7\u-c?(8R1 cyhјSo6=c ]ΐz?_?t2%iwǫob=cn%_wWQlxb>s*.Gwqܪo3_B8gCY?w.;9wcisPsb;e*~s?&۫##ſװxCvF{ЎwW>[Z 1]ekW_"!޸+ȕ!Iji{U^mq5@KJ<]ӿތB+ǃݯB|"AױZzH_>uW`̘H`1W-^{~6 mB w糳x~M)q3=s@b 8P7~(l>먒6'7BN/,s>ΪtO7UOߊ{&ç$o_}*X4Uۭ}îc$19? 6|? piczEcchg)5 6&|o8ka U0phh|ο5,w;dZ8'h+jcyZdcAbrGݑ6ʥJ#>۰=1gy0t5)d` =5@xCp#>]DЄZ+]YڎѫĺB 5c1t/Aex5`\`؆q܋GJ~}N ƻK!+FhJA}wƣϮ@6Z1@jk0&@CXt'mlxץ _-8/u]6 N@w03*C*pV$v:?1s{zΨOy,Bk[ mH}$| ]Iyb b/V\ ɺ|ɚ]/fU"ʿќL (5,9u B׽WDk5㵕0v :^b1Gxw",B+ѯf|XO}[<)]mU{v#RVn9x q~ _/Sĩo_oe&653gNǩߺ_cĖ-qǣ{Lخ '"*S@͞g ]8D[ˋx_9|0iWRr:F\1.xUx%WH ^Lo7\/߃=~O 6x'տxkBAapbh rvp8RvlUo0߹ >1̩a~ &C_Է>n~lD.`Ê盾+Zn?!iU<,?QGS۹O.撫mx_[ |e"?h~PRqhf@X{_9w? 8lL%i闟=w݅^_+ٶ7Z֍yxijPHV GfciɦbA$(6>]*V.c$c }Wmtrzzf0̣  cZ5u-%(t>Y1\|P[G{{َjk1[s },*RRHV*T"a[!%`un7Ԣ^+sW>G/< >~x(S _+Y듕!hӎ pji59l; ԩSK݄aJ=NDDD4̽_o(u3!h{> V""""ٰn& HWe_IU?9 sb)gN_!MU+b/ڲgzo1_+􉈈A_Cϖ}HODDDT|u%䫲DDDD堯!͇+a+EQ2Ŀf>H%#QI2׊=O*Q_ d_5\WRlɕ DDDD=iURHk1zbxՉSB jllTF"""fr1^b|s5V k@$PHk.=Rg2Z;~@~%lCU#P#zU DE 41D"(%vUN""""di(4DUHF6l6^י:s i>v>M).j7PL @L;1´,xE,k^]i"""ryuU׍ &056Ą&Ĉ8B y3aƼpiE@SLRukCUkURޥH…  NT"Qºai&Y`bbhjX &޷شǑf0al]Q؄HdRKJUq)L*:L5Y//6͂b7-Bվj.k5u֪4BSPuSk6!1Bz+*!Pp6@ z `mˆnDDDD*?U"2>6k5+9j䭋X6!֋gU% uYqT*Z[QvUMq;@ÄYںxiKh%̩jU}ʈ 'TX%Fa\>cCkWBUə龉v<^8Ҍ5 Lۜ@2 b8oTlmG%5ꬪJ~ g& 4yZ firt. h~vW&ucv׎%&M5]VʫLm5E 0>##zk2N%aLoEDDDTT!ޛ $L(89xXGh )t{bՌUu 74Z0ٱhǰ.SE>9Y@ԪS7oj4IbzUD$ahqFu"^$kE $6 DDDDd#k[j|@ȋ"a aP%@꡾vQg顫ś9ں"?_6;kaƪzU©7.0[85iW(6 km5; 6qd$R(aT/. x!%RQUDs$ڼc?=M-Cjy} We6gEFuV#TQsFdD*N:D!,qsUXxYJ PXoYI%"""05'*c瓒klEcHơXTRI*Q[~hSk+1?@+=ghF vr,ٚv'$ULx20DɉFj!' X1p 7BU >UhlDMG@#^Z|*a|5KjU"m7H5@7t]20ΘLZkUv:NUF #@$5פ%66PٮF!lQM砊zHȨoW⣌HUK&K}kަ;HSQUr*S C5uu(UcjFhڎ/@g,n(VH:쿭Z4&c<8>2&NC,C*DZ,\BջX;qV%i{ZP@a"6 6jՑikڽ)omIqc}`L*9c|S vT""" |p1ԥTs1ŪU bhhE4DYѮ9Th!xoOűSѺr$ZTڭQ F40&J9,$SEk.ю& ,fB uV5 D|huN5֋n-nE @1+zTTW,6iL&L|U5L[3"iL4&jNv/\vT躬h^+XkBm0k `T`B*ՠ WUi33ZvPRѪ|8ͫ0̐ j U;u DDDD+U/_oL;+: Z@;U`˪*y`%"""Lg8R=5CRjj籮|Y]i]h;uREh0k` ig UHfaDDDDT<=C)LS`H*0!S/a=[V""""~M:h!pqCa#݁JDDDDF{3CN>U""""*Ӯ/oaJN;o0dh%"""|eJh?"r=IENDB`qdirstat-1.4/screenshots/QDirStat-cleanup-output.png000066400000000000000000002621131311502036700227400ustar00rootroot00000000000000PNG  IHDRj8sBIT|d pHYs+ IDATxwx93I6$!* "E~ذ`/WAŮ6ോൠ(6.xQ*(^QA(E $!m̜!$$<3ݙ3gA!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!>Ow2&B!~J.* 'K B!̅B!DCRAq keB!B:ubWP^ޟ@B!;7J,WpPs᷊`^U(j!]!Bԝk+ΘZ=L+J,]ܹ|ԅB!NK%`/X@j*^mP!}ygTY0/婥-^ЁL B!%4߰tiyhOͧBXO鴠~B U{ͷCyzBV٤% !B3d;!59%a}렾uo /nΫ5/ d_PI( 㵊J0B!u'.3ž yBX/wO!v*j/1OOT(RMZhRN4't!BJ#ƔƞIImٔ祖^R8c\+ӎ1g8aŴm$Ƌخzx+ʭ'}wMbyNڅs@ktUZ)eqJ[."ڵFk=iUQ!Bb^i\c\+γܰquZxNx72^2^4y 1cŹQ-z18%xCok(B1HGU9ƢzVU mI*^7}:!jkeVQZkm(e,7AYJ) bc+[ eU!BKgqm Qv>q-!dܠ1{N,d<xuܐǼFb@ߵ[yunUB)sTiy@)˵61eyZulֶmYr-WEB!Ďs6vl7j/q8`lE, QOm| h zxeQ5Lh}0Fj| Uvκ.D尥eڮV(OUB!baJyFyg[2ży@2PJ<ZetP'|@mňcܐ)Ku5q (h,0>Oic\L4wV鉖*j/F0]P' >SQjU~~i֨Ҟe֢0ʊJ{εp]t8s .B!v13ӶZtTk\7- 8&fYFE<@y_y֖ҡsS ~Q8%)ީ!AR~TL)J,T4GV2&A$bFn^*>3xu2B!G~v:}\ GcbxWU=q²>/ndSi/.\b{wNX)BʋO|XVVURh42mNG]f<#ST\PT\L8zM!M3mGQZ7ysJޜUQ^,+TiûAϊ\Q'<P a٥3/Sf<))ZQ,;gQJzK+1_ϟ˖ϷB!gw}mxxnL,e# :<.uGϣjNY@WJ?4u( [>h6+mԴ4KJٳHmcB͛ǃ=w)B}v)'#܆ÏK/y~QUk K*P5Yw۔)_sgw*7UC͔oxnijD"aƌynKe]keO|b"#y~H8RjFcJ)hKQa~`q6_d :tpzQ@"EE[ PgpgDBP0X_ѯn嗟v4ݯ)t^ NOyګ$&&/yqKnۖ_yP'Y)M\| p|9+>桺U=j( x|xÇ x䑇wmiӦOpǝw2N=];}.ς X:?QX/Ϊ|ˉ7L7 ׏3֮]˪UXd [x`h$L41W/g |B/++-ZbhV}yG3~x7bGoB{7KΣQB8Q @V} sYt1\r,>X^zcnj#7w#S~aaASJG`/֌'o|VIj*X nݪuj\ץ.f38}{sKR/вe V0!jqt9)+ ;?*Dx @qFw5ȑ7.^H21|g6/ⳉ[osW^u%JL& zQ$&&O c6J),X,+ϲ~lx׭%)Nڲ m&>!Bkz*_57noEEEUs!-QvZ LN94ҚfU& ~?\muUClj&qmb1/_^/Ѽyuܷ/SL!//LkN9Rl+_jc.\Hرvwy9յ˚U+)ܔG:i%sjs)Km_:c?@ŒhrҤ_ᣏ>V-˫آ^zk2mt>3.ZѼ9˖-cڵ30?nyhx5}uuv823]nsg[\A4emj"b]p_*1bM`i4{8C,q.>u1yOJJM,X_LCDqbQ\Ekt8ϬY(..sN$%%·,cbƼ6O'~ƺuHHH{wUӭ[W}yF>Kbb"|0W_}5  t qqq~q;T_̪+ꪫič3{Μ $&6˯G>'u_GU=ַ}Q/+F^^iiiz\nx> }7_r)\qU<[>@5wc%}tnzJ)8^G`S=c[BKjr;!f53R؝٦>ܜ 6m~U{.Ș_:jUx%ߊVmQVIʲ݈6O1?b^34:Iǫ˯X41nakWڦ绠muq]pX4ʦV-[`ݺul!s ))R!zsXha}RnM7j<{ ݙ?OBeT8ذa3B!joF!B B!b'Z.B!Dz#B!Di]!B}t!B! B!B4 ЅB!h@$ !BрH@B!i]fYB!ЅB!ؗH@B!뻆be IDATA.m7!B!ûV%Թ K.KB!sg`x1`@}t9 S_}[eB!ػxU@JzоƠ-md B!wSJ@B!.B!D"]!B4H:[o$ !B箻%sb{߰.g^x{MeOKJ}ײ=c~o+ .zu^n~:3HZvj@'Y~4QWKt0mo+>ecނBzaa!~zhϒ[pQ7Zqhx†vkmn 3Pl3p|ݬ(,!;Uo;.H-j`;=%y{GqnT!oWgmsVVon=TY drsg{pB˸Kk}W,c=[37üC>gI1aO۩+|K]sv1y_}%])J2{!l -$󇗸Vݼ]ncfI!3_~_PL(oOIN!8OoM`Z߁\;ƔdZU\Gn1E||C)#}Gp֔xOa9Lec/xti&/%j &‰7cgZ㓖0K89_wtexZj?BZ.}Q|_ ݯ{YkJp=/Vº_䒭E1zdϣ8HS:$@˞g⍥MsmT>&6禎%^ _GlǶ2vIQzK7y|7II0|v!,}q:ÿ11k-JH_X/‚lکny'/a(> ) .^|+Nẫ?#7C*m/5#dWǿm"f ќ_yoRKcI^!A!Uۇzn|o?1Wҵ"iS;|bjڝZ4ߎo&؍Md ԃrcPr~d溓sԃ>aСMi}#k?\MH~vK\w)6)]wYO[[szsyeb,]MOb؜;ZOҶWFLeI:},NC`F:.+Fsu':Z okGਫGb%|d_[f=6G aDz6\۲ q"7s)mgiR9pqa V4e!H;|Z Hbxt?l1pHSͻ]tlBSF,F5ktjLϻSTwLrr*uXq?Xh܌^J~n@.ѝɇqčD>1$dp3 +鱧b'A:;η!W^{e25<[/޹ֿ8Qd 3m2 U;ӮYOn <~;X%tla\ !C#_z4 s率1?rfŽbVA}r`'F?!KrS|xi2' X;sFG=V}WALIjiq7@~w2Jե}7cˣ|w'?O3~d̜S};=7ېM )`b&4.oLZ==̀6+xb?Yp.G):ɣY'pXZ~I m^!Sùl4«-aq(>AFql^@rF2_|>Vڬ[[@$KJjjqR< _Y-w^Շ.ShzżPZt?84SF~8-ȢqwpIϝSI:m(w_PiJciĺ5Eؿq[({^+;HKOکajLdHlDgҊ5ʶZyRuMfi'1cSkuΠTI.زe<%I٘WRը%-7 G/M{d!ػ8O;x=89X9Xzs >ݛ^٫={Ue6 ?Y%| a}/'ɑ)AozHqTr]` V~,d|gu;v朻eJV} f=/}:>9kovhHEl2 _QUcȝ:n|ń%<ط(5_1|J-E !k>9l%%l3Ŕॳbmy]9UޘCŬ8Σߞf:s>`avJ.3yIyC~YVv>uNJo|2q3^siÇQkܔԄ"wߍ<5c?r6-{xq9?fٌ8!weﵩ]!(U1|s:jZ^C>⭄e[nԲUl7ⳍ>s:>u`L#N*&2Mphոn:7.zh;%Г{7G9'Ӡfw4>d{Ցk;: 8nfsD+.`}yL39{<]f},\ғ+?ށ^uϙb[FCs !h0'B\׭0yucЖov,ۦy rQyn¦+rcFs0Q[y1/+.fk]Ǹ;^ 1&x-&}!q[0UjǃՅfHsϾV @%KLhP^[FX?E|yshD}1-BL{aF|Y@Gz(I?UB!cncw *q4c>^/2Oc %ѧ|G !'H@AËa}!v\v<{pB>tB! _ B!; > !B/^KnFQtnTߕԗ G;$Kټۯn<\ޙ'ȧWv9?;~Q|>vClp9#ek,{XR껖=l^5{A@A. C!|6c>ˆ.e]b?c}C+h}g>\[9Y KY+>ĢN!?H?WVEv{?jVxL$o'˜qyVֵepY1os~ ~\R2}(]!S)r3y-w3|8cݶ?W:rMyQX=C1\;]}ޑ+eQK9L{fw k 67[[>f _IYuv=Mӹ'?ƍ5g\Adx7 dX"j˦8!яM歓gϾ71%~Ou%w.Y'J`D&կ___֫u.t+/1b/cV2N簺p}=ˆy} .]j{}K&3et}'kמΩ@O_eQ|0{57Rỡ]tN7fϟƭN):2,'E6qR?c,ZKȜOqIyO JC\:^1&  igX=~ O3yQ.Qc0<NeG֛cc`byv8;q0Kfg+8mքԱNz؂>VdTV:cg½'n9(A?оSzr˄G|յmaѤ(mr1&ʺ#8GZ]klX7ʚ&0}M[t/=ҏf{X]\zѕm;K-׽ɬ5%+aݯorI35Ծw)/ɴVg%E=_W7 hȼA7R6MU.z }խ}1+ )0Ǐ/=ӎO~_CAP|>}ҳJif>?8yp4m_vrw%| ~XC~A19 ?tϥyc-gS`(1+|K~=1^.[pe6a"OysO"96!.bŊXc0!\y-?0ׇ0,g>@-^8׸X1s[4 _&}ڤ9'ԣ19?|ɫ)(,!fLC\+w.&AۼOS6eX:;v:oo xoaB Y>aυڽ?Vϥv\>a#E}JaLndi3摙,aN-;+IˋQ8ZGo\1N=\{<26J\~uzF_:pt/޹ֿ8Qd 3`{ qvf4p>/?*d5ǞEtjL#\N>ҹiW؂#|kjā' fՄjDYi\=o}4/p6FS&@YEz *ҚK޺r3wonxqN)|!7fa=3!tY1~5ecM;9d 9&p8:^gI=:WRY"\L} -y3XjF-+.ت;Gh\Oӌ:.9zpcYl 7=M2pw?-}R`k*<>$''Ӥ@Sw9N-rs؀vM2wa@ ?p9*pnll$cֲ>$ gOthSZb3Wo餰S8\u=k/fRz,SZre]V}afO_GS:Vx+MJRΏ\6 w>*~Xy$wM8"T딿j}AjkD ܒ<1S~QI_.\ֳ 1;yz rgQn{rJy/-gF2=kUsH&ޝS Qt+>?gCc9Gd|5?es(nz(ۺJCdkx{ocH]jcB~eOUz& c&hZpO(UDEgͯ;j=}ִ,60c+="?n^ AudNXqql\0+ժ\ٞ0pktZû7VƟL]9GK]zkCv VeChe-4OҐʿǭXqLKo5dOlo ovToL*+ffy|m;+PlfO⎳uEo Dd<[UW۴U}?OZma7Aп$876%&ݼ"\ofUĝd_(ڱ5מP6}+'-۶sJ ڐ=l;NZm/ @wruIZΑ@BB~mA3(*R! bH"1C(E.3. ܻOV?]I2 *9; <ߟwOѠh8[8b$ݍ$!WJ*V.DsYv6hK]$6SwQ'sdEX.SNghСHrdo@6>JײXV V*ahwzƾ.q\G*!M9ex([`Lgv(װ[w:o1N|˖rѫUM 5]s7">yFL_63430T.GL`@gВ3ZFJ>~\3 @#;pPZ-&ᨬ#S -K>ץ@ٳpQ`' е_2&|$9.T Gsq89>Un^ ^PQ$}9t$S㈊'z[BPȢCKHAIAsr Z?Q4Dyt`(cHzx!KkhI=it2+QF%Z8N@PCz-b4TZPT¹,[-t'^hγ[sәS ƒcgCLMen4p C1m Ĝ^mX|x>ĵ0>eRD5)u'c_w35 XXjq2cJ\ 'ejwKk6|w88ȸAazҀPvY koGwߥ\_/e-!9Z'Z,CCu{=͵6-1ܼCQs[>O3PlRM?^xPGn:e5uuxW؛4V`U8ڰ"k;@Gu6m{fFsS~_|A8C6Xxί[D9U;oxFW;|Il"b~#8qa$[ep@ٌ\eQ#d8TɇXl#ao xg 5,TFS9ѐu^R&6|)쉊bO}.}wPcD474hg=SVh ^:90τw{j!..6iYԣ`NޓSFuˡ=B~A̫`k w-G?gA1˼WXO&[$[' z/=c"GY+WHd3yhLoGҷX|{V%gضtƟ35haT LZq%d0>sC6p!Hz]&l`؝Zʊ*lW|Iܿ縝兾b]Žԏ"csc:&ۭٔjCٱh'^?p21fQW>ce?}i?Ը<^۫YF'*-{uo|Vuk~>tMJ;>r^vn#T; q4l)WːkoA~zb"j&LXNw2L 7wr/k1)}G2x9b+om,$ cwG*8\#*q Ȏʱ=zx`se/9).]A~Um9f?5HK%U\:u CA|iWBJy:l,f{qxkOJi)0CmSgƫL=~;Ai{ moj9p}秔?9q4ͫ_Ew _ecFY 1Ao*/$"v]d#2RL.g䒲\n#7l6RQj:t^!08leHJ%JLb`I+.|-{[mC߀U!>ZpZHqKSrKkG:OL͙/V8ŭ?Zs_s<-!)0M%Eg݂ώi4HdHQw@cnymj^h0`01 ƇшT&ؑ4j|d2UV7~Do% C!ͨ6`HgJRHSCΐ Đi4d$L.Әll:^O2izLcuW ctqѯI׍T:Ձz~1>7Y{[K1x1떕0R,n6\uƽj*b_V.RJ(籲N7~gj;7̛l[r M >B`k{a@tC32爥O3>b\Tt7˸OW2:0A%tR+k|?d3Jp89('%M>vUŔ9*ӳ∎dbM ^Bwk8S>4^R!QfvqKQ Dƀj'ۯ[ ?II @ xZ|] @ (E] @ (A ?҆\ ~!|EQT WRMpcܫKp,oUxe/":p}PpS*/]C""1[΂-E.=z$ !%S!l_V @`WlC1V~ IaZ<&1/!zm4k`dqV6}\lـz(`<a=Khհ(D?4%υb%[m)%Csw] Av4Sc.J3[Gg>/K~9{9 [ i)kd3|b`[>n7ݫ_BNgdP_5_f^k8<Ҷq ܟ oӳ3T%g V7q6s p'8 6/$s_Ka׶CzXlzHZ`)o8;Z/Bү0"[!iXu flLsZ0(Ym84o ~)0YK \ ar`n5 {D6-D 3ht[\s= γV+802;ׁ?z)UY[ ֶ7}w#BZnި1pwZoz&2 q)H6 mY>78ZhE O0sh(? B;3ZmaP ӹÌpߋЯ?poNJoCc1jcB;Ϣ ch=y @͐ ǥ!,P{(LeVx‚~P -\KX GmtNSXaʻx wgq!0$ ou"jԂwMP߄땬ԛޫu|c 6ywbt8CLiZo9V]$u1\KemX9ʍ%0a|wy.vLmkM} ny,ٲȷΕHXN7ɶ?jM B= 5fW`I/p5[{.Cu3T nj`@0*{ u tw/ys#x' 1U9)L_n NܰOk\ xR^31 Q@F:(5 ޫ ;{p7 D&X [{?Ю;(5Bת53a>S>8}F]h(u{ H aQiSz5S( kAֈkP:x:?jBKgx B*NU_|z:O,bBaIDPͲNSb!"h!>y)l o '` |.[A @`AXy:A{lk@EWh 1a0g7`!D aIaShghUxl}NJ, >V.ԗ_&y%eowaaP`~1Pd HL\;=cj ORw?MQGˀ+÷…SŮ#F:0><ίBX j,1Ka|(,HfUX :ׄ^/]l * 5rXvGAD?@sDZ\ eS#fr̡DG=S;@Z9B } -<#nK KVֹ@1%gQ. PrxpZkeh[N\ ,4&' 706 w_~8;$3R^ZGYvd+8) 'ŨW0_9 k~{ H kl bpXS qKh rVhe9L=3Nz% *; YbzmKK!?> ^ ,˞7AyX~"r |gK_n#]UAۅ8Z0mc9-# 6Ku*( -Hh \(F5jCvvpTVu C;VtxM>A\;pM$ c$QY՚ RXǒ-չSypB?JY~o$R'C9P{ti'P9܂t3˥ՂM^P=t g@$+oO =`PMhmjh*ܮɷእu.<)/tL&,yD#de6pr 4U'g2e5[05=aloM!%sk 6P.kh$ [ IDATm1X%郑55F(6qc>yJI+P)|X6"n #m[tW!G.{ym*Gsh[n-'ԅAye=1*x>GnPk8gl#R4}`쥦,x䉡kT`Gۢ_fv5eVLH1Z iPZ{^pmۼ}.a`7h&aHu=g\ƫ ^lx}*3!Na)W0Hª yÉDh "W] S|%eY٫u+waYIe  {Ԭ' &w$@Moe˲_*A{Bx\N w{:RA'feon Oxo8 ri"O㱷AA;Դ!""`Z2@wO8fyՍo D_g6`cPޖ"a[/ Ѧؽ9`55 "`nX>~R5iaFXN2 $|uzO@y~u#a X :CZ, ;,ySY0* 8jp \PA۠j|%;`i"SP,D6 XS \=p7H o1/Toƽ 3Magw= E;]/tCM|`\S-- ~V.0=} :WZ֏5z :_s`vC XLk 5 .'w 'W.ex9~4>> -3tr_Ab (m+x; 0Qh6x8kZu: /B=UbPKL5Lzt0 N) /k;t\ ipnfƂ $ظ rXᡡpK|)40¤pP$p:O\ xJ<)7RUI.MuerD&3drIYLOe6R(m\jJud62ReVZA&1V0ʤK =zkcp>? XE <[3t}=)X6pj4=fS"G5t4g%LC!S'gdvd^f:}ΐO;$eۿbve۷,H-ZSMq> p]{q'ݬ"@ (.< Tկ-DbN ']|f )^pzi#xX!GO1&oE9qa\q!xf/Cݏ[atXYBJ//qYVq@ J2@@ J@@ "J~K1Jq,mXu<\VP@ cGB1" [R=N돷!K +xˡ (k!is_cL=/Bzcigg\;[? L8s-c5rX BA'I*PWqyha1] +- 2mH߅I7 BߋIZ&8%O$ftۑZ AixЭ`$Pmhxud3 n,FuJ0YXpF]Eh g$eo^ 0coVH[{3/̚n<ͷwaL~0j5A p`|gB7Wص~40S}gW^#NAa8rs垻[.07|$,Y田| .C>&ݴbò`'C:8z!wAZ{pyU A9X4 Km60\ϏaFS8UEF[ηV'ׇA~Ϸ!f q/.u ?;{\*|`l]X?@%pS5oT-8 @8t =&Ci+_.4ú=oV]jF>9(w:W%t~/`P`~)]|ԆŒScOB0 >i!5npH!:| AVd2Aɾ'F rWpR@n+pcXh9[*5؁h |H@h=LPg=j8>@ @L_<͒g@T\9M6[6js'@SH{"|& , !ylRa(a0'l?ntRI[c`rl}^tpa5VRN IZ0(5wt3c'BR wX1:'CpixCL:8rF#,k ()c!KJ5k3TwdgW@ ϜגH4z*x>IҲj ?BT , LFdz~0.^;9jT`Gۢ_fvogLc 5l~^64!y3hcf+pAA3%4iCC9U/_6]<>WMW *=`U Wx[ҫ\YPࢆn_ 5WN4H"zm*!)U MQ)3²~7HקB75Mi"O㱷AA;Դ!""`Z2@wO8f>m0+ayG@9J (oHb[/ Ѱ`#ϑx%X{ F~:mgA߅T Dh,0v#,W: sO  QyשE'`A' i0d*j=Wv/xih:ԁxn N0|L:毁*a"xWA'>% ρ:wm:O+ `(2!L>g:zz@Lym}FBR*;iץN6[!C.2}L.)+6rFj#6MKRXF^J+$ F⯯} z}a |0&=o`q@ (mj^h0`01 ƇшT&ؑ4jrfd2.U{aDo% C!ͨ6`HgJRHSCΐ Đi4d$L.Әll:^O2izLcuW ctq i_C\@ R `B@ ӡŠ ]-@ g A@ J@@ J@@ J@wc+Ama9r.߳AU RC1#P- '`u˛=uz vv`9wहco j[Zƫ+$1vF}xMc_^٤Sz\z@P"E k)JXoAV`U`Sٗ?P/5]/{ܞ0.4@PZ)=t+= !sۣ^]!L@BFA%LwLXRXeT5j:oOws*O!z5loSĂ;ÌI [!m ΀[K>0k{ 4ީ3Dפ-60Y_hnVWWHYd\abHa j#a.| 43RRڥ7\Xi:[Ggγ)Uµ|e]@?D|@ {П6E"gs^j 4>Ae1h ~3v?X܈ N" i RhR?M>CPhc0,jlADS&Cto< ~̾ץ!,#P{4j@% OX*k6 Qa(L+qeQT'6R8wΝNIk}G̾!ޫ#QRt9V.!zփS `LA/Lh2C.C.ЯN!J kvy)t@!0\ j;lGسƯ NHzCE-Px@H0/кZf&ajӲר n! {,*har2Za|D*D÷; D '` |ѫ1L?/Z Y5J3vɈh ׁN umį33dVLH1Z iPZ{^pmۼ1Qݠ!!IxMwOe&wKB:O``h xH$u z^gW6C  N3²~7HקB79ہ i'q[ jZŐ0- \' PG 3odqaTO453R$l@@!!l9".k0j9_Tq 3]o?>BS+.D‡`oԓUM`mg(eiZp&-HqqZt[}A0س`6J$D")~(kh>}QcV2fSm,,եV*3Z67+k6=0W* Etˇt:z+RFRU^mW*/%  Fkv\ .ԮI$D"H/u@ӡEGQGg(jΞ:M_ZcʌcGh]>Z'Q%'))`jnOӧtiRiJS[].2]KYŧ)J FqBٳ(̬ƔD"H$II(D"H$DR]"H$D")FH.H$D"#@H$D"HRK$D"H$ň/ПbG۳P<ۊU]+7(6@3H"H$IQRS=`ON,\0;(E*p rqϱΧIN~ :om@D"D"H$EIɛI6aM] l%e`.xh|ɯɈ4`Bј#H$D/D &?5OCT:z@S]Q} "B&c[ԙ\ `{ pwK@Y`>"g " ӵ]!S xw4h8ayö+`CFGn~ EDs; ש}n@s J@$!lSxxH$D8B??V \*@5PbX !r!X` 0҄z D] !] ˶~u$kP(oB[k%pHG-(SG`)".!Q5 `͎4Dt3oo"TlknƯW= Apq_sp@?}AieBKO]6ǣD"H$) Ba@D4K۞& [| 4bD}?3cJmط1-Btn06//#R "#^;[n> ~͋4B< PVn(v<O(H$E  "L⯌g qfU; R\ҿ-kv΍ f~x_!"giSs5 +!"_Nv/zLK)(Yܷ^C ۞G14F Klߝ{ IDATB7#{GU"Ry2e.ҰXld~Cy-(@ˏ]9"/ B B2;UA!Ds a4 Du9Ҩ~-03:'!DHbxBbT8D<t-"y6_A}ۃ_z>iXӰ|9E a7KQ6)D"HS"SV>٩veY{ç0w&϶ r3:3ֹpᓝ\r 1cn)0A';yDgލQXUg0߄2s݋GD"H$9X"#D"H$IqE tD"H$Q B"H$D"yj{.H$D"$@H$D"HRK$D"HJ?D q`umE glD"H$I)Q=bB|;x(Y?Ix|&Ҍ NqqϱΧIN~GLg*p SD6J$D"@ (?6aMX 113蟳]/:9 `,./#f]U4fJ$D"z~ADxC}m` "_~߈4\P[B@ȷD/ɣ?/MߥG(z#{Lo@6//#R "j#^;[n>f#NﲕSXBr:aaG"H$/@/F(Hqz2+#w 1@#w!"6d ݮh PA6s5 +!"_U6P?%D"8Cm\np!> ۞GfDz "7y9"5Έ$˧dbDB%(1RͲmiXf,#C/~CQYկEɥ T!DH0w n}dY_ !ķs a4u7!c@ R|$D"HrD~N|+>3i~W>XPn5/>9%7C1/yrt_0@a 0ɉپoGwD"H$/D]"H$D")9H.H$D")1B tD"H$!D"H$DR]"H$D")FH.H$D"#@/I8wgGzEYG#U1Qe;֠T|hm6sABy>u/D$]؄JD"H$/ %Gwf=EH ξ;?- uzNFa,jo|/d RW[d.i㹴f‰K$9*;ڃƍ({8>*XCqN$)HͼbX؆I/ Q>1,o;}7I+u?83b4d3ziZBof &Qg!b9;.V<}eq캜$((R\~gq;иgf=wc̱kISR\Lݬ MADHy0nop6@^ѣ}*zOD"H$@l0yӯNJ$w3Wq*lyeB%Sg,Νy]CyJwBվ46Ek>A^ 2%&rŦ=aK@ya[rlH69ud~sUPQ^7qvgTwH ǰmƛ|?267I9:ܜ nil]Jn})c&ެRۺ#8MM]GY6.G0m~sϷKbުQspkPinH$DRyf**¦ ЗsG깔oNޠmHZÑp.o^[i/y'H$D+%L+$z̤wδoVM5ڎ݉O*z-wt®BitqAfk#֚ah;*U)Yr`i]eTT鷕;11sa&Jgߌ)vdv0AcVwfƞDtr̡gBjB"o:j Ԛ<7`OlKz*:E:_Y@`P6)p-D"H$ϛ')x9UrL%ڶ 2l "XBPlkR.$<7Rʕ Kͻ @ܵ ~!5ʗvyܪ֗/&v$wOg3W50,eߜė} 3 lop+3JccWZK$D"y)asKUçw֍FZω^Ǎ_wsӼpn8c ˬMqV}l<>p>cSm1 4W֨T[-2*TeUlՖj3V9,^ʕ7a5D"H$t:(,ZSiQ88VS2{tHbKGS8=]Y9$>T>Si4}Z.-]]*MIPtjK]K%[Su):4Z;(^({vu33+p^F%D"H$bD"H$I1B tD"H$Qzh+H$D"<5@H$D"HJRK$D"H$)M} Խ-)*\~4kSi kѴ^v~<ƞ%>_a gr;5&E_xm/ ?68#h>;{z>+6fw*܏\wmys=X)~*wY&) H.1xn}7(jSS%yzMC&G¥iy^H ͩRޯ\?,]F vS,* grZǣ-6(ܞgQ\ݽ':Yms0ъg st8Vt37b(q&m`OUH7eixIѤgv<9&^ I~3\* m. .ļ (lEmcF6O\J*jkRrmO赒Gv`Kcy"#)rlc=3Ez '=90%ǶbK7H8VA Ϳ R\ иg_`2]#N8EFup طfҞ[D*(i\onۏ*wPN¶^jZ1dBwYgOGQR=UGזNH]lG\en{q ۷ʯ7Kգ(z=90,M͢=">>h XO6Kk6q/D2h9GlO%,鞽r ->˛+]{ql;7IQ]<έfp}7N֣;Mv1R%\lK+^?\ g oy|#) JZ>:v#ѦD=DM.՜h3UMj^wC>~gq;иgf+]f'NwŽV[̥ -zEA q>m:O9ۦ4yOD($5`{z7[5qseвzCqh]o+9ԣEYwݣ{Sp+uƮfOV6gҊ 0-ޠ"v{&9͛Y.8}ngCYw% NSYeGR~~0Be[<ʶpf| wYj6 lsR&ѤugCbtqCCmM#!=ۖ>[&2(^[3z\of܄ x%X6G}@j*f -F/fV GG7b!*׉εl. aCF+7q&Bn]+"-WɺscZVN 4`(wBU'W2k E7y5j)]kƥ=wxfyEnV=vۦWo:m0q}͙LbL/Dhl3S1Γ=(ۦ5!_e!sHM`+s{Xrlb*Wlv \ 4ԑާiVAEzb5RL=Wzy?_7k-?\ l^ hh8b ?~ޒCh`S8p/s 548~12ZY8WJo.-2 7_Z7q-J]EÏ MR\lӯ,|"6} pBS8+F]JM쥵솃C-Grؼ:~2666w/^\Teiܽ '?iF9[G^3Aԝ?-b@L\2yoUYwa =7L wbof+_vj:%> RJLmV=WSLqVشc\ݶ4z`Z? Ņ=* OvT<>xoVtms*T56hu zX5h‘x j7C*)w(SGs*w=*v._tjG]L\&FMQ,]0ShU"-'Ʈ\Op'U7q-Ϲ+-3MSYINΥIͩrG-;2ڞ&٦\wC=XؙGř)qy#Ië66:~ {Ndtr2'M凓Dye3$E@#M OL^pQDIE9퇹#\ʃccPXu8ìXvm Ha b=É=WItxTxxk=->O8y֩+uRbݒxE{z.$荶ӡMiռ<wp!MuNz o{r;woxeT23PfbWC̦>,4}Z_e错"jA׻}Mھ2^[XY8|܆ &1m˵\7]:zwb᝹SToUS_jFmN[bw֞"0ʋWs>]:g{s~F~}.eFb/Z2{ȞHm\q1[ytgB-R:o>;w#a$'عt``.~ 7pݼ =W36bKjـRgٴ`'CL=6Cтk6p-zy9j4jCcDn_odkۜΕ]oՍeLv7Q~y _M^e;2$m3Ė mj,AHȟl\kjV=KB,@\m7y~j6CbY<پn7>:'^S=A 9I8ڏ&1# O6> O:yn*-'(Ϭim2^e%l֝kxDmK?T=m| W<3DPN=*Ryx}ێB7 p߉N5Ӥz"gG&M_ӗW IDAT]&7ÞIrq=tLذt>Q^l[3‹߯Rx8.dM nGNL&θ8JdK;9QqC".p鿼LjS k>m#ZVEr e]koĄk'y&Aԟ} MOW'ISb36rtZ|bbb#6z5vqU*s=ѕxb _S)*`mAd% $  D'jj\5l,-:V[*LLXu#)Pqfwm1˩E`$=iIQt f<dzh+U"c?P[eT MS3;lXS΂Gؠrpضĸ7vg)g._Ǯa#}*q8uj+P>/.[bW4 B3vGA kG, q~0tcm3O!6pץ9jLM/1- ^O>t=,([eTT鷕;s!L+ecVwfƞDt2V߹ڞ3oB},1>m~3~ ?tT.o}ϺCJwؼ72%!.Qa!$zi;҉ 7GMjz.;>Z2|l_غ'Ҫlfٷ~!1dJz2IOz!36L^9c61z@F L`/l?-:1eD:h8֧oajgǟn׋A[Neb1gynm\͉lw,gфM8!NDBV;w%ӏ;lF #ii/_*z!vr8ل;4vҐKR.EKIƇ#.pM}[pl< F ]ZعW|loW֛qɩ Cz}<]j TʠwjN)~M$<^\FR26EzsZ IW~ܟz]SbzhCymxnygƶwFqi۞c:Xņ0]7+(scwKOy-Nm?f‚$^s]TV4h<Է|ކ{'Op˔h)JSku3 [ `pGǧ4|Z#T\BH9rIIx>U z ՟v{~f;'=M?̇ xvɮy<rڴИj[>q.~>D[μ>;.gr>6oo xg <~Qq{bM*9JHJ2>s=69&+-ߝx6чd( e̢4vp/CQǙ3zGy b >3~?2iҏe̿߁TgY`mzqs~͊+ʦݎzAw-Z lAqG j L>~>Đ_+x IǨ/\:Ž7+?u'~_a\^ڑ_1vy+WIpnq?s,,=єmh̳T>yfr=Xt V^!44_W#$Ӷt/;D@Oq@a8Yx˯#p7<{Q\i Gc۳V )ɑ}G'IpEy]1[)wU6fjTs\KU5SZ+j "]QY@CsUiJU:B)BUVUVm*6S+jb>au7aڵ9xe%EmM~?ޢSOu'fO%o'-&}qqk[N l}&ȳ_r&6l(GM :}uyy\-y4{>!zo}m]^Ioh5u@ӡEGQGg(jΞ:M\Zޱ"1#uY.UOQtif樒R0O57ӧiftu4%Aѩ-u.]lOեӔjk8zmjfV1DE/`*ȏ::>mW^Ǖ@W J6)fl l]Sr2?~˒+UcxY}K `oIOْm! A)fAOz]NSJi3q>:Щ%v=qR_$,YJmI78vQy%9_$uoxQP5֤qGm:/mH$%)_|X۽k ]$nΡa9Em⹠9es UfVND"H$ D"H$I1MD"H$DTx1ή6Pvꆹg[ׂ >D?é.֮#Ƌl{Ѹݟa[+~j7|'6RWA"pCgP:Iq@h?\@`^C'Ùs.P[qxt׎>0cgvRqn= -įv#* Co &} sE&ˏ8u΄>23<\7dX-ѩ9moayYl2N v-}lDP-!Х%+ z dL,G3r$mETwhP5c)Hx)~uQ ">zQݶux湏#kupi_mx=o\*Ϸ^?aT>d@Ck-:YGC\-(55aǣDRDL?3 @S4ܻA684 [pc4eDla8xUhWPk GBcW S ɹU_/i3( e3%\έk#\e`I ]faSVǾ]6:63b §2CjᎀX ߀9X`ѡ"-^7-aIwr6RV@gۼm@ϰaYq[!n 7BOp,n^v'F9e'_CjI+<95>nLf85\s8Yr-] aqӬe#y vgL5-bmmcHEX9omYo '@nPvB| fgpi+T n⵵)mJAs<4/C{' 6 phjwoNx4 w?x%f{_a ȘWԶJ_5 6܁lZ8u ، !$7 5!]m(w8{Ė AWQcxf5?Bp ҜǏSl˯g`7«f?dTp,,\5@|KX^,Z8lH8.f|͸'hsz`C4X}` @uC*I7Fӻ/|V/1*&}ԿcM8&=L *&۾g!\mKl`!04Wÿ`7Awy8qcni]c׀DJrv5y6աvWt<ߠ00~jpà ~*}JOx[hY!3D(iCoxAsa`#_8x?<.z}gfTC"Ehdf5VZ5l,+Ͳrɥiכ41KK%SRsEà(W1g9ߵ{(>OBO %F> AOb?<tGy͛CHHm?\eY毆ͯ60[fka h䴲Uy\Zœa 60 ^(B-oa;ܴ ౵ӒV^ R 4JsL2 9NX 4H ;B4xej x6 !jh Y 3?È[ {HץQ)W׵ D `UoopχU`1`QWgm5Z`w*.~swN¤u`2gkTAyvZL;>,}̄h?z+=\1(< RcN(Wփ ߜ{(%<6k})nv`65p.H´퐙փ1ٶBXz pHLa am2Saf a [`>@(tJvBj8‘R:92`h!( WBUе.$&ؾ(ilwDdH l:rU,Dy?4\hTMrМ`pz(!f88BpC׵t@lKˀ {~{3fv<'" tfsQ<tcm)3f0BX%>W*+06( s<I`c#6!>6.Gܜp3𤃖p":w(Ѷ"ּcC`m. 4kWݿ+adCB_2ڶ| |~  30:ο s c9>x~9yy*wa%@\: /<"<F]dXQBH+,`Qg 5ݟS0)Uj̀#:.dya\ i;ל)ʘ[0DC~6ueΆ\ǝPtX r@ Wmٰh=axȚ_˯A^aN uL@P={СVsѹDv(R,nV ::H-^WP/H%ucu<4@up} ρc*VtK]V6HU! WX668hoc>̃).0q:z3zFעfpBݢ{IX0"k0\% 9iz` Jm:k4 &#t`qA-w<ډK9 yn/rim zk/.,Σxb;tCbfJ{Z&hFh^FukO.q IDAT-5X, KQvk)n;EpJp])mc^RBꌱ0-/…pj׃A(ZEV(r\Oے7 C_às.  _An%=u:-u`Aؒ][@A\Cw#£?vy9 spY ~7 p$ŃT%虙UY+5!E=x/!d ;˰%f|ACad1WC!ƫ@0ͅe]>6y`qV` M]H mU{pGrr|?v°;C8i{w,dWo1g2put9«qkZl< vCT}fq&lG|ж7CE5>v?K 0,ZS|AP$" ۣ!Cs{,xAD~c j{6lu&zn +olF 4Ŀ5 0hw=GUH_C TWy_\c @[s|wCV܋&O^3`羛!av OfHl:@DSx;NzrѶ 4H DЊ\ԕi0!vFpI=g0o %sFCT<<T8v `Un'|_$[{,Ivl qLpL< iAIHW7nɽ vf#o2_=]UPcX먵$ &8{orZ &Ū¦h>g ]p&.RˌBTى=doC u6k(s<L+&C Ғn=p~,I0f)BvJ|cپh/X!'2=; BppSpgumau0cߖ@番Fxu|>sXg.1 O>O? 6 _ #oRcWΒ6 F0ٰğ]k ٧/%϶&} 3l 蜉E]u˶|Z6Lzs&$@x21JSRՃ2e[saP: !% ì 'Øy l΂7^K^1ص}ћѵh ,Pd1ԲufЅ :4} 8 !F>ā!PGх :f7" 1ؕ;Ю Q)k1v\-JUִly~*Oql{nʏq׍0i<ܟ&yUcχ0uu)OrӰ8zիmB\ hr44i\4|hlGnhs1 D4KuNWSe9m,U3p:pY!s]vݡs`9 ANt8 .ꬕcך\:x-r%Մ:]{:7UjtۢæaҞ_/Q =殻/E֪|4BS,VTeL8YtkMKd2fj3Kt!.iU75mW拷2&CU*G ̞ h5",GOMK-4N'{UUGt!,0]y\Ϫn:q!B)%%$B!FUu3|]!B=zʫ>WԜ)l A[&79QB!X>՜= IRVQW0$@lHC"!<VM%l/arQ~Oay ._J\#ah} C՛몋/B(z\h\BR"xUp L`p4l ēaErRJ\\agaҏK \ N?TuBQ,q3֜t?<*K4@|U89/ħeQok8'`f(Ogllsh\2m,9 'K LmI.{ 4Ҿʹ0U` kC͋fö |I?UpN Wy]>p͇#;0} wc_F,ap1NHWdBƗ6~ 9sa]jV}`>!O_ !Iee{<,.y>.O@!fxAA0r ODn\/8? N gà|E)0]O`4 V]k P{4O !ƾaʏ! le#cuca`ht: AN05i{8Qۮ׏W1W{[TѸ/30,y`<R !m< 0s V ~4*B\~u;տEr| UD00mWAf]zwJSHɅBS8g3f ]z~#;Z4om#!q;|ɿVpfCfZ7oa'u;W7c L|m箧Bq ۯ0};M0u c*el:~5fzDUBeA/ {. Ahr3P<=8׵t@[Sϝ%^whtq[wbOZSxx)<,>]!_)+UVkCL˜1C@!q5FÌg k g_!hZւs\t> aPrV/BԮ]kAPI_$5.Aw@+smj?@sD7v,=hhzAmLAu=0k+O8IaJr/ !R\faIg{`L`d;`vxQHRNB8)0u#L5y&_>*Vh?A]@\H\,a0b 59 &͆&5}JqX54pxէlki:TӜ>{xmfqB!.keܞ&*vw[\MZ4FwzX_ 2j:Ci3Buga`f>A^UѣՇ AV_3Lh{_ɄUۅε+wV]rЪ/l^LK=BQ-]5׵nNM=wnhs 2PRӕtYN+e.\N./};\V\vewv!خjNCӡ9΂ :kصf!WF܇tɟӕƕ!BQI.B!D5Rkе_&$%0~SխB! =B!BT# !BQH.B!D5Rsa&m |֦"` H " 8$B!DQs6b&AJYCUpb:l= } fş0^[|Fz3]+|)q U gK> :_ J*Bjڏrd9/&n4ºc3a h `MUM)qaI8W aI谢-BW%ؗ_Jr÷‘!$> -a(89O3{ "94.]6ӝ8f*X4Ҿʹ0U` kCд Z ^ 84WwX벯]/9k> ݁๢5D7 2=5J%&| w¶$c|ؽT׸g鎹P8b{mz <0O} laKpz6̇/Bq_:S߃0} hrC}A} w C`LH.{q`}4{B iC&z8 ٰxnx=0Bw.50c:mAR@Ho /&btC,X<NA_?SRe> }Vqaq|lzعF;w=1qœ{jƟ{7x4"5'ހeХ9<}/~+)n !Iz9hvXI%ʼn UD00mWAf]zwJSHɅBS8]͂~S0۹yBhм9&jZUvajj-hsmfؾf ,/q, 1sן;B4xe$az]nU9-j?'[` HfXrJ!Z҃^,]@!f8ءxzpok#^6!,ugu+Ak[>:}BA,^ Ϯ?[D !NYU<6_3DA.>WC; Wø- q1( oq)#ed !B\R5.Awc6HB9aިJ,ڎ' ~#F&z-ʺaa" o<;a( y-aW rA-Pk :1J/m"qqjʅ< WY5ӅBqոLHq@xQ MwowH &^C| ;!}| hJ"c:A>uK;s{; \Xֽ|o>m#'8`[P he쁤@V=۱ VxݩڞeJ5m] CVXŏ aM,<3FžpcU1k6% x#DDvBqLz+qd>N {!-8b $m`M;]7x4{FWl M7~])XzOW?[Ͱn*aƆFDՁ@AvL^?{ H8IaJr/ !E$xvLl F&cz&lw $zSS7^z;X3aY傫o=!X|{ݹwAc\=a@лL:,]T6 !)W4Ect'a C-@36C.Tgph@}>СT1!\ Z=P}.oi5'q9e1r#~W :B&B!.֭ti' m` AC [s2.iseم+i/\` 0۵\ir:4YpٜVg,jhЖ. \J\B!$AB!]!BjDt!B!IЅB!Di8:E" B!HJ7Q?+cy׼_6Ig8jux xH!UF%݀ |~9 ҁ!g.2Q6 rQp NTl{WA3%L m.iBQ.7^Zsp7Pw0 _qΪie.vi!Ba=<5s~FQITL"c1ITOl>00c@cTգzHFJwN@,2r E7ۀPCTOQw{zz5TU^C%6<^׽4{,FzK{d"q}Omqo `B]$8ĥ;|Qk}8|B!ItSQ R&@3 <&` ?J d< Q^- ئV@m&{*:.PƢzD]DQ5-P)7zۈJ[)`:Վ~cǽ~};B% xq-ME+j߽ːB]l7 kOdž0TV=|B!KrЀ@*2=m07Q=X!T9؃JbSPI~:pzg@(^){mQǡYl~* D|O{k5l]ĵ,A uabG (ǺJ B!._).⢸1w(1+JjcQ ҭ^Ӎ ÍR^CGL[J^<;Wz_8. PeZב2㠸,|bHAwh끺XIB]\( 8yD!+q zhTTscfTC{`$ @TA~1CFTE2UW}wcð IDATQ#s D%Id})~%cZT-{]Txىz`H 溞,|iT$JOJF2QQxoQ/IFՠ/h#eT]QST݃uvb=}{-@"ۀ5lB!k%ߺ?ZX.?0i״}W^0cyƿ Ǻ?֢Fp)>PIR oeü}qMܤXG&pW (BSAB!]!BjDt!B!IЅB!F$AB!]!BjF%PNkge75D^%h_O!jT BGx|T/MsH^qt.x u YJkeAxڀ (B5EE̩mC%Ozz%n室€I/uNf !BԬt_A9D#ET&s_Y?8f^1X1*yl qH9K^W_^,TۭFMQo܆zs凨n!U^CLzzLuo{pu eOؾ/5 Jw籿Oq\Q+20.Ҁ< lC!Uu|TTbz 3 <&` ?J 1 T*9(e=@# x |8P@@GXT󕨋H`2`Z.RnXxB%́St ʫWQǠ{wTB#QQ!a_F>@Qw EnTTU97TzO<=OW\Q/qϷuܚzqM@]<ӨsB!jz35"H*yDzɯrOD%h,$Tbgؖ%G |^9 ~>*.z@u*Q?*FS<>Epw+_ι\Leŵ hu 1*?ztG!45roo|,cܟ|CSoE3nv-XZ.ه4I=B7㭬ÿg*Wݟy ! !BQ]I.B!D5r$B!BT AB!]!Bj'`B!BTjJn&n:EKCsfsG#o2"뎺yl$}ҕr,?zyy.9q\7[al #?{r9{R,;#\v֫%73N1_$fw|-ou/vM+ŏDTMa, Ć|\_ S!:y z3 *^Jۻ >f9A/Z^xJT#ϟ vMػxo?q}Hx cudhmb嗸*> }YNզwsVB!հ]#o[ Փn[،#q1+:֢nStڑMBљr,k7q=M`v6d7C-cpo2UϰpzBFwt |8c~4ͥ[75m]X G%8܎H‰4?!F ;n!';BB'@ԭ<=prʱlX Jn.>6Ecm! jrI3%Iٜ]gv!B* |g|y? Ru>gfrYq8xو'@ < l+Y~';G؞3jⵏH0o]3qjg?\o^v%#?Mn~>޽cۘ+|Q=LLd'?irը5'sǿdж[bG:NbSyO O^M`u֥AD!BKbr DoGע1@]!P N!@38 4C>P* ЇZ@}>Dn7Aسegf:Tga5!Bqi-]5׵=NM=wnhsEDbRݥ:+é鲜6W˪]rv]^e v` й.9C]՜ Cs:AiuʱkBv<mGtr_!=B!BT# !BC2K.B!D5" B!Ո$B!- B!Պ$~ܼ<_-* _e?R;-^ĭ\-Gn ǚ+ Xo?Ƣv.綗Svq}/@8h3h362V *u/NH+y"5$O9_=9SM9Ok^ޙGA0'3^RO5mQ}gqԚ‚AUpQ3܋J\meΗW ٛ'l^y$Uz>mgᩖrX2y&ye&4Mc7'e޳tJi 6åih'pڔ'ՇћQ< 'IXNx8b4.r.L CW7hSM ˅MfSU7Dv{':XX3|,Uݚsܶ⾑ioINGr[^@f%95}I^bUz>FS u+,;p)77beY6WbvOkd|[N5u|:1bn_Gy^w^Umw2祧5P^zgG1;44 yγ#ZN4ͅ5Ndt]ڽ"q0Z.Ee4;هFZ=5;44F֡d@,vN;23 YI2o1ӘV@$=ghVsǭ1cL9v\ GAV#ϭ8J^zsKn[1{NY'f#m$u2ն31;mڸͧhSz:"0fvNs=/|5wԶp>9q\shdg;eSQ7R>[s, Ě}w)I*w0r+ٓni8 LY6;״O>܊NaޢuYHjh3\qR*֏1{{*VMÑĔS؝CUC;[BKm/+xac:9IKyoD?c99n2} ͅ(0囷zJx69_e`CCNNYfqyǥǼ lasxD9|CO3{Q54 tƍt2;2czL2%:eMX5 ͙1!9]Bsrtxyn1U(q)m Dʁ 6eݦ 1o\ǥiOc(:zY*;n~k 4 (?L@lѮ]2w(pi6rNnf]ӕ c,p2cʹq;l^l=vFʜD<_c&G/l=tSd9ۨ='fqUw*lMf_Vu&4|k99]Q8k>ֻ1>3O`=:-y&$gcd,M" (Zݷ"Jj[UQ&"$6"L&~{}{=(j n@m+Ŗ#]#>or ."dQUǵ/)UC*Yܹt,݅]jꞿ7o%,{M{l=3yOh%rE{f;ļfo?f*VHo`nҚuF!D&dN@lڴ&ꋶ ;&G}ogAo3NNnCfci(5,kG&{tWc_3\#&8sS#|7=sNɶ~X]i9Ÿ Խ HiJ$z׮1V'Hc'>jHuRHd4+Qb|?>߫o匭m;.9FJ~>F8^fcYx .3hBɿa7`+'m5r[f#eTݜuVmɓ>O]|mع1=­D5G=7,T_ ф=JŬ7 ^p}0q̝/RյC~E 4"\%li1[[{jDO ,pk] 1(EvDh٘Adn4wD~O&aUj fϳ8mR$ დm#'wek̕KofQVuwb  <8°oiO-ѯA:g~gIsϡۓ LĖ/bK0ng{Jwٵt%"88q8ЭCOp$ yqV8NK[7s37r*4y1JSjWd. C난'p+WnTMtj4T|%KnrTIܾ;Id&vx8aXWl(}=ŷ|p$Rr3"N8wJ#ǚɭmo!6(kV"Nc/pjfmb,t7ڑXuX.} #$jwquv3hNm'\ Vݖ=>ugLŞekE׎Mm"D^о\#Wdn0) -Z'p.ڔuqðl 'NlYsc^yNA뗲#4saO8{&ǝIMlM Z֟SN40:xĕ?b,mA'g: Jb?F+AZ Gk#b@6mQו.mPΖfKW-̥g|- $vJ M{oOOZ+[1Ԗ94gkKs;^ɳk{B)WL44YF*e< zu*Sg[Py.?_]G܂NKfδmoH.=~u)1Qmd&#{cK#V}觤f?a:ɬ1fҙћnFUJ#] )j?\ݰAI|\2*71q%h2ڂ4RWsz.Vyc'~H:X`̡LZJ"02\p,KJH8eqΤLNf¯Lhb\v6XވT0cJ,ZJ1AV ɳ)A7H܎zT-<փ۹qt30UrUmU*VZ 6HijCYAW> єU|n^?BQ$2LnwjN[EjfK7Mɝ3x't<6LSPl0zpmZN&lxWc6ԃ`tݻ,y.zk72_\/$J5ZZ3v,z۫Ugꟍ_HJcmpl$#).rL++KACBZ!lZ8)"=sW3Nc{˴3Os}>+pz}#Hqg6 9psNpBuMTΙq:ZZ 珟Wg:&ˇZnRFMVV̛!{yx^Q{2O0w`3jӖ,d԰lKwBF*)Y(Ӌ͟nj'VZ`@R,>RQ3dQ(ed4/Q_>zh|vGq +*tNWHޏ kk=g )T1 S 0FĦh߄Z& Xۚ+"QJ=0C3HȴvCVs^gG^DZ~ݐJ=2q_Ԕgxx eXqWM/9N7ŨT_kQL&iW~bN@ؒx;Qmyt47t1$.̍loN#FMeDC ?_$CzÉP6Ȃ9}𖁣W{^nK]$%)LLej)j2pze xs)]Iܚz-)u *6Y_uodGܜ[0t‡T0HL dzѷ KO#ò: fB (H]bw'Q~cdsl@o/bLF| ٙ*e:铱p#U4[Ѧ;a_o,ʽZvTĞٯĢߞP X Z1h2(bs蛾ԵJ|WX2;*I(gڏCSvŎI0JsBLR3.ʤuw7OoC3ϼyH8ϒC~X6Rddߔa|uFʀ5M&5|Ua@6+ɲwH&s}${__l B2͜ޠ̝\y@\X>k-Rd\FFKWU6 kpΘ_^ /ގLw<{ -(;MpmӧKދmG4p! ~g*}]g_W?16We(W"k.%g¢2"S?xʣN0#e9ʪ]74QۂL\QG9d*mi88M5vcV'+se)|?Zt FT 鶦"3 ,Xd"1QgHD6":T51MUZ)2%b XlBcib#[d&fbAk"vZ\+rbMz 2^?^YMeh8̲]vF;W 1sOK.' T<?9CYWE*>NdYCC#m&/bR[" :G{`>c#\+ll9"K#T&.ߔi} ?Pz0.j*nb–K"X6`'Ǻ^XWt .A$hl]YK! ]ⲖƆnl(k1J͐ mԨ8D@9B0@w@aM"s l%?QT@_yBwٮ/Vh U/^BunʸlZ>ᅃ c4d@w"~$xCdqOsa}^D"M<;B:22Ľ{@6PIݯ}Db3-  7 RG SEi(}3! s)(c,룫/<Zύ /bg-([n_tn5 wWD~8zE{j8]^^U%2Ω}TXe'̺\ϮMg8x?,=Nw ժQ cAe8Xֺt׿\Ԃ' 47&#,wq}\"a`.-.*V| .;;! .kD G@k9,j0N `a,o/hxԝpl^!jDoK⎰`$> \nfl,aw:OéeV{̀Z>٬+~섫~C>C3w\jHJQg'.K,3[;pb3~!ct7Э$ rWn: p׋|]bW랟_\l~ 5t'(Wх651t76j+4dsCK }hBX,d#|`7)|?xMVLgN@&gn&$坴 5f穏݆tS*^qiT'~O@Vj)̝ܺh. }77p%1ԖwաO ,BH, 'oJl'Cr]?d ;Ed-$n߇2 GwnS*㒡]@=l2I* >6cnp];4ۡH #B^? *U0<߁Foj.6`n9o` 1"/hRa`;j.01, ʋPg$L 6yK=a@p FB` Vv7"F= z9pG?=3wgY90#${uu1jxAS ~%#&j@6z0U<{{¹0hOqAZCpB~=TC{ +xu-CEh2]aq(w-)  í4dϧ6l8 9jqZsa]H/ JvLR[GS;&@eRXo8 -',!: Mv09.%7>{#{qz=˜ + à<'Ò9 ZҒvl1l?  eT$= ̂t s-2 |íBBI5`W~`Zذ C@2Lk©u4h`0h7Nlvy(&(<{U@yb4 -s| iP[YM GBX7j,!b-7brSȶĨ*6?;|G'_u\z1QB!%@ uy-A=g6p] a8{'Xn5~Tfcakht,鉀ZJF q`>и|P+63#zzX[AOаًiiSzӰ%-!g]g+r{wXicpPoa^A7aWO>9b&[q0qy)ӴxJ|c  _z숅6M[Qi4`b kC])p8ٟ#ѝ@yv8HW#'Wh q`Q(-Up۸94Rp< zʟ{WrQ_uz9~N^o$O š%1z- J ɫ9@} B9U0H#Y].Sn@A7 <V8;gF !!ρ b^M =p:ԍy!4-y AaGD` m\ ASh)hD-bR1㎩<3UnccaފCuypBm&[z Ъw@bA & I[![h"Kc..Ϻ`FNV/@pnƅ8ڂ(?< ̳!V[$R7P`dgȼ[w@n M=2@m@ojxȋce@2r]*.?qiԠTZPAL[Tc~@kϛK1kp{<[ %{-=l= yoC ۿ]MAJ O "%<*&0j |l0S{!뺐@cm\|, Z%gؿ@9A,8k߁g=!)ޜ >xHYgȈ cՇH\4Y!3+{@*a|865R C| y"DT<5FòrfC!\ &E*הe}vei9۞OrܨE62A0^0}EY QXK˾XB`XH=J^^ +.6Jز] JL8x fp|S, ˞2Dz :‚)<[B TT*6bwH f!nUS&:ob l%qzր*p=|<Aap3.jDoK⎰`$> #om}? ]?{[u3j5 AkA4;+ƻnr<w\jHFF鞝 w4ke杁w\oezufB~#i9,_x<? Yu0ڦ`AV8!}'-\W׃`a|M=I_Af o°k}pr;T ~7a`n^]!n/a*@\|H k/ s0L|L-Kzm)X}-t =ZtK pn {" S MnROX>\Br;صݍQvQOuv ~4(Fww@hxk0lXv!  =˜ + à{f |ǀ41BWԫE0K6Br DPpM 2|q(\{oI4??B 2&Xؗ(a:\Y\dI_ Q|!$4.߫>ʆ=9Ƚ^4c$S14lF]^ G|?ҫ 7 䱰AwRy=*8xQWrh\K'{2ǠZ5(s X@7ous c:;lϨy܇uW!w@z<;ρ@ZG[eBttx9R+0φXEn89H\V (AЫMv:6`HdO$H*x4 ϩr-XNeD7KFggAT> 6j@s)g|j"n)H * RaY,d(\Sz7F@x9hLL8^W* XdRB4jЊ@jfh yvW; `8YZ! V`n5Bf6@~҂Ԣw,f*6לMPSAH^^^;.%!"U]os6yx0g #} bBr[fCtFd.04a3ܼdjnJ&~68Bv(ՠΆ<驐a O{&B?݆2G_4#C5c!Qo߹ xِFa^ei2Pp<@pKU'ocCȜa\7pït'C #'|q/-4/0HN B^^^^;΃N,8k߁g=!)ޜ >n9óΐ =޷h "3B&g W!U5usd+0zS ${P,fлL b-$E]p!O03a݀IGa+ Bf `us!AwR;4C*HXuwn#ACnzZs ͗&FO& Ͱ+VwQ? d )ADXV:n; ͆0ZԫkV@덨ND3mMEf&&YDb2lD&uDkb*6bSPeJRBTk-Fl#L&"D촨fbyR"8q=oR& _~of( gM _Vj;o4nd8XށԚxV$j2r Tu(M8]d4 ɒ4ٚlMJVgkSj3JVT,u2%[[ݢ3ηO*xKe q(@<}#p*^ BHYK! :<@8@(OT oN5! +bz* Pa8z$ YùÉJl b`g .'mѥva{@6`dׁ ھd"*GS6E L* P.|_R–#S JL8x s||92Fz6`x5}`i_X|A7@ JRw±Y`-(vA8+ )v7V6tia*P%ǃ'݇'yUOY } /;‚Y c+ [+:89N۾KYE^cѨ1$&jLb&F&11lbE`W DiRlvy~첍.[xޯ׾s\/wsϼw67g*_\#L^cة۾;fqP \]WA3_è|Yf쵷éml.?>~ -YeP _=fޝ߿^F48FoA|#N k7RJ *_   p%poq9pp\8<xp̹᳅św;߄>ٷK5{pX=#`a3!~ԬW_Am{|Wapd|`t===nܱlö{ŸO`)0Lg=$w\ {/EpLl~0.8-]ݯ?IqMp [UG}‚`3wv"8A "8os8!8S[AMoB1̟hliյZoσ{@a9["-  ohp`px ä74ջLV7Ć 4lfu@a.ʹo֦ka! }(nz涭ё_!ÿ9PfF\ĵ ~-,dRJm9 L@oڳz^gOlw=pDS"{=Px0!7b1pσ]H n; _\? & /g ɦPޑ @2 yn[ }F!ޤ4vс ja`f6ul~RJms]"vn0Z0q4*e ~8xwkχ7|bbcX!WÝ@L/LIEeÔC[7Q-ސ4$|ZDvxy`a1>sAa*. fp0:.?}m ~;f0Q5>rl~{L. W ¬SuP;~  QJ)&tbc`n6w#_C= epM_}҃0"j..o؂9I#G!wwU w<8hi'*է{-\7J"J$N:,͇^ zz+, ?xr*,:5 NwR{pտt}Xy:,[ +S 6hH7”5[__;t ?u(uXWZ7GR368t^_vVu 3e1 ,I,°x1/' yA ㅂd8$^؆m? X1%b ly3K\ئRJ)ɏ=1Gs[Xti>h`ՍzЧ:cDZRX\_lWYZ Ҧ::.TȸKoER% | ]*H9i/GJ"oAjL]E)RJmWkQ'hҀRJ)0PtcgOgzЕRJ)TpPWлÕJ)RJ.ЕRJ)ڞh@WJ)R ٮTL?6|{6SOu.%f4P\!3RJ):n֮"٫HuRJթAtT6d)]ug`=U6lRJ>h"mR4zM}mRJ)z)tmR>#=)(RJ)&'RJ)@RJ)R]tRJ) J)Rj֌рRJ)T#WqQJuM֯'LRQYS6 buTRhɲeP-ۇ|S=6/Y@ӧ?qR֯'77;c֯_OqqqgOE),[F,'#:ҭ,]쩴;@܁TkI&"L: 55~Qz~l:g~!zd@#¹=?@m\Zå9]SEev4R\ϏmTv٥|@oZ^^w"BUU9D#lso@U-DPkc:{ Jm@Ϗsc]>H=LRVVqR$5kPRRB^6[r tq153R!7ߢjG_|VmώÇu|T۠{n@ori,Yƪj2EqQ>pi5{({nIPbV$-JbCQdQӸo IDATJ_@mU{o6/=\Fcsc M+W.aY.}Gbגm]rZ|-967nN#Ig+:t܄ X <:r9ce\Z"lS/95#!_ĝo0YVh\gWԏFoytɱ~{/ԃύ=6h2Ls7j06dR1>ىQf.Z.$lqwi0~Qw$vEc\RaZ$a>yN'&=lqj A6\/! >q'/:GZf4׍dhv:D"Hς Pw{wާ~uKCƳCn7;W~!?Y  xG^[U <ɓ=ǫs+t<'tr4;^c;+x50`<,?8,WN\7n{p@h55PdW$l jjn`! OyE!S]Sv ڍ<2@ p({tظi'~ ׋0 {2ÉIJW'V*"sBX7܀!?5Y[]Mgo9@ظD 3XkqiG8oGk0,/[ON4BIa>.X_HAvWT*uo_OĢGpPʴl+^Ct e+;"*Oyd# ;!R4wG-*ՇSⳝ|U39v_oX%s职-`Ifi|0w)ӆhP:X& $X>so}05?0&"ė~S?ድ)a'CP3>,!Pc䃆c[G_Qjk ů0iq'y@NA\{?ze8鮱<ÉO߼{^-WCQt]||#ٹ/q;V^hԥHFp`l]}k6‹.vW$? ً3M셇/s2yw> /؉6uۋA0gP!B@~ #~};j;;!kv>+5Ax[O16>7f&GsՉ(bwO>7؀_<TVҷ r3.!DB}31̗)Uol\ ]F[kk|jr2naSLfDX2ݏYd!:XhU5\ Z5YHbrPwH:7]}gZk^v3H$U˱1Us*98>e>sس`|U3^'_!z1ًO{s'0 א\ͺ8~Ƴ)j]wI. v$ٍ# ?0co -.j^Jk1Js1&jcG_2MKOo'~zfsy?_%_(|ZʗΧz2R!ًE`|JKbF=e[Ey/w>QD. XۃA9O_9xRKk+B>x7ZC~25 <`FK;psYʵ嬭ML>}1XԲ|-\zǣkQrxrJڑ/yMۏ[#~gSdE E~Œk!\Џ!r$Y⣔mNޭ7Qv>:7zۚW;&w$Bο4>$)/%!T0as0g;Yy5/ R:sܝ^_>7 zw,] ;2oy٫!?b!<=̚5%Krх k6 lvVdǵdov(֦YSb}CNbaE/L~w1ilcsuCec$΃[\0t̳x(K,7(ʏSPe( _V Sk Wui1mIN"=Gdygqy'wkZoy_Mt$Z˜_Vy *ԮXSh7FTky;gr [|s8`P-eK19XXv%9K9/n۶^ maXqcDy~///>CO95y-X N>d2ae̠~^zspʩi\Z H &{ɡygIx<{b t}#ސ 6>v0p4F4b՗E ;ңFSJײFɋ`"E井 شD)̋!gprx%#x&Pj.>o>#G2ÆPd·x7(:vU)*7N!: !Wu80a|ZR ׽)_j+kF2q;^AY{3}x(n~#;(7I7"dE>KN+S5_QH>}i/ɬ.R|Ŗ~%hۼ"vDzw?dIU ͙άb {6+k|$+VGl1VĒe8s8?GX *>"H,F3ખWG,'Fؒ׿n"!U&w(<;'=IOΔSx{ہU8ŗ0uS=RTb:R|5NC1X{^}Zj2ao\Ǖ_]5Y+H}U+?mz 6:W>Z'ѧĀ]^IʁRTT@g1&!KQrU}M'.ȵK. ,]Km2I|2fv/7(sg.;wA@~ T|3#8L$B=!N]B὿gG+ $j. דύݠ6M%7m;#wO}=<6icƌ/+W^]S=qG{Ƕi\ZC[}>{}$zoO>xeBv czg+2st85Eda,Ñn&CEڒS:}݇1Ae7~-ĞAߜcx}}!^1z ܉=도S_[K6Z~/ޝkI!R4чȰ؆Ƥ?A7rȐƫtEc/ܑ;;nf`h:DJ}eԙW2bܯz<8;?p'Oߺ^wFosS'yP:SN0Yc\jNLG<~MTfgD_`-(1Ϥh8{p'{!uwvPaM~Kkaޜyy{`.ht.6Eѽq3™T ?˾ :-تxyʾ\??av!eGp͘smƶ2Etزј]b$xaD Yㅼ LBA2/l6 Il,ژ’o6f%󻡫OhJ#oO{N9 h[?~i&NȯKy--{e՞ n5z=7yܙX=]c{a=u:ԓύ=6Dqj \|E~l|uw%V4dѢ͏ۍϵ=#zqI1~@;~K?())qj+}TϧGf͘ip1k, 6އTk~o$Z|? ?7 z~lscO-$Ȁ>t-Z˺u9KJ)((dȐt\ /dȰx^߰s,YXNlVJuK̚-qBbٯiaÆLt\F^XS^󩮭tyDsbի QhZSH`!'Lr: ]]=HM`)jL mg .݉~RJ)j9d;3AN]RJ):-XHaqI?#-VDRJ)u4lki *]E+J)R43- RJ)6ҨŅQA]+J)Rj36|_-."aJRJ)ՙ6֢t,*RJfE[\:^$RJ)Z%m-Z\DE-.]OH)RJm{[t-|}٪dgA)RJ KAP Gl8&i3 O xN'I/ 9*RJRdI>@gC,9q~6B!6Pɴob>zEV hqZ Hd @D'N\siěQ)]TJ)R۷Y割">AH\Zҁ#'.mpʄD"Am Wy204m1lͻ&yQ(ty 9kp73)160qHs9{=-ZV$RJ)eekWE/DwF ՂqI_|[L P&zd2]q>vHt 2`n:]QV$'*x11.\* EsVa=HAa| 1&LE{X)RJm7`DL 7~ZLʷ^:m\s✑ dΥ. 8/$q.ΣN ?)0g۾̙Cc$zOX :L!QD!8'NK ƴ\xDLFC1R`)+ K IOX uS. ҈oK)kuVҖ@pR".iB&5^;nRJ)= $blOKۤqq⇜iqV"iَG& (8FʖSӦ~HWglhm)0R5L4$ZdݺLrA8/ AqxK^q%2.$I=qacJ)RI{Tr$[SA:'>6DqE "q+.mq))q9IE6hu"vi=a ָͥʊ߉saq^g= DĂpڥR3c=ֹ.HIo4+RJV!q/oLk5pR>H HL%= I{Kl}8AksYTȴĖzY+`\Z, B7/ ĤM:,6 5MC)RJf|Op6.-"T!\ʆB Idzڊs8p.7)JɶFJ4oo m 7撓,$ȈWe%'1A8#t %yssA&|lX RJ)jY sD\&@|?eŗqш85yED UlЎm.UC|gˬK3.@,1Ĥ8@`Nքg}i RJ)jB Ҿ87N| L6%내KՊ8/S= ]ٚ@r*RBڻ6od5Ⱦȇꥲ>ϘxZk9Z&׏@)0!18H;?维5xo}RJ)^9 ,hSAȉÆ3=N/KP+X\sι8 8o䱡zNo54 fL.1K l0l R[ٜ"F}kol8X1^$ ٰ`$Xߥ aoXLx'RJ)Gi̷;aqQ$Ly*E$l8ĉsA2xE ¾\NeZF[=Z\TGi )*9Q>BD9j,~4"&01.H:6F<D07ޢRJ)$ ؈H:@"q6pb\,5$y8/. M|6Fme8C*\LL}] *_؜DV%3ol$p`l20ㅢzsIx1Ixp4_RJ)]IL:/HH`.p~RQO\ʹԅxwUkR.0)FJe{"Go+&[]6s#$|cP3 .d$l6& J)Rl8&D/,x1g}yymJdy?M{< (fV8iIDATBz'(fMmh`m:8k& BDC iL׀RJ)Z-H-I狤s4WpRs%-5]хoU &7\' g1^8 O`r"HDmJ)Rj'H<%!ID$@Nr" ' hpYAB?:CJ&^6y|O+->;s.ىRZZҽGO,˵wYΞ>W!jY֭[/3Ci,# x'omPTTs2TsȻ g[ӳ7V۷]۶#GZob*'{sի`r+VOl[1}FNȴc0zUB7z/T`4;nܨdfNz(?f+˲ܤT*fs)))UI њM,cB)//?ufg9/Dq8ݻv ;xpU+pf#F=~ܙJVwS'Bvl-&&v{,HII^ŗp!5%//O~ϽVm/ -/Zw흢LFcnv!nW=s>Js |ϓ'm6jKjW$ 8(T|jbz tն!j~ELș6mԺ$yydJ:Ft9kEo=ȴ?`׮]$jH69p7NIBCCϜs\ji]" *`#yh;CϺWEADV;]BjX9|/2c!jA8I1DQnԦm"lӧϜ}9jm{/_Xt-))$ˍM(nJunפ9e8|LsPR Wse" ꑚ`۪^ BJpp0dfl1VR.\>`QA~IaA^=y?v˗o_gO>vWB/ wevvcMe'Z[9NyYST`Xd9zOGC!Ԣhuy|eYHBM} 2uDz^^Rq FMsqZh!ZY^xa~Nn[oǎ,[6mࠪr򲳳SRR~瞟6a„|߁.\HHL|,rBH6m>d(+$ioM&SJO8a0m i{L0n9|xتBͪ+h:^ DvŅ6$O4Z-˲RS6{|h !FFc1JG٣P(q1w5 ,)ƌW "4$X_, t<=y !P%8 a{'=9l=V[ɸc KL>*?Tn48 V3zԳ@l޽cz-_r:Š;뙙R*Jj$=is`XK2;[\CKu ĥS/X{So 6mTs̕p]Kg&շ6 ;vEzCk"j_XJTuܔB<6հ,7}*Q}Nyil;um qJYڳqQwMy3,:q߼ԯ?)s^4<[.}I~;p­%[J,|┡QݢY5 ӱ7yqW BIݢ_?\N36d6߃WWR(A="͕M)?}~L訾lGJ6H8Jd}_2_szq b1~qvyŹ|h#ֽnCyk"Yr_Ϗ|~xkZnCb_؆W6UGJ%ֽ;{ШnտY6 H| xf֣/>'4r7v,Y,½5JJ׶3_ֱ?5xs޲Μ2 'YͰiܙ#oUp gP4C}"jԒq2n{?{~]R#zmMn{9Cwvb74`t]5O^jiR:Wܹ |.iF v-/q}??U(/X)H%g["f)E'IcG!s8v-aZc7g-;~Şq{'kp_QC1 n'O}3oWn^yn+}e+V<%l%l:r1)5S #NVӖ?ǽΚ碞z #v:LMWm;}.zcKF¦S[NN|7?^e/oШTRIܿcG hUynsAmym/z#k͍iyuao~[j_^~~WC>y`nzx`vd̋VZjUyxWJݺ~Y~iْy&}KXZ&)?k'z/ڶء=}ˆn٦Bs15}8Col6}FT\A*K8TثOA{i xi*{S6|i_$A*>=fYupg˱[ )i/Oc'>62!뾡9Koq΃Z8Ӷc򄺦;1np{#Ԝ§A2 xn#u |pD6Re؉} s]_veוJW:Խ?wX/qkջVݦn0ndۜy|;bz<rG0J)uaN5TDʷSܦVn,{u1^}켒+-Hphn<p?\zJkD!Ԓ*j^QY7?ۆ}dX`F*P4KVST4J>-ɰ2\ih:!=~ݤkf68-{s68x4P <޸Ky.yq{&`x7;(u*`|@6:7Lƺyfz$8y:TT  =7_.>d +֪_hkjl K'_BVR0T4dzy(>]ہ{&yQ ^յ?SK\5@fV WR43/S6Ǧ]}G"1L|pSjHpBæH5uI#<ʐ^ʌ<pW@NyU83ۺ6K^5g}"j.5vR_R&ݘ@c,K@>t㌲B /[1[ʯp"Fzo^+7jgZd Dťd`aO~m¿Wlջ)"x3ϳ%Aktc_n>Q Ğx'=rĨeY JNר5p8ޓ_L*J3ZtJef y-'^a$Del{{X%>v2&H(Ͽ9c\]s59?m2ybCC*4q۶H+l/M;󶄘u߭L%)\\j}~FaZ ԭ6~7FT%@LirR׻8i$M!P לWΏ,}Ko}ܝ鸂D׸!1zV</?Fytss}mӢ.zMzTqKN5R P:ihQk\yy$v;[$ j2J"uT}j{hhN.e=1}ӫ3ǤWV%E~V'5w s|7w.s6Wp_CCO,[{D?Uݟ/'9~s?{ڹ[,X{@gKXuǞyq[fҾj[51sy ߛԮg.|/M3:sh9_҇{ٽ3^drDZM4Fזz~]{U SۊnXttAd93A3Ǘ=gTi_jtHm)?6_/=(5PiѴAQ}X6ųMwB-V5G~;v3l5y1nR>B5Bf"&d% T(:W{hlBh([t) gN]`j)jx}u1 kSf:]Ս'^gO?|vֱ"{}7ZBk{/ B^@!B7'tB!͉¢B!B͌Νw!B53,&WΊB!PKB!B76" !Bݜ0E!B7'tB! "BӦ{ :hZ%IrefIKJJJJJvT!rhBd"( ʰ$ʢvSkZ,u.jJԸfW,{%%@WE|}(I R\RsD!P]_YsB?q\󮼊j%ϏRZV&K`,.)iz7GZy=zDK|n^nnNRp7m۴iM&SiY$ %0 0PJ aax^R\Y-P2xrIt:]eHqRtDNС\Yd]VvAH>ھ]?@,PmXt|.551*Pv Ei\^n4'$t"k FÀ[nQ*$IIJNEoګgOA|||b{>s^/7KhXsHq3rcՓzXc`HM *p<P*3 J_d(0xKߙ'LDqJ ؘ^8pwMCdI"!=|˛,"MxQJ%zgcYP(vSmµZ]U$_HoӦ ò:ʊ]wlJp&mN5t&aIR,PJssr===Ԅ BVjZO B.޶"?]H+*֭[;78Yud7o/ooo&ð VB!ti $^O~,ABlgPL#%Xz]Rq5kMwu18((3+X8dhec$n*R++e8gLTgAAj5:wVv>l6˲qEER{{z* 7Z 9N8/EQe qq,gѾ}PP`tks!szT-qZ;v?V+B dٹlunujUrS\||NnChXQJ"8[sBQ-tˍO֦MxHp;ԜGZ@% D |}@Rؑx+3[:v쐛gZ:!s.@J,ˤgt< :MZYEPJ/g͖"d9'/fʔp,}EԳ˱@x%,a:6((hv{Vvf !<;uS\CJT*+g` gss)*zT/_+!P*˲$IΐZ?FU,YR!TJ__wwTV7B!D|7'&6ԳJ6n(Iڋa7$$.\٣ǩӧ|}| eJl1ݺt-*.޿v:DD4ZZjRPJbcbl6+sAAeCSJmJY7$$#;;k0 eB,ɒ,h]_UlUZ[x̆}HC UXU(ǰ3ǭMPTe,0 SW2ֈ6]IΥ?q3SRaQ[АPLvBJ-_̱k>`ݫWcSk_`4͒,+J7:u&QR)@eRn6VkvvF1͒$J6,IΫ\Sn:#L,Z8swwMNIyHvHs ya8sL+2j?wks$I)R;&8.!qvg%$$8yu&! c/\LpLE^j{RRY9nr:,ػw_ݳʕ"rrs%Qlz۷Jv{zzz%yklRT$RBlmVF.]:oߞr.SKnehh4PIj`XVKKKAyq UBt9ي{TPds/RLeBegkZYe wp̩Sgde2fGo.B!tnb&ꉋyV4a|Y [DT*-VkII) =tZ]YYY\BBFVn!ݻoO_9:\)"//tzEddeY:4zjcYBjEˌ`Y)!XNȄpt.PlU)[K+8uިrBI#:W[*ͺÐde*Jtwu&64j/T;v(<J "{;9jL2PG B!f%gtldi ju˺*~j7S TJexx=_QZZqU(,*x]vWVD N&fs<##;iZAJKK N (ڈv]`iWIIV Pj+6-UiBTfΌa %ٹKfY_D=30 Tɰ~cEE9TEee e]SRZb1[vn>A&/`ڬVo9l>PL/Ȓ\O)>>={DB! GNM[!jZHC!B&MP!B愙.B!9aB!nNO!Bݜx8q!Bf$ǟպ{\0B!jf<ʮw!B53" !Bݜ0E!B7'tB! 3]B!tsL!Bݜ0E!B7'tB! 3]B!ts&B!W.5|5&bY6999""zn8o\֩CˊeEoiÙ.B͆wWT+7VՃue߲m[pK) L(@qwE} `]=XN-ZV-+ڦlK1E7}wWTW+ujвoY6[c/ B颛tEKkL+z#UoJ8|Kۜ9~CXI+,{g-V 4ᱷue&%R-?W y(%h7BwD_VHeIwpEerUmؾ|jenOW,QJ0T.;acw 8x?'˔RJm 1a?~<;[fLG}cK9M|^!aL]é2"t*vWtXҀQ{y(Y^>?RjO2|b)8c \}Ιv=cpqϺ?>1kӃ(uyא;rǝC%8%y`r\~x~vhJIoj,9b‚=,gBѵ//"}T;,=yKg9r?9)ˇ꼃:ݩ͹q^msєRJl-ugXp{dySeBl9Z[DZq&GK%{ϊtlե]3/ږ:#o\bh"&u͗&jsJ8x9_v_Czp6|6W~QߌĽ-Z[Rގ^N|oVVگ5gی':Yd]7c^|0 ?I;hE[naoOo׿9Hyg)!3g8`p~l:{ߢe+鰸>W"!c|wv֟[<*X|; Ks);_+fm>w _˨[x?/dgNߜ/Z,ZVQQQ$~Hn-ճ8sYi;^rhlm1Z׆T|^E$Հ>YJe I2fK6ed%->9iӥ5ǧl;vY}ی=2TyEd \=adv{36Ox=H,T&DdI$2{^eI 2" RYԅj͙_7hn4jM=o%k?gJ :{$3JLNQdSzB g%Uqok}ɰ'?a"ٜuO9n IDATule^z. $Wl%|F7__s>b{虇U-X(1B>_8Ui<C\l jpi/>(J;CTي" T^)T6\!FwlXӮv^Ϥ-R ".0XWq܃ܝQ }D7ηXVï;cc_RJg|l5u/|~8F=~-䀪:J la_r ae n5欽 |]C,ƱNھ/@\[,,xAs,bS*w:>5AMg>y^|%+(n>;jOeUCn?}y˦O,V9eC3j!#[~jQjc]uDˎ{hb[7T}_Çg)i4O~E!l=q߿Tqyok|Ύ˄Ў弮ZrMUXmh\% FJ+vACQXJ ʴ8?B߳lKQ!ڧ_S *NS_|AJj8lVZ`#fSzydim/:.R WSq @-gV>[+]fR j_? $ r LЉRjC'LY@K:\߹2C\>q 5Sίu0lU6{ ۼ~ߥsv_N nԻލU1+N@[ܸQD9Nd?K;mha >#WCS]Kh/q6L[ܻq];wN?e 6-u+߈~o6xM 6n¨Y}wTUŠw,,M)O.ˆDstg\C>i4aÁ릩vТadϦpat pcۡHφ>{f=3g={߮])+xI)Wq>|n^}'o<_ޣu#6U.SOBåZ~D E5ׯzV2!3>ɿX'*4QMe ˗6"Q ccJR6Wӽ)Jxxh4y@j׎ќ*%mܡ}?>kZAw,\a)=)nTL5nNTp&I#H?m?K! OZW^$`m(ttir+r2S(1We?)k)k'mjPț{wS'9g !O¥v,b}=B^Ms,' i'T yFR  0uϻmk~|3LwNNm[\y|}V<ȣ0tvOUREvǵ޽uDe9dP}?3q. XҳIJܪ"EQ=g7`[ٟ}.M_mFo>K(Q#cv߃𑱍Uw*@Z }/o[g3Alͣ1ulu4Jb|ZՏ__\:]vڴka;u۱h9Og5+_Z<]Ǟ1Wï3O?\Ww3e#ʆ#?gGRǥ|y۪kzSSWP /p~OկWOA3a_+gW܁wvQ_i-'2^>T,ibCSǐsaIoKV%+Ǘ5- {pW_IdiNs>yliђhKV/kLWò2$90rp%~2!kc0IWjt[{oC!Fd_|Yog7!^!9!?{߁ۑ`\h]IE z\ltSCD&<8fFCV2ki=ºtjWl6MM:(o0j)Jʹ7%+Ӛ~;6Wݒ2T#pQDI@![XG^܁?/O6f·[m u⻇zQb_="5Y[]Qfb'??)6.a6kMqM0 =} 3yVj⎂ zݾCqGAذSdo|jH%m&tȂ&¥='̘3S^~˽6v4@rY⿯z8ܪvպ^ZL^af [Uf3;Jdq%7t)(,$Ry&|#SG_6yEc)1;=ܞ(! ZGloa)^XlŖ}wd]f{.A;kw[z2Y25H{1(JV:OZ#jOK0?GQE1 {h44 D\ںl:﫡eM;kX# bs?\qQ?6XVF[;OKԆ+6Sì6_͵qwSW MvnOw.Z;PnjSz8QU!gM{,Vaq+=enN$|'ϙ7m_y;V F x ?2y+ M?wi߶?K`bΌoy6N㗶p.+`E_ =oߍ0p2'Bs%!To6lݞn8jZucuĥyNgDH[tO\5oћCSB/V u-8;0uVӐikm 5p캟ߍPrdĦç}w3{˵lj2G BͽHgi\YN9fĴ?5'$+a|b{9v"IQ^>_ymMJ:Q'tH >4 *Z?n}~-uģ,E0H{-?B)1Gg,kM{*u4M \}h@E~vW>k8=BDRt l^eŝOo X07Wqq7w_h2gt3+9Em]qNuM A_7$0yY]1tlۭû9FH RIieh#5,CZeca݃ݘ;[&48mo%2Qrƍ7{>G" ޿.fA̤IJ2O҄reI+:ۙ1UlQ%o~y1֫5m߅v{uـЄuDze*ק57u?B"}'pvvrToSŝ/+GVmRPJ!FϾPk~Ubq+($2o(ci;NH(mKdG(YnBDDL&C!ӝ1y^ Z` ~>Znf}s|FdJ7yFJQ  4IF&t_2&iƆ\TY\!3${bWɌzobfSli`ZīxJ-eiI@Ȋ{蟑ʵ (yY\ T9)LG&BcV)uRtXQ4g Bg}\Gwz3DȎJ7PDE/7ⶍNN1 x d'Ũ9!Y)rb 2""?h_b҆JrDVtH$n((SȰ8Vd2ʿAH$:::y#.Aߍ1վU} (chã4u>MY&79R9Ӣ henC{϶5bNۻ+dg(DdR D uv=}*BT]wXP[ЯZnn&:3Aos/Z%ԩAiBcĭY/0a`JlqTc3_ U鑯ަbN{%A`1/%}mF )i6: 6ޝw2@^uf Mzwxӯ1lD璣O`.+)479N-ISO4#;kM-5]"i\juVI{]wL?}_=; 'qW06ުx5lv:2-ء[]m5uطxOݲ /:LDWsm52e]'RwB~^!iBJwcI; ]> > yv-B5Vncm[RT:y|"8;)}U2@!fC|!dx+QAB+~~P7%4ŵBMx `u)]BȾϛ+|Gm'} ww/KZYYy{{!!! TPd2))*++K&)"!=ݻY1F}X嗞յW<1FOkx#pQ{LwʣRf {$K1]n EfZ5_GneF+6vor_Pg>Y_Ksjdc/u_@1LEt1J_ݟ;ZGȌ|K(DBzեݺ%]Ds)oޤ蘚ɨG5ٽiRmooLRc;+Ҕj: ;j]H6̲7 1u>4gxĪ?rs I7f7zUM̸$J&ׅ>KRA\ 0 3f̘/ȲlY[$iW֎Jܮ=5н{Ĉ(}eB{6)RJ;3`ͻlNC z06m*v:J`qoF!xz4hdq滳s:Xs+V˚-`M# XW>4Axh66ջLx54ЄjիYڦ͸30u?Iszo޷M޳|ƩqjϏ-ֲC?z(TmDݐ5eJcuͭqXŹN$կZu_snCN?ñIO{wfcmS{ɼ6Ыl[Wѣs)bl}Wm0z2&IXfSB6vѭg3ugl҃=6h]JV /h2lfèݻu.(W95g*66M-<_ A aH c\|Ff4; y856_n?{DCK#j:jVc[.|cO >FwsPکF-A_(FKcV]˺Nvyg(EV t =M+鉊*qd +ٕ6Su ,-l,Ji6& k!E;\q:@Rn<8mTU-?*hZ@ L[&dݺuUTq B $s|\⳹D N|:S4h`4g9̇DKy|1~k\db%>5,^-31W v> }7iX ~`po3!|}ܘlL0`eSC幡f`MرIϔ{7W6;l݃TmΉF֘qٛ9e kΤ&N 3Ysξ5Sz ^lх^YTGg穦DmC_~[mc8kT:v{u_y*(Nڊ@ znܱgygƻ2tzk'6[GuS. esSW[ᙕؓ%7 X#u&{z}i^=sb']Z 7 FAFVoފ԰IA7cj+#l#T !Eck\>t'ŀq0fjթgYguAxXOCַQд̪~FI!,D^9Ӹ^LD@+ʶ9QRDLLi`ӽY/IH*٤>*VZajhעy(852,,:-[F6ֺ .0smRό %J0knm.E1`\ -cz{rg>5ͥ e9 91d_3ml`6; {U3[7<.ƀ&*9t*ߑFmGa-GħkZ[(呼l?쌤 Yi݌,x /v ƢâS3S_[=iA Buޢ~JA]=qn@I 66;NsO{uW0)`BJ:bƾg46._wc^ Nuh:۷|AdyG#@eFr)xwo_fbF]s7N-pgozIyn+U7ɿ >+!>YQ'YK^nk}Pf~)Qicc3ggg,qHh`DE [DiNO2"1t~cvR)Unt[ *970x+eBfl<˖QXZ0`Y)Sdu3 ]8yACtsPFr`@TY5 eFGY}@Y[҉qPO 12R 0FH AH;m@>}wSIBF6SMƺuMn[j kOHc Jfb~ [GȮpa|oGfc Abf*0)k$ʳ#o4hY͘ d&[ܦֱ:gFG.k$ק1N2g<2qzfx_y!|Q_2_6mu,f2~  22_I)H/khC.mMmۏ_rמ)ߌ[Vn5jϨ~( M5óΑ#Y@RQK֟UR;NA\HQb=}08?yVpvvvqq)dy}bD3H(hf$HF12R"Q"]P |_hi^lQޕuMkw^ ,AL̳cb2srQ+Uu~.g/Qkw"ec#siQI)y!o^L)J[Xe߷ 7([MY=[%.s*༏Mzt)Q2bmv_[Ͽx߽̅/ tDOfqhn[JLX+#snwY*54cGkB‡ s˲FF(@/bF"c2T)XL-Uh$rDJtXo#d}VuHԦQyOnh@"3?BmلT7;>7^ۤ~}Jbtن;9VgsL*_R\yo>Mb1ݻT-&fL hkw̩Bkpjj?|0 ͥ<נ@Hy,2M#%10ե@ji.b,hҢFe l5&3ĔյMG$qXP_}WS]M/a.C/SQa |cJoP(#"Ҵ2`V!7/c _^)JpbAwۏϟ^%r1.7* jWwݍS ѷ.4e|{)݊}֟6ӌ 8U/QqݿV5oӮ=jXXx8eY<$4>Uֹ˹!=**&d#JVF_>`>MKO}",Qxxި36Җ]ZI4~kX?l.g. WaxͱgfXrVVJ[]q1 (1M 2 q2 s29'R+RTI\ރ*gWk'UZVP!7 *Kԯl[\cM嚵޶^a_RuGy/-wb/3olH}}Wu[Rζl=3 ;,eTҎI&tqishj Ya+G4'?| RT ǾYKK7{-[kJߩ5]u;yV)xʫQM콫|:f9iӖ7u[ҮZu*SwnKX0𯉓gm}ػ^oW3O,ƺR#3waeɆVv6-=e[t>4kAШU[L)5ҭKQH~/:"'-t84 L G--eW:μTIvZvS#oT&U4MMUq ae)Z{omti\~bبӜtb6 2۞kZ0~ ޣ[X &\0hw>A5r3nۭNl96%i:N=V,UX,$@҈>u,'?iy*L3!tAh(cD41"xDcDa@ !iGu-sI¥5صTls2]S"OzUo\QSbW%!ڟ^٤pj^XrqGA4 z֭b ~s 425A|PtH$"F`DH1 O31EQ@01 '+ZTף~}7 ܪǫ:-&N0ͻo-.h%d,Qt>=ADai'%ESf8) (@0c@ bౖ%b(*͚Ro>dLj2HlQE+37{DAA2]ZmbbQ_TfIP?9+hX f-T@_q>=BAo2]DRV-Z( i?J GAAgu=%A;+( LDWޡ.  br(  J^.AeW/]JLLf1R[*x YtA!Q~ bЦ}oxl/6.su|IqBP2F/DDDJII.Ј"J~hd࢏@ZÈ?nčg_5=B86;y"yZtAl%OW$I7wPP)Zd|@+e2E埲K$"}tܹC Ό3.^xʕzѪ&֛zsv?ʇ+ |5ܵMZ۠,@:5mߎ (X1dF𰷷/"H:0((((T>+WwPs_2Ϛ@% w;!dY. mB L+wd@cI;Ƴ?/%7M%h.U \b> j)S4Ќ@шf0Ec#.i} //`%ўBl^yʎ#.k- \ѥ_9WxAДƦ"2` ~[._ɓ'g̘ի}֭[hm9jooo_Z7Ȥۮq@b1lN_NS~ZQ2+*RSKXZ|F"Cռmz,zc6{V(+EEis\ƽ^ HKBBu "lSZ >ut)C8,O!XỠ[Pǃc7lBॻM]~8#?̅"$^_րo|. q>5@Ȫو5 oLY]j;:5ؓ~flCE"Ѱa SeYP"1ňQ"_D#BBnĈb?$iXmxF6Ls2]F3!!юM3a*%+Ubi)t wAQѣydK.X|t.{^%> |tCC"XJ}g̖19o#52B1o7#Aqmb=p~>{/= KPyNnF>nOck”~a#<}sYIg~{"4QBuޢA]=Tgd[t^1Ww{E &ԯdooo#6k{FcK6<ᇚ5ZtWo.Fg%ħ8k0{>+`I˭z,\ ۏݻ=eG{ScҐ^g˻M}L?+ZFҭ鰯B!?מsZVFӊv[,Y+AIt..󇞔) +hOn!lwmprrrrruCҫ9ض[шL$/#_7'dȼ?|e~"Je&HiiB'8Ysgh㪞<}wgd^+a#.2fqOB =cs4ݼ?J'r6SRZ'ur?ɬjs.gijj` #zwPbbڵkmmm Y8$b@ # @Q 0F@@~TļNYuܨ խ뗛1IiJޅ$s ZիWHβ7>{6m#Ȫ Z;+=,ݵ>`XFc׉N\uW$ݻ}0rQIzC۵!sĕ=.W&& Kӫ|mjV} T)37\Z佫7p->u% i1w\Ɋê7'u]kurA+KW~0&ʸb=BHpηOmOzŅOsA;z## @axH#RF*ST*4Z`%:XrO#512}C#}QB1-m jķ12: 5k3kɡ?yQr) b5;x8}kN#[ηҭgىi;8p֜i9U/cX*(vhxL)eY3\ IVi^5h@=9,lUʪh;ZDz8}\_GHuetrFv2ٕS6&p۲e.q1C-P(Q( FA |&үu޹ )HSs|r3 Z^I+WؓQLMWbߵڂn>&  9He2B@G|A/Wthc/G2]7][V乧|lazu7H TY>IjNSolY  /gSS#Uwm m#ۛ3FA*^)t䔳W)۹@ ֺ_ఝbT]J%k!gi__nN(`P /ptG'}g_ `NT41"fx@Q,H+JKu$ J$Zj*@  TBAAt  'AAN$%  Ji g@4]m  dd2 !!"mh4"7&.0ivɵ uzgB e2`ׄv!NSV;Nq7yq/.m*!EgW')>+snUpQ dPoEwM.)mBh£/ B>wobM #!^x28S:ǔN!dM.@qͽRFB8NJ S)#Rb2#2•q/NORY>|>}b_CQh0)]0.#<?JlNA2]?FH~IHFaGi~*6~GqM*٬cՋL/tJW\KIOzcY!gk"|Wm}5- ,GDo>|KmyYv|?> gsJ(8.W[,[~gԮ S!v&JLWmYӐ.`lcJ5mڴ'O<˲)ggm钴m^Y;z*rzowxCf#Db`D(tT.VfȤR1[k7Bņpz& PD1~#%W|0ήӁH:! si'sIQ!sFwsa(bF-Av:Wc'[S]C=%\{ hfMOڵHdsrEF[nPB_h|C˼+qݳouZ2fOWPM^Znt;L\zY{joX>y&SDg˲6m*LI!E9>.U \b> j)S4Ќ@шf0EcG$}ʣǑ˞i@h">7u?[zYذ_ JC]pw_v߼AP8.'L>)q+6s#D%[ r6OVU:զ CrQ u<:&y3-&^kʋ3?2[4rqiNn Oհ_HjYzgI?Qv|8Mp3ogY`!.5I\5+.bjÇq^ rWC Xs9CR^H$6lXaJ,+P"1J$vR"1E?! bD@1NtcofڠZDRص5I';%Lhm}IQՌ:VV{2 ޿.fA̤IJ2OHKPBuBTP^$h'(>sn͎ӭz^+L Pجo+f/y;xڑ">'>pڰ[.$Pn$U@j?|*O; z7X -׍O`y5u=V;D(o!$H,X\lj0MQ 5QcIA;*̨X#+3YΖdm nxW]x>72>ˮϊHrHlb`g\^(yY؈HHnNȐʈ ꦤ: Pkr;AF>}{׬tKK~çqUϋGK0k{Mq+Ə Ύ0\vmsBeLk403n>P."1Dfr(3@_RwMY;GmXg6T!Px $zz 9WJS#1J'r6#0Y/G8JS=4Ňb@ߠv!-u=nK⚼u,% RU?4ԓ:=gP]Hqa=*mxqx>k=8w{jg<@'~e K? b'O8V/+ S+$)/&֋/.|  !0H XċE4RZ`2T+a:| *Ƽa}t%ƌc~~OKv˗~)sFUT> vC훳##K(eqt&yd0!2EY;b?Nn%Q%͍;y<&>%ː|ȊIS~]+j !C "ne)VhG {ky#DQEHDEQlyZZsjUKM ~McKZZѧgU|iuZSuKb$X0񓁵1 M>~?.q)Cb- 7Ubp2ݕ+W*$QǀV(@"j Q%5Z#5J-5JeYR$_N=Ucs)y.WVVvY>gQq&Go^hT>qO7 R#Up Z „?Wwc4'fՀM*'EɾӔ.Uj;k}NƘmK}w4"P2GubB>V: TX{_svSU:''{NeSP+dO*_ə~oqcS/ʃ7{*VTh,ctr,:]ԅ^}SVdt\fw? /H/s cq ܍"D("B9>u-ӭo[uJXxvvu6Cuܙ͑f}1e`37l{0m&2T /By)Q1€ !˄«/u!Yw(lb/^86eF680 md R2/a,c S(DL͈,K'rCr#CTTh}Z&0/nWb[yH0 0Ō dFDzIFiÈ!(q̫*\_dWuXa?tƪX<$akl U*km@aa[b1 0 0+`.0 0 Saen||ZF=Nm),B<<<bBnάam R0F@)N{=ZJ-G˼;:wla+dÇ +*,ScZN 3A 4 !Di  yhֱaՖ>m\؄_~ Y;a$/fZP]* < c/ܽ{w„ E_EeptXiLuӹ69јuqKƐdm] 9Hy䤈`fyaWF2Ky,];/Bb 2dK,#;[s*I|}qy$H'Cnhjǵ9B3!: _|%I2)I3SrR?1ΰk\xuM!_+JDkHK*ad^:VVYL9׉ bΑQE{(vdYsSw|bIEΔ >w'巫]쯲v<̶}UTna!ڬK4bW6:kB4dLRj0&N](Em]]gvtMwӪi<,(Ppt9wY$j}Y|.5&]5S!mfCVE :6Էm+ڮɒ11XRͫ/߱z^]Ziod@J}j'?PrF)]iM)-0T/lbwk~{`Iko9XH(JO,.7fU>۷5v w6Z Ek/˹ _{0`, =YxȞdYN(jއ҈Kz Z{رcn:aqz̄A[RX{.*3 cŚ"#r:,xQN96UƺnaG|#:%¶}EbŨj5<T5_ZZ3aE))"q< PPP`_߿s^A*2ܔd_B7yFn*ڵ\R*xhHQkV>[Fl~+PZ.<ҖdbѝX٠GGEdGG?md3o ƚ2GOm?=/-Naxk'S*X1wms+ߓ`*fnxL!M޽{SSSm-$/C(゘٠Wd X gg^{yIgyvz~ڂ S#4WNQ&5qY~ܺkվ?Z#l+2RAkWE 22Ƕ3!R9s̠$IbcL1@10ÄX{޽ݢ ߯ mlѡ}?|;?HZSo- FzXr@Tr"^3b%yк`Vc2joo}o~[г.16:+ϹmNkOaɣ/ܼk+TݠaƆR8rH4ͫA2,v^@aXa} L y'N9?4ۓT ;pxy7Xqm䥍u{3J+emE/` $H5sAYȋ:BXxqٲeX^$9 (pE@S) #0P0< )R?W;ҤfNY)y*1xˎ`IhV!d!o^Q z)}g;gXNxr0ͽ{xͺ;lŢ>N騄4Z)(͛7wuu} ȆZGB9T@_:E1!MUՓr.@μy>VOLU:, :k=PhtJ:oѯˎ;֪~ qKVRۊU7`jdcha.$QVtK.=rȢ @C3<$0 8D(s1X+DIt iP;89;1}Z{V+!ScD Oj ov/? pUܴkwQe [^ص }޽QH9Vă}c'/*V9[)&*ru2 ,M  R߅bڕ_w?s/OZ^]7ŨQԁ]/< #[~؁L6";:|PMſjV)̌<]`-*sOmWJ>\@̷') 2owT# zm꥞D2~&+oo^x! \PV^݂ZwmY&Xāqق{=Z8`52s6|ߢ2Ԯmzu fI9ҴiSww~oi?"s;A%RɟgOn7ٌ9kOz|cXX(XW)x.&־L~lH^ڍ[CHWoog ͸Ƿ//BwԶ7C!bmt!B;bo]!9N\+W xU$I2+8PRERKj-Qk$FRkdZTkdRIJdqǩ1}k8aJԟr 05&5Ta 9hs=}ͱ;5eIu{e // -{tXwD6jӶ]IB}ӡtՆUTQA{L J|t|N<6|t/.͋;`zǟOO^6in쁵K1i?~pdqIm>8l~yEκ}5ݱj3b[4mꘞiSAULqJ:y>qk7_)?\YWb0t쏸'@{|SM2aD;JWZGjAh' 9W~ͥ xuYuTɼ>RtzOjn1?4PHWEq'h]7\6fsӣֆթ>Yox|w`[HWc̶zG_lX؞R۸$ӷ]?GQUߟ5TRĝJ՞1 IDATo *]ه5TtV"P^^\QXР4'Ku(7QrJ}A7իz|?;yZ9X]83Glv2t)]TwԪVY;h%m7qc_\62]YOxAO9b PTX&Dby=_@l`^^\!uA n-ߝ{MStt|<P>ؗ )]̏4~jtwDp*uy+Րe$n\U U72&ƩumW]sD)5Tb%:g=I_F4 p-d*z8k֬Yɒ%ül# 1ox cc0bD9 djFdY„bwv̫[tɋ 4Z;;L7rR3s : PcA@ 2 rR*Fr trN //WPG {>KR yY"-% 9)zs0ρ,BEL@iWN;bLdž<s~̫8M6ai6%JdW}?'o5# Fex2zRG#[ V l8~9ݳ/g\;q)PxwuvNJ:$&_8vC4> gZyjN >nE!wӱ:6SBÉGgb=ZTnj^N|p\N>ُ^GW +iA8! 9 )kcPaO{`0 <8,,߿()1!$555--*8JKK2yy_5/y{Q'üvalPn<9?nnج3!c/s z0?ruӰuSJ ĉ:m,*Bt(U KFP Di3=~Ԯd#`1 X[o|T+K6MVBA]tYOĤߎOm +r6@aa浘4Brl43j*n̄.U)?)ޚObŊUV9y^eY)<n.xR@-G攵POK ܯvI\5˫wz9ؕ*W0ָ7ߴY1'>hhG㸱a.0 0BLc1LL+ aOIoL!T*gΜTRy "FYs|J2E.K~kWRNϥ0 s?|Mt!~՘;}M.DkcĪCFڮݓ}Ex;Ҿ~UktdnC% 2]aa^>p(ptĉÞbu2]Bxe8>Z_NNNgK`u * BɷRQڍzmr̶QQ~J*ߍ:뾟_tخ~]x(aa^(|}0ۘ8U7`jd?)ҔB_t9s=J)N_ KG*)9PX N3]p*_9[rN~ݩkik}(J}F9,rDJ13 ͹s͔\b^Ƚs%gH[^1O,eӔ{3xb_^nҢƙ`&yڤT֎1^NE7֎æ['.FCDR敟iOVtW\RBhv:'(xA)*V#h퉝l(9IA8IjgYH"|`KfF {Ӄe]sUŖ,Buy6xoZm__vэܳgPǑ 60V455/" {T;Z/jls#omў+W~ڨ-?j$%膐^SNgK=Osn[8B975~xv_nVܞzlQ1fR]=ym4jSJQN&&189s2Ɉ##)` d0'S,ػy;U)OU(GvÝy=o9}S XˀElw+0 uge\.$-MSܚ.5L&utkTCٔ}M/s#a^]~siNZzޕL^;z9}̚_C;)k߈]ƣ ӷsdKx+i{FJ~>ZPo}{u*Jѭu!*K]ܘLT<ݸ7sOF+'_z7:u g? Ue囮OZ6eNJ믬(bLHDGsq7}WzOmd xwiW%lMQ.9}}9h0SSuV27%iMVM}}v4cSXYi%]3&|fau{a[Q_a޵FˀOfm.׫SƳ6[U P}iutZVIQtpgc_r4Q"_c.chE=@" @=~!S ̏JvTk/=4ttI/H}1}y\_IBRR mg?E)w?Ү"<Ҁ-G/9t<\ i{婲6e1zjٶyTi?^cDdf gOAY[C*k!蚕,e?6zy>{;cl U*km@uZU2bƺ{sѭ&:WRl4n1dMKv9B~)wW 8 CZ@ Y9Y&$&֍|<%ˁJ0~2ݚGiSv}uLWx;]\]K4zpoCgh\joo]~w޾l>>o}lSǫM4p,Ye@0 zUTPM\ @H܂.ğyѪ٩i9u%2=bDSLǃ,VVCNdzbu7'^_'dvƶhz72_,oeb[+w~'s+!cj.%9D1 1fe0^Q z)}gDS>]sYre@b @ ۻ(Uc^,a.wp/^OQF|,GnE89+H+U\­$J:hYye7%-M2 LOfF}vjPVPhCaQr^JFQL(-2<\Wk)ёQW..kmxۗq @rn^y%rv!qR̷"xF!~hB!ߗ9־_OgRұuE%덲dHz(|]d|nMN=upn^[Pc䰹/& P)756f`e W EN|uqyL毋Nװ/4~ҷokͧJ9V@>ՕqO9{Sʋ;#n(&ߒUTmGyw Us>g>}sMy4ƶ>|V\/n>}Lh{?UnՎ!?͞պE^أe^ 6b1h(t=Ŕ֎ak6BIB=10 0 <62xZcQJeY&xxr؅[azW_3N`̻62]AcZ5(ŜSiݻVq!1+J;;6WΝꮼ YF0eB;|P??"25f$P@!<D1*ABDQRJIz_cKs.Ϋ~}2o/ _g(Wqpea+dwޝ0aªU\]],SQJ &9e1NS~jY&&&"(IJ;G>\;I}z> Daa 8~1b/6}H^i3oQZUȞZ`xyW-4`yDQ\bŪU^XR$L %&SR!JB RQ_Lw8nKiK/)y6_Sw*)qcVR@bܓ[sߗ.~z-+X䯋{4^yn[ üФjP5hCO~r /<՟3ɱͣ/8iΑS;o}q_GMɝ]?:1~렎~PaȦ }חvM'>f)ؾv<3 s=8ٞky1jzOc'3nQɑ>?q<tlNs-ivZ9z+a/FVa>!g /Juu-{lZaE))"q<0Gx e/-?)wnK1X\kV&SMVT|wk<4~IǀK}t!m'E&a'>t3*lh)~F ԛ!q! bVqYJ.8nQT踨_Z٦[yA)c:`漤? T;=b~WOS#4WNQ&5yKi.wĔ Z )tZ4Z:y:;J UVQKD)"^ #'SxYn-wZz/֞|$R}?|+8?][ȁ(U0}=R8;&~v9K*N3 XvZg NĘ}*gu%vכ5jKˠ-13V]<>{dʼCZZZDZ_w;ƧV%^BމSkiH='\8y!᝿<cbw0V.#志IJKVY'U(/.J]3Im @9^ j̫AÂ(챠C)j1kŲMܹfiB?Bn>^>ێd/\َaW4ejVv.6mRμy>V-ϗ| GY{j B回 8/(t~ ˍq}q oR>X*]1=3?:HF\ҧ·[fs+3O3ٵ+U/n4&wԶ4e.]zΜ9e˖-*(E00 AV&ZTM*QUjJkRjJv2X+DeW;89;9{eΙ%*H)K}swyq7?_͒|&|!x U.$V:067gGFx|c|PJ1uG](DQd"IEQ< g1w5|=_7P9^a 9ߣc2 y97X=RZIK IDATnG'xeKk_V R-4PPWv˗/_>'[b*/36s|I{]2\=u?pϐa'f)-[ /+?['*\2 V$ʔG<BJQkJ-DIUjQU*ϒJ%)wcop?N:al_k/uMjXsѤ3pr=*>iʞ6,⦦j*0¶^ja xuYuTɼۺ⃽{(H"z+ f^S(" 54J]L ?+>ĸ=9ive/kcoM:Vvh71<@z~?R@ΩZstr0܎c~i98Nкo&kňa^Dvpr)cƁt5l[껫=/x5hͦ]#˅ޫo*";xc2j᠉[ysI+-vfl dFDzIFi*?4(< r}C!F+4zC3IawEc)io?zke}K05jg+/i:0 03kkdRsm_5k7 Yt,I4Nev [~8I$΁o4Öq?PJ;m.ZM:uyWp mC?,oTʸcvHRGS#r[j \v-/ G-|H.k}+ɔ?*C K_C99ioǚmǝ7P1~z'-B_68>0 0̛{̀6|ok2lUVzIOAk;vl-\QOz ".hraumZI؆̮EWi?F9XzL-}MDB~_\Npkj/DZcnDO T O2qw'"<{HM5g rSE韾*hr䫰UO>̲411111FLoS-E:2 0 2J\˅@7Q,>[DJs/Ƕg_ShH3ܺh5_U#nɨLqˎuy{igεA֧@ 7vl4 ̨5+u-Y@X[a]l 7X(a J9(Or]>E60 0;D\x"(?א)g޽`˴I)1&Gjh]ݴi+͋s5&(xSl䵮$ {C]9TG7mۥ[T}W 95>>o}loFzSc_ӐIMC&-[=Yܿͮ4χlKh32]aa^~$y.Z<33D TIy.nbkʖ;VEH^TJv;S4Ή7s,-@-Y+`'~1HJQ>6Ɋڼvw䝤pPXU[8CR9cu1pbbZJ=cJ8UffZrʮT*r;!ԹsgkGXMPP ob325 ><44ϯȲLj9 *P4Q3Jh4 QHz_^0 I;2ng۔Fn~egx:kGXA,yb ܵoڡ0 cwN0!99Ȳ ξ4MRןn:W"10s.nI=csM3ût!;9ܾ0 Xzv6&lʰp_NLO{CXp)'oݦ}.4;MRc~!<߇ҶќQ$Bv|_ J97wկa  $ 8eOt8nͩ!wځ0/a-t.&!vW"X Q4a _|%I2)I3SrR?1ΰk\xuM!_+JDaKL9׉ bΑQE{\nWܫ'n&b+fz$YM,fy KIsj1ṅ?1NȽWǿ-'?O0gW8Υ+Yg`R3w馬y>?l@vrͺD)ve3!_))Z'ӥ 'FGG(0uQ5=rtׯ"홵]ݴj :}(x T\3ԳkF5@%*0껿ݭ]L:fLCs3ќ or l鶱a So:x7>񎕇<`ȗzn'%w4^J?.YL[\Υ^HHZ\t%Vcdk׽m~̓מm-q~}->_c̫+Ƥr.c{JU)i/5̨u1TqFWnm15[[(+V(JIIdNH$?ʕHRbTBĈ(( SQ= s;G?{K~> =hnm;#ێmSktd=zjw:9sX\dwlW:Pu~yxo$ngFS{Ĕ]yN>cn{<~35uXLǭG-t rlZ$˼M~ȩ8&+bŨj5<3v g.ZB yA8p`QJH@(hłqT+A>:~AݕtD >=_=m@ݒJWnkGe\/:; Z]^0̛@Ll+ X ggEM۳_64DSojWDž3`Yr$Y;j|ŽL*9y:㜗tajG-&5rL~~~e%ljRs0qC<#TW#N FKJLzB**,,VZE)/I`x`o6F y`r|~%rvCW_Om N}]ߋu+;=6%}},( XViAe*8cf&9tmn(]ojOר޹[RTj̙a`@P@7  &>!<䑨h`HTkF%0TbP %1Wj$(#/f朳㜳wWZVUW}}?]UUk㗝/?S7?ڶ{1g?}7UwwNz{?l +z7|v6116>6dlb3>e&Wt&0[v&V-:cSb[ $ήսbkܷ1_n+vZ?vοܟ]fRC^{|}N>w'~[wgn=>N7 l3}_8n7~9xKՄ[}^}:/};|ʵ*Q+W\6?~Wo`ȴu=wϩgH6-w*j]"ݝv.좯2==nZ5ɉɉMKNmZ:qjҩKoZlKbP7ߑ/g/mCϘo+cYoxƿ|kԛ}.}VNl1\]Lz3u-h`L~__onXϝvAo~'1w}\;79333ݙ܏W.W:u;eWo÷䡝b|ŧbO?7aMNNnGyGzΊw\B w_zꅻtӗYc:_;UGaYg# ޸6K'xͅkg3{xgljߓ~|3153]>rKOӷ_8u׾&ow?O՟߫|"|_'Ҍ]ۿ~-'o/.<~ +Omqn33>136>;6>3>tfXvzv5zv{k:ݞV+vT Zܯ7Y `|U1vbIob;>1=193>>;6u:1v5=^tl3vM5'@QXc{ƱNg1c;fޘ1fژ鞙-LۛZʹ;.`dlƍvg1v" Ϳ]gLgz ҧ/n=p%8g3t,Y>Ϩ;2xۉ_'~{,?M#/6ZL{>3o{aK77:ۋ{.fo]Cb{u-Ӵ` @UwO~7Wܗ_luxV{gg6=5x>=_noOLA N_^r;;c'Ykw;^ncle/~On4Ƙޣk<`Wk{k7Ɵ㿴s}iǼʟ~~}Gzo}/^mcw1kglX Oל+_73/{mkV}䑮\p+nXᎯ=g{k߾{S7ٗ_bQTޯ?}'5vz~/|to-н˗oG|:(A 5u7^qNˬxf/|lw?K^wΘ??x}]{×ߵvct}}W~Gݙ|z~aӏ'}1\q5\Hrw}|ϗk޽V7}otGwymm>k߼^oíڋv]o|a\nǶspwӞ}]&v>9):\s7:dwÿzGwz .DڷO{.[On%/#v0~y};jkϿ3vlɒ~z`Colԭ̽W_-ؖO?ģwnLc|Nxϡo=a'}/X\NxpC[=ǜl%O|߱uɓpg|%} /ʟetMN>rmvnSHwl^YSͿmWqI^'<ל{A?^9w%fglNz?oxy?ķze~={?1_v̫U>v;|U~)뿵Y&_mz׿\VK{{Ǐͯ|w/{ W\v䤹ڟ}tV;+sN_5:'D3lʕ[-Y׾7?cϸCM77~nWvӮ=e;rه vUO\~ǚf̎3Xê\̟Զ;>'sv[╩n{9y_nI޴Ys[:9q>& Zc'{{|߷%@g}r^gKvw:]xY߹N?ru3fjLώ/zVu/|羅_~˃=ӛ^pƞ,fU߿v;˶5?0\.{!o<#7~O-?ݨWvggٙw/:wpێzo]=>5[ӿ}hv]Vocosc.c|ճ43M_l'V k|,m_gNt&u_9ˉqy/{-ӯ^r~OGRk_A|53f;OU懻^=|o:K'_vsv=W֗G{⡯98?!Oկ>wͦk:*o4 IDATXO9F5T-?yvv˾G7~Qpک|I'`tJ < k{K{=\.D@D 6_p[4h't@;A i~p]`QHhx*}ph't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]Nv1Qw5]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h't@;A "]NvHD .h'b㛻Qw`֟o֩TpM6s>1yHi7߽_>-^V9MV T?秄 ]c1+P`PI#7 **5\N@RhIɅkj&+E"JJ(De1DSfƗRFeaǔZ IGl1P:f$) e{S/hos5wSΣ>`fjFHr*a[}aUkjT$kF)vTU :JLc[H( ÔeԞ8QHJ|dF9|ŒlWFSjĎIv,H3(NB2_7{0t=;IQs$S(m|k,|*0N!M`WI!J>*Ql=7EOR7": miixq"/dpHQ<aB_l!m"aeL3"صcGgY}\MR8-*KuJP&;U"1X3ua)kI13fAHy1_ ;ь ͐#:Rp%3bǙuߡO7)>+)]MJjЯEPCB.QavwX+tUYS>;,Xb'{BT& qQjRGM|MIA$|b9(VGcã c$xQ+Pƾ#判xW.HԍbG]lNX-r#QID?#xzibEӌPxZP`Wm'* c*KyIC_43.gM5>׺0,qNA2o]\Ѵ̕Ԥ(&MD'2¢>\J3M-Y& m%3ܢ%p: Eݤ1u4'n$r,1]Y++>2&UVhgHeKUO$F^]ő-,E)DSu\_JJT\"ZcLOLRv'xX⭈dI1/BRKZT)HjK$JJuDR$*pen[ۥJVH&ILuHBb_N}ay#]Ak|)FĔh#9aGGoB!e@hb,2ytbEݑEraC\rDGqjc'wՊR-QXjLR`Oծ ZQ䍣HU][ H4?)ؕZcz)&%m/1'1$ϢG:* }u7Z3f-m--Y҅Z"e ÒfP.pԏxm~FʰF" "D.|BT$ PԖW4ra}t]##g)ROBœ7ODBk4G-it(:I3C,g:UTI[k” sy Ec 9Ӂsޛ|e\+[̴rPkKdZ35ÌO7'>+2'Dr'sYf$~fPJZ@?KQx5 -箑Aa! UxU`S|#,N):PQ)$'ે6{;렲fKmvwI6Q{ֳ-Wn,~JCz"ViJ'i,G2Ss+5We3HN}e M.uVSCӪd(cr LuE@."n5-:Dt 'dTbgRtk\B_\sc[}iΩݤF^?,b,3PCE[ ɼ'\Z &ԵH^Il<Ǧqy^24} :?jcZ̭/['f-]m?hlP ] bUn3D{3~ $}G1Ma"1)&9੪G'񙸫;pfYE"Y&5G)ϥEdZ0)Σ;\ӺӋf2/)25`j1M; UQX{Ӎ++Kzk`Wa,;DKZ,:p hptm2"; ĭe50E+i)͏F?#46%.g6t.rɘa51;{D,62?3S{>9WOIrd3/^ Rnr9GW 2|j^)O~`̑'i\LJIR LWL%ihj肢6/k-JTGiI%jWJ8}Xcz FoWRN=) 6:dhRw$$E= |v@ nթv5yO7}eKM?'ܠq]TˢzR dskme|G̭:*LIRGh -דtԊʥIfƤĨS`K r|}VHp*w2U3&꒲}j襐焪٬TF|:?݊\˚Xٔ$&ܻ 6 + klHo+1y~2"*͔Hms+;F`9%N.c]'2MK6@:NӜCդ?CV2YQ܏W4 g jR:Udt47dIy_?\~#u?XIuT<7C=V,Dc g&Jo臙Ww(IJF89[r4A`ːNL=Vk_I<5]{ GٽP>#dM&:bbP空":ǒ $s9іN05 nfDѼ{A`1R9"P 71 4Yjer)J^Yg@v\M쳓K ?nr9䉓mr5+J>j 9QN44&2R%%Q J8"3}FN_@J vil{(n';:rRp#9r)JJI%6m6;aL)W!sdqG3γޯr4@ci(\Շ2L#f )aMC?ܹӔf`X\8ҝVE\ ٙ4kH)|PuYUp h`MuP&6Jjmb )xjrɀO"<. 4A#gCCyQON]_0]hep/4S[\4y4aƭ%^Ya/ja3"iea3$y WI=-Z" r%kTv^McQI$R5E34qg -I4UF._^$I -QpK$: թѝjpWW!QÜ\;_9(2[4جZNuͦ'3i$I- &}aΠi8дwBrF݉Mb & ŲQE{uL"K‘MkN,):1m0ؘ<33/4Q *Qj.nCJzXȉ%^Q7y;ȆtBO@ajdޤDoK]5M(W;yO)K{Ƣ?\aRn]ykPxIXrũ㨑*鵢m0%uШ;@ylΔ HW^S-K'>8x^Еe朣 A9d_`e)_9hG#[c8@DnD ({^u S`71 {hDtvi3?"LGhyvn\-E6622Ɔ¤Q/EܘRզy"hݑ(W&S/IGW :X q לENGaՄ_娥ЗI6a'.ͨgrInal,?/2)OQ'g[OVY5d] ^,YLAISWA1mY14!Wm9%((d`L"vW!HL UWSǏ$~n):Dh:@ IPGɗWHO" 3cCB^Ml*'>T6su?)dw0"$"Bd =\H-Fid!݂k0 ~XI7Q_јd.QglBXtXvϮy C[jH|XC^,a|i9Ӑ3ےF SXdV?=Em Kn&QL>DYuf<Чq|HE69.UM_2R GP4U|ʊ:N(f~#M%Ol/uHX URGⴷՄhJlZ85DP* dj SR2erSiD1HnH ޗ,[f 7yY |"g~W2>UH5u(vhD"eҽFTnϹ%x>OCUt yHg~o`ilDUCeѫ,8ǩLh9d3G#ZdP(xNNՙVkcb?v_;jqȆȀFnVPi2eIXj;7\d54 Wt$1@bUJl;NY#Sn.l)$X!j] ,_Pe!{~3 [jE(՝(,rL 9o"k]e_" E$YF͸[A(Cn9\efp7)FpjRHӁ6'>6`_% E6e p9c5vY3EhQZ8'ZhUaq0X&Hs{>J0FJ%ΥdБ]L\^u_Zj̹\x$5T1I3?#&&*z}$4Y{mC&'FY>xK[45JI:R2݄'Z$RTKğ !T H{}z-S Bҧ9 g-YǏ!i0gz O^ R{] R0k9;oAZ+2 \C\tH7þ:^ba1F҂}a TԙSHI6,-&FcjC+ Wv+/N}b+!Q#H}ӧHLcG3雪"wvΑ|]d3$C {t`ڢ[/3RJ2&]]+LmŒ>ީ8{IjAw81# ţj0Ƥ.4ې>yWt cujcsDv&}TF*G>@IYF_`{Rt˛TO%ybP2\O4)ƣNj(N=|!}+<$N>$uMgIr 4v|5D' t\U2#Eﹰ& -»}xc3Kt{B,5k6tb Ҩ v8I֤m4WVZZhEjP\#TJ ry[5Zf@: YIНtabxQl? rvcfUk??K$jֱ1"EГ{:x):.TKqFh87y ΜnL76LEXe렽k.cg#~<aјJ7WYaAYɅ-ZFDZªV Dd*Th6@v\_Q^rLz]1$ޛ⚪Iei,҅`[Ф޽K\ sBhWF׻`+!w'pu[YjЏ]G&&4هxt:N"QqE>0D}[VB~* d$n4 < "[|;W+0gb^LW\"N `ycx%TjWEOOZKRV,o8Iz76m IRc> k6&kgR, ՉsO}{5fbRF{^ҹ#҂W̵Ws\'L e vH*啴Va7:yJpZb*r Zq۔| 2ޢHOΐ(ãQ$Q'Ҷf!38O (7eʢs&bDAmU()E6B#g'A3S5> Ya[[MK=[XbBp[/_Y9n'iRVrVɹ/LAf~S/C P'E(Pҫ0Պ]1I.r2#y1CTfNd?Q_℠)6$ӧ!qP҄K䔩I,?55Q j: RG̬RMLO.$3Yz.f:nO}!ݕzree2 x8B։q5O,'N6}FɈt / L^L ryi?PNaqb'04-$S̗ X G^@<.W=H+gF$fRe0ޝ@dE(%A|ም/p IzLEeL~\e._ s ^ޯ[D<*H_eT[0\ #ȞG-(&;~ZYFH^J r!eO?~p rC^y= 7F.WJn9gXa _:!] ׀Utn41~v^BKL%JndEr*{3T+HI (A.GtJSs?[ ?3bzuϳ&U7uEvw'У ߢD c q :O8k#`(Y,݈9R)襠n3pra;@v;|j1긜DϲR.TyCE.Loʈ#x(mZʨ~5J-_8b&P 3E̷ d^gfPk­GD͝Vتu1ړ=wE dpUAq(^<O:Nvsh~f:qnjU >.K92|k1A^B'BǕ6E)Gtʢu02!SAFlVW6_I[q>xtU)J.Ug_a… XQdA0x/iߙLtdҽPJFo"o%ʾҫ-U1hy^GheTBrmnW#7KDawWCUIEgT $ZRw[9n҂TÕVl K:AiP3y|)մ$N?:n " lb/rWUk6[iI^TH߇\vUAWƺ:3(/*ab14yrg֘\vᑎ&׵X_]h6SqVdeиSu.z0 #=Z}$6:x)Qb)aZOTBb)5/1C>R4_LK1" tb :<ث1#w/_÷=boF#kA† ӭIXܝOV-iTL{ŷHoW)4_p0_AQ?zpSz|^4oR#.Uw%QG66>вnV8Pkko 2Ҕ)-K\7%,ݽΓ {lrj8hU@ Zߚr (doacu>ѩ6٦C'Ҭ<+Ti֚OT0UIO}ݛ{ԦrY%I+vR}UyYŠʼR2{\hEDv(/Y?%vXebXȱFtP;O$ߐ(' ~u&d)؍^NR^jX %/^0tZ ,']$]LV2z5͈L+KHP\-S-'PD; Kn㍩j1b\3b >'HD+ )^#*(bU;eETIFcoܱܨR?2JNڤP&Hӏv#zQB,-+mf0@؅tniIP#V:1 }v«Ӷ3>pzЅҩvRxcpW mHRC~t %#+, S'M &Aoc]~I{8mzUuz&9/ϊ$Efҥ,<$Z& ωV YZ[}p|:WDGI𜪙>Hh 6OMqt# 31/V(S\oLY|$)!q?QR(PI^ m|V8Vl}1j)9+-z{-k:ٕF0ԼXfLt1}vgDfjƾ奂Oh$,9ϊ(}g8I7$7pZYMO<3x%imnB/2HDsz}2Ft7*Vrʤ)!_h?à\P6ʩFVC/]"_!GY}ZOa`;xqjdEM0֝0a}.g}a C~"߷f--ks2aAus?-$ PP6:- lhrMo>+J(F:QiU-L:a5-UZ,XiB"m/ .mOL'$}O-/}oGwgtC\MܚDo+$O{ %XQrloen3M`o8upynU$c]խ_JxX5oB]tP[97OU-畷fI#K`Z": jCI%&PL\~*:[GxX\X\yJ qDF$JDRJ #sbWi%*1}TJ7! %Y2N)ISA;Kjw1(HusTD8V])t Dn菔1 p]!733F,Y$v5'zUX{N#od՚VY%X3BdMx"r蝀Ͱn.whvDSSR$Yi[DbJ: dqy,Qa#1N1"I-WVsqQLS +Yؤ\ΓY?%L 4 Op\o|>݆Np=:CxN[`}%nR uĨVC~ŘaZƩUa9h-0 g%ߚ}rD0=y,KTIãrjkLn.N:zWWJr2 C$N%jXDLjdŸ<ћEo3GO %rvTp:OxNU> #N?83Q/nr)8('d9C=^DKF2l'@6N8A]{'06u3</ֿH٩ 1x_f-d>&ZkLϹ]i+?a+[Sr%Ĥ(=aݹ$)"UK)f-IpWsEx>8lU,|OcɚQIqQYN<#Q5J#4&VO$ /NyS<~eGVUg1HH'hv R$F(dZ ٶ pҖн^x;P*Mc!?HεIQf*[>-knڰŽך]oľsg\ٚatB{{ 5Wz6w Ǩngp bCrE[-D=*}l0hIiip"bdI%ZB1'poѓOuG);K2^,&n%hWSUXGM!B)dtp xQ%< Y BBX s6edSJSֹX;:3uiJwZ0HF{K)cqtB(F %U ui(Ȫfˊo)"*<%\]+%N/Uw}QsÎ([̌h5uǻ(Soϓe hajA䠇^.1rA20IdiI4X-dPRX<\ulcM{"5UmpX%;"㴻B7C;aW:K צzߜʱ-uL! Tgr? !cLC|~̿Ҝ5%Ȇ$ꁂ\i-4g`K-鶖D9i )-13Pޕ G?\%IDAT:2CES5t]ԈKC0.r+†LK%Vrs{>@NFN#Qɞ"U4XC8̝ U[A 15(Z`]>]98= LK}ztG&gɫtQca=UCz$հP8TRKXH (*UdT"M0B#NՖ<'Bk6#ǟL8N~5~:mPbN,^;ht;Ej Vu/gv@ xÙoY 4H1xzek\ca]&W(M<gBcZ{aߺ" 6cЂ2 שKf;~KdݞTSYװj[8_ ˓4OOVI@_Aш='gY\loa_+Ue7}+2H N)<mƑD?=v:ܓkNqZz 7dB`*Rͪc̬ >(a:X@atnG1qFB _r8>S Α;kQC_;%?rMS*M\xd'i>g{+a}Ͼ1_rֱϋSG3ߪ &./neF넕&NͶdNs]=[S_4No]Ӝ !0^JUKN=u󼨺O?%qEj/^;iNrD Lq7][ f2ވ%ᐶ<з,CVrH ^\Uk][RQN0-J2OGBzoKuGlyÇ:Z0o~5[zLP< K o\UmTh}Y\'IENDB`qdirstat-1.4/screenshots/QDirStat-exclude-rules-config.png000066400000000000000000001550031311502036700237760ustar00rootroot00000000000000PNG  IHDR|-=sBIT|d pHYs+ IDATxwx93M!@ )ҹ6^]P]QkWEP,{Î I RH63GH $_3&=sfv|rڂB!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!QjOWJuB!_(et*A B!{^Z|0p*BauĭGXs@-Bkߞ sWf,v/~ B!5-`:Ze`auJietPڦT!B`u0S [rt`ZJsWQtP5 % !B줤VB94`|h- UTw}*v@Ӳ`R߂5 Z̐`*B73,\X\Sr)X:`3Au׆J歧-iZBV!% !B줸ڞaMS\U(X7Πfp+L#@Z;U$_©B!DM噼gB)Xc4nUu]P4D实 ZN, X*Ui0)*BQCG) q= ղ՜IiZoe歧`i_)ǯTY@uVB!v0ea8j/cG)SX7=t㕅-ZUZo[-)DT(3C%E:*ui8sJc+QARNdc=jB!qP;cbya5wg Q/XI*\P-vMT:[ 1['[Z+ZkrJ{RA?ʍ(Pㆤ%U!bپ)(&gL$qc60Zm-ϋ†g h,tҠZUSABߖUTm]tc鐣t_S(ZJY.ڳܰvcJXXBB!Ҿ X>c\+i³\cbxxQc"%Ź^(xUԚ }Cj_*qVJYvҖv܈v>->%Bb^I\c\+γܰquZxNx72^2^Tbv [CMc.WZ>`ʦŽҾҪX[VZ)eY~ G,SڳP1Wi4%BmL,iŌG u%!ՍxύJZUeA5 Q/3I9QE5Rw~LcQ7_P bv* hK%(ˎElm+O[QډƴѨRF|;]Y!BW PQFl\ܨ֖q^BlM@(I@A-<6TSk`lηNn֊ZY7R `ʲڎW",7AYJ) bc+[ e%BqqPm Ƶ3D]1\c Ƶ|~qqsb!ymqC~ǫyMvdHݹԷ-] N`]KkS2Ux,׎Ĕieױ12ZSrei5VOB!QծF]0VE6*A_mBg(j{&ȏhUF7ˁNXܹ,6JZn`RqZJ)Wi7ZOPYĔ,e{F12JsmW+ ZkvkB!(U3,x>rAP/E@(C{++:r[& M@-K5ݿ!u`BE-ZkPJšXv=m{9>Gke\>_smWk(V\iIB!A=)'Mx^֖zXT[e[vɀXMQ|xZ% ,Ek ,Te².hMAxsSP$"pʊ+iEUhPڳJƝj[iSq3v-s=+ħx[Z GKKB!Ҷ.ǧQuY>e)F;1eSr)c\ׯ-~Qq6~c6RB!v13ӶZX:5Җe,"QJy<˯qbʉjB!C|"/olG[[(*xng/UTe9^LltUF4N$NJTaxS+U:.0&R@$p"(χR1+PѨRVk Z[ٞ6~˘F$`ė:[XbYzK!b}ڶ:/䜻9cE\BV4 ~)Frm,I3.%/{wg ;E/4UpxRFvZXJ&I)=>e@hgӌ1c(e+K !ˮ|(e!<ȿ2`Zlx>rsC x(7WҚ䩹sQdk.䄕RI!e,il,U'I dK6Z63pXԣ-7X=#sxxBb¡"|GB!Dەh4JxQOyVRhQUVR_ɲ4ʋc NRNAbxV8xY볩k}O7((,V-W/ gCVf&-VR">o%BMv3@/3UB{T:g3OQw9h / gY]Cmxì38sjQu𢋨j%= x':/ؑz~,;T\\Tc >o%`G //x:rO”Oa|NnF]mWPXHԺX>P1h-T\\L3yt>QrDN?MT_0!o7q"6:˯+װaCӯ_swʇ}[o.l@`BvK\ ?R^Ͽ"c?;9LٮcnMֺuvءde-sXqgTuxAխ+%P3833Ժ ~ ]8r뭌9᭡oF\oֺT 6f(z5ju@'"uRe9R_' WjrED"aq pݽx;`[p(D8"kzAaa!ӦOHh$BqQ3Ҫe 7oԿԦ_?8O_ϴꪫIOoҥK3k&pPܜlrKzCE:u:zKJ.r~)#?ERZK4mڔ ))KpR.첊!̯#3#ϟgc?QVAC^/|7eԘ8h0O,#.P_||B e4Tu}ct9l{qyqdffOsŗx 43g3etZiÐߨƝ'DU= Xl)?);~WVA(.**)+'c(?|O>$w^ȸ?zի?ѧwoF8GiӦU.٧CkJbכTfÆQ{4B0p$eo}pq0@4&V؆6EFF#xF79]l [_ŹU9shצ #*ۅhۮ7xe+<|̙tw(p̘1(Yk`,̙E^NNs^`||YR/&rUWqQG뮻HII/۷E\حceX8.+Oue-,,Ixj%>C-oi\x$r饗ҸqcfΚ]ŗ__kF3<w='[ne\t̞={/ [{G^|e8 wv?++)߿?veΜvi$~}~K~kzsU\sH~pHd(7pb1)Ft?6[UkEdcˑ˲PR,@muݭv95nԈ’HKgg/?3`cե 7|S^͌3+7KRR6 `Y6ys+VMVo.s-vYYf&M) p$ 9N,++ c uSMHMC]w[^_qx^ .sL;Pge%-ڵeꔿ헜D,V;SHb9#Xx!h˖}Ͻ;]'|矍cСC{Foλキ_&~w@IX1iʾڲHUYga[ cRKǭlib$תއz2Gq|>n\}gNIcǎ[-c_|r?w"EQ6f * ҳgOXp_O_VwGARRb5)sڼE Ν[g̡Yf[-fѢEe[dIsN]lS˗W,l4#.gMjV-`Όi,^,W:5kޜYfٳiޢV TB9Yw\Uٹ9٬ZO ?/uY5Ryꚱx!̛e׫~H|spca>͚6ۯr~R_|)(KkRRjc}L7qxh[ ϔ)S đRkA'DUG6|8dddΰa7'zhdSXr%W`9{<ޣ'c#F[o1u,[)SK/qp˖4n 1s rrrʂcD2lr妥 5kD+e<2`&L篿tR~W1W\qc?&Mbʕ 2 rY}+sι2x,^%K ؘڴnMAa!'Pmݢy &y98]Cu֭?`ժU||7\ګW8l|)୕_̵kjp8\in;]vg[,XJ4eDB\ܣ~KݚW;V8&d_SĢQ\q 'O&;;jRnBK<㘣͡CYh1w7}g}Fѡ]r]YYY|˭ӗg_22̳{兩=ٰ!W^}︓] y.uqus뭽x衇Xp!W]}5^]^=N 7r+Yz]vyINQGɻ#FxQv|ʩ{1{Æ OXƛo Ÿ53Qu].6mSO?5^R#>g?}. +fٗ\z 6novJ :jS|0Ο'ӻO_~)V\#/L[{/"~,{]\YY,[d%;bL@gGiZ^C|o`ʲ-7j*IYi9FGl:-I$Pɖ_ױc,]waN+Uv8x-kymp:n_Nv7Z! W57B˖xg-?bXz K/"??L #XS IDATf ,vZ8%og /IHL"^=AeeqIiݚ;n+=%.i 6i -\@phI~^n}R%IJl\)Y*kmYw?.M .#..@F}~#JJL ZS\\L4! "ciWkMFO<7cq+Nm:²%ʮeBb7> ehծiѺM8bڕ`),ۦa&\okTr1UhCŞs0Q[y1/+.f k]Ǹ;^ 9([63f4&)#K컣i1 ;>\X|>7jHBB0$UBB!HHB!{ B!b#!U!Bu$ !BT!Bב*B!:RB!^GBB!HHB!{ B!Q=]!]XAaa!9{*b;!)1&M!v B+8ܓPJaFR`~gԤɞb7oCڵB骈(11` = MDaa!gs"j5{ _Lk"Mːvm&1mUɟbg gX8mvOdg甴zޞZjqCtBeqkٶM3{Lڴm!('/YL[#?B '(qmp8,6P2`}wBP%{U= Jɽ %U!"mq.SCT!ā2ޗ{'eB{p3 ` ^Oz-|V+#c^bWZ]^.?sA~!qX <{*bg]GUNDێ׫|;JKYǯ&ؿIH-c(^;>ߏKNiG >\[?1r΋ 6 ofySJ+2>mpY|x:nݶ]^SF3xW;ZcrjJbUϋgz՜q<Яh32kO{)1vՙdgm^vUVvwzع fvfVdhw9Z[2<19w !R0x9M/鏦2{t~x/'gԄXG8Lq2`g~+vC*ɤx4S?첕bi,O_4YeP 9gv# Oٛ5WY&²su293νPGN{}7R`"d/}'ޝSvMw8w|¤%m&W⹼GgZn#&+_Ƿ"-1?f9鍊9N6.|V؎G7'2\zy3go<Ϣ׃z㧬. N[yKSɗx?p3-`^ѺI\LΊ3=3~hz<{>Ō!r|KBXO\v"Oܜ|UV*WWyl7^ɨSx&|"-+}ê MˆN%''?/n|qkj!v*_̉bWN[䵫ogEzrfɅyOq?o' Vg,`Ƹ'ev/B^Rw/%'g?z4]OhBPqEC$c,- {_7$xyrƇfg `$^ZkffS>ez݋yٗ:yΘ?W~FG9YL,@Ղ/~_*#oG|ҕZqQY*K7cx`LO^B$Cn~ywHx3J8y[dos`op3XWz?yFk }G;|CgQ聓ϿʟΓugqfW1ǷM.m֪E걿逗7ŅSwP{>]$VVݟ m3o?o_>,|A,/e!ytt< ^k<<ۇf3|1Q,=tuoY}y7yyL~_w}:s&2y<',D7rdvkSuY;9큗8e\{ռTI~0An֯I{\ڦP"~+Znd?]Wt&ͯЉ-8k9:~ѕ|8lz9XGUi卜v־.i/bi4`&ۓS83vKB8Xb=k5yzB1Bɢ.u{9",?}vh*qZw_ז/+ GҘZqe'K8Olzzh{!u_1w%V̙vuOWdF^AYi䷩{ԅMÀBrۏ48G:PtGuƞ;|EXܐKAuvoHG.&훉,,cѱ[GT멭4BWs[bݟcY~yMx_mn:$?t+*J̓iov*ݎ>In}&Ws(12nҊ>oq^A_1- h?ݯ:%T&.;6*omלHD e%⴫?jخ񏀁S^_~?JQ6Pujwlz]v•7Y-]ul1T^Gp5u0aSYv4Z]wze<#ƫN{O~/`/V5!UX@nxƅ71OoAz% !IBTa+`]XbRF0٫aᏸ|2~3JF!:1z6SR7kUX>J"%u$6*%BkHt|\`:~:v~_;`a M+^Z: ^o'5$=.$$j76eG"]d|%ĘOUrW]}]OŷU{1ߦnhZU*_:'uK掏#4snAPͩ_ql T j)am.T>hp ?'*ƶ5Q (Z5=7TlB벡A6(m $NʿU̚Kwgxi1^\8+a7{b{ `U6vşx$ q` u_VNt)[zUWN%#U70{i` /Y'ؔL4X DʕGm3rK+bQL\y-e)lODŽtң3XY.PIPUdoUu6Atk6)XCf>UZwxWn=+<\ĪЧ+OxSſK#ߞc[=":;y~n䃊dO "EBS2_/$l @7 :GЄ|7.WyMBZ=O;^>aȫ k)r!p)\~o#IuB: /+OT{¸81\Vx37hXn?Y1nx(H+|A~]hU[`)-?Ԝ 8ڨ%|5lYv =~wYFNj60|݂|M8C8QB,$ޡNWlj}/%oҭŋu\ӗ?o%5Y?+!-`K6M\\))$Z>FJQ}7kY$wO,'D40k1~o(bv]/Ɍu<0^0kih~!) opȞ>Ӌ]%x֛ Kg*W1;_VbSBW8OGgsw|~4嫟?oJL?8u,sMN2EVSP7t;O8̰ _gʩ\j'w/Ȥ0jPvZ$5n)^xᢦTc4j98zTUB87{N=am1%+1 az7T@NCϖm:#;ddG7R$v%CxD pJYE<q=/zkc6.e21O:uircU,UrA}/b&Ͼ=kuLk9|m)uጛ!GkITw.YRZ)=wOH^ց^}qqc_3Cm?3/kځN9^A]ʡy%\e?K~W9[gsV 5;>ӽEŤNҝ[{b5~7ԧ~Vɝ_7ߜ3}^PƗbjךC.噏.-oJĕ~pe?J}y쾼E=+sɹ-<{[)~+zuJS8 _쑣 $yqXG~O$ q`u{ڣ4D-/ԡZ>V0jkeٖl,ۍlcO}#kp$jtd˯X1ڡkVu?Vsu18OA8?땟H-l?eI2t7_}EK/ueEZk>`'ܞ4˶IoԘ>3cwq^6<7 mtq;j+/żܘcLq-qC~Nja73Zy Vcbƌެ}J;SZRUpɞ;Amio;[SɂcLlrONT!D;'2?/WiBIHWu9o8sOC|4ڟBQ6Jށ}{@tOHL:!,mHu7.#=zOWaoC*IWBd"z$ !BT!Bב*B!:RB!^GBB!f_(!U!Bu$ !BT!Bٯ󯎯jOWAyV*6grss̬cկO:uhߡ}'>=]!{V9 j?s̡}5ZBT?uJ qy^nǝp9{b&!U!1.ٲ=x:t, ʢ!]B5Z-x|{1)oWggUbe5`*0ЯLrwkāEBY-}^}1yܶn,~+mo ʍےAX? 7)d v<ϏJ"[3/gGMAO%qEx._Z>_amW3gu6{VD1ٻ(ߙMH]D EX ׊EYTHG: 3 $Y3)w̲;{gg@Jq=~uG$ [yo<.1zI^ݯIIsa2~HBA1g,7 .W‹,]e[RejJ ;wmN /8 x 1))Wۘq"Ri"i4+<>#i̸.OSD~9wi~1̖|F[<{דkG0hr{X=-<κ]G*nQym1vX_z_ƒEٌ; I+[ G0yQ 0$a7WԬׄ\K S*`pVd[ž-$ǍnbvN.KX\vK;F퉎['$&t"^ VO&:6]F= [ĭ_xY>Ą?1-@ٯeIy\կ'XDZl6~W& {u9,-ڗeܨ~)c'ճQ;7 >t=LX!O;a}]|2}"sDiFLpl]+HYGc.a>Xyx&w2'600X:\,37ecco3\wO wL>O|mۅLQ4kڔ֭ZQ?>ZshըhP-֭ZѬiS"#- kͯ g=O0kg.iS҃Qei7Q2qI}ʸ p 6&pfSv+ǣYkyX~fnCw<9n|{-rjvy+2~%8|8/ S^O/:3V'a <82΃_5=Լ?3&Kxq:a׷=uOvp9L2Ͽ|2χEW[G/̶MkY6I .hM*FL͖_F4\w.b>T]%`w3A摴cM7Wqt=+Z7< 7g5duՍ_Kӎ0󛷸GUE^˒^TwS4iyy"'Bj9+G[F⺕0 ? Em9+20u(¾?Ƕ7G`4QWrpU]}y+ZGoŶe̙}ֱ}kyܣ~1m~w?V~#;|6Ѯ>w?G6H!~!UU%ċޔnM_w:W;&c)n7IK糧S7ju =#Ap?L8]ue1M3 ۷Uo ~=b kLV571}U YG1`XyeZEb2_K"D+X;%X?-ICtP5.\ Cn.YE=!~TԅjEE9c2􎞼_콢:D4 )h n؇<'K3ؾv6fD1uva7pA@+C̜+_ĹӠXƾفOVKN9ٖmvRTρˍAՀL~.|GyR1xL!cR}`Q.;/wU* :ViqV(JQ#=1pgS~6]F~,v'mq,m*R&&_|ٷHk͐{ lp)yc=I8 A 0qwu`DhQv͟ٳW2<:_?oBjGx务mx^@YkYщ!&6I(6 XT&&1 )n/[?(?V?̝!a7w^K@`apWαȉZgܥÄp^0'/ CNn|9&Rm/)~FAxj3qZ̊j#1ڿ%sp[H{~JX0jtݞ,,REƁg*+eY ؞\`aeK!֝ƺ1jTP_I, ?eO2~^+ 2>pL~x㷝ތ?A&zKJ pJUb֣/~ؗ˕gǼoݍg]d\4Zsnϗ-Zy(,hv &Mnvkԡ -94=gz橜DV|v  }r~w<ǘhstj˗S[]YJ(1wNW BB|؎ ;xdǭLQjTr`lG~H#,k^%E2NȓSwy ƃb{_}f~FԹ?x7¼Yt s*IlgO&[W jv'?bnB .'!& G%jTMBJu=$lWRb@$"(i;bז5X=a'{&amJU )e6Xdyݸn[hy u'i6;~w4JF«3֓o%/};ANY$sٻg# '=ҹA/cb0_Z`[ݵUas W%wOZf-9l˦ y4.ZaeٞIf@%Ct| B]x湿hݡjaL.uɧqƕ\#x߻jD;0pt-)^ !"p^K9(CMI]5;W`c8 4Ёy_,w{U=Mx}Vs^{ 9Xv;}\spI`N# u8פרF|,K)/➫:&l%C708,qxNOUsv&f&=!m.PueڼwfKX"V%:=nz[sFiz3_vCgx6?eٷs0M8μ-|8^r*m;v?ݾRBf/fOri .HdG 1{s$  1+c)ou iMfiN9L QS R>rss: L0 ;B/ ,q;`xLɓܩQop:ϭO1V6ҽVgﵰ{F37Dz=V8 ܖcxo{~^xsR5dRD*mۥ>Զm >P``vۉIcJ]xk"""Q˲ [O€ YBҞZR]uIO-jA- mSv9(-_g>k^DN 66Ɩ U#LRS/9l~TT,u;CV)B*ڋ_d|EWCDN=dYإt;LUPJb UCLU^IDT$ 4M<^/Qǥ<)RO-= Ԕ"vpͷ=Hr>_"#"s6k<>_f-5u\9fFNzb<ÖToPM2U u޹us !UzƧaD$͚7իYl)iiǥȨH"#hҴq)ODtz `pV) .>[;,(pжn[{lvHâLh&9Z*O֭]GffII]9 qGҸIJSH-Vwbc ¼NI,)(Lf@0# X(epXwuFHoȢNNwr5jJ' 2̝$֭]a:ܥ[EWEDkְ~z7i\UP ]`B ͳ0B+qN,6lcAt>k k4}+|fg0^Ts͂6yyv †/33>}Wt5DuڕoVըp8=:&m<0D핂ݖ&m#i[9`Ǧ /Oee&M|e:}_u߿ǟZRlRmvlKc/8Re&/a:7Jr;pSZRGH(޽؆?mM*#J e6ʑP(p۲I{}_go"qg38|V.ݕҸA%`uk[cY})qƞ|3f SLamA;" p_>OhɐWbܗ:C"X}O׊TIܲ2Cjʆ%Bd`哶{"nԩm*(}soK~1l7)H'IT WO|&ɸ!e6=FNA!UD mcrToOKLv3<&e{$e%ӦoɅ1ʤr Xbi(,/-\9?Fpه1%^ٻHNl;CkR=L!UT!㎎Ƥ-20<oODt4O!%n{n:ZfHKy;~Wrۅ#8$g6vdS2("J!UD e1%OlMZ ,lOxw3~?K%[ 9{\Σjej|: puN?KIqX ~M~[r21)9_AUDT2XuĔm1\~S-b{sM"!a3?aC`)̛n[WXռvᏑ8/.EӬKz'k9q4ֿ#Ńc0(Aw1јT2%tjD`;qvn=ƈB.DppW#JN\܋y\UM,w .h&5MV6)fyv|?؇Y?oܤIۗ*"RH<»ׯD%2v剈TRDFD5ؖ4d[kV&**ODħ%UD͚7իYl)iiǥȨH"#hҴq)ODt*"Rf-ZTtDDH*"""">G!UDDDD|)ROD""""rQH*"""">G!UDDDD|BT9 """"sREDDD(ߛ9N!UDDDD< """"sREDDD(QH9S """"sREDDD(QH*"""">G!UDDDD|BT9 """"sREDDD(QH*"7 IDAT""">G!UDDDD|T+ """rz9T9(QH*"""">^9N*""""gT9 """"sREDDD(QH*"""">G!UDDDD|BT9 """"sREDDD(QH!ծ nN!UDDDD< ""+;?#:qLXZQpC;\7?Dǧדwbk^7i+u=iGt~/L xx"RREDNk|t;w} wa]A1AY=d| wZHSH9ݙ&i^ weq:Oԗ∎Đ&<ûmLcz'mkyl>kxVe`s%͉|U Q:S_G [طy:ό/rMF2]4'.c~K^]"8Bӆ`Xd̿sMc!JZ\$/߹ޟ9'nUz ,I-x-`wpஅ-sׄ)ΣSXYf_=+;iD_AED?2o9 pFYu\tU~z+F3K70gd^@^yd C?W7&7{f>1y~ΘW`]*o C֒/Y6+y3Wvȳ fQGT;^icxݺ\ۭ jWIX+|ћ7} hd0u˭|p"9pFْ:- ?\n|^JY'w\}?0Uamጼ fM{^myiETuS4TZӪ~u^bH-:: ̠xXbK1j:a.›W3mIjQk*Du4Ўq`W.Y<v㈹g~^|PխAaO1eM^ԈL\I۹lpk4+$ AUH+ӏ綧aLN/%oyo7yx۸֕\m8("QKi-}ƴQw? "r,Ū͗2cQOŸU@8KXFo3,C~y(A`ݖ㭜DVN}~$9?*ڽ:b:믹;fEn7AvC? ?~]%rkk~]qF/{ZXh]\E}9YjX* cݬhOx [ 1 'shţ3h{^,wIb}zm*?ag,es^r=^ dML'D uDʎ,|96zT?GW fmw3quG5lr6~ا $_@] ۹a{3Q&NOIýϸeP dשt|4)}؜wrʎvV*Fu9|H=Hhբ[y>߷5sc={X5q|Eѽ! *u'!~xmd31za++Yf"g&T &6 jƔ38Z+ySY0a z?ͫ[HhJToXZ wz|:I^8pk7ĤGyBKp=&s0ԕwD3jqtcpG_W3wѠA֬\IzzLRSYz_*`Uv(ƍg|lW5zjʌ&xG^rgi2̚np &[YKْ\X|ӑ61.03!0ps&9~=>|"+rSHb]w9?V:iuvh }=7&}&sT>b_%OWWmn;re ^%_јZkPP^^ׂ7&c F0MKiY%NwHUjqZ_f|֪-zdŌSWc# .n  bld憸 ?G#i[p ӛr2]t/if++#gF8 ;vQ LI܃[pC-XaYo3 >?9M Q8a 8gsi޲%a񟔔DfFk֬[nj1uxC+9#x^222=4`tw8Dqdž)JFJ~rbXVgӰܖr{ wm뱽o*yccO|ȃ3 טT9L``M&!aKc"##K.MLڑY &^W "*""%נ>5U/q~]S;/y;[VïWPۿ+&{RED8h)sR9hT9 """"sREDDD(QH!Նc9~H3BT9 """"sNۦDDDD4@H3+ ""i_INN&=- (bc߰ALD ""rܜVZSFMbbcHNJ$33g΢kVpMEt~)Ò?_jӆZkLpp0jסU6\֯?KXBnnq7=+oXqNqJ<{~UZ{v(rRHbsB^8IM؅Gؿށ:3f w6wUiLס0}k>P3f4O\A" 7Y׷c3x[f^\Nd{wҳa9ƌeܳ?Ȗs֠x nv oӔ+;,\l[+Ҟ*i#Ty֠ "Ru϶831F6!.,p8Fe滜eL6]wA tJ&fe3uÎfFGvߔfE 4*9?f4ȩoOg Lxxqǯ?ϥy˖[tRRYnݻp-rFzddd[pt0ud:wx;b!xR-ҭ<{69Y4,8~zlǛ y}nF@=knS&88;_EDD$\6m-ŏ &&/k("gT)Qנ>J1gޗ~REDPn*"""">C1 &""""e;χT9(QH*"""">G!UDDDwN)QH*"""">G!UDDDD|BgEW@DD|ƿ6LzZQDSa RED099̝ ZzHff&ϜE wQ?3^ S:J  bYѳ{wWS 'QPi%! H f5/IvgfM曧L""R[\̒KsXzE6m$22mңg/s!K.-iλL݁IPm|gk"r8Tpqqqϰ#ⳅVIJ餦z_4|7^z*bub3g$&" ."h_={P+'Э{w6@jس /dۢsۉU.o驿6VLqkMvLYmYetz/V^%UDDΦIll#;;M4q69׬-k _:i A^_OE͢gofxt o~ q*/`SNްJs8M]W¹}ړ֞W?; );֗10o4|)׼Pu9.!  YxpQ.V9ϱ Cv)\´S'ܼxhtx.cKsܭlޟқx5+'L xn:c.%]Gg?>3׎Fjt3Bҝ|[ݳ=m:uLjkeu;ߟs~餦uܛ-eQ^kwښ؇]B[9I.RRR;wKDp d~x7hr?f;5 @)[߼V?JU IDATiƺ>Uryw3ޱϟ*bV_^񏙯 =0c{qSÝ^{[ Oa8M+w|Ɯ_:s#Ofؠ:]vT Yi^*wv+'&għ9[Rd~d̋Kٽi#?9lJiS)n_җ?/ZukXmD>um-{<}vbKڕzMϾ&s;K"RHch/~MVt>gC==31|$G`!18l5!ɧob )ƅኡpY&L- 51\Ѵ: 1_]ցU ddZn{ǰvJm+`࡫o暛W2nTz437\>.P_?W)5QWKc%Vnn(\f4FNa|<>0Cb]z-8J$0algˎ= Bh~wKaFvܐ:s+o-Mf̤e&1k 63NI_E|B"YnӶNgee_^M|kyU+},x?0Rl]71KّJؐ~&hMQ]_c~p%^V 7)Mug&;:4&Ft]5f/x̗xCCaT )B&%:Ea/c eS\Q l\my9gS${mpeLǀkk3 @`?w*!v5e ec‰  ""@rJ$$׺;"&D̨?OnoK~EѼS&=2wyx3R^i){ݿ;<Tf$I)gۧ2{io1WnF&(VVf}t )eaTN9(|A\QMibx UƛBnu!{_xŏ006\\CLz3?1ܑ4Od[n)N? dHJvtȱ~cǎ^ǙzJ:t8O1ݹl1򪮼+| Edm\x9d{g؅lyfr`Qϐ^ =gU+(">. |}_|DP Y]>v 7L/w^Wyo{kĬ~" ǟˊ7f)qzZC\I⬕iE{3^kƎm~̂>f2H7Y 9qdeeUڽl!ݺw'6.YYYz* BXX5]ǐ]˓Cܳsu_S;dȻ,/U,R04]78w\$&p˺eXga>ڿ߃ ф6IP*"R+T؎sXH.܍إ0M"d嫸6~g|{@TBCWD&Nq g r=Y?ضNdQxR:a["_RFuDDT8}V+ŝ!fzL\.01ċgx37+˨d,EDj]i6".WjicC4)r7ȓx0)5ɭ(+SUTuHX, >ؗ>#s4L !,* Kx~[p3doW%44AED1 *"Ҁm8!DGr{ 4 #s(2إ~-"R;TvBmDY00gx4|KRxR?v^6 `*A""RHSj' _bBr`؎R6`!7paZ *$@Kf)j/vl0VX0f؀U}ҖHn:P""QHSNijwr\#?ځ0qloSwQ1yH9"" eǎXըEDjp QMk=>Ɲ ϋٷiv~|2"!,,2 =UD˖6tUj*"RIqInڒQloٟkpigfu񎡖Ti8g A`UCפf ""5qyBT|\,%R\ű\ᄆxW]qEo6?#>V-"R/"ȝd~\_FnNn@BB"]v=c/"A""ǁO9PI"R/""J-"R"#)-RՄ`uPDDWU(4ED uH}pǶzH^~G"r"QKH5p kP<BH ,V*΁l'4#)!aU5*RwHREDja!2fm>a>=4eN#944TTm `Ya?Q0o`;8Q6{1!k3doW""G@!UDAmaX>@a]% IQ& ԏWS͊V""rTvBC|w|Ҕeؔ7``X0\4`"" -CZD!98-ix%$$wvֲ RSMrkՃ-GȉCEDjIw]m6+, 'v R8(K-my 6ݮؚ/"RT8Wlᔦv'XX/wa5Pms* *&4)GDDj"" $z0b};kSBvH$VsMzHQ>UDD*"RIqInڒQloٟkpigfu񎡖T( QqFSHqvpyWƱm\Y/c۬^Ć>c֗.QU9XJ:uv&"R Tn'U|2rsr̄ҵkW#qL8g8=e"~/LKX-eY9|t9, slG`9Ku_ٞfӍm4~2f_%]ȑk!U`E|) ]Qw}Þd ~rwZ3wvF^ފ*ܓHA{+A""5mLa||̻qľt Sn`:%tʅ.ugΝooߍQȵkޟoGu#)9Ng^ţ 2LKv qVTN:,8U*-wc%.+-|ņS`hν|+Ԩ"RREDwm9w[o0퓮>\X&@'?#o޻yA$|o:̬8!ƴ(ج{%6tyvs{y<,Wd+ǞJ˓/WOa.|e3Y?#CrxeȮx|ݓ2{Si5ohO{y̟}{N1ky-'2ٶa9͘H7=nwy=JiO ""ǽaݾ|-]r ڧO_:%G6 BsCˍVo[ν{ [E2 <1M:hw"=LӘLCls\ZKuS]:3[cecY w܇7)i[ȯI+ ?L`nq~r /wS↜l9 _uVM $1)ЊFMX(|>.`t1ݹH `tr)Y%9p2Hhޜ:Z{Y̜)?l/bw>m$We]x<u5w2/ & ]dZDBȉlBqb:D6?9Ӧ2>LfuEѢN6)i?|+3s͕ ,xiΚL\J;v#@Rd*mgpceCø(dFc2Kϼs8nyn ơ+9!D|/Zij!^uEZIhG vf;*v0Cؾ%@jH3FNûa;lܺV˚,~ZO>O>/~fsKqF]blOުۋ˃9Q؜pL|;7~9N1~Xɖl$$ M& qdlg\9&REDN&؞fw% yixv= !chVE+14KIﭟ>1^ڵIII G Kެ匽q4'%Sjn*ykZyw[q}ft'ߒ\$BgpzT=jUOG;8]433FǦ%Moq}np]6 *cz R6"L3,8Q&ff4q.Éw\f:(wl۪s-}̄'eo+>rDCWCo yatư 4]78ݏqHHL 1s α#yv.F%>am? ; !gXN]8?}W SK4VWmaGֲxn\pjqL EDH%%y=ٙǰ&)aqKBB\?iHng"Rg9N5y$ܩ kj芈ȱ~ : """"tREDDD$hLq<\..#", ˶H'""ӠREDc{rr&<, 41"r8m۔K ""r=D3Dmj48I9\.42ahx ""=TE?eREDDDN0OTH*""""AG!UDDDDBT : """"tREDDD$(HQHn HpZn=HJr:ulȉ@!UDD-.fѣ'[$9%L Oq昗k7{Џۿ{b`aW  r^RI!UDD1={1VO[lX=/غs;;36Kw1:ewKZ0Hϔ*CcնOB5f;yAǝԝˍEfߺd?߮!<:m|M zRgl glg_X:lr  RsTDDegg$6őUi<ĦudQ8s'5=C~wV󒟟`ٻOq餦bڜ)طwo}I=^Z@ _:i A^_O4zcѢm (fˢ_0:ؽev}" 5 =3~Σ?ɚoUc.`70sSiϖϞa餦 Wq_3|Ȕ~wl]u'ͮ@)̼?ٷL`pS_3ip;s{([G}^@#jЇTuVNrshqh\̊Ky칗y1$mNf8j"^ǿơ׸_"_azqC0<6kyG*XŸ&=HȧYs;Km**S^]ׁ~WQ`{~v9Μ@$WgkDg٬):Y=:yIQH_D2{-IR&jFY$(a/=VH"0 I \߅O^>_@wpy4M3$Y]fߚx\? QIHR/.}4+gʎܜЛI~CCۈ:1{ɜ FA\wS&=`Z9<~L- 51\Ѵ: 1_An<׎LExzoW o+VΣl31|$G`!18l5쩢5$ ض{3Nf~_ǐN49i7FbIHBWF߁U?dgPOrLe~ٜ=&c,JH'-A%""@:YnӶNgeeTe{M aUh MM&eg:V/KUtJ2 o%v jp<;{p7'$,%;_OI88Km~ܑ5ft}\+7K΢Z,2o|,aj?S\MhH,ITTp ٺfo=+OK=ݾuy/7vavK+ׂ/n(8S:Oxu I!O￝KMhD8!f'Vkd%I!UDDHNI"??uܿxR.bq aħu)krؾ^rb؜*nleeh4HNڽB bM=dh[C_t(v| Gi^Cac^ΗWpee+e[Tz/#]`SZXT֊}:NTt чQk%I""@ǎYbyy3atPO6mc\9shZDo,kcoϬܴ0ڍe/;~~ w;ؔSRgLbe܎gy~V6=yw6 J}X<25h^EhCɿxo: OoFb ?9߿k׵y1򪮼+|l+9־DGxxQG,_,4W^aߠ “Bfq]a30cZ#y9Od[ddWagcK~ưVk%I!UDD* :O|D^^n 2tHJ*9-҇xkGX&F3k;gA֋S蝞NZL~x> m MﯜK?'%MMvQ ڊq5IK WۛgN#nLoN3y,fmYK4>ss J9IW4d~N'sŗ[ qN#*P&̻ i7R@ua-я_rR:DUăZ5{0 4zK2wsR;]_חZKӊq_&p'GZe#:imK˴t {(K~漤fSyE0;ctlQxW+6 e\n#pRqyL 8!n3,4.ebFaFW2xe&>~Ey9{h׌7ۮ}|Ȃ>f2H7Y 9qdeeU8g ֽ;qqʢ ?իW1dªiV;3xm~}D=R,"?: 1M~M_ME|b"ol2װ1,g8{mBo1Ŷ]KsaPSX+X}Vko߅7mGڏ[`0rl>aGg k)eIMYk=_{v@G3ǼR*""@Ԟ={P'NH~ׯ'O~||ݺwg ڄn,dl؞G1$ήt<4_BMʯ'NС:t`ٲe\y啕őU{n7nO2|Ȕ~wlqU{CgL01$v%+PZW¹}ړ֞W?; +sI|sϿJʳgaX:ir5|" T /7rTNN}Z|UV,Z|RRRkƗOANq yw3ޱϟl\ Ct0/{mC~;xd+~q3/SˬȯD!UDDo=NASzc3*wTFGin2voĆh Ȅ.&[Oqp~7CMB2! ]uh *Aʤu$&&ҿ-[VٚeL\լ,k) ['*MMmz[}5r&u]FiQE~- ""@rJ.z̙\y,ZW_PP@rJr#c-el3 P'y-ܿ}*s^. fsA95T$ب_DDر#W /8_|KtCjnNWC{ӊ|'^'=8 OoFb ?9߿kKx2[,uDZR׭ȯeС|#> 99| roiŸ?Nࢰ4Kʙ#Ǒ6}Uh?=\|ymӢIv*􎪜i:.;{7gsM}WCDX#""k }ϼֽ;qqʢ ?իW1dj)-SUfe6Sx(*T>6H֎UOR_o=]p$9;/R "N!UDDYزeS2S $'pg5p ED*""Uj߱;v8&ez}EPH_B&g;7%"""r *""""'T : """"tREDDD$(HQH*""""AG!UDDDDBT : ""9GϗiT3[F!UD8fYnx"8Xhp;@q0M0J"R qmoI REDc zq\ ]eYXERbbCW)"""hj1I*""""AG!UDDDDBTM#X?Y!UDDDDBT : """"tREDDDN(?i REDDD$)HQH*""""AG!UDDDN)HQH*""""AG!UDDDDNT1 !UDDDDN8 """"tREDDD$(H iS""""'""""rQH*""""AG!UDDDDBT : """"tREDDD$(HQH*""""AG!UDDDDBT : """"tREDDDN8NCWV """"tREDDD$(HQH*""""AG!UDDDDBT : """"'__!UDDDDBT : """"tAHm#{EDDD^5*""""'T : """"tREDDD$Hռ)NT9(HQH*""""AG!UDDD+HQH*""""AG!UDDDDBT : """"tREDDD$(HQH!1 """"tREDDD$(Hq7tjFq+c6 ϯ∊ERTuZپmED'FQQ!]uözݺҝ¢>=Tj81*;+"rPHT=6q3{&MbxIQq}_DDPHcՆTON7=;?;'χ㩺PTZ)vjCe C8e۸9NUDv ""5pǮz\S`ª]Lk:SsVEDj*"RDZ<86aNm4j<""RHc;8v5l(Pj,Lè8=DDV ""5 ugle?] 84MoF|BBT^D i@cVj WZJTd$a6fXS0ؿw̧4_CREDm;mEl|L1u,c$"RF sgE *PM! OMDD4,T"Ȱ!;U; jwjwfEC*1@T cfkN1U0cD%"ڲ5&,UR'MuJDD}j U@<ջ9Z3,&""T"(T.A}mi`ZZ466!SW7mC*6mvhjnBC]]_8xa |s1uV4T"fJmljBCc#  1D*944#ظOEDDp>DtG:3`vtvv"U\xd2utә!ADD#cH%"Bcl:7fEQshf{ m1\JDel@XګwW5JciVT7NmC* \;7 n4Ђ#C*DD42T" mUa05SmZ6Zv+v2eYI%"ڲ,8Q uԆlSw?&C tf׫؈C*Q tojhG]&ߡ p*1Df _M_a6bQ?T"adY8c῵pޣ,#"Rmjů`lyZ"eK!h$ Uv K^~_z :7嚍Fd1cneD݇GC *6s=*="QaH%"""ÐJDDDaH%"""ÐJDDDDU!C*U }TkKnm""""6z͕҄ O@DDDD`BlCC@DDDDۀ0QթZ _EDDDT[?aU}H%"""C*U } te*=کڷuX.nն&l}Me8[yU DDԵOAuSo#nF.p~Rv+snI|,/|;=}7?.8G΢!ŌCOz/oc=T" XIx%~w᜕e05n|gpۭ;@OhD[UW-}05f*X ɾG,^۞;]Wkqnó6O_SK01@aRދ!wh@%.%- [^s+fu>.87xnEx;/M s>}>Kq|8cpWBO%UŔ Ϳ \t$o\5Z/<߹fcDɳpI7Dzgwf57Ӈja%:u/q]' s.}]|hjnƬC>~*bۀ]1xl^<SI-a^kC*&Z߁}cA+xqx7BoH]o|_aΏndE(~o܏pկ߀<nY(6<L: Ɵ_qx+s~]+7ގ|\qf BB$;?^Kv<}7p:@bz.8銿}_ݯs㱞ZU!uN>ј-=Gǚ4 lz =i`JtR<{p; Ę'qڊO;nZ&h-SZ: 1ѵj 0HbReG|7c;?;'anr5)eXYW?;Y)x G+w}'"5Y+}YONkCGC!ɘ1 ڴv7 AP\ -8HL mi-.'o•/k>uk,Ι}Xp"ΞWEWЖ(f15H/1]mXjg[gY;]pWksG z6SNr̫a_ĭXN{fxRa|ca/{툔t<|.v|v(nSig&4Sisg㴯]/SU_l ThhUS@~g+ǧϿY99<?/4iWbE)9w.w;N>2<^L^7Lo^O=;_xzIlRLNk~On% 0=!gqO 4ZfpAJs;μ=_eXcƱp*勐Gq (D9lX<|qᣍ'a)Hz:(.PnS&❧ r<^< b]p{o._m6_/ϮǸk:DDc2L.?{Cn3w D\w98gCUOОqjЊ7j\~SUS*RGXp! ƝS?)]Gc*2f9G탩]Ni-^ 3مk8sw} |\wc@?O&;uZ61> 0~ 1ū}oQv<`'\sډguӠ񛌿x7}Dpcʔ}_:$//N1uK푇/8Ī}{`̙ ,&LZdMB" a6&,6]gmA2AB,l֦MS;Fw߹a}Tնcz3JMI# y?{,y?]}θ'c-Q8WI.PlxА- p෾e㕜Zy&t-KWGV^ >6C\H>$Qh$Xbg|Tꃤw%D>3b%/m}zV3lkR&0Q-}M}DKZ Oz>[1TzPZX=?=rx,JmRV1M`ޜ2__[T{h-ϣSO~?d S=JUj^k'kC*=7ҕ2_spu@qm':@)bC/K.{f,?ZVʼ*T" LYIj%{wVSbw?m <_ DD^SsNMx5qs` @pΣys8[ye DDIuCg# ,&]BÏ"T?Y,~)^꿓c5}anR浖1M`K0!͜9C84DDDD^BcsKUR&7p@ժݯ="""" otUT7gQY1_P.URDDDD[o`P_&E[~VQfW_IODDDT ko~Cj-$}"""j0\_ {p-MЩJj "RJiov3WURE摈"Ji6T~'h8UU}%uŪB@DDD4,|5!5L }Fm"qO>8xuE6TQ@XgT㥶iXh{4fTc5AU!6,@T:\O^bDZC)ط9Νۿd4;e@y-|MCU#P#zU DE yC={mJyx@ Ԇ@=zs_oJjO+*~0 4H^5PPg@L&0]̾?.KV4Q5ZѶjYrO׍ %0956Sg5Pobn sbywY6N΃hm}.(ڽ.@wjj&ꃴID$L&p>jAQk.%A)W5&1v&N %wyg]$LlF@TĨmB$*H2%%ު)\*R F܀=Y/mmnyw/\́4qv䭆uj-DT-VCGJ" Ĉ444TaBcX0"U7"""jU\*9L:NbQ@.v*F> ^>*I-8h*^D;-^]Lţ +XGQUMq @yڹhikLh2H YP5ީ#)AON%: >g#kW"U)Є&(&"""xĩ9k:C$-$*ΈPTQ=Լj`UUK8sIkf"Lm/1fTS2 @?;e準TN4"n]oJƫ )Y5\ xD0>'C# 5@%aL2ZB7q 0Xx pc176S/^%p9Ri:(ٳij@knƩ΅bл.53yU@HB%!6PP%l`DHފ$!>6) gRFɆ*Fթs6(.D1h%pIAz>RqXQ 곛7G[/]-ޖ:hb?cM;ZkWX-& Bq&:MڄF&NM+fK """a@!*pFbUXA0tƫXEM1VE "+JhۚVzCuõ3ymyLѠj^5`DS. `AA^E>ck"q T"""Q/X DAꬨ IYuڥJUUE[^;V(ףelЙ @vfMw G$TLxr0)քj!& X1ƄXI%"""%oBU B>v*FQT@=r5^ǪuJPӝkK-w֐:.'U7˵#.L`L[`5[sI cqP1q^@eKDDD} AE6Q\*D![[s*""PE\Isޫ$եulK8 fF7ƀ l^M}mn&j|h; Ŋj6-xc1A26&b@M2h;K1L^) |^M >āJ]l\IH2gjv#e]Zgs疷 +#T䝱 16Lc+1[N!q!hl"|ABiNJlH:m˔"T` AgjSښnؔ6N$Z$X a|pA!hBn)ՂN5*FV$C H]e}^o j)([H-7S>9y&:W-,\ҚDP0A҈01Z@2Umo\^`)h.R "UPϊTsI'Y/:R@ PrVR{ >UTW.2ƄiL.eŪj2u[S4%a\F+Lk_Tu0RT:dAu}^4;I&ﵭx/Y*n)#,}+lT`PsYȭZV 4)lPd8%"""*V{iQ#/j g*-Bvm-SmVAˀ UHF iUZ[BN{똍h;L ʹ)lZ= XT`T7VV :VUY+L{+=FlcPAؼ *lXSNT`Ce7D,6AaaOb n!] TLV\kp$kaa<6 [KBjE],mbAdm^a60 0L|F;ŋIHjh1h;@iZBoFl]k40 0:+ 4n-Cj{ ihqYkA(]0 02SYi6G':%P4p+e; j{M=E?UI4AaaOLEӃJ.eFt~ж^@h/Z$Dڦ"'-1%BRh!h&`3 0 儵cb*+FaB샠]]O{MҲ۲og E Ԝ 0 (=ۧ ܰ֞X:'u~T: ]zxZ ~գȪl]+^K2?Hqxc ~N(qeZZ0 0U9?v :mGܰ֞:d) ( +:>"a*@-+bJ%cT@J)nXH{nHA0=kaa\ 1ZhZJaeIk)@ֵh,[ ֢ ~v=@W Y2Ʊd2+Dң}BTnDχMfaFIOA,֮SڵP*"Z况ZlWǸ*sTV{FZ?ŌSKi^@+2 )!-it-ܐtX54O30 0 "*TY֮,7]\ 儴Z1VKpR% ؖ2 vbU+="> :BzB\iY1H!ey$GHe!" sqaaeGZG\Jh _놣BXF^6[9*V̈)PŎ_+`cvV@-+bK@ i8aّ-m!qHB:ሔ62BKԅ5 0 À hiklQG7,]R8hǯgKb*Ŏ_+k*ԫVdHؖ²#Tai a ,!˱x-GE@XZ:,0 0 X 5ڵGi®hWkv-!\]UN$RZiq^GUETV:jCK. fW -s]KJ&DG-V˵6a))l:6ZXZJ[+a{-GZ\HKHa 40 0JRՖ8nؕ*vrRX [XK=~RrJY:6 JdFH=P<w̺,AW-mz[+ %'ptSEDX)le [iaG<K aKڮ%˪aa,-+B)Ki-Ghday"*,-" -\49۫:#e8Vz[&&:HCc er5k^Z譬+=|"7W AR #!UVy#ҮmI'\ە£ml!aQjK{VHJEliYDrmi0^WxuR)Gk+E%%quwh|Tp*ke7,/-AF$f't)h@JʊKv[ia;RzHʵB/` [JmHӳfaFI[)Wv<ҊaG"Jh4[KPhZ+*KguZ6MNBkENk RE{դDB*[Hˊ^)Šx=jRznweh -uS!23Pv!p'.H(z{"eIKT~߱yW(%#bm[KH?RxVaaRG$- JVRZ)Rz$Z{eJBhph(8b-v?z6ibS2(BB' G Zy^ql|--[K)!OKK-raqLZG"(le\pWDDR+,k9*J%\Jj B)R mBx5(`텦2D !nH[H)H>jRHqx_zD2N] KTruAX')baq=ǣ6ն,vCQnģ'"EXha9*"=62 qC~Z ּ H >t%)RjK[xBd_i/Sڢ5Qxoaơw0ۢc%o7PɾA-j_[ؖVBz4R !-P|"KhZ ,AP޵>` !qŽXBXB \==ZZJOXYym8:mlwӧeV~p m^/0 8f[t,gWByR6RXB #h'z{\<"AX%=PbJr#FyTʫϐ7IDF ^=!XR&eVV\I xsfT+ 25ʗ?7Ǎmo墋/^Eb{ qqLη4VXĉXjH5kp֙gѭM<ZnWw(qg}:vzb>4]֭[c=Z0VR\{m`;kxɧ{lZj#=FJ-:ܡ;[55i`1Cb 2tbcco1SoQr~DfweegSj5,` wx1T\l*WTV_0ʄ?.ꉉ5"miqɄArJjZ^w\HΝkzz:L۶2G,[31>7C<())D"{ZRR}Anڸ_e1~ŵE[nJ*&MbSO3avnoyHMJժeAV}SM㥗_>jr}toFy}iF\q|~,MXtlQRؑJ5  CLj%bǎT>xMZk&Mf̘ݽzs]ݧ/3gVH^ xۯu]E>D|cf͞M0ʫ:{KW|?6l8,_\B u<<‹̝;Q#GrUv-,]G}7vKכxIM^yfOVVW^Ձ+7|ZdI{k׮NtF0|駂7lsжuݾk>}~[&O@NN>]uO{`8r-W.Þ|&MYp~Ey&rssm6nH.uG䓏 -.ˏ?ȗ_" 2~[|Y@FFM>JME 6mӠWi^]ş u],^/ٻ|r5jTlYYk5 #6ޥs2 2SN=A=FhڤI*v?ZW2v,_ƍ0kl|>wi}oP3)g?#xWBWYj&%i_q] /ĝ=/{8êeMhղpWFŗ^'Q^=&Lz{huFwv>9j9LFN$ٳ,NoU|2ƌ}5+hby̘ߌ < ]܎;X0o.NBvvLB XqG=Epܜl~6sZ!7&mQqykdfd0tP<u3xa`1b~WFJ]`Gtt/&9y8ժ~ԴGfSs*.*ϝK $ Ͽ{Jq@8$ ?"ByD́(6mXЛsU4x>㏹_?ZYYYaRl`,[ P+lTZjE$Ҷm[*)? ^}Lכ᪫P52]m233iޢ1E(7fӤ`8- C|8/ŭo㍷ꫣRcG*^ŕ:x."*}{Q>=kp @eSֵv[΃`0"\|C p'A0]֬\^K@JA(*kc֤fZ ʰCL?kٮrW0x z+9̚5{*LL$ ֭GʶmT@ w_e;|W<oiƽ5瓞^P;҈/[7JV-iۦ %`ݺutޝ\{u_֪mڴ^z%8-jݺ5\בEܵ =oIŊp2å{c&F ~+-QxMy>5boO=ȳ!Q>Zaw־CS_3.{#mؼep"E˖v"^-7GMG1kRD1?77cpɥņukk'hؖ T&Ξܝ7 aORm[`Y6֒6mp]wsхqmѯa{<|0y uCA&(nݺqy+i4}:> < aiѼ9gw~3fۧ7_|q h5lԈ W Jw8‰{tڅqoEzɻW>(Yj׭ ZTyO5_|%85y)tzmGM|D-lhw6EY8o!!I99MyT248YOӨYf|3Svi5^ߡ˯gСHl҂333INNnݺ*:dede,<O3_<nWXAΝZf2G{rl+]t'ӸqfϙsQ̛7rJ%Q޳gc_mю)rs-Si;Rٸ~ _|5nK)W-_ʪ)U+XR]z"LLˊq#A>c׫TGMvAہ$!2Ü!K8cc3ob|1$$T:B/Ʈzq'|-S|Ć Xf _|%?cֈ]v̜9e˗sy> 7+RNN:*˟ňgg͚5,_>)%]pt gǎdeEo]R㏄BAyg„"&&&Xp!lq^;|R}k׭Q踲Z5krJ6mDfffWy96mb|,_?~Ϫ0jhlݲŶ`ywj'DÆK<5pU+?Y&Cb}V^MiҤ)5kGΝ;sw>^tzr3ٱ=:}5[` @vf&t"S?oL J&_} nK) ضm7uy@ Fbu>K116oP0(xRJ<(q=r lOI)+Wg'u]V- |0y2Njr]le[` @$[oaYv;- ᏍŲm!#mGA=8/<ظ8Y۶p!+] DOuuh;<^/㐾#۸wxeggySI6t0"?7\ߑ)<٧\su%P$bٲe RRXf H JQB5lH͚5I\` a7iۋ\YXXE^/[ fE^gffO3D" ¡k g ٲ'C!֭*z7Yl~C^w3z뤤0CA,ömUJJS`qm;fxlS{x+gFQ-2y`흷v0u>+!^oJp?W0b˦dgeyb֮\A(S 8mɻ;bDw= IDAT50+L)W0 c#{ĝaaF)CLfaQ`0 0 3aaF9f50 0rkaa 0 01aac&X3 0 (LfaQ`0 0cX 0 01aac.0w]0 0rP` +.?E0JJɲehԨ.ߡaKٴpĎΚ?e[8)W}L cv.WwA5me0ld58Ji CԳa웹0 0 3=kqya_-}QsKS2+FsuFOIP*O۩aWGϚfJQ sv^n^sZ fXqL0˝I4g -{v'6Rvѹkq@.=lw(ċxlyT;l;Sۛ6*\YS0vX+si$Wַ c4"fI7ᅠȜg7G_E7V7/ӓ̰ngtܩtzKVf2At:I'3'(pD2Xs ]J~fCpgB[bҐ8Q_ͽ.m˼>{曇s{mc'Xy[.[| :ޚ8f0Xcq}Go #G<']}o-y4 nwIsjaKBM:$ZkGso*сżԹ^.hCquzZӛtN;~߷ҥ.KכwN)B c*syse1j5;qcȇG7ү_kt]<̈́F;|ʈ;/quh.r9Yy"y.v_}"W]#bCH#:h o\5va cj풹d*OvkCR6\|#c6D9eqڮDl#߁ٻo|&N_†us1eAȗKZV^^~K_~yÆ}&aɍBrj<;8./ȺkK?u'ԓf{5Uk/ٯb?7ςS$~3ϛ/`y#z:K||؉ٻo/EV;g͏>f'=oY\.h&ɫex |WH*'ۈ/X15ŏ~^ l 6^#~eomΰ'`OmH;. 4b>os`F.oYԯƱ:4\0 LΆVM^w{;N֛=k suaبyW|bղ_ 1u TvDuڔK DF?GqbM*X.JPt0?7: ;re$\5[\cK.sX nDTlڞ.\n&_>L:XuPn%@;By)@MR?V6\t<&>4NhCzҫCc*\qWg2ޟ@3)Nz_րDz ~eAkO ׇTdq7W6CܒϗDp]-R.8?Iv5ѣC*3n%DnP.Fq(]ҒYΫSG] AdoLڔzOT _ܝ3cr]Nv݇R 4J)n,z5n˙'6;Oѱ}WTf.A;Z}gŀ hPN&+>ϖN}xb%lr h. -v=oUJVԶI,;oyvu&mLkt;7^`WkIWPI;NAZ/ï܏Y+X:ěy]NZ~]>n6+,X_xg bjT'{!lbT/xK Y];c60d^WZP9*!ujSŻs]2!#Pqf6'#"9lAnDGVYfCy L=$ԫC`f! S{Lt:lb{% VTd2ϿοGH_=7N_c ɨ{ q;tk^YHNl/"wwwJC%>8nO\\Ejɯ7Z4۽^tYc{L\ot a]1 w{^W{]mX5PXתA|~z1\>X;Pٵ"ol3Jޕ 4[nbyrc/?:q6"]z?p]H7-nVhK& ?)6qp:D˂pGipdfTWsZ<.;` @r2;Bvtog$R"m?:/QcV1G%o2=?h4*'I^kD "ۈ?2^4Z:o,kts~3a5}H,zOMګOrN.e|8Qt{T[?2&Iۘi{xI{幇닣B x?jۢNͬ@2Z 9LрKKhc?:zQAu%(?}ZuܭɊ$pڴ,>h8re':`: xN^?_l*JϙOy$Z^S4BѪ48܂?qp6[W,NdҡJS͖T5 uS):o.ŸQn_KzDf'SvHOL2륤Z9ҒYpn<,>\ ݱL[IuH_%'ҵh1թu [sT'InqJ!OOIeǟ˒fq#ARWǟ,V w?'kO_(_Y,]UVDrRY`1[C@+qȼvu;ou9JªYG?>5a26-c,ܼmwc~8VȚ_I|+l8k AW7MF.o8`_CXYS0=q' xI&>O/4-:ݦCMـ9ᄆ;C>GS|&t0Ow4v<ܿ*q+w{'fsfxwg׼3zq[5 N鍇b׆FTh=I_ۙ¹\sh~X@qv mz cFAѰaS G˗GҽNޝRxoy#cx]ǽ^\z&gL>~ˮˮgWpZ  î? Ƈ"h;ݙu\-n;I|(k>\ИsU(w ELy RW,vRBӼx[,7hoĿ+Wo%hrr;&;S۲h(7른}83ZwC'dJsD$ ^göma²ݐ֖Gz7dK_>黥ISO#qYqy] ?H0}Q_DOl:Igzrq\4:?]Mҙ`ݓ8`>^Er$wO& hyUW׋{K_\Shl{;'̄U7\MDR?@#.9*4ˤLג]=e2C/8Y¸:<8{d+o,{ N9ᒫhL_2r<޲(ڱ\.YQR>y=9 )e2UpcmŚzpF/cvOE<Xcz`p'7/0'ki*xfϕӍsz_v)ΚK/`,GzSGdZ_n/$atxxy5'㛁<|Ofr+=qp)4?'cqN?McvRmh9Ɲ>۟WFY~ŌD PEC_྿+r姐P<0k35f8\Osf=r[Y‰{qAbO"^t8igp;z0uu,vǹX^=zrK]O U=/k7ˇItF &t9Ua1rwOҢEmT߼臤Mo}&̽;0qxiֆ1\d p>C(Z/ 㙗'tx.L"pH[o\@=t7'Yt0^k7@Ց0"+4H,jjm\[uЦ'^Lm[:`XqvՕsE kҞq\ňMbY+n17Bn[J'g}}--N6?%w<3OCqx;[6>3y]ueY氭k};fأI z'/sW+^mV~K)F"Մ|W+_$|VؑޓP`~i]ͳs֠]r0GkNn\.M:{17G| |w(>C)5[{);xcDAyHutAk8RcUɧjгDa|^IŤrKk{ <W N{Ax,edwr2V^HS49yqХF"ljLe J8L./Z,/{Y/gWҬ;9i¸9GQ] q]W\ljșM㝛2)ԫw ]߫-ѳ*9ۙ4.}j2-`a?3L?Nd@xL>x!Mn}_:MNj*L 9PU0˩+ɨ~L:.б IDAT}! >oVz?NNXpJ޴-eC. H\$sqp{𻚴8 <_BC\*?t:k)G#ӉRnqPzzk c[~'C`TVEh5sMrh7'!KɄLuto;Kh鷌kg1v?dO{Cl:;LRvUA~CP5PiSУ8fqdDZZg1l0x` We܅K;a^#)\_l&:ʔ)Rs?>p-OcDYOر5!ǷwN}bhBNC% Z$ smL2R./;Ӷɭ2)Hvo+$$'j]ᄆ'fEl܂fu.T-39S9г3di^Agoc)&gNTSf"aJSMȀdH$ rbCPR"p0^1uF@2ɩm1$vIL6H_EjGJ׮ s9@`_]S[.^Kʤ?ANqdg( ]( k9`߇s\XZըD%t*S.6d_X9;OkY@bj}\rucSm4 \b : "oT o \[2c rΝ5Uh]&V.SHghC1KmprV͎wԨU!rlOI8ON +d̔7 䤩+`Ql44hxf+b5&qSF#[%:N2jךƩ90}}/o8/Kn? L4i=s$iD{* & L5 [5>VVtZskp2. nb =Q{͑9@A|BmpH_OhW|Wnf9ާ鐥~9.O~?`Ak9J7>^Nڡ+(50mD mtFRSmTsJ瞮>$?μbxaoI6AҩjQPU&J-X *)EUQ#j6E-,DQgD2Wid+Z *E%YdK1}!L8l9lA&ۏ_L<6 ƈ}/ݑ}w"X|hFll4V~&ǟeo]~pP`|Uc'CP(kVd~J&sN_nLRIc)YL!^(IfF)z $d0 &QefdJk2&)IkdyAvyH gq Ὣ<Ȓ c'㽩Va̅$fh=_ut~.ب>ţ)LP(%)`-k*tϫ?t^l]T[>L{%) ŧN 2\xSnowa|NDYgޏ BP`--GP( 3;P( BFP( ,k BP(_0%X)י- v& Y}ڤ/r |2 qrA@;O$ϰx@ *;{:_ə5h 8ˮ(R4 Eym;Sp֝s"gPKw'F Xr}о$5( _ǁtg~O[#-N ~'Ues<1}W 1(mHF_SR@n:_?L;>vΒbv8 B]cƖ#825%:7\#!ML2Y)  GSqW*gK vX*н{bڻ<9P5 Z;8gP\W7,rzj *Hop@Ek:@3xXrq%`&]}K"c̚'7ܪ>` ![TCod~r2pb(K,jYN[rmøzűOɹX9Oj sr'm߿2fκ4YTuL+'ek?VehQA;gvbxhuy[]©p8%jħJ8>É+urjޝGEkݺu#88sRZg֪4 }Å,p~2Nyv ډ;7tbɠt^p~ j7[m@N*9F3}t?M[uz 6a73uX&=I (Q6NOzSC)CQBFj7iɉ|6WGBS*4`BVrwvポ7T=|yy6\@|]Urܧ}y&o0/>~&ў* q  qhjeG` d@-<8pBbQMOz{ ur18dL?h׈sZr\m슗elv?: ;p΋c oݤ1 m6,=<,Ԕ9޾|6=`dL1~aH`k@M}_t N$ILg/IPth8۹+SiW~&ȥɦm> az=zW;0Eppwt^pNl'lKrs9Zޑ-cz5~.h g]i;{5VGIJ E&rAu@ZR^@%bN/aiiOHD̕lf^Wv+и5e)wb0=rQe('}FǢf} 3l]wi>AR7 'eo_qrDW j>'՞j%9'ԉܧNNE9H  %)E Ȥ@t4~2! P4nhQx6 S#IxrMLG:l˭ATۨ<33_ϟ˅fff̜9EߟQ{6S>d+ܩe#"UeV5Ov1<>1@;1 4OI憩|;w2}էLX=IdˑvRf6e*2/՚ĠТw͠7Yt= cgO!9ۭ2tK$xhteZj~39 c ?#i[mG2oiiaB8h!AN=rox_Ϊf>{^;*R5`YIgmӼrG 8%<8)!P9{ urow+Yl@FG"@@kOIzd$\|?xﲦkQ3}4?2/_ՠˌ?xRΧ fJ@@ZAj5ܹs[F"h-6(^sA =~<Ut}x=0*hVSx|2% 9}Y I٨6`17*䊃yyEBѐo{b0/?Ȟt/6qN޴-e*R6FNgR) p+&yl<йnU~2!tRFfḥ'%IY΁h?*D-6Ω?90qf+VDDKR PY4ɑ^j?,%vh0ѽl.%~wݼ52fdUgO0>忂գ_ۯCfTl){4 h c.ץ}w:K,DaKp޿*#.,_ *;|i` H"ưa(^?esd1[I__1bOmKڣre/z]|} \69Ǒq}%Ĵ ϫXOCF7h5 ^PR-kTH01ـ$lғ`Ęs)ԌT9TiO·Dy"p0^fLԭr!Nîvt8Chܵ=K%z;X3Fcz\++j&ӦMgoi]dng[$J`߇s\).g98HH pΟ(]w,PZz±C 6. x7_i*@H~KŋYqigKU^4jʹQlpg1ͪ!tqܿzwkb{`or˂z\"۱Um,I*ϪL2w\0vGunVR-89pqHqGii('Znj;BM}{;wV/L|[834=#k[])M9@;|Xjt^o79*}*1AK*tN#Y:p$%BqsR L\g]t>j.[;B9#DYl!T|V ɇg9ŻgG~;Y"jo[}WЁ imk5Ƿt_OEgsZg=Έ=@.bFOL >\) a `Qw*aNB?8(c0K˙sG5GPѴi]..WegN7,&r5]VN"\Ư:΃$ 0{c/sƯV:Qޓ c9'JK>KB|4V0k E]F%egӣɻ`'L_vI,Phuh !'gQ=ǜ$V0SEhJ"p\Qby>^# ?CRJ2'ӯ9ylEJOLɄɐD涤7l3o1u91b~Kk8OlT vXq=@VD$qe`NZè}R;l*ca+}JщؕHghMŠc}š{4"wT j cK\4]I:ѡT+F?)ښ2v%`̪NSN*ψ9)葋vXXÙ dApu!%7mfS<Ԙfg} ,)Ҭu5 ֎]w MLWf@j4{1[V]">3Gk y K K)٬a2u, #WmUI:1eClajJnNkeWWm˰U\E(jY TY-89O1; imoEnǚ#v0n23U@6lV(:DnCh rp'H8 ?wH_PL@Jœgx`0];IH4BY*h6~WM-/psy{ڜ̒;ZAKf&y/Bֵ){.cknaשPM <>R­,ŃNcؕ+1׎,UgI*` IDAT).K$"/(fN)\UBΈ:DZgO,-|[R'`Rxtf[S3㷜WO4͗%c8˾vT.Df=9T cD2< \e quaӳ_uZ2f5%@S3I6pH0n%`7vGDj}t n`;#~Gi DdӁz]i#o8).ݣUFS#m)Rg:4Ix ug"0(K{;o枍CBƘG-/ȈZk#'}tXW+`M&&v n }tXZν cH^Ff%o<ݳ=ډ^o*֑ JGr(7uUej7יN6[>?؉FQ<*$Y}{W:Udo d>]i㘃ygv4Ĩ1qRQ{ Rs٤j\\QG aGiCfؐ}#|>z'b{v}[7E{֜}Cӗ}D URfN,j>dӆ-yv-qrqL{B,O{r7vDx":k[\(\GɤeHXƾT, Lj`䎱fXM&:z֝M (BDk %-f(6.+%gB#L@Nƒ &b<=0D[27ߩp"T9 + Y| Oƒs/'0 dmGnYR jк=E LH^L =Ⱥ}Ԗbkc<5e)7Uȴzo8REv&~pR#mpԔky3Y!7/@z] !,y|.>Wu*Wvd)Z&'';M i7'"Ʉuh#*3WjrfŤ\6"bu &PVH\hxmnOХ!}8Rcr5B_ $ I$#Wؿn7)BO.(Ψw]9Fe$ Z塴m>D ٔ#Mfۃt8)+2k㥆/Pvٌs mqDSm.Ÿ-U抏B 299&L7=oWBKmMf KEK,7֧o5gwQQ`M(aoUnߥWH&2z+UfB[?Wjoaa<r_MTeVM}e̹$3zVpr҆~6FA/^M7OL#.+P-6mGgj&/XQfޥtMWa>t?gCū ׈ؔS6v^64Z̽3lIF tXTT,6efs+_FfCxf_wdBT[;5v5@j1wGV@'jvoghyΣ;X|(- Z CEMQ \Gu|>!F(p/d*\ZeҫԂRR4jY5(0jSԢBuF$sFE`ҊYTEV Xr BP;5BP(L,k| BP(`?XS( B)BP( E&k/Pkdn`zƔwϺYICYS'uWm$5C)ehk/Ut/+v89ie MR g eR>^_S>aZf˕7M=0Uwߞ,8MO(AgU:98w>L q9(RR$b|siW=S{6}D9k^Bo_F"6p=v y:ͧ1(3R{_čgʤMNQeVJIDUy$FboeR6gG"91UL$1aiidr6bG^h;m{u="~$GꋹH=i/e$M">=+`&ϡXD)^]ɜO/FÆRz9MɜS۱[&T[S.+~˳wqh*қ(=2&&CQے2Ɨ{g0կ3Wk,^O9ٺ/&:vǚ}}psx}֥"?NxbkO'Tº + sb؄F{:t6Oa~1Sf.Ȭ`+ݑ^l425hDtBK0 O^0;Q{idr_tq ؾzuyanQcqtH3o*bw ri] r:`m]Zor Ҡ<}Un:Ŧ%ѹ*yTO\8"*A4j@Dk TWAr^w͍ Tk4Z67"c RcҤdVD3jF:oAXMŎ]0_i3,hI/|6(""ZGUiV N]|sgO&rz3~al5=-y.n\,%Qݧζ>ΩܜƁ.duNR"aHA49KLpghVY&j)'*Z& %3f.:DHx`&KS9fy=ӱdF&Fa; *&;1jL}\݄n5c46A6Lؘ7>,v|8$Q1YřsEqw yx SEV_p#K+4$%DǐYa̾Sz?ǚ1G3 *kgE'Ug mL2%NO֍\vƾ)ofd~&쪼 4Yf>&:ye/s#*j {IȎ_sįnVj b-;o&_,XV~k )m1B4nt-KcDka-vYpMvU92m3҇!kRxxERkDAb:ق!d;ſY~4/qŇjN%"7err ~[_ @t&$ cȆo_[FkaSDd`Ιáod3V5Zǜ070 pAXtI1Ai\+%19G~cO3q՝2"I=v !&&qsolCHCf<.ɘ7QJ`*=n 'JȦ oʸC~/?&>kWCyL;[6:2AG5\>%8]$ I2yvC"dbg-ٚΆL~8[4ǒn- ?n|m0!%I] `4.NPvٌs mqDSm.Ÿ:<(^ktm&q'of+˺oޒXե0.QPwz_C!mVbҐ \֒] fe-rhk$y~> Qm(Z@7ڴEӝ422Km&_a!TX ZRHxEqoa,T*T* YR3 h%X{{,mZs_niAfCpZ1أ=jؔ͘xjj۱7m=Li[,VXfƈSux:xr CiY*2LnZW: 3"k^3½bFЪt*sZTjIR ւJmJѨeFԈ,jMQ: QUJDuJ+fQ rY%:*(A(&SƋeYVk]aم_wuj 9?2JZ3T( ⿶f J(T*]qQQ0I&YxlKd9FB3x5bR$%dPՂd ( FAM*($QқMU!]{2 /.WJ־82I!\xcctcMP( ū>`MO3=9hm2}PJ B|&*(. `U+ˎuP( _ ) BP|`MP( "S5BP(LL >7 kCR2=vx;YbY;9^ B$)Z&"Ee $?~x ji°LG•YTuPNgzĚ! 24 Ƶ"НLٌŔk/md8.u- %odR g e6xKN4R;A@ܩ~<ۮĽqb>! YQ:#BȀDZn}*RngɧK&1x[K홺oQZڛP B<ʌvޗ6qMNɹ?:Ss8$H썽[iRsqRN3a|U g{CzZďx~ߝ*E3A$Gske 2﬈">=+`bAcٶY}{ EdTk2+o|qP[S.+~˳pCKP @ɗI40y|LWϽdd FZb)miURJ,VRRjWԾzcWBLf#DZ9k^d{dn'\LίoFg3ڷa,V4WA3p羅i2 Fs>3s)S/>d@a<A.Ex/[ɹ;3-DhGrߟedYF֛ GpM nFrT$u,OJe֢Sc4s vNqw9Wbǵ|9fpT(AD BWd[Dqss_+P3ra<%4$9w}F)q )k! J8Ǎڝ ήciY2P  SIW&ܟPQ3.La;WHt>za(οđW8qz03 ʟ`/gqtl#W>I9 bZZx,]@7J%rK&'Fp՟p?o|gTI`Đ I-fHJ&+Wa˘d7V4#nwFӡM/Vư65жPOF^\|=^ BOX֯M?|kY(i7"S3.U(p 4fY_Jt.Vžʑ1Yx'~OFN*f}(RyZEzaړj;河jG^.WB?*ʾC8t4~h9 )."K8sXÞVheY - IDAT'fRI*45dfG-D e˗Qb CiU8N`V-}q"#_O!٫ -.G,d~܈LNOfy Py:|$b.cPۜ65nx"=}cA#A2e#ZՊ5iک{Zͅ(\) GSqgw^+G+yz_9sSIȥ(nzf\Pmq3Mcs>6^MR]Bo-Cfh()8D H1"XsqZyw[ aFXJצזtRw8BAvf1[1{{M{yh232ȀCKފ*>f=K1VoaK#b4)$/lH1 uhMzAX-Ldw\Dw{ {QBix%rh@(::s,4 dלSNT^z~h*$G1djJ4m2 {8Sz~[S?rpu(VVBrH0uS_@ЈTKdGDr"9!)$-Z2HFIn˒NS:dtz%ˠt l1K/*ݲQGѦ{OkĮ^U-8   K. JG^_,NIzKi*jșjss6P))͡jΨ85ũd]))-C+rm\mHcO tݛH!omN>mZ1% SHkI̚~.C!OꎎŪ4+!B5AAx>hz  ѳ& D& D& D:3'smDM3}ؙX` B'5Ơ/O`{6S# ;K6dȤ#v Oa⯩J=?q!7-Gy$IX=3q&?*2UIJ6f[orTnxhNn>%%B)) IvX|2{5I1LlNv>0MR /v`ѥDSzj}.Onnc?O8M82I\ݑ d[9zIHvbf@6L?Nᒃ+k{h^a>47ܷt|gU&fOaED<dm̜o8V1:sLg]dyDW%ZwtĺY0o [hA 1~K%aC~џz+uޚgr j5, ߓL%yWy>$< ;3ՋO3~R iV BJaby_}>Vr)»}Jqn!F;6xJ2,#MԣMC8xՓX4"fX |*F0W*"-h˦;h8un!z;9L-ʅ.Ѷja b{ PɃUv6 Y\\=mQ S 5*'&YBCJ=s7yQߌ+XnvZJ\[fA?viL]( v'}yPr*5K{>qp zNeֳx*6ί]Bt Ǎ(n n"J5Vߒø}$ߡe\ x֒s\t!TМI=OߍERYeO*:|=1TZFmЖ I48(0죦Tݞφ&(7  IL4~Lھp 5|L)[OB)}!^P] |kF<D{ζW{R"=1HFʣKS/cRݰZhZ))`sBm;nwFӡM/Vư65жPOypy%Kz)BO!Qv2K_jp#ڎmu٭""cڎDZr;v"zΏJw0n9jOˉI d&c+85{԰%'ӲUzvUy鏌V+Vo_Kפizj5gp0܏ZA"1*W kɣ$+{s h\A&$7!qЕ{O:8vLZy))&Gѿ Or>`=S 8-=MFDGQ|㢉KՂ4TÎ:ќNN%?Tys2+n}NմxI{~f^ "#wа`x8b3ڕ]qd(`"NJ0˃'*N2naDz-Pv\G֞)L\M$0ӫswz5$]Jh24Hy|g3g,tb-{8SI'fLH};aj }zk'6CCI JXw]_2ϳxʾ1ͧ]Z]qq}AF4[e0T+G2Xyxn p\Dw{pruK KTdh~5_G#{QBix%rh@(::s,4 dל>T,|*eo@@wr?3T$$G2-Gy$IX{$#%$˯^6W%qgrd RǠBcGCHAqj`$_̤壘ʋ3f I DN ى5HDX;LԀ75UDgcY1~!t?N%L-G\ 8IƌqMDm<:ގ~C -݃"VlqQBgy׺e{nޜOf~ϼG3zj}.oPAI~g>4$quGF7m :-0"뛑̪Ám~2U97f ;cLwQh}KwvPeIlVD3HVLXaC3=>;KEEVGPMd.pU"XxWJjI?0}F6l\Xܚ&s]:eT6UZĂ}ֹ5 gIs{e;9~#h^ABjcn'b $:T"_IzÝ.c`UUl.A@ {[0{W,bEB2oԮBpGxd*o%):Rw[n!F;6xJ2,#MԣMC8x{jQc`P>#+YNWfe4ڍ:{R^^=@&OBh[0n q=p UPA*A\;w,.ɶω(㖏\q,!%QȹxJ&ʴ)%ׇHJ?q9u`*:cD~<&9WO3XфQNc>Mhs "9H|<`%6"΄0; "ᑻ5rIJCee#p zNeֳx*6ί]B{FyS?ƿ˺7GYw#jDa>zjJlHkq#`I_#R]KZׂ̔w]_^Lv^wZu)Ģ%'s :QuxLīd}0-5t|DX"D`Kybg[ +=)̞rm IdqTҰeUjVBZM"%craZHmGÍN_h:ŊV;#7X2}vʒ)pAzq2x% ?aZ6p){ѪcӡW= p_{Y2L1/慿9d&pPD&oZ9V>JRQ>Ŋ_qBdt2֪hpVΪyH^è~T}qh,/BrAR lD ct9皆=5*FO̤bUhj:̞$ //HOs l)1fӴ1[-_F2 / U(:I vXe qrDBd*|$nqf'x3zl0sErwKurPM&F걅IL皾VIb,QIlq~v~@=,XV޾INj.d@Ja?5ݟew^+G+yz_9sWIȥ(nB{R]D#cUkghn"xmB}P$ Ik.NKfS2~=AMS(3u fy>rnd2gޞkdi*m䫯n^ xvH(Hԛ2w>ޥ%ɯp6~<CBRD4/tҩE9:ќ8թt8p8wpǕDF$.gtpQT'3GU7i OnUUUQU'7ϰcQG|#a kOw&&Uq|z g;KMiU6Ͼ,T[{ew^SeODzq*lIqnTW0z5ՆKYw W\Tr%,Ո`iYa<{o)gǰll8aᵡsi _l6Q /óA$>cW08BKNY X?U|̸{"b%З)?h+l8瓧PjhĶ9ǵMtpw71lE2;l4Rm¯b\ <96}yCIXU96dȤ#v OeTL5-#Ƣ~qh]T|R);64֒(mKQnxG SH{aʾZ2,#MԣMC8xf޽{FrT$u,OJe֢S7c4s vNqw9Wb5ɹS3V-Bp|\l>sBU3~* yPJF!G-s"ʸ=aJ# 5f\y>KhHI8r&?\"o0Tye]Kk Ѭ]6r'vnv[ɘ굙Gvo[E P9qx''*#>u$W6y:Soo`Jy뱆  IDAT)4s?Ӕlb8lJFϬG%1=lHЯ_ӮI*OÏaot.= a9S,mF4^jcFyS?-ǣȬRշdx0n=IbZe@g-9;U3R#U*8|8IPEQbS9'2 ^Z˨-uڲ &4T/GðRv{>Қs(?y#Mѻ'.*dKi9.ɾ/3zAzqc|+1{Q{SNqu:A8b2{#jub2j9_2 KqmEe>k)l }5'<؜&C^|p0<1lGŞfO 9%a!)Cz}]p~T}qh,/BrAR lD ct97tG,=1J=WY$'0{$7 =͑+RRLjȖP"˲K([Fᅡ*A'i0a̖8Bw, 5"{U%yx(!Z>)JO avYsVr4X7YT2!j^`(R?TZ+(=#֍R?-#kp6gθo=,XV޾INj.dyO?+~rn ;r cQ~pLjN0$GsR j7! \㇮{ԑc ժ?]ȵ3MY N]6>zU~I$5G)rȾy7.{[*Gh[> ^'Irj8nań[@W9s;_vۗطh#C0PJM6/b84 { 6.܄OP| Ԡs/'fn|jcod܂KʉxcW|ƫEd'72r?7aK_BUQUUuq ;m-Sg%aѤ*NOa 3>c {1jcϜnҝ׋wʶIwXv6N%_3)#]}C†ѫ6]ʺKez %(aqD,0t oi8z!ya)WYJɣ<ERk߇das.ݦĎ/ٷ>g4,d^qX,>;CfZX%@Rs*m{8ّ涡@!q8:!S-;/&Qhh4fX}[ S&{(Lco D CC3`.ܚAkYg&cŸ4 3#I5Ųc~ВY2>,~jɺ% Z*{{*4f}$8|1׮fILqșx$dbrFp$I"H֝MYygtjl*sjd,C\GA#J[Lp[QΧ"uCGN oƣ)%¶87/YlŰU繕rsp>|nx%qf]bwy8wuGPPW2cMm[?|pߓO~TqlϱuT{ZN\ĦOjU #6\IǩAvaOMo+nylL*)\aErIr QRN.[B-8]ٓ / ev(t=IU xٶQaT7AP /W%{U%y=x!g/)NoTPz;ٹs';w{Naug0< [{Zx1WHOAk+l1}bvZ[{>JɹU39}鵏Yul8i}3rg}7V+Vo_Kפizj5 C W L"1*W/"zU~I$5G)rxУlzb2P5W~ŘiW:c)!b*N TG*D܂x_$'_ͯ> Kmx, l7i_|Sr٨k}2~c̀715ۚ;Iػd ,HN/H-\knOMPUTUEUd<Îe[F| 츎5=S>TI5aWcc aWPmq3Mz1Nٖ= nˎƩk&uoW0z5ՆKYw W\Tr%,D72ϳxzНNiz )RK`}O%]*b%,!o70lot(nxvD:1~zq O- X?U|̸{"b%ЗY1K<47F1Gn aE 9ʭ}Օ-ttqnȡxtt̅[0]s",kEJj[>2߷Ko T^1P4o{5Mғޢ@TK9;ޓ f/>\8ЮG_8ÄMi~A#R5(0hZZD '" ]E˙^ɨ3zYu],Nd dS 4fe,:)#[dde_j:ДЌ ׯ(-umڽDlFRO/mC:kZ2k-(_ f XpaU*?:{c7M[MKVQSGPUSޮTPNIq8un-UStFũ)N%TMqOqhA`lZh+WznC{q)S$_BPSs l*hD-  Z {<֋a?"~POc5)ǂ  |G (V^_Xٯ6f_z  o|ϚH++ BA  BA&5AA&5uv"$ ?h]\AAZ"X{Y\SB$$o]NƖNw~.Q㫳Ռ*)ڵsB #ٽ15Ke_KuhsFL9źq](!If*ޕi3r&iQ|zl+v4ޯSJkڏ\rYja lK݀;uPɜ˫QS88?7[9!={h^޿"ǸzΫT8 _Ήd*\M9Q-!Ix v]z=o|M΍>?p(;t"w5"9(mN@b[t` >;X\[$Y+by ~힣Zbֶ;9{؋ެO2oM$s`XQP c}:>zfGS[7+8c:D~uN;\hc&vbs;l6}/hM}A7S;|! q_4.QPJMZ zELLٳ3Kg;-ZBeWXղ8ڥ4*Չ3AY:f@ߦIQR ùXnGf;}l &Me=\ ?ߦxA΄BL1wԕ Qޯp 5̤H]?nXY2~s4/U@ԘB/p˿>Łn3yuawp.Ҍ lc5i_u N>'?ǻ_|Š g?bcx+ȔAEMʙ+ @NOIv~\)y孿dMl*n1OYmЋ/EsO|k2`Wfz3:1bxj{\&b):n;*mwf ((ر؉Q5w`]c]wMŊ +J/;bCc9{Dswg3x`d/O"+mMŚ0 &3z- &xb/R,usssEd2EAңG?ǚtˣXw)We[vڲޙ` d]_Z Yv ,mI?F,?Jў:B+FOM^@ CW{$|pTJB d:D̉`c,]{ h<)[($Rs|j'Ƹen2"a~(k$IxϿ?"Qac8g^~VፇvphL8Ԣ8Yy .G̥e'>HTwK ts&0?X+ؑc&9vWns![6 ;YZ=k̟?Ν;{333fΜI޼yҙ?s[nP`bpr!>$[)䅻/H֜DnؘlV&eF1dOqjTuBV" T40z\s$ prw{ޠ .%АX#"1BIt(dΏLD)S8;ʭr&トzwXӔC BW<ߤfʍjsf)ed[.}}/]ڲgQ锍JrL $ #Fx><̋cOd-1=y2k%JȈU/$5$ ^Ϙ1cBB-N2mT[ˏbT2F^ T nf|5oW ݱzy.ڬA >c$g涡Paga.*e~߿'CN. `B)7/b ) Ll @^2XǍu$q8pǧp]ƾ5?1~p&ގxѻ<..)?ދhͬQ4ϙޛrgx`ȓC(p5> kŻnl\NpdƗxZSKmlŠ$GG`SBkn~ah;v8: G d,Y/Z(3b$s7uҤI5%49 ϓPQIxr͈QĆpF}Cg۳ޒpSgV)&qb 5ԥ|-3sZQ:,S,#$pu(Wne%6NT9U.̘Y+y9] 0ȱ+D5iJ;6e`y~P;ҠޓdG<nIBE1õT-nՊ&U0PڟD^đ#$Uܭ"N'4ACa;eKd1x+CP5ސ|𕧄$P &MÏ1_ɠJWvmWpWs /cʓ߰v{q:MF)H4%rj\u`?eʴ*a5B63"Υ-?jj5FX b.9ё'HHJ$TjZp~k'NFɄɐ@Ħ$aྰ,]suqx_a =<ĘGlQl1bxֱi2w"$n/kKU9z$crj\{\U/©zپc#2fӔtcP}/2x,Lk9R['Oe9eCvNx W chZTB>y*~h$!UŪKNμzйc c bS/d+7 yK+[r3{\lu1Ņ u:ZthURs`c[Y_zudoH~}EYNK{i_fH Xe>k4994Y>L@%{;ܶ?K9c&\%aں$dPL!ߟ/0)Rz\oq\[6&бBX?s73a +f&K/F*< E 9,q+7c"{Ʋ|=D}`-Pr9Y;Ӝze}|#_0kD~5C47{ʀM Mܘ|d5lt:U C(kە#>[[* "9Lr*㤁ӳ;Qͻ0ejᇅIѓۧ pp&%v%&ElUXy]I!(:sX%2ր10vk§uW1(FUg؝T ߶%;gu`3|d26k-Z3JNtzϥ>Wl^SHZlqqJ0e9f0^:;bikΑ0&Șa"2{8]&.7\B&f)rHhp(^rɑ=y{$r-] ZҊ`xLJ2׺gC&BA¶*>qv.XLSl'Pr-kH-?ǟV->jLcBvxvq,Vj$zÉ{9y,g/ <3Dgو@%Tg$L$<=OSչ4w^IhX9ٛ9 lE괊_3\8DŽ;Ď\-M|G/aYvTNs L|)Y2ʛ=gs97!2sɑmK߾gCBN ̌K[9mҩy4黦_;7bH2H~ ) (Fïs`(W)\fWs Jrev؅C"b$vJiS ݰhcxzu"ϘKiM/nr-$\`l>vE,15<`ǸMފZ;\bը9dMR}K#:rXŰLx~ؔBX96`JPev CF'relAz+ ~iG`E E68|9:`mfȼ]h0}m}XX`o>␱-ݓ7Q|uc+%Նpc2#A;=6R8٩*Civ9ytzAkm9+[rNk5ZYh5dV4ZSNjtNUYF}V6es#FZ6dˎIuT5r㚅=}b`Kl_:OO2wLN*N:OAO)Uh4dsAV$nRHS$Q J j%̨$6Y+)Š`ԘդћhJdS"ڠ1TfakmHҟ/#AA4  d`Yvg֡'r~  %gMA!  B&5AA Lk  XֲR2%|']&~#dR2L zj"!gҥ+$Ӌ07ood?HdgDzz{s7Y7+M+CU.+񔐤&{zV]$ T@x7)w/_EI2{AfbrXIwdځieҾ|!!I^4 Rytd6] IekP\go ?>|U߇&6r+-JRJڵ]ݤ&v>} /cʓ FV>Ɯcon|d-s%=q[S3w3owjWěKhJNBbr4}2X?W/©zپc#2fSI8GLd.ȨD/ۉ.e^uT/ϜS6ٌo0>bc< qg!DޡS5c t#][ͰOw1\wƣ*B_86=NMT{ZԭUٱx{iv,#mrL6ùtK79ôu7I/[ݼ^:d|~F;_ԭN"d'9y;,nfj!tۧdedYF֚ULߋשD]`/Ná/CʫW'k L\h-sS03nuigt6xǀKYt:E](Z d[<<I4}UGaS eJC>#rt7I~:S#Ht@B0EТܨ;b=Lqg8\ɩ;7H{§MU)kxYUt9[ eD1Drmzs,O:xlgu` *޲xY}h+ó ?iOr.wxxep5KdNx~ | ,J6iދra"AR\n,^~)ܹ$)n΅sI4Et4PB࿧ ^2&YFiLm:ynKOj= <9~QN<1wiS9 :c-sExvDJҪY̑Keҫ4j['>ifmAej z͊w/2 37(1Ņ1㚐gYq+J:n`[žxFR}3Sn|_D5IBoc/HJgC,6_+5 ;;T5hѿVl{{gZvc}Q;8)vѿmKZwq;Y|0dl K/[f.*oڕɕNk_'\<UJQJ^x3 \w3,ܚZ)Ub*HkqFnĩ$N#_Z_ 'a[v[Vx8;oa, &)[6,2 `|k37܋13Ŗ}/!&cW > ٰuK9Q/'ϞP=A'=z, .cڅJrLaO[cE ɯDT+kd-^ L$FǐA6EV3geL{Qq8͝/0a|,g(oL{eͬ'I-_wtXG*@o~_j:‘WP+ 0>`Sv.> /rNM#W(ЄvkYVܪ9EE_HV7EExf$kQw&]eJvlMsJ[kx|ق-װvIVkQMYӚ-m|hܡ&Gon&GsRXY($%lN+YS u!(IkwN>xuG!KL)!t;cgx˂"r+We8hѻ3+~oȘDqR'2v͚v8]|j}VNԞ1%+V'6-`[k;7s^|2ˬIA,E&| ThB1l0z2gxDA܉_b)#QQn:xGX!A pGiS,T!bD5S19Vs^ytEAQH|ueJؕjKLnEHԵLkEH^6v| o:/$G]0uVN`AAY61;imy7zvD(h!a *\ʃM&b`-SndGђtM$ b-dSZuNh>cRyG:Aõf*lȚ An^ E]dpqz=Ƨ`x¯R+L LTrU'W= kA h'%5A1}|셋h替th  dNW,TI^_ѐ- }nXoLJI"MJF)(1&ENWD3db0J&QcfPcTFo2&)AoTM&hS zM'?=+!_F  |D& `MA!  B&5AA ,k‚    da"X@} t9% [;׏]$$IS 'ȳ2W$$/x+51IՍ[海0SB  IR#Dn)L{mH' 3C%>x7۔J#**=,WEAzZ(5GGfӥ $QXť=~|D IDATMmVZOkI`?<&<ɣ0}ks'㎈C,=NtV12v QƦ5:M`~;}&JK^Nts~ e>nHkI!,*ˁ);oY'NFɄɐ@Ħ$a0rI5|p%'sNmɜ+qc_1 {B%}Ӯzߧ j2 pbp#@=6=@3 2*dvKl<3 {6#y:2.s#IykvC%U㹽} MJHy+;F}FV їW1+$+Otέ]*b[-6.=W#rt7I~U _˓|6=d%Ksys\CE%LZ xJm2N G"ߊ8Ȧ30 798$#_>fAH ၜV Phٹ\.Ӏ*!NxCA%[V#/mbxv'Vz,gH(YחdNx~ wPs.( ؤ}?5^Q/rc2gs瞒,[9=$E`LAȀL/3CsvW[G@Xg87NzsЉk ڕnOB6l]"6(ῗgrb(O˓M=CtdN1- VI{;ie5VZ)IDEi!IfB\@Dbt HlSKXn5zVƴǟ_grfO\7d4"X@dے5p罳EdsrZW="` 9N9 z\M$aP+6Htc^3$Q6oouְ[9>4Ӥ%[R䳐\%ɪ0~ҵ!j){Z vvv;⒯;MMJO<㴀8G/a]tb^ҝ%np.՜JS-·\.s$=^9 t#ҙߝID^ǶhnGͤ"Rc wѮ=dY+d/dpNw-Gu ͇{/FFʹ+t8S'ٔﺟ[x݊[&"~H$:ܚf[뇌`Ƣ*}J]rh$ v `MUNwDr{7sכyw{m Y :UeH?Ң1M.'ϘޔAF>UMۮ/rX$/W[טk,jLd#i$Vd3$ln)F NmdsN5jl 6{ݲ.^eoҡ}rVUg_.ޭS<Ԃ{ra~5D. dRW,TI^_ѐ- }nXoLJI"MJF)(1&ENWD3db0J&QcfPcTFo2&)AoTM&hS zM'?݅/O9WA5''0~k*jF.^_;}c' S&/s:څjBiqM^)]]B29p!قl  PҺRv{ zïJAHt  d`"XAAD& `42ls3ސ|9%$kd'; ڟ$IWOSx[O% hsSM :ɆN ^_. 7\][&E')/v$?wE$$ɕ[d(xyzeńk{0nR㮰TH] ߌ^ǥRZvuL-bP{H:J;.ũ޼?3\ HɌ ooު|3zlbT*Sz}Y6E_ M|# nGiWR".t#DGg$!a 2[g ևCπ2Cq7%;RegXkN0^'H+\ڰ(ajwcr 'IsQx K31Ofd9o.C1C-t ]'UkJK*G%펀yv{dp\Iϸv׌2-Y1(G g< V< ]%9D<{P㮲M1:oI]( ?S}Ζ_yߩw"GqzV "R_Qd^JGF֠R(d}'' `vx>cOzR2y(ѱD ߷s7wi[j0KlhĠEt}.HJ~5UW0[$&ŀm4ti%2,u֍WDsf-nVslzΩE%״ST*x 94#}{a; 㷘1sŴLkѠ19iLb\Ý]zPgjD2>Ēn*ѤLЊ|O2 jQ'9-dPSMF7SAN.|ԪUЇӹ]e*tcrݩQEiFgEkC B`[ejLV-F#âIVI'Xq:U"`@A)Z>eK d26yI!uƫ=Z@vo_C9$eaZ:O1wދ5r| o{Jvee13wPgh/j d+܊z!Z6i٣93oPA-cU5ɖ vaڵfN||7C?y _ŗֳǍj0hwĬ`G>D-nMlڄx|Z:]<==?>ov1k,+q;l)۞U4uq~OގOi^:-W `ioҴ&66dsp"114h g`ȔUܞĒӑ D..-B&}fYvA8@`f5C:!ưm5Lr}<:6 {G;{[g (ݯ#h&0`j]=iU!LyQD?H.\,f6(rqO:xzYn?K #KOlMB%x0o%n:@N[r5˅>Wd#93 Z.+83s 0~|CC4n r,U|aS\(ɏ ǜNE-e+\\R~ XYh3 $ EG9\A6L;2osiN~~Cmّ39̟N2p%]!/(5Ld?0dpIdK;cYῆZ5\PhQqwwgĈx{{}HEhڦ ? b!@sJH%-JA4&@M+hrq%H``ŋ)jun(< k.44;O{;f'l}7^W'IMzwxU̖lʦPC HQP (JG^"MibĄޑ&͂ziBHlH#B}]{ٙ٩yΙy6^p-nЬpw)֬,dAQAbw{1~~%WX3ҰZ'V _EXnqrNv9E<5H`9kFJzм,L V @b2`(97|UZK;KrvwFrGor?g%r]rx'-;r1bgkm/e_qPG Mɯ]*gO:Tq{LR1}M1̧CXƪ \^_O߁s UO3F1"45P?T|7hg ~$TtV{`I{OktxY)SfU@Y~XAADfG | [ӳh$IH"Қ=bc\.pxrSfhMb٘Np-G@%-z_lOmZ %|2MvLI"Ǒj$!m#ᾟ_i׆$$ɏgecz)f`7I"0DϞǯ!fD*([k=:>ƒRA4arm|LoIa<Χ<݃yY0":6Jf"BrYZ /^8;0i~b3JrVfOZ_MM;CֱnۯggK冹$@=-h6n/wLjJߴk D^H"Qzz P0'4GIN.Vc%{"d|yl\TtSG>#.[೜6392 l6L7һ`uz.ţ (6>H۟DF ry'է!ff au72'3tkWssk,> KSXn,sXZEblSɬɰ{[284 gUr͸m7̿Y5~;FPe`텓qދn4"?g#M'GSd6GT>G}4?m$!ŧS[Tfӈr9#ёAܗP8(vսD2~9iP8F<ס뀞7-Vb7Os|/oW\ܼ(V5 $@gPB Ŀ'FW*4jcן)(OJ6(Rq*9SSOZc2#ލGGEe$ne{%n,X1c̳0-As>_*uc r*edYFDp( ܖpUпw%\4h%yχ?]l@b\ fRpLDQҹqʗD'9Q//F& )Ҕ\ˋDfk:xXv G/c~LF:٬Hoɼ(+i1ĖtmX9&CJƹ K/e8}ݙ/L*ig~?3.q /5{^ :@Ihf&$|jva(XOLUjpyN IpxB3xBd~Tt~ڱ~~sϽG7|]$o 8߻|G??k0cwI:ï zlm< <xuFˠm|\IWP/l*VT5dp6sW 7#qͨ8+BHX~(01uY?~#F-{vsQ,9l̞%N'QÓa}?"YDϼ|9QP}Ber"IBZ%WeÔ e˗M~ZO<5TO#7 /Z͋?KWHb_7Nj<6m`7(] RvafסC؝$ZD;[͋54dWJU@%A'7ZofZR",/c*y+ag:/zw A+o²m1eNI댫nXz'#nnnçD Vs1+Y9u&!*W-cxmiXDZw+9KǏۨV.g˕_::Axu ТLMSy'a?XSvE)bnY"x ữ*Jk ~i"WqiN>΁q궙F 𿦤pr4ɴ[j`ڲC1J;|qdVpB[svƶʱv˘ݥ6 bfZVUŪdv+ gЩZ#( bbr=b!v\Cҏ)7}qO O[ q)dZ-sy>) (Vϲ}X|y.'s+q{9$BJY.%nJML|}D 8R}_|IJ҈ c|_-W0q5FGG [I ];t[EN'Rʴ\^qjƟ,l$!4(%8/V0;2 xx{9qtt݈^!QN2bbMIQgz}֫gqꊅ0wM{.AQ[XK&ai3s>X?͢>ƗAw) zfPdKdόlu|pnugVs"kA>~jNƵj\Ns^NcUGS FF٫# u]E.׹][CFvzv1J8p+;ݽ1@P;KpC?tZZD3aHj׽j 4.e0˞ 1v|֡nwoj|B !]6E:I1hZYh56F+%֖ӪuVUցU Nl8jtl F/Hj>U#.>.Ey`%q:u\?c99c*6  ,JJ| ￷y?zZ O讌8?-s?=͂i=l9?U2cvqOݹ}O%NΡ9LZ ٓS$Q,K"&,'LNe_Ԕ#L͹#5[u*gմ3Dk %_Gb\F76Z8kN#* ] t*u]7H;TB$tá `7$gwIzb_7Ļѻ8hT"ȰtxTaD.:Mꋌ48-Gudq0%|jmT'~L VNҚd͂+G'zͧj\F.N^}p\ D'ydYѩ):OM=P﷧Ax(^zrC̵"5vi΍P':ɉ"}~662{x6MHI,irݠ3Sүqb]J_ VEշgdcwS<Ȉ݅ -fd-Ʀ;Ώ }Owõ"&g8{;=Ìj3mqwۼ*wJ6qD6oKon< ֌Lp;+n;t~GKNpDQ!{@U} /8Jڙ )]̓pL,Sשs?S)$`ғjnO>,d5(_.}Oۄ%׳D *&\s,ضߝ>aSӸ(-Tk4E쿑]` 5L$d(2zj_-ݠ3RHG.Ȏ]CMO꼉?i}xvkMۈ`Yh1/ouFtxVĐY+;bNȒiz"$tQ;.5 `8PFkoڎ^h EMn:m~-Y*bG9%@|']\$FgD Jigqį4ׁR]9U)zJq![v[n!z'Waџ{b&~ׯ1r'?ozrw6?jsANtM!5),P.}=ZE7o%6,U 'r|o=kx&5C6~.\B|);0 P!NRR1N=bU2.xʔv}fpavBHt:-V-$rowaf?jw2憛{>|JAj5GtW Zƭ Oc&Zy2˕_::Axu ТLMSy'4]4ex*95-Mw+-ФKR%%JQ~-HSiٯ*+GSXR~'sE$e\~fk>4K"X^bVϠSGQłbEQ$ܪ2iIYI:)5\^DBAWKIzӧOsqS6׍Zzz g• K~*P"W LM9^ ۉA@!n%1Մ)6Nct}3rY u_™S[TAQPE~˳:ϲYۻѤd'V|F#ołj .+$HuG0F[*&ڨ((u+Ik'bK$_@} 3S3dy&mh_57H[ep@2$D: KzV@'Ks• th-.L|rOH4; %g@6_:>8z3+#1pLJWBRbUp~Awi0zq w#zhZkIP6_rwu*$'ܵ+=@Yo",l3wfłM(itѵ,"3{-+>z]|)W 8<8'FWGꆱ> F®I!C5$z,&fuޟ xB깕l]7gG\`ou=r_-\8Fҥ {6` ]ZF;F.9.ɿeS᪓Ѭ%Vc3kQhm::YgUeXZ$+FF ir>S5r)PgOF;N.] rZ0*+=Fg~o]0lJMmf%Q1I J"j3`UL5k%ŢXUY4zUYmzblড়E>rE6$DfMA`MA`MA`MA`MA`MA`-Op)mDakA*Ob}|G0KZ «NMq}i[$l,ORq$Z,IHaHx\mk[>A1?qL%-z_lOm Ij(nbyܵtq~ԚWPHIz$IܜW Oݯ6L꒵-k`˘3X8` o$Z[LTPq'$$_݃yY0":d,",t!3?hɫD)94IV2{rף6_=ެI"e蜟o8֥2_j+q;>)̂#$'`I+Sk)u_"rӥ{74 .}{R}m6l Vw#sb0CƑwO>LM9ޜ{;X8ډYpu4 bt,i;5MݫF!f"4x %@xbtB>vviЫVr!;;c3Ip 2,#k SS8t235*IQ dXt:<*0_ s&Qњ lWSQIs~=kMj}j[P+ܸz(Rٗnc#WgkфtxAքg!5;_#ĺ&9z!#ZOfәuVuNe\)IQP桅Y(IgZ54Rgq$ «ǎ_8j{ }gR/M^r=KNbϵK;IbŶ4 AUa։(2*Wݢիp)ϡ_ȉ6l?K5G\.V0u&[wPb~Kks=F/A\k+߅v9[͏3] 峑G4=5iXub̀MچH$(BұŬ,FGAxX1i! S()'YҾ{%JiS;&;$!K["8<+ާ[cDO($ IBot;Id>"SHň>Zpsjyu&֩+ aLt֏HQmqcKN$?>*0/IU&c,Crh|S+il?kwq!r:f2*; -А>eJǁu6by+y-n'K ^5 QՅ ~\eqڅX΃U1[˝-lՆLElkdp5 Y}*4pwDֻL \[U$)I/ec!c  WVeCQbdS4]I}:z~KRII^x(s6J&GZ<꽖Q9KhK@ X3˕_::Axu ТLMSy'/aDfԴh6E,c-+`o1]HXۿCƽZZ|˴@p7zAxթ(V bEZX,Xm=Be/UdbUP㹚HӜ>}Vw!>`PEAQǟe!3k2ۙ~_jZۻѤ(M4b 3`W޼U0y*X-V5%+{*&ڨ((u+Ik'bK$_5ވ`Ωs1^鹾µV IDATXYi$]:!gF ߥuh$>Qtڛ"3_$BHMrNk GV4ZͬJFIe괪F'dUu`gje,("#e4OIip+EylԱt~  /% #R3O/k4xbוMRͬ$*&5IAIYT-rF fXbJ6U`QSTFo6-CoU61٢gPW5Tq _\AAAAAAAAK  M/A& w`MAx.4+ ¿BkvD'1W~Ҷn!$I+X^B=5!ec:Q]BRIz\NiA$\5C̻CGR]j.IH[c<[fhT$$i G3 _ֲʷ`p~qeOlfR@% =2'&ph@.)!IS5[z7A$tϺi9aF`nLaNe*1 ]L1^`Ssh'6C$Goe%6A(X-CDx 4DMpN$Re7(z&TwbdRXc[%a'}Jߊ?:X7{}m(o OO=C͆͒AndN f8rI5Czsbfb`h'fJ{(m W~Hp/Jǒ _tj* ?Эv*O?ɜ̊ k= ߍ@poX(ٌv3k?Uht%D{%Nƽz/zWú)ӈ Y4ߎR&Ʋ]9NBԴ|ZTgGHS5=.c90dw%YBԅv f>P)}n+phd%}}.WfO7CL2;x=H}* 7/B`͹enς( s4pip,\nkӬ\ydfKC*iR2~plNtֆ,ZLJRT4:7 !EI}Tf¦9i:}vDT}GR\_\X>=?sU/tF bH|0EIE(_Dʾ\pz<[&s4Dfk:xXv G/c~zQ"7@Ͻ;b2bewa'rjj8מ̮d׿.Nd3b͸𻳘$ʷyjM+\_fgnA¹;)S!M()IuIUrMg²*,*Jk[#Į ; .gEIp'GlŜB*F\֚쀛T Ir28֫fT!M$S?VØZ=C;ѹ(H_;I=^소\ouJVm\hz:6~ԯWz5& n#d$ p_ڜz0gfq(AY|;.`[ݨmD u]ZYG6 ea/c0Y}aM&~8?w:[G᷺QqcccyZN>Jj5pƄ>(O2~GC7NFpsχO=_bëbOz#O2=zJ|DXr*F8ْ9z)$; r{wZ8~Fjw9[gթ DKOej:2, /e8FjZ4"V@ٍ&X֏((T"J#lqEwmTmt{WϘޫ& jb1cSV+^5h՟w~ŇT$*#6noc)ѿ&[ޮlVMMhIǔO0gG`%nR"6Gs)YbX 剫EX#37"iHKFlt#(EQP+gپg,OD1Ų/ղ7oi'm4b|n|=U6L\MQQQBVBNp%]Ŗ|I1j^Ċ% .5OMaoݖUx$jU $cY LATeOjȝBp 20-=zǢ^氒8Tz{I芅0wM{.AQ[H`ጣKqBDU &.oIpag]J;_]`6vM"lE *Jz\Ϥpӣwgk,% %Z hwIAՑa.yx d3)S\: uJW1FGSka@؀)}Y? h$ e?CuE;֌G˼k'HulA0㻴w'T5y-9 A @/t-g$Ơq4keId4Z[NjtNYUYV}V68ɲѩ.2Q6HnO#TZv Pgu8t}& iHT tudSmh3+IMRPRl)U(&bY+)ŢXb8Xզ۬j[dsL?|,ԕ+r '5AA;&5AA;&5AA;&5AA;&5AA;&5AA;&5AṘNB<.> +Ua?Obz "85mBHDWzL.-m$It& >$$I~DDgA,WT}kMЂ]RBi9l1Q[zHMao| '~WJzf&u Yp݃/_AO6؝һ$Qx֝Oy5~3v`Z[Ed,",t!3?hɫD)94IV2{rQ wޖs~"ۋ^'ʼ_73xSnkno{d yfw_]'wif^ ߕ%mܰ>{R}m6l Vw#sb0CƑO)GқsoGk63C;1Tc+>mۨ.@6۩<&s2+Bn2xV ~7MYaf3nMjv\`DɸWEjwX7e3뀑fQԦp2Wmy IIܾs埶O}ө-*3iD~HӠgyRsl%b>kW{^y>נÄlS_gfl$MB(mRTK[MQMuww}*=h; "rnݙ z<9fi*o2yK])g*k w_Q,L%/ )_5:KdFci?B֪#Urfk?]<~/K:Ʊ)<\DԞQ4 u׭GE.*' U{Bx {$x٤I2\:KL/<6XB_>#.}N4?~TRNA5,1+1iA "RD)$] Z;#zק\`k ;"w3izꊶwc?+ӤZ2|V֑B5RaWYĽu`՚$Ʉ ֗i'I&WkBS|kOjc,(7#ٔ)r3CgdG?TS[IMw҅W$O5i: IDVJ V,J}rdR+ $∓d$&3R9+>eShkDM |@1__|;ž \=|Rccݣ;Cl `ب&QDj08; |M屴iޕ\#hd蝼7'ӯusZƚ|&nῒ bP=)S 'ekzf>O.9I OOG?RYk3fUCn>kpȕhd#rN6 7 ْB-y+:?H)^EGj$.ȨqO-2z'gpKߦ~%|dh߽\Q"{mrE,ӑ_K8d:%''NՊ8 LKuCPVwJ|QbZdfZxp*̉<2vǾOApmCTd½kW0 K^a#^yŎ^۹mQ l32`܍s f0!·r/p<"Qϊ5.)ǐ>Б$j}74}Co爳3.nx@v98}WW9J n=DM<_ 3ByѺP/7]|E9P+r6Gmgwּ0HqW-zO*ڞҫ^,kDũI||XqdIUH*-E[ty~b"6 Pprj&*&ωQ{*ŌٜUZ,f,֬],UcܿpsqaԴ<&9v[7kQ1;i)EM=qvNy7sMg[]U@ڝk21׉ׄq,Ĭ}_;#( bx Kmu$˴y&S`w~3ӵEI$ƖM֝~ŚDLٖ=}7_gM ¶Zx8MQsquԼCkY|m&ґ(ާEJ :>A]-ҁ!5h$4z-gT$fDwVq@ ]wrGxCFm>ıMAz\W868抃-GW\ ȀdWSpOdeZc'!]JhKM̚nӞ<=[906!$:6Ͷ7Uƶ 㻰}ʧza`%a(P;`_>҃ b8֯8v A d&>${~5Iëݏ-YMRc#a(܎kp/:uW0fPw}6sc6 eѴ9̲{)AizޣzQQ f5vDTz GG*t-%\NvIzAc%VcMh%GItZUu΢:MZ`' F:ȎAre7cj1wQxT([z]{ry^-ܙ#JQƲkYfV9@H-qLh$!I~4z%D6K4wD(KFM෮iѣD]-9Lt*@ -c/Iߞi{=Y.'%$iTnM*HDf^{2]->S7n|=1EM\1!cِ^;أ07B|NXe ¿C!wF %u_ɀ>OLđD'k>̺ȴHG+ħ}TT.+HY">:cN<^Ʌ!*票o>r8bg{n/r, P#9s6M>-E/}5\Dc,' g{r12=,#2ր[4 Gb=%Yqp-Մ]EkQ|7o/uR[ve(7g-3a-FoϽG(Fn_EIvX1quhT&m^1_Zopqn:C">XÎp=R3Ne.!z,8i!)k[f]֠mx.tC~zTZ0w+4Ȃ%kپv3Z0H *fE;4ߖ5 ?fPRWE_hqڛgRD(ֵ)C|2zD|\՟EiY*X/(T9pReK8y)8FPJİ1H-Kkt-k]r24ͤ+ږލpkLjY1WtZG }ԔJaj|wgj\iUkΒ }מ~YQ uKMjA[ep.q6Ln;1O _8q:tf;֫''RtiYrh9K|/*8S,DT}lLDstW|>˞ۧbw@Y=50{6>(ƀG%w8L Q+ $∓RmpvhFUMǃr`pv$A**6NciӼ+!F0";yoX#O._h?5yL%^ bZOKl@dɅf`ㄧ)k `l}iȑ GG[CDc4sD^-aɖ>qWY |vCrco1O18:➇50=&{$_C. Uur4;I߀xH R~].ܳ5|Νcc;+tM%>F2zwHJ=.dpVؓ@|`ClprDrٱ8MF.e5ĺ{ ;F'?,`?v Z";32xuVEFUș;6DE=cpU1 *Y*)m;YP5|qIhnطo? |xyyp LǒiJl IbFwO7v8;;g oW7q%NՑtlO֣B5qD(N~%hY\ HxY9Yy HZ돯(5Gj% C.ÚFwy)EOE۳\ΗdM"XԤp[Cw_rLWOf[T;>>J QQKLsu9 E5s|Dc Yb1c6bU, f5(Icn )H iZ VϡDIIK/ >BE@.U"+$XU߲](,D1`?~Νhfʒ 4"e1kg_cȧoA((X0vCe:eZћc&}Aa[ sAn&ʨb¹8o:U?!,NM6iHӇSZq .H8c@AՉJ`Q =z|4cWLeVԶ`[MF-Ƭ3K H`dfc됟&3"i7>H@>s ua=2ۊ =[t-hA WWG7W'lm8l}s u!= ccѠJ@/lB~!9g, nkVW[{؀ f FU0.l)iכH c*N@.<]9 ~CiY4m^}aJP}^^uWd5vDTz GG*t-%\NvIzAc%VcMh%GItZUu΢:MZ`' F:ȎAre7co\(/?PlJIZ43G"eY!MdpU  d=kVK//<<A*tߚWR8%jFEI()MJY1+fd5[46f5AjVjX%՚b7_%&jBN(I _t`}x`VA5qRm "PALkDlC`nW<<:6 Aug㷞B_DzQgv>  /K  da"XAAD& `MAx%)gT\N7Zs`- QaФ3"o9x( I: e,YSWB|TcQD&{zAՊ"IHRA?^-o]yu0o]aU*ƈ]LhY{IL{ϲptY>)(!IE7p5'L rsl:UD$4ְGrWf'uj`FT1EM\1e%k{tVfX ,6Aw6.׈󶱤4t?Kjjj$uݶ]}kI$Qlr]N)1ZXljil-&;gT3I'.|D̯đ͙s6)>3׷tΒ :`ĜKip/ΒOH; l0(@2,ﵗ}F9ewAq^}ӄ6"sAV%Nƥܗt e䩬X29;RGc en 7:]FѨ$U<=+IHz\bz*QB&uU:ˠa$=jX=}{+lvHd;O >Tѡ=|h^o1 vWOxyJi%bZ4d{9pReK8y)8FPJİ1H-Kkt-k]r24ͤ+ږލpkLjY1WtZG }ԔJahNϗ_iĽZ2*sCגQ1-==ã_ ٙ_Țe's;X |sz$ѓ;͐x^7XJ4G~} |衉X(o~USsg㓏Bjl ;{TPzG{ÔA0&#N'JMJbU5'Uّn:M.M@#Gap>~Ӣ0֜9o0 vdUC@L1'6IBܜ>vhBCy[eX#jwƮq8|DŽr s^'jno',$"fͶtx:;n"`:i*+&K]Q"DũɗXf2Z:e{z;+8X s~h9lu!R#XTC6 Bզ z=S.=W@଎Tqu΅w{m *Hڼv+1&&$d@%U>v̉o[PH c1ץφ +FF>G+uٿ !Er Y 'v?d5]K=ёl 4U߅S>%@PVH7_tZpa桼d=n1lJˢise* SӠ Gj^툨7A.T ZJ줓6U+KƚJFk5鴪F'dEu`ћN [NuenIuS5߸EQ^~S4ovMXw-*iGLlAkVK//\edUYU5Uq J,%jbcQR@bVjhljjj&-J5joV JMԜQ7ioM:_CW]_x 4 {wcTn\(^tWl' Y9h>ƙeD9ӳ$_^]1P"?oG#38K,b}>jV"^F9,I-E'ޑos:Gď2ȼ?Nsdp)l_utJa!u5T%hIwq0;~MOi~"raTh2kgB{|仜VHNT4o VYI]o-9Zh;g5VE)3w h5 qǖ2ԓO&,3V~gj=˝;:IreQ/5{IMomٞ%Td$?;i6$Jm>dG"ޏ{qU f3@󡃄$ZibD,.qt'xK:ML*nA oռ?k9^dT ?4K{륿l63w\,Xkb P 6|Q|?oP!ۖ1# +ދҼvm=~em66qY{rcwI~2/;o:P`ĝU?ݤI dBD Ƶ;ySM\[%WpH 9s]>Y{¹ioMέekPёl0XTmӆ 5,\Շ'PNN@Q<4G P,(2{rIڜ#.rᾕ?紮5lʔ>buyǐ¥w7̝SA[ /9ӹE^uOhچI1 hPQy2)[g(۷=埍8 N1Yt E"Ew׻3ZϽ[ L}?^A|Ľ$y$рI=çsR9cd):E}PG~ƚ|3k̦gH.mC| FL-6f"V1hv`fɬ;-Q&h|!^ze%ozt::t֐q2r DhV>GQF\u+]GY~䲑pHMEy-fH`AjUIܜp[%r=AKƣY  ņO&,/nl<7Q*-^)bU9~)ƕ2jo}jntX]Y tAcO\&R uZWUNlXTuؼOYGXթvpnT'2|~wg] Y32}zOp_wv6 {3T;|YG,ë1{_ 6X$ 1c(__Zא|iL 9O͋$HmBR] ?OXt:9-> 2 IDAT,gr+E5gӆo}:If*kY~՞=g=p;XJr/W.>^ IGtq-; KQϑH6h}",MJD4ϩ#A Sęc,0^g̙ϟ/+9ׂ>l5-JӪ/hVDѕXLV|ܹ[ŘcZ+Gr[ WGѰm 1s-.->BGL N|<{fC#q ;#?eŷ Rɼ8[/Y7\V"W~k/nC>l^ΐcݹWzt3kץk"=foڋX|^/um(Ԥta4ǹ8w>7v#+.oMZ׆}aY_PKݫ{rUsi;b$g?捏L!|8MSsME@{x9]3}߆c$9uNs&W,ƀSuYZ HLܴre3_[x˚^<n8yw̳mkP@s}NLM6J!isW?|wކEhv!e0(:G;{1lō--~ɼKɾ4mȔ;2|)zr4ص㋊O4UC2x-6EKc]U (5YT<t4:r}<_OEKY>o5 ~Mݙ!wgqzCa&MCtC};>Y#y&FLfL Jcodp[Vg`ftlN>ThP-peLKq& (P+W- &cph27 t4vIu"Ⱦ>rkPofMb*HbmEl_3>->Ӛ'=m3fEt$^\MV @#ZW}81#@N[gѰ:xe_ڿ)3YЁ Ol Q'b6ZA݆mݙmO@%}|ԋ%ޠ[T,?{:5᧠h` $Rt\s"koYlѤ1?sI9kEե3} ٗj!9_XG/}tXHvi67`A? XO`tXFap/z\)X;te umw>-5mfnMOފ;ؼE^~RG5n]ҵp9I'5mV4Z5U%jiUN:*7ie,,( #;Y4jd6~sEyBi޲+ZVe Eq&nm@.qAY2~/,kpuw% UgUT徒)( VEN6*JEImVR̊Y1[$٢1 UZTŚ(mY6*a7QsGIsq?  B'5AA,L !lu AAcgMA!   B&5AA,Lk  YX ֺtBxxot$$7=n][D$UBcZߏK$?)l*ӿ1I˩/:J,}׼xpօƢpH;jI't3Q)׫bPD$_*ϾTkJq lAU0kL2ğcӘTt67Laɜ <h9~upB FL<Ǚ4 H+2Mr&.}B˳wĎI(9bt%$"3M`)#IH^3 $hBo!Q"TV-z*dȑom+gFTDӝY(Ϡ TLs4އZ 0{]D~Вe]ZZ/ /b3x8FQ:俻P[{FTĺ){Nq}݊:noLXW&_Ogs3)$]P3ƙ;2L0hzdeʇ9?e2(ɤ%x)\2]Y:ȼ?Nsdp)l_X*o+ 7tP%I0!Wtc 2Jyq62mXh ?O)ޒVB@>kH [L^|*H}~0ۨ6}d˞5Hǎ9w؊d߸q h; @q$I4e}5O9Yyق[nO1ϙKIc:@,[k~#xkFV=m$2^`÷Pс6YSӆ||q|ISor0=!!E%Gr2{H@qEڡcɀ|X>_R:åO8%T l{%>#RU>CG.f^)\ݷodDaJeHg(S#1sP_ 63}Pp~o5jY>x+Uw=o95O^ʖàO2̝; -I p1.qn C-ctyGLV;7sQc~#t;fVsGD5)B(?j`b!i} ;-SN3t;ϰ(.A XMcKXłذaT,@#(6"("KGcKTT$lbL># >>{{gs93߱X)j+lM>Y <˅;YЏ탙Yu辕QgV*`eS; |K?y07I6؅]Nx G0F}:;?i|N1iyza<5'f|c˚yƽ7}+YtGeңR&`M1aƼ05@[CgA% XlFjK7D>_r,b$G}{6;41]pzFWSu31s@kc)qe++Γpk۔T Tsd 06Pš|gR"bLe6XKxqmtI$'7,FB@]+" ;YiVʼn)9%Zmf&RJ@V ]F_c VMF=R)e<7Pl> L+wb-Ug-P)q!$8$.uh3~>^^:=:MQj5@3y{>5 O{H ̣\UÃh2=t|vdZi㦱$`0[_(Sac1^avnrre[8-i>|:an{PT~5^,N>%qCWsEYr5d2S͑2 UEL=ȼ^}*Nq6 UtI ( 16N:lDW{扣zN;=* .Sb5A044'']x&`6vX\zNyt8FU134Ms_Z\?FD$37b:\F=辋 Xr+Xakgbb}.0/6O j^,VIK3/OrX_L/;gG(_5=wtЪu҉2KVQCf&6fq_N!M_ ˵"/a \:sg.UU5qz @Ϗ۾=[TzCgd4ȸfC (`Q.vnYrgNp~6_/S9h^ɓD*Z7f„* >D={)Z"0X f1%yZOi,zӫr1QcGjlJV}QfpkQK^'%ڝ0Ϗ0p5lh!)lg=nRC1:B`xD7B5Ƣ^#,8kqur] $L>xp@ DFi|OaܟOr0lS>6\ ba\b/-"u{7k_H=հẗpڐ ټd/5BV n/pوoS-d]]_rez93y=NYrB9FwkrsuPi.0@v3g$ʕ[3KGR 3UO3*97>wgQWBWWmIMK9\Mvc,&6(|(3iƪ?ŬaN tcX o= ߛ AT"XxtM!@BNX4{LbAC:Gg}e=O'92̚{9>>LE,=81- 4Yw (sGzj^蘼y1AκeNZ*5XIYӘQxLB~bUz"&Ly}E|^!3GOu6<?f!ӟzFVzmnmV(M DHΏM :z&c5rI޿r KP 8Y/7QBɑ+Ad)DLOezV d2C5Rr= P0(Y.GhE_HAR$$$$$$$ҸQ"d)k[ev#(.U{{o qtd邋[]LK%AW6NH[MHv VwFg$f&k81Zmy'Pqwk7mj!}ξ71E׷5S.o30<^G{]{8jmZ3xv.J$T.EΡnlCcrjs6p ݝgmݖFFnw.`d/{'/S?4+gF^'##qs!dR#ɝ;w6m+W/ԠfҮFf/#t smLU]$I\̤N83ͨz)E͸/UэKAHy-]LW[G|vcrY4G5FG(fFCѴ-/\WXQ(H$;WΥYө-"ߢ ,x)͜eqk"zO%j/asOqA.Q3S-BoӠo(Ey]63xgZ%$aP?Swq8ր''`g$kl|-t ;b`>Gat|Esx:e/ )"ATƕ+W޺v:A{p,I ¡K$ 9Mꞅ  `ؗY[%E "as'Ał]Ln`Iit)[}ы]+ز• VO+fAXK}1kդDoūƂ`Ӊ yaЦŲճ'swbUw}},ĂӠzŜ[֟ze;¢ؚ+6H(S$i6|A[~Z.wo׊^AX܋uٛojyz.Q@l^ÊDM_K=}3~#fc?q`?~_lu)%#-“Nۓ(zveޮ`>P#_&<,Y䛹 xLϲEp9Y%YϮe #뻖EP;t _ͦ5˗u3 ! gǁ .lr0SsSJJ%*fFB; m;DDQDTŋߪlVwDLwqxEQ &25G3|#- e$ 6ehح?݈gg}AhlS8 b:tm 1!q:7|O-LnΎWŠ- r }|Tͭ|8LZ5+< `GY{"alcVN!4ȾYp;d6uaPK=G8J_ҿSaR#F, 6i#.@o ȏ IOHWA5fv4mp>#oDHGe75Djw0b 4a7_L{XIBQ 43.sp`K}LKڴ84!`#gn?/Y9;ŋ3|j7AEiPk8~ 1íN; IDATl m}G0ϠŅb3E/T*AAAH?HA.ք ٟ[pDv=;;}$v 3d8/]%r!tmmLoٮ5TRoi4{[ݧO*Y&dqeYՐwȥNl\Uy*#,W}m;Ll囖ŕ;d W0h8>0YR4lKQ -G"_V}OšHzfF}W;K5?1p?{3JTBlRug6A!OAdDO ӧ R4<>>66{־@nA~8)6n'3E4׾cLm"3a<֤Lf Vw.~'_U.CgA% XlFjK7D>_r,b$+mf1z3g+q=%+31s@^ U{%B) Tć7YGﶔX.S= VX({w}C% +` p6jI}E$_Ξ1̇ c"cX#T4R '\y5$>FZU7Mb6 55ŬJ'6iƅۋ6áo9aF: $L>xpHV0tS>6\ ba\bo5ڴKD9%Tܚ_H6YόmpJ8?€& GҼ&Eչe_cuӝp #Qoz8VAvk7 B:3zّݱa }K0_3, f\cu63gU@ݬ~W zVq0#:Zh: qqٖԴr|4$0SCj.0&Pv8 ^YwqiM$oyb8ªk jQ7uEE;t9E,; s.:f`=޵L)%|TV ww$У"D`Ml^h}+\[a!@bwbɊNzkbw,*K'%n?,w5=+a3&py+5{~FA 1ȮPF ضMY, =4e W}V}Cz.`X0]L8{^ I<=E~NfupnWS0 u61ҷ> 7{P ,M0難^+7YrkB8܇Na1+Xe6&o >7|I gO p|{0{%R"N>Τ^91`Ӎak äZ]~+]/}4fSPݠ(_E*=Vak&ۼG>ϐ֣':l3`FO=#\ g]{Qffm]Q@̺ɶY4Yp2]|#9?7ժ*蹛^gYkӖ((׻~ϊe rCyL+B0 MBdzjQjlH&3T-%Kː 3\ˊrOz?}V[t54/u}}9-"]%X-!!!!!!!Q5 bdL`P{2w3$$$$$$$a$͚D1F$$$$$$$$1&!!!!!!!Q5Ѧpx 0R֛%$$$$$$J6fF "Yw ;A@,׺7c!7C+20A^JLW\|F Q/jesC,A0a >vjF}͔ -M2D@L秱_c<dOƹi-Kڧ\VV8OOLD1{0G6se{ln{ s TUg~9Æi?xѮ0?.9%ʙuJ΅ȻRJ|Ν;L6`ʕ+d$d'?dL I hf[w!܈" ;kuNrWH23<<% 鷯j㌻dnaYdbq7~UdmfHsW_8t]O9)Ei̭/ʢ/T|C|:Nւ2h*w1w>gS߮z4|ԩmy7AC,B^p)$)ɡhږ-y}L fX,S9c)֞5, w+E(J_^]fԧT#EoӠo(Ey]6*Y㋧I,ז bT &!wOMS@UɺgTL2=̡ѧh:9hO{>$?%RT*qssʕ+o]V*N8kVĮ d1Z(QyF݃u-D|eǃ-B}5;@s=Tt_Hg;ݮz;Ɔ"su1{B5O 4@ z4sH;5g՞(f)r^YV1{Yv~_l i5!Ԉ : Ffn;dlg\DVIVedzkY(ˆ%bQ# e; eHq`BF{3UQSWG?flVT6177ܔhI=_CɈRl)5QQ*xzzCÆo [k j.Sf iԳhS81=ǃ$ Wl?FL¥}y29 )SQFҷicJ3b(j~㗸T4Nػ.'y:{F̦{?էVg5b rO αl0NKP/;hIz}$ 6 ft]@[}P? \<`DFG@V{}"Xqp@ۢ]p6A[[X`D^~ըT[>\fzSC+V LVVd 3Տ̱X !F-<6"bȭ 侢|R*mZQgJ`l 4v;9s 4`ڈfyn6@\ 6'hX,SujT*.rtc<&u,!K&ow8 X<p凭hoaPTEaW[%&92c{i[V;l %=; dVE|tuKy47Q$fq@Ol)>G?xf,SJ ض0K%:ۛc}nf @Lu+o2aI]6'#xY>m4A>uE".+KtZc ی܂qSmNogh}ǘچ6qftZ6agpNe w*F¿`y|whSIc=(ӞWɸGI5֝Gt=jl*\XSݛﬣw[JD@cl(%xoCOOWW׷,1l ع5!!t%=&RZaQ)@_/Pǭ| I#!9j8y2 cCe3LM-h8 R㠛d"("kȴ𛴰i͛3q+11vpc e%ro5<;x"&a4D!e =Gw_9JF&dHCqBS觯YjM٨YxCb`g?S6 [6ҫb(E=p6p0C=Q*yLDmI'f`,3 S2PJK45{Hc~ ^U`؄.TX@ah ua||`g#b3O7suyF"_J&VeŬDOhk$\u1))&Ut07< UyJd$8S yL ek;_8w/VEG#* Җ\PޖB'3az.f=X}V>%1L>6iLb’Mm%W. e9thABF>ЛZ oU2e &L5J~ (gD5хtC.93y,?JGBffdBZ52L d\3h^a/`Q.vnY5S;>l ^r<ٓ'9}1I\DTZʒ<'bcU9(h#5j6M+`a]ĚAˊYq7mft1ֲlҮY -qd6d3-Д)QZONFyEsb*MӢ ?^>;#!NwOjopNt#dN Of_0K73 h} >?Pt!,x aЍI{UJEKÒCБ}m\дLɸߝ]rAA8/ÇqCR6/'*L <<x0xg?OfG99pS#Q۱3EN;M:~{5|ђju2)Jp|LYt1[!D=#Qoz8VAvk7 B:3 BlKjZq~9u>k~V~>6Rt l1 2}8xG-@p\x0ɛ;SNPqzB}ȝcjN-g9KguC\X>4Mu8ٓ?H/ {X{ImGk+SJVIPe1`$ua|5q*K#J*/a85;'h5*KL6Mf˘Н- m]V"k2Xa<32  VM`Оc zԷK'8poFM3+/kߵ|2eqgcVl P}p3^6kհPBY쳈s}1j6^ok+琰ϟPTWym>mSq)Y:=0/mrJҥeBS*Iw&3;"iD_ s!3qvcV7lMOEyPCI<^ K5{:!T_RУJUDヷ78634<9Y^r3t3by6.;c:uĬlJ'ij**7c{S X!o{YEE}%Em{V,TOЗK(d\! Wh\O'S2=Pg+dF2m)XZDf(eeXV,xt4/uMBBBBBBIxX(d2˖eꭲ;FkrYbmF%?IyNjEr`P}L.L1+0>[^NȾ湿=شf\J"OMR9Ʀq9D^J-0&qKR@j>U'62[wHUj=N,^?0w}or.56 ۏb^,`,"Ir.͚NlH/ϫQq-}VM`Ƴhg  cM/ۏ?ߌAl`ԑ`<njMĜt61Ű+v'{!(wt#';QE ;bh49hỌ{$7%v T*qʕ.yzS'f~5Wob2I}W f1'Ep-w%<:ɒ!oוgC֮@ lKY rsF7{] n#8}oa5{fq*; B F?Gv?V>oQ=wmEjm IDAT s-/3q/ w;ƃ^7IފW?'O 7ʱ6-=ڼ;cy/xGmc~~G9,pq4TC_L]Es`瀬l[ 3Wu{xWQ2^!^XD2l}LSBоHΎwҕk`>P#_&<,Y䛹 xLϲEp9Y%YϮe #뻖EP3t:(l< p+!l14s{>iߞVX@MƘbjnJirPi[/Yb_ܓK{J&"JOOO.^VeeVZQs2۟-N^J\_ɜ5fJNta~^ykla+kxQ$^W݇-[ 儬նh ՠyȑΌZcL 6}:%ح3>Uҟm(-,LcK66a鲚+WW- r }|f 웛q >-kVvy@*JQEv.CƬ6<_w T*|ҢʵԮizƥ{L%.s LBI}3W/`h4-a^,g b%6 LmS1xEoG2y9Ƈxưȭ3Տna[$ !F-<F ܺ@+a^i.1-ϠM#,@XX99p6ioXE-bm$^y6,s.j:Zլ:vce|w/Sy9`C>J3w$ .Q\(_ERDpppm5Ic Y2}Kt[^a4,2oÄʓ)TɱsILʽYZTUvrkC6J} Zs&?`0O/.;Wi[%Pw` AldZ*))-!vf^6*T :S9p2?/Sr4AzY܌\5˘ܿԉC:Se:`eTu> oP0Ό&,>`'Z g9Z@$’ܤVA!곘NL&fr~f7 &6|Z6 sNK&Ԗ nÉ| X8PH7ꝡN% ctWQ)]bStK+"oZH,9kZn2"8e/ivt&W Tsd 06Pš|gR"bLe6X뻠Q6-K)p .)yx'vdxMHCj*Ѥq% cdQ5?vt;*|"JTÖ 5HYEfZp.=%'#?8`k*P/JaQ> äZ-n:_m7 Σw}>uq?JZΫhU8RW8:ځUFwHLW`{>: h٨U tI/qw1a# \P_q;,?~Nضo9-nXbi.Ոŏ2p>;^ˤkk΀QasbM:x!ɛ6Gcl )xo3s[|tl?FFwkb3Y$}JㆾU/Y 0 ^|y#ML0x,wI{ @2~;f*ӆtC D&sF12Ij Sw ビ[9k#,:J. b\ql%Uod/I*ɎXbcs?/K[JUDRE@CZb[hFJ8b*VV?8; 'bU< _0LU{ڮ8ƅؗK2r:2`*ϒUz(㿆i澇FSsn~hͅ:S7HҠ]FwjB-[ y&t"-=l-rINWn-$@vBYj-ä@5ʨVڞ ^;kH,šNp~6_/S9h^ɓD(`XC:LT&4m`B.ffQCV˲JXkӊYďW4bǎԨٔ6 #$Rb͠ccceŬ8cE3|kMui׬zyZ(VTq^q->ɚm~,l؏*}Oo5Gw/{7{J">ӗ<Ly_b4w{5{`|PU z?֬P$g1L޵OL5I|P3 ~ Ps'"apcp<f-'3o@u?2uX8cᆪ. +`CQTb7$Q5 vA+`FߘD;bAPX2J5?#9s){ޝ疙VEgf6}=[Ee)\ԧDխ,x;~ qƱjz5,ȭ'.)ؗF$;was`J[t5k?< [/+20qoowG`?8gT&O6Z|6a#p?5c8v9hh&V%ڮeT_R vdx7ݍutDl$nB\sҩO _ZKcMU~ +8`rN4țB%lͬob;O|1ە+ٙV =fyw}w,fw#X9/"`MPw5ӮlK:6db.+۩]f3g4_Ӏ Cc2aL/oK1vf싍`fva|3a0Ұ,bNMf0IS<=g sK$)tw">+; ^[ҶsEU*Jzb93GXj7$'gEf< 4qK^_gP_VE`ڭ -cˤbBaX׾ [z@=C=WBGGpsz4t}*lQ>]Yq ٍVo<9`h֏N^rN~vf&$d2tV5VSg>=JmF:`͊>+ˬAf4$c\‚[Yа0o՚ BEy]v!8!.R4RUIP ژBmaLX(jJ i*J5`ʣ(yUlUZaTP V9N/y1^DI:vZ&I$Iһi]d+U|U*`tרt}NI4aJ6# T)&`ҁE0Mz zJ$+FѠ TK)ݨ3I+ZwӅ8BP6Ee!%+M$I$ZII$I$`2X$I$Id&I$I`M$I$)$I$IR&7(, hSM7;'Cʹ5ټZy"I$J2X߿?.]g;Qt<1jQBO'm^9` W×-yNk#@ kPRhP!m?m'yC2\OK!yNҖ^&WIIW!>y`C,݃ƕ/F 3҆%3+Q.7rar4bm*\HVt.bX߉:NR{ 2B ;:]j /#]%+#i ZH\tӉrILO漩=Ӊ/Sy|={PQ DZ _ɑ)iZΈ3^<߭BRYS#FF]qFoFQ9zb-W`p5Yx1 |(i\:*_,ݛϔ,KuQ6/~TTu`ahBy|e= (:*g17;}Vo؊I"4aI˘ȺvLht'/P?)bĀs,dΔ)3'_f h2hpU;L3- ^LCtPէӮĬvA1,شtKQJ5~=l^{/W +h7j& u&q b0#>hJǕm gЩ*ȑ!DNr |?) mwL@૩Ɩ[i[7F/LՃ]'ZwKz3hߔS{⢺ù߯dݕe| =JM槑pSpZd5{|JJ {ٳ/{8gM~\%q}[0%ej^*?>;38 Mew b-_XM|!Q{*?$IJu1Z >פ1UQ&]l\vŵϦ|(Tx/I鹱WW6rVoGM19iqX6%@|OfN=P!›kC@,s/jZ*@tMvmϧe3ZUmN<0fyeJS5ƱƐQJzgv8J+ֲn:֭[2WL{2}usY6fCh5%bm@kh(ՂKO]x?!)c*aaa:u :ƯCYlhgg1~F߮o gU:ܱc4[d>7seA¤nFNڰ덄e$h+W?v0|0ui5,?۠R - &yΜ#}.71@iG(ј!ˏdv#Мm,u+ XaܵϞ6;O;]N)GT©zUHzt7~f/@jX bB@ GOEp}pZ ;GV{2' .Z?Z FQ"S'menz= ,`ٯ BZ]n^ .4( $'!ـ?cxG#ZχӶf:ӞwfɌpHDl Ty-;/fѷ|䶊ɿ>{FEXgm 2֋y$qe5Bد VP"dR': dPx?0f]2B0O)G h)?Gik([c2hE0}Jl=̉kۿ(?FӰ$Y-kzg #n"ѨO'<f?7&[?'X`5PIat-%kz68#cꇶ4+=1XX2s9Nhl8%a$2ǝZ.ۘi4|||^a #"IRܼA![gr) )[k7ʓ1f6챳s8s>HxşW -E%P#lyHΔOjR:ʆ…Ϳ޸P-O /hx$R2veX` k;M^yV/WMJMƇBWo0뛚1KU;;; bbHLDu_,A Y$U~H4( p{dϓvvor׸l[ILl 5FggSr7_](k(ݫsZU6av f?ͱ-l: Lc"ǣ+7Dv~|Hi…~+;']¦.,I/T;sn1~gSro<+>%ռ.s#XIÛR'gX?4_ fG" ωSώ?:zWcQ!$(!G63wr{?$WrP[Jg.mNc8P/Bh^8'.G*Jsr4DU=\>_ Ǘ#O9"TؼIO2z VTV0c8ȋ+JSsqfN9 c>xC'ISHU@S *8-XEԨsk?C̀ K"*FpˎǕ-ҒP\]]_y[U+W3;) +܏jvvѺc\bތXj;hB1=~bf`@˜p|leJz⿯ IDATu;]ů=wNޤj\[S͚E5w>nEED1}~Ia]|更+/Le=9ŶѴ{7 .m.F),6cϰow }//]~Ttyv)&(iw9wy?/ѨO'n l[Uup-ϒA)=. eXQsYM_PV̭* JٟgP˳8Ƌ~,sGxĀ9b;7Ͽ"P & b`QPӗڳU4]B8~m^׭M}JdvNOlf£cڕ0%fү ?S)VSw̯YqQ(lo<Y0J7JqyJʓ&gY9RQ Z}ѾF1,* [3o%\{͢OO]f3g4_ Vb)8w6§1r5K3k{`._: -Xפ_5tw"h=mS'{/:M ߯%N/}zJKYjWj4_|bVa(8w᣺(I{Z톻l#_#co3 h0x߁b??:ϙƀN3h6oMǚ@s|e@dz<Өϟ^2^MFY!|Vs{w$ZmثTnscg'pߏ1ȟn %0bHn-57BPح -cˤbBaX׾ q|PٻĈ :9_ }ѶYM^|M>C3=gkn(׋Ƭyи_F 54o5 nmF~pZe #up00!э&C16y2֔CS :PD6YgzEwc"2 T@QDql@[KX0`+ κgEz+^o<ݮm;T euTva֪[BmLW[[0i,FQi J4 Z0Qk*T*W[ R@Q6}LY݉t_e_9w%I$IȺ*WT*jMhkT}cI$0%Ige0"B&IoFAmWhPcn$gBJs(2 ʖ@IW2BI$I.6bїTBv%]W$I$*ٲ 5g$I$.?,s$I$Ir0I$I$`2X$I$Id&/3@K/I$I`\twv^!\wZgt!h㏿)i!.BNvg0rO3xp2p!,p)sۦЭVaTf߸q>@\.Ofom.ˇB j bP *٬c^~gfG9NEc\ WT)b|/{Fٽ&m%&LIXڜN!(ՂKOH1k۾:6B \3h!n=>+;U \[2n$RÇՍB-V|‘[ #({,Cmx ӻ5}' 'Ȩl*90PV~jxq^8?7SC #,l0_~73ЬN+?+S?Յ%א R:N/X} (gX0X}B'+69%gb͍ki1lx2e"BBaj% c;u!~bޏ3=SX}6}6M4ұ!_>;ّtFG1xWtpGzsI\)BJJ CcuY:k6-a{2Ri;)^yyD˩\@!UKe@[ =T>?c6_7ڀYdN.`]cx%IJ?EޣʈH.𪺍~嬳nj]ѣ74>i$KtdO[wacJK$ l4\X1/Lz߇ *''7/Mv?H!u,)4QN$ipk;aԨTlA~þxcܾ4nglݨjGJbR͟kϊvHOǤ/,W*5Vy(TwySwNZsGH j+燹gp[JsKóeVqbNbzӞi?Zp`s@?9qi&O9(M:ttN):@w6thyaCrB|j.ܩ@4'Ҁt~;Wuw`|xrds܏=þ)Ng}C>U")`ٛqgP˳8Ƌ~,m(vayle:bf w>ØiMߦ3?8( bnRAxC6>[)J/[ÞL3Jryŏl4ȵu7&L*yZ&| 4 kyk4/^,Vxtr [3۲XkE_Gp8xϽA+ٙ^ vgf/dyrC0dh7*oChKu%D^'l(AUi(y86fY mXЎwQH5<nj;W=fYeoН?PpGug5Pl wk:_YP@~d{l1mt7۽[T1k6Ɯjt&(_EsC^tMz6f̓2tdV|i(j&(<یf*Ggg`&O aBM,cl@Jkr3Ewc"2 T@QDql@[KX0`+ 6]z}tP%CqB\]RiZΓnj 1]m!l˜PF1(* ,,TZkJkGQP٪^m*JErV^0^DI:vZ_va{ [5Ere(z\S찓?"SH^$IުuTTWTˏ&a45*1tߤSMzUjɤ2t`n!Lzޤ7ޠ+ɊQmi4(F1`J7yt!9MQpx1-I/ ~Rs/qgp7FGI$Io $%ݨ긄^-3w>uȽOH$Io r 2MNS;|̐UmD$IMd$I$IR*I$Iްw!$I$IR.&"8C@.$j{|M +NgpI\ߟK..2K^$)2$=h\ !g!۔)U눖S27*(BP loS"Ӿ@AeDN,nl^GxboshS|¼~>LuךNu2ӏtӉrɗ-̔W35B4] p(+@85bdԅ媿EDݐLT2Xvܹsm'E7p sfO& oů[.fzӾGB=[LiV$_=Kk#Obxz~GIlu& IxWc{\SIվݛ'*ڇ[o8h +QprZ fv9t*›Оϒ{t%Wk#OAvWU\).]XF{"`SpDZd5{` %%޽{sWΎ!!>$R`N!(;,:X !DpH Sq|u=9_^ Df?O$bٙpmA[pie MaNq $-&pﷆ-3aXf@ @'r=m<#vwx\{t7~f/@jX bB@ GOq65{2' .Z?Z FQ"S'meL׳`Ԩċ>/~48~;aimk2P5̈ŒL<%c]>\X_"rpFLX#k #mo~ҍ@wkJ6~Gəo*.=b {>)9#UvkG+ I(ߚ rm&88IDAT@LTXjjҹ-|Sj|6|^Œ$);J v1}!4w%s0'l ~yO*:Rj, Zoզ`/)I9t\J]aÄAl,5# WPgvedt B9dK8Q9Ux|n!Y%V%ڮeT_R vdx7]R;H>wžputDl$ncњ4?:AVq8h7%dLp{i4\c[|jdy'#ߎf@(7׶s,Z1w.k_5(XxSxtr [3۲XkE_Gp8xA.+ٙ@MA1h2lE9ÐXa?!a-ok]X],RAu^4}*bm*C2w3~m,Qo)QB]>KsP=ߗ6[#zgѬ;VaS_c5u&fѬh6 UJ=z-ŇfpБ(irͫʑ:Y8SCF!ЅZdL]fL>H5;P!Q4 ʂCm9덬U۵m**N#,Zut P[j a+4֨4*AQi`fZTZ9}֡ Cvkz,f=]2I$IzEFPRŗ^_Ra/?1tרt}NI4aJ6# T)&`ҁE0Mz zJ$+FѠ TK)ݨ3I+ZwӅ8BP6Ee(+wʶW彨ފ;QIj$I$92X{% ~O)h5ru5ۗI$I$\9fi8䷝I$I7rɲeM$I$)$I$IR&5I$ILk$I$^9Ț $I$Ir2I$I$`2X$I$Id&I$I;0O$I$ y5I$IKk$I$I9 $I$Ir0I$I$`2X$I$Id&I$I`M$I$)$I$IR&5I$I,krI$IrI$I$b2X$I$Id&I$I`M$I$)$I$IR&5I$ILk$I$I9 $I$Ir0I$I$`2X$I$)z&J$I$IR&5I$Im'MY I$I'ʕ*$H$I$OnPI$ILkwQrU^UuZB HBc;c`c2^v98fgg2N03@bO `{<ƀlZ,ML# VkyoVk^9uNky:o~GDDDMa15kduDDD4[5hFDDD41515"""&ưFDDDֈXK^n V+#xЉ1oxv⾁+.C7+#GV`x{??y+lĎT#;w.O/j@u]6fB7h-1akAzz*:aU<?ށ /;'Y( Xf $iq'xQ{;}o?߼K/y7X-'.Zڏ_f^CJxXV8楀?, nndz|nl*`Qq)V\2zv߱ dz|w?hڤ۠_`5Ag;taA("q)WϢg R5041֎;~?a#l U Rm:i9ѬҐ6S}C-Zj*Uzv-G9"hNݎ8}[t>`I|e%m[ر kCEZ͛<5X/IkME=\-9tRe ]PaE=IMR#ҏgzϺr 6nH[L9/?O}ޘF.l]DDd NEל?Ǎϗ_ew+jӀ1/^v dr6tBl'-/z q6~j,8,\p[:s6촴ֲmPLfT#obc6AC}\uY o_:o {xTwcA o9y+0ן{~t|=p`?Xl'v|l{ e z PiK}Nu77mƫC +!a͇.6oߏR<]/2n>PnM;/p0T6uЕX{ nG5LҎs9q'q_gv*|?;EH=o<5emTj!ls;:|kql{`fQX|&}ݻqZ^h+ߋF"7οJ,*tKGŷ@{V39/?Hn%*:='{pD,XzP`6=m3a OoƢoʶO3k &&_~G8w֏}| 8B7.G,N)d_f7`_Ƨnc>o}m+q~?]EF`Nu|"ྦྷwҙkq'?u"u/6w:7~o-̚0*=]!q LѸ(TH]lc{1jdm=bga6o.pF | B&}]| BSz{ssg^=C!"9lsK.s(v^doP?_*:(l$RyQ$̛ytHKC9J(tE~x+o[d̤۬јVh66y[Rӛ|'"F6QXپDj9eÚB'_hVj{%"jf&j[o[wyάՉb+V}\~= o&"SI 6`4DDDjժB˺`kmVsӇ5fъ(WoflFLDDD3ŞWuPn>q' M@fAQ۠c5#۠SYFDDD-xڠm 4ydt6䌦oJDDDs 5ѩg斉> 6h̆$ͼ>mp:"""yi} cLZY3֢*(yͤ_ xD©TT!5l{Եc$""iiT35CT!6'*A~$@m(j&ܴڵ6kOYkJN$KITL0dfDj!Yoj T+Ƙ5"""`BU "!*FQ5@4֠m2UIKjUh}A 2Jn k y@vHqƔKk Z`Y H1dA%y T5\"""H=vZHT`5ģ,$deB!H9Y ꗬb;U ty2k_"u0}0klrGlib;k]5㒬X*sjV1jaivKHD6`Tr֨qΫjБTT$T PJ@+e W Gq;C* u@ 9`@ȢR> ƹH\3Y06I`@.b6]B*ITls!# UVT_¡v؁ԀzTրk[a֪k]0C`ʻ{M**leolfmc1. .o\jA-u/iB ą !T2jѠV{ڗJa*-vU ]U5^a xv[Ę76cDƸP!3&C MZTڵ˭W ₪dVM+ j hL=^aa x6m~ޚRp6bDL,ƆȘ\Ƅ we5"""(y˩V=y̪DZ8VH 2X[6-露G ֌r* "rbM[ mRFT,KhdLSH*L\݆KDDDs,S(uVj DBQZNPԳ6p#pXmW)wfq33CjU4g/YӞcL[rhcpM_ױ0UJU6hQhRUWx)T ΥV0]P(*G' P*'%Ivr@.䧬gBDDDDDDTGE7i'IJB\b VJB*p DIR7?e@maxBDDDDDD7Oh~}irJ|I&L9AE%!J*J$>l&@(G2T!""""""J#k ] U*eSfr‰2!JUU(%JU.< CX<(DDDDDDDzJo@rJ^X*N9Baʑ )tHNN=( ʑ$*dBDDDDDDTH˧ Kk)hP*,ZZMB YueʑJ9 (H="PѶG(BJ#iE0B`ȐʀBZr,Q]%M.eh%]h >A SRni|yaettQrC_#(el Qæt* Q ) 32)$\a,iZHKiBڶZBXY"""""""i -Mmʔr--]REzh ˯ >Sa @~=(tðVʡWyFlJOtv60L#)4,ʖfpö Caa1 Kahù6.2vMi) 5Zv "]QN8RZiqG*?C R-$^Yl)P)^/8ʱ)=vMCZVX+eiaiB.+R C{V: 0\ri mx\!GHV֪H!P*ECJ9|.Ɏ@T{l99Rj)TF:(UЮc*-LGJ*%^c8R^XHcg"0u2RڧF@=&""""""cFhA aT WCJ8WEP+ c8*J!\Jj RJUӥ>\)HIOڳ>JPB!ܐJCIRJ20J!--,(r,ᗖRF c`Ǜg7n8,ppt!Ӳ -K(T9r6aBl(7lii2!îJ:!{ZLD:)k)j NBY",mC=W!F0D! "dۈkzDVvjTI>7͞=}xՠ>""ڿ#9NdŜpE1J H9P;wܹsj* ?wW^#$a%Tq]ѳg/h *5M]vŲ!I" 8DDDTΦMpkرC˖-m}lXl9 P~}t FBdd聦͚tcsNx<4o ]v8t=܋N; _ޯmΘ1[nC=XIb"?jƉx'%ѳ'x!8HAfہJDZò:3vAS ADDnF|B|8KguǷo{ߠ! B0P}ö ELl} 6&p]^<`7@B|BvC ! 멉O?,$6[~S\-`y<8,+?<~;>\!,_ y9x}>##]d$|%&&λBZ΃:H""9*'Aaƌx'8HAvVf&7hp~d84l64Py|rLz:3vAʔ,)}%$$K.i2+$g: ;Url 2ѭGOp}Ibb9EGsY"":~{;0n&tR/\YEucݺŹ眃7BXz5ڶi 'Fǎ@^'"#= ^}7#axjgQK.fΚEEEh׮-F|3Zn]i_X={b(Cߏ.ٙx?cٲeXl^<9Y6n)%t[FB |7M}٘cx\-[0WaFD˖~>ſ={kqƸa0tIU[;U[hG{EEzucm+k;338BCjzw}[<mߎn[oŬY0ytvΌkmRQrsswӱr/}@4etn$T|x<uо}rJGD"?/""=¶PC|>""*ŸGQ1ŗ|> k(#"՗C!D(DajH|z*Zow_}Yf#)i^|e$4n翏qǫӦ"B4iIDƍ2EϤIyM1|8kWC+k E=md^~W &,(ħFQQ?! ?&N{/M h.ߨ!̝k]$l߾}6@^nN;LMI i! z- ՙUfqء ދxsn&;CDDGÆ~mY>`>qi}0p(Cbyxg* RxjD<X`:uݻᬳϮ7PTRSSq=qЬY3࣏?{GH8:|e紽e,_7< -Z@.q)GۡG\\ 2tyz"5kV1mɧ& /g,¶mdQج VdTddf/c„GqхbQU^gXbrrrJFtttǕ5dP޽;zA\\\MIIA8F-PP&"ck_>W@nvV2Nض aƬٸk0ƑW/Ν\m޹=_z 'x֯]bo>9䶁i, o.<7 ΌkgM%'omy s/ Q f&|~RR**ڰv@mUHMIelj5R^ > B~0ߴܫtr}&i ÇǂO>EÆO<敩xpw!'; J-l~C(cf(;s>?&>,>3deeWyu1罹HZ׭/~@? z*~y1F[lֱULX(P&"cgcǶM>qbemdg"u6=scY@VCnƠGؼq=l;m[7Mָ{? >A.1ݹxgƌ:5v3A_8Pyk[Xzs0 a.**,k4 X1b!k#(Y#?:t}ڤ?K_VSRӰ}&Cb_h~70y23vnoժ 9ʝ{mҟ*_elFnvRvnS\?5Ȳ~z\}ՐZaBk]Y<}HOG \{5{?:`%:iӦ, +W<ඉ813+'VvvV&vnی~,dJ?,mo\׭.-cF1`$ {ZSc:\5x~wIr ) ca돀mU|,];>/barnrdddIqFܹfϙS{֭ƍ1kl/83Mxx'ae  t|HMMŚko`핞Yxmtغu+.]^xm۵+V+W@VVV(Z_}P(mҸ16l؀d8ie˗a5lGزu C7 7ԩ/ -- ˖-߶8Y^AvVf~+`c`0xmrXm[6öm$؎P Sc[KSA|-#)iX;;8C6 WҀ~CAA!t\DDDG9'!ZltHt,\;w4k ONN9y'ˮ_mn+}QKq뭷"663fDFFpb^hذa?㬳0K/!778SqDG~#n(̘z!j֭ESj‚"""`fvDDDDDDTq"FU@R ʽ>f-1fwR]Bx,  &IDDDDDDuˑ'횯.KDDDDDDDt1H!"""""""&)DDDDDDDD jZ,"""""""bBDDDDDDDTM RA Q51H!"""""""&)DDDDDDDD U"""""""jbBDDDDDDD5>/)DDDDDDDD U2H }/ǥ}LwG\EⲾp;>&Bk0帴XVpx9Y1{H\ַ.O|BDDDDDTǺu0n{f٩8Oot$gk CnVEs\7޹SƜNDDf.xD\ʋ `'Da#w WD=qnHЯm|x@F O \y#i7Bfr.4"pjF+Z{D cmq[ Q"""""ڠN)QpCծ:n{w&轎t+̙>_ 7=ιz(] ={d o`$dA׸z_vks[sĭ3Wxf޿S?y׭AOU_?`pE|8-74Gqp ^{g q%eв _⁛j ypӳ0dqja*&_@;5 _szD$,7-\T%JkzFao͹b}nO\Vٛ'j'8Ϲ]+95D$ڞ ''!T.~yz<s$x 6ފ[~ O0f.xtDlw~Yss;?O.A`лVT݇Lx/ĉX# .!['aEkƢmЍKZ!* "mWh.xֶh}Umjt;'YvXǻ<5<]AE {}*2 "uvSȜmX"7׋ijl YM#>sxR5ϸ=0x|y:=K~6 пC#DT2gIw`]-ؒv5 ZpsHFf:>JS^ŹGzSQ~^y}l;Nu~tfoX?v31zk|F `?-¦~[ A@L\$h'Q*N2{xЎ/1qF=pW܅ x:\ڋPtU|\oĖMRP0-[5F/EG%#L\~JU> S |KWby!Nr~)N?jnpCq5sb 7֜H]p z6hCϒ;~7v(Yٺ5㉻7cgqJߵiAFMzk= "HzK'OcL#YǽT">q'.j"5HG GeHKAA^O|Mqѽ0O|NǛs *WwQ߃8oy (huG{wGBlI{ _0}v<>E?!aDq@oGy {5JCS#7#'ǢwBHݑBޟoɹAwx{^zm+v)Uy>ߠ!$nwD Ϟ2μ1i;bcxehG~B m@>@] #L2aN&V=D?  #ڷ\WE: ΔyOb{AE0d<ү5LSj){hX7C|q&ZYڶjUa) mjnm!RmǖL(7=Vj{w6S&-'u@~VwɶRYXd,M!ҷ #o[syqZI!%t8~ҋX@ ޝC 8Ty%6 b Ls7O؉ˏB]p8h.U]/;BЈB:Oh{1'|q/@o_XCG_:׃D~5ܜ5yK~4Vꝃ5o46<.wSAn`AoR}Nߧ|8~\2賯"""""":ZER{ڋ}OOH$v3/h R$"험ElhD;n$SfW02AK7lt>dt9xQǬ>/mNNbwEö Mr4|h{ ~h|&\VC^p<ο:7/}2 ?,(t8gn~|x ﹈hk|ヌ])߭?NIH |,|Sd)  |=Wk!OGs0>hg0=c$PeMY?XqBW%:x˂8ip'$>3?;o} >3 b&bXטJ~h:qk]zU ;CtH\/,1|60Lõ SD tC KZr2/BJ7,%!OY6d)]W%uE.nƴ"""""":DiIfmgpUEk,Թ * 2PT `ڦPaVaGauv hqGnu _{6:~e~.DuW -U+Rv=&ܩ C""""""*)DGA3>ֽ """""hϓ%"""""""U"""""""jA %"""""")DDDDDDDD5"""""""jbBDDDDDDDTMmv 33XwjР>Ѽyc""""""N)۶oKτvBZk,y1mߎ͛.QmW u2H)((ŗ{SwIO9 ?i( PPPp{'WC]_e:dffW(uR)!%23:CJQ\BGPJc˦ؼe ^UR$a R'VT %U6Rqcڟ 4ѪM[Jt{?u~\ӚիuWVn54G9v00MǁiPW5)JDDDDD LGm"Qsꩋ.] Q-Qg+RN98#"""""h >(=&"""""N9* _= >|O R݊nNϽ' "=!g{alu-Ο K{-0؛ #gc}UO1#|{RTy!""""ګ)S{*/2A }3Fڇi' uQo pх,]P Lft <=^| J%wѵ폐o,w/x8{ ?pVSB]OŰ[Q.#Sq\_]"""" RFǖ׷;(Z{ N?ϓ(X2}a5߽ #^ v:|:ztӯyo'[0O]a⣇Ģj:8t"jrf;' qxPP"""""":b:d_U8]zu?O[<tEtPّ"o.b}BAsW~<) Isqczlb{pڗϡcTFǹe>~ ^6NoF~eyX?O @#_{?M᯷np7wƓKI^$Cw RJ>29ѯo[?oۋPz s Lck帾R:NZh1{\,#f}ŭ5\/f.Oj }A,rs/SFן" OOw\-<{ĤqS %翃~~9=Y:?ay坸op'DhSJRBJWN'ۊ<ֿz3^ ON*>s,6up];5๧cP];31$d{ yhR<5kBޚ#!bx4~HhǸ~O#5ں'Ad,qcj+w@EX| 4wޅ?W =2%S(<=hb˗/?gDbxiZ:.<O6B۹HMsqޅ_֢C[4[>~kiĄ8(\O΁O`m`ܬxyĩ< ϕxv 4a#_ bVSs,ky0_ ΏǤmPIBDDDDD5D Rt ]/\&wAGa2oKk@qwmO⧌6h08\/҂h9fi[Z%"S66mcLzhăVA<" ]$e OӪtؖ @vsV%u,>5CnW>DԫXoIL''0Rg܆kQgⳉI=nظxb\}#g];:sj=7-- #=xꩇVnȾdW:Q7\>F}'/3;18ģk3Nܬ?wq맡E Ͼ{?Š ;R }1Hl~ 9I0jA^~t!xf?PJ@BYH)xFlP\#|/1+' ۆtDJ& dN2dQJ@t#%7c{B!O\WJZ5/ĕa f}tlM;AfQu `H+bcS&HɏBiKFŹ#Ĺ#G(s <<Z1{DSh!3UHzC\x0(O4UpVT_PY?c p#r~3M vXhtxqp x~\[ͤ9dↂ ĵwO^=* bBLDꊉ*ʄYi ]L MH ,kށwK/!< [hq:|4?[ZexkAQ ;܂=ٻ(MzQDDQ ;Q PPg,8 S`9TPP)v"f@nxf;3I6{<+AٲL}.ǿiWʩwRɌWCPqey|)/(*hGi\sxA\E 8fMsWJ}ofQ  gue՜Mɯ06)ߌF`QIuO$I.'nA(M!޺=[4#^#+NIaYhpOögqyW[dطOSrv)/y웪,7UˆD!^==:٧Z˧^z˦[6ᠿY*7R1ȥQ2*K4}4F͚y~̖.)`ac-h'2voPqbEKGe#گoѬ<գ^P{ٽieXN6e%ŋY$9p㝔H.?';GenMɎDӴ {Ңwl l \|.ր?#V_/'?wE RbO-i lLlLmFJ$I${מof-g1\{sgv^h1k؜D&iyϻvskxQ۝nχDλrMsvu$rhFٍnӥ= ȊV X`pSFv]7N^[1vקsx[޹i>i) .ew_2enϛK^{K)éx~ү,C"^_%&4ʛ͏KB)ƻpߪ| IDATpߨAܒ &ٷsXR ˣ^fEVsfQ ۵e]ʘK4sExAmz2,B|gmw>̃MaAI,/bYyM)?VN/Ŕ!ODҫUWy,,KPx|C+H$IHY!*Qz\7fG#W<߄}[폾}G =Gp^*]ܖyP<#dїpZ >n/=J|;>jExXa?Y[ãc+n'vgᩊ;]eb!iF]{M]B`sv~be3MDk݇чqR9]lJ/3Y݈;uW+b5[pȀݸ#Ugu=R5Y7F1TDl +g~2<:X(Z$%1$I$6 ӫ#$ #p7 WϞk\رX'ձ:^1$I663}xV&I$IէV)X~D"$-[o~.A$IԞHw ] RjۏD*$I$Iѣ]Q+m?զI;%I$IO4Z{G]$I$IRMA$I$IR E$I$)SH$I$d"I$IA$I$IRH5 HqYI$IjD͸A$I$IRfJwc]$I$I5zc?!%H$I{tv$I$I E$I$)$I$Ij{ R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I"51 8':r]P(3&@B~Z߾UMWN#/N.(ټLZ\wKݚ$InHm0s\zlH<W\áHYm$1~>?hhx K^t4g@W [aKNNjJZ7EU38,Ο'5V_76ףmpHg'8Vr6{B7*0coW2O.o8%O,o&mG 殶@^9}r܋aXUNL,\/x39묳*:?YHzU|ї//t=/@K[0NLi7~͗e z7=in4 o̲IwrGsR%\ ?;}ZU^7L%oo$IF)H|!vf88&1\ȅ3GnCv|[|2|kp?6~' ]EoÍWc6א XPIQ@{Y=hlK(۔ T `p-d;Vy=k~WǮnAClod2D >^ 7\lp W^7?o?7]tH7Zz^| T 7)6_I8c?8{}M!;E[WS 0z@|Կ`I7}N |?{X]H.__߈Fuʉ"H.=-H>{/t#vW0^~8Qr`=~=8.޴<ԝ\\1Ql{b0'k| 2#o}Kܭ9-{?$Ie~]k9@+8uEPZ3፵³D`PbIJ;4bL{9 omV.~%~+\r|tnװ.I|%=QT App0pFqL0g<uaqT HXq>$PY0V||BmcY9dM  -AM>GTVU2dl@ؾ xG&ر 9.dW0A8z8Dw8Y : z `mLp乳[?'9{,^sΰB僑:>7?Rb4u a-̱t8? _0pKxbܻ?D^[}aX46 . :Ia=;ca0a}/Nm~~^g zI~ K?&L_L0DeE/'sT t\N>?կJ$ۭ]hlM0<2Ct!\ְQ*Xo]RߒiEO~TӤ/A`C0Т,{3~7!Mlv$a-<1n(xօ.`]WVGᆑ)O~zpI"pɭK)Lz>^}{S<~̨,¾{KIRIɞ:˾D~y _V5q5I_E>kcF-Zuۆd!~D"uKs׶H>|Yӏ>cah2hb "yΥo8'Kܭx9~'7O{' n[}1y9ޞДu$I2HEZC&л% ?h=H,~&U)0?ͅa3Qw<Nh.?uvSQu\%"Ƿ aYAYr@`8К\'T+V ~Nn6q> 4 G0 "o$|ӃԳE0<&AE+w)eAcF7K|( tŐ(4l ];Μ'qG*h\F+OgСpOL/bʓ@Ka9@iPCBxmyX&JaNaYh#N3^\:5itb2RհjX:ÃjƈiG>6~]sis8X߳_?-iSW8GsT Kx`E|r‘y)b-F;e:9]y.f@yr6AT|~Ar:p+-'$u 0\R5',-7|) n +C4i{.~ :gõ!lK?pȬyp0 (XN9=A.>,:v_ި M{A 盃9`XL0N@`ۣd1\f=_A֩Kۃ-`3Х|Fo>C[&Guv Gu9k즜M:X6m.^NqbS0嫸uhr O$RFs;hOZf-Apkn} {n eɏQoiS_^zlF>۳f&72E9?:Q$IR1HM"e?)s/<8*^7.Vss0AR*qY*looSzw;C/‰@#e>p 8t5m) @˷!nd`v 8gW|]t&17_G I}֭Oo"z$:-|JtYHN,/V$+eKbYH,8;+ˎfGl()ΊՍFʈ׉e'ED" b9ƱHq"mzG~4Tλ#ǫ^畗r'a 捇úۍXφ Åd4q~}v:{g¶u+Ɍʜ%Ic<zV.mێbhT?}U?{5-I$ITՀ Ek+Hӵޫ-[h~*$I$vpI$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB %$I$IR!@)$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$eD A$I$IRH)$I$I!H$I$d"I$IA$I$IRH)$I$I!H$I$d"I$IA$I$IRH$]$I$IR I$I a"I$IA$I$IRH)$I$I!Հ f%I$IԄ)$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$eD A$I$IRH)$I$I!H$I$d"I$IR)5`I$I E$I$)SH$I$d"I$IA$I IDAT$IRH)$I$I!H$I 5H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB %t I$IDMR$I$I2A$I$IRH)$I$I!H$I$T$I$I)$I$I E$I$)$I$I R$I$IB2H$I$I E$I$ep^I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I R$I$IB %$I$IR!@)$I$I E$I$)$I$I R$I$IB2H$I$I"g5H$I$I %-M˨F3~vY$I$I!eR|M/%hϞu".J$I$U)iP>g;5?zIK2 $I$I2HIf6ȠΥǒ'y]$I$IAJ5K, |z].yD]^}]8U$I$I Z%X3<1lMnK%.N$I$U :OKmDoߛOfSXT)$I$e4j_y;?};u7H$IiZEiBnݝ];nIÜėaex$I$IU1Hu: Ng@i6f{I$I RE%Aɼ+*Dvwvkﭔ$I$IP)*Nwq 2~'/HI$IF&0HN%|xzthB؊*ٴh[E$I fR(h;`H$IbK.OϛҲ2V|kB'&I$I6^HVM5 .˘Uvl,#jI$I$m)$I$I!ZߙkXlI$I RY$%$I$Hvf-._7xM$I$iՌ %I{9h8禇y郯abJwIS4>v&/.KsŒ$I$29[ap7éZ+ثE$IL{55xާɄw$f/O@t֍={v]\BE$IdRm>;O]$I$IZ5cZ*QV_N۟ſ)$I$eRj&Zc>^Hv=suY<}uJ$IJ#:ErhЪ%=Cfq_~ѹYed&-90ߌK$ILcRr8txIs$I$rHVS^q2J!uX$I$I))Og@9hϽf䦻FI$I`̙4l$eT Zhb<</0'x$99T$I$IcJE"5۔f6Iw)$I$e H$I$I E$I$)$I$I R$I$IB2H$I$I ɻ֚8q2Ç ++] HIdtޛX,6EEKyH$IjR7n¹RX$I$pI$I R$I$IB2H$I$I 9RT|\v͔,O.b$I$I8'Oe뭷[)ۍ=*$I$m, RT#E"єw x I$Ie 2;8~}RMI$Iv R,O<'eY'H$I2V R.@A$uM&778$I%I$IB=R$I$IREgϥvmi5Tq1H$I$) :x<]II gqӮT E$IdΜ_ilz蓲ŏ?2HYϜ#E$I$)$I$I R$I$IB2H$I$I E$I$)$]$I$IRM R$I$I E$I$)$I$I R$I$IB2H$I$I )+H0mm~u>I$I) 3g>:v jm*I$IV2HQ(.^N~~=0H$I$I E$I$)$I$I R$I$IB2H$I$I E$I$)$I$I] K(*ZMVV99T$I$)hhQ!CK4&kP^~5U&I$I4)sAGҺuFe)$IsI$I R$I$IB2H$I$I E$I$)RDK$I$IZ E$I$)SH$I$d"I$IA$I$IRH)$I$I!H$I$d"I$IA$I$IRH)$I$I!eIkVRRʨQϲdҔ튋KF!;;'e)--M.0`1VSe$I6H2'|I$ W_McƌyUoyo}bRC=IQѲj8+{|*k6'^~jM$IRg)бcm+6ݤvc}b1j;Zh֨Q*_…I$I{H$I$d"I$IA$I$IRH)$I$I!H$I$d"I$IA$I$IRHY.@M8^zSLM.,Yiz;]w=]NNzgX:+ٳlӡC*hy}Fz&e&Mp啃d) /ƍ{n6\}m,YWʏ?]"?X~7?8/KlƸ!oU5Uƍa#lW^}/.]۶m ]ejyo{ҴiSr-Z4$IZM"T EZ۩qE)M5{΂>Ҿ}x`zgXg%˭꿉Uno>l7vS̘SAʗ_NhРqvwyM.pq0qd MNV[н)}L4 ?nzұc r9cl-h7)5ĉӟgvI嗟d֬_ R$IJ ERjEPDxEbU7]"{Lh~{Xz=vU82H5U&>u%IX?MI$I R$I$IB2H$I$I E$I$eDߴ E$I$),I$I R$I$IB2H$I$I E$I$)$I$ٻ(ōߙ-ɦ@ lH񊠠 ( kZWV@DDT䢂 E@IH#mwg~$lbBy}Ȟ9my3"""R"""""""" )""""""""A](V}`c&h537ei8iD?.e|;if+M3؈ra3nJRR,+}r eK-xѧ\v7###:o( }BIk=yKNIDD$!!a%>ޮ]ۉrXnǎ-$&a擒 XYYPb='r{"$$%''MppHvڎi?ٓJÆMJ,Cff: %؋#&^RRvv)\rN# -AllR_F/(%/Kll|Ubd%kzz&118m߾~roPb$""ra`%Ϧi]r9z}sX&//6*LDzvx+\.7^ocp:|i`Y%99\{_w]Y/׿vNN.Ngpq]% up6qKL8&~ ߉}=@(8 ĶK?@sU3[WΉwbZwΉ~+^m"'rۇFEno֛o3MsgϦ=zDrFom#_`YyvN Yy,pZ^A^;;~s>'6$aǯÞ3o(荒{Rg OQ_11-";1/z:%Lbbl'!'88/ȘfmP<<)ii饖kٲAA%w=`7/9xE&?4. J <5RJgOZ5OhhhBBUbAK e tG@'Ҟ(9X. ͕mB0""""""uQYnR(HubiԷ\N ضx=E2ixjNi EDDDDD &ՎZM璔,\}eN1 Gʂx঱λKUّ^ݰٷa.]{>4ԢoN:L Oדk2_ٯ] RjЖ n2{_av4 K4,?qSәB > Y񩶈HPgι5k/i;sS\ЗZ>}RMZ[&#QUGV)H$E>3^i#,eg1fhWbJg^񨳈H]H$E#a`4Qil/*9`ܕ$}S\1fvK~i]kqg0SQ{םm"0CT!5G|4LDDDDDrw۾wHm}07ym1V}$F7E0+M $f]/͗O$iE ӧHDDDDD)K;u˥,6:]?v>3yG2,hDJe&~7 gU]%9B)}7p7 e?_?xFlr~ɤ6̟ąɻ&麀ƫ_ f(Uյws7ayø85ciwm;VƏr*"""""RgfzS޿2 SC6W/WVd,h)H )H jr RDDDDDDDD EDDD*/0p& %]ɬ cHM ̻كs ?5c&x<o{ymggΗ3W`EDH_z玢۠׷]$FAAgGOb:aymE~3W cؘD:*b"""%) i &_w><< ˶0-&wb^ׇD&nb/1طy:v(:v=k΢{Y|?sr R||rZG҇3Xnd');sM {1%_bMrii)\=s6M`䔟Џz""R. :aÆ1lإtzgi_q}X-Wy+[3xXOS. %cf=V&6F?3B=N mʶ?pC<zw쬕6.|ƓH}dYǨTO'2L>_q2bGSq`[<-ϴ϶P|o w>e{ AS{rLQ#f`|Gڪ9<|U/Ck߲bqMFWv$'"RkavwkCH"b[{8nu{.lVbs<]ІH O!Lz^ϾNAޭxxGInBᬑsY: ,9nՇuihPJA/kOf^XGTK6Y/;Kfvc~q8Ycz/獯wH36}=øv {I6O>ϓ5i##x`W?:?0&4M۹ofoR~=6]=~D@}];c22kS +t9C O2&w'Wdpt EkfS_?N7`;u'0e@Pyq<7/zc^ANEsEJz&'6ˍS ) "s㷬jr2m<1v5:S]'#'u$szҊI;|{~ӥfdMYg+"8z~0)U>‰pn"<~e{.'wkD't`1~{]Ci^'ڿg9]7C#o9,^a ڷ͛ fq)HaV{s;w.sgF]xX2mw.`877&DQxkYMJ.{mbG8ᲫrՈ ZЀo?E4>zM} b\|;SZe{nlaxt7370L;[^XI CwYu%Kf^J/2[KFLcM&w+ujl3Bh8wB!#EZ!vk]ҵkW|5Ie]9kWvhHV짙#FJ.Ka %CZVYB]jue 6=~>9!sq$>b_Ż1jnsB(̭l9G$O=pAy}#7fŀ <6zT{dÌ H8ǷRضW9%zߖd }&FHsοg) kqs0e): VCSØ)r.OM&{wum߹,ZE/xwm L.)*26pHC [3VNbuX!lw]ɭ<. a>6E#Llr *ؑfHV%+wƝ9⽥[䊖`8CGAdd$n 2d.՛F/`˸R-Phk爵,: wkSY~ޕA oYX}UO_AwGe©?S?^ll|9)r5 lk~mY6#h%DHJЙVqxG<1 L~߁8^Gbbb &~֔'?z>,H}d!:吹v挸l~ӊhO[.#>qW&D{8&_D v~_>3^MxZ\4t("R9I8߽u?|styd=b~sRDrZdW˂_;1p3|@&vI4iKr/}2wqSxwwСώn_زf&=KRDDj߿x/~-I#..syջM̻i[8ՈMQl,'޸Ӧ3]1fDv~~^H#<3-'4Ie=hCLL Z\ͻ!4JQ^lvLn&ckfnp;!Np8ӈ0Ni;\tl>w 5`Vefp1ÎfZ8=- _}aÇcY_5{O=nFFFuu\=5gdB2-""""""YTTT@f_j9t0wlz#:'&;cm 4+ΰ^#ۉcYyA>+NZ^3^#kg~>g!^Vֆ$usfr@(D |߭ǵZ+D:KAX'KFDDDDDDҌ)))#}rUWDDDDDDD)H)@猉H=""""""""R"""""""" )""""""""R"""""""" )""""""""R"""""""" )""""""""R"""""""" )"""""""RMU]R)H 97ߨ*H P烔~*H =""""""""R"""""""" )""""""""R"""""""" )""""""""WX3|U]u&0 k"""""""5](]RU]oƯ| HAʶ}piXV +EU] JS烔3|XUը5 GRR8˶5"2 Mڭ)pX (Hڮ)϶m)"""""""R*)mX-Hysg0ԀmcYU/}-o6-0+|$L+>%O( M 8<LGDDDDDD=dd~Yڷ<5ro|Ƿ?LJx#tqҩibMDDDDDD6#RCܲRFmo,y!*в9ֿ8ƟCQM{p#Sr449= ǹkYz7I; qMCsﻋO2vCy=8Oard,]~ @>I_s˒߲ ?q oK{$ss%>wvnE?nq}Ht/_{\ ǸG83rXvk|.F^D[▶6]dgvsq c盙н {XؕV^Ӛ VLW^`=9.l9^I2Յ6}kgs57?Mƶ oC;˻Gėd}p:/-zaެ$e>zkDr R6 d әi.F?wk >R0v'At\F"<>ܿ ƌ=rq /kE~vaeq.Q8wkLXN숉3"uOO n v1Sy[2- o@iQE{4H-Yڳ?J^o՜ 氏*Wֲ^}HKw}<2v%Ӷ,z!Izocq>6`-,_.i(@'Q'$R;\_>\roAIU|?M~?""""""" Gm`0|kuv/fʥg2Gy359vs%pY{v{Xv*>ܤw-wR2iO22=>Vnk{:eo݅qpV(Fqyr Ų׸b|hu? ڈT!)e3v4_y7>iw'y edLH©A 1o5i~ы ]BL.66B}5x!/o ػv>/ fömoQ8ٺ<0"pFab"""""""RiRBPO{2IQocC^ֈ `;3yl]l̲q79Þd'ఱ ' [}ƳrW$7hIec9r 脳7_? -<6nu%o&/=0'!y_.{h*[vVQSbx(ZwX`yP"""""""Wz R88%& H@ᔗ_iKqCG6 "iyuLtQu}'l Ӑ-z`Mc|bn}+g_ .z"+oG!P R8luli;U]c B"""""""5 dh~zTn^>ƥ F )?)^ƲPE˾ e[ZVRl],""""""/ZBϡvu>Hi߇_u^s&G0WUWEDDDDDD i .H0MZ.loY,YA|2X`ӾM,0D9Iګ)h:"""""""R]T EDDDDDDDP"""""""" )""""""""R"""""""" )""""""""R"""""""" )""""""""R"""""""" )""""""""rVuDDDYZ%yJ_?ڵoWU#쪮@k] .(_-[ƺki׾}UWEDDD)"""u޽{9 l۪(gTu5DDDP"""RG$ލeUՑB~ RDDDVRaTuDDDQ"""Rؖ ?5 H W1""RY Hmp)Hc.2Բ˖.""RciDJ9hDR Yj3Ro={$%5ܪHضU7_+;eNoٶfѸL\uF\-Χmd;3>]+vOމHb|F)LJh۾=ʮQ֬Y }˵uu==pD?WӨogA{ Rtԉ"""˲+GizY˾8$0H-pU E c6ve^&K}YU]#fHmVκ?HSW|!1|~2i|~bb*"""RM(H#bccYz5:v0:5eYYT RDDDꈎ:f*~q)U]!6.8wPUjBAHұs窮Hq""""""""R"""""""" )""""""""R"""""""" )""""""""A])RBAHY{I޵R!'C*""""""m74 RjRtЫYU]c;\sݸ2me_mVRDDDDDDꞅ;bDs?^ˉUw95`_|ˀ5+HR!C첽QՋ~PIq'E2 <5woᎀ˧X,WMJu>H)yl*6vUBMDDDDDD3|xP/(儤|zQB>#R èjg IDATm2W?/Pm,qV RjL>z)""""""R_} zTՀE#,>أy}WA:}}=э3Y62p>ۿI}?Qw/˛T5.N>! pHLoͼ3>;)^Xr2~Sa}:ꊍWsW |Ix}"o{'Vetc̨6RDDDDj4 `Up[ˬC\t:3xCF<2ؐUg)FrUđtiF>^"r\-{Xl<~N.n֬H$.'zW(R-Wm[jCVmJ-P R2LLCsFqg?nҠE?9!4 ^66v٦ neof0Gߊdz=މ1 3wO;?`70ơtq^u5ƸYΥع摟H`Cat w2Ltli ߰)Ӣ I|9%?6dѺ?drO2i~sLoks܉2dܷ>N+?΋35; ^s'7לeLca{Ly*ux6d˯0s*s zeo%""""tt鰕& 1;Oo}Nc> BJ1'sKm#zOgqlsnɃ˛cP1/١OQ}es: ndtfx֪QM-CMm~2/7dѻi45t`Q)'ǫYԀ \̲/GVvOA '&i fiSbOPrnjlf;;mNhHz N޸-ElY)Ѹ v˷2qJ"sI 'xOOx4uXA&~?(4o[:2MCrGxKibdc5o6ߏ/NŖPLZ4nX;&Ȕq,Q֨7Ŋ#cW֑O3DzwLk7v LY61~3n_`u[_j#ۏk[rwH2nM{-Zz Ea& }@Q,pegj)BZ#Dylz| ݻvs2f9g<,p&/2C:fPad_1O1M}O3j8Y}|HfqrfH".I˟f!8_r|p G0ÆL2s~`֧-?,;0?A4i2ZA6r ϕoτ$ah@˦ޝ,7{b("`W+:ֈqV` Ӟ^mKR^9+<20Cs("}f%"""RGyIzqgC|yImd L }Ch .p``/\F23zH5)% э v Y䆆I!#+?}DT׈3g 3l6ryqIe6yI1|_dXN nv!׷c#qqqԙLj&4؅cxm KV:]$'6`xf8$3W>r=׻[=&aXfpv_gϾZ#_Nm]']`S86SDDDD ?Mh8 0?%I-i>tl_!7Ocos=6mjV R|{Kx1;I3 Ld CB]-5E^_(H)+4ȣuşLXCC'`6$vEdů]k74>m u3 q};{a<3Q.qG<ؑu2,tEyxO>gFṣqړ05B" L8GD (""""Eax<_AfٛS=i땼iqmն@Y͢M)~|+I#ŚLgCMXp> R/fmҔI-=?17KٖkMYSpՃiZ s,Ʋlwboǁrf/aXl~sV֣kxپl/$4'e?ᗬeQtF_2rRشz-xLWC^ډ/xòm|ٻظ9Ո~#ٓ3n{6~,o64 % x>|l?y{vvrYχ=BȟMe\r5/FVmr*4u)Q~ۄsQ䒎aaaF刿ۘGn\844 6M Ovչ|<o3k^^f,[xaǰ;C&iV`RؼE rsٗBhڼrb"_oHAb*wLWR̟ W?IC26]HeQ5%<ҽK`~  Ot-5H ~gzmrU6os_ߨ o }Ϩ ;<=(rs,~۬\ (Fϵޔ&EY<*ۺcawߗϢ2]KP&5%]vvx3yLzۇ/M"ּ?Hv;B p:a8|vL٦ ||j>71#`#6cc;̸ǚ\U偿z9ÆDzJO4}k\O 3hj/x\.t=~qѰǭ""""""m+|<3KdkЄ2/3ϰ/G0|a.p0e~`+NZ^3^#kg~>g!^Vֆ$usf2@0ijO aa`&aұsH C8~<uԞ.fDN]ym/#vi%"""""R:x*/9acg[ Rj01yc}1Tk'}&F@MR*u_ydU4XLQ/뛉HrvXx܁E*e]x)K?3otUbjT-]J>}*%2Zk=MჍ nIR ^7d7H|ǠiXYS ]v[ޟ#.T|paeGR^""""""߀DhG>/LeCS~MoQ h )vr סP.-k䈈T:)""""""""R"""""""" )""""""""R"""""""" )""""""""R""""""""Ղ]94U]Ejm2w쪮22HҥsUWADDDDDDDjZDWulC\6 A "l!`F>V\!_F> B R6A *ǏknnNN꣌k_xv\nxVeSRXՙء׾>Xyuq(CGH` s?:Ve|ZOm16!5:uJfKNny1t.\':܌\=ߐ2) )(ֵu)I?q~?Ͼl 7&RM{kO>>?XO~䍺_ܡגK>xXĄ'4cR6;~_|ߧ^wb˟է?wLuM ?N/`cR:6^ zQzx.O4b#aABwsk*롏~@#uΞԛ~t^_~էt\v+uީu& l+e)6c"~BzսҞe4 w+yD}賿Rk}wXs_~/_tӎfI=~#3SwCz~C_е 3xǿqLk-e[{+ \8Yr:OvߣxK#Jյ{s:VT>o;sI*N/nBƧ~GOת%}ټ 6Ia"uljOh^oNʼƔCBKIŽ/Tՙ7O׹$~B/7?Sǟ_~b{?MSL>l2!e\_)蕷Շ{]R%\fQk85UQ=sK5!ū^\)}ivy_Яsګsբ˲}~jZHzcϨ[}\_o?zn ?g~S7u.gO~YwF{Zi)&u;ԊAR[o~POj>㿤rNjTY3_zI5qJoK^&W>S?uk }I!smҥaj-]tMY)sk~rvr?q X03=GsjVeSRXK^r9|K:}Vg,LONx/w~ճgN_ X{E `۷om}8CS`4D0 ^f6?Hpi_? 5.Ņ#R|,{F,_Y>[)35 lu W{GD(y^bg8`muUo0=6c=`mkZHqYFy.\)uwe#35 u=c㑟H9Vlc6=wIeXu'$)){ܢ L!-v=g[hu"7b)b9heO. 5&U<1hir`޵yI^o=`0}iDt@{g3;+oZ}P螓{n 65ʭLn<W,cQ$XEo˂T[?T Őo0*gOZy_͋ܳOO)IV TO| V0/C&Z!x_'IЎ FCꙢ-eG^D~Yn2S}n+T6_/z"4̉E/EwJ+&S8;{G"L| ;Z!Vͼd%Džl7eǗB|^M}v/'[}=Mex(,9aₘ"I+|N /h߯SGJL :1=U$iGv7Wb1=(t$]Ɉ"mfH.~>T'TQEt?CP`j2߯'( E]6-HRit4*taT:IZPuPM(ҕ)1et[*'<9O&M-FIҡC{pE<eq EER!EZS t>oy8i"]"]ɐ"AExTV}>I6O+Pw%AE:U[ ,`Y &˭O+P]aoW lq@Y4 '`bXgmIENDB`qdirstat-1.4/screenshots/QDirStat-histogram-P99.png000066400000000000000000002256731311502036700223410ustar00rootroot00000000000000PNG  IHDRR[;#sBIT|d pHYs+ IDATxwxwfwOI! %ۥ)M ^@DD{!X\Xi bko 49gBOygwvvyYoJTI7""""""":Ǻ 9a"""""""J V}x*.GjU }{$ュ1 T~8QER&WoOObBDDDDDDwewx2}IRerRTTT N:$2H!""""""X\>0]P(*G' P*'%Ivr@.䧬gBDDDDDDTGE7i'IJB\b VJB*p DIR7?e@maxBDDDDDD7Oh~}irJ|I&L9AE%!J*J$>l&@(G2T!""""""J#k ] U*eSfr‰2!JUU(%JU.< CX<(DDDDDDDzJo@rJ^X*N9Baʑ )tHNN=( ʑ$*dBDDDDDDTH˧ Kk)hP*,ZZMB YueʑJ9 (H="PѶG(BJ#iE0B`ȐʀBZr,Q]%M.eh%]h >A SRni|yaettQrC_#(el Qæt* Q ) 32)$\a,iZHKiBڶZBXY"""""""i -Mmʔr--]REzh ˯ >Sa @~=(tðVʡWyFlJOtv60L#)4,ʖfpö Caa1 Kahù6.2vMi) 5Zv "]QN8RZiqG*?C R-$^Yl)P)^/8ʱ)=vMCZVX+eiaiB.+R C{V: 0\ri mx\!GHV֪H!P*ECJ9|.Ɏ@T{l99Rj)TF:(UЮc*-LGJ*%^c8R^XHcg"0u2RڧF@=&""""""cFhA aT WCJ8WEP+ c8*J!\Jj RJUӥ>\)HIOڳ>JPB!ܐJCIRJ20J!--,(r,ᗖRF c`Ǜg7n8,ppt!Ӳ -K(T9r6aBl(7lii2!îJ:!{ZLD:)k)j NBY",mC=W!F0D! "dۈkzDVvjTI>7͞=}xՠ>""ڿ#9NdŜpE1J H9P;wܹsj* ?wW^#$a%Tq]ѳg/h *5M]vŲ!I" 8DDDTΦMpkرC˖-m}lXl9 P~}t FBdd聦͚tcsNx<4o ]v8t=܋N; _ޯmΘ1[nC=XIb"?jƉx'%ѳ'x!8HAfہJDZò:3vAS ADDnF|B|8KguǷo{ߠ! B0P}ö ELl} 6&p]^<`7@B|BvC ! 멉O?,$6[~S\-`y<8,+?<~;>\!,_ y9x}>##]d$|%&&λBZ΃:H""9*'Aaƌx'8HAvVf&7hp~d84l64Py|rLz:3vAʔ,)}%$$K.i2+$g: ;Url 2ѭGOp}Ibb9EGsY"":~{;0n&tR/\YEucݺŹ眃7BXz5ڶi 'Fǎ@^'"#= ^}7#axjgQK.fΚEEEh׮-F|3Zn]i_X={b(Cߏ.ٙx?cٲeXl^<9Y6n)%t[FB |7M}٘cx\-[0WaFD˖~>ſ={kqƸa0tIU[;U[hG{EEzucm+k;338BCjzw}[<mߎn[oŬY0ytvΌkmRQrsswӱr/}@4etn$T|x<uо}rJGD"?/""=¶PC|>""*ŸGQ1ŗ|> k(#"՗C!D(DajH|z*Zow_}Yf#)i^|e$4n翏qǫӦ"B4iIDƍ2EϤIyM1|8kWC+k E=md^~W &,(ħFQQ?! ?&N{/M h.ߨ!̝k]$l߾}6@^nN;LMI i! z- ՙUfqء ދxsn&;CDDGÆ~mY>`>qi}0p(Cbyxg* RxjD<X`:uݻᬳϮ7PTRSSq=qЬY3࣏?{GH8:|e紽e,_7< -Z@.q)GۡG\\ 2tyz"5kV1mɧ& /g,¶mdQج VdTddf/c„GqхbQU^gXbrrrJFtttǕ5dP޽;zA\\\MIIA8F-PP&"ck_>W@nvV2Nض aƬٸk0ƑW/Ν\m޹=_z 'x֯]bo>9䶁i, o.<7 ΌkgM%'omy s/ Q f&|~RR**ڰv@mUHMIelj5R^ > B~0ߴܫtr}&i ÇǂO>EÆO<敩xpw!'; J-l~C(cf(;s>?&>,>3deeWyu1罹HZ׭/~@? z*~y1F[lֱULX(P&"cgcǶM>qbemdg"u6=scY@VCnƠGؼq=l;m[7Mָ{? >A.1ݹxgƌ:5v3A_8Pyk[Xzs0 a.**,k4 X1b!k#(Y#?:t}ڤ?K_VSRӰ}&Cb_h~70y23vnoժ 9ʝ{mҟ*_elFnvRvnS\?5Ȳ~z\}ՐZaBk]Y<}HOG \{5{?:`%:iӦ, +W<ඉ813+'VvvV&vnی~,dJ?,mo\׭.-cF1`$ {ZSc:\5x~wIr ) ca돀mU|,];>/barnrdddIqFܹfϙS{֭ƍ1kl/83Mxx'ae  t|HMMŚko`핞Yxmtغu+.]^xm۵+V+W@VVV(Z_}P(mҸ16l؀d8ie˗a5lGزu C7 7ԩ/ -- ˖-߶8Y^AvVf~+`c`0xmrXm[6öm$؎P Sc[KSA|-#)iX;;8C6 WҀ~CAA!t\DDDG9'!ZltHt,\;w4k ONN9y'ˮ_mn+}QKq뭷"663fDFFpb^hذa?㬳0K/!778SqDG~#n(̘z!j֭ESj‚"""`fvDDDDDDTq"FU@R ʽ>f-1fwR]Bx,  &IDDDDDDuˑ'횯.KDDDDDDDt1H!"""""""&)DDDDDDDD jZ,"""""""bBDDDDDDDTM RA Q51H!"""""""&)DDDDDDDD U"""""""jbBDDDDDDD5>/)DDDDDDDD U2H }/ǥ}LwG\EⲾp;>&Bk0帴XVpx9Y1{H\ַ.O|BDDDDDTǺu0n{f٩8Oot$gk CnVEs\7޹SƜNDDf.xD\ʋ `'Da#w WD=qnHЯm|x@F O \y#i7Bfr.4"pjF+Z{D cmq[ Q"""""ڠN)QpCծ:n{w&轎t+̙>_ 7=ιz(] ={d o`$dA׸z_vks[sĭ3Wxf޿S?y׭AOU_?`pE|8-74Gqp ^{g q%eв _⁛j ypӳ0dqja*&_@;5 _szD$,7-\T%JkzFao͹b}nO\Vٛ'j'8Ϲ]+95D$ڞ ''!T.~yz<s$x 6ފ[~ O0f.xtDlw~Yss;?O.A`лVT݇Lx/ĉX# .!['aEkƢmЍKZ!* "mWh.xֶh}Umjt;'YvXǻ<5<]AE {}*2 "uvSȜmX"7׋ijl YM#>sxR5ϸ=0x|y:=K~6 пC#DT2gIw`]-ؒv5 ZpsHFf:>JS^ŹGzSQ~^y}l;Nu~tfoX?v31zk|F `?-¦~[ A@L\$h'Q*N2{xЎ/1qF=pW܅ x:\ڋPtU|\oĖMRP0-[5F/EG%#L\~JU> S |KWby!Nr~)N?jnpCq5sb 7֜H]p z6hCϒ;~7v(Yٺ5㉻7cgqJߵiAFMzk= "HzK'OcL#YǽT">q'.j"5HG GeHKAA^O|Mqѽ0O|NǛs *WwQ߃8oy (huG{wGBlI{ _0}v<>E?!aDq@oGy {5JCS#7#'ǢwBHݑBޟoɹAwx{^zm+v)Uy>ߠ!$nwD Ϟ2μ1i;bcxehG~B m@>@] #L2aN&V=D?  #ڷ\WE: ΔyOb{AE0d<ү5LSj){hX7C|q&ZYڶjUa) mjnm!RmǖL(7=Vj{w6S&-'u@~VwɶRYXd,M!ҷ #o[syqZI!%t8~ҋX@ ޝC 8Ty%6 b Ls7O؉ˏB]p8h.U]/;BЈB:Oh{1'|q/@o_XCG_:׃D~5ܜ5yK~4Vꝃ5o46<.wSAn`AoR}Nߧ|8~\2賯"""""":ZER{ڋ}OOH$v3/h R$"험ElhD;n$SfW02AK7lt>dt9xQǬ>/mNNbwEö Mr4|h{ ~h|&\VC^p<ο:7/}2 ?,(t8gn~|x ﹈hk|ヌ])߭?NIH |,|Sd)  |=Wk!OGs0>hg0=c$PeMY?XqBW%:x˂8ip'$>3?;o} >3 b&bXטJ~h:qk]zU ;CtH\/,1|60Lõ SD tC KZr2/BJ7,%!OY6d)]W%uE.nƴ"""""":DiIfmgpUEk,Թ * 2PT `ڦPaVaGauv hqGnu _{6:~e~.DuW -U+Rv=&ܩ C""""""*)DGA3>ֽ """""hϓ%"""""""U"""""""jA %"""""")DDDDDDDD5"""""""jbBDDDDDDDTMmv 33XwjР>Ѽyc""""""N)۶oKτvBZk,y1mߎ͛.QmW u2H)((ŗ{SwIO9 ?i( PPPp{'WC]_e:dffW(uR)!%23:CJQ\BGPJc˦ؼe ^UR$a R'VT %U6Rqcڟ 4ѪM[Jt{?u~\ӚիuWVn54G9v00MǁiPW5)JDDDDD LGm"Qsꩋ.] Q-Qg+RN98#"""""h >(=&"""""N9* _= >|O R݊nNϽ' "=!g{alu-Ο K{-0؛ #gc}UO1#|{RTy!""""ګ)S{*/2A }3Fڇi' uQo pх,]P Lft <=^| J%wѵ폐o,w/x8{ ?pVSB]OŰ[Q.#Sq\_]"""" RFǖ׷;(Z{ N?ϓ(X2}a5߽ #^ v:|:ztӯyo'[0O]a⣇Ģj:8t"jrf;' qxPP"""""":b:d_U8]zu?O[<tEtPّ"o.b}BAsW~<) Isqczlb{pڗϡcTFǹe>~ ^6NoF~eyX?O @#_{?M᯷np7wƓKI^$Cw RJ>29ѯo[?oۋPz s Lck帾R:NZh1{\,#f}ŭ5\/f.Oj }A,rs/SFן" OOw\-<{ĤqS %翃~~9=Y:?ay坸op'DhSJRBJWN'ۊ<ֿz3^ ON*>s,6up];5๧cP];31$d{ yhR<5kBޚ#!bx4~HhǸ~O#5ں'Ad,qcj+w@EX| 4wޅ?W =2%S(<=hb˗/?gDbxiZ:.<O6B۹HMsqޅ_֢C[4[>~kiĄ8(\O΁O`m`ܬxyĩ< ϕxv 4a#_ bVSs,ky0_ ΏǤmPIBDDDDD5D Rt ]/\&wAGa2oKk@qwmO⧌6h08\/҂h9fi[Z%"S66mcLzhăVA<" ]$e OӪtؖ @vsV%u,>5CnW>DԫXoIL''0Rg܆kQgⳉI=nظxb\}#g];:sj=7-- #=xꩇVnȾdW:Q7\>F}'/3;18ģk3Nܬ?wq맡E Ͼ{?Š ;R }1Hl~ 9I0jA^~t!xf?PJ@BYH)xFlP\#|/1+' ۆtDJ& dN2dQJ@t#%7c{B!O\WJZ5/ĕa f}tlM;AfQu `H+bcS&HɏBiKFŹ#Ĺ#G(s <<Z1{DSh!3UHzC\x0(O4UpVT_PY?c p#r~3M vXhtxqp x~\[ͤ9dↂ ĵwO^=* bBLDꊉ*ʄYi ]L MH ,kށwK/!< [hq:|4?[ZexkAQ ;܂=ٻ(ÿM#M:H':(K Bo~(إ+D&((HG7 E:H mlH̝; {́5 GVOӏ2bKƷN~)P< e'E7V%}آ$)]meYY4-쉧 /Ҧ|@Rdk>ѭ%jlڍ%K~^=e'$Ov!cHwImkj_gONr_@{z'U6xZQT\3k|GY-wC>i.4~Z%AVS/qaHK^NWnݟ=엏'z^Ii ^`/fx޹'O\ }s41Y(\ꆴOqAJ u12vo>_Cl^ Ld/^Ѯ8N[ժ)@14 Oe~ژ~oT#[ef[WJ 7>{=KV&IǵZ|1=lw7yX,&oq3,n8w7nv:`s3{y^V,_3f?)aj19:,l㟌oq)lz#ljJy}(x P]V`Ʒ/S3k2s|:XҺ:7wwmB*Ut]Wt7S\xNO>t*'""""F,nnʝ{=lK6-~c%"0DV{,Ż {dKZ<fuج=kU~,p!<=R.;XmlZr$ˆQϋ'x my+ z8{k,""""""0HAh?̕>guEuꤺnʕ&[]{蚉 Be+'{'uIm{z`Hg;}/YSQ Q`Ryѫ 0ɹ /"P&Q I=2}sYf"4''=hsـT(FfaXg'P(X d-|BHUx9xc~_$shGq툅:˭d0^>Cػ_v1ÜZ:o1mzs>qT0W$6W@R ƬvĆ\~+Ig=CJ`8Id;01/rXXOgFݡ-zJu ?` h8Zþ['ׇ!qTF1x> yuah82J=0'x\:5}c>Vǵ#~P _ —߾ào;?-J)}:ze=1)&oh֍n{Kκ2 !vFl?>dy+m'쏩h?2>Q{ҳ7N_\w8TmLbd%(*l`$x"""" yąY B@>&wWF}q\};刃htFYPs3Ĵ?BQ ,~q|תE0B@ e~p0FpFo>]C +0z$7(1f4@0;I=-TLn6P~WCп|:Iưpz%L~ 6B[Lvp |ꌆoliB^t{%;\ZQ/ |If[4 6F֟ŚoL5d̗kh/Guk=#ٺaן<'yygMrvOC}'h')2f|sN&yD)2gD$*ԑs2d) 5jj{ G@q0`` 9yu/oߣO@ c Y|ކIA9!*0^{+ Ո#Od@AM,-"""n(Hyx vѶg"P'-wqM~XvIaF uat:φ= w Ԧ0jkwɔJ7MЃfhͽ%L@>CXvayx@wO}şOJ灵_c@Ɛcpo|ֳV4F]|In ʿ`<\0E|(BV3D%i2CP9xz>wDß`vH+욘ɜFG`W ֞ FlWaZذ, p!,`J:6m]6)ͥ_`ac}=}LДicB(p,̩5uD kYXʯ!`{4kۖeſ%xǒ&ukH6ׂbnؿOęQs;gnSy0ÏVT̩ϋHC{"֗0  +LrNx(`tX{~e7 86jοä)b> n&Xr] } {d-#;e* t(~r mƲ7IKy1oc 0Y-P|<0‘˷8^bɂ;%xnÁF q.# W`lWG0ݹMonIn|F} rÉ_#jB߻y!% dnHX1gG@%ƕ[gŘFlϑRxcn4d }Ao`ʷ͗-a($@Ŧq c:f]=ug¼FGʭ[qv>lF[ ͸ O M2σS)n^z|ozHl<UsϱIϑRG;8[8mz-cOw\bu=ovMk1׉Y0ܰGל~>/`@Кx"G9\A1䋏X&] d`r6U'ED1ec׹5qDfl7X ef+&G<rT6Ӻ"6van 4Oy{bG|JѺ_C>MDDDDDDDE RDDDDDDDD\ EDDDDDDDE RDDDDDDDD\ EDDDDDDDE HquDDDDDDDD  RDDDDDDDD\ EDDDDDDDE RDDDDDDDD\HҺ """""z[#$#/GzHAHA}H ȃBt RDDDDDD])m*Twr <7kӺ"[ZW@DDDDDDRc%t/̝= y7*@֯"q{FUʯ^!|a K]>iA|Б:(Ǵ .@q\$Q"""""".Yv({"kR3;2Rԫy $D8QOРEc^`*"hhH:FR7#3Z9MJq9@©9 "8;N^\U+C cecxi%JS^W+=q ly: .S!{^Xc;A_!y8f#EDDDDD$;WlZį͙U$?T؜°ϼ_cM듋7r~Zeb\X8>L]1x_ ~-9֋^SJrHz EDDDDD$q~Y=n=&.ߔ0[/c~Wvx%9Rβf m&_eUӱvg^Aӗv2cNNMa?ǪilW-;OC{ѡ="""""" a'p] Gr$@a p,J3g"D~doZW|30rgZWEeќt/Xk[gv!`N>XqY>&[3evl&Q"ӪIBlNJyu=+gWM K޴mܳ;*910{LD7~ ;3.Sb_ѝ~?&xqwl}zپk+^bxQlO&?J5+9^= EDDDDD$=3[0Xo ޯ9qضk$*- \z+`\#Zsp,?Õc鷰W)\3890ݼ`8|oM}^)\b;_"` _W)^&^F钰E3'c癘p7_C RDDDDDDҭXNkEy\JӪ'>E^cD_y_DI6r&Ǝ=4g~"%-6o'pEZLxd/CNU90v>%0G{hTɚrN՗cԬ U|yygL|R[-&x??<5{Mv ޾ ^~ބ']S~v¯*Hyݾ /ru iKb >No}훇2{-7 ta+Ѵ<5Y}RqW?ќƳhyBBuec!f.dĹC Bj6<[?gF2o<|6GpcTN~Rxds5aGT$wi$|=`$6b#Ϝ,\c7yX$St=$ Q0_oOXĦe2Mhjpp ,GalZ:e8 O4V?2Q6n^Z+k_+~aVlX?#v5K'3vśsx^y9C >rbp^xT1gvs8gi %3sxYbpA''I'P:w,k*"""""9b81 !. OÑV:Fv3ȓsb1qQ\< g)rS0Z~~9#_l.Tȓ­3t )p$DaFDza{1~k9c><܎/w8,9r='O=-حV 6v+ V+VqK*wIs&N•Ǜ#, '/Ŋ?I$,kV܆oa^GC1 xsHkyT4AoRR<_-V/pS!e(_yOQL0Jи74N[LwTi vW&*Ɇ<,n_$iYyyR{tݑO0jƐBq{<,԰MxX[V@* fg_o,ˏjό5 9?x*uMKǗ0}4-%SJ=bˋGf_"2΍1L6rz'31}fMi/XNkEޘa[)v<ʪ^ IFHڋGs,{= b=ڵE~@~1j#621Ds߱͢)(*RN~bђ%,[;KkB'| qud!wAAY1s*WL>xDEn$|=nʜ)\BtP!ݙd 6DX}y~ZE+ֲjL\w*y$(HIY>' U$nJϕ'o-<^23w%6qe%~ۡ(&b4/>bkт?gFޠi|\Oݩ>9;uG[ќ9{e~%hw^f| נZ_*!S#"""""""")"""""""".R""""""""")"""""""".R""""""""CN_HAHA}GDRDDDDDDDD )"""""""".R""""""""")"""""""".R""""""""")"""""""N{uDDDDDDe߿#GpQ.]իWOOO|}}ɛ7/ |֧ (HyȜ={yrJS,MXX8^ݝӰaC6lHN+gϦrt#<l6˖-clذ"KٲU)R4ٲ$00'ٲ$kxyenNxx(ᡄrqٲe [laTZ=zPn],u۰amڴ!!! FΝץd`6s2j(9@@@UGju)Z491f3 nn]lڴaƍlܸ 2`5kv}رVZpmݻEҘ j֭ۗ={P`1ZD*blTr*UW^yaѢY=;wf„ :*Ui֬QQQזӡC\7 EDDDDD$eL2kM 1LnnԨQ_d˖5L>]vQ^=zV4iܘk˲eƂ x'KEXDDDDD$y2e k׋cb-DId2S1~Ok ̸qUǎܹs4nܘ{mܹs|r()H ֯_ϳ>ɓ #F̢yN{<𺸹Ӽy'E޼8p=+ViӦ8qZ… rJ-)r H[h͚5#22U_/`bi]-$>kJHHuQ.U˗/'_|iXK{')""""""ŋ+OÆmyxyyua67-PK.%gΜiP+C͊ٻ>$'KDD؂5mAUz[T[Z5BcVԞ-EjMys$u.$$y~~lXTTшnѵ@:nܸ<رcQH+$"26Rjuؼyɺ'5kDDDDDoڵk֭4 {M6Qbcob0}TRVHFdlQxj\r>>ݻ+p2"""WVѧOdddnݦo5QyN.Νkp!|HRDz(Q V}K Q"""mǏ_|2`[K\$bĈPgda&cƌt:&8~Z##%%sή>}ymHHEt2k_lkf b#)))hҤ<=}$}55^wwL<Ɯ իWٳh83$$=yH/̘D}q)lܸ:uT\"`#0EܿWoH  j5h׮d-%%vuF""""`0`̙>}F^aD2 ⋏p'Ì+n8B^>Ōah߾=r%")DjjogX8dgg盼-((FC2Q|󙺣#W5{N"""""kQՈJ傐xN_}y+TJ'N@B]^)du qHM- r6vz@DUohZTZ26N<ݺ Bny3{D&lPDGGٳQFȒH!tps+(]"5~gFdg"ΜyqCU<'G)'Od#%6R >}u__oCDDDDڍ (i / <0a8ŊbbbDF ټѨӈ(zT/a]c{=y7Pbuh6;wr~"sc#WCٲҋn]3 3坄WQsG|xf]k1̉ ێ IDATrrr0z$څL|h/EDDDDdJVVABiqoݺ#=yTƬcy:BVEN}+Y? z 6R6eeewdڴQO>{F/l1H1XD+K*r9$s7x`̙"MP(-2Q^U&T*$%%CEJgoxVKW8#T*DVc(fpwwr7c3RDk||d;(nݚh֬=RhQ\x(V,q*)EVNB6)4lB[%wڵH!"""" {nFJҥͰB %J\x6--gB*""""?ZԬӘWbFJ2f\F UZpi+'1/*Vh$Do""""""+ B h4Z; z?7PZ5k!z#lYWL\zqsPQN[;$_m""""""{i$s࣏iӦVNBH 7vcuJ[;Lg0p 4#Q!СCÇw`(x zL&Cqk0SFel<k*O$ZUǐ!, ԭ[QQQڋ [Z;R:rd23ФIX;c# cN Yή{CMvR`hѩS_͛p \z9BB!Q 4QQQظq 4hQ`~E#~u!`VNC;lXwqXiu3kOA$&gdKh޼emBJѲe 'z5I:5FANEDDD{-[DҥqU8'jjdHyرsʗ/f͚Y;Qbab lwKG'_qjVWWwt[~a?ll ~~5;;~k#""[nĩSoѥKkGʕ #!!j"T hIz 2wCmѩez 9]6L&ԩSVN_ AL>Q@b 2fU׿ῷ8͠z """"B歷Bxx8zO,kGzmٙ>} z=PkG"H)@4dnat '^m o}$""""<4qD5k !YRĒ%Kc@d,"Ǐ;/^ ARFc|xEdB"""""RJa͚5P*عsVgQblٳXv-(OBDDDDDdԩ%K@&aݺH,XMc016,\.DzePV-k"slٸVZaʕP*صkNlY6;;Sx2eժUh޼c_B /R FBV Лh8tΟ"YwpP`pp2""""*hZl͛7k׮8~|?FѣTVu̘1 q(R֭[5kZ59b-r'xAiAÇGh(>}MԷp2""""*j׮O>8s >CtBam@Z 6lX A#,, /(TJl @?*fKIIÇI23mg*(`ٳuX:Cvıc@Ϳv(q>|q{]1v&  BT@ݹロd=''WphVsXX|i?ˆ""""zRĔ)SЩS'3ј2eK}hРtL^waň Y&N<ȖBT@%%%]o۶֦γ&V.]鹚F X!jԨ}aݺu9s&^YcQ^S4hU\. \|GEff:\r>|8:w w |H)z\lpHOOżyK`/b0apY8T*瞗elL&CnХK޽8tvZ]Q嫡B(V$+//?888>iF9HLۈKNSPӨQ#YflP)ʵ,++oʅJ7mZd6R(d2Zl-[">>oߎ'N :0?wjZ9аaCj ۷Y?"3`o @DDDDfPhQ#<<ZNӧqM >>8;; ~~~(Y$QjUTZ D)DDDDDDB@ZPV-kG!*xS+3BrH1^ŊŞWRz:N&˹ a#B18g6{=*#tiVTE1G^8YY)L,)S>]< zTX©HL!F~($6# qc0'z8ķ=?~i V.]>NB7FJ|)Y߽7skt"""""mJ 4 36BJ%x~197BhDEv'"""""6R,ḪPd>(S-n Nv#y(U Ɉ '6R,`ڤ\rI&k`R'j5:wRc:ǟF+VHǒ%kj&ɺ7ߏEǍ%IIIE2e\.YEG^-)eDZ\pK;4~7BO.dgg`0bǞ<wo^ʖ,Yߵk=FtDD,G$AѼylձc'ѯZJJF (=x' Uv|cŮ } "_rTQ1E8Wv[c=K.?y$fGMUѺ'g7؉MzmsRggWɚL&չr9WnvtLo.F5ƌ 77|uj4odL_h&w""΀c b^ +NNDeu#2.q {alp~ z~z5X=wp`XX>Ίg<=FW^+`#Ţ79_7#}'ĩSgM^ ۡjhQjCzejՆOꉉi2fŘJy= a]0p'X`D5s>6"i8S`kE#z)Ӱ). g񻱬k(/۸{7E-6h:(JtG~I[6k܏c'11W=w|~໹iWa P=ncH؍Za' Nye'DDoDETZgp""""B-EsFap3*(>Q6N{ƇwCuS#fZh*{e l*7dPFv^(󟃈49bh4 {~KJ1w!ZC@۸_ 2c *,H(%JمSMP"""""W$!] $^C~@E賿"~9Ǿ¢/ I jWpPG 6)"4qG~j8z)F{u fY`k1:?^N& (3An;n4AзM%s:6R,Ld DDDDDH"Nqam᭐C^-d}):DM!=8x{UqqRD|7{{a`#f(!W! (:_UMT>zvc/ JmØ؁ ,NCz,g^"te|K 0 0dcr"apPdpC;4Ⱦw p}mtGz3WiЋz^؄9k`RG^{r uHz 6Yz᪒Aw)nj_k慴1 ?'PÞhհ**?Og(dDbq98%uxqshۓgz ~88 MjLшep<.SLj#_ӏ27¯TceES|}% e[aG3<^z)D`ڴk0'60:^挐C0ݸn ^[# 'Aہp8uGZV>o7ҞJvG,lӦ.*YCzz*T(Z a0,bDDDDdelX *hܭ2wa)99FZ %+WǪU[T>wAzw h4ZL8E[".D8qdt +bDDDDTbE> w܁#T48s*5*_""iѰas*U32EXf1rH)SBtJjF,[- 2\̚&f̬>7466R }5E2%˖ͱp"""""6RGOw%Up++1Lnc(j5(Z4M/Y?th7-r+''P\L/)(R)ݠ21QȬH;_=l.50B ;xj"@apDD:A@PP<<$;wjX^9Qn0УGVvtކ !v7:(㺁6R,ʈk'p橵_N} Jgo^^YY Qzl-s"Bʘz#~DcH@C1|@3R'"z\^D8k^C>AFpCDN[tb-*$8p*.ǗA!P~I(Xj.DqE0oU|ǛC[d(vOq/xMu ZTϟ]""[u~z酨3X>L?ZVV:YfbH9{6 쥨1q?]{EwgyQ#qcE}1.[aYIճ"~qLA#myYMyA+1wר_D@ħ]D7K1h4G?Ah)M#"zUiij*M^~9tjt:vvMY!k#dGXw [bۣ-8r!nNme]ko#b8ezŤE xEIa!\v‰uut)P>&?-ǡ^G!_Sb=6GWLHV=ΐy5gS3Ⱥ0CFG%mgd_1 f*W:0*Q8,W,; CocPՙoVSbIblZ=WfgYt2MBk,#1hDDV`4Lr;%kɘ8dddJ55%kDDDJb(4pQ+2C =1gժtGT-]ƚ,$ ߍ Bb`e\PƥH2]ü߷m`yt<ր\)CjmI(~PAټ,@^uY!owʒePG.n ±xՔ{lX[?Zǡ{હÿG,}-%DDٌqҥeffAӣwa?؁#jBY*jص0d~A\HJPÿ=C Zʘ?V,='q+ip=u\)D`ؙ>u8:}LGd˼N&aԟquGDBY9hQ_\x xq$^q0zM~,z2Qw=[>w7 sCʝ{pLhb_JA) IDAT{]"%/?l"= }>dhPL%T(;i; [;$܆hg}NNT>2"u$9U[G|r}\dR_jwAeO2c`~B'xFR([.lĝވKhQvƹ?KﱮƗX(AF| b!wO]!<8@w˥9e$dpD;þ\lm:ʪyqqB%pLIz$܀_g~DFJekBLlG""sJNNg_iptt`"zN۷0qL#Hw '˽GOb5P*ed˫S#nĄoWZ1i (Ph.&k"dNj17d0BbϜ1-@ڡOKUj&tO̚?qAG* ȼ3Y9B.%$g7ơH@Y+)0닦J˶G3 *& = -+|Byxa#Ĝy|7q-P\n N×_΀Ng0Q׾pWшƍdNɓ!cNF%;}JMj #0dsصwogdw~ˣ^=e;;k2UiD j`0,Szw'ޙ}v(RFnk,+Cƞ>]@h45#>䯊2CWD$o5Q7Aa|3[~űMc6'"0HHxlp!}={>'Nݻ(S/CfI=14-7o oLMOOF#qA%Hu6ppp xx0DDDDoKp ?Xn,\>1y_4ߣA /A(= 2xxxI6ȸ?J]QϲZRffz=N!YOOOɓW-l)$Pz&Z7+wcnىEb'#"qƍT\|K2=ʅtl-[vKptt49(## ~~1gL%A7֭CDDT1^÷&|:RL Q(鴨T) իK/8t, '*RSQJ-ԬY_vm$lYj,jxZFF&>n^N r &"""*||klX,FOdeBQ%ܰބ-MIC/ؾ=JtVNDDDf\4 ƽ`#D􆧷崇WHM4 y)zv\'PEqqq9ɺJ2eJ<>99oJt:]"Gי ʅTvz89y#HO϶p*""-5%YBODV+ߍe]E!*>ǝ;Yv-NVgOlYfɳa4 7~HJVV4=V*YWsD !Woל(=DDt:*VjjKַm[,$cǾpv~~֜LDFgY =M?p%$'% IP͖C ~ /qY""*PT* ߽{iȖ >!""Ƕmۋ]C&~ %88vv CDDDD~0*V //ƍqH$v3fY3Yo!""""I2 .*Yj֙ظqYJ:)DDDD6H&Icv """ $&"""""""Sg#YYوXZp""'M@^\i8;,`#(@_\~b '""KɁ buZ|tFdM.\y̟7oޑFi MHoAӛ<ѨB)a>}DDD`#(_nnEL.PIDi_Wp=ɺBa!CzelQh4KލK'LI,YNN3V|QԬY-O>-''QQ'жmOÇع'OCQm޽!( BB*H֏ًۨR}DDD`#%$܇SV?ǏG^.))ŋA#))l ~~5р+/ @xf4_8GQ#>! -YBR Y )DDDDLZZ֯*Yr:DF琑)YDFuMqiϏ-[֘<6==JjĹw`޶NkbL6 __o &"""k`#y0\PŃM~]!sޞXd6펎NUr=$kʗ2:N& %k999Pj-zff:~: 66R Q:uH֓$ %"4d=!!hJH7̂ <(Q|37lD5>>'Nyl` d֎Bd3H!"""Wf0qQ\tDz޼FD`EGNZBT{ܹs8<Ν;˗/#-- 999ɁV-bŊŋGZP^=[ 86R%' .ҳRL6C#"֯ߎ7nJ֍FSkY8YױalܸW\1:{{]g J*hРڵkի;:M`#^L&b0IeKiZ_͚/YOJz_MP(ajQX1Lfri 6 gΜy򜋋BB*#8,J,%ˢHO(ΓHN~{ܹp >}Oٳ}P*9 .6RRx1rY.LA@HHEɚh&MIO8& 49s G۶uLۥzZɺM-XIIhذ%*W~"OsrRɩ$J"4Z Q48yvǸq0x` 2 *lO2#"""|`0b/ab-Z }q" zcܸah.eVv)0 &ju6l؆~%Ywuu_ C￟/X8S{a~z5Xz5ʗO> AAeT:_mVܹ0i$Y3gD =F %tZ= *st,]ƾvjzիדoݺ $lL211 RY[o5B͚;wC|7n{^-PϞ=1yd\t w@``<;L&CZQVc\vqenݺuɓgY)DDDDDaY-nyW܉Eǎ}*99ϝ{"RS@j4r gϞ矱m* <,㄄T+}jZ5k֬C~zTP,cY)DDDDDfvCɦZcr6J~+6aml '* lÇ~gg7#ѶPλ/ph֬,YMeL"Ka#O 4iFv" 'VFZTr)NT.]M6޽{w&o۬y{W_E`Μ;еkWL:7DF Ki?~:ލ5}Qtؼy3ʗ/wipݻ۷A۶Ү=ao~_[3F AЯ_?Kd.lVARR ?geeD DQR4ytӯ$Wŋ |#EaŊ9s&޽ صkj׮-ƍ#$$׮]ÉQλf(z OODDLg} &klRFFd295,Y?rdYw)j55Hv :u‰lѣG1b\tϟo"0p@5 [H#;!))Ewسg|Gzz"""""z-2^ kL}^U*kGZÇe˖t;azEo `֭3y|ꊋsقɁaÖD.]dr"""""|xwd(dך[_y;`0`"ӋT*|mVY*:G :*!66Ǜgf"s+ODDDDDFƍq9ceu? rR&h֭[ѡ}{ddd]o'ׅ*QUd_вeK:9KC#FVx7F ۺu+zNV*˹J?>D,pΝ6+hӦ'ʕ+7o'zlٰ(#Fctiѫb#Ȇ^gϞE=>,= y/ yРA]~VkuwJ*ȰD*4RLg'"""""*( fΜ Y0wࣔ/QV-"==K&R0 ?dI#۾};bbbPYNyrN;A@GR"""LN'Rn]+RrM->6ѫb#Fsg1d2H%ɒ) E$ eIJJ"Bd_}ǎ{ARf6C1}ν{y{r%xqn $ʞ={]^zt/d'ٺ40Cb)H)f[l`1 ԩS \weʕt777~u?O<љe>#;;חa RDS""""""RunX}q7ػwoFGG}v}YBCC9|x>ؚ?tI'9(HLAH1ۿ?WHHÆ c۶mL6zꑖ䡇CرcEIL< EG^sإ EDDDDD8q0w9^{f͚EJJJls=,_˗ӥKV -gĈ<++V|ANNunW~Aۋ\ RDDDDDDYzz:f[.LmA̙3Q^={=mưa(U[oo6̚6 '> IJP""""""R421i< gagʹxgپ};.u!%% ӯ_[&LƮ][4dAJ5.+AAP /uĈTZCgϞ ڟ;]veʕ,[N:a6Y[yCtgժs{#={v"%bMŕfluxf <`ڴiԯ_<(._d2ѠA}mƐ!C b߾L4}oOpT߶ۼgS",,R% EDDDDDy{{2 yeXb6A^LƂt<ȝ;wQFL> xx8#Gdǎ;ԬYDΝJ~1qp5ЩSKv~"bgَbexBVv͐!CV#GouիYt)w}7a_3thx~k:vx)OKS""""""R*TbnfgIҌ^oSNz?Xcd2ѨQ#fΜɖ-[4h:tz^zQ\K}J"bg??YM&Zxat8sn]f૯]v4mڔYfuAdԨQ[׏~ȥ EDDDDDթS\Iު3Z0KGpy;6 ۷ogԨQѣGs ڷ={dTZW.r)H)fufscCr+;l0"yj0U}l$$$0a۷/ׯ/2E.+)""""""ÃnGŶ+\6;|^DѪ. p뭷ҲeKϟONNNq*r)H)ڵk7q`{0FKFҫ?V36l_~ԪU_ܥ\2 RDDDDDDJ;b26.<{XT1e0JyqqƌCyGٶm[q)rJ|r!DDDФIN:..˹`DAi Osr={6M6]TWRDDDDDD+ #W5eL@@Oޮ Jۋ(K@AH Ѷm[*U~z{ӮӓVm IDATPn8 RDDDDDDJxm_"%YE4x)j-D.k׮DGGs$GG6P1YҥKq#r fW_}%+-+p;SsH &_R%\4)""""""%L ߿?.;NtwIZ;p<]% EDDDDDzUG2syxR\CzFU%\2 RDDDDDDJ wwwf̘?gބ0vO3gƌl.KQ""""""RBUXO?wwwKI%:L1bAL*̝;wY"q̘1̴CI;Dqw'd, ~!5*D.9)""""""%ٳOLIq;Ji䳘T<<<3gv[q%rY(H mۖ/VguC wfso1A@@/M6]e EDDDDD*ѨQ#V\Iڵ9ML=Dv1vL9D9nݺ\_ZD$)""""""W *l2O0c|qENqd~=ԃI8tRM,+ RDDDDDD2+,_ur4q1O#2$*.Cv~XѣGa-DDDDDDԫW˗3o<^uvsym)n-m!wb2]lK绸tRLp[jU =܃٬ߢ EDDDDD*f6ڵ+]toeʔ)Y1̏Ij&ϝ:\F9/+V<-fgNe88˦,6%gt=N߿?[V"Y RDDDDDDfmҶm[?΢EXd +k3Yy6g&ٍ СD RDDDDDD1aaaߟæMؼy3`?~ ˋp:*T@:uS>)""""""0FÆ iذaq"RWQ"R""""""""RD RDDDDDDDDHAH)H(Q""""""""RT RDDDDDDq%i 7Mt>*&|c|۝FV!e>~ġKR EDDDDDsg)L(jkǀ7$ C욙}37EEQ;݇Ϛ?: r~QQԻ{0p391؟n={ҽDVݗ;?<uFGf,F,Ħ,^ /u(EU"raH1dy?e|ky<Ү ~V7nlc ^ =B y %7 sFq(jG5He<6[=ZLĜiUV]G08=FQVMDFG}6w"yloۗ9_m xw+E&As lǒ蜅Lyn(Ck-q w/ՁiE?j9+? UFm2nY:\ ͧQJ)""""""%QQ֬1S{=lEڴ;ے \]!ubϫF.;wZPۙ_ ]HtXXp q*T?{"%3[WZü&[QPޛ9 ^:Ol ˍY~k>_&1&[MֳjP/&1+_h=M!@(s'۶?;tv4.ӯ2x|=h ]Z ʒ߶il_3(%fK+ظm;k1#{'bӶ-|6:{yWR)H)\9)JIb#4| 6mw:gNQ|'Ybs<7ռLy 79q;؄ RR1Lxz7Ge<׿2 &'hfĴ1𱡼y9y{id7n(edm% #n ~iȣb3a}{P!q<&;C8rt"(nv<uHr.d37ONRLOk+=a1Co_t{!ujJy5/ً@8y<~bOznNܰH\ 2Ƒ0  ;*g)|+*RoZDDDDDZer#?aGo )g3o{(g{=/Jq8!™edBPWD lOݕGB~0کq#yߨzF_&c14'c³Mt&%yw{qVrP2&~L1{cuIJhP~c&SǗ#fwCr5&Bgx[FJ { vtWg1glglX-kXnVfv39 8lViq3|̘}&h1A\\/ʗIdx{]fssyLa"1t8r;NDDk ..PnK|vyzz*~{̧#F`_$6Ksی4R ɻS;Zo[9~jj=JRaXg"&Ks RR syRR"" 8E~^z]غu˙}Arrֆ_9Q#Hg'.M0}ܓ2[Xʰ[#hsM[R(]-\c~m1C ?ԅ ӆҲkޠq Z.YcϞvOāҍio"{b2R;-iđzj.2t`{#(K7~zU ?jZS׾(Uf1y`&ei&5i]οK;?]H$$$sN6mZܥ\qW&** WZ:u`>jƍJ]\"%3%:o~)EQR ("""""""r%iXBhZwR")""""""""%"R""""""""RD RDDDDDDJ`c7sy+rP,0_g<|0j0`"fpoT]OZOKu~h >F&QԎAf8z&J`3iՋ@#ݞ71 FS""""""R)lĶeOٴ{ܴQLa[c#K0ߏ6e`V#MXCp+pMi?vV+,Zǯ7I hζot6̣mlڲ޽w2feQș]94f*Y1ns#|=KAHF6p_̀/ sI8Ln7R)w /{$5'|f3f;7sͰS䞷l~0$ntЁWWҗ6]5S\lc{!L(jG5Qsؘ_W EDDDDD$5ٹ8p&;с3+pd8>>n|C?2V<վvod٢^?2mʻ_x&믈&sk3yjxdq{i5 #S)66,|G:毫KR Yǩ}<~kݡymeƻB#O4Uzhvs݋xp"R""""""R9bzXOfUϒ_Q=k炗/ͥkF2kn )g0A `W>&{vNgv p|EHS\鱜S-e7xz~K ݜra=d8 P" Ir劻bQ|y<==bW|y<<<ݝwW,;ڋŕkBcp}"-/t{WxfV| @6КV̬Wn#&șذsWz/o >~-5Fxa: LV/|#namƌ9kLfk\W8ĤqzԣwRۜ68bY2r(?1)*f;o_r"QrdO*]Ex,{.W([lqQ,OÃ뮻˸jw "r3{f=|d#i@{&~%Ǫq{SƮ]WGG,_=ޕ3M02bV-^pw?79<$(251a6[$2#3;tr:#ekui DrnkH#:5~"&bY;c2o|Cyn+t/B˄fW ;ᷔTo9DdoI[9Axow |춿wd;fu/_JR/w_9#]rr<'5[Ӿ9??̀|.vR4KSCLw' R|k0GS msJ'I?'~GxքZڦ%fܸW@5jM]~ D]>0nwOq1]psfxX&̱XM&ՙf5,nf70Öm5{x\7njáhX+%s*!-Y#trҭEorCDDDDD.oo|6g6[X0oMo5>t; S3Ǖ2]R4+ +kur&gkN0gqf9=Sr]`Ę?(5wf$D0Qr-1R);vA+8bn^m4;8ݍNZ6kwp}Z"rURr-D.f}, v=hYVv2w_u4_|u77<\y*W:H]霧hLexr>ekn 6y\lDA{J"}# 7"]BNZ6y@*"""")a6@tjFuᣧh Q̛Sge)OD.?,GH)H)")""""""""E EDDDDDDDHp5L7 EDDDDDDD5ybirev;v`~Jȿ ZLdtmnGQؖoen'|;#WɢE[_Drj۱3??^O#BA5At(A~e2 9Le[\"ṋ}t#UD.uSg:wL(J2并X/.]}Ʊpsݗ^Bd"vHpDק3}bM}Kr?[D.;#1L;Ob&&5^o5=/Ff~ v:]'2 yi;3+͋ƷeG]cu4kIV_ML$1>Aքͫ`\V<4e3ߦ)]O1L>ӧ0M֢ qǒ<ڮvmcCdˉu+I93&Na޻#tP=^y=f0lAs.=fxΥsXBX>^jpE2q&og&;Be?+f[ ZueLɫ1H:1aށLyO@<,b;rˀ8C];ӥ5lڙ:ȅ(AyM;R:oſ6)6HٱlX2 khkX3z#=q6:';s_t~uqozHD֌ [3im~exjd#v)^8=r*&gmJƍ[Z}K߾}0( (b~_dvvMy^^_G7t 0{Lp\B<ȫs+u3/6 &[,^€1~a0Lzۜ`m| c3~Hͼ& ΋\k:g؛{]?gW!(JNڄNxݚl[V( waa.*{TAnV妺p30)WN*k;m5;IO7HIXڗ7D]Qt=؛ 0Rg{Z\Hggs1vOɇ䏼 oŗ*徔,;l==@qW""e3_ `fEn ˧D1wg~07t.ͬ!֏yتGg<{XÚ+p~:#|2&f`xEz]%^==4#e+)I5dS] ;7|}mz +u2Ҕȥu^dm, X:n|;# ҖɧMy{Ar vгѰ[}~d)ٗtoG8mMtTiJUn-`ȍ bEi9|w吚d-;-`aKn~>fw=)sX? W.,E;*)9;о}?ɉaً-y}/F6`FLN| {cA.dѼoOI k[MX}B)[ 5nZ[cHwKAw~l;#läϱ">IL@F9 r3߯fjK˝諏YUM + Xvo^'9HD?&2ԭ p]w:awc˱hZ捯~VϟFqðF6Lfu5$t+lc ygwwGCR3""(ߜt_EҺOSOoq9̉Z)d8q\\NrO},Fe?DZ(ۦ>}c^M 9C)#kKMi1|\ ۼ9΄m#63f +ͭ4΄w>cܸd ,KNW?KʡoߋǞw\QHe<ݟN],9eI+-կMǶZ&F`9MC9l2=VJ5ןIŴ| ^vɷq~fm}fȐ! ?':ԃ+xɾ?wi}WM.aho6qhl^ۖH؞̒c9+m*RDDDDDDD.|r$iu^%xׄ.CDDDDDD) Wqq8=[ B݋LiyT-gBki: |e#""""""RLt_C{$#9\ůL\Ǥ]8%#>uֳx| ]:8 j5m@YOӿ<)Wrk 'qZŲgpb *1EOp+Mڏy{ Jçj;8n}<֮Mxxa3A1V|w>^7g+9O+p^bh8m 9'#c]Đt~+FU!}wo7RUi͒컜^KսˤeIRRV+|ebSLAu.jұC5AL铏(sM:` %U3[<|+2%GSB&K6wf)DJɚ4F}7뫊n4[㴨#:@Ǭ -ӴE3Wai!4*B[iwM_WXъ-5_e=0/M%}"X+3 &{${(y2a%$}Κt?FJ)5=n 5#^)zW#WݭW'+^v26]05џ_գ~C}f=kU}}lnFq ]nK=OYGSԜo+;ofued{}IϟK{R͜@ђ}rZ0yR}z(>/y7v4-^]w. 8n}{t[X""H*:H,!#͓.Mn:k?{LWNZp%[6=:+uM'ͥ5t.UI5<{_r ?_n}L ^gL}1'\Ic >`ߪg>^l GJ5vJ5|O;-}0y2^T_@W)Br|n>ZcNHӧeM~1TtwώT֚R:p{ M烞!'ils*1X`/>L]x~sJ_~vz[:7Sv{z+G k=ez raTISb u7책y3bUKc&)Y;C׍9ڥ}ne@<{}\Jw=YWz*yzej/k'btR)ZlG{5N)v5έy':1dMns/F̭;)h9T}[=JAyJ$߱cb@FV;pBI>H٤BqIQG^K|iHEإf epSX.u홤{=9#&kR ė^O E]6ȇ(b@׵)4vc5,_ :t)"H(A @R DP  @bτNU3sVK吏=5|bzŠ] tИ]Jp 1إ u12.Suz'] RXO̚%;~lGT(Є apЁ1 RA \4*.AZ"FtDa E`:ָ^b~@EGJ Б`WP-Nk޼e]xѣ5gbZ3|o$/I$ Ht a)sb99eY=S֭[;TRUݵ6[o-z~SEi?כ;~]iM\iZloCMy*x4͌j2׶ӕ!8m t+Ϫ5R#?]k }ABszКڴ#%Կn^v.W^xJkTSks0JAV{i^6}wж]6AsĠV,7o^NjamԳwOEq,)qɔdTݳF:%kO&[3=+֭iFC'KSM[g쵛*:V-9[:U{Q]f[ou :*Nixx @{a [|}GJYYzꭷzK_v Vɩ!Ӡ 0!Sfmlj3K?ib;}/4=-w#u*t.w._IݷИ oИ ?lO#Ư` [|}"I[n>x}?4wΜfۯ[hh=tX=s, XAJZ[m]*h[ھcMv=zv0@x:~ dmy4>^VdAǪ3A h=mzמ. , D^E$W EzUR@AzW^V[* b)xw.t)'z+}{z75wb)Kzֈ-,v) H`=6N^ @)"H(PR4A @GAP %]@G04|̜URZEԳ^RjcB8㯔);AAj,v)z3\<~>#mmT:3[nR/9eKvm7'ڨX?u1d!gztV,~3s6_e Yƙ-)&ι60lNbUIUW^!IʫV~pjtqf_kwlg\()E5׬& ̖!H$%-7ݤŵ23ꖛnZnuCNUuJRN=U0'Σuح*[RJ{j3ČH\sqf4jy4xІK@4U~?]uF #wK56*Ǽ̼ӣ1}NKӧGZ8)4egK ÎqQߍ׬$4h)5|r>^MZ{~Ow;.U/L_:D=G&Xo`}u' ms.pͭ:Ӵ]huy USũ_A4xǣӂxK CW 딟=um^8kahZ{Oq_Q2@:sT:q"X*?h@ik\9{&*iJ`|| ~& ny~{ ,xT}l8Z|SN;ӥ[(Z<]ostCghҵbE>P"lcôӨv=$:v8e|)H𭕮]2hCh~ y|?uїG֭)5ur~sy%zu7ꁏ m :ן6hhqf "C@A(QSþq챿ޚ1%Ols_GT$>IGa] Ҡ/w\5 ꞔ$u?T#Ki{>܅: veםMgwnEzlsN;,uqgG~?;]Ӧ9mu~CT2wtK\ҵ8Etz쬷Oɍ5uIkZ@W %U VMZ$YFq~yF :Tc6sͽy*ke.oN/17k?ܤV>7Li~:d˾Cq=^r|0uOJN8w{|_5eSKBIho[S65j:AAXNs}Nl(yKoz7Nemaӟgb Ӻp- nqʹPGiFnJ:IrY鸷uԋuE[XusεJegӅ#?$Śs= v\I Wuo9Q/gϪІ uy4,S}?[& Ik蔛~Ӻrԥ_>oT!x[@9|*Muo/$p#ޟkK~k,U<%]q57 w~t\ᜲ?[Fg ړy6Ӹ&B6S^޴VFw7͕M{_{\pFoMsJVffsӨ \R#7(j<՞IJ݆}wgZ-T;a=Zzz$ 5U_5S9Mhڽi#6|uפ}QjM)pIp~skBWPR< 1d*r]xn{vjc7]bfžQwwהz/_?YMiGma8#eJ9gUiRYyIJ/RvOoU*UYm6·?GWċ5?L?颯Xc>\}87Җ$$S'֦UaZ7sa7 yӅZ*9ã?пU_'OXVIVآJUV-տrwϴk*7^qn4`>m|ȰBnGc/]m]oTܒsBmu7QXQ=zh+FP>?1rd9-=Oq?uU_#wk 1jt݇2IRN?ZtJA'ASI2?^Ա' gvvLiD]uOuí/iJ+7?z'c5 yo4sg'.ٯꉇ稶!oX/xRGmS *CSiQS(]~UeI"}GNV_e}vq{~>_OPMLnZ/:NLt"az_S+6f{x^[sr(vǚ`̟ LU9E\n-.貹LC_ ?ĒLiuujeK;5w m5㉚^[?i܅{*WEM3诺;f4~c'Whۓ?̮ ^t^xdcZҹkC6T+[*/!CyKV*s{ם4jݻk׵7-׎'봒tN;j 5+si:e+n۽mXɁ{kFi5 + {jnwFqܥ3äpn;yN#w^HO}WRJ7%k#~ռok{NAtWiש{ȑ{o-A. w=wE,]Ƣ0*F_f;kEj5 UגkuݲqCM~j0m::{tV;s>~P0\Çn=ZeՍGogqر׿J~뀃dc~#TP3\n@əA*RaiXM.Lq6LJ&dd I)J5$ (¤u T{ zzZ&sX`/W_G)לh>tYgmh/rƌ{rd2mn0ԟ{L~X ]]gCbU^u$I*4s{|mƙAч]w) Tս.9yq[k[P>S&E.EaIj-SqdqSƙlQ6*?.쑇skёIx嶭Vr.Vl㞖+j8pK]L Rvb.TvV@b"H(A @R +vt)A @R DP %]SUWW9Nwު 7ܠإ 1yTUh}-v)+kԩ.ЌuNeF\2A ͘3gb)͙=G6e:0em8ZN6=Aji ތ e-u *^GJ}K~|b+#=OCǟћS2hQG]$SĸNt 1omr? ]wzkWowS~NO>?E_;e0w0]x, ̷~G}W _O=-Lr僔%)^u=YR }!sN5L˿nKM:kt(7^T;sY S6hK-:R3 S5Q*rƯhPܵ(5-u֭G Rݿ~{zRᔫiKWq/k_ߩo-Wxsua/GFw2D%+E=VcGJn%z%:fUO)fY8Mxe[ W}k_BX #7SN|K2_ K{ 'D=FL^gpGzӅF:~G EdZeCrݷ9wܭzX;3Ul2ozuonP^6U#t駇lU;]=pzylJ (]{r_{K4t=4[i@b붤LpC.Ol̤ޮgT:douJ5tᄉ1BU ?@*3{"))F[utetVH}53WZu݆Vkƿڑ5!H`uDu fCQKrR E{6A@3*+k˭T.S?PUeUKi)4c7ҤI7N*+Fָ?vТۡ)D H3Л-2)jRKe존[Z9H>|Z$XyzIL&Є2Yɛ7{qEq$s2e'7τZ'>y9;2e}΢8cbؼ9/ $ɨ~הM4eFKMGJcI]6RY¤Y ,]NE\dQ]\riSl.ISkvP5s^'=Smy zuE.R8%/ IDAT YC$KC,Bm4U;Bo\JU5 8,r'ìf8sA l6g鄔R‡AEOs.Q1J$gSdq\G>Y:%0s>zYg|*e>%>̇%Y3!JI2~2]wLֽֽkτ *q-b 2%ʽA`NDf5X>R6ƁO&ȼ)kY_0,aNA,'9YNAtw _缔#Woe|e-kf8\d>q"H 8cS2,d-6I#Z֖Ι̖tIå#vDWSTT̅f.0#yKrY''"9YLA"t &郎op PV:oQ[#sA:Y:,#Q4xt2|E o>v惜8hHɘ"TS[ٌ8jkIvs-Z/e;].ʦ>PC }:(rޅ)H%/-| S{޲ƅfsՕlL>\R:)e/?60"o'͇ ɂdgABg.Cy{ O)s. +Ȣ(K(xo؇Ql$,8Κ|gJ,ŕ+LYt}ZEj5R̗OZPcVzrA,69 Z„ B\6Zd iY˹\҂\5:(4y\s>gfdD}%A""y}μ| {y}yfn㴞ҡV#sHA)t9>9'8ЛD.S>E(Ll`ՙ/I|.ߍpji=-\EjŎe TYʍ">> \ܼ+,rJyK2or rKX rIAw%ґ@dfN Źȼ9oQ$]c"YŖ}3z3QEfnlerVi]f#5&?ݤSlA*YɅΥ뽂 p2z \yʜ)\œs^(pQl0) r2NE[8+HDTfq ,aاS-7*+ֳdIZ6HJGL6PnrfbJl*%aP 0 Y t΅\C"H@ra\ " 9g\rMN a#D3_"(dIdf5( }ܐ}za+Me}٢mT:/F ki=RkLY+ee࣬IRm|VRI$&eRKu؅adIbRr>rL JJ RfXJboAμ/-l²u|$eByYDKC!)]) w̯&5UJeDPېLIG.HA2vAC\(qA+}C.8̇(ɠF06Qy3KB|>?)DIFvn֗leFP6|xvHH⳦0<\&rAһ Q8t.sa s A ]L,L&0i>P>͢\BϚ%//"i EZCҸfJaPA.)A%q¹\\+iD\fH5D02,xB/x[&J!!jAJx;hR5}`Κ+%S+Jro>p| s\Y9kHRC $%t,Q* 2/Jo fT+co QV:@+(Rkv4Yz):BZ3eDJKvr;%[\TsQʹ\\yj"Qgj$Ϛ%eY],Q-`0rȗeblQ* ].D#R[ &VS$ii>'ڞ)C5iIҰ p=Jװhi"I)l>Pi OJ-x+mIoiDUZ+ue"U"6LS$oECPPB6t(M$UIZ E3D2HV S}$)PiP*R4#“EV;GjEj EZe"ܝ"IZ1TeIZ6@VӅ"i"G"5,ӝؒPe#9B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B(EmB!B!ĮMVHp"B!B-K=^H"B!BÁʞ 17dv͞>B!B!%ڷg!Nl!@T&ϙ%B!BWa}x2enTv_HQERUxip6K!B!bʁIfLB자bRIx!8_5KѡCE%PB!B!jm Bf"#ʆPenSv}8jCRdYzM"kHx"B!Bń0̟_dS)Ti?kτ)6"DxʦIf"Vy+!B!T07.8ᙜR@Pe@e)3LuF!ʖFlP"uJI,\I"B!BU `7Blst. SvMHm*,U\7P1%3RbZmOAܲ%9$LB!B!jҸ1vo1c6*t߄J`6N]aJ(NxʆxB'܀R2TF!@E!B!m쐩<8I;nLiܘ Ja7]"PdtpRĶFdSP5KTj%I)˳6 eZsmֶ\mY-LB!B!jhiXW F+V$`1FH[&)tD,Q%)L6*RcC( (߶R:7Q~VZE-)]R[Yw=;liZO,.*9Jyq=K)CoqL2ZX(akr +۲X;^!B!Be|*hC(Ihl[~Tq3Jkh|W+v֎$bژ7R<_) TLqOuRj6ai=zôo+!Wn<A+`Z_XG4*ڄl[ZIZ'+HF kWB!B!IUTlPxTB%,],׏y:`))_ĨH(dzOG Rrf>"J)SVQmZ'F',myZi(s>Fr-O+evm'DByG$g].Srynб y T%ߦ5 d VcY P'5qvZB!B!~W7>WI"{3{PW݅eǏO[ᯡ$[/>#y0mEC!Uo89PRRcYYYr뭬Yr bQU?q͚5ԫ_/QF+[;/7X LA믿iykMy RȒWÆ 9Syc#>gպ8bȠ>\_E |'//y[_s]g5ө* !Ra?\}5ݺu-?/2'==w?*#TRRœ9sxWؿUKD<]ƺ5˿_x sL>{wzgy3?2Zޟ\C˖-l3ҥ >%EÜqix'6mӦMaHOOg7c\x .\֚:pԫW|)*_<x{x,Y^`XfZpɏ?Te9@oƎ_|Aaa!5.[n[;==Z_w!{Ɩ5o?JYY).]O<O܊-xK^^ 23w k^nVzY:;Z7W^\{u3oMॗ_"՚>ljoIځ(m$ʜ\E[3 Ol˯M(XyιeƐp]G!.wɥV|83q'qds6%EEd5j- E)Ï<=w|@S{qUōt|۹g`6mJQa>oMx:)ɸ_|1_|:=ܬgf\}M7oN9ܩW,=;뷊roضM4!tw`уPYY)V*urܥ hGue%m|4>a8C{b(o xuB=m[ħ ꫮw>˩8^~bUu;x00-[/H,٩L=8Þ}>UW\{x;Uw^^.u93y套ݻ7igǃF@6Pt܉K/]*΋Fcb_ E$ DcLϽ>j4̫HVb1ئU !k(zG|U|WgJ@cܱ##??'Ofףдi*qzN>; XM<w_8vShϏ`]n.} ?LSN>o>W\K/Œ3(((wb)C({\z)-x:Φ YdZ.?~|G[,nV *F[Luf׿˫}V,]cy_?7y\c[\̛_4m׏?Ï8￟Bײdj`*wn!{ζmڴaŲEow? s^G!a#FCA:rt^?Ν;x|˖.-;vw}1ѡC{Ƽ9￟Fժs RsO>Sنy[.g  [p@[~s7iq9sv-bﵭ~bn^'n\V.[}LQAksj`9ںd|}n qoER8?f%6-kQε&H9eiMFF:va/ 'Ƿ : Xb9B!jaݺu]v)(1b۬[!mkğ|S]uWQwnN̘1cF(wn_tN{T,Բ|㨀q[+˶eTe^̱hG;CIZ\N!ft]Kwt]|)&h#xm6ύhknϝ74`uki [L$\E PTTDQFĢ1 ٫W`"ԡix]qX!ľ# b6,7&4kъҒ"֭mYhHl n8WSJQ/!))8McR_FĬBaV,[BFzd6ڬիʷUzQ۶\Rr֬ƫbǚd2'Ʋ<]NvԞ@0HCx¹sC4j {r֐մK/$q$%'fyضM-?gJ)7iF8) ˶q]@뤥W< Ϯ~fCg`Yx5)+)jB!~(uմg8~. IDAT~5>~P%6:RѠGO ?*/Z)6\^$q/ꅋy?w&s6fxR1[QFlspnguv9C&Y$''ڜ,^ ZB֭iԨB9B!ht[._MϋEXZ1ưnM6dou9k*>-L\!ksRVZsK.t,tJs\xl\97ӰjŲ-^? u]*BەD{߱AS2kk<ޭkW^;#F×>W+۶MzHKKYfDQ\ŶmBIII8]B!BmWnU jvxWK)EqAZv_S!B!D+Ro]&W!B!b7 E!B!$HB!B!& RB!BW֚ E!B!$HB!B!& RB!B!I!B!Bj E!B!$HB!B!& RB!B!I!B!Bj E!B!$HB!B!^l)B!B!$AB!B!D5I"B!BQM %t,|I]y}˚wpF3$v<ճ|i%5;͛⌞grzϛxo[W;|/䇡8煼 + "B!{H;W⌞gVz ft!]v6X[\ƢFpv^Tjr= n[ڍ-Ty]~GulT-ƒd%䷴OOql9ؾc,R[ΡvIhg`(\?l!B!tv@NnA ||9w^kcQm'4kz~U8S9M`1Q6"Hgx?|H/xoAG^މYM gܘwdz6^r~^?.=#K0v,0W36֑NF-ߤ 7!Po&2zG4νtbo% mprVh_| j?Cpv&=nLS{sE'6u51(V2>.Z6+ϡ#vv^;>CJHb7iپ& "$1Wyu/6f|ؙ dl KyhAQG89nCd&ǻA.ԙ\ЯeQ~!?e>aE)zޕY"J{Gsw:U93z"pԵh>a'"Q+U9>OLU#yW'€זp1bspǧ!z=`S03L_lJ3sU%5{JPƂr˿: w-!B!!:HQCY~DJe/^܉m/^/xѯ faijPeynBZqPrW0>`Mvb<< qhԐ$0=&.Ќ5yAr!t'x׆p@:ș7չ1ݸ?xe2Lc8d"+Yr5fȞ2?Fz<\.ϥv=ѭnlXՕgyݼ8DlE}b_/I!g&e̜M8 Y^Q Ma.&Lc]1!ېuY2tz@ Qx59$zm@RO KVHɬ[Ui]syxdh =u.-s5d874:MWcFWƏ(ߌ^|<COhPv|ͯT֙MHKDsf唜foK5c {N_f.tهK?b'e;ΆyJWޤsPg{[_} $!B!bUcÀmgCr {e,:ZWaH˨GtNqPl:m"8`Clg<2*3{6-Z>xG bNo$,?u'}$wERI~-I h Nѓk} [ts?.fNZs2G|6~o¡fಆnJϫl$&rr̓ g42@Rz]4nIGpr Qr797v(4t7HC]@K:e2ξNpY|OEG_K.߼u[U&x 8 3şhXȃL#rhQp5 u6<6?3{N.nAK̟XwH_Z&) IcMqfΆmə=ua~[tL0CSv(ꊻq 9!D4MHK?-+ڟa7@ZE!B!ZRʧBl:gՍ>&̧}xSNSQ2}T6}K:W9+냟'?sSPRW"6.f5>]@1L M8#s O_?zU|KJHT׭'-$sgr퉳x/2O:]wmʶc7#Ha0%ue$? Bءa! M %к^pnCp] dCo3ݽ7 ~*Y: B;i<{̫w[\+t{yphyy)V 9259+1:?;lcWM^WPHHGYz6ecmu)/d@89gԦ~4OrP7N"EP)!"z9(dFG6P۸x>m$r 9|~!kN}Vt[A<ұ> c"q,]Јb/bULU{P~R„B!jlơ}h+̛._%C 'e3!0&绬8^Ԝ/gI.@RM{Q /4<̵D ؄O/>39NiKj<dnyhM0dtmTTrRP h,6/Y8rC5&Q`qL~sVt>vGsZǍ+P$>s`+uP  9l<)!ͨxE C i웬HTz7?W=;LIѾjԳ~1޸gԣ3#tkdy!Pghz2Ge9ݿsZg|0Yyl1]/|_Ijw&oEˠBq})6~-^-S,k5"u] !B!ľglT;/:=mjYtqT Yḭe[^ܲUl/rh@֡$C.~rLFJL]cIj2<ϫ測|V6c'vMp6+cG\S>;3|nAJII v4>^Zs1O^CY$BIIɞn_BJJ I05g_ ym|OB!BݧV)y#Q|O7v}摞ڣ*"vc}ÒE Yd `H=^ %LB!bwA j ϹEVhp]w¶mZڟIoKm|^9tSB!KA1Ye[kCt_.mFWCm|^i_$B!ľF?5c_"/WOm|^^B!G) {v !B!+A1ȾǻXuB!BSk]/wYn|e6 `T2^j} Mt۲"x[ 5.j,K{]{8=ݒ&/B!B}W R*Ta|IU8AN56l˸ ]|jkSOᔓOxcb{a2cf9wڍ:N֏S!/O>2|?+xx-!)e=tR*ed~>ɠV#B!c/nf_Y~._p|S>]3}u¡]KU J=O!f01V~2;u oWW 7ӳk?*_^8O/ 6qN:)(p+qVL-NN]twq㍻Σ{.sS|_^xаޛ4?gټwCL^RΠCN4M7۵+NI㈕ø)B!B=.6N6oRlYycʘ=|1ҴKi -瑛r{g{k( oy~ȃR(5;D7f۹cR㊙# 懺oЈ@UݸɫyA4F:u'|,lP~_cu\v npl&=8+[0>d>pѹfÛ/;?"fliɕ]3)ih\%g2uqL^ĨroYuN:~#ݝ&ϥ%Mʬ8ZxE^ y#GV;ve㬡8/i]V<.SR2nG%&~4"lumߘq! u.m058cs2?8ɳCx8)x}U{>Ͻ̋2 yb|=P.ȟ+>LiU!y!h9F4{.ON%oT_ߛ y(W5/:z,Ņk)d)V}< G6:ƙJDklk3Łظ tblRx7Rj h>Pvb7*nRu`j>Tk݊ϮP2KgokL4&wpR(:5W{NZ/H i$ner\e٪=>-sRI.QS↧"""""[6H=V@BMbMku !^ |ԥnN*d%,%|! ɜ9t 9p8ȟc}oۓc9t$aE)0No9m "qX bټaJi\PU IDATkmkC6cҾ06 ?ns2p (ٟDO _/DN;ű'܉pM|GpH^>`IJr]Es4Gyi\кcGi^TO2aD=8ORƍjI1LVZ{{$wgAWR.<߿WYzq]O9.$B*lƳޙDZҾT{zXzJ \1lz^ϕ[uE`IIl,$""""čls_m1pN?Aa(:G[-xpJreL[GwcxlrފA_1OO%ժ<9#a8`\U&:7 _ AAAH8M] ̈kIzR9y.#w8Zgr".I̴u%O}3j_*׈mynː37gU3(Y~d|~bE,>8 Q3=j(іfCx2nUrc+ȇxuL}sI7N'yrKy+։_Dיlwsn,6?B [ge 'ٷa5;E)b伳8~In+X9]Sv`%X}ўsӟcں$-ٌggIrE#5x~>}?ɯq$`uj$KZWaΊ8ݸ_и5GDDDD$[e{!*Vr՟h!ۦW_!RKtm @7(XcjvKw|#k"5zy޼ É2YV|tYxx>|nR. ZM4ܯnAK8m]t;][o0;3odg~kp!AZ>L`(?~N ,D1?aE+A,?A it箸Oathp֗r}3jq<&S.ERN3+QwIΝ¨9kXQڼؓ !7.p:.M'AJ 3#Us,B+v=y7E{Px g;=|#j~3t Fxt@?~wp'w{) >ykҹLlאɴͧưS$[)~3>S\=X~\+֞AZ;J2&Ovzmb=~X%ƇX6?jm$l]>vcq>t$ڭ~Vb YBmkNŝmV.Ѩø\FҺhס=M8'Sp|3Ez.Hh笮HќY],=""""""""^R""""""""%)"""""""=7Q""""""""%)""""""""^R""""""""%)""""""""^R""""""""%)""""""""^R""""""""%)""""""""^R""""""""%)"""""""MguD+}ept>O{Q7@C`'pw+;1PusY~01ݥ>kѮYYBH?n5nZBX#zHH dhS\nkܟ[G(Qk?Kzi՞PYP97gV] 1CCyayW\y0З) L<˿s~˕LU Tl.`gkٟ%ͣ( py=yq.pC߁Bn=mpB+%Я 4ש4]:S$ĪVaR~ǵ+K?'GWtO>>z|\v2C `X[ r#'u"喪wĨԃXGi91:s ;;_Oͅ+߽,,eܗ'VCAʭ > 5`<(K \Wj]l/S8 eAHx/qnCз9u݂'P# yAMaOWxiv. ^gz?ؾx tfaB=ebm@]H1{|>c0Y@O=ur{w"r*u׆A(2x{K<G_ux9(2ȴ mL= Bﺰe=L]q0uKeC;8=Ms}ZЖvӜNyۈ<של+W8|H^זŌ?9ddlєtwmgb:<5}e@ռZMN'0q:wSfJ}1xA#uFo?1S),J Rn!F L `|x{Zbv44x^aФBMn5F Laapb-@{pL -gN)SNjmB@|/W=> 3GYuW[ ً9 jYr:fAe  oo"G8M5 -+=@o~Áʱ"3`[i1go֜g0y$*[qH_f8,j7_=Jǔ* k`K0m -Sr0`fSg0`\v YX(o}?r,8d%G#q`֬8K /`oJqXXZ8:.i_fP^88 < UX fL3>>s3>ڳnL}X.N9!g;~4#F38?T=vщd'O.XD:rl#"͞oRz%Pl` {=o5 O692 . S_'{ғ%2Nr-_,iÚ0c6ZBlFw9L90 YzvG'[N 0?yY[̝.OpV$YJYN]+g&; [3!* f GVz&=ˠd$vr9i M3O5π]` <s%㭱yn4!bbdn@<zKV}|A)Y`XAػͯGVމ4-$ymHQI}834wCλ/{z=t e~Nfn@`@`_o>>`dgsM<$k@4> qxSp`K H`Sp. _S8<=ǒ9ț/Jav lYf >4 ɕ?p<5t.HX,Fy"sAZ1۠c@ xg;V㢠tx83Z`TN%l~`}ʋp( y?%;LcߩR(}|TOg2E„sv1Ak9KL3l$: @XT1f/Dwp+ܗ?Kiʟ܅dβ# 4_]!Oy`QjՂs {p:m72|+8<c<kp3\&/Ͷ 8xi(/]N&t1d (_-`X_]10_V&B |yfhfy> w{ʆ`(p0C,wc 1wI$5|9i#E;Y̰&x˳=0t9L[g=x&0jR`il1!ZZ [i~0\ğ͂.l]g%9SY 7Ҙd;s.Jg$~7{$Y}3ŷfo?e|~sZ!OB)H_:ϼ!n8-s( {3{`u*Nۓ`(|.l><]lg]`OF+MD:(<߄Rmf-_*OAu:Ԅ'ѴA}lP!LRڳ؎y'\0S%#G1 vfP63̠b+2!B?!nRBbIxm|LK8̠%X PgJ`1,^ۜS,%+g5\dOLe3oz~2=aP.Y M1M]`8'`R{x]>t-td>re‹CIp, ?3l>igd$^~6n߼5 \kg^y87!_}~w~*u?} Yz4M95qltz@hͬ""""^ 5 }f) N鄙oO{l= SϼФ;gAI{Ykw 7)w&Iq`v0t(h޵gTE:E@f'j<nm9Gg\p}`(hFCyPUsq x}<~xSW=M,̑3ߪqy͝-ctY0ŜC/ ̻J̒s -;f3?)Poq`69fO0\IĜ^̐fMaO*g|1 M> xaHi#|Gڞ}do>QmcixB h\T,xٜZ^09k9i/=믁=o? =Τל* ݏBD)\wGʽ.+գYګ# i4^>ِ";@%|c?`96jc^'*1'z=J/hz3?|M<eSY[>dX4vlLAʭE0c&?d`070tUKƙܑAʿJ0_ A#axXzLa=Rg7_z]ϿLs9;^=' \*f9p)Uax?_#u׺Z`N&C͊y0'˥#7$YŻ炀b$|2= <yfc C[.y;yv'yq %) zÀPrW|_fyfpj4SXf-I炬:d7VbADDD3-gXh5m6y# oq嶜v%Y#Εl9g0|Fؓ#H6WslrN#ɕMv+i;/?^fg7KwOڰ[Y81b'|)~]>T"t.Z1bDr }SWQDDDDn RDDDk֜TybpKC{DDDDDDDD EDDDDDDDK RDDDDDDDD EDDDDDDDK RDDDDDDDDt)pS)""""""""ك/)H/ٳ7gfuDDDDD$ ^󺺎ݨGxIAx))7ABA\J*,K!98{. IDATJ>V|ٗoOY]Kž89k[/~+BUөn 3j8|~eɵL=TLj6)ʎ]O#P:rm(HɖX:,nkS#ۖ2ݻhX; $/֒V}If4*sc*" hhH6/!JAYtƎƼkiK)YKϧcd$ġky|ޫ 1dBȲӰ'cMI ? ~Ѐ;.4@zSؗx[HnMYHɆ}ˊ }Z!(kp?JR [V[O7c8F kN|񽼬c+^͠?(M*ӵFkalJO<%iFAH&)q`r:>.._zm8w/-:?)|;[ ߞ $5 ])iٛ-1{6G8cl]m;ӾCC{DDDDDD c8p5 0u8w#:P IA4J !,,'nC%8^ԨDXX(wٳ=z4EEEqܹbbb8vXVWCո%8N8ոmC c\S619v0 ΞMML łe͉A, 'O&O_"QHKtttVW#SrutmrG& ?jEO1h`_h\qCwዅoN3fFޜ@̘?)e;#uS9ק^7kDy"ٟlN:Xh\&-FM@͊d[vr݄c{L:yC~x6[OSB ^/\}7l:MQIdt\^ȭC=RDDDDDDDD EDDDDDDDK RDDDDDDDD EDDDDDDDK RDDDDDDDD EDDDDDDDK RDDDDDDDDwVW@DDDDDDDn!AH6 EDDDDDDDK RDDDDDDDDd an7իWꪈVݻOgZ;RrP#A0L[ne>ifʔ+'"""" HIU\eϴܯnۍH/)H/)H/)H/)H/)H/)H/e ŝ&}""""""""](H9s~O\xGrԧ >`qKp^ |[8ۖg8+KWM.?DT2y[,8rWE}~ e:2z^O;i1rN3P˗'IzԮYj ܃ 㖔-?ORp04E 8Ϲ$$A@#Mxc/8سImjul dϼd ?uż.- >C>Ӟ*ׄG['x|-`ɘ$9nl*x  x{q\+!wi,[e#2ɜy)Yʆ='H3q&)iŗQ^,>weHsӗqpu8SE+y~;W7Gv?oY[wG4 );M>/BrS{$fߡ-,g*"""""r3rstA'i{&8ާq'o>l6=_ &Gaµ Yp)?tyQ!_wǟ̦Wd;tJX/ٞY4x>O/JpN[%]Ck_JdȆ$vhH ifcIo6-ǽ F{imU3[#&Q\e}€湼vs`wjJϒ4GHvd <0*W}2*`'o|Xo׻*;vEκL]7|0`ժ PB~yi TaR;xykO]`qP)|pƻGOio1Extn͸24.2j6|ueܒKgqjA߷ pPIv EDDDDDDnN@/\s* QL$7+)""""""rӲ Z!=4͑""""""""%)""""""""^R""""""""%)""""""""^Ae EDDDDD䶔ā)YǓ+O`d;cc`*,K^Xy|2f$#4ڙfϛ|~eSR]Mu oCl['^zl z4783E3lV|dmg3j+{Q>,ǖxGR>@򡹴L.UhT9x^nQ RDDDDDD-X;P .$πlݾMO2DdFJ|*\'ظpeʇr|h1o v61w8K|QFAzO[mKg՗ bN~1^ uOW+㵬'l3Ո_]&qg s}?d_WG,7)""""""ٙՎݎY-L9D7Kr8A]×`[LƽRҩ~˖s C|d5O5KBW\4Z6V+6 WmBOۇqD5 8rQNسWً@m^͒_&? kƔZ\ݷ-ϗ❬掏b"+tRr~cDZ@Pn[Y &|'q[rJ%ȞȜFNxnaɲ1o*K_I˯э$A@#Ma/8سIWSmy}3%BX2mގ &Iz|ly4q yh<=ϾsH#MY\82 hB|WC^ğuly^^06MAj6Mor57C}EDDDDDnkVBgbv4ySFQ?޳a5ó#?s.)0#8+>Wm ςs#KoqeAZh$Yq;E >Eiq+rʎ?"""""";ްrǝaMBJ|_~2XKp㿙k]tmBHX. F>H_˦ӁX RavJ{{='P!!I6מ;~mxP3R5Zpķ,r2; MGAHv.$rdG>i:m˸Wٱ;ʸ%]>|0`ժ*@N Skw3_%-OCfnqG]G3Zn/Hyi{{9q:Vr7 _j -$| ?ݏx]UhhxIAxIAd;Q""""""""%)""""""""^R""""""""%)""""""""^AM0ό&}""""""""](H/)H/)Hl"߻מNٻ8Əsfc4v&c'[053#YϜL ebg_/Wu뾮4}:p>#G|]&yyy_EU%TdIUVM6B3gO>њ5k?br\*.I:tП~jժe˖jٲ/~Ǚk͟?_jҳ>{Fͦ/R3f͛p\D_UURRPTHHA[@>JJW/KrN>CСUll^z%խ[W}Ufl7oVǎ˗]zroT)l6-ZH'NÇ%IAAyT~oҥ#d6fY ~fumlY-[h˖- K/m%i׮]С2222ۻw0`0ȥo߮!Ch߾}2zɞ]Q=٬ BmٲV>OG^zرcUv[!mVəK.w 0 E 2iiizJ .z2LN~4hu;]ٳGQQQ߿^~eyyye?vZjK.e>L>S29 SFS;{}5vZG&I=HS,Se65yd=#$={VZRBbbqꫯ(QQ@.i&=:p Ԯ]OyxxxwwkSo5OE>QFZzڴiǏg ך5kTt d7/R `?\m۶URRm^2FRɒ5a|ը.]?m\B}W*V)E V\]beN}E.B5i9-[y:uW_Su>&I/-#(RZJ`)ZjAƍhȐ2cd:)}ViiiڵkTtqiW3_jEݺ VPU~~ڱc,<=]gW" ۹s,*V&؏i?Qo="utRHlVٲ}e9Fۻw$|ʆطoF~.'[Ql%I?r 9"I*Z2:W;+LQժ:EI@NH(BCKr_~9ß|Tb5\+00$ĉN9?l)`DIRHHv|! )m``$ԩSNL)`dLfyzzuљ}w8AAy%I)))N,)`dy{d2uzkp?OLŊ;7f:Z3kܧ ה)H"Innjٍ͑)`0???]pQ#GgL&M,Ǯ'I))ɲX 3R`~~~r8Xҍt'H N/RF'+Tn=7J{م w(ʗ/IrA E ïOrq8ߍ"TR' E FrdIEJ2fp0Xʕ%I?$wIRŊ NvAKMMW_rJBhܿV*OOO8Sv]ff;*U#)vӧO'N\PHH,_h-p;ުVmۦU\ё".GQF0:\6Klg2TtyUP9Kw*ԢE m۶M6}u)7~%Iz N9 x'd2ylVd;5C6lO駳d24~xfbp15kTLL ?DFGRR4~PYV 0@*U2:-\Hw,{TR%={R&n7:RvMOjժz嗍d/R>9s(((H4s\%ohٳgX@HUdI-ZH^^^%ZpK)CMڵ[/VXXѱlE.졇Ҝ9sd6dL}.fӴi駳榹sVZFE ͛kK4n ))I;v`L iӦF"r(XBAAAھ}֑#?Kr@/AAyʕ+)QpOH\vZ~"##pRÆubI,K.#QbiUZUׯW5r< (R  ڵk#5C NӀmNNq8ڶF ͦk,,ƎviСڵkƎKM_=Vk6n\efԩ5jhܸqZj^ pe)KU^]|,YwyGqqq4if~[u>\rssl6:G6|[VRUIRr /'̃"uHfEGG}ZfMM6iOz'SUTBe)),AvRuY>}\NO?y *&&FM4@}+)1͊RTT|rZJ;vЮ]k曎][ 4PզM,XЩ)p)Tbbb#ŢݻwkϞ=:z㕐%%%I… Pxx*Wʕ+\ E =dqWL؝jْŬTZTV-.==M;3y+=]ڹsE )p -RL?e" (R" (R"7:ibTWȦc>NjJY_LQL*hq?׮fxvdK|4mڴnV~xMz],qt4<̒dչO먷{V#±ߪčVWwz_*M5cz d\%FhO*/?8Z ki I4eiq XKI:uJv~"ɑ~A'.z_+\%`C5돭Wt\1U,)WA/_.Y%ۯ0y kQ:iȈafo>td=Fvu}Bm)}¡e׿ȈzmڨmhD⾜ZTdDE=5-s鷱v]qFukR^ #"RT%츾?RL7)Z\xީwY$%PWS_IkhJhb*4볂bΝBn=Crգ/|&啗匶N}VϽ5Tս{[\ϑ]#[aU—/Jӻ xE~&?yk+3>x/wG.H]WIaF F(H5ܦ b:l6O;/j>GW,VzԺbM xBm+\_ %$O~ٹQ=rJk>ޥN_MV}>UnǏt9> SsGI[_oOR5!?y{z!t{.$)B M-fn[ɜr[.=䖑U3 ltnю8~AW:]vzr[r? ixTV L]H\Ϯ[i^zA_%}yXUW~O7B3EC B+f/-3'Ȧ¿}8Хg?VJ~Dgh*MVUV]v] VaEoJ 0ZXɇN(PʙPoG%[=)k+:|3MYMnnd_,VH&~UW-Wg15{ּH!3[?]I>N璭r@?&*ܝ1#ךlе/^/22IjIzJK6mJK=>ʨ+uoI~{s54dmK3D}\9j6z\]=(9t|߭:z!"^S(+HIiq<̜Gu_Pu{?*ְ&4sSՄt*w :m2hK*yߟ3͚wǛUY?Mhg Sg<E)YDE.F ʕk?~Ο?UsC`/R`Sj,ENN1(R%nnʛ7$Kcfܛ C'hT%:͊әoMbdoӠe7:M?P$ȭ(R9tT#"QONWqI%ך:D(2"J[5}3zN"#*J5-#I>-i;4Gi-E?UJ>&nwnN+2)oh _yeFW*%#6߻ajڽ$?ؤ)1=4zMz,߬ۓxڢ-$I&yE9)^Z7^W! ȟO޿5 Ò#{{|oJxG*n1rT J=~&ɡu4m__A7dե}YZ졵վOY%;4;j}B wKj珢5nl9PLVHy]u NoX&ҚP?>T7Tn}3ji:zY*T)=;/#)u]KҎ46 _˗vr"fkذYZnMjѢQ$p(yuN^J}{U=߲AӺfҫo.<P*O;P$>֦Bd:]3պ^:8E,VT٪st7CѰݵ<LUA=gTWڣ?Z :F_Ë*=YG~KLUp_HAp^KLNNX,銊zR~~{ m޼"LO}Kip [JKFPV?͹VԘOHz-כCinA>աj~yIRS^m:eu"-(a_X?Pr~8e~spթrUyFVlB*;$ByyY󕚚D\UPPo;ڵ2 L U@`Uznm2G4V,OK1/P^~ jMC;}n5tW4i::A3[tT_U2Ii3U/\=M)^d/R`2WؤL q(iʘ :p*W'jo9lQGhۍ9jjV~땽d8S֠ǔ*7l}Zl_3ɻT'Mz?Hg]@j7V}UaRҡezgpаϿ8L?= ˳ ",H"`SNf(Rv~C FǸ-`FM*d)cE 0KdtۢH,rxZDD(4-`ZGD(aMF@wܗMbԩw}MIӇV5CUdtf՚5<L wk;R`##w*7ifAbS%?0RjjVm;ϟWաC+''{_={Nn2il !ataPÆ-46+-TpSzZ#I0oI<@A kPdk Rjgí^_O H",H",H",H""F-,H",r7:YJIIXwwwyzz89(R;t%ر__1K (Q+((9L&c/؋ԵkWTRuիXϟ]KH=-!!A:(9M8Q͚53:X#mF={ٳV޽uEcن"-ݫl: ٤%KvZd pl6k.ڵKJNNVRR,)RDEQhh)HլYS^^^YЈ#p8ԹX̫EuWlRfR-|ǀsQ=ŋOb ٳG)));d2ٳ3___կ__>5jRJyV\[*MKKkFz#>;Ν;kرӧO(`l6_^ӗ_~)"IVUTLJP%'ooyySK.\H %&Ҿ};?j͚5Zf$^zzըQ?ȓ#GJ+U$M&R6D5e 6L(SkQ@.p8j*K:~IFԸqk)SInnnx//oPhh:v짤+ڻwvܬuڼy6oެ=jݺ5}t?~\~jMzV>7ÇXbj޼y^9"rYÇ%I%KWӦO^n&[zkjŊiٳյkWM0A4d^a_ Яݻ/P:'(R IMMoӧj*Ou:P D鑛֭QO'kJ?7xCIIIGu<}‚nIԱboW[OV8͚5^C}ԩSp8]$@zd<&^/"/I-ի^HXB۷WRR}L&W3ƮӁ;/_>UTI7oVY}~(@CӰF +W[nzmL^<#â>zG4l0曒`y,-6MUIRJfoX(RmٲE={nSO={Z( xZ˗Wjj=0_/sɫuRmvyxxgF8 IDAT^)~EGG+==]-Zn俬/l6k:wܟuֆ- d\RoժUWXXUnܮ6׷;!v $ *Gf=yEO\Q!Ĩnݺ=z/I*[z2ݻݫ 6aÆFpX#\Ĵi$Imv3tƂSf͚iͺzj!Z}.YԣfsyZt+$ zScU2K-[vt}V 1#\ӧm6U:M qX3{7+gvվ;PF[]vȐxZ"OO?7*.N 7F.`ٲez6ph֬r8;FӧOi/H˧_|QCׅ d2裏sʛ7-Zw}uQ עHrHFU~@޷k;46LoZJԠAavN?ͫM:5g7AUFCI*T=d =juw_oUϞ=v3) !) _m^rQKE }"--Mv풟_J0$;~5{̟5o\=zЌ34ydIREԵ ]Qs\!L&mܸQEJ)>9d2), ؄S9bΝX,\fcYjN\rڵ:w֭[wڱc:t *?oK-Z#)6X@DKNNO=>Uj?WZOݺ TbN$)##é"`/+555Kc;ڇ~TzfzF0ŋo+55=K㓓_tr" .p ͛!Ǯ'Iii)(RHMMUjj:w~DO]KTHAnGr:u;g&-ܪPB:xΟOP"aFqdI)Ƚ(RSFPyz~UeXr p ׺ut{H9y F))ժZҖf{lO?ɁTFpdjx4$J*'p\$_`(RUfpPV*OOO8Sv8Nc+>gdɒFE [ժUSJJR挍{eYUjU|E) m;%M<[i^8C{wONhB۶mӦM_\H8ŷ.$j$\ХK2ϯCױcgaCpx L&m޼F68ڵڶ[yyy]vFHS꧟vJKKɼNÆ &MPE٬(EEE)!!A˗/תUcڵYvmOO/IjՠA5o\mڴQz@n@B )&&F111X,ڽ{٣G*>>^ JIIQRR$_*\xrʪ\<== P=SjRZdCmYDE)YDE,6 vQ)))Y_t|S"$$l,_dΝ$///''s=)"<*Um5Rƞ|HKGS*jXoLڏa%:edoӠeǣ,:Q{5ҳ':%H;㏇斥%4tpr2p/_=ϧȌ<@çފ*o~|M=i˘7I;4{ԻxA,^$9d9MV%LwXLѻh|43c4L)poߥe#Ub,_xRS(R@9j绽5`}}򾦟3}uPE}<MFS4E~z&~WKF夾QuW;.Q$ɪk^LAwi z)gC> /vUGYPU*]f<*hkոN\^&w{_n#T;!.W&XX_Mb=P,Z>FF(2[%^yNmgt=v];\otizj;p6N1Y;g-iI@G|9A϶HUܧkvq-V<~QC=Џlѩ5ccՎPdf%~G1`:6PdD5Б#`E(2: m Ȉ\)ԬtT'I?_#5J޿8et h=CTXR.JO̾*ZK<2qJj䗚PBbKW"5;v 6Ln7S35) 6F/[i}>RD愍Ty#Eg֊] 2[|.?b=g hGbsg֘ΪMZK:}=_ݭj؞kNUm>NE=$sp-zn.'BnovV R~=n]݆jWo5 ZV8i:H䥰6/YwծNT*y# 94 5SnS]ϱIzٗyT+MkFUoq[.j=MlW>ԠsܸD[eaUYueZ]?\T>fBKZpj2ˬ˧DUY.a*h5b'}0[(drgJ? vU,,D7R~I2y#O~Rm^UVi7*[O$/Ӗ,0#\UkWNlvy]>KG鑐 H ExnRd?!$)C?׸?ьT;K z~}N}8|OZ t)%"""""g#}=/B:G"3Pؒ*Ĺ:R ޅl;zn._4ƁxbkH4hP2v׈m e'(6$m@ +9Ͱԡ0Q7q|1 `'˼}L zGR=bsQ{noy1]a#<%.vY;ؚꅸlcہ1RЯhLnn~N(ص#2q޿ؑ~I .#7?vR("""""RكѴ̜'{s L#]ͬ i_xb? ZvGց|U7yΦٽ`VJ{בmbdngcF< !xԊ^[ž<#g7>|mpk kғ[?ۍY9'r3Ŗ\ ӎ+4wh~=*?ĸG݌6eu/eK&obs'i?ؓcg1`7Zaz0Ft.6uT194}d'mfA/JmJF#.p!p_ι|6#W ]bw-RF<gJjjqQKIEs-2myw<0#h(91`2stFw0߁{W0.ITб?Or0z<ʇ=uGl I;FQ'Xv;Msǜ7ػt*GC&4oҘV=nwg") o=w]ヅJfRVfYʧMqHYdsyN?h;ȐY34jsOiYFN2Nf.[#} z1&,+z\t]ORnw`qQ®tU8aPgͽuM?/Y]ݸI_v#OMd勇gל1߁VMмU' #RY&Y+GqЯؙN^y>T;i>Y#pn¼S cՅ!C-{v~Us,[}] iA/;~||0t ۦu /dЫRLF_|:|0FNݞ P+9H)l5f~˷~“c9ohLp rSBXBgGЮ۵ 9+|ycڷk5uRo50H_%*jbt>̺/+d۹Hh՚qlbZpͭmشo2^,FSx'"""""RٜAv??~XJ.KP;$l9N@d$#@^cZ|~=~?jZ?3O?V^r,|Ko/ *W%`lT#*q7Y']_CptO&hv)""""""刉ĩ4%@9^#xO_L%[ 9mʜu"6!x t8#,,0\{H}{.nK I ~سtMrwr &8~0RЯhLnn~N8'rhjHYIdKٴ Yy9'bۯY7*_^/my~"~7912, IDATIyONa8!1HM>|z擕u90|#mۯ̚B.~ks-ɹ;aM{qaYIe|l*¶ӓEM\v0ݧsO}5")""""""eI J1ί2]{.$3X}; \2)qlTnՇZ߀?fxM_v?>W Յ{MacK{\wA-yfчL_Q""N\\wRYؽ{FE RDDDDDDDD,R""""""""bH`AX EDDDDDDD")"""""""")HY ̴To4ټyAWeYP""gc Y]%UsϽfm)wŖo6v|7oȝwdy"""""P""gTjj ˖cEiKAg_[-O~sX􈔭[fڿ7eӚ5Ÿ́ o]i䭷>T+DDDDQ"""g_cl"k=|^UG^/Rfͪoߺ;FA1 ,yDGMb,?ʚ@5;R};KSyXnVA1v*Yt$""""rf)HRz1 =XusK)SP""z'-oY^A)""rR>d yy322K#U<,5#"R1͟U6Qv#K%ܑH*AhWYdA6#""""RHGJAK{&trl6[iio NA,]R~Y{@u@DDDDD EDʍLm̥^i~ؗiܸ%11qEZo[ )ZjVD1 7͛ZOOϠZ%ܕHQ9s<-O[,/^>֎9al߾Ze>>>J%ܕsY,^Z`i@@@iU_XrƌyCB--,""""=)""eemvr.DgѠA3K"Zѯ5ߴ(""""%DAHk`>=}=m۶nEdv(rrOZ]v[l/نDDDD)H)-vXFDDDDDv""""""""兂X EDDDDDDD")""""""""="""eaӦ###0ZK39ۘIrrBBK#AAHEtt-K6mҤIL6sħ~iȑrJ3ҥ EDD nƖj׬;9Vhq{ ["Aʊk=:Qv K{>}!!W-0yt)Ȟ=?Z4%++R;n$88ߴ("g)""""rEts v;\&%a„<}p8T)5Xfy)F|hBCËMO?i׮}ܹoG~=m"rƘ@`~sK~l*W>v$ W/f,955xk]|^FϞs6L II-k2b`ڴ6I{~~~4jԜjEڵ[QoO%%%_mTwo2 Z۷0t#ܖ^.8qʕXjLAY0 ;g~Æ-T֨z1 mΖ7oXǰG͆n;ChPzVDD+ RDDDDJвe+شi޽>fSIJJfʵd'Of޼4o~}8FgRT[`Ҥjh׮U wTmڴCvahٲ))""""%$55W^yrx_5%kl$2U!9yii9'MK;f|9uTW޽\mVƜ9Yr-nK_|ժU7-V8۶F\vՖǍ{;))"""rF8p͛YoРaaj7lO֥NZ Ҵ ^}YY'!8x GѣF|>ӴѪU{K1c"励T';_&+Gtv,Ym*U;Zw&+99Y,X:cǎHY EDDfȷ+4MZ>[o_"›R/99|T~oÃgɒUפfzz DG-Mٲe;))Y{Ŗ=wju+W/655o~|ő kv49؄"kH")i}{>r}Uh*""r(H)Dzi۶#EOLg)| 0,ҷ "kW?\DxÈ@??<""R^l6+Vl)tqڵpZz>>b2 99<`T)RI3p8E2  mio02??0ؿ1hi""坂rfŠ^!++|226ly絡u-տ΋sQ~SMU}6m:Z OIOO+EH#?CLL-K6mqƜ{nK+WA> <[| J/9Ӯ]KcndԨ,[DS"""rli#[]݈T|u[ߊC'00UѮ]N𐙹6Zw~~c""grp4>ؓamG0?wm×pBm/i:~v?i+i?3Ď=` wi:#k65a -w>ys7ZoZZKlٲuOa{Rxtrr64)i!![gdD<DLoSK?Z'$'-08΢do 3Bܪ7YάS߿)k6޽ja<%2‡IIEP^KRR" ֮Nq~N'ETT%Kddji;{ "$ ;-1qqqU,M3HOO#*ڷII{ aسg7+[;))0۷h\."kr8x0ʖtէe; Rd}bNbc,-N^^ѱz)8υl~׮m""R}qsy8P]sEdeeALL)իI\\%k|>HkSw󐔴}@N_1s\ue_;v6;;t*U:1?<LHזs !2ˎMOO/y.Pccs]^βe+ٻw ))q8[;ݻK-٤% pKǼ2v\yyyDG%cst֑?L 1q'nv[=%vKOOCcNENLۋ+Ǝ;"DNdiK)Ff`dksoT^b,?x֏yժ,GD,1/,ږ?%y\*1{w.Š>skSy.&i1zn*W.\b;- ?\.*1oRcPcU1(qVO/`S8r̭Y(k˱<0 }q8DZx*Umktt} ^[#"jXC_[sOv ncYsA?S,xm.qˬ-4-"r b <(Qꅑo*11`׿T=`w0*)J۶!Z? MX@%Ν;IJJ{.Vʴ~kA\ѣm۶J=!2ڨ9\,X~Tڭk#DDDDDDDD<)&^DDDDDDDʆr RDDDDDDDD,R""""""""b~fEDDDDDD(AH EDDDDDDD")"""""""")HHAE RDDDDDDDL(uv""""'ө+ER !!! n75j 00ۨN'u-6DDJޙHqcziJ~v=_,\Y-H)'<<(TR-vv TV[0N'k.6DDJX EDDDDDDD")g+#no݋H9 "13X2fco4wq7|5-FƀJ_"x}D7w{\ۍ^n}+֤5=InUw]yGas; M^3NAJE$ߖy"p@s^)ۢcڦdRghf;F[?Sb$/e%~;2Uo~3 IJIMC%S R*.ɟA ІM1ax~?#z+w.woR{&"""""v?Ρٵl re\9z. UwpC{|2|v̞~wӫY4.潸_5m39D\RRա[;gn!5S].:vF8>z&["0k#7q_utvlOǾϘ/5ZH'ڱhueke)TTpZ^w .AԋK%eEDDDrFX؉ɇ?^0ӗiPl[: _2:M5&_> (TX6B eoqV?uEDDDmbSZc0o`VۇY?`'i[>1#$ꛗx`x繪v"R.i0[E FT ֯YDDDD*&__?SL{q2$p̍\P9xxЭ"rz4""r+q>o[4W+55W>0~[2XWc3682j浌:FN'"g!Ű"""""""")HHAE RDDDDDDDD,R""""""""eY IAE RDD{r_n7WJ /9+x/e))x|poZݸݏ"o2&ZL[zz9'lz [M*8G$g<ޞ]f:^jiޣ0H?1-& 85U?dI/"Rgi7 g#ފaܔ|VɁ?sq1jӨ똶 Gc'wr@ξ%DD,jdV?6\ o]z߾k6HY,oy_az\~$:[Sݝ@Bzl+C&"G;q1n;<)᯵):^PfF+H9ҡ/uE۳y$̔\ xF_ڦS;չj@M/R/73W3er0{֣ҹy41g3{}8~s?H9̼k3{1ko2Mٽn! kCOȩ| n[o[o{[eϷpOY5|g4;&H^Ɖqt~\$O =\“bԨQ0Иj99w\2E3շy>޻ 7S.O |4cn]3.A|57$|輈i{wqЮ [?M*>6~@12wcYA/&>7>ISEvL{݃3SLT0/ܡ<;N7ZuV IDATv/_۳s,`MC,""Epy~Pʑ.,gڳ}zg̥$/ iȆ_psz(.>>z|9#'7,ݳ`ė|&R*iѹlby |ךirp?ۖ "~^^79駅,ݼk3cwAH∼u^̈́{e\.2Oٺb;On֭ݺ@Z|6swXjvKVzDD6H%55< 'esjUTNlؾB ֢H޹߿Y߇'2 FON <5Tj^LسYEM11/NeԩLj3|-nxm:c>pRV={1V&ehX)܍ZqNFRi' }k6# ; ϑyx!< )3^;arڏ>s @B0GѩO6.7$]3E4hDķe׿F@쀻~G_~?Ͱ(tY?aaف0/M-qLiYߞ$=2MsT6yԛtG(U4`_X§UkMG^'<{@ެGd1J`WT>h#=a̷u݄1;/:5L~/v19aΟ {h0|oؘ;zF=?. #6:w"R=֦SSZYkYL"C3tB:iL\Wcᇁ,,#q3\SW/5ay],ӊ->='rUӄ94XΠPpaar 0l|Mu)rIߒy ^/^oό)sXizIѧH La3l: Klu<՟s`'0&;I=ͮ*W jWώgю |& n5)>o )ˋis~EDDN_e: f_ڍs!ߌ}gd8#UXvwƀ@v:~%/scF[1nICtV-eyUxN|Ӗy,s+sůMșM+ٞNN^^bM(xIĉڬ?˛7^{?A}qS䷩k>|ax9_~-ERD4Sb%U)؂iv'|r)DDD4 nL_姸ہY'H*U3+i$zU.7a }{5T{ɈQvnK3T6/n52""T9~^z.&A]4 h9Ü$t{>}So z~"pEхĴGLCfnUwܗ*dJI`-|o)>{@ݼ{2x_mtӱ{S+#B/gnB* 3߽ ՈFYx4_Lw< CKB[0fDEΟh8nmdm$=  `Idd4k^/">?]{R#l۞gs9NtN[9M5~u9Av{#gرl=a3#M=ZM;xð>q(zQys7ZoZZaIorKM8~Er,<<)8:vTd`ɴv;53}-ŗof2s #k3i313L>/5}tY-!Z)Z"f+4H3wcrm]EDDDDDD*()/Hn-b;qySL)4+P%WaEnDDDDDDD)H)3/RDDDDDN!RhjE RDDDDDDDD,R""""""""bQR}Eg)CP2BAE RDDDDDDDD,R""""""""bX EDDDDDDD"gi7PLIi """""""Ytܩ[rBS{DDDDDDDD,*AY RBAE RDDDDDDDD,:0s7̂inܪz\PڝHUWJ=냔kwpn:Y󹪲[)g}3  (WY7Q/~)1g}1͋aFQ0=g%"""""">R045"߲4GDDDDDD*6)a R)""""""򯔃 R( EDDDDDDD 0  Rx-/sco?a׀ib.8M]O?/I@\s\b%fRGXǡ{iTen)9>rdj_ʯz}?&\#~?}7~O%1{W]Y2=1KW#5qmng-Pپ?=0Sxk dvy;y$.o}3 ip7umֽL]ˢ7g^.G'e+=amFχ^dhR2#u xRZMIFVDDDDDDlQgG?."ib[p^᭚a7!g~Oo?_gcX.|<bюl|~#(5zWrC"YW+""""""Rij`rh X.43ҫ?Wv.y*xLI5&)RP?0h CӅ JkR0CꎽbܸlЈC414rvsbo\MloHٺ~dilʵ=Q+*;:ũ=tEDDDDDD*2)a}cj}7oxkjdcV3eFA 7ӺQ_Bs62iGe?$2`/[sa+x=iS8˷>UuZ? K%A#KڦM݄p\~0Gΐ;˹N |g8Q{ͦhEDDDDDbSqԪV `žԉm\QT|s8 RDDDDDDbSP(Xg8ldhjTp R:FStl6~^|hqUХKrb""""""R)HХ͂!%s~Zhqw8CA `Tle?H fHEWV3  Z9v Z~݊H9냔6e݁K->38#(""""""Ytt5)j(]j {uMGiE RDDDDDDDD,R""""""""bX EDDDDDDD@AEn$nADDDDDDD* L<[ B)-Z4/DDDDDDDAJhHHi """""""HAE RDDDDDDD B |H>BF|H "l!`)TneGܜNʦ Ǐ3C}[}z 7lQ~ur>X{>cl B k8u|1N<%|Vc)\;1!MDTC~LGJ=ߩ7/FQIiڇ?O}WηS7MWRXmDJ{_=.i>&3W:>p{gj=}ZNWzA_JAz\Gf7OkfJ[-)wi ! WS'\;0qƯ u?ПG?ڗjGkoћA=tvl+>}To\>xVIggShMw߬~o|6yOʛi^= F"-flH[_oʓYSwݱW|YSyooG>Ӻ]\}PIgСjvo )Mzo}CVh w+0;BH`.ۤK?~}[ޥ˻V7w7>SP'Z3Fn}ryz^_ACƗRXfMlgL-\CHg~%΃?ʦ F9rDȗt>Xޥ_~7ݷުgϜ')۷oVa[o]qȇ+hX52 `l,~Ҿ~ڹkz] }G>X Xγb},RFg jؘ<~ѯQ`mk,jpXXZ<3 `W{l zZY3[)#?u\3)Rx1cg#<fG~gjXi#<+V{#?rɓ>|GǠlzH);5m))M)͂2VfuZ-lmѭhwkwADi4.:t[{+Ĺc~4/b y^xc^ʒ\hUY$7kT{m1yA1+Hs7 f#! DƤnNaޓ=ݛ$\b6W[I^v.y63=]U\tphg}~a">)4>fvV**p='mjj˕[y XƢH1FDev~(C!}`TdϞ,yx7&ɬR웬["eSin9-Dž{Wt[\'kzA9v$u_eOx?z~gޝ;]Ӄ՞&\+ZuLb"[TEsUJ )U[迮<7CSBmQb_ٺ(RByRr[9ɽ =vڼn-\4l\eCY9p@=){\ y27܊R %UcuP(dzѬ,M(C?H@H`[0eOR,WhQ̼VYݳ\4L)MY.X9w~" '=Sg b!gwk<2"UxV M屒TZ єåL*\RqIlE*eu,'gk< JLf&ɾ6yzagk=e3>3:DCIDATx1f;کU%E7EBjK+D ێek,YanyN En )j:z9vͣ[37F9{|w/.)z)B,;!""+ZB{17!t:Y#Ī^OE型 YSϭ)}CeVz0!EDLY3N cS),T*Tb.Ch B.&%KH`)K*hHMt+fU#fE=;Q6Qx|򾔛?gf:bS&k4<-*`^)LBBOZ3EIE[ޭˎݳd'Vl^DY!Ei).r_VLlS_QIi3EYns1EV8f_ ڿ_ݧ,vub?{>HҎnxi~gePs>gj{p$fFiBnL S$i"tO?1(QeFbl5t>,XL[3HW<,=v+:A`- (Kʇ@Pk′htao]#N( 8IENDB`qdirstat-1.4/screenshots/QDirStat-histogram-log-scale.png000066400000000000000000002125631311502036700236200ustar00rootroot00000000000000PNG  IHDRR[;#sBIT|d pHYs+ IDATxwxwfwOI! %ۥ)M ^@DD{!X\Xi bko 49gBOygwvvyYoJTI7""""""":Ǻ 9a"""""""J V}x*.GjU }{$ュ1 T~8QER&WoOObBDDDDDDwewx2}IRerRTTT N:$2H!""""""X\>0]P(*G' P*'%Ivr@.䧬gBDDDDDDTGE7i'IJB\b VJB*p DIR7?e@maxBDDDDDD7Oh~}irJ|I&L9AE%!J*J$>l&@(G2T!""""""J#k ] U*eSfr‰2!JUU(%JU.< CX<(DDDDDDDzJo@rJ^X*N9Baʑ )tHNN=( ʑ$*dBDDDDDDTH˧ Kk)hP*,ZZMB YueʑJ9 (H="PѶG(BJ#iE0B`ȐʀBZr,Q]%M.eh%]h >A SRni|yaettQrC_#(el Qæt* Q ) 32)$\a,iZHKiBڶZBXY"""""""i -Mmʔr--]REzh ˯ >Sa @~=(tðVʡWyFlJOtv60L#)4,ʖfpö Caa1 Kahù6.2vMi) 5Zv "]QN8RZiqG*?C R-$^Yl)P)^/8ʱ)=vMCZVX+eiaiB.+R C{V: 0\ri mx\!GHV֪H!P*ECJ9|.Ɏ@T{l99Rj)TF:(UЮc*-LGJ*%^c8R^XHcg"0u2RڧF@=&""""""cFhA aT WCJ8WEP+ c8*J!\Jj RJUӥ>\)HIOڳ>JPB!ܐJCIRJ20J!--,(r,ᗖRF c`Ǜg7n8,ppt!Ӳ -K(T9r6aBl(7lii2!îJ:!{ZLD:)k)j NBY",mC=W!F0D! "dۈkzDVvjTI>7͞=}xՠ>""ڿ#9NdŜpE1J H9P;wܹsj* ?wW^#$a%Tq]ѳg/h *5M]vŲ!I" 8DDDTΦMpkرC˖-m}lXl9 P~}t FBdd聦͚tcsNx<4o ]v8t=܋N; _ޯmΘ1[nC=XIb"?jƉx'%ѳ'x!8HAfہJDZò:3vAS ADDnF|B|8KguǷo{ߠ! B0P}ö ELl} 6&p]^<`7@B|BvC ! 멉O?,$6[~S\-`y<8,+?<~;>\!,_ y9x}>##]d$|%&&λBZ΃:H""9*'Aaƌx'8HAvVf&7hp~d84l64Py|rLz:3vAʔ,)}%$$K.i2+$g: ;Url 2ѭGOp}Ibb9EGsY"":~{;0n&tR/\YEucݺŹ眃7BXz5ڶi 'Fǎ@^'"#= ^}7#axjgQK.fΚEEEh׮-F|3Zn]i_X={b(Cߏ.ٙx?cٲeXl^<9Y6n)%t[FB |7M}٘cx\-[0WaFD˖~>ſ={kqƸa0tIU[;U[hG{EEzucm+k;338BCjzw}[<mߎn[oŬY0ytvΌkmRQrsswӱr/}@4etn$T|x<uо}rJGD"?/""=¶PC|>""*ŸGQ1ŗ|> k(#"՗C!D(DajH|z*Zow_}Yf#)i^|e$4n翏qǫӦ"B4iIDƍ2EϤIyM1|8kWC+k E=md^~W &,(ħFQQ?! ?&N{/M h.ߨ!̝k]$l߾}6@^nN;LMI i! z- ՙUfqء ދxsn&;CDDGÆ~mY>`>qi}0p(Cbyxg* RxjD<X`:uݻᬳϮ7PTRSSq=qЬY3࣏?{GH8:|e紽e,_7< -Z@.q)GۡG\\ 2tyz"5kV1mɧ& /g,¶mdQج VdTddf/c„GqхbQU^gXbrrrJFtttǕ5dP޽;zA\\\MIIA8F-PP&"ck_>W@nvV2Nض aƬٸk0ƑW/Ν\m޹=_z 'x֯]bo>9䶁i, o.<7 ΌkgM%'omy s/ Q f&|~RR**ڰv@mUHMIelj5R^ > B~0ߴܫtr}&i ÇǂO>EÆO<敩xpw!'; J-l~C(cf(;s>?&>,>3deeWyu1罹HZ׭/~@? z*~y1F[lֱULX(P&"cgcǶM>qbemdg"u6=scY@VCnƠGؼq=l;m[7Mָ{? >A.1ݹxgƌ:5v3A_8Pyk[Xzs0 a.**,k4 X1b!k#(Y#?:t}ڤ?K_VSRӰ}&Cb_h~70y23vnoժ 9ʝ{mҟ*_elFnvRvnS\?5Ȳ~z\}ՐZaBk]Y<}HOG \{5{?:`%:iӦ, +W<ඉ813+'VvvV&vnی~,dJ?,mo\׭.-cF1`$ {ZSc:\5x~wIr ) ca돀mU|,];>/barnrdddIqFܹfϙS{֭ƍ1kl/83Mxx'ae  t|HMMŚko`핞Yxmtغu+.]^xm۵+V+W@VVV(Z_}P(mҸ16l؀d8ie˗a5lGزu C7 7ԩ/ -- ˖-߶8Y^AvVf~+`c`0xmrXm[6öm$؎P Sc[KSA|-#)iX;;8C6 WҀ~CAA!t\DDDG9'!ZltHt,\;w4k ONN9y'ˮ_mn+}QKq뭷"663fDFFpb^hذa?㬳0K/!778SqDG~#n(̘z!j֭ESj‚"""`fvDDDDDDTq"FU@R ʽ>f-1fwR]Bx,  &IDDDDDDuˑ'횯.KDDDDDDDt1H!"""""""&)DDDDDDDD jZ,"""""""bBDDDDDDDTM RA Q51H!"""""""&)DDDDDDDD U"""""""jbBDDDDDDD5>/)DDDDDDDD U2H }/ǥ}LwG\EⲾp;>&Bk0帴XVpx9Y1{H\ַ.O|BDDDDDTǺu0n{f٩8Oot$gk CnVEs\7޹SƜNDDf.xD\ʋ `'Da#w WD=qnHЯm|x@F O \y#i7Bfr.4"pjF+Z{D cmq[ Q"""""ڠN)QpCծ:n{w&轎t+̙>_ 7=ιz(] ={d o`$dA׸z_vks[sĭ3Wxf޿S?y׭AOU_?`pE|8-74Gqp ^{g q%eв _⁛j ypӳ0dqja*&_@;5 _szD$,7-\T%JkzFao͹b}nO\Vٛ'j'8Ϲ]+95D$ڞ ''!T.~yz<s$x 6ފ[~ O0f.xtDlw~Yss;?O.A`лVT݇Lx/ĉX# .!['aEkƢmЍKZ!* "mWh.xֶh}Umjt;'YvXǻ<5<]AE {}*2 "uvSȜmX"7׋ijl YM#>sxR5ϸ=0x|y:=K~6 пC#DT2gIw`]-ؒv5 ZpsHFf:>JS^ŹGzSQ~^y}l;Nu~tfoX?v31zk|F `?-¦~[ A@L\$h'Q*N2{xЎ/1qF=pW܅ x:\ڋPtU|\oĖMRP0-[5F/EG%#L\~JU> S |KWby!Nr~)N?jnpCq5sb 7֜H]p z6hCϒ;~7v(Yٺ5㉻7cgqJߵiAFMzk= "HzK'OcL#YǽT">q'.j"5HG GeHKAA^O|Mqѽ0O|NǛs *WwQ߃8oy (huG{wGBlI{ _0}v<>E?!aDq@oGy {5JCS#7#'ǢwBHݑBޟoɹAwx{^zm+v)Uy>ߠ!$nwD Ϟ2μ1i;bcxehG~B m@>@] #L2aN&V=D?  #ڷ\WE: ΔyOb{AE0d<ү5LSj){hX7C|q&ZYڶjUa) mjnm!RmǖL(7=Vj{w6S&-'u@~VwɶRYXd,M!ҷ #o[syqZI!%t8~ҋX@ ޝC 8Ty%6 b Ls7O؉ˏB]p8h.U]/;BЈB:Oh{1'|q/@o_XCG_:׃D~5ܜ5yK~4Vꝃ5o46<.wSAn`AoR}Nߧ|8~\2賯"""""":ZER{ڋ}OOH$v3/h R$"험ElhD;n$SfW02AK7lt>dt9xQǬ>/mNNbwEö Mr4|h{ ~h|&\VC^p<ο:7/}2 ?,(t8gn~|x ﹈hk|ヌ])߭?NIH |,|Sd)  |=Wk!OGs0>hg0=c$PeMY?XqBW%:x˂8ip'$>3?;o} >3 b&bXטJ~h:qk]zU ;CtH\/,1|60Lõ SD tC KZr2/BJ7,%!OY6d)]W%uE.nƴ"""""":DiIfmgpUEk,Թ * 2PT `ڦPaVaGauv hqGnu _{6:~e~.DuW -U+Rv=&ܩ C""""""*)DGA3>ֽ """""hϓ%"""""""U"""""""jA %"""""")DDDDDDDD5"""""""jbBDDDDDDDTMmv 33XwjР>Ѽyc""""""N)۶oKτvBZk,y1mߎ͛.QmW u2H)((ŗ{SwIO9 ?i( PPPp{'WC]_e:dffW(uR)!%23:CJQ\BGPJc˦ؼe ^UR$a R'VT %U6Rqcڟ 4ѪM[Jt{?u~\ӚիuWVn54G9v00MǁiPW5)JDDDDD LGm"Qsꩋ.] Q-Qg+RN98#"""""h >(=&"""""N9* _= >|O R݊nNϽ' "=!g{alu-Ο K{-0؛ #gc}UO1#|{RTy!""""ګ)S{*/2A }3Fڇi' uQo pх,]P Lft <=^| J%wѵ폐o,w/x8{ ?pVSB]OŰ[Q.#Sq\_]"""" RFǖ׷;(Z{ N?ϓ(X2}a5߽ #^ v:|:ztӯyo'[0O]a⣇Ģj:8t"jrf;' qxPP"""""":b:d_U8]zu?O[<tEtPّ"o.b}BAsW~<) Isqczlb{pڗϡcTFǹe>~ ^6NoF~eyX?O @#_{?M᯷np7wƓKI^$Cw RJ>29ѯo[?oۋPz s Lck帾R:NZh1{\,#f}ŭ5\/f.Oj }A,rs/SFן" OOw\-<{ĤqS %翃~~9=Y:?ay坸op'DhSJRBJWN'ۊ<ֿz3^ ON*>s,6up];5๧cP];31$d{ yhR<5kBޚ#!bx4~HhǸ~O#5ں'Ad,qcj+w@EX| 4wޅ?W =2%S(<=hb˗/?gDbxiZ:.<O6B۹HMsqޅ_֢C[4[>~kiĄ8(\O΁O`m`ܬxyĩ< ϕxv 4a#_ bVSs,ky0_ ΏǤmPIBDDDDD5D Rt ]/\&wAGa2oKk@qwmO⧌6h08\/҂h9fi[Z%"S66mcLzhăVA<" ]$e OӪtؖ @vsV%u,>5CnW>DԫXoIL''0Rg܆kQgⳉI=nظxb\}#g];:sj=7-- #=xꩇVnȾdW:Q7\>F}'/3;18ģk3Nܬ?wq맡E Ͼ{?Š ;R }1Hl~ 9I0jA^~t!xf?PJ@BYH)xFlP\#|/1+' ۆtDJ& dN2dQJ@t#%7c{B!O\WJZ5/ĕa f}tlM;AfQu `H+bcS&HɏBiKFŹ#Ĺ#G(s <<Z1{DSh!3UHzC\x0(O4UpVT_PY?c p#r~3M vXhtxqp x~\[ͤ9dↂ ĵwO^=* bBLDꊉ*ʄYi ]L MH ,kށwK/!< [hq:|4?[ZexkAQ ;܂=ٻ(ÿM6!B =Q)JiRBUX@JGBAAPD@z>T%!}lHݙ;3wf {É-"WN0bHS xf[]ok(AONruv+?|Q|䮶R]O,؛;(Z)aR>b&sn'1T_f'p,>LFңDr7\3⚒^dtT6gf/2f &Ow:_Kbo[Sc:[|i^.og~G~[;3S!_??<?J׬K)3p!X=%%k"[]ok zݟ9+`:όLaɖ̧O9G jXs?~@LẐ%??;^ )ϋŜ:ΥX'y=.OT&"""""wkםIfo>_Ae(\O~և_ȃi"|xNre)Sc wSeaPFcyxLN+cЧzy*?&kbH $p$\^}23K{;#VYiow+f?ݮ^IY3qG|$nE:M Z4;p∋?"-E#zCF3Vb$/Tϗ3s4܆ѽ8~iwNLo0aY IDAT~gÁa'><[ 0d*^ LqqHnu`Ƨ@m~ o1~:MoD+әs$>Eޙxsщ?Gߧ"sK@/V,-u+3͉=˧-Ƨ~urkXHH!*f25x4h+\2`{ +֥geX#oJ]<5 r Nk xSoz/#cfڗų1;8@R-mg*'Z?&q06@ٟgȜvnكa<wx]g(۲/6D"""""i鼶]ϖT4'c1&ے!lxXqapZ<͞fO 6kl`t1M9䴘3"'cfk׭e0w_>{~DO2}J%l63glj֮->>HdӟRbE]{7{`"Gg/;SܕpNO<z*'""""J,dϙv=qa7]px1ar;6=fwF8V#c]رά{q><=RNn;)WۖټZrƟaݨxe9yV|ڒV=As{EDDDDDDi?HyT~{jW>Sv.[kյ]zȣ&)Q3ߙu w e"""""r=AqC ;. {#zڻa^y'm"ffv5)&u0^/Sڹ#CAv$bW=J8'yp b龟VL&@lYY]GyuS """""zrԮ=P)ۏNUVKZH3S C<,ӺiNww9+ """""""^ EDDDDDDD$HAHZ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM Ht"""""""=gh EDDDDDDD$mH KvDDDDDDDҍZujvR#n> """"""}7czjW!ihIA = RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDgjW*ïJ+gq qR@10 }ZWXjOww‡vd;ÚY?;"?2=ٌ僱ZEàFA׶ABM28`K+\ +ܰu.w/WѣG2n|2{r '1W1g}BL&L&Q6aݵ3|~(^{XI'1a2R37_v}:=;^I~ S'b]o,y}]nĬ{rv""""#}0q±L3Th uLX7&4 FXs7Ǻ}8`0_gCدjdJ<ë`䗰^<>_ր xu{+:AS<8 #F0h^&a |<ΨLXqW?ȝ">a옡-zV)q0/|v'C~@;,w?uoJMBnWW1J^$+lfbXs6t}b" cr$ѣL呓>F}Q.N ̋Y6vsl Q/T&o0c{䯫[YviWA˵/o#D=R"0#D΂/gñȏ_^mJ~_[4:/uP}_ ރ;'48*u0d /SrX$@ aLrmеg+Dwa>hM0b HqoSe8\ڼc1B$c ad7Lƿ*AV5uyg#ަ<3d.&z>xmE`e/G@F2f4>X )ݦOc`LT}s6"?>&MVsYϖ(@@+I/i1jXƎؑppqgtZex ώ.oDM@OL1#L[`Slt 3>}ӽsG\R@"(p u5Lt Uw:^1A0 n̓]! x'^|zF[P>=|`H P#X;}a-\76]>qT_]ϻa$Hh.'0z$ـͮ 8$%;1qf`4=b|X`2io<7@ ׵^ .ƅS0(ǵ32FW/_෩0rg~_)seOc᫹Az>Ht'yI/Λz*5[ϧ1Pa/Lm̌V%ɗ$g~bT .HYR~&xg.9'.~O&L48 7T"YX'+c$t""""r y^1ڳ$}M'?pD}q\2};包%ÈPo4MwͷPmDBa ,_z|מ a@| !@ 0a@'0e1CE K1z$5(1f4@Iw{xܨcȍe'Ab FaLAS9ru[Apٳ9??Qm2V%ZR@0([`ط}1A|0 ji͛_]j}<2` )N,6P//ڣajכCu#`tk.qJѳmK[7O2I$+mbdoY4q-s!*~^yQ/͸@>3UexשPv>Kݞ*O"cv&1kE/7Qi! cstvv(O{f+~pN& =HY\mPgFC&3D& i2CP~j0X1‘ 8^Bc͂;e]y]y@`y*Fq-# WbliWG80͵MOnIn<'1nx>9R.c܂CTR LwV@h)X N.'0!xjI("yuKFf]AJp`ò!Éabջ?iU'/^s`fC}$[ 7DiV`':J֥|>hEƏXTք^f|weHxgVrQ JLfiSX}|=slh9SuGAî0qLiL/*X;YF#/vFr[G荳T:!:2/wnyKRȲڸI p)@| @[/|tq-k sm[¾ |W .:aL~̮zYRyRNĊ`?c08de0z$et ksӤ"sY ſ7V_C/Y0pFG AَPghtT zat6zwAϠ_7.<177@P6>ژ[Pv Pi<M\t:@W 5k_?+7)x`fH웘=i +i9[F(AH:fEDDDDD,2=ހW5aɬzi;qK/y :n}sşŸ{%Z;ֳwyxGIAIAIA~L ȃ" RDDDDDDDDܤ EDDDDDDDM]7N:g]%@/^lWS:AAWIt.)aԷk ?/FpE_{?쓊IA"w"d%s5W,ԩY5tOsIAIAIAIAIAIAIA|L ȃB4 RDDDDDDDDܤ EDDDDDD'g,J9LjKğW;MPl:"wEAHZ fםh;:q7|h(%Cki]ڝ?$xq{xzĠ%l޾ ϟgxQlMLh\ӖqyJQD8~C_h\x'Ԛg9bW6J>̶nr)wL%?w `iV_LxM:UbD4IF bk+mNWh7TL36+6?n\kb.^&h#ӅP۝{t$q&)jC$W#*Y7};IYd53;⅏Wqq=> Y\eˌ>tqMɝGUXm%A37ʰ,\atl!2ߺ)3~9b==Q. >!0yZK|ЍEG2_gLV_|̑DÓ_%2`f Ä%/ȫ$ݥ#*Qg5يDE'ib'jAIGfՖԥ=""""""igM QbO`QԳP &>9)ݠ =/&#?@vT~K7a3hO7+E Mu||<.g/56I ϳvl'Mgs7UsD߅X _CgRFe:>B(oK S$4<{'p-"$w,{*"""""yf.ῲ`Q"NgٱGvdh89i$o?+GpFfŜuޝ%{Qx0n7H"ɝ##V38ˈV ?{Y=G&ߴS53$w -' [|f2c[fF/mC9dcfX)ʖIq.K0Ɯ}[^| 353!Q& f>e(G5Mh-])p,HsE&? S\o%kW-兩3Ϫ2Cر;֙cRVHa'y6 HLi|}ƭ\O5/%0Yp,7L9jsݙ,dU^kJyk>MK`/F~Ш_ LV?ݑ;2"Վ 3"lH RDDDDDD$}2RugsWy{b5o{ IHe%0 k@<4GIA))n\DDDDDDD~KAȣ~ͳ?R24_et3& n,=I[cdPJvd)[.cIˆ\{T 7kO{ϾߵSҳCC)Z6|E:Q#48}3mG퐞4{uNUSuelΫl"~64}w*+y}(7GnJɈós-%-aLx<ûb[/ =ŏ+Nwc6 ;zd&-`wÂ(Yp~Γ0{֯B̋x7N!Jq\dΌiٴyv {2]Ǯ|a|`nctŮe;I\1;wmVVOlI۹)y)HIy߮OK_y:\s{ ="b8`X=(X2{,o8 +OdޅFtFll6c oȺ]ncm&_6mCrE_x߯81퍯o.iWe)O K8m6l6WygaVY_g-+Һ!&MYw0o2O^daC=1ʇHl6b#pha.8L:lD_X؝rNr3onU)KRXƶ/Lrظ x$7w\ddUxmc\8N8cI/['3[}ۄdOA !/;b zYNB:xV#B3$ M0!u.| ?O.YzEDDDDD o9[P#vNOwdp ^bE +=fIRvnzPH YnjbL1vs//F~Ш2[*VQnnv uw7)Hq7)HqI-vڢ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܔ惔t0ό<"|""""""""V(HdTV &];pd 0JTTTjWMP"""""""wmڴidZ(Mxx8Æ '̗pQ"""""""w%66Yf0:4+ߔ9(ũSСڵҥK\S{GAܕ_~ .PJHL/3?3+W?LJ{0yvDDDDDDeӦMܹcǎ]{9sɄbrEѢE)RETRd̘1}' y!?$&hÏ 9v EDDDDD!sa.]oƺu눎vk_{mXxꩧ_>#_|9rիWe6Q/oRy3OӡCΜ9C ")""""""_|˯-RTEJ(Clɚ5Y c,͆n#66ӧOpa?ѣٻw+֭cݺuߟ^z1h O@{xk̙ Rx{gϐJjcFN>NXt)gϞ'%_;}]t!gΜTP?SAR""""""0bƌf#KtЇc2ۛDf^|E $9d/ \'ر#֭#((^VYR"""""":u-Z{nf3HXX{%9k.%&&+RX1?ʕ+4hgwtLz% JG#JEX/zQ"% E"{BMLZ~Xd?9{Ly\:&v9 /ĉ1n$#9[\sN4iž={(V4~:޽_ε" eVL4 NpB``XBy?>?s+~!vw """""fK,uSj] Hɒ'N=Ӿ}{, &Mc5u&דKo" )""""""㏓N:Kr}efЭ[7XbqqqyQ3I@}d9s yqRDDDDDDӷo_l6ݻg׎,M&S&V-3a:EvYGxLG&555F]*Q{L&ڴAnϺ)IOOFTT8-[cd֙|V$~W$""""""effҧORRRW9}ғm/Mfm6M)#s؁mIN30sW$7jVDDDDD=CeϞ=DG`pOcЩS'l6_MfJi̎Kxzֵw5c|PHlڴ1c믏ߥdK./pi}=zgG-J&RB:YoGDDOORDz "F9q)ΰ`0hѢzExyyX"M橧'hѢ2Dr )""""""yjeȑ ^^.aҿ Lbq?|nd6den| sR˼ÃGZW^4k iT+.* .رc(Q5|sNgҥ 6')*=Vu2}. Ŋ$22U/A$ש""""""G=N?-_>;̚5k8~8>gٸL sRB 'iC^hܸ1FՓOll,-[n[}aos{UHΞ=ƍ)P zZ|~%_~l@6\ʸ[T)zE=(\0̙3X6o|m#Fлwo)&THfϾAn#y*/S|yjժŅ X`>f/_\4_]}E۶ի 4fΝ2c RRR ࡇڰsFN`}YFBHpB5j-Zݻ7'b6g׮իݺu`0sLbccٱc߮B_~Y#… UH|K7d۶mQl%ϟp;6Cn5kֵ:twԮ]ng˖-L0Yf@``0?͛wX2f͆xxx~z._Lhh^HQ!EDDDDDͶn݊ljzҊsh߾ܹsҥ ݺuGp~'bccٷoߵ1-Ztnݦx{8?`ޭڵz(_HS!EDDDDDv @ U]>jeŊ_Mf *ĪUlذXΝd 88MҼyG|ŋaޭ:tHɗTHqGPhIϽeZ._@ٲe[?b; IDAT.\`ڴirkZ͛wvxzz|111H~B;v Wu˯Bիƚ5kede]m8Nfi֬w~tqLL):E@7KHH <<ҥ^֭I&9'r #5k6yN4QQ1={6c )""""""n`tڤ5,[6FV bZ(T(f:дi/xy]}%GqRDDDDDD,-- __? K1kԩӄ-:AWCUHJ{ԗ_bt/6mOhhxBo*C\IbҕN+W :ڵ{2EDDDDxvݥR-鿹l>.W$r8>+WظqøٜŜ9Ka.LDDDDDm&|||ݝN|<zW<_HQ2gX6hܸxJJsĺ8+E}qB}͙+RTHJ7Z*ps&o߾m<nDΨ""""""fիWۛ{bܝNIOOQF w#rGTHq3___jԨAzz*vw:fϞ߱Z4j///w#yR6BHЦ6׮]Lr϶mhڴ3s*;v`0nRVqi^H˖-ݝS!EDDDDD$^z$%]fN'\22hӦ Eqw:"wLmv;lٲNI$GBӨZDDDDD䖽TR|Pl6SeYYf>h0gϞ_vwJ"9&RDDDDDDA>>>? iӯ3,_lٻw+E᧟~iRDDDDDDҥK3m4|||Xx:S~)vI`2c "##ݝHR!EDDDDD$[.Ǐh42}_￯&44ӲeKw%k<ݝ &S&fsׄ3l|}(JDDDDԩʕ+ӧ;w7Ktoon65kfbPzuƍG%\"deea%׌3٬B*Ue˖2uh~u>} v niӯ?s yysun@|LJaÆѹsg^umưa)V4:aVxzzKk,aq9sZj1|pWse*S5kdŊL>#Gr!>|(}JiذWƷZ8իarRS(_`v3_ſnѐ~N"7&޽'(\8aDv>H׮9#&&JQDDDDV.l)YNď[ާ6RvOgv.cPvt?=*63XsWc>57>A#:Qpg)S5fL`x05G~Xo3O!1Dr )"c)YU>0vr=?:[,""yݗs3M' (AÞsYuqzzcO'nD=&bQʡI+Ʒ f}6.4 F" -8 +(wLπoi\ )*)(Z0~BWsqV""""rw2R1Ӂex?q>JSǾ$48P_#RI<e[i"(LJbU(=S7O4uȠm{ɯqË@#Xof򨑌_$?*o&Z✾;DDDDDD1ۥ5m~=} 1- {-qʅplbb;W>ȠOs(Ӈ`ܦ,G{ъ~ l8j8)PľY`4/~/|CS56xt0 +^bG71ƠhD~!7Ƽ#fn}b(`xKVH1iii|8|||^[/¬\/==~4~[ 31oL^83^KL7|({< ``R;ﬠaMHg1Hׯ$ndZ!E@ LgCb3*RڟQ^tU6gQLnXɑKU/@ăt!^M<|\9{S %/*ۡ܌ )na'2MDԏ; iԮ݈m6yvڷobXHMMs7煠|"fRRWs'"""""`& ț`t 1uK?(1m_E[8;,2/cZ+Q.E [Z Q [ ħ )cxf,‰T28}LϬ\^y`xozk tҩd7%Փ}S)U)rw|~co_vS*3 1S.3 R`apdwMfÆ 0ZVjn9<=VK8tx``]jGDDDDrsKliU}Z EI6=F(",{9j~߫C[So-Lq0<Ǹ|1]rN1R02R?aR2d,Cgޡ3ock3nguLY UZe6JJ0j94E6݈.0>uw5>>>|Exzz:'|}}yݗ)[)H^abڱXlج6,Y,II@Ɉ͉[{w69}*>{pq o\c:ɡ(0Yj'nsűnSr옒R .J,\2GiL' zS|NU#DJ1JiNo?DJT _}SL&;?4ЪU' r*eڥ[itYfeԫ>-""""yCĥk]w6ЄQk>I[zƌzu/ԦLyfeK|R`Nj>CT*;jIƒgџ"s coA`kGҳW$#)\-l3[']qG-L:@ ȡKr2 c`iwjQH3`^b|@tϿ~\KbvD_9r2{q̤NjѦ{DB23-8n{R;_|~n'ٳ7ΩSgF<胗lǍ&vΝDo"{nEPPU0vaw~;^ +RS+WNhhG)Ugaz\#V1c&s?`Ԩ1*tNpp !NOp gώ:%JDDDDD=*J>:gk1wZL&m9s&ҵkw'M |*Ma?Ν;Gnk.W^&r:,Y3' r|o'99%b߶mK ""EDDm4 зo?d&LZn '"j`0p} q8֭8u))s?KFeՈclI>or;/o)ȯ|6YJǃKmv,검BBܓ (_ e0yZ,60x2fi<44l*"""*+6Mbu' t-SϸS?}V 0*EOРl\Z9_庑C{dFڑe7LZy6`0uD?+~=]W©yБJ.bC`B7ˏ,}+\uwrTHqڼ2 WZE+lܸY9Fhhl6|\y/RӬY#m' xaӹ,c"՞/OE!'Ϛ6s>4;SmmFPM 卌xH{%_GfƾЏwf#xb!nTQ3P+"G7%% p9(CQ$b*?adh)H|5S~SMVsq:w0~bӦL1~OԬY>|ʕ+8""" ܘƀ2Ig}{6A4чfsr?*yb0zyJ*;Ȼ;Z%znj/kޓbw!|1R_ZYߔEHiʆF]yvt=GpƄWPq=SX{ݏs5^fԐFeQx@ hK,'4b KbV8tǠR=LТBۨ٬`0PN[!6'o>r$f|||SSSٳϑ|EDD$rwKEgY17j>>En b0wg2'~]NJSd7ey&:۽FB_xÒ|81^_t|IEIeU|MҞ);LE+rq]\7E}p6΂uO>yz8Cv`œSڦcM`;}m(βzT_˼߃4h/~E3oxcK)RDD$33%a<1͚D27$>c2ΏH" p:@ro/22-h< 0x_ʌ1H3۱S -0zd#=-el0am4~CV&oi^ xN<ł% !ĭoIȌxqaC}ΆfptRu~EӣXSc&RDD`0P:oٲ''_f̜afOfføjU7EDD$vd.LZNgt2;|A55|Ǿ_ x<ʓI!> @|I#,63))Fߜ՚WX~Ǝ",kP9`ʴv׿ѩf!nar[Z Q>  ħ9;Tfʢl#+ӉMHA{ )nf"]IԮݘڵ9]KӮ]O$̉EDD$H37^\LӯV6`;Suja$B[^-řu)``)NT[Q/OHR<(Z*NCcyj ̠yiX*g֏sSdp\m`J:(",{9j~߫[Sop,q,|56=:o˹I%6%;^4/̛ 9,~B>MY>_OՋ᱊$63FΞ0v{iE1;^kIC`Ӷ<\e֏ՋB>۶m %NjU#::"󈈈H޶̈́Bܝ ~_7b+L:m)W-:]prwv`ٲ|G.LDDDD\i*]v;S!%^Dcx}Os1򷢉RuxT"" Nhh 4wx1_~0&""""w+/VH5O?G;4t)*=H[{zTNZD ՎG+*^DWEDDDDDDI#xT( WR-}SDDDDDDD#3sE.E_TxU\I YfӸ/>Gbe셜;+MM\&N9g›?JCۭ(""#" x>0Ϝ9-Z4n"Yxj5rzOEpaf""۴GDD$RS0opxz:_*$*33gW0nXxw_"rGX˅S͊723 wrC*e[N͊jh4c;櫯vIhҥ )RR9(]2Izdw, ߞ55jH%__}\IFBNONݿtj'WyTT"Ɋѣ'DDDW8~8k׮};\B+88g*m0 cr&Ujqq!C+2Q!!7^l OII|4isپ}Bfc19rEDa.r;xhtㄅ\J[bq~JOTV C2`yݜHݴMѐ>6 6d̕|\:i]W"" @xx E:{xxdk|JRR2Ǐbǎo޼?#4 y+g0f $44a<))%B*0@VaLDq]{RRÆ c„ |GopE<_HPao)g/T }Ey1O\|ي/2k2eb w:ɔI6(PuK9t )OOOJ,GѢ%ڄD233;v,}4 Fq.ôio(XKF3T7jnɳEUbL< PK qw""r&00po=##իt C<=Ƚj̙\xҥ+R|U ÆM`Ǝbҥ4lؐqQNw+m*b&3=ttW )""""o!o4lrn'><vzMٲ޶:"++۷i&N:Źs爋#..t \rT\x￟ cv{k #-Ztzz|߿G}o]uR\̞qYCi|0V""""#V~8W$8wyN:ζm{322hѢ!]8n,Ǯ];w1F第, \Y;u?3k֬aÆ 9h޼y?>V]tcǎDF׺uطoԯ#2i̝K~p+qR\Bܒ^-4KγsL6ybDpfVDDDh4RV}rdZTRa|-$&^tqVf\oA""ҥ+޽3v5kw߱dl'z V/%(I!½=60dXmdX\βr05&9ffl߾z 0d֭ pm5JV]w gO2j3S$R!ŕi߰ž`7tuOSj<_֟4?7)""""r7 *(%Ks?>9r$ H`j/W =(_O*W-6쬿4Ocڵ,YǏd<=hժMlI2d# ).ebj0ZȲѨm=""rr%,x``~~.HD$;x ֭=hD_m4p?a#?MH"|wv5jMa4^fHMMf„Q 8ŋSvl)J*!ՇS8@-] Z5,sVplkի{7n:NSH$~h6gxkbb""'|NB'o q?lΒī}VOJJ ?#=j߾/&2d~i֮]KXحbDR\ʃCp5 l>놩?KqllWƏ=0App0{0ΤI_g+Ifnxy9>dʤ_ǩ_l#"֭vh0+ϖ(#+PYJR5kRV-FMjj*_%z~Cvs.{9Lr.RN G|KM UၲЁ=""_ Fʔ}Ur?CiР֭9rdnH\\ 4t6ԩsԯimtfꖿf~vk׮S*a Q.qלb&zπZ|mɫ~K/uf,XIY?B]nb{Aȋh\oZ=Tl6v/k- A{V%ǫnjԨB16Ƚ$==If5>>^|ћ03Yd O?4 k,h۶-K.ɓDDVxB"y꩗y7hҤ R7RrmPܛ^YiRbEDD&f > r wrEV}iSa<+ļy˙0ls3gѨrw0\t}_qz0D!e F@*WOm(ڑmϜ-;r|ѣyWHn3 B"m6;8oFOTm=fLMSS9q+l ի۷L1(" ?zу0 @Ӧ~nq˗Yp!ݺu"IW0Ql6j?|]R\;KxOT&OZj3 Sz;#))8YVm˅ oZxn\6, GDvr3Ӈ 2a.-$[l̋Og̘1@6=5vff:2 p)iܸqvu*pHJr]3 _ӝ nի1ϟ'p^0Nbb<-[vt:޽"+++WܝFK (DttqÇdJzCeϞ=]윸2v4iB>|8f5]LL<…X|6W4111ߟ'x K*!$$%o&.]^!fL&?4%KV99s%1 ` UN?ųF˕+8p`'[8ކeСYv3rqDӣG;<=?2xx ttB|zڴicƌh`DB{ ng&cc=ok,΁;7o26~ivݺu8p [v}&UDDD$HJBTTMu9Mii)(Q9ǟj=rlfƌiy+ӬY"h V֭;ƭV;iw4>\maNOIIIjЯxsXwg~N|eҴiSONbb"ŊJoi %u2d:uTZ57_HQ!EDDD$0 DGw] gᆪ6IBHD" 4H }EQU)( &($$$2L x_ke-}39sg#5k/}U%~jjUm=10V.Qb嗭xxw())?2kΜ9lݺ> X*5:u㸸8 Ù[v["vRzz˖oqx <{w&r%Bgi """"Rdeet9קЉ`/__BGXdqX.WpC{] N_v;ockY wؑ|뮻Xv-[n% ֭;ށ{Xx6? VkueȑooD.+$H8v,9sTȼiٳut:뉋w)˔K`ɒ%۷Z u=1vz4etOO-p8Xh۶?xǎ1bZ`0e&OLBBO>$͛7|OH"S"""""r摛[hgz̘1\*T?QnuW CA.뭎O;ogYr&Cr!/^dS^gfŊXxGח~1l0jԨfcѢE]̺?7EAEb'9 'ӧ8ts c l7LTTz\Oy^ħvO>+]}8BLvvv}%g͚5xhV:Q&d`w:ۉ⩧pp ')aŊUTÇӿ8q.|GH0_&)) X)H Z XXX\*ǏC 8NM⡇-t~.9G:O͚a `01#dAGff:gNsڂ 懩 ]/| '#F̙3øqӢE FɭފlfϞ= ̞=̈J>fT FmVW_1lذE.)""""͖n'. ^ɥVv p8XrIfeem 5k^*/`V,7ZfBϞ\&1wJdM/IN&Mky89_ʌo`6޽;qqq4i}%X|m5@n r;2%/BA\\fuZeK~-Vkw///6`6U ̎1Yδ0x` BDD999L:>={e49ܟr?B}2X~=^:&R)Hʤw߭unp׮)6l@Jrqv< k׮2wq o߾x{{sayf̘Azz:Lȝx}m/lgΝ4m?7MAUn-tsٞşUIQl@?ΎF:t('G?t:Yn'OfѢEgB^ m/1KSAʶmIAH)ۻw/ΟwR;k8p/Ɠɹ2???RSpeR̚\=Bީ'\\,>n"pB߱DFFr%"FA42F IDATH)h+ȕNAH)`+NE*T(JD.Rv:Hٗ})âʕ+r%"FAH)kܸ1KKylٲ+0 RDDDDDDJY&M`CzxlѠA.G(H)e4mz Y62Q)Np7ވd*rD.2s|]ʕ\:?ЪURD)H)w``Yr66w}Olf3]t)rD.XRW?EFFҲeK[|S\t_"K.DDDv9R]!e>H1b_)nq8aN|&Æ +jDJFAHѩS'jԨ~LzFHp7o^刔2d21fܛFUp/,L`̘1 RHd!}!66ù6fN/rJI)ӺukuV刔2h4kt*(.֌|g5E RDDDDDDʘk8'8FQ%k'vu '0fXjԨQ%\ RDDDDDDʠ r8ӻRKw8yh{2smCvI"2ˋӧʔ^+%xnw 󉊊>ۻhQիW>ˋy񙼿DS}6)>sK,JAHvu1}tF#<=e2K{R~(Č3[ni%r)H)nVf͚urdJB&cw$m+;f~/2fٴiӦ$\:uW_}EPPRr!]k=SsfѢEtСd\!ZhUhԨsm ؔN_ ;L>p{6%>F&MXj͚5쵈\N RDDDDDD |wa=fܹ>)9eˡo|pv`ԨQ,]U^DJ+*˗/I&ɵ1f{2=g, Q:,:ŝyxG2 y65kƊ+x饗)̥]\k˗3o)""""""W1OOO7oNK7\[y[MDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDLp(Hq|'h\ۈ6OqĘgeqdn_Zb:{`E\P""""""Rf92vtQL,wz%{8=R8yQL}ZxɫWܽ|c Z m/H`Մ8ߟqXPM9w1uS|lsiY|OxMlZ2ifbx EDDDDD,rfa؉ nfƕ|9mNA6HױiFZ|ޟzF/ƈqx3̍cbj_&͘Ǚ8y#sf_DOˑywF[pcL%D(H)D@3F`궹f9ޅE^<p5(E7[;vR F#xLW7oN15 e@\rpį|,m}=1դǞOE5$~O9Ǚ&0au oAY744}_`а-ZSuppTrum=Zo攳ۗt?oaZ2cśT3PHB?'aDLȠߤt=S|9ٙK$<<,V/Ha` {lF|^M9I;!x$#x`\$_֚E=ӫ1#+)~q'IMM#=I>G&p[t4"EDDDDDLj'a~-{=}> :S_<;nmNl&Orgpjt\MO`m+=u?KjKM0O w!-(ْ0]s{-= eH? `˜zmHV9{ُ3t/M}\($Aq}(W*Ag5oNFG/68uQ }*{',xmMU0 xDRZ Ƃ#,cҲ/F;y;Q)e-Ȗ7od] *zp"7Z7gCWᣕhf"e9w_要sw=Ļ)l/Id:I̊{/N_̳b&hy:V\V%Rl DR-6RJ~\Lе0yl1GYi}(o ZFnׄ1=gzӬOx-߆c1&4,F_ʅ(3W>>o5mȱ9,'FP-=֝Bh|')L7-"""""rsdùK3LTiٍ^X?=˶ӽ {c4x`Ֆpμ,;iHe*4S&uN-<,&_*F$s(5l-ÉZ׭PoBsR8vdR BFelX?*}.#PC4!_ƄRP)J7w&VH`gΩɑgG9 ,-%O=ں0y2v g>5/Txɮ~g~DEGp33w.͝gsLWN , RDDDDDD{~iPO/\NG6G~%uiTB[=;R p:md/VYi0s{V8l6lV+vÆf3 fSi& ų;9-?xSQ'yFѮW5Nǖ,}SSn1oA| Nζٞji{~gۡ8%8/э '{y#仼,(!9ۆ`'Bx:?'LފnMC1: %Rpdsl~8{i?MC8Nl u g%:SeCY؝fg. ҦK{DDDDDD"h8 {l+q۝~`0`xm$^Urbt=FMct0#o?_uvr&(8Ĭ;3SI/hD-dѨF?8߿ ظ#H7^eCr䎧\qh0Ը//Gw;w@v{]ƞ}?5;M]#"""""""285׬GDDDDDD(tp5K)BAIAy.w|ҮD RDDDDDD$;)k?>&F1ϲ-KOtb_mY/roԧuc޾;͑E ]L ZᩙISiO}]QL}Ŵ7>-;vQ'^[Ȏ G![rhVڍA^uD)""""""e_Un3'.vA<3 Z\;f:qSu24Zpכi6ۢGt~qk8ey/!&~ï6~\ `2:,ylƦ[X zl YE )""""""eKִnCtx.0]Cۛnr{^pK>ՇfUB |z 1ܣ=e7SόWX<Б?f.ᐫ!\Y> ?ޝU偧_(c#hg8hh4Sm$g_7I榉<:~;fOnݸslv3?^-hSz?ƴ ; _qb74QL#: y2)l,HQ\ln]Z9616F-z?r$MlOAJ.bk"~ ݮ#ESg~"~Fhz}!K {&.eö-,~!knjdڮ\]c)f-#Y #4'">Z=N1j.rs)A$FO|&E!(rzlj_xK+ZjEv\7n'Ğ®ů0OAjx8HM#ɬઑF^!8|c>ת)iDUDp?kLLNvIn Oຶ^ӫ= $0\c?0 ë0 b0¹Yы$N~A+%:1zO\e߲U"S""""""RV9l6l6Նfq:(p:lجvv ͆ `vV)A͉5m+ ?8ٱd.ʵN{`9ma˨ݿ3\gng{Wl>_R^ YHX0Zb8a17Zg|Вok?=k ]mߥK{DDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDD+(7)Hq7)Hq)D EDDDDDDDm RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDʄ+aY)""""""""nR""""""""&)""""""""nR""""""""⦲8fDDDDDDD俠)""""""""e7)Hq7 ES͊HYQBAIAIAIAIAIAIAH, EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDM RDDDDDDDlpv3\ZNz˜\CH 4z&cd4 X{HKp]ϫG^8bn2?]V$& :z2+oJn%6!#ddj- 4 IM=F Q#!Q󷤤,];voo\a; )=??ӈXhOpp9<= Ǐ=77GZ#Zhѣ񄆆YhlOK;hb qٞEVV&Wpt:HH8LŊU 110aa.ۓe{jj2fAA.۳2!,,en'))l2:4jX|L&s5=%% OO/-.32ұZ S6DFVrTEFq^|:n#$$eX,OHt吞^t*yO<է ) ,}z5e⥅)p!4|d ׷~o2 rﳳɤ>l߾#GpILbʅNu/OeffKr.m6 g}a5;v//o5uWfB՚OJJTrr%K8~9OfҾcb3M̟7oF#H; iG#ϙiss^\Mlë8xZ,"B3oŠ1ZD{" QxK"kXT<6[Q56(rj~HHtR PX1#G{^L1(pFSgj4y[ݪ14:v{Q5׽P!D}*4f},XXt/Z+U*_~_|8(b*^%u)w}8f 3\EKKڧBZ`br##Kv,-ywXZ΍~_}bcd$ ~_| ~,-W`0⍇ /<<\1,N T5קEx1}>uXZk׫A67Y?)HJ4hЀ_~9 oQ<"W[ngzxG\,#++cGv)nYf ݺu%<)ҥK8qޮGaȿb ^}GuzMwi7]A0ӌ'\AH٠ EDDDDDDDM RDDDDDDDDܤ EDDDDDDDMe?H\"""""""RF EDDDDDDDP""""""""&)""""""""nR""""""""&)""""""""nR""""""""e•p^si ""r ׷p[TT]f͚t1UV //.5!"ߥwī꫹d/(jD.*?*88KW*UT%\W^%\uKkBDKIAW9R~x#FpGi"""""""rPr5qfnUi Hl k`;?>J^bX|LϸKv %;2N}ڵ'Oړuo{V$ mEu}uyD䊥 JTV ӏpxxzMf)Bb_)#q2oFαOs$~OjZ?>[wɾ|H͓HII9Wh=]r%"IAUǓ#2G8sb|_x=uNqi3W4G_sзK:[=LF&"p[߮}6iۮ;7Td|Nj/;p |uEAQC#E(H֠K/##'Y;>۪h[ѳ.ez<f}C7>:Pz}ߞ#==}xݯyYol3~Sib)'Hw1ػncIڝ~TDDDDPf/ 8؏7kiֻ3}0;g2`n.łEj jfjD,""""W! ɬvˌX1ք=Т9پ<<O`T@ءĞoמ|ۙQo_َ"Vr{;& oMBex-ւҗ s}r! 83Y7Lj}x پH1\Ul$,z>3Cm") >"r-9Nc;~"UD,у=EL;Eb.>]΂͵:h(O ,ܙޚ” qJNjY(KΞMRAz0?'.zd)ͼ7Ac˄ly/)|_xϾ;|vt=ճЪ][8/#1-$G<E(Hi?pc.OׯLX?-k~1Gdn46f,1lEvao\?p0ש7lN͈ќ7 xɋ6LCRDʠ+ })Wg6CjgV̦<^D6@ 19n$y0X=ƽŐ*oۅ= #_sGT1vl-q)>OOrϬn>->;{tΏLUgaŒ}Vʇzm#&{s<ǏgO=Z &aMCycA9F>:$C4B Y/=ySv>t^Dbpp\ېr.ZIٱ< MuiE$ѯ|# 'y[<S- )[X>qOLD\EdO9V';YBԥCh4Fu ρA55ק9b\}~ΏQ`` V+s;RWv"!5׎+ EDJd3|131š)sxm wދC8q&T>|3lHvR; //Op9њ>sP!sޢ{}_NbjKх~c?fgS\aЂ>dx4Mf ɛtl!EWF26|]nG53mYJSDpZ9 Xp#om噇Ǚς<|!="Ci~w3~]|u"IehKlLEjvfewx )Rf=%s>; ~| g,ד-]Fzԕ=ʠd?strܞ݁q3s9 n;f}#լ9P'v;]̠m{&+mkʹmaϿb涧QKcxiܾ)OA=߃1ˠ[yC$dp<~݂Y>bAޡU̝C+r$>O-39''fp*Gע~h [&B""%0Ӵ /ÀWP0$fcu5;l$Qoھ8Q?F3~r<5ê㉝,Ǡ>dMT""MɆY8L{K = $ Ѣ4}l+VuO >5no-ɭMgM?K~Z&7H&"ɟ7n`ZΉ]9Z.auMjTu{$, ud(:cfҀ< +_Mgu:<*ЋZCu޲vvfOy6C0jϴ>>zșޅOf?͑ED[H*hI@>G7sbM 4GV@A }  lnb䀯9ׄ>%x"t|rpcyF~,0ߓ pe@T((cw8p8XؾK֥foB=|/#7s#O5< 8ޔs.y+݊'n'mۑ@fɇ`,F2TD.7`=3>|~t5i;wd.@VT ׽Aߧ2~<)昙jw-ӛx.vo[ &Ļ۰ VCֻ/o%Vm?šiO2]("rq929AO᥏F66gEk*f^{!hx7 {%n'c"ȇQϼ*6ӟwma!$ED.>=]UDz%Zwbb{ÕeiP>P*d슪9Z;)Iw9דzF牶6&}'˯UQCNp'8ZU bN}cp}ᬈ%d&Y>ᡃl6uοfZGS=k3L,{3gNǓN=(?0yoΣ,|=SUR S# (d J_eRlm[h \۫"҂Evb" 3STJR:~:kUNcjyknW#_͗~H]Y}:7 hy~?|SwM{gmKAN]Ǐ5~kruE?zߡ@]|rc8ч/ުMka?`Jz+դ]v.פ׷ 7 wyg(.dcyL>RRŐ䒬B[HrY5$1zKiK%K=)]x}j G}Lq̶|2Xg}zU6(𲞹i.ӏ.}*shoo#0b=-^c̚#vxk1cqw̖fg5[n_eάVfbj)W[iiR{gI!K=Kr!ZVZ^^gws8c[=C %]K}ۻ^Ki`|~sa൲KI{Sؼ0Zo+9ԅ0RE9=h.A @?RDg0`)A @?A @?A @?Sn C]v h@? Ň>H.R vS{$/K?J9=Zz䡮0r M;}򃗥4 u)#m\\ӌP郔y]'iOsu^6e0hv ϫRP4Q;V&7^5&H^!0hn)̌ ejNF7 A In.QA-.y~x;;D!R$]8yO\S>pAX_b૟?[tĤM=:kLM66S,櫵=l/u_Ow~P}X k6X<&tX֪lg rnf}:R3KޥƳS9^:e!-zeЇOӋrB.?={~j~zҿJzSӾPTU C_O]/X?|A^UGL¹ B/oԗ*M|Nuqdq}ZzY:.ٚkY eّR[~:_^sY@].]~]*&)-cם9I_=z'[xOwV?5Q}u5{Ūv>Ve._WOKWݴƇo5~ny7*޹P V7ͼN={uuYgjG{-#Qc7L[HcǷH}w)ƪ|*'wS"%gG]HskÙuMnpݪuf]~.GFOP[^vkzƅL jߵWTkWTصCлV==]w_+}>Y~EOuhޫjOGs<~{N+)Nl͵=GA$ߙש^O~OVzo:쓺Mc$F ROsj+Y?:V7h+zqiYٮ 5F{VԔ'+f՚1U]ޫ[.餛`ZQ&I&75Ǝ,ժ~:](R!^[}wuN?8勴Q=N6ۆk{2Z@s#H>[eCak'{'B[>N8HY#){N:=k/{3whћu) $34]7u5'sӭҾO}^geaz~VO-f|"c; ]wj\ :?+ߛyFn嵽b#RMu:O ?kY%5>ec.|q: <4mj} Tn{DNmO)DO)DO)`X.R)7 .4 R3kPLS)C]hBM=%&IJY~"H'~"HaPv ` H'~"H'~ u gsWWW.Y:ԥwQu) M;J-ṯu)##=yk=RA еKGXP2G{7e 6aҥ2.cDZdC]ƀ#H` SFa^8)llm RF6 RR()luuֳЃWA!`ёvjO9wiֽy'3wRK޸ q+4# HQ=q} ؛g/}L76ZD䃺'Uqtsl# H`wxYy8S?=|~u^RH1uOtۿ}I|%Uw=P1}7i\^z*M|NgSTOߧ|ޯv;T25zGy A aёR[~:_]p&&.HN\ W[gQaot>,|M_^ wWdf-]z:s_Ͽ8^aڥ:?>V4oҼCK 9g@Y-vqGgZ{ QQʏ?Hػܬh^ͥ\Qq\8oVRnn{/ݩe^t#ߟU |&nI#ўP҄otʼ.Lr ZRu-^8ywE[3:SvyeVҔ.տmͺ|Uijtg譓Z:^~ ⚣D}UL>4q2&?s hOn=rǵ޷s$eL.q*uWu/,/U_+ˋԷ^_;V|huLUS3}Uܠm=6#e`EM=3O~rk5UVg~ }Tqk$*=G M;I/w}/juIş5T8o)Z>J$IWܤug&*ZV)ϧA:.z8) !7xˆGo]Ӿ;K_W2tɧS&+o&7Y6k cbſWW}N8)+o:?nZ^zl#5pv i=r~|NX\*#"Hi5nʔ)C]B:H?#A'?$زgAc:nK#bR|D4;γhJ=# wg FM8Oߟ%F{hq N6mS<aߑκYF?3:R8kd,=#!8:=#aߑ2%ա #  %WrWZ/^Vs*ծe eXӐ*AyyP{]W\˲+KCwZrAƤ^VO͂g7UPpˬhYtK嚻Y#D)1/crrԞٳrtoY=WVZ͓=H^ɋrO1Fże,Z>nVWkVRSyPYc> SiDI, ݞzgLbQUռ,&i=ubbfn\Igfb16t%MZ-徦DwK&<;>,BWݳ=+ V4kr[]W$I=+Z1ZzT ܭr!`&i4gnYpu,tTܓX)R.H2oYNhMvF۴/e;+2+,sKRrtkn+kE}F|f^fdTf4K{RZ&NYw3zH䩹Y-b♻GcnZLB<$YfVfer@@9`<4Ic!3K҂Y-g)xҴљ3gmkL(@HY!\ix\ޝŨc =sWG%$b4ԲS/ļ,PǼMYR`I) i=XD,IsZҐy*nJ=LfUw`xYXOi/6ٓJ+-Qn!xȪlT1-$A%咜bz=I BHrL1j̒RHj̒FT/6<=KdbѲDV=+&nĭ Qʥ:լeo[-g73iE Eϖ”B4ļ+%!$BHJ!J%YB@W*%y,)YLݳDdiŭ](5~(0ҳmM$H[SzvbΒXb cS[Y.bN!Z%I &Z[Rʓ{5'{=Ry-jb֚dbf'JBi;x|{8EXr!֚Tk5<[TH <BR I*\0<S{$O{dV˅2ͅ(`Bi ;Rzmd_NLY|(ɇ P.%sn;V !aT!B[vlZa,&W5AGw=*ܻjVB}UżmZ*/ʼպMN؋)Θς١sBԩ*/&PCյ$*j@7<)1_Y1/v P&Nq=ږ|t f" V"m6LS$i¨$W$PzCA +$-c$߅"I;2D3H6vQI Tz;T$iT]I@*vkau“E6;# Z" v"m4L6N$GD(fPA QHStnM`vk^ӹyBToh"I=[c'O_'<JoCiG)a^"iPEZ78ֆ'fi(Ҏ Rzm$P6H+yM'BkQnLiS*GQ<*pܰTB!B!va/d*7 0cSFkUMy 1({&(_.sP0Fm`eNP̯C[E-p,vN+qyJA]K)E{Rn\`0H"B!B´/h" z1Ƶ,'b6^6^e̘mz p#VvhRԳJA T Z\J)(mhˋj *ˍjתZKŧwB!B!ة^UaƸV܈qus-<'jxxq n*Tqx&sQ+ܚ`ec^4nb^lPeTYg-~G Tv TЖJTVWYQ,kmc1FB!B!h amL,gkpcZ[F{<"aښe@8@Y<.ATlU}GQ*MI._#>ZYvZ[^L JYc6(K)eArl~Z,=B!B!DC<kkgc<kaVj< 3{eImNPeRuw9SeYnSv3 ںҵ6Uk(U5B%A)˵c6qeyZulֶmYr-LB!B!vaծ\1V6*E_m•gS=_(\-m݆~̝*Q* HTr[R i *\XՔB",Vg)3ʎQ֞kZiZ<+B!B2s<3϶eq{1m)42P+%x&)$jY vgCuw&>AK\GivGke\>_smWk(V\"B!B4{SN\񼸭-񘶔9ʶS1𛨣)*J Z ה.P5U1jmhH!4kP$u&|*. TRQhPڳMѶҮ,:gh[ʧzW:O\6*B!B!.L۞z`L1ng8xmOyUR1.&XDKe7kQ`֛ KRg__ifM(Q!ҞeU򣔲0ʊFh~mF\m=m§m$TB!B!va(@\*fA bָnX[qLܲzF),l -1yUjUxKUrb{%kN@i 6* iKJ+RnLiRvģU&ֶ,km^tȱ |*dReB!B!h<\KQ*v=4z~3V6Ľ(D=K=R)mguNuqۣB!B!h lVTxw|\cke\17J ύŵ),NjkJܨxډTȯ1JG'Uҭ!R@$p(χRq+PRVk Z[ٞ6~˘F$b'N*Y\aB!B!Ӷm7}wP9ј1^*llAc,QGRnL)F(Wƥ*(EѭEj s^A^ QhюVڠVZkc _բʇ2*Y WTlkS1c UĨM_ B!b#Kn! -٣Qwt>Bkmϧ>RvZyR`xQ:FF^v\8Ze/DRae-iQl,< ©RƳ־ :uI,zF=6%B!q㔕WGNg Vc(g…4IN>^g0r$>0-Zb2>NH@0[:9gsLW]WzyEEխ; @(McMeZ!DBFQcu4^ޜ4k\eر|ŗTVVҩ\qtСg̜E>}O˙7o/2{t^{ +Vp7USo]9O<_z~"2z?8.  a7]kG;O?R8_?N=u/*'~ݻsml! _ug>Dnڶ{GPYYǵW_E,uZfd3Wvaaa͈jPTTDzF6]ooo߾uڲ.\aW2vX&1_zX,e7t6TYW@.&WWJN~p8BNN?CtKYiIpBGaLJLYi67BC4Rw@0R{hq̙3y-֛ .s$$?Me,k̞E-Y X!q 8CVVPw;sCxgn% 0`LJJ"F3ZF(IҮ];^=ͦL{IZhɌ~nUV+z~Gn]yڭe%%\N0$!!?U5wr-^ k?bnN<$ (}ɲB4|}FOeyyx,FeE9SwC%vG)B 3W>KiI w}7>uTV1m*gȑ|-<` 'p6;#9'NAg0gVXɸ o޼%ś]vCרCQert]}@9s0y]"̼BE w Uo =+3Ç\={hw}7&IDx;/CYg\vmۖݻqAѻWeJKK쳔r!2p锗"oG~PE)#Gr{uի'Gu))b1 rs:^xET Wҧw/O?LYOrV.Go`2Z"3#Z7unڵ[nxM4hEWml! _u1gO>e^J(\]PsܲM+v0έʓO<+yFTԩ?ЃOsG>=p=c=v.**IJ*/HIKKa>*-<Χ*Pݻ\.*!֜DF~Qn4u\|SgGA^.q F-J!a]SҊ?c_4ή+ 3X]X}ˏSrp3d_7|g΄)+^@vv_5|qkXC=ǟ嗟㏙8Mzp$[ཾ$|-rss#:#0a{.?pdg~Ss,lB|Hx,zȡvJՌTZF7ϸnٱhcqgq%ҤI*&Nx,Megɧfesi^|e>`6 s2x׹x /ݐ55UfϨ:P(f|M0dժ|>~Ϋd|>c>UCA|vΩB4"kT 8ӦƂK.z<˖"1>F>0EEkf<3~W5g;rW6bb:vhυ^{SާytޛYhO=4W]s  /aWṛ#cB(ǟ|n mٌ Ocn^E:w))YSss=rs7g5e/1clqc)^U\Ыѻwo,Z@,etܣ7t6=yd{w cǏ{n0~GoQ .|@UWmo5o mY4Ieq_ezôiHin[A !h\T~kC i߾=e1qX3Ϋh^(YSDn x|*++83ٷO:>u҅oyg֩{7yeU.]LFFFMPp K/Yʞ]R͟sf3k *uZcYVMqqrWлWOza٬;urSe !hgƶ|c:¢•uib挙3n5Ed/_{@iq Kًu̟67 !gspOzoQ .1j.vu,IKKEi͏Sw ?NIKKj!~9<o?䥗_f^3fX^xE~u:˖-cڴi<ѩSo~Қ6.pUX&|9}V^c?΢Eoe]VVƍ7ħ}YhcǍ㧟~# ##p8ٳ)--%q,]s]~a*?S[fe1}tKJg}μys97}g2;tY~S0,˖-c=yf-a3~~N @,y]Y}0i6gXE/neG":m~E"m.ߩ-/]B,#g rEe7tw x:Ɨp%99m0g\gxAgdbY6Ҹ:߳j*wFrrv!br]+TFիIKKcy^sG27x)))!55>kΟ5{6%%%6􀿶T?oJ)ڵkǙ[wbb"z}1nݚG䐃fM2JF>%%% v% .ƛnƲ,z jʾyx饗9Ci՚3}6l! _>icģ1x_~~b+FW5ePR\̙3l>13 dGp[A+lˍYJVF}|ڧ}>pQ[:x!g4:YUM-eK79#gŲzyF=Æs-Y5tkْa]̙lz:W S=x䑑 >fe񢅔cjvZCNNMJr2Dvb!Op]r IDATu'$&Ҫm{̛@L+/:A)5O'%)m:;}(!1 &_]W3KYx!pN{uZg,c.`̖nFYSW=SJ,#d|kǢ)*d_4$iS,ˮRyF&)iMJx?Pޢ>fK6;RQ^J$%7Yz@nJ rj3w} %ѢP {ŲM-qg,--{ТE (`\.^Lj&[gvj݆a3}v*rc^1%^W6:\yEʋ{q/(7X)3w:nx17Jmg&c.fDTC-ˍTYpwa6vf_h*Xt)s~#))Nk i؍xa!Oe TV= WPQYQAeEFϩqux!H˖lVV:?o._>;V[Yi e%uXR6q}ׯs$\%YצB8g\UP%K;wU}F)hw˴i :~XϰCgnFmӼY3RRRhӦ Hqm`0HBB>ۖ9B!Bڑ}F)qhJo^}-.i! [l.T))u !B!u>n_v#.+B!BI"B!B$TB!B! !B!Bl UB!B4uj%TB!B!!B!Bl UB!B!*B!B![AB!B!B B!B!VPE!B!b+H"B!B$TB!B! !B!Bl UB!B݀MPE!B!b+얡Jl8.{*'Ⱥo放l[SD{*'}ʷo`ݗrJ~_lNS9wal;(B!]3T-gerJ~u^'}YϤ}8s*ڱM;-29N{*'?Ro3/rVNC:>Qv}`t?zU ;ڎDk~QKsd_q;buCI"ba>a$VB!b7ahN葲'jO\=svgX4=b8`֦(9%891Q6zȣlTlJݮiz~{X+cH'B!b} ?TنO I?vT[6+z$y+Jcyr=i_'/^fs(lѕOa:a/]!T/bvCMwK}1e6s3,Uk/_p ѹ^0ӂ|gx{8T0]҈}(&|7k\nIs9%Onٌrc>8sQh{st14qVž.D}e0,c4ۏʠ>*2'ƌy񿮡Wr>`7o2f"If1{\ }sQ˙53uYGaCVmȈgw2)ϐui 1bF>7>_>*PϨY8_& ͺ3ΙE^9r yP6s$ٻv|^XmQOpڄdzɲcmE')YCrG.e%MxOwc4{NH/{ы.[4ňc(qygL'' l/,t7>*nO1a`(?LGţqv|F7CWĒY7B!bKҡ @l 8G0d+x?0thg}hS}?L-TnpÕ,RҚٶ q4|(֝Zdq!sFc͕wN{ C9;)>dʔ q S!H&yڷN&ů N:W|h#8hq=w`kpx~yYfŞGO[9pgQyU.I9`:^wFۀM|M% !)-;к? {Ch؉x)}|Tzt{},0bL{6R࣪wB/ˍ-oAwSPBY mڣbYqo憁O7ކ>O9KJz,}7.!;n|rʨz/ xО4P3~t DP#MOC5W`B#L} I?\-\u8ǝS->p0*Sfw3ٯ!e,ʌ83We)EF(J⪹Z:kZ}ϱ0E1LSHߧNH9,a~9٣-z|,%|{^d.]#B!*t~eO GfYn:;~-=;`i!@|v#,z>^e ЃU[@ݏ)o~A+bܟܿ:EyEL}IKdTR WCdKɘi0k/YP;RAcuiKc&e=z.@Df}/qٜ#ErٵY9{Vm64 FY2!쾣HDg~[?'Vrwޚj0qJ&h6p]gֲ>AY :5oIdB?={Cd6^yjWN dᙦOr)q:n:*y;q\J4iM3z9v~9v$}׃$2Dv2yZsxA4UK.B!bw%z'3ߘ/%}:@MBVGB_}OaHt8{=(ƥjĂNciU9nG^S-ƾ>= &Ђ̱=SY?R|fz S!HrnjqGߜGc硏ۛc/?)cp/ >[O!yM^^Xq=\%t#uL&d!A⣗ާ3{ ڬi#* Mƍ/&&!::OZ lT[)`tAχڻ+zB>.oک-jCt-Szr]W}|]4K[)1li|Uތl2O&c&LJf`{rҐ8}']6w?? I]ϡot<=ZW;%jpɭmIB!Bшl\w tA7T,nS~+hbVm1Vʲݨ6O1?j`A/dLF'JLScr9nbL93[Amoy뮙ǹ/)U޺[7ۜbypD^3,{6ǎKd^xEcYl'.xsnIE!BkeC?wRjO־'ӷenie8c^[`'p׼_0~'SS9ju}Ytr):/g?a~GyC&21˨yknx_~/ƿB!bk55GqUUmpT>!w|gyLbO1܀K40zag$r}8Kog|Q Q @t#7q n|x?A됳ɍ--!Gq[^}8rey?H^GsŨYvd}d|7Ny8wK3vEƹTZ^~!g?ɭ/Ny B!eҩ)z\gjiJx;}ɿCv(XɚDĬi\6ҍ̰p+Sks&r%W}uftM<^Jd;wr2Ux 5#'.}2FVƘfxIZcRp)x5FB7xu~^QI'rqRl⬜t-7,9Nyy8͈R9SƍG'ӮsjG3{+8$*<~.?B-T=++01݀۹B?zz3K$oΘ_,D#K'݇2ao4Ͽ XY9znܕ+Kk`Nr\R'I( {9OeMpeiia':r^Ls5)88'P'Îb-5sڸzl?fv aVCݾoqB}09ܗI> SwFO>(8wF~͘M \䥌3:^ΘKYoGPN^D{V0a4}oc{{ g7v3lL ݌2jjK{u},,ąC(cz""3῱ *O"D^lxدgzo[ H#"""""|N0V8u^e9ⱮSt13^͎˅%:" pDs(r |, &jUb<h@<ݚY 򌭟hϑ[*[0uڮFg }CY;(ܮ uPq~zmwLT% xǯE\m0fes.H- e\7Cz (CvEo,WO ,9)]1 _V%=L+?BtU~&B5P8"-}<3%/Y ΗfL%щto= 6nE,юq=Lɵܗk IDAT7DD_WpGAי'L[^m|=`*5oƲ8ծٛdx_!Gl"_5DXg^7//&*NѧܼqHTmV̉0glD ™f)M'3NІ*c% (xJ'xN|=!]Qi0p:= ŅSױ=lSʑŇ.{&"&6P#|OjJ V1x&ٯkL):.;KdώoK&dq1Nҭےܓ6TG//&~붒x(Ұ)?f Ѩ/7]ʹ^4Uo5K|M1(3Yja #yn" /~~~1@61%M?$;9s~o$Klk>m $$5uҀ䛋l*&~qt=G7|ByoS1Ӛ셯~fϟ'^K OC 0`x`7͍Iko7K?KgQt ňɕ'c–6RfGJ[Q8b8'2Z| g0&o?~~v|=cwu4Wpݠv }r5޻S#ތvŽd5ēTxkrcd|XUD7h\Oɏ7< SFbϐzT|dSWbR>EʿaÉ7_q)Ɖ1~V'~ 䵴Ác;6qXFL aq6Z3Sr#>jܜӶ'iFԿ>s5 N;QrsD:+7ut؉Cz.-b1oݏ+Q1o1ٜd_#""""i<=Um쵧vܶ.fi;[ƾ&osT|fh6+x^څU$ ԟ QBI:ߟuf\txTߞ#WU:VuDZOLGX1i,~ jpF߳d8q%ƫPk^N8Z暤VDDDD$3IݿNZx$NE7Fx,&/wh0Mo0fa9`D^>F go2,Ƭ&3d>tLgNc'KN۶U8)釐q8n͑4].W=9/Q3k8ȒEyvmlVkzW?ݻP>2R{EΓr0fR3&2JJSCҮr"""""l&wp^z|i;.۝+GGjipDyQ`1VaV sMi#-6G=}U99x {7Tq:qphJrOu}?otWN?ltjZQLQ6i%m,""""""ro2C܋1NWӻ"Yڵ\ͷ>$Onj32*"4j/Ϣ=?-"""""CnL evM|/í$mĶ>ezXCDDDD$zhCy66-bpSXm2c{2}EDDDD2~b3qOwhhrSXm2c{d?2 8rӻ:Yj{0׶;һ """""wl]4P*z<(NUUOZHl}P*KaSDDDDDDnL dF UDDDDDDDDRAH*(TI*""""""""PEDDDDDDD$BU]Dӻm7ߦwDDDDDDD2Zujw>ThۡczWADDDDDD$SY8onzW!e?""""""""BTOqf, *""""""""BTP"""""""" UDDDDDDDDRAH*(T'HH*(TI*""""""""PEDDDDDDD$]!7x/I0x|Oze$.9|>R l{bgMТkΤr7:r"!G`j8U5| ^J~wBFk!@Nc`SzI rm6y`ML _a5a06 7poKaynnC 1=A;S&n>$'u\=` a>6S^a-dV Lv=6j0</[Pz9]/ {yD`&p>"$瀷11o\| xfezv6WϏ:Y.q=EzuN_$RptܯWVӽop(`T.$'' fq`_$H> &wFwubws#" Cw\oB{Pni+aP! Md9{=\M/C}9Dbx{>~YJ~K9e$K,GFG(^6`0/ܨ0/z/Xlc€Ќek`kN=3ױ316:aʔ)L2c^R61WY2މ0zxᅚBU*˅w0VӸ)EDDD2*蓰"> 5՜؜a> 9`^0|& |iCv0~z94| P PkپC\b`|Ȅ! l-kBLaE)Λv~+l`@C\X+@+IXFBǀz mFL֤+dlo#.|-Ƈhpc^sp@66ضfM07 (#9@Q7%)oV׷%egatx9| UFlB?2 OGuR9~F 'ϭtq} J5?g@7iR~E(ІA( folٖ6.|.̩P?EŊdZ󐈾g BGW>m[]Ɛd^]GgǠO^5PvLC`u2~ >.j";U׷qYܝ6" ,v+`W!X ͛Nxu<]$RWL!\szzwpd{d;b3qb|[+).ـm~$֘4\I,%^8_#Hw̿1WX3 ΝɄxgM{:XaMO^ ;O\ߵ%|eg4 @na?4 謰X%1j$I~ʝM6vڀW`Y2'jbCjL?.4*Xy4KbU孞əFF.L\ЕBFC0?MC=B4i'"""CyNCX4V8\w0R Us$ ǖlp-l|+8a& +v[8Xם7ʉqbɚ%J#eq}8cO\В ($ Ty+n&k Zvs+&\bU"v(\f5!+B J<qM0(oכ[(Og30 82:uC\VuGsW}k+٫s7 pq ɞ n @'aeI0Xꏇ&Sa~0ϻz 5Iz! CP MS65a= y)Z83<\=1snI#f; mSO 3ܓOOvp6Ӑ/߹AWx<N̄ꓠ0Zx<3ϣa|%6y!r?/DzI(|5 wroR)0ahh >:BQmgsBzApr?9t0]!ONxs\/ƻ^z)W' ׼ٹ}Zp.O P8+qJ),"n9_uW3)$P\AIe\C92]oM恉7o :C3 zu? Tڻ O:k!KHbᚳ=W[ǟ~b6߹W)>K +>Uw}ukڞB =K\D+1?@H^5lMj}:?@?2Bқ\ t)2&ܙ]u(3_)=tc潷UsQ%4NxrrAgj$׌0X//mQ;l~8{7b_N߹ ѠkkG-Va̛ LgIV]e$W8޾<5 :}wjf'9"""Q0@p8|2f/pC67.A6]9u[ȷ`j{( @V5F\0j zÐP̋Dx`H0 |*F nl OFgkj 9UU!o@g3Xzez eom \'f&Q^0Х|[ܩ)Цs;f]p?F U4d$};ep(=P Un|xWpsky\SF}_/|Z-n+] ~mqO}}V)ۧG(;+P%*u^>pz/8 sz4u>fsʷ·iǁ5r'@2(Sr[,ejNB"G=UDDDDDD2SY jA&%hM" K7qtW\-hL^L ߡŀM4-⪹,cֵLY2zTΝe'ӯJtA$#R""""""a9q0Y-Wb2p{]-aW\z&_N|N96 d_֗Aj2lht?sLɚ~>9lͮ#Ũ޲#ihHe p$Wbws)<(Ξ-e<2|_[/jއ@֮U0yه@<+"@yڵk\p^6>}:MqYnܸe&'44˗/?xA K>ZS8"i`p B~=N.D2 $oxl#o~9q9'`' &  dF U9uTٳܼy3MLΥK1Ct՜lqt3|{J+v/'}4L}Id+R%\Y>sW#Ԟ`Gh_eA>o_8)R= x>ȣdhfr̲Ec^I}7p)wc^{YMW};>_s2;Sx=K<ՠ6`I|\O`&OQ,~3Usel2Vջزy"&d}mkcYl F/7':$c؇/Itȫ=j ]|)>zBɀ2L UDDDDDDDDRAH*(TI*""""""""PEDDDDDDD$BTP"""""""" UDDDDDDDDRoǎ8NTUl?\J+W _X#Ɍ<mPEDDD$~8篠hS~DD87OO皉HfPEDDDDs|}Tz goDD$SҜ*""""""""PEDDDDDDD$BT3+ """""""Zf2~"""""""")TI*""""""""PEDDDDDDD$2ALd< UDDDDDDDDRAH*(TI*""""""""PEDDDDDDD$Bܜ;.9ELzzfw˟G UDDDDDD22MBR5۽^w7LՐBB(S#vhN,AϖϹTU&dv{O1jeB:-Wsջ.nܧ|KᕺyV6{}݉p3OpWLH)^Zv[2~]BJrڵd8 UDDDDDD2?ӰfEʝc3qEعd?%♆sprB_zd^:ľo#oͱH'=U?-wq]Պ`ͫ_IE鵍g߁=L2Od5wbdjŷ(g$)T &F#&,ђZ\7e5]%l+OZu{_lLPȕ_o|s;Wvsd+-9Ю^HWM, mDj]|p曉m[J!!Ԓ3s=Lqm/4ň88qs{kx]dﺿ(S ކU20MXSqc> yRu>WN-)=tyOl$Yd*""""""8=5B=V=70 WjǸ0S'st% }6ctL]rU)ڗZ$Uŧx|% !8i4R8,F%~iM\NOgQ)ka3m~z&\5QWY&w#7%DoU¹G a7/1Í1qBעpt#B ϋ]fSa8Hn;ڏ>d{TΝx/Xd+ܙ3Tȓm#pZ sd'o,X8w% 1^3#'gͩį=r ٿ3]ʉffbwq:lXm6lL+Ѷ̘QWlP^<ڸ=WMc/װ9"8y&_nH'n]hǜO5*  H2ќn,-O a8#^.h8y`ﶫ3 &7'5bbCX=b%_vF߼+D&0A߁9Yе-{Q·61]522i"~ O*ۓuۑ{:'<1Xк,ʽ;b8^]*-Cp3ƬT)=Ly|2ɟl݋t9UDDDDDD225I-7Q rG꾕]z#vyy> Ƅ! ̪sx \ϵ}]p_7쪭fֶsD'Zxj8;@(RÖlv.È7Q+$2!C9|.}Ӄ2!xn[|82!Mw Si]*ͩ|w"<6BEkQæ{aY?חq=\śCӁ~}AMhXCR1(R+6!־/s~J {d^:?bkXj?VI>H9X{/w:mub$W LoAm6+e51HN"~ՎJ'\y&p㞯x;doߓ o$i?R""""""YSC#y,?| _]ps.'aLffѕlق4Bvx?Ag7,h4a41ybj×2؀gG)/A~>xg%Gd N/WM y^zm0cQ>=3 ^x0ކoqqMWoŻ ;P3vS)܉ȎTzrXׯm,J`IAT^^~zN湻b$[ds?M4ěz[&̤SY4W2*""""""<aT2x#fn̬Sٸ1o⭻}RVrF}}|azw.Rˎ!漴\pq_q,Ma $QE{+V#{i²a?""""""""PEDDDDDDD$2~ DDDDDDDDd@ UDDDDDDDDRAH*dPEd4 *""""""""BwQU ߙ$I$tBOD`  xQ!(R>zҫ@jHHBp᪴!d2{ʒs{(5o (UrR (UrR (UsyܹS.W~x@.pc(Uq U\YM6U޽uYoGr #^}UeddHΝM*!!˩ϳڿmۦ۷kǎ:s挬Vl6,l6}+**J111*T ]o={}RHնGЃ ԡC)w(UJKKܹs5sLmܸQǤhϞ={d2{Ճ>X-Zԋ/(IP)\ #̪^J%jڑt[)))͡P@bO?iƌZx"%88T5jTJUT"E_~~SJN>xڱw-[L˖-hT&MO]v2 extajR%I~VDM~W^yE(VQ@r|r 6L$L瞶j!լY_,Z-5_z-++S7kҦMzڵkkذajٲre˖- QR$.^}U,YR;v P@>g駟$IUMMܯ>pp;Vw+%[+W.̙k֭ҥ5jwyG111zgt:xªVt=\ڜ$)UORJq7k*O?^o&L á"9w߃nJɉ@ZzX͛ղekQJHH믿vi۶m*mW KJ^ *d=rΤ_|?)+Vyڵkʖ?޽+884Osl޼VBfY.Kي-u$IsUbb'K̛7O]vUFF>pʗ-sdgW|;mjڵ*oKqxӥORΓ2eʨbŊ x  ,P޽eZվze6{%:q"YUVՊ+$In85P맄'@>fWNS<_]㼖K+Ѩ *hݪnV^~fs3{,CtwO?Uy(U۷OݻwbQ۶xPq8;-\N=C?LF^TWK䒴D>FgL2t}YLW~2PV޽u95irBE,VII{TLm۶MԯB*\qlwZO$5mTcƌm>0o|5>lڱc"#+g̓%_G4m8IR *:$@O+|XKz$]oHO?T .PALQ 0aL:t6$˥wdZԲeK-X@IRLƿϜٛaտ8],X9͚5KժUӝw;r áCJu맊oj_]-['On[BU8ӥՔr\*SZjNO IDAT6}׵d.ar M>]۶mSddyoӫYjQVZi֭*g+E\[yupT%k׮*Q&O 4taO?r3U8=ZԻ r&MPgU~}-^Xj 7ͩhAʅ(ժUSڵwnh55l\I>;C-Z0[3U,ZHIIIXvի̫YlIЊ `eddbj^,XgZ@=p8Զmw}a撤袢EKh˖-ZhW TbjunR%ڃip+$u۫9,lǿ#Iz+ߨ'ʅiZsc7nEo$/y URo3յk?ǿxk.ooe*5;&ժo5k PP=zT֭SXX5iʫYf̈GTJZJT$Wép=CZpΜ9#)Pݺ=z7﹧&NuԩS*VX^(Ukp:2nHOp*ds̑$uWky-GR͛ nv-X@t](--M_$VJ.wA[~ҥKգGA>^#͚z-رotM6 I*W}Q/Zn  sϽ7Bƍ[J.\@^*. i&R5ciJLܥҥKԩS^ܹo߮iӦI7o'|Q G\TWT~3VFFBCCs5?W|T[ƍeZDFw8iJF_۷WѢE5{l\.,YVSLL]#88T5kӖ- ڶm4iغu$j\riwed롇Rll.]$͟?_A?[|} ʕ𔬤܈x3UG$&&JʖZT6Q…K5`TJ\t(UQX0DFVk;wV_~$lٲz衇!9H=6Pm>K"#)UQ8~$XRy~ɓG+==Uk.IRzӯxLT?n 22~y#"驧^V-e0y!*pk̔"j>Knݺz|N!!brpx^R҅Rf͚^N I[TAG>nݺ2LڹsNxaׁ((( ?Ta6uw*++C{nvټyV4h ???orR|H۶m%IV-rnݺy9 psgΤjqJKK꘴HIo(99E|0Nfspn?ÇkezɗW>edi C=8M)X:pٿOl.jc Ւ%RhhTQb{SRRkܯM6NijӦor Ѩ#GJfBII{(璒hɒ~q\C>AnӨQCt|#ݰ 5D.SWtt#R|؛oZjر3fN#tj̘:vj׮^{ۑ\Jyxܸ@MZ;w? \nӯ.՜9tIR5rHխ[7W:JիQfѣw^3\&}Mw?;_p8g\XktIwܡ^xA]tyR Ѩݻk׮Zlj*-].NAA!ZUQ2TL+VZfsХBt*;N:Gȑڽ{vڬKi޼ԪU+(U1UllRRR4w\-ZHׯצMiˎ1%ݚf5kLmڴQǎUdI_P@UT))..NVU7o֖-[t%%%)%%EYYYȐ$*88XKVJd2ynCɤ aÆގ,~JT/U\p9/U| @P ::Sŵ:[k7|[ە-IY5ޚlk>S\:]Fn?MRdwx o{;,P?ϧxܥ?Sl 휡#)ȶ/U(IvzGQj 1<?ǿ*zrzZczvff| n NS{&=xb`"Mzz=uG>$!`k){T[NT r\Ͼ/AP䲜ё2$U*n <%[S|2#\7?yˣd4CÕGK;6o6R$K(vL2T5/.=RAEGW1NԲ]Tz;=99=4R~)AiT>/q;H5zN2>d٣Ӷbݩc ɡ}IC?:iI싩Z?SEvӃU˩s4fxpRUnO#}TQ7 <&áΝtkfՄ y8No\]4U,թxP˩fqNfC3ĥ]_wzZ2v>dj⪵[ÔvZOT^\ώ)@k֎gߏ/?n/}2ixkv,~]}Ǯ"MJ1MC]4]&N:> # i6uJ=^_)_ZS^Ҁ'{0Ӹ4rs8p{[m<}]4o,=U7+zkfKuH* cP5z ݾW_}I_&ee4+F' gvRv)tNGԱ4\ XQa~΅[?_kǫeA--/|<_VŞXQ'/!2'[OAXa3[g+Z> Q1Rk()]KkZnR) vs;oЋMKR9M7 iKܧG{ӓP8 nR>(U<lX8UAJ]Sgۈf2C*n Tj:co0_1H ɡؔz(YEdvg} v_) 0ȞJfw9J VrT( 9ӵk4~sS9=DU-k=!Kr2t|f>㐬)ڼaNd2+(,\C2SpL9qtW]Lպ) 0Z ]h]Bj=k}nW7^aXB?#h?2T|8N=]qZo}AO=^8JaETQ+ {7E{_LSV3Mj!|e@KAe롧>V\ fQ3=pϵD___/?kWb0\a|갦pbTXczwc{ɎlZq:z{䫟3;5jCUg\la0Tȥ;p{tbETdqJF?M0c,l}*jSO}g#'U @P 2jjT IXw3[:215k46k]57$a*aƇzTFunI/~LqYnvj5+6n&fy\3YjPW7(Zpס_'ic.\zwq\)8uz٧5Y+@J27jaãã@x2GN*_2EvW}R'j ftɒ4]RKN@Y>"M tW*UvR¥s)J O:w ES?UCմ~Lejx{5Z^ (|uye$l)$e+q7J0H]j?TQǩOfw(=R3o];͇f]F!! /jхv~>ڣ#[ǎԱ: ..') _Oe]!=O:t\VĿNjNzjW>uL}u-HhaT󫿟Җ֜.ԠW'kᢪ4oT}?A(Ptz_.Eء/^~*l;_F?g(Vh&G1Ț~Lə!(:~s5ڕ$9ϮF({D<&JS4q` 1T1Uz?4x6qVd?ɇe'yĺ?^;ՑZh=ӥ:PGO5.D>r4gb7+*SqٔcޚPFI6eH~2 VzU.]X3s;3U 4(ufTm7j̍$֍S~Z07Th1M3iڃU )KSz-PR*(:pJVB!#Uw*}l-*OZG+(D}=2rtzJxI(cԱoS}=wuT2n|k>ӄrX5U?d.Z! rtR{ܹK4v p2.4J?I731PiƞegdpIyVFeSr./)R_ ||tt(hmM/K3u"2RX!7MGԐly]w5:~B*SNa' s*|TWݛ֦Sj7sfIYԃJR6VAPR}4Oq҄]ڟP(74h.wڜ_:VpPS/R]5\&+M $Nin8-?mm=t ʔKmϦWTӼFnרR%T~}:τzzu>E}NO+BK>oR7Ƞ>ƨťcŒR:YI!~ed͙:X1bH7d:崤hìXUc:V-ܥr(;vl;,S{CgeuJB (@?{Sҩ޿QkvRI?tzwMUzʚteꜳʖ(9÷t&Jf47ݐk/u~}oZSں3lveKAQjk˰V}]XǿFIF Wx (\Xa2% JzZsgW;U?zXnj? jѨjlG\(9g6W:Z5TNkPO#h~W8:K6QLF;/*b3VM%?>RA,~^|>~a^ߣB7|!ݱC^sIѨQ=IO/"ZD-ʤ>/{DSW\_eMեoed}=2vBsar)ncc s{aC;<_۫' ,f@R1_v ~;"LTȁޖ-;z֭OUք5Jx]b?[/^ʭΥbz8  >&ɤ-ڻ5>)iVXTf)33 `"ϗ*ѣ'h۶]2 n/ßWɒ= n]*@>pAuKEskOٳ*A*4{b͘1[{3aBC 뭷^Tre< | m߾[[wVŊ/xR-R  2J,⋩ rkc'T| R(ΝP*uN S?RWIXR\ɲl7t~ҥ˪tn3*WvqP+V[t\Fc232 _\N:˩ UHH_퓪U s_taƛL֭<  vx/3gn?xpԶmK'Ce IDAT FUt[33={ )GvT>eJIIvT\jv BZjۼبpUE?)RDQQQZV[*U`vT gSS!)QRpUZLeffZr1ʕSVԵkW5hЀ7m*V(U֬٠#G9ީ}dp2\e?!S[:f+%ۡL֟Ç5qDM8Q*UR>}Իwox9=Kz;ɵQcRVD5?iΜ޽z,$)ϨA*.I3dЁ4l0}GӠAXe0HeTPLLggg)9~ZNiD\ř*+/1HbR*ٚx0M z_׃>Ȳ ?CǏSzi;vƭΝS˖չs;'\*U(D ꇛU?ܬFێUϞ=զM;VN?C6E+PFysRS< uT1]e,ּ }tF/]wݥ'QF$4$D y;5Q-ܹsڰa֯_D:tHֹsdXdW_};*&_h:U"f뤶=۵SܹsnU*P@矚;wϟ͛7r]sѣ/+UndՔ ĘRo߾:q sR ݮEiܸq.n6rR*TV*^BB iz~ iۨ]~GQ1F'k&yoTphڴi5j:$I*\8\TӦzzxZ,&w'wӳ\aꫯx,e\3'P@>_~Y[^xTJ } ('&I2͗g]xfå ݩS?.NʕSÆ s@^T|b_Ə/I*YzzAJI^Tra:aqhtGVqw(U ڷo|Im߾]ڵ:t)}QfoʕTX?Btvh#4h*o? ']V-ZY^#G~]Q"]Tɍ\ՊpQ .Ԓ%Kr'Q@>`uQjܸF7uk-XJ ~^~e?#33S~~nUk֬Q߾}t:ս{u{:[\cZO,h^zn:qi B\…ͭ۶m< ȿۧݻbmGrPSŃ3U$V@7kӚ2e o7zr*!!A&LP@ICx{ڋ]IҌ3<~=:ߟL F*UFv{"#]z#2 ,v5ͪ_]捘qCC$uO+k{\Ԫx<1O JfզM曣oճgU\rnڶm"#˫}ŧx{$bRD8Ç\r?Jމk5С7o^zor8=z~Q M\iʥY,y4ShGDV^Gy$O ϗ*l  R%Ğ?^= -Z$Ux&|{g. $ܹ3. $u;|%vRZh$6_={@NL4_5kޡ &ѣZnŠIVyrM_Z#I/|Tݿ] J')9f2*[6ҭNS[߫:u̙#I˓k^[3U.wjjj] JͦbJ*6[׬YSXXƧ7|OrdѢEfbךrʧٜ.Y] uJֿ}rvy.]˰;%Iiiir8yV.7R*U+ICN lmڴI!!TrZ{\\sӱ"11QTl<%>W*U\ $IRd{k-pu*#?.I*VT^Z\]>S'233e0e2mq?CgϞbfkzWNZz饗t}%*pk̔Z-+u%GJNNR>C6μGf1HӧdL_IWx-@7) @v]#F 7R>e֝Fmy9EDp* o3r\y:[s>ܹO]O22% 7J3gΪxjѢ[׬Y'Np* orj(08!I*T9G*u?Nx98qa{9 s*#$I(UPPX>$w~IRʕ9J111ݻx9VIR9Ju֕dΝt:cl6wOuv (UGfy޽۽cm[/ͪ:u(88q' OmVj/'5kI:v$' ~a ^LqrjQB/:x9 ps(UDFFI&JKK՚5?x;N[b2twL2ގJ1$͙3Y.Wrj޼o$I<7?$'w{SUXvmڿ֯_ {;RX'=*WVZy;p(Up];w1c&I25>++SŊl(5`Mi,)۱nŒH4d,@G:qJTf:q∇S[5am޼Ys~]vNLQÆ եKor u['_*[@c45rHjJf}zVTގ#wM`Ј#d07 u* W%'ϾRٲo4gR}H|A5j=CAA!ގuC2/p^P:u 5* W9~j޼[32< 7|Sk׮նm4fp aُtj̘uyz׼ U_"ܢ5yd)!gM0"_Χ˥oT˗ϖl֬YTR%oB>/b'O+33ŊQhhZO nNƍ5ydCfMPzz{9}{Z|4eկ_۱TZmJLUʨ+%&4M4Kӭs;.+{%M6:uzꥥKg)5{[2ǯkÆ2͚2eZnXP@.KO?t}їW|ٽOh~Y,eԻnM=j޼y֭~ ]C|^͵oN}P?~T5k3TPQ@.Z 4k׾W| !IؤhŊyg5/޽{k֭zҥ:v%)0OX͞=IgOnWݺu5i$UX1Os[n'ݦ5hP'%$,˽e7rjݺ5p`G͜KRLȧ5buYCզM4b`/{>n_jΜI:r$~9r֭| sӏ?YfiڻwƌI>RӦw/Gw8ڳgV\kPFF$; /.]S@hTյkW-[LZj.NK~UZGժŨLJ*S+-9R!t:}^Nѣu޽YvmVvv֥4o\qqqjժe ni*v9vŽ15kV3ۢԧO7 p+IK;'ج,g7q?ph;E\γvߩ1SGf>oԔYv]J ܽ (UmZ-Q̝z$)*o߭Qt@j(:S6|7Y3/ێKwe~~E R@+,Op)+};e/YY.l]ĩ˝`\d&lʔ!GdܭIޝXe0 3}V%]BR%DED%?mRTTZB13Ƭ1vc ~>p}3s}_R:~sCx~Fj;3JrBErBzMdzh"""Y2 lŢWDDDn3}m÷zBϜep|Vq(UdU?NQ)UĹss; % AQ)x3 .ʀyoΞ/ѫߛ-Nz;ǔ`ڬ)U>Š$Q0|5?%TE&1b}=f},d8LtruDzO}۴*EG0?1n^g^I,eG1 B 8OqW`!SV~|2 ~5e5&I=Iz@1_>O9exuj&Eyu>O?>O&oUDD"v]d?|}}cDDDIoy-^_Sd 2tj%1WJ#yG,Uec| =#d#g/e[ o]Ldd]4>ýMgvgmD+uckmݧ;ӿؘe5n8FGQW Ï3rrCm(nA 87'dj^_!t}`zciY<+` LofAPPfؓ} s&;Fv:υ7ɣV˳Nd:FDr4{yvϾ&> RS\Of:N1&48ȗ?SӸ-Ռ1NlaSC޻LQA#y+Iꮹ<_ӓI=a^X\a:/;C1 9BBh WU97Q"Y*VBj=͔~xB^Zׅ3 k _rq@.6oO#ݦV̦ bqyg~1_6 ႔(w\${3M LzØ$7P}O,^ aa<>@XXun\ʞe/#ç?Ýg |j+?k'w2w\ "lic[wԵ"AqL͒iX,0@1 M ̎N,}0? e\:fSϹ9pB#=Ih:M\|K,`wP@^i=Rcc}!_MmG>R&G12';4۳ ?'e|L-g*$qp_"zWr'rAx,4ɔ!˂+z)vHB1>v}9PdA9g\<,Ir%MTQ`aG`zvD֌iz~=Ip+n ]V+Ox;^\'f3e+?]on$#3ae3\\.^L% Rah:+R(yY|4NgT>m}{t"jC>MHdlMMز? >A8crqVKw`̌GI= eİqN&0-vBX?Ͷz*ᵳnjdp"ٟE eۿo'ξ/2z9}+=_=ΡL[ ?0էWr=>aŧgZwdI)Nh?"N[.&C TƘ翹cS0m;[)1^oXm\GHOHH>ty͛g˖ ׵M: UDDDDDrӉ4MNekm6VGi UDD?3MkQ}DD(KxV/\PD&fV]P`+fҤ]dbpl,.""׏-V*!B\.7kqwRSSZ=C /ɕ EFGr%vA]vw}P""viذտ8|yTh H""""""""٠PEDDDDDDn~)٠K]9CrFV>{TLժ4kv'O2+Sr6pҼFtb6,aԲu Lxm9>)KL <2"9AsHd֬Ezvu zun =y?5F!jb?}#E#OAU3>=ņRsěi)k#BqB}!5o=JŶ\/0'9nZ#5 i,Ke{ậ6V+SvkEc˱t:s^nT>]QPZS"""bHDF~-gQj4Q$Oټy;GIaTZ:JftIR|O#H5nǃ=R=›$C[2RU&qϬ?Q \n´i JݏҺ`e_x8҆~o;vz-KڵX@VGmNk;?#/Q:NDDn9_<T׷a"wRfCiQb Hne_of4ܐHY;o&Hd {d{! Ɩ| H^`]h"jx @M @{4 +x"h5v-"==48e1_DcARیI!- חY.MTzD^}3{?$:6Kr22hٲ%J~8p Z222?[,VL^^ȑcDG٤7>w>Ibx-:<ԋ? ='`JSwh5evj ?=ٹo(-t At_O /ZOY*2cX^s|ʈFt1H9r !t',%4ɗ1$|4g)k# xf8JQ"""yi$%ر8V+ݞ'&&a6wb֯??&wLJ J 5x`<0$tn@(NՆT) & 6@}]_ &88sB`x|'4$Tłs_ S&i*A 0.\5$4xMf8^Q"""yY+MMrrIɐ!z&55K0< IO$:+(XGrsOZ/_ţ?J թVGkf[x4̱@}]Elޟ=b6O~LSCy?O׈45 /GL-e[xc>9?Gkqo[HOώ\8Ka3L'I~UkS,v1=PM,+ǽ1]=^q(3 {żp0$ȧ=|;Z"S"""y^zz5ЪUQ&OGDF={(ZQڵsAjE$w ʣn7Xw4iH|!7ur$\¨stį| z̈́q7+ QfLxq0K"AޙݕڗŏO6cP> f4>VN ʽ]er\tڀQ-֏#0KMΧ_N}e:7aسx,,QGpI6Uj UDDDjb@jj UԺI=<U܇әQ~ǽ۷+~~srXl}%'U͞eVg/YWez?e||uRNgә.US?neUׇ"-cV{ثtKܒ'bGQKw=꼼棫iPEDDD1n brR .G|o3[M͚<ކȅIO>jKHޣPEDDD/4|"""B>11ڵYأ~I>۳V۠^+Ja0hV 9sG1zP< EDn UDDDD.B6 ~ʔq.܀`w{_n-Q%jrs5}ѵk?r10o^y-|}})\83\>$$AzY{DDr+*"""r1M˿>)$=wW * ~??= mv"UrI*Wpp8\_cΜ-Yo4M*"r-)T4M9O6n\G&z-- L'6=7 7P:X,OZmY>cHQK/cb?>=Mpp>|}ݴi}~Oސ}Fc?zܶO8@f5+ֆd|N!rͯXgX` xV|<˱6bݦ%ޝaifvZNڱFH{b8 tYNi&ne]ToNspE}GcFl\abzS4Ю]k>|9GG, pjzl9lW2} ryV)>***@WU^y_Wf'o_+\U{^ aae>RWt_(qmf͵O{yeО}zӗiW jPOyc;ǎt`7vuWO{yY)V0p}7r!׋Pп͐k{w/!CӪ'rsKaЮ_N7GD$OرFݺPHaΝyCw^:tș6oL`` %KrcǎsN{ڱ~z .LTg=m ߐ퉈$ͩ"""""""" UDDDDDDDDAH6(T*""""""""٠PEDDDDDDD$dBlP"""""""" UDDDDDDDDA>-"*""""""""٠PEDDDDDDD$9[ (% hѢ״ "00r1o.""ׂB\hܔn\G)3*TpxCp8.z@]kڎB ]]Ihh ݞHNeno UDDDDDDDDAJ^dU:#"""""""rRr0X7́`ȪW98*¶4H>oѳjUpI[GQ}^m'2|MQNO/cU8ES5֕cDDDDDbV,6+VQ5hݭF\a~\FH?lʵ@S9 GQT!B"@$ErB[iv`09m!_NBޗ_n|"'MgyWfp6 XpM[cq~uQB>Jg#syC'E"mxլ;D<}ZjbMu_u?%{bWXNDDDDFGzSjGMe3]z+`v4ÝĮv8qn{',ǵY'#IxdەN&dG*Eooʐ*AX_a!o!dl6_*""""GH'~: eLd|lH/˽=6<_C0!w=¨>i?o="HcD$܊!Tz'CF 7>|q{O Na '6hl˟X,SEDM-B`A,"sI"""""ב;qQ(?|7y_4r~Xp6S "%q!cv2+Uls)5[!/_O,""""_6;)IV/KXJs ,zѨh$ U甃4ghZ>TUX]i ¸{}np=7ק"""""W˫xOy罋,ѓz2:OD&""""""""٠PEDDDDDDD$dCU4MF>TɍdBŹ8fKE?y'4UDDDVPVeW|_- 4+v%gk bNcH8ɬ0I5S=e8uŜ Gq^| }UϬ=}~pt!wQs]jD$o0HX=ϢӷĂwx uBHkNd뒱nʍ4`437Pw':*KZlPD&ɱy gyqHj3ǢX:]d.?d-'LLbݰ ] #l ֕EDu `;{8p`'pYpy Cwd?˞vOD$'T:ѩS':uJ>XL>#[Fa0_ zgɦՇDp,ݞTכә>?,yׂĿ}df#"r]BV5Lllۑ;-ϥOdŁ=GY35+LyšT{e㉏;¿z'F7b2!ב/[0˜zOvǦXmS7 沸\/ڗ({wRvv\д$uڰYXm>+ӘHRDKʭLaMժBp'cTQJTbMȪ/+vJ(nwڸԍb B?YɧNx[FS<)#N+C&}\}Ч'c ]jwͼ&lsxxsCbRe(&Z3P,7^_!MN=ZH{>f}$GdKz}%B.ѝ_xlcz >kjVNl>ve 2PEr"-ZĢ_7ŃhVN׆ҵMgJ1b¬Ihv"[ܧ9DO:6EYeO{~l2& Nm>l4 \)pH${j6S2>}xb&Lӎc?eMוЍҶvi t̖JVD: k)3D6=dǿbEҭidAI7fT\ZP IDAT2[C@6~T8VgX]ޏ>ʀ)C<ц}\S;2iiƞܾpA e_IZXB1{}.__̈́'gfdhVoxyޜqH9~%TAU|hkB}:lPr+1SٽtMqiuN2 mc4i d%clg=IE?'cj_|pC1G%* e3Lm^҇e\C“?zۢ^T&9z;|MP ZԯDA?M5vcpǭcpz}U@^K@9:- :N+3a˅>3ŗRY5;+29Azܞ+&Wڃ Z?Åm\Ka7w: Fڻ!x>|E޷wgP~3]})QBbH549qh9a&?۴GH ^ddW!|-;Oߴ:En|:e P<>l=ϧQ Mȵ@Eҙә>S~9fD4~|o[6z g ΋7mѮbC:LxY xnS""MWq.bV}ȼ{Ӧo+J=!~]U/n܆aHɪ+zyiR&TE);1h'}" ~:,ӝU3_R~DJīpKg;uyᛥ ) ft=CҨik?* Rt;hk ov-^*"MvN׹yi.# v4eq;]6dmnvS]F;wi-cssb\+ןgk>4 S"""""""*r]9BrQܿ!C-C*څ;t3DDDDDDD9*/c'EDDDDDtN!rzN1DDDDDDDDAH6(T*""""""""٠PEDDDDDDD$dBlP"""""""" UDDDDDDDDA>fN7d=̟3; """""""7<ӢyN7ADDDDDDDnB#""""""" 7ArL#"""""""yM> UDDDDDDDDAH6,?ag+r*bX -1| Mؚ2hUȒMrr/s a*CUϊ[!rrLtaFN7㖑9*V""""""0*Ţa?""""""w(T Pr (TD TPq*)u$/AH ٤UUDDDDDDib93Y+a̝NjfGotړNR FJESi]Tb/D1qfޘ툈: nnRO4{;&uœԦ<ɯoBgBVˋY8w;P4EQ?Uv+S̉j/ߛ$#~7~^͊2kL,#)OkSkK̏MW!sk,S[bD;&ql|蘿KG |}C3Q>FH;N9;#Vu1h]G@Q<5?z7&q7g5{3-PώcPP%s""""""')T,zY}O|SGni\E0W @a~wnyG5b{Z VR,d}g0./1֎3s#WYڼ2oFp?)G\*0 ROmӇyB 0 g̡O&Z5 ^,{oqMn/ԯ'P*30'2"""""""yBNgg̛̏2$Ric_V`s A<DC0?87|9NkH{:/ F<+>X2~03CL 3]dZUWjGg2t.,VLQTvLLTmGȸˁiQ:H:uj*""""""hgR󏭤N2%)NͼjkϻKxA?zׅϹH?hMjCS^=p(wPDDDDDD<-b}79[s*.yUDDDDDD$o @b""""""""WG DDDDDDDDAH6(T\\BlP"""""""" UDDDDDDDDAH6(T*"""""""(T{N7@DDDnm[q<8GctSn  ?_~*VM\FHm6XiӶ}N7?}6*VM\DHrqZmi9ݔJF Yr"""M03M#[CåDDDB7A""""ךi*X% """B<4 *WKdA)\ Aȭ0M*WIE:G2*d~XX6w?^ED䦦*٠*"I3֜n@NKMM%>> `W5lؐظXRSSs"""bbbY\un܇eW_ϰ 7Wi|Ct$hc*]M RkGxBH@6P֗;CG2W]SmߦǷv_VA3v^t~:'hʡi떱vR}:s-f_H_1F_wo~BտuVtPеWwwԍ֧ .!nפ̑z;NUZ$!)C5Jz,uY[oӦdž ѩP=q2m k>cPEAv7OXY&L`.XZO15.ޮFr80Sr}S0-eiIKw0iwqKuCjPvi}=z 0t_4:9Rw@h sHXt'*-,I-t&L @Ǩǖ|OXOШYe=vpx4 R ACs'\%_Ճ5ً K'_]9 l0Z앗zA@U[ƌiラ9/ǚԠtZatţ6WJDMS?yiR\sҺQU PۚQhL& ghv_V.iZ,6=zT5č99Vo}" f;$!(A޽{0[I;Ub|N4[iȒ~{"GSUf-=Sz)-GgԳWi\9)3VLF~ch^wzko¾7ר!kԐv,JO?{9PnTTTwފD&SLl.޵責e|In]Ѯ'VG[6k:=0yBj1j$/T{J-c4ᓴ뫽ϿRGdS>v)#9VJS H@6N Wva{yU4rM?貂B6|F'tʹ\QG[Rև]M7u*r.e.\rI=քsԄsl^O W΄9P>TmF[o'͝? یڀоXw`ƅ9PBV*(`X6P%q41G֎PJyRN~5|t*llJzO7VPH>}lj$W1^qO>] dU؈Gowt9]BAoѥNPmG7Ыysut9]B}ԧO_f.t2>Ta[8~ڀP UڀP U@'!ThB6 ThB6HutOU7.]8@k{k䨑] tkm>Y KmO^]j{ם7Nyg;h뭷.QUq bt9g?Pe:: n?Mȃ%U`6}UZ,u~왳KP @:b0l>T*55tΕ@wÜmUU"IE?x(sζG*wi6`g^+.٥tsζ ԰vUWiq}Lf檫Ci\ÎQ%/m:0l GkWK)7t>ԃb1.sζ!TY׋g !.t9ʵr4~ uι%JT{5k 5w,͚9Csג6tۏƎӗ8]?3 IMxwC+uѷh޳}i8޵zrjcaZkJK9{waօ-k?X:^:&OWTkvқ{FVA = 2DCw:B7 i}|Nql =nJel9g4oʵw֣>t~>긯qC陋/S?Q^O>V2떯mv$؉?MSu9gɽ~kQ+-7]ウ@b i}u6e+7ϔnڪ|DqJEv9B;ߠ@֠o'n̒9T)r4noǹD}n}6WccK<_ܫW2s^5'V<'RʥghOu:qY:Di_sv3*k㼼Jֈ/zWeuT Ã[ꌧU)j 5giD;*fG54 |NCz%I=׸dZ5:w5p{|ͮӴ嬇u/OBFO8AN?Lcz$ѭ'[S׷'=CinլMg\mYe]{y)S3DZV.ԋOu^{HIR^xN'^K3TЬ78TfU gy*hc;%~Ts~[W l~s}Zv׏tٷʕyZs:|;?:VSVrld0}V5zI:mTE5Z4wnҹq{RVE~#%'ˌ{ˏ yt50s^rj$BUxx$czݚ:wv8C^5mQim9gwÞ*kӇ8P^m9L;+-3J+WSe-eժRk麵omC/S}n"{u3ucaOT88#'_1X;}}k2K==Nl]A2A_w_>:Mte'h|FNK[̗NЄGm45u=eaz=9t }fh|a ~1?RޥU;jN=\-rRGi_3smH1O[^i'_v?X<NZPA3=R{ﱧ>z#0upiN}鈓=]Z}SY۬|Qb+;[J\n>Yު=6EIP+*iKl+G{~V={kY9g7Ck WyQEeR-!J/R~ɡ^ VuYlB~v9t],Ѕg\?VxϔnjaH%hƼ=[TۧF65imrU$?u' +~rS4Ik'}Ýd>B姧jJK[6^UՕZ-IKq>i;alտ;ZO[ܨZ75l`րV7t龍.j/)ǧ!֧ut+Zs_M/b¸S9D{Y|R}te.PcӐeU[p*RMϱ: n/*mCjԬlnz{^m6II2eK V[ִ"u_>qАq1*ޡ\rn3YE??VWzYc^^VIV܆jU,DU5zOsϴ[*^ohF=4d\wNN k&*my?Mu:oU,&.5I*St54XFzҪw\_~?%~d-~k~E;9D;[|R0]pa@TǷvU RQsή?m꿛NiMS_:i`^LSWy`ʔ%Bz'sUߔ(4-G/?{^{RZg-ʖk&UvRH=W+缏TضZ~;똽onxJ]X7ՇoNV]~5ϙDz3ŋgқjcF_ݦ/VbR(,Vݔ7ɪo^SG萅Gռ&,Qn4M~kt@űBa[RB<@M<7$L趇v,o[˝j9D)Xf;E6*0O?ugM:w/$^f~\xC'zzõl:K~C::hQ?Mk~uf;ǜ>KEλ@UTmeܹmC5G/ۍV[)7/aެSFhiD1տv3qYm诽փ?d#'L40pA쩲,׍1XILTUSE(G)WTҔNYiͧ8Ӕޗ Qzxj_zF;r"gC~e ?A a}IzZކ kքKBs;\:vc_(t}`uƤ+'9W\ Utݿ.sN#{}]{}qI4ɇOC䳍!␓R P%8*+X%Q&-l&$T,*f{3eߖs2:Gkttl9/Fo7fX"8<}$EHQ*&1\ "l:c~k[^qkWѦncCZռs]}msv7*]ĺ[ tͱ!m9gwч*dpuJX4@ud1sF߯ӻy.c|} fz7էwߎ.2,sζ;UF'OփߧOfrVG){>}5r%6n]e>Y mч*4rԨ.1ܸmڂP UڀPt:P UڀP U QGn{]ƺe2fv]eRݣGG96hNXG:@O:} @ @ @A xt544h]Jз__UWЦnѥ ExtWTi}RyFӦOאM7R EhXܠBGҥz7B0w\f9s#:vG:0#XYι.dU(@U@0#TYG7R!Thשk]w/TH$d%;'YvzeZNVYq:CЌdR3e; + @a˺S.օW_!^{\=1M;qdߕu]+Z'*,e.#ߝM-_OȽ&9C%*A <Z=!'^}Ғ5гӚO|:{+7uWA4]aNgGG J4*)S%?K/<9]O)"1k`_sl e>}U7M}Gw#_U9gkr:kҳW7詫ս:Su~k?W龩J]@;4蓙Rユ-(5W D ߺOR:/꽻дI2yis8R=jrߪy髌tosN¤tN,q?Xz+_MC"Yh ]b5͑}X={'ݥyZFO8Z_?ePVs]_,[rܱ5Qٰ} A·tL *tRӞu/kj 3u$%L!x0sƦTw5}On 舘;EoSta~y%ʽk@? =R]0T̪{2(ZKJ4먙_=7}l>z[tM)g9]i9VzDWwԇZ$jI}搽48kWiՔLzR;IerQӿf1 $3/TRקAЩ@,YrH:4Owg'-_ V:Yj\͎:7֍W.BQ:C6Q:$u~Ezv|y~?{ r[nix#e}4|잚pB7뾭**))hW=\_/X>3iСі9GrR^v<^U<fԷWqv_Ӎ7U!THTTնsw}sϵ57$}UU(5mҎ~ٵ_Oڀw׆PbhuP"KqHr R8Qmm.$U(BMuzMm3zErz-Ttt)%A@6|3M:Ux%͟jk{Fm6d5nX-Z0T>:}|6oС]B5n~o|R)tPE]mlk*~XWx{wUүtP莖].qRXeAm:}JWH@qVg?]! *t[?%)P-YqOW:}̺**:,YNBRx#g tt?]!W̒tVPbSA,$ R!|RIEsQ^VUF\l&IeJ7JrM s!e IP$*X SV\8g}][ssufL9P8D$(`3s!e.|9@rj\|VTi-i7T,eQ,J I 6YTNŊ]lq\ޜ5(ŏTyŹayyM/ S-y%\֜F]l{T0YS9CXsRéIk.ij7Y_+`#5ͼ7(3K B:ʇ|^!I)N`୐Q!eSRF(-~65\Z ۣbIάr&!]c\lF.Pp YM!x QYl,@&Xv=pߛ)?J_n3y*veقTe{s5ee2ɼ+ҩ( [>+'r >BkC%MbhrIy˛Y!Q\-xOR>|LI,d)e&Y-UXcɒF[m )3-J=FJGY)&m(L̜7Kbʂ -b YL>(${SpR,4Kɻ^7K,9 B6}SPȦ}'b,N ҩ3-H!YST;xԒc ڴzw~\CWtOmʲj͟߼{ $B)Kʒ.qA.JBNI J\H'M'e# i:|F.7) YEq>),O'e I(/KBe?`L&,Qm,9RQR*.ޛdq,13/OB>#9s>BB·Q\59) #T) .(G[9P ILXY"gI+ DTgTFj=Ti]4_V?y Pu|Ycr{3P0R!v+2>m+B|ZR*x2@G`A .̬*IBާRK,V$,kX BPA!T6,)nuKCCeUY\bu`=EU34LB^^R*JDZ yD!I C,6ө@Pp )DBҲJpQ ́O,(bkP`BKe`sk-KڸԎ*.!>W:I՛yP{*C"RVN)s IL)Xy5/9RD Xb9Bpb .Xű,q-dX I,Bܥ,uXTڼH %!U,f 2qK.r.w銠F2HTK.eι B]X&C;EQc' U.\HY|\'`A>ݼJ$Jgbe-i4KBRZ!KġW.xP.v:glr%W7Yn`sS|&__H/#/r |䜋2O;/I.8Oɇ9r.tfI.|, )P&K=Tk TS,)$TPɇE۬|xXҥ2Y^KXB˜IR}B2^RY,rY)],c.qQq!k >D8ȅرn.-g ,``!%IeS VrR]2Jy{OK.**oՍlV_+WC.TW'+r)_ܱTzNoJwE2D> M>]4$jTҾR!4QbDe!JrD q3K" ByOk-C|0ԪjlR+Tָ hmJeƹ\|:8*w>r.Jr>)8W^^PЍtr9Ei$*>6K"(1s ;1oVTRe?K=Dr`e5&/K/28%')RrIsIJRRe URI5JbYTfˢج-bYއ.Ț*$,[J1nJI@Z~_0TL Ւ*R2XhYrQK9Ud&$eڭ\Ĺ /)*efrY͚fȂBHU6e3qN)PYH٩j+r+lM\BkQnLiS*GQ<*pܰTB!B!va/d*7 0cSFkUMy 1({&(_.sP0Fm`eNP̯C[E-p,vN+qyJA]K)E{Rn\`0H"B!B´/h" z1Ƶ,'b6^6^e̘mz p#VvhRԳJA T Z\J)(mhˋj *ˍjתZKŧwB!B!ة^UaƸV܈qus-<'jxxq n*Tqx&sQ+ܚ`ec^4nb^lPeTYg-~G Tv TЖJTVWYQ,kmc1FB!B!h amL,gkpcZ[F{<"aښe@8@Y<.ATlU}GQ*MI._#>ZYvZ[^L JYc6(K)eArl~Z,=B!B!DC<kkgc<kaVj< 3{eImNPeRuw9SeYnSv3 ںҵ6Uk(U5B%A)˵c6qeyZulֶmYr-LB!B!vaծ\1V6*E_m•gS=_(\-m݆~̝*Q* HTr[R i *\XՔB",Vg)3ʎQ֞kZiZ<+B!B2s<3϶eq{1m)42P+%x&)$jY vgCuw&>AK\GivGke\>_smWk(V\"B!B4{SN\񼸭-񘶔9ʶS1𛨣)*J Z ה.P5U1jmhH!4kP$u&|*. TRQhPڳMѶҮ,:gh[ʧzW:O\6*B!B!.L۞z`L1ng8xmOyUR1.&XDKe7kQ`֛ KRg__ifM(Q!ҞeU򣔲0ʊFh~mF\m=m§m$TB!B!va(@\*fA bָnX[qLܲzF),l -1yUjUxKUrb{%kN@i 6* iKJ+RnLiRvģU&ֶ,km^tȱ |*dReB!B!h<\KQ*v=4z~3V6Ľ(D=K=R)mguNuqۣB!B!h lVTxw|\cke\17J ύŵ),NjkJܨxډTȯ1JG'Uҭ!R@$p(χRq+PRVk Z[ٞ6~˘F$b'N*Y\aB!B!Ӷm7}wP9ј1^*llAc,QGRnL)F(Wƥ*(EѭEj s^A^ QhюVڠVZkc _բʇ2*Y WTlkS1c UĨM_ B!b#Kn! -٣Qwt>Bkmϧ>RvZyR`xQ:FF^v\8Ze/DRae-iQl,< ©RƳ־ :uI,zF=6%B!q㔕WGNg Vc(g…4IN>^g0r$>0-Zb2>NH@0[:9gsLW]WzyEEխ; @(McMeZ!DBFQcu4^ޜ4k\eر|ŗTVVҩ\qtСg̜E>}O˙7o/2{t^{ +Vp7USo]9O<_z~"2z?8.  a7]kG;O?R8_?N=u/*'~ݻsml! _ug>Dnڶ{GPYYǵW_E,uZfd3Wvaaa͈jPTTDzF6]ooo߾uڲ.\aW2vX&1_zX,e7t6TYW@.&WWJN~p8BNN?CtKYiIpBGaLJLYi67BC4Rw@0R{hq̙3y-֛ .s$$?Me,k̞E-Y X!q 8CVVPw;sCxgn% 0`LJJ"F3ZF(IҮ];^=ͦL{IZhɌ~nUV+z~Gn]yڭe%%\N0$!!?U5wr-^ k?bnN<$ (}ɲB4|}FOeyyx,FeE9SwC%vG)B 3W>KiI w}7>uTV1m*gȑ|-<` 'p6;#9'NAg0gVXɸ o޼%ś]vCרCQert]}@9s0y]"̼BE w Uo =+3Ç\={hw}7&IDx;/CYg\vmۖݻqAѻWeJKK쳔r!2p锗"oG~PE)#Gr{uի'Gu))b1 rs:^xET Wҧw/O?LYOrV.Go`2Z"3#Z7unڵ[nxM4hEWml! _u1gO>e^J(\]PsܲM+v0έʓO<+yFTԩ?ЃOsG>=p=c=v.**IJ*/HIKKa>*-<Χ*Pݻ\.*!֜DF~Qn4u\|SgGA^.q F-J!a]SҊ?c_4ή+ 3X]X}ˏSrp3d_7|g΄)+^@vv_5|qkXC=ǟ嗟㏙8Mzp$[ཾ$|-rss#:#0a{.?pdg~Ss,lB|Hx,zȡvJՌTZF7ϸnٱhcqgq%ҤI*&Nx,Megɧfesi^|e>`6 s2x׹x /ݐ55UfϨ:P(f|M0dժ|>~Ϋd|>c>UCA|vΩB4"kT 8ӦƂK.z<˖"1>F>0EEkf<3~W5g;rW6bb:vhυ^{SާytޛYhO=4W]s  /aWṛ#cB(ǟ|n mٌ Ocn^E:w))YSss=rs7g5e/1clqc)^U\Ыѻwo,Z@,etܣ7t6=yd{w cǏ{n0~GoQ .|@UWmo5o mY4Ieq_ezôiHin[A !h\T~kC i߾=e1qX3Ϋh^(YSDn x|*++83ٷO:>u҅oyg֩{7yeU.]LFFFMPp K/Yʞ]R͟sf3k *uZcYVMqqrWлWOza٬;urSe !hgƶ|c:¢•uib挙3n5Ed/_{@iq Kًu̟67 !gspOzoQ .1j.vu,IKKEi͏Sw ?NIKKj!~9<o?䥗_f^3fX^xE~u:˖-cڴi<ѩSo~Қ6.pUX&|9}V^c?΢Eoe]VVƍ7ħ}YhcǍ㧟~# ##p8ٳ)--%q,]s]~a*?S[fe1}tKJg}μys97}g2;tY~S0,˖-c=yf-a3~~N @,y]Y}0i6gXE/neG":m~E"m.ߩ-/]B,#g rEe7tw x:Ɨp%99m0g\gxAgdbY6Ҹ:߳j*wFrrv!br]+TFիIKKcy^sG27x)))!55>kΟ5{6%%%6􀿶T?oJ)ڵkǙ[wbb"z}1nݚG䐃fM2JF>%%% v% .ƛnƲ,z jʾyx饗9Ci՚3}6l! _>icģ1x_~~b+FW5ePR\̙3l>13 dGp[A+lˍYJVF}|ڧ}>pQ[:x!g4:YUM-eK79#gŲzyF=Æs-Y5tkْa]̙lz:W S=x䑑 >fe񢅔cjvZCNNMJr2Dvb!Op]r IDATu'$&Ҫm{̛@L+/:A)5O'%)m:;}(!1 &_]W3KYx!pN{uZg,c.`̖nFYSW=SJ,#d|kǢ)*d_4$iS,ˮRyF&)iMJx?Pޢ>fK6;RQ^J$%7Yz@nJ rj3w} %ѢP {ŲM-qg,--{ТE (`\.^Lj&[gvj݆a3}v*rc^1%^W6:\yEʋ{q/(7X)3w:nx17Jmg&c.fDTC-ˍTYpwa6vf_h*Xt)s~#))Nk i؍xa!Oe TV= WPQYQAeEFϩqux!H˖lVV:?o._>;V[Yi e%uXR6q}ׯs$\%YצB8g\UP%K;wU}F)hw˴i :~XϰCgnFmӼY3RRRhӦ Hqm`0HBB>ۖ9B!Bڑ}F)qhJo^}-.i! [l.T))u !B!u>n_v#.+B!BI"B!B$TB!B! !B!Bl UB!B4uj%TB!B!!B!Bl UB!B!*B!B![AB!B!B B!B!VPE!B!b+H"B!B$TB!B! !B!Bl UB!B݀MPE!B!b+얡Jl8.{*'Ⱥo放l[SD{*'}ʷo`ݗrJ~_lNS9wal;(B!]3T-gerJ~u^'}YϤ}8s*ڱM;-29N{*'?Ro3/rVNC:>Qv}`t?zU ;ڎDk~QKsd_q;buCI"ba>a$VB!b7ahN葲'jO\=svgX4=b8`֦(9%891Q6zȣlTlJݮiz~{X+cH'B!b} ?TنO I?vT[6+z$y+Jcyr=i_'/^fs(lѕOa:a/]!T/bvCMwK}1e6s3,Uk/_p ѹ^0ӂ|gx{8T0]҈}(&|7k\nIs9%Onٌrc>8sQh{st14qVž.D}e0,c4ۏʠ>*2'ƌy񿮡Wr>`7o2f"If1{\ }sQ˙53uYGaCVmȈgw2)ϐui 1bF>7>_>*PϨY8_& ͺ3ΙE^9r yP6s$ٻv|^XmQOpڄdzɲcmE')YCrG.e%MxOwc4{NH/{ы.[4ňc(qygL'' l/,t7>*nO1a`(?LGţqv|F7CWĒY7B!bKҡ @l 8G0d+x?0thg}hS}?L-TnpÕ,RҚٶ q4|(֝Zdq!sFc͕wN{ C9;)>dʔ q S!H&yڷN&ů N:W|h#8hq=w`kpx~yYfŞGO[9pgQyU.I9`:^wFۀM|M% !)-;к? {Ch؉x)}|Tzt{},0bL{6R࣪wB/ˍ-oAwSPBY mڣbYqo憁O7ކ>O9KJz,}7.!;n|rʨz/ xО4P3~t DP#MOC5W`B#L} I?\-\u8ǝS->p0*Sfw3ٯ!e,ʌ83We)EF(J⪹Z:kZ}ϱ0E1LSHߧNH9,a~9٣-z|,%|{^d.]#B!*t~eO GfYn:;~-=;`i!@|v#,z>^e ЃU[@ݏ)o~A+bܟܿ:EyEL}IKdTR WCdKɘi0k/YP;RAcuiKc&e=z.@Df}/qٜ#ErٵY9{Vm64 FY2!쾣HDg~[?'Vrwޚj0qJ&h6p]gֲ>AY :5oIdB?={Cd6^yjWN dᙦOr)q:n:*y;q\J4iM3z9v~9v$}׃$2Dv2yZsxA4UK.B!bw%z'3ߘ/%}:@MBVGB_}OaHt8{=(ƥjĂNciU9nG^S-ƾ>= &Ђ̱=SY?R|fz S!HrnjqGߜGc硏ۛc/?)cp/ >[O!yM^^Xq=\%t#uL&d!A⣗ާ3{ ڬi#* Mƍ/&&!::OZ lT[)`tAχڻ+zB>.oک-jCt-Szr]W}|]4K[)1li|Uތl2O&c&LJf`{rҐ8}']6w?? I]ϡot<=ZW;%jpɭmIB!Bшl\w tA7T,nS~+hbVm1Vʲݨ6O1?j`A/dLF'JLScr9nbL93[Amoy뮙ǹ/)U޺[7ۜbypD^3,{6ǎKd^xEcYl'.xsnIE!BkeC?wRjO־'ӷenie8c^[`'p׼_0~'SS9ju}Ytr):/g?a~GyC&21˨yknx_~/ƿB!bk55GqUUmpT>!w|gyLbO1܀K40zag$r}8Kog|Q Q @t#7q n|x?A됳ɍ--!Gq[^}8rey?H^GsŨYvd}d|7Ny8wK3vEƹTZ^~!g?ɭ/Ny B!eҩ)z\gjiJx;}ɿCv(XɚDĬi\6ҍ̰p+Sks&r%W}uftM<^Jd;wr2Ux 5#'.}2FVƘfxIZcRp)x5FB7xu~^QI'rqRl⬜t-7,9Nyy8͈R9SƍG'ӮsjG3{+8$*<~.?B-T=++01݀۹B?zz3K$oΘ_,D#K'݇2ao4Ͽ XY9znܕ+Kk`Nr\R'I( {9OeZ _vnCOR#4kY, R7_eв" y|vh%_ qzݲaCoKye˒a8\aw|Ç}C'X.a+x;-W  :qFvs4T#^`T01S> ,[O^pɼ4j5ooI˛6M,fL>_W|r`$"U|ѧl>vrei$o#{lX۵AoB,|pŹ)龥*?H|KdPgoJρ<׼p-WY¼.R7&ٖZyǯڥ\n2V` b9n fi֩8=?+ 4af(\<,W;dr_e(h(Z?3 >u /ٌ:8gŵh<:1W } IDAT6)8K\: q]?g* Vu`Z>ںKlDRMfoND9C[iy=h?qGl{p&U*ڃвJ> Mj=kN*F۞ld>Yav;6TIO$ U"}&^҇5nty:]wuc=,rINd%4̏'$w؂';;?r]F![x5NУs>9qX lBC>H[X/ [66 {SE50apAe^4޻? 9{Eq\>Kުٱ q\<{{ߠ~n]QqAIzn'>ޝs_Lws,D^B02'ˇЄ;Ҩ\6đu {p\ 3xm ƏiIQZ{{şA})3 yeO>h.#:>ֶ\:d/[ҾcS*MUj= &l+li:.nՑ+I/r>{ȰnK"""""ܱʿG0P?!aȖ3-*M[m>7f%*/bdp\<1s5hE}e|>a fÖ-Ϗ&7!qחb#Nr9C!+8矛ە?vo8-Ifuyh9Kr|g Z᱐rzEJ(SL]QJ4Mٰxm3nc`T{K xlvkzuAߣ3  A73?mVO4s ED-})Ұ%g|9b F|$!Hx.kLj'vORbwN\OSbwo5 o>CB`f4:r~$#VruJVܗ[{+.ȣ|1g kS@CDDDDD;b%Wilk]m簭m9yxʆ?z*vx5}[B*yr:u? ݒ]T5꽼/Fdܜ4-= n5M2韷״]B0y{$ُPG>3S/T3VgR1/o8Uj7%8/룩u+=|ROS<8#y#U/B0/ɝ?Lb\nމwM11v4xv^]>j4~JOtn-=y ~Z\;cE =ԌAW'Wԏ+9~Eh׌"bAlIjEDDDD^XϕR2?G1>ϖ-n6wn 8c*dI6*d|],e] dF UDDDDDDDD! *VDDDDDD?œ5,d> UDDDDDDDDAH:(TI*""""""""PEDDDDDDD2,p *""""""""PEDDDDDDD$BtgtD q?ÃpcȫOz1@`7땙]亏X},.٥>jҮYY5H?$8^~ Zb[ 6ad|=T5[,tπ]cN $h\ U5Z.sY`ww~' lf}~Q ֯|S5e mO$y)O:h{iq b3$$x&@3H}v햰q@$۲E[% O#`uy FI;NƦ\ómdNhc%'j7!&aA,Ll% &Wwy\3}qqfm7ǂN+?絞MRĂb`nQ{zl73[B+jl=<=XkE VEog3UEB-fbu1vtEDDD23*w XpW;̇.աrp߂_%wye'x)|Uh<Ղ{7ʓp$#d zN&Ɣ/Ҥ0:^V3úo$aV?p一~0 @+ [,f>m 5V/'&Tȍ"J7χcKFJ?`P-&=tIc J}{f:s!p}0mge7߀vqF@'h @[{.q)1a7?|+Kq8C̩hS'l{k lB7MCԁ鴪ٛ{+1zLFmٕOy~G yrފT!+0i\?w‰fc7TH~[3M_W`Rw}P%1N5}g~\gaڛ@,  50`2sa P=6f/0ip& =6.m&YP z=/aK#Wx86EI"H11da>`;]k˼ǻo0g44R fHp S tkOS>^`/'%W.Orx;mDCdr!l*|.z U牛 =`)h4, }0&,]/&_|DؒCN(;%tcP&pv#}ىl<ᄀ@) A\w`R@Tu]o=NbCM?dfok_ e׌N Lfqn<&2]=֐{hk߈2WכS"\1QύJU9n~n GׁRg9db@sz~<]f ̹b,%"i9gcmd=l\ Le{ .ZQ-sMi{,s#4omW"7CCQy:0`wo`wNޛ@pq_,t)CjA |_LNNBaQͼѴX`E ӒON/uO~NJva?7Xyh#:dyw0eϳФ:}A]X<9~a9C |>>EV*M-My?7u)|hr?l<_Uݼ91 LSoIDʝ|0s|0 2}/1>qP FW=@ x rx0= VoШ %Hv_ Ǝ2־yw+{3A-TY= g.\0 œe20Z &R9yw 53ty7ژÏn;M sf5cfR(t+SuM.Q$A6*V[;^ nNtN1'Nni<&at9,2 x A|_jW|x8n_v5cI=x;yOb<]߅u U x|rQ2a_IN_uhKG~nZ1^yAsPg Lݛ@VC3dMOK#ڴz =b 8l~lvfmvKfw=6g[~.l6OkbsXs,5״{ڜ=} ;26oJm1źxt5Cfwq+4GӠ_FHD2}q3#}LZMqH`\7lprV%SCi޶f#o{۸X.KF突vZ۱DFˈ{b8 tYNmvc.#v)ws|8ɤO`[·`NT "rgR IDATӹ 4#|c%B|qQHVwJбRFBD2+ܳL~o1 HVPEDDdA姆q#/sd?""""""""BtP""""""""NVoBtP"""""""" UDDDDDDDDAH:(TI*""""""""PEDDDDDDD$]ի]`!!!^WzBt'+ """""""Y T|BtP"""""""iX9e)?t~[Ǹ'?KFFR䶱gtDDDDDDf\\> /bgsOiI:)NM.7neC=ү= LY¸I/. 1 wFWS#x|aJXҷq,HH7oСBZ Y8{3fZ7UnYM7-izNp4iӌF|nOED2 <{x%3P8x ?ә.>UxnNt]q<1)~'oⅇz%2LLj)kQe]K.?<&ͦq|;RBC^3QםB"G=UDDDDDD2_ ׆>-Jո5y [z[58mmNk_ ?(sY0| 1n%vɘ?@h}v)Oqog~X?ToW,mN;dF UDDDDDD2- &#Jl$YnF|1e%gE'SW) @#k1>\OӢnͩ2uiDcŒ8%ն3 jhHe ,p8=7_rI9uw伇Os͕m2}_[IM!retM2?BBCU-:t'44u-^n_~%vm'N &&/%W^̙3]GQwkH0 oP=I6sիx=wcIaX R5~؅8os~29lا*ڗYJq,v/v4[>̛Ck4wFޝ,UiGLj[vA=xeY3(peO2{;öh5o~˕[yoQb֟J->϶E)U>[?sC>Ԃ𠤗~kB\ }>PЄޯbH%_7i\b˸Lm;s@ ͠ =a<}7S敵ڳ^`\IJhTKe9s2t[NHV`aZfx\?kVU]:gN0.ao/TŚʝ:j5Gc.)Xr]jLrϩuб.U)_-Y0N&4k.0"vk~a-d:5RfYnՆj\*͛s=f`-@:չdrI,X[kS(oilCq]1}iS.'{ kU,}叞)SMr'P""""""x\\ۮTۀ(/%]/(KBg7,^L}Vw*Kd\z%84rQ _vV0GGxN~:W<ƛC3hBg:OO%}蓇mI:tS Ӊp1\8].\[t|(>X祽,9%oL!_?nyWLgŏWpќ=޿Дq-꩒.Y ǩ/ҹz%*W #yt[䮲})H'nXÑd'#Wbz ޑPByXsPm;}うctƵ*X-֑ǞR\%- ~T ^f{b8 :=J~Ғ4Hff iJ˭T3TNCSwHwk=d90@W-ESXCNGK%\yRO2wӓ , 4Ʀ)ޞ.O1al黔Wp%x<XJllly]bV~[oŭd%B,6âoĻ@PeϬEM6$YB,B3jOsBtP"""""""" UDDDDDDDDAH:(T9:1{yVsv jUeyDJ|!&|xWVD,0iρ۹IZ6.5e< "cX 7Uyo be囃<'DJun.|!=ۉ^/~pʇpvIۥ2ƗǢe"BLχ=m^>ϕcӿfʼ]{v0 9]WRUnx?E|kl[RC݁h1'9Y{ +NkGywYN tŪg,b%O&~}C*9ҴM{@wʔmK[MyR\Mh;чWʨJ a7{ٽo?XwS o$e?R""""""XؽՒBXGD)=bz5*rokn*wߪvqR_.VVo04n؏?w.-澛sOΛg[us_aVBE*DZb߻н~hɁ)ޥuVՊO@>7hBو9y=0K4*"""""" miܾ/c>ɘ Ut/!wqli8V}Nbx rxnyI~A\zO[N*-Ovsx0+օ|ycXvWAV\ї i^bZC2xϟOfЀi_8rlw7sG,:Q6(7 ka{ 1~58 E|۪ djVBKWB `ٺt⸋ۆY:6)N䮦}jUt oOê/YDj$+S""""""Xl>1p'.Bt(GF8/OPM4m;^Ƀ+U ߀` Ezҕ?o'[9(l=؞;~m_0Ylv ɑ[4Wy&w&JHf:9q1q1\9Ek&n^9#aMuqwȻb:+~ˈW/4 0OΥWx@=[ Ía8ϾD{\صyo|7DqtF;W㈹rLciZ><..cp\ lk^Kqrp rcav]k ^e7 oIYc(w 6#TQ!wŧ{ڳ/ &Uc骱i\J~nTBE˾_§j]?W%Z[uS}p= }jIh7:?E%_UؖZ+ɫZ4 HJtpR% d6/U @:PC(UXTMVh@~(UҁR (UҁR (U1cjǎ=2nn׮*k̘5{ٲ T{CW{wGO7W*tF>c(Un$//mۍF{$ՒT*HJJ۵~9rDGU\\\ׯKfY*X)bŊr /p;*:s挾+YF;vrY޾z$)**o{yyrjڴ6m… ;szzW}<y*lZj>mڴI;S__UXKŋUy+W^ΝW9s>"oov_ӵkue]zY11GQQ{H[Uz쩰0yxx9ۦMԮ];hҥ/쬿 (U`ٴ`M8QG$P:UNJI]NFgT쁒wv]QQ/?hڼy6oެEꭷRVܒsNmV)))ٓ  dq[nw^IRѢ%TF}yxmhT2TL%uW7_уzkԨQQRV-{ر}g\R$ 2D3gΔ$_H] P*ue02x}F?iΜ{n5nXzҐ!Cd6S?~7k˗/n˝;+W)nСCzꩧ4sLyy⋽G_j'V`?)S{h4jz'-I:{5ksR w}Gۗ*Y`_T7nT~(PTc~֭˔Y<=Ժu7 |TSO=իWE:qDZfJ(9gpR˗UVWZ 5~<-ZձTXi7WU>˗/+<۶}`p۸˗ԯ_[%%%n2i٪\***J#GtaR ׿F@H͘1C^^& 4֭k/\Ry{hܸz$?FMhrzǙLfk_6YgT7rJEGGhђRr8zWuo .?\ly|Z UhI?~\k׮ufT SP6m$UndáѣhϞ?-Yƍ'4`0iF +T7-[( jl8&O~[?~P>`L&:OݺS6lPLL̽ [֮H.NsӌcOS?׬@o=U\^^&ժ$oͰ+PYr3:ܹSr ce0vfMJ<{ $%%iΝ˦%B\G7~Yܹ}LJ˦m۶bdr3UM믲X,*[FޮرAǿ9< )T$h4+99Y{͐s@nbϞ=ҥ+4޽}R?0Z=2t+/IڱcGL<$=*I*XQeڣaú~6l*U(PT2 [CPP~ R#>Uٲ2V9$I'Ot@nܹsܹeQ8}ctbٳJN>1g pHHH`dq?~S?"-Zҩc$%&&:u@y{`0dc HɓP`ykʍ7>,rL kʔo2P$OLfYLpfŋp82u`K2m>~*]ʔUE;w~y{"v]II7wV11't1>^/___ϟ_>UBUPA&WJxL&U^]իWwuo@*nBp)!99׭[Mupr2 \nbIQrl9_>iz~9sh#}|#]}QB|^tu< =L~ &ٜ'p y-qCOw8V:*(P6''3O Pk ڮO~\$]<2 h6_R]i(UJE_͞U[K)t|}%ZP]׉Wjxg5kޡRɲqc1 |G}u.MC${ܧ,P8 <0캴yK*~yWzNyL(YMfKׅYf|[gN]MILg'UY2P~iPA3Kգ/NʿS|j5tWˣNjjz^c:bjPLxhL=wjjn˚bj_ڬisԳSye3_ Q'ow(A-jGŚ=/kEUYV],Ufˆnѵ_-Oټ 2^*5c>/'esHx;K/$Kvm? V9 Tv?i]4Y` <MmN/T_7LR[/k˴99AWe=sɣ uEc +>5GzZ ǞQqSձ͙|~TX-1c:C`T U)P+/=fh%Tr#I'֌EǮ9Sq=DEa  5U=FnL6GTo*TqSҸMv*׈yK *v[Qm}s<*IxJqalE|'j>_?@*@*@*p(P[Ct^%/޵]5,&mqude*l}8 hW_!eZOY  >w: QhH50]bꓷ{yU.iގ JqeLGM߶inY}| ν jz#=ӝP;%|J ~e~^e8U3z9۵:0M(<^v*hUӺw룺hː:5<z>^eou)̝Wz!3{&cԽT]:HnL*)]?Q[M@$|3 ɲۮO V~rۺZ0doZgݒI:3ŵ鯶l0Ȕ{K QWbNkS~yZoGl_eiT`HK_x-\vTIw9XF5+V(G6?ZoQd]yҁ*8X21EzSO>b'kc}ԶZ N^{ߤۯ/ՆSaˈ $7fnґ|AbJrtp}m:rǧUUtT&Xr RKJKw:,!Z?}9[_ݡ1YNY8+Jpw^"f͙D~ڇAyjuqs;4Y>'UyCLч/Qzn\)8}ѽmIAajujِ4pA -| 2:ΰ1o9uU6zRty)oQQ_լQ!?,G5M]Π$fivN95cjjO-WЩKJHJҵ3iS~j[G9dYׁg'k%cjfψ*ު}9^v]rؓuA>rMvGNܥKI;2e P`6oyyy\8sQfkZuUVUW) |զYxCW-rz v|G3z?1SܘA}9rʡk_xyd[s׷QWԴ[ӮzJU?N#mTw䟧<}]&}YDuGt@-TyAQK4a8 1jF>_䎳Z?'J ԫxMzi{|{F]MU2~2嘈N*lP)ͮGWVC@Q3UՈ}4_1n[e/nP{A=O7 Fn0EKOMޤ<@95W+=}4G{PW8zLѡUJi hK]+Wiͦ^j}Z61R_oSllc p+O5lb](U[r](U[tt45 QhiZ<}(^MrAVW m*44T} )]\-בOfo,Hp:d'j͚5:q^xu]/_vu,d<;U顎=|Б6W s)M#IR#~0jѢEQvt t1:EK* L()6E3U8j;wjΝVBB㕘Dyzz@ ,rʩz2ikذaJX?}P&Nݰzg5k,=3NZ sPd6A\ҥKZh.]={ƍ`0p(66V߾QݺuSOA yl٢oFfACTSՈCuo^FR=2BTf_hժUX,$ɬRBUDJQ"/G>2)%Ţs;ܹڷoj͚5Zf$v۷ׯ/_v jnڵ)11Ak.ֲe_~S.]ꫯ7лÇK^ )/x26]Hi+ҥV\ʕ+wN Q@w}W3f̐fS``.uWO>^*GogtTBUŊ5Ҵ1NNي+Թsgv5kQ:͔G}kђ^zi„ ΅+bIh~%ITR 8 d7oVnd M^HҺu+u˗Oyվ}쩗 廹b㗵uR``|MuʼnɁGn Wrr4yeʍ I_]#F$V,ʷX-kV<<<ԽkW ֭PDboH5rH5jeQ(UMEFFjƌ2iРuY>ڶm *%%EMl;BծON\Ѽes8-[6 4H=zdȚpORܐfӠA$ImvWѢ%]e߾ڲ(,,LVQ}q۾vu5/N]]Rǎ5k,mٲEGfRw^Vf]nk1^{Mcǎ$u-?}M)v|||ԯ_?,XPÇWLL$zzԩrzDݻ?;wjÆ z'\vm@FpR6ӦM$j٥9-DW^?ŋ୧riyl>8QղeK?^[n$)RB]PS٬Y͙&NH,5Uh˖- ȩ5,Ǚ3'd0ԫW/M>]I Ջ;jXT,6URE .`P6muVeW^ PF_6_^Ǐwɵ*F,Y"I]<<<̚5^6M;v_|!*Iu$)_|2dbccչsg%&&SMS6//jiݺյkL& QYr$n.˰k/ڱcUF 3;ɤ}x1bN:%IV:uꧠ<J(U@T7;w/JqIͪO?AiΜ95o\ڵĉ5n8IRեUP#cTPCQ?,L&׽n_bQٲe4vmt1GZ|j׮Yf_m۶Ֆ-[-[""ĉ S"Iٲd%$$h۶mNnbϞ=ҥ+dׯho1bfՠAGP&/mw]7%-ʕ߫}vu @T7qQIRd)>|IiŊ:th[zT.]+(}7oI7vdU*&%)CJɣZ+yxx]vjڴ6m$I*\OTR%'ҏRD/dի4|ʛ7)`p *T$tfs?<*U:upb"EJN0' QZu"~~[gץSZ}6Li__%}d$3Q;s\ӯvר5ڵ'}HoZq_eWBm4tx͞3CeB_vTSeXu=&VE' fUJ̔*p[*lt,ʢǛ==e4PU:y_XNi՘ yeU{:R*Q<< >_6.D_MvܻȰ_ݯQhBC:x.O~Yt^j"\o}{F?cѱBCkUO)&7xzaz!XwzȑˇyprKd :j^iRMR9Wz^A|=S > )RuzDo@5BBZܤؿq$׺鯫]ݛ%o>qRRxPgkK2"`ZpgyTrt:ZYVhgT1]1L?M-諂̚Y% T*T#ViҺjzm\s묙jV'ʯ<:cT M}Aӝ^`=Y@ f|ΎDVe;C`*i]3J};hU6g1gˍZ,GŜyviZ0ruj`u~_Mk^1^F7[G:WuU)ys*YKuBAگy_?6LIQU3~ъ1=j9$voVou 'F}}]W'I*T~Gz|ޙCǜ%|?@c+gjm.|o~44!=0N1J1Կ8XfP ~IN RgHI2ٰWכVכ&0u>x}TC]˭>ݣsYۿyaln=@c[]SrtWtO!)w~HſQ=iQjdFS|f"k7^SjGpuz6j_֟QxņvӰצS5.9[JTK|C?҃e\qpP_$dwu5kZ|}mEcO?Zz69Ck+:iL9{3;Nǟ6:۪%5oXh?5oLצh+ڬ>ٙ+C K*7sǍڝ^ ô7$L8Mq5ѥ7=ſ87gmؖl)_!0;%h̥ڙm,JӦ^WMQ8E6"U#|풑[󙲏,ꈾTCm״kGU^.:#uݬf|]E2eʓ?d7#U*F@eWWC^._Ԡ6uX.짡3Vŧtzb]X_lœ w'%-^4KS&V^IE Typ =>unh}6׍uS̉{K5d̍1S>+MC9,s}\OԖ7|qf>9Sw<^/=!MC2,L7LҽGQ-{ib]ʖD([ӟ8jH.&=9j?\uui_*RMxKiGb.&MPjһ3X)ɣ鲞itf֞4T:*P_2z2z䊀 &-'X^WiM˦T]9\?Mk+~8_7"tKktׇL*q[u/gv6iΗ%oUc_ꪱ%xS nCq-a߉z_;SۦmS[-:x\F<^rsr Uʀd iִ6P0R UʀP UU_F=F}Np!T,t5Sf4pKtg0=4:7k͚4k>'N҆znu=\۾7W?O)nTT_[NP mnЃF$_ @efs( qƒew֨1Rݡ~- v_-H~fx[co,CHEKimg|]\UCK_2rt}۽ - )&N{<TjN6QTHTK&zUHU+yysvjtS?.ikKnKVo;d%PպFχ umMlЇ?3 տY=7N_;_Vat+9V_J扖RҲR}9IM}w}{TBLnac>,E3^V% :9H_GOԗӕqo&kP3.q-zf=(#uw&Wsr ~Ev&LxR6۩z4պuK]wgߤI/hǎ_-՚vۇoS,bS`ǣT[_{@MSz*guvW[?cݝ=ƿ[*H?,ER?rkٿ# HGU$hѰ2.O^ klzzi(EZ}tW6z:+q9_ŷmF]GGz,B,RXX /,B-]P4ᇍ,dOsGlcs*$4P!2hWA! UA֥}7nQbx5)%Yϑ IDAT|ڃ^~n%}4FC׻G_YK[Yiz5_;EXb(/9E^Sa ?"*s)ƜC*f]UTYP8l6yF@KuOtXR1e/;ruL{^˶R eM`{[P_PBC%I+tOkGtW ;.Uɦc+0&JJܯ,ԛ*Hݯd}H_)c>PW_ԂfX}z)퓀¬aTʬ(AWlo[gUjsk-JIIfvZM'+3P.eOQ5έ_By3e(F@f*g=mm=m 7XVmѸRO5{[o_ScR,ӰD}Gtc*sFVVo,6j[˹3TE*snWn,ڵC ʹ+TULT P*e?rdiU꥗oc.*ӃPPSԥ˕a};N*0 @SBʇP UʀP *}b2O-*}P @Pq ë^`KY3;P8G(9m>;;S6^z;P8viRmR_Z@A%UjjzE#TL2]))iۙ@Uz,?J`ʀP UʀP UʀP UʀP UʀP 0 \*Q@!T`INNRSkG-{^]y4O6d)0_~~іwܢ={sWPqS UʀP U@%S'UʄP UʀP U@S%T(B2pVt^ڳgڵkfcGp(kʔ-h~ڵc9w rQPX]y KF&sW8nݏ ˱TPŬ c̹ڽ;Aa322˹#bTP9!??O_|^k~oO&ܡr WXX&MZQfwZP@ZUvׯZ7oW\VΝ@UT TW8'dff\z˱gJ0Mn2,P-[ƗsW@⋯+##_A˹#U]Upj[Z߹sW9w?HW޽-'&R۶]U';vl'U)ahٲ,קVXXrUAjРuVo3(eg-gffsGUׂKf&EEXOLLQ]kpV#TPEUV]5kRƍʹvvjӦ{ϭniiZx+&r Tǣ^k ),,R4iya"nm-P9$''(;@۷'YOIIPzzFRΝ2 T3,//GW˗[=իkĻ,˯SWXY;okڵk˖J aa4M]qՖ߭חjNSAAjvkR֭Y߸q6lؤ^sg(*PhϞ&KiI ʹ+H@@bbݶ> @y"TJ.''[aa.9R0r T/ӱI2˳ @)((矯O?mT#) ;*TdEE**~N[6m2 TlRTT4hj~Ο˹#s @ ̊n_mpg+U}Z[OLLaիk9w@C?uR5ILL֚5-7hPW\`6S*("V\;w[ҍ7R@ɓ_RXX-/ZTgOS``z BYrr\j m~˖qj׮zá/RLˑ6o ӬtL4KYYYڸqs-IS IA*(3ͦX5jR=k?i*11HrǶm;dr5nRUTTuk~ڴi+ R#TcRSӴAn%'Rnn ^oo5etlvK;n(6pz>?Gx^%$$ڔC R-;]EETp85 C3&##]}?^mhŊJO:a}nnNv5|;HPgO+qzᇟUa៓wr^x W_Poy^8UpաCW5hTٿvr8NXkS`w8Sn234b##S^uv{RS-,()).Zp#T8JS#|;˘_dyݩZ[uR}nVg***na>|Pr?U/Uddf^|z*88Xaz5p`_ht U@^y^~x?\l]Z^iTeeesaxUTVWROZ/_ꢋ:[ZB>}2B8PEhڴr:|רQ]&ܡOO|O-w^11QjwإjcMkݺ-TY|ZjfY߽{uB>t(QX^?N/é:u[xJI)݋UKU4رjժkVzzF*zWղ%333b*5hPR}JJ-]>#wɒZ K~*(ȗnmΓ vըQR}YX_7Vi"?u^6˵Ngp $MWPPzǫ3Q@%%%[5MSNڶl~W.WmKnR22ռyk]|e,vګq^cE:t(R+vfլi-|ܱc_"kǨfFY*//OQQubmRܤ[ny@㔵釴pᛥW5T{>gjS~~$M\EfaڵW<5mJ\R]Ծj"K Oջٔ"7hPWwq3@Yffmyai eyyQ>Y_dL.V6zZϟCG T?czixE***^UsfSHH#-/c-=vjȐ,էX*+kc4XkeOi"[xj:np:nbs8>NcxL-tvl=o s63t#~MFz ð5h0]3 ~)23+Ş={k=jڐꔔD*0DeUZ|},'$Sllu>nzukt_ 7i:վ}ol2UTThSCr8 ̡CI *&+RCI|HJJBBBPǐ%)߶U&*<;W-ꚟ [PQ1$-퐜NªY/>)88R}JJBC?R}1$F>>>Kw )RJJkZZwnne.4TZCBh[ns?T_11.L8O5jX}-,éz TaacHO>脲C޽/oVRҡ'%TDDyCNv ;׫2FkժNZRQx^)1$Q *cHbEEZ{-+**Tj__ JK(V99YSTT>\Gv^T!UTT#˳7)U}ttR WQǬ_brt9uV\_SvMamǫVR Ӎh Z/XωKN\jZ>.ߪ=i?nYǑ ,u~)ڏW(s_F):*s߰Kⓤ ?y11ۏk֌.~+aUS6q!<<,qRǥ;U+~S8^]^o8T^Wvkm~l҆frKZY~ w^uqjuT+V""wu: =YIG^ ?M#__)VRǵdYZr}RcHil6KZZcTPt뭷[o6*DTCEE[o.U'KOKӕvr7xp>T?~zZ|9Zry͊n\߿_)))1gd{VR~W+<ڨr; \l2434YʀP UʀPT:U5*e@P*e@P*e@P*e@P*e*;կ_(waaar8gl{uQ@@މmqEkРUN?j*C2+ U0@ * yݼn(qN* =c۫UɄ),,8իW[R2 T(Bsoi1+3dTt/TQ*g 3[ߍwrx:KI`57 JhϛU~rհF>f5R pK.WC}u9_|\.\HE8U"Tk'RGskyRC6UoYſ*=|RmQY,PϽM}ߏOA]]F-$S?oV-'VJzx|}q+UYWu/MSjŁM. M۫ѿ.1ոڒ7蘑S^ѺTO&9;|JoUZ~V-^s. FnМzgsLy?No)_"[םWmŻ_ѿ*PlX_W]kׂw@rO }Oe|~~S}q5*!#o-[&,~nӟ#m6ٔM[RU$4%ُlrO; YW]*n"mJ~k)_p$[vl'M?+LPYZ–+<zv Uʹ`|}R(Û>׶I32嫚+fpkSg~Ÿ־FS?FSOs[PxeFR.8G @ʧP,UʀP Ug9.(˥^AOz5NfUP&U Tͨ%T\.\Ҙ?oƟ5[Iݽrӈ\W۵L<ⓔdLYitV˥hWNiqJmLIf׉М J``AU`7WuA5]7X<^$*5W [fO|z=2}aH2T~XaݡW;5kW/]1Z d}A+-yܥEyuP.пЀ4``MEu_gza(gZ8R7Vʻگn|nfMU͂lx7w8s8ot05UG^ef&w]y zH?MkFߤ׶cV@]c[ϑVP_#t)1=]i*:@8ı@-|kW}Z V[ =L~!$hעsx l)_gu;ːCmkHVh51B#.ޠow8ɦvK\ IDATv~ݮz5ܠM)2\mI_ޡ? e};A]~KB5Yܫa{goSSFҴӴGy?'F2j_VI;RӓTP&k[#;&v9?ͦ7lF uj)W/خ~/P9hXyuup9v~֠&mܖ.I(+B=7)tJf-ԢUu}-VJIݪ ;ZM ;W;W뛴κ4O6[0XkWB#].QNS}u]>V;jڹ6'פ0啱Ztޣj;B-CؕHY}H9R#o_~rmGܧK{Ls ӯ<s`znCf CaJ>򰦽~RᯒN|.ӣNԩS][sd@?^ >jxL/6C(0 Yѝ;eTVV{~C>٪w}H5u|ubizʶ8ܮu nzszZ~uq`j~i5zX,ЯT 4u$) XEuh#Sih_R]Ƈ*(<ç b>Yȿk]锟%hŬw%5ӄip#;=gA] *޹'_CѤy]8SvߏrSg9[MHwS^zn>i3b{eأiOdwuzh ioc(Rݶ}t[۫4ꁽڴs-zVZh5*88yZ]}UI+w՗(!$ 3KPdOPsF!m40L9qi4ڼ*{Q~?/@mB|M=c r&ի\E|BIoq^T' L#}K[YՌۯ%zs8znz}q'|_u. ?մFߦ_>^FW Pѳؼ9z(Frn] x9y}h+C)u{7IڢɗcwϺצ򈿿o/"SGFV*͓B{Ó]-IմPt*5P\O }VLU7wJP*g3_>_qyK1R.5hT;8():-?{? j3gfW Qhh|%֕C/aKVjE A-lm{߼Gzjo܊Ҽy_)#I6WOw)U֎4j`S$?ջu}nh|qwW^ÐaxS_-Z!]X՘T@.,am1 w3$NQTdhK$_o^^?Z^&ιWMϬ߫wvP#GFj؇'<靫+<<\1st^Ph?.ޱqA `~S Kҽ-S~q+z)ajR5Eږm4 eo{_oj.Up>{B (eTUh;h}3FmM3 g5s-ĩN)stJ?.$-+r 4ͧUU#"BoZͧ&.NPuzQ-i4Ņ+<6_#NpBli:|>vi\P*e@P*e@P*e@P*ePC(AU*#B2pVt9oWt 9Cn=Wt P U[ @ @wJsnjT`_ g9||P}5mhERޒUVѭB0_$TS֧Ut|3#4*F%Tn8pEHfPEa* \RB;L$TRBg3i+t'zK33@9PEa2NVتyS.ZiwՃZ+Zz`lC=g8`0YCj4 USϦ,X^s˛V_7Hs/׃6\jУ)У5v*q_o}mRAzY|j*ѺmrGz_k[ߧ_^ ]3N=I',?\=F `aG`Ҡ֯zF>.SEsirygL.s/xn_Zn oQ+t3)S[-?Ao#_|;qrrErUVk՚>l"qh.]|K?z)CWtֵv1eUcd!J,5ufuΟMf! w\:QGdeڡʺ6o*n{yG.Vk&=*s窪Ώb%W^*ܷK:t|ՃJ־ÕuG.{}@0[0#5ˢP?e>s=ZZ4Ϳ\k~ ӑyjmZs"y9#8\C#E& U;Cݢ= ThGU=dax:A^7\<2U=G|kp#:Mmz>oۭg\]:E)}v{` Td6H嚎:W=.zm/͏<=9s%v8Ҽ]7z[}M:brS:Jt)o1[MK8[7SK4pm-:%վ}IM$+{X-]uk:UJ]uܢ0]a!0{Hrsوaމ7;_>~Wݠ_sf.vqtVަ{{j|^{C8U/ܩu9]P$3ctO_sn84]ꂧuTW; U\~7^zq=/AwU*Gߺy xTS?T9fWz[>[A'y\Re7g}*Z|;ޱNȷtxjߨk_=ާʹmT{zMCUQj_~KB1C`KV$}f62>g/yѨ^~8Շ/ cQ-`!Tn5֝w5ҷ7IH2nA%"0PnR,H%Q,QJ]R8 f}'k^c&V;t#>T9LKk2=<0L_Gw^0CI:(FV` UƀPL9>  A>L.P36T+&0P.p32T3gK3j`ʇ*>I0)LE*c@0*c@0*c@0*cOvL׮6n8٥L rzR& zZutvW>٥L+wy֬]#?|Kw*W&i/9I}-PQظq̦S ㎛2 `e_& C(ʾ"TNfnBM^J_XWR$T0ftL&@ ;'m}@ꗵ;5 yՅ;G/ZRK޾O9ɮ`LP' |>]}J}9 [gw1j7ȴ?u+'*u?/,V|:2|erRlT1 wt?~R_wjlsɕzyAɛ]AUQ?y!]Uj}3㵲C_vi44*MDJkue'ja=d6CϻUnG7\voGg7]Z/XUI7R[|ܪ2;Ufwf&d'thbeޱ$ .6(.>L=Ѷ>\OytҒ?^URϛz֙ ^.k߫K~T~ܱ77v+0a=38S S'_X=ZwZ.)HJL.['o_5طZ=ZrY~ez_}_֏ ђ?nv+fGe枨6ԩ2^zk~fꭖ[~_@ v2trϲtz?s{XRRsu'sWJm}g͚j&Svi޼nUcTӱg^=1}헏j0<5_=Ui>&ꩀNF!y7}^˾BzGXtŪ͇՚u?\?N޵*-kQ9bI՗oZwܠ"hꚿ=YT.gZ03_kn.eB0 GuVZcm޼e˙z{竧g<'O8Ao|*S>Ti [dd0c=v0-BM/Ut4w~n?K# F4>-NX?`9کLNLϮ?! *{ 0)0:{ug:SSE` hF~F̤̑iE=Ϯ4T?!{7]C0;U<95k4&z/uڞcl˜wǵϿ`OϢ^XjuZ:ǔ˪TKXe%+JV Jn`25J13JSh0vBZUE526l`^*VRMRrJztkfVuhI1kE2Nl\˥* <=dܬ岘yr(yj,dC2%F4*R Rfe T`[0%/,c^vbEJyr)ʲݱܓ<2m>e@Eϝ*#@Gz<ff1*CtO VxT)dyYPnehKƊ,y(BQX[ є“2sP w/*ݡ,+sY+y2OVyh,Et3̺ﱡџ'>ثFyYJ[R3uj()rŲ"i;UF'Qx#K}1 ffE+j[$R]A$ M"ܣ,d h!\*`).w͂t e0/Ky CIuO^] wk [Rɏ,䝏ے菴^NR9R5ZZWK YAS1T:MCWY:hI!I1ɫYiE ʲ2AnU.Lr/ec+XiP1OYZi=EY*nffdji˅K[;Tԟ/ߟKPk~\oqV7Ӫ"X+bebBȪE35C,1W2 .Le`[)cRpɓޡҪJwO>tnnyd=-|#;.cgne+GKR\YΚ/VJyT.U:M*kU)dY5XѴX 1VPU+?pI^$yy,ܬRkh)퀛wԒ#M-@;n4**U[Vܫ?G~U9;yo;Veծ+)f 1Y3#dST*qSRa#K)YbR&+nj[#?ÁJZֹplnڥ[eۥ"W"=Г+]e 11e!dIԈCV4Ub{:,)eɽlݝ2rU2c?frϻ̫M #Kl$Hx=i"41!.$4 neJ5hRׯ40#;I0 pRka^o=LYwP@EPEz`EvZYoB ,V#I;{a$ڝ"I2P&2Tvq IW;W$iBlPoG? w )>҄*D*iHҮ F)42L;E@E:`eD߶,V-_5&HXvf;K"XFm8<iAtÔ 0e';!\1aʰdiʄ(`]fg{y!IENDB`qdirstat-1.4/screenshots/QDirStat-locate-file-types-window.png000066400000000000000000003233521311502036700246110ustar00rootroot00000000000000PNG  IHDR&r)ysBIT|d pHYs+ IDATxwxU93%$!Ћ`[kW^ PYqwZ~Pz-Hm$$!~_3Or9 3B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!BQ+P#kn݄B!B=RvwW:u/AB!BԑbH!B!n(v_(@⮻7׌u DB!B!ݻIpݛ>Wn7_C QFRN@B!B!^9=6SC]PF5DuaD KK &B!B5{E"vB]PFPR Q%( "֯ѣ|s%B!B!RFnB堢,1oJ@aDvgʹΝ^$aB!B"[-+S)>};_M(QD@jz'} k )B!Bjh,+SG}[[RT (*ؕkW%j%QHD3ˆx$B4 k/@B!B!^LccV ) ,bNFfB.-QWLWE=$r ;*UY)啦BpB!B!F% k4cqkBPCc#T@Qރb]fazOpUBnT%QH-quVxcT *,EU%B!B!Ėa[ & a݄% kBm=SPT=QNnCK=%QE PՋTF"" W!_d FxR^  (73Vk+B!BO%nMZ놱gmi@w) (Aτ&Ҭ(R8{NUPՁ.aDQYVCEZJ(?1JE(? ϏJ !B!b @Ė~ YO`}ZQVkSmcLZ fE 0{:‰r֪ 'j_BA(訧tZPt(톕m\?RpI0!B!Blm, X;a=k}z1kښkMiڈkMMF7Ѱgj93zMNCq%ro](L:+VJ9nHiG;&}'?}'5D@MB!Bz iR[;!1Zk5Rc*Mj0Qu\FA DPG7Jk')(JJ) *M,A%}x2B!Bkmk5Ik|? &8Ʀ?Mz&R6&j!1&-Q%DQ^uQqqWJ+'ЎcI]t"ըWV!B!J`km"qukB~Bk&iIyXM bE!jB$dE.aTMX; Bon(^cIZ9Z;&4" r xҊ㙤V(jOXB!B!D塌k-wuXYZ@#jRk}4^2j1ƏXA4 'MQ6ft`0c-3q~-Z9WE3mTBW65RiJ9pI*hZsʱZ(7xq[O;J+GiC!B!jk:5 _$Sj帊d\Ҽ q D j-5شD]HQ$;9@Th;kֺ ̘ecohI@;*w#YJR~"uTN@+85VɀJE{ڪB!BQ_9V_)c1&:$ $MB; $ QVXJ4nX7lDD%m.>U> jeV&QᥢsaGe*-PJBh7w}]!:w$ZVK !B!b 4 k6iIq|L&\)qSH$} ڸ1ʚTUѰ(mʹ,v5Q{6lʱ>E/UZ9To GBJF9\ci :*u  *!?\DŽB!B57`v$l³~4Jy ʵ:6`F[ciZ;Y{ &sZ &*DW/Rn"fk~}֨HPi*87RV9@ցԎ iTnh"B!B*c!]p a8:5Վc=t* (qv&1eJ*QђE*#r t;5h J*R~BiQ$)AI:Vk7vtDk1FG

b$oFÏ?m{' o4nD< Lĉb 7f}X>Db˽:B]nV:u*g뿻Qɧܹj|=q)x]Xݣ'[Bv%uTN>TןA3jh֮][icGzN|ʩ,X`jѲ%qF-jS?O>T^}5N>Tϟ_1?̳΢iNSʀsΩTR`hʫn6]*[eO<IKKߍ5BvWڵ4F:p\=krsݵ3thiieGKKU[^Ϗ w @~~>iii\veؗ/{~|V94 |a@Qq17 EKI&5.Rn(*.{*b[ipС|xkDz,\5^ˢE0 k_6PU0 <ϣe˖t;TNM{83gͪ9sh޼9f)nb1=0vm4mP8ر/SXXHZZ:pٳءrk0>\ 喝!D}R]k4nҘ/"C<]٦\٫WղoV|qxy/ŵ׫hc"=Kf8ywbTMqgqM5ۖ1ưn]C,Zo~| hѲSBfF )uL$BY08 \zŌ=+:38X,s5h,_|.]_2 Ҽys;\=Νؗ_aAzƥ -J,cԨ|wxG޽4j5jcYrM4o:Яs}3qBn^%%% ~e x-ZpWo^=zrJ֮]K&MH$̞=!7?t"gϦEdeeL$8OzI4HgС@r1|rz)/X@2ZhI=pqcys!33A9L+VaÆx ߟO=4\p>>\ݵanr#ۏy1"W\q98͞[ 6k|~qϧ|FO?ݛ+L[xsV"--޽{sM7nBծm[~JKK kH$ַ+;//,\wc<֭[GӜ*_CoSN>[5]]y 47| oO1/Hķ/cר7-芡@AA]ƏV'9z0|&kr|ߧ`0H,$M>mZ*H]h>2ƐljǢ|b9}o7} < k Ck׎W_ .X 9yWj &w2?4kֵ+\x!c|4pa'y9=|>SI۶D"0cLɧ|(.)aؗ˷B|\s 履;xGYfM>X|I&|>U=Cddd2퉌{mК'z"I]s _|&:!ĞvWIqK/Ix9omnwUW /ÆQZR*+ǟᲓdef.K.ZoSҫDU+SNS_+}{CZ8ȠA6mZ00[_p\5jy!ޟ~Or xIg7OTM7eŬ^믿}x|;m0oLzWW4DYT_իs{ ͽO?D~~>c٣;%DBAN<͖){͵8O= 'n6l]Օ}ǝwRqwRT\ă=ĢEKxw쯾z}/QcÙ.{ݺ<O=gpǒڵ-Q#T(ѻ~\|".XlX,N}0ڵkW}eI6m:~:D8YfӽG&-7qJKKIKKv|4H^AZ#GfT'u\r%8T,ZZ{8&tI&XkiM2$7w mڴ}vCqa!:ubݟo±ccWpbŊqoڵk޽|0 8<áJ"B'\a}9̳(X-e'q^sw._v9 ?aE$*{A2Vx -[W˯/pAB=zܳϲn:Mưaի? hڴ)M5*nVne+UMoFk1s%.^ WR>xJJR~*Hhl~ϪcLTpQd2I.]% ˆL:Sƽ5ᩧpBQlչsg-YP)vWue'qdWx ;ƌ!Z w sXx:пvɓ?I2n4kÛ'pnѮù 7m=V"5]Y,E_o 8de6dꔩN`1&Ih)p_`B~rA,TЭ[71[ʖeЩS'~j{5hqc6ժUKIB`ժU]K۶m7c zQ;}.yÏhԸ1 ݻucoS>sxPD >׊Ǧ ( ك̬JUyy2eJL&+M:{l-7/n镶>}z=K6:DϷ:{7cŴjٜGY|9sսRbGlݕ.hivj*{̪U[̝;Ҩ굡Otڍz~ʪUe~ 5wai̚17^}ڵz!v7ܔoa;]+{]ZsVZYkebjۊXl>ӵRx IDATK-$HbRb߿^Eܾ5 g0_{ ڶm3ǟOO^2o|v (..Gddd!-Ff~B4oޜQWGjSø"==]W_!7ӧO7#=Ę1c9uP<I&za~DK~>-+AcƾիD"u 4‚j˳һO{g8믾{Ǘh(GqllYlYݺC3gyW3(==^t1}1 4₍7y^v}e7n3=G$QZZѣxxGF4k֬|̜9ߟD4m۶<76*\vfnwm<\ _?槨$6WG3*脝Hq?*C9 xV ]N:a"N6 VYNP7rmdd~+.٤K#>b-X3jr6<ެ]FBӦj : ?Y]aolv$WdyҡcG7oN<'jJ-X@L:tD-TOU!Dйk$%Ŭ[Sצ}J Yv-Zk:wys72#3MsBFY[>b8FN#ic|m6oN ˖ƹhޒLPҒbVXQCi/+.)CZz:ڶg[UMsjH >E\7͡IN3VXNjnמ.=ayĢQ4aF8)A:݅flSf-Zx[26q 瑿.k:m<(|M5q] Y|Y1[9ࢋHo%]йkwrW }~>-qhڼ 22!HP\TȚիB4oI8FkD< !D}3]R68KVD囵UYgb`*vRcb!M$M$='='Ewg}Ϗ=c~0iۆ;+93'KRۜ;;,[$==UV&7E ` 4sN4oޜ 7;Bg[E00{j+*, bվVݶVXƪnš SoVTZRR)R䒷&:o6eVTUx]՛]'Lx'e )̯y‚AΪce[]έOs RcZf@Wʲ Bۙ.){ϱ?fVo|d>b$|i`V4iܘ,ڴiC,<\%FuM\!B!vgcWƼ x57[K)E0 YYB!ؽ9Gm&Rvä́Bٙ.)c !BQ\TP4VB!v:?H?T!B!۫B!B!`BL!B!L!B!`B!B!$B!B!n#B!B!v &B!BH0!B!BF !B!ƾ`B!B!B!B!DULH0!B!Bآw~kC!B!zBvI'*쑴̞=Ν;krB!gqk ZXk1X(`,|;E &*챌orB!}3T&L*Vli-qvwuwzLX[6$qrv29B!B6ۤ}FJB!BȬB!B!m|3QDg= w67/]`wf WwKiCC p9~]iYןG' %YB!rMX O>N*]ɏE HIĘ t! ToaD٭wk-).yę"YHZ مCcG`ؤDŽ`u{eG^Len;|7&D u-,0;kfB!B'?E y'!VNm:TlpOqglFu  \l8s©r;w!lyy2NІ.OظN0ǸOѲ慯XXݗrT6~ T02fҫ}U\x=|WڷPS.N٢gϪ_ѲU7 bs;W}9DZ5|36.Sj}NҲz-l r,:f#<}jHvKXkIf~byjqs辴lՆo.!a-~t }+mCVo+|*^>ϮY(ЁYw3<~;̏Yo[KtsS֣ R:$~{NK%=&m ]|r,On?/0ɫ]xeEYdEYd-,]l6ex7jqElDU*3g=sWv^l^5E{\xqwYorEOͧOp\Tü}<͌,ͻ]ĵoK;,ƨQ{X+<)I`g5 =qM̧e)2OpO-&1 v$K78pޡ9~(s˪OsV,\߃Fno\w~xw,=Ź}4INeteu3%wx|pL"ƃ^s)z| ;O98C?YN,q9d$z<B!W6Ӕ#kȷG^G$mc hݘHS%J7&Z6iTlC)HxdXɲgP>iG(Mԍ6&޳Nq֭Ȭ 'PvmzToL!3&?/5ͣɭ]6dƣƇ/?F_w o_ U&^<{(ry 7@~2~0lLypR&4Q ,gcg9Lv..T~!x~;[7Q!&U2;:(Mېl%e&iNOyP.X~NB!B߯zL߷c ƠX;!g]O"kA9$xbGцq†50nҥںX`)+rt5)<;dZTIآrsᾧ%aNK l3R$/'Ӑ k@[䷑\;*#^a4Q=z*nx1&(fs\:3Ns-H*ےٌ6^06l}6xó7=NP8W8O'g}̷FNklʲ5ˏY8҇y/kZfxzYjܐBQϩum7L;ۋ1Wo0ByU˶6dThc +N㡳?GMchЄzuCq'io _н5s'+o㾅pR+^dwqJ4Jf8ﵽYCMizK RNjR݉aė/^,jx/&}ChӔaCoy84UGNχsFG"l,S77ݘcO>e9,{?B!B\Q|q꯺LlsN\scO[mx9aCgsVt>ά UW֦W~.'=r>ֈSǓu",4/Zتcfٺ;\.*UG)Պ*t=35Xyke=#Klr-n3B!nu{u|0!]vgqBU_5n*#ו:v+Ym.W-6sqOc@ftakZj$$?,jIғ:sQV.Q 7ޗ Սa13ysZWҹ8srʡCwjG-.wꕤggSjQj+ڷ&+o5?DM%mm.Lߦ(نt,;ɟ_ȒɜCWִ"C[6>yִN=nB!bձ/Ր` 6`Yv&+X|P34Vc)4euWح9by _aqMQC,4ptRy5p.ٔN [na)OŢ/gr˴V%[x\׶!ҩ&bYr2-Ԅ7e3ޒզ=/ЈuOcPӎӸs!ѐG!B\øVqMö-X9m8sYr:2OQ1E,N,zz m%|$h;Nk)/_YK| ܜ?J9}-u\sDszf:K{* sI6] Kq:&}qkM3p~M@tHwJRd5ͦ)uL#qbi{ 4ۦiW'njgz~{>颍%y5#7\ֻvfX/XHOa$Z?:|=sz5]nu:DvL4olK%%}׌M7ّ['nvA IM5XMgu݂Eq;]!}i)DŽʖUD$1,?Bhn[U)ˌge{ѻ@&cdZђ$NKv 0+9({oY D_c` wKg6eih E¯3GBFՙ֢"miTڬ*ed%֤iݸ;2fKkcb@oVSY ob nz?vfaHtS♳"s4mRIq8 IDAT*,Ec+-ܱH d#ےS\ԫ93T g_-pvi;3rT:'jeGln^mW]bR5:j (mˠcD*<͛osIRsDh٬3q6giҢ:$hX< wJ_i\JTprLtUf.S,C?/-#Z{vήObdie@ nD`_[JLi`Tn(w`1Y;؄RѨ?{mi^?♷$3&{4+a]/o@ZfLVUUdd{ngȮ pr9p}j3sTEfYK6TiiաsX"jO>6;^Q@B7x;(oL,6ܲ VNYP JDNiW٤Xx\ib`D eh9l&""ŲeT6Q>ِ JxS8)JdR"cXg"8t>z>raU5<ÚT+=qAᷳf@r$ɗ$X6YlEf-ĞJt]edx~R{NұF%~LQ0nvZ{T\? #ێ!*wK?dR.%S_cev$)Llؼs]BlLhbd:us.J)C֛@ ߎL[:2 ΰZڲrN&NDZ y4RIyBfr ?Lpn \Z$aBreWS8Ŏ 3/aBF&>JޖV[[„/Xٱ~+'̇Z+1щ8;-b|/yhI NJ*-Axz@  6N4tױ;HU@Ua1+g`V@RS+`Qv sbC7ɔv+M,ܓy3OѯImZTUL9;/Xܹ.t""7-fgHH7Qv>4Iv4^O|SUWu -9!-FTs̹ܽ 49R0斵wIr ?Ýi|}ˋ #XrQE~ͤUx8А{ T**-*_99d6xt%tȇ[j}֡ 3U)WE~$Ȧtll2a9*:Ϳb&1GM#w|ۍjr:_Z`rȻ RQ}VV㮻[DQ'pwuatXUƵs|O #IEWRT~7gp^Sk(Sl7@ գ@`0%0aI.`r}Y|s"X՛SA=ϵPo+"QW@&ě>~ipfRǪԗYt!TJbōGO/^J;U`FK'r'p Q? 4wOcv&׍Z4𤹝JMpL\NQ76u#ł':Zݕŭ;N?hh3ɆLNihTמh=q̅,bmѱt1'nIM6{VΜʹ5E+o?Ce?LY2S rm}?k2w݄<(qd7YK޴s]Mdc3]xZS4S6Rd2LXeS_ōK$G`4Hα r^  T"j-)4ZQx*9&s͎fҵ+u :{^hcM}JSW\Ӈ:jմ3*ll#&ŚȲ*?^ɸMYIC`wܥkQی8!qCqgL6+4k Y`ނ 3Z0ABve3C|XI͢5YP4ƉuE$ܑz?}`+l4p! SH%VPQa&~9AQχN[振0e9"ŕFbL W|ݧ?.2a=&[&h I%".՚;Ο^%;Irw*CWh<̱}[Ϲ{\ʫ?IǛ?"[HKYdp-3k*K&V]fLkR_27[N.wY#-&[@ Ke+JA~ϣJT)pY㬕tj[IդHNZc5j5ZҪEΨQګTd;VqTrRJ.j]-)Zu]C[X{ITS,1辪&8{CXt$/6I?Ι'eyHz\3ZObVx&mN],Xus懾\՛@ Y5y][V+J^f"(RbWTj5KC}Zw?^9gZVEm5ɷe.#f)S*'[ 6FͲY6[$٢1+zŪY-bYd`0+m8(WI6]x3&@p(^Ϫ+F .IJHsδl:N| 5J@ < ߋ 423 ΜZIo%rQxyz@ o #D5=Ez\"'S:QK!@ k5"@ @p[6nx"}e$$!_Dq)[?2/@N'b Fj$!KbIչv>0?̼W{9r h.5,׏)'mexȾO= A9Q,'hi:;'>+Vc2 CThaCzPDmCK9ANa]y`M^ېL>Mw ʭnh$T!m#!5??{}AqɶZsHYY#k9J[)3b,dRO|԰{|3 vtW ￵MX(d,.n<@gCp}TӶMүX1[[Q;_@ z@A#ݢqAyr8goÒJV;$R\cWӞeiN׎ ο.g/Mӗh聓+՞gޔʉ:Ӧa-*ٖ Tin-:y$IP +i?3aN.)VPT4npl2e_B፤tDe9 gMSIb\G.,5m˷siY>/!C^ܲJF8c{ymh_u®a%Uh6ݱΙghٳyFbJ:Ƣ$\C' "б4'rxՔ$Z ͗򂴹KGnaCi !Wd\GB$r,UU1{,%$ɟv8cole"~aZ`\%|jv.Iw'Wbf w}`_Vdޯ'GLOIB hI2ѻ*r'yR;l"6/ePP%J7g8M]%|BzS.bDŖrXY/!WAҍNfaJ: GpYc"njz}7?@PB{^&ҖTnSs$(w)J&F>,~ڂ#$VySz !9Ԥݘy?YC@ O0"0E&=ONVmBl"n턍Fe?/a!nΆ"aXB$$v43dqI\/;=^1rsL;KK̳@9)]i؇2UmMXu ީdE= fրc)OZZ,jTaskFFZ?!l%Q\_͖_Ż]88{00o :TAX 8?; md3E *f7 [.{zPsŧg5;%=2$:sKN4:fr )NwSfd9os#splWX4imfl:\ڡsbaɈ&Tnxj"N.gZd_fSx ZBHe8`I#*ڊ}u6j'*Wgdݹp".3#ضIWi7DϽI|s _*GB⡍ԉ=45x8[zU)rN2YoD/֛I/x\rP' ~p E@ w ,àh< ͖͘N?Xn;lb"[rm6 !a_gV1{_Y'Y2 Ւ["csmyăY2 9p4aseLlu`vz1 +[ЛQR6U>6Kg-x ŪҦ/04pF =ʌfFA2*wуϲHquѠV#eI8:tJ!v'bAe넻 .j]Wv8oCd 1o)ٻ mE 5f,:JYAκƶoB}v}5'άf,`+Pc\NqrZBB;Q 3Jdz*TY+5k~dÍ R4;, mT`ζd ƄC,`) Ft 3GdTPdW#@ Lq`9Szc;NCӡӵ+E X7w?/LŲ6w|X62XCޚx# Ndzk3zb~:ZS9q3#+:5#nTա 7R IDATVR?UQ(deވeD00!xp(ٗX9s<}[!IݗI{/Y9E3ի1NR|/l?#/IH>g 9$9I,,׏g''mex~C3?kG SiV׾%cTڹ}_Fgeh֒±S(!I5ˈHd˛=?-|rӘ(s~ï=KR;~*љБ%LOc2mxa|^BQ?NZ}CdQ*&$wͭ;_bG3\b:? Cy e( JAN;wP$W x1At|Q\_rg\1'qb';>j6jbxD_*zI"FU&n~|csi?^v+ҭdq\*-@w~F6^g¾?GV.-oOPO8C&PPQ_.Z:܊!,`-) Kxl Hu=~:y3g|DžRYem:"С c$T!m#!5??{}AjfbM|/ƜVKe ɷq: O$ϯ/Xŋ,Q4P0LyNFȚrYq\S$`$R^oi`&68ނ tp+F $lG#y}52ӷDNe =cֽO7l8"9Pgw5+`Pr'Lz9PM}?CO30| ?L'(BBhR Obˬʉ:Ӧa-*ٖ=osHyc.#?WG=*Q;*Nz:EІ}s8pMBR^Pxx#):Q;ckdCBn89=yi9gi[;aM;} qBJΦU2ؓoV~kCҭv%(YDD5tά?C˞prO3%cIXV萛9< jJH-}ܥ#Sˡ4vB^x2m!HDs9Z8T1{,%$ɟv8cPg2i0W0>5i;jLS~xsE1D;>|/ +y)ܡ3Y9-I+i6t|)37SZ0puA cĶIȼK8mrj%&2z@uϻk")61hse' ;gvn \-.mrݝ! o|8Z=!4#cW|2c3B}̿Bځ)l7;rܫ#ޥ~ON[ԛO9j>MD\1{T 8;CE?ya.lhDbTy% K酞؀n^5ƌbXt;? RX!#:#IH>bt^ڳa,F ]h(fq$r%}G=HcS6 gp~G m1V,:S佦!Lݝ-5G'LHnH'~Y<7?mvu-%C'$i1։ne.=Њvhi;~[R|ú6f%}>q~JE?4)#l `hZntyY`_BM֥V,XTXpu9?ޏH!}gl]% Ƹ8'u$$f Vz"u˯_%@Y}`Q*;g4#5]t<q-лƧ9];6'8'lg}#_N[j{3T}y}~Oٺz&}fԴs|'A e]v~oR%@& H9.$1`մ[˗[S-~uh;|& 23^aD2ܾհ{zw;[%\fՔWI~F;"!=Bfoc*9"I;eeg7(FnIqgb yQ0'E+m+d]@jѹIv^ԣ`&~,a 8 d-mrMvK6'Y&md¦l)0mjl.88{00o :TAX ,?; md3E *f7 [.{z@_zO 0pkvKzeIt(h>ẗ́/:r ӝ鷺1rۜb\1ܩ3[O$YdE6xT^۷u6Tʤ=YiI\;A5 Y?h_ }gt[uD[e[ٽr-V=^0`[~ICVKhsoI ȩk*e1{ߥaXz UMWɑbe Ε|cKRwJN~vhu}''- rvuZґrj'Q-;R>WwڣB։w S@OXxU &ԭ\v->_R 4)~Μv7#"V_ aw?#ǯ*X e2So`&) LxOw '|[4 jr+X? ]s_Em3&;/U6qpfʆ8 *Ly4gMel̈T*&nHaYdSJ9V.q(E(Y\;xrdGsL]Ww*X]kҨq52'4XdpOta̜˾'?JSVLO˗=C)2ص& ~쵂 A?ey= d8/QRj}_FOXAԷ8;Ͻ퀲b6UKmj-Xt 6w\>4|0ePRh_n j* DeީYϪ^̋&ŀ .M`뫹Y )kc?%^'gfߏ&K]sXeg[u})уGF¦j?>ʃ[W|hs[.SL?aJ@ LM܈ۯhQ,xVÇ'\ [08PdF SZR;(Gt>mixYSNZ[UCR{t@F%{t  mOU;$gѶgxgB;U~۴ܰ?ݚZ->J0>Ǫi=x3y4 '%_J iЛ4Lo2՜Ѩl?\L1?wFIL^Ә潐% 'BS_l66}0 jJoOұZ{u%YvV K_ƶ;u&I%5bR (j{Uõ`|qLvUBWo$Υ*(tx!ׯ{y[V^%q#VUƯW<5ym/#ᣓP9TI.cf]fHOYZ/x۪yէ:8KY\iZƷ6] ]Ye$kd[EpZ΋om&Ȭf9DZ/FN%M_FTzsFmli ]O/bWR6u@#I4fЫ9bg*r%s+A:z.nۦh6~N*IGALv_ Po$s?2a<1-|PR1DMK8"e}^J2rENoݶMz2qYW ..V23e&dYNJs\hamo58>)~)>+#9PX7k4>5ݞM㪸٪4u} e>PHNx_0Z CMco\OHYHϏ#r-_ʲ2b*O܁ |t;qբy>̜ˌMd(h_.IK>/^br.+ܳIXjSر * [,+j oyx+ O\Dk0|KݨڈK)t҉*"*!ϓ/< $Qe Oǿ B$rA{ r# xy @a ꉾGMWJ`5[oe"HxybJg%<" LF5:o-ɿl$% ;u&2tB4?cDŜ4)'3ӸQ%:3+o=[Y;u> Juڿ:W^}vUrm+V1_t9ty>5\g.wz.ݻ˜C{e| DR*RNj}1'$mX\Bco!ǂLf-U.o G/5%e:-;ɴ-ڻ_;_'eڍN5 ){ƛxQ5ug(MJ|x-t M9a)>ﻊ-[ h5tѭII V- Z4sB"Rʥ'41C,Jx4fds"*˷rڗL 6nT.(fYl(FT=VN1۵'{w;/)cå?m4|l<Ϝhj4x< IDATvIB cޅwoՉpTDãHHMM5CܯuN߁/MUj=;O`ӄIO9pAʶ2MsfD$$SK/̠ =+.p5#ҐgfJ2olҿE>Ƚ5p\ESfϹx6a$AXTbx7vN{-sWE*ЌV+yLprI㻏I=qW{C9~,EDL5vo^ɼfƸL\~$Rfc`܉"#*mպҰ Q@'GK V𸀶0.Nl#SƷNk 'hл.s趾~u~{FQϋ;)G2VM”C?hBR+օ! il.4Nxn\+~=mhjm 4WVre*bs,N__:(WKA"Q&p&uVͫLXL")ɱ^6Sv\d$S&>@ [Iijcr"_p;uzXt?oL3GtM$%:e1C@Muz.1,s ̫OToT$ Q!\w= =c nXCTw;æx$"iy|f [{P#=IDVh5?$޾ g[c8 m{#5Q\I+{{ՆQ`^kZ]ʎ;9ĻZ.3*C0َQH:9w> SOkA)+oY8'B H2s9fT᏿a̮𑑑Ƀ 019E7Gȑ[b9}}ͺ]` C N}}>ص(i~Qi A-!$KJl` Tr?Ez o*[0|kz(.RRڟo9, ^& wqe(̨?]nM}(>Cʾ=g`|)Q4e8S0yQ cٱJ_Z Ҙ`Yg8-ruUgt"L+eym}أ~tn-Ys-?v.Hi0yKZ6]> ɷ%X{g4T(6=>ưvtzXn@cE *C_ R-xW{PDqn, T2 n%> fnwL`쇴 ?_JҞ 97Gu]J^ϘaȋgVӌ`~u{}}gf2\{U~\w hK)F '\eu yL'( l騻í3/Ӭs. ]u 8`mnygz{c4s)f}9ծMAQZ_OeΓ|l9U6qcy7V;ڠ=5Q3QmKrigмűf>#/'S ϜP9li>K0[4AU{N Wʋx| ZtI1{0Jo`Vy [gC}#JQ+ZW2E9~kp_wf/L8[+4łnszGL*cD<2222۩4\(+"#JqAg-%qsf=z8f"ގ^[v6\FF&_mވ5@"I7ߠJeB?T*;&[W4"ŊZ"9IS 4b ZTjUkj)^*I&k4m(N-6,'{dsi,qSAxxd8ddciyNde0iٰ1T/ʇVWiј`J9J#K0w_vOQ;~IJ W!Z"f$ގN[.###1d-fy22#J+6Х@Q>?t) Lݗ~ؽeGL=Z/>-R<Ԣc/YC;,a1{P$evgwr90!###SDPׇӧl%!dCy iS222نȼ >"`ȁ yKRnR}IOIJa cG;(N^\(zguW.IaI:x̼GSw!C]%#Fp =E#Kv}䲗uHFFFFo&-DQ@qI@Lf/gxHY|ur3ݳcne |J=UGA@(QO.s/)(_\qpu!ߡ~>+"qq%I,*nXvGSq^qJg҆m_M1#6ldcbG_ P v݉ ԄҐJ(\0ۣIl5]5ލ+l=g^BDqip+~߮ZL^W"1x/swV͊s/Q4lh=< cB Sј->wO]C(tB]#1!k;ѓG#o/j8)>wI$8dυx<ԋap2%RнRq!:{;;+ϺMVVL6fBY {|hX] P0M H]]s^e#G,mVIM=g;EW/n7/>SfwןIB"Ǚ\:.N޿V-rZ7VYSݻ.&hmaiA^FT> 9֌ JBxsh6' D{$+DƆ.fƺY >iӎ){EԠ/7xĻ!D]C(LJQ#fê=%m*b[Lv:J 돞2*ڛ*eKbifAØ}k3'5f16w”bVYzkP sGf?   =Czө\II!ʻS~?_!9K&&< Xqmq7Li7~37cuR[0"FYx#L"%rojLسT$W]e 9-5^įb2ru8W R 'Ou[GFg0ܻ0;(Ac13))s" SSL3ed(sm-ܰL0u^_ βoԧ9d싧 ) Gf8VkÔ@^pӣ] Sס%6ԾK0NeK&+^(A,ݷN.3Ua:OOyw`{d[s :UѭR <ӌ,(Ŀ0=<|"Ԁ1ga6gCm~:gx.ss,+1gZ19r~I&Pg9p l~I42kɦzXKI+cji-e1Vf[Y؇-~=R$ ^ 95cyۛmҤb~HyJl솭 8֧3x:gHj!%V_tk¬-n9gzQ({l2rk4ydd[-?}R Oϥo}GA{O.]dIܖƵjuʣf[_̶CK֤%UrG!lin}dVvǩ[;V6%KNDj`ƾ$IYtߥ /cLN\μN̪Cb'G{ !\|~ʄ~ʦnUpqT_+!w0RkA%:87^9ّRBt9 Zv;3ӳLm] A0J۱]pvÓi&-6aHK#qj^h#`lVUrn<j^^8Ƨ*'IsBSOм`7MYї}Z{襝!{VEFChb]ug|M,2oJ'įiz's(9h;O4 \~˹ʃ=ȸ)`V0d$GGP\ /8y[΋h0d9bX|]" 蹚)9efzC~Fo1"D_c/3_ҕ#btFo !a·* tn½t%Q`JνތKkvP/No.~F.yty_y?cu!_6X'(xe(4eyy֬sƂ vi3 }xy7iHš bn,t!{Vug޶% /k [ugH|vklʹCo6>߳|7nDPAǣ\48/efsʰT䬺g;PAh4N.ޯas ڌ7b$"OO/X69VcBl_tEny.+`fZJ٫X|Q%-:RQe'J Wg)#x8fBX> *ns#>[`.nOYiZ =9 (Hc:?HӸcUNu›?vOmյGQMlrQCv2m }6AD~v3u*{= cKs\NІaO8˳鶀i,:ݥ߃_ʒb1jv=j%l@w7orMv]ZW毫222222Q2-:܇#ZQܓ;+}ΖM9yh#k>ʝ^._MGLkV2״|1-!,W/QK2Sc~so„=h[$KIIr(d-eUNu]#pC48HRqjrg p6Ӭ:XX¸ ݿrez=l_ت{inetsΥ=p7]JۻP%n^?wb)Mpi܍@'_ГZbfJ\tKF; y%庶JRxvh@ĥDk@~Eܙ8)!(Qo]csijN J y!)HJclʖ")?9iR}@Pxƒ/׀y):g|o6,xHކy<H/KaPXT Bޯ&%c{V_@aRCyv5eu{Օث6I _ CUhٱ"W·F$:V͈b0M _sy^亍g?mM@ lhÃXy z6,ɛ>kA'Ҩu߉G̱7އG"AϝCWS3!/}0vK׸oxe!ڦ`\M,{[VƷ E =@0t4jRu=Aif8yl(Gkzj@J浈LW캝= h1iuMP*tbTlzzxҾ%O+e.?ѧ;]Å(Q׳ծ~e URTzmb/x1-( ͵$$ L7Y9xKzWaNsqFE>r/o >.YDаl1URT%ۼoxN͒HNAr@p|Xnio ޒ Ŕ*kjtK+uzҖf$mY4D%Veгf**BPaֆT+و5>뺌.:Kz g^*#####90C9VTl4A&E?u:]&y ɾ{0 2~ӛzeLPI ,I}%Ю|c ъϧ\6?]".H̵]՜rv'Q8&5i`uߟFph)hByf䈣YW xab]w7OOػY$%poYZk^g!ijmgB1 KlkaTjm]ȡ^;[ˌd"I H IDATO\g3If_ͱIP~a z4;Ujx{%Q߹70sױu?1k7ҳu9"nkbyp5U,1(_eٽmJ'7<y=z<ʠhW\X ݛR& Gqj&Fc;ȃdFik(M1!,FNL%6Vi1WYڣ#mfumc((챱uR̜ۀOyH9{|H,m/ęQ$[ʒ( T$%k;!E0kzov Q/R)U<3/a]lnkcc ա{j o9Z`iZ)hݣ湚0(ȼۜaH:a"JFP)5Ómv.h'yO0ۘ`Y&Bgn6źYߖ)s7}lΨMy8xˍ75cbnP^8z:?>k-žR3ilWgnҤRHPi,,VN yUlJ@ѨϠnGR0{>pE0v|NHD*R &'ZlL) 4st߶o\ F!325,'>7ryA!^5!sK^q*ż6 f_[:[̢+ #KIN}zC&-Xf3JRؽ:JXg'jb4&SZ<~JCM9 GjI_H~ r)< |jΏ't_P4Ozxch?-/ Kvs8tZ)tMw &-X4!",-<҈ {Nm + JLAM'aUTk "PeIrkL0v]7c:nI˚+y/F;o=3+2৽V7Fi98g3,ze jwk7?I 3VCY2ˤ$\KfL#L'YQ k$5YߗVRH;K$w&#]ʢminOQ`VޟF;ʏg+(;tjTx>@1&֢e`TFg jX3A:_p@f*']}N0miBSDĤ\8 n|e[@QaHɊ9n"sҩ%U0(o \4$m<Y/ҹj~=ۺouqr/F:1+x*Ys.MXIIJ8z(PpM$<ǻ3dv;(Tf2\cm`lsH%h}LF艃|>}VΓ.^"j 1!جTGVyA$`g"Rr(0҅.O~b$/ϱr:*3l̞0тѕ݋uOYٞ+*@uc'1pU+AiL0(//t~z.{EBJ1qlʟz%IZ˯D,}78-:V+ K jmqr@bb0{qmal]ؐGYw) 54]UNwo`U[oH yq74 xHCr`[Hj}պ:d?͞ͅݩ01+3׊|O}FZ#3˦ח=x;GvXԥFZ5jMzG/HJr,W0*7ŀ:l;c!h% u\(wĢŘzp&[A#i LY_ނث,{":+krNެ;Rc>mۅԅ8 QRue?. Ow mR,%P1 $RcŚ-AJ&x`i[P:KE*##### r`?ԑʖ&:~cdk惋F}M*d3RC60vmn/l˧ }DwftBĦ а1J)-WáY4)ȡGُb8÷;Ȋ+(*LYS㘗D]\GbY&x 3*4vץ9{SB\ET+Joؙ ܹ>_TYphШ.5GKK]3#, Xs- Vʚ1ұGKvs+o̲c_onsIGJ@ևɳXҲ1za}7L-s8㌦Fq.4A=>ưvt Ƕ3@dC/7T 3W,@Z" SXd|c`~H+RM\Oȹ8dQHUR3&{4Ǹ4#آ~n^_فL=^)n;m>םC3ei59H WYA2Z!;:PP7lPQ)TTr/o? $RMK8bL8sZ,n4cےVVwfU~k}M1sW#P`1Ҩ%1z] _,0"1fӥ{^#)槫c22222m\2kExEW{')b*A_i4JSJ=6M' J=mJOR*J#)TOS+D#J2U0S J}Eq 'CxGB׮ߠSwA˜ϒr~&K_Uf"ztV/D6ۡ~=^1}P\tA|u^*`qcZ˅nؿP W^@ii辔͙!.w ={P﬇éUĖ]6ogj$oP{S*e]ӭVJ+mJLbExZHC$)1Q-EFЪ5J/iZh5b6EkJ=GuK$!%c8}N2vgĶ.Yo222222YG+"7>N>e-'Kz?d[H3go|?tAddddddޞ:RFFFFFFFFFFFFFFFLKNm222222222222222 90!#%>&)&\p&c/.7D_ZQ5Uf9r6oumKsZcQtBiF=S裱>%jv'p$$yɕOѪB:Ъ>[}-wޛn]B46 t /xuv*gS6D{$+DƆ.fƺY >CZZZ= ,, 8~ፇ[&޽nwoN6ߛ oؗ*<-tx,qf63)KC'SŻO=p(0+IV22n E|ei}jV,C =e4O#7`_m_(P*(JTToCo2ͣ u;ژlwĝv7s3V.7/bD@[5ш7V2DmB-{vb,/[4}qUb/Xxk1>u8W .3vLѥzϾa" wavPq0; Pb.Eg JJ ~x#,,f!SfN"12 [W, `H}zCƾxکRpdV<M0(c6L9`l^==ڵqM[6{JI<H79KqAsjƜݷ7]4IھxTz6vVwIik%/Oy1=m($&-1~!Z枏L/GCԕ|߮% "~Ay)}LwT'#ٷr0R^]0+) z Up7_e,`JKӶ-NtYúѯ5%.Maħ*\ippFgj; ZUz3֐EqeJP`d7%oo`\zZfWp!Эl :RF lnɾ#5x e깫ʔ[)D3,ނJ&BZty$iyW>L:RQe(•e/sٛy &r(TrŔl@巰IS H@5[* \Ƽ^y Z.T}s0Z1˱o\^N#&&}1(hD]Ϩc4r#wPi4>Ut>I=zx:{iϊТC/ |\ /*2zVGe#8;k:wgqx;Vz?u&~MW~BX1'DaiL)5ek]aBO*O9__|}C+ˮsd n8FM`PQ0dk~#sI6v'm#6]ڦ_Js))jP#e7krAM깚ev|[jUri,9@|\NEi(z~1+!C"Rz~q&SM.Ŋ{Y/mPn ;ޞe>U?fD=ʇ>*Kr֣(]^B)|q(]%{E6n UЉiV:{PAlAy,g۰bZXԙe.)wוHPG#^GA&>-pMΞO~ϴHM IYv?JDxVk92"u7vf2{Mɞ[zw ;&5n[Y#xuۙ^O!7aQ61-̱PeS]:4K+Pr3*1oi>1d4܅ RwmAߋd҂9—NGYLPb[ vpr<LT . MLoq>:H' IDATysb zk7.~N-w%stj>c` }T[RgUoߏrZQ{C3G) /˂ *gBPZ'I&`Z'L5JAM/1-wdtgT}:a$`Tޖ533,J; N[:E9u;QOOQvmU=uՠ ĺZWȬZ֌][ YST~3gl۬2W_mgfs{*Z-i 7#ǯ7L˙1h9J(>H6Dpc(:/S3BJ2/5l:`,ljptbEY7`ڝ=&vFW7ϣSD|=ʏ+Yf"{[JoW v*RX(Z_Յ2@eU/!O,MeH#Gr?͙*w=rٖE\hb=f.\Y&4Sԙ&~4A)Yq6vn(Q65p%8?o{S ֭@%5gTuR@.KQݱp "S&lSfb*rfsZ4!iyys_zՅutwVbޗ>9KeCN$icy iI J)۳x|&Ҥ1}͸"1yt8M@c7\ 86g2.m7GH$'R맘 I奉3Y ΪLЁ9vveTj |n8[\ZiX@Scg&[ Ƥt>۾Zn.rJ@D Ye%hdJLKE+P -}W;gK2ŜJt$tMޕF>(֮aHMϤ۵:R~@G0?}u쟲 3@ -'eApkSI2.&K9/;Tyq N~?ujB(mh& KW\d{H Y{1sGATʩ$晞\@ajLJ ׯb%%_癄ExԕzS4"[a[޺O=%,UVCGg |Onoنj,XXեyt)'g^^֙+V KŵMVEf'PeZ:˖%V'qm+0RU*:dCNS hcO.=s#h6+-&ĴrE +vfh1t̥Ο}+!~u" /6yu4| W&oLIRg\UYgtBEOlK68d.8[)ǔ l^=g%PrQ7$SvGM´k=:gCkr.QSֽ2>fy~c̨ߗoVB~-eM~S9t*dv̍4i,N_|ݪpt/b2^;/rui QDqLsYֻ]o?rtv3oHzO|UіV(F`d*RN6`f2.yu8jo\0EZ9.E,[2 }0\T}5c[RMDA@J#ui> Oh<{Dm39b9N}[P#۳é:g9ޱ5A+wr"?1|. 4ؖ ?!9O7fYx+,f9vJe$9>7k#/KawaQ)(3prWNA}P[8SÛAm)پ%_ M Y:%DYfwQT_ntN!*i~?{)+b)2Rr~`'ZMSj keVT#9|{,lZQa.OL(c}l1n9Xw7.7-Kȹ/P©2&p||<,R*Au ~x˺qbzt,Sk&6,fssR)o-V" $_}ax}H"yzJ YBcݯp|sq3(+njC@~q=s+bІ[ߋVwH ~'he/]3| R%qԛzS02``HO!!j5h4iD-VFATHqDL-8WSS¸|GЪdA;t"(K#wy C)y:Gap42cllEFy,cjgj~VQϫ7E廡ĥI ,m4:-W qЯ>+gb/SU%71,+IYjI!_=ġ)3ƥ|lc( 䧿qlgj3cB!:7#Ӑt<> _ oMr6 f:3' F&1'y*+0_~D-@mmyA@axqMߏ, ~/ޒ*,|g&T=e3Yw%IGA$i;CJу~MODj$_cSFҶXHⳣ,Zd* 3K?#AH ܭҁ2F (ͱ7IDa?/{S5;/K~beTTS&tSfjآPV4MяGM(g]&e4 )IĄ3٤7TїM۸FHdբМe{k Ui%&Xe1#'0!6osJwB|R*Abl7>xd3 (êV?.Ef3c3%Zj4h(R$߬ =ͦMgӟDIZif{vW FGE7wx cII%nLEMqT%#:n̾8NąY,:Ls?wv`a=+:.{ǪŇ 4={Tz|/5nH]c% ѷӊKbI.Bϰ~^WJɎ ԝm?uL};@]OJ,È' i\J̼iLM2+fNf Rb rwlFJL=n""Ї1E殝fzϵZ.~3cX"i4h4@!â`F~ϜDJHb Qx"g}- N$xK#ӻ f»(Jɍу>Oæq3+WfM1x5˖B).;~P:_tї<ȸKe ǂwLAҒ$˫P (? imBeLݱZG[@I.9%s#7iOq9]V"!/7^\.GalI4{iu-2T  <ˎT6̋9Gͣ¶* ;JNs-}h52 ^[{( Ha[؟Z2 g208mGs;2:R¸v͝+Jh=*;uYī_5;+OD+Sh*Ǭ&E["ًrƍgNk.G&8uc ž:qcZd_r~Y/j -hPR (ըnвu9pRx>JX×e07Qcxǭ㷱/'`V}Tc?2J ;VX=xi\Z6fZQwqlfFh'IlB&åv>JDD@>krqLe2%U]݌L]d0i/=}WNU/g^QU5'G[t0ܵ1c1dFmLg ԛʲzѯugԭ14^aDZn=ւ%v7kCaKU^2%qF՛xA'& ~n T޼ZލO2t{q"k,U]&dz_'D`~ ,ı| [S5fTYb̢Sn46!3wOHy__UV%|'U:fǫQXTRQτ6DOW~ʕ^HҜv5cpپ3]{aA\wdP3f]X̢6lZ;degG&}Xπuv\"*#T(DlTrcIB&r]\! r.UJRJ2%hU LfE4+%32s`)Wld#e%~=*"QsCt߾P #%q 4wL?:>u+{V0!?I;]\(~TDF85vV#-GS!o0f_HZjC%\IQ8_FU_N\`c}a~zH1\S%M}өk}{SW#*C|j~w0Ww}V^Lt:$qjTw/sr[;{&tbN7b+"4BYr(iP)Q#jDVir#/*Viu*Kљi2ŀ0$H{vg {.(n>؀ M/ncLJI 1 wg],RLC2ӡ5a?EB';'}@;K[d1{[Oy@J |=s_k?bG-cC"9ď{aU ڸ,ZLL|RX (Xe߅ϵS)Vo{YU|l{AfQ w) Lc#o?r"`Ҝ7P}|_ ;K[d1!%=. v1y UoĎ[k< ǠQUfZw9he߃`N#w:2O6}n=Şz8bx1ST5ޏCHx7ovjl/b$1l0`.1oߒwP $a4tjJ8(MJz̮9ָ a[Єrx@p@R m܊Χ3j'_@^\҉_%BS:KN<3TxUf)<w$Nȳ)/[W}*+?+sI<6-*a%-p0!p]+|shI~$V߯Sg]֦RmʐPdD[7Aߞ"$m(;-X˙3Yx+g̮TV]s9gMF Hom~ىzeߡх).*5gPϲ,,} ɭ 7l0PlIzW܊".5iYp [:b.Ȍ(YSWb}'w.Z?\_W:οN\^}2 LFZZO<4Ʋo_}5^$&}H߆'#(ʱ3KIUrQH}TI'>5),5Snh^IZmb)G/Qsw8#h޴_TlhDAvD2>﵂y%tLm-o>n+7uFJ8oxsyщs.k=%o35^L;[Ԙ+1|)9E&Fsnfg$hs)öܑHyA]OS?IIcwpe.AfZvWpv 1<OL=-d>ŏe0`1l0P̐c`աBi[-a\iqa؅&ZP %L6,p N%,Q+3ed JJ")}B8̃HG:ʒQY322  |n+1 IDATlMY7]ԀM_|5g}7Vs3t{g8_FubٮLߍ&q:2WDJ$`8{TN4T>mZ 6NlE)AK6d&'Ѿ 8p}>o67ҟ:j|_r ^ōY)%rrH<Wp!,53KfeEb0ջVClH 9 x8*R9p0jV%pՕ{Rch3|'! 72gJBن_K..O8z= e{f8_FmmK:bU9Jy iS A@pny.lЩ E }"N,\!?{/n_nV`PA3o>Sykχ~Cߚv))a2SJD@.MYcd)JWBIrQ"2f_~o]d)mD6B%t܍a}gNmVF"5NDP>~Y$뷉PԲ,\&R*!'m=:̸%H~Hh"9uՊuPN]E[7L+Ҧ#!E^5q)I9ms<@#lG#u"3T^~˚ <º~XJ[lM$Y{NF'oŻYzG7})> ܚƜky-ۙSOȸshsz^47q)Z\1bi$m]GlH=~1X ^НvFȍKѳ%7V ڈ wQB DnxH2%sBߦ M/W̌QЄqᨆ-PYx ς‰ׂʲ4L3QYq#ZD ؾ1ި425e+`&H!Jyץ"{1}H}T2u9ڍG\;lc9S@nU^CKu$HeWkao,CeWν*sk4meSL)r#dž Շkvž0 -^T*I1ka'Uuۜ|. gaL/zL.'Us!?}0uo7y*`7Gympb?b,mLn3 aހSBFi=vw6r:TQqS:QFubBy9r .l8Nk b^TW8nsx/fĶLihPWʪ:@73 ۼ~)qD#-68ĻqΏJNcΦވI UȌԑ)41gLYRgUoߏrZQ{C3WQ WgD%R#0]/ 6)kKLeĥI jsU!ҜiYT:y}5U+NrLT0µ/,s[L}蹽kCɂN{@leܼWA!6X6ʴհQ ei5j;490` ɐbX3ǚbjK{PcieGꝘcw.g =ɕv*ÌѾ4?L!ټ\yCx #^7+pόHA7HySPؠ/xץeɻi)fByi⌳y DaႳ%/q|gģ]s c9T@TNf5vj2EP`LZ@OpH)썲4 +\䄿JH( YeueJLK"kPaTt./^۞^xzzڍ`GH\Tn_C5 iMu;3[PKIlg#@ubʉpTVĕ J;,b2`*/Jy6t?Bk28fɱ!x9fh#HJoVSI3/ ScRH$~+yM("<<)3FtX:VhbzBOn{ \9WF /*%SN]Ϭ핧>Pcaek]zNG=+898`5-&'6YI)Tȹɢ%Y$,q %8AhYRݝu9̇h2;O[ˍ{_nXt`H򘤷E/i!V|uKۗ`Ky|Q< pl`pmA* jKvAH)34>=mR?0J5_'#S&lNNL%6VLL|c̜ Ql)r?.iɁM3r}pl}H9&j5Or!za^`ő0ɶEGJ\<֪laln[fQLP8и/d~ء43fTֽ$S 3mqi 0jR&'& |\W.z`:X:6%A2Qx*CS{g6 1LX%KKK,lpp=h J9t*dv̍4iN_<ݪY:Ps/rjeեqJ~IhѦ6.iN8e뼽؈߶RT>8JIO8)װ*Q9l?hc aۅΔqO{Oq9_2q20uiy9FDLw\Kĕüi:kK†]t?gVv?&& !K2J[$}H 9 u';K.`^gDO !.Y}Q(fB^Drx ʖAҗ_zg8gG7q5,>2.6y4pzXO\ɳ2VUhxq%EG BvEo1%DNHiľ˹l(m3u[aNYʌ^upߗk~&#T,[.)P tC3*$orǵ:XAaEܽO;:j*d[`䶙,z E?/R&taNv}}[IӋ* Q)Fs"ìTI\:}ˎg}7p  ;Yٯ&: mrFBjhЉZ$V_OHd~p,Z".`ӱ'd?J˶_8X pdWͲA9"("ZrzqSrb=էs%N`R `)ݪ悊Rpn,у^~EBSDĤίiPHEfKٖDzQ"O|Դ)bȅC*u&nF!y|>(1Xt URø~H V &m5}H+xK2csll-dPXdݕ$b[ z8M(>Up_ӓ: 19Ǘ/'_zE$(*Eɰя~?3D+J!(c{`Dd > F_ jv_ʨnL k?U4͘:հE(AfiM硏PLhR ggIoBS*KҦm|$RNjQhcz~4\8ЪQ@΁@L|‘_TH[".Rv4uÚzWUeS=3Vxx^=h-HFq8闓RU~t \ϋq g"sg8^Kly7hhu'Tδقcp5<1%K.{CzM$;\1$zk7 qϦ8*6ʟwCK&XZ`i"e{uS{0,!"[l~5tHO{y-Z]"'K ֵAOrN 1I$F_o-WD-k3ڣ6ӳpzNίe]3jBAZ6ѿ˧g9 ќȰ5X."HZD  (63hyyG] dP??VH dm+*g@7*>Jb-EJZPuf/#$9%z[ tp]<tbҞdG47\\Dmכ-q8{oDƒ\M웎ͩ "_nI h>iS~):.1hk"Gnjq"udQ8މ38u[Ip!lhLJN,<8 6܎0$Y!d5ʢ3%3)gfѥ ùRt73i{s/ZҮIo$Y3 NrܝᳰC>208mGs;2:R¸v͝(Jh=*;uYī_5;+OD+Sh*Ǭ&E["ًrƍ+\iLp@t=tµȾA$_z M]i"\[РPQQ "er}/=`nƺ$[Moc]mdV}0o`*eVȊrf0̫ѻW+=k:GHX3dWΌ*w%]sK3FnҔFsxado{_#f$"CP%P$b^EQmR5^w "5Bs~LO+|y?IYq~ ,1{)V´(|AՓv ni1F^L{JP7mer1M-TV[X-g+ٛ}Y!g>FJ[oD]; ;tsK:ιCLg6S\{2y Dc(lUۓ<)4WS./[` mx/b(a%ԌBSg%uMg獴d2222Zo.IuarjDi4R)JR+AgURP+:IIJafP͕jRJa&(MeTFR*y3ãxD хq]{KUy%HɜIJ, 2~HNUi1r+ӥId^D !K?wE{w>f殑s YI3ifӟbVe~AR}N?RlD_N386=(6*A"xشaժzIt5:R#cIЋ zIxR )*ia3@D:A)MRWu^O7щY yV`-FGr|^Ax%Ȕ,T1߮T ,xkx)̓j3=:LPW%Ћi ^NU)"ڸp~XȰ]^i\T"ۨXmFFFFF߉cȔ iKº2^u)Rmƥ^(./n0soDk/u3ς!V#qLJ%_fdddddȉ RL ? +-:E?JF?FeddddQ222222222222222$1:RFFFFFFFFFFFFFF& #rbBF?K76dXtbs ^Bȸ KG/??3_uIJJ&U^"R2+u1W]b<{zx|G|wDk_#z!### !?0u(/ ?K^ɜѝ, mƱdHQ$%r; TmÄ5yL"gB> IDAThи ;,@?dG/}hV fn)=;i/c7Rma=^~'|juq)0|ڳ˫ʥ%_hݲ5ҸA+/mW_Jr4/, Xҗ&a,v%uXU6hfr')F,{ٰ4BE)s ] k[ }cD=s2,Y_b4=U-O0դ,Ǡ@}/3NfbپPJȔ )eyq +(HFc?"|IcVެcIHnq;KG.m7n儲žZzYZw]]qvTQD#S'qAk4/rRmyB-t:ʵyל/v4jXo_>0vf9NtJ* Z(m;jѿ^+YZ4V;N`}4%x0b*=IT5!SOH'B92>< mA͡=2dɧZ~^f%Ó05RF-6*{&^"տ$6vqIٍ3su"U %͔hLiDJza[!ӠEcjWqU)Vբ>v7dC=IdD$Rmf FVVܵ}Fe=?VUPչB0 J +HKNѣ^oŲ`o>%} $lu +P|B>bGJ)t匠`Uߝ'h< lJ_Ӆq9 e/Mw0?ĺI4~tˉkp{ }Źgf2T"7NT4pb"mz+am,D9A6~xkrjhZVrWͮo{RK# `vx,Iyg?ì`߅7Ңy`Cs~f3ff"O#V1.[AهF~zbd=>\H՗7 [jgڑxdoʆeۡ5VKLT A@KY$sr]ǼiS{teQNprpZMWMsUyjV~]h؉O7GR`Z̍=_еa}̱H;ٳ)5`6AhÆ{HVf5&]λ2^eX`ik9g9bױf@:iF#ɔҸk|ɟy`Y3qЫ}/ܩLlNf8 [c=½lֶr4 t#ӝe}b5G|+1`A$.|ۈRp+GF$sv$qZԘA'vNVyԣ9K\Q{ZNH9* 7 D͋8𠰋y(|z_И"ڸCQxtY2G6Sٟ>raf2s?o;b;d cˆ|QUJ 'xX.oy4f5P$Fx;GXXb.=1xwl:'6~=;PVko$Gr0F+####SrĄ+E'% x& (H.mAY尮{bw_wVFdU'vKs|kLӍXq;&eSbٜp~h] Ge1uedrsU_B61X:a!Qh3㹉g-vݯOVzAsitL|ZQ ^dhxff7X1[T/r? Glѐj'ǧ10=^M&i<7G75||G`~N7ҽ:o%Z/Ԑ e_~s=N%kT;TADf<l3XU!`tֱcGXWgs_QsN|{1Pz@|Δб ]IN$\Vo-2ta혿,ک Y6ǜ]>!x<;am{R~.$@|CiP&ODDǣDO AkI%Vgkk?~fJ/ͥ(mJBw2i qgˮ1nVlŢ1w߻!QOqO87~ƈ1yik'dV U>^p·O߻8ݱ5a~ߦxQeҁ\2mwH86~/ZQm5f^5H̉S`5=:VFNI:qwkEGJoUUBi;q^FV<ɒͩYُFݞH $^Tcjc.~^\ݴqg8m]_ǜI E]FtOGZnĉ~JΟרULjOU%/=.-ї-(>g3$5&> ɕ?1_OE,]3+x?ԃ6@\Y Wذ_v 1lȔ91!/6|,3 iMG?`u"Y ,P-gaˁ#l!4x(wVP烷JK|F*>'o {ێVeH)abμeU"+i=e(iPjktels C4$nFGaVNFGv-0GPS"MKS4c>w;:^@Gwii@P8u`bS©4AAفH:kr +B@ajG%w,D=H8ّ`>Wg"-F3UE @i[XwR2.5q2S`X6pT,ZD/fEqi&VJS $Ʈx=ײr NwTgcVcOi|5}uhƤ\')d@Jaa(`7g#r4k*]7A4h8>gN06P+ N߀g.{ATh:s F R~CrѠLkfvZn_T[+@ to4og4=:c @}aԸ᭝+9H4Reۋh Ej1_7ދ.-;} KIʒ@$) 4V&jJlx$ }E6͑}=>ޕ93-(^3kHbj6T w,fn<-*=m]?MPӏm3  AcU5hV 'ӑJ#k+AvfO 蛻M@̟qsؗ坁[5N1SJ|Q;.N.x_O'aӅp\w}uUֆ~Z@ʯ;Fbb;ӯ7EO Q,0@ @R ҍhQQN)ȝ'mGn N<9fdD-il/w%qRyq XLM +=OSƁĺx yxsYE-攩ߋ.ctٙڌ zS2ւ}[ࢮBQ 8t'=72s-eNtcIahm(C:+)1ĖK}*Om_ѩ y{(tqBjZċŒt")P{bs/ގ&D^ 1$[\੨0NÌ>?~M}8Q55|QoěW3brV%.vy3b: 3|L^Ea>/u9jڒ`bm )Y؇WiF-q#9m֞ŘMk~p1ȮRSMyP7]m>;wIa4}Bq(tqA6zg%xፕ/5q C)+851aF;klD\6M %C?+̰/!>6=d'9fVsҁ7e;lw4ov1kT 欔$V_;T٨dĊ(}u.ܩEsW"ZZ=Y|ab8_/ڹO{*@"=<Ts1du1OKȹ`"-.Jj:Dm湾̈nKطRf:@KHHG͘~}+]C[C@YgR%i3F޳\([FFF(+&^D_$D6 Cj%`JhO.vXς1k eKi\΃id&p|FM2q|.3G#zHZFO~%O]j"(Ll>IewCr?=L3PQ^΍r4 t4iNF'Mճ\~CbHʒTؕ\IqgtIvm*[4+#?XKX &.W {@jgR\|#&CDLˑқFFG 3[`7i5RH#mx؀;!*z g!szЋo%Q9ǐg4{/OHHhSr|2my3'CTh`kBipT@ l晽W]Փ\LfVF,"2ǧpғH%'ܹv1{Q4\ԛ% gJ;{~IOikfdJ"7w1{czvZ@LM$EȌ;Iشռ/ pÜD_c({Cwo VݦP{~&^^ {T*jԡaC qz!ОD{DJFOc"$7BEI[sD束Y8;Uc-\M#i9|j"QB7;L ^g˸cYX8!1v;Pia#6Ee1{fEٳ9ݬsc6fD;)ihugMh91{>T\&b}0Ae?mV8}-?=ı׉}JFz"172swjp|QiuѾ^\{7^7S].M8ϪQcX{:P)蝓h /}JZ-{CV2M?"¿kH(G+hFT24ش s* <ĺc8+ϚF+|"N*/jO0#&A R}IM;@ISA+8S37[QY0<|@?Òvs@Gwi5oI#fxxgѣtr, =X6[̍SU,2|u;S^4;Ǟ^zsjSNtrB!~yzc׀|^9;k RT]C OCƼ[V P^cBs(|v1V\] ˻gv?##Y9^b!t;Q?&t;8Y-ۤCj8xl]ԙ jP93u 4C߁ f]p/I(q $U c9;Aq#zGN RERoP2y2H-|D"Xҥs fߢ}ZGHYo Q'iT+Քo71 yCNʎY-rY`7{>AVǿHC;K-l^|z=0-J3_Z]ޥM@i[\LS %&qtngfoeźʒ+meu˦Aب`1D?4B2#B}K1)= |w&u~ .(sxk|f9Hbhꤤ6S0/G_%)Q6[*/NV22m\8?rdخlR@B#J[̂F"0TYfڀ*Ͽ*^,OOzY?E ՝RFRڌ22222) =̫EJ:ԙgE+Qb/J{j4֕ nKaj35.BqyIw+{#_^ |QӝRFRڌ22222Ƒ22_.E@~7*9̥WZun?$뎌 ~EW]RFFFFFFFFFFFFFF!'&ddddddddddddddd^rbBFFFFFFFFFFFFFF!'&dd^˟ƿ[}v|]˖^ = 4𺗿J/f^s3Ud9>_^)_!,#BY{%7!Ƴ>/u/nhKD/dddѯ!e>IJqa^ z}'sFwmƱdڜaǔ4 5T`<ٵ =_*b2'P5-;ÒѬhRى{[w^ưo,+_7Æ{N"8 >R`N)xgWSKK'Ker15kѥqelAq/v5H/-QK:Rɒ.}ImAoWn_ω1YlmH/wbIJG Ms/A!kxZ@u1m Y2,Q1~ܞ' RcPCCV4E }嶙XvtbѧpxZ4V_/!>ؔ9Ø $%?!| ޱS꒕~DcYCǬY}'{4Ʒ$aq"Gb7n_=̺B^^Σ}Ȝьq??,QCw)U_.Еhd*64h͛W.^2u^ENg< R8oöΗF M&8Ì5ljNI%9Sm\-4k> +q[+jG FBlVe'I<>1j&d Zb~@2GƇM=p9B^%s<~i6geG?/D &>6LMî-QqKkʞG?@o'#+_ix!xvc<\HUek3@tXZn<h[&:&gW}e-.Qo|(Z§=V aȻ' =KƳ:ؠ`XWg7*8Yd*T܏J!LzF,g|w*!o]@PPQ'-/6B/ 8C:#3rCKf/#]7 cO/ni&orZ))^~|-Fs 4J {NLmQu%,M壂('|OrCN-MKApn/u=5;4l]F@Xn~Y 9o-Ez |f{k ,uc?w0gCy*0k֍- kA pmqHɜGkf%O\|~+Gq/-Sj/0#fm(І -If5&]λ2^eX`ik9g9bױf@:iF#ɔҸk|ɟy`Y3qЫ}/ܩLlNf8 [c=½lֶr4 t#7ޫ=̬({3e}sz- |s_ߏ :$&qF F[92"З$#)_ԢƔRM((m4FJ%r:rFhCΓ$u(a8KTffxjT9grW.LT&@:n['mGLVxal0y> .JIOb d( & ;H#]|,ikH⍠"wN+/VulFekÁJ`VF<ͻG1m&G#_}@N!ԯ՚"ɑŋԷH_+֑sţCZ̥dy酌̿91AG\D܊3 9 Vڄ8ym=-9s&߷W9fLTQXkrfUfP&,9DSyeZ_Ɉ:$?$?eKZΘ>3ѸVhV%#%1tos $Ⱥ+up5v~؜oG/;o2j'K¸e?{\;[Ĝnt⍓t5Ev6U,Q,N6K,^µ oKF7&@]',$mq<7 eܮIOBAK^"`AË ,+F|jATRGa|CsZ\ p-RV-4ҫɤ>&w||G`~N7ҽ:o%Z/Ԑ e_~s=N%kT;TADf<l3XU!`tֱcGXWgs_QsN|{1Pz@|Δб ]IN$\Vo-2ta혿,ک Y6Fǜ]>!x<;am{R~.$@|CiP&ODDǣgv}%RJJ ^K*rE/^p·O߻ c/eJXlgzִ5Y~F˽ φ,NLfg~_®.clF±[.?|ъͼh˕k.5jztYRu(rߪR \-VNsQ*yKF6fe?vw{")dt|15W0# S.~^\ݴqg8m]_ǜ^C½6~QS"/Q93q5jSշ>m}K lAk3Ts;{2 ge J#]%㚙_L}&Ѓ&gU8=s!X' }fe6uz0f+Kw!vˮ!<8MZ@"Xxk9ϲnEun /a\C%8y?$q(vem=fR@S:}9ov5BLLn^C~*_é f57(<)[XÖG<3Ch4P,wdo3Ao"IS~}Ҽ+&6C;q$Ħ<]-rg"Da3X< ܱTd Bk~fG_M16}¾0ZU@߁k'E)Co>R'3&5hӹ OŢE$jVǘob0uˀOqnN ݎo7z-/ ~Aey6f5KֺWѧ\fL̵O P? Xc:͚J=qM; N&1 ! `o7YupP)ťߐ\4SZt ݾq/wV![ hvA!ѕ-ϱ6<pq{ѱYzM Mij܂Ε~$5қЊf*i:7d( 1+6)66zRRF†ZNqf:\l]}VF"{ܺMBY+:a*ucIҒI J$%IRhLJlx$ }E6͑}=>ޕ93-(^3kHbj6T w,fn<-*=m]?MPӏm3  AcU5hV 'ӑJ%oq}!xa &2A9+Q̗̿ 1F̥&6`?17Q`\cpmbJѩ%AvfO 蛻 *To͘/;p,4Sb[Zqqrï% װURrɌ_Ø44#{sSTSq]bodP:}sbW`<Ɵ [m!j\m旣D?զ ~?Fob)>%{nY!*kwLq/%;âq6LcH )ȝ'mGn N79fdD-i^Fe)ى GGۼBCy\f U&'u|)@ç ŋ$eHċx/j16L^Lp+?=fV0՛–uZZ;鹪dZ˜$Rƍ ήЧ[.}l@2]({;Bo%ԓlYs8ԇNϯ2v5<:DD`jCD=o\ GTmpMS [8`$2yI.o\d]$bCta|ڷ9uQ˟aHNFӾ mk"`םnv#11UgQuܼC ʱeP(2 K0Ži_ZFnHHZɫ\7aqǜ^}ZRwN$-Sv~N3Ą=pQG(L,ѐLRV>3ILTTS\(U+~ןprvj|]8awȳihʥ%st#e(hT0هT{uPYXaDV0s;X[Cj6߶ =I8ٙ uꄓ{LaS,e/,`-Iߒ,Z/q֫9E38i: {/}I 6rs5h3HFEkIwޤ̋v$###$&d^*\Qu@o:wX:V;%(PFSb̚eӥ)|>/0028{Ӷo goVqƋ\~}r0 ⷷqv-c**Pj~|Ѧ.){YZ QjsaM9i;mn):;ߤm ے Ғ nw)Qz],(ܨޗ7p"3׬ X7"jiN7 ũG8X{qQ}ێ&q}hZLW1uLZyIМ$IHR*j#XNk;Bx wjQլ~\@VryV3_:ݙx7WIld¼pHnڹO.{BH>wTTEc`%FDĂb4vŎ]X$&[bQ(ƮXb!,Rݽ]EF79gIp;|frXw,ٵ"W/Dq劎8((QUh`׫-50Kk"%BRbIɚ^51ih4hGSΣDҒxz&/ZZNmbۤJ6sCJ 5=ga0}W;u~#d5zxg$e"("ZRcnrxhPؕ1;/5cM`\VMdȍT`]9d{0{ZeF_Yyt1ǖ!اl,(v6~(ǂx+ ;8БzeK~ê ɆK=?2I_z׳x%Q4g2$$4)Qܾ“ EeDp hVeP,I`Jùxv>.4?#C9eY`T12ƹ(OӏI%Čg!CIQ1u,/n/д;5eƄpj8 X+scEzq]Tn uQ&"Dq4z݆Se\6_}VBEџA f]z37#KN'=) KOB^ IDATmU k3 #ʖyp'qK-iN/:ZY;ꤔ[\징D? C{X*N+s}GE^LyZA7a s) IL'n(OGLȼ>oXG3cV`PwF-i[Vc?=K TPc1jぬATؐ%~o!N}{M Q鳳vNíPV=̲qY85p2 ]T[BP`z󩋉މ.<;m5Hhcϱrh3*)sWy>ET`t&⇶TP*P:Ȍ>m[TwtT|HǂϬ5n5NQYuX}KEQ֍;fSnsw*+5nY!aufT7k=׆ӗGہVٕZEEI8=0#ejsH:U076Ū8XNȬOX3vM&|@?fr4~> u_vN5l1ϖ[e?çŠuvLA'w0}Sڌ`NaplBy^"uztb4SzQܙvCO܍ITy\ ;aߴ1 &2jwVR|)wӋ+^_{E߹'Hܕߟ J#&ddd7y\ru"ۊ2j@i4T)JTsAeURP+ZIAJadPijL\a$X( eTVR*N|g1b_r =Rdd Rg'zs+_~NnfzT.\_DbÉao /ͣ_6 oI3qA `=]έMy-wSBNwdAVg OQt5`*׾m'$.mzPmTgbo]SAQOm3]!Fqp K [Gߴ\N)UN3ZCufQ)ىd S_zx6Kt?\H:3CW )%bSg~x}%UٶcVX_# )@X 켙 a?{Q{ $}Mm@Ȫݾ6Sk3u,ʹsg{McYm,I@"@"F,mv8է#6/ R%* &^ש-^ZyE28!6@3i3Ol_V(4P>OHɩҦz}HJŌrȶqƬ8ɓ(ƟkAFFFFx !? wˇc/D9FYK"پ#C\3ZڊcsD-QAsX֝f%r}9AӒtCeH{<ɞdo/@hK42yvy'7u]+f8t &/"I?!R$}e5 -kC&o؟ف'yBRf9ݗr N# YZ6VWϦ8bt<ͬI,Sx8E|N!|H|VW`bp* F-gyZhK$=&+ CbS62I?6vmq8L)Эi=Y&&puU>PJʌ>ڱ^ n#Y7!Dqf89g<5;;Sh`* a~SgNw׬U9o-x: =×r<"#H$>&`)bjLko!p7[5RC)屯ߙǢё}m[VOf@# ҭ ~6{OTc]+6|,@Mc4l;#7͋[).)-o_"8=s;ţ_j4z"k\KF_#[g 5ai]w*!))*ĩb9ʘ`feC%;UDo5Gm"p?;P2TM7=f酔Pv,\Ą!ً6CgRvvb`klރ!8慵]f3 n鎇n9Zl9?ȕAY$&r8ICY¤sIVS6u!Npwq+;c,jsZ#-?LU2FebOShmHIҷm+ü .>iP/*B+hLZסlڨ`Vd80iD=daie1Mw ͩ+|)?G—ї-SffY> |(&O.m>g{(F3ҫ>3Ւs?lK+Dǖ3LJv(Ֆ)p9_fe.aPbZ)tx Wb&D.bLR Kddddd &dIW):պRUŖ<HoC?#~'88zRAQ,Umtb&fTgOOEx_N|DmSR> t16NנuKȳ'z;J'G-pd' ?*7Z.z7ts/o2l?_ńտ"X+~Wͩϕ[Ybņ2솱zA0Gn6c31t2|3D:6>a8~NLַ!iڴ2]ȟnfMXʇIOڱQ{e>pw_Q֍ #B2ѝ E-."G֝jg'gܜo&ݣ i? gwwM:]>fT(;Au*Ac;Xe6!\)6g)CpkN-+Woboc7ߝKȝ_bXpZGFz#1Y0_z´"Ǿv77#C]3±KApaVtGY\z6BSsq_}px~ZO;y!.hA|Ƶ#i.A% %!>$ˀ/DiUwU5X/ :n-َ|6mj["ڰ`zyշ\t~ key7Ʈ=cQ$7{/Fo ӱZgɬII9L4^Xfu}5GaՄ?smxv>H%7 !?mO9Ѿo%^"!g~|-jt:%p%,?[)!֦; 3T%Z\z4r478 c՘6ԯ{,JR\~jLZ%nދ+&gBN&`R!am?q>tQ$џl;\K,ɭhyLȁ 7`̐?/u>\ UZUCn sUV%*h6?糦e)Ѹ 6/WgWwFi!(LJ:4- u="ٽ4_) AM=#* 0Hz̽Iա0*Kjz؋ׂv#(Q'#U+GS$]8ƒ -1ح%Ơ<j& &Ui9z*Zѣu3m`&2㮳uB{gZȂDҍ]291CV>ǭx-dSDŽ}<}ĭ\a*޻?YX1/m?|!,mvg(:13d)c C,,t$'kĤkO7 =SX3۸ew0~ Ͻ2CZ&MM"ʢ@00nj$3%2HLSs|5%FD=D$iam9vfI|5`Bw$LTUFUsbnTv4J_8M$tb\>[ؚn0V*1. AvQa W&7ʔ؞FM\VJ45KϰrwXKM'ugؽ+NKP f'/qTp!G6}G0wM켓/mة:E=OKa/OO<==@b: v,ދcifn/ 8Un"jl?< %AC<]Ҳ)|߯Ҡջ K籱=yFQc'go5dX;K}R2{NѕXT6  *c$C x'küJ"$g&*T+ԘmUCdft d_uβ'm)Z$1]zfNyJ3lӾr9k/IƳ!꣯>ބSbE8 -weT"f9YӈOs ]0Kϡe8 ]r8OV6߹o#U-'RR,y{(1FEjvTy]@ebDz OPVuRƶNTBwb #>xxQ˓O3g zOik+gNClBj{S75/!,NVYU?2֎ 6i]i[l1 )DQ`sގ,2vT4kK=shme51~.yH 3LI"13v1%fOtX9;[laK1T찶v|%;#teחUqZ]kŖM@ebYb"O  R $kБ%Oh33XnkJҷG32v ߽sﺽCe_W׋A_pяØټem7w?bR' *YD"|?WIHt[qTI$"3+)9?0!󿍠DVJ=)#:0?;f姌BzcggGw={d=|k3 ,,,,_-{a=3]q5 `hc7B RZp8( rM `mLYDv 1`_qY1L \u&sUZ{'N64l9S o |MmCgVY ֋Cr)Ў>{yn)6{㺖% U#w6:ll^IlT:;m r;).FLj ZѰL~Hԗ=jI%nZ;*KY=#|鰝cw|TlA GA4@S۬!Ҵ2qym'ڄ<ϟJH̭V-k{C-G;.*d3/T5u@tېTCM#O,ljgY KxٞhIpIQB^s #U4%i y$i;l͝|Ӟri%͔1Gm#6#s< !rt@>ښ@|/՝}[h82{4gg ,24׆kx$k7e@ˊyF)[v;Qn۰^$ IJa^]c|-.Kͥ hPɨ6aͣ IDAT$?t MbZ@Vjsy^3_b_MmӀF.WLN I=:c%ήz!krEG6ie)؟f^趺}K.h< =N=!<>Пw(N%F2@b2-F,0ߨFF6_ˣ/>.1T(0vC_7Bv"R2vPbLɝoWsȔRKN$D&Ejh4huo"'9s3tғVRso>Kos}ʣ&Z{:3 \~g#~<'{T)fBDE]F"a1GjV5^=7 iGi99c'eˉ<CǯSV$$<ϵX-ژN] '1SBPcaU cs=kԘ5sq5Z51#7R٫&vM?,.IUj}2g EG[:`~4ѳUaDնC9[)HH1{,pQVg`M6^DžL$]yOһ+ʦ9>>ǔ !IdH/,#sn4E$0* eqAùxv>.4?#C9eY`T12ƹ(OӏI%Čg4Y. Dfar,Sc&OʎhpmƧ@ŭ|vsV]f,h_//ڍn#C#Id^c/_*:F\\%!džcRu'/bsiySL&d^#a2؞N[ SϻśzYcq27ƸL `~?rLZrK?2d}㙘5*fVXƮRȂ&BhlX&7փG k9u9 {ԩdlZ!`Ugрy~ԷR i26LikHs}]&csjtn艇E,pRʾcDb+Qe8S$p5ؾ>Ȫ+=D _Ȍ!N}{M Q鳳vNUS@{e;>D!(pj>Adf3)ѩ"tS]yvoIj9x$X9+CD<"l*`\c0{:C[*((GddFp|-*Tvw= tϓXƍ;*1ko2qv(ʺ1}lmNe3ym?k00ߌVfB0t@};p~*=R(I]BGZBVT}SlU-tIW2ҳ ƦX5I\Z;{bWx>ƮIՄ(pLOާAu>ˎݩ73ٲck gԽŽ AqL1Z@p jS9)70| Z>Z Ljcl%SzJ܅ݓY6!\c@N4Om'qW,i z?fF##|8[4Oѯ_C<-NiP'FdȌbܭ06(;0,J3_Z]ޥMQ;\I+%OfMYʌ-} MV|ZH)/ӣ/շR!X 끌oS BzWT~Nu,ӵQlӅ>3bw:6,;gY(cbeI=.rgsp ;;bP`XkA+11IJc)VwόL^M1%)7](j!8!41xɶ+ӈo~BVV8ͷ)N%]2O3kD>K$,>3N_k1&%QF h~Is.Ɛ}kҏ u:!:z|)JP6}Dk0u~DvN39,_%8bODz}nNQ䵙R :iÿ@_KA/%Ҭ kUɿz}eF*&ǴTM#Oɥ%+42ªzM* fV6T]L%ɑߙgbV   e=_)-Qgvي*0Թ" h$2v9ZvVtW4\MSWLµRb0C:x2>vmq80B4A,*u녝 `65!yrMgV Ф\N¬#.G? }{5kUprxKa`(N`ȧy6s0 .X 8bnbd<:AlH94onZǾ~gfFG1 lY=]:34/l`J& &FS=QuP;<5Grz:q F̵WX?{{γӶR`ZĝsY7k<ȱH߻ƯqV~jٚDk6Ұh77/ny4R秸VpXrW!Ө뽊p-}lyՒ4ai]w*!))nFm"p?;P2TM7=fPv,\Ą!ً6CgRvvb`klރ!8慵]f3 n鎇n9N923X]Qlۀȍskcs^E dz#WEg鐘ȥZvȢD,T*2)4۶O K܇}۶Εa^a 4w zQ(ը9 !s4FJ!tto``jScz/Hסl4޲{&ӻ^ T\\>(PGyrی#9UqssADУ-SffY KOdpw NgpA"2%P.m˧L1 Xˈ1j4#Gf1)c>Kƍo;{oA`_ޑ)5h"qL\*-L652wHDiUwU5X/K<} Fݸ|!+E @ùhㄉy Z׽ġ[IHh<{w=CrTJ}žOb{uw3H7qV+ZLX+.uȋ&S zs++N! %΋ e= c`*Cm2f2c*ndplgʉtDm|q&'s [&Γo CEz9ie?̚ ce :/3|:h3;#AD)$Ge;rZ\4Dۏ;"N?9?L"%>G]܁/ϲ}M/Lv(?ju"}Qv91U {v"lB2SlfSXֲ[V>dAo;;1Ic zഎ49ԗGb`ciEҏ}onG*=/gc'ìf4 m 8~;3vC\тkGӬ]J@DKC}䅣I_G}mWǭ%vƝm\ tWst~KDBG,,xշ\t~ !ey7Ʈ=cQ$7{/Fo L>:{OfKrɩSvEhQX5a\6R9 7|OsSy-3r}Jl DB<:[ZSK);u yDGJ}ūiyBi.pqzzrMUNߨG#G|0ViCw$hˉbJ q73C.v^\UxBDR=93#5|܈.M8[]+p-͔戟Xݑ́o=ԣ%[rѯ4^*(0,;_if,8FZ}f%#r ϼ; {/r-/LȔ mjV* 1#̢0&w>Xc&qq1Q_3M{T7ͷJ˅qQzu;a`V2ɽ{-h1uZ9q=Rϸr4n_Nޅ#<s0Zh =МFz`o@aRѮ5=Z7ch&ب 3㮳uB{gZR".KYɘ!xV+JiSxGV2@"(; ɛHW>>l1RbۨTۅz QUƭ[KQYѕ韵z 5|7!2^#Y:jհ̍MjhQ @P H``QjLrQ]c0CfODݸ2& 5bH'@v )ʮcLi5ڎMN(4Le*φ, uؽg_q XMy'c ?:>)gtMvb ^88O* ˈq7Bpm>|1?zޥ_9z }e>>jO๜8ypՇiO7 MQa(B҃C0(*@/1ע{qWg`'‚w^}OK_[>6*]9 "X߯\-%:~{d#;zm 8 Դ` 4mO@`\ӯ75o?,I=DC>[*Yc%g/n { ^ RGb)i`YoO?ŧbKp_ٟI,v,} u"(t4Ryk~?˜.X/0r^S"}'C:+*)jo ]8}*'EvpgHETE@` &'f*B3siCQi0Э[犋q@JI D_o<cǎMw1lQ,8#W=  q3'; R| -xqq IWއ~½zSYmcP[I]abcV_Tv3_ 9薝=tɆ)%okW/ nJE p @gz k@ԀeBpxϰذh.#s21|`,wغ-,z4F8|VmZ/3~ո?w:Y b8U9hZq,`r:Ś"CGqcq1`p.+,Wv|xL!m8'^.=LH{QeUwW-ǝkPK_*V IDAT~oۇ gKC9 SsnG_>SCBb]p#N-܁cr[nYI.⚥Q`'J'9G~N N=  hXyt` ` {GF:dsfr99x=}%Hu11wq$uu|VӁ"RنAٙA(*:{Fv8[>ă/J嘩^C>[sc%]u iݻ!+\0KD"pcVii^nӢ~0A G[zOl3AF. /EW-\cSҐY>`:u,>w|_פ6%=ipyQo*w,ftAGxX{x!8zXr'7zEamަ_ЫSV*w<|DO>xN+SGtn؉鄾}cJ?;jAN:8i}зTpϢtqXm(L5V%o Eq.`}-yƏ(Ipi/,Ea[ 8ʗQq UMuzg`Պ-.'ᰜ%9`cRk~EAc@vv@蔓ULUп/de ׸)GUX0pAȪ C&A̡o:K; at鑊+&7ZʱmVmnʍЧen8Itl>] K?vjGcMi؝ 2ON|Mñ}Jm7 _er"|{$?oK|8eZ1w,Te8t# fa:GEQJ٫p,t'N.M뱘/~~?*0+#1W`fu;)̿l$2ܯt ρ9sr97> Auz?<t-bea2,P9\@P1 l)W9ss`yk|DD?Zs{L0և><σowu7p\xW_Bn9Yu9j KSI+PS=0W?A a?_?uJvsG/1 [r?a2^D:~ݎ? fO`ǂ? W~N'l@\,W9saġ id8筙{D7-!@Ґ+:%/l(L9r.ܷ FۤG[pٝGL3u($5쏍:vS0sQt O?gm;漀 یݎ<z`"'! x塇C=EJ,Z]ii?z͋0#Qgos7>wVz'rH?Lj:%nK|wx~UPNaª?c9)8l2[/^Fgk7|>8xpS6Y;cŝ?@]oY_EAB22q'ج}_xY^gNGy_lo?S0,hX|>z=+܈:˞t\?j:ftY],~n ǭܥϖΙρDDrCoďIb:.`&<'Dj0[iEo{31>Ap___d`gW!* (A\>/"<*,|>wna]N^'Jlŧ AqH6û>^ z x2W.:N> 틱ÓC#btVyU~Oxk,'qx}ΉѐrF߀7?uf\N9]<$?N7v༗zn1Y9U? 49 sEm&Q͘044Ga)v\̶O18nHK@/GA % s>mB69u<2i`x ¤[cЪN e矄O+g`Hm)I_+LqcAh ƌߣt?6U0??gMW> ̬0T)Q"LUXmN 7Fv-vPsF±oᩍc!et>-6 6ha'(LuT IH{2r.}ˋkQi0"7{6idR% Z2 GIE0L܀e^c'8wn=8 '2 wLwWx^ea֒Uxj 'Gz$6?]QI錃X?ã"T9sI|== fj(=|fV1j8ޥ*^SSp;1qhi{A$}oLǴ^/KQiYQhM.}qΔ΁DDD4\|π5'Ԛ Mv" W+uLqUr\t@|]N:Fti:2rd~wlk,ίbpy҈Z'lv1sӘػZIŖ7.I] Μ w+ #bOخ>V &lpu|-?Jt?O_(L#E"nsxCρDD?&?=xc Š@^"ЎwZozug=bDm3 $Okc!7*Yz2<)/7Ѡo&f" ߮dyJPAiEDM=|&~upf `+g'-1k&f~I!oƤb /]쏍mz= olc6ۨNm9.Zd "@D JA s;#&],XRE.]vy9"""""[^^:v3TaaQ׉б˼h}T#HDDDDDyױa &b 5z./0tȐ]^nvy%"4Bkݨ刈neDQcTBj9;SLx YSrDDDDD:ne<Ї|tc8y/jg:l0aKg3o;W$m9"""""j$^_SUS?ºu0cu,ag6+F>\Í((,({տ  5/GDDDDD'sͫ)Ō7;fհHKm?D^\y<߫=Rm9"""""=>dʫ0UPM &,U/א#""""k긪=+Mgi_ &$=n7((J5I)rPUS4HOOǬnIU`qNMXz-Xvm)N~IDDDD,)zkƾ%A08󚫮O>Y}](Q~CLU }Fέ_㡺Lky&NXÈ刈h)^^SUSsϩO㡺L5tvLޕi]ccZ)DM}H7qv҈刈nQӘ>dL4={E-mZ DM}ȥ-t<0b"""""""j """"""/DDDDDDDj|0aq|0ADDDDDDD """"""!0 """"""V`j&LQiD;wQA0ADDDDDDD """""ǖ%Xf{k7]7[)͂ǖS0PDv6% f>/݄sGto&5Lp """""c? N;LL<8tMI4K j C#1 """""1=m} 08{p#W9i%yXp{$ 64y jcWQ[dmSo=;{g">/B J(Z>tDC?x9Mt t2cO8zy/6KSGaB j#&:n&DDDDDDd:ډX8CXw,f":q,3KOx %KuKS X_XOiocOB}_:lQ[hUs,HSblZduew)1(Y -X%3>RKqct=u9&ݜ7G.jKIv`)([z&AϞ_^+nEI"=kD$[+@p1Qd|7gN+>3 -#)H{t1Q_/VWmy """"""jQe_6JK/̏qߴ0l6r<G ZEr kpCF˗}0?` p}XԌ 8/ 27}x a (AY}i4 { Kx 0qW@;(h54G)G)i/5e&29`@x\2g<.Sjd83M$V pω>DLJ)I3mDDDDDDԑX=9X &E'4a/W|ߤlIMw яXi҄/]٠Wiu( #&::ۋ}{q~k7]p]5طgzk7Y0 """""Wop騽:j&qc|wnLhDǭ!"""""q:nNo4 s̩߬zm>7$5䑽Z A#G.hf`BJ5HH2O[3oV|Ι~HS`;DDDDDDDrF߁ѧn;rX= ;!""""""jIoT)@1ZRm,hbm;*Q˩|r4 ACDDDDDDԜRs)G{O`_5|J)H1K98%Q7v+G{c͏XiK@DDDDDD嶃>unXŀk"aJ>XhW,,(+/m$""""""rJ}XX&k/@X\I?b!C*nc@s!JbJ]e!ʺbDSb c <k=bly^m'яɗ[by^ A zxˆ)X#"ʺ,D"+@c5ψ1ʼnrCLJ8Ljx&bZ`_;V%D騅 T1%[y[""""""ִ6ok|f~H@[(uJ(_| QnI}Je}{4S=CL~=r ;BVJ;(Ih- 'l 8 H|X/ O.k8P﹃R7E:D<bkLUI4yzkWMm0(ؐ5ZMX %BVv=${(wM{W9xDreGLbZ $G⢵WIm㋵a8W u@Y"BDDDDDDڒsJXQPq$$!"юbNW6V`b"6(q!VvĬt4w/h9Mus=J*/= A'`\D9"J_ĄU6d% u}WjDuBkO"6\B+^7QeĈo}Q:{վ`muFX_Y]+(kt鈉E&db# +sGyPNF7#n 9$ZZVBVoOrh-6bDWY'2!>ZYc=/ZhU#a:bJۛ6XcX$P }Q8~xUQV| c:HTrdfZۭ$_V*eO~$C@0(g"ҽrB-ʁV u\X x6Ўr(8Xa`\Wc}`,INd(ax:~ڄ1"bĘXOp-D ĤTQT1~(4e!i]y"%ZCi1"P Gr\*a4%Fj-DDDDDDD?z#b+S/#%u|6]WF|X1+*RxZ֦EleAT/ &*3Q[9G$f$/f%)H(W֦/ u\hqĈJkXc<և1ADDDDDDT/k`uXS:U d(ڊ~B/bCAzVcF QOG#pDr cH[Uc*"VX@ (X[rE*G*YRʅDDDDDDD0kb_Y}Q Q1#)x"6Q"bh ox4uD-wJN@(Wv}TBk*%rE)eZFo=8V5IDATs~,uŇM T'kBsJX1N #*DhXEZkm+hзcF%-%nP9y&WCC &BG*-ԅ#VZ;1_@Di(wu@i@9q(}iB[_)Pn,QP]ú:` 9D"EHi(vŊ&76-`F <dGK,4U;:(LM B>v5bQ @ 2qbqJ렣qgSv_a;x.:hЅcܾQCCAA uP( BP(HtU?@`0r{&N0aD쬭ZV Hrt:ogg =J3\N$I rf#BWW\QmV-=++++-(}^N2u}TWW7aekz u+ ;v]67dP_srLx z{Yz5wC7ܼdMo__~^^} hkiJS( %EDV{v`C<_aEe@E\2nܼ7xM1c4ҧO==z'"vp@uDB9z*ޮjFI,'($e ht\`-otQ?P9 >r5'@aP yS( LyOK o'"̾p;kŋjk/_#?kiic;nHOBP(pq_}|O>6 zOWGP#.\s*>|PطgOSs+׿[^{)M~,I}Ihj+3n媳kOdi<]a^2a|j\+5\hZVkHV&q {SdX8e.wԶCi'| ~++ ,:ò6kG8 Џ ʰ졃ltSBPtƎ+9ydxX{{?A>'L{!$ptuuw,JC`gʴXkO;r;!"D|) rڈU}5_ζ.5*#H' )ړ'Uj5f\5~}6nJTAɇb7 EGMQPDy(G~B ;sh [UQxY>Yc\8\bW]#a&##8O3 rҌ732YZ8BPt$I\|޻wo__nhhXh^7۷gL2ErGGǾ}G__ݻBE`6{z= ̬%IұcDŽ=kD P(iAVeqgGJeG߯Ȍ3NgSC m-]攩;/Z jHYi)/%a-3|)͠ ==G?'c,.`jOi|,yy<-_h2s<{Buj^]b49r:;ф1v:iFt:zOA B212HZl8@y[d?q=IŞתM|Z]vS Ѹu?_=y/.*4]] 0l{u+Wsg=5?s5.7EIB?.w橍Фew~'.m4[ŗ}u?yxh-=MKf^voӶ*g?|۷=v̇;/*+_[]}".|x%|_i5gm/ܳiiKxv_Ohbה.[Ook'./oϏ.h|=['%F7LXtŷom|y=ǙqEkwشh)85qp۲KΞgYޘ^0uPIWȝW/];AԷ8xӦ~ж/6a)?x7]}6~;Oڲ7}|yShw>ߦK,^j6KiEO\O BP(Qbh]:o̕]GSc(eN%'CL7Eke8E힂 :4"vhm 9xbb F*S_︿r/t>vߏk䊶/q~\H3oM2ä%jǯ  4}ZWϊX;?_bC']"c,Y6^b/Y*w5 +v B=uOEg1]memzr#Ϻ+xy>8r=oAtWnRacw/q{x4 ؾW{Džyϟ8Yg>;/&*ݡ"iWەu{q`k}?㿹џR)$VnU~Q9!9ĠeƉ7췏Jףn3Ly{_yeM[WLoO|롊O^]oGKos^;geӍ%Q^;~У?{;]=} 7?;-߽ÿqilGݧH'BP(ʩCV(92UMN~ *N)~xZ<_y *:YV+$0PjDPm!Ge,Q]f5V_|>KfCLZQ}pl%|Yzcބ םSbb5[5U._w?n;.b-?}o_ .}z@ȦO[Z|`W_rV_x-G b&}c}K. ozĞ/cޭWPd7~g:7ܴjE9W}뒪W u5kZXx齩}}83Xs6]|v!^{h\^^rΞi蒲<gXxx\<8۔s~q+Z#.k{YDE]8=ǟ.p ]8֘0S6emmBd9 ^{v @v峲笻awNma jEpSM;'o`kWMc16s:#o=ɳfչmP( B=e1aak݊WHtA658_Upժ|jc|_LU&g!AYA-Q>ȍSnoASlѾk]4x;tA mg/漼5yΤw ųe 9c'p)]cl~RXeeQwbZ2'psʍoo63ҷZYK7`̂/L@K7$}]uaͅyNþ<0e.N]ZFƀm]=þFDGDC#`ɰި^' U+/g6?ǁ>`h>?<`M9}k{:!ě,i ~")<|8ۤen[{E} IDATGݔZS1 tu'0(X:= `-5g0[߯=|(tu.[T(Ol_PD~zR( B" |[A1Qھ1âdVwQdEQnjf(}qE: f:1,̤_?hZmF9`]=]bVHHl\|7w'i\FbMߛ-Iͻ;1iY9Q Xu[ Y%O/,00@=8}ٷE"jk+錸 mh 9 \׳XK/=pO0nyc7Ԥ/#Hn翷T-Sba /h~a XpulpaƐeh|F=Uay/ه__^;T00:f1L[Qi3IP( r.@aB(wŸx.½D,h-Ӓ8>&%> ? œ&GHH\P'ofS7W:«M$BW`Տ 2Nۛpop/4+=17\:tm`55{.*j`.qV]iˀQ ?$QT*-5 9\8 BP( BD{ȣ2-(xUk›7!v%~Zs(ODyBP( BPR Yj D{ Uv,_NW !5) BPN3taB@{}uK~qũeo4AOɬɏW]P}QYѥ BP(WGbT x/FGV?<':5TM!tk{;G Bc BP(P(Q_MR Ub3ؕ?bg_6xB{T"J4MdetK "gQz BP(B1Lج& hpPl(yQiISv)ou%4@i^!(e&dxkjflii ;~d2BPHa CXd])[:;'D{peLK*d<ű`0x_xky=/c˅1oA˭E6#C29:( KMCTS(_AD eMV  `[T\W_փСT I~~2GK)(|yHSn|B{GIjox`O:/hkk>mrFaO bA x<(fde#zEgge1(x7IHx񞾾1;wX sro7xcܸqFqO:U^o1c222FhDrٙ9u gfuXDQZ WM5!+B}NxLsfņD߷ ]o <# &zeG *}*+N׌3B(4jFYbiӲ2z*zM8tcǎ=YSSTX.+K>δLtC99Pal~}f&!D9fү %F("$s C2~~'ۮ4`ܴ|ȝI#ɒ}Gi_ّoϛ@2ˣ$ʜs@ĬN?ޱ8px7?9aGcK.-e0,,wE,x7u䜜a<τV &mMME6-%.0X bS뢶@A^qy^n];{{ٳ[[[G"V ~?{}^{We`zz%>zgK9j iKgX,SXzYյʱe__`UcccNNkcF%ti.-`7 ϝ|> V+BEtgOP(SDW1 +`@ٝH%]]D~i^D#qSxBLT8f4R#kE3-~)\$^'Z4. `@a /?y4oE&.+3fIֶ1ct0ͥ999M *b)c[Z^x TէZ9tz;!$"u"X[GnNt Hט[XΠP(i!^ VP(C G`4X,KD+؂HdUbϓ. 0HWZS?[3y,N'I]K IXX;\zn.:,fdLOOGam$I6Inwr.^C`kkKoooYYzDZ1,|>\SC !([ 7JD8BAǏӟD8$3h،'vuu'[ffEQM!}zzem:nt\ }`䯩z{yӱ H7Ki BP|h 7*P(3X@l}9b N8 JxI$%#/ڧ0*>G'!<(S/`r @zS4ffp p!c¼)?z$8 !v˛4b5J =gg_a;D^B6u2ۼ}}F^N$+l0-?KA#R(ʗ - (p^?T3/&U^b@")OjO_c/7gVtW3 SNnX]REXs9jL^z$IM?R fp` @"v d1nԆ'?s40l?ڏrˊ%@"흮es] w9 o{WN<)777E Xl.?YNC C !Ѕf3BbH`LX]p,'Aow^ϧg"{e8X6 &B!u&!p3>*b#BM!FM, vS]1tpH2dA0`!|cl1!rNwȑʣUnGy qc1ߧU+mçbnlmXfP(ʁp P(_)B WG`5Z]!BQIM">TKD\GIUqH&PuzQyz?m{4.L@,=r H @߰.&ʖ ,AwK'͜ uUy) Dzc^ ||ewgΘfĒ(b6[{G)=U(_2i$eCy% #tx_q`(.xI0K~"u^^ϲl)~@C?B}sյrɼ|Qhf&QXP2PweD)CoXDIJt:J\0e9fୟ"靝]nv746X\W[v%IʴZvZA5;z^LƘ`,JR0 häOOsI-^|q׮s^d6CFF4@P(_N v5HP0!㘔x&yVW9$I* GO^,f CHs3 vbQn no B( $IP #|}b.ݎJ]sQn_yTɥ.wBP()!nPAMB**^5|k4x'v W2_s<B&P QABױ]Ry>Q;gP\&| 2yǎ(/_r:(9z/@ @NvvQQQ% Au9a,1-a٬y8_4ƌĐ`RKaӊf7wCxc"1{?|ĉS&OZuOpa7 ,a,,#q%?H"HA~&&o%W2cI5(~h5jP(,b_ `b Ϟ2@TyeYe IDATx[CP6P`>$[v>X?H0GoE7ϚW BҢ))"p'NPN)dx(޻=F[8j3"H!}@R(' 60!uC}Š*/ &,dsTs"u_2Qԃ fd75f[< {.N/6bDv3XN\Sss;::ZZ[Š 32/Zd߲۟Οq2KnwnQx.`(7tE<&+!(9-YH:K]Ϟf KqW ] Ho= 4IR$&O`>h-l:# k}pG G_]1(CCYcb96t`Ibaa10Wƛo<8C :!18ZUf.I=P(/ re: G)ʙHNfkJؖn핊ɈƠ NQ<-#K&`cB+i3zaS^2oָ"6б]Fcx@ H9l &?^ZZ6e::ƍolҥmmb08r&M~!,$QK,B0AV}[&b,^!t,76Mj+J `WS7!-y8Hf(YXc'V.,㫻/X˲0!O0,'Ibx,aP($ko.]8חr 2[xvVUN}Һ4@P(_6b@P 1/@ú=FX vsAx=B:4ҵԕ`)ڊ撔DĈ>Y^=P EsF28>rڛnc7}d5lv.78кs攛:IJ#ooFe>z>;[z{{A`Y&seUUcs:eǟ~z%6Dw.;aszLɅyގ<@ ?yzJ3_#^' BҁfNm,ʁX@\'Dz8lILFcҳxxgŒ|ҋZX <DZb?&` z 4 H.|C'=v{@()o,xueWT=#pdX'h8BP4D6 FBd1 PP 0 2P# hK@4*!)WpէR|]S1Ed#@D[$ s϶`֦cxM <G,ǰAl'wt{U ,H38xN;W._b(a.xH<2L[̤LF.ʛsy$Id0!BB04Mu:dP@(/歋1Z^S`h#@[?j *#Oc] V~ 7̻22]g@p4m~Rd+i8BPN ʕ" `B6 !Q뺇W)DvZw:"$&aIG'5d&XxBh@p"{d@ |Wo alV9KnA)S ! A C0㵃΅YW.(Y),B˲&aBaBQP tBAx<^N8a1ȷ(XRp{~~Nw/شq(0p%% tcnY֜*/BPFؤơ L0$2 z B(ju#nX'\W^vN>.i^5CB:N> K$@M"FA/\4@S?2ssOOOT{:>?i:.77sg>}rk,cnFD0 zAmqsL %^J&N`w4c挔rPx4#!$i7s`2FWU!4՚.qEAq}}iS&+; 55Y0_DPK֌pE7ܰpӵQ:mǞ{?0_xƌQxP( E D&= &J @ph}jCYf̳S^  d H[_G -1DR!ehKd7OŋfT.bL EFR p&85X,ӧM G:Es!1EOмֆzG z-i#.;-//d6p=6OD?:< {{7 AKA+iᣴSܽ)hqwIH\vw.%Ā gp77;μP׮[ϻBwWg Tؕ)2>5ݶw!(ЬfDQL_+廾@o^}޲c̏0Y:SS^t< YrLf(kRA`+#~BQ1;"Șgu 0.PQk32T*Zh4 X#LJa,-'`@kj"/|bbbXd&Vilg+#ɩfʉNBhyWzHDt)SV%(C!I+n>8Ҭ*9JCB!Pq,tW;VdHD^ *)))%%%<"b5jSOkBN&8N_cD ~(uƦD!Bők8Aj9asFi- h4ZZJY%R0 ;C}J@ae"jŹ1&;8%P` @!*I4׆wf"At ʕBuDaܘ/߬lK (̔ffJFdJ9wD9}Й A%YCTd0XB!TBɤ AEQt\n}|bE -oZ5 !vzVy5qUkԸ{놫D"y>d!!!=2ӦMJsdryqzRiN޲JMM}IZZ!DT:;;W\.^ZB¿pMӂU^ʪO>MOO_᭍m5Jb=PsW.]vvvnԤ\./΁DL @!BWΧ4'@V@YHEAEQjZNȰ]̭^`TR_:DžGZTuWU/xZw3T2vTQ盀2M @)-,,,z='#5Kf2^++wCT3>z`o5kPTt=ktW^*צ}GL\P[\auMy^oz9/9o E|@%,ρ.#=̬s߻|bf͊s+ehjRf\xLiVN]G>kզ[9HOMyo"B}jGb Y# R "@DAt:NS5uVt.qͺOS899uIvщTfO5>wbBHrr_ZJ IZWYYZbO JԪ췢(?[vSQQQjSgJXeժϟ?ު#!ӵk׶?yd54Eڵ-,, HKKxeViL]ٲq1ѷoߎ\ޡCCajԨP(233ϟ;~~~^^^֮1HOOAjj*˲VVVՋwx[&&9|8@TTTPPPff\.X"OHHEܼzoczj۾ZYv':(@'V#ɳBZR|L 3^^tNz-V^+z'OEf͚O< 3^Wvv BHKKoo?i4>sWWq`!*[Ø)33DQĺO ir|+߿?%%Ő2..N*VHO=_7olѢ0E.ll(urrV ]u?~X%uA |*Hj׭QVKsΝF?#&}5 b^&'CVo{٧0jԬefnߣw JNJow&͚W̌) 山`Oܫ:^WgbcBBCzzz=u˓;wz} X޺uFV&}֭&͚]ruKbaiٷ{w'%$fd/aԢY  `1.!Bm:'z "m[Wՙ[>Mb8u^(^n:u2pPnx< 67YHHH&lml֨Y+:::-tZMoXChUY7 RSj֬D,ڦ~ׯ_S(eʔqrrrsscY6&*Q!+q) ˴hj zғ ;)V윒0ZQg oZu/_>-9Hʗ/":#]&)2yAmQ(@w޽5kU^-6ء]LhqW\]333;5-52{n.]<=9:;zX kedemSr۷oVR$&&:EºB5b֪UsȐaҴZcV:ϛvkݷ_hpY,>nD/pZZg4QEQ9w/_J DGG׫߀220vFjr^sAz  ɋ/6mєG%$$m^_xOGGG777yQʔMIJ45WV̩SaVG%D%%]YϲU$&uEL3T`V}J$CձKO]ܺun^ٳw3Pg*UX) B}mUTnH-[RS)bb--->'YpdCT0SH9> }H}߳-_-xG!0;7ha:ځB{hi"@0~rXS7^@ݿGȔy33+WRU-9)z}Zjk-H4$ 'D"4F#--U6Ԕ8CaeY{lqrJ*:?!!ʊe%!>.&W LUNR[/.TtKHLt3PԁLRx4txp7$$i[Xse !OZ*,䥽Swn]bMB؁!By^U#P|d[͔(̔nݖ+䶶6 S^/^T/^DEE狔ROOϨȤ<ǫT{[ؔ)S yftttZZZrrkqquKK8Vk `[.((POsT*^Mo!<~yԔdG'HJN4w%BBBB233SRR""" 00˗/>z"u66zmZl#R]$'%^ؘ7İ+jIjTaz>:*2!>_ͷ8nXB!!ӻ';5ez$%&޹u[0c D^QJ 7n$%%-aiiYjG6.ݺǟ?ի)Na< [4mٳgϟ'tFY9>{ŋ7n`XW~~54j_u9hѲejJ3g.^XNrAƷn? w,2,{޽{u/.\d¼C.QΝu0 (-LU]a#FJe2QRj֪լEKLFDQʈ. DtY&+.o/B!'O췆M_A!""zZmjjjZZzbR"@ y^ v{Jn؄P`Y Ɔè"^d6E/#=-#=8نe"3U:]XW^x>6eu:6EH'9&%|Q9B^F.P`+|gRB|vUzgJ@dR avXWݽw}EgB, ޖi]@=?C*B_QEADQhzٳR4>>!88xʕёfCQի[gͺlYHbJ)/jZ qBP*Rn;P:y$q;vb(/C9~x"FCuȁDqne8HJat躀!+> ~AokM;J(( ( VӧϤR.!!!88U \R=eYUÂtEaz-Ŭ (%-` B(R?+D@)`F1}*eLމBe Uh]n(zBmO' DLE!B!>2&v!P3yClwo. ,r `/BPPY.V=43cF6!k;oިo_$#]E|jjjPSUq҅-!Ч,u x؁U%?20vi?"B.@bާd=KRٔR 3+x&&Q\[M!olg4=_"@"OY)Q -SꨨfSa @!.}}"`xs+\NLPJŔ~ٵQ%WJmF.iH)Tdy>Ȗnfyےa <\{;iHFŌ?~ЭGK_m]B}،T1#ֳ&];󰒱ۿE]R}c~#t|ԁ& j(@P[=k}# Q*$\X:GWٻW㶆3 |l ZOs>UM\s.\c.h~0 0ݿ[;4#+9<`/{qu~bR'?8tTnێ^v<(PjZ=n#WQG;kkY{wƱz>كyT6RO.hӤMa(RJEMM4pu|+|ֳ/b fU%P@!F{Z_矉}!kӬ_VV`D/_!ug|{e_7* m:xC 4W<8zGDD\-qgR G/tz9w Z)o=-tfMN|o mBL˘w#9+T7ܲh]~hI"}!~=KJ̫_zRd4 : )זU:`HU}qg)W$3Q7_ ӽB}hL{0y G@ ]JѢڀz.?iCOsB( oj *lگעT//#"a{}ǚv꟪hUNRhбs6_wRZvjk1m8]8B@Os9>O݉մ_`xBO^A,!DeZQ56|KÏGU# PQv=/ 4Q;ʜe>w~jf&i:m$A?R ߓ)ێj7pPO)x?FiAX3B#[bU͚(gdnGLoh&iIDv5kn%*F=k"i;Uw;m+OSM*!rmuߑ݇y,dw $(51&D4 HAE* e(RJަl!Pġ;m|b<;w37CT ci'鍧FN.734E`$ z@{uhgF a#9B+³Qﱍz]$"ooi G8:ϓ+7r 핆t$3:&kS.5|gF+ռP| ycXthFe+5S*8Q%VrC*2ҥ"WvTڷCȍ$0 D*h|.Hӻw9w'Jش&1AjaX8YJq >% :B!1 %P d];o\gcna1-Ǥͩ470v%UWvL> F!>|=`tA|MGV&u1FMM5 @ń8XIRbg`(%R*s43G6Z%ٞ??P+-,,9x%91q)5I&u;lsHuW @'.( @3l,h-뺐RJAa ƽks dDe@eJ)tvuzDE g(h4A0M3 !z ʼn9q'V3kͩ$@)ѧl\\8BcdJ iש#[έ'*Brq 'pcHD]j]rv|/ߍQJ;K:o2iG6:֭)ݻrиLɩַ5%%&%(XWjz6LssÎK"!|FlHXHqjO!ҼW 4k"Y MS RAusU0.;j\]:zV$J ]vo'$IhA. {#B% )%ʼnHM22&V 5Α{pЈ3f/\ǺO&s8 ftPjK 'p }2ֶY}U-l̶6dI&|5okOeykI+9jLMK(rl9-*z.HXT _ѫBל ӐT`SvkεCWhC@QW>WT+{@AkJ;xo塗f~JRnswuk2tq0@79C GȮE(nI#@oڑ>-nO ߢ<_zEB!><~^.'^qI쀬( "DaA !oVħVGopk|"BB. diBOUTD.z[y. j`| @ b J(!H<:.--==#=..Kn |j[8E-VQcƖjB!>0 (@AhZJ~ !lj1i] `TqB! >CoɴT-0yOii/0kM90TҗwՊ\B!,wvf/3cFǘ`5|R;Ww|yW=MPufoۢE;o&[;䱬7NMz9Fk Ti8DGGv!2a$ !BxhJp䇓6}^V5!%.דܑԼ֗E$x|f5慽 }}1fRIJy iQT)@^YGyIv|QΧŇP0V5ؾ_ߺƜ է^e̮mQdC*򔕲o{C@>[.lPZ"##SRRRSSӲE)B}TX"Je2\.fffJֶL2nnnoC$#~]r`@L{]UrufߞRJ5O?lmƞ)i-õǼÁdT 긺y4hLqv$~㛆c75uTL>ш- hViIwSõƠɾӞaD{W5.T{}a-|<\t\Pc6>A$qH8 I$bm3yfh-B…|tۑ{u9nk 7ͣzɿ&RJr'j$&?Ӭg˙ٺ6hVݖjt)DG}۶jݶU붭Z6qu;BO8iVFnv%VG^ɾHO=?`g RJea6~K@Oo;rFo щN2GW7G/+FO)|#KGuQeǃ2OU'4}u|R>Y[Oܻ{3)ӟ]էIf5V:_W5-\qKL\{vA/\=hL"~{ }9!;|w,c\?ZH ?bkņcLrul?^Ƕ,h/_W=x]{2m=-b#X.5nþ ޠ{~v7tq;Bv|Ʋ.ζٴgU/;ɂIvlEyJj4F\>nvW(Ldvgݰ/6wHʕ-\fRrbȯnu`E Wx[BHz|RTӳ; zZ㚉JߧR5'ذ$s@z`^z;Hq?T7ܚxp*g)/[Kn^h.N!1LR-!;k- W )Wz}h^ZDQ:f IVjתA!U*7֭,UVJ4gs=]lbߓ+Ĝ(.B}~oz<%٧,(z0 %ES+\~ӆyQ%@$Tٴ_u3E^^FDz5#s ?UѪѠcEm("UYv5YO]׬BDMl'Ny샴j}|=i`wJz }׬lqzIY!D^޿;0Fj&M6N4yu !P`Al(yqkstzG;BAmo&Q`˻ϏlW5kN_}0ѿHU>o'ylv\h()x;;9űvRQZ}wڰW^[SJ(Pu)@ z_yP}&p":*q2pΝ~'q,f{@_ܦ>?|话.d!zmoT|6\n>1'7u}H;Io\2K{{3- #QȀ׋bFؓC G?4ެ]CZ~;Ra=Sml$N!uq1p/#3^`rV.iwUtLԿצ xgF+<>;w4ͭnK): fyRw+v&wX8YJ[Aə /0XPqƅ:cÆ |QVhnndYe5YFFkl`_<2 `UHDu,D]Ķz̥"OXC"B0ڍP ̳˔{7X0<Ѕ왶嘭[fxs>tK1)\`ˍf%N)ҽwU7gY0.lGF"^ 2 hӄ2@)$k,%D0id)1OvX3G6Z% 0`ȶt7g,2"M|JK3GPJTZ'l4[n"g G˺.4<3>/g]Qn~y!T0IO3͘qy{ U:X}S\[vؚkPB(t@ dЬGLpxJMl][}xܭ ȘKlgP;q/3ZqPR[e!؁Erx}ɯ̽>.dE@=W?Ыcw2Rޭ cnT-ugkFMiXMvq6AO|в 0o? IDAT:O|=Q7jڴing0B=0v˹Х@Zs* (PJi*W{3p;@Rkujsk;{ED{i\> N+^|$PJuQ'~m3#b ?M婘|z~mJYj}'^sYP"hR"=Ry-ɸ EN}]N)rиLB)PJMVPphx%s>ơ}2)C/ڤ~_˂5I=lʡjK`k ݃ I)%|fRq:Z~rsÎK"!|FlHXHqjO!Ҽ5H,^& άe.~}=V+][Nb (φ rUVUV/ $'B1N#ĪIVHT*3DPVBY H8J GY p`ɄSz.]]#nŮ/{{~q}?|w>};&M9@2Uwl ۸_[\xqP*u4D"ffS cUo֦m|ŋͮc B"+57?Zq;`nFL1{:ֵJ\`&s8 ftPjKC#QαivG5i£r} ^-oJ1=NOٸs4[PƢȵUK@^ulmi`-z}noo߶ Zrsm9Oj[):kΒt(--G53{3w IMf[X~޻_fwsqs2K)a0.XVxbOOϹs"A!8)a%a !@LNJX pƦUQe:gGg.ic #"T/sǬqLdo"t4pJ>qf@z~ki2GUB}JN8v?RDM]kTђye؁Wx<ApRnC%  eKCe(@),duEbWTS E>(!HDUt1Jϖ#hSJ9sk0-D?B?.2BԾM.d}%Bu[EGDthքORypk0rW lܠ&.=Jʀzc`eΆ~. B Foّ>-56dNQ^f@E1+1t  a$% K߂2@P`¹v`d0afc{Ȧicf#Z)pTrlc͞ÿUu%КcWldT]ߩ߲)sfwd[lMV HNեݓ}}V>!z<_t" Fx^tvOm} [~,-gΜe48 D 'pR²"#1t C(` eXtWx$숺;>=}@!cN@.!JX&o;ݪ\m#&;v (5(0R9rRq eYaa0@P*RV$@P|ҎB̶P,oδ^ O]K5fgBr JO,'N ,+,e(Fx bՁ( ,f!>`۶m{Eh7mp}۟(A!Q|BRPXP*t: 0 PCO0)|E.-fˋ6%^rB: TY`պQ uBO \ B!TR=l61d%#I_˃}/>\}G@"Ig'Th77zA҆9Bرc?zߡڨK۾ h0 |Wct0{|AvjR[rgg&?gaKzg]{1 xLcf|[/a<ڌ[}>JG-ɾKw%W/%B%3 Øu\ 7w0 S7WƽK8Bf>2W 0G O ^706uzM|- h0 ø6 ~+AD6/:W5u~Xi".n7m%a}@vj>xi%#ww{|@[t:UU{aӷ<P]z1 x5p$ $\Z904s} 䝰]B!G",,lƌ6lpp(!E_$}Guw6\M37I 8Q֞K(4[k=vJ~V,XZ0rĔ;fG:Ԓg\qc^=Kȸsn@}j߷TwΨe(}`aKf)14|kUGENBwz:vխMDx~hxm&@}bP-[F%aS]u̫eKX+#}n뎻ɳ7`nccex^$i7WϾ3d?i@>B!P(jz̙=.#Gr2ܽ1cXfSf˳>[\U39.oR'`~)뷭˦}?Qg7g>>wZ;U؝u9tM3ܣ蟏[Y߳thF'f2 ;!w[pҫ<@%of6XԭnQVk pc@ҟڽu_}nْ#57gTi@͇I9Cm[[~RrYwB7ṇPs)($X9.˖?Lzܼ׿iMu@޺'ƪ' on;Nn`x~veU+ ?mO7m1j3Wͪ`R/FhH*Uud `\ܱ,7B?쥰nY,[%,?a"B(:1 #H#B!T"x_v  MEuiQn-5^c0R/g g!=]4>Ґh立|fQ5—ۀd<03@8{3i**P}>y_+C ʒ$<|w8.bH/?bHײ 0rSҵ"!'#)!ddPkugocq]^Lԛ|,¾Mw8]@Rw[c9y')kI.Ù 1[sgy{_7&f  G}&568%[*L<}x9"~q$ͳt3[N av<^R*MfQvS"DAp1yӈ~KoE4@je͡NNn=TwYѻ'5e_gZ/JdRQVQC!UT hZ]MBȣ^JuCQE}Hߝ;ŕ/Wۭ7%BLLW*L& ̌OcCvi+n B7_.Yː, jwR=<ϠC"Iԙ׭6i[3ϞR^ĠZoE;u}juJ0x 8=NF}n]? =Qq{53yn+_8[[bYHy{Aܮjbkyڴa*47iձnZ| ft){DhyM!FALF%OO-F&$)4(Wl +YemjvóGMP6fu@,Ō6h%-ZϚ{f][K۷RNm?dWm5/#?Z0{bMK>=\^8t  8Sҷ5p0{4/ O4q͌/qmkMJjIW3AgBMs'(q}TRIb8fse|7h,@v(˲eWo {Lv<[}+E~s4{Ӵћ,hҩ{"# /-hGT{^NFkqUCc 9F :i@f܇d/9%Μ06PUcGg{ ^T^[4|ն:<σT$==Lu&H$ T*ӤBZֹPrጨEQ$($g5e8HQE(!۷//o߾,j4gϞ=ݻsf<@L燩q XwwX-wMASbŪ/by?/j?&UY(ꇷ!|]&aҖFekAnVV#0  FV_ !2lĈPվ<8K{FB"! # x>t>11 IDAT99 j"KX@q=̻;laTop1gHUZ;h9|]Psk/ }`@'Љ(-I8U:!"SĘ(*>>{ |EjZ"?eqb @Nr@QdDBDFQ$& .$L/:d$Gb7*DMJ.w=n=zH)).5d%eIѱ((꫒(MD_ŒLQ z*YL&1cƧ jHeD2RJJLwM$RJI]! [xG"?yqg%ʙܧ^))+C &Ob`,YѢu:)(9HEq @Q*UM:SV_HFV*0@ ]Vd$DV*0QŠ;z,#cӘ_ؚ'{^z)V(A{PEQEQEh,[prr ]}+q_@90D*V.*V #Շ̐V(IEyzM1H/Grs0Vx KQEQEQE%!o-.H@h,{j"!`DD#/2i\U(slVVUr=\_+ %Kz.2>-G$ȤR0xE( wi>>EQEQ_( R/>qLc#D^d ˀI rT %*N*^*UB)\:lN~z|^oz>` kOع  cmD-PEQEQEH58NRVxBPj~^J/GUrJRPh2LIeTZxUug΁A JIbGۗ~=CQ4]Q3]N(bfС -KzC EQiFba /.ؒBH݅,Bj6rMZ'j@!.nӶLhsb7Ork\ɘBJD-@xu}ozwWST?:hDKַRZnw\ɿto{Et|1G16ms[OQN߽!OUR܇ҹg$Xn-nn[_P=y R(eV8%(   B!ȋ / @REQq׷#7w1&uJkkUcbb<==CCCK,EU:9 W3`HL\yImG[tmv~=w{8R Myjǃ%vx[ ۙj®votV2,ϰca0`!Z@+ϫY<b1tSEQEh͚5E]b^#ouM< q} {j_*U>oK>muX sٔ_7w9+i\J*_[>a}ey=KV\dJ mlnM%+. |Imb$-P?4ƈThѶϜ L%_;U{.𪔿᫪"9mэFU#U;icCϷtLQAQ^ ˾{dY5^;6dS:M7@xڤ*HFin\۰yfqO),WL|BX*=Mٴq<=v=VAw@]㾣Vcnovu3:I#1.bH 5vē@v㻝r_+뤰 ri,໓mffQǓ=OHU (G G=@QEW,|b, wc}oqIwb(WۼF+g]":{bMpyen @h{[Z5+`1іq=/`׉ -dg{kw68dP#Ac\^NNQ(JՆmsuw9ῆ_wqN W[ߤIvWVZZ3@0f8 @`K>yJ~+}#9n`fnaS}J(EvR\u_C_ ׎-] 52P3EP'&'.XPIӞU~0j-Μ#Ռ\ʙ9}F_PI(1_UY}o/:Zu|ƓuJ< `&9ؖ1bm\x{y^Թqy>0j"+&fsKgfEMc{G;̜}F9jR K)/YkyNj}D'F-+;ݕ`"IMS4߸@}܁EQEQ?"T65\LJd&jZ) #74BZ_80\aRk9:9Jv 3T1wgbv ZȺjb]=t;WJz|oR.km\?uprɧ'g<ܾp Pwl?gR?.>zs+;N簥[ϻr7>TE6D0g%JQpI,y 'j>^_v6ACz/ 7zk*DFT)I~ދu(P)YI8혼iD& Z?n;,kP5񵻠|qsGz@ #C+sR0Q) OE" ӓ3\a??x{Ոl8xmdb2硱(!DPծ]?@)`$R ~nx̨g#o_="Yp%*.Crߊ+@W#s]6̤MqG?sJ+JFP) D1rh֭g֕Sk"9+dghQwU @dܫPkq}qSgoptz ѵS (šje'CUXYܴleQpŹݪZ-N&9Z`}`WQ:uzBH?7pJ\mbdd"`W{uxy.'zNVi"PWrk5j+7rc((JL& 0(`§?>u3]ĥe]*J{ټǴth֒TR?:7զFSS:J'XqokYaZhb)Ͽ8, FFx3vcʽΟ7$0ʪa>u[}[OжOs+zjb 8f^Y3e3:բHZ(9hJ!3< <.ɇ\7G)4w75s_%-mkž}JvhݧJ*+<=I3>qJ*icU,И\Gwlο ɗ{)EQEQEv_-Zrc:\5oIɦ3/F ^PŁL^UR(* xSaW{9IV,W/7roE-1.Zo'LM1ndr9sbOtk*jbޘ{Xchszf2.+3zlGLУ"gV^`Z#:,߈ԯ]m 򾧆zasoS`3v Fی 8Wɿ=cTkac?QM &DdžG7\fưբ.۽Y8!oǖCطd~\V'uv3f.7kv2ǬջKQ`:Yj2E-ua]!W9!woy}_v{߲@ ^PBD"!NwAQEQߋ/Fx޽;; If:_ M5Y\%%u+QVE`MQU6Y#kHXQU@#a `@hQ\\R$n^ҲhFQE}h[v051թ Ш9^@i (QR4;%j"#4%H?~T*1Br\__(޴o߾Pl#n^ -ersw47p6?EQw~G׆:fO߄y1;C'BL*jrj5j(*JVעvzzz*U;:oQƮmܚ_( YE(b7yCno#AyP~5#!E](  w[w!t-&&344dɒ (QVv! hAѵy^ڑs  99R~D=liA((oݵ&.@ j??*U|J~5$==Lu&H$ T*ӤBZֹPrጨEQ$>($:_88(((*KoEQV{yy]~Skڗd-fu׬]C;raWw u'.@d +e2RwC}p#Dϩ7RLt~rjGľŸuW_]aլtEQEQEQ@cŃV !xq)/ϳrW"Fl"2@ HXG(rn _vg/=vryu`i'ÉY(L.EQwT)9Z0RTưRu`2"VJ"/a`؏^sMlT k:rJ]z7j9zXs;CVT{ 4@QEQСC߿d[XWq/tuI0 Ii «+gjWמBl)=vkl6*.J%'=B!o|O.ܞblؒE6jϞ- !]xIHN_ƭg)俈YYۿyEB)UI; !7=}T]+Bڭm~~2&7rI/p`fƇE>ν8ܧ&!IJ-w3EoqspVG:_"g̘)9Dd$ ۃ ɝ 7Q[MH>4Dicc e ldOd(!$I:tEQEa5sO5;ZJ `cY/PEQ7 :l6U Z C Ԉ7t(9zDu}jtL~7(΍kb +Z(u AYdE0eJ}6LH,,%9Ԫ LDB?!<7 ːA.%>KZ BH6`ox.}ZLjheT4yS =&8h]@UOjŹGX>ܽI~vQĝ;~-;ti {+~^_/dR{kw6T$IC) #][|nqȋ,a DVF".@$##F#"A=ov>}lO=wf+e{m-XPğj=jZKOQEQE@7phheY1~s/*WK9ANTfm+ڵa$#@њθŀ'F-w7O^2BJJb"++"F̘>Ŭґs^H Fo &YSdSFH98~eT_GUdvR\u_C_ D9ؖ1bm\x{y^Թqy2j"s񹈡%-?8dh^qH1'=] @__Ja 1:t [I:(peeg1wS$6qFp80ˊ óRNcD"F@"! A_&5{oQ u} IDATGN`YOQEQԧ:V1gAPwAjŬe:Ϙ~喝-f˳bv Pĥ\ u3|y]*DJL-_GgrqkkElh*tH}9M~bfQm..|[xq+Mӻ*_A]F@X^[O>X웁^R54WhaM?)Q3g4j?__.OqR}OOg!zՆnR̿Q\;>YR"30P @IKPD,<]az,%S+vdJĕ-Kx`4y R(eV8%(   B!ȋ / @ B㛏EQT1oQEJ&tozWm(aHo=cyD&2[p'2uqIOc.KNv.>V@FU/B̎?23/ԘwֹމҶnK0 a$L޿Jtퟁ׮O\~R}+{}Ǿ^/nDNiUKH4)I9F% YcuXZm[cN6ҹsȴM{wDnZ0!K,Ʊ@5w 1k= )7Xzi•6HLjU7+]x\O EKho$i[Q%ҊR6[r 3 ,#2D@A8@ hEyAjnկ7)Y]+}7_/p qܻ}Y?k!uQ5 ZK$_i8yb\s'kcÇNYF;70ouf).$(~ń+xi ƮbŞcĨ=Z5`\/2nfPVIֆz/SoU3yn+_8[hbPBڍM+>J8@ސ,+ԫTTivⶹYb?K4 ȈC+Δb<>+ @M,߮TKm;^}s\v׼$h@@5 ,#hsyb~AΘ{ gW#6n[=%m]Ңֻ.9H٧i}B#bާ:?RI%Mp嗢KWnC6ȃߕmffQǓ=ѯ[4PO(BDQQ}eK(7tB}b, wcoPwعYٿ;'zM1gܪZycOc#ù&51{{o̽w,x14[չWO^1v2|>!`Zmq#+K#<6|Xš(((5/G#n!ulllRRGYZ*!@ʕ>|X\*-EQEQo+9PEQ_ɻ~X<B8˓?( "55511Rֶ LQE}?tb۸vҚEQU4/Џd牑(8.''@QJezz:666&99Y.I)G틺F-ע(:::~'wsm6v,˜`igmfMkEQ1|BH"ZARRR 󼱱D"IJJzQvvO?NPhc׶kv?rnMb\^̄NAQU, Uɚ7%BLL(СCnjICKv>^mpqju4V~SEFxue{퉈u#yk«[]r{ 9aL'zn}N7HJ9,`_O>,{zt97||ܵl4`ݠqp2) `ͦF<[Ѓٲ:MaGj-~ګw;'_+gk~C'\ͨXEM܉/@8@6mܮ@[VHJnKDH>߬|=NZЈqf]ppoz-p|];/o.4ELy}Z-q/_8NEK,@ssFj$)nM=l熢(OOВ%K~<7SvwbPNllW:p]_d5S1Ӛ&[y:"·AνUf\A 븍Cf{KqJ2~y6Y7ڟ*CȌp][C!{_~$wqъyr/4|ڙ3K7f՞._Lk٭̒MbUz`ѴL­G_6l$oo `, |Պ"0ɧ| C~ KFOwxgK#|3%:ݽXwZ*'3]5h;Mjch(#`::Q`^ĕHXny{gY/3Yc)JQEQAV{xxURcycÍV,ټ삶,X!ږ?@^ Kw}=F@~gؑ3vݔ9 gÃ.6*9in%X]y ܆]A{zQſΜ>w@ У>T&1ki01c:Xs Raͬ 8aSJ0&uͭ Sy\ݮcU;icCϗΔh/ .,qzokf#Q LgECǧ47zhB[@GeGmym+{XZb\6D"E%/ߵ|[M~{ HXk,Ům0jV'wv1#鏩J@xvzDزZ㵀u;ncw].Ւ|!k~8|YryN/br _[A  >k1-]N4wBZOYa6j$:0EnUjbycڹ:6M|"L?]3!sa>jxO.kW/5kj kL,.QyVFϺJE7]!bO ;kPӭanú>2 wss޴2F&AE@^a Z9H@!!44CVRrypp7ԅ233Y/y_J=s@ 28Q}uIg|ӛ6/4TcvNio9fD>ٴ?~9I8Gf'7RD.Tv]DHM֗Dew.7י 3[UUx[*oK˱jҵ\ҹ5KɃ7}#M aڌmoLYcN|v)W'`JTWhZ7Df&ᤷc*5֢ESm~3%,<}_{nۚ ==9%W)ͦ׆ypMO!h,VJ???;;S:99}&( ӻsGm9 8xBy9՝KO%9TJ%ɉLV*22M$ލ8KL| =qi?:={J6t\]TiYژ́/v /|=w3 |X}s۲kq(*BB]'ׯG @̎?N&Fxy.'zNVi"PWrk5j+7C;@(朜>/Au2 D"I% ! 5-HH=#{45ﮍV.z]W`F&&&'%-(ͬ*v`TEy یfĜ76h: c#䀨}sZxDȾ\R(@&}ʠ7ʱc3>tP usyg`oz9>nkˁAS}yo_Qkr2$%};yn]Go#?(39w闊U[w2z.J}6v3// FMQ̥+=j倲1bV.f,h*OgZ=V}p,!YVV (iݨ2 fD-m(##2K<ھ|sԋH=rnK}5qq< E-ԉ["*p+B[pϺm.Z+* 2! "_]/)poc^p `x "c@qmu‚̿n^prSgϯӱ(ٍg֎t2V8"6V:JB5-m u$>tH}N6` MEQE 333ool:颹ͫ#J̙19pO޴e:568keB[fЅ`eY~;j3҆L趙@;hBjJ Y?.o3Z (Z}Mzuvo3g8@ی_ŕ&5`K.!ӱG$@ՠ'NhTf]Yű ;Xjln߾gݛ`yC\+f;}xXUmSv.\nnԲ ~W `Bֆ ɟjl3<}3;Ep8kϨfo>&\Ӄ "Z,Rz=e)= HLVwcFr?SAT&pp %<0,a8p`8p 2VDzDb?|p҂|*L郀& i_@~G]4!anduq0jlwG݋l=rvI^~ |۩2'RS+}ź(c! I=4OO7cY699Ã痖edd|2!!!xŊܛ;4f830i+A F! q pG0` X'cx2OFx,cy  8FCEEO^|'MFW^:͇/88n}7k[7MQEQEQEՄyp#M |)_ Ycx,S`#q,ǀ@r|/]v(;C'3GJG6˾gF:=EQU!5VIBcBD 2%aqrDr2'c2_EQgϞ/]Z1OUjGLƲT*J?pp(7?ooX,fuхB TĄ8o(}Go \rQ&JT>'8߆st)lynLL`t {uyank gd@f<5 cKw짛{9xqSL>3/0$3 !Ǖ@0 a"_|)(zC$yyy=|CsMX y@x 6vlA !*쿓# IBi]4n KH[o k !߇ dT2(%QGW5!ؼ?׍_o_[FӚ '.P{6~^'>gSu8 y~kxN `T\ݳrqƓ,ӗ_ՒzܵOCX*?ݿ`c{|ߴimX`ePTWTWED8?f 7kź]ѩKy*71)%yڳW9y2a(U BP(*)))++khhhiiikk֫WܼS8Dqqq4$@w}yGF#}Mb`ё#[LRƂ=,s.l׬ DI{v=>}3zM:sb040IKwú>[6Э"Nrwʓ<`E޳wBҎzw}0^vqvE>UE0lQDTi+MM.HxjByw#l+6݀,wZ*Xri֯ ]ٴ#H^Х>6ۀo|f^?wsOa>VnK//o^ ?֎0޼y)խ8ϟMQ1il+D=!+?5Q7DYyGN*hި֋Yb+g"fݾt!7#DWؕt1͸um<~4ZݎsԗEx>112d0 pX]m_Brv (/quuEpWU99ϏT6Dyy/SY ]zaK`9eNjbWF3΄x6bFt.McAtͱ (oݤBVMEE_vXtroC_vdAn[acxΕKEP/ v><RC; ̹t ;JZ͚+|xtOkP{;Gضw?{Szg'8 F3Z^@'ْqreoCut빱b:6{dftOk.wMCh+G"ͼi]LfM_Q}d*^{['h1svܨU-?SN9r*~,5$5'h3-SEGɷtMɷZĩ=WצLj2Lplf"Hy3/(}QSQ 9,^9wIQ~zڳi+"1QRJ"ݶX-;o=m΢IZ4CcTUgF4=#!0ZZZBT&I^iv^`#/}i~)e{~ޭ}Z^}WDzlrr'-@ TDi`97W9Zh voH%'K8l`@bJAy}{ǀ״ډrm[n]>w̑B}W[}Uu[ª-WˈVamYSJ"Աjd Qbft"cpQ;y9٩b4,эW28I~V< C:10TiZP! ,T 6::oвs{ܯ}Α !NLL۶2677eY ȤRe2@qo\OINr2 xu;IQEQBhhŇ$&N3}Omm[gtw$uw8Mi{^ƔH]XwS q^0TPţ)"4Hm{ TDNSuNϟhbgck(s`c>o[e@vj#eXXo: r6,|o4{]e@`sto\J@}mKP4Ls6~Suas~9չ>/ZȆǀԟBwx /Qk6ďVpNlL\M;cZtQ6Nl=(;:W:i\)!0ONYd1=,yi΍ryO:cYʯܦWxQ>,o?hPz5lvfHRu^2\^:[2]}_ny g!$*Mfח:ڿ: cNM<+66TdcG]yj}o!x>B<oW|?iέK,x_یNeTuN~eŻ5M^ NY֏?͵[vdTВUN?蛴mpiRn:SPk8bE7儃A+={qM/9n+4~]]MMBQEQ̼?0:v]{bԲ:<{GmV {M@6oKX3N4*l3#6c"olXkD>[?dT3 [٫X:& >)lނvZv2BskcǮ%Uޜͽu`6w8fszt^舻C63zU*QW8w<|*ZΝXqa7/ca/K94jDٲ["Vf8ţ&+?r6cj]Y}m,eq,}'3ۃ۷sp&t?mJk'/eD9Vuz.'-)o]vE5~* Ga)>>@ᄃQ ˂g{FKGfrI-_mFܞ2̔_”Ixx_&uq#FQ_PIIITTT֭?ybcc+YYbX>C@&cRJQQ311𙜜}}sf8UXѓ<;=π0|+I] GL:w ep3 oGMďC{N|V`^_dى14 EOq tҮ2E-=uIҎ^}YLs^Po !ՕPɿ/Ã痖edd|2!!!h/so&ߡֶ3x_EQu؁Ȉޟkv&('0 `@܁Tu !|^=BT*x GDee]]]0t ((5mZǽ7@g#CF8h =)|M +L'~,~PNQV78fjUׄ(((%uyi04hЀcF( We9*dEif3iz]k[͚2PW)`swq-ۏ8YU+GpjѩMu{~((X P5Û*Zd2TZVV&H੘>ϳ+ON͓jfQ6/+JO/Be.{~K*K5mb RMiqo+M#[7oo^q4ҘEQE}Bۙw8;JPE}AjUi,0#02e˗Yy))i/^<2K$2oaTDgK8Fy%]Qv˩-r?3hikjy æ<}%._ݧPH]@ ˋ;T Bv~RrM] (((] P5!@||DIXhh骨ii**: _Aʒi险/2j͍oѡ~ zMf)A`uGG6g7˿)Wxj0.a3(0)v%؎?g9|(W㼦ڷ>>z>o5h7׀}[4?fڍҎ GogNp((hϡ<4fdn.k*NXnV۔7=4BmY:lQO3&umW?]966.Sl>Μ/;֭ߴc4h?r⵳ټ;%h. NJlÓa컙o}ʜsu'|J6j&0s^wn񒓓сwvx6M=}}mz/p; ][nO㴦"h?90H;[eE/fvɩ~>:RgMS^iŽ 3O;Eͽ8o~&_:>*>o``PPP ^~܂@`nnNPEQI$yyy=|d>!$?^l$mlA !*쿓#&];ٚBNHCdC[BR@ۙcg⿂Bo9ˉ ?d>;BH*Gտ1!4v+_B}Ј&G;y8a]{i7n" ʿۦXBn?h}e‰K<:eB](кS{ A᧳ܰl_u~'ZI+:{w>ƝcSon_oж C');KLYt긩K7o<~)C>8ߢw&?IJ%q5C[ v"KWI7Į m;"=/EC,hLŐV\MMuuMuUIdlcFp}J4@%7nAjjj_EQEՌ8HOk9` yqŏS7ߊEGl9&2Q i-kV`$_&r|zc/S \,[4Qa#O+ a?,߱k㝕J~[?-ͤsDvk%|T`ئͳ>v†M>thOOI B}~P 4{7z{LVbccF;1I{[6*r<O IDATMkO..a L>gVwB\+7l>B-j\Ɋ^x+8oϯwwY:Qo1a& iM~3;1ZcjJv-ʮTK_H2cXq~V?+١h y+~?"H "Y,%$)mղ1^#,XBc[eeeFFW>e !7 (% (@ tUqe9h*E?P zv)Onՠ}W T_)att4u DJ3_8xoFAx U~Z6vD;0v-ZOr4|EۨYЫN3XԜ%OۂBw߀JG0_xQ=yy-sS4pga3ZeP\,HD%YCO~FZfNK,tz>?ƒぱ{W  fy-4_xܚ6]fmwѫPH[m*Okx:zzzzzzzr<'wEQEQ=͎Oݷ,)15,1z5 ~V Ź+^y0T  {=XRM,dyEkd>{{8#SVJT[ E!+JXTɉY.-ꥠrS[1@(*j}ZO_D,+4nc? י+]϶4#0fbOZ BF%fon@t1P~.N<ݸz5*.ŚW3i=(*QJ^\.͂uVc,HlPhXAsUc4fFh*gϴBXcT+!xKQmd EQEQBhh?9(%wTҋ+gnd0#$G@q) 3#zyR3ј2F ]-@{is:ryuRk Z;b[[ܔΉ&P҈q=7]ne[ƮaB`BrFNl=(;:W:禎i73]u V:bn n 4skF??}vz:S+~}pL. wx.~ڸBꅀ՗3>^jч=ź tyȭz=e)?su1Xh1Cu*K-~5Rp,e乬4 sܸOZҤ˶hջ'J8 y{ӪGm\kCeA=~م܎7;)" hhj06U6r+ յ'EQߏ+66wbfff0Y, 6pǨz&Y6h4wD!`/4tЍ g¼<V3/Mx#+-K0ߝ=}Mo sl:?ZްШ3ZwNugg[.؞|8{^t̻ ;Z#w_^aݴ]eRi+;ߥ]i?04}\Nq;JΚw<٥E}ǐQk;w?<5eLɁ0_qݍ7ЁQ3kP_o s0  !_`\U3ѵ055[_JyCs#VIN*|BN#fܻ($_6ng@uufKfV]ϧָxJUX((:*/!A|0_Q/BjxgʓqL;~4|}ſ\$M.VP@N}$局!DFت0 ON8hXV||+ƠR= KQEQ7N~lX!'ZK6CW/Uv\ t}AQE}jEP5@ސop'ɤRiYYD")++xҽe/ kȾmްS"ލ{o;Ǚ=r+ A! fjf>v_.v |RX(+&Oɓx4'~T!N֟M(d?I:[wyQȁQHK71!ɉӮlaA1>e3AV8B$uw>> ℵasbYl9QքB4g߭6 5 !XY ?s\HVx[tr_z~~n,H!͇->R)76LdJ!kՙ,HRO-ЯXivTc9G9qv;*|)*? DAPUqttdF&c322 xl"VrFMi[)Wq; ][n\uVe^>ⴍtx[rGBHHRB.?{fMxBC|y,*?!ɨePK!"tkBx^Ҝ ;B,\Ge9lțZ[~y'Ps\YokF4&Dod̫6O{@.|2ySΉ t~Q;foL!]J@}c4y3uA3'ћ_oж C~g7w+|n40ސgGsFfyH3(BY*/+? Ũz,iͅ[xt77v_ʐrle)xL XWug8~šAA[;k%Uo2x]k,v YE2?sŤgePTWTWED8?f 7ků!Z~;GyjhhW\\Z{vjm7_[‡U[yzۗk8賁MF灿-/=ɻi3ls0sOuLX5k?_2?0@WKw9ߺG^ȌbJxsdz?Oam8W^}ioNP;Q_TȆYW2gĎ6x3;IR. /`D.OohX#{#qZʈ4҉+ g|)r_ Em]c+ԾHPBTTTd,2ka'|0LZ*[Xd%EQmJ4I_U1bVܛv+Y7I$͛77'{JJEzaK`9eNjbWF3΄x6b< Guyl14]sl8[y7Ui:lg#EQ㗧[СYFPp9ۖ53GseDRuQ!ohfgk2KC@ԐN&s.NRAf]9r_褟dO}O[ٽcZ%B"x~` ]y\V-_i.ԽEٕjiB[:&ʤNO͊ @EE@ g~*='N}HDIE(ItbyLCHs9&u6VtMLL|J^IIDffdREQ՞={t*~EʣL&cYV*JnJ3OOϿKE@ʣg\w”'*@A<4Rcx%Z OQ]*+c+&@xVV*'}${IoHN+[v_ɲ95W@&qӦ@TQz|iXqߨ![@ '6ͯ_;Fc J8lYQ! G:omf_pzEe37T59=?'N"syؕV  >~! rوN0t[k-(4 } tZ ؓ:w^1uLw6`P\,HD%YC꺃c٭> ^@ _QH3 ļs/U#`펺@Q_ ~>0P @X|ETZR'#€ @e)!;jj@JBB3zƛx@  ӥUmP tJI8&cY%3eFjeKRBM4j}:}/-xz&vN snsI/ wJs_i "{gEٯ8}'UP&ɾ &YQk:rj 1{ rkIE:VG3K: Pvj}7b曆uHZ;Y {RiPAZ\BL~gE, Y4zknckᅭ}Ȃu Po|BHIŚ,d2@`nnIQEQTBCC-,,>$1p{%䤧o~nˤߊ<#鬻đ/ulJȥ7^<4tػ(6I"wq\ .Nqå@q+"Iw|\(BHCɳ77g;μau2@>6\(R_vsG]^)qEbsqw`̼n=7_ ;K2Jɧ_Wtfĥ֣Do.hIj[w˶כeŽ~^5&kiJz,s쯃 =\t{ܖj[ۖC75هn3-bF543lf [ըஇ+θѰWw ڎUރF)u(e[nݰΆ:,4*;b/ ?'g>&P_%qΧhpW6T1b.. :5"IWv{ O}Fp1t bCϾcBn4,zMˏwS?rk֬>ϛD0 ðoaܸqUޱ{փnY:~f2Wm?\fǠOΜү*ucW&άʍkz9p?*\ 9Di#c?iLZ_ LpeMMIE)+ Y%pŽ7_Mtr>d2 IN9`~ݦ_{ ǤaTW5L9wRmQe/jbM]o|wD.;uRkaܑuu7{%d ?uB*Т呇N8[ [>aʘ$Ri7'VehQW IDATBP&O3z ?}uk#KOsϛֽĴf=`g2cs~ӯO6:7̰YsƵ<t@a ܄=0 0 M}NZ`a*VD"QLn^ba###Z!9,BX,$a`gbaX LXa"X!L"`eb4 , T1 ðPn* "f)GbYuwwv0 ðp4+$'E D B,j.ɥ(@`$026r8v~AOQ, ð,аX\5onCa&66[W0 >@xx8+I|B*[Z2Ks.݄oaU0&Bi~2aV:TJ,`% KLvnnffvFfVFfVzzFJjZfVvzzEӀ~Ȉi5aa_i\{Wlk첓1ڊ:h *mK iZ{x?VryvryvFഎJwB&Mw>RcQqod3T {5!p» # 4A!dd#!9L9 ?rBn"Iþ >a#.{w\dϋGLf>3B w=@h߬oX -0B^}+}񧗎ia >fG/@ Zni7X'X[7`Y[YA"d$%L ;9$ie L& X,[D;jeh-;btWrv -jC%E:ʐͽ֗; $z3e ժi^FBR>xB*=\bz<ը>rNk&V|>0y[NDGK3J<6 ¹~M~knl'Ia:u0 ðmA?LBeeݜ_f)%/Tcoc8BSv2ٌ+)Z2ש8>qxY8}~ _#gOڿzVOVz?^sێǀй#x=hwq e]1?x)p;Q)y,rdWea|eҫ e/V$ Z2?Lq+w=ޠDz-MY"qk<] w"QI&j 5 [ϱ㉻zkY!w[ |kS=(&7d{;GsԤӺ'/aQʳnX3tW;ܽWOq,+Z@4zCp.I дQk$щHUdF:+ֽCTgiF|c^D3sjj 爅-ͨO,]73~}UPeoje}5ͅ ۺ9PcI^7p5CryEjΨ֩K۟_PT@HE'l&b`a+P\_Wq(24_wq, ܽB*Nc2Bd aX;vlLLL۶m+QtΫ[ <=ɍ*-"`UWv^n8p2yicml퉮dSi>-oڄ⏷D_ؾvۯDs1 wTc [@7[қ9-&mKL敡v=[\Ȗleڄ.Y+ k{97o μGuť`/aNNL@ӵk6]ܼO+6z1>V!GkV # [-۴Olc{Kr MUupUt1l,5ra&eN)ƪ'ҟYmѮLz5q^V⓵$}F!$ތ}rެy |jc79f񴯝 ðnVãvM'k!`2om&M^:LufQg_Z'lJ;{ԂKL3v߭#("f2o/ݪk4T1+_Ѣ3Ҁ1&@he],'+rmwC4>`^]:(!eq]/*a:<@C/ߏWN5ܧ>;ǚ\Ǿ;oDwk=lfnXNWv͡`zaV=VV?gw^ZO u8y֌!lJ{:ɿjQm7զqmE6wZ'[Ox[KZyL^Pl{?x&v5tqg7=sDSڰunvqr;٧Z-)>"e_XqB666xT0<qI!ɓF#Z.HVb:`xɵ)YoԒ!E&-j,'x0n8b9$B?X#vʣed5 inBJW0Tyϡ9B7+ʣ :?TR.p,0 +_۶m9rJe |>Æ NNNy{M99e=+'] 8hMC=4w~j_=%a^^n2qzC+3:VlZb،WŀlܦEJʫg&mꜶK9%}sÒUeq2};h*]έd.[M0gdG R(tlL*u`7mOikK/z &/bJv+LeUÑywu & !t1n\8:گ\?M7 Ubkg5,<섨RVey"Wh{{*_\{ 5D/Pi9w˒F:y1rTw9.C'J˲4M4MQG>zzF`$6~+$Or,M9[X&"+Ԭؔ',MؘZW"#K!h;7z(tHGE+CPPK F\: 4@UU*O_90 ðsssgx7;TtêB.h PNLpenU 3)UU'eJĶhVpّ΋ \$H6[T9ȡbK`ߛK< /LƤ]=ߺc78iKk#Ow92'y,!01TVRP"yDX !u?z2-͘3rM{e:˃cvZUBrYpz|xӲV~iVRg9~u9&t{y,I5=!_V7(zիRדɺm+;3HH'+0{V|I-h=FF%O XBUVE1 TedffddhZNǖBPKsy??_i!$:;>Ԅup][h"v ;!9$W!jC༴jv|Z}fX 龎CeH %'4#Cr0n`AϦ]% sPfK)0qsmG٤c{zxdaVNj֬8|OOOnj>cuZ4j:F;[|dhX iYj@:xnA#utGOHf8b-FyyK,x N|~sˏc(`NWCHKHS1V=gːT='MIl^w~ثZ)m"Fϰ:(ܚqT?{ q1M _=*ڥק޻}ދ, de(]mC\̮8 `6ܲ\j@XT2@pP@,wr {pݐOxi6T;>&ڹ1cdRO3 ͨ i3B޾}Z͍aA$|@pzWis9z TNGvt=^yjqi1wZ {0:˧o?~?5:fU=.rC%F͊5GzGBF>m8efTi6*aw&SdLqn\H|"/hM΀ :#cɷzIͱo]箜K/oʼn1 ðo#a5)kЩ#yt0@ ,r;P3)rc/V,\%o{f`Es:"gS뮺%=Ro#,h2luVsܒɈ pAAq䥗Y[h]Uy/#J.*ZAx;H\tPGAdA-uy)3II0z.Hg߷vb•`Z:wwǶpʊlZж|{i6AeH$,R$r:=CQz^djjj,1~w6RE1@agb}azѺnuSSe\_PLЋ~/Ln=8޼n-gGv .-h:Iz3#9e)7 %Y1SG>;}r싆aa_ ?K׮l;>CM1Kq%ۮ\~ P-3#FG.twk g(!L~6o*8ȘCZ߸vooon~=m,[e"bۦ{d*_ 8f7wx|3''. ?k.6lü $o374-Ԉe_1FUsOB_}j9 _jӺ C;M2c/y,.HRu[}G]BasH5; }|$c"!qaHYjϗwۏ=eKyLp|iyӺ2dӯs 7"/0.>ݵ)Oj"_wzRcOr':wo {% Y U$[SSji& " (JOӌVk>(gb}k*rRb0ۧR8ׯV'ACt8aXIASWtB[n?pYuKg}0 0~~~$Ij4;(E6mĹiItfA!*]0 U?ڴ`d \D@p  ~Xq,˦rI Ph=21FM=Pԙ*R_E iݪu0 þ{*Tb7 yabif(qc 0XVBzDkZt.ZAG.'ڔR.t}oRu__ZFBJ7a7d>3P @Xa"%0 &p, n%#@a*{Ye&_O?~ 0 0 0 Dpd 4܅caaa`昙B P(R}lLaaNa})РXV"PLtò"`xq0 ð͞IK_Ê ;96YPV7yIL~^gQ]Kӱkݥ,){SӤڦL$09i'nM2҉쭗6%Az$jޓr}d9U׾ }нԾ,3ŊXd6ņMIj ^bCT~?Z =ׁH =zmxXnUL?E^.8X ˯FH}F@df}u>Pik$\R w6VoXñD Bg3 24-J .0T*555E0 ߯+88$+22w+@N6s.ZO2ɉ釞'{T[x=G0[&a֤|q*+}4)@Ln DXJW"%YAVnC{IW)-UXyN՗}ComѸIu_΍ӂبPp/]3'_eE =eUe4 y饼l z6SBSE88.KVY~ɹL+|}ujֳٲpr^# < Ӱ.2ڞ}f޹Rē0yqō;a! Ąp$"CA2r3.5 2,Ka%ݺu*,[ ,*Z.ȗѫ~&'+w^I(~LԮa?E `Y^ -ngj'yBm 1;2 sj7}ؚOtтh=ѬE֋d뇓XPe}hyu;sw*)&X' nKmO^Gժd.ID3^>"#|GoA%t(aWnkN=l.)&hY&EEFy l˹ eZd#jzr!v_7>c{ IDATe_%WYKֽdpAo͚]Xu^lA*^ 1"URZm8멤d!A)<>ESz!'_g;|M?Jdb-F}߯:hZٵ/jBןl{(ޗaU0 dZ,ZT /0Lll췮7tuJ5d9vƯo Mm{ ~]bġPr=*{:]S~ݻ Tƨ )x5$ :@zMLL۩NjWc6FD^k$u%q!3-.gZZCcwg0 FY랼8c#Ep?׋;־时vUUGUPƧx#UږRY H (VE/ɫaU_*zup4H)dmCnv씷`S$`կ_Krx\"BA 1PD_Ij.sK;b\kaaQ[]д#N|8#'}F!$ތւԓ<x2> WI,&]ʯ&ؒQyabK'ZzwVu@HH`_ǭ} c2Ӿ>+{aGCE˚z~J=.F0@F!֙ ߤ:;҅IH|8U^=]ͨ!ej/=MoJus9-g*q+XVB4iJLVV0@MQ y\."Y,@`+y=_Y`0 *%6.*y OHӫuÏ Z*Cͼ[K!Ϫ(JրPWhqx((`" zgF{X1N -E6u1ϺrRV 5 8"dȢD(xOGQ{IX垻)][Ϯ :oaQx -6,m&.2XMLky ^?TYY7tFTee/S\C! S,ӐhңAJ̈uwcBرm4_6VUqqpkiaammekcmccdmm`o%ICoO{˂u& ײ`/ tv-/"]ֵ?vP}BIɋgOЭO ;?}-K}Qo&jY哉.?N@:V/5gFz--mt* y=u貆~m2y/D.͇mV>`MSȳ׼4x*Џu;H>fW{yAʢVBT.`aXE)+yC%+YL -yՀK9EȂKc9OhU*O}]J6)\"թ^)4zUuwUzŸgw@62IHl-UD,E[f.BɀA Nn`Ur[GbY= Sf.xFg(:(3Ĺ5CctgۃT'zS_RWٌPf8\ '4!Z5s@R*is9Q]]F8W*E)))qq IIi)YYYo߾gl_b&+i;sS㶿6D8>LdO8P@qw}uAc]Ϡn@H{^ SO}@j]ҽTſ/K-ɺrf5"o1lM%a-1\:MNh7| F.bfPd^m,ڋ\+1M8ہ6ڴM . a/A }u+0C4Њ<E`8DϦ]% sPfK)h9#ylRDZXu=\;|g$!% $ 6-!lb#qnx=-i4Yk9φOY,lc!ʸn`{՜:IHIGF"وFRGZv#YN|y^F)utWcv" 4g_`S 'h RXcHWZ7$8[ "."-M C^(sʬu^-ח(F<sIZBP)mꄯ#/t\XjSPBRx$!%uY~B5C9Wq6\!H&Ez{Q |/n$";RVY![TJ%B$6!HpJ- r9"q`=fVV { Uל`׼ò$߮YK̫e~o<h9:Æ#].{h)GV˂Ѫv!7}~zSXPe?V~o5zJ5{Ԁ}懶?LcX|(Zdŗݹx7@{Ka;pbOQ 3W7A 7+.? hM΀ :#cɷz9)cߺ]9P+_ =fOJhe&=ALZLYcy>:,z-E6 ㈖@b^O|Bp]M h[窯h494߿۩z$U=zADM(=bt·:e1IiO>]*_b@,{ɏ(?6u/ `U^.(_@?U=HZ$2߼WTK9[3xD#} V4$P,6-6vm_}tFsg~wJ4n\iFhfm1k01ޜ>p,+@jժ$ m}*qgyOSٔgO=>nPRM? Y}̃;;|ؒy{_3 xV@VXi(Nu:#Qw?&7O*dܘB_}fHNgّwh2Հs=|]-߸pav>s6Bleiʂ2-0 GdgNLPAMڊ9\ˆ&\zh[Ĵf.6CaaaQ8ۛ fRRSSRSsrscަT*F ܻF9Ϗo;\ϥ-M0ʈwӢQMMwȮMu 4kzMrq0ӿGضVvjDUn,aUtkaIϮOi/Iʽ}t,lҞ2#u 0 0 #z^F ƦrC,16*UzXdڔ]ĭ=fCv?p,ٗ"--^xf{]d&n>:^e<_OSokR]?UlmwAC-ml8ZQcu&йuck.4mvy*FXuQUaO(a]iקvW;I0 > e28[V@j޽{M4tsscX65%|>_tzF466V*6662EcaB[n=+.ȸ7gҁ|:Jb&66Ϗ$IFIzJ2]>C0 o:t`WϏop-<| B DBD4 "  Ь(V䔜daaa5QC & @Ѹ@e)Ǽa_8DzlTT/`Q-\xY !$T*3~ MB͆,.V|׌Bȵ}dU1~!juu2AڰU^>RJvbU1V /BȤɰWjJFb5/"zMxp&(u;`z]zVW2qd|gJۏ3;!TTƽ Cwܾ̿"TYm~Dk xi1 >r5k֔2w ,--%IE0 ð<ٺ⏇Ijʋe(>[9c]]KyiydvPIvFAS_c,Umor9XnSOg)>)[13Nn#KuyubnSQx&%ba_N{ǃm~,IJ u>NkI}U{BdVR4Wg]~O$&w#O89.YwTz^(oƝdd]g?ٿoY|%m_Kۙ_y.:c dee|TrrrbQ*+aa7F1;Ԫ5w-HyB*[ъ +y!~Zz)†#Hآc5’㔙GSF,U}S|9 |Rf8I LVof!; F{o+4uI&VUjהs>ϷϽwbMn&!.ĞxŃlnоm)3{0rMk=V/K~z#F}}'Z<  fn:Ќ3.֫lnkD [W6ļ#uNjnkTQDCMw 8$ɦA{|{TH@Qc:.888''7'''777///OP()T*UvvvEW0 ðoQ%x,I\#8MD[Eym?i\NzZmݙ\l4p|gB=Snn}ƕމ|^q&︟/Z&7pf`o1} uo> m=%;rs ȓ?JOФU}ʜ㳎 zyU%1qWD@wb ֒|8ء Y R[ĝ|^ (l8}`HkdffFp82\nnnnnnnaanaaa`eeegUҒéWaU F6n4~ 3Cڛ~z[Wk<{RIbyqal_W6bU܍@BbufVEua;چ^6:=-s&cNk_mgShiy)1ϻK)Lj:X]-;8SCTr2A$~w,O"\mS&~nx !63NiZI̳ly-eYG)A"QolLYm܉j,))rCZo1 ,9x^O㠝0lޡy4G2 B,!!`X "w1 0 O!$}}ܤ$ҫ[m̶G38"ƒG]Ůxo~}ϭ&jvjr}Iì$"1iY i&q&Z Oj Sxx#Ž\MЕXAq:}S{;~?k}¥-'ՙ_eT:L?穝iaQlO> O~0*eB5O*s @{67#s.n?FE=qB3~6Z>Ew/8PՅ)061DhLzF:baY%RIBrJa8ud?#utJ`>kb_3j\_vy'V~Av< U }#!`HyM/g#¿ djq_[-:`S7׼ѡd]s)I!R_de|[ Q>>^eB@N{yB1ؤa~=GO_Ǩ> caObL@F`+`^]ځ+շp4u{9b-]ޕ?dyqnD6aJ:NDО$wK׃abbBr8\Y[! X`N%DB ðnݺUtEX-fbYuwwvXeąuٸDjt `)P,EzD$:fȂO:dʃ_=|F."EmtX|1w6uULvz.?B5Lvyr=XCo>D0?l,5lŮ]\b˂x~p{ƅ"cל鸦3~b2OCv (1 aadz"_dV?92T?/Uȳ4e{8w~u5 Zo`(IF>']z{jF5vIi~POFTVNBQQz=L !SS73ghaMm8Y`d\!AA"CX = lҤ)E3YYY A4E1 #(q, G V$ok]iIqZ^<ȱi;NJaaaߵc/dbUqqpkiaammekcmccdmm`o%ICoO{KqqkY 0 ]fS:e~mB=M,6U\^?!dzIڂ)COk_!dzƛTʉ^N8iٻ&7{,BaoPDTT[qYZnց{^uUk-j "(7$yw?T۟Vcirwv;ZNh/3h}]fE@x߂s'שKpr d4I6mrn?Ɨj_vrCvnڴ߲KIZq;Gx*~SP~=Z8tvW$p ]%(9w[qÿe[ƍ*9;'B&?8uXX6 @+^>-BȽNd taMKr ðk0 \VB@@JOOOxDE3~I'wXaZJs}NZV&`O{'5+].]3<<<Ő.EGycAܙ ^^]pbM;8 nj)φ!.vW.گ>Gc)Zw{۹~M- `k<ˉ3NO`aaV\VB*B$ٶvv5jZZYٚ[Xd,Y%bZ"!ޣ؝[y-MD"vaIZ_z!i]}(j{`3x|@@uj~{]FigAl+~81Gw%e#Bƨ=27}'j4-=1k\k{B\[+Vl̰$:v+Ά!7:؂k ZK<9 b|}-PxFd3~?{)e%I0 0 0 xXYB5k$YA<i#b!3D`PƿqpWoޤ!9Yg=yˑZ"|r0~\4S)Qq okݴFP|R"]͸U<>K<Ďs58y y;!5Veŧzajrώ{#px=d+BWAOf#H3 } Uب!RI0(&f%@nl\lI+<,u 5]GA$RUgšsU>-aVa'TiBѰaC (NJJNHʒ+oSR322 5F$eu}*?:״s9\ϧFL~JQrn%Ҫ> `4-C K=}Wމm+ڝ-ϼspw+3g 'VHGq~uq'rc{xd&@?"!tѦڽmB֝z}ֽN4] ]Z~Ulø_s MZ蓯w5 aaa_ JC={= b@(%<)%2hONMOJI+"S[Onץ1Kn }^BSiG^JTgY[vn-$"\[Zw5Y@ZuZ:w~c&;c }*imw njuP1uh/+C o{]=GXXHLH]?5EH0kjۛ"Iec Wi1a"equ~rd-T5O4V[ة5`H;9<#}BZ!$Nw:y\؂#7ݒm7se铏kZH)`Xm=Y:7of/E鷷w>эY&;p?/@dEϵumMjC/~>F}Cx{eaemfXl X@@ @B@@$AAX,ђ@ A;9;ZZZ~*ÐP'eedOДQ'EDZj׵51֭?Xa0?ty2((;!i4zUk_rml"@qtê !"r շ}>нmgwGJWNXf>;hB^WiN;`J٢狗!d v;6_O!rlMAlv/־97~>\  ?A?z-έF{ˡy }RؾӺ_6F<3j `fPG?go>Xtan6 ph3anK+ ;u4nFv };ݓW1IK.ݵ%?eyꕽ=dosXjZ%,d2V}ǜ.PmӱMD_UOw4*KMtm?I*qg^:LԆB|1 8{!|ae%}j꿭IQM`ޝ”'"SMkq7bEieyQ9.'O'Js}2ڄSB/<)D ꮿZQ0>+;6+JB(Z϶MϮO'901Q]ߚBc%qoT#""E3ā]Ҋ[Q.KY@:zEhj܌wmiN'^?ok 8j޼ywD"էh>?ϧ\/e߇l~FH'2 >DGJ6( (ʘ P+]MЪX]ǩo[ڽgcmLxxL {:ז~p6}ug cSk/WzgFcCe;q5iGٯV/^uMuG oڍ^ 4ot{9çlG/:'bF -R>5.ٜK'ZɪpqN:= Wh2P)>P+S %fԯN|?>jԞseA4-.+<;|y[;g\O'kt|J*Z HR*r\.*JZfp 0 o#[HZ5gW#JVpTkXK85w>U; |_HP,p9~7{Գom'kKkgnl@d^NCHӡ oOolaQ/pGAdLPM h3;6ҲLCV;_56}JjEHdRs|H\FWꊏ*w `T1GrE!#GmG-=l?z^a6=.:S]ͮ[o 7 aa%;G+lcGtIgac Re9_82}kU$e X6Peo$mnwuqO>U <z0* k9&BXK npT_:PۢPT_mjCxY-2qjT|Q ]iŃcjkKN7;X;:RC{7埊S^&_MùsssZzT*51cca*H}YNl=ogۭx)U Zo0ڠT H0k97wC^zggOg>=M%bZ2n_y)W)wK\Cƽ[V"6-6@|5aP{[60\]S>gSc ܂=kGٸ 3i侼r$ |U l5.t̩U[/3E`ȼ}`ӯCR7V)']՚romq1ҬV|/qooS/=5whm@Z͙  qUɧ^<}9lؿGV{z֗+fffA(1Daa 0 E|@FSPPľ͌p 0Ё>^߆b[Y<;_lpAA"wA)A @Q0 0 0 xXAbYYahl6H$J6 '0 +pzIaE +! B",D6A ܌MAa\a_һw/BRf杒,,aڵk{baX98zꕥ^oHMK#bT*U+2uz‚`n&tMNKNYfN;bҕc`rT7o'G|t3}ffQt_:/}(1@4My0 J,!___6ZΈ(-@f&&*6D ^$}$b)?)TŊEEe|Nc0 0 ð\VBQQ͛0Ptnn.M@e04 Ɔf3 ޡquS'^~BKaaaاB5\]Y,f[YZX8::88:8IZ{cT. !$2=zm3z dtO կ!W߹G+i<v;ZN{?mf@+uj!V Ɲ]ܷ.BM,=~na&?=זAx߂s'שK0O!d| V> G?fk}z_^?+Bȡ7R{C%O5E;|5'mZ 0 0 ê BT@Q oSSR2ғrsshhJEe]kh:Ξq$.9&?z]ߑi*H`޼`g>ĐŃVEom5ja70Z`#/y̯+]f W7mkrsG"@\];Mg\_O{kxaݜ2ɀ 4d7ImLĩݔy-~}#mk3x|@@uj~P;)93qj 5AV٦lQcsoĀ=_iHƭ}EL}-"<:ǬqyqmFN/6N-&"KTа 0 0=. yͼnFrox}).`<@|v=wbx2 }sbɕp3vXyB5k$YMp,.ej8\6&b!"YB2)A'&]]ŕ KA'%%zXF]mu4~ZV |6=V\WF_|ٲBC:!2|}vذ`V8襤ɁR`\c!A}O*i흊N58?yEasGZfu PG'VrgJZβw Fb\MNkױheYS 0 gIcϬZwݧ+>+@_ssaó)`nSm+-ao2.E]jR/.].Yqb{wK©n=[s42ĺFUj@dRj# LLVvVN&e75ǂKp- pї$[?re!}YCuYjAAgW"z6֌lg9C>-(S%]zۼ1v|ġ̈́-O\I_4ಅng~kg\.L uk1e7'\n5W (yvP8UÇIq0E Nu:{,EeGƩ×q7}3|],ʂ ֌7EUuM֔meѼN> d )E O-< 7)8FFaQgٓqEvFFb+@~OWn-aGeܯʚJMR 0)Mn\oEg𹞥 hަ0hBo`a]^di:NT̽ٺR%Fbn'Nh*<2bU_ˡGgdW62.[ϟ==:ŕ~!C)yW}mrh;f*w;QE.ws6g \w޿oKdj{[,*&;O\Ng=g@w1wAoϊ펤Ɨznhk=xS0+,{) y7Z+22CG:z#S4"fk}s:0y {Qa" AQtRRrzFFzFFfV\xYXXh3 ijt`Լ>3AS2ItʼnGYZ:'>:򍊦5y )@yTwUBv[YM iFG=65/S0Nxߗo3YCӅI7/LaRP_hFypJ\shT1ȟ["ǕP 6/iB30m75 M{1Eua1r=^e?8C9 ܺRPG'ViPaVJN^8O#?2 Gu̡iaoB +udJЊ][?.ВG oQWQ>Cek83+Ux99-گ{c؞o@2L8RGc/7" ZpЏSީ:uhwGyzFڍT*< ҼyP(>e;}~NČnnnΦV;nJVo:yL#\l_B@ XLFT@v'fjYРǬ.+<|y};g 4dCջRe}:_ <{LO1zRsP"Jx|SKd1(OW~ӞeqEO'uӑ">J̓;F/hBcK3a7t1dĸ'@ܚ7L-Xҹ}{e-WtTN>sGr+D/],k=6dN$l0='فBa#6+ Z):=[:ރ Bd/M. {qʛgL6MQj?7sh'6ˢݲsK/h!!zԺ:wzO25v] ̀pha!h]Dr|%p\%8T=] $wmd*|8iBD*4|K):>r)~Ts ^Ϋ^6mªO8LmW2RG,D3L"0\.W1:F*6BfReۡfY;QbE4yO_fj>3W.e; -zL6^zV^A@J}/?5xyMI>nx!kyu~vz/:{#1{zt6`K॥b9wwۼ )>j50V2qn?icIKqx3qX4⧓5Y0 ð Dށ=*\f;]q\C[iun; v^u@2s`O:7^>4ҮF&&%9Ҽ P0@Tp jv@e]OftTE~)̽JBZP,sĒ&}|=o,E}4 Ԩ"5ZdԨt @)b|rycmR g4O:tyjS#%9wS89eUT`7C>)@ h0P IA,b$HghNi2YCcPyO֯!%u^~a٠Cf^N"Bݗ{q[ >W# >KGQ%1ŸF%t51~*H}YNl=ogۭxAxEŇ}W6gksvp7B|%ɹ m|THS^=L_vq uɡȣ 3CI<铯]Ir 1W=rr6蓯: joFKpjǣq|D[g(w!r#4M4КܗW*}_s:Ԫ-"0d>&oԯ ǡ۸98~Xk kNplHzKצ]Y|nɆv#Fjr3Sc#aUba40 +{{{62 j^KXYd2KK/l5O 5X1OѣUOw4*KMtmq*ðj޽_:/LӒu~cUmOh6 {&uѠU^/4 GũGN-MYT홽{V ҤV֬rùB-JӌJbNCN/l'k2lֶK0spZ:im>lt=*t}1MyBpj=bԜ߸pimW^n&}4G:zԭpMNĬ:&ݍԼ 6qG4xWDOrW=_ս bl`& 5}$ ^} 'S¥f6wb) @Vsfv`6[ ]CSA ct yê Z}֭-ZPrT:N(JRicc[`aA (|.8#`P ---###&&fY4)q 0Ё>^߆b[Zw `AAA"! !IJT"IL)H4EQl6I(`~aaaXUs;l6nݺ%xz$aaaXUQQù5})^EXUgH ð+zf/VE}!֐Xm1 0wh費 !@,R)[Jk30 0 0 þ| J`Ix8T*Pn?(Z("baaaD2a+t b\ @ 2-0 0 7haߊhR`ikjbh01ᛚ ð ԃH?YSݟ깴''00)V._X)") X,dn&A! #2eHcaaDR!aK޽tUHw>-Oaj׮9ٗ]8ۓ8N>?׹/&x̔Y{zK\:ڄÜ <ˊ&+l5;O-l8UjȺ}p#Gw^~6-Κ=iς!yk^:w/LL8c6GysA\#IjtØ?!Đ{Ŗ9caM-ٟ(?'0>lKF_`B{G^_!e󗬻_ #a0?/dށ,]@omR&i7n&Ƈ]>ĕ[ew \VHOKK%"aj*(T$)`|_,X97kWGFhuߞd5v %jߊaV(/4͛;O3 `P^}RiZ`I -b_D7wD|Bu/3m©$c(_O<2V.lE'_diґ**Hy Y숌-J9WIJ ]gn2TV~?:cowKV&~=_H= ٦ӣw[s;t<>ȵMۍ~: ҕu}Iw?^xNOf&#M}^,1O}}n7=IKݥ'6(3"</B͍$.mgmekcecm)ZY$V涶ֶ6RÉ5Yfg|ye֎l=ݣ{ ND©$CqTWRncMv*'Ld6_,AA<3ޭaf|PGfK=ϙriAaVtI^6o4qh3an˓!WGy=! ,l[y/ _C262vL{G%[54 (1Wtp.+W`(S(rrsrsr32sr󲲲 Jo]«jm!`l$pQ |7y<~Ew:v v={Q>Ӈ!߸ *~3}Vow$m|(Gj{g'201Q]ߚEKިFDD1cfx:+22CG:z#S4"fk}s:0y>~P SfZ^:l $K!',kU4IeE S_[NL|Q?Wq%z"; ?]IK[-<>>)Ja*4y꼃^ma r4 8 #h.^KPN*zB2=Bż#@ ,>嵵YM[#fs6̈́g7еRY*Qso*iq\{VOO9,O'baاBcvkZ>2KoiWXLf_?M{ukomm©,:%$RKnMȚykݍ$U'Om#^iQq-m?: R#|4nk3+ؐ4ot{9çlG/:'bF -R>5.ٜK'ZɪXN6#\l_B@ XL=/3V O,1u ^A vټ蝳B5Nv@}Qu>oiAaZ@M22rrrr En<;+; ?+++;+f1JOB"K@5m< 3漻" y{OFZ{7Iv΋ZLm S.?cHlIpGsW/Z#YH])埯rB,nG"AQ9ɹqQ#nZuV6#l ~}wӄEssj7}y-ڻîjYFͭd՛|8<fԳx]ؼI}<mnSI8 ^ۡ$gu9W'iK:H|$a![HZ5HH"ti8gi/%Apjn}VИ5}F y(uFTCV+&)lnEwl(?'Kdvu:NX6){Ǫ7юgv^m0eK/݉xSWV#8TqZt*eF[ _+>NZPl" +(2RANE=q\y,W|zM]C|j8VAX,L&6df2D*"PdieinaA/EE?,p(<~Nzq*K_099!jȩUInyb` 0Q 80Z"vf_ nS;k"l,b^ewĤ=J0qsOwM2v19C'o&=Vcw' @?g,ͼ9g :&^҂Z0_]-u$4$e*.& jEnh ]KbJy,Z%g C䤋u \0 ê0Bé bqؠ)< uƪ'V> ;xu^{[[[;rvs6ݠKû{s gsUc c躔\|fEn^y <LnhM 8&BX,Y4溓qSE}QE^ue ĩQb7J!Re("YcRg>|H5lXӄ>Ӎ }kWGJrɿx@![[[AYM$q& 62I XBN2Ꜭ ou~+Lseck IDATMj $M_ 'i&Yr}]8q\F)p1U?6BS4 C*UQ46ӦhV|TUqJ0H NI"E~˗yuޮ"nNvtW _ NA+N 09XwS$ۼ̂a'F{aߑ mVFxunɥ> 6 ϯ ߺUlmH3|~ÚAԪ-C"0d>bl!q6{dhiM+{` wGyJiy-;pZ|D]mS%2Sν>8U >>h\w((`QeZw>RvbO{mlSĈpj*v}7H{7@YwmJFj>n/>[Go mT3RI VJj] /ams_fa\y'gv֫CW.NM ٦|d'cVK\}qT7](0 SuѠUs) z\nҫCA+[ ~V ۤB@7#L2'j.JIM|P* d]Ziuz u_u9cSq¨oNj}څ@O8hT7u>ɰy*`D:zuTPωUDŽbߡN 6q_Hm5]&rWW3됔Mx,~U gWw&j;$76isd驹ߝW}ǽmY93a>;.֠4K5ĔN7j>P͚5B4Ml`* (fI>1`b^1ѧ+̋$ ,m p/ y#V&5/*/- @ @ 2#Vݸ>U}ikҦO}ӓ$\>_)pMJݫO՘]+n[`_tk^s6l|s-EkD N6Zr!ݻww;dá>a4NP!ŋ|>_Ro [ɉinػq "=fﮝ2<s@R <>к)BHD'H"@ 0Z @#4Zyr@ jZ㸀I, †_@ [~1 L!I255F<>&!]u:LZ;$J;@G@ ؾ}Vc 0]}o8A:N{^t@ j #(0BظqcHyi= 2D+:{; OZVo8Pct:6@T $ V ŗ,)% B-~-IE@ !Iк1N'@@[~-)@ *Au^w'Ύ!@T"di @ N5BgV|]Q?7}S @ "¬޵j.gw)w!iW|B%i48F5]]M~TnM}T#/w?/wzn~^~^ͼܛys#@|h`ƴ=|έ?vCSw ]6(Bw$5 /zϯ3ƌ Eױ߬ԥ{O=rpN|{;as s8[ρ뽦D&'+Xn> xmûr9u7͵ ާwx2 Yp{^KGta|ݧNml(N}6r@Zu<őEyt$ i8 @P0-5AH$0,b!a a(o@ Q!_ߌIoķ.杧=b5\?3K|g>;ŭ*qPpO,m|x𬋶}QI$071q&^6޵[y۠C=>=yY'ڢ:{{gbJ+f^fwh3*Zx(P20n|V׳ůb5 j ӏ;O۲ۯU.I\Z@PmޤB^LL'y\InVxylٍo#<$Pw  BT 舼|HAH$RHI|:|Efݻ|ĈW xI]cη.=кz3" l*@{@S\D6|9۬Qa#jzm`獅_p({tˮ-'vV'Z>窍M^6w%YpB~]_ ͼo_mDŻnf5V;1p-iS>iޑMy󇃝m02bfugB B svB-ITf( D> [$b|MyiNlnt!_rBT aR{{x’$ I{ $ 14+D ޽{k#H=4קM>IlԨQ)Z)`Ɲ>w l5ҍ*$)+lBXԕB"U{i&uR_ebQ{?-qѣg?jgN;G ~67[%b5@6'ɛ2{١͇}-Sl>"W<=8gf٨_ &T8"]ɋHMAPEkJ#:/'@(rpEZdm1ɤH p\Kpuj1ɛ5J~ef3>N4d,bRCu~B!1@ ,J8{8Ʃ[6@޽KFۗn}-V]wa)lFEkX H'tN! s>s*%_5gibI^o#Xk8(9G䨽/uxߗݳdƫNsl.cgއ5}ePv$ @F?8ٰca+Ov[E<9|t™!@~йܖ_uق]Zue˽_USau:.I]2lNoESKPI+I4i)^` [!* H'rr23322Sҳs222u8 o,h:8Qۭ5? oʽiyFG˿c;w>YĠԚ?餮Hſ/ m@˰@ !D,m.rgNo\>:q@yꐸ4e%z>PYޚVrP8Bsnh`g8_WtZ⾑Nb~Rt暩B{}s&"B;р\*H䎊S4nꥠqnOkbx]6ն7AY)zx  ~zϺ,`j;1Vb$xy+Pp}7'=w*`VӋ9Ϟ V 1i6A=q}`{{7N(t+ͽ%@ –ayF@T A88Ѩ5ZJM~zΝinƗ7hJaC_=.ԣF{v>F Jbﮝ2<ŵF@v@ |XqHU@ %@cOAI$I$+Сi V>Q!K?cIe-)))9""ܨD Np ~}?PZ@ DeA`ͺn3Ii*@ Q0 Ч >ɒJ(]:P  )@8`nTVk/#HcI@ X-&%pZ@ =U藮`UqD@ a&`.t0)h@! P(@ U)YFr2(ym> @ƒ?tH4.Hd^}ջVaqM(*Z a\^VB~~}V av@Z;zBۍWhޫ.gw)wLbdqeC*ڎXJE*~0@4Ȋ!c.W'49mt-e[ۦt'6z"5)֍ vXtIv]kwڽK %A]u]SQVp+V&''gB@ ú. (FdQ@O$ HڴI`]~…?vܿjt:Cj ^^XsJ.=})dA_sΧ=E4@_p#OII2T'kC71q5 fUؘg]HÇxg\A S_]/wy{L}@W:v{פּs>;C.3ܞnʫU,M>6f/rАw6p瓪 Bթﻇ.qvGg{2T‹v_^ټ^j,ֽSpڔkIB)@  @c$L,M(AY,@ 1EQc,_|Ql @u^88k(ﭔW>/!y\K8t;Wv=W(dYCZQÿ.I; v/)ң\;NbT;S-]wYN~=ҽGSP=8%9 2d^M)C͞KF/XfbG}!36܎!Gzh,GiPy?Skñn$;wc.CjkX|]Dt:}}-7>M{9 V@798pL>B&@q!\]HI@ jK,Yv--KX(,=4|4(~3&žA_{;O N xyf̯k uiѳDlufR1 ԖS.n&DΥY/>GqAG;yMR|붦XwXdd޶wvQ6}rzk.ͬǀ~a`['u'^{$ywkf܋U|@gUYeNckc{|tuڌ؋ٚ5dU̽A dy ߖo~\I\Z)k?oMLs:~M1U\IPxyl{C$wŲ~, @ v baR\@?W xI]cη.=кz3^#G^K6cnalx[7Ȼ{G{6po;ꇯԫA`.1=]@ X)/HPfeg]ۺw=\|N=:__sn;uM=k?Z*8l^Ahr^PBL rԴ˯5F^fVcž6.κ=O IDATyڔg/>8֬a 'B svB-ITf( D> [$b|MyiNln`";sM;fbxf״qD ]o]}H$ $I$@ $ 1? b6t 5)D[`cȭnT!qm&Oy-W]Zoxu%SH(qUN QѦo?[,g85x d 6bߍ!7'3,a\\̸}>1 }&T8"]ɓݤ("zg7eCΕ[ԹQ}D$yz~qxYe0kJ/BǓ 98B-*IdMڤCO;wT|TGkz{IEnuE5nZ|,?X5wI@ [d $˺@Y PPAI8FժTܼ7oCs߃t@ ^(<B4}5f'Á# ioݥ R|aAySנR<5{ 5oҳ\[5 @Cݯ3W4(.%{Ѵw)w93mPڸWEܝ{sec@h'"V}w=۠IrdhWeǷ x^A]=Őyv=@V mE>PWg&|!ZrY.ol:aP j(j * ^Mङ.Wr@ ?daF{pSjXjmj@Ȣck?udsyQeG-X@)g--xM_wA TOA /kXetWmUW;a퐱-quIYW6/U5_HtU)6}vU6Ԓ#-"4@RJRq?7yuZlxb8}XژSǖ8P-zCƁĽ=|[" d89:H$B{܎ x1Aan:9K/s;6Ka&}7Z-&F(:.x\(EoDDMr`|?@}}M4N~iMx<O uK0ڶDfYELTAu'^J̓/rE7w>߱/D߾Ns:aӋ9Ϟ V M_`5j+ymB8>AG^ss,JKՔJ]rݺffw Z9]0T}yo[޸@ +iv>svqs2peȁOBƃ fkD`p-J @|TjPT$"(08){7TC 5*u̬*@ '$I@P̱us[Kl[ЖR3p?4IٱǮ'{mRYd)"IR&*`[*KCy41[3+Y2b1-m\=@ `x;EPe8A[3S>.pT%IVMU*MK!әJ-n+`Жņ_ʻX",bPX' @ BOrr2A0l@vI{6ɮuv0>%-j Uk஡P3Y%4Nj|+hab,֠ ۟GO.}Z @ Asf W7b`E,!Ya?^p7F5X$f-5ɡҦ, \e{[ʚE %zSg$XrH@߆Wk= y~6=׼k= ٻ~2Ekbz9ͱtN̝,.-Yl7hi^9 Ri䣲RZ+D8:LZ:4 1Aݡ@ *"¬sdt'AZ}2vx"5jA_qeC*ڎXJUU?*(VEm !ŤMWӵJuWե1zԓBBd F49mu&l n˺mJWoo{bsKW˓KA,:HoM]kwڽK Iu]69).*4ͅJj uZƽ`q r] Lp2]ITjHi,'a9kXGYLVޠӪgc|heDf9M@AQ 6,}=EIO~فPHQ)ң\Сl[ϊ4%i#@Ĭ &qc~/_AZEw̋h`]!+BӅZE7QmR#^iK#¥,N-Gi{|ʝ[톬7_h3n?^ۡ+.g̿<;tӻփeMuY7;/~&~B}Yi Kqw.σ<̋ݱ7efh@6{B *@^#Z:a6]4m/)_jX;뎘D^sU}2Jcnڢ 0 ㋝|; gnI:!*$rt{O ߮vs;F 遵GE$t:-7 89hYjy4G]mgP=k.Mv+ifzA~X!u8PˏVĮ!m)Km=e(dZu܉\NxYzmPhPk3>4IPmJA+DAbߠo];O35eWD+oƤcprfa:bc#'h|tݱDmcEgVyc3 (zs4͸Ag7K96oذ 8דOh@uAddΦ[_6_V!#쾞_ɭ͸ h!Ş-sWYpN%_a^b_xm~%hWcĻoۓEϯQ t0 .,7~;i]HmF늎Anrt]i|W15]·e۷_H](]y11i̾86 {r%ѻY GW،)}FҁLc,3o9*z_QgɊ-uy~ppF3G4_ͫ]`8r{4 ңNΉW@9x}';vc+n,  eR`Q0Ȣgp@2%+.(t;cB=(0ڔG0GZN~qJ8֬S>iS^|M+V;B svxa$@*3rYz"ῄ$bЄ+>t~- ^~\A3l )hZ^4CٷA޽%aw r?dYM@ExAꟳ74.a R $=a" r\d(j>wIT~gz$˟1`-wk@ &kS||[/˾Pf$"IKq(jHy%GFK;rI4]Ɇ^,vzJߝ{4Xessw<=zpځOkɀ][sB<2H T8"HMAPEUҫ>.?k(ȷK=X9 J:C Nŝ~UmsuMe#"qU}fF0. _Sz<^j*IdMڤCO;wT|TGkz{;[Z$PpWEZ &+|pqDbEUjbL!5%A{Hm"#忊X.i\U,FcDՀ9Q;$. L9%ߜCWܺvn]2l;{Yu߭H˫W'e2F+h׬;v/{bҞS%Ӛx<@2p`a ]wb녭:O/>?wH#;<{*X1Oh: '7UET1H{7]X˼$Ei}B*nFUj 9V (]dCIsv^VxPlWYCDT'm!I5kqqm)օB!Յf9aϷ/!GVXXbm˾ @T0aT*J2??.ew ZB ];e0Ϲۗcc`@ |!! f~~nM[$ ˽YӉ,b,*q16.Ǥ6|.("15IdBsn:-kd:W*SQ:R=LCd+daMB*A @2aϋpkr+NgMO5UYsQ,g/(`<,PT&R[tHÔɮ!nc㳴D&_X7)E@ D U.E{AVp%ͽ!L|e:ˊӹ&&9&i!ms9P_햎ٶu.C@-eJkN{sip@ )Hf,ɩL4${ |8Zxa,Z̬$#QZ3!Mg9[vX6m!KYu4S%,5~IY@?@ yszEXN޽-C[d% 8/0Zm]v1!S .KSL2TXƥVn!Q`)?˸Й:&0uZ@ @Xat EfoJҞΒ_>^+`zfkLEVKfZW3ɰ3\sٞuMa4"LRgou1io@ fLS9sS^&%Y-YK3[{\Ҧi͙$q `f+7{rRZNI S (@ PE 54; 0_NLMda!2/] lo;!C&X#UIE=!+o4U#&5ILZ@.Ҫ=[ՃBi`-Wި˨D^[x/sw~~BiРǟ\" N0ҧii[kwYxvِ )#VER.ֶ)]!fK֤\Z7& B8` ҵ{ЙJ$u]ye~L`.,0]Cw鐩r)'d)3˥6$MD${zHL^ Tm(iI;"P$Q6,}=EIO~فPHQE@gUGn奝mo_jWG~ŸϩO:ZWUjuHSš62]nS;}70]ψ 7.}ֹ3}:D8YӦ\ tl[xXVudzIqg1<#EIf(mݷ̺\-$^2l% IDAT@1oTx&`XEWs6ϾÑ /E}6/KT9;}4 g26'XJuEyc94ۻhR L&Ui}?aw,mV֫44m\d퀚O mLnvKf[nh[hrYPD@T21-r/_s돿ݐu2gչS_H@Gq"w6. l(v(98{zuwC&}|!x:lx;.b<cZ|j(dvR5]9J.N5tYfL'/{_؉~x9ŝsc mw̒^g`|oA!L[^@ě23\ p =`&Mҙ Q!{Jv;ƨ7ZO}>r."̧5mMũAFhW+Λ98P8B0j aRͦ9Ve)ՠ,m>Փ9K5~.tQh, XZI{]䓪!$9VV { Q;ŔS!6d*ʨ@|ůoƤ7h[rLZ7^9v?3$cfGJ`t`oyDֵmǚ^WT=@6Df>|ypT5=I>cRTQ(= Jk*dSkGzƄ5]Q?"ro0yԜ.5 $b@ޕ 0K.ފy?RN]R{O 'W'TTOVǜwh7v>a(;w\2m#_!`9[I*&"HWhNo1Z'WVu{'}|| ݂/|ivsXr 4Y@j_j/(IAn0*(2aiG1\jIR2CO,hH KK"M8>~ⓋN'2-|{[XMbtV$C; g*e% LC㨹kH+@}&mi0jE-2vbLQY, ZM 0<#`,HXL'܇jPD[`.&nv0YN:En"_pp(y2׹<;iqn,\tnk|myU=:  gwq,wVdp\ Ǖiwz* ][kS͵f߯ei˘X&W8{6r˷/"ܛ{6|~ZJmzCNug\uBw;|ո>f_}ݤƤ~-[k1BHMAPEkJIxR{"PT--UB&kM;Sm".e?~\CUNydҖpIgZ ,9 Y!8k1yԚ%3}S?\0x>47\*w.Qhza_v:r.G @р\"H {Ϻ,`|,J'L ثOrHJȺ= .w f^V홄(k1Zo3OL46V_/l%I?; |sosbѹm ŇidgO+ Yg9S#w._,nS3sLJ 2&P/X2Y+DsCB&L~EsXQ3 1mi?i&i;;;ʩC$ ]NoݺF)(p1D"c ТC|.2/!-*LĂ iLvj\0@ǁ@PDk^ #C`6'qǵZRT*/]H'3Qc 22:U 1t?6|@ v`si UYd(c矶B@k}L Dy 5ֹ@@x"S8ij_I<+4^ĔÔiV1.EPKpqWKQ-nr x&bhD5k!D}s[-{*z@ (TX,!:֩dQ{aEP҈]@غud!0}d-cd&mN; LX:L58~LlhRd}C r#[x?&_PwT,~Ey[} EA L&ɛ46K@9KTԲ&1-`#X:"wfŬ0E=hCifb@pIPy@ fJc,3Z'd eJs, -hp[CPViY5, ܰ kCVL_$ID"NgnYjUdv. !ar0d:6@ lEF DUP;i9V&P/hJ7rZ-wZ 2,?G!ڑ*g?.\K:N޵ձ! J`LRC&:M#@ >(*~mQ:`Bg~8Ձ cS@;쾜Y= @R MCCKPBPvtL^?ԀI&j1H_w/^{~uT**;,'ˈ0cR!7jsԵSL@ ԏu%䆢w Q-`'aiR6o5̉3-hϵԣN5,6lsuU~8¤9no1 PKM>,w7>b\d88B^]mp!@2ubq. ^CX @ UyaUZ ć'8!ARmGz@"oB8d⚋$Í}ƫ@+dqs-MN4cmaKqӈ,:=mNSmm|uYM !5sOlФ\Z7& B8`'E{2 ҵ{ЙHu]ye>`vRkDj!{%AmYbehe5(IiŘ2aY_ΤlBM5ET_)`r/MԠ,Ua{BfSsk21Ovh@ovjUzhphQ6,}=EIO~فPHQ_C1!,Y6q)M7_T%?P<~ՑEyi'uyקRT=4'4!_TKvrׯ7r {=7s[xXVudzIqgp_mݷ̺\-$^2l@1oTx&`XEWs6ϾÑ /E}6/KT1wX_Lr̦3Y2)iӽ,9i. mYPI Gͩ5m,C7aO{hzo4N`b Z MY b pi)alskVBYGкQ`ƴ=|έ?vCMdtY1{|բ ~=(7ˣ/SREě23\ p =`U3nueR;gwONbo7N0~ira_u+Ϛaf?s~^26ύ2E53KV |oA!L[^m|5Ig6DDn)8~n#hP>=92Sܶf6A>M9 ]:o@Ȣ ¼[$ ~Fs01rt36-vY,*-jhiѦY|6K%ưuATaZTbꦱ}=bZAX4&w Pý 69X.@?7cR4?yi춰m_5l2A,0`ޥ, @TG#4?5f܋UoEŞ-sgq\T_nɭ})ਐkzn͖knVMӑlSuG7=::ؕeY#CB( 7{Ol}Rtaaq{Me"+:Ɨ,~siP mY*R$.- D?bb4}?qlkJwcϵ-63õ9L燕_v_0LA9nDCsT^^P,+ЩzϹ6nelRW(Vv6[$$E+YD)d)[IH{&al3f?9l1|=s|sm wsm@Q(bo-hT}D%.Ƨd'f iR}!7ȡ%$N0i`*/@AAJ!/Xf^٥^8}>wo\: !Gz]*P_:rn7 IeAL-}{\ ddzԨӊ[<[I=^];-X4>5^Y2׫[D|iǓ~|3<Ugx Ϲ-=蔘חOX5&o&uݷUZX{k9EH.;L7΁x{#!!uoV s>U{7w1c[tTDŽtTQ_κ.nqf#`~.T委z~Ѵ( \i#ʙ/~(b-`^RfOq$c˔ \I PczMӌ>9ܴ|]"3S`,枂 Sq $5M0KB$ <"*(((Z@(t⭎wVں~M41g?NhZ\gP>_ա=߭_zQ|Qf,_y33-16]|de*fGZ\No| +Yr>{,w^ݦZj]$ ²H@YF% n4-S@Ke&&mfg#O堒E&NoYŨ'J3 \6n{ʌ$ 3AT3IerFʈ0 @ ' O`;D%G̘ P W Z|ΏT9]\ͻe]-[h߳Vq?ze˖-W+>Z^guG~g4l_V44l@jʹw=hz (ۤiדpZuŻy㸟R:vg\BBBBbҕ<ֳXSEJ ܖ|q`5*ٽŬ ] -X>nYQ].;RY$t;([. qB +T=[4CQ҂-K S(2SXJ)B-,H z"kyވ€dd q.zDY%7 [wn: >H" ru_9r+$MTD@AȢf#.| S/$L3W7ĞBV쾏/\pp߾}4Ag/6:RVP[?.? d_:iZ̀np/t蹇~qWM_ Y uhæ)r<3{WǷ>p]:>Xmz#.Z2gIw(vc;MQ8-F)+gm?b! \.*VqFWh}ߚ7IɄ=P]sO\;=MRzn\?cOxsIQ Uʞ}¥ˬX>r0 w%o{J@L6$Sd3Brqru$7Rr0ES X^Q!.dgjLHSz"c%bC\Zfg/X:dȞov4B!Bw]} A]EOOxiux=Y!I9P,)NݓV[ٞ?ם=@s@XltLlmʺd`9_D!yNO6Z;0HXhf^bl}A57{Bb% ,OH'%A>ɇRs c>0 /`fN:;'$"]܈U6#7i{Z{]U|($1'RL/ a;Ju]4%ꋨ&GF9$) A>>Ҥo))cMI9Z*/Vk(nT3 PPPPPPPPPPdSPv*/b, =H$%4 /a{t0) Yu um)do,ɕwB^NA:p тɡitl"`("'r?vxTSf "Sd"ɟ'ەqT& ?`mEq{.^RwI,diz1|-ZpM OW@ <(GS璝PwQ>e:k>'v P^ * 1)7 ^UL"μ#EMͳP9Ӑ$jDD~8r7i".ᗃWn4 /@21X6CهROTZLUAdo\ohrX[ ԡԑ b3E=4MZpROd-wE> . N(+Q]=`!|jXȨȪ"-(µ-/KUnxn4wU_mQ.\ W<jH6G+lV"yESLWSՈ(ۑrm-)%)bP}Jfvp8v{TTp8QQQl\6f7bBKi$@6Mҕl[%6Yav6qY(oLxqn(((\VR gjpA8k`-| N8B2{>s!TS~7O$sW!TKl<ϓ4Ȋݛ@Ŷ ^ϡ}oPFON< ={bjRݐٛ,tWO7A(^ÝҶԺ Bzawd䭟})kQ!Tq5^Rgm[uQ&ٽǼ$T,@>giCQI&Ft҂Ղ[& H9ٞ%MSprC\aE1΃Q&א?ԑU XͲƔ] X2CFd@eYBJ!0\&rDke -'~)dY3m¿UH@ {n/:Wwh X}wYgkd̳&~̬^){]:o8y'͚k:w qv6'[mhϑy=ҳ3-{Qx[`0w-}+k#uB^~[Mg4ܭ{sY.9|˟ QLtz<{{=E0ncz}|Q x6[{N NENYz ΒQ$ <):䔟*-*ȅgmQf\8؀[ä(PohẬqȞqj:E\EN'&F83LzQA|9F|JD~kj3=庛}Ob g;$:FoTr,6 1IvPPPP(ec㋗v8 fL?ܔz'cza*Ve6eOjQ 3w̝i4C-vg|/;j66/muV{X{>pʱޯ=uGI-jC̙B(:s j(nC*>?Kƭi1S&Y & 7rRdWSFn٤rEDG~JnK9ihA#})nIH-o3BDqyfd+R_ '`!ӻTr5’s#5$. `c"|&m5!dFB"/ysʾR*3l{J7dݷWIbֲt/7pgqS o2W \aǷ̈I2睝~R'ʑ:m=gEp2MO׉޵轏\2ӧʴ~OQ@n}3\ΐ/3x򬏒,ƢPя<00nv71$sngϽG6/# i[}۴$?qW?,nQ<9|ik˛b #e@\=OQ͑U{iݻzJ=fL3W65=aǬ!3~=cᗆ>Y'(ۍL0T g+%JWf #bFx(hAtXy,]"!eC|10>'l!y"^,W4N 7Z`XV5 \yy{oe". vB jgsp-C)BäLCU:J׿-(}ǃ1/*,ROe g/%rŪ#:$+崀fOw[ܮEn>=b鹇3+I@ .`%KӜG&_Dh Bi|5k}@Ήo-hg넇_so5vLzWsF_Kݚ"S æ[xg4ػh⌤^Uq\U3?vgܱhLo{{M'>X7#S{•X"HaG5=F B:;\+{iOdn_r,;҃YeV,wEFq3c$/e',U"z`1٫cD l҅> :AUn1$ fʺC$d{=<QNu<\Enٌ] $$$P6)@:5", .lc< QF6>~VOp#Jl *%)(((.tх'=XӒVgBe}?lg''|5f1 L2kvnmK~u+r˹hK5z^YWb/aݥ\ju/Uu/9xir}!kҤmT_3i'v?0mNd)ٓǴv޷t5Z18U+=n{7mRyQ:[I W (S>d|&=Ξ?i4[S?IԚ㷶dUܯcgCnj_:J㿩;rv '@[ah|t;⮿\:BLw-3-,b&xyLJJRZHj̨pGr"-(+[ɖ唞]*x9͛)H pafA.ԨQ ٌL%T'vr={ܹs999Ŋ3t8qb̞rk"ŒɯR~p88 6111v|>_NNNfffzzzFFFfffvvvnnrǗ@(kFt]SN~-f2ɰnvgee_[sP&ع\ = ,~U b^zum4X7=J$Sl`! vysDn$ـHWtzp#hAHmlψpRH.j) %)FmF@_YY'>(1_Ɇ X-0YzTT(/ %(woL R<<e F Tod&$#KW ) 7X@^p'Db&x#kA.UfXDeTn#3W/3RA8#M- P˼#^l.OJbLjw@|/$wᮢ~`*M$2˛I~!&:1'a Df/٠X@Q& t "6VPPPPPPP0ȱQhg/TyLhv*-$wQ!T<_D/H ,H5`so$񢛼*:TrFH#]x kd\2X.^42 ҅#111~ZWo2W>(ڟ-}"oL*H~Պd% @y!*PaoZ jBAAAANF _hJMD.*?*- Wx }} /՞?b |OY Qg-"` xO'(q޳t466"-&rrm.q "&H$Hv gD Q nEAAAAAAhB0\ki4U!9:2?{k*G[6X`ք\NEɲ$ t^fq)A"p eǻn# ^R0{*y:)<7 5ѯ="T  7p`'ak"Χ)GK3[0dd ҂UyeDlef"Lnɔ~RLb`UDY+yz"aa'P{  $$$dggmA(7(`@`51KbFBW*Ö'ʡP4! ؘSvD[SFrdׂ# b֋JhYaqܱ90;ިQr `G *5AF[zz1 㖲kL3.x װZƂsPP(Y럭3j Bg-gSAc DHѢNe>瞲݊*r8?"bOFDvo6q zMSnc- @ȣK kS͆"cC4LnK#W$$?UvrANdf^m9CA!zC ؘ} _޳܌B1; L}ߌzB/x=8>5A0Pӳ7 nMG1nP][@ږ9ZWAUo?l`ݾuS(o@lպmq=/wjK.K 3KU@[>;6cF>fz3W佬x֐|kv;8uPP`2}◛R!@֑5&.[Y`zޥRՖ4-xάܜx?+k ˨GǺ{񻷎ei>_%{m!{zꮒw/p~W0Ӗ5XN%h[׏2eϷ]rz?>h3xßx|mz|Y g IDAT:a'#j3{ţl,ѝ*;"" SL[$3c`HvNU oFf3"[Dyی]7\Ifm%$T@ Pө2`Xk+effz^#PqɵC!0)Jv)Ͽp-f(h kw~ھ-a+Ϟѵ]8Okw ?m;uD~((E?^ A/5V(猉/^lR5K@O6VcQu%L0Y6VѥsNtӼE`ƎY4xM 5X]=EWg;2hX 6[RN#dr_5X5}mQ}:+=Kf=p^8XמWe|!r9j!gzON%ִݩu 0F:MyES%hˏ\"nX-dR"s$/k|̽Q* ?xxD9Oֹ)0BP)S|w111K._|A]Jr/\ D=[eV/Ph^kw={ɓw?~QP :w[kV}$=fl[0;KAt?nJQi{iu?{^@QO߹7-|̈́wZn3 eI[Oy@ơ]g5m {zu-۶ikGvy뚦G-fSFb5 (₨-GDF:*S⡼eB!\o ꂄn%emij .zf%ݔpe@(#;_}R>/U.gj@ w m';lc:WP( ;__maܣS~kIٶ`xgX>؀+;'fYBvQ3#vB6| .C`(ew[e[QKʕ%'*WNxKU*yߜ (tׁE#*(HH|=euf,?ô͞P!x9#qBRx?}Cz0[w\J"k5{bq8\HLphTEBLKL !G|O؅̋鼺+ʖ>+(-V,+[lMr2[FMw_wuWz&pËo\˲Q]덜;)-;䱞-75$l%ԏ޽ů'zS[xUR:%g`5*ٽOl lфqZvaߑrj&YhFr|HɹY/vsk'Wf`f% /R[0#"PVN')KGJRQQÁcFFE8.nǝ\su ׀\@0Jc+((\]GV]y72O`O[{*)@`+ Nܷo߾}WcG7+B0}_w%pyr |F k}>S}<^s:vzuT߯2e̡G<ߗ.Nrk|j6T, PBnHv0i1=A<{l: yR6|2a}~DWܿNs轔Ϩ+\`E#kBvpc2+nxT鐯5H@ O6NHlȣO0FVC,lD\ %Sn /Hr9L*l.Ll6Mӌt]> o7ܒ⽅Wټ>3y*ۃD ވ(+}taIu>֔{džɚD/֜3B KT|R, 1脤8AFo׾_%w;I} gV;`Og,:.l=;Ou#4PToDAœ;uHMjSCq -';mw61vHw]QMחO~&+j=~|>n8fw%P9-F 0c>m:vW3t-!<;vڶssr+:r 2dɒJ fTQftr6WE<֘J5ܛu7v8QQQhۍ(s9\.x<|>#9ȕ 3)؜+z<<vJ㥜J|qzNt<=92ʖ-ʣpq_7n۝o^H=1c箮O?s9RPPPP׫+oib%Js("8QLqEV;h,4@Z!:umx}Hn%%*%TQ6؁3W)y ))$ߢc-@jB!P0lFV' up$ܞٟL?H ~t1@7/sX i"zIjH% `O5"QENa9 Q #b}쀤6pl6@ `Hr|H̓RLt@B ?6#٭9fxdYnxf 0ɸ.A3^ @8dQ~H)r\F$ KB(WlCbGRx9b|>Al":N_};cό briRL (<:b6*(pC7K ]_^&,/'Rgť p5/yܫ\e 1: zDPsQ`bdPM'r -d8Pߥ? >3Vk. K7ɟ[* @ZXAFdH`%T!`rw~|(|"#R"XQxyWT9^"_) bbtTĽ zw1]׍F*iG5`X0Q3I@mKyD #(#@쏈Y au@.E1ɬIS^ML+WO Vx{JN21Hf:̽>fGpoRP֐7ʵ(nG Z,=o?Gd,,K042[V=ZsY]qon"*Ks$w^PGޛI k{jaGK(W0`&=NI%?C1:.)x)._Bx83s'$ԉp?Cަ꼯Q+j(EHIx HyۏArD`}MPPPPPP3r߭W~EQLP!"h)R-Čy$ f`J $-䴤3,@i/POdCXoXYO]"P#Fi`0 oٷl5B fv֌\c˟%yb@.7BksPP0/ۿcO<B!Te'y,B%=9go@*j2{ӹk"WO|Q Bwzo'eΠUB##w/e~-J#?9CB@lպmq=/w☷OdG3fifø&zk!zH*V |M\ <z "RJ9 `lG 4@~z^x^~?Q,6 w!y/pOb.f}J#k SPPPel>M)@ ȚiB WLÎLnv-JDO-cr!;š]k2LɈ^bic<?ǭotʎBbI:P|K;5t"]. o4KYsHZ@&L LS3$Zk(;0W^̓aidH4# <u\n*;# >n 0%u+i?i|^!yu(;x@á,ƆTP@AA@Klا_o';o['nordF%B7A=g\rWy|aok~{~WM-ҜEEU׬TisiW zOFnTHK*[ND (tac҆OHVr3vznJ=`0QŪI-ʙz掹3-u`%4b@/P߉U׶շyh½G޳d~S~;J:lqUZfάB!יcPFqrW xY2nMѝ\a_^rDT>EF3{V[ grͨ@Oj^ +XYH U`؊5qjF6I(I.* C; p: 윜E& Jnٴ|P&r˳ DuEuN$sdKSPPP0RboYRS}g=/,7 Z5m(bkgr2wL7{>U-^,=s+^ӟhQE |)֜]GO7A6?xO9j؍;B(~w dĚn, w)Fw5(Ua{M֋1Kblzʣ2:[Qhcne/Ue۶>-bNy6$WS"t|\%꺋Pw$<  YUd'T?:oAoL-̐ \J~1+V"zal#@ In'/"d$JAAAH<9e_{ԁuKg}Qʀ]މI7HGNM|g{hIMױkדTP($g~=k~ɜk;{OzlYY2ӎ'(yo, %jwC<|;j||dRڴmZşr(^Y!_FuF9oSTs$$uݛ1q%*!\OG՞wfRw̵MGMO1kȌ_XoyO։/rvoG6X(U7@WLZDSԂb!cd';DNWqȭAnRA!}!QY 7Ƒj뺦i@|Gm8`P+2p@tt8Cr8Ap~q. A|HGp(DIMF6~ nP`U#N?AU†w[e[QK]ϟ̼塒vOtgeԦSMt\?xã^4{MpϷ`мn_ա=߭_zQ܀@eBbC@v/offZbbm9!7de*fGZ\No| +Yr>{,w^ݦZj]gěĔײ-"D@aۍd{h (~nr  [p%ANgTT(/©,IfW)_Ƨhe r\On274 WZ|ΏTq.D,|Z82M&MueO#kO+#DߥpVA<3yFMZ: gQ]덜;)ٝq JWnXϖ_r[X\yJ֩{iqMپ+noR:%gEGoԨ\&V[f֓?=?kWAE-kYR0;L׫rL ^0IpcfMD@r H4)˵DJܧS\ 0)Q^]q, ''Lj2=]cccNa.ȳ% P\8HHS%]` `:wXPbb WzUsy>] )WHyӏ<[Fo[͞OF>7{_3`Dhܧ#_z{VzMSP ~_0^ jIz ̞`ȓq?ݥsKnY &9XǎuxNeCۏXy/]\.*vo(J߭w2/4-fS"3Bg[֜Mg!OʆO&o26jW|`nңwbrśK_hdMR.=ul_fqEs2򒞿 !5`΢h'H׷\EGBK_^"CL 0IQVآg#J8`äF Cnp`?% #4xӉISUT` 0k.:BdʆEN| IDATRQ%YO\0/CAAA.>i gS}ETdސ%?4`&G՜?.ANܱÒO_!$z+\?}naQUb^/µ&O* VKtS{y&.-b(rWn7G\:mRiX,] [I 4"`)U{2j+纳f+awO$bRV (ZϹ_|U5ݼKGޕt 'Њ1&wyCyǾ|G\_  :;vwDz 6h;Ysrݣΰ+ Z@8*51}:55ㄵ{I+ING)!U*5tp( 014/[6 7,_I@ZORPKi`X4N5K μ*p%T>IT V R~JIK  |bBIFb( 3~.jyƋev{*FL~;ĩSΟ?v!ށ*mLPMj ]l6p"}i^anr ~%lRT8F (, +((((((((I7!g&iLB؍иڦ@nN}dѯ-GJV".\)!/: qBxkr!R#Q *t 9ŖYP!2G `jj%>P>(?> ğ (J pQ8sLjj*Py&}UIHxQPGqWSF#`,**tt+$DQT kL!t==c]_Pn3!гr!{' V G,ED\Z 5o#t̜1$"55tLy`uaNu\(EJ~*%Q (b X\M~"Pϥ6$C((@DASSS322X@ p!SGXt& $톀!džD_<c8p8=Hly[*pàG/SoU!JjĀ%{/xJbiS_.}k[.S ?ݥW|O.B׮!T y5\6l̙3K,i9oPno];{ʶK`@׬Z Ggg|Q6HIBRwu ퟏ^;3'̙=?\7(ֵw-U˛3׾6,=5뱲c]ƶN4~c6lo3ALaFнgmɪS$;:0gDw|+,wf9C%4˦h6hc27OŘwjnQ;ڬ )߾X5>c_f-hW¯_]FAž,e&x M~Ho`?%zgr|}h!Q"8ԈJH9s"FWr`101 rE1"""l!^.z9Yz\ܜ쬬,rnظl~; ٹ^_@Dp!A^ #,nvvvIscZFF>A."BAA۷}4f7ْusϾVۉsj#b:S׽%Bj?b~[]㾙=]?PjuƟ@_36A53mCJ~ pxRM!t׳nI p%{Ke).7_|v5G=(!tsfn8 {BUhOw?-~[5kϛwr킿о^ykT.MV}ᛣ^7u \rHKj13tonNls}|3CRֳo<3"*̚逞i8/ 6v79S3K&3&L`b=yL3?Oy7^\4{қSy`[ssShxC-oPC1C[[]F](Ղo Qhb2IfL5b-bQBW-(fjA@j8L> dWJ@&2 O$oқ\/4\b 4 jcq`YL$,/jt6>MA^zfS.zw` qVdJ+,ӉydBч.kǏ[Sr%cFջ:n.DH|x8atz&*c=?|vUZs]d kUgsCk~wNe}F?U>\<=i&܃6 ԝܻ}uEqwpGQXK]QX5Qc$ԯ,! #;?֛.g:qunnvvfcgޙ6—-?On1EL=m7o6cc[Ս< mmV<)vMWxOT'ZL413׿dX^l¥⯀;`T 'H/!$_ߜ%k}o9c\߿{ч\^Ypa==7jy JO3z.8;2@rpOւ\9IA6 0ef*]~.[ @,0 #6 Ƙu,1mvd8&&IOol62- @o/h9FA2M1 I-@pƘFcqf?"`g?|-跀V2Zت ǁF}P:*TOj[.>>^9G#.{x @pMW"A_YˌR<ң{wҁ`Z'|5P}s"ýmur846~ZD\ݵ1߱Oּ]+0@Et˰P}züm8?U+$>f۬G9ubgN?qdk7(@*m_ʺ6['\㓗 PlJm\ĭs)ϮM4v8fmVD9@GGF_Z\g_>ִE2odewTߤ'[/ x1$b`hd̆q}XNsiFC~aAP sf y0Kvvxy 7biO˯&w^u1W781u23#wO5%/bॻP힓fkyש%" $S?V O@5,`:OB`h:dKLXq󜊩HSaHĽBK>jt"Qtx$7F/`Fq>1W$U쬞*Ul6L2] ЍOY!R"۟^Cd=D zM~~>iFq݇ KY XFBū ^BB?2`I.~=vKsڵ.e_Qȴ0ۓg͚*䑛gu̼Ѱ}>diUz IxsKGNX9 [ɰD R yX \;hKB̓Kϙ*+3B$֒c_aaņ9"޹k}ϺaD?crf/C/`{z>>(oD+vݾp'׫kAǍp8]C 9bR*%Ξ13 # iPÓW &λq2?]hJ RÎίRHJ۴Q4ߌj E|rsy>Ξ /'NJ[@F۽6h:irv{ڙ WF7.錞:ۣcb`ZI3|/{Ji/|⿗ (_#rf:]PrfEvD'[ k2>t-h! M7" U L2/r]$ʖM$AT` 0)?BajR~%șb@$"^asl_G0B 1 a4%3,Pt1F9KS,c,lr/΃ +xѠ QDWQ!{@KA>2Q|].qܾa`gݻǪ{F>$(YS &}ށ"}6f' l5V!C2Şm TQέcܻsÁݖL[sf`.Mşln~59m·MFB=˨ЭuE/b!GTC7nf^-@pøÅĥD}֌+?a;V]&nYqQ; hk`aԹC[W HN(b-'˗#Ѓ]>Z?O>co5Jhqx7wHKJJW_'جoalg6j$<6vzʈ]Kg-; }4m˯[73[}]xz0Ĥ3EqxMvq^OgeȘW/(8S8Zh'#G!2S̈́[$ĩ t%)dMA"(M ȘRJZ^HD8 XPqNB>"gQt`XOD9@/~_ Je3P?77Wcz75hv`ͭ= 6oPB2a4Zfg6>Ԑnv97Cz+\C =xd> ELr|OU1fO>{$m¶ g\8,OW[,,<1'E@E~y]דj\/[[˧.Ҏmi۴J7umY*$?5d~i²u~к}bͼgNپ؊Yk5r$$pr#cȏ6Wׂzj[܊@{@7*xk;w ]Lwwl:/Ѵmj1jl+{qWٟDLWި}懱Q ].-U" SΏ~eU<* ɏ rd,[: ]PPz-aт Sp2 2bZ0w1a*N(mҴԢhOUh^ IDAT g2Oo'œ[pfqb!5gҌhZ7s!pD4@E)愴"`9)^-ZM#~$ Ai[v.9+'0ZĔz^8A\D9ŕˠB$ʖ-;rH@Xu/??MN;idm/$ /ezu:k_8 R`ʩ󞫗Z9W&wԽO"|' 3^L(rت- iǶT޿%Qo_vE^QE&4:ĶS:V\^?2T0\hV : fШIm}P5w7ºNhƄf1'hrmmݷgEV6V)ۣǷ/cӭ'ԙU= @v ^ѽl]Z(+3wVc|5Ia8{򏗯\eX !nS=:= -r|ݱA):"3xgG+VԂ35`N@>ka0įA/`0ĩ a6ȷBo[رcre,s2H&f^BGi9xGM4LrE?ɍ\nZ7ߤg^LSI3U L Db?NwN'@\/ }↝U ΫPw59Z@VVWN>H/Pjt^}RB fJL]3b4ڢ~~Z AEˀGQz#h3҂F @kiA~5dhșh: !& qӕd(L>2a:oԂ)-e0DwƱY\qs]etJW_i5{ c :^*&gL)Bh֖[. bM6:svv twv4=,87T-/HX^a:$vjAڍ8?ykb \ *TPB .i45#?ӣj9.M"4g{YiZ")pc!ˑ[R-h)q-*(IB7&CXHp~Xc8vP\CNS6S;̉@*G2Ԏy%}I:VE?BݯKzNm9-)\ $c,ֈ|8S0R}L /<߼*TPB *^ `mc@\#8]זd Cӭ8ɃdJbcAWAp (Irfj!FDrt$LdY4<Dlr༒"(u (\@)d%W`$$)0dէ1=(%ۿ@(WMFld\qC5,IUR*TPB *^1!.X 0<+BfG@j 2kI-!q*B ďeʔ^ZV*XShu:$Cq5-tZmVVC$#1x+ KBpa{?_1:xr+ڈؾ$âiӓGh=E%r݃nnn"7fÇ: 7 lHW^^ڹMI;o(˜ A *PB *TfM"#HtgHH@Q_ s rM D+LE Ǫ{ cWpz!)]S$-TbBHdrƘ<_NôA*mbZ`Lɔ4 _P^WЙ3 6WQj5KU6:CҶv s'kԈ#0t9/'9E@},`e&WEIX*F1N[nۙމ1d0FQ\92L p 7>VܫJAApމi%aIi9@r*@*TPB *T0=q_C9邂q.=EԆ"d9;4 իPSj4!d&6!$,[y4M)ևdF& Q('R;8%i;GGYadd ƴsVP0\oa&C݆‘)dTP7+OmÏnjB#HJ[ۃOzό]ޖ *TPƊ 5;;Cʁ>s>|>[Lz$sfVS8rՔχOpjm> zJXE@g;F|&-iDJoZs νḮ#*Ӹ=?>'-|”5BJIϧ@x-{7 D!l7y_5J!ڸ/l /ME!2,}Nl7VSҤ=W2!YE=f합ν}lFJ'l=р얉]j"PSݵ؞W!1iϹzooО{Zu`Kp SU #ʌytQ28r]q)qFn7]0[R*M̒GW$[HJIyi 9Kat iIۀsE4-/XC(H(ZRAcEM +FzK ouY >% _ʿڢu'G@؞|bוFe׌2$9/=羭eL|g̫7 s`u|.,ԿuOV0 w~Zs+godn[3˽;eW=ȕm.Ihs@ gznju?l>]GT,c}t tfBY-O)uT,x'}BBZ,Q]ԢA'5ۛugz{N&Z4ăPM2X$ 8HOE Ir%3s撔&*՗w~kJjDLx n44 MY_wOR'89Olf:ץɕʌ~KT+O.%_5!tK``0^`g'8T/ӆq @D0J *^Y <ڵk$;|K 9t7>끁pݨU?2'緍nP>X0yP+&y)Ǎ(B{S-6G}_oΤRalE#Bh<2sz-8p=K":xב˞<ɃTw$/7lש9w?QZ !Pww\|jȿB=6\ث:Bndˋ޻kfM@{gפ/B>uǥgvݓӧ6 D7='NY\֫Bͣ/+<p]vڵyrâGt*[ŝ3ޫ i3&!d%R!P#7%? ȣEVZjUܢ@=x"З~PZG+6kஸ3[sOgHI˲=vaM9nnL'~à+ug{⢻+܎/o5vD/ڴo97O<쫻}~|fDMlQ'n*Ԟ}ްp݋j$,$lN^EFݲt[#-~-o휾tLoѣ'jFlO___/XB5.[3H mSYWDO|$IщqF\DIJQloAվ3r.:pk;|ِY-/-1mL벎A3Z%9:7|.t_͜ܧMHwȋXvհ#b UQH֥SN`n@/%Ycs&/90]C*m6=9ozxd؆a?}`Vi7З{o쎲[Ս< mmV<)vMWxOT'ZL413׿dXB!‡z\ZPwvCz G_;~#Ω͋)^S֏?W2l=]c<;NO;iEq~U7*Fme$$d_ lr>yiuwPNݹYao@z5kI馀 'CcޞF̜7{H@CA+Ou1\isۧ~lޅ=q8C6P71}%$aɤ[1ǮuKЃlxG5ѫSSt_yK:JOR c ^^3q%w$`PvmR 0Wxe8ؚjŶZfD]H1 |tssI>MrRh[御`)9/ْʏSB պnݺxT؜~BeBҒӲm(Ti¬9ܪEqi \='2V'Cc7|1rb׻T4"k޼ϐ.y80nJ nbv~#OkV̙-WD`Nپ,K惌 XpD?nmbqSGonØ! n[ݥ;9"uֺ/v 5"l/;Qb~\B}}`~]+hevsWMWŘz c6[&صu5̾[g%0{e{ն/ye]-G(Yr6.B)G'֮xAF4 p/K;ƭ]q>:2Q >Mmw*!ٮ's_;7Z0kA5SWFO/`kR {]Č_ha)`sZ@@x`q3gG'@=~.Y7 ifxLi z+Ԭ^rQ@^ r&s}c6IhŠ sD>s/[׮9u5 OL/{£)BayxziO?t8M)ǜ{?RoHlq8?o]))g~P:ޭ(Q yO -j䈢O+&omȵN9hM)qa\ t5\Is3s6]0j@Qew@c(k`uGny99V ؒ5jEڮ'—~ܓ錞:ۣcb`ZI3|/{Ji/7ox 塹$RǕW*3܏'v5Hg ;I•SSI[bzyBvj?HyydaBJb4 x)UpEA}77P3D[ www0fYv"8`gϞefffdZy7 l|}MtJ3$L*TP!d0Ν[0`ս-~5zRzlrӦ4!$'q8'Y;4 ȈJ.xt+ ,!"C2Uߺns{e/>I/^u:}>[t-`b,ofր`^2u)}bRߎN+kU:FÏ;JTAwp(@jiG(#Q,b% S}n2z[fjj*PLef'c[`+UTsk=Xp`%֜ذ0@.o= iLkἛw[}¯v+ESΣDu*¡Spi6YDxe-&>rSV̭d7nV4ZQ+=x=¨s?W HN(b-'˗#Ѓ]>Z?O>co5Jhqx7wHKJJWXFRpVi4Z0~kٷSFZ]:k9h8ki#X~%ڦ '~ !:/ q$OpћIdi{iZJ'3XK_4 ťc&*d/S$LZY$ϑ{2"xŸ A<ÒJQXarq pwwcj6&&b㣺 KU SF mv]~a.}݀V|y;Ϊl7riGX*\]j)ӯu, 1ujoګ#|vhژˮX*t1}k>VŘ}?Զ *&qR㰠"?]bni)Pd67]_N7*={n]ѓ#mi۴J7umYFf߽+ zŚlh՗wtG玬[_tO^ۨi<>WӯYa sFϩu­[*LYMn:2VZk-Hhŭ~104}Wa> CHt9屮輋OZ`gymo[TQc\{{ bjjCS.uxڬ;_'^28ǍS*G`ÅGЅP9hhȏ$1r/`'q e IƔ9}R7CHDIi%rԅv 5 u!`0~#ĒjCIzC-:e0vBV$)EReXPEK@9E^) X,"vVďwMKK-sSE(XD^V O*TxPlّ#G( Cp WJ6^~˖⿃R ߟ9t{ K_Wt-Y{YR]цSx8b6{LQ=ZU#z/RuuҫQe]s._j3ٖ0VxsU+ʄ.YD1$aҋiZ[5uzâ ZR%ԘN۲Ɓ7ĨFOD%ʵhy܄]:ށ"i&PˤQczlsd?'}c>oL1 Zzlp%iV2GTn3|hԤ k..3ouь c4bN*3ٙڎ<#oE#2䣳n-Ա>2t uUGP½Ft/[F:z% ժMPQI..t:yW:gЇh C&Bl6rsF;hMfJ^2){FxL&Snnnyyy&.3]N9H:B4L ƸA<}#<<]Yh.R;8//ٳgO))  R c/"yg̏ *T)r6? ]V\UPoBvaA;!n\$GZ.flsq }M=8/G'JIW[<+JՔ_L,kZ"@)nnnbxff l')yu%| !IBg3FT:'DъB'c}ȚZV777AL&SVVVVVVnnn~~>C/@!٢_pׁ$Di+&@Ԃ ɏrOvp$rN e D%M  %V*TP va. *Tx`mL];g"j) f8Kd=3(Q1[I7fcHThԔV2)x#)-.ND뉊X7$?T!YBɑFI"ʓCNefŀb!%sX,k f9777;;[Dw{Yѳ~tS39M%M gѹ1YI;H"S}W9E *TPB^B 1Va+3eW8ld}2,|͓ Sdp1թ3H3R<%???''';;[t&Ŵ#~|O.pN +\_#'D@4;%fYK\L3x w Z tcF[L@JXR`4~V`ڟPḟd~sHg *!PfMwOծXjF>y5 }v-wݳہ&}칒)+d2^]c^*ǖ lqsOlJ'gFFLs.3޻ֿb#`wx3CT}Ǿg\XZ/NNwc<=KiiB9oyg btEFfDa $O(hHyH~LXGS!re`݅h2Ozr,;wl6F~'8Ys$KRt"ɮ((@mw2t7t:{%{-˷?/0YvhS|ad*T(4c;w&O_x?D`^rU1p`EO@?X[?l6RK|7AtcR5Z9 \W=7T#FGξ[:Z!V햧:~ <ƾAnO%}*Nb2E#9U0R0WL/@F>++x.3ƴ?Es0 EuH+vLCK>"KXY hFg33MAiO"vc_Iv}+nD',V meI0XjH@\ BܜA;~r]dPA^^]G3z#Pbh#ddq l~;_@~V!@y1}2lUGuZ3x󛆾j}1mBB6:~g]#*q䦤 ;gW!fLهf n)N3Yt5u{ЛmGWwOlP.<Ւ#~l7tlj7zdCGD+(SW]F/[jժUz C?:l\Zt٤s}8r[K܊(-Zjպy}(XMZ  g_ݵ;S4?&je:ՔtS 0[` 7^T a')wщS[_skۯYelO___/XB5.[3_/7WS&Q|$8fp QWyRp^3W Lk4.qƒvgjn[9(O qH~x-L~imfi᭯r A[*H2@;ܞ ;[V+S)obI,W@RNr]lܖ|ya,˄%w$: wrVgv)>s[\а=*gU&zalڛFd|y=vܺy:7|.t_͜ܧMHwɟYk[c^d|LJݚ'-mVݘr_2,̷yL۰xRء/]%oi7cb j}7aVN[mEjӾމ[쫱4k Z6+ =Q֎~?l4Ȱar$+K,%hc'LNU9Y+Gz6IMoK|§vq5&ߝ"ĸ oUq6w2rQSSbί?6g}#)AȺy;S'\܍,{hq-IMw= { ԬS'ڤ>!sݧͽolikz71ƎrU gzF3ҕ]fq2 xj*uAΤ9`)-@uB1bqR4^Ry4PAr]` ƲcN`A@ANxݱ V2)31C1^+*=AL&5FO~5}uPɫWoRJ~oKji^vd裉 ½rIۥ*ةD]^q c |Mܚ3ߣkEpǚ^]H dy׷QgbK {`XUƐ͒C3c9ͥ9}V yB=,̙Yzzw)`Kvvxy 7biOKǛC O[g噑s}y|1nIvI35 ,GBJ|9-}t% /h2%vTp Q0I82I9-/\>/a $@C?''o)E!@b!4RKZʂdoI[K?E*o|I0 x O_lRԁ)LD99:hAEŸBMP`ZxYJo0NKߨoȂ!^ >Yt:*?(2-6,z4itKvMZ\ ˿fZS+iFJEu yVǣB}u-|^D- <<Ȉ~&^~Å[Oƺ:-62b=@k?449u56bj?1,0G6UJhp55Vi>,-YşJ#7Y~jFȽdj@8&fWýV̉8 f?/hY\zs@P 183fa! R~ "JZKٳls<ღ۸0.:^.EaM.5Jͨ)*h E|rsy>Ξ /'NJ[@F =uGԣf1~+^F6)^<*ؿ(ZpdI.zi˲bQWfWLQ( H-dMW_ߑ^ + N%upa};1 Pf\ n􀜧yw>FktYJ:"/.4@IjD۟6@k|&tarv&jFj4z//ooQE!B`0̝;ץZo&R3D녋TLb 3Ebe\|׼^@ ZPԟN32zKzMUk^ A`4h իM=\T]z73yk wYevڽveĦizf S IDAT9nK93Êe*$7=]5˲< w3 t1_]YgT|jGjΩsƫtɏL.UtҰKWC!Sm #bD!ᷧ?;M>\H\ZK`͸rSV L&`&+ƻFQ F0uC|Pۏq!|B;|9=%s?>V_1Vww{4z5=KJ" Ͼ2bYAu_M+6 \ :Ac讋(_XVrLrL,7E)j5e?×~.#8o } r^ b>䪐Z3i}BDn<"gDsl"5]Ssܞ !gzc;9 M]L&䫗2x-F4d Da,8rߤh,8:!Ք(奚WEaB^LTnWЍAT+Rj_x~;D[^h0G%x0nTiGg햱0d&n17|#AU%._j|cnA!?-{бw@=0+ȻFuVMݷ`cioCOS872?XƕJz]9 'NMVŘ}?Զ *=zߒ،)0-X3oחj~8}GiCy`>q .oOƲηڬJoW܄Uӿݾ> |j޿b1lM<w)X?[8+ym0\N\1=/?4vܖ䌃A=۔{rZ+kAoBmq+_L; Mߨ/h CHt9屮輋OZ`gymo[TQc\{{ bjjz7xqW]QCrlp*G-? fWz0dwt& ōc)Jѵ3a wp~9`׎ #` %`Bf^dmDzA @ӖbN|ˋ%pFTh1 Э[f0աEDi_D^Q}t n[,f/U®[GE;ӽ ިAſe˖9rBxE_Zv[u7b\Td7G .y]jPm/;>$v){FmzU0H.Wt-Y{Y=dy׉:t P:uꁴU4q\!j5q^' 3^L(;I{\eaQXHD7|G=E/|+OtX77gq ߹S^}I*ǽ+[Ͽ/Wk/Ovg~u_;_jmOʠ;z%/=o>o7g\}=89\z;:@};f񋿉Nz;1vsS.'cS^yUԘvםp"[^>-:5Yg~f7mte8]w{4s~|M_w~ ^u\Q+_w5~gO8Ͻ߾Lٿ>tȱrm/ _FH#+֎e﬚C{z fuæׯ__Fg*GtQ> OS1tǣ f~3۲ fr?WA#`>W=k4jUXT(Pj=4?f1YjM7?xfffhqRX뽋Zւ6*P TwZ_,[T######cccccc|>jbQ,(;J%uGuNsUƑGjժ5EnY8m7NLC6JhGOٚGh/,,y7ܱ/PO>=_z¯?GM? `-1QQy E F1j|)5F cuAls)xEZ҉I 0 HC4ײY1KBjUW|A-rXqjc9;n*`i#8AP(l$)Qq~&rbXd7wNŒwNA1= eocӶD%rjf$њ:ۊ4%QG-ꈷpe}@2b-^y5ZkH}TJ1#^{ȨXD?{a >O=1vwuA ƞ=kcl߼3?YQy }4c/A˘A^g|0cOyw?1p׼7K[>lcO֪m}/ŧb1v3+&W_Ė^ԃc^uߘ啯~S`ygiWe7KJ?)Jozӛ6mt'vvgc w˾OmۏMM}իo3׽{_t|S>_}seNG?3w<η$Hsޣ2_Zȳ˛yˆ5)x{o/]u+?r({?7oNۿq5I_XUwt5W=,x/s)Kv$?;민uۚ#y_?I/Ҟ_!bzkǦ<_;woxȷ\n.|'a8OG=gpj VML'ưoEg&?}ⅱ٩T [NM{)!+rJS[sL.F)Ƅ>+AVT)hzԔd*If-/)Mj @R^`Vo+A+yT 6mt'w%~ {>?3W?Rcןx?~׽ qW{ln:vݸ xs?xi'[n̓'n}ƛ_859kp׷n]h{p/msrӶ:*cz7o9 ǟ Շ~t^=/_xc?+ymW8;r YJWvrQ# '?v۝ņ?>~/Ƿ~o=N_і"~^>/aNM寝jzG+LMeRD(CyIuXOV0=\Qu IVgLQV看ut&IӪ9@HP1^2͚Ԭfnƙ]vϗJ)55Fv5nƔ@X0@BGdR彪9@sL눲 %b?^>&9?:/FwwNե-G}~xԃۿ\Dwx;>̛޸/ly#ۿ)W^u~FG @z$ {+^;{&FFYoU/=+^zt?h*So-ԭSTuIkG؊~K,ZP06fXf@`\lx ϻKUַ]{\7};:|ښJ XhsmJ1',~S5q ܗ)MnzOSg JMcmRdYi, +;Jw  nb877` Z{8aJ^]z@[@ZB"7 'N o%nlrcqJffov>6X>7=4xa>f.W=fdJ.u˾_ZwȱP,9z r߹fpރ;tIZZO;dE@>\I崭!`1X4FD. VOk0$5QHUy J2L.\.N9jrY }b; Wk3OΝ;ժP՚Ɩ[*l Qv+>&6_f; d̖=9_3]P#ͧ_t3X}}^rg\W+f}Sߓg?ǿW <=bͻp2~OypOv;vUu;< N5W$?Ezcs[HsՆ'<05xS7'ï+_Ǘ=]e:c-[xW-`"<ܻE[n W~7,H=Q?-I/֯^u)GiO'?lt–)-زb\JaʩmL=Zu_ {글'_Ϭ)S޷.|~tt4ϧiyZMR5e-?ع91Р^׷f£E`4`&_ +m n7[Z/^yYGmAL&sW}ߙ|)'ᆻ?=_>?2k]}%g]Ch1`*߾䪭q\_x?[>1m~Ww~㬵oխ8()ك^xK}z[{{^>K_zPy߮{?qYTYOl++9>Tw_?fy?nW|^yo|~'4E7xړ="}Gl!?mXO}oο[>Yđt'_/ً>?I?|Iny췷7O%İ(cb0K)3ØVD]>D IDATfJfY.]ו=cd&hōR^{ƈS5S l*[o-t:F5ļ]1O`![s @1oOw^w'x_~'a,,{s>tgxٗ=o'dA,x0 /r^pƛw=p[^|t3?6m2⋮=g&ަ>A#W\|=pʋ #_ur;տ;X/gwcV^J:Qy:?}Os}̯;x:.ǀ(S?'^~ouG_D mN۹ͿG?+!xCNZlܸqh7>jGI`w>r]I0[*aR'FKַrщUVMNNybqvvvjjjzzzfff~~~aaAPTľ-@]Ǎ7 C=0}58::i 0%;/ !U- "zI0Zu^rpO~wv&Lp߿}Wqux}Gd W񧴙8Ϊ\7bȁH঑2qƒ:1v*'h?6^ `M9F &xK1D%L|۷I#J[=iZs4_TZXXX\\_,W W\qŸzhffP(dZz5 3XU`Dx4 XjAD2לś< AQH` 8b{Ò GEHm{ov怘SjʕFZ.,,*JP/ ڈah8O~o.VDi>ak-yιbLIlVoe ?7wy8/?:3A}90io aUXuؙ\EF"G $zTl h^ZD{ wGoFCU|"2r< O^Iv4ˆh=ϓ{ fp]7N ĞpzW. ojurrrbbB<%zW(fggȈfH*T*333sssB!MLLBsΝ;wvI+Y׭-}oE\"`u8JJEDST*JbX,KhNA&7xw=vђ[63 7MD*ga}gl5)QG8Lȵ8v`1!c!*{jxh8#=.)ap]bZ9/˥RZuej6'*UQz5hVwGrz6RQԈ&lݺulz=(bDc%/ Ϙt_  a㦜L>=~M4=07ځB"L6|B1 -% ӃNT]*Z a f}83,_vE0U jax!jC] ϊ #tvN(GcGesp $6:3FhLOOK˔zl]Tb|#UϦ^@T$x2QpZ dol4nd8` fǁfr.uRH6٣ׂJnE;\i.wd"F\ƙ%mFAWRe:RY`.$7$`5/֘Mbv]&y5$FnX[ &cV u(S F%#x'#)Nw55(*l$J%f|BbXVj̝%^W/F.y-WA2OrVm4!ز 4%@ !,⧀181(lmwlC 01[Ǘ&r9 b Ja|QlAJdk֙jD'ptKu\R#fޚa&^ȭ)RyjxYؓ_ 0"Xx#D#Z{[n za R9&!c<;;{=O^\\*bB:-yt^f U8QE0H!:ADZb@F8Gj5ѫo^9$ƐJVcHN^Up [d4 :4mp XpϷ||ͅ핷w_5% _%V9[=1_&bbS@UÛD`@ h2 朋{$l-14ϘSsnw7Zǎ0GPۡ٨4E8S͛7ET?"bj2[ա-b#ױ"/o 1?}bRBϫ 4G*bGZ7 HE9e8=?y\A  kn2%I^eIGӶ'&4*alVf] o:3 YlZu=ᙼ uIO~_߮9icBQE6$뮻nzzz۶mӅBA2czDG'eͣ׎VD;bh9z2BۧRz4~XRIJܻzoGHiLO=d2ᡇy3nu AA,!l6016lB pOuU-̲ĪӋPz&QIҡBwZjik1)ٺ>]2n J`[ ֧w+UL&m>G?<#}֬Y#vTqǘF#`5BJM;,@S2JYQ*֬A&l>ڵ Ëqd f1:Ylތ[o]CAJ)x"E])#yu>IӅ- .],eyX@V[v%ubFH!nhJy 'H0 8N(N#i@x$FbV{u?I33'`l X ,zVxʈ}77o~M0}B[oU[&@ !ŠZ&~xIh6Q1l !Ѯ" P}i|99( j;H"lۆnC`l%q{7N9GfwϜAİo+Hs%,-` ?nr7o۶?֭[ b5o]Xc1b.FFl>;ĺut`\##ؾ]Ri#l88ZA>{E_a|;pXlA>W=#I:@Tg[>RT(+J^_nڗf<8@rώQ.4hP(Vgq= NC6r yqFP.sp]LO *Ad1a-XRN=a'ݻwIXq6A7ފ0,TBq.1ss~CգRF!gz0=[dT*(G]X\7AĠo@{[@>I;g8tLLL$ 4իWDŽYnw1nCƼd9Xp nOO#w'([(P*F#NL&8NR1[EfYtLy繮{K>(O 6:U<b> '\9zw{rTwp6Xl3G!    U_`QD=NoIa[1PN$/PNS3՝GpKRAM:^SYo>1,!1RTV#(PNrkQƼjJMͧS-PnΠ#oR8f`:@ek)wGXYC AP:`ߜ# s-ຨ13;pmP Pcqg`B; b`p{P^S>iǼkV)evj|RN×(K~ʼx]2]#f,[/^{ cu]uzG.cB-J!xd 7ysrHa][s^9< CzJl)Oc |7AA,9[`mQoVMTN.Jiњ_dѧ~{c;1cڀYVCV^t:JY~Eն5sրMKB\}Z := pm9(=R챡r99={09qkB09ky3v/I@A+nvi Zb=lV J+JD!SN)+"m֍Mk8foMb-4FU֋Yw nd2ZL8QZ6=K@<&[ ej_s ٭clm.^.bџW R(p 0>;xk@r"J%݋jb_S1<P(cAA,7/t@|[:JnE9JJm]D=H9М}$7j_dXSKf2J8".yl6=f Y^vjAMU)}Bil:їغw#$?R@t3lF᣹mí#B2{{7fgQZ%[A'DumYǥ&{]ڛUQN)+:zp+WYJh<1}Z"ctl9@X9@ |@8ĸfl63[CPLfL;A =X{[ v[MVMRV>u͚hҊA9ܜB[ŞL`B+*cL-VO^SrZ0@ςh4ffՇX!#mXiic0H<ayO]kswӻc rX/qJS8^?>nyn ڰ> d02I<&'qxғp啡dr8?Sv b`5(t3.^Cj f=M(L FJ"ĕrrsOi[ krQsv yrqu!Cl(p !cDZ'p3: _.X0+`@tC IDAT56lh]%[AwqEb[\1l60BKRqLMa|k`F| {8}KAA, Z\z0{ JuDѭQQzs.z4e%zTM3c&6rrsON1G#2aG/Dkb`Z^z#IH&ˏ1qRT:  NE0T{W鴰 f#~D@ p40` |0J%ՓcY OA X;uQcf>nC. w?plAľ?^;J-VV/QI:Qԗx޶Mu(ӕSЋ[sȣPݪ&2 Ahp}!e?j"Ե  cB)=bl1u3L.######|>N 3D\."m‚ BTDb}A?U,Kq|IJavbgn ?@k:_@L8ֽ!M  A`}DmQ#DDW[K|nmdT"6qjRTRNWnNual" Zſh:!QNwDYx{q~/EIh j늚Y,Pul6;666::JFPHd&y\fJ"D@ `XIN+j8ع g'ݷl <B90)qҥ  Q@ad@M&Y1$ 7)ԣ`Ax"rL1h4*|0UV18R7A, ,$?P(9!6rJg7@A8Z/ }5ͣj!'9t$FC= DLE0Zͪ&)`"15vXO@"R*s)1#d=3<Qt&d2l6͊T @ѨjrYLuĔQ6tt)6!mA.s0ylvrrCd2SSSRq/Xh1旼0d*>j7to9Hv: IlY*zÖ!UeQ/YA [oB2#p^xBkjǩ*̢rrsKhz:Pcգhoz[DPn7#T ֙E ct}qDϼ٬8FT* aT+0` ~٨Lc"[Zx8T^7 \ם/JjVeY?\ L +ss9֯vR X Hb h _GUVIKP_G*+mmLRRSa!nZT*Ȃ"yPUSSik\\qhG XI!4 H}.~?rjZ [1S@+2,UVgZ6??8NZKɪTl!mI;pƠ/GFFĊv횙YXX(JrRdV)H@ Z g8X 9d  )IrU]م)(r9ղU=s]W}@QVK #ur]f hu-qj¡kRJQG)tubfʚ|fګ\.d<ʳ()r dhG-@Yh_= N WSP)ɏ("V-bݻwϞ=PT&''[X6J^TDV <a  `9XqBhc\5M*wZϪtAP& AUQxGJQ(E&T%SͩDi.`. `NG P")2*,X7#T,z]-:ă^jSSSsss󋋋RI(mQYRT.;C'&&mj R!@utV*@^C\m6ryqqqqqX,ԯ%E`(elh27o:pqN hm b`ĐfMMinL}7D'0A-9Z)++ê_9rrsYkkhn)ݵQGh4RW׃rP(LOOg2qzTZXXXXX( br1v]#Z_6 U#z6Bq2DMT8f 0,- YXAľͼj5Y˥iƘP,-LS,(+u7:)8H2blKc6v$E~| 6ċ+8čBUrT*# Ԩ0Lqn. ...cg˪R&B9ܜL϶_uxva w0XxxƨVVVq^T  ' 3MR 41PFGq1dP*uX\Z bɀOG&lƄ~?`j 8 g1$AD M.I'AUTV"(ZZjzzg /a batv AohP(HGl6=k4fS&ndpرӑ?s߱kWwOYWz  @)bAĸyv⡇07U;;n% F $ J" -`"VSSdzXR"AD_ځA˒j*G ;- f'F]evd(06; ' hANg+nW6b##M  }} 㴏ASlڢ{}⎆#'CAA诸b@ɕJm B [AU'b6,(  A R'    %"42 КdٲX/   eJpk$SpժUKA.+ȄJAA,†NA PDAAp[6@AAA<•lOG[B.=ސkcT`Lޒ"Fsp{W+ 2[ԄrSB#J{(!*[?170pHVBGG­xEk8ҹ[k5]J) E'+ j'RϽxS-eq=E:=q7fY[{_9>>u$ɚO&@GoupFm3<7fy8zgf  ^t)? 0yb`-7cxc)"g"$W%-*qcpɏ {|WD J[')%J,K[_* 5^;F˻& 1kf\c;e\ ,a-rƔ/_XҥOUʹ^^R*](ĒyA.O$bY:Pӿ6sӊ2.yI8(n%UuKҩ庋``J kCQ)!NRA!+/\`\eČlHmuuY} E]t}ZzJ,E)Wʁ>d0+%y>kXaBe_84ņCdW®pp: x؛dAt`_0%r] -xZb`W)~SF,V}blЋAҎcMR{G2݁#M4aT o/NLAoZk|ȳЋ^;ե(^[=jGRe|oQAHF`JtH!?]cf30bhUy*4Ą3L~6;Y_mEZx`p0tc҄ym+B_"!ncKjkf#YZO)s$[tT0л;׽mUG'cbbSJ$29#8:f2$!14  7%3/܁,7*䮐60o3aǑrK`,Y&/+Uن@>żČK-WM/&B>'y[*eIO`Z?3SQɠKzM _ff=H Tp.e8WUJVO>$YSe&)ybb0ID JR0 $qzM7S.}l /\wjqC/# bPR.(PüKˑz [&N+>0 @-IH,B;&sr>0ylJơPRRo~` k0aµdzPVo2<ӋTJVBhֆej/NK[)Yz)s-k *w]fQ**IZ5O5=XI4|'t맥&yI39 +\w[x'lR`^C[]j}n N c^I!|1k _=ݢ&Rrx;RmU6?M3' &rkxaD0j 5bMf m_Td?H|np(rQ@ƮX mGP?< xaCCd:껿ԥK^۴>L:n›ht&4kJ֎᭢SQ՗..Y'3 $%I 9-qxq6: A`0 wsZxvhz3%槍e.xVz&\nn1·^g~*dK9` Х#$$%Usa"_E~0n@$y #G]@& &o/18As'(ËDrI7A `)=_!İesPC؜9cBmKTG|$Y4Ifbb#h;jpA ~FW݄1( vqwADȷp?T}IQ<8Jx3ɡ{pjuKa-ae_zV TH{V $,(5Z ~X@$3h#i2X-B~† 2?B53#AIr#n.) ?+ùX"OYf['o~0xC #E_cG]6/_K3 ]jhi{)*4 |x"Q~) j1E* 恍y{< ~i*X`&x%&*7FF j]:j]ý*䷥ADP<%(R.E/0%<2D"UIi0?yq0/hC #_~(9ӱj~.@CyQ[&!&B1i" R4`CEH (4$9Ǚ;dM·9<3yE&EK}|_:2a xݮc7+(o$ZhY z2P^W65ACWUTh5|J UUhR+VO$n:#6DpeqU\Q-˲,KGm `&Z}Ċ#6cyTEI]+?ȆCZx-oK5(UZMJLkmI(=ž0օ e${XɢrbVҀoih8X2Bj/Cyk@d23r ͵x bPXƨ:8t".@,-t؅ ߑ_WA6OOD{?W@Mc8-P=\kQXA(w$Zr6Jʭx("Pdr"-U* D~*]TիԧT^" 0)א*۶u2<:˲l6  a)(^pll-br0D$H@y~mRZ%6p\mz) h*F `Pq7"6DMN}a <b$'=$fHbVQ ˂ m]}y @V?3F["e]u pIK/s :Ɨ VîeGE? ~+zKzʃTCl_%!!p[C kQ@B X-V<Ѳ*, X emFo_[5G@hnUfFSr?@ @/D5O{IJaD}{]Cjoue9OgDԏ8aƁ`0 G{kдFR ØXžbG2p􌠃{G`+;V'ބd*=!mbAذb4h pe09fX.=l IjǍz ]@[#"cÊAz0c"K.+o DJ]\T:_/maUU@PK ud--iP@ڟdڼXH2 AHwՎ.~L2%_O%*zgd@,R_~ty,;0@baaY_Lp+"tpZ`W9pRׂDWHG*˲a#^7'SE"Ӱ h,ZIRkW@=K|߱?8+xU+LYYbE-y\=D#**U/gTmTE.8x,yRb^`HlI O[!3 e=xTD7pP>0JضU, DO!℧` {:D7׆"Dg1`0VSx/`ER}!J?+5Z|%<݌d-\q#)$B9Ěa^5X V:F#Zࠟ^}+(7Eɂ݋۠H*Qy82J/o҇^ wrɊ^89JBPoh`#9(-sV bI$rPKgK!Ռxn`8}WKXH!5B_;pǐh@N?lHG, on%Q?,-NN L?>ߡbхZ88BA/h[?C7jHzTׇj* MDZ U>a}(^JZ2M B>/ ڟR) Rzrucږ9M.2E?|>H$ld20 a-VCq=K0EreXJVH'_(=bmxTN0U^M_Zb~z6JG`!t/p$ s M()q@#(cP.<sPZ*< {Cxν-H6!= 8Yt/*hjnNO 99,.33,zByddѵإU=p2Z+e~XyH#׍eH }ˣsVt_PnX" F]+@w!^o'^ b;B/ =ІC\r~u n ݨk d׎ew8 k>T3,qoJ6YB&w:- ^NFr%t@z[庆l'<=bW v14wD"H$D"[r\.fYm|jA[;eCQbVCjŴ;@GPl6wX%!RJ0JRVCM2L__/N؁&<}ŻZ qB߲,0XC/X5 ?DG/ K.]lY.(f0 *xJ2@--leYx¶C~A`$k`}ITlH(tnAnK\zhX u-kiR(ٯx72D=7@n􂹨̺! bH5azա%oյt-} 2DH5~$еnx5 $nA$q,t^'~8x貐GHԣc* q(GAOyZ-v"ہy5Q[s>D,VX1,P( Aw=^U*b01{T]c"T)zaDI*} eye:_?&0lb*5 }}}> P+#(z  l?K9FTNK+{yy H/ߝl„͐lFLJuA)xyxFfI! nD@!7EN񲏌OOc&o{UFzq-ȴCJġ$7 ^D5"'X1( ;M0@B988Q)#"&L-, A@X9 S0~:>~+[V ҅Dp#e'9\v@rڮBݘ2+0?p2Ս|Ĵ] 8XUlȯ8Jb.x!?y*ڶE>?QZ)e_u,1Aՠ*UC#Uic/U&5LgP5.$I]hlhL3=z' `XMb@Zt2vyI}r!ӎ\8Ta_2a%гзNzP$zr]pK]B_zdd;itD( +0 ЇιȬ@κ$ Ê9]wr]E)dQCv%:>tݵȶ# 't͡A߀Eb RM Ȃ_7w)ޥ^L;}H6^^N+Їsѻn$jd0?蜇ȮD<=v=C.؉ncKL;XŖ @}ː?+ѽF+?B* UrD̪ U; 4ФjoɓFD`A\X䮪RUM*UGO8Vt |;aZF!=9Y2Hjr  efmP=PY5jg*S/@6-[YgHA zÕ+Wj:iS;`0 F /Wt 5$bi$jB, 7ޥ]l' }h,f8bĄ$iG"@-z/@btIIS`09PC@ӟz.A`Y1%d0< lds$a^I`Ҙ3 FGrF1a5w:(ׯnWAFhQ)x92H5E-~rhJ*29~-p+z{ٿnjYX.ܼ^V^rzn\5kH*0uVM(jP_Z@xdǍ&vk0 C'iNbz`>=1W:F&?v%h T$?dkʹ" *Hei[\eC#eWejUY}t!B^]wU/TfDgΜH΂&,r9uG6 ؆K8H89@a_acU5$3fyFmvA+UMˈVr s 9`Zt`0 90 0ځXM#+fdmQ;]kF^T%0V?Ҋq׿,\ԩ5I3 "h0 P'gZfr#`d2{yw3zxSɟI _`0 X' _ l4Ҋ K{{zqCh[*p$^[5- `01W+kX`X2P)VJJq]7wuuuw,YdreI0ܬDȕkzrA`}_N;0D `0Y (]gbfJIOz+ B!ͭh_n(u 0 J{#L@`0 1Z_FZ0P/`R*#`0 0QZ eg`5-f˶O U `3RP$2W`0 R_:>׾\r[Gof0`X}̬Vvo/:74o)?I}# H#PAA00q`0 Z<Ug=CCz5 +<-qW|m]y3OTiSzE +0aW`0 c5(W+,>~ָ->O~'xGOGֺ^G}rJɾ_qA:Kn{QJ~qʗczG*G>{-Zvwy\Z+m0;ޮ2o'SnC?Qs*f'ڶ|ekT٤i/_r+ŬTnSלVm7_rڽ?MRJ4o}xƏrK_#3?i]N_4Qr$^*(-Dž`r#jg0 0<J,_H+b0 7p *bg!&׃[eY?gvm`1!DCcF{D (H&IY6Ȃ AD&.`/spU!`0 k{ Bj=!  cx-CeN#P;0&Z\@?k+ tpXIt`0 CUj 0V@'FBēplml|sj;тv^C/D`{;`P֍bi׵`U3jSsֈ/Mm_֪޲Gy[_mS];_)åHGE'f1KQw\cz5w~z7[ՍZ`0))H/y X?ly^~kvխj(Ϸi5 a$"`t>fո͟;=&UQ*(W>{呧3]{T@~w?l(p-/{2;jsD [/:s62̘aHv'qh/gعٝo>ЫK]OiwxM~~ǝpħ$Ïu8=sMݴ^'߲!BLYUt=raW쯍N:ݧnFyye{Zlb` 0O=}n `0 k%F{0s3(~'/HA$/6)YvŷjtOIoٿy{ԇcaĻ{/̻>`q;{ts|/O?~amvI8@{.%չ _?Y!D* 4{K#9^w& 1`80F1D>w_{fIs3 H \^^'?}ON&w8᫧mm;ǟ;kS8|w׿{[~?8ӷKdc/*;K^kۜXOu%_e'o{nω_=}fԉRUV܂?pmwz_߳Y}7,'6/? Vs%_8 %Z6[6ؠurkSJ.{og}Ӧ@b.Zz^DŇЄ[rKKI  !Ԅ->.78'"޲'ŃK>gߝN8[3}v{6so=b{^{{~Gx?=%EHS`0SE&Jl`0.\\@ :?# &$~jhO}%ĺk'ZL\a÷tvN 0464ne,J|q[rᒻi\Mw$Obt Nv Gv~T)]Q-g;X쇿{Uu~PТ;.rig֡|^?;G|7\z lr%dUϫ7^̛ir{/ɦ\ȷa+ϫS}_7t.QojZpYWᬟ}Fu,Xf k<#_[eOʃϨP Kxw-7HDcWJo_z~v۸mzg>uo.@TW}?\$^wZh@aX~;[wd<0?X`>~͕8''mlca1d-zՏ~JږG!k>gk|l7nW~Sc]o/_~@[f_<?}W9-Ajtz_>Q Y`0 Ú?)b |T#PAbR,+ TyymU͞oOr԰M'%X&򷭭2R) @p:@,_*hisK/vvv.kqM۰?9̙=]@SyfzoOz&QcO71eb]W}֒{o:y0μh[}=Օ{?Gv „޽ؗz|v1Gn:ފٹ,7u|iJEEwlqk]i s{aW]K@1w'wI gw~'86m[|~gW_/WM%|a~RCK>K?;-%"̓8孩1d,l낟-^]"!XW?'&sn,e/%>D m80c#?-u2mD,Vz\S7`0 #OqЅ43|wVb"&@LB0\K:Qy0K z6/ cJ1z| w@56xVaeL+U,jWo',\y<e~'ybn[^L:o unoR`}X 1xdX-S;ZbQxӯ9{yOv9Ү>x??-:X>oK}Gq;1 ̪ߞ{qSt7L\{>-?(@ixs-f/+X2/n=Ǔ B8~ VS@`0F;hEO?) P #@@ֹ:=@0`f@پ)8R;q#4t;U]ϝ,,8之ЩbD"Wh !ãZum[O?kݦl:vIf˷~N~YMi}Od/ίxKN/W1nO+t¥~+&9o-[&K3mrϊgaYT@ɉL_Am!lRF.n~WN'Ar>naXl羛={Mo1w>oĥgqZPlQ"LץP?mǽ>7w?(̖E|n_'pkb[Hq.0q%WӚ ?I(&f9^ϢE3`@`08%M9\%Ĝo~vC0YD/k0*?O~h h@0>C)aj@1G922IXNr3z'|]?; EG_ls~믽/d;poqFPr\SfYk//H2+>z.YI9eM 7Y(xDSu"]s{KheQ,ss?j==jy,:^}=ᓟKcBv߷Ky_uw μ9t9ыϿ=EwZƣ7^ᾟߺI*G|S1Cze=⌂,/MbrR$CE%l9lez⽌R El<Ş_߆&"/5w.$HJ{f ]>q3kkL n<)@a[?ޡms;YNѼ˼˼k_r6$ /d,0e^e^k%u@d H~}@& s"x$Р SJq?^qf뚚.~䯮x,6#nO4 P,q=}8{;{GҒ?[xx֟˦rN%fn_;=u{L6>5uy_˛˛^{V%;'Umw IDATsƽogyԋϙ8iJӸ-v>|ש+S|އO鏎Um/|/337Pߢ.yWn'_>7*ܱ{nlۭwtMA^q7LR9~c 3]e3g0 ""ˀR+ "@O^}Dej@@DDbϟ&'RͰlq "4(űWR/V"B B_Q2I_ӈ?C ;D~$c 0 (A).2#A:2@ P %Ȓ–Vva9 Ø BA,bF  )`` G~r kM Cު4C[~ibL̬ӓBi?($  0)0WX@X7(/迈IJdٖ$f4 c]2PdIT,&E`&RD$<Ѫ ްvL <:0uhPC(6ZTI Q/I `Hk9Q_0vbHfƒ $يle J_daDSh?PP KL ,dRyB#lbcE~. _)/dLN4 a`JJ~V~bf.R:RKaIees,N1 $@Ă" G-b]>@o{bH X 5,G.VG}(*C 8DD)en#`0 Di,䙡g Zt=A։{g ((f!<@5\[I@ ""Ha$laYŠe &+fdbLɺxC]!^WOM8纃*d0 `0jǎXu\Kn6N6d2N_+伂:9%:,=d̊YI#Ei(o6h~v7Qjܰk84v1鷇XdAt#+Nz(Vx`%H`Y1" 4o2@!X+m抅:zD4ˎXQa]m5ꛔ\)9*T0U\g[ "nA$,"A"-%bq˶E,ODNS D>Pq:K]a`0 `0x̶m۞w2N.[2Y(x-tYI%R) @)@q*Pn'"ʠnl{WWUZ 1碿pxID,M4$Y6D &a, +VAI! hF ߸={4wC6s?T*~SpE_Aj Q!$ebddŽYv\"Ru")+ΥLm]0IG0c `0F3d8v"s^SCv>W"!ɖİ1GGRBJRR(JgxUu%t:H^\!C*ώ8JP <_հ-[5:|;q{RB8LE Vv,pK6Ddx\i S_H \Pvt*mшpA *Rҳ(q"T+˝eXa-_AUew_"&)@@B@XM{,Fvv $RO ;I6}>uvo™?QJ9z^2Nҹ\6l; a14 `X'1qݤY$RUA"8DqIiK!=%``) L̊PgWE_@&\4ҽ4k (vU2b;C *.WZz%+-Pܰl `aHI6o-X(~Gˬ(خQ ":]Gml%]@+-s*/Uds@5u"lGUZ\vP*ʎ^8Y@ H"AX$lm81cd'Ȏi/Q2SR>owߜo*x\l 6 "˗-cؐvh0 ` ˓X߉bK&KRLHY$y. (",ɀįNhgR`sFDpF+튆RqD2WfC+`%VŹP܋μ@5Zʽ ) zD##@@X ȷIiN$TYaXV3K~ 񑖒ʬ2EmK-Pby.ʜ\ %U*< N}qw ?{_U!*4uW/ֵ!u *k[+A⪫.OUQz ;?3Ų:3r̙/~sf/ ' C(\p+% \`իo="Lx_BOo8XӬ8lCmTx/Ja0y5%e""YL-|7D?J7pE0@`S(Az C@B"O*nDT!ƀ={*d%_2LD"Q)Z ۯ,/BaaaaaTW@zzz^}2͛{wOӟڷokI$gsر/(8G|0+3zs?N:Æ_pu餓w^<X Lxu|5s}ѺӁ?D_-===33g gfXYY-~rrrfxP^/ښeF/4%%%BBĥ&$H"ԡu@]p([-,RRq?F[r}ATPSF:-{DU-kƪjhC8!54B!< !τ@D8qNQۘdރ D֒ .2tT5JT5A]IUC=*!D|y!T[;B?Y 0Q8aBB$i+w7 3oɗkVVU5mJI1ĢєԴ&*$ qBwɧ֮/,|q1_ȄG:thÇUWU"RuHv^Rĥ9xAA-޺{*A̛;[תU<-`MuuuGu4;KKJbhZzs=/33+-=pƍO?y8o{ҟ䝆BNJfaaf{SK/Mx|!od_ii{iޢ1{3goO|z8~/{KOupJ PJ\JU3gAX ʑm~'׼Ɖ ?qMp]qOQeaAWJx[= e>a>=?&@8ăE& BJ1"C>: +MF&"M VSK!Z·o.,(a˅NPNDoFB:^YH, l 〓ě .攩hC˖-O?7g~s? 1u+=_ڪD"pO"/_ƍ: GFZF8O9.>c=\}^%_?f;ݱcDŽ֭ے%K濺UV]xAG{ׯ_?م{;˕pu#cquuuӧx~FYf0s֬]7Աs5VWWOyo]D ݫ׮]ۼyh4ZXX8g~dǢсO|Fƍ>,=j';v8qM:u8vM':i"[.;;{zo/YdkܹI&vaþ꫉䒋|󭊊xp؛aÆ6edd\}U8HClܸQF?M$}qnEYY3-[ w5Wgggg}+s333w-77caaC3l߮rԨW^ye=?h4 Z8)Ku\ >M|J4+**8VJmRyBbT)#!x|^o|Nx"fspEeo_&l=LD/5w@ƜeQDvωO8 r !DyAO2W+bURJ' 'ˢHZ."'3;! P?s-{pM&O^[Xeeewuwnx ^QGOxOO 3ffgCL$"uu'~xx„ƍW_yrSPYYߟ5fK+GdWͰr,\=hPC '>TWǢHm>?P'h}gE? -xmɒcF^ꂹo߾]o4Vx :9KvP|}fb[#:vE&Ç aq}+͉gp Mk1FT1UDX-qëF)v-BP7Y9/J+f5jʕJ-뎿n^;G'Lxk[k~ŗu6mri:nwlᇑHĻ5xڵݰvM> e|p?s3LYuo_ijJgjN:iӜ{KF!P?6~`F99\@`i 4sx jr~> b;)_I?|z,18"G(2~Kao jLQcQReV(D4"Z ~#رsw.F"u%DښjHIMm޼yɞ=;wC:vܷwHA5;d-7;A6,Oi߾}-\+W:sb老׮-Jzِoղ!'dffN(#6j6̜6}mj{ IDAT[4ŭ[^~Kz|zmzzzZj8RJ5mJJm:thRUEEΝw0/ 0;w*--UٻwoϞ8 _p[XXa|3tsWrX!vD^ze]xՕWeg7`AUey,= ';|z/\ݥsgZuӦ>/yqm>6!~{AN7V?HDHr@g6TXGUG=%sQQJP_"Ii/KDZ{CU;@|^!?(ÏO pDTHgo=) PP*%NHUqFB7- SSRwJHO1[XXX4[nu'//O堿555SN=1\]UYu cU)P[S͊E]?bA5%KK,cFc{i _- tRmW*NH<+\t3g[Q^vNFtm릎wׯ= 'hsڲe+\xP'B}y E 5J+>D}DLs4"s+RTJBU^\MT9 7j- ]u &1\N!mD @(PU,eacL%{.ز>%||X'h ҲA9$`X~&wX,)xe-f_ lsq|" ֢k7B8Z 'JAEfooIB9MV,_Yޜ.qB$M¢^$E>#LkSP=/m;wo!}qB+Kn] ֮ǮKm߼мOpUeN5,ҡCEo,77++z֬xb,"MԿ?w~ѥk˗bM6yDž)))ZyWfV2d=^g]vݰaçamm ضuAѣG/zgqю| _! K4Pw_ml_鞒d㺵׭lٸ~ݚEy~Dnkwhߡ]1n^ץ%1_=w"Ղf3ڥ&𧦋ŀZT/ 7B(ƌasJWO80/x 1T (!]dCǟbZ}pũujhQ l4]rW9E =G L ~GJ<?8V^z0h#/;:ש<[v)Hb`r\Q)pw_~P?Ws_c &4E]$ňx\z0E9NӦM©)_/&-#3jBzF_/KKOkڴIn"`aaq ػwoQQѦM,]z۶mwn}^u5{ VTTyE^'pyܹ)nݺuog_P7ߔ֦wӞ{n7mrq_|źµ>s.zx,ַo;`x,555y߾yyy+V *I[o-\8id W]p… ܹsݺu~w=%%e7mڴg9oæ-_wϝ7o|]u |o/ꩧ`+׮^ل;Z,,,~jx-oF'J~Ż~:@u)ж-΢ڪÆK0B F1) l?A.# CGUagbtM !P@➜f 8 JBkՃ0bmu\p0c 㰙 #Y<QB(7d¬v"@Pim[Dk"͘tb?5Lٹ8q~ ()<<7W_OBn0D񉋠:Yu(AA_t{n(Æ?(7n׮UzYC{"x,pJMM ~UUսzlܸqZXXX --UV9fkcHa?F߾}&>=iΛս{/}a΋?McoNOO߿gqN0sct۸qcFN?`,;VcV3g{O8aԨQUJYJiC=ԻDҥ={ myѣGx‰c/^T L<ٳ6mzz׳]:|O9jdU?oʫfBnnӓ'gai3?>Xmmm˖-%4mfڷZX[[ۮ]Sm$'Ck`|3?w@o'rҒ.sK%ހ 6W rkWw\w_,zb{)̧4)@W/"QJRnP]4dIȿv/KI,J `yꄋ~&z:IR-=Z;%PB6\%r"xʇOLB}JĺzJ,Y6%T_N5*A&pXA\gF 0 ^_&p{J8?e)$6O;N8 N p8%5%;oÙSN2uL3򺼩SG,2t>-v];s2vܵiㆊ:j*RIKO+޵kæMM;vܺ ?M1ht[R׍bUUJpضCꪊ}{:ӥG-gKMKsD]mޒo1̼V32]׭ޱ}gܢUEkU8;ڽs7ޢU~JJۼ*2Z~ͪ$5i&UU%vs[5k{玲mwj7[CnPW[ Z6i, ޵ 7?%%cn׮7{Zgdngg7iآEZl *+wyMmz%#Fd5jJwUUTbI 7  hߨqc ŢѪʊ=SZg;N(--haakAy3 8 ۜ֞hM.DuX<%h%4.K] 4RpۓRNٲpIr c0NyZzsT'ULF5N9zjT6狴;#+YՈbbpRR/|G -0HT T$M 4,\.Hȹ>:Ҁp$`L Ճ*Dŕr`]d(7 )*2$;8݂\pd/ Ú Szv*/vMJ Cϻ䉷8!-SRRڴ.,..SRefppFuܹUVM41maaa׮Nrw뺅V(w+++xٶySrcuwT)ޅOkTc鞒=%IZd-7۸dޒ[XT -xٞKHP .cph &yrb؝ A~ZDu~wh,"E.Cp {‘im_MPh< (m!QhCD))1hxHRBqj5R)fsd:wĩ#zDȜ\SuP+}EtZ4uOUjW"%q~Zi ׈.X૯=r$yxǣw_+G~M:d Í^ 7i۶m]]]<陙)᰺oK'@qhƆO|:˹J5/0/,L}B$oj*2o2P 4x> SwET1EW$>_}(=,p)˹\Ap޹KX Ȣ|&,ѝ琣YF'D~*Ws6X(dF}/X/_ nO?\ +%5MGxkě~=U3u=Ip!8 9ě#'8))s2R9YͰ 7nպSF+WGeaaa?½h]],REcx̟#DŸ#.u]Jˉ,"m%w5<)@G!ݤ5^Vt y)0*)jin HBj8x*sҖ4.U^ U.KR8^z痔#F ,;5cL$pf#">p-!%McfDߒ͡]s!, 9T tε)% 0y4 WH 1BPg&C P R0nOem`&.!c5AG),ύ|JU^91&¬7[ CS1DkDžg"_Q|ʍ;T\R DnzU2\@زoV */Kb^MXg+et:HPE9UPﲉ¿i)S@|@8Siyq OM& /h{o<;\Qe @6gThl:]&(: 巩bDz$(ƁetZ)M&^Fo_ scG)(A!j>w0Fr(V`ZAoys%Bă*!ďS[ #̸.Ҩ#4l"k!R)]Bf;_wȑ7\>a)(Z j82Wm 3+As4Z06xpq]}l)>J"܀ _OFE@84}@`PTw "]9/LrT!k7Xú8nxZD[nY / U_$1wSCxy@>(c%.ȳBQp)+@ht ꀾO<{1rky UÛMzAKi9e0/$E!2,i ({r*)8M xIš>RQ<c:+[ `7V 1kgϕ_93D/8 H qE[SL.`U _Dhl[,׻ Ly:lOT)y 9Qr5'BqgSHi\x)jF޹&b Y }zHodBW"3RqXeŽ L f_;P-H& VKIb\ ƨ xOCQBDbaaaaaaaaaaӂ좟*Syf^RwzCa5djjj"`3UZDQAk/2Fi |/@C|RIB(+iF 1Ό)6P)0vU|N\lg[e/˖8+j !2ꉿw a\CJ˧d a_oAcA, 8,Tnc Dݔ`{H' ࿹A\X(Y" \]>J *"h L"uISPTeBy\Ik:!é\ ǐAx=H) >Og6Y>cQʥ)Y"-pNBě"f #"ŮCL' (?:^=H&(HP&"(j.UHŵgde _hxVe?5l$UT\8sZKU rxRVaFy`oMvIr˶>٣C%5P5 [N} { IDATtj[9՗`_32D!hmQ=w.1qUӊwxB\h@&.IhP#"J\\) WƁXmBԈ.AvW{XQp(2L& 18Uy~ELk=h*! `xT9*Tz'Q+mE5jZ` 8y@eAiG eܧ@}ݯ ZPnQErDF_ jr/[WLʎ~ڏ)?q tK 3ᇧqK)u) RRK>+oH1U#G` * n^eB>2o=PɌ \AesCW`}SZD(TVQPg(e`Fw [5rgmL>F|Qw3sqMLxv&.۴I=dfX7=ȥ؇ |m@( ˁn"pu w䰽aaaaaaa;L `( _>}uB rr.$ "+֝`S0eObk q\NApwȲw`ڄ̹X:_@\=-ؾvF u~a\4_U&DⱌuJWdc͏TI5z.SS-"W"8/@[9&Jj:%U0B K ڕA7 J}yloXXXXXXXXd˩pש".-WQ86(Loz4v̍̕""r݁WK`j@fi=ǽ8t)>K9ACD~q^'a" Pu=~tGPh Trd" ! 7;^?y;Wd䰽aaaaaaaa񓁑ǀ4l9e`KFʌ)H  / @zfLv~D0MFG".R_+ @}GS†lNT@ ph)IA\;V75ϕZA-q;h8sPO BL B)ʜEaf $*e}:(Qm\0{#UV3  { PtE&+='c{PU{@JA)*. })v rLO h|!(e"j̱סo78_01A zV!44hW4!@ "0 Rjpe!zU_Py@ؖD 3~'NW.iSW p]?qiS\1'?8p}t [c,,,,,,,,~{-ߟxVY%:yzQ> =BPKSGݹo"`4WRܤ%ſ!#@ M%#0k04.^)])+NT)@-CS(#LD&D*nU`V 'B`cE&i= daJ˘ a8 tW4&mi~)Zm N<%j]&oEj)|jys~`UfGqm t?~^j ἓA~9n}bҍ '$e^% UkBYXXXXXX㎿b]wxS0wā. g|? `G.S(vR.yRG⾠XRө6/ !Ga0J Boǀ: <۟\ Ϳ""^NY0 #ؘ9؋H +`'P$oaQR:~.7wU抈'7@(,iHs1sRJpfٷ*$-Q` bmg( VdCePfDŽ=v_\p]9r x sMԭ|/klt'9(jmt{7\kkKnQRB_(7ߺSJt_MG4u -Z4pß  }[XXXXXXXG+**< FS$r`N{[d@~ _*YL;y@7IP$cM@Zdxq1/HFH❥l!yRgT{F 5 ;UzUDT\mlH<ϯWWvGqBr _v=tU`8`QHQ"$m+ rk$ICn8'tWM)퍣N_>(IxuSJ?x3zn[pOoi{xa{wzι޾pGU>t=Z-8voRλw7v8%8j _ھVpY0Sjn"v :F9Q=*I.^9."1*ݭ$J_gB2 +9}v'w8[޸Ko|ecgWO?WywnVSƝ#WtI^9q.ƝrEKf[wܿh3e5/?ؽQժnxtt8n&3^[ Y.|d- q/_)5.c|m*7Kߡ6M? -f7aw_1!4~tȬWڬ/>$3޷{//ݩ/[8aZ4s\׏~{n0̈8cƲ)i۪RZs߄Qseܲ>uŃշCRJsda =}j'|ċ?IkaaaaaaaF\z饗PץR?ˤ_1*{  5k4`=`P6кRN#\4jI)p-ȍZ@zų PBucBWyk1Wlܞ*XS6;8j/UU0xn`"؊hsT!^">R&e7>N)P7ѨE7wۧ?7$˥@D<&\q7K8s]X"sq{ŗ!9]|yh: :Ӝe5'6Is._5̎_;|M7]0*/e^!FS[}шYWnq{% bxÛR/z _?wr4׏qut$\pn<;59@q9kʤow_>M$܄E.#{,һ~_{ݷx6Du[yϘ$9ovA]M;O}sE 8=S1?Y.)$1&h˴9KwzN2L`c,Fv}5~ ޹ECm58mji X0 ABRr ! Y'y K!wKG5DB!FT< Gu)$fSwh"n0h]9ya'#E?9i=xЦ(!I^mq2ۿuGF^TkUӮh@κz=o{p6Y8琣=U;5Bpwnd(Nf6C/1MHG{"|~1oD@jxd_:sdoݼ? \!m-;Wn%m:dK~( > uLV\mqJWBjJ@E8͘GSFKRJ @Pb-L*? !@Z S" 8BAC5r1iPwRhI% i bQƷy6TG@p qriB $K}\8;,|IFDKCq+!TI}.O)-qP )-(tU潺ս}-I+YJ5EgOڣq=tf' n籧tm֕XD:l=HPsx(Mx->3;gV=̋^<$B"EkwWri9i:4L]W5^Ozޫm&nٖ^#.AzGf)='3\=cv(^hcqfyO7HDt/{Ǿ9$5=JpϺUo9}Zf@b-5;5:K_0q¢_^Zb e6ڱyoF=R|%Grb &}oC=9ǟXX7ۤ-,,,,,,,0fsѰPaWIvU|\:hF:2痪

hͽ@h8 y }y=תzE_\{L C2޻mUlvָs:Ш>֬ɗ{+DB.c}GMԱ_1{.8a԰O>:xGv};v4ii]7fR5`'Ixr>ym 4{ҋiswa~c&=o|`PN`d?eo~)O_ 1w4./=|Ӯښ61{=SNyx^yGIg>CN-=A3O<) b@?/`Gjaʯ<  Y+UͯTP9!@dO0 Aqn_OJ I QB3|c`ڑ,X5s Ν0v!GT'->!9A1KܘB"̛a@ rjۈ:9 PEpPC"x 8$N 㤤SRRR2R2SR3<+xgQ"!V3uQm~3Å:uKXoĊ\󗵣^l]8PZOH$|}J -~}K- *h};њh$Ƣux,%܄O4ԅp]"󗲧.x("ʮ{瀅1@ `Bցsݵ| -BRUZnYk 6eR hA"(@y)Q I"D,DK@_\5|S^VokWrHwK>F|PpB8a|.wy}) ZV7S3CD4[i]m3J%zíX+U?ֻQV.(T6iE8#4HHBA@5cv]#RպCRè)4߮GN20noށƍEYE" X@x/jR߻sD")7COG ^}͏ d^R,gJ}jbƓZ>!:a֪ 7ĸԠD?G$+"_Drŷ$8} y@)rER r*l~闟Ⱦ3M㰰@}NX F:mX8QCyY6_hP.P{akB1 {Q x}2,!zVQezj6O%!mJyȌj2ٽiDDڐ;? f Tr~#4q! :aS{4xI&5M@G&[ ?%=鍔WRxw?'yH7?ܰMwxA)7UIUQ;MzF}œJH5EN]CqR@!@c=Գ* P`Q kab>Q岒Nh&R R4¸zJgOce: rJ.%GoDo(#5 ~ڛ7,,,,,,,,~IB MI2̓t $.Pپ@G+Vz%jɬP@U1ț !h=O +jFn#S}_f]*ċ07+RY-O] HV 4-XF! 4U-( SS<Z}2Kx^bדpBQ' 6@qKBȟ#W5#@ ^~ku"`\sxѰuLUb 6xqڅz`83 ǦH~+&mAE U婹?(naaaaaaa+FO4M0L):N}RHT܉BY|㋁sѴ]Ǚǻm] ix]O5OJpD<.)4>Z`3ȉyR2@@si&tϕF0>X"d*l`V rrmT6B %?I*7^\T҇W]ZNӿap [鱍hC"W]2`t5RvV帨Pᝲ>YuwVb5i9ocG ɚI:ypWOvTܳA!Ֆ] ݜh`_=ۮ\\ZXXXXX MWc~ Ten ek,]#>JAYh7eLJ/ Z'~{5>NAO, cj (;#@D(-އ@n 1#bE.f%eOEa_W&d;R`bNe3حT1w;4%W $z蒱tK DMtY q!\Y`5B]EjqD) i6vKlB7wŴ}\8.sc]-KJ_fw{ƾvҏjifNw+وڐKOzFZo&{?k^i(?5Y\^FB?pV}^[+ìM{ٻ]_!h5ЮiNj.$kfr) 56"NH6;m@TW^>gnA;譁}ZXXXXX`Z]Tx( Y8r2 x&cq^BZ R!Z AY@zTEː10 Dl'p EehB0 D1kc7IA߆PW'!a:@`>Z3e?iSbhZh=Enz&m}L~Z$Jw홻t׻U4;uxՕ?~w2'NluI:,0 5ʹZHgozbC,aG)+'Lk%@9[22~}cm;;_QA ulU~}^oqECַ1+[]V:K40M;Os+kZLBe\itHХޭӲzkg!vg:(-J H JWYTA{BoH -$$!֝237"1gfΙ{s眙IM?gl% `_)[3JjYB_h_޾amW]wߩ4ssj댨^jAa[__ ZmFG&h&+EA3IH@XQ+](J2SU,:5dvM!PZUTXLeOz'd NO*[arK0 8d5LelĐNs$0\l0D *+8 a{XΖG*|x9;C50Ω 8LDY}A PJ"D&!P,-.%{M6ywFްn7&L⺥A86ո%% a1a:}{jX#袥o,v>kDV\@;GMso̼1p*%;Xg.g!y%Ҷ`{y2'ܵٱ0 srqZ[WiŶ9jɊ59sd?a\)-UD~вևw]|hOQ.gֵVO9͵kNZ5헔߬yzW[Wr6ws)^fwUPÚ^8- jF ,r0u˒X]v Zobo>Zy4T_cZ)B8Q]?֖c ,1`ԦeE߯нu (9Wo|eF1U5k n9Pj|jy!ӽS |赏Y ;|iS$Fy&h&z6Kk3[̏2aZIfWfjSKѮ#u , 9B, ^SNI[ƩQJqUJD@s$%ф_$VQerze|Z|Gu>V-kD 6K ,.U=@&v]#vSVVǼdU~ -%g灱ioz1)Ks2]ɱY=/)me !u`WCt|ލթK6Ȼ$, zK e;zxTwِ[)?ޥvD`[/G~OXO(йǂAޮ \?\V8`0F.^R}]h?{wRV˱TGyp` e;v]c/?u} ΉmE<;GpS]# 7x7(ɶ)i9Ǫ3]{5f]3SM4DM4 OtEg0XxI#0 "pM5T|Չ#t5 N @ž U,rql/ĕRPܠ BAJg\Aj^P,R1IZpYŮ`HD*R %q]c`iԁJw$`"7(N9HzhMT e1R4Tqy?הAYG.R<del!Ѱ ~Jrgrcj_Mث>B[ZnY7 L~ksh#o ߡk Z 4suW]<|{ԃ; %ylN9a_Q1B>:͹$TO^֙r)?л)w 4tKbȻ]r‡}iqy!.;?zvȺg[)5F,J۲"609Ev j{؆1@2I%[àwwsGn]{Fw4ppS0&,no&!_~7 {0xV򯏊f+ɋܫlU*{<,? 7Tf)f>A R &aW. \{`,r8tXL XVŅ78R_NMh0`DG:w];TxDj&hɿQᘹ'"Dai@ohM!:UWMUЌ`2@ek1[ f(ZvJ.;P PKDF$?CPmf,I!k"PXFt? ܫԩdK4TKq1QSP9lKc@z̵2|YC52lYo)@%?r\ǐ[U!Jq&`(OUiWPrRqyA6mf֛V9nyL}aK杯MV}{;ٶE;$|m\78}7\^lҧ_xӁ-ז #&̞=լ:sES].NmzS`rs&jD2R Ѷre>5/xf' iD/:]%#3P1Ԗ;6˭/ut/uRέ7wݶgPx 5y?&h&+Ej~3y"j\xPf+>,QܦJS]m  /y) 馩ZR&^{-/I}c\<-dCǮ1dTܷD.` N" o9E6- w@5)6C8L@`(Tp47!@ r'ml$/[-F،VFRxJR5qK-Mӵ{꘍(FK5=yꃽԻ 8Y<]əچs)Kr1 !-knyb?qru݂6 ݫ<ŧ]c0*r̯M/4}wO4a]'䲮mmg|87YpAvZ_xma3򈪷5MG܅QTj@P%_[]]]} :yGUygxydwTp p:ՙq(ϲ?rf6՞h=./,ڵ/e]V\նyڄ6Mv޽ܥ)HWV&x֍En>6:7/ލz8̗n:}*9kR{Y[)s]tLؾQ;?}ܵܜJN.A%厲ŗ=|+!A-#cDdd-ӱF`vE< u]K2+')MCG{Kz ^$JI~CTe Wr ]獓H*WM &hIKS.׊$ S&3g\wb߾~>пr̿Phϕ7B-N<O5DM4_+H/(fcr;tEd^nT-$2 c_@E+`@HO^CS, , )Tq AA4YH k$%q@-speh3ay Y,Ag BzZ;:G-BQ)^ӻcYaYu &+H )p]BJ+`4p -UOqt\U̳hIE"|p8 IDAT,d=%E?y<])ϻ/^ɼϽͽ :qUɣTM4DMR"@%tM ,¤.0)fHDDՉԉKAUꂁPƌ + @T8XD/`=B1V)+m'"8[V.ڥ0RR,Ygbt\ŷIf gvw0şOSq7eLZ@ˋIBJ(.{U2D0?/h&hɣ'v3 qZ!1,4#ZfE̋@v *xY Ʋ]4t )<`H A#%hk\k0O(OCkX҅b}aJDbf ٩ʪgW%%Ҋ~⦸Ex aw4|WLpz!Ch&h&h.۷l~]* OOar5(]L. @t&^. Ŗ^)˅ %:bn(pתA~%E&XlLK;*0p 9D_oWW6JN\(zՊ`/i''KT:;{D"fV zMU5+*(+pJnCmj&h&h&Z8BcΤj@DEp @&dQ.QNE`j:Y<({&r 6XVDidڗ;H| NI Қ  AȿhܔaR UG1۪HAr@ir+>fUq 1GIjEd '*7Dtb:4DM4DM4D %;;{׎ J&]5)@:{@*%y^,V] t*,{G]!@+ Z+QI{n ){ d~,6Ҷ}Q&'Qc˽c?BQ]^Y~ &.9&'B=y}[9ǖ?[= k?& .> 1 DbR꺥BG#|Ύg-{hwy7W>8`m/uOLo9~?>9] nKK/%dm~_^J][E1gWj>*245_7oy?ұ:o-*OX88jmd'm|]5(ɴάf?uOY hٕ2a+[eN黳YGu(+oҮOmwϫY={[+ka.g ^r1~utيas>jp\X='B1Y{(a|d~={LݛC4iq[07]lӧ^6KB~$\-= BZ3lc۾L,A1F#8%7s$B(oeX0f_h?RØ%7Du{,wj= oÃ9wcg]}]sf9rf?Ku8 pTF=IP`I9|g.ؒqp~($&sf:Ey- "-_!|\5肉]<_Xt76YN<}W>1666~b3us⓹vPÏSfEyKoxx@P^/9# ^45>!:-P$RK4DM4aD}W91<.ceقHR-LfӱhtDɋrTcXErd3#gxpҙ$B6FA#ČԔ 1 ejB?bI,ؑ5=&2O@"}Td(bU$=T}H+dغDTU$"pTݵd r JNZ'b `[#MB }Lt!SƔ-/L:zFB]{g'ޞsvߥYdž!q켽)f& .}_F.SıY_g͊-i~r,x8rOmJ=ûnF\+`:yޛeG;V1׺ۖpl7u{{H}W݃7tEfvbBMgw*O\j/9;:k`^g6K{%O%?[|' E{"V?n_7f~{׌{=ߵ??afM7哿Oٗ×d$}}`=`8Cף}eñ x ցCj{:yG ݺ- 㰞'mLuzUsCvxi%mܪjs-97wdgG+G =bm[eClߕ6a)k?vi.&rB\z|M|>g9&ހ U{.1w{oB =*OY Av|ЕqV޶Eg>}vhBw9k6?4DM4/zR"cY*XrE]Nh$ !myXyQub=" twbc'JEKN8wüBY w"0Y%Ruj8a816r& D܈a0HUФ:Fxl;Ԯr|߹TP rA*Q 6A,C92VʝUh5B)P(~GqA\~7_>7W,ikC=$Y9مۧl鎣O:Kx5e=zM3斛O/yמm4yge i\e;nݡg-w xk䑽|kF3S,ܳ{c;p{e;ywbpi;m6/9en7~DY_^7[c7._|qh\G4,.Ե;XRwG 1!OӃH,t'LyE8ﬨtnUcv9}-C=|HS7~ʈU;Z(7dOu;-ߌu5k ϊ=`8ֽc#2qYɷR`ZC1TwCPWۦ8D^w o{efjbDg'sn[z{،!OW#i/PO|>OMrνB+*׬g+]Azy{iR){ <OYA3[!Sh1 =T _xnwo0I8u+ ?4DM4A~,f% 7( y9MaK1 tHz #mcB@Z(])U@^Ot!%p`!Ӽ $g`)4) v}W!8.P'lDCPПD$(C!Օx!1nj{D*:@bZW!nTFŊLMB"Q$*KHSD r%ˌ$@ ziрj_ay\-P uKּwA5 q?b3u83B 0rn!͇Msm4iL[?`>t愄vhE <5{׉3gΜy??]R$n޾w0ۡԼ});4pݜ˻/6Z $-=<[}Kkk?|yiWt 0.Iz, gP-ww(Nl"97NDAA~ X5G/6jq8 ܹ݁qcȌ)7/}&yѨڎ|ݵ=#[Kuf|aǮwzrg[^N[šu|gJ}Z%i 585-<*H/d 6eS~R'kjt|֥YL&Zxu˵2M,K2C; ]I3|h&hBh@S\ d@ԒL,'(,Mag:h] aEp˽Sitica|DeZF]@bw%k]k+@jKjc'_+ĊO]~.ۤ^ \&ȅ vV eT( d@]ŰreXz rav 0EՁǎܣ?. 7$>Aܟ7X7lMpu4 }VW)FgGv>۪6_jݧ3TC}{oذsoHvo=Q?.ڟyVRV,l`/JMV%6]ԸeV}MnlMl yU H S!^IëU{9@B⍄nȣzѳH&7_ ]Þ}|]#+=oWKϔ- ~pAU}oZ-w6T:ϪS3œwH+wddvgμ4j- N>Ǟ~⋿E˱gOM|u<}YvWhBY"y8*apx&h&<.A7A@Ae`}XiLIHVN8dd"FXYA *6 (v~첖sW"Dl9)~ bg mQX  C0H18WH4EeҷTwq+(^rC0MNfZèQ@E#&lCn Nwc+&56f'-c¥-?W`nm6f<n ؖ{nnfcQKK|9f2;mNؑw,5;Y՘*_tiӹ} rٵW'\K=od kWZt8ew~QB۹ZU1gzOZ)\~s+bkTsɱbG_|voİj1f5чXSnFc0upEV%)8:B+[6>Sq⮼3ot:g 9*ÂKl:$0qAv1:;[E򯻻t=Sv|ٻriqƆ|vrnWo S K7|xaS6+>tAl{j?qόr_qs »}x}k.p?N5GD`{ީEU!3PRY_=tNwwܵX3mw >/y^7|5/#~c'~ht;.ֽC^QϯFNQi}2lVF྽kEMybmjG!9kUqnm?LcHlڦe-hq1>=mgi&h*H<3B`Z*$ |KB~+˩\g-Z@n#ILȨWTRe%>4f_ɰ r%GĨv'r! (Z/j"(Ŋ8AT$bL.|+X6P5E'!IxKN6܁O%+t$LI4 ל#@J nq(H"SS!;F#β&h&HN3s%NAOe!7NI)"iJV`8 ѾzSdX;1bmb3TMwwE ] N-;H|<ˊ9QM\.In+Χ^\ӕB6{VCYOt5DM4 u\AaT hsP(Dե~Y@JWdMPiDbQ  R dM$V'4c [ Hd:JX=g; m4Sp -:cP (VHv#)HQnfRID xVm$,!T9 a@ĕ 0}U=kJC4\JDM4DMKНZOޝSY,UDi;2Bj`5NVh\2:Ю8k@J1:$bS6"@eQS +ȝ)^Ď)B X@} ,ƶQr2VUTu%!c3:ّwlS@ddw(1wOAq\KL&b3~)Tᗰ,i&h&h&YDD7 %ep(7EAXTk# yjX^ %m<c^2`p(OF1- cjEN iK"@9 G(G@X\Q\= vJ5EYQCgU%&`kXb"M.DvC5^6I+!R39$JuPiAБTX#4DM4DM4C &KHOs!tW Ij*M=V/V(W "P-a >d9 B X*t2(Zfe.lʢФ>R ^aA(&aq8i#D*fsRșO ?]W7By)F*o#/Y$ @LZȚ9w>{69jcT1ף&h&h&+\%Wx-1`EUCӝ`&?q #L(EXOi\RnH\ET fYZQKb{e(D 8K8N TTH8q%j@vXF}HK7#(ER=>tT\|I:`̧5yH5$l0H<N=S?]̗ލIւ1_2Wb0 r‘'ZD[mvucΕI_mW)__fv<1ˏ-eyi =x!rԾ|`B߈<(Dal .nI" B5{ `o T r ؈t/K$1C\8[)Y]ZR )4/>G fXG@x 7[&d>`D UI4eΚпmBת _E\&.9&'B=y.Wf>>ߍqW, Dv#bK]7#[<[HyAn|qNp-MkƟWsj0ץe7VMܱBEv5w;4xBE䔬c OJ{αeV!ڏI%.wz:YXPh:!N_|J`/&Ko!mB(ŀ7q]IcU#zT[Rq{ Q)z/4Z'Ӌ(1H T). |k SƍTY{-kY2H8DȎ;=E vy]L(LL ;5n w#@#k,ivwf) IXf0 ebad%3 G\cо_Skc`:ZRZӇUc[HVCbjڹm!sdZ tgV~c:ڧ׬c*ϊ-m^L(6;2YΛsw~cܢ̟_ŕ)1xU="d';2[Ï3ZL_Tb^\FwĠk*1O{y ߑi<2wTl|U, H\xbN)iϮ̷:,u{Gz\rtY;fm?/]ZE_rl)'6_)ȳo/6eM3\v}7Pۃ3El~O&,Pw7Nl_&|'3e-%F2%  f$doS( P;obJDtT:PYnR*-Y̘Ja{_$LIA;T8ۑ8 HT<%] m N! 33j" #MF^c5GJnUUSV>o]1d@~S2H!'h&/(2:)Tv3]=V]W_&4ӱ[&u\a~^>UE됣 M?+8ӻUyHO8})J{-yV36Y$k<_EonXQpa1y xgBࢄ}^1uoA;Ҥu[ڗn^tM^szٔ.aN\(~CeX"7{E!Q l)O2ዑj{n>a;G ?0W//X ۆ s:ƺhWM%SE@.ֱ+\@`iyQFT ǘƋqlb y *W>< . bXdm^bA%4DO$(xD$%#e_s"E@\*_SbQԯtЧ!@fPrs|$JA>]'΅L [Fi<Z}x(L@%1(HA_H>6YLAr4G9eױ5@ȳQ]Y_g͊-i~r,誺#Ԧ#=vktnϵb qOYqClm}ܸm9GΖюqS A?^?}/w}=X'l96o1\ńp6nx^BS%gXg,~k]f~ci}?<"|g$|o^Ċ}Sٞ&~ |oq6~'Z~Lf|)rҒĵoUlwzl|86:0HmO[Cc[e~suऍޑ}Vjvxi%mܪjs-97wdy2} EWo y>9Uto~2Òu OK_l ]7jm/Rowpj0pINx?bCK"ȈtΞsv/Ӯ}`;'MعƥgߋyFPw5 lMOՐZdONX|-f?,u.GOX\ D:ϛ|pU/>\ƚ nil?&<fď#o[7جC_ۜa[Oq쥗mJ)=񨕭ۻ*h{D9 \^7i)5Wy۽_b:HWeQgI()k3x^bq(Sp! m|u .w<ϰ. wŜc]N-u>B{Jn]YD{i[0'~Є×_]5_ei.?RT `O N~¬~/p~ٳOmaHZ7ᷩƀϾ ]_F~}On/hkV_}F0 Q^]/4 dkM$@rQ.L+|.Ė+.0kHX"(7CR,J}!I/ ĺR=_@ Hx;0u?B]v.1t0~"iN'J0c"8]lYpBZ}R8YV7:#浪鄎:mT5ȘnUD//X;#0/%}yn]lW O/yמm8LmS/***~wE3;vܑ.鮑G._8P:OsMTY|݉=8ΣzټP C hyoݸhds\|e}\G4,.Ե;XRwG 1!OӃHV0n:Sh⼳F hdҹU)|;س}s#O)# WkD:)?|3y׬'|Wlٺwb@7.+VJVUkVpzb;f\nʓ~*9cTg[݋s}a`:`܌Q-CcvZѯt~Oߝ9ˆ/1Ig jwP'2m[!Sh1 =T6J y~nk.`Gv=FuL"DW㉼tmv~bGɍ}7|'ڞ%⫻5더sV0Dj;n}?g!tQ]=O޵wb ;w1ۧ7S[t$n~l0Pj^})G4ݜ/6W $-=<[?zuEut3w eA@",!Q#D]1Xc>5cnc%&"Jβw?{"I|ռ?ݽw9g^y9&pI~;W]c<RܔQ !d)iz$ d2u0', ?bXMl|7 QB"ԢƟ,DBh+:R|9ɾ;"r>݅"@s}",iL͗%"$Y `hu%,6~E|hA~ޤUlBٔm[wZa6 9m<Q>yݺͿbm6j9ԅ>kQa W*ELqaT2MUT`z;W6 )8͞9m΋;iQER9ym?3yxyKv){΄ Dhwڌ'5^P-5iL|uyu*.i?vQދkcG+8@[W[MxDxO5te<_Jc?e4P,!1lcno0ħ&paĿ+0[,w^OxeW?MUvEx;8rwx?gL@23uiɹ&3z/ =65T쫳:ogn6 qUb/;!3"=ۦgP&_p ͬ!w33_pNך!E*Ru{6jg57{Fi΋5b5IR6aI[[r )3fBf kƴwwM?X 1Ɯ4Mݨukɇ1dd_>Kz橆We}ܚ^?zx\ܨm:O.bJ޾' #CڮKI14B)Q*䫬8.b3?tw_:J4no_Y$؋1 NXlwr61*-bqp i&pTjZ-vzq8 ;&sal/,lМFggcװOcƼ^[el?p6LX}b^ˉaJw,_ K_^ "&9D(V'd ,X:9V{{8"*M(5$@ 3*")$5b@AK$Y)Rg?D#2ܔ gJmA\)@J\.1Q eFٕ_/5 BkF`0>8+bQ%l2 5F`0q1G0tؠMgSWʅIV-{?˄ i6]G2֐iqa͍;f]Gٻ̌!k}[ͷ6мHM_Ԑj?M\l#֐F=ca?:zw^awol…W#{3ofuoo(OaGgg ^\\3;6jy߆!ƍ_855*v+W3;%-LuovSC+[4i箓w]OxWhxoݣvP{^;3B)~-t-F`H˹q޷ڌٻKӳ~}[,#L,7nw 8cy,6&\ܵvHMo[Dy{&}m0vaqܩ 2jYz;t'MAc) zx'b|sX`-74w͘c7^K ^;ͺlOj]Fr ze3gI3?|-;cQvcG%|5~ba*X* S "hB-sQ3n aa]D>|J zLL73y*Q%؜zH<'#l},Y@ub0{GD"\Ԧ5|~Cy*F^g15H8OAi"[@Qc b>+a:єbzb}I2R"@BgP & PTm,W,;8@B((IQNƯmەygN>8GTOZݧennQVm99=wcP7shqE3{ʡof u{x֣~~cL%{Jܢ7k>ZzT b+FF@g.*;0Ozs^JkytaEo"g؄k+lig흴N{U-+Z6z4 {ɡE.[㙇fx3}N*ܮAOM_YNez}}˙*1U9<-e# jbAs7 lD}GL?uzgZv _6/V4jTc"75vQaL)fRF֛cl|̴:3ȧxbLNAٟ޿IcHSZ", 7-g 58et.FspsC704/вK#l:޿mtM[?RVji=WػIѾ~Rh7+HPYԞalOث9A,h|:887H k2{?3Vc+\>S5i:0tǠ.9+>iS8 6<ҳ|Asg\޷JI[?0@ať8;X77sk'uef>N-ZKƄ 5)* ^Va`zwQc{V5 1ek9УrR((>v]dʺ߳M`SϖhS1j{KY m0RՖ2 GV;F^14@b/g㛸im!lxq/RyStOԺu>QXeO-޲ZmUvo,8Oco*^mƨ1?)0nVG)$A t*C|Y" 8 ^@|S`Eo b#D2@zX]I:2: l≉d(auB9@|! r#B/!D܎ATK,)&@3ĈOM1 joƒ.1Cy$LWTXs p 숑`y% mC܎9 ĝ` FH/P $Ф9E hHR0BEs)b0aJV1QkZkhv6?E8$"ΒuN1E㛬 ?̂L /h>ki{o&xT bHܹهG*g_[cSk2>^.e)A =g,6p0λ;Qovo}޳&ȿwb)Rbw-wn@L&wV .JrxuanAAA>Wo/4 B#kb F6XYXeY1bbͩY/ h ƞ>&,Py,<R+j _}]*Iբےɓ/%UyJnӄ"2ǔ@K=(0KE* 7HM!J*Vy#3-+h%]QH $H,_DJDD 1%\8[@$DDĒ# V/P:eDHIW5>HozzJla[&fr_ZWˇb!%vf!+r1!Yx_l 2ɋ*VG$|Uq1׌ @@Wba`c5*$UJ vI$抔-j:km(G$w䛢w+,2V`%0HELDHX.$"N %nK(KoE."@A% L2Y1!Aw0TE.cX$T Y~'-/=*Vkr2tŔt%o(=m/9}u|яO-Ŧ /Xb|l_̘SWg3c 'BSC,-\ꎉf) aI+b5@4dG_3 =ь @"u2k^'n čE&ے `@-0H/mA/0TI*VDyL,VGoR+"UA$-#_L6(2YL̋HUb$DU” I8h :{1 *Ik1dx;k*VXJU>HAi([Ԕ ߶)1D ]i@S,(HvKbZ&Pf0$0AtrS*@`I@F ^'ݗ֔EO0;5&pU26Kq,\[d,HWU,wi!~u,CY] D9ϊRD.Y`%bX*VUbB\tROn}MX([ gXHz߂">FZ%_҉%\L7@7(, #A@%,":&E"@_ N6ԥ"QQ @KL"z!ZWU>I,/)x7rJi \TJI(ef=W #14edDH$V$C֟UbX*VU>`rIZG`@/D<;&//bQX! k@+0%~%@'eaӎvs:Y:OȜc2X*UH t8@Y x#8@AO]s:RZ$"6ae`#rӈ[b/ |t?$g!sJ4\S A"@ o $/d7(SA)!Mc Xd]P4K&$?"N[TϖYz9R %Ĺ&o0edH4UF 9|g TD2Ai:!tUۍKvtoDHio34!u;&۷BT.ϥW+ξ4r1뮤bxMĒشN5O<}3 ? 8ʸϼϛ/ hWb̦7ֹyq[EUtF>s~oIoENe$u_3#i6LY!{aӯ,![oowhѨu=B(͸uS 淝1i[k6xc9_{|P!Ub tcTbd x,VHXX0BRNw]LT,\1OsYVf9k{bta iv]$+HJlL2Gip07N}vD W,O XLSe@ +_V)4N"8t,+fDb^!Z!$*hl,ܷp8BH̰Y <,W"%ȜPCܦ!#5Hb iߐ N{9a5ܜ77w3 w*MbOЋB-)/5ǧ͔ݏ^geiˆ#ʗpAܦ^MD-p~WkL&!?}O/q'R1⡜&em2aƢH6{[j~}3 'ODuW 6-\;CԨA'?RzzYNn3Ӫoe}).&a2!7'ƭFxer +vw,%#ҺKo!iЖrO]bz>f2u7ίsK]~ýs Ow->uCl_NUb#SD9H*Ks-@`:BsKP=&H09K-y\/FTG6&4o&Gqzr_q0Q,G@K yD^,2p^j >"C[s141\JWI8_F x_`K%j["# KƕEH1/@on X,/spMx}WV\P^DCJ IDAT | w1%ate*qsvוp-UڽG G&FE2jJ8:iDo^HNIVA^%\T w,7CL0 èmKwmᄇ`Lr0=iقFH1` F`zsg:t'i0^s-HpN?c`3+8 ´F6B9t菷xddHnT@Gsb󾃠GSSPpYO{ +΋?h`xB'l/L?[ͭ㢂Nبߏq>3[zjp{tΥ|~.dsݷ;#`Heb皥B~ucǾ2;||. 1aPV5 +lc![6ֿOtΓǦGGt l?x"g1K!*4!aAi04b8ExT\2NOPgޭU#KƤmQ1LEVtZ+d<:8CeBДFcEC[WAyԍsq'O@{֌ӵ]xHhV5⤲B(`IyX*V-]qI2 !rA_D pZz]Oe|́}= $ |cI/D/19XQȉ7 ˶{!8Lv*"5+#:pt%"wKtG_cG' rH Ur!H1"\W`@Z\_|oŰXn$ y WѴH:EoH(RˋIy#VŐgF[GSC?ۆTf=w^J₤7 k{j%7 Ne>s4]etU;LzN: zǦKkؐvF5=]bzumf"< !cDa(|YcPo0/Ƹ-ㇷ~ج60`IZkg3t_lߵNJ2Vh#O9/nWQ08wTռAi qqz؆?}⮟OcUK_tCK Ěֲ-|_%U`|yxdegҧ+S3Nj`~4ww_ey&.1+;5jMF7["lyF/\9ĿC?ƞZGX 9T]yC3fb__ߴ|~{z+#w<_3Y0>E{ұƹN-WJ X[ae{nbϨ ;Ko;8,qԫ"Gpt݃qn}xU}zfP s-1_&&do4a߆oܿ~fn}듻TwfI\gb /M+˯02.u^]gK5sZ!7SgM?vntTQGs\\|{ok~~*nx^Kë.߫׎hVbp#}(2i5_၁e-mIWj/-9.]5qȾG%w;μ2$/o]ҁ#*&/Ǧt=c,"u8IC>+=6V14Wq]m侀+0:qm޽{ݛX7jT)O`X*)DcSQ_9xɊD,+F›A/Dlе͊2 @"v1\C**M.zg̸s6787v`LX3oᓾ8#{=z57[;9ξwj6A%_;^Z h-"ڃ7F?;_~ק R7}[.=xdO[gHǔ=:VsQٖ 8 #SϯOشM9qEN9oVc~ޓ[+l°aQ@ÐQ*uu?/u.@6eh~gé$Mz >ԩN?lB¸ f#&I᳃c[OG kծc[bqztyoB]Ut^t5`3ooɳgT9[>689+'|!g+p,o06NN%.;~ً 0N5rmc?^1}CN@hZefդ\ 5Be*~⤂;5KiJV:qpƪJ m 2ܺdTϝ զb Ҹ1ݯ#*'&I]CFD M_uvհjZi\ڏ~ubt5]HIڛӔ `n3m-NX*V)P|\'#MǮq0Q`L:"|¾|x$J,z`Hπ`-RIڎAK*lY 6Ⱦi^}3pAⱉm'ձ.ϟṋ|F렃BYe*v'ӛ{w9hAsXNHe?/wʍ]xs/ Ӳ3v^GOs_ZWFo!C>/Sn<|VE=$)H/$[N˻sFի\fe ~uvFjm$3;tvVURkЀILD'|$`Y.cT ] TIMPh^鈩_PxWT|Y6X#L"֒Č5o~~MD"@$wDKtoXDfibD_H<)!d MаZo*VD2)9| 2`ϪPz'I `{c$[h'd|TG0"F6yWtbj3G[L+$>N|p-cxEwx緍wtrrpri;g=OFԬb'f9pn@3)ۨASyG._1ŅPxJ6US1B|>`îbڎ&༸CUdN:CYiz\M3C1{}{m$ Dhwڌ'5^P-5iL|uyu*.i?vQދkcG+8@[W[MxDxO5te<_Jc?e4P,!1lcn/Yxq4%>4 8?%_yG !e`h|+㼒nr,#$yő .׽9M<`:Ը6 ֵ.-9\Ѓ:k#xO~]Až:;j{6fðgW]%BMHĐI}`Ǟ]vmSkς/fp>z33_pNך!(*Ug~VqézgQ?8/nטv]ԛ'J5ۄ&no\f˹2̸ 5yBcaޟP~<h̙)J$>H1 FV^?Iyⓜc%Ke_grÇ TqPQZS&1!*=-}sn|{Ng ]"lƕOF 1bXHx>S;8@?Bf8) R%,XB9I{ۑ0buS 1w?lߵ9W"w�HBHFL(ԜӁV_ B/BL'ZT@HWdMJH?q1?ۅ$e O J;>__ڑ*($eH#^AΡ+HЖDe1e>qN|꛼ܴL?ct1lËWxSP=;&bts|5F`ٌo<ԥt}lR>ƟZI"+)c襇Ggp8A܄ŘǠfJI٬onSёIvemeTtDZzuTx-w5=C{DBR%[>+e2(e|Z t_j%-B[ߖ}*nFZ!6ey/{th=j{mc0`Cnjܯ^1eŵKsu.%*D1vEx-O3,0%]T*YMaK'pyY}Fƒ01M^0{s6\K3`6ɱeKu޺/}|x1ѕ-cƩj,>8o֧eY@GwgqڳAg_ZXyzNAޛ[{oэJO,-oMXpb$q6U 2aCڵ 3wWѤ5d<|\l`sY`Qn%3fZߖ}6}䳍5TH_Ԑj?M\l#֐F=ca?:zwRƹzv,\x5W=s: 6]6̝1 |q@b`Y믤ق̎`޷aH:q/NMqNJL`d1_߹p=.MnA~fүf^i3alƆ3M`_s?ƈwv^9PN BϱI͕>f!ͳ~ӤҪ/98ņ_[ ؔ_ʷl){u,>Ώ>Ŏ[.+#&Ub)\"CƳ 7bq!P lrEb{R4ͱTjՄɢKv pnD|@ ԦS2ܩp )1"ғ$$T0I UJhlM#FFG@HR0pRV|$"_Dq <`I[+Œ&f&`Dcr_򊽤e\ }6d R$R WC]:-Jsln*[GF8ٕk}?!} [6Z <)=vN]TMm\^rhYB݀la;0S^R4:͚ϯp\<ιZ%98Vƒ]TvaN4 VŽZ->2$i3;J|;VT^ϰ {VҶ;inSTTM@Mkè_rk< pfаI3qU0\b ^_qrfLVB1x/o)3UP U`& _?bjțWŸ:=3[P/W5 U]f_0 d}3]wt)blM16`S>fZK~CR1`\h}}ZkJrAٟ޿IcHSZ", 7-g 58et.FspsC7#C%Zv䏙MMΟiGԾU]j@1m6{<62WO*Qfi {9 3_{6:p'_Le=bk0/kT呞= ;rUJru S..޹WJN1&F'] rY@U0T~]EcJ"kU 7mwZ^եFU1|Xmֹ[:8r̭vq 4Hmb M)0a{`Y F~*NbhX*f1/ N ?fnSQ g. M~ IDATNx!є#@\YICm  $I!@t Z9WRX k;' ($8^X0H 1%M<)@8 .*@BpTWi܁"fxȊ&1(f؎Slx Q\0`YҖ(F!?BH\aoh(QXnwtKb"Rsd,a!s-B B bB 0 P4*bZjl466vWSdTYn=2V}u|uGV5YI'ym]?#L~/ : ;~=@3קچfWFKY|uJBY,绛<8F5 GYxqNoAbX_,wn@L&wV .J*izan@)(/4 F5L&eeY߀1fY d{bHP_%(d[I6H@b:QK> YRUB]P7WXBorpЋGoRV[o9;rkzzJl 6eb&w P"+CuŐfې\L{|޷|mL(À/8k_XUb-,lu]#Q+XqƎi"K4G( tI "uGo  ྐxP ,B'"b$SHCX!'7% e"@ !y/bND6jS>:Ăj R^RPz"RLjFX qaLuD8+uKr+"m#d䎼*{BKhC~U-*-#OWLOW2fj<#[Fm|i+"c]W׮~ЪMYxq{Gun {޽5Ube!<\҇Qii^<&W%k|!$Cgz]@6?h3a!\pIň+4$ Ɗ~i^;F!c VE+;L1(Aj,׌T1DyKbNX2 EK@O2 `R>9IJRDNN]n)A|XLUhZEvEi%C|f" v(d߶U/dO@[n;XQPUOB]s!ssY{Vyj9`˙Z X*V Z %uxL/zߩCyh `.,ERH'M/EPB7H1-Yĥj1 Tգ4)>'| I0_a"x[ Nl-zX<6R #b3gn8.cpN#K*"Xq%^@% ,CHl.ȏЗ@M\ Kij X$j+tY%bX*VUb|!J.uyGx ɖETDXK!ijYuJ4"=@)VyԣtY7_vQDSDn?C6}^8@HZӜH7rԈ'=rPS-`JmDVBd[嬄%!9[\):FJ!F" dD2q" -$IY%`TJ9X,:X*VUbX*Kh,AY7{1&~\HHe—@ ɓ,P%DT Dvw @E(Oj$qKCQ(pKO|b&\E"Rc ,@\4(,K#U u~,MX$ edlc"DqMѼ,Y"@+u I'EB*VUbX*V98qEHX/4NKRN'y-֖sRSў'YO:@@<' I1q5| v^(ۮOC2, H"K ([."l.UG$Cd"F%mw`kQ0@vp@=@$/8"nDTmЏk@[D@J3 %SAgy%+G(WO[PDcގ/fɩ#>.(|ԝzԿ,ipa?Ŕ#'?iG9؁'d??~!^8!accoh=!tAOS )1D&Rc R Du"R̽ƀ$mtZ oD`%"@4 ˈ?C<!nL3G:p@DIυ@8) ԏ6,Za/cH&',Jq0'ؑXPСXtM #"P"Nz!,uEAt |9mpz^[ ZN׏j z7&yC0$Gh9rjS߼`xMĒشN5CFfܛqpqy7g_~ڳŜM5T nsⶎBa}쿟~C){D}آ3]0_dEjg9|΍;hT!fܺ)5"$lm<.|[r %C[(y'/O:F~!T>r3 UwzX{Ң*YwªhjQ8TOXbb2_(hPJ(b1^bWs#h3Vk I ( V`ۊ,fŒӼj"GF5 !V XLiMЁ(@0,=R FJK<)I#%T`[` c9U *5|M\zqPցx Mܥ(E r6$FBYn\ؔaZ;}hU1$r6xd2fZw]q.@S.ʉhREf~O>aL}ɓ.Quzv6-LŹ^muλ\5^[V[/>~ufZm,/d`#l[&T$Ѹ2SNrandd4_Zv\)K-x%|__ee&on_}D.5֧Nx[_+ZI!+BB(`-QCo?6fhB.vdK{{YaeKZHaˇ6j=*ojb/fXb>$R%/fЈDL-`\Gp_Bg)yȮŻ,` 9h3?4xkͼb@|5o*1 Lrրp2`cĚ}>4#*$ Ѓ`r#7’@"ɿ T^`bSry8/yL˫Hs YQ@T"  iB w$t*H$ٖXC _$d/`w3I G~Pl}7UɷGua⑕ZLmi4xb=NT Y`T*aT;yc2>>4Wba~Nk{E6t ͺoVL]/P`1n>7KM9,7W7-[)&?\P3,ߝhYLol!X.㤝w3MKwӡEQ҈LpN?c`3+8 ´F6B9t菷xddHnT@GssQW=r:/MzrtV`P+8/Ģ!ϿcL?[ͭ㢂Nبߏq>3[zjp{tΥ|~.d sݷ;#`Heb皥B~ucǾ2;||. 1aPV5 +lc![6ֿOtΓǦGGt l?x"g1K!*4!aAi04b8ExT\2NOPgޭU#KƤmQ1/EVtT|H$ʏ˔౧ӌf\($p^pI ײ!ywԬ:Vֿ] ܝ]7ˠX/ k= ,X#Au.>C-5#@fcﬞ^!; a>!K% ~:sϦu]yX%BǨRo٬r)Tah,?I 2CSjsI)g m]!QٻD6B A{X EKR][(H B@lv2W6оל{eޑsH3aߟ3[cgX{dazm|[zk3k1R !z2Լ*u/):02NiUu-\-au{] !;^zGޟ\ g̺aꐠox&+:X;Um3t—"b>Td77N AHzy4CG{{ }l}[ogEqnRr>ӊJŝ~@/z|ĆVr_"}M]_ <;w@+_;o[ %q[טtB4m  벝!EO6֦jhrj4至aebIIBb7t"% Hc&18 S+9IN>dP B/ya(, G*dAo5ɧi7aR6TڕUFFW@? H@G߅_zDŏ]q>#vxl-m!R1Qqd*|Uz]4 ]ғUlrmF:(XXau]mZ{Ds?uVe-5+]r{aS'Hߝ53ߑ㳳Kx\!2d?uGKj.àKwST'B %)^շjn&wu:`H?9}3~<>c3WutQ0%oƃsۺ! +"ʍ?8d/@khsoW]'v_te[61" ]{Za}}Qb͊y.w^HG럮 |4v؎3͵wLE9r:]}`f3>KvV)κhdD- 㮮WUctjޭ 7F;x¶.q[t4X6ĞYإ9(;{z п?=ǞKONvd_</>?lܺ,W ~kve[qǠMyW2 tVĂwkv F ]~wGD\⡐Mj:kJyʐ.^ ZmbT謘+o[4[ G㛶D nk\p~*^N j;w V9| GV3<^ob|ù.c[_XyE{0Qpj>ew4]`i 'agМVjDDĉ9 Ȏ,;$ ?(&ӷ3xBaͥv7} as܏26z`j`? 9pQvxrYV/͓:=eX! LK:<ݲ/t4|mEɪ~w-RBDTF߾kcJyvjs7}=vޕ @4 f'%~JN~' m; =lݵ8]bcۧcny\v9}ޣ{bO coD]wzF4r01]Njfڭ/E ޼:4Ϝi~m҅tۿsb#'?U*L?Lө'kF&*qvdž/V|j֨{tR}N:'(홌dE>5iB!Z.ضĕK ֎ԟEHdp~ئˮOéV|'tH=1?Vk?3-ƪ 9A .O2j3R ϶=qcL;(`̪>0&&&&ɝ}S[Vu//3װDdӆ!YBWDLwEЏD$cZX*b4,"Rs(#|@r6 d~RAC^so ~F m'">jGdO1gр%t K `D+ گ4|xx,2de@})S.Yv1ɧ`R/[9GHnCd%9I<#M2_]6jRf|LeRUa;Z*xhmt_p谾5%}$ڈn ƶPHoz{#R :ݛČBeY`|xMΕ-±v{[_-5΃+ Z}K}Z~3%EYz8m7R.-Fj(2F8Ľ:k4m%Bf@Pz&[o5r5C 3\wF3ˍ2̭a *zq6SWh&=Ei7vZ*6JkA5rU#JSĉ-s-udvwڽ|lbWu])s@:'j 3uj@fnMF`DbSɐea6{cCZDڕ#)"+]xguu^\|o{~>nP5k$mkd?Ld7T7xwlQ}bøi vi8_ k@fۏxdYf54J\L_tH^L,V45_dgPg5wTKWy yjLyJ{KxJϪIØ>/&|+(߻FW}0 MK8&*(RTl&oB*p xVɬfYF}~Rm댛FT|V|ܮ7se TN5֑BҠe@5TzN ͸ ڏ @-Q sm6W{rQ ܫMw뵉ע͙;l}akEn}fe0P]~ \2+dW>Ρo'vaMidǝHjez#:]7:Y(Oر-ҢIUgK%,=Z RCQ#tDJ$ɍ>ݻ3sBwl0O9[7XϘջ Qvc&:;,[uC`ӈߊ/^Fdbh; @Kb|lȭ{ | f v%}f͞c⠃@a~И]4Y-0̡BىAvA>xeX| O$eq|[e#d୼KXG0Mr<20$M̲D$O&%cᝅR@eA9enpWV՛R~V##Jy%,Kksr+_ʶnm@a]޻;@_T.z~aXHsOֈITp+:8Z%|Jg{͜8eƲ/GVD*ƭ5n$fֻ` ;~MJ~ϪVt,<<P{okw~q`m@6{vl)#qvBJ s( yI}8Bi8> rvc^P*K N6EJ35h o&$m% mf:,3Op숪6u” =kۃ }n*谤7]ptm:>VfIsrVF]JAj^-E OPэ@iiwMpvq`c)(\tiPY3s&扃͙NfeW=Q37-~ݸ&o;L+5f^xjl{56v!ü@jt(#EЁ!#(Kʾjn޵)_NuKN7@ڽ}k70EVCN!IA&FI ̳Σ[zr-kiJVC Hm]uoq!_yw8^u N}MtƹΝvXN' CvԦ/:cd-+f\XWiu+/W~/VTƿR^.H):+{\,AvR+TE&bsoorC.SZ2NR^[-Wg%۰n{o j* Jhٳ#Xk'fnxh dr^uqn;R]}\hٌ0  ť"DEi E] 3qЅ,(Bj݇7+bڭ%} v^*n8u'+:] q3C 6f P+YT"bW<ʳJiaVh=U) >8xZp3ݯFn\Е Z,WLFvf!Z:Bvh/*.49s9I ַ"åf#uHR < b-S MB%!p!`ԙY,&`(i(I!wu$,(" 0&hcފ%dCr^#TPH.•clxJ`?dYyt%G **~Gw?Js+[[[[ ֮MhW=2]i{e1b BDk+ԒzV hy ח׷q.D<>d1YV9/f'[Wnܭ=Tp/N3ԶP>7]{C+/Fm?Pؗ3TGcpSUZj'UEt-b@hpu̟T kCQ"D/n5|:\/LOscoJ=9}Eaʽam8<O-sW%]IxDt&7%(4>^PH4@6)KhHLH5+@\\,E ϼPVnn9ƿb0}t2PłwgOc~Q1O׆m֝iv=mmSm\/ @;Ӥ(0.RʾG=W]!{=+quv:Gvp6+#6R :dG9L+Ч]Y2SreA% &;Nrb}헚 ]\I _JewgI-;1-IC~뗁#{9 (Je &0'Ň"fO҃@Mͱyyd*pqzBzV V|A'1KJуpqFyQ?.\w:wK fL+EwYw8^,`S Tcک -8O[~[ 6wb&ע)FVCN՛N ?7WEk͚9ǧu~v#3!yeTѺ[MiucbÛDy!O}|ڟ.. ZwWR6iGܡETHW)/\hvmUrB VT& w+j3{ĸ݈Eiv==bV_9"*_T ZCżI$L \VJp\9fy_d~F"Ui2=)MO-J(k"Lɢ7B5غXUxrML؝[K܄:=AⲰ2A9y,DRoLu:]c^l_,jΣ[.n.NiiD(lNhiڠM5o?O㚋ڳp̿fDK7 NxS{shoh]1z}F'ɹ%)-ll-\ǡscG5ǜ=@7uY#ufکm%(ݚ ƛ4]tmw]@!F(sNKN츢넽/ 0gyuPOF3.v/ ^eA~&tm9saWkLm>1Rjl1>ɔwfii̭mm IN .mƴ6+EB>]|K*0q`Oa͹5^+[ﵘ.;|ǰ0' 80iMhwa]*RYX'J3@8_V.OڶL[,2Qt۲do3=%_9{;]f~qavroJf XPcσM~y22ɆG.%jWAEs ^fNmښ`Q9o%J%$&`m‘>}E_v8^+h({įy{43bGt.KcK ޿nA47#_}.(.I~xpBT"%9QWͣ.kWA%se^kW+.֦69yVtk/os/EM|US@0!ҹ~[5FjҬk{WDw6>=-gz X49[T0vͷ;ҀimvR̃pqENaK_^V#!Ayweo9-;9YQ6unt-tqF\b Rٵ,NӅVJZ *eB#EּLa ºuLKi*xQ!0d?>鄉C*[?.iz\;RuL_t- X_mqmn" zgrH̱Dn8F4{(oLMr+vD/lilP>=JPCP&|FG,zsj`OtF@pȁ V#nk=*eysqn!69P{Hc@PqdWE 4  #I`9؁  .ART BoL@?H.#d1sa/B8/:bDQ!4SL4,ˀdHL9&E R|* BDGIIvjG9gh^7VDUǚ-lh)wed/eR(Js&[>5unGC!ؕYd]{b=,(;tAkɱT ^6결BNM =M8ukذ}i5+,۶ͬܪ;*^3VwP(46S.Z_Hzv9lsݻ7p* 0~"&f{qe7;mZvajS; Q>-/\"2ŝߣBGUi;'2y c䱷m:U2b"ϼqt wBo4 _Eb>6bϩ)?wrVP ߮ߜMҖ8cʝڹV W:ڝ ;)Y#rh%VPP%cfUB! xPe~}KYy Kvm ͻur*u}ҠMJEn߶ƾsv" Y՞s&^իKߡ#li?9݋6|ᬮ2i }+@pۆz9viuPOy?)Ok]-B 3DcAvXg΅VP]7f񬋬k_Mϰ΋ b6gqFmُeN4t l_P^)ס=Z=2ҮsvɘD<[Mtpk㪫(Uw98 q c9wCZJw>oEHȺΔ=?8bel9asY(ʶ l=l$_NAϫ ̽y.-[{(kl̽8|ibӞAw ~We\j/&6d[1|m5zy)L<1nW$C+M8USW 5[Z :dEԟ~|{SߟnC 7KqB+EL VhoZppf#;JU))J+x>O\-x+@) ;u;l䄥]wf:ovu}%ǚX-eSoڑuwU bO.,"IrqP@1bWĻ  KPx" F` Q R"F'c Aи4@ZP!c@%*>%/&< ,$ Q&`JѦKW,)wﱅ(t f+yE&8 k)@(&#\&Sd` ) ۔-qd ;k5ƀ(]gΉ4HS. !BBQ!( !B(BT \ef2S+,XdѴİH=704e\CM?^x޽=d .46?n&q~Dc.K2ݽ}{G'}=RWL?g5΍S{M{siP+_,LpquVF qK?gB,Z?E냂\`iV&o}0y8(cT(.!2J EZmVW՗tZu@MiLӘƘ g\`E9]&005R.EOy{AlH%P DQ,m`sЏ0G-|A2PHpϥ,dF P<<' 0?@ZHF~eGb;$(^)gDlBW<czQgeyg$ :ۿMo]jĦ]B|"eo'5e*9ef?uE#rVwgxdcᯖiX+CӇtÝmҴ)jkbR i}n+t\ʹ2)?E0pz `@6=^@l#疚.={_tMW5YQ O &#垫5߆̬  ]y-4eG\-5k.}?c%&#:)@Xѳʈ>!l-F&D9^}$M])Dr' $܁n?Zql@T$ⱸ/ʔ8+UJH B@p޽ago/Q8RD(MUfܚ#sV=R֟##/ 3MZSL-C^jL'O3'?!ϣ{SW9J-2e;..B"p'{9%{ -"3Ւ HWWbF\!`^lG 6%ʾa)v KJQ׀tГD_o1]dI My >0:5B}l k! 5b ?I,DHXDk2& #M)U\rؙ*B\2$y%!ź, n $@q$k|5,`OB"IB⁈+$JiMRLʤLʤLʤLʤLʤL0򾓋+P 4`l3| XYz@HwH_\|;Al-FMuR%Ba 5 ?ev !Y^cBXȉ(#"Kf"[} #*D։s!fDDi'HpXZDPqN!juNFu偅c{5+'Iǽ%\0C+Bo=3%B$>i|5}n,݃V%N?;܇o?nfZ>?z8F|ny8t.T _!|Z󼿶u[՘4rO:k]OB|N>32|jGo{`MOwIxbü9}zh^!v6g'\rcͨ@WP@Ec >ҧet^! 1}˭Z~~gX'FI/@%@<-\w#:L,`RHD<*Ɋ1Go#6VWtvV>yONyJҙWu_X4tJG/ y/uEh,+u܂]t?5q)иn?Q&eR&Sb<# ]͖,s,"_!!^.=a| 9,G4 Pbob[rl0)1%|@#()U-E LO'zL  + ҿNjb XE q I_]BP$ZBD6 GAy *,YdD&ABI, ƃu[ƵV1c߉x={ԺAuO'K!l*;j,5v]=*XI@&R(UFQ>4xDs'E)n((Ji۶_g0Ml۾bѾ'R ]Wh(a5`~on/ BFia:wJ\{pbi19O?iڭ(I>]y욏"#]ݭS;"\ +z_Iֵ9KX} BG|}s#Ͷ0Šm}BǮ- 2fzѻfײCo^ hM/.Cssѵtqڻ[twBy5 [a0**)}f #' Ov.67n%F 6dbؐB=Ob̢ ^\ !eڶ{:]¾)c׵eFH&ysxr}koв,d\r' Fqτ.~kyZi_ϧսgygKӦ~Y2o}VjqKBj!0tɩ9L_ƹ:سjƨz8zR6aj"Χ-Teuc: waM#||Aۆ/΍:@qZ?0 c @cdH`-/;k{aS_Lɒ3/u7ңع-l^P$8>o(c wEO+&; ϛTRyI5Js׆CZs$^ E/~3|΀:f**]M/GTVRcX|96*2bJ8*C$.zOEt>{XŐzrG)zN rK ֦4[ BNp6Lg_C"3yĽ@z, a jTnk+d&ITKUiP?H+&)JxY< ,1sФ7( A@lg&0 ԊwSÂh#Lj!9 ]wU-89EE"C͇>!A*$很$.Oujah i&sX+(IG XCWsh2yV?xFOy}r)Li9Q;6յ5i&]XkLL;'6r X}]jS kҺZ/0RՉCIʯWFN7O7|4 hj3:s~UGХ^ѿu7C8W7R[WD$QpJћ_6n.=,»Oo˶mcDn^;*Ś7=/:7]f?]hfk_rt ?%@gF_Y}@rS`9ukȈ[d]]ٯny6p myӄc{fa(U/9(@{*.֦?=:Ғ}|cXwq뾓\19F ٕn6mg]0Y r4l3tq=֞qiCB6ZHx#w2llŸ>m:+.C>-<߼B㳹Uk{.{‘ Wp>>be뤵 n}?cOoh9|D©wt5/x=OtȞAs6/k[}'4fd[3=}Qd'ݻcxeKn/r)zʾ-#cL?Pqsݍ7}ߵcܧ #{͆أOCp\v]Vs\I]a[҃K.~u{OYy6gxsݩY3I >>;^yY%uԮrB 1>;qjƼjS>K?8ǃR; stAs<*5rÂv<ω^7j/+Tգu|knFds}zF]/%/zya-Ȧ C慮+ˤL&#罹H!Wٍ ٬#nC|>`,{E dR09fn4>OX9hÁ[\ *kIga|<"`c A%l1Z" v<0HuM a b |<Kr>_W_{c1ƈH"B6 U6AR&J,ad- >azҕ}L+ s7qBM.)g=Z2kvW5omԛϵf|kKl3q^n\ZU+Y]geKqZױ̩<=m+Tr4Z6bT;OsE{W[2iK Qf^<((?w|p'%Son4{X#W54:M؂8D8|\J@aWp{*ZŜR;t[:sv0cZ dd6J7 YVfwL>0E_l<]9'm_хyW_w;/ŗUFҶF3DF?{soO}~!Q}{bøi vi8_ k@fۏxdYf54J\L_tH^(C{n;3]tXߚHIJO`lK Tw~7"UHSsE}9(|VsGvGАvˤG{ dοǺ\?4]6jefkk7DY+ަ d['$|A)OLu]CDo`=cVZ*Diڍ"M^&eR&.=4bn dTJQ+$ iDdg :PO!'؜R<7#gDoIMQy"@*H_ه2e96(X_&쨍Cmu`ZVK)-m+6޷~>g".t6uƷc#ZLXwL 92W}e`*@ָ 7hxפo_ !?5~6w 77ai1Ǎh-Skug8h;̡D0%&qaS޸S9;1/(S7fiQi}߄5JQb,0S5eau, Zx]V[ :h@7]ptyTջMYw%81g():8?e@YSuD1DJKk\sdfc:xCqn=W*enmk^%3~SP6 K;SibYU}E.~srGJul)ӃI7꺼.. (1lkLʤLhH%A>0Ƚ@dolE *h#zQ1SqE" g6@jgN4(h^A.{w/ ($Ԑ(h&aԂ@y"ٔ lA,Y@edgƄlvJi9$)ʕ)gy?_@EWȂnG\bd.^ @j 6Cd1:J =)G9 5!(RT +2͢Os7W߾4D4J<>ߘM3o3{-RB$jKk[[[[;W_m{k7tDLnF,aVU`K7O?ֵA k7OݭT˞Ph*Kf>7]3WP.b=r7oh\TD/J g'\>ڣП_lѯ"2,=[ _j|IiB~RJr}ڝ۷gv+jht^Y^GM9ɆgG(e\6UFDmnܔTpIA6)KhHLHe\\,Mvf͐6IR{UV0O'SwSυ1& *׆my{v5ڹ9 6 T@ɐc9MV͒)^d|M}a3:nёnI"O)22!=r'C  Jk/cןZ~+Od!˧TNMw|r[/5ڦ3zq᫃S;-V.<CPNwb, @x0oyPtQ*9Q8?K[s7y=6JonfD7ʵ~ìG1MpQ޵+*@i_Ƀdf.cCݺ&7WAnff˾K}v=#Kat;E)<}<b#(OX&e[‚CfH~ۘXA ddax\MDoL8E<|.J8 N2 1E莅YbaJ?FMzGC9X{Y%y| Xr0C%J^ ʥwT^lZKD\H3H҈$EL;04nK ޿nAK+ZJ :NoO}.iRznQQއgVY]i>g_qqpޓ=2mlr?e]-ti9ӃgNFf<ԯ 'й1ǣufzEM~4~ov~H]YƭvjE J惂~fr1M&][]D-\Mg%'~v\up3׼q(12oK!_4X BQf0`]AګX`6g )5vJI.@qdJt;Qo4P $oyWHcZ"!.IzNեEy800]ܚsxiZLĝ^cXh 80iMhwa]*RYX'J3@8_V.OڶL[,2Qt۲do3=%_9{;]f~qavroڪZ6K> wy /OFslX~yo_rvT.?aoF]Ԧ &e6rj.ývΚ3j-ݔ W 1к#c2 GlO|=~x)u΋ sZPt Gѭ IDAT~~7UKڴ4"x܆.ҎStPtfE9.uYHJe "so xPJTLJRDAN'B\)B$Q&]%$gTjYɹ&ѿ;;v0Wס?z%%۩=Q.{(~n~65,4 >nE?ݺfOG?^lCF*!W- BqݥƦ>2wbg a@Yumm[fVnܝY/uqE;Z(N)gw-W={Hzv9lsݻ7(60~"&f{qe7/v(,9Ԧv|Z_~9Dd&.;1G ( vN616*Yݥϼqt wBo4 _Eb>6bϩ)?wrVP ߮ߜMҖ8cʝie}]S\mfz٫OZ@oUKlT cK̛-J 9- ̪-l;ąB=L%ʱn6ST@@wTM[A,5΋8mEk }fGm wY՞s&^իKߡ#li?9݋6|ᬮ2i }+@pۆz9viuPOy?)Ok]-B?;?so͔ID*Q"ĈĨڱwQ/E*mF͢W]M"F$F~:3"?t%79yrdc{7uxp6Zp캾V r l]qwUc_麉j9vpɋ-6h_CyvELUvwt{8%Vg;gL{zO~߿KOtie|rpѣ#k2םpI9MT&ڜB2n[^g]}̍[v} }dw]2m넺 ;p594~Ԗ}2i:Wqѽ->N|DƯ7 .rmU!w֙O,ґ%qzoԖ5&7!Rvη,dFJVbw d`( W`фbp>G%ZBHsNx!|'̣#!l^G;% $0);ESGcVCT!HѓBL:~)Cpd C!&@V5;IjA͙0,t±y.^|EFڈ/[CxˈhAGb2cR} 0x,$n BNY #<$"kQh$C,D80 BA b1zal6ֶzk[medl w$]ҥ{|e,'svlQ{7-1Po[NjC犯f{bЁ;~>c`C}[܊;K{P[zc՘6onk_5p|\=*۵PoU/RJMԵ,iի\l6c\^#䒌NyScnAQAQQn1T\l,2l4dbY,6YeY f3,,f1f:f%D<B io̍'p i횖 E DRBp cA`L*ʣ5-YUQXQrtr񃼆`m ~u٘< 0Ɲ!_W~*le;{-&Z4Z)ފ'3i(U5Ur Aգl! [bxD)xg/į;#lf+O JrKMV{ DŽZ(kf˄++=44 ɌB5xH|"P %™F9@*Cpjd \&ȡLA[酠 H@Xf&( I02 ISUT Jx'q{9\jd8Fc ɐ8K0"u)3?m2h  P)-WTIV3y48D.jZy׋#[Fm(c]9g֩3~Uteʚݧ,d&a O:1"s322o9+~V[`<"5`)超l VDr="$P%@r-V*)%>4=LG7Q a k  w7#+ L*eЬR D`<|Uw!YQgh& *~)*"*ĀtPi Aw`! s)(<ȕX#!w#;Lj~_1~k! YDrx,f_r>vd<~"PJcPlQ! ?kjG䐒Z/,L  x J !Q#$M<"At#IAЃdA -^rAHgVP[*0he]ZͨߤH>p#įlV>KdJ֪a<O YB,d! YBe@"rSm sxBKf@"?a 4BU+H#iYLbma`Hę3` ! siPT!(S2TBnLdtP Іʒ8U'2΢Ah1Vso#4C/Ԭ&3@P/ɃVsR91, qʅj! YB,d! YO!Q HUBK_˼| e g%3QȍN/<%K XL`-,C_2b ÓZHj!B5"|dor$m2UVpMsoP :"GJ+ *(Z洦-T=9G0gȐNrª!rM~jOyKi!Q|j!e %ŶUe YB,d! YBeOj`*#^Ȁ ҂(' IJgx\-Jf 0hY!@GU6QfKyIxUД27`P/$WM VDcaga' @Y:I SZ{DS\b]8+I=#]i䥕+I%Wswd6Eژ_C YAw5Za ELOv|2wkF-[\FݘQEeԜɳG|u/w~x`4_-^،z > j2zֈ, cXc,zxUyܐ,ƈHv i HWa _(5x[a1pW*@Q+PGvZC3DЂ7F`Z} L2R*-HC.Hf 0KV$3`9^|y+-@#\]˩^Q8_EVӎ$WǷZUe|2^A*WT~ad@Pp&T{)m],4^BeK0!|]r(#.~t|^NS'q}>?ԛT+hʯX,ɛJ,$!5 ` 0=QXZH/pjC`L: J *~V`B }eV1!Kr %8D?*F3'a\P) M/&x^kV~X%-Hh)Y!V\(<H?Iؽ 6W ^y w5Hގd z_OBu\JlH~V%6S՞|1!ZxQƐ M }8fюNlasרO.ffg=Y4n5>;y{1 MF,k3|ljy55=uzj4M9?e?G 2ܕݴŚL%}g_\~Ave篯f\z 64aλ;m\\C5ڽvkOdRxN nq96?ŽbB5'{Q ]f}R}/Vؘ)^cڶc{M7j;ըO&ͽ~)l9K7_MBώLl3\c[R W58{Gk7Q!֍li篫,TƄ&)PmK +@2UøJ/"p2W%.Y$݁O$%G)"tTZ#$,ǂxb"HL^y-ȫa TߪIH $V  A"G*K-2R#?UajѺ8%e@"f'4!#u!K ڜȦ9߫B֯AƵۗ&qk=Z 3ho簀sonYe;`x\Χ^uw,+E&0z+x1:0:+b?u^pc>38eytcOn,?lC^ё-w( f_e| OW\xfmrZ^`p mlMjzzf糨f .%ω@,\2[E`~ye :Lx- 8;q``Uˑ3O&K4NC0YW_[g_1i\"?1I@FƧglcn>J΢ơ.de0PxÈS~30*!x㏊0-2iPd0x7-Q.@уc"paY#} wߚ0sS6.߻ClLX!_7~VbAm]ӳˇ6C.ٽK`L1dȚUӇӹUTI[9ޙ]BsF|wPH̨f׏ eDF6Q9?!,rM'G7^t:#ڟI£9)m]Bm cZX`S˯ӐNߩMO.wwOD~A0NjycѾi~]EO< !x,M/;5~6YueqH$ˊ}ae;m~ӌy C?;#|˿6VXVNk/ѩn9j[J*PyM!MO ;yAokbK@w|w=lbF.'Ij, mbcTI71T96 B>s,ӓ|;/_'vJPݽ΢Ն;ԯ;vs2/ѐB_D$NJXtD OOj%<Ġ d v * '܆G]f dC$tyv$By 90/ 0!/`i ܂@iEA`E!pIx %)[q~լ2{B@ RG:} 22X O+r-dlURT]C)V?kt^"檅d̼z h$bK忸(,f1dRN~N_I&'㝂%<_+d:K911qWQ:mCc062ŧɎG&]>>16ZsҜyn-4tfcw/GL"}lx'-c03v5ό/eײߪYӞZƌSsvdӄ(~v\U|Nbr/(2pB(w& ' Yӭamq>u{uN.|<Uh9SA4ÜQc|բF†YyRӶaG`r%mЃWU0>:Wײay+ɩ?Xv#'eƝ#sm:5n]=,jmf֜gJL%[PpgӁVTON_" ͅᣯ,_ss}}.S>Ϛ9m.zgF?[bb ^g"+γ h`ױă;T!j;ޒMKU[znc L/נCf`zv@Jc.N wVYGmy*+ Ki9۔8J]~3l̂+7^|:+"Hue0$eŸA<1Ϛٺ"y6u-k/qÆs۸֪G!Fw%Õ0p~ūj9׹W…%l^tx!a ;7YHAi5apM9*1YK|; WkZ{]ρFT fW[<C%i5v614S>>sUXįH۰&#jekO͠1͸l7nʍrͩFF4e,אN[05G 8*}``I0/pȬb;@/CkcW],`^ϓ/GX"LS P1[=xiIiDŽ aZ$VSDwJIvDK꘯B 5`83)'xW%M 'rKP :MwbKՅ7H4 BE9TYlZC,iaа OiH!LxUkʞ؜k CG͘5c?z=rlѓ[ ]=;wpփG#ÙΚg MÂtÙi߲`.}XwzQ1Sw.H<_»nua]bIgm|3c[ί-Zetn5{E̋F6 S>ƾ cdz;~ݳk9~C9`h\0[_) v!kψGMfZ^Yq0`S~w zljuC7i,ih-+@w.jQz0.Mv7;V}Y3.2[ N ٜkS{\kܙs;{/9iI5(R DkhyU!)?'Y܎kG.ƀ(*uv| \޴a?]%s4#Hc').aHcKJZMdhȶ^Cd7Ug50~ GzO`55YB*[wkNbbx)Y$FcYi""p` Ast sI\!:H!0Ha<QA#y(@rAD-1 A 8 (`(!?@XX'Q_{" \ҁy-T"ZdC"I\fw \%KC2*eD3R)^WNX] _P\,䐕, KKzwhSt3=tVzVΖй֫U?'IX}Q5Msm']5}9u뚵bB6+i>uMYw.$iTTTTTTӸOd2ޭl횻aD>øSx} ǎ>K>tvTX&n~yWk5{97#~N~ ai|sA o Wt]B0xx8^Hog E&sN BKE#ce^ۉw-m `κw;Fsr 6SjZ/O eIw1e&myLONkUq7yh[z[USm};piY=e˱ށbx̹iOU\r:rB.1)lSޑY ma /dX^jޤ]& ֵ^GN5ՀNٟ:װf~r8Ztxxtȥ)o8vtuWX\\=jwlZ!˕ lA棢`kQ .ifӳ&nQ',,VDT99Fn'$IZ+$ˊd׬wG#w uTn;hBb}~v^-D5p}N0Neso+`3 &0.v (+KgpP5iE8QͿo&dʣjYJz Duhyu!!;X؎dyFAysav5@vu*xz>y~3Kv4#VI%lbܸwu8~ź0_&*+"4M(#3ҤsgkO}ٶ>CONz1<@zG5=YuMmfoyS:"V{0W٦RYxr^N #j=9.nҲf<*:,>zGo[:CE2`ʺXМzA9VwzI`e\?Q`&v1iګgTHKݤڲ ٟ^Q. p=ŕm=g q&=UcQ cl2t<*>u *-xr{:6g׽ep}qbz#ēHuekA{Y=/՞%ӫs۳'J`pM:kf>wo Ubb組bůЊz\zJ@uw +BZa[o`|z効^rtVVz c46FĪM'e.-a2Qlg\ZfXbtzVci\ZQOJc! YD"бY1$!#q i/!9W^P/Io9CkzXC`;$3!p+p'a/R#0b2;NiMKDdzQn$dRB3 (r'AbJȈ,@?"A_ UAVh2(8ɸ> Эi~o":2;k IJBLP?A5b3k&h4lWG'_aa;h48xnz20/֑#&Ǐm0;4+0E/ _LڮCMWU`ǚ,˲vm9b7~ґ&>13qqCicrLXc=32N]M.HoZN;R6!dWY_bGd]7 =ޑ=|DZ!?8Ę P'֯ߺi=t< m- mlbBF16Y{t{WJz=7aF ؘŤERѹSן0\˹8ջ#S湝/otE c97ggNQ.P'.;0lы7iGY4`\7vo2ͻoDz^_򓏋0wg;Wosxw'EyOL%@VrsDwsYQβ+6 kzOų }dcmL;Tg/Ӓ~=aC΍+o,[ʵpNh.F3έfXcnՆ6֮({rY)^H*+$ p->xŴaSx"Fø.egmޫ>͹?z۷7d4w(kV2Lz[3p6iW<%EWNe^aAVM3m߱|6 :5{Fz̋\>} ؽqp37\}a2ݣ^}kcN>yƣ繅9O~oŷM3ƨXzS]fktmws,λ}gPz?0o),.L;˳봦&ilM4;u _E=8'0C B@{H #I\Ipxz^ "]^<( A #9dD] N$RҶ/J]PQЅEbPz@*w Y eե_ &HTfc CbSd@e;e ee+b81I!1`/ävb|(dNy -)d["l(7ē$g,JV^MzA  !Z])1b( o{#e!NzqtJ%߂pf8>.L>c.ڳ"So[NjCed3=1JVw|j7}oUs+Z,j.}/BmU sM5NTc~Skۨ^)r-1[U+-%j2=ڹc,d! iyꚇ92++$ʹw8'((Wd*.2Xd4IJ,f̲,YcfY 1+a|kDE]&z%>RnWd2 &.vUJDW2(Y3a)ԴV(%K7|NC(CVJVTj&X1dwț7[bxD)xg jMSUcsa3[1~RT롈 c]j2\ eMRp疰,d"!,`.8pck"7LbUsd$9)Qġw:@rAfcHoIȬg:D[*VF@t'w&է1KUC )H=@;:4WL1+ZZx9"DQ%|ERKaPK` DRQmTnPiPiPErJlVTZcmzZ_H8:uZ<֛![͘ g1N!ѭ˦)Vh֯Q?DXTWVje8sKB34GJHUXQ2׷  X$\.("$]fIeL;:JZ% Q)%Bݫf6ac 4#V0? `g SBymȕb*@W>pm4ڿ*j<#:M%@CGi'!2 ## Wa?rQ?ލʃ\;r\|7ͱ, -t_-,d2"hcyke)E{xXtAQ 7F@4Z@ @>)[๊_{B%Ϯ#\ږsN !jVt%O5l=Lw _+W7;l|Ǡ93|qΩo~[͜ꏊu^mF` IDATc:7qA}fnSoLYִ+^oXwatI2N_аWs5|Mz\{)m],m4^B2\% fBM.9%Nz!;MݞPoR)cO';;?4~sOB+,E=K=fQJq *xB_*h6?,X£y#$y^r$c#[+ǔ˝@ # db"E߂4sL>Q5JF! AsHAviVO]`zTC#cS!blSI)K)-H ePSW b>;1eSvdfH\<=W_+PasרO.ffg=Y4n5:Џ&,?{n^sG i=?ڦWsyZ{fc-7L rVzg&SI}qyoEpʫ̱ɤya.{uVr cmo^'Ssr2Oqm7쟲bB5'{Q ]f}R}/Vؘ)^cڶc{M7j;ըO& `¶qdyդ-$6S z5\Zyklu)E{?X_ 7}vSO~j_VjHf,aJ/sXB" Sɋ&q,@S sX8I(ȷ+5A\LXE<+J$P'q  %99 d$&,@\Y@tP%%XIbbp"@B}ϩ ?0"Gd$oB{Gy/J [ gJkˤe5=aۖ _Ԏ 0==YTJwD  }h"0~‡a a&ne800 Gتȃ%oV'zʡEجۯ֋3ίѴB.$ #3G Fy1s< ;gw u$/;!{/:/`Q!ƃTi5mٗIą +Qo Ruyom Sk0l?h qbh̸fBZ!3͜`vj_>Q=t5]e!C֬>έ:NB89 n?}^-63#BbFx6`~Ġ)[ 2p asn <92[EO͹MijLS7č4zנnN{W/ ^~[ѩnj[J8/yNX܋٬PyM!MO ;yAokbK@w|w=lbF.&Ij, maaRlCfD}#IuKmؘ d3HjB}1=u|ҿoQxi-jc׊9^kRfUnݦKFƅ27JGXBxW5nsCF$âO$O;FTr"!`g#k-Yɰv9 xܫz 'Jh+ 1BV΋R"tؐ@QܽOA@$JHn'҇ 0cKem J\ʨnrȸ}n x2,&JSK-Hi@nTkVF)Y$SCªY!_7.cߍp,vEdžV`l}g4"^eF(,f.z]ݰjXwڬIθ4eUݜyn-4tfcw/GL"}lx'-c03v5όwZZ[1ڳ^ 1qjN.{–lcp/֎ʙRI,TSS.YEwV;D!k2ԓ<ǿZ~׉مjyͿ?g*Hf7 }vZtȚ~[>+oRj^9;Cl^czGGZ6,ož89n̸sdn ܸ\|ܽM;eZw-̚Ld =r:0==Jӓ2~Sp;|Ւwn~NeqY9EOW=cL3"qrqRLlqk[dy!:xpqG_j1Pc[>?jkPmџvQiŵԿs,L.H4|qIA:C*V~?oY|e^a)6gR6~`Y)CoYt݋;xw<[9bř,[xa;?wE8OLΊن#;G5IJc--I. 9IpИLl)A~㑉q;zYkFoybF50uEhغϖaùm\kqS\WV#Q\߫|Ò2ޒtx!a ;7YrjPdzk]g_;=Fss^UHcN5B= K|; WkZ{]ρFT fW[<C%i2y%(NR&Ɠ20=56ގ< Q׋XMcZmI0g>[LgmQ:C`nn4AQevO/s 33aU=Vg.1=Gw=lt#;68 LO/\ŨANzs7G}(5EꝻi/ ޳re|&mlY2)wڹbe>.٪JMl$h*3q@aʾCj~bFra8KwH@RS_5~\=?\Ӗoө3Of]ZQo;ꐍw~^X+U~\]Ӻ r1ib4-OSDj]F9֡'Ly\s΍jFWqDʱFacO~*{Ppu{$oJ!u3~:zdSـWVL3To!Z]>i~M~(&D%N8"j\;yYwºt ;}M5G=H&;c]>cجkWYhl|t`Z }VO^-G'kcl5jdq5̹u۽pF ڜb):;fƶ_eO5a漪ؔl# c9pQv6EuΎO_cd<˛69~^˲dn˔M34v614٬5+ϞAlk0ԉ@*qkYuYsoP@{wo~tj^#Yu@\)l֥ OVӖAG*m_-,d)bX q>#, u48q@B. J$ E3ˁ~$ıp z XQ%cEx:K u.I1w&c ')9ϙ8!zy/H4 T!r̼#O,p)>EH C(#@z`*)6I2VZh+QEJ!HU*@k* :X9'*ӆ|!KiIK 4d{߲&Ffz6  //-io+:sRoQF쨯:v9~ӹ֫U?'IX}Q-u/ '6}V}3.\ l`OeGV76;,QaAo?_mܴv<;Z?|k0x{S͍S%5__$Mu*`A't-9* _SAKE#ce^ۉw-m `κw;FGqr 6SjZ/O eIw1e&myLONkUq7yh[z[UnyiY=eNsӞ-o;HYNȥs4?⏭};6 -,0a`s<K͑یߺKH©)4S,R'Ut8ގSk@zg@펟Mӂ7]_66s_<iRc`baEYY:sVeoaޏ_˷Z~_mmFZ5,%w9[n0.TkL9.$;:dg dyFAysav5@vu*xz>y~3Kv4#VI%lb,qU ߶.q]o /1Ρ ᐿeJۡ*dmGJ~|GGn%ND~N[q$8eY:{;7kGh?z֤Ǝ)V,cQ9Vf1ͱz*z?O}"ܤ`ʺXМzA/OO{͙8x{;u<Ŭ|{G)~oףv95"\9OTUckdzγnRT~^->9}?sN׋=kߪJk Q-Se۴W%ٯ6uC.0.|Ur:]l=3>C=ZK1ELl|پ Q?@<vF9tk nS/ ^2)a4j{mS̳7l6Ue[ႄݓٿ'KPnŌ/kl<||Z"oNa* 2-typi^&AMXw>g:I+1ΥagWoz^Zʷ&Yz~}&ƲaFzDgrcEiS* iHS3:U ȟ yFOwGK C?l|b(Jd #l/:jx +gz?X\Z^ {}wyF8e.Pĕ,fp38 :vTD2Ż9S^o0*Gu).J>Â̾ }-[b`jmy}\\«k|Y@WtE n%`w`o8U: {Uk?QwLW/Kji0'_}a*P@<8^뼢W^#?O >ޟ! vA?{.^8 H>mE CEa 5$>K\<m_(<Qs$nRj^ $jV2v?QϡdQ#B*lC1@Q=AbDŽX "p.iU,7bۖ&&Qu' 9{GJ718ͼ;թ`eH/rѽu)ѐ31#v݉==6o#[k g_[j& <'P l4Fg[½ 8+k,E ԏ5^A z:,;2pE[kƶZz%*(E:נi{yiTԨb)W#Zz:pfSKJEg]"J"seҧ[ [T"i&.|t`V: Qm?э`|Ivխs2ټ!;g?Z&k>9/.I>{خenK~YTe&Myqr\- vOmb*0{_^U5Uz4,k BOg wݜhTK';-ZOQK:(xTO*,> NV[#(z,knlp5;k[f9Lv\ [z )>{;J5>omj:кY亶SC"F sd.ܻ>8>OG!;/qMg5CjR65,z2^74:Pw[v9pvPjJc]胋1_ȠAkKIm}v¬[x[ʧy'^4#PŦ364決TŠjֵX|<^2Y}8dˎ+ck:nuwFSG QCx}?EaꌚҚB>UV1iESr ә;1MU6_Nmu9Y2Lt)]g%*pMMkfEQv;zTYbWX{x"RMPBF.@oU.xUpW'/@Z> }Ml@Lv%! xJ|S:OQG.p "\L> g@ĄĊ21ai%I Fta `DD YvE׸?mu6Y~l:h߼qn))JW%%EŹ"CI 1mF#iڈшh14 Ox<>`-Wɿ"@`~W?fsAr [0k"6D4%k(@T ,{³=b'$ǢIJyTi y;@A|ڂ$ gj|+ KDUMb$K\.b.e DZDdRzbꤻ Y2~@|("ij5E/JY'.̞иn >8;r7m`qZo5:`V_g_Y)?Xia_6&=΅-ѦaoFbp6f/p~s؛yO =VAt1X"n<-V]BQqIy+6G9|ˇi;8d=v3 bNlIsLdRU%s_dt{UBϦ!YV'(PN'#$NwY}%AR%T,5߳86@I%DY@"vEf1Ʃ~XSU7J&oLo[=hmKe{yj&+mFݓ;S=΅-ѦaoFbaXޖ r3o ?31f4RrJˣ!+ mZ1jEyB-oNgQ3,9'Mog+H& vbd43䒖>A -\)\!Z%dH s 0T*GZĄ9oẐ⽈"j_:.,#ZD)SF&8,*oz G7OT>`wW]ooYyf1K)u.f1Yއ63gns+/ +D!+D\JK<as1 c,D1l.Z(5+ J")J( Li2'V?i8EXjiEɈ'HP¶@ q{Z$&B1TeŜeDYFd}d*CJYCш k9V!ULYfo,f1YbC\\7?1dy H1W Wa%@h8q>i"s>m1HȉE%5MK,H,y%H aR#(IT9˜2l)%+U$Ѐ=Nz 15\ H'J  s\Zd>}SԀ&' DrFOd"[!sxGԪ0^v)/29&,f1Yb,fpc®or8.J0}!)\\'n يOsP0 d̦SЫH=D]QW  o̙m|(>Jj.@@pJc=2 d4*p_@p"q$.q4ᦖeˈ?BBJ^Nj1Ez0|V4SUxq#Tp}}7Yb,f1Y/ |X(,KHc,3XԓEF~' U"6P:&A؍/@`}"s6Gd h\M\g۟+:)D6@RLfaD`'@nғ̥Q Hv'B!,qjD>!*PRoYʼi$?")eړ)T4-ReA&&jFH>'bSJ }DëݽG>b)_%|'R|oafK(~Oթi`I(Mߑd0˛ vИRef1Y$]7)yx4L2!L=dE0%c>SaHVBDi4_,[ 0<-1ar_0E0*!ND9Bb"1q?f " 7ÈςXX\,Spio g@9cw *߉ERYzg|xA z6Gx"l1\*)z2^)"g5r J[R) }"/ME)' ?g3[37PXs_P:f"Ɯߋ講 krhgΛFqNC.OTK>H(%`C Ԙzw٬wg[:./N;:ke͛Yt^o{iJ^Mǹzw9 պ_Yj}_=wBy ]^~}←o"o4H,<0Ե} goBnC9 OImB>2RCK'lB~lgC"%^s47$s秙]k#CƭKϮk^4fz Q֖2}ʅ @_X1!!T턵_Mg]Oj%,WYhͺpe}rK@FR˖˕Ɲ?YM@ȗ0О'>$| XR,k1HFDXzA|@H٥À0c[Q⯘۔pT/e "@1peF# b` DBSVAԠ*)U#ԓJ+?fV_;u-='EMm{iq5POyӼtQW8=ӜWVqb\Ǧ]O=ReO2q쯟W,߁?<0$kZs< g;#ZrBѐws4%uyłnf1Y$"qD3H9bYwbOP-x;HDX܍DY-?' JQ` Q" E6gX^*0$.4'a! 9@DʘB!ݢ0/D D0-!z"J^xqrM J3@ גLY4$4eȍ2*~.{̧2< jTˣMxm8jB [C=& 9|.6_Q˩m;,VCQFWJ=n>3^=xS$qchq*bC/&@7@S7Of?u.IerTA!Պ~@,mPĩL ooreB1n![3w6ΉqŮ՟־ݤi'?=I蜘[o}ڱf9PybBc7sHzi>!f$J |"I쫜GG& #BAWM.fzZY?N s@.>-oJ??u&,UX4$֡{sϤ96NҽcflX!tt#Xs5:u qǵtC}Cǭ;c4F1۶Fڻ}pY{1х}"|F6M*"|>t9McU{th2rsb27?`}|$(ڳ ~VPlHP'&fBMݙL }u]٩M9G*n.nl4lѫS+LJ#{!ٸw?YsbGz_|ʈ7֕\tm\BA#aFd@89{G^~8iEg649?IO=X7J.<(aݯ-D tvstaigRqB%Ϗ9~fD@k{3Y{$铁5dW/lԨO.>B-EVWUҐ>w6^Z+ƃgrOb1kaիdQa4 k/1̼VFDy#Eq0G@ۚ!5l_/&VBϽN?6{H 8\K}f9eQ7r0@Iʍ:wnfMil5ë738.κ|ޫ᳻6Yb\~aӜ@>J4>EL:&fb1 Ef osdijM<NOc< ЀK15 0k 1t2mYBAH*|Kp+cqט( Vsc-4brQbϺ> _K= ZPIr tT":)3FF"UIϕߣ։%3Hz%i,Xѹqmf|ky6.JZՂnH\j=峦Nec( 'oFyrV6:zk@}1?,5}'M)zskn#YqPlұ?+:ׯ¦l憞6Yxc-Dʹ*~eډ1it~^rX}}򙣚vut-6J{tzYm_{bц~wT6>82'(|tg4`xyxbjiw~r2rGW߬۸_,l1#dEcq֦'aaf +쉾tλ+Z׿-9p >+߅ ]Uv qiPEXP}w5*9Oh[?eG 4(TRZ@ .<ԧ\\_%fID6o<6!͔: ݭu5׮c@e写laTYIL,bNsa ]ykiNWq~泋Fշ׀ ܁# c(4=u΃Ⱦ".x۞NC:z0YI>Me O ^<>d;%7KItk\&k%{˴"Q:6b*pX`H@}vC8U1 v0yeg&" D<0KжKR? 2JɒHM)GMquHZQjYE4b򨑰㤴:L@6'l)%4l:U"PFf YGE_7!߹߾a[LYS? #*ߧF oM9 Լ>>c #; )yvpUlǯGpΩnnM1h,,r_<~,HYU3ܲHT 7OrZү| )6k wh5~6M1879NS:|o{ܻ.Wmˆ[VBӮ2@~&.HS'|稭,XL|qRf8W5J>a}۠*HgEwK IDAT$>zk իqɺGxX!(|}yȈOPtQc1n*jrniCX ʶzZPhVq0SŠ/zw,*ԫֵK@g_߶;~hAM{ugjɐ͇]߾v0FdhHei/ry 1̘zy{ǯi}lrt~G a 쎂1isAN哈M*je#|2I`YYGZ,]ͭX HAg0HԦ ۏkc`Aq pLn{mA7r^]hO>1o5>7Kr7y:vԸ ~y~=zW5sciiP ڀQJbCAn=Qv 7.[;+{lj 3BTV'*\DRҦ?}ev hUaG $j#Mּ/ӆV2iʩڜ bV }0L'þj8bHM$A urKT2j<&E Ɠ3 ~iY;z &+p'\ Wwc6_R$x0yeYdU>SH pĿs%d!K-o4(@"E,.*FKRW@i4ùp NRbgŚWzgYT{ի8;WiLszcU=Sc"E_LiQ&sW^m\޼aN]jX]OYxHppppppH'r(K9n/. :+~j 'A} i`F.W f @9~6gs8qQT.B%eW$u=9qB&Zc^ҫ \Z{/>s,M9Wg}JjJe;Q UQˁd]ɳ\iȳz2KA{gц. n.>A՞G>O>**r wuHzgЧ^:kH&u607WpI"ʴYzg&סum9$LTl~}y~ãOwNۢJ/x.Um4s/mpZrnջ d}]^:, h93=ggU.*j| S_zVӀxH2[.%'FĆV'\;zKUk98qxѳ꠴@7`eT6U>fI+ x _=zUŽN?=v1[ߌ|zPрDy2"ڴC/0u~LTl:M1^|ِVY vOj7O;g,BUl҉յF6 >- 7f'\ڰa+nH;Ws;io]Mb7owJa&ZUVEiNNaR(}¸E\<4Q 4Vb~[QvI}!˪-Ǭ8v/=qlܭުJ^a~-)ٿR g8ggy.0%`?ҏDLgZxӌ>5`/0/J)HkmXZC) :M:{uM0v{_;d{#ƬY Z׀;TDϬ6J+e.bm>ȟ yFOwGK C?l|b(JY%$* p=_;zs?ωŲr߿KK\n3YνiAΔ e~dQR?, 'ܲ%&Y$nt߹Q 4^ef']۽]zӼ,( 19`x߻߮:֧_qczY=GWۼpL1?kTR]{L0$/b\4/%1eiXN u]~;G>0fڳKUF1돻Os w?Al*ilyt{zK2ncZ5Ɲy:;w܉?3ckk#b(W+=!GbAh'--șAT3*RyWrHJk,!j*b)Qs hPuXvdL኶mģK:T6\]_s[o=:SSvLXz:pfSKJEgoMV2S Q--I*4>:0Km(6ˍoFm_{Ҫ]ufs6d\Y7y Bv#~(L|d]sxɋUP_}^\|]*,к/ǣ}dQɯ˒ך4Ɂ^rm8.=0 B}N;{UPV>ytoK1`N =)usQ-PN h=էG-9lOd R>p4;Zn豨qnܺmM:0~^ 3aT[X!7e@gyzz~\ɢgwUMZ9\vj}H虇-PRtMAafIw7 eK*R3s;d׻W%h ^{ċBmUuMCuU<ŜVrF\Ԏ*/ /hxqyw S-O(I9""бCώUu}oK4/. Ficu%AsMլkmxʽ{epȖWiu0oa&]UV1iSXHk̹=mu-豫5-WT΄5]nkն{UՅ 83VjPơ߼;9rjy|˾^eYkT}ӛ#qq;:/1YQxaN#6$s~Kf|1 !?O|q%$f& ԎBF(D.ۧ mwkQI8ω@sAn%Q|y`0#P A !_";V@쥀] J dQ|Hy6/'%X@L@ i("t$0 `$|gH{,Y3 buP Q((D!4( ZPZRkitP V>7`:Y nr/U{yj#kCʌT-n7mUK͛Iܨ DpL9]ta vmEã5m,8;r7m`qZoe|lE}]fά8޷G)l텁8&3qp\yxϟǟϧ"f1d@eq-lEHd(  @ pdx,W/=r g3fdDJ#"@ ._DRrO@RBV( `*We` y E4dAh 5$\8X ,\GP 1ApMvkwOYF4N%%˄*T%7op׷Yy번zs}iqf1YJ0wT!f3 }F)lY|-3(cRJY l,-opp]}B8 q#vD$!GGCHDPhq&Eb yFc쩕XAG iR(Gϝ'\ZS\։<"oD&kFJQ1C]oon5 U!x`>ͿYk3,f1Y/y c.?N_DHDL>j CS-!7bXχs /i?&`8,P2@LexEdDbdD(7i`q!\C| rjpz'pJ+\pl)U*+L8W-Z R RgR.DE+bf1Yb,f1?J0aĆpLc b/%H/4":c$fDTKDKIg8KO%) 4JD>}QXOR.$| IH??" 8J>UXu,P*'eԲ|b^ GD.B" TV1Xn Hլ T ܐ$Vi$A{6m,f1YbEQrsЎY~]+?@Ms!g@Jgd \`^By5XBIQ3& %<Հ'RW bDL@@9N3DU@_G-5{R$0,N+m Y;(keg&LK?Wgn)IbPPAd=RAj(2DJpcQjVwf1Yb,f1YDbgWeP41s? د4\xSZ(_A@)d>o2-!r &B\౐X@HˋH<*Å*EB0`IJQ,$xi,`4q8 ȉLI130Y2"ʑP"HUY/Y$9g̓2*"p"@>*W"e6:e)$P+dpF[ +q<~)Rt+uKn=RhME&^=|?e{{ 7[G{NMK5߬E%?nw$߭YT责drYbЂiHI1os!ߢ(  I"bO; LE1 0FGBz,z8i y19"\ǷND΅ v4 k%H`&M|[Ȯ a.XCj%Bota.b"|q HyR dd*CfrN Zb$(@2YBp !\w&Us4km{ȸuR⢄)|B;hr#^񋍗 ElKiG4q,]P]/wν4S cj]/l{[5ؾ/xnD!)!  ?L6um!"[o=S!#.jR[oO㳌8?I= _)/4 I IDAT;sO$f{榔4+G A>c#uY5N%;r^q6믤6YQcm0&`L>r`0o(HUJ -p4 !s|L. X ,LQ4`Ij$qM2H[8=AkId]@Jğt7QKțLƵSOWA*,=1p >6ƜBHB˘Au \qd?,ՓO5t8O)'/QΥdFI"-X=$B*$ H,2"@Q PtƎ*DgiNy«s8|{9Vl482Sskս2AF,[`4{GKRbH9(/4ڻ>6L3oۼeo'N87u.*sl0:;y8 zr}mcQz/Aq H UjVdƼW%;¼6BX'}~8??JJEj{â=׸Y%)0:r.J.ME%9{ ޫ"Y׶*_?`f1Y"K+D;.hHs(}Χb*p4w WngPW9Ág\ ȷ\v^9Es Jp7pk̈6C¤7\l~p(p.s餗>,E"$ ?))#K-~E e]sȿŢ>/j7-jO +hS*^{O!5v} mlV.s}u]٩M9G*n.nl4&j3foPK,p((U>!vzd!Պ~@,mPĩL ooreB1n![3w6ΉqŮ՟־ݤi$tN̋b t>X(I<1 !9dOqR{KӁ 'cf߁#!Kb_<>:?B5qf,rlr17ӊΊqJui9|Sg|e}:nEN,nkPѽ~׹gҌL]ޱMz}m3z6l:`QlQ,:RZ{tim[#E >=ؘ>uB>]#?gEqp&Bao?1qԪĽc:^1΍>qI>AkE{Y?n(r6$mG3OئxDŽV%ѫS+LJ#{!ٸw?ٱsbGz_|ʈ7֕\tm\BA#aFd@89{G^~ieK7+3A@7@S7Off7f:>'=EM4*aݯ-D tvstaigRs5'όbqo9zF=kO8}2p`>Uʻ؇BqXm*:x7Z:`c^UI]+ޯ^%K]'WpbW; h4J8)$+ޫ{{s|ywsiNeC8 T7g^b(ɦcƌ3nqǍ0~g>}ۖ+±ߕt J#U1J$P(&𨀫v,B!V c0 y%¥w W$dbDQO @2:R9Xroy %:tXJeN#H:n7o`G}lI0I ߊFbJT~4Mi } b Or|J Al<'x(= YQc뽾-bq_tuέTs!XCˆ.j ӯƮfOŠO|Z/ %ɿ6 b >k=5pјvpqa#2І;lm9Bvai>G\_k^7.O>sT.:zڳs 0<cH]|חxʪ[~>6$n7_zAEW|K{-Ā:}Zv=0qVmEE5Eп7.l5xW.0ơH6PM'o=j  ;T%'wUD_g ז\q >+߅ ]Uv̿կ^}QdbYקߺx^cr?ω'}ⲣ@he*^r>{ sT0WTRu4d=R5¹ڵv $8s~:f|7̜|_bcc}\IXXQ4V]G_dLC]M(zYb!W%TZo>oZc`Y@Ƚ%N e2<Hx?&O`)<\9W&z^̞5G7YSah,a  &a1!g40/à?\ngB"; 67@@K`dqϥǀb㰕S4" E1 Պ Pr ؗ3 H#]&SLo'H«$Rކ80l(s:+9%lrt~\*J4 Yu#>Qg9 _ZAk̸qX#SO>.0dDEqi}.ʢ? !@XL2˽]GwUںLէN۷眮z-{gyLzmM&%0)t7Sv߰{{b/8ݯl4S7 Pĉgޤ5s#޺TĊ;/dއ?-3{>;N'_~}-y^uʁq~OAWe]!|~٪s_֏NY÷sjo֬Ni|\^w za\my{)bφ{\q&F2U']oݶI2߼ >clmztp⶧~o9-'~¢fӜIҿ<'Ċ'hj/y^>jwy1j'䉤gʔl`}E՟)|^~ŵESw;K]_%hZ#?&Kzo٬ MМʕ0_u; #}[tO|0Xӌ!p')I+ NYoSdbڜGc} ֬]zgdrx:냣3,.uukp23$KԎq(868||ƴuu٠܌[/C}z@ࠚ YRVUAdu #Pb"67#{![=4Z/ , l{#ڇa弘K>Au_劻oV_q!1R'_>?SZ;o|󺥞ɡ^t7^egluqw/y}+/-& @s?>܃?;[{3rЖO͟_t&[O<1L=xY/ݧ?_i_ݲ3gΚ(z #lK,%B:u&3q̩ʼn9ay'Ŵ#@GG|@y3bl-_<_>䀍{i>4ẏ6>p 旱wFr[3KWlLz=ORl`S7-_oN,dk̜5]И4{Vk2܍ z;b',Z\웽pG_ezM;_'o\tˁ'e.ƴ=z;twްw˖o?֡ܘbg /|z1 7J'LDف֔S>>O|;.pڢWjܞؿño_q/+r}$xxYX9${69>ӛ^m﶑ܴ;\O:l Zr9G>w&g=XoYw &Ia]+V4&N4 {k%nRU|96OW%7=6P竔~W~+?t7t-O)0aBsod='ꁶ|6rլi-fsg͚՞};W/4c $풛Xל} 6q|+iNpbZcK DDϝl6is?3V]dX]sT96j%7LYDPcERaPuPPts&&yL|+x,k)hGjLO||8M_)qЮ dC. I6fҦOjO:ģe>Xq/㸭r.ѳ{Խpʆjsӟfݶ4&Λ;xUَ} |M ЋۿvG~__8baК~uGY&]c-~fA輸lٓʪ74&NdSsƒa\nRY~"s>?7~+k{{3]+9o⇞)%_7 ߝ@c5b:+]llt^xQ5+ND2ilɣ+2 >Modna1h=?}mt]O w;`EӴpi_O&T]kc2wFyjuYԲ zI@ >Ss_9!cG_wٓnxN֭7Lzu۟-o6g\Ͼr, ϼ]ohP`}?Kſ6*hCWuW4W2 RUwdWnWf$ي|lC_3q_znPs3浀=w?ݏozOl|0922xLnFޱtٓ{r^nFv:D4>t'i paHx/_ H~Ƅ]b7,X9gKBZhXO-X^nz].WfAi@`+FC%ŖlI_6’Ma0}/񆫃QSX; ֙cpjB = & &@L yL(M٤A&)4hPAp[(J k@~4 0Pˇ(Å="eaW-G0DžO͗o? U9(`$ЈWCaWND:v{$oR:5 ]ӻ߸:okZC7\s˃O<70ťw?ιrcȻ`@ccbΚg./[TQw~4=}|ށ[ckΞ:+tkN8}OKXo~םC]_^0+XM@MxRG&;e>{όPuJHߟγz,/띏0, >cʔFéٷ16[X#H  7^|^sq{ 6_ =jk~a>1/dN_AOߺ^q6lA1Hg}>7~_ٷ})VSּYw>gi|O=[ֵ;'lc\;h~¥lŽ߾g̨_/Ow>yMXmi= ,0PfN_t&xkםO޸iΘ$M+~rηhz{4uϸ?]c㋿p/tՋڗt+m/{~`hhSI5͒3c?[\U}~͍pDDD>/ JW PoK^ӓ'iECr>w~Yqf@vس%Ur-4SM#-'4iTXУ#W*@3[@LEo8)<3mj{ƌY37wxÛZM7[0f[,\f[l6¡M73=sF?I482XrUbe /6W6WjHWI}_Ŧ%L.OWU6m >u/pe 5+gK4:E]3XUadluՊkN\8>]l߹??&4Z{o_=wNj ;9`<کc~ g5q6F9q1?l~}|S, O'a0зOfC}o7!ɞfyBuw޵b:~7.ఙ?q͒eMvؾs+9Ÿ呏lۚQ>,շ9̗4&rɴ_uei|矝q[5=}k~ptѳƋg!1Hf7~eOa^Q5-\Y?k]s2w7'?XqЇ_߳_p1ݣ7!Ϝ?Gq:MԘ3vM>tJt~pOМ>C\~v:˳mZqLxىlI=ow[.o<~|sʏz'r=yG}>z}{iWXh?O?њfؿm}_?$71ל̯pDDDD=MU +B"ɭG]=g} ț+ӡu(ԯ-2c<.\< br5A) źMe7ѲIC`{Itk'@ 4[b„l̙#xЂM|pVo՚j-7|M772wN{3SEE`%ɚƪttŊʕUUUՍ5p22Ia& @lq*Q1@ /%yDZI!!$?AZ-OEC `k"/d26PCGv5d:D^h6Df1H ȫI&I#A$HF&iI{z=Fyٞ ϋm_.Z C_p\z1x%?`qrݴ=nf7{6L;,aZF雿ÙEN:.kvmNpDĿ$! "@"" 3 }ا"S]i3ZW%1)R?E0|>>PtDpHZH^b -WK".ڠ@)7DM}#o"$ !pa$o7$@E^zgdxp>E^@/-r!-d2: 02Y6vVK ޑ` H k2A^yUU4*UĒ +hvhDŽ & $ & @h&c hje;Y38cƌ:k ˗/xbժq!##yOWY30 @ig02" D&:LA @=Y.zq@vV({ MN姐4jBd.0=u}*b lRIMjL!mR@PF(f*bPdj5DWyA9'PKw9v8 r>I"P5)ž PwYqfl@EΈ2jΫb'n=[`LY.r*"%8#vӍ7߾FDDDDDDD?mn}[C=~Ց7y6ԑ{/h%f9$(2Uv7d x;dnM:_y t&0@h@$$ADJy~zz(M)MB#FX e(fm29ʬW`6S g|m'똷6 e c}/^-r'#cmIЀ F BS˜2GmX߇*IdDDDDDDDZB@QkmvDrV Yj%"ȔXf 󑕀_?ϝgJTH0wN@B d*O@ī FV,Tao%'~YAяBeL~HSJH)m`|c?'|y~/Ym(Jp`E FݔU_nDG&SH7 [Uf318(Nyqר_de.SJ: 5G,UY 8v[2`GDDDDDD琈J؏Dr |[{sIAU4 bJBǽs ;%2O B k sd/zZjAZ-l5Q,_}Aee82ROPeFݫals1qp8v*( '6(^÷5v'Y/pV Un}LX ,_REE)ugK=iT|Uu$#"""""""9sHD5[YHygҭ'n[;L'H2Ԡl[0I.c&)l6N)[]e7gDBf?0 )lÛ'S`7h,SzO4>1_Z,A7u!R(#4;F5_O3Kdǵ9J?pKFDDDDDDD%s=ۄ4?5sIsϤ!4{W夺A9-!;uӁ!d2ͯs%zB۱q 7L$s \\m/PMcDrLZ3:,m9۰%-qehհ<W,>_ؽZw`kWHE |N3h^c8?4"""""""""_8aBnP:0t:ePQA&@d@$f;f2pc"S!ωj亻:Tqx#c\6%i$[ ,FoE1θH.~{sTGbOZtӻ8T~W fKe`C2y7J5.$ hp:t2hw:$0|l)Ju꺗ݢR2U+qi ޺]0t;pb&4E `'u+7Sli:E5:t z$.ԲH œ<*Qͨ~~ ?R}MgBČi+M{Nzjul¶rW3~l.Y#~M.kpb02 T?V WJ'c7kk:/*4*?~ XPIۍ]3v@ inǖ d!~Qs]oɦA/!Fv?MMze08%OӴ)D=9|pόrvo[u$NOS& Hwr}S }|:n8,+,)VXtUΕuRؒS gP\->E: ;n3G8EP _z>:umJ Bܡ褭A"͞t=vw\ER>}2Zݦ-? (! Jduol -,x"5*l4d,+/KmOY%+9A 0~*6 w P>pQ ٷ[B#V}H3v֡, f7f JҷPQOQiPrZ:C$%YwІ*L14Dʣk4""""""""""b}@]cp'oہq# m\ "̢In| J*"ȍENODwSS~=g) $HR-kQXSq85 r-~ލvQ#"_7mN/5AEGADDDDDDDDDK,>  (( ]RSEשPXl!f+`s?G@n>6)t`2N8dN r~Br=?0W w4MK9:K3"'!lo<9?]R^>xNSsU˹dMX.KU]uB'$dA"'B'ЌE񖙎0I`[_ T^<ٖ+|Ś5u!r EoMkxeT,;5X|%ʖSM5412Q7֍ϡXQ%rŽW$f+q}?9Rrlr{3 Kt/ÉȾՍތDRx IDAT視U7x[k<Gȉ8jS.:E7مFmԹ"MpCkl `Qzy;)䷨5  ΘS~15g/Gk! Dz1Q'S u:2'>batz)ƃh:N6~H'(BV i p{WG>#"""""""""^j{ DHzyMFQWFx pa%oiƾ ćvRW,̗a!Bʝ:2w޼iqfdWf1m%M8^/偿`SDGY؅h 8MIG N_C5XR@JN_ˠMI7wV5ˤt7""""""""% 2O ؙt,6gA3 E KCIn6{Nu'/2<$_['FDe7xjJ+{P1)+,=2?2qEܱPS㘑rADz3C;J*ȅS^=a hJ.) { ]<.UTQ=,[)D7""""""""@7DY^F?0[ LbQYN bR1g+uc>딦6߶ 0 1h? z>!X V)Lh1hY#H1~-x,U,ϘOW)2((T n.^vjj,Ew("""""""""bmCBݝWꏟپw4 :#TH e )xx~&?X}i:`oTA9ע=RƂKXhxL[ (00='#Sn; O/*Ʃ_̅/+ɘ|Mk(A&`s~Dž{N)`@.4k8*/]DDDDDDDDD:4V_@.ʫ~|F~ێ>ocV.hm9꣌S@rT.*-Xf2[dx~ F`(ϹO9 VZ -3B )wݎ}Ӏp2n[,(hpok0 넪nC't4L2=Gy=@ 780.YĥJUJ }n`LEDDDDDDDDDT@#pW9{pf'k?rǵWW l3Ʋ *IF<W]o;-)/Ðv}N6(1pæIra?3GbqmW7=)/,b pd~vx;n7X]K)t]Pb$+ڣDAw*%tu{ kb E9ryzӴ5yᓷh "AH!Dg|`ڜݏe?3,7}#f_Br랗+ 'b{z߾l3Nԫ?紮 ș".@kǺeWeH`&EP"g Ik]pE+?UFU>޸-]r٘ *zϷ Po%ʆl`e nŇ5iIU(s40;`ƸUx=n2.za9JJ:tMn<) $t̥ÆڌVbڴ? EKih-83̀KV@}LyMߒфp0WW )?""""""""⥄1#;s,Y>} W7P&Dg੧sM¢挍g=d糾+1g\7SO9c3̒<<@ =շc/3>)lk17#e}{ F @#]& ѐ&N-f enO}sqd4qF7V7{gq;G)m/+)jSXMMڢ@Xd'Z.*~ؘ~doyB`̙ٲ%+Zy ' d=~\?9:p[ԯZFKcڍ@r#ɨ P~. W@&Vf`9/PMc,7`HupqOMrQKUHƄL ivMSY>-,2L8AKw`I ge>|1Q:m=QJ+U<24VGEA3~R 1g>%xyϒ֌ Y7-) Xo@~FΊno Cք)'5Q'M^ՙȲ߽2P\^a/B#LBY@n>sp MrڿY0X҂ (~@v貶IjЂ6].n~t?I4zQӖs<߼E*}< Ɋ׶O()ST;Ϛ~ۤ@, `DDDDDDDDDZGvXwyץן<vm݁YtĽɻ|{m:#."y+>jMńmlHMŋzzѩl:w:sx`E'nk㸞ʐW^ɳo{(b˒̓V`}cѴ}a1}ef#,يĉGʹm:/`Z*bk% \2I=ſJ4@H  `;[aҨlKXe(]&xu:B#lͥPm:'a:TQeK U9b# AL@h& &IF'm͞%{dVK\񃻮9v'[߆u4a_/Nީ\,ISNΪ5#kګ;lCN݁N2B,+# +$!aqٵ>"繞l C&. F"mnq/^5(*:!|gkedmςa_du<6/rFD֩4 [2 o S0(& v6W70HPORSRIKt A w$t8'"~ B!H^ߛj(*{@1g|k^"rYȌ[' G-;Wj|hLvꁣAX';`- 9J >sOܵ@ ը#FWJ#4GDDDDDDDDD C{V;Cs.ݓ@d{r ;# J,^~ղC @$LU6ݕT yC91"e~Ef,NfԦ"i G.iR yQ `^Tg-[R9+bOT-Sxy̬7zSM[\?s(2o9Ha{|DՎ;6AL˩X`XT`!_iz}e:mDm˶HoŪe[tO8>hu+fx*ǭ`ג#Lf7Y!y҃wyw|qݤ_Ƨ-OZ9ȣ3w=pJ(?1v${DZЙ Wy/<6}!"""""""""b\@c 6$t襊몠!^sGeMɿ/.sI+L@dEQg*zomchXd37r;Oʽ*lqQPʼ=b_悏WhIy}\6TLP%Qgj:=,F]!"""""""""ݨ-t:ۖ4M"vѫͱ,i1,YKz !R1O.˧1Z9ڊ Oan1ro{o612(:_6sb**dT҇L`c290.CT%Vo78 nZGk1T0rCֱak3F;.Au䗁F} ,aydCA~TY FtuScONk7RÒiO{=6p+\|^}ߞ\mYvfM:v!zx]vY P0cRd+B|uEK%!"|2s` 򠏙ljQVV A˞<Ȧ Er|Zt-;P k :3J1(3 zQ'];&"DieBto_-Ie9H#"""""""""'2w}.lA|ywrA Ǚ;:fz՚fsBAG+;U{1<[Z^ƥʶ+1ZU +f.\+74VfӦP97GFԍk 1qhFZU$(7X3rߒK'95H1zVaY#lj(m,3ʿ`2h[G؀@BDu#9W*%Ba#@U'O0j'+P4L@|+`zU oX:+6Oz y_DlX1?< rB߄f\?+yyJ03nh}9>OFKI d) qMaHَ#_d+^<ȷ@cLF,szLOC2xQ4kF7eq<(rVx a.f X PЏV{ ^ ,ZZ_q!t.l%j(ceL$zx˃A pR8v!x i56Dyܺz"qKjaڨ\)PPM$TJ[IyWmu.xXxԱoh aZY!&VDDDDDDDDDD^ !?gOy@)>KAf9+Y`[4{h%G?Y>oq́N: dr Ts9Rf> *sNy#ڿ^,C "G8įNYE)@R%;gyW5GoYD+"Įw""""""""""`{G[4Ԏ0g,O('s=y0 ѺdrL$J"HEu}Th)0.n2a!>2<~.-BS_;5J-jKl̞Ҷ|Ј)OAXI|> 5T\'2rqlP;;^x&͓i굼ډ`!x=-p$tJva4ONI^8k, RfDka/:ORM`ɧӁ]$W?S%.9~]qR0OJS#<ŗ""""""""""ꀊwW#p,_ "4V(qZ_B=y>i&l IOPʳq7e^ Sm)2v\#n6u8;y9e*Qyf@- <P9!w$vFA]|p+'usMV'i?9 FDDDDDDDDDDtW;ųA˞I/B|6GEET >r%M,[@iv<3'/H@rva2  mDRn¼w@]eI0cKr)^@}`MEyO# do+6eZ Vk܈")k#iK}/ #=>.yO]ϴY|V"G[8肅81"g=cluYe"=I+6xt% LoF^5;J^ Sܶ5a<*KL'CĢA% 9L3]iGl ʜ/}l^!xGuiS^ |%ωǺ=PEFƎ{49-{,dphCo#KJ8,̶T{(L{?('{J ^#R41 C 9,`5*Ȣd.eͅ^W la}| I#VyJK1ؤqmN#w86xmG}vM2ՏH}˽9\@^pɽf0`akz?T j2"H#( t6q ˈ"($DE; NH Ryʀ @@N*!HEsR$2Xy܅ | A &E|uYeEm]r?+AM\9ulas GMIqJloP(܎CXkdHz{Ҧy^/4]D˓՗ A" ʄo65]3n{tMOM#jweLd @y8y4_;+5uۙgV4MW"ިȽd㰍GrƳ\Q%VT@JmFc>:L.|pdXR3쓆k(C!w`~iLu.BR w@W D Iϐ]ۙy]2 ^K>>G#GC>l٪gm|T0U.sD{XZ2"6{f2-}su]4$I$D5;J/8уUjkv~4T+/uUֶ)64';[/!Sc5'"3|]AA3M?nZuqW|4U>'x>%vWOK%}8Al ;Cm:$D&: H  m^ "ҷY+aGYT%/2%k#[Ξ+iK#iJhnbE?:5_A P‡,cD wE~bn IR?ql:/: /%3m"0@LP#ȄH:#eH7FR H[++!" ~Y;-7ID줝+)ˤ=5y"l}~!&IL1E uŭ% -1Domv͞V+FGӥgڻku4\Q1I)61;d\n~JٻNx}mݥZՕZԳ>yvDePҊoJsg1/`/Bt:Y; ahE'vF  ,z!@ : - S=υ6w=_%pHWzX`% P_[7 1t|Q]JM"mzw(5cʮN)1bj2EUhb >7!<+DRfYǞ54b<#Aא r d|`R>_{I!LϷ_xDG:T̿ @4&(ov\?%?Fm4hDd/!0ڿ6#<f+i^c>Ύm1PC:mGǫkٹ0Z] (*AJ)w`\H%)M:Oea(IYL= 4*jY_r+d}V C|iݾչ:iF˿_mG}gV:Z0R8C_LN&:Pm1ie$dkVC/J:W\i&ݲ Yy,F*ߚb/`-ݳ  **Du/w0k yIBBbB>Q @@"BA k$Ȳ4D@mF}As%FJ_Y({\v`_=ϯ1I&bd@kY\(d>URk尻%E@/tRkFɣDf?D/m.||<)|=nꑍ $Htt22dI:D3A2(-{`UѪQ|6&9q$>XMtG[MG@Qu; 9Xm8Jٿ`#m,ځ^ V>RJX!ml2Lu,|C?p.pB}-o`ɣ<יW^`ND4" !I:$I!A!.)`زCa H!5R_ԅIA;gևϮ%R=Z@I{'3^"YTPjjl;*h`lbwkdvjuBպۅ Vt5n8qI 24EI!I0i$V61m&Bd4</i%țx/UP_K?z'Ȫb:3zNP` |l3+2Qp3CP. e2ABHGt:D:2 B "AD_E">3/W0R4V_ 1!踵"0{Ny2wZW \|Bi2ب[+9\iL|'W[R}fE[+ʔjʿo9PNƼs^:gVQOU Zs,_ FGM "&XQ<`:fWvaXIo. ,{0[3tj@>/P#)dd}Uֽ{&=҉dQ6k|vYwF@txpP.Ϻ~<6jk9Vt j5,(mʀQe\62*m/b_)w,,Rr|2t!_c#4$͓YA t*Få_۰pG` -gdl\>?)w>Xӕ 4];aPyDZ+:I0?y<Ex ,2AYDu(#Ȳ|="!@7 7;Y+["L3nQ +>;u*ڏm3D8jQ_c]\K#c |zm/M kD}m fx~~Оu,#ufJ* |}70oМ@D$рaL '=gv~۹StGxY  @Sy_-GiPg}>gƄiIߴvgxO;^gy}N#Ã?F+?WĒqlVo\zCmַvZ[r~zPϐv@]YT))U}+ xG D~"*3&'zK܂F`Pfqf@% ENifA񚀼? iD@H;%n=3@<Uy( JRas۹xM%ۧgc˲,˶$"#`z0t!@$v+ƟCjo@>| RD^!v1fx"^_l# ާ}'n+1cH6)nNo7o~\E~2]}ba|>~ a{xdL aOV)PBb4ٗ t&cxYAk Jf'Ny\IQ]ڡYrzMLDBۆ)m7m$,(yՎj6reIM%ZY? (/ ;6?snn9s9WX"[T7egTտhJ򲘬X X]"W5,[._J#(RP鱀=RLO  #P׆(R^(gV%duuϋ 5.]f)ZY_vG]U-ۏcp"mR"Pn8[uF$[isoܮVDչ8lWOXBDyO|BD"E$ Tv` l<@%U ù ^.÷1Bj7 RG  @KY$P5PilӄOSO{wz ᆭgZdz9^# VŊ0 eKy{~yIBi@JK~hG 3R]5IFK|u? ,^2qk$ t3l[n')^!v'Ѧ}.!:%]k0&f5nPPsc !J^ꖼjݘ}{ͼK\k? Noz1r>n7sxGp %¨?j"@\@HDXNc,k`Hظ7Ǝ!?V\e5}a 9cܡ!Jd0T cFu@kUs_bѐ8n0gx:[f/b|}pp,%:[('`pӽHJzpGD]5͓A>ژRe5%~_͏(Y1@/,6]6g~n֚bxݗ#`2t "')/HN77}NýX/1x?\'O&%L xY ~ൎi )WUiYrXt"&Y$fμ1&{p]gdauیl,Ҧ2@̰vsη.t|PgA 5\ץ'(s~~KE7} RJH e/UDGBo a,֮'鱸߬!ΐ uiV)O/,Ŧ@_nL'5@@^(ׂɬksF_.(ݞXe:8&!.*4~%`]γ+2 y9GrNtrz pX [(mJ<bّ5GB ;U%i/KcA\v r@*!# FDJ"g3ztg6y*$}hр!`R{"BprSf쮭v3X:^$9pwgb_`, Nןmw/O+C$ߑ⦁zg@Q8z6No~&ګPe+°BP=_Cz/xnYZەw#n._Wa8Of .;0b d$ϐ.Z.N3+XϪ^UQ1cD(]U4ޱsgp^mG٣i7WojXCӆEI&ⰯZsd=7=(*<: lslќeOHF"#QD gPW 3ꁏZ5P j[3T`8rp],~g*JiUş34"TcLd3NiKJrdr'pnTY.1yL̾F0`,礰p֘Q낼TnOO(IBDb@U둬Z)VnZ=0 鈴v*@> D1Մ+{@{ [uK"i]:]ݾ9?ħ3)Yv `xjT4CٟАPkPfypճ]G`p`K.1ZJa9SԌᴇk9֍+l4RI܆Op:cp Ÿ?~sMj#e>$ )#Ƿʤ坆`PjָI#i8{+FdAV8$w* S=U}@0.:BÉ" /l8#dIe _} ._U]ɤ##6X7:TSL&="@Gb~ @V9QPN$+&$euw0-*HTy@ʋ-X3![Ck ڞ>`F_9;PtFtM.ӂ6*=\LL <*I6AB_!*ɉG'AbWB(|wA&b:"f;HE*m"L' D?~s?@ !F´!l)$V"CO1u!?gELJO/,IYa'w/|y|$?!b\y cl9Lj3g} gdzQc8z1FY9ɉ_ec(*i,i"^|l 3.@=ݾ p!#+ՠ)AnX({,͗4q{O1Y8Y%}RǥŹ^Xx~jcrhkG4fPH% è_[@ d.F `sM$r8ּS6BWW]Fӗڹ4N.]2tLU mbH˼!_$;bE 08y"sǖ ձˢs֑5X!؞ɐ溇%3u8T}k5`;MtHPlе+bm5ouv AG(brjedW@]lI!VHH 2:2jG=#!~oP/ LmRD-mtk Rz5  0 L.XuŊ~Qlt>$7٠3 80r7_^~.?ذyUx1xthr eNL:,Ǡpqq2 x>̵a4֪?WUh -oaE8D6 [Nv{g 'wڟF!UlQGm^m鰓2.yH}\jH_¹"H%ƓQF{&"HfR{Iig tqoiǣ%F̾uxOgf ݰuݮ9QO)숔NYNCl$gdi`Э.pnضeAԅkZr} Rzj,_^%a-= :3{mmb55^km"Rf> + ܈3$_u0Ӆ՞ m vgvUm{kuZE jI)b ׈wJGD-JGׅm;jkml}3 E8W_gHr)5/[S6"""""""T5!}17hmV_Vj,]Wն ضڰz.\ 219X pj B 67ʰhat}VckmM[j["t۶jVZ7Y[2D8"RF$> JMY=)6XsM!(Dmg\ڳL?t @5֖3 ">W#J} vEmfk5"cDCϐʂRJR)!>/& B\/J6"""""""iu φОZ ZJ#,uT* (t `i6,.hhBn/`K`Ԕ!!#!QWHK i ! RB^Tz@ʉ2d#"""""""OH+( Kk(jPʑZLjlV1S ~OE l-Z'jd̦l'dRa~! P1ax1sY WC%"""""""vQai~exQI (7Z9VvRM rb~V ٶ-2H}29`RQWH+(BOHDcT iDDDDDDDDijxЖ~ϳkC6/Cs"UmZ)>h+sUg`Jm],l|Nbk8L479` ;t ' Ӊ0b4 -k;R-V;KDDDDDDDD{ mCR߳4-U߅ 0%.qP7l07[˫T56L4j,Z2hRqRVPHeK3$0<6a! 1\SH*G CKW: DDDDDDDD޹34lt,Ok3,jOND+4ҞE|J 8*]ph CV[(:@v"fO+MYR9؄` axmԞkB CKij%LJÐ]i) !9dh?i=iC p=ۓʁvr]@Ka Z\b *h-uFA)Cl t`@@0AlVQUljK0הD!a)ҳk"( 8°0!LXg”3=)$ ԐPKDDDDDDDD훡PZ(e(,pt Q4$G -MNvHH)=],/r讇l[(G,DH HQS# sTJheijH h ՞/l͵ꇌ&9TbW >HZ'˥0UlR yפ)=TZ>!,)-S2K< 0\J6"""""""4<@4v KB ۓҀ00ZI=h;W.Ez!z*Ao3dZ%db(Ha>,EYYmA0jWBp 6)- 瓆 JK'Mڧ XC6"""""""Bi VҖC1 -bJ ! 4 !dJIU#Er2CD׈oƦF[ihC RR30=H81#fIÀch)M 0MlҐA)UP)tM,K 4LH-/%U1O ᩀPR ?D!Pj!YYcZ)d+<[X !^LSDt҄t# C‚,O>Ai2NCOo-$<F2- ҲjU~"KiS 'ۋKKˑZreB:J1Z漪NݼlaNFuP7,aBSv% 6aghASX' mh}&"""""""vY4͔w?] hbaSЮ0 AxJ3!t TCmnUmi99Ȭ~уr)[=.@p %0RC )EV D[ZCkYΟ@DDDDDDD2hOm{1P~ ܏ %LaZY0ҐJJWh)r4TL!Uj@lmB$c˒Հ J[;RZB2imt;=$:E(vpUWZRm" ! !A4R 4 lm-޶mg$iYB)RB@*WHOxRHVPNT' avi]0\Z>'Daq :Ɨ?*a8WU>!=N+;ێ4:e3>1أO< L (//G(e]r濁ttw^ )aX8[i!1)᪪6S"""j/rssqux'1s{wK/ǟxq>+O_|gu>c\ÍF7O[nAZǎnu]ݎ]2s[oW yD0.PYRKo]_}h|bGmj۷|3烰c6}i\e kk[Np'18⪷0ާ0F[G)tHl;[]2j'Ѿ駟A=0G-3)'LG}-oI =$%SͷAQQfOc RO܋'z L.,[ 555HKMF(ÈÇcҤI~ ^xy|sX9u,֯_ ?e ~wE8{x\wXxIv/2W^1Ŕ<ևv|"??55[djlXYĎO?N9ۻ}45'O?ÿ>X,ӟu_O*pцTTTHw*NyHyyyۣL2y•a|>4.[ }٢P•axFqew[~~X,[Yq`bheSNO?;q@m5Y(.?*{?PUU_ >} 6v(*+jιlR<+!?#18 qqqxֻ3O#.._}3fYC23@ܶ?DDD]?8*+*pw,(S&ᆱٳߏ&M#5Nk;=#^-7~nz6 uLEeE>읽':᧹7 / i|D"QD1%`qɎs\vmnMpu6Jk8fKDDDCaa 55>`SD^PPP6\Anݰ1?ڵ+.[ %E`+p]wK.?x9MTbiB,^;CN83;ݺuï V-_ [ 6D Ú5{O4W_SME_G} |A.--20fXdgCrr" \e/:ǟlԩIh4Vh4X$5X4 v:6c_|X} umY;uK`SVrhd:<EZC)H_v'[ѵk7L\Ím{b1L:&'r Fŋb}$""=g|Ž!.ڵo'n{ú³Mƍ-n۱m)lG e3#ph;222.~ИիV[;mgֵvEQRXCڿ^yVvf>=y?_VcaPzO!""=|7W^EzxWQ^VҒf}5WcXr9l;ܵpApÍ73gbֻ_GVV&^&/>3!6l{a _6搆IXBM%[Mu6I_ C^,5M(Ĉ#1sL譆Ι֯_?~m?1l/< nC: ˲[7?KC׬oO< )ؐ cR0za""}l]YR6;h˖`[kV.DzŋZvZZ:^ >,_ ωF=\e Ɲ}aۮ2DrrL?σ?m۽!̝3?`쥓Qyo p=`%Xa>ck4\zecXl{}\w ޽;>&o~S9szj,^{RJ ݴBΝb 塲J)@(/+xŗhKF͛ D"$"""j%P1ڎFhm=4X5a6֯C,RǏߧro;Ɵ}&]pݑysơ:6χUUDBBB+ g q!;λnF7\`ҤIB  gϞpP:99/`óӟGrR"G˵D"x'pyb͚ո'ÆߢoS=7Gynᆖ$"""j'D.),DEy9,X*\VgYgo>9sf#}p+DNp]U+W}:;wc [V!C;KQbQ~L?W]q~m 4ă:WR v,pe%6on0DsXj&ϰ, y6r Bq0- JyE(.,D1<<_AJ+!@(*+ P]Fiq1`/aY>+*(Q;Жv{φluƝ}()ă7N?&?ϲ,t뚁6n܈BYP ӻ7:w${|DDDkX>B`ʔ)x}Xl  vu ^mU mccގ+ߔRؐfu WV Fڝ'ֶ۫`sqUWJ+?0\}Օx'QXX/pNl&:"11ݻwG40M@PiBƈhFqF7v,<#"""UmO5m![^xf?ꫮ՛BgY%&&?(-. ""}P[{k=ؕ`FDDDDDDDDB وZ!k{ وZ!Q 1d#""""""""j!lDDDDDDDDD-_l+XcYW.AtOwl6Vt1O_ "pǍPe1J=ݗ}VӾQB6] B怭nDuQ~(CJi K)MX{E ;mb-횮‚c0llL*ww/'(ԬoMv1=r4 |Y{9Go"5ݽBͺI0a/7:O=-.ƺdmO;.Mh)Mf!v2Q.7#! yln]⵫2`[In4Xճ뙃 AE&UíބK.&>]@hޙ_֠"oG:7U=IN@A8隇03.;NKj[׼6UDW/ǫ-{-3W8-]wi7l^x>xz>b2Gǵ~eVBǀ)è^^ eF&b̅(mQi'Ť14p$L5xtq*߾|&) IDAT7.9y2Klԝ}{cpw_??oQ8U:a2Bq~% !ie {o?;'ߎkn~~g||OtPL gv ?㏸|@͑vɾyxw00W1e'펑W1"S,B( 6 Iu鲋1s1r ;z~>La"&;oM M׳> xbBwmc cQ6h3:*//.gXM2jl}?oīO,jdx@G˧i#++Vw>{;m0OYgE6`. >!qbтxIB2G[٫kdPE"h>wðt 7[_0';;u_N/ʳė˩8K?< ^U~ރO/]GMSfa'_2m5xHL~gdϟۆ-]\*Ǐ;9`=bpc=+<|Obx|y&7Xŝx~QզN 6,Z06+ݼ_pwi[ђl-YS8+oߝ Yk%Ӟ~g~/f8F05`|sEXWao=/ǜ'/@͛rQ87l=?L >k[<Ps|]N1'%QQ] =` OgZ&1qYl @zx;<g 3?aD!'rRFy߭Gԫ8ˑ#le9ߣph)JѥO“ओK’(|;W;]2?sZ^Mq@r r m着 )W3f|7 8 8|oumxa&b@AN3,>:%eCx RH<82|]Zq#:T 9~skdSou~w & G✓E @qaCa,mab# >_úYð֗`CTaG+qzTE!ܢQ] I}qDUecQd|^>$gKIttrJPVB') m}?w bw:&珈vAK>:'[_49Ms Xq> w{Pq# 7]k75-wvԠ2̌6d8nz82U8 ,5 g>>UyUXh=ޙ,k0S#4s.ʳ0'PPtJyۜ|49?i54U #v.T./@A)BF׮]nq#lv 7^U6~i7ź.*Jl Oum&5hSĥ%#Ww2LmbŒƂ(LF[KsG7xMqiH)|ve Qwǚw/% AaP x[WDjSlphc0pg\Tn#ÿlXU?6?'Rшi wB"Cfƀe"ģ~)7]$]i<'\Y ' '3-f@c=:i6;DDDDDGC6 @<;`I嘓C'sBM~$PRj?jBiLHx>4&3z4!܈CFf/\p4%+byz\e@T0yH]G\Т3Pu$|zzvO _c,d/*ªQ넁@"1^~P6Fd;6|tP'tr}vJv^/mkT/~7$)r4xTu(i` Ny.:კz(yޟ͐Qng_E;ߗf!*!>Pv)rצS5hDb;&O-^*ɝzaS i } HJac^@',UwދWGVNzȻ?ޝ5%հ]"Y>(Cqڨxy()F0Y;z,ulj$_߬CҰKO̳B]ZYpq٘ҷXvFJ6g lӟ7B4)Hh?n,y?XrW Ͻg-9.fxM̚eخUqxV!޿Mܗ9 <>Z\T?W{7+ϳ>(yQ=`kI"DX& ڊčkQ}@^.r>s3J6\!jr*a+@BHLL@!kuu-m"pqҧpQC9$;i| T|}+> l~l9b;_u׿߅gVaԥVNg1v d~i`uQOJ1v\c 1~6c½,B2F?pUaт56<޿}׼[  o%p+W3 8 ^ ï ;d9{Rk{U1;s=ǬΞ(ϲ:`qqqE9A  ֵ+RHHa{`)*/{@wPF"pTi% ~Emc""""""!X<>}uX(R\R᠃Uy2;kZtz &}zHOOR ee HJJByy 15͎S{CSbE838L}xt87Z} f:D!B@J~ hh! D0@߃ !>ZcMn.L7Ұqub1tJ누&|" ER0#U ~; H5Ab —t@ѯmDDDDDDt{Aȶ{y=Ve?Nk7yyy8_?TTVHLNEȊÓ,CYT[Zga1׿#9 ?|=z莀>6T#. J,u!6R /?!# ztVXXf뾤aڵ! )P\R ˴ߪ}hyKP\ZnݺPXX>FxwLP*wZSS%KQT\nݻ  ! A[,C4ƍ1BuLA>} eGXCTS6 ְm_~2&m++)E B 4Q`!nF<RFJ F+߻._ʘ%Kpᨪ]yr?~"<P_ǒ>n'\jUR;򩨬D JKiGA)B yXWX/8oH|;{62\jhi¶m,]MUQlAEy%6lXj+VSzzl>""S'teY(-+GUe%***VCS+*~C.2~xX, CHOOC,v JJJ0~xD"Qt/7w>6nm۰,+))łEPQFVVu@B Boh@צi"!!ܹ(**Ff~HMMiбcGD"4# bA3k 8p^ ~CA0w?Cχ VÉH#n4 J l:A0DDDDDDd{M֘Ço]Qe 2dHEᐅc'jж#%8t`Ư-)Ps7~2R0We]Ykנ[׌VCuu5v} -- RJ(\) t`ÆwBp8Th Ґ0QaR_#33iii]ۯZÆᗟFYII{PJ"!>qHINARRҦy;$B롪Ji5Uub6|\ QRRA!\Y GMMaB֪D!!+"]޶ի뇊n/0妜zGyZk(u!>]w#bRK,n555bOJBQGoPRYM \AO?CJ芕KJ` `RmómD?j$ ؈ڟ`6&dkln^Z[|TT""5s4Z>dMj+OqgG}t\RJD !EɃw I3,+MQYyZx|^rSRq8lEˋ9.rs"jj4Aff&I 4P,rIm^Y2N[*;Rr4A3ٲu3[=-ZnU4bWF 6d|,:7ݗ_Rmy^OrѢ4>/;fRNa8=2l"#G`B!BQ.:ȶiVwFVfK#'7o ['=nD)KF^#| 3:p8v 0r8EVg6l I߶S˫IPlJArj`&C\8ZƷb\3 L4|L48Dp݆b5#88ufb%dge<fZ~*4MO= kfVuDDxZ>-';) M` bFEѿ؄B M`x IDAT!B[guQ#·%) 0p\! MShy*OʙJv<7 *쟊T~$IIIЀoWh b0h4`''+Bά &=#h$Oo`UGC˃0t`hLh"9x0\ٝАPCNRaԭSBP:uhG0DaEP=-3F).pfQ,e*0.s=ۣ4ig*_˗WK%Z Ahh(v|͛<;$a 0 #''ɖN hw}! +VGH8 9`B!BQ!M/.@5QL4_pdrPQT4ӃWA6 00o:kvCmX)\b3 r]D^u dփ4 nBt OjC֭\CB0M>> e`&9SgrJbsh*@`_^ eb-ԭ[BPmX2S&x]h1u2<2- 35a;NOFfCagVJhHm[P$Z-Ufd dlX\YlYvv6W`x !B!٪M8l[8vi8;Gܧi`n::hy oH5jt Jr&?0.vw: j`؛L5 mpn߾ : 9-,,]vqVά]"]f琞AH9te˖ѢE ZǗ{с_F#ՊLuәj!a4i䣡 /cǘ^'~Mر |pf;,_PK.}>l,[a|#B B`v<}0Yv|jR*4/nc۱ll6ib| p80m3gGZuPphyd3N6}޴4g ,Y"CMQIsIM!B!DT [ng{di:(硂E^Wpp\֭] Ŧ݇m>r v+ ޫ_"#F >>/={XGnZٓY;}ygFxDtNzz:o.q&9KrrZ\3gvkڔS!ĝJڂޥoǴL,8QP_?,S'(&\yuDF%5La*!$846lāIڟю_~^={V|!!1\ZjU&O"44 >aÆ ѣG9MMVCHp0!ǹ={ 05kqavN .)[L^=Z󐜒jEX-r<$Aedn|Urөl67N,XEӕpx L  0hB!B*oI)Evv6SFVKNf&_Zڿvݺ5k8G3`գNΝ2m6\wg{Dqc Wa6ϛGMլ1W&4Y!B!+˔BيY䬵r^.J6qa'4@]Egj6h@s<4jԈ~BBBh$ܐDX(CIN'zFZ:iYNz5ƍb__l6Jqu >,7M!oEѬLFDо]6hPGG7$99?.4*l6gwLXXX^i|s缌s^K1qԍ(ڌX?oQO6k !B!u"O~*կ_CE'?6i%'"<塬ԡ[_>^e)~bNR@@d0gu-߂AA\5rm<U JrS[qDxt3RD4 %&B!$&D95Y\\eg֋t-@?9t< bB!BTIU: !jMNr *áB!BWmUB!B!Ouf\B!B!B B!B!TlrB!B!dN6!B!B!ʩVYSYB!B!g]Y(jd;΂B!B!8r*; Rmli!B!BqY#|U>B!B! B!B!$A6!B!B!IlB!B!BلB!B!(*dS!B!B!JPlB!B!BTudB!B!f΂B!B!(Νά,Td4dpegAQ֭[Qnҟ.iEԪ[[_[YѤj+; lܴCB&R(SDA}&<^AlKq!3 SQcHmjiSom)m)gEziEl?vD-RK7Dz V6TFQ#HmjiSom)m)gEz┒ BRaEQHmjiSom)m)gEzԒEB!B!(dSyQyI$IG1͸*=/$IIm/q7]ycȿ8+=/**q <'.Ièy;dE7;^΅/mǭ*g 3U2.ۛ^QIlْ [8,xx3 ,X*Pf7|ϟ1j/&&P+0 ݦSW)Y-~*J <Z?oq1bPOqny(~7_Ȳ۾ 8UOuU3tc+ڙ5xg|cnjyBf^=j=2b_S,uػnAyCYzKIGE{ޓfX5)=e d2Pfa: jo_ nF̙#3+<31JթWd+:hksyMbÙout0/;K.܇Ǜ7cn ًv[% sBӛ\2 ~^z޼6v7aTXbu{?KWt{)hE\x1sbHWHo޲F_-[dt,Vk^[V+Aoq([v^.ۏU%MK߰Dذи(zy";n}_} ] ^4y|b}*hy߾ӧ1䶹:Tel%)/ #p*{Lt>iԗgs,%_OytLbubc_##5>t3yR{G|,-uaG]FxlueŢk\>HNT'[cyEt{ыLKLOU$0{^¼c_|4nUw~ޜ,~v.ښeD]]c&~thKLQ5w9/7s81is8\O0qo#R>Ν|e ׎NO{?|kzӨnO; $q;Cy}x 6<5/%`D%|/i3U5{޽ӧَ3al.4^u{~ֹ%$&;hCtSBTN<}/c I{{^]H2gk"qiQS~5M:g>ϔg^_&^t'ϼ7!SH3{ /ŎeY~7A}7n#{5/Þ[̞A.iw-$zIL` zo*O^a0y*:饩F\\Bx~!3`ϸ,#1q'K{ÝnV ob m]w#ixjO&`揻ػ豑{s|n\̲]ieᠴyGG#%P^W91ejzGv'Y9e*䢟 'jwh?/:[M#`E[7Mĥl8lɖ{-[01H۸$0 ?6cfv_]GV1^>eov5,'CS9Xa)M~䝥!\5g {|Ȅ{X3VdgXje㋦=l߰ Ѭz;㢉"g[L{0mbϊx~v5l/YYw4O=s)!_?{Ml߸ A,Dt`ub;ֿ7Vm ~}ϋn;{rZ0dwB 5E{'y\u ,A➥<{^"^"ed\u=%<[J1; Wy|) ?Oߺs?e_sk3g6sfK_d/ 11Sddz hxމT iI A>WrE2Vy1 00,K,]ى=g0ݷ͞,3[[ e(ʤ|$IRH(!<+o?gLL/fv+#q&rE,Qƍ6b&F{1 ^7\z&ub]a1z=:a c IDAT?yP:}٭ e(BgT9!m|=WwąCS> 弳 Ii:hvuX/9+?>`9WoNlj+>qF48 m^6[n4M0M[n=ɯik䎿McymߋiYǚ7;d\eACHMЄ>74}W_n7,O[YO>M2*7/nK^ FlnXo ULJӧ @\-z) cinOX?bNJw1} RИ&]?4$EH mr1 U'-q'Sԍ!:gszVW:Օg]39Le|>̒$wrq1_͇19 x 7^ϿM@&ϗw̘XZ^QXaI=tyу"'+ގ:>LQgue a oq}ظx ^/cIb׮eP`j=C>#hB6ςtىpɩix1rX&F|gk(A1b> Ɨ \:e(B&A2k n#<}LqsR~Ӧ5G+oKl/yXӀ`uEc,?D a{Y`$A/2KVr۵_ra@7rWPka}Snn $(յcupo&11 V9 +gptGDxа8]Z3?|{.v;y܋y(KB -F7 4?Y{IL079TR%Wa>6N` ky9|O)ń7{o=E9|Il"^mD4Ź, c=I!9ׄzGMn搴 Ģж_sf-M -63 Zt KiFia]gC,vn7q >U\ +ֿ'ytFŴiUR?VS` pQ/V^܆isllN}0fL3AQ0>ɦa=: k*) 7h)>@b? $a]oI0򣇞_GҳQ1KoxoX! 7q ,Qy5'/x˯\}dOΊ,sZl.oTm}|Fھ"O0sw &zk\ 3}I iQH;"h2 'SWDQl#+?φ>[M/>2GnN7yoMlͳLZ$Y ]/n}G5Qz[ď׹Cp1_"TP'(BЃie(gvBe 鞼혠 R$h]wz]'amK( U]̋\D1I /f^E8B (,?@c3%c'z0qЉvkDD븙39cs9y2h2DUnz=^yGdìa<LGdzPCbd+O'ؓert{ϳb&m~T|>vvkXS+lG'j%-aQ).%l)iqT{Z":ҿ-|{"nV$l'6[٩'uuӰ(15VӃ,ys%}>5 ۪L=Oq)xx=C s>qeCuXQc~i8fߊL1??BO۱ٱy):=ރ?2S}=܅!|$3 @ 9ۇRy!))QR(K sQ9u\.+J[M>kgzv0L[PuBBhŎGT[\:Vw\ 8?uiJ){A*>}$cMmf!,!=/PyLJLz4nΚ9M), z!aajg'J'82v`&([#\g/}κCL_6;˫)qi:`kD|*z'|}ERѼ(EɟsJ~W\'+/f￳t.]KYl,_Ί?`?XbVlWd+Ox$ϓ_dep>zDwn{Zr_g3i}4XP`sG%<: q[Ix+V|.+ ^ǚ[#X^y-pk \&8P:ǚFHVqS4{7ogYkޝgokVq;n5V- ֊yFKwv4-?6`ƫ6F<ciƮv\գ <(sNYw:ڴrիWpn;\G}ӧ/WՋ={rNtу=ΩlW[]> =Z=M[,YcjjmVe6S |vUfŦBtP=@ MU=rvIbFZv={<" !ɰZlݺ-WvV)a㭌jyªd)J3T6Y=O^MfrTvعk7_4PioW)tſJNg}BØܴf 6iefzUxs~T&' M+sVUBڢj$Gƭ8QkيвVC?W6mSI{Z~kKkK9+ԛR U둅CU AIOoؔF}3en?'?WJegzylKԪ[[_[YѤDV;n UJBHS3؈Oʃv浳mj.iSom)m)gEzԪqA6[YB" z}2As%mSH{Z~kKkK9+ԛV -Y{egAQ ݳ D\uI,ҞVmRRΊ&Vݫ Ը TvB!B!jvWv3P"T\!B!BTqU?&B!B!DW.=L0c4 łi+!B!BQ$VFi5a`&111C!B!BqIl66aREA5P b#b-`C`` ~q!!!)B!B!T90 ;@##[p.Vk^W.aR ׋vt:!++Lٱc^T^4O%͙,zOQˇÚs_7Ϥ{| !B׿!jv aP9A?OP|O< %Sn'?"k9(?CW(^p"ޜ%Իw.ċU$rb|3'׬_֙MO U֎Zy +: 2 ̫z|θo]邬'!{븰sT1=\l.ЖpMCӚ3|9㾭*fqmWqs <i1oO&?Oocd(@eT`ZMsW\~Wf ?†}׼ ni~I?v~RIKi дH敇Ĥ~>GbkNA6x:( NR޽0ќi]xf>+r6aM Rރm дù{'lEyk=E{p?`38vO}4Fܻ?O f:̜hFx<: DJ'7jV٦Nʐ!C&MTm|>ܮ\RJPr"iH!5y/:Hr]ߚ-xmؼc~]I%2M婆3}Je 6F}* S{Fj~r2_z&P׮m)Q?!^,u0jsm#;'fЮ\d*@m=9dG:ΥWaq=s>_n'>ܴ?Y}q~@W:A6OGק7k^'c2'ZztV~D/{N㢹xs~榀zw$/5~}$;+\b܈Etzv.O& F叴"*]]?o3NsNǥfGnO26R9xE)a'Uo_Ds<[yeF&_>WdԘ%%'>ɇ?Nz?)yhl 5͘YJվ%3%aCdfIt=#7KxLcÜ H}~Pz)VQU(I[ (X4?j妛n*^/i?܏KI}~0W;.7J2gE hVYm6;XmhE҄l|$.k17/?B>OwM_<ѽ?/m3ь kURnl>_#:d:Rhrغf?sC3_װ6 x4L5%o2+Nghk-=7Voڙ$2w~Wo+U䃅ŏy54-S~wSG ,.$}{5Z0 Z[l/ ᇠІr᧧'6HbR0Ȼ#̟{/ƅ7|LK3㊳4}z)l%\9ܛEvMn>sthpp.8Ƽgf<:Or^v>1t|דLg6=q%'$gӇӟ_N˪C>@5BQA:4kےFa^?F bi×4G B"(McTw*<ײK[ &9K=~M 缉N5zaKٕ:5cPC<3I_"%M9=|"}b U(Mmy]FCSח3O̮=7GTmgs}9>[(ΝxE>Xl6\669*IǥA߃ͣ 7Y#،JÖmNv15<e\32|ktj 981m|N` \3.7& >A`i *n|SzPC'>O/ֳje bKz+5TlA5,:I2V-BݲK3"xӸVl_{:"}>nI1k|3<TŻ<5g ͣ[2w̢W g؇^[H0*==kp@ԅ.`uTˊQ&,|.o. IDATh˘e2Ώ7H}^쐸JOZ?usqIđ/=2%Y뇎r4aޠT }'o\r:ٷ?fu<Ѯ}]1ddv倐=A6B 1n8V+$aZ3f K8N @XbEV-Zwi=2}F%s-4v$՞ `ז3$j9-. ?qΡq.5hJ;ha;F݄2k)3aiZᆼѣE,7)Qlh[>֗U3{~Ov 3tzz*n4N+Zy:FQ ICZxCb2{k)Mqh#Njk^*"ĉES<}.,!PB)edB7nů}m i {.E[YZ N;γnJ5_I!mm0LwZTQPm*ΝRPq/VRw* dR\!\U ٵ { x奱?AG/dÜ YM_2p Bg.Kqڪ(aĥg݊RC䯥cysӔ/jf<'&C0q7(T-pT;6Rph ~vQRv!(Td S3=o$T+8=,g,fd4k,ujݏyf sx&t&=iǷ~,='٤ЮbmBKtd|]45E-h7h:?Kʨឞt#1-_,o&-:֛%)zc^e(%,dOZ޷.9\ Ϟg]R9oL\ˉ;]L/}؝浂^O~5őAA>Iv QZ;EvMZLC?H>.S.QwlUk$$u#Hu~Ktql/m2^OB#߰|,>ًMٿ.po]&#˶haTFͨM$qĦdpALtɿa[;inmN7L⽡P0䂧'$;3Ltc(cE${ a +f %5-D?Gr<(C$(g!۞e3kÄO3]`Z D+[>ƈدYz")ջ$$d$%.pG2VO/(0!])`Mג-\qcK7kL=vs.'s,| 3sLjժuOgZj6bEUEUP],vV;X=e,b ˆR]\J6QVXǑ**BN{*"(ul/ŭ8Iwc5-!(xuZU@荷J1'9xmwۚG?c^_qn~BQ\sDL*4 )7僋qd=5>S,M3XOv}ײgx?TOS[ϑ\Ӹ46y3;=^ucIUqYE-Z\n9|0gT)X:e]fME6}ҎTtId}] r:aJHȘ:H&X-:VK .v'6{ 6݁-W.nN\ܝXu͈=uPF%{Y+ᄑ+!YϴͨvGU-ڀ-;l`$^zҰHlT0`_ $Zϥ;o.C.x|7~#R08^^tEg9ę!\q2> SRqKEɡrv\Y2 8x:dR4ج/ιopqF,5/Z4̧s'ib$aW%F~~(+fe 8 -D>kI覌^Xٵ/1go3RsxbxZ$У9\  < Zn6 $%qF~<=KOvsR$ɉD_ agYeK:/na޼\vX(T.cӟq&)GY`=>5*cF`E?!=ܐ3 04ɖ%V\,?/8gB??-\K eׁP߽yN M9%_fM`g~4/]_8 /3mboϰuiH|jcɴc ^r}/vKbN.oQr,9rMO tT܋k"c{b{LT|2qW9nC~W[`\ӉZNgj'?]Gu|0{Vŵ8ڏz?w$b.l[n2\#Cst櫞:әyh7$ ׈ML&!oN'ʧ>m&d%^{9IkNk_߽JFSOKfi׌- d Z;1y15絃,b!=K,fiVׂ!)eIOC._0v,sɘ('s.Ni*X\lvW]f`w&ݙ-o MŪee7?kgd*lUh4W$O4nF+?NYOi+(na b×m) dha=ƭw}Z]xe??ňz.j^Y՟=Mǯe\ ~Y xuzLбY)r* rUgҺl 3LߙFC #7?͜!O%p \ԚBR-#7\ruZ7Q~r9O@k!:~ɕrDorz~ͤyiV5S'ߪ,,ؙ'WP`CEB zߒKgHӚ/F]m3Vob߻ ƒ̟ ?]E/\]={>=~eAI&qfvx?88;eD+sCڋd <3MaU2XeJo V}\\eT\&d{pUł[Y`י$zscc㍻Et"w~Je$w_bLǾŚ)c}TV=]7ۄv ^ο+YxHHfFv ՝vr8 jAgzwUS-=VyՊշ!9ćAXV۟(<}n+/7+v>X~}{5s~F[$%o[KqY zfRc_d$wZxVͩ)bfsfǽ L=ߒ->~ڱi&bi$QKKxzDJ?V96Vm(fbm N<ɵ"}G=R"c>c[U2,G"}u_w V5uzgRӗSZz.r2r@mf^^ rE*6Şʒ*zJj*"[4SfuUm]2lHUI~K躞]9tzO[7o{W_ȲjPTEP-#)&lvsKaNxg3zf4&ɤ#𛿄ۄ4 mCow[tńuR>ێFV^9K(AAA۬_4i똆ai_DV~iի<^(cn\M)JO1d3ӝRh. j*Ni85Iwjӌ3uŪkIVHѓu{,i 4N\,|sLbJ] ɣђ+5'aq1ʼnŪ:j(&,# L$`MP ;DoxF T!5s<<<1O;nOg   p?p$rdUGV(,2HȨȦd*` ipbcElMCGd ӞJx忹Yْ=+ҢNEhY(t{>LV1J<    A֍K OJ捗2OMHǖWF[!B~%63v2AAAAȁj׮ ~IAAAA0ܗ     k"&    IAAAA>     '⃇0 t]sIPI     Cvv;$P3M]1 ??BA Itt4^^^;   X,XQD,,K`Ȋb(n?ݎ,gt RAIv!G;  | AG똎xz8m``&@gr",bN41M02\2ao iV^ <Ν@@# $IAևAA;kɸ6{1Og8WRRR2&##Qs;; 33q;b3!ao  f2MҩC7rV~>D$!բ՜H0rpwA$^!Xk2wKZ=ג|u8Bgq[E֌IER_=\ȁHCiG"s:/w,PBj0:{P:1y:,mWwC$t%QD/ɱv$ ߄歳Xw"vO֭8/4 Gr"Wϑɵ \B|LIZyŽ=8D <~2Rīf# M\AG6]JI57 v_5i8.{h:ITǹM']3}ğ7mffΘR8cddgʸqP< <[&>!ߧ"?mN ⪷ynv!>ܙ3a+li3dWh|- f15bczݹl8+۞csd40~v[M3$:3poch)1;mZaƻ?WBx}&!*pNAx{"Z 2&`K:uA͉I֓;fۃ n fqBK!Fͥ2X{9Fg??-Ri1S 7:Ly ;\̸|ѹBg4]XBZ0UƵd}M=+Y P|*^ub#[kwypظя>JÉ/сQߟ"*:Ǿ~s6bІ\Kr,'5·I/.+}"vfx3hd2`\/tr}f n%ө]9D}|:kFw#oMof3"&+G,io3PB,+ūqpvX67ID-IO_ 7W7 ÿH JvO$6#ߎZo lULS=ѺóAϽɛOSqܱ#Q7/Yi=62/|ۚo,Ȫ z+Sw^Lmλ?҉ū5^`ʞkdm*V˭_;/=ܓ(o*uH)9k=^^مBOv彎bEng3sG^YHsk2Œ:łEUrqMa%)7k`QdyTAJxY,ufX8f|& {PIKը@q[Z)Z7xoqz1zt@<ܽ)Z* f=ů95zbxxSfgʺImhW>[63rR yч({7;!A{̙3o>]\\:u*UT4MCn`DiaIhW1“Ѯ`FC”LYEŐ$EMLQSl@ڥ|8@ 7C2J wcgcbF h}^gվ$~eŖnW +ib"#t f_S#XXuV'|P9p2ϊwyjKY=zv;#vIq϶bRְH&ɜZ wn&Έ~MZEx32uE|ܒb? ͣ[2w̢寉i-sJ\i<Op{rN0I8>weL2\ |*էCpиSr6>;\uv.d|c9udCRߝݣB 1n8V+$aZ3f K8N @XbEV-Zwi=2}F%!X]\Kԑm*[FpCQ" 0983{ d$N(&r #B.P!SZ?vEd38kz#Jo#Sg…D#۾\$6I8*1o0մ\%Og,+:QY3vOW,ѕ`ё;zX)B<̹մ/"#%x6~{Ig߷oaH@LzWa`~=a -k1DF;0pT)6Ktux_LMR~3Uۙah3%ʊGI˖My%FVʬˬ>k~bQt੶Օ %:ܹ?C18NRD81-VI?[˴$Z$M~_6rsV'^3ʱ:IRBESʕ7nJbȑ24M4% YՂ!+WT ILﵖMEћ-j6L^ٍ%hRŏ;@nE)~H_ uAdwp:A$:Iai%8N XJ{y?=KFC8׊Uz{9+K1oR3jQΣeEL}>q}j/ a‡h9q>ߎ f8_Z$ w!JVkǐȮI8qĦdjbbܳ%64^ʼA؎zZg^4,U%Umb?tg~w2iYE ߧ2ToF-Nne'9 k' So]ӣd|l{>[ N?Ͱ^vEA³ZX݃jSP|O M)P Ҳi;D?Grv]%S/)_櫾{&-p ?H")V/|4_DR<wHH4ηIJ\x{2VO/(0!])`Mג-\.͚;pρݜI=|+?xo3GR~)`fΜIZed3-Wb"*ł*. j2 ]FKeHrh XV#qFƯe<)MsAA)\ڶcMz\PA\d[`h@݄],j󳕄\¾%|X:m-i\>LFq6~m+R?t[wm;/aڌZKO%kjԵԽfZU@" {9kb@\9xTxi\c{qϕ"9M fttT%UE@1(xMK%W$L3 (KUûG0gR\.vtYE{ N~݂g>,{'vs\ _\hN?~*uǗdnĹ[ $dGǹ̈́l;T!=̤5Ա Ɖ|>ݍd6u pit:q* *#ZHii:)NIJ3(5WW]}_,R=bD34+?hHs ?mK) Hꍗ:p,c&wR.9vr1꓌P jZIy2TzOsYAQ<AǏLgƳ"U,RM: .F^=j7M/(p^YOϞR{.x>b჏-SɥuX[w8l1xGuV93:^VlL _5tuŻ0~ 'Xz~9NTpۖ'3o<}q۩`Xrb{5/mj_aΠxر{V|Z;Urݕ>3k9;V͎{z%[6hKIXsvGFG% ^:^S'g/PzZ96Vm(fbm N<-l ݬV _!> juVw]*Ydpu,{JjE 8ǿD9OI}+c-_FRM9)Yé19IYLw=ۙE݉]؍cU ab| c%y@a=AAȆAC,dG%ڣA$ `RK5a5VTF}&Br#ڵ_һ%kIdb7&cg၈}eMnHw|03}~c ,ݼRo;1&`Ʊ-ˮ܎f!`$0ct8cYf\-}s*@BD>~p<nwQ$$nWj&Ix{/'9v5r.Ksgw#>{D٧yqەfTI'qݳ1(loޟy'.5gUN2/nS~r,Mp$'qq\ +D~('.8k#qq8Ipϳ.#^@Ond< /m>PaW&w, 43E?T4_X'M.S8oIf6k~1 qnΔq5ėO{c_?˹w1h<}Օm192tZ|-Kqj PsquݙD^8Ʒdp16S-Z0مpg"΄ M͐ \r=[lN%8FS=fx3hd2`\/tr}fLm͈4𷣺[ib[&7tCfjqG:ALǨ~dĄc2:Vb'31?gѧe;=o+K!-围Q 媓Z)Z7xd1b/Wx{SlU*9rѮ}l8)]9y-!A< 003gb\R0uTTeiqÒЮ&b']K6c% )+!+H:jWX;_XGuSZ ^ne(>Eُ$~_{ Br76籠LL#CW8p8N !.pbW(U b[Ÿ %ݑ|}ShV(d.%[;` a̩U@ylS3"xӸV̈1qKY?X8RZOxd4:,f.lC7n|ީ[0F7}JATӆGǞrq$j5KoK6kVcDsq?owg~Znq`+G+6 IH%w9{h>v.d|t7AȷPUFv-EwF߲=,$4/,oZLA!?2I<u3E}ՏY90XNc_xzvϲU?5cԈNx]%i/Z$M~_6wՂY ~'2WѫE,b4 ,펵H#6?;a ީ8HYrqiL[.s=39}߾Iin|f"2_2aغh-3xDAJt$c DG㲝6߲gnZNA~guOg2( 95lcȓ LO]£Q=2*W̸q(U#G$88i}GQ<3lzBBB M@ ( vNȝrryxg;={E XPD ovw t">;<>8 [pakzϺmYkկl`UM#-r{ #i\rh>j{eDS[)A6!S_jX#oT⺜ÃpѤ&ZdwF2Sߙ“7 >>Ză-g]|q,~QKv<3ןFW2| LEf&6uq৅ Y8 ?2.ylME6e??ɿ֏ڴh*J*޸\g091O[HÀ;HrǾ\􏧸YA՘&VVCL4aGP>ܲ4M p%Ļ5=4͆LiuYmˍ t 1t\^ H W4\ #BC*؋ػkC?2b3TR#޶yS15 s-ZD:BqX%?+yR* Ox/VP{^Wvdp]Bٟp'r]pmYt5p'$r,G'Ì;ӣ._3Wn\22~+O f7EqGMtLIqClu"#H92mBJJ w3}61Ũ o ǭ旬ʆL|nKTn2='ޒbGpѹ4alEz]+ y.!*Gay`gvhR Go:xۿ瘽'GlGP((lGp,P6hhX]nW0o7 Ꮀl&EQz c}Z&oy˩Ijrf<_mc;Õ'%HM!!"xߵ\ɳb$  Yئ  P,^{m6y[ekYJE{|t݌>}q] #:ܥd8XXQޖ6ﳣS㖊Isf듽||ӵy}A`{m*?-.cսiژݮoT8u2e g)»fbw*k& IDAT)3B%ߢg kYwoM8-'[MqD Q4MPn]075lf c6 `QC}7 )gL?Y^w6Hngg- rsf!~Ǖ'uvC7v}7˟_{3Kއ?c&.cO *ccp)v6E ѹσ#ɣgӺـo}x/̚q'4>S|)Qq_[L;~σo[sui_;caee]p}t8dyo]0 ? wܩ<[zFvuaMkw7_㤟nK{KN%?1|{|ed )hVG9NFB+Ꚃ\NG[ޠ)ЭnHVe8Ksi.\` 4]NyTt9d<,/+Ooh1sLb>MDnai&D7,tphԥ)G)lll8o]W^41+G#FGuQ~{-++'}"B!P6=;[8,Y޽^uSqwQ[ŮumJ+ 4m׆v-AC!;dLeL=,T:L2-۴V9m=5y8+qh):HO; F*\a.ppM B7tA4>(q 60mxȮbʹ?.FwǹSÏYYYB!BCDbGB3,4#nhB@s42¡.8masjs)=yxE꫇B!B!~# E T^iP:PǶc<BϱLay5!#lB!Bq4 Q$,,O<8PE!B!wEfB!B!7L6GmeoNll,TB!B! = ,^A)R TnJ4q7#A6!B!B ~h9mQV^F\\5T}~m555B!B!8:"MY6)ljS-gMPmA9!B!Ba&uAP!b`[QTUVrm(bccQ \؄$P-2u1B!8IM4K)4 ]e($F4L5;!jv4MIp@bĈ(q B!QAlERl$1)P$/?M)tM#66 aI(B) U+4J|L? / = ԫ=Mt ۇ 9LT~c9+Byv.9 D-uAwb*>t.BwdL6"R%=;cz{c.6)6.)D c/cs*7nK-2sBPiYZۂmHz^<&߸g];kn@eKxpAoJ)b]ΝSj~i|rXgU\Ԭ[X#wڏJ%|T`6qq$ h_qiQPTLn^9yys6ϦC&(XR~:s_CaC`guhi@KyH?~)a-iDƀEYTRN5g-E07m`|U=!^؞>;1r !IRNmI^b}u`D"Us^Orϗw,(:P bo)N A|y w^Peh`*˼-[-.o~K75NFxxQ$x5UT|=KaUKn6)]IeaEX?YѤ:?ʩ^#/$빁? IR37noiVlk?]΅C1p->V'pf\fnۅte[aH:{ _ş`ӎS>#!ƞI331`HO'NDl)IKiExmޝX-z?'~*~S?&fx:ρJd6!UsGZ;¡|kO_؝h؞}B%Ͻ*}OHC3=Ho3~\O-KI8lc' d?k.|cg^ dj)o;I>3uw) S@(GEƉ olV`me٬vM ěS8W̺;g&ZW|ӏ6(U.]3 PI.'Nz|)A;ȯϜK/e8F+چfo6üs7 ⫹ 9>aϧ7ſL/?C 3$Y!Z,b89ewxGsoSA;==,%Z5sH?.{Ӈ@$Dā`fI!s'+C_ ?_d`$>_8_Cz'8g-sI M4BŋN &ās.B/]WR5ᔇzurJH;Ĥ,8׮e`J]"5Ŧږ `a!'ny}b0޿2=q-`S-=͓?6'Ờm}?3Og9QjRT;v$%5ZBBV'о}{ڢ{1&[7m#僩,//I*6qlkR%򛆳tjwח?L_֗xP>:6)xh?x(_!;`R[*D/3گnz&su=J4I?̄fѷ_N8eI\pg;/v.͈ť\owE)1@y?8aǂ8;x_ -\C o_fNDلy&E1$nGKn2R/_>Obz= y?c/5|rtq1ы^13Ow0eiž[%DSt7jx#)MCyPg,buیtrvV[ĂcS>Q.kY›O[tn;i3Оm; /WpG9Y(l"c磍rܬ3eu,瑔y9Sn:-~u }ᦷֳK*ߠK;lG 9єSNFK#̥҉71t CW(g/یS,^h/,;GC;ǝIۏ!WJB=16FakX"󙜞5[Y3;NK#L28_o,k fPkxk( U4:4Tʝ@1u~Ji=\w@u~)~ڞΩ%99u`oE/Mр3hSUC7B#i\r˨B4*+ni-a$aIKJ$c_.SQ SC;~L`}qK[-ۖ3y ib?QaDEAuUQ֢X Q1$v8Kn=ÌGjxϩ7.3Ls}3iB.Φ`Ï/K[@m}!~ܹmGxlXhHB p%Ļ5_'dI 9o>_,ΐN>:ǝNԼ?{[%ݻA۴R+eYUUտd6bˆMZ@:1J>;>=SS#i3?ÜWoXgvڐ%r{@ͬLn0/ l<ie(~5v6t܆E5{?<;.k ֥{;'yLnĈkF2KlϦdE>ƞ::xO%wSu;;NH#C?0ns N4(8@tnw7(p䅽dУ7^4p9̸|} >=n"D‶s}Y~:ȄG QF>}4 ˲ΡB)+/gM撝ͦM),,}Af,_ɔqUQn%>-0 u|Kl-oH30uz0ݣJG׃s8QrԄ+[Kߒrs_楥+s%1mycuT|՗t E}Xo!t*; ! }8Fähۼ:j0Zd̰yߑSkcd3c95I*s!h׽lº+Xb+ϥ?emqYlBgӼ,.a⮾/C9|z xFt:)Kɮq*6-m"冈 I("M3"2/].>ԥ[1jf<ɿ'7 l3D(IJMn{=X3mLL>`B9|xx2SOӓ4(F1[(tOߴc7+ƶmlۤd~}{'6B=-89쵩Xlcz>YGeR %dW SW.l\P}"h&v~2!T+o-_q&MuFrj2aR1vmehT^B{5fn,߯ _?si(]ͩ\[ϗ2v\%*sTS4Vʕ+ Y!cEpyG3ܘbky%9ydSTT/1bУm`$ G[܈w 1~S&:p(hA9,YX:33[4OS4o?1gdckz+|7K݄4=no mk$?(.D(P0o9:ZE1,`p1gyutRh-P nz'RPx㵷_:2"8`2'onxa7 -n<$ZG뾡sHqutC!mp3_ίC},L |Q1uw5 ]ױ*hRѮ}{HLLs%~aI+B!BHM8dffҦM\NǷ!'HJL ?xqɅ8z꫇B!B!vClER|ɻQQ$%%I^+B!⠒ #0HJJ~aj4mX]vDFF !B!Bd{rѣGhRvB!B!8ZA!L9~+DZߴET(!?n ~#R!B#EMRm,8u]D(ԎOPjm(_eVRtB!B!- =s6(lR: ^"""@IMJIZ@eeeDGGb!BqD hRujtMC q1(=k@׍㠴]FmB#F"PFFơ.B!G# ȶӋBDb[ؔFD²-,^(t]z%7OcА<*B1t1/ <gk3#'䒈EVV֡.B4HҍOb&C4B!'GBtÁRΝ;ch:>KM4EdM7ڐjiW&1 IDAT޻3wB%w9o[9$;vqnM8'7rk!0ex F'|ܒm7;@;l+~ɣY!/.O[Ef]6Ƨ!'ldv5;ax{FGFw"_͂_6pU:2ԧ=&.\dܵO%ƭ6))ٛOK=Qn<-`lbLB#EFtnC87aMvTɅoh̽CSk@m drǂ*J@wsCit#gRFN%0_.k'hpƝցQD*bmܵ3R&x78?Wlﶰj~EsdX4;'w~b-セ0 Qt rı*)lq\.7m8h- Ք2-\0xj(f[QC*M醵 yB4CŌ]ӡtR!)ӑs**qx(XUkmܕ{B+yLڒa%#q2|?jwǰ|-6)?+7c2<УG{=&.mӑN /smaݸl 6YX(9_גw⪳;sY~]Dnۆ-?~Pn5~VNIo̽w䞪*Fsޏ k׭mnMo2uqoDmir5^Hot޲ELXkb;P9X]:qmle k2kAcMu?U^0[l}j: #dQI|T1 r5Tp젹z2PMǵМ6<b؎d-)Erh)bc@@u7iT59JŮi;T6F8ؔGGNܥ0aHFt;TY<_ha7n=9qm6R85хUw>ܤ27,4!,&J$>j+LX$@}U&tKr| L-*Ӧ.v1hۻ=$-@jY$;/#s"}*wLX vf%rW!/!xgf9\5 Ij72Gk M$/ RXCtwNc-!GfhI .aJN?pu!H =Nب8G <uU6S{>Q$mJX|M?Vˏ)ӁLJFU}#!h90YU%\: db8Z* S"C h=h߹5=)XoyyS+&Cں6A>[hiQ7b-׊KXֆRjj/gfUYU3qke6oLomDPCuKu%[ͿsLfI4UZx #:d-bD"vOl²m* B躎k v- 7Z-iaErg7oNYu2;#yi_ָ8{1LC{6 õ#HO0PcY= 2Yk.=0zI exjY.< wՑռ^UWhW.㪙Ք^nٓ{YY]7}оOf [QӪ^ԅ^ʕ k9!,&/HŽhPIE\+`䗕l!a,gJYq]7c[uY\R=DίdmYI Яk1ڴab zbدl.zHk.oS3y6ݏI60׶y@A{c+&fpg'7n]Q۾J{s4t}uto41.]]Keb_D.L J^/jƐSUMŪzHҍ61:DQSI=HBlZ SU _>њ\li=5GeH/ZF)(nOOtL,qDEGEbR" ZiJEVqy]oy|<;dYrnm,\rCT>_VFab~;lazCr_gW&`Af,fAV#ǪEՔ9geZsʮׄ{nȃ8E<8@1t(VtD`XAPZ\#DT!vCK6FZ퇚+LCb7̋cqfu.7np,kΥk:Scqob9l^wq%'0o≼xf mRXPR9(ѭk 99_-Wsgd&qǠ(gŀ!p/&g᝻1~ %Bۉwk MǪ2`G QN܆c[a!h!oB2[2 OThtK X@/8XN,X?;,uw9yW. 9[ۖ˙Zl!=KfY +qgd:s3CѵF?z?/%',iR8eN㧞nL)9Gơ6k=ϮR)"9#䪏KȔBU%<_7? Kl:^݅s1_: !DYe/,b+^O_,e**<4$~ɜ_JII.aDOl@W% ؝qx6|/SA7飍bs +-][sA۷fD+( P h.8& %&? ʨr̯Hh-c&愎L>%B3P(RTˎْ?(ۿ aK.[Wq1\3jc< ;QϨ;܆Fp+@ H^(nځު/ͺIvjl\W2'ENWtʸvRFv}L^ӭ׬Vod[}FKPVWYy̯cb(5YD`xc.s1TW(QRƟсhZD wXUqTL6Ѽ,͛7ӹKWl|Q(fq@5|>@0@ȴc&BZ`%ў[Ǵ~9<ق{dƷ8Ldߢ5;DmM:mSa3UNo9Q~ٖI{0ݱ(dϙഌD6grE}ӻI nu&Ib/f5Rmܘ8TX_aϰ XC>M(ڸ?sL4WѿGN)ȟ65P[xbI4]ޛd_Urw['Niݰ\eܽnVNe詝'@â8W꿻:zqax؁ZVYshİ o\A^ =)i6O^ԝݫwupwƌeQ_se3WfPb)ҏ;D4kq5R I\700Xl7rٶ vlUq G'8;יfmkMㅿn|1̝ | 4+Ll {Ȕ]v'gIM$ mxp| J-aٚ\iI=YB7k+k<8[~=/i()͵4Ku  ꆊTa\42;`hpM^DhhGEn-NWNk OtYTe5]x uާ$f!Bnp 8eee pp\ C!򈍍%<<%9oKҍOb&N΢[+1b^򙑓닣WVV'N$::oqB!iy-q,^B^ͮ:iU4e%XA{]ؕVHUhۮ 3Z0Cv zXȩt,meZ~iZ[rz:kpWL{QcndQJeCׇi6!4ʴ ,Z%&!O>lB,ϕ\􂒬[!B!; hq((( !!syve45 VHźͅ|J5_RW_}PA!B!nHMRnݺ0hcfubJj+h*NZ{K!VgB!Bq #i(sVP ?mS1;Hw`B!B!ad܍CKi:8i:B!B!8A6q96VcuSB!B!/d{d61S7&RP icM٦|YIo !B!B$&q&22aVQ?Î[Ka,B!B!#R)U7`[444 U4 7!B!BdєiS^QrnVQKߏn86{&6!~+%jq}!B!MlYJe""5 ]W$Š5'*]7:vMFq BB!Bs , Q@A~>1XE-u6el 4Aٻ(3۲I! Ҥ DAQADQDAް^ Q@RBo!ۦ$H@jzdVQ98AaK f&ۨɟ58pz/pT#wI$zI\SwȎ#NNl>ACf|WSHjôyt!멒tpZUl[ wns9,kejP9 'F\A #Ҹ0D|J~h(`N6c`Zku0(ÏK'Ts T)fEpQ3ʹՇ/Be2j Z ĝ'eR))Whn$t㡡1 5n剟Y?MN\Ƌצй`+?+Wumc+&sy@BU%UdC$I6قjFϞfN 72`luy6_PKG@?<L,&i죏$ 6|fp+6jpIa&!| (,盢eßzJKZK{wR N6&FEmӗ\йK"ϟLo2jT6e}yDp ltp 6m.b)'LԴZtL;9!-o)}۳ք0vsSnAaAہI}b(55l1.THa+ hpnHw~2)'y1׶K[˴ݘ͠psqPiJ46Fȭ‡{~ T7Իu06{ Aonxp0LJ7qо@I/.9iJ4dDƀ.305"s{qa&.ki^+4RK1a=ؒޠ Rk #md'Z)LPYNa|YYmܰZ! 3y\/W~SNk-IE]yoŊr;3@a\8PwJFg5|>i`_,p)pQͲv w04 MPU6bM[K!)n7x^]`kZ=NfR:G.݅k>}!g#r]yY]oĔpyXVc-odt \UJwNžƞ}fl;^ ;fרXSذz=TiXRmOY\eͶ#BYf j>ʽ&"M;#vQeMШ0pEVL^ԗgT/tBc q;# xjTY^MG@9D_:DL~ hrsKU<".7ٟ uQU̻n*t*>X&}];.kl27Iӓ$ s)m. 4NHUײL𬳽Ѕ5=4eOS:vA6۰OBЩS'NyyUN'UN'j))-rJKp:x<<^/F[:^:ҩ t(-VNޑ vvfyX_SIy}m60qϾJ zr0b􀧶,'wbAL9vkTxvS,*ЈG'o5˛KהUe`L' k=Ukq\#YJȰEr} ڛ1AuF)˼ai1T %0<\ztੁA [7|$ hp;0Z˼m- $I:No¥3VqٻLx7I)6T[ˍcxjX *!6[:09_GXjvglf_sWZ[iv=AG["*ь 7aьn.tcGqy ! eB7;ZU-*Aw \d-摯 XviyG{?3øX*T{/أjL. 6ϛ$I&gGlmfNɅ~$$q˙f ƮkŬ\= &A8&w0XI^SljLB؛>iY˓<: @`2+yn^U2w , ㆓4䔑BzyiLk&r{|ه$M&JkKJTtA0@1)8 SBSU. }d;}6 s6&{cc`னaٟxfEmS+_MZjUߐ)~k\@wU;OUx{.X8[ ?i'C?5Vlo@#Y1|xW~]+ XiV/5oQwx3}]ndZX'n7|XSrZg)w}kSzz؜_jjJcKV 5'ER|Ժ m5Ya&ÿj(4g$qL14T9jN&6$IqDW}lew+** u54 k(b D֋E }+&1^fl3 ".,;.٢+?O ej?̀#?fSZJs.ʛ{"\)i̿m^EutI'_Fg 4*$nFEq%}\70pZHr3yBColaGOuS/ַ]ݣ<W$O7`\AEw9y,=+Z0>3U{BZ-Z9/l MPE/4cJ.+"5P\Aa5^"Lf5E05l,Eb1+~⧢M#@A TDɪf.*-)B=LiA2]p!a8Nf ``X4U(*,$44rkwi9ogPtJXkBFgd}A+++)SZg1$I$It9u't?6iafz&vQܶrWF^Dՠn5 ݧt*4jZC3Y5TeUu5>_#r#vq,G=eO6Ml6t4lv(PUhd6I:^Q> YlF$I$I$I &aP\\LDD&*z| 2rKrs-$I{xt$I$I$I}A6M {sGWҭHBΎkL$I$I$I::A6Y< msѼ+n:u>%y^|GYM$I$I$I$p:lґ$0f4ma\I$I$I$I$] ѰDu*++x<+J$IG?y/$I$Iw٤CzjbbbcbB4.mM^jK$I$I$I$I:^ _8ZXXj'aaa(lM6v54m$I$I$I$IұH9 Bdm"WP=ۚ~W#('I$I$I$It0e1eO6 f!! >2akAbXu BCC,&`Kt|!I$I$I4dZ%(BHHf Y(zaX̖t@Q H!1z#8ԣG#I$I$I:. &BgfϧRXT"&E!44lVltG%e|??_L\[B%}>?gza_έc_piaw- p?xu I̽AN%zs#I$I6Ela9#)INHDx&}SHDLT$fǦS79"_ĝ|Ϧj:7SoDoW Y}qAȠx\;׫I~ո]LV*F<}xó[<{~ʰ=^~^Gw.(뛳Ҕ~-\ 0ťe_PH~Alʦ<>0d.)51ͬJwV#_7뎉U,'da:qn~$Yv4l0IY K8oG8'MH\T|q%GpׂRXI:Nq:Wl68}ܮڕ} ^_:Lx?}2mVX9ܛynW\a{jLkyidOm=Ӕ -"IIL VHbb!66ۓؑ'$`1M/Yw݌/yn)t f#(+O~f2\bwQ" X|M zr޾"%9Aٺu}|#\;a,# ԃ@-q)7.M4 o#䫀Z̗%p錙.b8z}#?_)Kg^&>܌6Gي\_"@tQZ~տą aȩOpѤQ|߼y|}(nYOep{yMO/rtv/UK$b&4%pFEv+ϖ2I cum\Y"ﮮ(ݺclO*4IwwTlH8NK <.:}+k \'?<}%''Btt`=ɗ Wr !ğt1Ngm4TKAs$PRÙ6W 5 K|]93$,abc^„bcʠ:}gJBhZhu:tB|_2G 3=)@[+zֆ}{sK~TưG폾'Ә=n~([/sV1niĶP7NY ]se4W6s`6F~B_h[s9z.bopc|[>׹fkP%ƍ_ʀսz7]r kkPQ$fP!t$ .|D[|f70tP[LP5ew#}en-H:1=+7%'#laa%atY<_t%+嫊q@lBB1$V r ?0Ý^ fӧ,|wƠQ^?[DP 7Nƀ_e~~ Q6GYL;-#y2dL\?&@ ŏç[{o>%y<܃yºW:D 7\yߟE hʍ7Qv<kP0znUDŽWu<ߧ_µ['3ՋIGKt!?-ӈhs 7,['20r.|Xyo_µŷ0Xח$0Gap"I˅5ٖ!P_ڼ[[!Kʰ=Lkxpd>/J;dl͚5(Î @4TUzm #1_d~n\W<]-\¦ĚGkܑ5.cuJ / la>(&+V|ǎxj}W'Du%:65g3a` }B!YetVdjDE"mX&+o n;wb~qU>*-)It43PZƠs/3oS9xNdoLQ{0~<03 d kkTO׳)re_/mGBl IDATf\>1/f""ѮgCss5|5ޓ3yz$KL3y9+cgl超v'¾vEUkэ9vm+t eZ| ?ccgݓN-r*_dVj(EQ4|KJ(.) gu599GNN.%%444v۶K/&MMF~y!^ZG0N 7ü ݃3o+T㮪&}"|.wԷN4W?  7?]~1Y,ϩc׸m84>z}Vy1Z~Ӌ&2wp+ikN7@T9:LфfPރ+o {S?]]NTCjͧ<ǥ$I?ėOɖ 8K9=Ҵˏ͹9Ժ\T3z#L/o>\FgDlZ lnO|t1'/feMP~a`vXwYz|<1]/;+ |ypF5wUQ)>=_YIƆ lذ ˾yn̸~zy(vAQ;7gt]uM<ۍRq zi誎`s1ʩipS_$Ʀ6_k"^9j*8n;η{y|y5k [-Z9/j > rXI*+Trboy׭)dMj]SSƍi>C#p GpH8ي k/,&2O{k焍0G~V;/xS-`V =?|0kEIDd=FN^u0 )% mM1|\'NLIZ~OpOsVdc>cj<>:qux~y0#OĆQx` Ŝ_1%9ػ\^HΤ`J=c%<M!$}s Af njg~7uju_p$1~V}H,OԒ9\fb ;׫Wsw@V+whhVʰ=^v^_o[lnqBE-MvpOn.F)HE3WEXM~&׬٤yMf(Lfc1&bQ,X@z̊vPP?l*a&a&%ⅴJKѵևK^˯8CZr?4h۶m#550().f6 Ovٖ('66Zء奃Xxj^1٥$BFgd}A8G"++)S|"I$I$f Okiх8S&BVwEd2(Cǎy$x|lʳٌH$I$I$IA6M 33x,f~?YM\.|'22\ޑ΂$I$I$IG}MwtB0hР}.`AADEE;zv|Hǽ+I$I$It:DG}M:f3QQQ r5oы @u4MbСC`qI$I$I$Ic IeX֭[{!M$I$I$I$xuz=HgbhdL~vz2%IG;,H!#勒$I$IY9zwA6uo9gJh"*4@!JC)$I$I$I$I:j Y!-!zW{;[7%ud%I$I$I$I:~+ɳb!hl%&i^6(J=$I$I$I$I'&8@Uukj躎nra20t̊ I%dZ:N'G:$I$ItLA6UB4Ps`RL&ADXBf```2PM4z#8ԣG#I$I$I:. &(.*"8$Mըl  .MTa2Qmʜ:<΍t4z__8Ήt:Y$Ij99gxLtn$I$ &BRRR0+ f訦^j(qk`)$sZ~m=^ 1V3n.G8] o\S%˩$I+afܚ@@x&K!f?& MfBZf\,_GX$O@ RƉ|:03Yi)qIZn$Q*dGd5mpىM)'UmVxN`-gBn5-H+KA=CH bk֍y>Jia4bvf}Bn`LX^G\24KH4#*aS cHdVY* ՟ɧ%rq YP6qwv D` ޳:pf6C8}>ʯُˇvʮt* yk^.UKA6m`[f&iiiAm]-XEka`XuаP&3J[m L|fF]ԛI ;E!R j@Ϸ~b;zWs/HI!p^HfT$Iڍg׻ɪSqr*׏Ld^0A~Ee+xР[L? ssړ}#8ܻE0eM:Zn|2sA9 wMur}?G&in.ZXK՞חaٙÑe̫<ʤACf|WSHjôytqJґu5ת*fb{p7aYs/S}\p՞v7s5:49ӹqn@mU5:w^frύ{^pWyLVꄇ;[Nfhǥ0.ܖOQWLcB6dMjEbQEEAeeQ_1Wwzcݠ^թ1s]HNL29ӏ%2:AɠO~ 0y_?;!S"-hU|vGA$ J3son1+TD aw~ /7 ?eBZ݂GgRJNo*M~\3԰pCt483Op^ |CAI|sħ jafH7˷V%I$ilMfQ3B| ,>\%AR sB| Rchl*e'+?y1I:Znfky%9k;p.k8#8'OS <4OpZ6pFsKatťoScsD?3_7; fAeSV1ߗqM 2&I`"6"~NM AǔhS8٦yӎCH('G݊B@ah{TC˘^=4!Kc|/S̪b_ {HBTPP˛1F?ןcsخ~̻*x"F\ɘBV'c,Kj3 4]YUEYI)eTTTPS]Merjj)++0P,~ Ihzc%6ftW.rT䌥ya3邎euPHDk8UX qOL OXgQ߁;Y1 2yq%l21d<:_0]ks L;3(|Wfa` vr?nc(-̠P&ڛu Ajb0g%+v{$tN!l)S[yHWe I ii~VNnޞO-zh[+&tE>T Dooȍ9>)kxyQlX8=%PIQDQ@"JPXE^;ĂJ*`A % !Crʞ)HH(Nmڔzvd0pkڗ4Ūu{)6vk`MND'>@iIWa:Y=x]BN}tw!_j) 0f@s "c0|XQ͜$]ZlcLft.fbbDtnh&X!i@xO|оJ$Jy256?K>bb؝6'y1逛M?e[@C>ٜ>ũ7p4ƲxT[֍lMxTw I 7ˆ>ߧqvCAq)hrq`ldP;J}z]+m,X|gJx5gC}J6qv29}[I.L>Xw,˃٩86婀K*)k`4u1՜b@s= JϏـ7u,=y63ݯ ۇ1׆CS 8HOɈŮ*uQSC C4oAH AhZ PPl<-^(^ ڞ[l&QcT9ۭ.r:TXg; _h(xaT9,u0Z 6 p$ f lC> Ujz n$f my|wTp} :twa0/AQ?F J}3 eIi I{/gTH^Whf}9 cx_Kra^'|]_ {\ED-l]X00$Em}7_Kc ?a8vd6`FVK7">N~\g+of4[da {&l*&~V؈Wou2\v$]Ey|[]);r5mB# Θ@ԮŀEPާX<PUJ/I_/;^Ȣ'rxg{$tZShϠڊj{oTAk"F,`IyZ e $ĊsO:4aEQ$7SoKfkxpgI(β6 ঞat娜M]mΑR43gs`i.I$IXz)VkZNݹ7aybd_*|jI1GK43cNVbLN䜬W9\T!7Fiq2?PT\LVv6yy撝C~~>Ӊ~SssXޑ⧠ o@:k~,C%: W_gW{ -` ࡮~3V9~Ac,JL1Xk(v~NS>sNN0zXF ͖=h bx8Ό4kͨ:w}!I+.! <;.k Gr:'tB3 ȀQ5g`dW"0Zxw~LR(-*Cs/B= %IZ wq' 4[yIL"/trXew{ |x g@ЮM /w%J ޯΉ$ƮīKKt!&lxJɨvDID| cهlT5 Fz HObD`6MQ;ϡsQ$ Fneص41 |BIR5a=z 4ѾQmo+*U5z1gCwj~sU̲v";`ތAlVdە@fI+RKNN&IS4,>6A1(X, QTR[U*%|(ݪ{+@<:>3M:f:l?o*L~Xml)8j2#6rt0xp}PIGyҷ!Sz_͖wi1m9ȳdz$IYQ<?#HM/S|؉OP7=?gbCԀc N;UW>Tҥ]s3XYq2Y{v G#?YQ$ؤDYjsTyf ֥UR dv>X}ڄ̚cď 8)kMN>t7YHObB,ʸoт͇S"\qYp^nr3r*!#IH*:0%|~By{,Ae2O0oq>)O3=ϡ1+^ݔU~ O'ZFޞ1>ř.u_.-YD֭뼿FuCmj`0ƔC>K[u۩zfsDDf(4\pTKn٭n]jV5*t=З~YeԮSfIu"M^ EQp &$4cYN`ʜoMk "I$I$I$F٤:uL1(Rl6Nm$I$I$I$I?r 3Ex6((m_+(U$I$I$I$IT2M?K#'7hn7V_+E6& M% !d6I_@t)w!I$I$Ih2&JP&^D8`(Tт1MibM6$I$ItEA6N;zа\. !0(  0{U\NB!!(<*Ya݈,z\cg }7v.׾vx%%JߘP7XK"])/w$I*>E)Q|n<]I$I:?Wz|BH!ر#&MbרbOØhEӰ~4MbkKDX(FyǦ6QBd[|{w~J 27qeZӏskisFoʣ% =?$I_Cq!"c^fA5JJrg6lzv5gfͷeH(+N# FcK҅*aF&o)@|{7(w3JQ/!qӻL9lVT\^f0G]jڊe+xHITr~#n.G=®v6u|OG,Bؘby;l{]h50z hgՑ3UYzOd~B :}r7 \wtd 8\|<7 hʀ'p? Iu#;wBu\3IMK'5-T%'-=.@w. :v+_Έ<Ԭ73(OsGA6s)t:q:8Z?g"❯DLfԊ9HZ;ۺbC$I #F1sV~sm7s94#.X@)?oesf8|j( =T կVyO:m-ϝq7.!mUGݙ2=S1='lZҩP"o8VtJ[> ̾Np{b$e Zu%sd LL&LFňXW&7ȻKf36KM 9AenA-LsO8_},l6Z=O>4dVNh 0n-Yfv~I$:6v{<ƂfjxlU;WhwlZ }]srk(FУ39l"_?3JX_<:b`5&I)fU-@%ZQx XbJ3I,X 5ch\/U7ucLxlس |ӫ_cpJvg;J8`>0GH%t{ۙ4y`T/qInnnJs)X;5XuM鎗hw ^3׷񏤔hh%I|,%R, yO%3o5"X~~nBG}R(Bиqc4O2& ᓠgM(^7<"Nq9fVEOswuڹWe Qǫ9/nrvwQ*i^D[O531DH+r&̐XИؐ˾Q 8+y`_eagAXs{/I _ s i6cL5lt -&,;3cтbmg?a(.RN.3 $cog\g_Řrh-SۤK/ef̞Wul^Q <'UWawpa _MlO8WsϤ[ig>z*^϶{h}z;]r=4)6p/%X_XIqxn'd #/XxG|eM.mߩAZ\6qڊK9U0ATن N l,ӧn$4ilML ~7LCȍfL+/hj*5栠$Tg{?mE _뺎i iߴ:坳Z%8 k4cFtv{;zTş&2-`GTi<67m]ja2i(:0INEZ84hӂ >\v~I$ntꚨ-f!Wj_ىs`Jn0br i-kŤc9aA*_NҾ_ʾork`<چ#ث߂t ZvFXGz>a |p;3΃Oj7pLlC<=o|/ݻ%D( ۷GQnT2";''%FJJ IIdeeSRRn?tnW iᓩ ӯKϋmưyߙ7w*&ag<XMe,Ǚ5wgM?jJRrH 3b =]uʖvh`nWt~wvr_6nU .ּ6ӹ7Pz0m*v {tqvGNo)]?/rTC̊Gt+?(~t~bFdxW;>F3&+_]P+gw xԟGVtO ?JJ)Af3H,:1G!O.6KFʶen k{Y_ _f&xdgM0-4y >Gm₳1f́~nʊl%enθ/sͯ¤`n{z WQ A˗vV>Ve"5W):DA4N`kT/]XM+oPd{RkfiThp; Faa2bRL@5;xh^XOg0+%fECrZ{.I^ii)?3^{-GiӦhNVf.ns$aQ\\Ldd$AA^$IgB0p@޿1%L2??]I$I$jْEjݺnt]g=kۦ A!MywP4`wi ttkfd2i:  2&I+.|.w1$I$I$od.?!@Q1 z(>>dIX޿1ᬟm>vJ"])/w$I*>E)Q|n<]I$I:?2!Չ";vd4`Il5QliMp֏I\,qc h%oI.Ӝ~ALQe'B8'_XOW:r$I%'w[I.*ƖϵzնLxc9Q\WYJ94~7_/cl6 qeoSCi!Z.6o~ՉYrphx?w"ŻL}5 ).qڝ7%EeG8Qx}!LYZ)Ed:3o:Yȉm/6/qsv|}y|C6*IJ`6Ʊ/۩UWMs9R\k +ݶ7Iw:IӝG }}4'+uVɼl%zWO¨mMU.l3XKtVM120Y=5a]ԕunRx=ߢudV[J42&H8 IDATՉ"bc1&aDDAddקaDDDP?:ш(_eOV6ϛ3f}G0$f&kX"^>ʼy:'GIɋX0sؗ.`ٽw橯( w\C,m+Lާh}&?{k2s=)\I,%`mӽ{o_ʯÏ3/tP,kG{yy >ǒO2zH[L9wML@X0dȦ$Ig$ 9AZ #*2m <Ú4&o £" 'SVB1h,^dy7/ =bh2&] hd*ٳ3<~e5Rfqф[IDh |Mٛw]0F{t՝У!IV Р+NUgn?w0Svb$i/{slt MGM{ é:ddnS? ĠLʴ6|"P4ٗQ/NXúpK. uvEL32AX} oԚXKyYECFk,D%fOXw^׫)}#f{Fhn0acŮ2&Չb@dfftoI4oM$u0ZJ^;3SFؤ̏efxW}ϹRX< $>gTil5i4cvߥ es ~`/ƃW q1ne$邝\2úe~a䐋?)m۞Ȋ$C;NG%鳨6Ț?#"'Hۣ҅((ݗl򀘚'&G g$cckejoJF;ؑfL#I٤b&"mԈȨ("## '2*iР1cN6HW L?cGb{[AX,ܒUd3td4I~w ^zލ|1 ɷa &cӌxD\G۱f ʣlm0GG=K<)ZG`WG/3 ih kF&ZCwݎ051vԬ<5' w 7>8_},e$Imgx15f^oП/܀qdљ6/ßn%~~ ]f /c1cfB9]tHY7z=m1g䬘Ώڝ H~ޏfB5_ϫbڳPt߾}{bf'0 O~q*ٝڊq |0`C#Hvl$2EŪY;6-|9t5vVwpSW`Z %)ɦ`O`q7;^>^/ zejπ^?R$GT KղUTҼd!ڜFZ$Iт_N94y1t6Ō׌ןɥh-CHY:xGeq}cFK5Lm..O}3{~VA'~I5o/]{j%W6?~7[[n'囧g~Nc)6p/嬔SmEݍ䟬awkI%a mOoB?0ci?~-gAZCF$SMem2 2}FRlMӚo<ܨ=aDBvP>XQitWlϞ=\(Sk]4UA?Hۊs4hӂ >T>U7}i¡R3QjA)CMw5h&fꇟ_D1ߴ^'{ހq5of/Q(Zͱc#4T^e604g}jS$Itw&])y~e'fm){"Yk5^+8轢lIm|?Uͮ;R`(wӸ ^B—2hVz>Q9yc|5g-#1WmE?>#-Ci[6%p:T-͆Og[:%蚃8\P9d%ԚLBsTU;'5G"/E]R@ip Qq$obg|N-+rO>` Έ~"ծ{/֑\&;b$I+mpZESYt_w7DwHwz17}ˎ#,Sr2_x;;b8_\NwK`%2RJt܅_PzVDȴ\~SMӖtsr~ؓHv~ ~_Q=zQV3\Zl9-3%KZ|UǕEo,}!&v2hr,kyen2Aِtj>sM{O5ˁfOg/exzG6YOI_r4 bb? U,IJZ9xyMD  kIXăFns☈>ԙfb4^M/`Jh[g{ Pj>  &/oya߰fxq鼖{ ޱtrU5&s磑g+[m2n2`m ޼ٸ$Itl?`RX,t{okpA22rgx}TW}yg[;m\5/tiL u;F|Fj|-]\jwф[g\I~_ Ӏo%k7Z#q!=\Njn/)A/c m94VRgw xԟGVth  ?JJ)Af3H,:1G!O4-eY qt+`Q/=ys^,r(DbJ45%1[>hb<1gDQA!APXYzz]ƙyꪇ.<}mMR;.|.x''xқ8{Lhi>aG$̿cc``i=);@z8>DwqߦOp٘J$I\QKg;ǧa脅K031oVT[۷eUw(5<8uIQz-qYxaid >n0y9ߣ}qH9o9Nwf4ȨF%m ֪IJceqLG,N*I,iOĝXJXc%t=n[VivY,`UZ:ƈ׉Yt5k`a|2Ndڊw}&L… 1j(؎իVRit:ֆ bTWW+O1z4L8}oA^kF¢E0uTTWW*`0 3O?1*-d8~2v+b_ W {]!2dnʤȖ8n+Im@#N씝SiIc%)ĒIgZi#Ӗ)ۜr+i_~]Q>Zi|)!@_- X qX i0t0\f0huG[}E `0 qp_|D<ҊRZ[[jPVD]]9 YyBW`0 `0 !&L`^`= fz `0 =fЀ͛7֭o%mF&A"СCQYYY `0 `0d3pI$e]wB `0 `0TYlji9d3pm6l@{{{|jkkQ^^V`0 `0>_WUbl.O0p`#ge (; fl`0 `0TĈw&|qض}b㦍۷/,v.g<\G[KKK7 `0 hiނbf^eX`ٺXζϖeter`0 `0 |῰jժBWCfiV]S m)k׭qq`g2Ė&$ ض*ւ 36!(Qm70 `0㢆^!eYA<C"N0xXXN5~}'f;,2A 'N,t c `0 r\8 RB_a R4V\ , ܴ%3i:R ӧx*^g|5睻Iay݌ C|t7`Ǒ#0rPx\}l6x\6 {|[=wnʄ&?xΩ8r| '\e3l}/{?37~'߇ U#ɝ&:\h/CCqڰKq;2| ocnDz7/~BFs›KڐNŝ'=G,h8h_8Nl7A7-xj羳 4/x XLh3R?66Wot-r !xl8T:UkbUX|-_%KE_aXd):Ri8ʻl4ͽGp.f< mpHxa%Gf?qA+cK[;8.NWPӶ_v@÷wPu֯%Au;={?O-6V C'%[ѴM\[Oisv'M{Mؼ/48.|h^|\U}/j+%C c94o݅/lv…&̻soTO #}**&rd3HaG@,f!HƁhlÇݐ!H ]JZ闞{;N.vd)GcFG~fQz5qhLQB*0+w}z5s}:>(8WkAz8v9'/ÞIJ4*!8'qɇ/£s6vN{|\;OxƟ`u(Iv|6n:g4J ?t!E@H&L3d@30sceG?~3<)uȾg}>{b!͟>KR1[|,8x}h]؋a衯%h$F2 \>X_Zkg;\?qLS.k͘/ `ԡ㑏փo5Ny'N!vY3 !ڑ;c:TUOm56`hcL:'vPoG|s n/]vCcna_#v| xm߫q̈`'HtŚ1GQzOj @ u{MǨujCę{wvܴ*1j;apmu%qib1P_SaO /s~$|yC|Ŋ0O{7lF KĶ!q9؅QHv1&Łx ް~0fD=*ۿx W>gΈ:Tw.IqDme R9fk#^ҫ֣_uX0|0_5*+P 5 v}~#A5;/ʼn~t_al)! `ժUXb,] +ڵkr*,]6l%KtRضӽVDzͿIrx~<)G?eկ^~Zv9͚f5= ^y)xYu  z|-~;ɗk2@r8v2w_W;M:`f9VL{z&1Ll"<$)Ïýy yMͿaw` ] IDATm[? Gf4 =_}FCXF<6sv66kcۍ)Ŝ- #v{s}pձ#PjSi |:v'vi$ Ci}%i[?{O b2v̿0<V \366͞S0ejpzb !hin!xaۣq 466a5_aÆaȐɿ-Ӳ0*de+?;<p0ɹd]-@Uy8xgAdqҾPBR2{`漿J_C3˜* ANG?X݌_86ۗ`>W=J@bUua<:gS׮; CO=?Q o7-ip:8 <8wqo|1mх#GbXmG}~S/CńZ\w ^a&(T.2 O O{v y{gGC{VO𹗠;qVF}qA-o׶LL׼k5µs|e>H6~{\oY !tEHtw^deqCyeкv 6e*f֜ʠ?w}fѢ)tx7~y@J4޽\T۟ޟ=<= <0TNf-y1 =X0[0~ RX`v@<ֹ=?;4vBPR] p\̎H{c UXl+kb0o7˻'Vvr>6Pݺ>x~|HZ-hv;Zd]-\XI-iSU?bk 4V-oBƪ@Ͱч2MX#]ǃ514Wn 5[R$dHglͫW!6x+GՐ{Y덯sF4^Rtwж-VFja݊u+1Gn@z@E ! TT81sl Sz ~>aVhsq 3K{]+O <(+ߍпތm8}9^q q2s!c/ 8w[+<95#ZSt455( ZHVUucǢ.Ioc%ʋ^Dzv(9}8=`D-JTUzpѯN.b{7μy8󈮡aCiΝ 9d~vLtHRvx/J*CA7]_D4۱E֙9Y/{Q3bI$B쨍[M[wd7% w7oaeǃ8@ֺ[7bђ 8aa2+b릜KWbG2Y^jTUdl9'cY`WC;c0`Rn.KoZ6v4κ%m៟Ϟ}Vlu+x׮]n)lr1*8D P8(1bc'03RH-}7qeYJ5uڗkùKOswO}Xl8U+>>̞t&h4{zfjXv}wXLҥ˰jjZk֮MX|9.]ŋ`5hiiA[[8WCGiĂhOayo*NEb+bݎK?G77nA k|Yw[U;`|gawwE-6,=!F1گŤkґBƥ꽸yh+CO4 퀓i/݁_q6B͸p~߿ m⏿M2lnaQ @f#>^XU2CM9{?'𳿉Wޏ|Մة& ecڴ7ؓWF4'|wN=v]2,_[Zq+&DcX߿&>=sWIJa{( /,vxXF_?JdfuxicLε:V)>9OQI!J!jN&;?v-5´`7ӇOÁwW`z T h'ʝ]3/¦K3mض Ne^fj0ϩ W.g.]-mh^9޸r\>G4/_ M 7/.@S&Mٓѽ;Vi<^鴻r (=SGNo Rf;!SN͗[DHOLk;/>HW݌& ~w]C1̵]i7x`=N;ז۷lƹߊw.bu>%⦉C:o36%( /UJ`Ň_}/,ǪM?ͷ퍲>;+gcbh"ىEr8~rT\C''soƬQ^ Liߋs?q;߅8vxk7\C/eS aT:=uK N8bʣ J3^&{j8rG?\_SvClM+vvD2Y;6=v&cX ֿs N4ߟw#Rѝ_r+|*A7pB{=>x4c1b T?%~8C.#1 8yH&wn{T'Lll \yĮ(C#%W]u!>6йT #^ 4&>ϫ'^"O&]ܷ\6dYf8i1:a!9LL? ^=yJQgω ,4e }8ljW'=)s`kllx!I'O2immŻヒ &`…5jlUQRRAII R4:Rhkk 1`@܌FCz|q''eN+={z~?ˇ}б>x2MW7mB&N /K P#CoaѢE:u*`0  8;]s--XaV,~$c8dC`9lMbm%i wĉSv*M2t$49X2v2Lk2mwd2eSv#+σ3c(gj6U Hgu,b1dvat֞aðr ^["5seZeup-_Au`֥s0vi,y>^oDZ9۩nQ1 `0 .*+`жa;ہ8t$ ]u'A q_`Hc(/ȹ v jJա^!l481{m+<xpG7"#ϹO;)'<#`0 `00md;l9:X{q `„ ܷVUUa#f|# ]!I |6&xd֙!m"sC`0 `0 qq444` u[jm# H`СT\`0 `0 cl.D첋.Bs`0 `0 ~~Q kwwq>s.=fb66l؀@֢\3i0 `0 Co椟UVaҥ9&ů1N6|'8B@{du~3N6`0 `0z?]s\vؼy \|.p8 \ǁm۷/6nڈ}²ngruD_y`0 `0 _ވ ^n^-q /tqrmrV }Ǜ`0 `0 ^olYɶ 8:{TB[ukAvؙ ** D HČ`qTdƍ.t5 `0 M; , !'V̊Z /B`0 5O`(,B0~x$1T`0ra~0C0qo7;;z171]zQ8װ"˯I,3H<"5TbYв73\?#2W9;uw[dL CHŬGũ9.7oaWO%B*p;H{wt> g%;;h_8Nl7A?s.Fm= MM ߸BFt>i=\7JLc)w.?i¬=0\X\`]pAˢq QAj&;^_ sON+ ^ٕZ6? $ dw>=Х8bLzgc %Qן+KxLyoTTwÇ/#l|:#{ ;Z3dT#ȒVkU$cEbX#'$ϴ'N,a%Dڱ@:J-4 ,pX*RRKZ}cĬ~tk`F7瓹~`0 `0 !z&~}_\y e!aoۜM6Lljm;N);&T:VrL,I;t5;2m)gґp1[ݢ(gr`0 `0 `Ѝ9.j0 P$oBTl0 `d3 `(=~`0 UE `0z27~`0 !zz\|`0 `0 sMN6~Kc'Tɇ*A.ÈK:^'^aCwNi,9~I2#w2q7xT(8DKwVJ-lۼ6+<+K(GJ:O]cT:T_+aūoپZ* D]߰ӝ7}r"MeT[)8p1۶8lb t~뿬0ݿ/Y/QLӧ,! Nt;i|䋝do W[WjCV@ƯS!K8#Bƹ :ŶLߺeǯ,9n+ 3)e2uqqI!:5tyMg.K=[)[q7gӗBI~tOAh<. :ҡKHe؝VFAHGd FuBV[߰.OgY$y_i(Յ*Y'O1sұ~-[/[B,˂m߷uO)0)/@gl(ٌb/$)I a~8*“N! 5@oY"AUXl{ .@PGwE %}J TUaUقt*Niҡj9F  Mu y'H G.4ae8x'|톣tnź?o' լ0l2%YNBۖMrɨ[R4ȴEF$D btx PJǓB{7}@Y6$InSеG-*s &bUTu*})(*t'`Ef"m)F\!n,t>:{bpX:23Q uelٿm(-TY9^>T8P^1B#enENOhZhN:o'EI8W@G8$!ŹAI#x@(N 8X@T$(u:V;W7g O%̾,mA)[_W~tM$]iM'uP:TwEAeYbyV1NuWѦ0i E䭀}OŹQuIw7EQL :M*LĴAHrDPI1tx E )Y}0Ʈ&QwgsPm֋Q'&%:̪`P-s(-r2s 4:mg(uqi=Nɖ3;zmH<-UKH+ ȋfI"@HW}6pCTxI=%V-%dO<,n$dxuB>J3^AStD*V3g tY,'}vue,C0i ._}Wɋ.".(PH^*[wy:U )CWޢw(OOM*;du.۶ ֍D"@l Œ[HyCQq"/8=%Q\.vT@vaթ&ZQ4BǷ"GT(*l;H?6ER"e۾3EiC> IDATĜ"=k:DElAtlKu9FRT*2~y0-oՑg[ju9W*Vt@sZrCv8s\#$7(h22eKV}':(*GZ_h7V|h_WM^Xd0-?ĔgJZaoV2yƱ* 7r"+FSeDַ.ҵ.=Qf["ק;_>ꢵҭCաʫ)d=G&sR"YQzoZߣ#U } ߹v >ywюuuYx`(*Hqheq8cl )N=Y#E8 wBCv70Q^g>\٤] \VEGF$D݋_lc)y^(/>|.Iy~\yQ/ z7:xFlXs@Z1t*ԧ`2/G~ϔ+z怋p GдQדC 0m2N0'Z:PZZX,Ud+2|.T MT&x_O炋9 lЎn[}Ef|.8!|؀gD {՟Dg'Lg-Y1}虭6DLt(Xa+ lyzw[iQPSuX*FΩvR0;`l,T5w,pR], aah!]00HUH!. $@N0C)OY'αǡK8o: z׺P)1$PD 6^D$*D C9_ o\ԇLY1tEt+t>=sz\sdSqOYTQSSjdC/]Oܓ@͛I|nJ'ϿN*eq[-΄*i7VV2*NP@Rm_W$o\1-c/ܛFyՐuge *0"*—Moj2WQdt)<CAdIUےw +CYtou[[ELKvr!+_ yiCa3IYn֋d2m֢,P~^d E`ʖ/r&@ zfb[*ɒrі͏FX֜CLw~5Í9tW&A&8AGG2T^>']/+')*_22m3I{JbˈWe@̟(e a\;%Q }AjHVHucwzе곑־2wΡ^Ta*\) 萗-ܒҶX.BWMaS,(h6mi8n(z@1hi]%N#JV f'_̳ePռ+=56,M./"R0qLY='\FA.e}j(Qda[tL /xx,P@x#T[LD6#ԘN#{@ɼ%} tͪsX ^:>J:e֝JqY¥2y[P|c0W8 7ݻto(vIн+H=h~f&c4)//mXd xittt(0;@\ dw'PeHiB,yB8ǹ"E2Rh\KQ}wz2Bm ?EdTUVvj)F 2൝0ڿJۗS%:tjc8u-!GRm(>cH2 HKNzZ@h (pa3Ϟo{n9ᥫLs.HAꕽƲbEɦ jpXǰX&:AAmەcPrS<Dy^$sFPнxCwEM:5y(z!* gpE7v1{1RH\3hAG8  Z]?QZ- gkw{!X.*N&SwARd} &/F-(ARNey[^`ڏlф-%rIxF mm%1(;”× 8aB8?+T;+Bf:osOvckL $/2DnǑG_^nMYnd~~/xa_X.;u0F!'{ӨΨv\ɼF;:䘨G !;t4l&ʻsV &YA^>mN^q,C[.n6H^ j ?GDR ltPp8"q"rV Y´ @s]Ȧ377P^*r2zTN"mS[tq&53z˶ഋV췃 y"P, s8du\dN6ټXxedsd#m 渨#]b"!q<ўxV} 6rDM+kwB^QR_G!-O@G$CcQ]eCkA d$((>͋Eͯô.5' sl`d2(ӫ<+B裏Yo@TۤL>/y_;Y#u 3]yEq(RrpY@اl*e²,b1qНlpdAXլ۝iJ*2E)Xڂ O(#APl:IG-̻΋W2qamG&BVջ̼*\:5҈7^Iw.u.ۆyRE U*!.ь6tnRɃ>?z9 |]E?-j^*)7a;nxGFe&#ù ˲ǑH$H$N6'[`xNŢ"&Z&*y. YfS\z,w"*_愉θE߾bS5\3]Aơz!\:5|1Nye(Vi@(2>/0{v…Uf19܊-|:BȨQr? B8JJJL& Vb84#`ȁ#p~/؄2i D1,psT'rBM*VDOr.KY;ů C%"R; q)#wYMY95(2[JNJgNYQB}J+dbl2:rRtMA?p.GG~AqjjeGWN=e{o8:qdC/fc{22_p ~>2-%-X~A&k/oѻ닔Aѫrie%R[H؁zQl_hbC pPaY{fғOk]0l=K. ”Z y nslԯJLt4[~&BBsegH$PQQ~m^dH$-\d0t2-SDPD5_҅@Fq26⋗'tiXPn>#x*)1_Kuic/=s ɕ"NR:2YfF Hۋ]:dKkVzϾu{#rlex{3HڰO S&_(ߗ ա;^Yx*:.vݭ&d2HHRH&, Ri{3ɦПX&$DehW,G݂.OeU ]\D>Pp^ڞӤի` !LP+0n2~uVd*;xzg/HG:ͩ TtD"J-ԫOzۏs'3eG0VŠC6)P LuwMO =:o:fi ٦*S/&-/:?h_ H/JHR@KK ֮]v477GV~l]&yfdԂ"L/pUve|ΌCQ<1grˈQX W>˳ vԙa YSh ΆB:ynqLŽRZ\FUuHx~`?ςrjxd,_BR!g4[˦cLU)ʌ¶d8h.eڤ6xoY~ڙqUB9vݡ4lӹ[MM: ñQr*;t9i2?D,úu?t෡l~pQ#9isiy'xQAGY{DMC>AlS ]/$~_]Ul yRD&Tu/lZѻA8熬PX:!ʇg@F&N|t'Zt*'e`ХCvC&:fӨ7DbAkQ$r . a CP`eo2~`ӽ+-ӈUOwoݽE"TBeY, X ealIuzsD_(ImǂW^u7-qvȫ/wfMp x}D`!'!̣}%Wlc ]N ޥYkZWjߌg5sl!o!ԟӆU.ӧL>\Xvk"1#~9 ]Nмr)"U^v$$9:dhpU癬ѯKѬ-uYq1 IޢUv2(ZD"k3b  nw]$ka\$Y`p.Гu%paV@[dr)bѽ8hf  )2Դ>7+#:y:e]>ewc"RYvɜ)k.-_JDә| Ct:!e(`H=l,y]EVX x8ٺd tCwYNΗ|y#G͗d)A_TllNJ7-xE)|1l&´HZ{+vO<7?Q6\/{;+-͆?LWCUi=t#ԱX.'k> ʏNStɀ7 6UuH6IN@ <턩+N c(v(Kx:QOZA%iz\22y 86|wsPѠ7ڶmlNg5ՃIgJ<-Ivb͜JLd&:^fY՗csP Jz%[(:y (<:LQY/g˖2}^|Y8QJe>sC.9^9-LfO*:uԧd:h9az1GQաt(*+pζ cwTN:V=u8Q7}[OpL8МQyּrE6deY;]KX,p])SN6U|uDzZL3qOuȏp(UdJ\WG'-t "mޤ@]~ NJܺg)Duh 2c*2 XԽC焒8ŝZ&- }ѵE۝Pj-]@??:Gwich<p3V aM*Ik@~?h*:Т@E7a83t;t:ޭ&#GVKWOq鎗}YM6Z7.-3HN6B'}Mag(: 1,^D$XAl'PPf]B|ˏ%SBrcLKXWXNF:ޥAG`}ri qIe$gCއC8@o,T=it;Ѭ r ILBG?i &dY?V CN.y㡺rq"uG8m28}AviF-B"@YYYٶuzx Xl5 %@[diq,B菰m'a/QR;؈Y60^= a bI0$}&p !ṿN╂;xۤJs(.ێ|bڱVñǓF7 }AĹarU,m2cIP]::V}&8 uVSYG>sG gB\;cd IDAT? P~{L߮)䘩]mƑ}|2]D͏v\=JɨzA&Q_~hkkRNt3_1!@^](id)N(q3~L{I*N<9}B;@5BP'µKa+!΃Z}3%ZSy:7TB2:1 he~NGy_P}E?sd\mɛVgX{h߇D:.!oeb)qTAFλa{Ds8 EeS۱yf,X---hjj*B8٨fBs|P-B'ȷsB=^d RhSW)&;Q蓪̮)z@^Vbg'-F8 F}3겺U@ʢш*l6+$d' QW`ᢚ6FUQB׿C:(H5éj,Ct(mYQKC5ɻ~"eĤt1-WFǒm* WNYPʓȸAy~'Al F{ɼ0 ?ŇY~QqSDeӆqLTIƓl ,w1Jm];D79yi:ٶ@/tU&IMx]$t98ڵ斍bw[#ڵVLx. P8bla8heI5d, 㘝l腷&>(-ɒ w}vGܰϬ82XRD(yê#2JѴ(([0ʗ/834= ptC0M^ۗ;#?DQRit\V״(-q^ ֫7VOJGnm'So'b"m KQE_wZʊesPF@-0zq$ $]m2!̅*ANIh"Ś(|M!mdzNMpa*-h~[ugĉ͛\ ejڀkFv`aM6jsuOmʋwG[Թʘ/jB<:BTz]m&ѮȲW:dQdՋ5{+L-pK5Nma2Ng?N, :38cD[x<$I h?= 8 9f 䤑FK-) Eo` RwN N9pm@(ljqdKd nauKs^n0-#K`;:m@ ~Ky3~51v]7^,K4z x!t.1ֈx*Kâ˨˯^yDZ*@[o.]J(U%e.76 4 4+t:(ƣz2AI[,q,Jӝr@xw;TK'sA"@YY!f'z-DySyOK,s^%cT>x2mV$W$7-g[,Ȃ.r}͋)y m ig'N΢&0/bxaۮy\Lk2)띲gsnKZ86xXEgiAZikN:\N5A:K;yJ{䍟(Zq r{duY0[У -xK-"e! (6Z;+5ds&~tOqi0o~8?j<ѵ}阙aƑm07?deUI3҄nǙ*ueW܏n>NS&H gpLoq5q hHq@&յwPa="s + Gt@e3Xi=]]]g}F}v\p'q42z/Y~6" `㦎A7<k;f.em(ۧF;fi 7bDƌ$Lo>7P1_G6ǒX}9ػߘω,pW4VNh7Lo3yDPVݚDҾdy @}1>TbA]H֭;{﮵hޝk^s߹zXfY}EW9xbw5]]c~!q~Ov}twwwŽE9k-ھlFVRuj.8hB Xyڻ`6(CbhYPy]F. h@;-m-ؖ,{Y䭱xG)} C\N66.O ^‚c{wOnzW1_ okgpUcYcaH߭lZ>W71 G ,1p~]ANAj}Y-t;&?;zH5I5$tx5I]mk9&j}yy>sz||]Βd;/-9&h#ôaT!sj XD<ɪ G+j䦴+ -Ie.&XkM,dgY B .B*Iۡg<,l/&]#aP #Ulcys}'zFopx@găGnO_׸@0;N`cƂݸc]N-Z^xv+Ze=|kKO";8} W}zzGz||$}w}EΎd[0_44Up[<(-?PI-}=[ZrK.X|dXD-E?"l]=tw1'nnƂ.kaʫEΖ9˜@;5`hUo5hhniUz7WhAL0/`uT|ScXOfv`Ӫcj.@xcE<6ws-B.񎊮{:2*c(-@޽_twwG޽CL~=; QC=1該x=kMDig垌;; )Mp1EղkZȓExARe9^p6vXpc,D>l#| VV>t`uvDk8Vwrv$QN->Ce|8<il酂?(k,1^{hEn{R}dmQ7.O#l+SK&=sڪjނmP̰Xix6ةDd˂]`r w`Isܥbm܅6+Iz4y祺ooև^ CFxܻS3N[/!&yvjdZ$[vλ^ $K.%,bm !GFw!R]tkqnHd;C(ƃaLe*вp+K`-P ׮6C*NdYlj2U{itXy [kN&ڢc!ӬE69P ;䌅J# y uj[C]{Joi/&+sMmp~0T՜[^`EĹ7(1E}z0UgyM ~oa& ],N׸W,ATw-;.$[KjGFhj]dVPXm'`v|hGqOBr$[bHELe W+|/ Tmj fJXjvClH;Eڨ=f-F R[4,8?05n$tcv8xdڠ6 riڸhޛB*sKTڬUxL͹gW|%`Z3ܓ"ıpc& G,%nt[^2Jw{i,%Ԣ|M [JY\mg]䋤D0v}}MD^%eQhz{!Og-8Lrj +YY0yn:Zڞ ]/. @~]ɆZڢc Eyj4΂\q|ljg]V7E6Ahsǂ41k`]p?aL%iQbjxӨgO a߽4UŜ?LyۿG!onJ=}8a~v~n]R =Ak,$*)oNq]|3&*?eS(RŶ&XkM<;ѸcNo7[ثl-X 7J?|O>h;.JgH1WǎI$2O(^,8G d2{ /_]o DV[\`p>=4_SZ[1-ٯNJ9NBYT,!y ^s<^k+|ov5R-r$~KdZϻju{YZinG9ݝ{r$[ѬYX-]~h:k G0xUDh] jbNh'28&jշE[mсjzNIDڡwA#Gi?r*ȮȰ\>z rҳ6| |RØK7s.YWw0BQ-JS0TvϹָw1"- 6}<^b\wK>l$t\-|wNc}GZڼ#c2 d9ޭ򽼼 @_|=< ǽC>h&^1;X;ٖnK3kIHH!Ry [CG?#vơxowCiyLOOOD~)]__%ɵD IDATّlISeխb0gSxV⠄畎VZ|ec.bmqŘSE[;$dA*-5!¯Lg`TV +c݂Kl<~^g5Eay.U] Ow؋0lBm1ӵxҢ_+f9ZKsL­eR%l-mMě23m#=={.5uG=>>ၾU1yl0öu9o Q^y]+i^K6pknY?kv \kYDW46y_~  Cc䲭Q,oDJ-{-!3\cGRRn5+aڙvn"޼/sEEGYA`[ZH8o[կ~HǫcdkhqAds-6\R %gHf\2YMH[0Hc4|!aoHjmLTw$O--`[ ;ꮖd gJX>49qGφv 2ΐؠW"7(OW0XJ27=2Wq50}w@˾JcS*a kY*QC'`⸬(9Sf&>kvo-۹k[o->kzuT4MAh+{T^OJ״툈 6d8Ϣ*QHoօm2GPW`aJȯʏ3`\Jmӳ -^^[ ]. t{IYadAU,d#1(gI[OO[1U;TˉJPkYNwȫ2ni+z슘k|{|QuR*`KO"[Qà?fnէt__xҼKe{j:}﮶SZ -!1Hr"mi=a-_ӂ 3.N~O4 '?;"odk;X26&P a"m2ˌÁ +pdL0DL򰳰Bj30r #6{uqT矆yCA,g5[kY?o#^C; 72}06z3qsԄA`+kqǺ!àysBe>@mmKBV9QZAR-;I2֔w|mE ؈"vFi4rVAK=ZYqg|s#ٴ+dV`4ٯy˩3u^YpF/ADMkM`$peXʴHw}_G"sIO>e]\7\V%Iu,QEy(S:E` M7~vv<).18t3w#8gz$/u"߭|Tz;.Z0Pul/V:ӿG ´}n\&NEI2#/)+m-rNAd;:%Qvّ]]Q.6D2-yZME߆^{Z;d[&zrA.IghymbϬt=GJ-&qcCGL7??vIΒd[jƼa6y %zؙ^=I3fdA6^YmT)ó) 802 Li,d-}}b,WsnXdutp/uc¡i!ΤoQsJK:QU9T Vuu@$""ՎM-w*i!d/m\CqQ"J%܎EyYKڵH9)-D)I7owגֈ47J!BrEk:Kwݻl < {a*!#ȸZ񋒚VwvC%ވe`1oI- qbtO;Q1nS׆!X8Ϧ8㦢*{I[,bÁp Иʠ:O${|~ސU+\VqkG]3C|5նtکw-M%#;FٲlnVS?5ҟtssCWWhF I6)jKٳCڨuٰA1S B[3m}!^erubU[%Xىaȃʴ=TK&хbQ8aqXE:N2ݭ1 ]l8P7q@@G\iVHRwyQ#mQTuRKӹHӕaI/&^혻,ڄJ4 )okU{/[im8Y8;ڬ"K'zuuUlI6"c'2PwCZ!C\Q"Wc-3y~xYFB5"~to͵dEopI^4,ߙRd.Ɛp1~ 06,l"{6sEUWq6*aqnpoLYC_on딧ԎFҬAEv-ݽBE ٵvlnkoWj=XM浤C^ZN6 fۈr$[gv22 .cفOueφsT,9"WKQp^E"1/?n=/г=[)y_ekkoq\4MOڵd{F2Mm Ҭ%mELON-;j_py/?RU&q;ؘhCFAlWg{vTt#ٺ Ԡaה6DظY{wi҅]/n 0Ka#Y1_P]*Ǫ802Gl2ЛJ#9i%9e}C0q#8*U.p Xx,'^k+ RV -0WпᔧP*-%\z _I1DܒPCqQm)C[SxZ.e2֬^6t\4k/z4TwݝّlIi5Pba`~Æ㚉6P/,bBunbf*ά.'װZ 'q+Sf  -nyHuSm,) n*, CJXx0;$DxG:QFD8cJ yy  Wf8HV+\H ?vL6$kbk=Z#"q-$ښښ%$ּrQ\6{.W݆vqhDF{/HYΒd;[X5lmpKYuk:epb!V6ݾe`T]iX-Stgӆ oȸJ'.aҵ0кAˆXih,'sr}WO72qJo5<ώݳڞPp1: vJm#;X}>( @z,!0."Ke9T{dSUFbaD6y\@$رS숫E[ӝZN)--wL9dQvE5}T"Zoβ]x'~_:]O$f#w}G~-=>>_&eOH zi CCq* ._;lN/eB(@ĭO~Uh&+Eq`0dN q-iرU&z /r0cH޳CφE *Кc8~n1AIha7ʾ=.:1)SP4:~+KKA*6poL:&*Dώ#.sNCu^ {5.kIFKDϱSj$XzIcq=e#Y`Ym"#XMf[:.޶{zyyO޽Ps$,C]]!pD ,:y%Ft0eZjiXG ^d=-ZF/tvؐJYIpYVL 8rN3c9@Y̱&-kym8upX2.z1 cBէN9/v'*.@E,tT^ {M'?v(m!ڎ˪GZ 鶄\;{=*j4\vQFB#,MiqQT޳z'sk>3 2+gGYz:M~DɀTgȦ1[;ΖO0!v{Kqa~}bEpr1('@e/Ӕcl6Ty7\ppIx,I qZaqpEḩiL)|{Ƅӆ1B1$%ĀP\!QqU[jX}#-}ó%7LJ뤽D?+X{[ Ʒk]nmךƊm5ZbdѴ]mki-yv;, edYP\m'>6ց(Cz?T?Ѷv#"gG6ԅ#jtFؘe[Tk]n 0&ژ_|au4FC|g H8 .aRK!Gzzq2ͤ6,›c8Gs\Ɇ!k(uPFa`=[9]gu%2WE㑃U,)S$_Ky^x-%͚!dDJJI#H;6vlYQ_#f}V?oEH777tss^Ɇ uXX7nI2Lg2dqCTI!$'`ذE:}+aS3\#̔Q/Ulr,e=4$Lj 4Fܯ,Hg.H"U4b&DjMLX0oƃ_ۭ*aqd cE/%"dDscS)8줩-RY6 2-zvt^{^D% \d\$[-7/%_QQ+}t[|-Dg^X-=Zۚbdqj>V]n2UR-L?6ّl1:;t׫-;!3$Y?K d-$Fbƿ{/"3ɶ:G 1b4?Ą#Bbᒧp`[p%T躈_LG{nu;)sk*7^|xn8aǙ IDAToPWI8f w}_UwVWm6rDC'ϩki kq-iQX$ Ѹ""qMW ;qe^#䎲ݢu~kDvw7-}twwׄŹّl,p,5#&+*qF y%dvg  V7#^ ª0a:/X(7՝9pGnLDDҭya"~0^,9V֧ [Tm!ҷ6wAvƄGV^5/h3])$$YbO\΃#Mk £k u4Tya?gճk5ugֱU׵ȸ57AhϮ4/>n6D$$%Z{~~v''t*{r$4hqZ7ȐeۓDAf'K:;Ld X:,O!LtSq`5%>?Vu堣.u\PXj%LdKr豣nyK6,T=c%8",~rϠ8p Xg 5$רaL,׼Р5HǬs&cg^9ZݩwEZ ڙVk!_#|YDh(սxt['?:^!ზ:jMLl"z;ݐ<==#=??NOOO|.gIiQpTF~R|IAF9쬾U ~7)+-->F0֘FS'W"R˲WW1Le\7E6G܁ֆ ,ֱ⍓l0Jt?D)ÒqbeMƘ`,{sgg|0)6v2E dUoc-Iz—%"Hx;,Mn;ZGEXk!Ӵ>-i_+ew#_Ebm~///ީ=.j~??oEg9; Aںd e$åx m|F""Vla  +YVx1Fs`VIW&R$tp9(PeZIM-;2͆E=aa:N2La_W6R BʸP$K0̚pK:8~Ҫ[ˎ$ZwNo(;!#04qi:GȢiIFckᵸLZGdYDZEw¼{Qnڇ:V-],Eчn޽8.zOH| }wg򞳜Fmz-Ay 췈\֌K _7YD4¨-Ia $`0Umm%VN)8ŕG=R 4LjZdâV#Wг!p(;1/ȼ)ulxTTQ0XC P%X/N[ r%%U,"Ю6BMryGJ{zDu]#z'&3Jk=V$Iv;^hzZOnnn憆a'Pd>z 9;m0=*4R<G4  e-aq0 >3=K(=*wࣳ1q "<=Qf0]~C6\bGdij-[ :.9e }FT uWkG2Eҭ~ %,*-;<ͭ 5!"݉w,ӫ'͚;/ڿV9fC?GFYx'M_z;;Pnk ~.gGljSwщa2/fĐ4tD9" 4X:B E 0KiA"Ljֽ^(qVwn>X_%?S -ô!nu%OWeL%%##Q|q␸7j5$QDF7Mh ʆCJhUߘ;a<_ckcTbm*nZ](s 8¼%掦HEn;TzC^lCU S$Z>|nH6}\Tm jH777'd%Yl].;@K 7Pyi=O㯅!,r kFI-)KI,TaKr* 7$AjPC¼;"d!}Y#,^!X[я~}]t$3`SXp wepRa^׋x©Y?6|!Z0Kf.| |8x+6F8~G3hp18 *v$hLT)uC hD†E^b$'ozӔ46 edС}MB}ҽCo%.W]#u.f&YJvرȸ8/%^GEkT=D",7"j"nZ:qiH#kM M:,-:~i~l$,gG *ڑ$aц+iCVŵiWT\tZEYXe8./[3ayIˊHDWX!*a: 5"BrGWYTMD9*|iz C 4VG' n"fáԡywSǸ@}N/( rܷ.݃m.*U}/U$k+XXK\o0[%rTٴd_-"ڈ(=wuh=ZۋqZ\m$$"#^;٬]bjh'$h;0 <$gG-8iؐi-u1ݴs jTP`I72V-†q%QroQ}4SwE +ԏ);ۆ [WhIպ1qRvDŽCK"A]C S] C9Ƣ6N7&d\=Ć5ZHG"a b0=g;nEPκ<̢'T1t"л'2(dkkE{d =U:NAX tb޻ظYddTxy}Gb8s_ råp 7Z ٯq"ǥ8*B-dB;X̽,qR{L|?ѻ[5UR_٫U $ <&";.Q5݋Gä06K?mGjvpB;آnk7[lYGYԒvnHzeI-ByGF(LĭN6Nt\)პRh_M@}]*gI)#U1\d,Q{apØ׉A孲5+ܞʐ؁#F7+LS3crn08D#h~US*.-8?ƱF7C6\h,qUSLR?$ucŘjBaq rh+8)+ߋс /fH\6,MiwД_"sDPTGc`l': :װ\έR":5ǍZPRFƴlQlzH*ԷuM6J ݹf#H0MPY$Ȩ/sMfc}>vE-=P޽{z)rv$8n"X1Uke¤B)k%|KP^ȍrqOI"o zq*Zw1$+8b4a4|o8(Ȇ Q~r>Z Y=G 1@;jZ߰83,Ɗ1NHAXF@axQ9˓ACR# nU[W<7ڼ.Uגj%Жw̝rk,AS۽&ݭZo1JQx M0Y&< q%qDSS*û"_J;׈N6k}RQ>GG.gG CPc;QKf{W5٘'erdi TFE{[6I!P*:#I#IfQ+ט0B*EX4pNCp)D/z\h)&z,j IKa5"p Őg@5NJ'{P+ zv0m88H]J+ϱ0$# y/ pUd::tXW'17 BgޝݩM{J{ a{GkwMk|kD^#j=MnJEIC¡2$kz'#(Cr㢵d\~'rSY>#D*nooiGz||7f=.E>Xa`C%aVrH0GA/,g #zI2l8nGVj­F NF}a 1S8kȊ01(S2WˆXN=bRiB5vGҝܭB6,:fz:_bRM ŏEBG&nP?=gAΗzd(Q?>'wL8!TӐ?#8TMU_RzɷYkZ$ZKikqڍVxtZ3/>Bդ֯9n VeHZʖ;RR.p =]ieP M ǔ7JDWxI$; lârXJ(Ke"ʞIւ;{/.G{Ɇp5FHye{Ь/Us tw 6*۾-{zFawk192"ɔ].ZB vAgŭA-rnJ WDi-o͘1l $ƌo!j8[o!^q,9.JDGF{Z#뢞~z n}N3 |]cCA eDT\Xm٢\]|6N.H6PBjbQJ0RMx&(m҉Fdq0Ca֜;MkN=b| g7 ;҆ Twpd2T4䄲)'d|uQٰUsx ,\rɤy#Sc p˵p qYqaOj1!_EDj}@b]thT6âr:ȵxc*FI-Ma5-jBEɵZܞf2m1\k/ohɈ6L~w{4rXo ZZ{۴{nnn?;H6"J#ҸacEqL'F8 ˋ8K˼, ٚ<xp6$ޓF u)7"L8\1Ӏ)2#SZꊌEI?0Jr6i% zS&p,qg$cq^AXT%fߞr'[g yş7:WEx֎Ӈqz7[ruj3=7X$,2E @PFb0xgbwՈ#D/':E@~k H2R:RM9وG0072`  cҮ9;RS{R"Pz[B*=yQM1 .PgInk(o DښiNvR,""dF 4D&fC"Ӵc"ڈ(P;4qTrd;.~'롿zuuE_-V;.*㟟=1===y/E<ɶd ʌl'C5fbNvpTqcdnCĪm(U.aQVD2Wh_*[rQ cY`;:{ e)]6\@ KELXՑ~1n(ǣaиڰ+\ L4Sc *>#Rq(tVz֘`:8&&P&+} ;_sB]i+NFsHȷf]kq}b.J<&-dZ4Mo^J0D86ӄ&OaVm{ڹ+<ɫ&/l+ :t\TI;d:/="<" }auv鵾-;*atO޽L.I<ɶHB ۔]Ԕ/IN4f94'U !6FeҷXφ2 '0yAbG!2`Kq+ [P `qҋȯaºdŭ$ClL|AR0r7р۰( L32-Ux8'8p7Vp!`?|qb|<c" J?js. 뮫 :d"gp:KC~Rm-YbVLP`&r.Ǩĉ1AF߄Ut B_FRO&&sjq)7E8+[Gx.3,(+cPAWQrɓ? IDATa0 7M(x+^ =(Wg|Ǧ~ndD{:ӊ8KmZ$j˫k|TCqFWMCY{R5` ` @m_E G$pGq-[+CI_㼾v{EwY[m-1hk)KY%Eug~Oһw-Bϸ`]|!=FаL;]SҦchb2QI[ .Tg^ ׈3&Ѧd_ӥpүAy oI'u:{T51T#א[b?h m`tYC0E_k [ Q;nnnN6#l2'Z2t9]ttVu{z||~;nt)rv$[z #ى-DȠD^t'@!|؝aAEguE$ÌĔ)>Ї8iӋF> ُjd!2#4φK#. <9SL4P@>p6Ȇֹ]OB+ɞ5a!tOoZ78 =R.ᲾŘBpJIݠ5 N~LOhwm"P^uB0%޸jI5MUbҍH5yon;k",bya8"wth~ rd`oY84MSe6}l-E>nG/RD9;ePp>)KC%`hMݴfn16r?ٵE\p9dc7h0K vtUg_3ҡ6Q;sPHÄ*KxœJALN>e Bk |"`ƒw2ÇEv0L;mXX(]3Io+#q 5N7idhxX!͆!@Մ&Ba@a8ԯ 9-_nz%f?Pm?8$:{xdsn֫Wͪ9jb6&zlC䛬W`5",Ay-Nkę3"FyitCԭdVvMfz,y=2L2ܳvL"լ:Y[K>S+j/AΟd 0Z+ך w`K{mҰ7j'脢p!7K}16Ơ\L*01$LhP!+I^`C/o^X>HGIDv]&儒c<.u\| #]n&pg&GAaP!t4(/^~&e2M]+` U" pw@bc54сddw'9z[]/=>Sy.H^XU c7˰!.`ܭ[4,J6-5kV}GGɴVB"-^H\'3L[8fEkGEtYR!W5D?K/k7ᆪawI6!zkls@2, l3 ٰ@)ʜCLf_dao/s}r!unuhNV_+ | YaJ&$KQƐCw]+&poڥ1 2> %ǃ79NNJ?*$Clzg/Ib\8HqUբ_AzV038 }0@@X Y5K))ׇ۫O0a,:#Gףt/&"E!&~xo+{9OZ%jؠ^!Z5^&~d,+ڦa7\dw7|Cկ]\ ɦ ֆ0ֵcðs_ԻNQܕEl e컩F/] p'Y2i^3+\OOna (e$#&+ acY-. .@AqE&`,Ecb-H`ca1)6,|,1"F7J6^r ?a"ګ{B{0j= 68 L$Zo^ X|i/ʲ#hM|-}F{zyy-;4fҍ5^=v;я~D?7m#jkjCF!]*E8wDx3Y;)ĕaۀ$uc4a~@ih FWK;0 DvWQ0dQXq9>&)UeҞI'obeCKTǒ-H\BapذhB^B.:^W!#X؋#r Q܆C7D"_*r\ v r@?۟l i^TO.Xi.1UD֚)DU.ޕ!,r$ol&5ҨFįIyz0aEqD $>( (N[ln6k'[丧c5W#"j;<=uMDM7S-H6:`Ff#0\8d#z>,D"xs%&NlȨkŸ)*[ـ(L*6sGeGX@?}[QV.4h?͆e 1R4#}gå39Pzu &"QlPTI )w5dž) %.RAUU>a,2QvDb Ro\8>q~쬓Խ _:%HohFicSOؿp'矊l땉JrJ8(*kd a2 10IF0閤BfId[Mkijď}TDZ#-C4n$t8"J˫퐳H.p,lvՎZ؈kz}7OO&&gIxK 8X!h~)j/{aiT [,.$ZZa? KQDZѸ, ɧon6"9g'7iLOOO򒮒dC"ю5lb?O?>G7K$(xKȉ;؍# ]'6,Ӽ,h ﲁS"OmN2@ WV[ lDBT,'a5_!A0JZ,M it20bCyObq,:H4\>Y ~\tcjT|Qy- ٜNц!~.$­ٝpŲ~#L2n$CSEۆC 8Hl플h! ^x]t` HaڜsқuG}@-m>3㼻SdGZV$'ZjuEܞ{'|G#m;$v׵:㶎z)q{W>ɦȿUkWf5KZ4h'G|yDl8f~DEz;ټj(Lq[ORlI6"aTmF$9Kn /slXI,@qeI,_3cbLiY~JP &Ji٘D {`Wxa @gKaxD'i$ l{ .'-fC׉ c.hgfåL[Fդa 5Φg%,KɛQ92:e3tLEO<<*&q&¬`5l~G fEI<0–\9Żo,ZPy=PgI"E!?ҟu? |֗#ǒ#٦I!"gia#afV6b3C?6ѱNaȐB0vlUw %d[ Ȏ^ 'uşCIM*L)\nh-FQz hF D]GCH"؈M*! #D$z'yetXX Q)[T׆E?VNፓÎ$hly $z^c"#]ďQpһ/Cy\?Kl?h~VK,޲/j q?Y1pWV~Pz_'ZMꦕiLVX?+J-vKL= u}l1$묉+MzEwyr`Zo NI'q0AP1)H6i(|(ub{||$"J$$"fha܌ g?;K#وrIՌViqGzI(CfOʸtzhLVׅ“pRyI cgƟ/-Cb6"m>’.$BYq bQ< l_` :1Y0Fs#-5~UZ"g ȠXڢJ#c(۩"*%>H6,b1WM0rN"Ëg>'I#q@5Sx\+G&0]蝑.4Ϗx8`"p01Ըp.|ITAgVC AzfuKXL*g^Sy]H5BEDmL^:H6&* 2,BI|M!ܢ;ZZZ[-a%jdRm)V+H~OOOOtH( +N)H7k'[mAfcRu\T. M[P:"Ju|yy/i3$ْ]2$ :m+cGk]lk@d?}(G.]H)7\ˠW&k:M8ba6N1'K23ܴm@-hVD]*2'(0p:,m\zr"`ܸpqqŠE{JU]mX4aq28\ 2bg_vƉp~EXl88dH<,>RA6&QOKUjXWRd{"Uݙp\DtO$2+:)|H|.WHoG-H,DܽfpH>Hb#tEF`m \H4\l:#fZX5 b'[qVK'˲&Z?zH4%wˑQ:^C{D~ѯm',gGQ"@`Ȩ4&cJ]-'^†^Yk9&^bX @6ٟ @qv$e t %^)~ \B Ә1,D&yUֿ#i(KG4tolQ]I<c26Mfp +S;-p 8RDh,aQB\B1vDϪ=(1'ec1ҳWc"{ MI6QOv]l>nqȮ9T_yۿղ.AΏd([ܳѮ- d8\ !x aCv<#Z"2v(7KŰ_`G3\|L"/E_ t.a2) I˘6N1z E`QГ" b]k2%F2}Ygyᐼp%;f KVCiEK~I,şag:9HbnIoXX>4e#U<<+M;ϳq"q^ͭa^/4Up`E8\/=6Ҙةgy>` a'9V>Ej_m;] ]փm'uIYAs}:b"Xj"r49zp "PX?&V󷺗kF2EȮeZTCN:#uX$kZ\-L+*d!"Tj IDATPzvEvIw===8~d]kl,wwwDwwwW_?\&mi:l_2O"6ܥAv񪏤?1/ȆԯCyOmf:Oy\2n3 ;Q6mx^h#Pc, Ī>?2 LˑEܷ C9ʙ>`"񙀱F&oPJaqSބ!1ނJ."j>[1}UԆEhQ+teg'q:X# S:0N6<'QOAk@ ڣL.`s@9@omk \r}"EwrZn^@}y:LԶ [C5E6yDEyZb;蟵5HiPCF2Lǣ8/lkOXĭw=<<$Gہf[و,H5o'Z/N=&ln|Ew\.LwwwFgJ 󃜆܀1)VW8ʘ/1%i}pO/V Fڭ "$BT> -L8 3Fh/fN.pP``U`@f(CW(G^s~aqT[q\+mDO-1pqqȅ5ܔA% ݁c)a{dToU1L6,,'L,]+B˔/HϨn>Hr7+ņCTCف핁1ѳ"|9+1AXA9gYwsj'lk"YoM:{HI;.Kifjn+ >Е[Z4_KynW#5r?  [r kul~0}\4SYبN~-Km}lhtaZ/ѧ~J@ ^FMd€ɌC'ʍdU-q 6ʉ&ÆQ2u׆4jH=ʴ?Y e]Pä @ ,|4fl1w#dcU1aIB*È 5g҈M"Я0(vHpw<Xv٬m cY,߆K sb.yb<c8,xciRx 0> 'Naa`tKi7C#2}'(H6<$S CF;Ҹ;笜+=2ӡޅ- yZ~^X;]Z M$pbū{8<޲I)ݸp<Zp1P+|Mx^{jdUT[Ӵꎮڭ#bZȨ1B`rfbU< 3]-~y:O|?a(qG=\ OtnO,bFr XafF-e ߒ8B}H,{d:Ბn@eMXg%n6 8v {cr vo&;1b{w=ٝ>?$~bQU$}498#zT#JA)z"*JGod@Lld8\*zGbvd zr V"Pf$$FůP|XJcm+:jz&] si_%e "|m{.2jx.tc-7tb@ޗAOX'lGEO(-5=zN+h `86n<}¥$r.l ' F9/7>r55pB#hm'p=?WܾD[n$\n9*EJ%]K-4_NVK/znrs׭}:SIҷpDYLidc8$ٴlkݷdrwwG?OL6_nd{bJx .@3k/tMurpNYEXJ̙7: D' :T=} i$:ס>y=?F3;NkLJa$:~\=:۝crT t~$k>#ry4WYq7|M~76w#现"F W-|t_Y,5]k>ꦱ8H}GGSbg0lpƪ_G&]Hl8_BMwY5e--%rm ֕RCXĔV%mkզVKk\dNdԚoY 3""k6$ᴙol6h.uT&ԲfIMʣpft8?O?4~*͑ljI Z]&NAP#M`Funj۫KF'N)Kq]Ѕ?[䔐`^J+KP1> ٺc@՘PsH;Nt̚.L.׊_8"~XXv//ؽkʕ`tIeBCB?Kq$nڮ-#b̵}Yb>O#)6n_/1+X~mlca²h|;Nk7n-tUv)&Yȕ"1Y.jW[^ *&(-mrn7,z:QI69f663M#جl,&[/I>|0۾r$[n+'FabO!0:&ڢ -UvS.'ɔU%r!HURL 1yQ8>y|0~R) ]5s:|. {+ sV }9ҋFثcOaNrbgB,M4} 3]m#Њh4,j5|XFE۸}}d>+V+{p.>&"_nf<%d+!$njAWGKd\"֦Ktܾ%3ڬ-Ꞌ+]#m/-&R!rdWv־|z嚺%'gSdffiĚv,oc.E .G~:ml(z&S"|]DttDJR 9꾦I_9>8f-Y F2D:#"pc%:J;)b{f q Ho+'2eɅEDFI _ ~)ؾ/.o["f5۪D#iD| ¹Tv>6 FȦ[ʙ_9|#.QE,ʺ 6GI`mM=[G `ӒV&]O^[qK5KK !#j-L[ҶVZlv5˵m.d_$'qh\l6l^; 6kJ) K&WI6\?|@Ç8{k(7IE7|liD4'2ꌀn'(IdeP|iI^'Ǻ  n>$MMk#Rzvf| [d!uW$n^fJ]zLr n. 9L48eKu~INfkX>;o čtP&fqwd㠄1n9 j܌O^CYMoK| QzC򴣉@02>E΍*.{'ΣhߒY_L^YOR%.k1}n%,Y jt~Eu5-!ԬZ-oKnmۭdӶlY]_ov칺-k]_/- H9:NѾp1mk=ocƯw$&%glrWS8xI2u2TIMl}@&@Fz,Uh顨.^cєRc_m`)Zd?dt`V l_AßO~_4?_Q: Z*.C -N֌ۜ]0{@ # 3!24nVW=?"SK8l#xIJs"F N͇5B`i~؈-5|\ϧDUfklc3Ie7E4ȶĚVWKYXjܾKs+W-4uK u%Y\.ݷ}KbmG1Df+(I6Ծ2ȴZ}'駟қ7ohӷ~K| {޿O]<ϭ@W0 ܚA&2@ rjƸ`PM7.TBʢ:7]kH]`ED"8xQK?Ax5(ӬҪC!ȩ\34pp%l`Ǥv:%mOˌ+ \R: X2~Oᯠy\gNؙmzhq߆> ^icW, Cn*k@NbpU=#N8fl )e aC cD|9lrLmm>,gE.Zfa}n Nʰ55DVj}E#dI(mjkȷK쯑g}[/w6TӉv]7\&FEׅDmX5ƳlaT9dWE5 7M6l[3>#/`$ _S]MR$(8!=S`|QtP^dQ0th] M&jb/"x)U]x5MMy=p}`SIG8_"CYDJYw"sz`PҁLzU5YR]7OyOd. u|lsuhֵKW5!KތṼ1*vM`&Af|ك_`x|6tF>hbHD ۨG~/v/_%+Y^BYYP{{cjmU*КnnMn%jsmpdӾUmmF,BN^4v\n&ckZYB1[O~B__᯽w^[]@Ki|Vz+ f/N#Jd dmKX/l@I+2t`@bB}tB+MM%=H} Y 7.BAHA B|bHzG4|  7ϟvj_Wf~}q '98 ? s'=` w确mj lfR5+,Q獰ʊk΋kxA'58 qv]c^sh/8tg [j44ugT!9*> %vݣ ~mj'D hßǭak@;HY8ADOB ɱ -+ 'Ğ%f Ƽ^3ۺtپH/cWSz/ fӜǝNgkdK2&^R8O_f; l;/RH*0~$,֐mr_M=[KY.!.q[MV} Ys-bߒ[Ӷ׶:|]g! 2-9wpum&*6L#ڰ9kdӰrRp8@O?sϫskI|LBB R^$[?Q] 8 t)2AHqkQ#T{KyÇ1p:5izhzX,~-![@D I7zZpZ$z_) /-)Ѡ J{ha ~q3݂q@?7vQM]l/G} 3wekj`5&2+*sJs6Ns-`Cw*>o/ؐ_K+'u?UG.q_\݅lMۿX[Bo}[e jȳ%m2:ۺ}K/ٷf{mCI67| ׭cl6N&s~w.hl6MV/O- - $ TzDq4,X>(DcA;R-2h:R( (Ug,% ]'./х5z*Kue&4s|Ws `$qb ҭA`_C7k#BD;A>X^dM zLO>^poDD&!crlQfA#ny@`.kdkX$ZKKaO5[ K|[CԐM٤iv&y=eq_Màw?S_ˇM|xma'Uvᣌ2=x=ep0%BMkt?ɑh9,[J=5OnRvVu[_dҶlm d~MO~kQܚ}'b;\Ͻ.Z"4˖$̈R$0 ITD@0qZԯ2v IDATJ n:wN%B=Xɤ HH6209xӞrGўxSꁱJ-rw؟*H#n:CGWd\1R%>0x9<'vIR畐]k'MI41"duN1x&teYlx+o'D]?ߣQ$,-\X}Ѵߪ!SjV;ٶvZ ɳ%f{%.m5ʚekrZmq5k-_^,ц$ּ&jlۢ0>/ݻwᯡNͮ͑lDqҀQJ . #2!IDOt ]7?g p-ܦx;J>C?k!A[QXcCB%FmozCCArR$fwAbܜu0viҝ&QDDZ"WjDK2F*ѩؘ|V%\*:h;$JqG{DI΀Y~dS;RQ_.3 0:lTtn/))N&kl8O&0~&5y1a諃]ge?w>2`ff0ҬףݼbY 1ifYSc :Ub7vKQp] $SC5}OYȽh[[\Ԭ&͞zږܢ^Fs6p(KI 10цx?}mnG&޼yC?~_x@arި4&I6.Fw[5JeKjεľu[noIm}Vlmsnݚz'gH6޿Ѷlx~.H_}!#4bQ^"mÁ=G+:NHx%#Hˈ19Hђ {.8KMخO <9LDs 괟b͖Lx4B!$Mcd \_-ɨjozhz_W~21-Z2KDf݌3"`)cKQ <zJf4FOk;ă,n>_B~m~pji:=~31@y5mEߓ6BU.AA='3F6&gp8ef6`"Mf]<+ɳh&{,Vd_c6MA;o#l^azx YqInSi;xobHS-b5͊@gqZri)V{l͹.E=uűTzfے[v[b궬}8 lB):DER"Klr{=4x<7|C| _~%}g%#E3cі+Et`D`_ 'hOtŵf " וL ݘP.8S(A iWJECC ɚ}– /-t(`F}/&>~ s;V q>vy>WBu"(|,D$/½/pvuHHѰvWubLGNb|xЉۊ1</FB%30ж_d_Q F]vX{$tÏI?64Y>8/ n hn^v6jͬshe,Z!?kCm=%u[Fdn',"ʒk~ -'k-Gռ>*]9g;Í_b2 L{$65`JТbx,K}>GB8v1h)2 #;t'hɨzdhNDwppł |J~s#"@R)up/t͚ 1>F߲Sc{tG@G$ )|oDFIL:`L^bCǼa1ψ>oP #qKH)Q8"ΣH^z՟Tc[:g'f7?,=-K}9?JH~qɱւ/̈́H蓉:uIV/+Z[{[*N]K$Ϟcv J'o[LY%цɦ{]txk+7G=)D|q 퉠|e4zL0|$D )fT7cw^f+`)kz'1. 䢈7Z2zch&ELJ2KsLT]R?ED2~ $]X>t ]tX'eKFIVCQihgs@qArhslh5 &B'[8Fm>q|v7xn/m.dzq`X.0%+79f4%L{S/2.uv#ȇ?(%wmU3ݞbR\n-1E<ʶH6XB2aJ _Dp 6cZDXFRpGA63"3O1dqkߪ@1dZWP hͬ\"*_aqVD c}+Fɺ@4(:HFlAg̚?oS1HƵ"eUR%?`у]_?1 ?N01`}xLv7+FCgAD,uE|jvMӉ< Kt.]m{qλ!yr_q˰kF:Z 6 L$">a$: SҎ9M蟲[vdn&?U̓vQh lG=5g[nsnis-XfImsڇ,mmD3Y%цĚL-M#,-7m_Ч~J}}'H?COofkr{$$H!JI P/DZT ^Ǭyj>)^S./|GI2ppyX I808t4 YbH,]4=4==$=>(!_xW7 3!@FsVi ?@Xhw8kHvdWU3)؅?$:hSZ.0_?c@?a=ZuiW+.@q ;&}L0^-LRcBB\# bqvZ|6S/)1J؇)f3IQFLp(S&Mvl/ }4e~<`~NF-)}Kyk]sSm}J2m9^r_~sēu\wp[#j6MNl| 3 ?#ၾ[Ndzl 7{Zy$O!!#4 +F0spOe"NBjt!A)"h> ddPD/ $izhzPp4R#XxE$4}x0y֓F$uRG(8$FG U6/"w2$ѹ7WY? v?U] ͚+82=ui9 aS7 ͓39?w1;JH3(n0|vے1 bt=I9 _;M'otSUj1c"Wl'I?]j7FC/|Frv/N|mKVSŵ $.vy.T4"bR刷!XܹJ\N'?9=>>ҿp~H[)?eA%7@S |4z^ q"o*d1>>ҺDGp ?F`axw"kzHl@$?EB2jbB\sRɸ@>H@}w,^ޝ%g׎yHPdNxRx|pcVίK[E>eg۲o̱;'g3 x_Sq p.U~Y"۶ N-nY}k G?z5R(&J6Yjg^ELD!>ke#=>>L{zxx~Oa뼴r$R;2}&ݑAg7dCPI t{ȡ6jHs0c[x]!dm ]b]-]4=4=@4Q4uP+P'zuM]h!pG6~G4' u0uob=;јX F|(%P^9oz|<"e8P^Xػy@xx@̎jAd[XIp p & kڢpMNW9]K:Ik6k h4K|>vU'gnxq-Gb]eKbY{-gմr6ԥHk"붸S_jE&(똚a׼.Ãl^.5hᆪ _}}W'ٖ(G?&( OG {Gss 8sw(\z8utL zeP%uq= F,5(눏mq RY(~ʏ%LG#˧G htN@;m:ĸyLtlQ;}lkRTv 5+]U:\;.p%~ߥKc!b4.?`L0γ,{G {1sFŶ)q>yTŪ3lwӖ}7u'yޣ^-k<&E1mH'K۹x9u /d{*ν%f]j[n5n[f/L3e2I#rӚYmګ[|"WE׼"zYlH66CA08H䁉)O0Ypi9n(a :0}V IB`f%Qx7'^D:brЏC7'1L0~~z4N@QE"4=4=@^%?Vmu|1u0@rD;$t0:INdHH7S?8_ qůD"qbx< 1pD֐ BNЬ9gҁ<Dw;tw_hc"IJ N> ?GD4r$+c`5~;GZ8ٿٶzXn$ox>J^"kTiAIa|~dii܎reg]4lKIp|Hz.F4s4%4;1_#VZn߭q>SS9FF^!ո~Ym5KYb-)7I Ĉ}Fˎ|2EsRt rQ%Ď4 0 &S>I -ItE`ú և+g1ng"䷵XGݏISab%(0u}4=4=ld'=ws06+QBpySwY揅O~|< UGBzï'A l :6AGF來h1x L\~Ϙwl]ꌓ1#! (Ĝ㐠a2Q57vEL$Rɶ&Rqj~- TI(jp"h,w3YFF@.~@$޿¸-o %` ť%7ylуi]?]8Ldt?2nD K#֞=匨k!.y5[SKiFF\IB(Kj[rҿ,驕˗#Fxpe D3@$#Ȉ$눺? jp~@?ZmLpi 3A01p@'ühi_AQ "K Xp+ ozhzX(@$ uK.w*(d|0Ɔhf˓mɀ:`hi߇yL?:O8 }payWL=%!ncdn/ ߼G3H$"] pq@?>iOQ3ڏifD{00ʸ48EJG磙c:˝x44\ڗqow>DHd} x$>bB8c$JF&ܳح`?F+=hqӁ\+c 32m/{M}G{uo3яGA"fw4|L䟒$vRmnt){EyUԚff%jaf-ye/G_'|B޽޽{G?/zk-7G9̏GGs6Ja&]r0 _ "H'"3HhZf9.L|Јg,DN^>0Dfb-;U l6 lۜD+>?`&rl%#|#8q@L8 (&a|rF[$?è$vQ$zq}?lI\Y|*AS1zb8-7; IDAT`_|=g>G<e[*㼴$%Y ("٘,눏A(ޥ$C<ӳL`Ƅ@0Ҍ 1ߗDïju_ۅKE-=)"Z[#ӬRz2G0ȶWHjx&5휿*u)O'? }Oox DbDa2$jtG P zo4=z8>b򨼂T$Y@.K\ф~'9I~ iDKxHkG:x `Ak\xrv>``FG=?U.Qy8W{xJnuEIoN~3e}oPeЇ<}]ǎx;#-~J6^uKCv.^eyc  g p v?rkw 3j¬5<.5WE^kfl9\K^_G:NtwwG/p8x~O׿r$\H_zA S*G=b90 yJ{}"3c%ى.E#ɕ( H'#Ѱ)M ƃ.@.{vPtOzjr OQ"5hl8eb#;U `^7پ;q}8'w NP,ג, ?RD4y0 _d#3}E9IO΄v0~<ͯp7S%>t9QWkRȵ6:mc.qhnUlӶ-LRf{4 }\%#8lj9, J&QJ08?&3آ #&Xd\ K;Q!\wy`!p@(@R4AV*,o\6=4=z f7.cg;;1&0IHdђQثB$c#0+ 'b 9C?Nb1~5 7?ʫfj ;=7⩏むI~c4[x@0%fmxjnN FD@2`TD!ďly(Tr}VI`7h&bp])!VZH6+K*[BqV[-&9G޽_W_޼yC?ϞZnd]Lah V8iywDϿL"鯈 >0:n*cus V6&s!^ H!C"Ze4ka\2l~ˑ`N'gkjF4"J%l뿋1⃰LI8ķ5WoZ٢Ծ.;(OZ}MyrZ6yV<Ɇ%V &)q}<`I$pp#Z@#ٴ[#ou?;vT&TzAp0%Scd)$c%@MMz8$cA7IkL}t TB$Eau0# .svOßŏ[?7#]ccq@MI }A.щ@* ⩛;Oc:k, t9[(0ٶU2XٿKTz?>H1Poc$NJz10gc> E h66oHcH '1ƅX2Sܣv`?v'G8jg T lHllXh[zK%Jm^wlSj6?d sjvג\lKf5by͑l |8t$P@kL/1 pi\<^+u [!v3(A@ pB' H( ˦z3$4 }>}t{Mb5`P dDU:&`Si;9iķe}/;x=9I8R݂l2e,Vn6Y_*Q\Ӿ=f]?#٦x8 nqf&H.DুDPCJ oPLH yF)P֣DDR%V@MM9= ~7-0.79r%7>h8-⽖dH:@0<zȜX&d_D~(qG`[H6J.kiXCy2sžI9DO#Yg\j |b/xYfH vdS($E.Hstrv4 ?1N#"YCß%lD:!ҙKϷqN%f\`[y +< FiF>-'qK;=uĩŚ?KE|pi1.CC0nZjq񽺿 us\hk3ٖsr]%zsQ[__*ռ/?1Blv+/Mr3ְHk.!ٴvXe# @?OxHO𳒸E/ph/q%zn ב?.ryMǩkl.1+djQ1:b<9I?/ǰ^!M&li>t|ẙ"sX pL)~\,4pYd[ZԫK>%҉uZm1[kH%.]#}77??/'Ml)IؤZ"xs@8"G<h9 B-]0~C!1G=lZD4rv@Q {sVd D7H?l:I_?m[G**b;JB5 3D5[ĜSwD:o-܌DuS k1 r| >u6ok.ƴv[y웆jf=9_ݺ]#Zye[nsɦ* y$Q ApB"#e_bĔe.H&x-)ԋ/H(6EwKXƄ\b&uKDW@+@OY?Aϝ?܌G_rfZ} Q'ca 7_Sʊ > ]e;_iX3j;0S粟-1&}9K-xJr(&dQKUWb~֖̾vkeGl=T9!  n}yJlq>[5imZiH#4lqVYr>K&f#Fբ : (@*A Y8L. g]xDyU 4Ht@NqyЃJ8zpB%uIïè xH,,#k<<~uV@=pY3s_"/2-F]Wڳez gƿo[8sZʹ1scx"4_F߷0.†5>ZaZ%%\#y5h힊lkR3ڷ|˝oq[}M?Gl_[z=t &I60:L hDq2Q*dy,.0+袣 771e-}4=4=]H5JF3mC5XUlΚ:8^#H5G.`CÒ(kpIYqmt}ؠm_jظֿ-?U%g=ZR 9DYUo)(X9Pרƶv| X7g;8%z[s/mf[+S4i9+{,6 =W9N4#}7 {lKojs`D$IO|" 0Fp֌|^]tiZ]2vrlt 9ࠍKXrY$ϽTb} ~6:}Ç<f*lT]+jKyOM52k*%ae vM؈a;PW_W_}=oIz _Y]|^'9dJsQpjY]l >jD9D99Kgs\^e) w4 dkzu(k#6 TziV[1%RXc:blgU;v;gնkDZ+/ȶ&?P"ՖmύɆ >T'RWmq}PzE(jC.adF%]L4, _n7=4=\Pb.-+h缸r~ uP*W?~<ޔgkFLI|pn  z6^3/Tľ-[*Kf }][4وܧ"\Ak<'V۶Jk/n^CY3ؠk]nd^P]0.c'Ԡ &12m=. 3sdnk/p-zpP])źH:IBɆYkrU0k]*agurn6ǪW-^IC bӮYdu瞹m#Zyc["ÒK mWndC[nVp ¼me})p4+u:YZ" qVOʺ!'`_ԩX3֌$K~Pj'l]R\-Y[+/6Zk,NE~X(Ug^ [vUcfJߴpr/At4"V\d:KfՒlJ}ggW_}EI[z=?n16oVÀLs$꬀K+]K+ׅFVmK:1ZizJTTҶkq%{fEj4p^{.F˖[bCͿ UX7UHVZR ofΟˣYN @HI=g͑l6r۔ NVbdZ*瀶E,5pZl++!e]^#Si#ݚzpe]#"J y.X/b0+lX~ v0mrY/;nWϵ!-kU^KauBlQ×`2EVN[_sض]_ZJpjRjq/H[ڶV^{yji+d6Z#޼yC=h?Rnd+>+)NXX sāu.6XGy\5 u,)ה4=L%ݜ\T VkTCKTYBpi3; X&_9\{50uJ/ɥ8A6 e0Ee c-q_n\R[cu *[úUJ56z m[i\pZrWDq}x5m8һwݻwoo믿%{rs$[\nFc̀eKdv`SK"3Tԙc]v$椬KR$;?kGq_\ 6de[@9_mĉ mKXU)w.d˜XXc,6)8~Yª"E=vqԾirrٴAk\J]~m/iS]Vx2mG`׵N/M ,[YuJ5i:sX[]ҶEVZieͧN5Q^55n/l Hdj^ E phెx"hY q=MlUء^h{NizJTDxv|,9c*?06r)q хFھ|6Y2U;^ibU=2,)` KmIBUatA_cm% ڬVZy^](/uV^F9-?# R].L&y>7X%ع%IF)\hzZ:fx~~hWE4f|"疆_V_;,K i4~_\ Z6Gv}Kk&& [S"9֔Ͱ}*'Xw6+VZٺl 6`h+7M%< Ԑ \_qKU>U}[%RXkkD;Z[O'ʄԺ VhGZ`Eƀ%vyx9[Zlg4|✲[u]m{D%g5"V^Wy-lFrs$D}7n^;]~wM7;7wDowDo>'owta$:DGG{p~'@tNF8-?C?u";X'̈́~70ǻ=b`0I x/M?a oܤۇ,;aO8㏧اOI;k>Q?N>˾ý&C]_ݣ ,Ot aq{$>D'M]z#?r~r7kc8Sh^Dž̑T^Ky?%ԏ_Kbk)on9~O\|Bbq$z__렭sȪܱ*Zrs$sGD#rDnO?]L 0At8́`M|R?MII-Jj11FX8$rXyIq zs}(|N`S5 gDJ#<@ON( |v ג^.` IQa>w|q{s? )wg !)sG% -q"S\ Ѵ]*}7cq2Jq7%^+ϖäzg@HS@@о'T)u4-^@n@>D";-[}#z1<&Gx,ʻ1N1&u('*0:;AZ y<.X/۠$cD0m".pxvÓ~BaƒAsX6^xܲK;2Nfп' eP``ہN$5J$'ˎ]`{7+G7It&$~X@/Unޡ}mOOXR}N2(҈VZie벖XkfYYlSndF$ nLB<bAt=@ů[kL ;ppw"rMI(s$s2VGDI1Ĭ'ݝb"gɤ1FX3DbnMDxN&FѮ!ĩ#Chϑ1F~$"$ AE\(LǙP x=S߻g'ELZÄk \7c0"wOD^+K5 %u LN,@01Ix3ϯ1LתkI.(؁mq{1}(> IΓA}>~;%vų:&y4k8](;9Taˏ(&oAFXѽ_#_rO}(h$7$ڽMYKwPrֳ|5~x)e%y58_-˳~ SE'Ƀ&^t5fJ+lm%msn^"͑l 'Lu788%XnZ(u$؈k 0: 8'|FdR`a|7v# p.GGz)y$״ĉؘXGvDO'ȁB[*Ĕ:\׻>s}(wES k̞L:?f s>gaAz::SCpH,(<\,&l#$=IbṀ&[D?2<`O ({3 |8ľI"9fiJu>}YwPc-dC?e?AO }$c,qSuL8LG1IrqAApuDQ8@?c@sC.Ha`.i%b"x6 1衛gDb'S&YPkDќ HD0DOȞL*I$I_.HÝtrDQKZybgyC `8j^M\g, ,H'0Tgp^`H: !v!6PҟP~!$g  q>H${pr#y} ) T3{& *ߔ4@;sc9u9('Z<"ei&ؘ $>:pm<+dM (q=y{ĦedQv@Rؕu&Iׂk<#ؠNc&yˌ:.Z{(h8VK$cD紱b! 80NצMD83 q@ O?GܳL¶ +ۤJP|0 ΔnG],T\{-ʭ=Lj7ט9yp >,mmlH@\+8?pDeY5b 9[iV\3ZyyI<A $ܯ$$dP5[XC[k4J%Y89xr 60Jl8HV"]$_+.+pXÔ:$&$E׀gD\ ͍R 1!& ;GBŤCB2 0Tރ=-'o=kDF.F>Z8Fҫ*(h~ Qa8lMi3XeD-Y# jܟ":ZiVԒUK@-odm#FH<0' ADFX7/$ɗK0$.$WDZ:8=Hd Y ~$ 8s-<(LܬDn ׆KIbgͮbxF"âH_U2aO&tx50tD4H ~A!W s@?2ԿԷ5k"57E]͐R߯IܽOoL?)XH'AmS"P{إMM0FBRV6{訕VZiYWB}K^ov͑lEOH`1ݜ$ ˀJqYU 9V0 g &F_S n,%A}B f\'"u?QAKر5gmR_ x{Y ~% ["l?%t.ҿF~f͆rn. W]sk~b]-\_{5x1c5VÀ>i%kpTߠ[rI=la, _ =y_#%| MbY5?Lz/<92V˭ͨ,oo%9r?K2|VZiIאnnQndszPXX+Q@ظ8 i(e]#T)V+yO1 w8 a% 45+%EXe^3*Bb>h?y sῼohX\J{9^Dx.C7$ vG-HDZD\XˇQݒW?{?gȖ;G ȌU̚ok1a YE}ꋚW$hVZyk^mr9m W;t -uq xJĒ|::,VX!je- jf%UK0ز/%^q1'EbK,%Ys|Mۗa, =XPaș%oG/&NkHU YwKȽXdq-V+ƱEai]'VEN֒^גJ+O]~m;_-dke# &׵NG d#@I Lp_k':TʏUv>)ʰB#,v.`ll\EL2[~X %>Ȥ%IMv6T/b6үXɕ1&o%Q9 (>Xz!=us~CطW6 Yk-kjUZiV%v-fo핛#نWNv*ɵ`siAaVb)VQvNƢKu_ Kǒ?IkYj|0T.m-!w1,+;k+Ɔ9q~O,f롎^;~lrU>m`Klr+[KJ+r-Mk햛#F/@l62 ֵ௔laҕ`OʣʶOV8Uد7n7\ʮ`;Z_OKcŒY֯% pjmW`i`(ءJ槔 疶V34Vd_ݯIݿBW9GF̪N2ὩN,WK 9[iVKɺ9ЎȵVnɦL։d-1$҃$qWS$ak&ZЗ+uZN LW W.sgd֒ǨxBKi7(ׯZ_b~1`j[~KR_Bv~_%kZdBVfU^85.fuYFs[+ڱVZi)%hov#* Pl"Њ_+Ni 2k sZ2V PRNldĮf戩Ri¸)g놫kZM4< CɗÒôơKdZ傼KGk28eޛ^$g/)L7eJyTW_;st?J+\CYDv[+ZyU$a+NC]8>-`1k˹X+0R/•85Ė(0i6n,L$2f04Lρ#o,;Xxj j\CRƏ?^; 5]L?N3K~ɫ%ٱÐgkݶJ+hw:үi~h}zl+sǼ`}Yڏ-&ʶч}9rnyϴ}{}kTKC ɶ5\wkBr{۾m]pۺ<:k l¼}?,-^ap_Vf[1Цm_Ϻaz~O?mmۿ뾬ۏe}ZTw۶uXף>˚^i]geк}<{ksܲ C5 8}`]Eq~.d[Hg+ۆM6ZA졂_Zc/,G֧sJaIٗMO8ޭۇuX+l}l!DuzA?^]OZ4=3^i箷Lnv NY݇u?N١,맕fy|ZZ~>}3fy~ԼW5YNI IDATUCϐMRۗl}n}~ҶDzo/ !مlsgCCmYec -k]c_^ĢvcU/Mα? s ^C&&?_6lc۴g{e[]6džvv![,F>f>,@r,s}m}tϽǴm./}CV ٪(KGU(TL!)]w9+wV觙ͅ0͇ż ]ٲyk4ݷݲCLwUϻ=Nl͙lUmiSlA6³ת![q2E3_LEVي!PYw|W=nzMgm^'˲iVg۫tV/fy9kˊEgnهB}UZ!dAUHk[6T[4m6SZr4zR"Щmv3[a:l*-[|&bN̴ !̅Eh5yi^l]Λ/+^"d[eul!=\taZ]:ڢyvʗ0CrԴLS(7ĺm6`z6Yl:y:X1Xoq֮CcYzΆ햝=ӫM B6{P|*XN2h;3ªYlL9>3!^u^ܭ^\۩S =UxՠpEgeE˿vM˛!dŗmlۜ^V òe\C횐>`)8[^5~zALSJymW=_Vaekz֪6hB`¶B6uVS1l6 Ԯl[u݋¾U5g۫S[vy]PV[9O~sqxཟ{,I iL^^~K=yD|tuuKu:twwoӛ7o[]__`0h4h4޽|e]qzvqEASP3ذaٺ˴؊uϮV3UgyMrնϗ:?~5Y*ܪ[$4M$LvuqqiWA@777k Z9lm&if߂dd[e6g׾{uZou_lMY^wlYem7p7ԉrlzWa\9 EUiǦ3ժaZyxl!=(KqkLmuov,no*/ -x< Җi[V[P ³3pl/}cjeV fYEWIȶʗߍsew{3iOrҦ&ԅjEnSM{Ѧp 煐 O>DzV_j;oxP MFE?=}T~>}+u]{}wokyF޽Bqw,˦C ]zl={TSu4rwѺ;Vhnhp8noou}}N3 ޼yn4lMw]tC4j .d݄y,}=~ү@9p?ն96Z{`_+˗cV4deAggPJru?t73Zf2S!:?^ZI?*ݏ똼^/_^U\H/_J/ICIǵ^OKH/_FR2WT}y.~,/s#>X1F Ch[9 Z-CmC9m±iSc%p0q{"P{ DM ϱ~CW7{}}]{fKq:u1JrW_5sMlIYIH禯e~N&`Z;~}N/{lDL]Xb5ݡ)T[44v юGjX7 PǻCC`c߾4`kcPn&7kGyFݝyjgY^Y- ˖8M.Iev1>p إ پC7سg uv! ; ].?>=ܓ;w~ N*j㶟g[t=,βǺ*em:: >{Lιi,˔e>i?Mk;ٮNEmS]lbJ&!OdiNمl'mHn*ݾUSe!ֻk^ն~z,μC-tCK;ʶxnQ߯?Tٴle֩M#mZy/3~?,JU7q}XUl{}ueד圛~q]4:^6XYp4mǫ}n_קe.-T^׶m6M;mvmmT׆6ium{r hJDI{?}b]!yx,45B 9[}NnX7mC%P _|nvi]Z.mQuM.,ЭIl?>mc^eVYMy\:R|z m٦/˶e>uˆU7FEem;,fumקnms˿U뮺Eӟ~W9ޭ{L~yy1ӛ M^tlZ^q20?^~,Eu4U^XwV;&5mjyyzxߦ*ynߪMMk,߿=WEzhn*kXu?ߋpL"((EP4NGiN^7t:t:uOqBF# C bFF}'O(2o}V777ݝB3)MS=yDO>~}'OuqqoF_Q^ݝdf_B/^__oo)Uꩧ ]Rz'ҕ>w+uULN[Սnt[e4Hc)[]Zݶ)7s\u:F3i۔K*&څ&>}I?=M"7~#Iwv!ۗ^ #- (ՙŗN37W۝);v!ZXڶv%I2 oybW^闿̼c٦Rvr7mw EL[rHz"ʡq`Cgw&۟ɿ;tȜU_ x\ l'vxN d!!B6`Cl Ep?d!!B6`Cl "d6Dl !!B6__=}XчlѢЍ?I11-n2dl7f2;d#_8KD DGL$x!_.ʩl|L'p-Vt'pчlT`uMV/5>tO`3`UMMG&]63墧 }v I%isf'&hs(w݁ݷCȇvf7߹>$)Wܒh+1Z4STT0sg&}ͮoYf f>II,7)ϛ,|ПR?n/nyLz\$ ɓf.\L-Y-Z Q!e\1f2 KիoN_~;|_1jPw5+r"ǒfuLsnǓN=Y˒Y̲0B蝢˕$9?rUGW@l^s]ޛm$-wrFNr$$eio9vtVn| %}\(=v&{~,$QN2bD)Iy:>i2$ZB;1G۵b/o1Ebl{*oe͛ݻ~I6z2Kld{K}'q&Řilx疚ren؎o,J;6^#mlfYIwfk\^LF{.&^腱.y&e +M]LH qnwCq0S eIԸ+7^<#8ICE-b$7xE?DwozPl/|l/T.[^2z%q3D1>Ʈb\FNJb ZtQrsL~jL-FBLn\,Ycy>9-2 pUT}6iV\2Fvѫ'_%1z/w,̼ .IOҘqJ,8s:;蝏 nY3p&-*wybffYO` 1SűO-̢IyQ1Fx92E{Rы+iR ~0ثaΒo'3F.'8)KJT>-K >$1̻q;&`,h`:2,b29-I_ֿXKEMCJRom7c% ӏ3.wl,ԜsQb]1NIF)r1\14ZL~-ZH:\ wf+l`1E !y|6 SzضtW,,I?߽{?k?xqW㮿R0`H-Za8xU'7q_gYl_ɶuE+g}UN$d]\\(fCB6Gw.l8*阅",$I0ˇ3?9{nl*`elc%fB6iIvm^xw gn>O::Kȹ]Jʓ!#IJrY3$7˼4}L6JbLB|76 6md+T4gyQOu_+Iwci|-ygA\uRC~9 %ZspadYz!KhlfAcv92tx- `K3 5Ϧ?fhk7xq=I"q769y\u.> r"iv76\ұ,FI`n3g3Rﰕ&m4sor7:gWӰmֻgލ7Iz%\xnǓzOF=6 >u؞b ]lҮB6ia&Iճ$'Iܨ? ׊mgmI(5I O5I&I ؤ]lR*JRgI$i =o&3Zq}&I /vI٤ڠM?MmT r&IpMZpӀMG&5mڊy_9x1]曯 "P$}b&X&ZqMW&mR%lT ܤ W9T5iA&%`j6>pC7<>kµf4mCV6 haZYc&=\>!tƂ h@3k Pu$bz:IENDB`qdirstat-1.4/screenshots/QDirStat-mime-config.png000066400000000000000000002530001311502036700221400ustar00rootroot00000000000000PNG  IHDR|-=sBIT|d pHYs+ IDATxwx93ɦBA@X@V U,Hb+VW/͂TkG@ҶBB}=>3Ϟs,!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B}J 1n݄B! BE (T!;DBNB!=9pkC P !BZ`?W vNKiiZ|| B!ZZ`:z ӊ鶡:RB!EʇѴJVL& ӒPne_,aU!b/%72'NKCkI`aX=AuԖpZLS[XѤ +$ !B'ZG/. )ٔ i-1-C`lipm0MT0*z}:sV!B?⚌@Z6mU=Au2uG%4XW.E49VpS!B}-grB z\`͍VTOI@=*{|/m9MT0RJi$F)(U!B} b ؘ@(fELJU@} vm=- yl5rJE Qqe*BXS& #0vĘ1%uK3G9^iXݦUu8зT^*qJu8U bpjSV >pq=imB!,E1`;c;FE1aJjx1A#^&1rAuAY@͋:ҪеtL֞ZkQ QnX)χ7(-B!{L!F0ceiShy^\D=m\QhZBIP-eWAu߅mwPu d뼰cKJ}vҮ=[) i7Tll,^4$!U!bi_ BX>c\+ӎ1g8!EbmF ۮzXqhM7q-*PqZ\îJ)ˎQrі֮,7]h,O˷O !B쩨W&-׊,7d\61ƍ)J1>umǡ1_UO%F:5*/*ԖVJY_iBaK,TUgeڮV(O !Bi,(11h;]O^q@um#!U!b<Qm/KGuڲceT3J)gg[hm)(Pٖ PGc鿏:?JjWJiH7I.hh)ejKMϧ1e[6ko+Bqp-:F`$j1֞xϸZ؞/,K)W jh[v忇,u,A$F)K+Pqі k2J;SQʎwk<P>g*QTFʧ'sP !B!ck*Qhض"k֮xV(}J kc:l+Jr=0P|-q6l}W.GyR"ʉD"[7IS~qlbm[%ZIZ+GX/>B!@EF=EW~OOi2IX*Vvzq:ٍFj !Blyk '9+ڲ@WA s>}Q"(g>71v1*WC[^q-1J2 ޯFy>*_)DR\h[4: K%)g݊'So !BQlO۶I;r1QcUP* ؞8ZaYߏr=܈R2a/yƥ(em hQқr l\cczne݊`AVuc0P4VlB!y >RvaoUkls)[ٖ| ,O+3hO)hG(XGhr9EeoZ^R*7쨥|>> *&)W @c)Fk_8"z N {{<"Q!6G G0XH(X϶hU!5H.; N6)ϳR 9J{JX +Fyѐr,WS&T!}|@cѨ2 NLj$d29o%B5H/3QqtH zIj,XnO.:6?ڵkԯW.:O?K.\5k6ĸcwy0q ."΅^;OIf?f0wl.i7v.҅iiVHP58//O?9uk~v?`aacP1|*K`ÆOC\\z";h-imeyyV Dv}$%T'ɧq|0v'nc=Ӧ.'V-k& B6mxx.WNs?_|;wfĉ;\r.K >~%&6w}yxjLŗ_fǟp=o3}ƌZdl 'OVF37ѨQC}V~E2;O@5G*oܸ5373虁{t ޟq}Z_ ֛oЯo*Kۖ!Æo"SU:]Ȥþa湜\D.^kKxGVV&'ԚP0xXqHٳ(7R*% opmϞַ/y[rׯg6l8mKll,PB^tnNmwԋϡUV̜1\w]wC֭Ylͣ{nӺukzA~^.(Evf^x%OO^{UywYh.K.CkM˖-VWnk /n F+n!ҦI{޹ZV?4ɓCÆ i޼#~ 6^6~-(_Dnޣ̛;Ae_z<^`fΜIjj*n_z{VZ70iG 2>3p > i(nu͛7~:ur3fdȑY5jЭ[W:>P+vb)[4"==}/ޕ5QG񯧞k;N$* 㐕Eʹ*ĴixG_.rӲon qsm=&ֈDU&@ـ e;֥C/遤K&RcO;,u]r>Y͟7'h$B8"6&<\,5kt+6'  ذݻϟfm}H8L$7Фq#6l? &6R[O?Lʍ7ğsҳa̟;p(D0XHvV&ٙE!/2mڜ̀Ge{+I}1cIV^~ 0ILLd,^+zm=|*֭YM~^P-^*Ϙ1cnӆ'|<>}: 9Qτ Yp!̚qǵ_O=]Z_/w|7f섉 :O'O![4_\\vCK?4h:ǩNQx멧(((~`ƍ<3tS?[nСØ=g@?gasM=᯿Qw8\˙'~} CЃRXPPTV0O? /eG#;yxAO?'NY1'?p{߾7ƎAU*!uȰZLPsـ pȑ$'`P(L||"e|pq0@$"l{. !Zn4!'3᳷?]l;Ź /F;nsAN4?X.P.f͛s-~ 6\^f5璗ˢsY/ڜ|2vxb|TKL袳]+/@ 8Jիǜ*>KZw7p=ʸtp>w)S[>}sYx]yvőagp$˯wkpEe?cC}:V3B;GH-Y_XQhp|ŋ޽;x,_~6kK^N:D>4tiFX`A͛?>zWVzz,Y˖!N%VZ}a+V U+?O.]R+nؐs{n޼y4lh BY 2Yj9NJnN2IK^ҿ*WK_53nq?Ǎ3a"G78J*R^V5))~3fAL H$Gl 3fCJJ2az;b<Ǟx?Fb VX;#G2y8HxkDYf Vf޼{s+}ȳkw[4>s;+;+s3? 7geB sC(;_r >bՊD"֭YM8ݺU\r|]q9~a511O1c&1h$X"&6Nff&GU݄8xGS,Y{O>elެ\vFFcŊɧ1G]pd~ ^z֮-WvfF+/Rd[)}]ncV`5[V bkeٖl, lcO}ö: X>щ:V%Y~j)j,]c NuWn4dp F><,M}zVZmޛ݇3fMڇƍ ҥtnb4e,[c IDAT\s k& ÆYlժԭ+$>!5k`SF=wئM;JS v.Pܜқ{,k> 5&7'eRRkl\)*cCiw?&zu].Xj׭.36R^}V._Z:FZ-SS,VxzIRk$CiM4!7'ͥ8%QVm ^|WkM!j㏉Fܜu4iޒK.nm4jzl8bڟ`),ۦN훠\okT񲼐Qoq[yQ/EF+&jk]Ǹ;^ ܨ9*h&mfxMRj7F9|GVR+df/|5"33x3<8⛖r+ڿ h?-_~ jEEvh4sBlk^a3fзOn/n >Sۧ7C '##=^5۶MIJJ~B!mbccgr88( ō7Hޖ-dbӖ村X~= q~rw>7y ͪ Vl䈷v5}סR χ?) v{BTUhRbtI|ŗ~\ץ0?tUKه6 !đK>B/B!RB!0T B!#!U!Br$ !BCT!Bqȑ*B!9RB!!GBB!8HHB! B!#!U!Br$ !Bq/Fv_V^M~~>Y* ^=ĄDׯw"b7HHUҪիcϳQJab?P 1_Xz5Gկ$lHݰa# *JHH . ?? ;Z`Қv>aخ]!uÆxЬy VE)33X̬T;ص硴&339/7n$U!~H݃n`B8ξ8dٶэaepqnH c{_ vUȡR@~~\P`Eokc F dP_%Ƕ Qu#Ŏ{&?!(U%UҎ*$!GBA0Tu UtGԨún"tR;ϯR-9;-;g$NNZgnaYlZr*"ߔ)7SO\-춏ΣVa¬u,\ _x9lVbzw>hRͫWw}hcӲIΉBLBj)C_bzoNf9]<,ͫZGVf8xzGY3F:E"uo(7R_թwOlrJ1T</_fH2?s Nbۙ+ZzǡY̌IWWQ &A|j7.#}t*}}/@Bv}| ց^nsͽ4m|G kwAP]ԇdSЋB#T ?b~ 8ysf~7K NK 싉>䏙7$E|6_C36GZSAKxb<7 ɯ/]Lx5 a32IP ! /4piX=?chץ7Xrə?)͚sʥwK/xz[2v^6kC;_᳿Knp5!kx߮m׃NUN=fMgSӰv?wc0W._|هty]t_'L֜7 cMd-W2lpK귆lƻhq6*x>/A_xys K{r-]쵫YXXSmh&OY*ZCt7Cx$kjz,7#0^^=⋟/[Sh4^\o3/Y5_e/r'y8ig0,! _"?gY836>/;ƒ /̳k9,g?Ӄ n֗y|07ocM|7V,y]746cw|)7=G-s_Zů}?f7tt ?uq 'Wn3WUWw g<,`Ï삮a-ܲ9͏-ytd܊n%(ܜuIY운9uhebzwfڬψ~sI R| woIY2g"5ΨCRĤޗT\?>L,4:>ڟ%kM[.URŕw7̈-yy4JPV"M; wm}gŊdjXCaN)CNH(yo+t/n]g={;ԾC%L^S~[>\,k.hw ʜQ safmG=#^_cZ-`w/)UaC0-Lά~QsQÀL&ءKf2A^<,>]_P$ՌSq{SIJ:J30cSO((mv9]NU89{3ѳS+IÕiPT︆rU~l M2v//u6sZu=dΘ͸hR*j6@%F934nT*]{/w@t%6@mO,DX>삍^T$QJ툊Xĭ5qԚd՞[UC.\i\K+Saͧs`U?ڿwN?[A}qnma%3V-R1E?KokYOí]|O#/0#N-STLH,._Z]%z[GQZ|jQ=.psW2Cް%oX/L&8a5;a:uK>ֶuT[ w (h v μ)tw͍cmü{Qb8vCɜGέDM_{5?S@d=ߎ?|Sh Et(ޚ.U[gwq+Y:<:Ϯ54/ݱ >WӯѽdEԷb6aL > wk%B#T@jf6zT o7S3s>aJ~0Ɋ|uy n$iUX>t~%R=nksP=6e}H1ߜK1%t`=XfmxO'=~:ldC?jvsZ  ⪞ӈx3=Iۃ-Q:{OA$av{e~.W+x7?j$msn__MBt[3oYZ P05z ¨y>=EOg@:U]ztw/vg4s pٲf#yۭP'2Mլs:ںJm7ġtP8eICNJr i^7)oܛӟdUv|m֜v˫H+N^Oey؜ZZe>HI TR QֺCzMd⫷paNz^߅vub.=!A!!S[qOܣv]l5:Zi}@FlXʉfFu-Td#ǖJIk?6.Nif5D )?-5kpuXq۷ >͢.b2>fu-hNzd6k]VpaUw'-R:PڑPNz6kqBeZ'v;Sd"mL_tFnMdƣ~Hf\S}Zih奵灗>õ<..iӀTCΚLGSS^^YKFjn cjǡT;Z˟66z!WCVGQU:/zw~n=g6>aK|v\a^zgZq:L2?wi fVxyf7ԻIq 3Y:[OX_MIHLN3G>P1~ Lx#ڿ҃&q 㩌]:P1u,,Y Mas\\}$$&RN8oiAR- >&^'+WI4؋G;b@0熁)|ʅe>!V0*W  w3Y$ >̛iQk`>Ƌo.'%q Y4U Gq|98|;C2-U5A=]H>h&N`I|z3POۅ߱4M+X$ UĮq2`c3qJ%ZcF#eǒTDf7nMT mB8K:/gް)bQe_:ud6N['Tabht֙dKZ\'dɩZ_re{x|Ni| p{jFjj+`%n "'yKڊo}/Hߖ˞M[Z\Xzޤkzv7@mmvQ>`@op1䄋dx^h= kڔ ^A]`?Ⱨ8nQy^Fx<7c2`lr=wz<ݮцKZOgܴ5 `X~*y״W^MK(3V*z&!é9"eWzd/1`\B9kX0-GY_KORr 1Bϯ(_k7qp˟1+Dn]8Mnc^/';8Yd$5Գn14: 7EZ lM+S(.pЋԭݒϻ.To=5o/ŵ=?o]SnSө(sYHlI^pK97o<~I?~_Dӳ.Gaԓq}F}pʮƮI1^'^4í7CPfxE2xXYDó:s :i.cݯh|\e4(o?/גp 5w5/|7vZKv=x]Zt-:Wnt+)SÌՖoՏWTM<ɷ@ZmtQ=uJ+>2T V-.zg.zWef9A}+~>O yOr-??N|si~j0}#|wӼuz l y9 jxڦ}`Wǻƹ>MΐdVOS.c Hcy瑋;νnnQ-U4W͓sVV8mZ?b\pK8]n7{c??͖zt5(:7!DEoJ_׵::U:XͧVZYF,[%*v>X>>h8c㴎u$htUI_ZʤK||5qʏ՜3wm۵Ém{%?_1?/=*3Ay| DMp4^?9|ɳV95ƌy}>~Wou5˶I['(F,/dxxynT`b/vV^ԋzQGQNJUs*sU2\ѭۮUR{-Cj1g}BǏ?U/lH<H'7K !20KcB!BBB!8HHB! B!#!U!s8N*!U!Br$ !BCT!Bqȑ*B!9RB!8SRB!!GBBÃd؂à Peثi\B;ZNi9x{>oWf'4$gc8fv7ds HR(JꪻTwEQhUK[UGVgݷ[G+nIIDݝA"4k^>33ygˇ޸6^>d-2ӾAgHzuow).5C@>XBb:O|G38DGGѥQm S=Gs)*rqNc; Љ9< Ii%ݧ#%94x[o<}h|aۍkwSmL;*Kr"GT2JYvA=$.9U IDATKóZ73o~;C/q9ez_ԥ|;U> = Z'bvXn5\A e۸t%+3 ?fUIhVٶv#9c7)EfÝ+uJP ozbxPŌ_ qxA*(\W˹@<+_h;$b!BojzYV0^{QzuU Ʉ1e1Y hD@cj쀃'jҵtA|ё%@Š8h[gGHS~WIl8aSˇIn%_[?|{tnFԢ[ш=kQˇeZD9!;[5SWA4kK MuЮsNjGTUU13&;}Ğ\ư x'VfcuD \~{5N4r+?85 ֧Néc֛d᝖C68?\Β1}Ժ!˪Ek߫EӤ́iⴅfƼ|oRքYjQGYwsJ_-mҲj1zPVw\J2Mpn{q(wp C -5Ke>?~+YrAyL$Y@k6CW/sla',3;3| 4tbN>,Wc20Uj!5J9ւ2Yx=/x\#6{91UNe\=ns0l;ڍիVೊɘ+Z,_?k?TͦKퟛ Jr(qjZu2qfv͇#pkBfi7?Mcʉ::"8ܗeۙ+\8c[[X^#k#,3b.^Q9ѯs$C`M>?ƩA8e+%j >m?iީpџMz4d'YԁaQw aoJH? RS8n3|֬D /Mf\7f7y#yy3]OcHTe{գ eQE1P -d8l*WZ[YqTKҼ[!~]7Z/q+"%+YR_ 8~ /bA}噌yՖ4(G#NпX4} B3bL t`ܑ ,Ԛ.: ;7xgG]e=]&łyq ˮAAtiS։;)okf1cF]u#V5=(*n; @1`2-ɎSn 󶤫0zEa,NŚ&/ZGf]ħ88 'Ajj;_xkΏϔu88bH*pS,]GW݋/`/b@I:q=%ث}eai#fBBz!HPxezh;:3.{noC`BXtl]KY{c,x 'W]fY>Sݤ` [A:;R(w{(*3k2OZҸLJY.ya0: b\qV lGY!?&,oR:.j樒:H5c!#9/1Qeh}~zOG%cifdwtuaobߍl7Nsu<$'P‚mۘ, ݍ fbZZҾ]ŽxW;A=dzD%XIŃ8b4NV+{2wo\r+q׳f5 mhBDTqFÉu? iT~;[~h)G˭pcL`Ҧsj:I22zA Y(Ӣ,ۇW hY#G:u!u77&gև\u$S&;]')Rqʜ/W됝AY,x WO'cqaA]O@U\pw􀳒YE|#ulq$fɁ_f'TtB`ӷ[V4H{F9?&Nf߻(EAj#6bV%c) ~Fw#{MOn$T"_ZNC/V$~*9s9Kʓd&o{[uWL=\fWͯҿ/Yg$y[\ځ>>x.mZα Pٙd1ŋR VǾ,OcֽIY uh1b3BOGq :O"] :3;RǔTy8eyg׮xâd)Mor.: uT{`BpڟL^|/keYȝ`#r\> ,NEH#/;zb[oO)"0 ׭< ~݆p2n I}SآXnIJ.6n]g( |;- *B'HEnnCw'h[>e|Qu2so$sӸyg/b❟^O!xL?jj2/8]͚_+Ӽf^hSvUjڙv>}pw9GJR$+oV )͑$^N%':e6ωlօx\Z*]f8s:̘FA-5nj/,ɍh61ƍ_i[%!f8g6O,(z,vbApvG޸_ӻR$ϠMr[Kqu}/,2xk$D-xʕ}3in>&foUŚ8z*s*}0`dl+4Mv,_/ӝ?̹e]e錿LJtF!XŅ74#wc:{f/#_:ruƫ[]Kb|jыa6H<ͬa콑p-[aX8"YK`O)mz6Fp!eoN=::Fe\w+cy]*1pVQ3ʮ֫Q{Q߂IS*ԓf-l$ k;`8ɍT%; `\XΙ; tiSoDD ,IAZמd̨WqUbl<~Ψl$_" #.7?ޘleh߷"*"g')iD1fp~tmzQՉ92ТD&. lifڴsNg4O'OҲ8^fEu"kd3+wf?6ރUWvǂ#kدmcƯT-2~tR b"syۮbS 8:♳H@78'2ഈ q$U³e31D jf90f̥K!x?$$?y%4{7>\JTfBSrOPBoB)9&g\``t2cM&s/bp+/n&IaI<ۉt nu8&dᒹ<1Ij<*zQvL 1s#`A؛tޓ]j9ksgjorNBq.ؐ.@VsXO! {AUޙkb*(7ll.4OVh4ARR]L517u/Y3QC~2BBgcfuOi$\h=m)zkO(?Hd87Lbb670}MjjBے=,ES!ңMVj󤊻fmjWgv`d/>wۢ/䇟˓Ǟ8͵X#NsRq͆_,[wqr(*x`1kzB T1;.gmGЌ3$Nd+H3Xnwut!gH.Ǥ;~[/۵?S$!>kȗ/o~2a7P?W?_8{d"~Y ;Ǻhm6c،qP(ёobhfO]fԾ (4#)S=~=[?84XڟlAzϒ3q8 ߬ǒhM :[ΈQ|ӦfM -[c[T~kc1w?Vͣ,>LA pL+{t o& p@)f/נzq$o)ɵ6iۡ;OCi2!evҲ_ eu=y$o^/n?IERu+I3)ʙUT"4׬O~f63j jtI>&r4_iP=" Y9 0**9*,sH#b0=wJkçک4k!ӛT,LfF] r¶$xu!PU5b Y 8dX]OY/1굂(}Q.&n&`68%U`4ؓ FU1&n0&dUYU64'IwQQ]UnpP= ,?N ݞImFi^hުg)`Jc8!ּgS};ô,ޚuyЭZl0만gm516Ŝ`i̙?.*V[D;)+lxf uГĔRqqCTE(_ld0QbŮEu=I%QZݪ2iZMKcQѬUfp1`v=%NV=9v2 E(mBI݇H$xr;>>?GՈx+7 yO=eFBЌ#߿B2gLw+s~)t)nCM_t_8BW̚Y +h$܈"sN\(XsMNBǡiZ~{۱߳ذ۟c_"fC9QϗmGp`HOjmIνd~>(z'Ư !3^!xiYj2[ɧ"gnwDZyahXVM3/"p|s+'-B!"Ñ U!Bd8g a^z{\U|UAo B!^mI#F&hN T }\*H8|cWq/ |B!x5I1~QׅbHH!vc2ƽ\ [(Hze(R%~x+O2w !/C!AXԿ ] 傣7߂Tn?wCԈ"Rr$ve-]nɢ(?u =A=P|~+wSpd0}Ƀֱ=5fį\z=z]Ÿu#jo6ö3O=ް((YJ۵NE~՞9,X<|%;`'W#EK}YDi`q( E1x}{Jy(xπg00.Fv| IDATow?<!B$HnZ5lՊ.WMS;:܎=:؇S{k[U/!G3ts$WShI'FNs"۲ua,^=V''8ŬY?3Q{K|Ͷ hr3=@qctVcΙ5 ᱝX0Q:7.w7: 3hi\] ˄ F"gbK)&reL[/r! q2\P Wb5 V9BrF7r8z2guNA59OsrɌ5іҒj[t'%ul'%.5㘼5K$ACXo?EG3{/dih҃aoҹ{OzwM~x]8͝9*F Ź`CbY)ET/zd_qJ>b8\yPr.W=x-+j L_z,⚯<DţDG:Ɋ=mwRg`vcSR&X(h Dߞ.$*1wo82$ņ V~!#AL4v}7k;$Z;Ɩ3bg򴩱a $ACĖV-qXFOUv(O$SPJ^¿% O@yi< Qgfw =;]Wqẗ́&Z/+8 t-d?ZtYuәv8;M(CAWsKOfҺƑ|MFX 2KZbh@6~,'o¹&Z5~ !# RAŵ,>*ӈt݀fv4&0dz%sɬW+A[QVfWhDb:XS lz J~_ jIq0 NIFU1 $QqU F{ɨLI5t6DjvVU `]TTWլTO{5`mQhڣujDYJ82X3e қlWoau}[3ѰolbY?e<3oT48qݟg1XӾ4?9Թ*ogIraV=pz6xe%ޭnG44]G4t]Oy}O]G5}t!j`ɢE/W6e2 xyb"rݞ]( -nUnQ4-Ѧ%1ɨhVͪYmj38Znpt`Ӓ vhӜO;u }TTǞUZR?Ju+JHv||*#V}ٱ 7 Y(Ӷ&obvfVU]B%R_g"!A fͬn4nD9?^.F\9ŦZCţx+cưv* !? ̅rd.N?¶#)rdu``@Ojي\I5ka5Ea$^ !OT!xYj2[ɧ"gnwDZܻbgvn&۬#9Uja!BH*B!2 RB!D#Av|(wߒuT~=Mgk}دK:m))!⅓ 5M)1qv;ք[|8MzT3 !BAQUTUh!SBT=+&dz8p;!jDb)Bg 9֪ԧEAΓ8AY&U+Η'lNXGlI.aw)iQPb̶+D]˰EPb'vw{aۙܧoX,iZnգ%Nf@PsV-E߳=$rb|'z.8ǔv5(_<5p?ӿ~a< T8 BW饘 ք*7lYի&ߩYn ég WlEedl+4Mv,_/SzDst4Η.캍<.~؍-"_Y}q=cla&7>$ߟ[7i~̄+̸8c۶mcݷUj;ͬa콑p-[aX8"2eSR' vg~Q+ !3Ԍ4>Rx5"5lW`J .9UTg+jQ iY/:5OBniUR z|my+#sv7BܰDD ,IAZמdVsd6* @1xgr#WVȚV5%;Y܌) );vb.]¯i]s>YXcd.OLvrA&ǻAbt!!6I5[ӧGoz|PL"ҸgOeE KoRW3;SVJT< *%'p~b6]^& Ňs~[EBs1 gOs=2ŀFbϴ(C73F6nl=?pߕe:|587} lñ/(\&+FfaJizgWM JR4zRUNm! x?#"R>j=ǴE"~Z4GW&]1(xj:!+e۾Ǯ雸l8N-C\f BиHr)tRcbsJtWX7kzLJTh+t̡+ 1{p.9ݞc2 M8nx=o9>]o)ؒq[Z;]LBdP*WE{Su7޼UIx"]ʓNqHsLJ s^ Q7zI~\Gvw/,(*!BdHBI]ӮɜBػOӓfw?ZM#y).R H5vM_dg1 WɫOBT!xm3$n\^:60aLȃ )^l6e$FPȑ\XڗnǺ1|9'̒s/A" U!^!ziɎv@G3QDQT_Te>mUi_θ1c6ОmϺNX SGƤ !+DRzͻo(7R EKKI?LyN{Tѕ5]SY7~; xeHKB!p$HB!B!"Ñ ~z ;>B1'I|eB!xEI*B!2 RAFL[7~5s(T뿈Q֓9|< :ܞeZV&vi슸;¦PCX}Z5'N i`q( E1xܙzO&tF>×5,;B!xiIFw:,;-vN~lޛ\__1dغ);/@=v#{Lɧ9=++3=ieXʈWlL'!xmZB4{aД[#XĂ҉qw<[$\<&E`XPEQxa<)JBI^حM]Q%:WLoy @ײlTPsP] y)aD1Ft,tgc7?ޘleh߷"JW0D\8Q$a%[]O)#D _(>bcѵ[*BXfi?BΌ{rIrDŽrc V!&]$Ga޴\'ZU3r"UXxA>lOf3>Ts 4X :$s.VnM2Fe#3<2B%k -2u0v"[f$8KaKa>TxxI {/V3m#zEXZyoIƾYԽK9wA/ѓ*%o{㩣\rDkE:EIq9_A^"jj;7d.ShK#6ͷweqM;1 ϝ.,Q/ 5}%w7{tQAxOxnHᙑ[~޾ "?c) 8ǥ~4̜rc. Y 3\e}~n_vMhX߭NxOsAvc?? lDŖK$k`GoiQ5JӡsgRMYCi!!Ix\;akXԷ% 61X$9S?E~&7jjVMH}8<0!pB[zQ 33+UQqL\EsGvXwu?W0ؽs7ȸtj6 `܃{l{oɧ"{йu[&G&joI 7*ǾbPٍ {*'RTȝSGI¾F&?G{>}񶽄s oƭ>"LǗ;?l}YZf'RAD1(;~nB֯`POְl(O;H ;+!ϖsl>r_'mʀb<ǼFK) mՔof(Y::TGtĀ{8pnNiM蹼ֹ2 cKE1LΈ4qM;GȖ=lY IXYNx/w]8^g*LW guGmgEkY¦e~ qdUV-I/Vqni+OIW02~HxsI* ^2vhAe}13KQݏ]"{[D)6p:P<ǦRh5ZY!K{w0Fwc3/GIS*#OZŮkz`|>#tHkO026RXi%d+WH鄇O3yz]BNOK#qj"iÐJfQefjb.CZhz+7DMʸي?Q){7EbζЪsVvzwD!AD\+gŭTӋeX P KEjSx{t:?ï]w*$Хd$[XG,eGlTp#d?oGL̽W-v88XV* AYwXz_=_^%c_glBY5c&{0/;a-Oqfo,)Ͽ͠9?=Ӷs0V.J6ޅQS _? GX4+WJUK|l)C9gW*8\pw|X> vͻ3|/WE΍_<םFSf2W,gtMuSmg/(G[zu|$H:7fG. Rc8Mֹ|Om`@U 'd JRz)}ArreR[O7|1y'߼?;GLR{9wXdjg`|O FDv EH++=dbMe(?j2VKu ג*a2!MUѓx ÓPhۅAcP.!;El*j*GI1u] t+!J =A+Tt~,O+yKfaԨ0՛nCC-! o3fzfЬQ&Ҽ\=w{YdrL~^XI&?Dp9ǹp5QϵIAA#dJƦQ$+aּ guc6Tuwq:9󰋦4ͦn =o,ɸ7wɼ{_;B݀HT@/\KYsO~,s{/e%>gD-f˧4tx,YRάnNhdo΂'g4QDFm\DxY$Wn/~)h1D#H҆6:ҾRF)p$-K'!yp2Xz'x77+ ٩&ƯL9/⻊oC23U*OIz|9TV1ueGW֖|?w̞qI:Lu<}4gTH\*}SRf*Kצ5K贶TnK#\5^s۞ټ5rg̨GNjZ>.o, mb.!xo|[EQ՜|"VC,!If eV4Z)Sl%֤iUN:*hVlaDTV4frIT5ji>nb27R.](=TxtN~UW?$dE0js|ޭ &2Lغsf¡kmYӹ Z@Ew|1K<%LJ_hJx pb ru&Iv?@M:!t?֎Doٱm+6d2* * п/{te ֭aE.FKZ/x*5e*w 5IAI1{Z4E07*JA1(d255E5iLFd4LS2٠VPcPΣ_JxhVq6x^{D"W\& P냖qrUYf?- jr\i=[.KGCYx$ fwy1E ņk87-pk33K1} !&1>ĮLzz b΄ܧAҐeH2THyiPȲzi4hzih^Pֿ`)IKӏٴh u͏uU_e k Ж |6vkKQѩU3 7޹˫o_ Dds[xMLh$[͍^u"1򐽜TKzW\Д .t]琧 w6UM&rAAbG  BS◗M1χ:!~,U۝j(}vMA߫/~K$ ]6s18GF?dXfui˴$<A1ăSy#Xܳ1[e[:\M^wSDb2:4iW%-'*z:xѤXAICIđ֥p(WOIP^Brm͸ ᤪ*Cث IۑA=&aV@լ:n[psb|j(I¤H?Wa~m/\ÛqOqi{vй+u-zM茬d 5;yB6#_ꙒvŞYi.!I4:145͟Mg$kkk 4  f"HCJFLb!!V2GcUΘz@..~0 @EՕͤu+RCe { L\aeGVl\WnnL=+mDub= 3woY>DcYAS/ҳ16h=;vϡy*wuR;>ٖ (skt˹?=6^EIMLmQ!b/R2Da2?;e0֍7ӫ Pfh6(F]lQxzJ+![n@j?:; H'd[LcLʁشO0 QxM%&TTC^5 zV2IN|2I`Jzq+YRW v?Lf1)*zxxmz1Wb *`%y \/)~Xs))mh-_qȩ#+=vXz'x77+ ٩&ƯL9/⻊oC23=vfeكWOgˡΎ?bp5 S3MiM.{YYqoܟBIֈ{񣶃$9Rob$+?)FG`S?&vBE DW/#|jPLUw4}i_֖|i~+i̻X7=ya?jɀի+š3PS- GI<]9gY9N2Xh,3jLd+i&NjtNUYF3Ve #Fȶd1Kj$gUKuT8;]vEQ _{署A !+yU羟ǝÔS@ng&rl9w3@MЇ5\-[;%\ߒW&bSAT4u11puyG;1#ꓺ3 }QJ|^B֮׋dBUUN:]s,kذn />4 ]zɤěT)SdI J ")JQmVR A1%17)Icf2&)̨d2Ltu\YBOjS \& P냖qrUYf?-҈tkїZΑ(v-H'()6 xnmuf)f$BjNuiD{v wgM> ~"HAxXg=@iQVYR߁c,Bѕj6"DɉqRA^"ck9-p&4-FR/:Qy^N|T롽hPA^ſ'U7̉   KIu6GҔ{,cTiP ޞ@:!s`*JX 9볛>[XHeot-~ 9MR;7*Rl٬WQl]~T D_zB ʕ , IDAT#Pl){7 /*P#M?1&s lځ'z d Tk71HEt'Qei&*^=ɽhUη %V:C_5//jdjUP ۏh-$,v-bD!BעW#0%i9ܗtAFBҖRC_ĉw1jlCTA1h.6Ȓ 3#\:)I$ʖ.oGTDs+Ո*iv(,FI٣'yjnrb>_KuҼYf$5jTA o`Ajߙӿ>v:2'1 $qtޗ9-AɆͧә@L7:=vXV흉نg{&^O:onЅW4SM:_͙d5[?Su$jQ zCg (FG`S?&vBE YW/#|jPLUw4}i_֖|i~+igChuEZ9JaG}YX'zQ &CDi f~-]dF!{9Fu8ϴL{tՍOWtEkLn~k&#q?tz=ݿ.AVmNc@IvVh͝y=0+m@ba^gg^ Yk9 U]7TI zbM==HvٿFbC G%j0'[P9׮&f}Eቈ U%Fc _XjaT+179O* DK3CwMio`ץXJ `Wi&R'.9 IAxȎ V[缷™\ HԛIDfO^\6+"i k^:~^Mdpy1I E% ϖ)s'.`PAsR΢gD"A lDmI288d5|6̥Sy Pt"HytpgK5}rG8vv' 4N / mYMƹDSkwbG_Oyž^;x豂Km`/ƔRD<%[jbAA' %`[!d0δ\̺ moO]\ AS83 SzuUݺL5}vd J&$!U77(^W~u>ڎQKș0Vt'v-gLH3-Ʈ#<)cAh*!9WP2<)U?XI@tms_>=%wy6h|:jT1qd[KHuz'Q>T3~4tڝ|_V!wk kxͦ+$s~+$IxͲwrV1ݏ%kx3n)0]cS<}|̲H_# g7$Q6ǎ}?#9hʃXM̴7YjauVH [Xo/%k=i2` A1 )qȹ?sVl`ռ6O~DŽJjDL;Ү( { 72*dʖ$'n̼P;+"o (wwȠIeG\&.]fajmլ^L?ӣrp2o6,E0:S9`߄O>+U! <И彳5ʟ}GTR9d4i7WLJ&xp=+mDub= c3 6suEeA8ׯ'N >YmY5t[zSu. ~p96:ITc*VZ*K,-)܋ cFc BD7 _rK {tCT/,!;P6Bɕ,/?Q^V#aRDgGN0 v:4iL~*aP5ȭ]@Y9tʐܻt `P AJRX l2Nj: ٺ"- \JIg|;Wob3T.g,Ih-_̕IdŦLeleȌftl(]%j`LQOK#qj"iÐJ{" ޟ.Z,*, IǞAvaT/ilQ0;~*G;זqmٗ׶PH:.}lQx% D_zB ʕ: ϙqϐOD) qyχF&S=*F#ȹzJ9`5:ҍJ:qדYGݺƭ9ےtq̕hR;ps>YXPұ4H:,3)N%sG۱ߦE2F&R]׺9͛gZE&)P36b'mpUÈyr5+Fe+ǘ*Z0SQ,Ml›3PL)D_wţENd戇}GDM=ϚWZ[m6r2~=mBP6*SOCuiBXz6F.oj6Qx ZJ㨅aILY{5+SH<6i+F#0oZ.hUl/>zb>H}46q1y9^:UKΔ+eQxɖ.oGTD<ظ`v*鷣YO} Dk$η| ?dlʖ$V%4kweЖf1FJ/#cٶ mgMҏ};2z-kTc/{{9x/6Ɔ wuMW@y[*xxTG\\{1x Gi͉%D8Ȳ5_2YVg$ܚe$jqGbwg柏K} Ȗ3 n-]:$Lg)t.!IutsIBj{0!#A#i)!IO( *^]# Pt"HKvv};uaH3*r su ;?8}  MQQ \p{]]of+y#̟भAU?ww^|{ejg`|O FDv B_9y%-%Ka D9FD|:&Uցv%i$$x'.+)UP )g܍6]+10pLX<p#<Ǐsq¢A rD~ }kS;h՗IYC繕jDX;NFχvGOc <0ł:ui, 35zmhZ7$samƌ^5+n+@1F]:~(YǏ;:֍ܷ-h"r\A(:>BƱT,b`fבY7:s`Çf]B²VmL6h<3i5*%2yTJFyEω?w:FEȑT9YtU2§4XUxMIkЗUim̗G>:#iJ=NK KBIOXo yKG'tHUYϧ+rl5$ϲHrz dXfjeI՘25ZVhMzVd3fzla%FKNme Nc&HjIU#;~W5'-S~H.](=TP|dry~+:ݞ(J_ WȊ`kq0%;Щ[=eě#ʱu 5CۦsVJ>ob[bTػ<Vs?/~hzb87&~z6*'o}kٰv5^^M&r"CdYÆuhؠ~hptraI7]SrWPAENOS sLb0J&QcnPSTdTMFSQ4e, j %< ģ /ٱ5j^S8kɖzs#wHf.8gmNUU>ò r=  B#TAAA3^';Ï%AAj^+׎8z sSMX$<5C":#hyAAxY %"AAS83 SzuUݺL͵97 _D7q$Y3x*^W~u>ڎQKșPM>`NZΘ$gZ]GxRǂUBrn'ۯB֌SMJ20;my;AӁVp͠9ȏ#;PZBr;J˪5z 3xXKXۗūh6]_%į^Y$I³hC>}񶽄s oƭ>k,Lg)t.!IutsIBjݻ빺 Zy,IHM4g7r͏j;4Yrj@~WP'İ^ٓ&/zAAxXR)qȹ?sVl`ռ6O~DŽJjDL;Ү( { 72*dʖ$'̼P;+"o (wwȠIe'%0o tAٶa4Vz1hRNiwȼuس2KL@|>0RT3@cBjbΦǫHj*iMRIM!Զnl\k#0)cD 羷Yi։e0bOc]7 ÌFto9 \|1s~qlȈeG(ddYA1#|Xל͌ܖ7Q{+NK,-)܋ cF<  Z _rK {tCT/,!;P6Bɕ,/?Q^V#aRDgGN0 v:4iL~*aP5ȭ]@VHƾ&;2,* @%),cEIl]CQj.@嫷I1]y*B$Z^$2bS2n2dFm:|6ƮȒRz0qBƨ槥5KjxaH'QW/#|jPLUw4}i_֖|i~+i*`Nx$a&= $)`+b\(i9t(אּ:I TN+c/F!aJM?C ݫJjvf$IxuKq ŏ>BB)TU1A;fV\a\GZUI'z[쑩ݺƭ9ےtq̕hR;Fps>YXPұ4H:,3)N%sG۱ (W#n"5֫əƐ5dC4&%gs͆4ukZ/ bo }GQmlI! *v(vQA`X9bEDT`{QlT&@Bz3 B*!bw< >';O㶻a=iigÒM|x_VD("'[`ٺ> 1ܱ4oɒ2_BnapN||o]3^LgDCG[60xxͧO`I>arY.|tn%m>ʥ i,EN>.ce/017}FB*"5>BrR; )x@$sذ>1ew?AԪuuqTMBm~Mv&v5jN8u6|txIٰ.bZ6 {bʌA+/!~ZN7Fİv@ꆝB/s ߳/ma4jך;NsҠ^v{+_;wfF3>0-R~oOw%aߏ$f[zoa[j elnx>Þ9aOGʚUgqcy_߽>?äePPLeZqՙϯٱŢO@ߖbBmuw}֧3QD\^QEoa+/2dy-܄Ψ9Sxn^61sd/މgGǿ% {Y볰];G]֎{Q#m<У)N cN2 Z^='@!j jnv7ct`؅z⌿^N+/nfl P+_UO+w-^5G2m\ƅiԿ |O侶E*`uyrD_:;GD RTŎW1I_\]y-"' ]=35F:[s֙.t9MtN#p8}.p.MxݹNk IDAT304XAjbFmF; ;vyX>_ifޯ,ev0v~*u?ٖJ?[+ CpUW#&reVz;YiKsW]ѐY8g_F7`x_m 79hopWv7{ W$>K]»>dg+^H )=rm]tit=Kp83butg%lc/g-tpbfgYVNgӰf7<7uÎ_?62R}>ΧGDʥWT7/7= Cgc1q`BUWR<3}?77rNe60gXzDѓ!"rLAH|cVu"r۷KtL*` "rhLFDة'9.aQ 0l;<ռ_' 4 8Lx91Rhu*' 5Wo|f"MDDDD*B!e8. KebڡQ^6.eTzP~Lڞ_͹irCb(F\PcXY,ZpJ5]\ұ׶ '> ƺ\2 8!W5 !i}x1hԴ.ΊI,Խ9kshWT2`\mC%ۙ%{kl6A|IC:nYX ͨe;6ex\>o>Ihجwm-VZAMR/32chʈ6cvN4%"LA ziEDD䤥ځ-VNbgP=䟣[a-N5ә!"c!ёtf,Xf}d8[8K.ko}n:5 ĥl[)>V?-"o06tm4ߡg83y9Ji[I#ga[G֢nɭXhݲ!5 X6#d˴>M}8O`'շ'l;x]h~^qSQv=/._&sՇ<<51u9 I-7ҥm埒}ټo]#-"q~Z3,\׽tѩ\d`ۻ]0o9m[fAftN&X\6ԋ*"űܺ_??e'#p2W# 48dCU.طlκ +c\3,'`Y]ZŇD'4` z9y(4-_WclU=LS3>oaF~XX|')sW3en1s Ɣ"7#$Etx: ėna> 'LJj3sLԊ&XЄ8! 26RDjT 2j8:CDy713X[kGKʆG̜f4{ص+ B97B"R6TO Ʊ3?g:ڏ_b-y^<ލy} ІPwCrY楜y90TpQH'czcc6 K)7D}!9SxnC>f7<7uã8t!\"BE[o"RN tD$3U]BL{|)Ph#s9E؃œaM1z}GO*ZXH1W."5.A%""""~G!UDDDDNc{EDj7M 9'UDDDDBT; """"w>)c%aɩBDD߇Tԅo?ٙm^aS٠*"ՈBI$-1_qaj9wi{|=)10>n )+PoF{xeylxZ5֛<1c ցzٻc#Ad<>}%YFgq3әdgzrO93Xn]mZ֮]5kYfMmjV^a횵] :""RnVV,XfnomFB8Ƒg˴aٌ8[lz 珚ι_ 걟ډ<+u!/_q=/';nyϟ=%RB9 m۲l۲m >gaχҫzREDN*[<'GӹCxA4HZOKNʈv<\MֹCU.gM/H59Y1⊦#= ed٬nyό'0}7bʹqu/=`.b;]Ǩ;cN"eo>n^|>oU7ԓ*"rR1 ku+-qs%%.ᮛ@؁OI`@8!{1Lg xT : 4!ObYl`O밲v*9ݕK> j5l[gʊH! ""')3=5غeiv:l qqۚ.#ͽ- 8bLv`ۖx`琼u3y+VREDj;s_sv0%ґ8W_ m58Dz pu";ֲ> EȽ }IY.9U8/IDNF*""""~G""""4BE5m00l00lm+x ""&Vu "R/f~^%fDFTueRH.Ҫ.AD DVu)1""""5ȅ\Jͪ2) ))defTueRH#K,%  ؽ{wUQ&T?rٝ9U~8%"Grss9׉S""RNʦ~0 HepTE Uu)ROp8"՝Bp8"՝ED) vUWQ6 ׊SH#ɧ~?Z|I#ɧ*"G4/"O""~D""ԓ*"G4/"O!UDďh_D$EDED'UDDDRH*""Ճ7oF UYՠZg ᳝g[_..9;{-/vz}e"%PH +Zqn]=$$KboiB?cmҗ}[yҿe0Ɓg=umw%P+\.{7_z}:.b*vciRk茻Nq8jF]7/WIM*"Ryl۽[\~fl^.cN^?V"Qg7?oL"g[v`Oxi9^biޙ4 .c݌ve}m0IBZ(\%Kb1C BN?Ob6|ɤ Pj rlsaN;_Lya')9G7;cot?K?uH\Wo @n8ƌeŒx7tgvpIڼ~#!(܊AX^3Du>Pw.qjҠU,˗$qs9BH朳ΦC2?Aiz6g6!a`A8_^Nv0\:F 4\D͌{ce͂` |͖Vv5#Qf9k 2Խx4)@bh̸ p69;`5o5ɖgɝ^ʹz_:oaꣃYz&'j.5YWzthu#H^ᕕڌ=a{]-L &lL<БnEmۀeֱA<~*/$eO_e0m.sՆˮwjSҾ;/uX&Sԟ/d׷q+kX&3 |NuN 12j/8kpyxD \3 04V~n/ncۦ}3&A1Qncz-_<7߶fdv)v[/eӾ,AdD(>vh7FID;x\nMyYغ[~3xȍOݘ LlSVCÎ&35ܗ!3q9_}4}΢NӮcWy}*Z`ٷo#g-g]@"# 21HżqA 9}Iz5%_<ٛyiK.;=qyREDNV\md|-2`aL.mX0͍i6*'ps6xnuuS,JwR Lj3$'kx%3x3OY24ar8λ,Xv躜.~r^ =s5ԧn?i#.JmIxǻyq5AF>Zlf縡KԮO37a`cheZZW9\s7n.lQZqm|kgE(/5,DǯgM|ٵZ >@\(>0Zc5g2܎@GP4N/4 ӗr2]^tם4M3Ћp١&fhD8fðm;E{$aY>?`@9\{ ""%D.Ҫ.䒻)w?ț\HU*o;Ӈ?NciQ 9LӦ._ & ndmY{N, Z9sXx;9>^+ϗ J [kvbǭž>ۆQo:&UDD xe2p`s,r\8b*G!UDD GpU]F j%:}OT "__9iT;BЉS""""wREDDD(QH*""""~G!UDDDDN5oTu "RIj)Tsig&Vu UN""""wIHկN$$HM*""""~G!UDDDDBT; """"wREDDD(QH*"""RضBT; """"wREDDD(QH*""""~G!UDDDD ?X%H!5>^r٥U]~; """"wREDDD(jvU """r&ѪƟrJRSSHܝXեH5OTT ۴RDDRWXa:.EDN˗-cUnӺKj|HMMMO~U]Du3gTu""՚Z4/"A-""ǦƇTK IDAT? """"wREDDD(s_cmnӭ}?pS|lDDDDN iy|E/tkpK+g/!U%UR 38a{A?'m Br~DjT Ŭϭ-0=>a70۸~ޅ~>uXZ]`]  Rr7mݙw<]εt#xw1{UL4Krr=~,S6ÎЩYyTsf]w_l&zMϣ`y1&i~M w=yce/F- #""""'B$\psyP}&‡?\÷CBڜ^E;^?pZ蹈ne+ey0n<ڏe8Ha농lOv״)5DDDdZ 3,Iih"]˩a2Vڕf4U K6}}袋>Hu[ppH4t+݄};|zᩩKI""""rR\q0Nn(}?basy6ܺAGB/3}I(Fvs,17w- dӞ\A՛ʦ>B11nx>Þ9aOGʚzReܢ?4z0UgBWn2wH Rk[0}:鏾xmW ̫?~ ~|yamqa-/ z;'٘>˟?A(l6|Wqa&/{mzQEDD䤥9o:vыF3Bs̭[ ta ~ip'׏ؔA/Lg G""""ՐzREDDD(8 T; """"wj|HOD$cSCjTT ̝[eI?c j_uVZ/f qwbU#"\|B<1jݪK)Qq75>nӦKBjpT; """"wREDDD(+IIM!I*xiݦu_b%)Y OTT T""B!BR qDGW,TU+WWky?̪+˼|+1L]*|2V\U9RCZ*bzm[ǵݹue/˜/55>}ğtޝ/fΨ2DDjR+'RRRyEo,.]CLUeUC9 ;ϋeءu 9 \`l |qdfdb*j?׋3}Xe` >6mUKƟ\"а0vթS*ƣ,E/C.ylx7~oE֐a`ԿN#ys.ehb`-+W$?ۺcydR=bTW~RO۶ rrqn3i͡`0q8 l\}M x%Jm{ <8~v6ؾRH=oKy;HJsqBfW:z5<mq"B~[GfaĔk/?=v%OeevEO2yHۺ(X/};\Mh*X3׸Z'Ff&g =_YAN^$򯫞T< 7G^F*?kG.\8MbS6z{z>v+] w>y3] SappѼ' ҒH3b .abX60 jx`@&Y@r <>!PM lmL L?{6`꣐۷+ZޤE|Lcl⚰|37kQWÁj󃐝2WM.cxu+0bZc[6i|w}`CH~˕ŷIO̜uwKog4m3coz =?ពx0?=: ᙴ-kt> k#m<[s%yhv\/k~cuDSE,ڑYw"OЁqoʼn]KDDDʦTI,>MpP(GiMdD!a+׃9zC !4$H"#&*8]ؖ۷+ 6KǓ;7G@#2NDo`gnnA֑8pyj?F޸>[Gh]-0[=TvwMFp?I<6cדk};܀33w^pնJE{bJ'#* 3aNZ^ pw3l;4 szpFRJ^%ԆdID˲##$#c`䵸^7:9NƶڗE B=8m Nq7k`[5KxC6|]K-I`ǸǗ: ` fh]:v+ÃgX/}3ipa8N U&э9o/9>`& !Ӣ2O;uuRZ^0!v:[k.Zog/AF~,l, aTryػe+!qv f1_xr<*mLe$}&?Y% lǤخ<; $} z93cl`LX2g|Ȋd/m9쭋q{E8 0,ܔ4_ǒ-gУn AvYh;9}5OCq~zP۶q:_`-lO~ǀba_ rqh=HHk`{ (TOrr1ݜug <96$gMڮ:p?fY <M^|Yۘq@:2CM~OYkq~_#eL^{?{7!ж 8+rUms`F~y}?`=.;c_0 e';! b1&=x3+\m|)tY>=o3?srv1m\\b4y>YחɦoCvf@DD3# "7=m3 $<7q;Ķ sn$4<<վ1{ll{Kv{i=wxk?`M_o\ߙhf-.y#f5R|軕O^HaNjAnWNG":}O *Wlr{t+_LuFg} \[nI}DDhϮ? 4"}cy rp+i 'Q{;_Op&"?KZ/e`C_1jx.7}G9 #lw /w /6w-GC+qLIѩNqm6cSXgs}Gf |3>S\;43 =j8o-'3nzoozrtλn%""r(r:N4$9 5BЮ8l &NkzGEzQV]3X """JI9%cInp9Qdfc[6 n\.W8۷Ğoаi۶n9TLQPHrJI p p#\Ez&}>^?Yq[7o.qZUT鿵 j|Haq\2MGLl߷<_*@KDDRqjSqle˲Xl9~~tL ^8~!dg&^o'ğ965>=-E7yqYgLl 119To?&& BC*| ᗹs9{/LDGs$CDDUC*@vjlOvкM+V\3g;T'U->!ZnUեTk R!d׺M.ADDT; """"5MOE(QH*""""~G!UDDDDBH'MB!T; """"wREXd)|_DDDBHgW)gU orss}9zI*""""~G!UDDDDT:+""""ǓTqREDDD(QH!UM<~REDDD?ݷs9I]r٥U]HUC*+q]⃲f.fKTܓt _+2ޖT}Ly 3eurk=W7̉yb[Q޿]I O˨mĶR)+'NyjϠzpRM-g;.^e)fH,JK*"[iV$|Q(-nKoLTC){AYC""r8VG{as^(?" G+#Qs-%( ~ΜNקwߪnĨvuoh5X3t85v3rc2-ǰaZ s}!ߪ GL*zALSl2{Cw0|Y+T=aV^X>cF&dlڦClܰN~B۱bڣZ *3cc*0WĤ:jzFزz^w5A-dzj\c<0jXoڲ\_ ]d\lC3:ie ϖeS#aA6}Bg4+[/nhdף;9]Q/%rxRI i#'jF9`Xy%bfni 79ns"y5t)?pnƎ 0Ĥ:Tm: fbvl3 4u]Y1 -M5]LSi0eY':5piPBeH A!&544M3NQ ^G!mE7:b1?i;ϘL7o8RլO㦈.Fh7LϴlxQAmnIdƩ ]颖w0<1}H CҦWE%Eu4y0(cq@N3a7U?Ĵp)ǭQ~K9ĩ l1ſ4ČQ躸#j Fu#ڃ]BfuAi/v]`fGmcnb ?uzǎj 0Y!!(ŸfS:g.6V^߫ 0Ĥ7?XWt4]BO7=m1_[yL3_LoxQpetcu49U8:YG1fȺ4.2:T>;n@syZAfGL*\ܹ m9Lfy0~1bf=Us(!Subbx %BƋ舚/Ku }vk i i:nBq.(  _XӔ od\f1O <4ț}F2sr>;6sx65qF'a E,rj՝n+oXNovUϖU`{b$-Y+UNuoBӭ uPzmvے69o?ԫ, GH'ע\l)]ݮNP78jD* %|;SWi:ITK\#{i9+;~; ®DL*&]g6|4{֛W*uտoѸ3:U3wP۔eǰ\_gT`ya0 IDATXklnVcǐ5-3>vv~0mݺiv,kق  &6L7~ܐeQ˼՘ޘ~fL[l׎nFse5OU/A漜!E;TLFCS@0:;U9T.fzft5"T4 c7 † r\p=7yF팛PFnNW] `L2,]ɨn@{-L,zC1 lߕTjp'7Z1BiM1 eo^owj{*Py UAv?*1@}1 ,X>A.q93QTې?|Q h=xw57`zYg:ԬZkϮHD ]T ӭPWx̩;nZAijOdqC*yIut0)"ssm)?fcףnڣ79zqckmRGo.6H(ygxQ 9i }tE!X~[]#eyĵ 1ly7ocvҎcJ*2M{Nfj iw hAZf`u) Uo#@Yt4o4dzM4!ܨboc:C˲~ FL*ȅ͔y 6f 歿EgB΍gh|b>E{T77nX3B!S 22tm 2/'0Wgb}׫i櫚we.PfMO`Գ \|ī-49KQ)fjcdF[4rkuAaCt1yYXyZ~~|C秚bxXil% rupˢ{Zd}_[p'S~hըeMl8u Y4~HÔ2y6 -ʮJbޖ jd mB"{ަwU6BtY샚f*s.crb _wðRݪ1ho}ј( S v=S9Ln+&6^w*Ԡ`tTò`6\A;ߤnht0}睉 ]s6Fipʺl,FܴSs`7wV30`2 N/].3崩C55! uW@#kOWzz#YU kho荍&e+P6\A;ߤnmY1< 3x΄yw"ՐyjbhVΙNbb3&6 :[LTZNs4t۔р2e#Nm3DQOE?엗:G۴5*4MMɟi_lZ+4UFA#&͋z4-E3^Voh.sY.=h^kT[tz+ː<5<ӌۇ˞:~O3=2 D o"7 9Vq%Kcd}(N]j"TmV氜4Pڦj&cAaÈITy_ 5deP qĤf()2E>وq1] V:GǙML/ܡjf~5D3bJPjV: F]7T.<5iL7PWq\"f5vҪe3"~?4bU8z_9r  tBL*25n&]>!͊1[ruyԘR CNzt~_*̗M@x[0 gbӨ9޹XǑng)3ܘ9 V;͔m6AIcI7VNj[yWǐl Ža7?%&3- tɘ04AY8dJsEϮEwCYM[CɼAqL3L{5[Ϊk6$3o8{efrޙ'nrx}۲m}, :1x4CʊWCv1uqabUk78|{ !{x{Z'c6*mcAa*bR6m̞gJSgU}1̓ \ 3fnMc2^ƐX=m[tn*|d63[MZҵ+x[FFU7)!s2]I/6,FN5Ԧ̻aݎWێĪb 4NŌ"WnL-ԹT^2U6ڶAAX'bR pe}ڌB+b50a]i60 tt0cft,?gVfOA^Ԥ4$X][PLBYtRjn Fxeujt睮v}7w ki?>͆#RAa}Io8I2eښ "Լ4yyq&tl_(~nPVkM7\-fMǎI[+H5/~gb{jx &$$: v騎/Jgu, 4Jz:%B/^n Ԙ f:SKx777CMCYnUqsq2幜.y)! 1!aGDffLӋZ[{Mĩ8~pN:tӲeSVtqH)$U ?(DŽ+Uܛp~]Uj|hfњ̘rvT,~kp9{dže9i&۲VQsF}8 GL*ps]c&B.ԍ5bڨ:[Y?MsC+h™;YRŽ1o'o*mFM+3?yL_d@ t\jAIԦbfM<+l)Tg\ EPh;o>i2:aF1! >u[Z[UeXvu&CuV7ymU}VwAaI=Ō+51l_60k ?JkjZ :L0<4v$VufǮo @$=v4KO2fվI֋9@ү3PyaxԤ.~xF.Po>YEo鏝߼ {Voheڹ9:Цrү1@tpYj e,-G#fd]QeI_LQ8c.uap>fUPuO0Y4qq1х!LR34ZfO4$^չ`>v~W]6\It&5fό3zR겵7IqB1[oCqÙת(AaCIE}F?7P_x6fN%t2~~C@Q=cHȸ9E3p\EJZG:tRYf 1^6ԇH]łwǕeBd ,ZKemiX'M/9WT(^6@Ҹ<֙;#^Ү ļ6ve- 1qJau7dfw'tFF1t4T+qP`$ra1<[zn4ZAuMV$$bλ ]F.ܱd(Idܷ.@bEzjHFa¹nf@ Ѫ]Ӱ. IVSIJy8j :/dE,OLg# ~1fL̝A7 n#;W%E cmirtQN6.uGQ\0ߕ2И%s3 XMٿ-_ m+cJC Ð摜._*O {ɋÖ- &uK 3w/<ڒmZ#23NLWu}YKu RwHbMˌR 9F3o2'ulH͚+'eˤaƘrYd QM>5k)v0 z:Ui]86;쳬|;11Doe@LOh\|Na2y*Q$Vn:@lU C+)#EѾ~d5VeF٫i&t~SgNo Jx#Kf`:hE]'emICKcJxMz{ ~oe@C@EA>T+eUTMZ% dhL: ,颌4dS8Kq ecVf!oPH<CiAg('գ:yiu̬%1r]WF4  dTAKgI̜V+޴j4[٨Ȯo56 ƋH 8VϨjZeeiw\1&.]&巋{&]&59'fu#ҙE܆'r&ku6ov .륉Yj F8q2^)$MAp6ᖜ( c+y=\7\55ՄbqߡXQMqʏS4FVA6T}e|.>L.#daa\2 12iXuIatR nrzͩ4C<_פZw:*5,jinW2>+g2Ԇ1/c9Meׂt\jAQZjߣ~dO&iHրJiM~t &+E';60w>4tLNa)ԦKǨjp~⪎3. l1(BtyNw(X.{θ4=`y&ogL75?z6fY_J{5ɰ6eܜ:7NFU] NTh-O `| 2Jq6Ve˲q۵ۀ8Ƨۀ'n|(`xPf]jߵE}Bͽ3.sN2Ii x9ZgT ,ͳ;WU+-7ԪTCX]UL!jp P{ێ hbNXYA;bRQ é]f#MSfN!1_'}MO_IIi~M4K4W3@4ggqiivHƲkL,ZmNivZFA5kRam٧vȨW y.x|nB7=hvV&A3*oGdGl:}"OꌥTB js>T +5UVkDbğ  1(̂ l> -Li~7;hF)d:X=t=?M;o6XMͨgLI*&Y4(5ǙE9n_bԘW F. &AM&xTw'hr?q fz .7Wz]i {:ݫ_ {u!WWT'78@{z9E2 @_UbLk63<6?/8#TS/MRrb{AfAacIEvf沆hPBfhD1݀ixL*q% j+fX\z^֣2 9L 1ĤS9 72H 4f+Ss)gex زio-1+,규 eC>䞃׿~y.45w 4ڔ!zpfM^H7jM& q"/ɜqN[ Nc6Ĥ Իb IDAT#2;Fv~cP9s 7̇%_p#J*]E>4aLBaZE[ {s{1vDVh\S7#"MKz vѩbdƒq]Vj,tхiZ-^ ^s;:YD>ߖ{{* 1Ĥbod=vKJfS=Vz"B)!spronUi\4ɨx6kr$qk>]9z˵e\4h|YnF79Lni10)dRֳ5>]ǬdVmC_f,A!&Uf2)}n yj{۔{y>|$ 6 e2>ͽP g='͘:kMYW2mi6oD^~7i-WW'52m14  l106Q't1] )>]E_;Z=qx3u%<\=kzb\<-dlfZ4b>Vq =2, Aac:U whh&mWcOxz@eb6}1Aml@A'!Ty" @&~A6.0sJM:L*@2}|\ZozeHh6mt>א74yǍt ENAbRaLjA]9uTSW+n' 4klk{g0ҶnMc*( CL @eFu#Tk!m #ź":ug3o <1^ fgD sAL @[s<̩{ԕ2,jZg4\iVx1;WM-o3qA10^ <1@V_h :MiW}޲lTWM/%YA610! 5<7d/dCZТm&&l, l=bRa\s0yĔ Lnj e.L&h)Fs4 |*3UY5׿2 t&gy=}SLa[Fu[52 ŽBL*K/t%kfK1(vŐ[aJk*m ŽFL*CmAӷ o; N$ oRrĉ/Dff7Xr;ىAv*ȝoR wk(CXdPM7kyz{T'wf}ϧl{m>O2%3$xwr^y>yo?uϺ^=&?=z26su+X/\$]dAEL*j9z"7fzؾ1غ-q֧#SGF~3MX'vڧqpӤl2>3dɍ^Q[c8А ^2t{Oy(}?.T%m&nuh9Q]xi^<-WcM uh9_e@A0bR2mc?l2`̬w5z3-7R&f' obYu e}lK)2 uź߀6X?S{.  ࢇPR7M'dMަ|\kk' dCsr֔ӡqE8* Lď- 4FFg~<ݶ49+? @R'} Z 0MZxR6.wZӲ_?N_֖Jm3(?}U1/<>BeJ*uA8bRQ\%MDi>*CwDLkehv}4RL͢ߘV!qꂜƋg5ϦV8S.Re٪Qy{u$HZ5=ly92dzediYUÌ^̤S6VE ͠fPfPfg.NtZlu=c*㭝6EdPhI>0)O=j/TPyf#aa֠bDڼ(_s_p7.tYu u?! ̆TJ#LG2sekCĘLMeXPIDzh91_eNJ.ê] i-jVMږ)7_ԶPe^2sx ^+4$>Gp 5-uͶ2J sÙC~|vUMQf׫@}l^S(Lӧxi$]~ZzxliW3Hi@lgiV Q]hwbRQ\l&iruse^1IIb&V@IO5]gbIYlLaT۲̠g/N/Pݾ"f֔be$$Wu#p`w1r\CMkڟp'b)ob͌M&U_98UdUuN"{9x\ 1O,)u6MX:*Ozgq`xEd!znr]0LiHGW~^|'긤/ɻE:n.8^)lɯ& bMGDz'0B3͗Հ,G5cXV 3m6&dƞ1ƈx$ Ժ]I3^1׹iƅ)g&s״o97-Y9M$4ᚘiwAȚyZhI3)ؓ"6*WI냚 =Y-?kA#[;OuR>MQI` B[7^)t:JoLڌI2#LJ } sx(g}~RgA6TԙQ Y9F?z*ԙlTdroVL i>34]}OfW aQL+obD[t}\}!.w|1jԏ7Cкq y~]F:Z7 `SmtY3Z|zG{$Ab@Bôl"gEYnp2#G&so5iyQ=- `~ ڄ^F -: bޣfjɊdN3K8L],FtOķ&d>tk- ֛M =e#7<#?qо~O1t䕧1pС#Zw\}SβΨ~4O 6-+Ԧyk &uF*6MӴ>䵩dm͘Ak]tĉٍiӍzm1ͺ*ߋM( 0նδ|R95,ޠ!!l\Ok l⃗q"4T#SR.Y ulap㍸]\/q]⺛*G51f (/xmVOu5['lz wFK\ǴfĤ Q>}qXk`ġ΄Vǎc.$Nn⺛*V.`U~PMk\w#bRA05FԬt0Su &UA؍k uV:N|ew>{Ow|a tų.=<zs_{-O~4WGe&.vx|^SuFϬsU3mI\'/%~xw?k \>׿㙏6\tgF8܌w?xލ?{OiO<>}yuN=#/(^_Cj lv W_XQdR;u"&Uacv!?>u|Gpؙ'.Wq>ۢt ?>7 ;.~q5[cqWg?/?•os<'ky͍x9~w7o׏r7<)o=+>u ?英h_>xÿ :r:އ;?\ 1o~1|/z;+~*|q˜ nx/_6c_ z>c._{z_o8v}=_KX:sqݭw/锣p⶛qg^a3ތլy>zy&L>0pgs+s%>ݏǷI0F\FZnc/x"sуM18+2KzַɏfOw~MM'+ z,9xOƣ.lNl ڭ>ݲ]p}o<'}K8q48=Q˗>|˿'3 x+k/8 w<\t2>Gm-A!o|,~>hq,nY\w+'Ua=X>|.n:z̠Crrp7bQKk-ϻ~{V7qPLQ̺O~ >{W_yGMsp> *IDAT98gIzpb @f<?5|c{/ܤ貿yU/ gr:=*ű{'^wCq3Fpoc`Xr5ϫzcI\],]}xӯ> _8XK\4K]{أIAlOswy?.|Yŷ&3=O‘Lww?|gkO(Ȋ<<乯K/iK=`>W/ ~ߏśv}ӧq*7snd'?zU8#}S4<^gOe[oCͽ9)\K}!*o7~7g`*b,Eo(|4Ɠ!N| }$i=2WqcQd8m_7y<W_]Anrkry.xwUO!3KߖzزRvIilAf{N<Ÿ?6{|UOlp94i#֟|?ǟS֘~&7}WA'G9xg<)?s|X c-<{G ]L/˟Xžp# XP\voǯ} wILTKW< |F?[W`e?Wpɗ^}nw}o#/^DrփK/^''~9~?w=/ƛMO/=<w\$8Q/_<%۟Pwa &9ɋ&9y$~^uyP׏Ã}5HIO䓤UM} {zq֋Rҷ4^Tg$}f6w nS'O ѯ+fvKU{ ~>uã^tg\Ovxw_ȳv8~A$x;ށ~Ƿog\w3Bkgy_=*7rn'v3' J=1̌ޤLjRf*Od!+6Oyf,23GҩԞxMG>ַ C?IAk5_ v|-6$O\ƐsF|5>l<rUR3%1 {j`q|kQ`Ewu>|<)y?; e7aTI{H$ǝ1gqp9n%%1 {p'xgW[ή.#9뮻p-T{9|F:;]⺛*y$^xvKؓH\AA8\8xv˘ 1  {o[~[~AAqqow3oAAC澸a^x*AA5[+E%* 0;ܿ Ϥ/ 5;ޤ/ 5_бWAa'kzgRw#AA.M{M1f7QAa[O-vӓvAs<'UA!F&~_pv|&[[  ^]6ݤ*˗/ڴlOrXXݳZVLY~UqfkAA#UuM* F ?krY +X_|u̽azeus/p9$ h4* Y 2=[kSc5AHmg0&KknT  |? .,F0&Y9 ƚTZezVX+ h4Z`9plN&}NJ` 6[֦yQa 'gQ2,1jbZEnOg1sݍGoiAAȍGoVs{j@ Ĩl2dZ$g,l{oKr[ PPIms8ur/^ 9 -4vxZ[`m,(eL&0AYkRmӾNLR;L*?.WT'XAMّZ5ygj-Kp5tʤ(tߘ fښdZc p!ś`\7.wK.iglUO``mbVkm{o2LIMd֘;1Htf{VAPMu_F  S),x+ˀ]nWV=طZXyfm2 }kz5)l,tO'Ifh6-&֚JToAA;mf20KPgvcYfI[)c&WԚ\ԑ֚ p]yۣ7J3"܋p:04vᰱǏZ[[I B>Z,Kܤi?+@SgT1ɵ&AAةX *M &g#7C$$OS\A,.ynMY;֌Ç5Ǎ AS_Ssi>2X\~K\7hXc$=ZLteN3 ꩱ)1  DQlj c$I[ks(kȨ aezٜ^:>8EYG]KJkP&US:QLMrfvvbrRAAA"dReRkmE57Iփ^/S`lnRk* k10}ckcV6/^dͦ ~JƚF=:2v emQʪ|ٿ he6M[cyb)IZc5 BnzĠ.>_DmP6hPydRf6PG/+CrZ>kF=2.2L>\iT[P:ɡ3y|0}='  w@RS$6OLlLdckBbMX3Y+A.ff嶉Y:B|/a/lYT`^&hmfT eJҽED$6=|TEt$&UAaFHɢљyf#kR]dO&v2_f;T`Q-Z\50Zg=Q:)ЃJ=}d(&UAa% `klYjkzDOalj1ܜ[AbP=̟? rufpվ 0gYFC%elOjiC`07  w4,'amxba ɗ7v8rnlAm0' 3O^Fk`_ٟbV/5JkPl$AAKoV&rmbmlob>cckO]>?3K]-|EA[goF3yUoZ9P" o2ZZj|6 TAa^N AcO]8dleNϹk|>Fu3 *Y&h5pd5^*̩3QA304vpaNgO`+ *&b̪ˬa OYAA( ŴgL]4ڼlA6ۤA 4@aVVAAaPc Ԝ-S`S *&UUu*z _^fkŰ  lgHW_]S0.{ lAʤ 0 V6  )bN-1VTGa 4M  q\^.2sZyD*PVJe^AAu(%jL-7UQGYAAm2UYUAAgͩcC1  1         =8$+l"0NZIENDB`qdirstat-1.4/screenshots/QDirStat-percentiles-extreme.png000066400000000000000000002111021311502036700237270ustar00rootroot00000000000000PNG  IHDRR[;#sBIT|d pHYs+ IDATxwxE{fwOKB D@X!^DTb""+" bA7PKHBz;ٝ  w]"g;;9sY_J5oDDDDDDDtp w*Ss 'DDDDDDD;5$X9"""""""c#vҥ5 !""""""}{2)P9n,0d{F """"""Ó%K݆*8P9t!E%JeId)DDDDDDD+R+&@Є;(“$'5ECc bBDDDDDDTK4l#IIA|r T VJC* L9BJYx_gUm ѿ?ƪUeJ|**ۧ0(P(;'Q%7¹ Q-S[Kǻ:@P|R:P)/( 4@ ֱ*'aIh"[Gܐ *]!Tɏ@e))L98!B9)%1A!¹R'W$D)DDDDDDD\5=aKCoPIRVm:P)P<|JiRєIG#D"P.DqB Tjӧb[k+mZZ*y!c:,P٩:eS}9L`bo("Ȱ_ mJJ A-!~FUko&(*B#Z>hѺڊ@ JQޠ[BTSveY] , bXCbא)! -RB=nXeA8n)DDDDDDDiu1׆{ЮZ ZJ@bC EP^!9-):aJEu)L%]pvBZEV>Sb[kUtUUA v_r0R'd]U Q<)-WȰ+0B.5|p5JFA~\3rUx֮UҮ*׀rZi]U.VJaR胱^J);YP#u,c{?~G"4B_HQ, )0  i +e@( V:B[V҅V]a(Pn$XRr”GxlϏl[gtjR|F)?gchGR1SYi(a)M! #lIB:vDJҶ:QM lhijmPkium) *@KX~P^(1 @@[DTZ)^Q)=1dnȒ~۔0#ҰB*[! Fl"c )1չ6.2vMi) 5Zv b]QN$RZiqG"  R,I=WH)`*c 3#,v )uɚ(BT0\6ԮcB CKij%LHÐi) !9qԮt!L8Jvr@Ka08!WZ`R@0N`z}mJrYJK!2%Xd(Cdl4?VoO %y"°0!L -)kRH@J!dujC PPZY 0! D…FQ)(hDWgȉ({$R@^`!EELTs6y|iz)K!!-kaKq4-0WHCT~1,7 0!ahQp :ZAhSJ%$rGZJE0 TV( Q!4Jp!nXSH) QipkXKKQBX"zıY2΍DTG02- Ҳ";jS + Ær#VD [ha8*"-2 ia  G( $JҾ&R2(!!"B#e@ض HM0Z%_Q0D]rS6>Q `z,ifݗ:7ޅΗюh®Aa0S9Ў0 @J5!tdEI6u{ ,] %_-4+χ!BjH!RڀU oıYy}ZCkU_ """""Z`-mAaP}ݯ %LaZY0ҐJHGh)r4|>TX!Sܒ .] J9苷:!!D AaF aYR8aR8BIpJ@ZZJQ@ƭg gnCSC+`6"??``,ӄご|*3ѿ'۶mfJR9B*•B0$c/! ~]B% 7Z=7nddf^t^LxsT*HEhզ5O0Xz5Dò:|soo[iױEF?bFRܪ.,;}tz?Pnq'7Gab?|n۶;#..¶P(F(Bض ;'vfg*{ɥaժ|SN'8h*7z]{-`v 'AkpR+RU1}t,]G@*S)7~^+U\Eƶ tr"Bn5M; CrdQDDDTڵkq]w;n95kZaseg…PXXu}v8p ع35n͏?3?Ɩ-[xФqc\r%8n|v.*9idlذÆ=Zar2c?jƉxɧܥ }'1l;X\\(ZkXUkε"Hym 1 1馛_YI@8}"~lnB=PxFlNjظ((,D\llu].<ޒ`ͷFRbRvC # Zg aӆ F)zI<deV믿/;Y眃p(E "?/lT>돊/-99?S>QQ81== 0bҤIx橧1Q}\]o l2L|mjN$> 'x238Xz>-ưۥAK.뺘} 1~?."@de_… pB2v,0yXb}YRJt DBB;~{#''#fL_xWaH4kCy̛W?s}J~;7u4|wC 0?tIm;..J?w"":NʖR ;;R?~\zγm~睸妛:vLķ&¶õf|);+@^^~bn_B0Bjj*z ) Ņ|ʕhӦMr%GQ(/G쇁F8T!>@yyyp2pƼҶncEϞ=w?::@~Hs5C(*QWRqʩe˾{AדOL2))Kk!AC̚?>oLNаa2~G 41cpͷ /Do8XbҸ溾ҹ ¶W_ƼW+W`[!v=WpI]kÉD0<W}Jx|H?֮^=MDD5ƉFqQ!6>~:"8_uaȑ, u1gQ\ēO:_~ѣձcqpô3pM𢡄M6c~֚/I8"|} ˆ,wfqȮxtأy+97LJkDO!"~ʾ, >KzJ#As)B<3z4 > >:uęgUi)n֬İѸqcO?Ň3>B(80z|w믅8viǕ=h"r@4m:)Ν:n\cEe 0M`~džPqqǩp23йKDBA!Э[7 /'{LJB!|g3v,P[ZDQanvg?="":6N3v,nfYe۫2Ndžǐۆ`P}y,6n܌7'p8x@mϝ{}UqFw{\G|Ź{@mgggNl.2=q"zXd= 4܀sNo= C(./ #.Vp6 !bGD"ZW{&ce)#H)a;7EDDtP_#E=ķlIŏ?̩T;voay3g=;7۶3qݑiim=*Y6{±;CA{}<2/?s1r1h^g͘Xx1rssALLn+ﺾ}CSNҥ3~:t֭[DмiS@g88NWD^Nv2Nܹm;Ƥ)SqnF:q`t!bM8jRi z_| L{/{s8??f|dT|pw(wQrgiakZ*\^W,E(M i[2lk| qC~Xv]W8;+ækѲEs}>g1ǃ9PVm௅ >,>'x"իW8LLCC\\N9Ty<ھÍ7݌hL> dž C;KXn?㮻A0Ą +WJPϿ$$$`v(J) o ??4h^&"mOs9q㖵\,^֌ap9ZwUoȌm!6V`Kx M) pm10ݰejÒ--M Hs%dX#BՆ7sU pw*7~ƍ!6xC kWOch( /FϣO%F"lI݊kV#??-[B yu+V]:uвUk4JnxĮ8LDDGχ`Ԁ&[0ٙņ ˎadg"?wĄHHLBtt F0rSFI$|~l޸u0yv2zw_8 t52Ӑ}23˾* Lv eT94(.*BqQalX¶p8 kTضbjl<ʷjYnjn޸sVv|Pƶ4lm""8m9+<`  } ({?$}cI'!a  g6M&M  q χ@ 4#"""""`6v(G@Rwߚ <C+U%DzbcDDDDDDTq"ۮer1)DDDDDDDDU Qp5 U"""""""*bBDDDDDDDTE RA Q1H!"""""""")DDDDDDDDU Q wA Q1H!"""""""")DDDDDDDDU R S1q` }Cp[ٟ&1qcaawsațqɥK'N("""""<ثw1uV`x{ޓ.'vA~8z;9=|T%2s/_}Xmԫ.uu3D~m;ӗ0uA.stUfჾFzy"""""": yZw1Hlx~N>A<:{ҍxhW>8>mJ̓F^|!iٯfr KJPf.V4=E9,A!""""": E#+ S1?Lrbڔ4Qmp}⎨ٵ&C{S [007?i(y7ni~f܃"y&&Ϙ?6`69WpzvMoj6)oMm~qoPs`X8|lqeCtn=M=Ao[>cL N[`PwmOG~ /݈\zd&P=-+R-.ǐ;!M_a mp鍗#nǘp_K[j886g Z\r3p2,JCD|%괻7+ 6  㧱ߡ~ w1(xUz\LmT">+ 7bX[Ǟ,s6B>5Gt|KĖV\6w2:ZWč30Hݥ}qR]?'&Ui )3?soAnĒ[Qvz|5f~hvu8Q$FVb1#M#+˳3'ecASỗq矇m#Pɜ%ڌ zY 1Xib YH,NF4;6fJ>J0^9@:QQ3>#l?~tf^5Wllv&C!$Śo3`e_~ԭa 6>IMG ;<\yFx7=)θ+\ngDz\‹p sLWĕORpbW/͚7@׳.FGHEs6!ܺ;.rZ%Z')q9Ƌe_KMuQǩ {&8W_ūŒT@G\^hWKDr [qSq~̝Gn8%/cf;܁Q$vE9|uGC-oW4E%EF% =t>eR2tj&!-H[p 4x{C;Q=}7(lXXaKLw<8%4DDDDDDth E#ywש={,M*ڦH<~CJ_ExokpASDi[ |p?|R(rQ1H1kkip<4NOͥe`xg|l-oa!"U]w?[B0+ hq4#!a@ M{OT-O~xhdYP06A $5@Vf1J|8CnC QF4 @ѴK_+V"#Eԁ ^?W,ǶuuAЇRGc#.!E*ӺS%"""""CV)ExS?@.Z\;W6B)bv '?uyېf~vWa#6/Nq\w)F zu".}~'iǏF:H'%Q>xrjef mGѵ cT =2Q=<=}tk]h/īe. eɾj4}]'ԃn%2Գ"4w7 =c O羇OV;G%T'-i;m3AdlH(7=ʄ;8YX{|qGH3>ALA;ئ D"1c:BHDd}~صم,z>3㗵i Q em>~+ghnmv2 k~):( G!)DcW|:θr xs||ѷH-bllZV4 Oک)Nh0"c=2 <H~G<}#J )#XwXU>^[1i06E:c/D0}[w\~L4rlC[™1jJ 0mC#<5G BH3y_ތ0s9*8͎i84lM[Ѻ^1I} :v ^ǵ1k#xXugPa oӋ1Y/8 '($w"H[7u:lhD>7퇎u$[nW(2A`֤%qڟ{2:y/^31xﵯ Sqn8#xQUߧCÇf]{ ѿ|Q cqKsSгY8KF^}Gx;dt:ױbE y)}!fk|D"c擐9ZV:νi==uNog#>+VڔWc/|=@chYǶ .ۧF܁-w\l%"""""":wZwUoȌm!6V`Kx M) pm10ݰejÒ--M Hs%dX#BՆ7U7ujh=҅Xh4^ADDDDDD0M4l/tvmB:OAQhB yL*"*7ވ.Юq:n( nkVB'.1ܯ؅ꊡej|E>_с.߂[5dBDDDDDD 萓hwYDDDDDDTyDDDDDDDD"""""""*bBDDDDDDDTEG@ff8"""""""A Q1H!""""""""pwj6YYه+ u&M0Hq&X/.;\Zcosq&4mpwzZ8DaaJߏB\xPງ[RSNW_~z~V4H55ѡS+t(qtR PJc5.DQpC))x~guz}G*wM[0a ѡR+`l8Ne&l5k WN=oޢ%?{QY%h{t_״|""""Z֊RM8L#(ޕ~VCP_tOQ""""":%GÏ?)O~զk!"""":Bʊ:""""""AʾP9eUx|A}yB:v*{}lP`4w6O|r :בe>Të& Cfbsp ^tp%Azy8H.\2W("6=GO`ˬqUn$S{ןXw=Y}lGA~^\LRͨND(y_m~Tg% ?u_ce׼Mƚ",zRT~~)l+51H‹]ql}OXS]#$0|h}f/VX嫸iܩ3? .A0Ɔ>cm7݀AoAg_SsvAΒY=2t'^0o^x 8+=c c ^~-"1kp|7Ot5zN" ~sԞFGpM.ԩ.obr ntrNwL?.W/Gpꖱ?(<"""""":P9eĭ0kŘ5Ma5 Gݣc!]&uC֟Q4لO/|^81.:.I2J:^5T6_OykfmLoE/nU9Hw0nkv^LNGD[azV ^ 4|~X=h2i g0ut|W"Qpu]p"? =Bm[ߟߤ h>a\Llۤ1tpÏwr6~ 6Iln7@AҰws]}ƮUpӳ^bmKω}1h 1-X99|< gC8s+r[Ի0nHxK@iJ\{xME+f~\MGe鏡u s^}ˋpZoŽG7W@qqah]Tv >~1<?\\_g._§X1aqi 9)Z}:;Ej06>@O<0s"t ( =Lc.<འo^RšY# 84i &c[1ݹ~"\}K[\Rz31OKTQ 'e \z= KBW]a֧FS ;"'_}/́)a_Ӛ L-5=%~Mu3VEes֡˕H' ]Ҕ !kk1w t[)Btl(-˦mu>BJïNxŎc ˃pȁlK(S?[ _㝲\ܰ_D%#гSRɠSl.p6R>}Sm ]L?k9kqroѢ [QYIhߗ"Ht+z}1R hsh庎U3|\5`EKBﱹgK􎈈)61 8HQܝR>n} n3zuC~ttJ7]o{~Bui7cx!|3UYP6=/ Ӈ@8Ė1Bv{L|шSVFѷP@%UW!E|R {H/Gg㛪?r鄶PfȐ -[A NPԯ _ ",ȞBҙhi@!}`;>䜘|rι^{*:$52'5gϙsq&`dX+3.CdoeS[ 딞;E}_L1<^jM“rm ?/՗o+4ŧRQ</{P+*ś$&i:^t?&sYJd#} ߾קS 7 LR xqǜn?ʕK,ؙ}R9nU/ܨDJF@0H sE^#$Ѣä>ocywisĀ@b?̊pb<QEp9z`/,9m>⃋TEDDDD ]{.¾ q9ײNx aÆ WD8p2..bt,ؖry|]-O`@)`'ٖ&cg9v[ZdJE`3"Wف\s}A[û;, IDATLf uѰ]zY3sUqp ZԯOV0v~L W;5=Dߤ'Swi<=mm7[Rn bn+s#2fwyRӣ OH7MԃxQ5j@Mnya/b ?Ϊ>ib^GsB7*[}Y7$]f'մ09/gWhzsys_Y6Bu|`+-b*FѽN9:'X`^$V` +Wi?8&n燏&jZH)29m.&cP`w*%sw1=Lk0i|&LU=I g,O&^ogܵGgzVHy]&&&<0cJZpS{l49=5mzr?eڜDɈz2cمGw\ |Ămm{"Q1qVi9C_/{R:Csrݵdzy<;/j Kt2J#0OedR3eYw/OTZ"""""")]}v3w޼K<{I7; \M:!\6`c ӂ"""""RFᝆn;+EO7w)( |"EDDDDDDDP"EDDDDDDDGJH]-7+""""""RYW+ """"""""R08|q8v;%u)"""""""1ltw(G˖,aS\կߡ)""""""r^ǎS.XPďhάw~DWC敱\ZڥDȺB"f)""""""/4H]D@ɗiYJ\F`;),Ӽ-JWHc/93ǣxMo<Ӹ?_Ol|HXXܵ'Jxto¢5iֶC22 ff<yn%b)""""""˴μsO~z[.eJia Tz²Q&3aT /FJZ9z2]Ա1 G %ᆛPnbYf~8ԦNnIfypsmԾnO`SrA`Y&iޣk<(^J.pG9YV{c}Ұvm4/㯴;9GXgPі&""""""">0r Mknٳ1UbPXI3>wF1e(<[汻_bV(k{<41>[E4v=#d4 DktIDpxj%nN!լю3ʼ6Egr #kt+ov/#s)VԞsU8͘5q6\ڵҭ[.\uH|Ywޜeu׼ ?ZҨCOV ;HZm_ f>LA}[ F(]E 'Eּ k!s)tx~nXξ4G/Hf ΍rRF\[,;,Vw7fm̌-Pg[9 ֭(U*9Jѹk<H6R&=Ix{?!ZkˠHT8dtLO"8FKOaZwi+ٗPkr[Z(5?L̒TKpsr[>t+88VFM˖,9X˺zn;AXNʠ{9Gy """""""2{rl!߉㤛^,9`D#=vy 4 QVtBTnJِbjaŊY<ͯ \͓W72c|̈́GYQ[B 6 ݎnga$R ~FY'7}niصj&nբ3Gyu3n3lb9KsS{+I$cL:r ]d犡iͼ;fM+ j{hiLH#QS2(S2c4_,"1炲YqXfƿjٞxIx|C#"""""">̌C’~eeX)Y=]_@.0X&9ffrtmc1Os6pӬ7MɼV0ׁ44 (ӈOY֠>%f퍨 ;ز aƄ-53nliSF9ez=)""""""/Ӳ0s.XEs´c3n7l҂i48Qgx3gA6Xt cĒysSGo-36Ό 3>} ɕMu(""""""">h ш ?ߙFk\lz+!"""""""~gYmPH_dݹE^z%RDDDDDD$QQx<^uRJax*PN9(6_O5 #~`&oXbHY&֭_!H?*ETT1Q^JXEWڵH1Y"""""""">R"EDDDDDDDGJH)""""""""⣫=?̝DDDDDDDm۷w~u'R!\ `˖-T\ߡXz8DDDD*q6ѡcG,2ML2-,ĂLLq"wJXTCutqTo"""""i9)fF"J濖a; HX ֥FTDDDDD)]˲2:87)t)B9}KZ<ȷ,7Kq;xK|Ď4ǢM$)}vKu /G}o'>gɾퟲ<>_CDDDD Wƌc^w)H Ҵq6nBshWeX¥nwA /y侦C}ss;пS`!(M6eVQ'IkxL9/,ӭqFpP2ی.#~hڸ ͻi ]N~M(~]KOye}tkܔ&Gy/2oﯿg8ۍyt8ծ,Nmݷѥro'uUc'M^ɂ&)""""qx<oXJˈ'ߛҟxD+#>6? efz|I6,h\AYOX6 hS'-sf2fO'm-jmoN1m IY)|]eRwcCB,YBJ.l-2qtfj7b̏X);f15mb]ZFH9+L3rjf7HyT lYKXG1GۿqkayXR*uO9mәj+>caOLjIJ:wҩS|G~R") af3p-x`#;Nz9iC&M+L[ eaYn߼ a {?Ó2Ì[x07G7|C{qcfaٚ=\?t6Ϙ{{nзp sd)cCa؀HJ^veNt){XݮM4-(#=[qp\vd3]|r=_ZдI ˬ-x35-0^=|>ov\G0t,3v.1,,GԷYp FQ篯?mDy!]ѴI[`niҌF2skR1VzźUh߮e0.£+ѠE}-,+?`{I:νvdL\E9q`͆"M~_Ikp=%x7OG*dװ,"՚Ҭ~UE5aX0>No3- xokҦ[7l{bV5|AY%ͮcކx|CDDDD盙p<~A[?DT=LdǪQ2byo]ɉM_/˴0o!OF` <5g1t= ؀]y4-掋kxpވ ul~g_-ӽY5ucs؇_FRޙssa0oWx}vb.muf#FwnI{C:[3Ż5A@lx҄ۓٽx )Cjyy ~,ۊ}я~و=y+utzסŌQ]՞^f0;{g;oJ FX%U|ImsmҔ yM favh*b7w#zMdܣ zu$BĚ7wTj4ʁN*?Ox}̔}xJ3yEb0)sm;DDDD@ڭ+v2,<_9M#Rǝf[h*QwPŶك=hP܁ҎqczqSƛmо4.^+2.$/Hr]+Ya9v8Jv{H^7IF%sAuS!a8reD9{R '|.A.6ݝȂc[Ho!BZ;E"+#-έ4:́5#jӏ{3i&GX8۰8HKfLAyWϼ;|0flyH<7/⮁ĴFIYp7&/abq쀕Ӿ؛ 8pCӛkw%nCJr; ib3Qg "2*(;j FHyvo~?FjOVۙ :1(t"Ȭ o!)8p2<+v§˥y<^LLnn7ch/$7jNـW2cJe^L͏3gm*^+oa|$ek{&1-ŋY,]eKlR/[~b\U+Wʕr. #OV d/`*؇+GuwTggGƳqKsP\3jtM~[W%Az-wr%[rwUGSo=S{Q=L«/k O ^0}ʼF z?_!)Wz,uQ].t9 }\^ձU)mOV#%i Afwؽv-fwxӜ4cN9 Wa~;&M\T5\[IJJ:8LN&,kʨa)rqHmF,lG̫L:1>ܚ}Gѣ|OIIJa6mfZ>3Ҷ}|7 ;ӦNy>_nSTƹy#^vԛn5S&fm;HI6@ ttny{Jz)3ݛ :ʹ*[`Eoj*ǃlFbYKutq [(RTN#Uc  (C痞! 0"ٗ Vh^C JKOutq g9 Ϙsie㒜߆ ' 2AowEhhPDDDD.RU"kf_TGG&""""")@Hv{T:87)H!\ R"EDDDDDDDGJH)""""""""#%RDDDDDDDD|D ~"w"""""""r9\ )H) H);?cL 1e3*73p4603w8IO}k"%GJ;IOӧQ>; cTzgFbc6|$̿tslGm$R1n 1sƹ.qe+b~Ӝ[λyl!ĜՖLyI| ό)%UJ $$"dē(3>"""""H)̤,~+S@L^ĮƲ]Ix4fNt GȎ2vbC&,`OZeğh|-䓅 ,ۖ~sr),RT콻Q%|GYco!4nSG8:{DFm=uflȜ _HpٖܨHwra`D9RI8H[FfD69 G󪸱?y7i&$^ suor7>zVa5 /Pfu:-o(kѪEjV)N)s;Վ4(s4"\2h/Aٶ=.|ɠ*sFxs =ʓ׿̭w~a|8jV<[X9[,^M佇hV V*&M/cNοOkObb W?ET+}؟] +uSܫ? ԽVq7V-C_Ò%,i-NCOq׸8iӅ4lA1\߸&JG]Zo^鶁&n)N1sFTa.Yo'p1GDDDDpR"Z$0r̞2{-tn ,G:""{+J>Ecl!UA^~z9-G^gp tМ-`o"Rp ;^JG$kBpWGDDDD0R"j㈠Jl6Nò<ܺ绩[NlW}홛8p' (ߣ5evq{1ۃeνS>Yȁ3Vt‰̭y7*{\\3C0kPLL4=$'iF5"5aN2x<L7JLea` ~rcRIMt$&]X$|Hy]<}ƌ(u|<|dPHekZhg(S&nn$W=O,6xYIW ?y~0V?=7tQqu|:Q_7N*5BH }WI3 z҂b5iV~wfVIBYay# Gya#t ߂_/&ٵ7`ʮg=;|:FsO:8x^v"D&FT;&mwo^ӚA#[3hd^Hᥩ="""""""">R"EDDDDDDDGJH)""""""""#%RDDDDDDDD|DH)"""""""">r;X:fθLW*|TwS]՛Ur%H\:uHfPCutqToW%DDDDJ="""""""">R"EDDDDDDDGJH)""""""""#%RDDDDDDDD|DH)"""""""R@X _JB1&ؘ[8rN;fy}>׵wb$̿96yjHXcz!D{7_?30T)+ jOxBJ\̤,~+S@L^ĮƲ]Ix4fNtvn$}/s'D{n!&Jb7M\,9a5Q*kE58a @`ٶ˗Oaobݍ* u,- )($J\/RM+c;ϵ{uME/(>"""""%:H%h"o#iؠ@^7ͫjpIX[.<2`4_ 0tfc; MN_lC Ϸ#FgpjUS}|#> #ḇk~'ͣ+٘cp9S3x^\۱70G(N&[=p3)yrًYl5a{ѬTM~?4_dǞ?VȺ)SH՟E @SR;͓_Dےy]0,RRdOHOJ"(EAYR?͊BrQ/aKsסko<_FH\;;'Ζ{c,n\CSʱsPd s߿pg>"""""Sv,="ᄇ3s9/RO °9ڎ-͢}8J>EQr?˻γ^b5kwf(k6\:Q Ty崸y吜a^$ u@s?(E`HoլԈ"0pEǾ7eJs(րw9B2AhγFJ\mTS͆iX[|7u7-ܚwӭˏf"qEw#yiғ,nqq{wq_Or `#v_'2aVNy=xyVP~@jR1ӝV@[<[gMթRU[͸u^Y}DDDDD `^<9+ bAy>oU<<'qUa|pֈ{2<]{8 xR"EDDDDDDDGJH),?%RDDDDDDDD|DH)"""""""">*+`JD\8ClLٌ 9 'zS>c?HZY[:8n79aTkgI[0axZW(c۟U*Bjӛi=909pHu,X~c۰#&a?[tߥD=cbKGa$-wA-C0~^RMv.Ѿff?۞AϾǜcx@}DDDDD 5%R +W_vx4 ~cVq?cpWپ{^2i[=S:`:1Oc};o粗U}4Voڹ溕U5bpEذi xx}|<v4sw' /`=ع6Ώ[XNi0h,Ʊ<=æ3#V޸1l.MX3d %|1I\.}[ _?o'nDbݬ5#""""R8)Rh0IHtגn$覍ؓ污 %uk=l:o`sl':__ NHLf$Rc6k'H_]8<~ݶ٨7rH¢ýYe=+"q,%h2./}HOl]b30 "ڛ mL@?_B~@4FLp¢*sӝxr6-uaqrݧ|jGV#$F3ɟo")L{7_?30T)+ jO=gL#""""R(r0vVLQG1mzzv%5ӈ_;':ѹz6 Rgz0~T$yJfAN wa$vZOpsv;!;p}ly}`ٶ˗Oaobݍ* u,- F`rrJ6n@{.ϻ9a5Q*kE58a dM=eZ֦" E}DDDDD K$u'ʑJD2F4#Ұy\ Ȧ$ %Ff.+eiG:e֯,,<*W$p4 Qq9( 3E3o6p_u]=} M15|4ayy3,ƬlŻ+[cGlgw3yK-ι*w3m6NUbv\bnK{] zV ˂U?G"Of؝x M#9xhS\JwhH9JڧxӶfal‡7Z2j\B9D"vr~B>ǒxbg5 :FDDDDzUR^9Yoo/ܯ<#f-&R"f >Av7.p,k Uq5q󽋮eHw")qg3z(-flAn6nNn(#=ԉT.J\ܽƻCAm?;Լۋx6x&|wF~ذ7PI* ~_޸!Uࡻv|Cj7= ".WՊjDDDDD#)gveaVZ !ͪ ՚܍ݾX I~_<5#n%i oOłŚ_UZc\8Fgob`ٓnQoP-㹦^6 ͆f\>/#1Cÿbbr7rv6gXM02ηw%ӿȐ~ zBmzMAL#gɳZ:΁ɤ_jDDDDD!)'͞όLxuٰS%ձ:N:_7M;i?揿kZ`a$1{ZNœPn<_r| &w+cDd.4WpCfOP\Ru ԭ@fy gpER'{l?3CT'uⳋ_mn䦰b \݌c8 fKtcbD3!X7ɳy֩CPP'6%4-\Y5"""" IDAT">,\DQvW ͤ۸b8Ьk|kd %2-ڸ7Ci0,CîE1a˖b6<^ơ"7Su"GJhbډYi :]Յvzҁ)ŵQH+RDDDDDDDD EDDDDDDDN RDDDDDDDD EDDDDDDDNe?H1/~""""""""RF(H;)H;PgU+)4w]͛57Ax磎Mih])4GGvP`&""""7#"""""""b')""""""""vR""""""""b')""""""""vR""""""""e7 RDDDDDDDD EDDDDDDDN RDDDDDDDD EDDDDDDDN R!KW؎aSb {iy=K cGHٜQ`)<㞂wcHζANjfH13/6c)n$'/ˎZ`; 8O_1~ńy[p$q4nLSCgĥ`q.S#cAW;FNjQ#bt&bLV' )Wn]pC$ŽM/fI_ >3ҽ<| fw 0IOH?A{-#Yt01c%>o-c$ľJFwfN=pD`ˣ|{‘Z~V5ݨ3v{!% ُIk-rM +gҝhɪ$vX¨+{]Ѽ'E.xg?g0a$mNjDDDDD')  #<3?&jTx7m[zk=#zѶqmW§vk<۝?UB ܂W˫:Aep(|[ 1Ĝyn 0AwL](9m-fFwޢ)\Œ֔@ (w{X _/oOKD6lUȍg#kOՂ ;B;X3~&6.XwS/SH amS9̓gLhC cjhz ‚4x`NRY>{s,·Y\(na0fe+];@5r^uK9sJhL[AX6,^WBzb"z沠mUROf؝x M<)(V~N'Ω<6x){ M+jDDDDD+-\QLq?le#E.`r`P¿EGʑT>M}5 &OB: 2xn תU#%m xoP/G? bVDcJ?4S)?/k m|o'~!̐*!A%? R+/+z9;)XY5"""""哂Jx{{^ $д_wBjVlr'Ž_`./ɷ $'o?Zr aMv9,OiLMvLĚ gcz9#=ԉT.J\ܽƻCAm?;T+6x&|wF~ذy]ࡻv|C*GAxVZQHy VC`3_~\î< JV:Zk!Y5\B+rr9w0LbIlgI,?kj`~:.X1 co$zF1}@n, V=&QoP-㹦^6 ͆f\>/T sVNnpٌha`Xt9|` 3.-vd`F-RS'jk8̯bIN?KBnqN&UdU#""""RI320π0cuÒNds;hiς$7Ik9f]6wEӊ`9IMDjO-+b#ڟ l]B?޵J=͞"ivsH$l=6; džoU#7g:ÅC~?o&] Nۖ)02Eq,7g]Or՚бcD~8M fVH rALrD^t7nnhSS7JdZ'=]zB qkĄ-[X|{ {jz_hNy4)j'fu uME> :1Sk/M EDDDDDDDP""""""""b')""""""""vR""""""""b')"""""""RFfIA(+VvtnZiMDDDDD)5 i.ܔv%lܕBst}4o] ;)H;)HSR Gw@DDDDDDD@RDDDDDDDD)""""""""vR""""""""b')""""""""vrvtgu!O}Vu=#܍@/3X3H/V;uE!33"ra"|Ϗ P~& Ktj~ b8;^ThpZ.^κ9kҗ~#̷>>}Od<\R+7Ǹ~61ӔM<+!Wk#ѣ9UTU}"\C; fȓᴼSQ9bOql?Ck[Raq.m#1˖zM)T&#t֓+jDDDDD/]R^$]!{_Ϸqxqu eRh2c9{im# ,^vY9nj%?t{i+ /1mdNyO:7ձnV|y9j)u+ _;m+ר.hFh|_}0I1_4lkbX:B>SX\«~p ?3Ls!Ĥ6rEbחWwq ~9aٰ3IAJedlvz3:lMή>;[A}ٹwbY .?Cx.T S#}8$Jp= n;snN zPO_?0pN ߨKH~' brl6cvrR0Oa-r-LdBp[/<|U4KN-o]TkXiӱɸQ.XɏxreFDDDDRr 0aRN tu&&αo&V,ܟąM^x +5sn>N3 YCis2ܲ.``p!+ *z\8ppg8| #y{T*)8SYt+lʜ8]כu9.qW7>< g1tRܴU|0u79(;;i~9>#~M&@X@5"""""M#%WEh%g]qs|R 5}'Z>:ײJE̘ 9X (|spqPſO-<=c"m~btǼ'R'x7EGۂ2jF|>.{&?qQ>|T3q?_=ŅCs>$?٪)`UwOo<==lEoʟY:)pMm3.T lDd?r}5QћqC'3z#gB]K%}_Zhwo@ bNܼӫ2BX+R<%ײo!_XJWҴ'In<-wGt&y?xvQ^ېȮ=0O{#%9;(_&|`+nzɋǤE&3NdUBv,aT =JFNlMcG >\}a?F_8UX)[&NfN.xjN0Lj_ e8T&(dfAY vm:==wPzFmTO x;Y.m'޹oWuuy;t c\ÆPqi4.xZ~]×'z3.ٌ x=$t;r2yа0 ƿ7^Ui'.N,YX^];C[W<|i~0Ʒ?)l9&\֧360T„lwe'8Fwޢ)\Œ֔@ (w{X _/oOKD6lUꔁkxDYbOV'֌M;TDbFDDDDpvt]Ͱ6ͩKɳ~xs&J|tϛ/bk[c>cQp?}5 oaV5>vDk%}r \𻙶h'*tm Xx;.1W7%l=Ei+eA۪J' 08;xzS'9s;dTET+4)W.(f:Tq N]\h0l_>ݮu!v0*FxF.ikd/~j~9JF`}X"SJ!iYw Y_g~M3q5=wo$CWaK֙8A%։/l9?K^{⊅jU#""""R>lyg%oQ \+%χɑvo8|<}937Zۍ2k&>4f3T3%2yǙ:q#TxWz{1-gGWt{FVbτ//Vkj-x讝,ߐJQPqVT#""""R)HNfLϟ'VL˚&00b8a`ZX,1 ۚ/%i oOłŚ_X`=,plSdW(lzn5*>1ll6l6+2~Y4JM|rr gfD o ʥIK؜aBmzMAL#gɳZ:΁ɤ_ȒjDDDDD!οFEt)ւLJ!RpsϛIOۖ)$fOZ) l5|-V5Lh"W{jX9IL܅f/VUo'(N@K 腟 O~`{" 74eT}WVLA{{k\GŢ`ϛ3'9ˀjM1"y 3FDDDD|RRԉ &9!"6e %2-PڥG. аkxFLزϷqh5<ȍTGHvbVZ\'ςgDL@ĔڨFDDDDҭ=""""""""v*Au9DDDDDDDDR2BAIAIA8ܯJ~~Q*)"""""""p۷mF݁bhGwᦥ+hDDDDDnD;A{R2)=QGwᦴjeyu(0ӧNq.'讔H,(H+S""""""""w֞MA8nnyݍR)Hq80 Gt RDDDDDDDD Ρ?~?6e0,lc!y 6R$fƸt,x}&t,J'< `m͏r11(Omgw3yK-?ֿØxwek|JJE\nx!2yf7X窄ʹE8Tncqa.u%t'f)2O[7l. V-a ΧD3yN}&z~N'Ω<6x){ M+jDDDDD+-\QLq?le#E.`r9|0vmL`ǘڒm\uϭ$0gdkâ;n,#53M C5K7"p^r&SBf*}\w oQy~wW02};YIK~,V>֝<|F_sņϱ$>}pM9uB)WNxV lr#lؖLrZ>~'GNؽ5 /QflAn6nNe qsX>>Ӝ՛tVZ'%-M4G3uF7w/C:cP[ώ&5"7( _ĝ_26ōRZ];Y!܋٣<+rUFDDDD4MENy4)j'fu*||}nƳ^"t bJqmT#""""R~;)H;)HSR`"|""""""""RV(H;)H;PVZ.ܴ4w]͛5 R.z磎Mih])4GGvP`&""""7#"""""""b')""""""""vR""""""""b H1RDDDDDDDD)""""""""vR""""""""b')""""""""vR""""""""b')%u] + lǰ)uaIgs8 '?Σf!-^kRueb&9'< `BJ$/֦;fD +gҝhɪ$vX¨+{=v89ǎA|n$i,ЍUpT#""""R>)H)L̘\՜ay7bHZqrLpQɞ͂ijÏ~VË5kq[ZzW䈡3mצz%/|jfsn_5h=lFs≧5|y7#;b11͘iЎ'CL8Ƀ}ѽU0ռZ?M>YTtDp;UN.O18p'dSdFi9WBF` /*O0=NWI5"""""参[-0݄kTv&W &Ld+ %7ɡ'0e1rHݼMRBCIJxw6z N}{^bd$aZTJ/f#kOՂ қ$rOGubĻxc]ܯ)UUHAksrW3Ms:y, mR!6Nj|VϘO_)t{5/d[R&K0ŰwlOI18W%4n-ɠJ,]uގK sI}+s=1[OyJasYжjgp>%cw%4(=_#/[#?'RQ~nT 꽈~A5"""""ϖW.(&gMM0`vw6&cLKm6.qsk3n^TZy}i>_D#3-#53M C5Ko f*}\w oQy~wW02};Yů+70ٿqgB^jS3 ڰ(fE4×jd =WlK㉝הSW,TIAJyg%op&W?F|m$'wr[Kp;8ǁ3͙_In;`G3uF7w/C:cP[ώ&5"7( _ĝ_26ō֌M|4h8fͩ\]@Z];Y!܋٣<+rUFDDDDg[;fY#'ٓr '[ͺm0_|r| &՞Z.1= .E.:<;73zW%"7BI6}OlBdc÷Š3h|oB} F?&wOVU?fCF(.f̻I2Z:v{oi̪)C.u"I(v{DDJf*G52yVL 7Ci]1a˖b60,h5=C}rSu"GJhbډYi  аk}!3:1SkKIAIAH`P*)""""""""vR""""""""b')""""""""vR""""""""b'gGwX2]iiJ9>7)k\HG݅ҪњRh֡LDDDDn&GDDDDDDDN RDDDDDDDD EDDDDDDDN RDDDDDDDD EDDDDDDDN RDDDDDDDD EDDDDDDDN RDDDDDDDDT0n2ȵΡ?~?6e0,lc!y 6q๞:'< `FDDDDQr f㷛pmX`d%&Iܕq g؅Wb9nމ{T+RkABC;u=Dx@,wgcԷ'%vKF"{ЪEu*\DnYbO8̒mitГ t_"qfLl]<ޱ.wA5"""""凳; 7HjiNU\2O3 U*Ӧ{}x[*8 (gk^BRj:^淄L= 2:Or~N'y\Te 309"!Ifi.%&wݚmKuߥf靚[+Z. bj[ 1p`f ǣùΜ\ys5®tA]3zJAJieSx+.f\;ݾ6/Ӳw?7[\ؿU[jRY}ߴҢy|ᷣܭzy)֖YN;2a=Yҏy.?Pq<[ 7G٧ꭁϒ+E)6,徟P #o,3.H}.q ,'y;Wq9 ϑ>~Ŗ|jDDDDDJ'}-\*ハ5!%D x?&&a9Ll_-;rPj֥r=AF\1}uDI&F}+qWIA F&l~]:giޣ>T|T~:y3cH+AٓiKͳrOQ&ݣW6ẻXFB2\Ì__o\!Gqd%1szNMf\]a]3@LH*!L"{ۏbL[ڞNbR#٤MjE+˕h} ub~WܱNl;`aL_Q2TFih`KgqEsfI>瀲uhXg&مz3FDDDDtRR D:9QLB(nTs7ݘG_:reɈoÁr;b-45i28"K=£E41aƑ6˾ yhS;2uo+Ƕ"zlamT#""""Rzi')Hq')Hq')Hq')Hq'%Ū1݅ۖ4F7G&""""rqwnHAe>ީp[Z"Fcwqs(0ۉq')Hq')HQGA8IA8IAJ)dKE{`kKg8l'<{ì[Ch;hqG2F\"aI.rdsQkw?լVh?`"_^&Y6~(ZlH~V>x3J5GsYa`sL~v49[8YNDnJ5ǟkj 0g_:Ƃ䢊NVZ<_mu֖1&4RMAJieiH=FR4<&l=yOcqy-LϋOMgk.[)$]z5-t,OֱmW2 ! 3Q.qN: !Yl:9W~{ooVnkl K?LjAvMY=N\ΞpAdVHb ZS>`B)ו!1䳝޷5FRNd&~H#܇?% ka!qvNjDDDDDJ') tٟ1!iT/L'f^k#.f3+/ b;~P?>xq]A *=ڴJxvQxc9^O}*X FF#F-y2d}ȭbfthh49={N],D IDATbLח&U\: އ-e&<AH9o,nxYٗ/ExmFDDDDRrgMլ v0&1`>x"a$'ghX[ F&lu#g t:QӼG}| 7>>>N>r`f i9KͳrOQo2Z?Wed*ۀbY\W1MvqLեVlWo~!>v3?;EVMd;~Wth;7r,\6<{KLd>j)Cy~c۱sKv(sRrj{8l6l\O{GV2k/f\Ghw%˙\,][QL\+uyߑ|"\spO2'AL5""""">ށlI: eYگMW'X(6TAE YL86ᯬg\M۞ϳrF'\Nvl1fLxO:4獤W_?H͑PqF6+䆁JТZd6,Wq!,֕"N;Ŧ'팃mO19Eu^[ˠjn8SY>jvq G Ϛo 灗SaS5 LֈO ƇhL}{#P/P/bfՈN%>HqgIn*ѬN.tkpcк߆yw[ս?lt]x:r\{G:Zܲ5i28" {Ghb hÌ#m 89:##^"zl+F5"""""q')Hq')Hq')Hq')Hq;PRZS]minLcts4n"""""R(H;wnKVhn@cts4nwf""""r;ѣ=""""""""NR""""""""$)""""""""NR""""""""$)""""""""NR""""""""$)""""""""NR""""""""$)""""""""NRR fj%Z+%.eY; 6A0+Fܑl׼#8?EƗ'a,H.rdsQkw?լVh?`"_^63](֊uά'>;7ì[Xz4vNm|i9a׌"2rN[ι޽5Q百7A/EWi[r%zGI:M.FDDDD9n)H),혹HF;ׄ͜:iz,.?y:q]C>}{Xn4.s,OֱmW2 ! vd%K|}@z _,L)|?&Bt[[[2|vz3;c֟ /:l?ǀ̄Oٰw?{`A,{jK^8xjDb.|;0u^7a-,$PH 2`t1bt1Y!"82~;F<47*b% L@N".τq}iR%o/_UCh@їX {CRO<} R`á58y(OW7aO2>Xr ۍM}I / :> b11MHHܓQ]/"KPuWoW r ̑ž7̿l,&W0BycquJȾ|)kkR5""""";=+n­f5|MఃW/ 8O_Z' MZ}ٍMیqdck <ʓT8:ɯRY~axچFxq$^F5""""">ϖVH]O[ٛrѬ y}mB;3) Xz1k]\X}hG,;$2~U/&lǬ?ZPb;yOc눖Ԭޘdvh]p/7R&Il\Y`AͷPq|@w;reMƹBg])j[pCnf}5CZSY ɦsGTŲ4r;m1fT0$w0M7IL_ԝF~eF/+5BjMڤVN\݇`ZW*ח~"i3r׹7㿈]KNeinؑƁnX||o޸XF|0>EsfI>瀲uhXg&مz3FDDDDtRR D:9QLbr- Uh8VO2[0zF#|"\]6xx}Xj1r˖:@p_ɔ#웋 t9(1 3)dՆ$p;2uo+Ƕ"zlamT#""""Rz)nf8IA8IAJ~;ARDDDDDDDDJ)""""""""NR""""""""$SqwX"pݘhDDDDD)A5죏wTZѸ9D8IA8IA8IA8IA8IAJ)dKE{`kKg8l'<{ì[Ch;hqGq`'cW>ny`'혝f+F\;֊'N0+(ͽ8q9a׽wwIoC[+XAUj0uExfM: -c>bMirA5"""""Ҏ;z(7iyzMY{ _3)[ή$lC{xU܊r97{4o?\=_&BtrwyooVun K?LjAvMY_E#'}!Td;Gv/~~CvurSGIYLG3S7eJ Iq3B/ՈN RJ-F#F3+?!c$,CCzӨ;.f_B; O&f嗁?c=}TC1Q8&~\T ψKq1\M}I /\O}*X FF#F-y2d?KIgK 3O埼1]7y%$Ŗβob{e 7W7<ԉȗ" tjDDDDDJ!)w{V:݄߯[jakBΓ/p.!vw4#X]n^ ޞ4 pq{SՂƍ[5A*>LX9lRV.%qB<ʁd"qw]`Bڜ߽%O&֥KxTU5"""""G}+{ `&T&ɬwͣYjBERVq"߽ ˙ց"dDۼg'r[,Չ^} #c"C,ߙb qLZ#jaɪn̫oM4 ci2roO`I)69+xca F- Z9{=1WOsMDrK~KU b%zAkS+4Z [4ל4.:&#f y6 Y.3~4Q2$7>>>#t fƐSp{[ɞ_%aF Vf7m̃ϭ3euNQǷţvM Mep],KfRxcVT#""""R鎔;Pޙd~>5:uk'g[)FWujf[ƽl5*?J_өSU ؎n`QQT0y3{TwRK<m]ռ165Înǎl\G௪b`{wvtw @1Gg}Z?Z?8]ih§^Oz3mU| W0e;>gAke}iijQ߂B){9awjDDDDDJ!}t63_ _{6dŬ~}*_vMxRm1fT0CޙD>kņ*=h!Q=!E&mR+B']YDCX0+yet07 /W3n~X0TFih]!s&=, c :Z'F|0>EsfI>瀲uhXg&مz3FDDDDtRR D:9QLbrQob y FH>L<'rH~ |ݕSK-FnRJ3W/ٛ&SphʟTnKv͏mq5?1QgcolVDmEڨFDDDD)""""""""NR""""""""$)""""""""NR""""""""$)""""""""NR""""""""%;pc RDDDDDDDD EDDDDDDDI RDDDDDDDDd*Vwn[4A46Vhn@cts4nwf""""r;ѣ=""""""""NR""""""""$)""""""""NR""""""""⤒=s͊PRDDDDDDDDJ)""""""""NR""""""""$Sqw@DDDDDDD^$''_Zp8.MOǕJv:ݑR*fj%Z+%.eY; 6A0+FܑEhKۇ=sbqMF\=˯_ :BvoY Fh5+8>9aQWFI_q"rH_ub'c`kE!Wi[r%zGI:M.FDDDDn-Z-x!GD`<`sxAh֌<@Miܤ)4QAAJieiH=FR4<&l=yOcqy-LϋOMgK)bYuKO'!΍bȽnoW%)5˯YqV},x#o !Yl:9W~{ooVnkl K?LjAvMYL#rk夯`B_:uӡ)95z>^ ;ҳvaꆽOI!)nZXH\k^y^yyK^s5x; 2`t1bt1Y!"82~;F<47*b% L(_w ֦tj].fLf3/Pt{GΖGC0r4%1p9Te[U#Fɂ_< {2ܥX夳}mMz2 akKjX]t~+ T!弱gNd_FIvRGAk7V&p` %Γ$6J,_d\8+#ʸQ:97GyuV*d߷ct`o\VazDzhydr1.QQVl'IA8F"9xŵЯן3?ZI{'bҥuU>x"a$'ghX9CzH܌F,ui߳!Vb$*y Hvr3ؾn [w K),{dӹ g t:QӼG} 4{xO?O>r`f i9XU"jDPjjK[~#<*Qyܥ􊪅Wɣleqid_.#RxcVT#""""Rў;Pޙd~>5:uP )[>tQǩ$b?/3&?pU 6s|'M` \hIs#yW~ԙniaBSu{&E.wUPԘ3[c't2C3Fr3=;w{=ZG+gGV2w׶3ﴲg[)FWt;04gգDž R$sv)qwfGLi(ۀ.ϼ~-(o0o>{]&?[/G Z{y瞓k89n#M}&?g_ǘQbFRǗt9z1덫`R#٤MjE+˕h} u gY0{͗fj_ FQӨݰ %;/fmSA,eќRd3hֹ\amkN )n 6i$cCJ#)M|^6s֞C꼧鱸J*2(Ŧ'fVj ädǼLΘ'[Ord&2gOG536vr2Nr(%{vft'Åv2?g {ٟBR j; @5"""""m1`t1bt1Y!"82~;F<47*b% Lph"uF`ؓ i83ͦ^ƌ՟m陽+O埼1]7y%$X$.5O}*X FF#F-y2d;r'M2aҀT '5kQRP^jۀjwDvO7d/n/[:FLx*rX\R'/#_$)Y|vn5k zieywt ~g.Ga$-H\jM6\]FbPAmKFVazDzhydr1.QQTN&͓& p#yLvFu j%e4o}yŸ[F[SC?سrODlb]GALT#""""Rz(H)пY8BZ#wF6.uDLWpEQM'Dz=9l޵ I+7>hS+U ^z#=/ zz@Y.uQi qlZ#%d]l}7?4&mb{^ £{F<aS9gtS4%`3E'ty={5^HTՂJ 彮vmXaaG+kT#""""R:lie)Ihʛ`zY},&$31@ .:%57'YZ܋=ʡy;|iiԮXG{߲Ƚ:..w\<#ez V%not׋>竄o/o6 SV3JφssY:`hGfFtm< 3篞58!ؙpK=}D)V.nx[E"IN\χwѰ&'{kw/ۍɩDϥR{Y<4 ɛ*>I/Yrc͔S׽;9~r8}/kPP.r g t:QӼG}| 7>>>#t fƐVLsMa<5iwMo9 Ƿ7muw,.- &KuZQHi w&}7YHzz`O_8ͅl?Q{rJܕ.݃;Jfl> 8xld㳙ҳ<6\{!ke}9;Odk#qIȪFDDDD;Pޙm|<`1Il<:Kv杵4=鋺ȯr7{7yBvrG{jvqc} ^m}^}le ˆO ƇhL}{#P/P/bfՈN RJ!shV'G58ɱQL.dOӷ{7{V<7M-GD6U1|v;; K-FnRJ3W/ٛ&SphshЇ 0ƀ68&9j0uo+Ƕ"zlamT#""""Rz' XnWDDDDDDDnCPBA8IA8IA8T()V).ܶ4v7197)i\㝊 U+b4v719;3' Q)""""""""%')Hq)!JL RDDDDDDDD EDDDDDDDI RDDDDDDDD vSp ;N]jb?^.o?\6 + z~q~}q=a+GCTmº`/bo\~A((A0>W tҟpvy6|w_6 vHz5i/  ; ρ[[u5aޑ3{31#{FHa ]s^NAoa??g Ĥ`πYow_]> AJjп;lFoIpfq}b0bC~hU}(55"""""%SɟkVA쉑k$+{sg@∙5 b*$Mp7߸K@c" **MTDPC@DWeXYwg{z~U眪T1_Է9_-/_^ tn[/ol Ix|<>W48-֎fprxc  =~=`Cw28@yp/K6 _nׯ?߫{.2,~"@X7|x`0C$z.N9 > :☕7Yo,}6,89иN_i 8\$Óc |nx{u(<9 ;ʿ>zݐuޓݿ e\#$I#Nw-0 f[ʝ7t> WB<R΃Ynw%pc!Oy P*ѕݻ} ׈=sEp?Ygwx;W7?? x> k/s?[YwpuC\ k21cx8f_/G π?{77" n [t\#$I6"e{#p`֟743KPswO<x|tۍ<4| %c{w}Gvx^zaOyv=gMJrx]N&}ن?8R~yNx;_‰9~2xKeUpp'3`rx_u_ /'mN 7 [~`4SI$iwi Ùs_x9p(t_7߾^J8 #{G>w>8#pߎd]#$I*bĭʒr[ciIѬ#mƟŠv~~r}w!n} xKςk.?e8Pq.pu;;?z!0wv< {<{w:߆˾6ʸ,n ' G| z /Cb.?n~4'M?ݭxk#fms5 tUMFwo98e0{}&]#$IrwyWo;m# E+?37=N >Ywá;œ,~ <~.\v.\4 πnX;Ά^{,7Uoͯ_Gӯ#O}K(__~pֽ=IpjZ \“/psp+>í7 =᫣}>yE7TďK#7]7zeq(;,x&L8snz xtF$I%I$IȊI$IŮ ~_t'hX̟}$pj"E$IGnlu8yϛMm)$I$=ʽS={ᤓOM])$I$3_:F%]2Ù#E$I$^6ϊI$I1AJL$I$I~"I$I4E8Gʰ˓=in?7I$ibEm HD)H-#A \9CGK>$IңW´R<깓=I$I4M8G$I$IH$I$A$I$IH$I$A$I$IH$I)!&{c`"I$I4FD*r I$If|'{$I$iAʓ$I$Ifd?gdA$I$@N6+I$I4F)$I$Icd"I$I4F)$I$Ic4僔H$IdS>H$I$I* R$I$I E$I$i R$I$I E$I$i=I$Iۖ-c{Ͻ=iaL9= a"I$I(n[޾<ȣ&{(ۗ-{9Cw)$I$b<9G'{(3\/O0&A$I$I{9&{ҽ ?w)$I$mEaÑRzdOA$I$I[9<\4H R$I$Iڂa0 E$I-e?l; #xĬH$I$) [^+%\oُO^b{1<}9{iUAʴ"I$Ia"DŽܓO:>m݅Kns(?W~vr~t aN 034R$I$I<y+Rb.~;m|M/`,:0 E RUdV;|kne1O易pKCOG>=ni7;QPϮ~/2nrgr3gGf2)$I$mAeoy# oi|~wUe5ryLZ#u}.Og)37IMK$I$^g\ojvyp(Y+]Ng;Kï.=nU4޻b|b{i]S_]ʊz .I"E$I-֞. YIQj<T^~ł=/֙dǻ}~>\S8'CS^}{Ng1t=`8/3si_$I4`[{ra saG`o$2A;Dc+=j۸}#+>,glhՏm$I$i+R;} =3_1 /ܿ|߱'|Ⴋx1Y`Τ,va6"= Ś: +~?oVPOc ~E$I$I(r&ƽds'.bї.g憎3_t,fDf3i,Ыo਷,bw=h暕%{]zǹo>ǤL%sEp+͝XxaW(q/ 4sKR R$I$IڂAI?RB8-q[6|cA&ѻ߳yͫ6cO|f^'J.:Wh^{g $ E$I-̊I$Ir0)gnkq=fnAA$I$I[ݹJv(ط E$I-Yn^)$I$b޼yTU $IQTU&{( E$IQ?xeYLp3?ϙ?w2! R$I$I{- 'ῖ._s϶S$I$M]?wp'`;QU]ө3uȝD#"FLnh288ȚͼlbmVfT אnwT(+lFuD 25rȩJUTeNH@& i5uzߓݽe%>$I$i-o{-ycUVg@b̩REU$r9htnPnH6`[e]Z '37ǚJִ#"'.{3)f6jf2Giev heQ*kGdxX$I$M =":T1չWUZSubEjWE)s䜢n͜CՊ\\˞툜!J#. npw՞K;tq=,1+GY De EQ(]"7e9whG;RU4"Q$HQDh*C$I$Ή;**VU !юN]U\Q4sQȭF/u`y\X츴,ZDΓҷ>,"D#fA.ʨ#(ne*S,ɹyȹEM;J)$I$0E#rQEUew!JѩsYrnWD5))LDMZ??"=D#em{;=;Q,XS\(RQGr' ʨSHEh*2hh:R'uQ4F.Rֆ!I$I rdTuRDDYt+Q\V rh4TGE:w"G*"r&Lγ".97ӻ0æm=)#Io9vHQ,9;rJꡔ잪U&)F٠eԑs*u)R;W͠ +R$I$Iqr;\$r#sT֭ Q:"GU6[U*VGiE"rgueŊ ֱѿ($-j ⳵0eV+*͜Fo*2ȍz;);)$I$0E7)uٛ*.eQ F*51(ҳeE J2l8_k7+%"jC{VHQ R Z=6\I$I45T({vD(vDD&?ǬV[ Q698(0)kmf *S9 m]fiL+oV{Riv+Rg iVk$ՠJ$I44zc]бќE4Y9ZC+sU:Np/D̋2)ܱ4ܱXoY =XyEzh}0e"I$IL Tֆ'=ss<8g^uʮ7L혿`&(D)0`]fi2 uʄQ$I$M)k} U(3D R`n6PY[Cv T$I$Iz “( [y`B 6) T6U$I$Iң`d[B Q`{)0z2:euK{;o6T$I$iZt), v&jkB!MY?vc1cLy_<"{BMj)YkPMo)m]ҪܵtDkχRh5ʍ)yJ(7C%u!Bl_Ȕn  a\,(DrbPL*P#5sNP+j+^xBzCEl]ttQ:ɯTQ)mv-,JYnDq ^<"A]!B0 H$3Ƶvq-<5Ɖ/W3&d/j^jA+|U[ø܎IZ\J)(mhˋj *ˍjJMiKB!qq/- x1xDgqb垷Ma}fWWՠ ~S1ҕVQRZk RWH>= wY(ϑ IB!Ӷ1q㳌]7Aݍ$ύʰ^x%Z71K'w~FcӫyY#mіJVVWYQ,kmc1FvB!,Fbxyx7e\/np0_# 8P hD8^ƪ|/uEl, ;Jk-_Hi/$,Br1 n9 xqPюk_B!ߑlc0}!ڎc\0;[n<7dϸ;^Z08f'%ߍgz9bt_ۺܵ61J%zғ\;fWm\(hmO~і-8RZYJR*B!vkqk,e{1W{q<e+1JrD0FpY&)4τs)IK*Y^Z뢞7 rW:T_@־RUڍ%Rqe=KٞQvܧ>R\JڠjB!\<<-Gte^L[ = r1ilgl22cI uFkrdT唍Y_v(ҁڎGmӶ!;s[Ƶ-=vu!B4{SN\񼸭-񘶔9ʶx &(yx>cr -EkJ.R$qUA Q#t** $zZ+8tm+z2c{Fَ~|Z|~Ca+[kchQB!;L۞z`L1ng8xmOyUR1.&HdKd6(`6j%Ws);WiZ&zӵFJ{ҖE)ea%zҵp]tHU@6~c6ԅB!3FyV1 b^KǴuڲceT3J)gg[hm)(\t… -SɭM 3 ikWJiX⎣&MLH2Z> =!cT2&lFcl{B!ߘk)1Jcq֎\ϯ}5ʆ|giXJ<-TtVѐV /;hǂff{)\3WѽSbKb,B)S*-ڧevll0EUtHTmTSIB+2(B!vqo5-+[[(*Qbxng/ULe9^\ltUF5N4B~Q4GP1Nc]^@.$p(χRq+PRVk Z[ٞ6~˘F$cg;hƫi)B!ߌi۶<ݭ)7|hL/jV1VX(\O)7kLeY׸$o.h7EϕiuI{1ީwhlhe)=\jm,%n}OxD9pJ; ۬NϢXN2339唓yC ÿ`M/Aqϵu+xGAA>vD =kRZhS/5U..J f̉ǹ98k3Ë-W^fEq?I~CSZZ+Wx}݇:?/Ȣŋ{f͚͝wݵIW^i뺌3/rڶݛ+6mYЭ[7GizRC!N;P ˲7~<_s=qN,]‚-bOTC~?奥eLa }Ï81؎RCj /{χ<裔yw6w}#<­sC1tI;ƍ7~=sr*ƾ5d}q6׮vtÆgrAetjHhkDGv}D$'2?_ѱkCpѣ2d&cXCqd! .gǤw&n~~}zEd57?VcPWJ#ptw_tSW2/Y@vv6r wBY_\Ļ[ަ^J2N<ϗ_~?#ߤ^z1k,.JZlIN9Cڥ kW\JJֳ`/mH8L(!C8#( q|vF<F)őGIyi Ņ[]?Сש#H{d»'"ĢbM/|zP.2zM~^nr˶Cj}א! zC aPVXK#_" T)S~G`sqQ=\vŸS W?N?WFW^'o;I]&@6]v qD"E"Q-_F#\>OcƒSeRljEB!UǨ+r[z _5~I\bk0GOO?m{7o^:X~Oe>O^: >{#bz(#h .EK:\ec%Yl){iE]LQƼͮ~}MTy&ۿ袋kycgRPP??e[/\ 70`MC;~•bٲ۴K| o¶-"^9bjvڱjR +yGڵ[!5.*'{ ^=&;< tD׮]}"b(+/ep-tI&{0f8:uȘ7SxcԨ]1A/e1pf-q_a&Ì3_/ O$Ğbzckڷo7__f`/~zƘĐV.[JFFfn'0m4:¼u[neY7ڶ*I,W'o'ۤ--sA-೏&WޒrwS ׊7b}3}mZYf|>̙ݵT_fmb˫-ӖYC6W +~uR{Xp~.[ڍg0H Y\xqަuUc}E+&== 5SL!}1NIOOM/VBl޽㩧fɒ%^on>Yp!K,aرTc/Y^=D,I|My^|Cvv6-X˯Š+kcxiH~g/_Ό3xgػma7YY͘3{6c[i×_|A4^ZݦMxb֬Y7 09k& Ƈ˲hOmZ߶4]| Ç`ԩ0sL~bOSCl?L D,|\ÿ7<1'VsȖj_jG"jmxD"}g-V,X,ƚU+Kӷvծv6o ߎTZlܹKCqF&e-zxCnN6?|=֭SVN/޼ysz?jCbX,u\SmWrکrWƨQ#==:Fո>oų=Gqq1iiiza\w D3%pwu\z))wy'wy'^t\w ̙DžGy$|-p#p#Wۮ֚H4?Aaa! 6/#d}V<. "ׯ'++n{9?p1O-~?ϴi(--ڮv=ǭKqQgޮuv@˜jZY|oPʲ-7f*UYi9FGmL:,ITT-n`)XѰkV.kaG0lp]Ûdlx>,): sFBƬ*ڶ'x9CFoq8׬eŔlõ5k˯P?5nKB n҅ o4B{QVčwwڟKWQ/ 8) !ƢQ X_/J)fdZ9k< F!VXFzd4ڤN5 aOom۸CyY9kqk$)9&?^]9дy  d| M5\`Khiڼ%Ih}BlۦY,?M e8}M IDAT8CqasO<ǮQF&ұ,x,FnZKKX[=U~z{o4iB4% v-.%^!R;1#LV 훠\/5y^{x%n\pE;f+/Žܸcĸua܈Z7-k00WJ{\ӛ{syw8̳y=GfY$''e˘믠5x)))pUQnF"p岥՞oh$ªov1dT\X_9Wf .wCiyYee[|M,eՖE/]RmقyV{ jEnhaͪfMW=5dcB6!rsYrHmw(Hng`UWp͆V<3rX~A1誁 >\m؆m4jؐӢE "`$7?B!2Hn_{yv3誁 ;nR*1McP KB!v]Cvݷ^+B!LB!uu!B! B!BAԅB!$ !BQA}o$B!Ės7B!BHPB!.B!D$A]!B:HB!uu!B! B!og7QB!uu!B! B!BAˠ[>{w~E]ݏC'rZӹwD7y|;"){/㴞sjxwSL~xL} NٟjB!L{fP`gpZӫ=N$s ڟIqX4,kgn N}hm\Yo?S{^ś++"נ=q07]q*VGvG"ڱYe=48RuԫS;yuSV/_/-$'\CB!jW7`W~7Pk4M!VfW5nݏE/ᮃw%gr7gZ6)Ɛa̱;TxFM>x,‚pMZ~؄lX3E:?B!|{tP7p;m[>+y7ƽGɚſ}1Ѭlv\xjg7MG^b>{~2 &~ :-:7pp#eDFȌ#- .w,lY-c^{?e ]7* MàG3 ƛaEMrr/.8ڇt<7ߠX{3c8o\:l>-/гpwa\[#x`MtMx\>0w?Mrtݒ3g:+Lj ?tD"~BaP3_}#y`ܿÇc1'#|7hKdʃ xh:-/za|t[tCzjgſo%ɛ h"^qǠn˙4n kHkoF*_#Gʸ iurq)Xی!VFЙ]8O/%ӷtV3q{[:G9s#ɝ6/1)#݀Ek.F{!Vj*JtУhsBV֋o|3H[_’3}FɃq)y8I9.D( g6?`.:7^dqҚH"~g7dO_X^zoڜx62C8A mXhE9Zcw}KpQ6yh޻fptK87"|kp jߘzMdSf&Lvs*,;!-O)|-(=C |!ol 6Lgس{F/z>{Cya,O?;ـCܩڦj(Pg8>n{}.{/{8qvٿGoYsد NOsS0Μҧy_|aX ;饛yRL_&}ȻSSZȨCA4 }Rr»ÌB!DݱGuYg`VB_L7 {]Ky&|ӯcj3r ٲ]9^)>H]9cwEkC;S;>oUMC4 JZ ZnBcN_rOd%Ѷ=8q}wakp~O93>=N'0f^8䰓ۍVx/ ku1s&- k4r"@RZ7mCqb$썃 ȓ81m}y`:]7O.Cم<0>ן.(%p-Kęf:ӼpsS?Э3|rbt簼+tk|G[nC#ш^ǥ&%Ε3=wVGЌĹW‚סPOCgُ/>L_~ywrr_(ڄsᓳ7?8Sޟ!ΕHk29O; a 8Y>??]ʙ(4e4]ց8%yEBAݐOЗ-c}n!z=Zwlr=:Wu%zYK/Zc[4ׇ<4/>ZQ2ׂ"wow2AnDqL|rC3N^]e:~:kޏvvva;dT VKns:W?|˅<|k/ڧl-y 0XM[PH"ecK~^9ɉcA};en6Cܙ)r -C T:_,$w+O ~c@nJbPa:7 nr.e zxdqWfqeT93bX#T?@W n8dhAˆZX.R+_G@fK2Co Odcoz|Lfޭ7 I2&KjI.iձ''!s{mM|mXa#ڴ ɜ |r/4ݧ! SU`i쫾G!#%wibRP}Օlo9լ(a2mN VOԘF=Z=W0=oKeŴyl|)B!j&A}>Zۛv :}a֭CaO-Wc,Goa[X=M89灼t>x ԞX+Ȃ Pw}TT2rRWCMyWb#9"jit,u4P7aoINm(N\"K__R(Z_LhA`WE1P?-(>^_1g*eI=:CS u-6cmo4KF ey3ΝCjCnI#oC3oF9]8!s?baSsw?wZ+?5ڟy4jz?܏%se;14׉m2Gt_~`V!5$oBhy*C 0IL9 d8'cuMR^QÐ(.p!qƥ,7ѳ34jFb1CtxVOd;yO1&t80Ʀ15@n[oM9 EդΓo1'W= y1t܏ 9?6 Z]3s-~ɃofZFb^K< l+[!x=}>0 Ӹ3 <'6Py>xc n4q )ѳ]:^{b]u\|j3|[kB!*pQc*;/:#}jEd)B1[+˶ܘeTeng˧}u0I렃|&ESuPշLcF:^r[Wn8#xY\flߖY>n>^'>-nSNR #Õv)ÔbJZhW7I!Գs()--JII!)O9 uf=h!}$68W4cW}Bg#zvv1ۡ#ZD]yeK_IUҚ\ߒ*˖wUe4SºBȠ^WC8_ݜ=m۴ko,]**y6{ɹ꯿̡{ا"b#ziiq]881p\ߺs51ǫbv!;.^~ G ug,Wҵ\ǡuQt Ȫ_ݒ:$<9r!N:._ijA8yzN=h&z`ՓEDwe뒊/|x3~>^}+Vƶsw`eV:yTyEtޕI'X8䋸OYXׇ蒗8xVԕoʘpO.j_x|7'׾!udvuB>㺻wϾh='ϫ#=uk{5Ds9wyg\} |e QgãWA.rdo#.CI<2twA'],t< Os˵W2^\9b=Cx]zm)ŐU}٘ ι=ѥˑ35lz%==K9G/Ke{ vy像xoz(_ҺM/B ITn +ԗ{=LZL)!Ӄx?0hv=tp%t ɞ6_ϷKIj{4}/^fP`bL{^;ϳO'Xy(n$h>nq)qNYB^ұ>xuFN3 Q\$ïW7q(^wƛn>W%[iA43b{bT*bߗ,?ſɭ7CҘ'9 xx)OIh ţ/9oXN1WWҷo8晗zx#TtF^=e =~jOέ([0nr>+'w6)O߿qx͖/^GPqrҺ W0wGI8<{7X06ny Gap{l^Ì7tI-rNx3 3}{Y8x=u5KBb3utFC']ȉ{'mJ(’Iow3 8)!h6 3ohy]'ދ9<v8!um_&t;)9 o瞹2\?ij=2|.\ݗsYl hNֵsTwc4<Ҷ/!](o?)!{M23UYYñBPn}du{凑2!_rWޛσ/_w*I/%-t bOi<1eLn<>dX)%f WpڟAЬk5:FB[SF([!gI[ `yG,|%|\-L'E|'Ki:c^a9cL~ R+Zf#l!bN{-fUK_LSlFOef6g꯭^Bj_zw($zJLx1 s+^emoG}Ɵ4lӉYfE'ZD@h0)_ JXW[ M~+qMTkwg%_bp+ pqz'okӳ}FO35)rlb|  IDAT +DW3w&O hi(K)rmwœ"(}_&q[&pMgJorr_#OKÀсBَ!c8+cC9lv([lq&rx$mG)K6 kv.E(R'S}L L3^#)v2zګ@M⢹ I)ku)˾{RhҎ.Z`QU]`9^f؁,r_܁y.} B$QjŚ!QO[']ѰPἳ,ϻ h[< 8:Ԃwrt4AXL^^\ɕ89ssk~P~̛|\t{egiҳ<>IwS;# %63[ȋmz#Fkd<+>O`ʶS9vU E p48eK9ыdvp-cpqSS|`CJ[M8b8y>*Q0~/H3{W_b닯 zm[QgJQ`4;q *[8w N=8dݣl'^Ǽ7_fa ,٠U0JMxn_0\ bc(X/^]`ϢѼ?_ׄ fjk*>iG,"ƗlgNrɮSltO]Yt!.2Knɜڽ쨺o+V fŀ+3gKBX}8uV1/oROok8y6?]y3$-V<ВOi/$>\ w&?6_X2%VAO쿈uj{h,g)݅ 7ܔ~4f[wc)ݙq#zƳ4$2%O]8յ%mZ8ZaZ>Dd<=={!R@_\M!#yHn>KαiS&5ף'xá73ih#"lYN%V0X41|8ݵ$Y; wFctx;KRz/RMQ&gb VhM+2c!.蠫خ3$kX { Ws]?OV<Wk:j'[-jƇ_ Jib$,wz0DQL;>w :!&SƠ(<#chQ|KY&>[nlaIeR@o20?^LPeG^a* x.p<+ g3Q׬M[AH Kҗ1b A7i7XC7bH&W8ORA~3!vyQ(: [G 7Wܜ ghEgfİt!_P|o_y+>KdA$BqU>t=}P+b(퐒l5<WI1MF5h2&n6FbVN]1nR,ފbqyͺX F%huR*gO@Usc,v:up:WSrGS#wlfͪUtMGu(¼9siܴ=Lf3m/7cǷ'6v>U\'dhcA.!VMb5~ECWJr< L)&iPNCUURTKXµgЃ/auIOr ڗ2%Юpp巬y E3IHRW+fw*^N[!{ Q5m<+W8/WѤh^l؞hCϪ$y's?9!nsmB/I|*yy2-w9w<2k]YB}JW {ieDKrs)e?BdMUәg|KI;W'7Q״[)Fbt1)9s&\KBDʕ+lڰ!7F#:Ow{`@ ˹~˖A!\:;L:t!J]CuB!D[8/t.miB\~z R!rvɏ !B!$B!B!IԅB!pC !B$QB! I.B!D]!B7$B!n#!B{˥˗>w>Cy Ha@ż%I.Bw^0(<ѪM^"ٷw/x CS !m\tZZ^"P Xò#I.B}͖/ЦfUEdIRד߽AGRꃴ:5Gt ^zVD;u /i]*/nE5}LhՉG7ĦvNM]*բ:3bfOqآ_.Su!Buԫ/'$c]"ŠS']o™3y y{yU!DxǺLv43$}аA6q gn:JbT5LR%c ]S3Vx8_~Yvqotu!BM%CȖz=\&EQ5@Q3ΗtE` 'iyc*Rĭlھ)HNnKҠ_ꃫNΘKxxQ4n#}8 6 шhdȰa7s$B!p/=Ta5<~8~cۗpg!/1QC7㑶%Yv^99v*__|}\YBWy?_]Ep`pͪ?ץrZJ ZŋZY7g3>0:Fx&_Gő#y/B!p3n/}"՚th́QOO ]3f /е ߅{SJ궼)ӠMnMãxjcsH LsG%C͇(,ko6Ґ1ˏdC7nA7#B!܊h;){а 4B&shn_\chJf ;ʔί^t gK1S7n뽁7[׾xظ6ݫ 6D R6$B!p3,EEu!BpҢB.J!Wt]Ga?5]B.BE~B^$QB! TSϗET *ס9IԅB6ؽk*Wh{ɏ4Mc,X0Cs !mTR;ws1&y `AAyR%I.BRjռA ) !B$QB! I.B!D]!B7$B!n(ߏz媼A!BdIyB:@Ǜu$EQ8x yے2)'̙Aqݷ-Z::::Cgú:<':j^pTM/RF#&M2$+Q&yOWQƼ-HMBMH厔B1-@J$e;RnB!"B![Dԇ)q'o7~eg躃S {{u\wxN]gpĞ$I#qThچō.;ny֌zir6!?uxBc`y[D='0Y=Ս^(6_kέ3v=gqܑEZُjV}8yf  sK9: _bCs2w~9C$śd5~r7;6u]uy!=m3o<kO>ԫEyĤtO:%:9iQ05leWMa@F ?I-9jSweB{@5J 8nq2קS4iIqMS!-sy/w0Vƒ$ sz\>hcX]Xƍk``u S߰MֲxL#b?{.u,g~|#Ynk[O v<9kg 5uparܪlڼ5sGP}~'WTos6Qu$JNi@'u6.8s"NLH`yD$ꩩA1`0(}S>#q*?&3kcGգY]GS8]Z^AO1#8Y5=\oЧi}E57fy{;uH c#-^ɑ e2xuEv1o05mH<QStҎi gد+v##/RonztWxb g2t1pԮ|@^SXg n]zQ]y}^._9xT}x%ӗrMM8Γ4kZɂ5 5FRШ6L@y'II[qEO`\ qh!05w]ġ9i=(lN]ͪ!yqj2=$łqYlCG+ԣ~dyJbD6ldimńWpeI:u+X4W72/U/ABa钥;{ϟ;Dze "%-#H@}uίÐyy㥼W̕}w.͂TbVC9yO/3hV ^1>h9[+/lX9>.7#Fit^Sۑ;h>,q/ `JyFwwxjwJScN\ 僅Q;+gŌ3aw82`Ԗ/ÁWEA_X[-zAa͇sŰ8~"ύF!T5;!u/ץud_^ËXi r~=c?ۛX2_VRvW\qQPAMG`Z+Q"AoT2б?!bPZh@4TTm]Sj4OJ>ҝ ?DR:V&ͣ`q)Łj?/ѡ!&ba|M$4=-ɩvu5]Cwd؆wr.Q@WMH_'`_D45Ov奪fj\AţpUH^  B=y OdBJϕUn< ^~_~HlAi3C}pi;*HAtҫeK7iHpP.]UbнJ[TTo:TͿlד,t+xiMΩ*861hք ' UsHH#kP>|Hᵬ'!7r&Cy\cc1ɂńvY0\R.&FHkS8HXA 74vb^_,W_Ogأ5&?+ 0zUW[354g.maIex_?Ih6zlt5夼LAxB`W]'N+.OIjym5S,` dXUs+ uTx6ل%T|}l տ&L8]̫m`::FZN+欙]w$cW|vsm^2=dJB;)u]8lxZ!D~s]ǒIXh-Jޙ$ގs!CaŇb/rb2ZIu˘)D.o0g)nIcO7lں!k$-ADCMK6]>D=KKҡx1KpPu;GɄ30q8}ǘwbR&MMp&z5FOt]Cxji:nCOuދL6'笼?Ο Bu-ʭm)lJJ8B0Lqf#.!u tN]hח{_Jq/Ӻ^|ꨡ@}ݰ"ZZ׮/"ǥ.Ct 3^>>(7lX29R|Y]\/%qet'➧(0^7t=n0`H{>It}HM\o>e9(t ggT"N D%f-pl=8sx2̟D&20/gԩ,Eb.ዥT[Ƽo_$(S!-B\Ci:4%/v1Џ`,>6cTUmW."r?e X+`@ҖmxRp! .DBPKy^S1(c$PP0PgO<9=vnkծ j%Wz=_ &?W1Ov2:FTiD˷?]/ @xq'2`5EQF asoA˔|)J\'e2-ﱴ~}Щ[ޢAsl]@*u8/lbrl~f^Q*o*HݎU^+zMNV`5EtG1rB~~x~UUu+Qn;/ױJtE 0RfbJ1)ɨM?Ѥ&hV̊٩+fpzM[Q,N4/YUP znT Nlx)T&C-t`a6V\ET\C~g28xʔ)ס-)ܹMzЉs^^WwM&=r/$K^>چ`h~ AcP3G4ɉ=ݷUxzfM_Q,?xF"CsA.!VMb5~ECWJr< L)&iPNCUURTKXµgЃ/K [nu@Z{rKVGq#)ܹ̀@Ɔkc [<֫$Y %G !OudnIIYnf|n/wg (+~ꇞ__c(-IUIL),I厔BDHqȏm8N)2)7!Bu6mؘ!N8!=)ܑr?n!0!/$Q-J6m:{%!e;Rn%Pj^!Kۗ!ܳB!pC !B$QB! I.B!D]!B7$B!nHu!B!ܐ$B!B!IԅȄm[DєD!$m/U%,4$uLADt4b<ὫS=n{vNQ54yn2OSГCѸa!ts G58N~Gcl6̶ ڕ,|'ZGǒh=mî~\bB6=c&|sN^[n8cJXh$_jV+#OLѓ"\rTWf{4=Eү]Xxڙ u]1 L!C$QϷ,t^z#Ǐqp(A}`_F9thtϯi[mJy՝\6R8l"̾ Apd:7ҕyG\|XDծ1g8~ۃ7N?{p?~^=Jc kGfǷ=ʨ5d {,I72vώѩ_EcVA_.it{i%睙OKCNv)]|qsN$6}9+cO{ͦ@du#Bq$QEAQLxZèױ3ɡ8bl6N.mez6nC}iUH里{r {b]K 7}ZJmd goӿY8/>;>F93G v$>$ePs:O5ʤ_cH{ M=JFsO `(4=a7N ѾF(~ r9)X9u+GT1/Lޡ< \=ug3;#Af5 /_04z8!oD}9zc8.vJ"uDrXߑD]?Vq <%KSNr/876nqXMdgGO¯9޶ 2\w:9ؿ{mCY,~;־K|T%tv>ԭ])& 90  E@}45J_ԍQ|/ߎDP+ !My{б!fk:"M"_6洫jHKrŎ2*>u-⛣xp$Y/gsZ|._GR “f_]hswcœ7Hoޝ38a Eq^"沓}g0A;NK>Y:ц?+9~]X?7%RHgOW#)76L÷ϿAKѥt6i):=j߉-ςE>8QB.I-3m]*^(f/|7~5NSuK:R|2uru{o։ Kcjgl_PK26_WZ!M eޒo?0wRh4mj_ߩBȳsY<(O]{?ÓY0<d"R< D6'jBYͯ śS2tZROP54IW`YtD ջh|4UzB&0!]r̷X|XV|3K6YD.{۝3҈9A=fSfwPgq5SPYn+Xץ ɏR :Ve*O/jw|f4{aZ\{5g>!r\j.׆]eѫ+y,Y& [<:)OGR >iᄇjdm!=,88n ++MdI쯟ѧԘ85-=ќ;k3eۑ%Lݔ^;mV&Iŷ$`8=KWiF|#:Ѽ!\y o8-cih[*U PwR={̙U4YϜmlÆh;,[F}iTU;2k:8tRάݮϰtw/%i9nl\UCRGH.2g;²iѸc媹; j,[??/)_K^ 6cF҄f|K\NgoiߛoT:Qkϲ<9u-%)Aljt3:fs,a-ygkX>Ep vaGQd J b~5 a)P<8[,Q:qtgΔ0S'| ctLˬ(;έb+Rktrf8כSlZ=,Eϒ鈎ׇJ 2:"K5#P6D0h͑;mc0-9I˛Q~+Of|wvd'÷rx|MxMYJ58㍵_wIٺ ޥi6| ͆g1)?`I2};CLLX9<˿śOOBߢC\ !Bqǹ.B!D>$B!nHu!B!ܐ$B!B!IԅB!pC !B$QB! I.B!{zIS-_8CgIeO(w܄Bgj٦m^pOZd]6rG-2!Ȝt}B! I.B!D]!B7$B!nHu!B!ܐ$B!B!IԅB!pC !B$Q"=obGS:!BWGW=Аԩ2}OtOfXʮᅩ[8߁9~ oFPBɬ?i#m 0VvX~^s %쁖Ԍʡ?D6r]6,cV/+nAOغ<ߦ뜫Ӂז8<l^PBb,;lyCW ,4_`h<ӯ]Xx:cш]7HB;D|B9r+ %8NgHEǏw |Ӆ!7y5t'W7;<>=&/ɕ+ޥi6x<6c߁}l I*8's('ŞF3&ak1gxxX(Z?mO2jM+F!(gGz};gTu7՛7fٻs)V_pЖtw~JPh` b1fF;~ǙvCX 'wbH=L^pQ I,pꍵ*ؑg+q!-@.:56@pyJ*XŦi$ƒ tiY;qW&2d,P 3?Q ?] Rg6U"37.:q~YvR0t{y;/g߲9]z<ӧ2vgqa'?CݚwD~rv+?G'$7#,GLc[#CSN⎷iZ2%#xdF89y7# iBۓإ 7#B7"1]VCX+vdT1eY:ц?+9~]X?7< xW~-0?7#q|+ݐ{Ri[:}ѭ/ 2i U( G'? ~F#B//o:CS=! D=3Ռb˜ڲcw~?͜cv1V2w` ٬:Gt3d\`bJs0k/}%dBǓ~7g0{mȁ}xFL<քxLBoS;LBȳsY<(O]{?ÓY0<d"R< D6'jBYͯ)⺔L>X}עËdּ؜aן"c/dģsXB>tZve솂n41/ `c+7'uDq#>蚆蚎h ~\*-#_+V$ 3r~`)TmDv'uc6e} &oa`j.Ť|rUbԪeĠdoYY%^؟hjb T-Zj9zg sp5Y\cPD7PLZCdǝ)xU& ~-Ox-4VY|HBdiZIuMzDUHq_D]\L50<.uRbr|U$𶿃qg5&Ne`M+ÁDT.\]Lj-"n;_tl[oӧa&~2kMkc$逩?՚|˖ShZ"MSh]zJ`7•׻Ɗ2&zIR-\*܁2ZJZ2gjWlg>s2kn Xr;%іĕ;Y6@"`̚3Or)).%Ht3GʁnԶDn-52_7RGH.Лy? AxPE=vXoۋ?0cuʗ.ExRnvq#"(_&O~~-(ä(A<,ҡ\I3ԵTp*['0jѱHgLP%#/e ,a-ygkX>E\?6~Jt0*V\fM@H(V-o]SU(8b3wrgJz9ZrTm65cnJ3qn^Y*G4?ETp*V̄4o$urRB)BRGv.:vB!CJl0Z^)&`4g0T٤͊Y1;u NIx+ʼne4 b1=@AԍJlϝ9|ͿlCNhZˬ^ -۴UQw˗,ˆQHrl)?f裮_o=_]G1ٰg4kiP^c2.V!{, vQ j+Z0$P4l`J14Np=z=T:dT8^<} ;g03Ң.B!D]!B7$B!nHu!B!ܐ$B!B!IԅB!pC !B>Q'B!=d}.B!D~˗,YRvٓ2)7!$sG~;{RF# BdN!B$QB! I.B!D]!B7$B!ȇ uIԅB!pC !B$QB! I.D&l{"4u$B!ȯ$QϏl{yz(a!Se'myCW ,4_`hwdvNQ54yn2O2yC'q %l6fpb኿c}k.;bYo˟ߌ]PB#v^Vs z<ۆe,jwy\Tl0/k䞹Khb~,khiuW4%7\RLTp_PPDp`DD~|<93gνshI)ɜ=s i2%iMO }Fz{7ol0cxd͕eZ=,marWAB %6F}!(, %ZFbEw(g֕\}u=+ږ2=$sV~awkCi'}h-]:LoJK?P聪vYʻ;aogsg(_ƃdIR/2/Ѹ|)v5z;Z~,97b֡82JֆZ=U[ҳ?WD<r 8B?[fUg4hutim96.NM(ɭd5tZ \W/K)z=gOMV!( ,wkvN{QQv[Q*v ׏Gq#9r7 APH\3]! IDATM)ӝ<Y<v٬$_v85US!?f7&)\5h`4pd@t8{Ө6 ka,7Pn`)JB2[_'(9L lAÆ/?qgBXy Fm\& vm%}D! "DO6d3$ߊ~|6w${ϙ[5f@w(܏^Qk*jڧl%)T֫86x_^)$\8Q3z ֭H'LEm{vK3=ėI+>G 8Fb&wB1SeB6s_Qopʹiwa͖O{m-+9Znq`zۊ}*}UJJeg{/'nJsY׺0S!ϙ՛zpt[(}D! K^/K,] t߯+ѯ+T8Y%ժ6$ڍ;QHZŇ]07rM;dN' cxR8P##>@Dg3^mHL>5{jJ9hsGL0 s vGp7>ܵf[q/'-;OJc?s(1p]Aj]Uir[/͎8UBn\̾Z}hZ&1#BQXK, z'p({4y{Ι3G(}&5quk~Y{|-٩ռËEq&u~5HYۃz/!,E%:OǮ"Us,%,ǯנnGmk e֏H:_ا :;Gprvû>6#jzb[!2yn\IpYƓvwǦ`5^#lTHr=# =r8 " FbZZ$ǝfPᏛL(ELR>}-4w-Xm~ӕF8%$+ܦ[eyu7]E\5XI+CQW}ψ1:[g=Wu$>*}c #j;ɗ!(y3Ųa| @>C \OpGS3T=cɅwKN..ب}NmdTiI`V)þyMT:*tfb*Sz}> vͳ{udR|7eg#1SZ?zik83Y!v/y;DJSVyJӭZ*>xx6]cUފ:9β/cW0ûyo\N` Js[CBH_1gr\ľ5t\|G FLo\}?u^o|U_cd+"n/|A_ˮ !Tg8:Mz(bkkS"^\3}1hmNnyk[Z];o 3w|vNh475NꩧjwVi?r;aVh5-6A%}D!?trm'9?!Q`dkTI:΢?&T6 g'sK1qMbٺi!A|3;g`i#~`r68Ȳq͸]_Œ>-I2X0?/3|BzZ_N~5R7H!r-*3{vmgt-~_̍cyo;Ξ]eVWM{{9AܷpZ7/w^˾h5x׾潗I};MlJugt,}D! KSKZFa4&D$w̠)]÷bi;EgVogx5NS訮ǧJ97G]Q<{d*4ZZ6Q`OќW_yj89QFg^qd;SŦ"/Lqwǹtӎ#Lj+w#1`bTj5j-Εӡ1DF\"j4Vr3u'ҳyEMWػϿD=}FfDE]-j=^Tm^ӹe:M\H?6_y7#BQ(KE=ʳ8f3(QVG-ekuEk%1g<dzΙ*w7#^W08}'Qԫ8ee@ϥcԪk^()\-M<͋L'97oBs (EZe>'zrM=QSѕ^!E]Te8y#%RӎPvNbx0;б!)n6^slB wnDձKVg#BQz2dk/6p7gW4%S3Իw=ڌi*tvH?V0^wNET-C q a 8n/]k̥, _<23ŲلL;gT )8#ZK=̩y;}&SٯG)q8~=c6ѧd PW"%Aik'󿠡z]~U89AlwwSR28:b_Fqcp7o}jTH G1:HA>G̷}B >&xpmdF6֌4+z~sfiXܳ)4^ V =>\7!Q Vn]Ǝҽc[=I$3I[S.୐1w'c/L#>XWEc8UN3 @kzGd`e#p͙?1;WõHN;xGgtZ s+?S@ޛ>Fޢ aȌq``&o2k88:BiZڈUL! |+ߣ=槨JyR%N]Jʸ/57Q6c=rnOZTuFƭ:-:!zfW/)9rGp$HV,f3fX=dZ¢=$[-;K? o wwC>a:A5PoM۽8}Rb9m/+yv~ӗQ^kl6c(_φ}@Ǚun. [. 5v2n[$NĴLwP,XVV3g8Wꇳ|N%!)&%=<ɭ/v+8v+ku&#mM}l iזpZ~ӝH]89̖JfpTy!(y,,aAL~i :f\6}ò[ϛ2sˋ*7Fr^Q}uq?¶B[ޟi˜>l:+m?X_yo?}%vyB1%3WWq:Ƣl/ni$#cƱSҒKtat ݶU731ӄG&|"zG"Ec)S{Xr:_tX+M O^n("od\ QV" o(~\UW)X~Yzu]}de#BQXԟZ*5juԜOgGCڶnH /ygV+Ҵm W.$_jStj䏡>.d|wʹL\[G#ow\([&iՕkMV<38:SnwiW~ VNЦctЄzz_z1PÓZZǵjKz'!ҩhuaN~<õ*x?㆓.+灳GiJK?P,M?6]β[=ҺKBk9}X|HP/I8- j>tcnAN0s+|/~>6cw(x4l y[I_r8.DS_0wx*ngQ{G(%5uMd>KۀVBfw IK@{u*lCW+OCȹv.JKB(vMV6H\|"^1Mq+Vf 3~ԟ*1. 鴅ǧc( ~lz&9C31iL\LRccp2iG4ȜxL@Åͷc,m.ge{eL.# z0Ɵ%t}˖i(MXW"Y:amX@e֝Au~ά\׃+ےuE#BQXzҵbPB=̩sP> G IQ\< Fֽ6j53J-ڗax4]u;|ǥ^`H <ϡ+رo9:ӎr7( qa Yяd=UZ{]O켒D% }i>+'wjz*b!k7.f_>YF>"%Ai ''Gl۟ x'h9N]ƨe3]Ħݿ6\Ãr} `99솅DvLryd[k(~Dj5R̼9:mFԼĤd_fι;5ynEMqhRgW-^|=>oSeGי4/ed!#BQ8-ɄljQML& YKrKQ\ta&LmΌy] dd2cUT͊w pVL%9c1>q ufL&'`%9SēXrn}s ߞLY9LvG+VV+V^ 5q ebmܪܣwh1]&47O1+ӝ?I3]E\5t[t}Zٵa,cSBvaDmǜO!DHP/̱X2>h:v~Tfi+ga4`TiF޼8/ =f'ld=Oeo|*aٴUv~ ?zGĻ">/DE,zv*H9/V_aV9}{o|B|||`m%bV9W\cT:2q' d3H̔WHJ^T{n+ =vyB5%K֏FݮH!|FuCun7.#87sL׷}u ;RN8q1tKB’q{[ ql'\s6 D%ƃ/1וTؖ!߿_6#䲽-qߩqo=x2.Sa[5v=ܸѴK(*GN8Bxvt:Kq9onWw2/m9t(:n!2gG#BQdD]!BbHB!Őu!B!! B!BCԅB!($ !BQ IPB!*A( S!B'LB!B@ͤ6oXoW%m7ivBQIPOױK OKAڨ`J9!B!B!! B!BCԅB!($ !BQ =A]n.B!֓0.B!D#A]!BbHB!Őu!a<9;'&߮B!J* O!S|: x<-8q 'i˯let 0ehQ)VH:oZ_b1U)\ m0e9^2_a%nQfMI xL""L<3c OAIໆGkН1qTȝ2 v8$FmwQ`˧9Ms*)9h,]ɡ##2!5W2j%~ GHPZ3/L; ȅγ+˜DK^(3Y;~ˎmc_D^;aO8yQ-^ ?\ /KSSB FZþ|]:5'ęAѐR{]45 "]=|*AoOZjStj䏡>.d|۷JEӥ?T>m$/K@ȁF6\Z*mph֋YKTQըz\g+8~20EN~Ud6gL&n4{:ptķ9ʧ[ĵu~4vk؋C4؟Rs6930,Ճ!+>"}D! Ez `MmaVE7Ep8ڗ^cnANk6#yF_`i*?|n3 CiqBr>()\5h`4p&T0<Ξ4M6Qdd,B4-~4/g:^/wr6s+|/~>6c [6y=۸ M`|r!(6D0ne`Ӻk'R1'Y>ZF`~{UUԴϬcqL'&4xxZ8=y`{ރDg1):' S׷"ϔyJ3X?<' &}~ChuOz<`Ǿ}/#O;B"'ޣ=2tvih^֑g۾I]l:y7)kjtbXZۨ{ԣ׈\Z+Hs@oZE,d#!DaIPZilqpv;g6 cz79rsߪK̆NrQf-x;Aq8I0q׭}4mjSߟ:,#l:erη~yZC5mk e֏H:_FjUuv899슇w}:mFԼĤd_fι;5-OTjU82?+-pQNT~tzIcB:#YIB‘^)V&fEb6a20+ Ww1NtY[җjL DxɄdM\=R9S"gl!ϣ?,PЕS0sJCΒXz7lL0|1/u% y48d$d¶<2}WbZZ$ǝfPᏛL(chV=>Ëot%|5r;:rB "xnT͊w pVLs*}c #j;!DHP/̱X2>h:v~Tfɀ!SYǞy7>Ak-O;S{WAms601K_#DWWׇg=:=N..Tx`} [VOUNx<M} WG&w^w&-c$fJk+Ur%/=7~ OAIYߠ;cfU0L͐ī|;Y97 3MIϫee^@\1gZ`%~2]#BQD$?~1D~Ic# 7ҹQ|dm4oLaX)N>E؏fǻob)l3  N[Pu é䴀`}ah;.p\2<nt[s31MeOp;GOGq|#j`2 9K>L;c FBd_aLnvVxU6ם~,<ykLzYZ S2Nͱ0bG$?T5j99 $ Zmݐ^gmxR;{Gܟ)O9qAUjStj䏡>.d|wj ":JRk74k;NHPktuZgpŃrYs|o4ŬCRVQkVmIVpd2`(J6Xס\/2': {}ycpK4hi`ʮ[Gx`J^'֗V!( %5a[m>72]bM ^p~R>n0VFTzRϾBwB5V+ɗa++a]x0p.DS_0wx*ngQ{TG!J2QkqI?PPg9Vw>篟=ֳ A^!hI.o'g(اayhiT)ˏx=-YW>"%O+]+o %Ü:w}?3y gF脋{y[ɧCpIE%^ IQ\< FBb_z 9f^>2~s#IV#UǿR9xo1'6 t>Jk+8Wr &}~Chx]}_GvBU0|<:}ọw*n?ߞ}(fZ>Y8UBn\̾Z}?BBg')?Qr ZγS1yL\ݷMx;j52Dm>HlgUhlthu+\m,^=z3 #NNNsfD[OLJ Qh윻Z^K"]_#9o ׻CM ^nIAC*{?uΤxw!DHP/+f ٌբ`10L bߟMHƘts0G =aWn&LmΌy] dd2cUtY8}AO{qxnZ0>rNwɟR }h`M4]&47O1+ӝrAoON@&l1sXWXVV3qٽ&j&?'2U,S$?MLl"Db#1yT=Ni/+^&O?˝*}c #j;|+}D! Ez dʕFyç7cHTL2i-jW/5|Ը.&6{2GUƧ7>0l ƽI6S6I,=Eo۹a|< {c>"UQEخGOԱPGuxF}I5RjFj*GFkIiNS̊ZfZoVXKitZrب4*MѨKOO{VKt5mvlё])JKAڨ`J[ tF^lłbbUEQ2ȿZa=i6j kVY&FLgx7~beQTTkը$X&ZL{ZVjmVe5YMVYe15&%Qhl,fbܷ1[S-FK&uUfTJ?QB!.B!D1$A]!BbHB!Őu!B!! B!BCԅB!(o9)B! B!B<9~sIy O,iIBLz:ꂑΛQHrB&ٓ/B!BCԅB!($ !BQ IPB!%Γpp B!BCԅB!($ !BQ IPB!.D6'?qĤ5B!DI%A)dO/g÷%'D5mL՟ >*%NVֻI,ˣS:Q`@sd|xbY oΣ[,2e~~cac1/C{rDe 3f!nH!rtv+S| _/CczF4c0eM'D);? bδJai`دU>"EDJߞy>CD486~# *ڽ͗KfFsJR$ ů b&!VCASc걎As8 Iǧo~+Qαc? a g/VFGs&:&WhݫVL̾ ~~"zG"Ec)S{X,.[,GAoq78{y7} qV@Ž~?&,QDȸ>Vo+r{s,,=L>!(, O-jF}tjN'3֣!m[793+ID.C?_[(*{6N1v݇ޢѥ)ߺsUR&'۟dPtʵ,>"y4̱{#FKw*mѬő1RVQkVmIVpd2`(5ןkUuB-FDq ŵ/ϸdoyQ}.'x`J^䴡w,Ճ!+>!( %5a[m~PH\3ThuSy{Pxt)\? dj2Qkqəc,J;%py$Fy`y=GiT.D]jѩ6n .Պ9,kǿۋ8;UH /mj[ɗ }59z!+'`UhkVG ȸM5H0LSqj$Et>|zgJ*܏^Qk*jګ[*{ϙ[5f@f?k{eL.KLo{M\gRccp2iG4ȜxL@Åͷc,m.gi8~ }*j#/[u|6a\Nà:LY~x?gVo.mɺ!(,y|ZZ1}K(Թq(MLs% }i>Vax~\FuGtV?lI 0v#jaNGX qa Yя9rsLU1;)W04Dms vGp7>=!k>>_Lx%Ν>ļk5t53#Qiqrvû>?GJ6M 8UBn\̾Z}r4KBg'fsl?ġI_͟xi9Rދc[~r ZγS1yG疫y{Ι3G(}&5qMW9w';YwrwqQ_sfe@Q p 5r7-FE3m75K2k˝{e["{ 3sPA|C,\gs3 }CC bDM'0: e~?clՌ`m`+g"QJ֓Y՞m4лՠiٹ_/}kB)us ?f;kR,!(Ri*vnGuh86l6GϹx:#__ib ݟ3=ҼYd;xC\fxрŕW>\āymXI܎Wf}=W11eLKgN^46f=G `;QnsvҀNG' fcUesBHB~2 !EnO=Qµ94| 4u)f[}o,n=:3L|/:Ֆ/S޶cq8~xoS7?*(?:'CXF O5O]*\'qTQM{w/=,5"@ƨ !BQu!B?(Jޠ[MCC"9::MCii> B!&--uJ<^P A]!B4hذ;4M#aU 2F]!B HB!u!ߵX IDATB!* f!BQ!u!B!*#yKWMǒ+QH !$ɿ HkW+QHUr@&/B!BT@ԅB!$ !BQIPB!.B!* u B!BT@ԅB!$ !BQIPփhewKBQYIP RgbR3o nsಚuL5-[Z159Ջy7!kyNJ,FmOx6"zdƦdӡebڇoIEݼì/,wYHyad0N-2Mыsws4cs X𷴠߻ h/0JfZ>} -Z[8o/rh99w }}ûBtJn=Ą-,?sv36˫a[!5"Dԙ9v'()w X3aSɹuNkRa"`&8ɱ#@Δ1 G-MC爏~G_W?&ꃟHW4Gy ]?ᇃ9kcKQj>]A _n½R z#ΰ(_fOoP? fB~ҡ7pE/I5/nƢW zt.o]솫ٛ~]y[ЙjѲ<Z [C=m;s;f O3p6Iݞˤ/͌;:pp)a6϶ˌ\?SP`«n鷜ԬS: Ovl@UgG~P2z'>3^}>zcIp܋9W4aGO<{6$ԧ/Pb \H%0 ,Лպu"5"e"APN}QP…260>Q5kO+Ens۔4Q? qdT/YliFίåV8g"ӈx. #6g opzxF&yL^Vj'׍M})eT ㉶gX*#ĭОp 6V!}O~cYpv.ȱ Ң1Ԃ ?WعfcXr*VY>;[JjD!JMX1e8>+~l4FĻf:S],]GpGbi CMrf]jdtvNwӺȾգ68q#̜B؏?+y 627}3-&!߂gNB9(_Sgi#Gq8}:O`Y`\u^ ~uѱSCӯm;cb p9/`}߽ C&L^3!,[{/k`Fnel˴ۺģ'PZV%t.hސ?_|Ң߻;A=EqA<4mFx/`]աwut 2Ifη X>cs''s3~"^"3Qsb~زmi%xAZmQj>olŒpGv3 ]I茮!i] }c&;x[? F;+ 'oSƩm+x6GCsXf[H!DYIP[qÌS:AæOlWWsFp]?h\;O_yܚsNnd }CC bDM-9l(s׽E FW3xxz"y*RoGwzr=+ӷmFz4ޛ:;E:g?x@N)XE(>ax9)Bs ?f;kB"bFl$WFfn:4v6 v'U+sZ7-\릧:fYlޣ縔e% v/Ȕ"/fkmr4G~yIےa?rꚊ-} 'KȐn;9s 1G%l,~];vmL}(},}A{p&/屑$7 TTUEUd'yy4[r۔KY% z}-eogփ:<ۍ_gkj7dNt @lg6ftZD.5l,ڽQA& M\tؗB2^ 280H؎3SAޗ R Akˋrd!/6p+jБCP/0It=ΜE0\nE췼G)>~/W3U6A-!9 cTYy:*^^x9y1 {zj(=0wåb47W?Jv֮E`m?ņDOE͒0 ~ݘYrg;Q!.zi! ڙ٫.Z¨WWsxgȿs a43jh;õ[ -5"eUܥiח%`?t')5Ioһޠw :Nop ި]S`w1(&WE1Q]F]A1+&I4oMTP%mէZ2?llk'Kի!}T:o-_aa%pi Щc+KҪC%ކ^o5F&/9 MU3TvYEttW (ײUlW`5TjSmvf;۴L͡wr5qɮ:+6)HM>曈liۄt;A\Ϩ/E !BQAU.B!D%$A]!B HB!u!B!* B!BT@ԅB!$ !BQIPB!*ǟ+WMǒ+QH !$瓟.I[!dBQ8"B!D$A]!B HB!? kwB!ԅB!|$ !BQIPB!.B!D$A]BXEY-B!De%A.dKEKͼ) ?\΁jg1e 6oi[֡c1mb-֩\Ũ ocDtl @#+e@[k va@Ӭ9 {\ф=EUؐPbw%jɷ.ukevMu{R ogǻYQTٗ_q**b& >|ZTcwJ5Z ˲Uɻ\͋jݺԈBJ@:;pDbO ۹#BHNP ;3l&NZǧͼަ1i-'ӥz፳bϱ`w+!^D4 %΃|h˼a pe./`ڟƞMH3y)§ bѼ/NŭS;:nx+~l -$$|3KwZidq;vO\<5;ÒWѰrtR v;B;'Ane]7 %05xY[]_܁5=۞SY& )nf*x?#o9lMyG[ ,{w"`6nֵ_fkK8.}*}'!n$4N/x= %+ЬqcI#F+)*QtJ|BC%N\%3WEͽJx8)NU Zayo C)C&X3Wlo_a3R#BQV}y2eqmCѓlj(-d节( I۔#qje,g)(nxW⡁o3{v0vq9Y/ac|=7j3Ubiԕ z_ l70kst i2ޕ[=<1y_#5"e#A2T6vա۰l5}yw|:Kv [z<˦vv,R-͛{d_<ҁ^=}_@|?#}j^xböDN]ڵL8,FǨ `%Dc3xEz( =}d8F7TTUEUd'yy4Ż(Z6gR8w9kV:G͉6(z&iƏ'-;;fO綃i{o ۙMD6GϹŶ;ضc ˆBylV{q& M\ԈB|]VB n:)i@տ1)kg̀⡷р'^ܧfi[>5~LJqvgc0;9v-=Dt)sP"-#_qc*$u۬{K<6:L]p FyLx:`%ur;B'9_-N^,Qux}ڏv l;ѽ{gHn2m_J=m6zϨQ PՈŃ*U8@w !CjD!ʪtKӮ/׻JZ=t~NZSkFޤw5(:Atf14Q1*FcPLb荚bVL:Oiޚ^:%ji:Jݭ۶ӫOTe~ـLO+*WICt*[ qw[d J<@4'СSbW=˗.UˇJ ^o5^Mr_s.ÑfVPeٮZkЩ6զ:ͮwiCk㚓]uX.WlZ-S|7mR+GGr!B!* B!BT@ԅB!$ !BQIPB!.B!D$A]!B HB!|;~wԅB! w*WMǒ+QH !$瓟.I[!dBQ8"B!D$A]!B HB!?#W!BQA]!BJFB!u!B!* B!BT@ԅ(8ZtEj!BTVBYtX̛0~fSF kc VLM)JgZAenʕY۞6FɌMOLދ6 ^lɘ;87z|Nfj+zkN4XjSoἽoAd+7m?|,T!mXc'pQȬ4~3,RԹ[Duel\ѐBr"Ane;ʡ DI]\VAg^07/ R^ =27LSV<7qHL'%_V<=e'k }ƒ$&%Hl3;5ر&=dQ߶4M h^1kOaZjR 00jOX gJ_٘FaIP32.r :/ǎsx0̍⍵s㱦I|~qBnRֹAOpŜ=CpBA]^Z:7N\ v06cf4ŭ`S IŝYS<䊮eKھxp5{S^T9o[MjrO3nf|qx8m_`>#TBsz'>3^}>zcIpKT.%V};`SP`«n CQ4Vy/v Өů9*2K3FutΕj<e8 vz .vnݡH!DT.N:;pD.{ǰ8c7z4 aX:ΟLg;ŲZҸ~-|;Ue|.'|'Uu"#ӪX$\*̞MH3y)‡[a;@^77I44@wSVnj \^F-nܹfcXr*VY>;R#Bq$߭2Ff1ktK/yO0o!VGvIJ-g>:bv~@~83g޴~,N"ޛ{2X O,GS0O{sƾOG[d%uR5nLx#}Sh#E%ʙ]t9bRtd y3ˆ~unYTv,+X^Q,!(+[28!I|5 R4-h iQ)'<<CfN/p[dA2Y7rc|O{uFW\Ӵ`澎1rKSNbƏCċQDw&j][-=?do1賽\)jBjl,~A</|,O1Շӓw^ VǖE\͒B~;遇Wv2oQq/b|anv_o$ls蔂[(vk8 e~?c'&f<<<7 lEU>!JOAOޞˁcX>$.4@W9'7b>܀p1{Arun!|l~M%5"e#A2T6vա۰lo6~51 {`1wѶHټGq)J^8))6]ƚu[fWz?k a=:L{on%D{䣡:<ۍ_gkj7dNt Mq%ù<6֟Z4UUQU;Il^ B0~ IDAT.1BBhٜIJlY7'ڣ%l,~];vmL}(},ۙMD7Y:7Qglb~XΈFzFL$WB  $(,5LBP`e5Ggw#fma ?z0a_㿝Dj@v?ͣ iʠOȬբͤZ&'S4z~;Z=>dP;3{%v0Q \t}K :L]p默>͕){:kX۟zaa8{H!@qjLH<72=\ü!_:*^^x9y1 {zj@m1mesBHhEԈBU4hzAI.Ikrèsқ.E7zά9F7*Fh#؝r UQLvTQsWP̊IwR:[+U? %mէO!ff3]?Y֮^%}W ґ~jyΡ^ph GZ*jæj@VgjCATj6٦ejî9kNv5au\iLAjY4DeK S区B!u!B!* B!BT@ԅB!$ !BQIPB!.B!DTvǏB!u!B!*~?Xz݄,IBLz>ґ.QHUr@&/B!BT@ԅB!$ !BQIPB!.B!*ӧOp8fKB!Ts(u!BQБ(u!BQ\x쬫w3%A]BXEY-B!Dy/ocKEKͼ) ?\΁jg1e 6oiWY9tm|sZ9NJ,FmOx~#zdƦd^ R9d-ì/,wYHIʑEc,-$MD-[2M蹻9_T(xHpĿ8KR/`XfV3'CZhn:2bBc Hж`VhH!*<"^̌?α@DMetFouz gA뢶K>p%6p };*"Y~t8hs)1x_eYvܻ=|cyoRϔΖɵ,JJ%)] `Tr ݤ9؛̡5h;IJDM>qcG?)}ygcrOfle\Nu_aTkϫI 'Fޙ1>c“i^_1LiaPEGaQ̉j͞O~7,5"dP ވ_8ݢZsی7KWEOvMu[/fo݋wjx; ̧719=m;s;f O3pФnN0սpsŭ/닧oUL<۪/3v((^uЧ-$LGN򥑕xk0F=.~0< _hQӈMiq)+b+ XWa4ՠbDJJ5Z ˲Uɿf;zbZPF }uw\/*wqzwUU>?zٵ6Nզͼަ1i-'ӥzel`|4k֞W>aՁ-\è_u '-4hd\;G1rrb94t="| 5lFGBICtn_ۯ8{4ͤ\.r4U +z A4΄_\=Hmȝkv ?%a蚥#zw 5"H)C_J?u[cIF3ktKKphx7g< /7{k_4,#;ūic^:߽Ok=:S],]GpGbi Cqd_Q'g3ndSԩ@ _eُ/c8B#~0~E4δ`/~| h%uRqG_$:M+9L[ݮt_tߏ߇=,hKf 8߼/G-VSuRh*Vɹ| \0ڎ+d^&v7o|hՄ &#ēekt <Ԉrws#z 0M-[28!I|5Ջ;} ?~/FuI>q}kygxo,3 7Oὀyq: 4oH/~ui]֝ zWwLWPV5',̘uEnRgp ߀4^_6)"|NbƏCċQDw&j][-=?do1賽\)BM_ ^6{V?OP}[ꍗIY֌㤦&C3S{a®2)8{VkYدבFnV6=qAq?Ê56vGjD!JJf\o׽I.gx(k`'.$yN>HH7_AæFp]5'/NSQUUq }$ʹl$pr6֬t}ɛm {Q|XfgU4G'w`͉3f3gm:<kMΕël 6yL83]!( ꕐ=m- d8:}ـOY=|RjYb$qAaQxjБCP/0Itv\J`=x04z-xyQ,ny@{ѼI jɏaF߀91wV{g1[եQ7Xe$kGsQW>\.O#yseJ+Zw=5K2H;pr8z5 &$wx{^M8a9t=1&?3m@m1#B܄s'R4?`,Ί[ -5"eUإiח%`?t')5Ioһޠw :Nop ި]S`w1(&WE1Q]F]A1+&I4oMT484TOݺm;)2?llk'Kի!}T:o-_aa%pi Щc+KҪC%ކ^_^M6/9 MU3TvYEttW (ײUlW`5TjSmvf;۴L͡wr5qɮ:+6)HM>曈liߝN?9.B!D$A]!B HB!u!BQhV^ ?$A]!B HB!u!B!* B!BT@ԅB!fUw'}T:oB!*3 KG~xG#VyBN!BQIPB!.B!D$A]!B HB!u!B!* B!BT@ԅB!D% (u! a=8]fwD!-u],-56 p9.yYǔQ؂Ssn\fd wRF1kWriʕY۞6FɌM.p`c1m7OxWNӬ9 {wĹ z#ΰ(׿ i{ݴԈBE荸-59H خ }q3޼\-l*Ί34bn{2֥nm_nw/Uk%| ?z>ݫP-!>U܇nnxS{|뎡M/q4JiDq^޴HꕒDfl؝s:EQP &궡O[H8^NWDe3բeGy >=cOΜ510>So>A5ըZ4>?O nS1`4'wg}Od+Rb \H%0 ,Лպu"5"e"APN}Q${ nYp.!KE.6o6iOnt?. ?r,$t _3æo⤵REDP<ȇ{4ͤ\.r4U-ӛ52γgRO! uyS$!-\èåV8gh6{ǰvف(kN햒BҐ~cppҚiƬ-./LOXq"6_3c2[N7H+^xe[|>t2[kz:=!ʳ,L8AR8=͠/u}N -[ٺ ~7Zh o^1Nc}u/o$7} 7F/@ /VR'uYƄ7 (V>RTi8bĹlƍL2sZ)+[~U ͢cd\9IJҿ} n8'5"e&ߗw+c[}G=$=ɖҲ[0FmSs4" g\8w 6#0ow:fw0E1W>N &ߦэS+c9s),: .fhZ$ٸmaŚyl @{ R#BQV>kwO<≮:Y}_exRR'j1[7&o0J+dNr"7WGr73 hՇ'\c"6"L FW3xxz"y*R[! 0$9Lکx¸ϣlE鸰y}{ NB'1~vׄԈBM@SlvTnfaZy~K>,+OwԏU;v)79.‰LI@p/p sՉ\kY6}-{va[".drZ&Rcrs~c^Kb=VYܱ5'g>L^2c#yoh*vӓؼ<]_ՁȯIGےa?rꚊ-} 'KȐń͞аmlvϬ&毉i4}TL& M\t I!DHPikHPX$klǙ)FΛƖO"$zabo-M{EM:rH`¾;:ϚA=x(Ás|E]5GhPkBt2vL坕s͜Cxpm== ޖ=t?;5EDִMxwfrz峴~yI-C:bf8EÊϤWtg|<\eÛyK_&gkTrƷc?~*UϿQ7h.3֐Xf$yVGL`,ݕJPx<K'|@;Eٟq_ LNO@1|zm#""7.oVƼ=]ZNnfxLW3'T8N/$v S4|$1~6M|oNm6C<䏦H|V̆Ot~^zk LnuzH L^ɰ),_mc|RK5WN"btϘ6=)Qw+&>zF|ǐ{PrKVtoډz eĚeU>SĴWۦtf>nqng>qA1!a|4;;eei1:8P_{Ik}Y%4$߁O;x{m7N`x:G}ʼnOp_| +?@w2y^\W-ķ¯9ʸT[Z宨'|QP/Y8FP `gvr;7I^:ŜRJv :Ú~.ws_j|G f (ôT؄Rά/y.&Q3"/px֋j׈0r*kdqlE*S~nm>nvC;p{-|JC[0Y,89 'kxb k{{m3vN h~)ˮ,1""_ 7+g^6C8|s^yj8o.7|N̓ `8"c w9 "n|ךΆ]R1wi}@lrjd+ڙ118AH#7ϲ,=QzWIQws WNQ}L7-:Qbf*&|:{O׬#/~ޕ~4}?onϮZ?qG=^ #=gqtŇxu5ZZFmNWȗO0קԼض4{ܭTc?qHpdc-xw4ŻeR|pjcӻI+ѴG Gs=3rA{輦p`[4Jp{1׼xI*1""_y[%hYkx%lt6;m>v?{ta;td;iNewN 'x|ay0؝VdB>Ff[vδO Xh 7+ٰm; ֐|N͞#a[6Πwx$_Hʆ/kᙑy [ذ,޾70b~/3MЭJn]~q,$S~Kt8WęPBؖ`GAÆ ]IٙA1KӘ3YC{+SwcW);+}# soLJf7Ϟ-_?JN]-I|}wFʂzR#a'.<ш8?N\Ga^VXcDD$oZ6 awPVT؃U4v{:V5)i+M 34yW_ T(S)Q$ i_0f?hFDq(>},+Of~[`ݨS6PJ\5.}ѝ"3'}xO&E|QP/v5budy3~b{T ѡuJ\‹^.|ZȬl\8i=Y;{uA6v9.+ËvZS"҄XOlb,ƍ B}6Wr F5=x 1c/=X[1<.-b=.|#[by3wjC k=ՠF8Ulcz_/nq~^{a3?NՀ0VK/D/Kmm9y{! Y9(mf5Ifv.Fחxӏ넾t$ၘK}[R;>USKyGhP f=wWp Q7RHIӲFCLsY>36̙s/DG;Ie^k9"pLҙm̜_.Mof ƈH~fl,cيul ?MJ-RwेF$ !ᮇ_|6/6j wf~82횐mfL}|QP/lIx8OT,Wre)׌OdNsg|rY?>ʕˍ3/'s{TZNgoq0u+PZGߺޟ:a \*_vS8 jF\\4^*S)mp3%%r 6[֌W{ڝywF4!Liʕ=ˤY>ƜAx>vSoϨe3ohs/D8>7"}fQehE 3'm1v5׽]eKs+li_<^ \LQT+KUǐƈH~ۃuq0W[ An|cIw6M;lA6ÛtXv4p'aiA-cmVe7[L1/j\r:t4s[w D6msv9PڭпmTV-^/ei&ۖeLf#{>,,mR'4t /,fǁݷ 63C$ _h3#'Fml Kǁ|EY^vqg7_ضiT_EjLCJ;0u.<9ΏQF/ n`؝A$Do::qD &("ΡUlMvk'poMbn '([I/+^I6šECߤYkO7 BbW#4<ŕ$gf+_ 8$;i+, ߿؂nW_;'Ʋo1>?VAHC4~]f cy<},4FDDKo7+/!eMlS Smd^hP<˗<'VÏF?^ksfn&Ԣj\+ף,61U}#.1cnǿJ%"nXEiV=qqɤ~[X3?G88u-uo|eν҅aKGwpLpHIk]Od=h-kJqTFῑ6=53׾œ-"=Ё;ʙDcDD$4^xHZ1Zݣx`,76"=܏]&Cq{fw07n{[6g̖xUϖ|[F*CÆz{Ӧ,E>6n{6k7ATN| '~1ʳ0bZ̿xl?K@ph(N/I͠]or_IƘAs ^uF_a7m~EUa~ѭxkF=܉䝶%F4!nąrݹ/>lGdB~7CeSiD>%bwj zR*9nK>AmiטRN;~\tFg`BCEŸkɯMZw8^ [l)l]N^$a7oaٝpz, 4o~"vh`~nY(:"&}fo b*ui|."8(Vm) sr6[k۬SZZ{^,bM4y ά3_\0- CfڼIeKIJ61Snۄ IDATYs.p;ltn}Vx==1ӽ.o3n_(VX3g\rgk:RkEDDDD uHA]DDDDRPB躗SP)EDDDD uHA]DDDDRP)k7sURLm7j7)3F?3Qި ]dOK_DDDDб mEDDDD "uHA]DDDDRP)EDDDD uHA]DDDDRPɆkm9}uMDDDRP eTQFxk[M #FZ{EtT+8c1""r(߬Z0f~ǶePks$ [CCq;5{dml8ž⑄O~. m>3}v:ՑAKN\ 7Bځ=%`RF97jd>8?`϶/x_$#f`t yw#jGAÆ ]IٙAm$DN}Qu8pʗ}+燽޻/󱓅p6DlgDXgd&lѝ=|1Fv؉u v9q~5𽬰ƈH~)ߴlv$T Z'4 $zԱ׉#h0A148ubkR$6&[B"D)J`l7zi7dNcͯ47θD۳ljb۱GU(k.O 1tvª7IV*bеy9į\<0 aѡ1lښ& z1аc5'7nv3HyS摻(NxI̭rG{Β.Q=Sdd^ػ/b<٤tzi䋂z!``շCh53~b{T >_41?^tW 0i;UѽJu0o6M<){X6YJ$<TOZOlb, $yd]Hr'ncX6H^gpۼ;!Z{ɋ>k= "1)2 `z_v8w͠j%[ǻ h~mk}2L;ː)8*߁A3fZ.߰) 8N c:e*vU}[R{| =1#t+-IVCn aleI}y2NS~&b3痤ˤ[q~seA٘YƲA֛z%. fC|o] (E\xi>~4 ޜHAq{P޺7 o)ⷝkSu6{ZkWi }sLV+=/g +2_ϙ/b;٪kƳM'{}qYAHC46dyԻ%9}BK`H0A\lrf8Jm#'BY^n6iB-Qr==jSڍ[.:-Sҹq !N[٦=ZS7kjzł9J-WtEQ이~>a_ZghًF%ssb5<a5v={V<C *gu<$GD`,ۃix9i17x9\'m8KlfÚլ\+x-_mB1qv^,o{I٧XMjqka3XmAvÉ3i]ז'cn/o;1/ɯubq]Z21Mp.q'Kf-*qkA\ky˛هMvq{˦2Lpֺb,f%ug/bv~-m~]8E&??7#U{HNT$E׺7ˤ/A| I%ljoP~OfȶC}* g_,Z3rF3Uz¨Һ'}E$7v}oHU;ξxiqʆ_t+ޚQaw/ym žMq\ijwˤy*7<.S%fnГZX13('I/ؕYղgE hcNƔrz8p$v%k-?~oڗ`FQ1Z%4FDD+ouq0W[ An|cIw6M;lA6ÛtXv4p'aiA-cmVe79>IL3W\E0͜A|pAAj6OMQ͟;GmQި [fMJjr]bY6nٽs,ovf͘Azwa',"δy͓^˖M7LlbxݶL1]HwL6kz,{c{]"gVisQb۱fθ䎷6uHA]DDDDRP) |PtwF) |P)EDDDD uHA]DDDDRP)rBc9uv9SMDD 3LOLm7jCd""HA]DDDDRP)EDDDD uHA]DDDDRP)EDDDD ulIݖcٗWDDDD +{XZFEmDf%8l4QQDGOXvȅeO?׳?@>q`zW"qzNȿQՌ\N ciY+`&ah(ㇲuzGWmӳWV;|ߝun7>CB8"i70v%3y ?GzDGEӰ;o鋃$k&ӭqyo}1pm(:1ȥ$iIY DAfׂ1w>-{Z#a۩s$7lc.$|sa+u,bPB)yÿy+}vV ZrbLf#{>o{e>vp@f]qmʏ/,fǁݷ 63?~yErx6<3r"ojŀ/װq6~шCxr]oblX*zNCpjY=cfa'.<@څTvL|ޠ[|(i7dN/Hbc"%4 "Jdx)n vIQ ٞ'>1""/ ꅀzU߮ƷR Y&MjR1"uD\ՂWm+s0 W ̾1zW.MODzKM) $o !9+ËvZS":o>S3u_6x]DJeߚ׬Nqod32}Y,\6oNmf5FDD KAZ@z5pHLJ};%S{ d^+u/(gc Zځ Rh;VfZ0>Af2F @y8$ϡdT ! }`a,C].M<. oIS$Px&֏կ{xX]o{[6㹰{Qْ;}˨Vesx9im+S`92>~bEm>7lǭ,o~zO0 x8l%ϬiNZW,;1ݟW:1xD(߅-411q͒YˠKkTu0=7^ӋuvvֹԙaLҒNn7`stLagHX_H[ @KX/ktޞy>ll!!3{Naѫ?^ƼoS-b@se0#0q*1""_ 7!gٞ|g/ڋC|黜]7nY8"8k7/>aZ'֓rEnƮ >Kl쿬AD$w/~9Άo& ^u?sYAC\eB|hշC.ʿpc^ɯ2֮ʋN{|Î?*1""rhH.""""R)@ """"RXuHA]DDDDRP)EDDDD uHLi9uv9SMDD 3Lڴ4]Fyv+C}mWfV5twp> Glvubm?k\[_Ph6Nٵq4<lI.WCL6Ypx% JO+gOx`?-tzO$pW8Ԋx=!k>1a0*L` w1]?sg&4C"Zޖ.EJVKK; _;Ո=D Ifd!oSyޯ׼2{'gΓyށЧ5ˇ%G2)D~H4%+O%FB៮5P:Lg `7Co8 lmu+S:OpK۹4t uC!~. n׷u3 G@o[0~> /CK80}F80 d^58x`\X[ -4`ص,oC6U29yf7] _ `vH:#I0XH:wF1pg'LY 6)hP(~=RJ{,f&1"BFԟiIWX'<`8ؼ^~v~M=Lh:nL12G#\{b`:L 3$L0zj9dz!}T n] fc1`lH2:a|5Qo$5sb}{wt+ -FE΅5| +O'mmWQi>TNnu Ն!0Qo](\鰩'ÖЯ7|-|,B>;J܀T0^-N2B!O?gpփ ߟ`K˨J>ݺGoO:NRag4˼ܐ*d.R4 Gڗ>b\l1_53`z:75ݜ0+`ڃ Rbay Ёo.[AT[_ ?cp 8ʢ]X? ]u߬ޅ_W~P:W화bD! jÐ/`VX~"W#eeXYlFD 09 5!nd sV0?$ Y l\c9!4`Q\KMKĝ'9%w!4:ml<2(k!~ё迃;\t4 \:o^-*^ ˃N$C=iIzN 6EjB @ $<+EV88:K::pv RS1gI5f$^Chw#,&S1"ςgv՚V!0[3 :{O48^ÎN )wܽ|0~%30a-$ O{ە |ǣs.^Wn+>]^؟65GطQB֧:[kҁwI8מ-zoxbaN{;m0-(p V>s;֫05,ӷÉ#0Ju=3 IDAT2>t&>}z'߃{Ó9c֫gZ l /}/kB?+x@Fݰc7ħYw xg ^y̭~Teo!dK>d>-Z@iwX, A;T^; HK4.e>)>+aj'u98_1&3+P1|~\OO㾄B!NC=7sp#OK@g%B 6 T,5O *r[rzg P+x~8X{>@ylŮ5|cS(oCIGEkO;PPik1O[>9A0J3/B!zYϴ翯'Ԅ>a_sЯ(σ ;ھ`/TF%=֌i۬; ch> 5X &_~m=1ʎ5 MaqFAٯJEǟ``+imc{o/51Уt:Յ!?Ӡ4Xjepl€5P+3ʮ?XM9[7^0p;((۫>rRFtۜVʦ=Oɢ\NcD!DNg5h_nW]`1ţdwA/jPtzޖ7tz-hFŨbCAqrV'+jQsUP'A)i5Rh 7[ߌaݴjUe[vӆѼE5E~vJilnx&.H?ٶl"WPlhF(6nmyEѳ,<ڵj>>E7z-?m.ޖƫf-AEMYtw (Ijvf0tEf-Zf;جjKv6mV)@smix{VtO<;QB<Lx~ !vlС?] !B< 2.B!Du9B!ȏ|.B!D~$B!y$B!BA !BI.B!D$QOv Zvٓ6i7!$isF;{F9#BdL!BI.B!D$B!y$B!BA !BI.B!D$B!y$B!BA h6&B!ȯ$QYbfdk֣ۨeMP.GLcxT43UED\4ۆrҾ};!?biSi K:gq؞dZNJZ+>]} KvƱ_ ~&̌ɶtƴD~}Mb\&E%fɗV˖K.-j[p\Ld~k< ͊&L!dQl>Ie%~v,nomW֐BDgSGG|I~GJB*'68GgoMDRZƳkt+ Ϣ=yuRPT =yloA5"y$+M[6JܶqLI~\ [8{s1gۉ !H0ϫ9<\Aٷ1eAGGsxԋJ؃ W#l~!3ѫxG: G7, zC/hC,)^y(%F"$QfP ވKC¯ǸasLn^=S!wܼ=_ͱxg%Z^P7WO,OU/%_,ˆ^T/vۿv(3GVe^nx |i:mc܏n ?'[Q3yv{&_yNAQ^Ѧ>D9VT .sXq?yG(V؇">R/a Nb08l֫ŹRݺR`JΤ[.mdAG?P$F"W$QԻ^2xY轜(V /=` n~+ۄޓpeH!vFruzu=53U孁3g!Zd |ԛP'83pi &Dr=m\^Ň Cx R8=/ Ùӻ:В.pLI*?(Msq8wmHѷkAsVkI!DNH2[B*S2CjQw\#J8BqQE0߸Wl|QI:wB/1{y\_M|k9)/|Z5??oM,Gosq Cɛ.Zh&f\3UDHyBڱ -A%&w;ٹv*̠g0k.;}n*Iw$깈s7*gAogڢt|yBܒ*c}&A8{?s?J5F34|^iA NanUo'*Wlrnz#QjػQ~'&;Rs/j^G'ڮo :'LO91#A>!NZ̦;Ɂ!nO"B<&n{T9}G6#rrΥ3wHLMT(p5;'7qQb9ЉZ=$1"L$*#۬r;j&=„ S$h x9(|瞚x͛1,-[Aѳ?\5k7ȋNMkra3+-(Lٗ|u_"lv $z1{`>mWI}(nᅏU\+Ix{B<]tsq*:;ˁm gVbNR\[-1fn^PL>I$F"w$Qw~_bbj:n񟙲,ɥ+?z}{صgv§ Tj=?i!+UƢi8hC5_e߼ܒ>K I0ߎaߞ}n+`Ȕ6 Nߣ5 ,CvXj*Vnb(LȒj`X64fpָ}lu&'72poߔ⎀/{Tc7s9jʞ8X{ >Ν(y&6-oE̓}!I[<{Э_кA% (O@ɆL=c9md@M Gf{ep0∛^^:qt qsީGɀLёSRF̟ ߧxsOgVw{*ԦLI^ &s*S:T/Cp`^K~9\tFcmkg%nWF-gcS@LMcYD~dz}B[1d~p"ӒN|L_^ KEx+Y.vho 6r1ִ)X瑘} 87J&LXv{'5$F)DYԄ9w>_zac`J uјqs\ֿЅVRbY2*E"_s^ZS Z6XctiW_xO7iE6lufX1G7 hӓTƭS=߸0SPWzQn I霊SQ]9Zq?yG(V؇">c_v/1)m|+Z#Kk<͔YLh%n`Y5~̊>LȘŃ~L̸fTbɍ[VJużr+&w)$e΀8p(T4|ARF./ƹjafAԸ?{=D'M'x>z#Qjػ65#Çfac/p귵4=؃.N:&tN, Oۮo :9A)3fB?#R'|{-fӎDWt߇O0UlNߑ͈s)z $8~,[oO :P,Î U8^bD!r+'"gzo [ 0NNCle2oڕ)MNWOyS?R>8ek1h2;zVkfMʎ՜Fr8* N+ЬKDK\q-ho3oB\3)6bz\}+GY%fd:ݱB/fL'*4pww ѹ6Wx42OaUI\x5 *Y~/1"#S_+NmnRfo8TJry K׮>9s'JuɆVP!w3enij] -(W@ X37^7%݇S8&nֻ:qt >Ȅp&h+z w/a+\7qx*6|ϰ4mX g^d4ᅻsv!ɯ9 0s;%˖fbi@7Z>̟ ߧ^"H=Ϭ_ikSf~'Shu)ۖEhf.l!=wp^Xӣ)ϥuq˵ cetz.\q5U !ȭMhдk% b.O+FI_ ՠ-Uoй[Ѡ鍊Q1Z5V(NVz檠)N:RP jz%[ߺ>ƝvӪMT5nڰw77h֮Z)m iv?ٶl"Wm6u8e[^Q, vEQ*sl6MoKUU&,;$U5;ZU3R :բZTUgX-QlVf%;XTVE+F_A94 NW^u!B! IԅB!ȃ$QB!"D]!B;D]!BjC}rߥE@{ n@߁mX25L&mϜfߔk=9G?mθ8_V2gjDzG%~ko{z䶆ĈB<%?0=lVT>9z8^>+x;l*'쉸B8}:4x#'cc9s1`rf&%vz!ݫw&ҥ.^سllJZ W1ȓ'\%m23ɘ˦c'9oC@# [8{s1gۉ 9KqHH N][ ǣ9k%lA{bl[1I“9st6m|EQYƳkt+ Ϣ=yuRPy= zC/hC,kw!^8>PXbD!rKgE荸 ፰:$z6ʴՃ1r;]ޣ|_s^ZS Z6O/QOe˨0Ջ/%\y/_,HJmS!e胴Sުl /A)zqwoZyXNJfNLޟ t *]6!؍,FȘΩ8եjpq3ťVw IDATA/Pg< ?G>qj{ ?A%3giq%Z^P7WO,O1zFX3/mdAG?P$F"W$QԻ^2xY轜(V /{Ph~*fU%^Vm]d0֗)ĮrZN:ֹ-+^ö |OMGm?LUyk Y2˶m ](~&?jwΒ[ُi)\2~'h2s:=Cy Ѱ\b!WyJm$R8=/ Ùӻ:@ 塘сWQZl n~+ۄޓp7G߆m`ɱ;h9:}:gĈB$*: !b0%01x5ϭd#]J*۽DP┩щ-OäĮ⋅A ^>mG7jX~&#˘I@M|k9)/|y+?Rm9fƷkY#H㷹}8Յ!tqͨV! iǶW38uwdک1`%Ud\LRQ.cOD$k67n`9a ̵(] (\)ޭ*S}m\nG :P,Î UL#B{?zo [ 0Nta\ٱhZGEpu|{ ~"jI6oǰPSl-OfGjp-׬΅gHN>ĚoR9KFy顿Ih*"bTGNԚG9VuI#c]pww ѹ6Wx UӘR{%n5t3}1T,P<ҩE6q6цjʾySW%} {0s6ݗQջ:ٗF,@k`Y҇LTTUEU$8eP.8m$# jb`Smh6sqظL$99?Nnd<߾)Tϟ"&.$s"q'3t!nr9=)Np˪aIk)ѪpTlش2O%F"W$Qol2C~eBJ'?%2L ]3}Z{V&5s{NSqW#n^x;;%vFPe*k0y {uWŝ>gENE?J4e,ږ6|ϰk=bA/+[d@`@4.cלQ4VNc&(N~y; }?Y4C gVw{*ԦLI^ &s*S:T/Cp`^K~9엖=4+C`[K?Ni1kaC7GY1sfLʁ/N˟plfW~j6WAxdB#B[9K4ZA+. JQwH5(:AoKtn:b4hzbTVM1!Š89+ި*(nC봂^)U 7QǟԸsnZifM6F-sU+!m3nB<ۖ-YD fC4GѰql+eԮU( ^tRMӦmjjTDEwǀfGjCAZTjlѢ%j6ͪ٬dj3 ܶhŝ+h>'ЖN{+dD]!B{N$QB!"D]!BKbZ,ӗWo҃Vosxg|غ};n!^b)|W|3ub'D~B[1d~?FJ}>5ac4{0sfP6JɄ"ǚSdKSyy{Ԃws-5|YɄ.轓#BHrj;/ =܏HYISFpzHQc/ItY6fkXx6Uϣ("c8}.M5ti Gy|^!u8jvd˜K{:w C16lGBN 9CNLhϰqrEeӨ  ^:U0bFxj>>~$ڜ,y95}ӎkAO`em8;eCp|ĈB$,^Aq)auH7l.iۍ׫c*䎛wuG9oR8n WK 8RR49ԥgH~JStz F#{e:jTvg6v@pxNCo/CYV/FkR(?ƭS=߸EA18UmCԱÕ?$̸?[A%J\A]qhQ<| Rrү9U-FE-pȍu5uҕI[.mdAGcQbD!rE|@{p,#*rX>5@C@EEs+3E2rtkXjuߤ?lX%!r ՎU>.mCX49<:aŶC.TCB䘚p)cu12(q7 U*O`@ `Ngrʩ ъ U̪JŽE%Î cw0svu8v-tΪ#B9=/:: `F|"%aƐZ| 3H>pʻG7jwX޹4ʹr2&/Ad6}Ioì5)';3w0m^`ځǎ?=k%E#%d'8~ۇx05}g`z=:+9K|ڶ 3wƽg/x{m ߏ@1sPt#m -e0LF{gXH6,ξswIJ Y$לQ۹e314 {S}OjofD]w+ŚNN .{zb,f0fr4؏Z6rm#ÆX٪>Ō u>cѧг2Τs ~^/ ΪĈB+i_nW]`1ţdwA/jPtzޖ7tz-hFŨbCAqrV'+jQsUP'A)i5R諒7Z'ܼ>vӪMT5nڰw77h֮Z)m iv?ٶl"Wm6u8e[^Q, vEQbPRMӦmjjTDEwǀfGjCAZTjlѢ%j6ͪ٬dj3 ܶhŝ+h>'Ж9/œ/B!BA !BI.B!DU !B|ߐbD]!B|Hu!B! IԅB!ȃ$QB!"D]!B!,-7)MB1g#nxO%c`{p o+U,O{^(?:σ;F#DDunP=?Ȇx󮑸|_hoK3REzMHAkos^tsexWp^:^J[ԿwJߌh~>Һ_GEkz7^vqz+yx&*.kú*<_K^7ރohdyy.5>T ๑/ '.5۔G|2Fp&z>~>fUlIc_fWx,:]z|\9n0Qmw^KC[Zu?,Bo?ڶjdSIHm (Z4o~jT\43^: .wT# i"Y&RR#1(g!~8^,Ŕsqc@VHONAz蘓VCcpQJAjFKJV-^C/Ĥ6,h%U!G A?ƥ'vC,nz#'dC2Ѿi8h VJ[5?<7\w&f7BJr:dwomZnt*>:{9BDT+ ~#Tp>`{ѧ%u8YeI f]Bɒ\GaKrƍA?Oü U7ָ 188; @,o-?=_ U44%8{aW;Qy)GXC80F1F ܍ $~H~LEB Ĥጋ]nBcoc'ʂ vc7bT.(xa6F?XjYRA&.s_a"]GP{_tGF顙+ylŝw<ތ2-[l dN=sZ5K^_W\'\.;J"~XGkz91q<9w]nڷ$EjyM\\p%w yۤ ft~~\U8qGa4--@A?qG6/=قy/>at wCx F^+ @U\ "6>;n2}_H. n;7S :m5Fń7"]ޝm '!"-[z o)O`}&b+?SӐѤtFeLaOKp˝\|unۡy&h}N}_-g `㋿<T֦}@6}rB6t%8B}ݰc_IHgZ@[hs( nf-Rv?𳇢ki'f#ŋW&aІpğJO#+'Wť}[V^]~̻fՏkBxŦʎ5|)o(F IW|p6U{FZe|0|wЙָ]"JtˈA}⩩bVJQ/e$1]`QmjM) >ަ9x+c0ÐV%}_My9>ĂҪRU4wN S_C+Bj( 4i+VLykhQ8XGX]9//8eT8qg?K07#2قBZٙ%2Pr%*Ń1Ƹl^p PFx.\ׁ1d{?1o N~tp~? :>SלqÉY"X;t8arpF;풓DYɥ|;'z/]`҃aIHMOG 0&< w!巂VRʲ-/f*,ۋl|ڧ}h&kta,jt˯YJmqȖ0fb/1xPo }k+u ~}G5X0c| = "'&9d<"y?C'ty-L2zZ#-#7h2Uyf'j3LD L":\bL$`leUZG ų+y/i#m͒S]`N?""""ĠNDDDDԉ:{2 DDDDDA(1% u""""ĠNDDDDEΥ9~#"}z)~}uͼ >};oh!%=e%Q:ѾA(1% u""""ĠNDDDDԉ:QbP'Dc5Hh_ŠrVLld:NÂ` n VQ+QRRR\'8u8O7]eFU_p/|:Z=n `WcXdF>pަ?8 =}KM^*9X_;;sL\==W.n7/ދN=2A'⒇Ңf,\\qvHO>~s˯ f]cs0﭂ܕXrr?Gt5FFߪF}3.…s%Y~/Yp#pWw /{ɒX6;Bjex^x\|J@Qɸo\|:/V~no_3xeJ,[< 60An& W,Ayxr4i ͙ocTN9o^܎__3|Nm݈Nj-t<7ngEnl0Qm1-RZvé#zUfu@JArlF(O*=O#jVN+ ֛CJǢIwcwadF۽Q}-3a7GF( %C􋵨S#./rR-ء8 l|aW"yqQ?g㶃CN?}}î9mφ:m98e?d_});`kXC ś4u~/of?(#DD 0ſBS{dإmvšrpa`s{~ѽ \z+v]:_ŋ&/3rTmr$QQi-R@|Id(W/Ā⒣cǽ$p?GdU>Zۄ7G@7`KPXU\H>P4U lcOW= 6WT90"L~ys 3OC9BDT/yv7bnƄ{Q顙;7aѻKǡwwk5Ͻuڴʀ] _x[܀n! )^IwF&]PaYu+s7aaZ敾F]1\V\9/^s9zvѣiYMq"ᘶrMaK''܋'Amݑ_U8R.ZAUuz(Q>cŧ7h1o]JxcpOniX: jf][G⻴u/o|sh##ѣ6- #d|IiɸoZ8nVI>6}oܶn/ԋo R: /'EU2(sNƽS03qczsw<u6> `=dY?pXAʁqoAm Źxa37߇Cg݇CK_^opCgaWpf]lxPuKpVʣ"e2:TǖP"Ku8ͧVJZY,[e{Q-O\d.LT Anu#KI#t9l)ȇ1~Ͽ1;G|P'vzvž7fpQp;h6m8Cvyy "<N´)SЫѻ 53p&Sg6x6y1Dz*%DvV1q\9pP<^8&,Y Z:e["g^G(1% u""""ĠNDDDDԉ:QbP'""""J@ DDDDD A( =D3z{,>7"=_aa.]A}#A f;}T3oBT"1Fb"30r|:zמp0NDDDDS.xP.Wڲz =DDDDD A(v_?9~"iHt6 +DDDD[ 4[4f͛c'7:6))e?k%.u""""ڭ*>m+h$,nwM7]*NJ:Q%"?ߍ'`EGBDDD*bfg#'uֱ/οw[NuO@et5\-^1xaoWx ʏ/5r7g⊏w5qO@ldYjjP<|I1X_S" ;j0n~~;5Xd)#N89٭15s0qER%xg[#'GonH.3144.[#DDuA}og+8ꧫ1b7(0 V0z˘p1..UM{%x,!ꪺ ~d ,]^z!UnF'~w7S"炿㻣~Ų03l3AdKǠ>y|2n9i?$xX*,_ s_<G*iߥh4\$_Bpƴ1*(cLtoRE.mBǣ~ë<|6[tv s^KA[!e7:7 ]`Vt/ $yh  FG`D#оU#BY<"8_-+B]uiezU%`mK]~b4 hi>0K_Yl׏??kN5n]rK3CpePZkh;}18`JUB۠}pAm8ֶmNli`ow4T]hBXΚ!mv9BDhݬͲ`mwaY>WpQ[0IOR5tHU׍,%Ml Oh_bС0fu>FW't-L2zZ#W6<ɋM&"sT .1&pMc2q*q#Y~~ļő6fZHB)jJ&}eWDDDDD[·DDDDD$~LNDDDD/bP'""""J@ DDDDD A(1% u""""W_G]]=""""iS4jl vhCVʠJMm! O&%""""J@ DDDDD A(1% u""""HC`ԉ:QbP'""""J@ DDDDD A( =""""[f aI&uV =zNDDDVY`R ׿G|l^٭[7P\RqQ1;DLCe^x =zu"""߆ ` 5acdžFcP'"""J " RPoԉàg1Q}3" ԉFU]<g- q0 0cE@/^̚ [t1 °3O9~@ߣjjNu"""!F/f#qJxP/2{/Ѧo칇O2C!|gch<-050͏K?vDj=DDDDSrt,8@~10Fã@gѸo;<=,<ۿ펉6ބp,HoXɋD{%CNE'+PySAK՛ ?)k OЫbu( ċE^=>,+DDDD ByPpϣ)x:?z6No 1#'nߗak5p;[g<n <}>]GacTCxq"kGSF^Ny\GDDDDTߌH GQ[wxLh1?x`qCƨm$J#XH4=0U:|ًԉD}UfQ3:k:ނ::Qxxtg;n]_if7}gԉE}\G}o/u"""(5\CffFC^0%P GU7 -C DDDD ``ʕv7ؼ9G@(6mw#ĖͻaduA(A4Z9ȆŸG\^""""*VeH 3&/] LnĿזO(R߂5]·5hTe="c&|E}O8!"""PU [_(1TR/f82[_HDDDDvtm$~E]QCٕvZ_k/DDDDT]iw/{@L3QvݥU_Iu =""""ڻ2fu;(bDx˹p+aň]%⬲2~1ѾeXDQڅ'x&O\ 8}Ax GzN h/ر@$oQ-8 F<8z.q cn^ڎl}?p.빞3Ĉq'"آ DPDPRf߭Y>#TTKkű˅X>q g)h\2*&J TXI;I}rMƄӚѯכ T a˨rU.\`,exڎgW˓xu!v ·f]SGL$ʄz_ Hf %1E"4P`lg1ǧ-b1G6m,mYP|(>'(Dx^ב*jqq,#(l3&5~X#ᘈ1H3.w꒵~u{՗\$YVK~DlZ $K[ٖ+8IaiWlQZ1 """"J\t 칪D\)ԮDF1iu\1Z<[D] 11鉛# sfW)HYSt2[v¥KU^OD\/2'f<@\%ж,Wihx*[ʪMDDDD"OOhh x%"cIň癰5Of9Jjz]y2w 3T^.TǖP"Ku8ͧB1.tlnkiq%)-w) (+ eYkmh*%WѾ D"ƅxJL/'!=hcpgB>c&i#mMY5=RWm/@]Tw-w `B@! mH%X Eyʲ"Q}JkOiʸm/DDDDT+>/x_hG :P Za`k`Zav@ NDDDD0.otwP* u bh'""""9@5Ut^C:;:PuX/W]XYh_йss _NDDDD5rsٲvUt`t`wu`T*v`[p'""""K9-t`t`w* @1ՅΥ!|W9zvƶSE`<Q-l U΁6N54P@/|Cn|; DDDD8ov DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ̖IENDB`qdirstat-1.4/screenshots/QDirStat-percentiles-table.png000066400000000000000000003072451311502036700233630ustar00rootroot00000000000000PNG  IHDRsBIT|d pHYs+ IDATxwx93R $bG"^+*^Qb)X^A@) HNRI63$&zЀy1;y~{B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!$nfSw&B!J 5;aXB! Hpñt!BQŁ [w߳iͫ*B!ncG6 ޳JQ`fzE8 g'Ε.B!j_F |ByElhk5y, B!-XS=gtlSh7 F"ԩr$ !BڴA{\ҳ:+Bfw}\H<=ߒY&\!B2ֆE*{z!B{F'LǹMXߵA^j@8g$[*\h%o "-]!B@gX92@^5W]3 UBz+zZ8<-Utt!BQv&jkB!MY?vc1cLy_<"{BMj)YkPMo)m]ҪܵtDkχRh5ʍ)yJ(7C%u!Bl_Ȕn  a\,(DrbPL*P#5sNP+j+^xBzCEl]ttQ:ɯTQ)mv-,JYnDq ^<"A]!B0 H$3Ƶvq-<5Ɖ/W3&d/j^jA+|U[ø܎IZ\J)(mhˋj *ˍjJMiKB!qq/- x1xDgqb垷Ma}fWWՠ ~S1ҕVQRZk RWH>= wY(ϑ IB!Ӷ1q㳌]7Aݍ$ύʰ^x%Z71K'w~FcӫyY#mіJVVWYQ,kmc1FvB!,Fbxyx7e\/np0_# 8P hD8^ƪ|/uEl, ;Jk-_Hi/$,Br1 n9 xqPюk_B!ߑlc0}!ڎc\0;[n<7dϸ;^Z08f'%ߍgz9bt_ۺܵ61J%zғ\;fWm\(hmO~і-8RZYJR*B!vkqk,e{1W{q<e+1JrD0FpY&)4τs)IK*Y^Z뢞7 rW:T_@־RUڍ%Rqe=KٞQvܧ>R\JڠjB!\<<-Gte^L[ = r1ilgl22cI uFkrdT唍Y_v(ҁڎGmӶ!;s[Ƶ-=vu!B4{SN\񼸭-񘶔9ʶx &(yx>cr -EkJ.R$qUA Q#t** $zZ+8tm+z2c{Fَ~|Z|~Ca+[kchQB!;L۞z`L1ng8xmOyUR1.&HdKd6(`6j%Ws);WiZ&zӵFJ{ҖE)ea%zҵp]tHU@6~c6ԅB!3FyV1 b^KǴuڲceT3J)gg[hm)(\t… -SɭM 3 ikWJiX⎣&MLH2Z> =!cT2&lFcl{B!ߘk)1Jcq֎\ϯ}5ʆ|giXJ<-TtVѐV /;hǂff{)\3WѽSbKb,B)S*-ڧevll0EUtHTmTSIB+2(B!vqo5-+[[(*Qbxng/ULe9^\ltUF5N4B~Q4GP1Nc]^@.$p(χRq+PRVk Z[ٞ6~˘F$cg;hƫi)B!ߌi۶<ݭ)7|hL/jV1VX(\O)7kLeY׸$o.h7EϕiuI{1ީwhlhe)=\jm,%n}OxD9pJ; ۬NϢXN2339唓yC ÿ`M/Aqϵu+xGAA>vD =kRZhS/5U..J f̉ǹ98k3Ë-W^fEq?I~CSZZ+Wx}݇:?/Ȣŋ{f͚͝wݵIW^i뺌3/rڶݛ+6mYЭ[7GizRC!N;P ˲7~<_s=qN,]‚-bOTC~?奥eLa }Ï81؎RCj /{χ<裔yw6w}#<­sC1tI;ƍ7~=sr*ƾ5d}q6׮vtÆgrAetjHhkDGv}D$'2?_ѱkCpѣ2d&cXCqd! .gǤw&n~~}zEd57?VcPWJ#ptw_tSW2/Y@vv6r wBY_\Ļ[ަ^J2N<ϗ_~?#ߤ^z1k,.JZlIN9Cڥ kW\JJֳ`/mH8L(!C8#( q|vF<F)őGIyi Ņ[]?Сש#H{d»'"ĢbM/|zP.2zM~^nr˶Cj}א! zC aPVXK#_" T)S~G`sqQ=\vŸS W?N?WFW^'o;I]&@6]v qD"E"Q-_F#\>OcƒSeRljEB!UǨ+r[z _5~I\bk0GOO?m{7o^:X~Oe>O^: >{#bz(#h .EK:\ec%Yl){iE]LQƼͮ~}MTy&ۿ袋kycgRPP??e[/\ 70`MC;~•bٲ۴K| o¶-"^9bjvڱjR +yGڵ[!5.*'{ ^=&;< tD׮]}"b(+/ep-tI&{0f8:uȘ7SxcԨ]1A/e1pf-q_a&Ì3_/ O$Ğbzckڷo7__f`/~zƘĐV.[JFFfn'0m4:¼u[neY7ڶ*I,W'o'ۤ--sA-೏&WޒrwS ׊7b}3}mZYf|>̙ݵT_fmb˫-ӖYC6W +~uR{Xp~.[ڍg0H Y\xqަuUc}E+&== 5SL!}1NIOOM/VBl޽㩧fɒ%^on>Yp!K,aرTc/Y^=D,I|My^|Cvv6-X˯Š+kcxiH~g/_Ό3xgػma7YY͘3{6c[i×_|A4^ZݦMxb֬Y7 09k& Ƈ˲hOmZ߶4]| Ç`ԩ0sL~bOSCl?L D,|\ÿ7<1'VsȖj_jG"jmxD"}g-V,X,ƚU+Kӷvծv6o ߎTZlܹKCqF&e-zxCnN6?|=֭SVN/޼ysz?jCbX,u\SmWrکrWƨQ#==:Fո>oų=Gqq1iiiza\w D3%pwu\z))wy'wy'^t\w ̙DžGy$|-p#p#Wۮ֚H4?Aaa! 6/#d}V<. "ׯ'++n{9?p1O-~?ϴi(--ڮv=ǭKqQgޮuv@˜jZY|oPʲ-7f*UYi9FGmL:,ITT-n`)XѰkV.kaG0lp]Ûdlx>,): sFBƬ*ڶ'x9CFoq8׬eŔlõ5k˯P?5nKB n҅ o4B{QVčwwڟKWQ/ 8) !ƢQ X_/J)fdZ9k< F!VXFzd4ڤN5 aOom۸CyY9kqk$)9&?^]9дy  d| M5\`Khiڼ%Ih}BlۦY,?M e8}M IDAT8CqasO<ǮQF&ұ,x,FnZKKX[=U~z{o4iB4% v-.%^!R;1#LV 훠\/5y^{x%n\pE;f+/Žܸcĸua܈Z7-k00WJ{\ӛ{syw8̳y=GfY$''e˘믠5x)))pUQnF"p岥՞oh$ªov1dT\X_9Wf .wCiyYee[|M,eՖE/]RmقyV{ jEnhaͪfMW=5dcB6!rsYrHmw(Hng`UWp͆V<3rX~A1誁 >\m؆m4jؐӢE "`$7?B!2Hn_{yv3誁 ;nR*1McP KB!v]Cvݷ^+B!LB!uu!B! B!BAԅB!$ !BQA}o$B!Ės7B!BHPB!.B!D$A]!B:HB!uu!B! B!og7QB!uu!B! B!BAˠ[>{w~E]ݏC'rZӹwD7y|;"){/㴞sjxwSL~xL} NٟjB!L{fP`gpZӫ=N$s ڟIqX4,kgn N}hm\Yo?S{^ś++"נ=q07]q*VGvG"ڱYe=48RuԫS;yuSV/_/-$'\CB!jW7`W~7Pk4M!VfW5nݏE/ᮃw%gr7gZ6)Ɛa̱;TxFM>x,‚pMZ~؄lX3E:?B!|{tP7p;m[>+y7ƽGɚſ}1Ѭlv\xjg7MG^b>{~2 &~ :-:7pp#eDFȌ#- .w,lY-c^{?e ]7* MàG3 ƛaEMrr/.8ڇt<7ߠX{3c8o\:l>-/гpwa\[#x`MtMx\>0w?Mrtݒ3g:+Lj ?tD"~BaP3_}#y`ܿÇc1'#|7hKdʃ xh:-/za|t[tCzjgſo%ɛ h"^qǠn˙4n kHkoF*_#Gʸ iurq)Xی!VFЙ]8O/%ӷtV3q{[:G9s#ɝ6/1)#݀Ek.F{!Vj*JtУhsBV֋o|3H[_’3}FɃq)y8I9.D( g6?`.:7^dqҚH"~g7dO_X^zoڜx62C8A mXhE9Zcw}KpQ6yh޻fptK87"|kp jߘzMdSf&Lvs*,;!-O)|-(=C |!ol 6Lgس{F/z>{Cya,O?;ـCܩڦj(Pg8>n{}.{/{8qvٿGoYsد NOsS0Μҧy_|aX ;饛yRL_&}ȻSSZȨCA4 }Rr»ÌB!DݱGuYg`VB_L7 {]Ky&|ӯcj3r ٲ]9^)>H]9cwEkC;S;>oUMC4 JZ ZnBcN_rOd%Ѷ=8q}wakp~O93>=N'0f^8䰓ۍVx/ ku1s&- k4r"@RZ7mCqb$썃 ȓ81m}y`:]7O.Cم<0>ן.(%p-Kęf:ӼpsS?Э3|rbt簼+tk|G[nC#ш^ǥ&%Ε3=wVGЌĹW‚סPOCgُ/>L_~ywrr_(ڄsᓳ7?8Sޟ!ΕHk29O; a 8Y>??]ʙ(4e4]ց8%yEBAݐOЗ-c}n!z=Zwlr=:Wu%zYK/Zc[4ׇ<4/>ZQ2ׂ"wow2AnDqL|rC3N^]e:~:kޏvvva;dT VKns:W?|˅<|k/ڧl-y 0XM[PH"ecK~^9ɉcA};en6Cܙ)r -C T:_,$w+O ~c@nJbPa:7 nr.e zxdqWfqeT93bX#T?@W n8dhAˆZX.R+_G@fK2Co Odcoz|Lfޭ7 I2&KjI.iձ''!s{mM|mXa#ڴ ɜ |r/4ݧ! SU`i쫾G!#%wibRP}Օlo9լ(a2mN VOԘF=Z=W0=oKeŴyl|)B!j&A}>Zۛv :}a֭CaO-Wc,Goa[X=M89灼t>x ԞX+Ȃ Pw}TT2rRWCMyWb#9"jit,u4P7aoINm(N\"K__R(Z_LhA`WE1P?-(>^_1g*eI=:CS u-6cmo4KF ey3ΝCjCnI#oC3oF9]8!s?baSsw?wZ+?5ڟy4jz?܏%se;14׉m2Gt_~`V!5$oBhy*C 0IL9 d8'cuMR^QÐ(.p!qƥ,7ѳ34jFb1CtxVOd;yO1&t80Ʀ15@n[oM9 EդΓo1'W= y1t܏ 9?6 Z]3s-~ɃofZFb^K< l+[!x=}>0 Ӹ3 <'6Py>xc n4q )ѳ]:^{b]u\|j3|[kB!*pQc*;/:#}jEd)B1[+˶ܘeTeng˧}u0I렃|&ESuPշLcF:^r[Wn8#xY\flߖY>n>^'>-nSNR #Õv)ÔbJZhW7I!Գs()--JII!)O9 uf=h!}$68W4cW}Bg#zvv1ۡ#ZD]yeK_IUҚ\ߒ*˖wUe4SºBȠ^WC8_ݜ=m۴ko,]**y6{ɹ꯿̡{ا"b#ziiq]881p\ߺs51ǫbv!;.^~ G ug,Wҵ\ǡuQt Ȫ_ݒ:$<9r!N:._ijA8yzN=h&z`ՓEDwe뒊/|x3~>^}+Vƶsw`eV:yTyEtޕI'X8䋸OYXׇ蒗8xVԕoʘpO.j_x|7'׾!udvuB>㺻wϾh='ϫ#=uk{5Ds9wyg\} |e QgãWA.rdo#.CI<2twA'],t< Os˵W2^\9b=Cx]zm)ŐU}٘ ι=ѥˑ35lz%==K9G/Ke{ vy像xoz(_ҺM/B ITn +ԗ{=LZL)!Ӄx?0hv=tp%t ɞ6_ϷKIj{4}/^fP`bL{^;ϳO'Xy(n$h>nq)qNYB^ұ>xuFN3 Q\$ïW7q(^wƛn>W%[iA43b{bT*bߗ,?ſɭ7CҘ'9 xx)OIh ţ/9oXN1WWҷo8晗zx#TtF^=e =~jOέ([0nr>+'w6)O߿qx͖/^GPqrҺ W0wGI8<{7X06ny Gap{l^Ì7tI-rNx3 3}{Y8x=u5KBb3utFC']ȉ{'mJ(’Iow3 8)!h6 3ohy]'ދ9<v8!um_&t;)9 o瞹2\?ij=2|.\ݗsYl hNֵsTwc4<Ҷ/!](o?)!{M23UYYñBPn}du{凑2!_rWޛσ/_w*I/%F xS~On$[ɿ m'frULiҹןf\dZQ%F<(ZQRz~Wip'w|ӳ&7<=9 ~Ǽ[A`8gwq@?∸Cg0'Kqey'ҬWp/Ҙ8MC/ef7qv篭}'cQO!Lz\d=wjngJz1}Ca_W2d>ߗSh.|d-VL6>Tlؔ߱rK 4`t3cOvJM煳;9-\:s3bݭhG#cKUc6(xdīL#}8$+;?(Ѡ%+\>F|,`F&Ꚋ{3~rT܅\0s{,EBKF鱜;ƙkVT݀/^̊,]@TMA,7ll:]W:h/k\`&bF~с)1lK^ْS ǽ0~Y|}&uM M5~3RAe2,_lA5ڽF` QAb?4-f:FMymj;Z*aHLFH_* {q 6hۅh; WghvPf+Mv׹ +5BhὅGq7_r!B${K:tD /x^ g)fb7)ɨMѤZ&hV̊ٮ+fYMSQ,v4YVP| znTR3jeT^U~5%c#|w~>s ]șf6_ ;iO]ݟ8hظ?&ݿ c3#g# TlBdF<3`R]UuCEjq -ZnPbc4-ݮŁ)dlM ntѺjtSjWcZzD/]#}=-.u'GJu)菛v#Ϋ.3f;U:m_>zͷB!LO@5i8y֭__e2p5 i[S)*xIX,e^BdIR:o_EzNxjʱxTrǷ>U !xMO!nOoiu1хEɱ> Ӕ/9T7n`֭Fa4yz< :3WN9Ә;"ծU3CxB}ǎBa0<دd5<\fG!BdeKBO@t|-ĝ "B(Oo7{8B!"H.B! B]!B$B!.H u!B!\B!B )ԅB!pAR !B႞<B!ē'`׮_#Eds@ҥ2;L'B!\F00(h:ChǶmFҥ3;L%B!\Ƶkh޲%ev("ժSի~02B!p/izf!\t}B]!.HץX CfPB!K5M N u@ u!BMץPG$aR !¥<-Zd kZ' s_~Y,GB!p1::% ZߪÚ|eɰ_gG0hѻY?_%Ǔ='52)4uLZHB!\Et_M'78q'Cm]7`R2زkhxō^)"#y~Nfu!B[YIlբvVz!FN-iqy ou]vtv -[N:P>F~ŮKVGk^ŀ?1{kܭ;Sze_3ͫRbEӒs!* {7v3O{ڵ[+aSi`mD5FfjK-yefYNԿ׽*>G_<}1gΟ߽OzP*b㉛ek`HN~uy}u{-|m~dwC !h;zv?<џyo}YyLWGuj:ZԵHv~So0q x>L:/gt^3v_'} Lz_o|t5.\T1g|F\FEIhN-cgl;ʁ=,k1exjpy 躎7xmM f-JVNK}gdռ竼z@ԟwT,uf|] gѣ`9Xct~ ;p0iʗe~VZAZԅBbt]_ge a4[#QGǃ5/WmI]J}.]W/#[AW)%ZEq\N-(嫤k3pN:OD- bFO}IAG mC1sQv Ǫ\?V#7n9WU^Ysj9uslZr:S1o 5~~7Puf&xuş\>߰;s̜W Zr: \AR]mڒ+Otmȕ'-ZrBZԅBbRt}5Vuܼs#i>X욆8phIQr>v'tkcz㉾l,d pǠkXF)Xwge2p?ӵwoTʁYh:Ő3.]뇻/F k ]s*Jx%N7'-Y7ќNP)q[(>ȫ-&n1'##VvQZŤܤ>.P8q͘T#i>̘6[nMܵ]ÀB!p)Nn8/LEFuEqgŤS.L D5Į$^F0B^sdY5PsҺEK(E MU@CG,._ ʦirLq>8JݶL+VԂf>npF@'hή-eBW;ZcY vͧrOǠ!Cp;# ]_Bj0"My lN^l}V0>?n]\Nx{o{A%,qn.mq&mS͉Ms*Ԣݞ[=Y.PC%1iѾ^^p#Fi_H*R !vǠ:p-L1cUFӑe#t,ncb:ԨVG΋X5YjI4týQ.ۜ7iWիե34}utSWgTVKOi8{'QTC4 _UOB̼<ڄSҭ>>Fq&&ZO`z\M1'f3hUOe }˶W5+l "_,$vQKa(ÙcJf=Mh2F`4VI7bnVbThֽb3)F쟔pYTUMwx;vJѴ/#B̷|ُnuC鱳3Vq5α_?QU}Ki۾]*eKPVd"w| <ԠjWUkZ~CCVm&Mskq`74flvjmzTX7ƩQ6%D;r=K$pB!\&v؂w~=B!x=!7`i\+Ɩv\:H.B0 Ǘ1z6NŨX/Napl Bc˽Xp:}ǽCb۞N_%Bd);gu&7߽cxZM=kc+tEx u!Bd-B@ u!B@v0I?,IQv쁙JB]!.#00SlFtVi {JB]!.lط?CՈGdft2JB]!.l.ASB!I.B! B]!B$B!.H u!B!\Pˆu3;!BFMgv*o!<Eȑ#dv(.Kr1'…Ab/CtRfvO,M$ieM!DV':zfdutt߽H2F&B~8ަ]$G#yB!/B!B$)q=í}k*?_6-{&ˆ`=;5cAAV\^ygG Dkyݶl|UIX-\{B!RB==Gդ&5kRF(5/ߩ5~Y~Jrږl[~ZC_cŕ95)şubk 1Zo"_O[3|{ۓ4Ӊ'u 9ڴ 唇#quׇ5Bf ,4W*w %GOA𾴮QK>]!jjgbdoub̵J8tn\[;Zxo4lf}D⋤B>T^ Pe?'&ݭꀹ6Vocla8M`gqC~;EZU&@I: dЂ-b{BꤣPwŀ`GQANDj4G Z>`kt]wh9f?}! N`U8sFts,S`fl\F䁟:#υ6XqgҺgbK/tfЧ۸`ձ_ң;ݻ Vo닎,i3l>עfhcz-\]*wϥ8,0V -Z3j?'K: CY}$9Ɵ5i]x;9?`{X#^n AX.$b8{;<=e' lUyoIoc<ZƳحe2~<7Olq4D~_7ߜER2ٍ:, γfLpR ui[n-X: _FǝX?x|C"!6Ct&WW`! BBniu9YWe[ٱc>sIt#c |˴y*VWk/gS6<_p#0>y ;aZXysmӿuk ӑYW1Kqq7cVcj5ױC|v\XqP|P|1>٫7ePIzy[ŲaԢ9vV4ڠLl_ǒKz'g(NkFAŞ-0)lWpسA>]5(q'qlJG,!xؤPT-Aƪmiԯ<}VbЄ.7aӢ}z=UrUz5\&nCtwnnC=E9+5jGh"ZUi?LS@(ʯ?͆jr7M M l{ ݆fW->hnC4TT](}{ Ȣiە7װLԴsw?VǿoCg]o_ ST.Mw'(=bsTВ]5t{|mqǦ=>=%>誉,Ms̓VTU؄ kPqUFVh(6ԙcQ͐vz,[5ndl ǀ=`G@3qģj:Ѽ9Mա~9t4oNay )aha1a;lpǽӉVa#~~՛\ 8ÝѭD\…3`%i|U܃a||qO\؀̈́ժ:瞩组u;9xӝ)rvGT幘m,?Rcr`l_?m0a%;3s纗&Q*нonz}&c6-=2♰f  F7ܱcS]XqP RTk28R F\oRޜuO6p8k4h„ ڵ}vckx{EbUqvs5ޝ3j~FXIQ*>xJMŽ^bp< o4B r'4w/, 9ސ/lLL9d/ɫhMw,c&[@ vzO"e3ބ Gk @KP4q'@&̯x&_7 IDATW-:Lyl)GԿԘ|m'W B6]rrhf^xˈvozzB,bRgc6XդhnA54;?&>>ZGX]7ٗM;/_wK O 뺖c~e4o'*7e:~[(nfvu3q d ~~;3Z&3_b7pjesӺ\4_sԐn#%IВ3Ek'9Y`%]t 3^^x{))e (E-\R|9FpuT 0%!Ȃ 8 {wהBv]-p䚚t<׾4;?Yogoj:˜8[neY *jJ~,qmiwhчX|+DZopfZV |1E~.YutNkXuzp9HH~ܥF5u6縤;&͗9bPUl6;x ͎ͦ:v"S6lvb..;:7B-[Bt,Zmbβ߂)돒Y!mE Ͷ.h$ܖ`Lg:vŧk7cOh"OaXW#ιx,+Ҭp^)P&Lb7iYbTf]{P2Xng,·rt3^{1f)[>=C*yR^+ztj0vXj+`ont`q:W3sB&iz 3%|=*(ioNX62{[}xoOƻE!Ľowf]O\CGRp&k6-Fxb0jd1MlҍfŬbդX<bG0uoGnJѠF%ΟCU;}ǎ ӰazBkf( Ydȑ)R8CqYyqOx{GM& _^yӠg\W#IoB46AiE vUL#tOM[}4j8Ȳ%K]fm4ɝ/?/5UU7DZТU %6FZMͦ4ݠFwF7ծv5ͮūqGM/` ю\@/%$}_j0wړQ::$G̀_~LIҍɥ}[|6P.{g,nP!?)ԑ%K&9ʘ3of|^~0ybz$7X|G?fW,x{;}C!xPW2&2%w%9ɛBG xBɏmdlv=H2F&BH2;'ڹ3g2;'9[q? !DV!:7Ona6[4\#w`4Gki7{p†>wMZ\5-Yp|s8w,s+D=a2IC+.9f^0-;!{F0436^o@ig+tHKhlvd|z$|h1N9ή/up A!]:Z3YiC?7luP U9*}!GcxQ0a ,5X0f`p.: ߂!F-_ôͷGt_Oh7!w ӆ;WP> ޱ0 <N>>/éx;_`u<Qj9z,ZpjMҹx/ƫ<0|ߣ V!w2ev"lh l>bYoǸOGCF= ם>n7;Z_=;B~OM-[-?}KQ 05Ȯom9,? lpț Cg˫`J#ھ:XJ⳿W Ccv=Z|B!yjͷ%prX=1zK! n:9Zҹn; Jtz;/l%(!3xG[M%XQ~MwP"0>/` ؼ( J%%G!b( |Oiǯ$ ?աh Sw%K%x:? _ !O)Գ:ix~pC- 1\iW†PuT{>RΉ&([o>1`@Cpl9aG)B~*}M`Ƿp<\J!"~.CW-a.0 !Bܛ"KPdv B!$gB!I.B! B]!B$B!.H u!B!\B!"y~Gnz%K(c$oB!2)ԝn!#B!DV%zVƤAwei*kBc8q0$8(??qƧqn i^_ּ1W. 3pZmH BwfO}}p<Z=X_c7 ͮ!j\yY? G3ó "&"#̨u1|9׍N,;|:7pQ:r!C"zeᅟp)bx_k6蠸rkO1{d3Kc9Aoӄڇz46f;M.J„e>xޥ~t;3XBol38y cޙw6fxυA0SZ݋1p 8ndI̍:Q=)Uf<7)^<߯;5a=teoY!xPO@=EQP%Nű(噒4>p(9-ɋb+(6Mrr`v@uKUiӸ LEס.ZxL>] 9|/J-t\/̧8b8rh_þ5(>ۈ-nF1Ehݫ&r gΖdȓ1-N*ɞs&i\W $e>5!Dr7~"+*=yo?-ة5=ﵔ#BwNT^W?E͜ɫ8N~ԌQ׈nh|S;P>̥^+ZJ<Hnh%X:]͇y͝39"J^/,3mn`˶9zb%2=]'zL 8Jǵpċs1a?8`nR;u=Gu(ӭ`T{r9mزs//9/2]g;y+ѧy;?, ~P?l>?mS+Gjm>r!ăB=2bo3ߎ ~Tn<_&wEͺV]!/x!g6`G(k-25=?)&F}?f-i{z[ļݕHK=}ϟU'ģ9%yt_JЮ%&:]*.$r!ăB]BG۰l:^3Vp:6]'>"uoŻB)L m'hq{_">FΕ]vqbt@&l:`#x6ffWӸTوwLY<u_|]C44NLa6/eJ #vyihffn;W#WwM|f.$~ 繅=b݆e .sr!B] R[kdmJ.s3`UJXl #kSVL_2_uLpC2ߺ|1/%<T";O~+lڑ9T! 9?6x X3~ɻXubc8NNi@ɂ(\0RijO\*}I )\c`[߇jE ~ o?Ļ;˥,mΨ$Vs;% wע[!xPҮYJ3rﱻOw+Dug"ɟ gASnp#Wh&ar3S|oJxSg2>By/3oj8ƌq+X(>Nsy|¡O&q繥4#.^á>r!C -B!B )ԅB!pAR !BႤPB!I.B! B]!B$B!. [B!"yL/ԅB!ȊIV\!<$wieM!DV&Sm2;'+$wie-dB:"B! B]!B$B!.H u!B!\B!" rK.B! B]!B$B!.H u!Rwp,q2>#B!DV%zVƤAwei*kBGֱޝ0c{H\ίe=i^1őU / {kD$q߿gk0PI?&-F;jؾϠP^) -9-b)B^c3+~ Cpq.uzgνJ#!2Gv#=9??QtQcO (ǏlWG=ql9qC{`ou vם&=teoY!xPRga(&}JcQPݚT!$_>>9)e^,ߎ dY S&8'^)lcW|(V+'[:b# 2dր\udϑ jz#z~8]g-[g~2#jS0D:'9QxgDIJ@A՞.}D!!J /H'kjn)`su,~3OI"0xg /srǕ4R'l54wm}٫nx̫SWVWlѝ2prGnKe'tۅ-L2wDR1{jvcsd?`tO/o]$L]FbFxiӡtU8{o^Gb|#h%)[:N{8kD8 Byy ֦L$GHP9hd]˘.tnjbSjf5춬k߿feNEUXV65k. [17WѲ[v ͊j#=3 (䭷TTUEUm'bݒ |N%-VϩRv-fʨ'ZXf=)r-'ioVp|d=sq óf7Ycäm\9/gЫKx!>2Qtb,aPM\NHB"A]`l'$~C[ IDATdkHp\cV=$wP5Xa=ΤVήBB'U٨XWn@;NʖxVH&ADd:ԗ_;ЖbEC?-$kFXJU >,4 d|H!5żGU ?sb>%`VY6BPSLқc[Q.+[ϯf7nרcSo"xF"&Nw6а@ GnɸFid;H@8۽3>L ޿j#r|D^˝ ys oãDX:"Fq:+6n,)Y qW ~O0h ʷ/uz~5s25C S S5ٶ-׍7~>"@FԅB!($ !BQIPB!.B!D $A]!BHB!%u!B!Jԋ0B!~%? !BQ 7fY|ٽ}K]7!,mwU/\L]CNȄ"w2E!BHB!%u!B!J B!B@APr)B!DB!u!B!J B!B@ԅȅhFb潮B!J+ ꥑ%Oj 0g=ӺxVל}?g)[Ϭb^e&ܘ ,5Vw{L̬ mY1G̭h{vzgk 0G {^'up;3q!*Qdiwm~e=ۗ[O002Yn[~~W1=Z9u卟Hr^1}Camc'Nr,gw'cBFDȯyW\h5KOx|uXw!6lR bOpږįsS-[ KB%ASE1@Nz|'\ U? ztŴ__=Z6GDnd̤ hӏUEfn@V~ߗL̡ 7g4UNB}hP& Κi;W=;N]-[tLxW}MaddP[lEh㊛?!W<3s3r@V]̀Zyc/k3nRBX>!ݒ^j0{ j]ps1|#w1X}s~u}OfĪt 1iH׎gTFKG[=,da0\{fGh4o9GRWq%lCj&i ._o¿B YcI9̚O_ח>,~3OI"8A O4{z-8z?ZU+MGg o6k|[9#Bq䥲cr!=7:Aݪ?MXdrv 7_C5hqVn%)7:NF6~ѹVVIL~{GY1Okgaۍϑ]=hף1 S(><6]`y[(u8ϘOڔDB "Կ-,,XRj"#ܺRk*6͆jװ۬XVlkcX5.a42]G1~~/]r w/(oqa"!]ib=6 T9LiZ!;q̸E<2>%{XTTUEUm'bݒ |N%Ymmzf-sŽkٴ8Iӱ\ѷv:uŵdoJĮY y{#BqWR~i/>~w&]h>Qn2?ݖuVL:-#]m ޛĄ~r$\CiSfO2f7x}up mE~dY'vRLdDhjQW}Oi\*Ko1wl+tQ c{D1,>P8a㮗D.;#e!6_p_͈:ulJE?~p= :LhX~%!*ZҴuꌒ."5OIoһdޠg :`04Q1*FaPLb荚⡘t^z'G|4RvRk>wwtU-x5mE:@Qq+=o-9iѪeEϒ7jXmz*TdPb]ǮRjj.v.̀r-]U-6LNVj٭6UKz'Mלljbwb*Մh~hcxL}B!.B!D $A]!BHB!%u!B!J B!B@ԅB!($ !BQ~wB! A, K˗*ܷLQqBQIP"__]4cT4rJ9!Bܕ/B!BFԅB!($ !BQIPB!.B!D $A]!BHB!%u!B!J Br`4 L#1^D!5qmfGȓh /gV1aH/2`nĄ[HOe|&7ĵhQ l/L_ ,\߼zq}O@1Y__F ~=]Z kI?q8M-SR:8Gv䝙۸`-&ȏ<'F6gKa笷ys$Ͽyv @pz n[=g̣͜[sKز-PIY7qECB *Sk>αm{^'z\VAg!U_>=WRw1כ; 57]害fr:}&rw{^l[iW;rXc(&"{ߤά?qOr q/a}j[5.1!k9x${vw2&ta/I(;v?٥)F+gVNܲ_IX+o:,s`=c'N@̊bgsG=!uϰ 7NmI:g;"q![X:7V1vMm`Gf͘s=+{1O o h;#Cz^exmR׹|o'<́o zA.kB3zF5GSË#;ү3?K3Uhߧ##*wt{l{v.K0e[SP`»tn {$# vfm//yة[h2 *`p5!Y3uroI9Ж܀ؿ/9A^,^Ƒk6t!DV,SUK 6` *mɌMc:D?<\;$l%bB 溺fLԫלYbA6-Sav]%}֩INTr1DOSWח^t~AIX2^C_dϑ jzxQ{Uq:k呧H,?y~j+7zնrmٿ,:+bG'5JKB"(0eEkJa;)L%%pqp}Nnz"OɍƵc9d]Cu7uYEpGO"y"n`KaUYҪ| ZrnX.gLbL aa4˞-$~ކz3QlIdJi+g_^üyVfFR&i\OlOq]%=͆@y%q&gEzÖum۰zѵ7)^,^YnsS΂GnIPP2/ W¾5*8{Wxwȼ^z3Ҹð3b.os1X}sO~u}OfĪt 9z߿|tgބrFpjEiQ>C 3Z뗳 Y/g͎%0k>}^_H<%-3Xדa7·+if?V3IMSpq7A#uDv>7Z>bIOe! gwRՕƳt7jt絇 \![R;剧t#eW)~oLx\#-S;+{/z>Lǐ&72=vz#|-4k>|ag^`΄t, _!m*r /rџn7Ʈ?GΛa]=hף1 S&:BY~jy_\+Qq$q=/a"+39iET/Ί8 +T7[(u8ϘO7Fs>"wGziجVl6]nbZ#ٍn0ivW.Y.[A@6RfbP5Կ-,,XRj"#ܺ΀~<i*mXV6>.l]#kJgC 6^e$zC:3n@.OzJMEUUTFz!-aT_b9[b :zl7Isl>M{ӴZYY+8NkcX5.a42]G цMT15KT#^#BqW$B "F+Ǚ*@ٕΣ6gO8W" .=-_}K2S-B  $8_q /exX0 xmAլg_Njr~eHY[e"#?EjSGńx~՛FZAa hG1a"v,$kFXJU >,4 dYi-Ms=_6}U< fEel*?+;BjF _uF&ཇ_m+u6졏Y +-}D!VrXSgpt!ѝVyuNz%Ӡ=Soy{Ѡ鍊Q146 brU EoŤ;)>z镲]t,v{ع3Z:kbWAt(J˗ɱ+VzZsfӢU)%114n԰x:]ӥ3բ]VQSV]ZZm jUզ[mzgNvfٯ9LrŪU2 gp!)#B!B@ԅB!($ !BQIPB!.B!D $A]!BHB!%Pw|I!B!%? !BQ ϥu[r &Ǩh !($g.1*9n !DdB!%u!B!J B!B@ԅB!(.7RB!~HAPB!.B!D $A]!BHM6H̼5B!Di%AdMF$?Z˪cULҋ31!Ջ}}?g)ک\=!]ϾΔIϺCK?1nFٟ Nc͹ԃ,Յzf3ƴ?HY(7$ּB5 B.Tq|v䝙۸PM ?GV1愘yhVF%5a%_kEu&llyn-<[gK=G{l;8>e&Œ37eG?W4!D12f;H܆OuetF[Shc}|(%:;n*pz1/Cfn??0'gEgЄ9t&d6kYp(C#pEw,L$HZ9_]{л~&K<ɘЅ$am õ_WQ369Y<ѣ~%Yа˫NvΎ=Lh  +ak-t3`{C!~ mI iAtعw:/5”mK)(b0]I:7onWOwq: Ovz5.K6@ɟ=!%}D!Mo,(_T*?iO!NtYEpGO"y"ed]n7NzФaOOYlQ=p#ԌB?`f4FLbL aa4>h!6ԛbH%Uz`Nc_9PGD~hn?aq\uf^V~{s3a?H׎oW$؎%9O}'ۥ,lqpu_Efzxe}O9 JB%*cS& m'I6}۟FH;W'~Ҡ{|~?Vn8O`xA>-sWu]1]!3[&W3Rη |6A7Ý gZȘ۩j4ur;f&6~O˝\Q ! CMĨb}s={mL.s :+zM*7xH˗\&`pS4:IW.qɷ+xJӸ,]1M5|!ݒ;剧Nwg) zV_]]!~LG|8N&b =g,"F{k''zfb'53s0n910z鉧7~ѮGc.#1+Zc?js4 ˨C0uwUhG\ӣSz߰x;)ELs3ffӵ6ex>"wGziجVl6]nbZi*ma[Y.Y'nDF.ܬ! IDAT1ӹuwu(ʾrxZv=ϥ/`L8܂g#ql 5NvՎfϪݑ ~x&STɻ?B#ƅ{t \jd׾}e oﱓ>7fA{Hg-QInHO>ĺ% " P&_"/M5TyvNZ<CyR;~7ͧW9n*3O] Ozf-s@kX^#_-MÚœWRc3 DnJĮY y}#BqW$B "F+Ǚ*@ٕ^,ހd}|^p+j&&mɣU, eӺ\ֻwqf "8.6fƄ/rNsJǪ n4f0K`։-q,р7S@[>yQ p-$kFXJU >,4 dnf؎ ^"sz"7'v˄yGocjǪU!z Cb>_YϯfA5ӦPgV"?ﲿLfk!:n&4,ZÍyy<">~7s,>i|~c7 ;g#tk3`¢cnk 74PKSy׉e6/08d-OXvNƄ._n3"3hFs}̦Q]; %rh{΀d(t'm\I|w '0yG3r]gX{~mI:g;"q![X:7V1vMn?ߛga.뉇o0O|6s h\;yWx]F#*s_UV WWOr8%F1HO:spc/_^lO9@oe=+d\;waʶdn%EA1$yH Z>cau=Zے63c# |nL~s3O]칺m<qAtz,Ί3zUQ ze2d[Of?xYP!]^ WO-8SpR$l%bB'36LTAxm9/b֓@vi9{mV9^>>}m\t:nߛ| bYt GWĠjOk~@BE~F,(_T*?i-f׎-c}t_ tJK;'7WHLZ4>~{f%>Mrm=̛g%jf$e<4P,m>NdQ=i047/I=I!Y8~-$~ކz3QlIdJi+giӰxV9[V=p# ;oTjcitp'm,C+dwk^tmAJWV܇1![z26eOv⏞dӷiT>{Ը]Y;1(8{kWi7f^M/(NyzS>=e(n9[b 9."qa"qіĎp-\<H7q̸E<2>y-*5UUQUɇXdD#PmVV+vՎfwfw48_#^hwl5k.>pPmzf-sl֕ZJ8Ŭ~ǜ ?ԕa*Q6&N% YGHP/m)lsv^ jHpP A-cKQ3RDhDL+nL/)<5i*xOv2i].ۻ?LES1Ԡp6~ٜaNʖ#XkNNjOV#<*:aoa\r~V:Lm(=L_D1Y{8a+T9G0;sH!ymˠ|1A˿AT|i\ұje L%b!ڸjF _Il߃x5`ʢ.ۂn&4,<![E]vcNQхTDwrXi9MzLLAF7*Fh#؜2 UQL6TQsWP<KuW~)sy7ӱsgTuĮÃ;Pv+/cW9FE#ǭ"7̦ES=Kbbhܨay\yt[5]=SMQ-e5nեP٦ZiЩVժZm:զwj]divMʹ[.WZ%Sp/mq 7&2.B!D $A]!BHB!%u!B!J B!B@ԅB!($ !BQAo9)B!}>B!B>~zir{]1*9nB!J3 Y|7F׵Z/~])_]zVz BNz*w<| BE.Ys5!B$s !BDzB!$p?B!Di!A=;'L!#A=&S!B ͤB!B@ԳhK5@ue/9[!3BQx40TC%G[2zZg3a+Fe3؊ʼײ~=0>u/le> s]UAu/e `m"='֓z?xN(>"BQEv2+&Š (|7 3߃8 pΝ5+qN+LX6ͧH2uZi9 *2 'r9Taf5n>,)ςS6]ռ_s_pq\ / M'3`FH?ÌP'| d#x'b`9xmH ZQ!hV56 z*pt/楨}D!?􃑣aJ_Cy o4 ~Mv߱.f2o>Q^_ Qo.}48 g;A0c\.C0y<10% f|Y EǨ - O7¸$%!l@AF_sW~-:(tea5@me@֨о͑F=`١lӀg@e X>xG!pp9n(W1|"*=mgOc`TXu Uxw<|&"?+`x PTXwTF!o Ni#&=({yۭ+>ۺˠV TzMҊgz1x3΀y{#̅o~ uVT.G,`5@C fMDzΣe+p6cLSxk]C8KxI07WӰtyOEt|܅080q鷖<ć +t3)кB>; <zVּ\ نVǿ!UA GmؘG{GA A=LR1G ?pqGղÓQGLy(k39`gy5?gѷ cނ-oΰ:*kpV`Fx7v,ʵ̬ z3gxi`ͪrfHw+X7)ʥ{`t+0hj388y?pڸ1]=gS 1 ܕ'=ufÉ OGօٗ%e6-<!hu&Χ`X5 ?<ڣ _Ӡd x7C>01 3^!xM?xo=1i|b@3NMKBڿq=sa_ +!)-[~ S@gu?uM? [ /M^t?4ؖ55 9QFg a< 7;}r>L83s48K@Jcf8 i ܎ KOԍFɽN\Y#\ ^if#?6OuPz_u:xQ3l )Ysl(GHiޅ̣ x-n~R!Di #Pax/ #/^DhVU`4ޝEU͝ÍQ4Q4=K%-f٪喖_}_Js%K(P\Ps f+xC˙99s,} (`Ұ#Cpy{N UաqTNbh2X0ng:qW(^atike\Vf7W[˵Xw;S}*ݻ_LJh e qo>"B- |j!pz 5- o ?( trNyJ).#tnb* ~F×30f2 jic>?+0(Ҍ {A؟aM_!C('<"CP~4jT{,̀aOCϥwn#Ɓhos[Cq+ y3aL8us- Y_N@1ht[lI8|Ca@)0]}U \?l. Nv#B!r;An׾JLtѝTR:IfPtzޑ7:j4hzbTvM1%ՠdGu5OŬtzW|5RxRHR:]w]jlݼ/gUUd/Z?k֭QhYNB<M$A]!B|HB!u!`= &:QD!ǐ-z6--[pz^Ed $۝_ ,}m3mYo}B#9z3_OF1y_Xg.R LY|5繓Nndn4 vnSZ2g͐VUl^YUOlכRb!0>=>U{./of*v +95 IDATW/ҒOz _!@ٷe5~cjZ:֌GnԷXA;z^y#\ٞZɢ֬7elU Nm~&ACB<$Wf:x3g9s,5 &|>U.%gbE'* ^g dy+x)=p"&^8>]m4;ODsLmBM:8| :v7_m\.m?q1Ks6 ZzjL 9FŌxn&Jcs&t#ubgF#JV kdO yڝk :./Č#g8sw&?wwzLЍlzO1p_"6NM>׸Hy=FP1;6>"y%AC+(z#h^ߏka/GR=p7Rx1| Uh$^b}_ h'oHb(RRWtz F#ƛ7.=5 o4A%|1UzS7PF$s>Vߧm5 >f|Q7YF LOI y"ż=1}zk,u Lk@pH=FȚTMzHIܳ *w/k[Pl(+u7ŗ MSz Y>A~= QL%BT)B^=q[So.la?ר/(G"O$j9lڋk ; T@*Ah^'2jt&?ʍ(bs3U$ 7OW| ?]BĕlGmG8L@ ^vĔ'4^H:m[ǰc}|֩@u凯Eib!b3L渹4&"y%/WƆL~'; yvOݢ₇7E=.f8Pp.)I3|4-)޸<cxE˄1U'RwdvP3{ K!k2wN>=3㮇<<٤=HBK=1DP_853O0[wbD$<!nS}ctd91~oaV/YsFլ7R0=΀vsQ0?MA-k.s#]hxt.ϮݨDVG"$?xz{e>ӵ`pJDʭT=~`tAm),f PiF*T1ezN@Z3Lprܟy^WLZFw3^^^xy_:-ĬDf} _$&[I$;Ѻ:4.mcL~Dä19ll63n(ӭ3r:сj̾_Zkj;WY΢ͧKNܫ-9=s{.I>yҲ=:LX>:w.QI=U;!4_P&jws@“ٻw/e(ztr^/Y*Ogͷ\JVI߻oU" `E s=3}Jg(5lY9u5" I&v歫9/}D!DzbkMR,*an<͊8_=uj 7R"40*$tlzj-I:OR),vc_=j(K'2D,;>hF *㼅\qE♷Qx@خ,#\5gӃ'fq;ڕL`4)10`1}ىwלL_oJF*IRTқe,ڎ{,!D2Ej04G2ynҟ훷 B0,=gͥŹy)i?5΋ mW0rNs/Ox:m.IгpV>:i|HiBG"r4~;T@\yI%˨sћniE7izάF7*Fh#]R ]QLvT7QTP̊IwQ|:W+'$T=Uye6ӢU\UEAaZH[!k!DV,\@MrNQZzuz=0JCǡijjUDMwÀVWjCATj6զ%jî9:lZISz> ="Da}ÎB!"? !BQIPB!".B!D>$A]!B|HB!u!B!! B!BCԅB!ȇrcúZRw9:7!tչ#_3ܑz+8L!&S_B!ȇ$ !BIPB!"uQ@!BAPB!.B!D>$A]!B|HB!u!`= &:QD!ǐ-z6--[pz^Ed $۝_ ,}m3mYQm経[:ևWF{!VI2-yLPHSb!kL֛ /]Y1'vP{ ?-bwl,}D!JcKWPF<2>!֮_r1{nhb*. z͛A.s=;cLxAf`]>%]`7apPMP _f*6{ ,@)B^=q[So.la?ר/(G"O$j9lڋk ; T@*Ah^p{-<5k@7`m5r=|Ga9w,l2U-B'HRlIZh5ә(t(7"U8Vۚk4|(6 1t%Щ2T+mV(.YZZ*!|p~A{"pwFz `%6.R/g+>hݏ OF [Lb#K1!/$vrz6g/rlCtavF5<0:wH'MބP?G780'i>˜i7H/ Cq쩒|ÎY?,ȔY6:l%z|sjD_#沰\*54/B-m1`ȇ$ [L29h5ë1aoĕfbt]T7>"y%/WƆL~'; yvOݢ₇7E=.f8*Q?Q|*ϑEP<=LQLyuߟ!WB0FZR2qQLٚ )U'-<ߋOF`]\=uwna]M#񆂛!z|c>Fpjg&/c]}al Wbe:xjmכafPܝ6n),f P㳢(OW3bvvkd?3#B7 -۷'YIv_cƴ AJ{%ݰbMэ`JfZ!7\ |/u|ŲWI$_\hғ멮tdꆓpI8Iٹ:_d笠r= kJb';y84s,|ʹKM_ɏj9a/n=| tMo/ I=U;!4_P&jap4gΫCủl+ 9>ڸ6-%|i1s?"[aRnSqeaU zʜ! 5JT܆34+|t\?mx&$jT-_BPd[&o .H׷RޭUЙ1p8J}ߋ@ɳ{i7xRyʗ@?zӵtlz6Rtq R&E&'bѸ100`1}ىwלL_oJF*IRTқe,.}$A]!B|HB!u!B!! B!BCԅB!ȇ$ !BG{e$ !Bņukur&u;RoB! 2 sG;gRG#VpBdM!BIPB!".B!D>!B!GPB!.B!D>$A]!B|HB!u!`= &:QD!ǐ-z6--[pz^EdiT-F%cpܺ_#9z3_OF1y_X;Cݓe,Z*B߯9^>,@KU[}1n&phGY>ۈԲ=q [hiƜh[gEK73ԯ%>W`ӒOz _pvK/pgSRI:{7 b!FG>Xv:m*'ԿMկ8#I'72uh7;r#/[vzU-Z:m<瀟IА>"ǕhKC Y=:>]R w%`JϷ7:s903&=2Lڕ5ݙ/Gd֠g)4O+2gN;C޻KNA6GLcvbvgzK0Qm;w3ѧ8;3삑R$&..w='FWY@y pۑم26sL4'o?>`_8Ldfv3}G6 qq7bᧅT !D^.KExex}?BWs|;j?O"F,eHF|Bv$,")Ͽ;cLxAfܞÎϧje=Ƙ%- >8fsfz ? woav=*DhNO(8Wvy浫SEo>sem=Ję`z51ၛY~VN}VHBwwFz `%6.R/g*)/gĢJx*2<0J:\"y%/WƆL~'; yvOݢFH;Ϸ,>T1gWp.)Iobd0{ 4DgbRTl )0 fᴪD m@r517*[.︺'8KFǗ1j &/c]}a^pF'vPϿ]cqǤz|*&,$E(J0W-{7HGAf0w(͖Ejo糫r7>՘!+ ++^xyqϐc0߄נRH+_SzM꽱+v#+U%Wn-MʕQV/(fT BfC 'O/:RWҟ5GP*PlF>/V`tܟy^W|h݌^>N81k-ѩYOS m{vy{W} SyʸgjoCٯeJ>i0{ IDAT}(tKQ0fRBټHB^(>eܷ{{_@6~L# :JWLn8 c4ߍ+h[N\ |/u|ŲWI$_\hғZU_,ZPî/妓PZ1mygjܼ5gĦ75aye8y^l\wB>ϯbd4탗{N]@)W1{'ME+2v%y #׋),s_~QGC0qR9ޙ#F4ӪgQVowqr|ʋMo+[9Bv )nsiD月QEeAP>^[HB]Ҵ[S]pqt'/Eoһޠw :Nop ި]S`wI5(&wE1QFSA1+&E4_M7z+{:t}nނLVsU݆ukr u;RoYYp6q;Eѳj խs=ϐ:C98ժū%%YUv 4N6f9lvMKz]s).v5au%ش %4(+2x=2E!B|HB!u!B!! B!BCԅB!ȇ$ !BIPB!"A]{%'B!A]!B(o.06[%u3ܑzBQIPO'__;9:C.Ȅ"k2E!B|HB!u!B!! B!BCԅB!Drǣ.F$ !Beo\rQ#GԅB!DҰq%s`hc[2dwfίyEsY{C#F&y`@Km8J |zS*Y,է绸z]%˛Cv +Wm8(4Nndn4 vG0_ &Gz`: $@=gޫmhNS?zU-Z:bƎ}~&AC"ߓ/25c9ѝcqh01[ǧK r}_`o9y&y]*Fܩ:9á5}(ۑv<+} a[8vGHxKR}9uSGEаZD6ӰGo1#^,[{ooع>Hؙ?ܾ`_8Ldfv3}wZGܰ`}:ʏxw>I9+WsgY1 qϑz>{ ?-bwl,}DP ވG0Z'#|N=ǷVQ*bbш͠GJfp\}2W5*^ɱT8nKmZ7'X쀚G>T@K |sRm უh6g4lWc$Ľbq&YOzکYh[N,; #7аr;"^g>"_-S_  ֍Jl\"^uUS^F-)ψET.ݵT+6RT<Ω3bOb-w額 gcW]o-{as:5jb(JK}|ܣXVv 3Rv= 31kFP9i] (M7HL̘eè*JԜbFu;e{ea=?y&aINe8~jӋ}ʪEsG<~5ë1aoĕfbt]T7>"ȿ<=+*s=uw=/`&}GrZ;z|c>Fpjg7[wbD$dw@!r?~f#*'vgn,؎Ҧ^6ϲ] eUurABǕOo/̸5aa A*V˻{cWߢS08l*|~ 7X„t{7CCLҮo9[7CpULOTyg8b`=I/йaFz<ݪ=e̢s-Nzt.ûpܟy^WL0ftuZvljYkNxB܋^tÞ7B;R/uTG]?NBE6rg(OW3bvFl"}D!Fz<Ǘpp^v~U5?17$_O\ ++8VYЬdU@exwL9cd6RR5 ;ulFZQ6/*5ӄ]]ph+XUyҬ\e96r ܫ-9=s{.I>yҲ=:LX>:X3uMEUUTNrq !ʄ2@4.mcL~Dä19ll6쪳igvx[>HQ/Qhfagh>́аmlv6-%O?7eaU zʜE! ⊹>>7oxq5P˄8f6<D yci*ݖ/_CnӳUY, ~?bOjP`v}ƂwK-Ut&4B<3flzD,ogVr)Lb7^1&9%^>/;DOhDH)H*YfȢBdΥs"4JqW_]Χ+/qeV(s?r]H-ʔ&7ږҾBiʼqy&+[9b ~YNO CJm>"yܥik%[O*)^FޤwK3(:AHtfH54Q1*FjPLb鍚bVL:oi^)epbbbP_y{hס}ufZj(6[+uܑz+8w-ʒ hܴI)U+VPn>^ 09.ΑƩV-^EMtt7 ()ɪjuV0tM6a]mZл8Hqi-4'.G\p: u!B!! B!BCԅB!ȇ$ !BEu!B!! B!BCԅB!ȇ$ !BIPB!" >"kIL(wބBdW|wΤrG 2!ȚL}B!".B!D>$A]!B|HB!u!B!! B!BCԅB!ȇ$ !BH{ȑu!2SakOG]9km.Bg703hݺmR`.6:h7s:YWp!QMգf!y_xv]}]| A*d:xe!} }_\{o5O :Cd|n>ϻnד<4yo>sWxO@ka`{p>ktn' ,>;è nV{s"W@0U;Šv?#B2<򝡩FSpq;:;ܴDG@O2~.3f ~fH%@Nղa= =kF[ZY_} O@0A@6 6+`EhS<2xv#B8X0q*lj, qam@-g3  _·p b8D\[xX=C07+HG=8Q ,)^Sr6O}φ~ ̚V8nd' y&sH4Xs=TR,~y1d:Ũw%6TLl5 ~< i|x8{#YL}9Zվ=2Z;=>ݙK%ϯ̀zx($>ˆ@,xM^uʗдΐ^vl{_ͳI?Yc²6/-ߜ?V.{I iy+_fF-d{w%?p}@@ݫIDal(^_ku8t.VfA-;Pv́eq< j<-6irJ5g%'899| '/AMxsT<h3_!xHP ͊*ֆϦ/wAIN/T=s=1USfLy,*k?{TqM[E@APYl\A Ns [d >"2D*CEeB$H]Hz$;NIVWU~(Pg@"C'BφLV*Op!7R|{@Oax<; ?oo80JO=wڶCp$VUP7a0 I;( 48-MBI3u  c=}r0s^3PM( f̂!4|Գ09̀!~ 9o4!Dr{OH"Prf}DD ',_wa"dH0k?_\2M;o7 Μ*;jMMCeN!&|GaXR` x%,j؏ JCY?<&5y?]h o3!D' `_^/f?Bf_M/PCAHd2L|dv8v̀Cv"4lXKAukׂC2~yGDD$:^ 7ԃƏA"Xz*"7 < D`]4lhxmR ̃ !x?dO¡8c `(Viow$@^퀴=l{\O_B{tZ.x¯3FѰ(S(yl.xx:4I2ŀsCiMh^ woYp}x /Ն&@I,_)Lk |ںg/O+rг* թ0?t(;ؚᣡ0D/}~XFO@0/n ·k yr3>""r%QP/`a:<*<05pxf6z a@ҌKBڧ{gz@ttAx uPator0a3{Bo,.p7me;UlNP, {o|qm' `t)Ͽ:-F@ۡE[( ^ ɽax8^{|Yh< @wo%ƂSgNGCz/< Oܗ"^^у`@I~>Xi뾄A`@b2)Ì򣏈\)..vY֙zma|4)[SN[eIs6K;l6×tXv4^p7(aB ;BFEڃvUԲ-6AL3hӮ]|?o>ӲE5EA7g,]FGVp-"b4kc9ð3c4nwkmDgn}-їf&)13籝p`:i)^3i1=ky`dA>Ny4_/**knُU<k #g]܀.""""R) u.""""EDDDDHRP @ """""HA]DDDD$9{Ŝٳ{.[j.MDD 2tꋣΙ d2b < """""HA]DDDD$) u.""""EDDDDHRPypM;+߀f u/Q:tw }VR摅o*eyР*]?_΁Գ?f&mfv[Y zGboؚlfL~r5gڝϦCNdA,aue_1_^+_;zv&27asu~"o bvǔyH= ?M\ME>R-` ]I}#~8B6M0BKӬL9?X>3`!d&N{+SF IDATůP2޿zM64;ٶaNCAK9UVW x W,; A.9FO6;v^}9_")rc#ս#MJPԪXP{c\M>m'g2={3p[oT⟝f`Er hoLH&ʗᄆuM4檈 l2~}=O?ՄRa\o#nL_o<<܀Bvh\=u KgGDDz`&bw Ts'~N&us<>R|w:uӡϻpof34K""w9R\׫A#$JՏ1Qu0Y>%ڵ9/P#*Gis)Vj8ʶE{W7LGyW>Y(tΰ/~!B$\KI):c axpKcx[~8w8ΫftVD$8C3 #T ոZF[7:QןboGDD^/TΆv1^M,$qส:u%U\SJ㙱 =M[R*8ţQ+r"-*DVDMcxЕzWev<"/~/]ꟾ/8Da pT4nGd&-BN'-^fjɄlg F|EtQBrU!ǿ|p>""W.n\DePdeov/wOa1 V֭02nTY434""PT-Z5"?,^ON/`qjZDb:K~޼ K&lͣl c&#""y2 N{26I d ɇۆV°arVmϑ)$`:M%λC^ǃYx</fg&M\3q-Lǃaj(~o leb&d,TqdN|K>g(m[U x6F~#{NxŰRG bLvA$N$qpww4׽85"/#""\8&[f߲jGC[L|G3|f߉nSC|nYy晶SFxg@4$ d}3pSz6*> Yl8Bn*T̮D Qq%i&lCbS &6.O,F2vue #MϻiS!.TVώÎe?Wp_R;re׶JGc۝8]4a;4n;|NewN 'xR+0\^*d`.[=(jYE-Qr&:i~PKѦ];L3~?o>ӲE5EA7g,]FGVp-"b4kc9ð3c4nwkmDgn}-їf&)13籝p`:i)^3i1=ky`dA>Ny4_/**knُU<k4XGk苈HRP @ """""HA]DDDD$) u.""""EDDDDHr 9g*\v9S]d G?3Q: `YV~B4EDDDD$) u.""""EDDDDHRP @ """""HA]DDDD$)_>+H:㬛:O؞ H43TK'1ĺ߿/g\FЕFdGDD՜kwcg<gJ`%Ν*FcӦv`%aDg'۱eMڔLdu7llg"]V1;_^RvuvǔyH= ?M\ME>R-` ]I}#~8"PJ̤а0suץ}طyӀrq}}Wg)dI& iЛgC>壶=;$>""ԯX6 aw]]s׍$x5m>|a5lp"dDll-*tRJ{0 SHΗnȍhTF$( N'7[ůnnLŶ myQvaE5]CX10b%y⛬ VܝMZy ۆqv_wm/[)flavBf5){]QËS#+A\׫A#$JՏ1QC$&)N͊w8y/߉E2cG!$ Ǚ`#(,婶bsǴ+y5aeۢQ ң+3(tΰ/~!B$\KI):c axpKcx[~Yɛ9]6/3fY\\*.I5_L9h<+!#]W}7KF=Ik`QЬ7oHVcV=39߱y?zT!l>""W.%L"" ͘pJTf;7,IU [ǁ36kR3a1sB-[`peީ:%p""",BRhml=ˋdʛX5*UrhOss`>""rY9K ܄"lsz;n)?r 棁ݩ'>G_R3ϴ4hƨu4s`>ۘզ!N]ݚ}xpR~'M +BFTvq t|I#kdǎ+0gJP'ΐ Q ezP Pm~$qxʌ#^{Ϸ$͹ճ꼷Ims|sPԯ@R=vklJ8oog:Fhhgx1}P7vLG?fqtBXCllJɯ-rh(^~%unb/TvM~xOxk#nF&Ts}s數~9nV+>o*y햂"9$+2gcʻĺɬ=re=ьn7epțbH:/tQy\}Ư<ʬ<#""@AJj;ٱ3MP{3ty{%La|VƱiӏ};W/ژ~//Rɕ_c~=w>LdaPg}G<[~}sgUa|}LyTQz.J=ͻv#~k't% i[ 73ib*4,3SǣR?,۶mO$)&rϻ|q3VN]% U$5!" zl[g|Զ'SvgGDDˆa70N¢kТK}Go0-NXUThWycrY"76Q>:\԰qdAZ z;۽!gg|&nJ p(R 脡\+d=o`of6VMP,Qmܴ^<ŠCI}̵|X e*oh.tiV%<8?ƒgU<^ɻXr+ĖE⮒ʜQb3;'gp;S1ˬ GA}[ w)?8 ]b1u ,R4ZR>4ZCY[, sY$oț˚rXB;4 } M$xxTl}:],ZdPJPXw,uz'awVlXo #""yǑ+ H\׫A#$JՏ1QC$&)N͊w8y/߉E2^alr6b%&l[4wu#aTzwaqrWywDQKu} ">Z:OL!~[{^tۢt+Jז)kh ~{^j?|;'fqMdΨ]יn ڼ@q5fF&}&ӡt1Z}DD$JlȈom͒QOR'A*4M盯e8)ROu2l!njRR)]^᝖?wi]JbIlוsDVDMcxЕzWer\<%/YkYWt%}dz7 $Lzō_CِL̈́%f g~UgJj<Kaws}Ӟt]7g=[˘{CGr<W+ W*{0"#'4(ÿMe1ls = ;>U;3ҡ2rQ-[`peީ:Y{gh8DDxZx6E|jE2M`U܂Z*R 4ԙmyG?H3ӱaY"6aQe[ʬG|؂Uˎدm9~=dY|h s#""yCA &GuoH>2^O&I.gՖ9BJ6Ϋ3ܴk^"+\jǃYx</fg&M\sᯅ1C,}!qQϙ zuرLL4L3CՀ2hZڵ+Y|9K/a%0ÂYFP8ӗsga`7-ׇq w<҂M`Sf2;ff!E 8Z~+y}H^e,њƧ2tpr0&V_[NJD_СJX>OHZ,UͤmeIAgQu ppl@t ޟzw{"TiуQczR!? br iSYs^iq}yx97zvm꼷Ims|sP..wY֙zma|4)[SN[eIs6K;l6×tXv4^p7(aB ;BFEڃvUԲņ=6!L3^6a9_y瞖.) 9gr68jCk'ФYӦq[[s=oðSX193,[/L4Sc&fc;8u4Sf 86czLx+ك|^ i_qUUܲxi&d]b } @ """""HA]DDDD$)HVP @ """""HA]DDDD$) uӯDsfUlr68j7)/~;gjv+8t@&"9 } ˨+"u.""""EDDDDHRP @ """""HA]DDDD$)_Eij*(B9]znwfG6NJA|Rp,} O,SֱaFA6BuiC&qV݅˨;رW߱u'Vf& \L9󩏈)+ n`؝EנEu# ^987I6LNp.aOfQHI*mxd&L#9?zp,-{*%)Nu}_kglkz'* *ԞyWS{7BbIzg<ި?;0 "Ю!ߘ{LnʠyT suTJF8lms]d?EQǥPm#E:1Ri[#x6Jf7Yu:3Tnz(8m#(,K·yz-gv]ۇ(tΰ/~!B$\KI):c axpKcx[~HIH-_83O IDATAt>U 1DS@@çE*73%4ysJllꪏ^^ bY2I]sgVf==3lT23',ҒOBx$AX):zxq4_>AdN44_g ]wUfdz.b,aҵ+>}0#gx!puW 2pI-"b|~F_?mI|f gxp(/I*F!dUAPϯK\ ""Lӵʼn߿`t9T'ŪV%(nT#J%3$fHaO%].rV֭02nTYgh8DDxZx6E|jE2  2.z6k-(m/~򟯢_Ū-U"+@Iٖwc_wGDDe0X9~:tJxx`#t|9[9r|l>BrX$6Mxq/R*ǃ;@<0iBx>,ח?eyϠY'4MLɄ?X8c1THQ ( b#bGzfqkIXs(٦1CW,׿&XQ$7]_}'M,_2]U?=8i=nk׮d,]Ok ff:H^ekcVۋe9o-:O{vJxw{vbgJ?po׃|[Ƭ6 vi;{ ܔJ B>[QMٕH!~X#*;u:>ͤm#rf @1;qKI}OcCҿBܐ=*!Fjjӻ.Cc-,Ձnyn(R8ԉ3$… EGW..wY֙zma|4)[SN[eIs6K;l6×tXv4^p7(aB ;BFEڃvUԲņ=6aL3^6a9_y瞖.) 9gr68jCk'ФYӦq[[s=oðS$*n}-їf&)13籝p`:i)^3i1=ky`dA>Ny4_/**knُU<k ;g]xn } @ """""HA]DDDD$|PtuF)>D """""HA]DDDD$) usfUlr68j7)/~;gjv+8t@&"9 } @ """""HA]DDDD$) u.""""EDDDDHRP͞`A!-"""{ WT?D>o[1Xw 8}3f&xaBXźd3 lOa:;!*k?/+ynt{dƱX|׿>pX9͸{€.Nm]` ´ᡎP:]UҜ#zAˮe0Y>WL?}yZ^G~\::B(X9|9&@5\/Hv= v>!wU6:쎬WgBϞ  /'Wk2 &l#^?G_B hT,g <33`,Mz}UqX1L|:auavXxj$æS@Ce v@P=4ɰt2, AՅL8(>o| z쁧cЮR׆&i@1p5I5pJ7xX/^ _vG@(p2wvUaoI6C !9Ya'!h NeW,(??_y8W:BV07<XhkM.XꌄV:c< |?[³E0L;4BI0p9U^NOg}AjxO(n~x<؟ 5Ђz ނus9ݙ0'oڇ`AiGrLQ }v  s'{ᩆYOv x9cH:|,… +uN/ p/7p'7dQ~8xx%;BD.{8<vrW7u<# il/E{3Tg=u7LF'aykd{o>U:Aג{>_z*0rtw`Ȋ%]wSg@BX3+F? G w3x_p2}DD+``ǷU-s6L? }u'al8Lz;U8_> C] = 偽;<3܄_C۪`w+wڵC/Z""[! 7{FOO?Bc=}Lj >> #9-37򰏈t Wwa";Evx  3i6!1:loOM//BB x`2X Þ|G&'H.? zXa%ٱATi( iɧP8jW?{?wV,!5VQ.3xo|v(MK]g/Hexma#o|絟.fnǬءd?{[7qf__m_]`?߇៟:q(O>ef4' Ϧ1e U&ؗ=C;Bx^M/-KܛaOP.v~~}$,e/y@AJ Ks:L/LX^g'pc޿Y Ne3ӳieS)qm' P:8ۡV+X6Qx h%†kQ0v` E0턶`5v&:a$8n=ޅwB9/ƓZ3x3.CaWx p-}/tW_"kÜa 5s[sap,L0VV>Ʃ-9 apKu:,pNe80\b؝V!#p"AFQ*jٍbCm{$0f?_.Mv/DzϛODx8luQMQ͙=KmjeТl}VR9tڷ E$3_L@fMs,gvfLmn N(VxgYD_hXL$vqi{p9lڃ=V;5|)e?V82\fk"Vj5_/w(""r(ȟ6\qׂN{-DDDߠ3"""""HA]DDDD +~MA]DDDD$) u.""""EDDDDnY -]FG&""z:|OLmtqnD$AC_DDDDDHRP @ """""HA]DDDD$) u.""""p%uu~ďnXwV`13!V{e*7{?ԙCKxG}Jݔm!%=Y9aOߞMyoz̢Eֹ|+n_yOVې!ĺ;0c7ą3-JbE !v[!ϿRpXX1?aD^9os7;\*[G?oz ~s_K3IuP㭍dVE}DD$)_\v';vƳij{.o/cofm,z" ?¸mXIkYl v`uYӫ;6%DT[3Xq3kBaJfMR)Ҡ7/Zφ5|Gm{2ew6)a|}LyTQs (6͎mЕ;2H6DՆW)ذy#sGFQ{BEi=#;o-g|'@DL  E * Jt<">Gr D " ɶEhb EB/6s̝^3s9ӽ6$3әԾ ЖZl_?7ҫSsFDD(k l`WO-8f2lٌ]iz-NMVg|f~:d~9Lb 9Խ40U/HHzY~.蜙ƽݶo%00ZA荬qc\G=+jm ʣ*XLa`X|.͙耡\35oGas]ĄYΰXZ y/db93݊O 2羖?NѹEΥWV} xٺQ<2W3voD~l=?}xCشLGouesH_u)o-9=3ui_Fq7nlj+vJaz4"VEN/jT'cPDUC-cƛa3iѰ)m{?d:&?N iq@^Ğ ܳG„4y"K؀U#""W@& hV0#TgF4#0A{k` ȴQ ;~ |9f_+mo0tAZД teofS/gtVBDѸw=|Gjc5oh#48J17 aĖ}ݛ$tX)l=SObVcup8[yD`B&B=GXzK rܴy|ށZbyyE$-;`UƎ_ٵ7䥏p. ds..Ʌrx㶱oz33_%NwOfңYb2_HS e~)IuЬBaŇ_]R+Y DG[| r=#sjDgI ՔѕX"Uc>K~)B٤̘An>4W\)W].=ٛrAwnvEс&+!5ЫAZX)_6^[6p0Lye ~5 +s0\v}XūS8SVA߇YuD&|u1'HEsRR&NWGSH[R@X&oτqˋggi:ftToDR#6Ǵ"fic(3qfIfrbT>X?8TƿF[zF_n{acI8С|=T]߂{sF(L=[C_DDDDD<RP@usF)<>E """""HA]DDDD)x uT/ /EjJ>47)OW_wGFVvhLDp"""""EDDDD<RP@ """""HA]DDDD)x u.""""ԯAI$*2}FaqשX7Y6,hS`_ɮtDŽFVq5FxdžӆYD WѳsW֬;#'`lITdww3őC wdw6?;3bZ52ĝwGmØvNѹsٽ#W5煯~න㋑oאꑑDE֥z[6EV.:gҚ ܄U#""Wʧwkw:hÓ~c ]N2>G {v_1,;;hk>i'i ?=CMRZ k9ۼ cEïmeVx~!ELt|3=U??4elݳ];Hև=x~iFѯ/RVg bnfj>΁t5[ɣ/Х^$!\_7 [)C ?8\xy|̅#OxTvhN+JA paշY`n?##y}5φ#Kx4nܚa8{+ɝC5Kyk1p3jU-<[pwJ`Yw"گ~(i K[+)N/jT'cPDUC-c 56Gِ.OO 9;nr_M\mDsꌟЇEՈ0q`vS+R b4OFl3I#j^=5(iS|7 UßcX Oӟe3SzGv~_C4M ).u[ow:'!Cxl-a4]1đ嘽zz͸H=`8yM0y~"9efb_& y[ϔA߱o8?~/罟;1gc9c/Q _DZAO0hׁJ Tnәnfnߛs? u/R@5""rZemIa[v%4h-l6>WvM'y#zƬ|#iؤ6U+^f|7;m{/urطezj癙pwVVrc|<#Bz2u s:}hVY"wII$LfgzU͐:y77o &( jG fn;fm&?ABڐ>Gܷa$DZ黨yscMɡu ÷oՈ\+ AAZe&\AAyovEс&+!5ЫAZ[Ad`q]Is1caҾ%7Q|&t|F.J~ F6gs-ȟYCQi [|M%W ύbɤw|.[&qΪKѷT`El: +m_,wKyu5k 샤.~Dҭ]pI8]?啩Тnpq_ƌ9`pr4eIwq<[av&Mf'Nv_ƇN&9jhib~|K*YM{X4f4Af"v9iZŤԈ)1syeʌqDrDWÛùL}f)[o/: xv7'1lrf/#lrFn<ؑL\ UwUzKXBP` v|I]Q-\0_}WѥQ_Ha>>۶)a3k͛vm<3t:t8]G\6qlt‚q2y;\6[L.;LNmwgf/t8Oz9\N7Sݵ-g:wLA/"""""HA]DDDD)x u.""""EDDDD<RP@ """""R )._ڋpRߕL}tio""R)4. wi/@4EDDDD)x u.""""EDDDD<RP@WAP nr)"""" H٣~ O}d$Q0jp3X3i$*2DZbsnrxg` EFR _[ipfʹQ<ޱaĴwvu3qA qDEvg~9\Y>}@pgs72F񌘺C_])yqHz4.ض;iSٱ1&:2Ȧ|3q[޾wkKH[Irn8=WYwFN^"D5""r)_|11y7v:6c=U-SF!1-lٶ՟t>_~mX5""rE)_LflſR}:n7yI6q>4LL3?ScZ gx}HQtO* $JSz=ށU?tΝ鯰/.ݸ;{>;r V>;ܕG[U&00,>|ZBLtP.VΙ[7FI0Zmb v/]9H=x+RtwuWv9Q~6C{jq}""At*HXJ\Z A^ZPՈ^rx׬N.08؄l:;7m"?ן>b~: yǏ?3քd'Bv~_C46%-؝/%q ݨs)FXOJeBH=_*wgt0\$'L$!|mP3A,"mF?7V榚w2"F,;¼Opۛ+ؙ=l4,fz픾P&nȦ2W\1y3^kK>XHزs/I YE+|y$>oo%IoĐfV*Tw`8L߻Ʌrx㶱oz33_ENwmƋ$~}>_(rq=i:_}JR>4`)令$W&y߳o=Y3#Wk`fH|¼ |㉎웷L_bmkX{.=fLV?PЃȍm2ٜUL6 "81xFj CT#""Wu4foyAA24R7w :,X)_6^[6p0ye ~5 +Jpc3<0/^}#_ekiX3Z1uhNv#XUޟɿ]:䵑g=_ AAA !jC:mI+H,!(r9Ѳ:&7РSWnq1:1yWaC3&tސKaqE4Q\ eX[drIo`ި,m}b0a"n/z'0na'.O}ߣ&\٤N{ghQacw8Ϝp_ƌ9`2ukXz5+W'1{pe{&lH>w2 ቺE ˅ 7s$Bl 3#W)~1=x7|` n*?-9tof>"` XI\v/ұNN,#in2b9ΤɌI5+U#""W>. gh +'Om z :ax$Ҏ]&wN*_Qjhib~|K*Ysa~VAu+aDR#6Ǵ"fic(3Q} EWÛùL}fAhԑ3~b !@>05|Th5ϲz& ,m 5bdâ1ylr0ٴ'͡O/&=M5""vk7+akK3NYM^fo0-fgb 4-]߂{s.2.K }@ """""HA]DDDD)Hs5TRP@ """""HA]DDDD)x Ki/X`~i/UK}W2ѥQHY~~觿K>4귲C;d"".""""EDDDD<RP@ """""HA]DDDDy|Pw"""""e5Ȟ>DEFlŞtҶ:k?aqQ(_|11y7v:6i'i ?=CMRZxioNjWm3#<1 xa[),0ױ07lAuxyILK*[ˢ^rx׬N.08'0qM~Ykqt7:]j$JDW)?UK #@>&CU|S'pccW0wD_f?Š4iN o!!޴z\tɇJ b9i $ԡKj]ԞjDDRXJ{ob[̀f .s3g-|;V|S'sLFґu~bvd>Y^*" FOQ ׌.:xJ(4` ӛiW._,gڄd' @98L*s7fs <󟣮/FDD.>/U֖|(ֱe^>LV0pI|zjKtވ!ͬT0FҰImV '4ovħ_dT. s}/$;3ևI)SY令$W&y߳o=Y_*a gɅrxR.f ;qv#H޻b?Z˥~2{P.@5yGbл)|q-n#&Ōڻ0(|:'kpL5 \=QTtfcl8n!]-8xfq 8tu}K5/lB1^ˈi+I&aǖu8jDD r[f~Q(߀.œwRrzz ~oُ+U[_JdciIЙH[nד~0όHjFVČ92{ eƸx".D* h0Oj[ ~~m7rvq z :axZ71̜:ZNZצ}3.=sjDDr)_U(m`ӽ36;c j||գ]47)OS^w%P][١2)u }D """""HA]DDDD)x u.""""EDDDD{P?(m^2V͇'F -/i,f狄=7 ZCCc_={ٕi}ۃf༼d&k(5i\r{ïmeVx~"c)՗maΝ;}HY G̨\ ,0[T[pd<@ҼM1*ba0l@~&F} +klJlژYAݑ?d)%qMw|vim ʣ*XLa`X|.͙耡KxcڴjLlT8֒DWBp ~U䅩{_ @|v~x%)S IDATAP\2U߮ƻfu-v9_&L e!O;6}?!t ^ V5aChVK]'pccW0wD_q~(i HR1fժL[eCyB~&!]ZWï$_ՈȥĶfy$*`҈fz9i֡:sĭ\߱|\ڄo2zJiAƊuSn U0ǘHr^x=f܀u mݞS0G<S<`޷]~Ƥ7bH3+*`Mv|W-={B!MJn)\O<ƚ\tu0(דSէ$C 1KKJ"qe2뾟G=K֓庤)%>AU"üH%:1W<߉o'DuT#""KAZe&\AAylŠwSi)KٻZz90  uhV/Rw)6cC[`+wJi[ t>k#Wq{zQ%V@*BxՆtۜ^6D<Ɲe)߀ldtl_PXϫՈQP/غ''OF gm# +kòKv M~f* _[jZ |/7fjV^ʄqaK[$V3/uᦾInO ,: ˅ 7s$BlLnÁcq 4>5)Hڸr3i2>qҵsǠ{U!~/eĴedc:ȎidjDD r[f~Q(߀.œwR`ex>V;ɴtQ5L@C>wB@ 6a%vmD X3i>vwq-w\ׁi:9kÄ}m<n0[.7bV UTՈ_AC_DDDDD<RP@K""""rm"u2HA]DDDD)x u.""""ˤ,\0᪥+ҨDD,SP?NK{J Wߕ@}tioevDD /"""""HA]DDDD)x u.""""EDDDD<.)EDDDD"k=}##(xDŀQst۞Os\$QѴ<lg^m]1b p&^jkG-ήϩGo2p9؂jTo5V)[*Eٝ9LpqdYn͏"<1u-JD_7.漿=tύa?]L9L~q mk |ʧwkw:hÓ~c ]yzΪEsZƶ?nMN{h%仗bX>Q>y_/ I uW:iW\Dkw/|ٰk6!$5T3эEά#璘V؇×u^v yZ^DRe?F<Ӓ FDD.zêoW]:pd1ׄl:TL&8cJ]}ӆw /NJbOnQMȏ| Y:xGMfn>;{'[67C)XOx] 79[ʪv<% ߢ}Oq:ti] ڞ>g)m1'b#H6UrҬCu^笫?[Cٹ#cr΄u7sLNlNE~܆B&B=GXzKtEcL0wVa4]1đ嘽zz͸H=`8yM0y~{dQB{g!Sg܍qg ˧k%,J$ulٹOӬL><`޷]~Ƥ7bH3+*`D`'>>uOE͛oJmwXŘ ՔѕX"Uc>K~9VX6. 'spB\,W`P.'-S0OIӇf ۟!b|Dd}?{'OeیIlݫr!(!wF[ f%%0w~T#"<& *7 djŠwSi)KٻZz])?7{&yinQ@dXppVdV׮ז ?<ؚp_.U޳ET/ ʅ^!6g5"ʑ/Kֲ4C:~{'yssmY7:"L:z^FDD.z<=8y7j8KnA?L;n96ra'v\!& ~aekL=;wj3/DP^O`4N8dm]{ҿGMK5`DHN^իY:ك+c3e F -߫ x/#$-#<[AvlN#DU#""Eez3h4SBty{I o8 4(gQH)׹m]2%BoCYf%UԜ$) h}}UF8i/_zr`m tBsg.x1‡CXv<<<ۻz㟵\) -(m<-"roZy U.P6HcMV_o]n*C9޳U՗ sOs-9w3:3ký_u9""2(w^x hd<@{m`ҁn;>sL1r~}sppAp%[?y\m?!3gծpɧÃKˀ󇭻Yu,g~rLN7d!&׮qOÉ]Cæ㒆s9ݵק DH[̞gÎA~}cؒjs|Ʒ{fm/fPaÝSa W~8;J#('Nn>~#B}q/"x-b=!|`v{׿?X> . >u=<rXn8 g_P>Εa~kޏ^3Z ;k9""2 eO\ <̓vq7/^L `o¾7Cg^9A @ۈ)omsP'\3XXVcg@zpMp̍0w^Ng~[duAw,+ѷ߁nG'/}V=ƙ~\^X8s,SWO¿NEsq1}-ww ~kC9""u #ן{wWw¡p/a7 pZgZH& v.\Ev;?98lLi_qpðaVl;8s0-#!ӻ,E%p#s;S &pMp{qo_{]h]k߇S | 6&spu0zUp)^(爈H)7E8~8u$:6MNpMYH=9^ˀǓ zu^ o<ܾgC=+7P=̾ 쪵wm\`}nv{=ב  <&ϕMs^n(WeFE1 RP u RP u RP u RP u 'v/o! [zhu:r_{uWԭ~k&ͯ?^vwݟߞ1pփz%񓻟9S872.Vy{\s y&!_8S2OGn]\Ln_=4?p=[EDDDq0*ż7111b̺HF\p<ʧ}ߞ7KG|p<&~yL娵/Mrmfk֗~^Xێo骘UfUp4Ǿs*<ɇNyOp;"~ųҍKA]DDD$ƎKէQimPeP(dV}v}$>fcyG:f2(EDDD2`'pB\PgXhkKk&Oim_$7r 1EDDD2bʔ)C=k!j"kyEDDDdK]Ia03+EDDDdS'EKWz """"2<; 2\ MV)RKEOb>gьH$3=}~(""""[g%άfΧD4iWfZ|rmc̙kl~Ǯ Nsf.b.,Y-Z 5KCJ5]<Y/S/ebYHh\̙Cy\ξYțjp*]5jrE,I$oZa!qѥ.4jΗ"duŸpde+*XV[m+$K-u)wa5 Vϲ)+Cxwe?r1YaBh+:fޛ5Bq.jVB>Bh歖I-jf' .܌1jĈEDDDdSgV#:b!uiJ\5Ib-X(X f1CzqLRTXM1Y_ϧyYּz\kxoRŊ%V1|>TC5%XjDS˙8 }ŘYjDDDD$=RiSjU3ԢՐC4B,b&Br9ض`)Y _ 5snfBۤY־`[6&o$Ob3Bj.XԪ1-R5,u$I-|{'A,V\.iq(X4|)YɧV&RJ$>IEKsbp}b]Y,[KXMe˖&&ov쳰C?uVX芥hŶh+W[_̇IS4k|wPxr9sѥB5xWJ,t""""]f\-T jTW$Z-$h)>!IjV+]/mmhBׅ=Z`>k/&mH+̙Oyu_ڽKŘ>`fkZK9$b, b8HbEDDDdE ZzM=hc5łPz.bګel~HFwڟK/3Lbw,b<Oj$Z\Gh"""""J#Z$uiŚ^I1IsĪR,%Z5꡽-FbR1-[4ݖm/aӃz>_5o,ie9sbUL Z>M$,F}Hb51 *""""b5GD'=$b=`&BZZbyz5}ժheӡ/3r͖yיXzWhZbuXܬኈ.bRb}E_ hG IRi<1Jc9gBBǖX(V4˚o΃z3=6 l>n$ܳ4&Z^m_LOʩf>q%Z%΃K*$1X>sqljϙŔ"ޓ^S3 қr-PɅXZbk>jl~f5X^/3!Eh)4<#txb\pIRp1_DwW  :f`V X`чhf16Cv]8aZs=BzKU{!}mfHFTace3UmѸ ]븂o.|{^Y/Z+y\+:|+>$M. zHWDDDDJXI0 I1&lcHiŢbbXv]Cz)+yk]M 9thTP [ ΕS\!q. s. ej555keud>dr$oS`-|Y5ۨ>-/kOaճMw!}-+D.99\8r MJ """"r:$ŒY%ŒԬ-RcװJcKr5=ҡaAqx{W})0w-UDY%-\k.8g\PlpEDDDd듖#HXjkoVY"1h-R!!چBz;hPHFVԻѯΡNe4&&J\)q֫բsiw ΥjڋHӲ.(Mk5AjorUY%ZburuJo~:!#4-/kOFN̒}ۂctJ/,\+/{7ɻ+kC;4NGػyqLъc  R&Z>!+:@:Q+L\лCQDDDDZXV[2`u^0݁kC;Cev|űxN8ﮠwt t}uX; g@ TaPC:lukBY< """"ٺC96i:[>Ö ^X^ampiֆs@@-aKn}v;]DDDD& a5ے;[G?ֆx{7kv;;]ȐfCu(H q@p.""""[BFȐ_H^IENDB`qdirstat-1.4/screenshots/QDirStat-stats-help.png000066400000000000000000003215241311502036700220410ustar00rootroot00000000000000PNG  IHDRU- ?sBIT|d pHYs+ IDATxwxwfwOKBHD{^P@r.*6T` "*ػT" RIo?BBB{l~;{ügf """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""":GumDDDDDDDtvjRw (DDDDDDD;Hr )DDDDDDD7rr)<}Vw;bGV +>ART'mZ0pik2eW\`QCRSR=DiPp*jx zZR%L(yi:uا(} """"""@TvBIUCeVP@DyRĖ(}@vgndBDDDDDDt&X"hC%t'XٿE J)ÔAJB!yFM`dBDDDDDDtp(*q4P5`Tr TT Tv4:j@+VT TO<:(D%!S 4RJ B a+ '2a! lئ.Va) -mQQ]dC(Skhǔ9`9ZkЎalS#]RJ9^S+؎eOXE6W;ʾ՟se_0Д!.[CE*>!  CIaj64˰aHѶ4DDDDDDDtsԎt!LNȑ* m eۀ0!gԖWAk J1J37 iWT-hZbDRX"!YɦF .!!Pٔx0,)LeSia-C aJ嘎RjH[(Y[%""""""B9B(-2ViBC! +B Wh@Dt)mH)O6eBE@TVEJɋ@d;$|) w()TFٺ)QЎm*-L[J(t %\PSRjH""""""C4r@ۖ4鐭eXZ iZ+ SKK(ChK ځvH0DQb+W 4Z UL(̐KJW6JEJKHe ieOB[e#T,8K+]-!܎4]Jj6`I UaZ 4EBCaжA p eJIU*Elp8Ѯ- 4 )FVf&֭]Q{g[GA<1f]`qhݲ, WM)-[Bhִ _GDDTaԨ'1w޼*5j^xWǷO_1}HMMBfpO\ڿ?;?hذ!:v[n>,^O~O5AKW^F6m*}9hٲ^?- kKz8ZEEExjԓkt#z0M>/&I3T{GrmiikhaYծPo "??>7pk@B8\6=sϡIRSlڄoal$ご{*/r:QRT\`XR@ff&5طOQO  rp5ޑڬZGFD\|n~/ծm2fۍ8ϯx%&&W oipNGojطR 98c'JKrk|_eb4o]QQ\xFQj…x'ɴ58&L~hrhݺu_d)zAQ^/. r聗^|ڵ}ݏ+~ɓ&֬Yw{WALL >, tyPcʕ{8Mk0:HwܱDJJ ^eSo`pbܻa޼EB|<]w`78p}nK8q;"66}A߾}vPvk`ժUp\ܩz&"ص{p5@[hǟ\}5 mIR,[x}ƚjTx)6rssOxqϽwUot pln'Nԏaܻ wv]WoC**PPPS (Ea1^9TqEE@~~xQ*k׬m:IDEFۛ5 t{b&NW_Gb&1|QX|Oj$ /[ƍ5|j}1~d=m|UHJJPy##q-Cҫ##=?8߮fdd$>~;$ RJ$iٲ%>?: ,d"?7xWиq,o<4MjΝ;~GŬ/ѡcG ms2<|1ocʦ&'c+_|<øW/<=@|ݷMDDu_yrb{8BiI193>z*[ >cMx eYPF|\#v^*c&Jah\>B DDDVtqͰmCpհ 0rȊ4ʁa擀耘5s&f͜YF׮v`0>O "#`k?bѢqꩧlOKaŸ[ТE t'tw8)_;(,,Ę7@An+|ʩR"q"{Ͻxgk Uxzh<4b t8(tgy&b X|Y}2Kѣ{7 8GΝ~*@d}WPXM4C&QTX[Kl <r 8[vZ>c(@)/ nF9Y eȑ#1xW{jϙ'}yk8rtWx8瞻Osss :ƍC~=&u]=U`*ݻwõnĐ! ~1Q7Xn7u}4q2ҡ+mK7T132 Яi&[.cc?~ sc= ?C޲>o1eTRS/ٳeZktΝc={6N>3͚5Nd>d:g< L2W_}5?8; jc=iۂ@&"/   SN%GA^nH)n?q xÍh SNEqQ¡>NMI+c=kV@G`ܻ/gsmxsŗxÏ}٧m\7:!v]V?Ԡr8q c,ӄ-pY\.wWA^,UeeYs*""GT)د¶mEc U^]7}RؼiT(<F=>Y_~ܼINIkQO= ˂Res _{vg厃l\6[3g!.._̜}֭[W_} q;koorv> abg+0``}MDDWy1=#  ڵkQPWM9 3T;?/pD$$6ƄIܜ-\{mѽ{wlXPɛ֣q}s3fgbԩ#&N?Əߣu!•6~~OH@t,klہrUyݶmc…nYEDDK*/gkh#Za:y"V-_V啛eB!"=5Wp8JKKSO/1=W}_rْ*^]gIqQ#!!", Nd8}{w1JOŪ˰tbeaTԨ#=5ݻu?W_{?ֻ۶mhѢ>Um""/iXBU^9YV& K/eqGrs_ْU+׭V֍`v||&1|^N8>Av]wȄ* (]-CJ@Hs lrv C;gLDll z.8VCrJJL0ZM6a…xqD۶5Ny۰!29[ *—KGvv6^|%[0i]TT{~V^uaI7o.Nߏe˖Pmh6`UP?yU$) -B~A~vwcXo| jݺb]߿1o`ӦMHNI3fVm""¿! U…qϸڹ9^k@>ӷ/,@ BHۜܣu]c\1p%** -Z4+wᄓNB|B" Ä4$GA9623`˖-ԩ#jLj8[' ;;8W>q~1^}5 &&'|2?o˖gl =mT\8y ~I @˖-qA5;""zz6RSS͚5SG㔓NBaA>5ab3ϢÇߊ`aܹ3<kW}Ͻ♧ƻヌN;m}4sxh<|-!ХKˀV~F=u7<z[g\/t`v8s~\.L GqqnwVQNlvNV dɒ=]G"ZWw@Ȭ k%\L) pB)a:AԆ%-iZZ cCy KGJ(цK64n 7}YZʦ&ƌ2&2l(~?& w/o#ahHϏFGN)ac(**B.]t뺵iiiX2DGEm4I]꟦-Zqdn-ZaDx<^lNX ~ IDAT!(.ѱ a&FiI 2k>䋈@l8x|^ƶggeT@iߩ 6_ߏGuQm8X A|bx>9 "/7ۯz&@DDFFںm8D^n  af#~)p.:D5F|ư,W#jBfg#2'.{ڟYiәjڿuׇƍ)vY}B94n@nX~=b4>#k=(Ys _bMvuB*Wt*r¢؄*p*!S -múH;˱c;~BNu O;* :a{<Re㱜,<٧Kw{?˲Ьi""|)[oؘxa""R7ո"P̪o9[% %%;}O'; yӆ:ٙ2;ϚUVTX‚*R6E;~qMWs_ QݮjQPϸ%+ 7lgl׶^Yg`B 6 p۰P̡@w1cDVV~Vq 4רѼysض 4x`&@gzTD_Ի/..ݤ]I݈{EZ 0wT_\J6T C3T %cM}qq>U^~KK5+=끓)XVť⢧PN|0LI)Oq1ǣK :+|hyZsjKD{w>5 b/b,4<}֠voi'g<8a]WV{=0n#"""""ÄyvC=yo+$`69<=3Ǫ 4p=KkM[ r ]۹V60!K'⶘ZM mBX8?Û}C:""""""^UxH?!Ҷjg;incdu =vF?`O 8pWڋ"ε}OVŷI#p7ax0+LnRgiw~ faަ'$x;F 7L|w">+Hh^; xc=AACyWtaxw1XL})h.Wl|3&RC n zf"JƬD!cʥIpA{QAH Mg_/AHv)n*(Y?cMj.'GSEǟO\jb0a)439WʼnI^UO 8?7"ړq%.?!ī}{܃q3z?nn'qS 7J[ Ҁ=ƜӰ|xe &#>ȳ8v銫[z.0c5:W> {T4}&LxC˳o}V^L% ׀+1蜣Y:}!Tl2&֗ht8u ad-|4s6eC~:6!"""""]tGߌԭ#Uܭb5~ĽY)&7B/Łm6gCoGP /D}qEp T|$4NO\spLz_=n>:\-y^qε)*Kr<_7;:'j6dGDkd̙_CGiXPѡ8@>WVMtL >Npu;&`gxݟQx̦X$%է7θ4Z g4mjLeh$~ V`0jq.;=~|}y>F}fۇ$רF/EFDĬZbhV"'EKC#Gwit5>Y@Lpi1z|q×܂/>\ڍ`,W9su>1Se#(%e8̋ܿ0av m{Ǣ.{apln\*.\-y>N~\5>7oUkLKt!xK-hp^)|1 ߤ5u?z/Zv!z6΋em-,}3vhu\=|0\8#>/jc q be3˜hD-}mOOFyWtrߖ@d|6Ыi6nx}%>f=.Bht,z\ct>/}BaV`w+,RkXH:z[8Ǘmm1<2{bp똯0` 2,|(qP5T1pWS1@).1 =5aS ^y^Uq1»;`/[?' h}d>vr;kُ\ݮC]9P04G >$d!' e)q F Pz @xѢG'U\[@&Z/lСZm(w$6lGSz[ŁUz< ' ƈ4Dؒ凂\<2.Hˆ8!.EF:4GFeDZbZ-(k)Td@b $z%MD8'擰x{ nugٽ_!Q=rH*{E ێ;Fqsં-L} _O_|4N^؀Y=Ϸqݏ.[}>4n =8'qۯFhoJу0jR?dg!cxO0{wB? ct!5>Q(\!:x=!VWeU;|˞w !lXQh6Rp5Yw7!3+K&?7|֜GC.m԰vfG#Jh4ʄʴ9X:7]:5D̑G i!oc ޚ6h$tmXS"6n=SlB􉜍f>9X}<.i=rg"DZ **+Jzam*sCЉ&d@) j}J_<lLA_K`sj #z?/BNV翋G~g՗!"""""lBݧa,?$/܌CF-еM<"T 6@DZ;ITH>_p,N},yif~]Q\USGT+r1W0'7ڈ,j76&ypJyXJp>k*Gҍ@ LѾs2鸧W|m/Ā1uTu[;qFT<1nF 6lB#y /gLU|y3Nps4tycHFnlm[Ɗ?G'#=_D۸F vkmc:Oq#1x+hl@j(<y1 4:q0Q GFC]94h 4u籝,|hwct8d5G n[f}JANA =q݀xzJܛ̉\7t&:#,8Ht0=׿_~1'nxVmO=)cƷ`RpGBVh-wg!Wi8λ[FDD{\ԣh0i206WCJ T͏R$s4;# t G㘤S[vՆ[`FwGoG꭯gEpQʺ ?n#>~o9±0pNcs7e"e| ӾWCwEW5>?,FMϿUW^|hѬ6>+eO}\֮DDDDDDTZWw@Ȭ k%\L) pB)a:AԆ%-iZZ cCy KGJ(цK64n 7ei8N4Nb,~ft4^]i_;Vwe^G7ڝ;$CRin!4MjsYj}nCjC\S{H*dm4M^~ϔ_/l-]_SP9""""z}2Aי3NDDDDDTɑ*DD;s`LDDDDDtp1T!ËևδCH5<v Mkz1w:dF ! W m/l0b8.t\0q=W]xsx9ݯ\}! H)a3v@~L)hB\} alv'.o+3`w ibzQp%z p[Lc|8*+z_{ [87w2sqXdOEY㞡vep9xy30t s 3~"/ڜqnz[ڏM?Ǜ~EYaIq

~=7㧗w1.'X){ \:z\$

0٣Iш1R}TMF+Fbח ן3l~v-0pQFN!2YBSG k}o>]4Ckh_[}A gGYi9ySec1*cs<F? ڃ&zW?#~'"^%6YSE!B ەJI]DNЖx*|Sl%#g[XNjގ7$K2ܻkǿà+sa=a>0>N鑤G< ;̑z "`Mz ,eW f\<|Q;Y`5g|!& ggzƕ(vN{n/TySS'SW 0{t) 5pDvQh\HeUɐO,|i}GX)m:uq,04qa\1O?[לɩ;6σJB|<G,w&m2q„V oENͩ)SU2>GO/$I쫊K6?5g-HnI -ѺU UB5r'vä}/?2B!BIR% <$UM).sCa6yc7[d O_wnF/1v"nclp/K8A6E{G~YSd*IyhXfW w!{n7~Œ⑸-4ℷk5GuNxg!gQ;Q'iДP`z`VgcoƼ]1=?e|8+-) f\p3n׈ sNsVЛحIvR㉌N+x'2h!(YIŇ("uRnW޷pr|0ՓEB|p/ՁÙc!7*I~ u+qc7LTسl -SB!xiǼ8nyk84f:[|E<`ظ/DaDM4'Svj4f\r9b 6ͭf%V&&q^byc[cWk9z+-K8/X8a+6}wǃ5[Wn:q+ܾ˦wVsJt\6Z5]} ~q5ҎFhbpsD47Ow\ rMUš[]q]r{Y#ܱj[r~)x߯@K ҁ3km5-h?'ܚ0uq3"NݏJԥu+ :+tGjՔBV;4t%委<9n5*R+zo&ۯ&$Wlpkfom ZԠ+Sl,:YTB!B|RT/ļ){99'eX@(xD]f|2yJȸk?+3/b[Mdxlƶ2a6h[$>if9U*SfL4e='֣U")`ӒOƛYdpI});^y^gn^ M25hء )c.ĤQiD~_/T76,gZ u`Vʵ[Э@a4],G..R{S˪[fa"GF+yS3w;Y| ,[\ Ҋ^e3ߌT8+F ؼr8NLeդ3 ѿ]dZFf2$Ɓtނak⛙ō c}sPg>O7ȕѕt^5}B!/@@iVqw氪aEPQ6%ڀ..VU-NvAQmMͮwiQCor5gVir goFvM -e DΙ`7ƤFp%Z_̄/#M9mb is䷣n8DE[3x{B!B^JRhؠAuo.bXUgrj͇{o}"J-HGe&a"Cؼ-B!IRARYy7{Q_$B!B_Tyc,I3a=f%!B!K_Tq'%{0 !B!D^J&ujv 'k+I3~B!iy*_}Ox??h;K)g!B!TF݄_ThӮnE(H4Z[!B!D֮YLk**S"N@B!xYtީ!B!B$UB!B!2A*B!B! I!B!BLB!B!D&HRE!B!"$"B!B /|RE{ B!B!Hy7y;wnB!BR*T0nsOTVy7A!B!x߿y7{!B!B$"B!B /AREB!B!S#$UB!B!^Xb#92^͹Xl%鐧# PEYdmRC%<6BՌ7786+*zt~+_&5zB!B! ϻ/ww>nsrw?flaHOJek@,UFsr^Gz ܘݦga8|^.R!B!ċO^~_f%&Tj}SP"ػW8z~A?Bw(]:\rd7P9:PEI|g&]8/g4}=SOqz/ 8=B!BrkHEɟ%+_⃒rq+8b`!sԓ+ar۶6VՠYlh{cN뵉,zEqcq`9e+PB9HrY?8m+&Uj{0bABiPFFV3wC* K٦}38u'zLf'̮Y)J#'sڱJhgWɀSx'TNP egs!XnenΗP~ʭ2(jzB!B_'#UKN`n$׋}hT$Ŋ Hx P)8wӏڋ|s207CZer`9DUgr-u85MƒB95NmonZg|Ҝ]jbmlRE};eڱzW\:T9@(\˫]#Kbzzfi΀npVB!B:y2L/c Hnv2ԯR@O70]ĝx\eiN­qMb/ ?pգ&_nMb=vдu~]ZW%$7N;E#b{W[Fu*L(q^Ҭ3=G]g]})euBF-ghEUڱr`_͗q9~ GmNOqʞ=*D>ͯKdB!B!SdJZo"UbW_2a^r=75)ژ#Y$xz杸ĭ $p%d990f#SpA /M1gzc%m4)`.P&,ONCKְK5:tAIW5@Q y: SHqJWN<9IȖ w/pD΋d++4",W!B!$U2Bq"[ԑgsA6Nkc\K")_fe|B!B!SdCziBCcDŏw ˽S"֋7ל%ªŝy^ӌm_}ۿcv7e_q.OO)qz4-T AJ1ԃD>o{~b481^!')fo|<~>}.K2-3 !B!x2>&I}48?K\8sVp˒0qG1 .݌ƞX#.(Aɒ0BlX]:.?_DprOF-{T:oFcn0%6% $x$6uXKi-l3u [bk;H|9g]cm'[^Ö j4UtLhAdۡaoOgy/~w+W!B!$U2zm3ҡ^%JOx넧|~0%_JEm_Bq W=ڻfp۷4; IX5);*TOyqա(^vBwfa_ 93[Ѕ\PRi%9''ӲXV\=/T#PYg5;W^m޳9M`NW4lӸj>t(ySȜiZ n+πbԞ}X- !B!OJz|/!o5E *cfu5:>.ke.^+|!l1̉]gh`ĩE6 0;^-Ǎ爥u{c3h͐jR*3[Iv:ŗ+z=Srg4:j4œzl?4YO> ՞|kN˾ ?앳y狸\țy(CCk PGQ qB!BEqW_w) E޽X,XmvjWon_ .l`0-P?z-ӤPo|߽?.Nt.yx}dʅ9hP7aC:b<&Jŋ$E)[AdzFخa(;?^dےX .Oe [/0 H `F ҇=_d{M)0"ëJW&xX$SI:2ʧև=Ro:bT:BtLrdJ+ k5zx PŽnB?/k{Y4Z} ťoR4.:;EO*vp`TA,?Sέ r~R7Tf%|$%z~ΪSsBp<8(}7bj]OGlìz?o|ѭ?F/Utph<@ryHE+Y3Z-æXs-i9iL[]oh?)? 6 ,CqRd<u<M6#h%G@U"lϳQ}U˙3,zja"p_.Nס)fAfzn}M3h[\-|/4l^ j mf{T)Wc,{Pgwe䉴ͭX5]e㝅TݏRW1tb)cPagIu\j: [4?ю B!BJ<%fFP8&+fgQACnw`ڱ[qXԇUtnQWNpCVwI;1ŏaf-AMhrFy19/en,x_*[VNeI+kPpجeM=rLFB,+3i&K(ai|118w.q+O|K1u6[Œs>9TdTywTsʠ/ORIwiw,vbb4}lb\]_Rv>Y,@B h'@rz4 [<_qZ+0 &fɳ܋f}@-V~Ԍ@yZ^_?kt-AKt~;C5J>xeМe[F.#P!bgzʪ̯?<2.?j' ZuNbu:KgJb1>~ݐrрYH:4"B!IiTi6 '7 IEUӰX,VΝ;FGaWtZ%=*Ġ/7x|?L8'Z3\@8)-L! IDATH>F1/ 7Ó1fWH~p}zYe׸G:/OdR4$@pF.$m^-I_L<%5 ԕBIsj ͆fMOxO!TNxw}ɇ`$/{GȠbEwRPTwVhn$tn.F˳Ӳo򺺐5EސrYFm )$_I~"$I(ӡىNWY)c wwVG&ɩk#L`mUu`oY-^!By /|ReשFapP:4ofxUá0LNL-JW9{ƠCWթ $$p OIׄGJMUqknVn܈AZ-nPw|5͛#dM#G9aS#OȻܳQ:ԩ˶`پa9ڠY F@ V SKp맴rka!>vz I׻%#z~o%+1Wfrj1ۭCs2ǿ}c=Ts,xg Nd/%>/ۊOTfxrDލ cTp't9&|NMqWq@q[,{^C5d#~R/ION(H]:ҡ(%7HL)~mֆ,}kop:O(szB!BI*OA@_~uh*-HX8Tv,y||1?>DN 9]FB(w*7Mz6`ࡥ| z;6drl.f#P:-~\XB%5ZR2Q>(词9ycbhPS:+h C|!/&C$EKxιTast0?Hk_l_kmO )LWm:P>3 jѵ lX:oj8(F=lݚ3Y?x4GUDvO_X~IKlõ>=!0~Ǫph!R2kzDz~r{>O|RtˇpLLfʖS.nCmv/5FnjޕLH 5Rc.JSų B!B4))p`×D_J\;@\I+fg3&'69G/M$㚓ĺNﺘ}}w¸lوf}y }Lj+[kRÔF_?I%iK+ԺGUNLlÛ_EV lsL_`Xb8ƊsD:ucnoV7+1;te*ylʉo͚H[o?(iR3S|V ʼn/a?-ޓR1[70E0_b*BX;|/FKu1?A2QV^rf嘁6qנ֯ (},zo>MA VR+R!B!-=ik]p1(,uqFŤ7띭7VAqWGѠ:htF :Ng:덚άxM,zEˢu_s&GwسwmڵCU>TV-SaHO 7Ax&uX>m\]ّ\i \@Š)y;o;̖YU!B!ċh*?t:=k׬f.[=28ԻM sX0բEQm@'jՠ6զf;ٴ(͡793UpiճN}ۥ(^E){2]KvEk>X۸<)\Vdo|,<]~ !rl4EwKaO俾sj9):'["BlHREfŚV ONt!o-ףs/MIm&كc?l?ySQN^F I%bپ! U!BgI*/N^G-x$wũei[%' 8u@rm+;WҴPǓ8졿VtUPaNBByqY6?~+Rv_ݰcPKAH[jGxh1gY7%\PL^iWbz|3[:%2{Hmv⸲szGQtvތGҾ`/EpnڋocӴwUo.sOh]TAق ;b{gѫfN\]]/ވaoHyޯS/é .BU@pqqJm{tt|?wnAF{N1IX^`vLX=@W\Six) CwKru3.UCGhJs!Z :N Y}6$~ŀeW/{.3iC\Q_iȢ6@#bO*-2?X /?x;W'[>Z=F3s;SREuM{E(9cc:S3Jc,ɾ7 );d?gX8|;Kk&ܟ{zQVLIq7҈s:S9+&7w2g ݘ*r~UY S~Np7uIF\szԞp K"@%0B˟y#t&?#dm$Sߤn5/Vk@Nŗҭưlx:B!$U^*53;RZp40iä.pıC_5ߢ4"92eڭZt WE8?~mWYݧrȎ0NʇR*ϜfҡG|Gv~I@輨:p خ._6S ?`O;BTb&:)>p._58rd;k<ځS|mȣ/~-aU\Iia?5]bw: KUp *=ҳyOf` 6ar9C~3DDsBxY87;Nʬ?l8O7sN+ޜAS-eLC{fZ[NfaVeadRouȘm:UsWqw n_rXk7BLIּc>&~x%dHSGí2k $>?LMlTرrsvbڮcSW%2BlϚQ ;ߠRG![SybMA'`Vn eI ylnƖzx ׼̈́$n,]KLi|vfB4pz,TžkVN}e>NYҳ|y˛sq`w>J1t]g\OcVB]^b,[Ns/@F_ZR.+k2zO^ d>gL)ô7)[L1 %4!h{ !BHRw95=) :'J3dx=;kT$:jy;aY˗fA3z#_v\BaEW2[rDH_y*R?gQZk_tFQ7.qV6 \M܏%eEqbr k]]Wc7'(1K)66Ps?:Uäs%-hEǖ6,ր^88)\t*l3<.7= x/~?lBttK(2u4u&EB.((6g-|{2ꉵy2tL5FCVϙ?Bl9fIgxK4<ɺc\ƚobf!;G)љIg18]e1*:\Nxh2#z~9G5ÐMu tf,R-Ӊ:`.[GNJ' n^W,j SgN9V0>fїmRNnħ4޷2fͱTr$x;Ǩ[NKm9b;P7zѢhbUҎC^-&ňon_f3ߞ"VVucHˢxuhʠ>vVlU՛)7 |(NяƁ e+ҹ!VCE#s@܏gOSK=JZ3|OtIq[_}N Ftԕ@I!_L*/ܼ'UP1~0A RnkRtY*VkʐjxPqbD/Oygr{/~p}"5A9V!g?Ɗ1iP4W7s"&[Sd;^̬΅1i N2)_K[gX4[uRQO^ꇇ:>Nפ(\L6"]8 éO&lS74K(׎n P. ߘ1X \W6ҽ$;f]猏'gN2Io2`py:gz1۔!҂-!QɟS:n1T65śU|MR4e+VmMXu(\>~Ke*"grIvUZvSer6wlniHN~.> Nv ?uSlE*͒sXX/#~Bس78.nv eGeNCe=Z؋^,W:{s#{v!!Xcn=%ʓ{";b Bϼ_'e:ϕk̺ Qz(ϽiK45$3I}Rp9yͭ5 T#B/,)CѻLCSh`.:K۴Jrt:H^H$er%¬FoHD.g+ƛ2S*~+̯ãhsl8a(-ɝaPq&B F\9QvwL㰏w|ׂEp;WpT8qN֦.I2!krL!lPGG]b<9s_IKE3'kuN6̺xLˠ.ǐ$5=uW4Jw&Wv^;~=ϩReNG霃vߝy\o1}ޖ*aGq0nWRoՏweonU F@sIWŖA~bЇƽy=bs&Q ;Y`r $ܳۉr :| aF=(n%$v_'[ȥY:L&pwt [Ld'i2|OR0Gm%Xxɢ*B!*/UUq*[ ~; Q""Iά.Qk#7K<)Z M1卻)W#Yʧ~#8^CEq'L<k܈?8A\92*h[Z)ySck:x+ (xqN\)_K*e>扶)ڎ3frMߏoK9zxnݓIs!w0}FgCT,W9~:qooa ==i(.Z,UrxS5mqI5ߤֱ?pX4[ wƩpz6|?g?_≌!g7fC;ooI%J: (DHbE^*b^DP{'$޲ EJAsnݝݝ9n^W>"ž_QNa|m9)W#[HKLKL;Pb s9{@^q>C3GLqx+DH LiRqild[+ЮfƎ}CrTϫP:LcܭM2L?m_MF:/nj0D:ѿGhscCMop"{0^섷ni?r$3_Ofӿ-W^s+2g0|_;V&3+⯌α5[=<$3K fQ~4}>wf͜9=4""""YB,0nbFŁ[t*O^M߇S޼"Mr"rxV bd#W~´?&{Sǂ%gd{1H{fʀԒ&ɜ0nvɕjS W>SUSOȏ(3"cims` , Et* pǬ+`ŰgNK ^;eT|Xn=/bEY?3K^~!!1͞ Ysy5 x6fN5}H kyW&R>D0:V<ڡ+9t{&:7U`Ի~+;P~m nX6 ^"%]!(eCʴ7ط5͊Q[XGBM ǰ;͵Qi2ot hS*~6ߏ۶GϥRm'i$Z0rYC.) )/G<ǔEmV,{Y AF0 nކJ]]4o5{:A77]A -ޠٗhP[|n*봥BJXo{~hU*@Ch޲N$3TԗgY曬:PEDDDx6k4/׺ 3e0J8גnxY}6aY]V`Xm$ʹ-viZJY|,'n_f`1rX,˴ZrX.q2>~xj;}ODDGA$3'u|dX"ӐfU`I;sgm """" 6P"tX,?ڵjflJ|y}eQdw;ьvu96, nwӝdvnp9Vok^.rdW7a s> si;qC ^6lwoO*yi1 /-Cʂ#К 9gvIaPzsy{>wer[EDDDDDN7Yrq"ǒ/$7xz17+, 'ɔbs:[0 >7f {yh# BͨӚMvJ 4R% y#\Y?N`ɇpĞ…xbcIv8_5_99E>M a]l> KKb9Ǿ=3Ӊ~ 'CׅڊA+9dI]i$?N϶z 3o Oϙɐsciq\S*O=:1ě]DDDDDD$iJ&a^V6/  NLӍtFtl"OC3Pv:On8K^z6eԴK8oƽ^ 8Er#,W3zWaU[OШ?ؗ{ĖT96߳#7I'A;Lx:}FwZ?މ ۥ]@{/VPzF>j5}&9&2jjʮQz4~M҇>!%)<~x|zmޜ3 ٯvu©3W w/St}kԇ1=Voe%Wt.cP%c㏏n`Zt$9)Wr9&QI?ge~vuĸXL׍\'kݘo6ū STL\4}I1c(F.;`", 'c/r|nPJujO]ŹM> | D:`}-s(\l8nuA l)ǏZ/-TFpT4y 2\ŏ`CڇUb9Zډ9=88wyL ˉ 9r8nܷRД@0G XF 2Z*jq@LIBۂôI&1eZ{fkO0kLl_hNoՂo3y[4n p/ߜ[C)p`着#}B@h E}{ȱ]r)2ec|b.덚i0 ,wJ74ͫK.j_ȩܹOƷ&tS-mz.>x9Gӏ׼ )OXm;v|m< yc䡫Y3v鵋^ȯM;g2v""""""L6hhn~]L7"X|<=tɸ.\rn}=s<XMC@>recXɗ4w ~uŰ)uy}£^]m-l!uRѻ|V˛ ٳoOdBiѾ)'#䇅2`EDDDDD$iJ&q'\ܷ FN/o/$e7tlTcnC`Z҇mCN 8=>ariQ$sGǂ[lx9cDZo5"C.S?~?caY)AqhQxk>m2;/e1X'wx)~x .kUa?nן^R&ϯm eO[32ԕ;ČhHiה[JCէ;Fhƙz""""""y7Ӽ_6XΔ(H^KBve&,fu%[mFa6j-vi+fX|}v3Kaf.j=lB3'Or]"M]VmvϞ4'|#9-ks!/[u;x~x[9uC5w;hÆ ',+ ϧvn{j%8$}w-0\s.ӈr%܉fwa\aIwD% p;z;Xer9Mӕt']1O{ ] se ø,56ʖ3=C]4?wB|HQ 4nTE <ҝ *PQr@f UMebkҔJN; 2gls=ʌfaw 24 Z\^Yz&OʺI̺ޔM+Qg4s+ ublגU$sp1.f#!8g2XDDDDDJ U,+Rd*xcd]s[ {|쌷'gx="zj&nwfp{FWdOB4x6h0 kP+rѝҎC[1g_ ~ O9V6گ{pUT ]@89xay -S$םK-wR~޿6S:!Sp5w@jw&z!7 S_R؁:ժ~{iߦ88n=jߟebWo0E?Io-G0o _)'s&ӷa ßV#X̛Yf{*{zN;R?tP+A:ޏGw_W=hNtOv޼h d.Uw>_…X TfcY|^)6~̳7=e>rj'k8vq마i&It*̗7y' Mc^b_k]7M@j/8O?174_9~:&.j7ߏlBeMƍۍl+q%o`X{q9g\@^xsO-#>wfe\=௙ {d4 cM\?c^Lu5ۗ |fEfO*IϋWtSpF}KvjW(OmW[su ᓺϮIkJ ɥjol!M9ezb/0'ai=B;/?"6"%#͌ѝ%6'bDM_R%ﰄRoJ+z:x">Ш|qօcXHGp&r:ͽv'sdT>nN#}~2cV~Bik,"""""w7wAf غb?qHvl#DNV5>}HS3U$nP]T/I>S EqX=҃7 ldNOѻQ|-J4O2bT4/bdJuVQA,dRƄذLZl=teTǛay)BjX<{Y{2Q*ΦV(Ol^>/BkE&so \ _, A-gy=וn'g6eK![* H ;w~jw}C3ڮ4NMU/@Ʈudi6rWCk8*Q)Zs-#r[Erk K{ꝜanL%z6X5CpbFv4gte_ 7|<f8oeΈXa d{m>eO{[<'V#j6K+#>n^\&df_)E暑 K.i8r'tb^ \: cpw2AWΗ5 9s.WyN%p\E 9w8G93r 笻''9.XL&cػiGbsob\{+"!&'X=s;q$dNӂO@Nr{a5 0| ~Rn섷m[f˂W'vsqW|ɍa#00l6KOhJC'xN%8o's`#8yy;t'r|DFlARyyƍnݹӶ޺!ۧȑ$x~=3p*;$XDDDDD. U:KJ7C(3u |Uõ#fFڧ$ުɲMhչ>A&.bd{1H{f9EtFX*s_ӝ II-iҮ+Oso&\&\ɨ6e[ roM>eP [0tXX<%xj›T\ei51}`6+f~T3ҠV$;QҐ[Z/|:2jn8>j՗z4,CiItFdߌ*??g.N%v]BNbb`ߜ3ح<ɠ9CF6*ňlSid^kM㶅c!\й ]8)2zEDDDD~Ӽ_6XΔ(H^KBve&,fu%[mFa6j-vi+fX|}v3Kaf.j=L|3Nry7vzZi۝>{'""£ 8X5c#W"wSoiW6 @뒈q6lD=ngXY8>kpV?cH4/eߤ=o IDATάY^ѱ_v67{{csO-H~f8o¥L>/GЩvs4M;3<:V /g̚5y+xUKsTy2X`mܥlwwiV|GlxZ>WOՙov@jFg_gNיxiym8r(u;5_s|''b^L~Jb"j{<{  fkZKz57Y '`FR FJߧRe-wUZDzqh0˚2mmGx*TܙR&=ɧ0ZWO%h֕&LdR:mQ?p^chE ÿ, ;ΒJDA U2R^u|r_5BO~ +n{g`o|Ǯ ,<1c05cHk6B | h>?l1[xIe6C*e1>nub3سc۶]nma3v;ZIY#D2Q]j1dy^RE]5b"_)0f jtⵙk8WcA4+Ӗ YA^6fdžG8fHt-'gW W+{ݛ"Ř>47φSY>\h]8Vrޞ:EDDDDD U2{é+{͚C(݉iߴ[ 1dq ?Zˡs9sx sHUV24 9D֝HY'5Fgj)??41)<ˊo~l?ŸlQ1>6ޝ;Z,Hb'uR x4ܿ${ jWbŊ_[kj}=`Gv¯)}Ȕ?oV7 ,y'-TDH67}ٿF1:Ɨ^4S5zK$_U:zMw+'޻MۏoasSIJODLL3*^03Pcnaw&n ,#9>C|B*aWn[&’u$.E'}׻֢/^Q>#>u58~*/f;9t:M4A]d}߿_>xk˭@qa`xn"W6L8Bh<Qtf T$jݱۙTs>9 yF=B$_UO'~Nys oFH %_e1a|d1e@c֜]7"L3lAά]̤8q>SJt8 2 Ë8b0/% ϧ,aLd,OMy5&:ٍE/=<3/Fc1τ[,͂_ސoN)"""""PQh1]cӢ,߾{~wlzGE?!5{vlןW<\yPt2  </<ŗPq3;`k7~(O\)#` ~~)$L%:uJeoz{Lt "V~4n>$sFk"]8w;?K;Šp-'g~zxhZ`c.eO\ʉ5"ٻfo|7p_Xˀ:56`&OYA5HܻΑ2Sn`kϡ ILI6|Ǻ}-OD'ycsbRrCkTq5%eNGJm>^JY\4rs "$d~kXVOMH~O❟S^n{29F-S_ڡ-=uc*S|cX >?_nvh*ȋU,%sZf}ǹ((zl@aS OYpzTy<ŏޮ?R^gF$=%Pl,>)QItN<\<L6-VZQ:^B;(*UI;-,=sUtD@풹,[!MHyxGø֑ިI/rS#|w֕:EDDDDD*žFĞ&2S}J\Yٱ/U\Yԏ5}',ݱ)˒+`G1+|tiVrA)oWoà?; T-?MZK {(-?YOV62S{_[Q7j%"}⛱xR8=٫Ѹ>\6MlEo=5e3SDp8l뗽HWMfcٲa&#OQٳ+rZȩ|l87IjŌޓWH Wܮ0)[y^˷B|#\4i֓F6+̱]{t}H-6ݐ%'/|%Чٽ\0zymSDDDDD$yym)Q2?ƑĽvcMY Jڌjs%mn[NbWg8qZf6 ee5\Ւ{tgOcS]VmvϞ4IyԞt_+.""""""6l@{bp|jתᲭV+C>2(W;ʝhFqǺEx;N[p;iNÌ5]V/t9] ^Nw+0 w ޅ`U=1[*O6]68g-g iaæ@(KO?a hۣ ;njN<j63Zea"=dNknNn2I7/5%|Gi.\'66dUCu1ZLqۓ>}:B0@L6?kwꆉXOEZ޺sp+tQ=#OVyu4OR/i,=0 šļ1\=XtkL Ws$Ks/i{gk ?O@0Oþs6njgiRg`xCgK `m"tsqFvrK6eD:L.1tx550N|wTf(o)ưg>N9 jN&@]ټ07F|({JFA|q04/d T$? :Šaap1މiq\8BrوM׿cոr?yW`"AuS"~5n;O'm .[rnT(3{i΀v^~V\gHu-DbN2iW2tz~]cW t&qT>F֧uNCY=gR*Kj{y-OQ Tk@;Vj7YЀϪQso} b-XFFuar/ۉrs"^#sub};iRqܾ \,e$o\S rJd('vr"eIlJ?idڢLjp=էg^&#^4 ח6|t1]Y3;S~z’]]d':, |2㠀>;JTTG\gn/׏C@D [R'Ո{jp!7o%!B!Uy ft8.QEӫx+ 15l#5Z|/@޷*.>Y(5l=SdMv}2^2ɤdxfZy^쨙 S! P4{6 FSL?GDNk\\ڋJ罯3ꓜ8*.9{[2w_(Iq )ez-%-B/A2b*[~HCEMX6OdȒPgƬpr_ gc{|M&Mru9M #Xnͣi͑zG z܀AU@ӰK4E!B!3Ty nK4vsFgdfaÉ+Nıt{M9R(т>9g0,jL{\ܷ?1'iL&])1r&,v%q‘ n.t~*%*M#wFT̕s8ԩ'#YB3h.PR#,z sSEjW޹S18_k,X>/yE;c5^x8: gcT؄OwԌnjAUiޑ]/Q9r!\$͞ɯ?PB!B^W@U`D[O\M\qNFρ,:*yTW2^8;ӞR%3&Bb=}x>SӭesZ[ǭdN9_+f{q9u*qF&5ɝPapiӵkW5ﴚW4oɰ&9/3ӊ/2Ztcs F*{ILmMa0wgfC. #̄ k~i! Ư:Y90}w+*gdՐ':[2;!B!x}6 մ7A /fPtFY*:fWEΠTUS `u׫FgU5Z; ZU5*:5N2i:k\Ʒob~];iԤ T8sTyM`do:ґR7!B!lT+B! IDATBTA#zOwtv-bČ5|,חҴNl>ޜ}մ ̱dOj81OoxkSsy^tu׻Gϟ۱B!˒Jzs}L5*Jѫ9`xTEQWiɀ)8׏bBS^| KKU~M3ME/u,aO}{((kDȇB!҅tuTI׬oH6;w7LfbOvh*͙ULGᯎmbd(tn֟o|6H0E)=j?f312Nnm5Iͷ71͛͘p{jEfL՛Ʃ8 kۘѫ Fܲ|h;JI׈ݖl+PrPr1Ψ{U]>_lD ho:Nԓ9X:[F$\ywk;q.Y /~yoTl.g7ְ܏ 'ct=;kq[oBTL!"YTIǴؓ迊GӦtv 8g.H ~rYEE]/˧20až~m>Ǥ` }եjq:X\ 3QbUfa M-AeM)Ѹt̖<5z1]l2LW3E>..xmDrހOj};QwJ(Vƴ}j{?Yx\R/2WwFrT²P5R]o2+XxOrDkYDm䵭(W)FR( e2]^w Y>8#g꽫(;wtR[R̯{7i_2~SI>i2u6-IQhLVfOI>ʿɟٖ͆^!m&Atrc'nTAqnbEOy]1rپ|Θ >sViE WጞCgs } ;c۾Z pՈםfc/f(-;PɀE@5+1ܽA8%S 9[2M.n:CҺv/M#C?ie٭?ko>=yG%y|7.Gs3Ξ34 f̌6t=^Xŭ:)ljR]ݓ{#&{;O͍19ݲs4HKf7oddeOWҫJ p-,}v0巎v=wNߺo*]9}X.Ϧ=,g±똾Ka3/ruU[GS5[64w6adせLc5np^}WvY>Š6c-!sěG?},ʜ{fF7ȃE{X5|,_)Xv1>:[r 5,VJ~G-2NNʉb߲N<7Fz2\'´P?]gf1=?:MoM?ETL4͢sq 9Ÿ*1;d=l8ֈ]L챀(z1=^UwVu%x%==鵿r^, E':ڧksv*!3;w%gWl6a3bH9 @-, r~U<ad&vϟ}3)nT3 v0ˍ̻\3`{^_J:bwo !BU1{lax<5]%;M;3{Oڶ $A Z0oW93~X7<|J]/@nGTՈotȵaڻC-iJ:7qwLh7Ɋs2R'%K5^fJ`K!>sfۻf!p dQ^z8βEq.+~~^,ntgOGaJQx0fy(gY2Sk:wӣ})߶ ymTOS4)u}OjzcQɘ#^ɮk!jT#~?wΥC ,1GpRU\գ{-PuS\zEwz]?KC)ZwCԫ`@_;s' :-hW%; ZL2;7 ZžVpNٲ4(/7B }v_~oG_ϾϐrY>/W]gFՌw\T[}wKRǓe M|mTϐty?N2UnD;m'aHybPT\rD3i̋ᨄsnѻd!Ov״ /SW.tZ̰YIn ;fte ='9+Q\, DypVul@ɱE)/rYQ mZȁ;W\b})d(Ԙz f,nX@' )b{n_b9>_߲苲doFhV5y0]^`wCb(z`؟P\u8O^_VeN,bn;'ZNlvmj-=qx$A]fo oaB&L` ;<*Xc'Ã0Ȝ9tFf+F {Fà'Ӈ:to+Y="5w?ɻ*qL=:[5БLx>{²%7I,_0_>ǝ9S %r}9nߊ`0c&/' 6 W1itVJӁCM7Kt%&ǻض/_FFbj a~┋*T~wҰx8^nY<,^l1-A#NhgXoʃ;:g![7c^q> RS3Ls~>it~Ѹhs^*U%m?mM*>9B!(-/ߕJ:fR|{IfĦg3o;ʖl. $3:2,G L:ξYNQ[F2et{8~DW_?udxq#Z6'(-OUXNNXnj_.쯿)k~{i[FϘ ".Y3#x>Wnx{;g#ͫDWh]9eTZ GGcL*A!f_JK_4.Ê:@ͅLTtѸk:oGXOr|!Y]݊ꈃLvZ<#,g\7;?U脳j?[vc-7Ԭ?Fcv)[dsjTUz=^ mq*n֥Ou=W~AK) 93}“iNФ;>8R+JGP{us┊}OϽ$M}&Vo@猷Q؊;7)ei)Tݻ@J}θw4m-DzDה鹍}'G+<1ݿSnm]׼ B!_ɰR3 fJJܭcDvU2'=Dc۱GsT=K*"gQ,fκ\bm,2~'.q7qvf$-;3;NԿރ?#9W"-h<2G} Г9-ό׈f郜_wZ1EdoKW.vEYEC}?ܘmLY4;9z*q<`?{8q#btHFtna\8`]6fX&mqи ٫q7\&n'*&v9-qfsfàub 6\nѬ.ބ^z1Q8dAW= 1sNT9>!GMwY={(;= ?|+nZ;ǗۚdΒ?oļܭzB, zz,A\ $IvUF dXf mS]e܍ ^Mqj̈{B#Xpi)x}'F`'_"T)¾.{pFCIX*c GRqHZ;=4m핃x?}Y55Nۍ"HnԔ8fS4`nj!!Uΰx`'ih:mx%BU5=>GҜ6n |ITlt: FW*t?yOϗܹiAE27m_a-w& ^s49MЪCە2&~$lDBT%-VQd7Tz}Q#'njcrc<ʡ2_ʩ $`OroSFm:s1r֪ļTʦCQSkZؐ),P܊ӹC Pr5cՄ-^CX 8~ 7cU] s+P";arLi3/1ߢ=]FHI_WųPrՕf,#u)ei,ה9z }jKOjݻ4-iO* &:To؂cOQQ6Gcם!BVڦhZqDrtVs3(:ɬW^g3􊫢 zMgP :U؝t-wIh45@t[7Rh4j=cΜ=OٲeT =ۿN 89xH%-*0Z~M1:~-ʷiDY;Y !o]vߧ:X\ϭMӮKMS;vvߎ=fQqvj7ެWn*6UhѢ4flV[nlN-~:I%!ll!B<B!B!H !B!BUB!B! UdZ!B!BG>"B!BIPE!B!" $"B!BTB!B!H !B!BUB!B!@*B!B!i A!B!B4B!B!D!B!B<%UB!B!! !B!BUB!B!@*B!B!i A!B!B4B!B!DHPE!B!Jhh(6Mg#ETB!B!Drp>t6R$A!B!B+~T<}HUB!Bܻ{ؘ7IPE!B!,B!B!HY#!B!BUdɗ;o}&Mt՞ʂ ҁ 3G\ _\zE%B!".UB!+9v>"N2?6sbHJHP]zNXզ@I~+/7Y{*b2eYvtB!B۲G3yQdUj.jCQS޷b _u\;fHp wY|@y&ÿs|'^arv\4lN:`˫K,m[º۽d#W:1ٜbjz= !B!) 8Mgd4==. Ϣ_KM݋%*ʄbr@ ȿ r̞=i# k6ٳ'>) `֟h]DAՈ;ncN̙UhUEA)ތ''[:/lc3Xq?3dH"ꄢ(4= +@&UPPQnDQEAq)K\׀xN @Q<`.{6AW ,kD6C~=x4W6MceEjW&mN(}xb9U>YD{EAi[ɭd{ȟ@1v)ԜoT5chG[37ŗj=f56%}fxn?/$[B!B!HPٸ}֧w&9F%:JlX3&dғDWeک8 YKS8]mldXL7\n͝joOm,w-"^rJ*涥L8UIADN TZ{$gCs,e@\aB!,yEBh].NhmV ي9ތ.n/E@))c W0rˏ̘<Jhքd(QפCw8{yБ!kǢd,N0mr|W ?m6PgwOKA./Z_~B^Xy,F~ۍTڴ,N8N/}}tWp1)+.En*Ԅp5"#{jYs? OX+@: p.YoC2)72+JY&T\cW t&qT>F֧uj$ leN5l?E$j)B!$h^K&/=88QUkLtt4pb0+h6s~3NxyX0lD`wbxyWmפ;g 6v+6bwZ팢fx`{Pn=r`u+e|4o;%>ØKqz(P|YQQqKAXty)\}Xv]]ڀ=/yg4|dRb߁]gR|\ VZKQ& -+̤Vb/r skLY$B!i[0+SDDơwP*^E[X .ގɬaT 71J{ɔ t UqIeRjzɚx5,d=zs4ds_TI.G,KղYp@%cƴg:?u{`=;+\8d /n7E!G TnX4=1s(or3_^Z)oh&xB@ ?=Gz{!з}e![CQےR%4:nmWQ˥mݩgKS!B![M*]~^ܲ4;%9 ΃d2c۰ĕKidxxhA3d{5=.[񀟘e?UenNE>O7r]6:~0c~mhR8Vpuz˘9<B#yǞ9_6.ݒB!B6+*{^TS!}K%2 P10ˌl[(7?M`HļNwf1y8NT~d}h3riDO;Ө's~#7oPv{,B!B!mdiI5n^%/Y5͠8:'^Utzͬ+No75A5WΪjbw *jTuj&etQocR;vҨITsyʖ-bHgя1l:m =Lݟ򾖴B!BҮ]NSUKCB,_.Vu:${R»ȏF2fbʐd,!B!,yM4Yj/!B!k#{B!B!k"B!B!@*/81F鴕/SjϡqokG|4ǿ%fԭWwN9&UˬJ[~{3]t+ҙ푯rڹw` mJzᒽ3/T^e;y}/??B!^% g4PP'^jbTעtRPEBZ>"p_z$*|5Oƒd43a{udWşGQ/g3CrBO3'7V gy\Ăf\WXD1O+&Ϗ` [Aip/EI/Q%s:^mXՈхBa݀o?q:Y8j.^$mx\;I燉i*!BW| '7rnZcHۏa0)e*xMo@vۯ w g#Kb@2֐ȋaAy&%1GM3xP;tYx6tq?td,Ru(%_'[7.>?64UF!-S*oހȟ^-jPjV"fFք)ﶘ]iӢUk~Cvm Ȩ)䡠xbZ.*SMTS3Wk*Ocn}sL^e@ V,Mk(437eq\+yr5.W<ĉn]?.C@@5oHhZ(.IPţ2~8E]1/xPx6_OubO0T3GO)DɨZ,N$"ӹH7vE%g#g꽛0 V9k-}BǙ٪2(G(95aʼnyh\:;F/fXGm=ţѢauJWȯ%]!G!EAS~ !|"3j`y3/>J ~l4oN;='"zugѡa/@@., M~{uM %1__B?q{ejTk?K+XnKwQP"4n5cQ3X.Cp/Bݘ}ƔXm;A(٩Hz^~6/Bfu`~^Y[÷\߇ 0ROliYm"ϦpT ͦr6>n緞UU zπf%P|+wcޞG`ɮPPNXRr3{=֋.(.^WfZc])縷tKFoJ#"uF=a(V˔ܴin^Feko'Ͽ}~$[n&#}UPkbш QJfwyl+J(xTKB!^  @|&Qg{|6~&YOF1k :}˶;|U=(sn۱\M{kY3K¨0tl`щuZN.vz}>G ˆ<v2qdNbP_GLZ72' `=>b!Gs n4"!4 ?ʀ*CΖk [qzӨdƧ$3Os:t);3rzCF6[;x1hF=\G.[ǦYo.K(>o߰lüo(9C:0bw2A ; f~clj{1qeavMq?Tb+vg4K'ODor'#=71/|}7Y9:ek4#}ęmz?`[OWu,S#i<&fb^ɔ$=v Ri1 48܋a+6هwJ6GOJzȹ&s%:31d?1tdh+Nڰ1z-{@6ç|Fضo?v œwc5W-)_ Frfߟ˰[|FkMA#C0!@LJz=;Gng!˥ h1t\c'bPZ-|\%c4-#>e,errݒ.!W8eX!~:I;y}M x´?ɌM޿?9Z=h Wtnڑ:QP0I{kYr<'hzEwz]?D'ГP]ň_J<ŝ3iii2}fW}SGnaJӋO SY#^h gPq< *N9*ҤiA؜ tFչδ]wq6?e13;e IdVDXJE "e_ DȾƬznnj1,wzyz5gXy, gX#cpFwA]UsDhG9q,8P"ri"}' 9.CY7j$NĥY_~ɿV;&[H;CF%rh*ʽ1yWTLER! cPCgyu̱?D6quk67Q1&B3SU,'^?TM~ : %!!BoǍeBe[u)@pax{"6v9GK>,-/vUߠ|t7{:܃{F=)9\I΍A=p-g_vCp=ZW k} (Yi/:7l\H^c'&V9}ϴXڡg8QJ^Sㇳ8{TNl tefMsՊ90ǟ f('պwt"v́9'bąh#+bOw=-DyQT%Gs9_ų;FO=vhdBr-K۶p [!V~=J}^+fgtOg+rœFL$tsܗAJͧy/֎fWp/<+}No4ڍ! !&GM_փ[.Nٺ Pxue }wx.Fi:?{o~Po4/A=#q:߅/>hN!oѣ`ɓ|;!.婉4/U++љG%7ت4,)u 8}NFW2 S |}xSNBOpZB_CqkDUqO4]{ kiպNgw|>?\6E僪xP&~62ti2hL7:kmw|wƔ[@=B@g/]f/wNA-ӄ>X[!FOj\ȐKnįp3rRk0iUԠӏOW̶<.=l) IDAT̬چӫ3K Rgj [xa;/bV\7N{ m3F*x}?.9wAiPP h6 ɐBdWCKV\B,\4ٹ#Bmiu GR1eP:բW^g􊧢 zMgP MUM6:桢z&[gTtԀ+$vp˯;1O",,PpҸ} e7*ӟ -L_$3cj,jUۈ諾[w8û?rK BQ0vB~NUu]9}nU?#{Q-8Yh*IzbsAo+զsj]g4͞j9,v5;]B CK9QMQi8b!ޮ( ۛh(]]ڗQi88vLG㊸+ RV#76}]#;z( J#p4wfTǻ3gdeX~z+g}|P燒_ϋfX8;U[w)ѕMO;ٖhfoEQCiZn6-`A Qu:Ηβ/!B!TC~ܾ#cGNoDQu($4vJkfz<8O,?> 3hF1E6ޓi{;1iDSqs\{Hyq|E=FMJ)*sՠی~w9{ѐ8e'4NSW //]I[1 u!I2!\^܏?usxrv^YmXQ8/ ~gh=/S?31whF}h^P\Fg~yd||k;T^62YRtceD<2*W6rIc:6͞^2A;-/~L8>)2T 0N_JCks IvShB!BdPQ4+M\Nh86ņ%͂ݒ.[I ۫v߱nEЬE(Z*@_\}g<>NգˀTw[*-S?+1bR~S+v_3>V |0*)I?EKP&:/٨E!B!dϝYp1ki$&INql'!F|4.F&rt{0''-N| ;94 -csb,33ݴB0.)0S<@$x.K=P=Ԧn)w҇>~ut#&zLfK*JV~?'Vk*}qRbIH9|Q2=xE"SdZTb.EU솊{rT\v*=LQ>b 廿ˏ{hbxܿY]!B!DaȠS&lUIsX540AjEîF`*݁鿛8ξR)j%㖟ĜU !B!x;AvkK"&7XlcǕgQӆR&oL=|,ENprL.N-TztK}x$ͭ;ЍǃKRK=m>_7f-K4Ş]p.MW1~ҔCWѹY6Jyl:n='1'JRƇϽO]GM $`GLrGӮToqbgЏ7ק)u_ۧ?fRXw[Y5] 2i ͋<̺?o٭?vVV0!WEgr~I;#9}r@!B!phjZqQ*T A9o>zΤsUE-:4^Tjil4jrSU ΠyIU?i:5 cp8r[r_~Ip8~aaaʆWkoDSPr]wfMsE1lW 1O )g#n *.'Da !B!]k.*/TUիiPVu:xkJskvGMMq8.6:M[m:uFMFb7]Z%#hkVscAQ %]~FTkjqpulz D{yPIG}EZoe~|zʒg͇%z"'M.WF>(!Yaf5{e|3ZSܫwbACedV6,?C҅)m|T{;xQciR>Z_k)--SPjӧbq>YzO{'̭qvh$:=Cw"sG^H& 5!%#6N@R N͎H,Nֶc {Tӛupma@)M=rgc<ljsu=d|R_+z 1{X&9B B@|Z [i* {"碲M uIo|ݚ걹;r^V._śϷ8#:|6".WQ\C8&aGSuo_Vc2S0+%sxVKjX9}e[tȇ-d!֖OĂWsh)[PGAEIqΜ>nNGr; ڞ&[2rձik9òCYy`֫EƃYa65FyY)ŝƳXRƏ94^Ō=Ԫ>a]?dGT.o 5>(i!o+ѿE]º|Ή9<}!OץVf8R/cV?((3g0,PQPt|+NZB|~3բ;>!xnbD)܎X5%c 7-KGi/"q#ӆtU,;Bԯ3Р6]MiʨS=jʋt{u'jьw~=ز ]&~Ql\^יs咖 ȮD;WwKoS֪E5ʰVZԪYEi@q[}"ô?bm7LYen4((!4 \Xb9ɬ-x^ә6 o{<~B:ݙ)FAs` #Z>0 {؟C]wvg+۔'#aᵌm]E)Ak!}EQ|g:.$7= cɼ7Ы ?kkQY7gNxM * J`_͑9xZ9ĿISTQݓ)ϑ~ُ0t~̯Q7^rᎫ\4Q(poy󮑰klXϳBHijŜq$rIt4fDȫ^WYY.uIYS\r&tҘwj9 [~iOUwhM:OFtޡ]bhY^AQJP쿖-hi\&M[N+7/˫XchXB;|?ν8ƕ-˻݊bp"4/>K8n&Lm')<w$|>А2>uYN}J69{(lƻ9,08^k˙#,'wv _|l=M6C)i3&JI6׻!>kcfn?U\Oqűw 2S\EK3n٥ MOD/M:%P2-p|F^/a+fONK9wmzP]65?(TAN3wxmB񥌘^Xn}BGDza^n<1vi#ûmc@+w=w+_-,m #?9CGAtmf]ί@"Ccr瘷7vH~Dasesf}{Ȥ(ys;I~e)w#faŞ!4[Z{OJ&/|ܹao2wo{qp޽f6XUH;ɢ#w$>*lN)PYj&qXdZ{'Q<\sVi0ǁ鱢,ӎY8jGȢhk5] g`qjR}[۹ޛZ S5򻆌-mR8ʹ?8 @#a߇t~nȊvxmJ2S޶g[}l6ɡgaccAdVy\Wק;pI7)bq3L,cǞ9? K `9 +l\~oeoY_K6EpU8&%Gx" \MxpRӗ$%JDbG|mo49Ic(Ə͸W_/ea(ތn`ђ{7ޘ`}x7eOwcՠl,[8"1}Ly;R8Y7͔=|VSYkk0Ο04*zrL>I_q˒x8zKQ3Q{%q\Bo*~5;}N9  zM45sOڏvRzL8Ϣ;;2#o8 {m|39Zw*pR,vz-Vlk~¸}W`dnOcʘS1<^*q+wLOo$xeFlA%0Obk3QH(Yl ʮd>ɘI;wzS Tcv2 !$$t^|+UG/qtM{7:; n((J?EGc߉NkQrQ zi;iN|"mR}EջMgOũcsg#j 51&7~%ײiӷ=UUPL#G sWTݏzA."<{ `_NHN*Pz  Ӂ&q9䀴Y1d3TңB{0_ǹ[ Ϝ&"ΌfX`򚻙z kx(kmxg\5; gtT uX5~X=C=/Be9G4V-V}ˣ#%}thH)bXT\C^Xzy8Q/DDv4Юb叕֠(ԓ_K/6ާ*tm\*ਊw,:ۃz>Fbxx'YHǰ:R׀[!́E/m}Uf.JmŠ4-N#<̿dSV-JF@C`-%K+\I}B:%G>פknЍѬ+΋**v܉=XnrVPzaT <ޓWt:&Ck'PԺ1]\;P't T7 Я+.%ך5+5(Ƣ>%ox޽lP%c_-J&Bºѿ~ˌW^Ї%\Q]. o;EFFmy!ܽޅ/ɞ*W>{cfeStыvsMEp<3fD:g&X3n8:o_ܮXa;Xh=csg'r%qySobh#^>̵ވju ==Ŋ{f^DW,WR_Zrf :#F+iv }?GKV_mhOBZKxQtl6j6h!:z %vx"-xzTq)EPpx"ގG;R.>މټ&d휚bQt4ޅoW5EZW( Qy =n{Q'wXAÞAtȣ^O5,+S~fdҏ| GUDx[4_|RX64{ Q1n(v.MI_)>v.EPڎwREnt6݆@zd%Ff=˗j\bffa%7}r`'M{Q?cppQ8Hz@#->wuգ bP栊mIFLʱvZmEFv |Sqz4*Yj*Hd_yؓnν8E^t MTs+VY둃k7L-v3CF`83ܞEtjǘs|];Gd@!5{]Ͷ\~ݦ E*{Z5wjyUL*`LA>)|l,HX S,xa*w LjG4e(Ϙ3{q\>UϤqe|C?&qUlEhi1( utޟwj2>h"a .Rx"ܗߚ\-'ܨ==+'zaR[q{+vӠ|dȹ;%,kY#\/).~s6uGWc(Kg>|B 4:skZ$܃-g?qG_fA܁ڜ/S>s}ky&c].$hG8Q]EIuhxҸeAr{זIt$q9F"nm7B[~iRp/ߘ aGq=1'xllQ94>v̹z⛭ zW '\RߖKgcNgL+z:pN^dnbfgK{foȰYoG*+O|*b,ĢY޳icelvR,,AA\bU+cU/IHȩ'035ʪ?9\>δCTQک-dwþ%qgs+{ErJs7jS:23}&jEqRok3+bOw=],)hi2o6'3l mEEL\q4 .kػi>>>xUOH[VD܁)Ȏ,%G8OtlJqU13)h)vˏ_?P-ЋKc̛<ś~ kH_OmOv4lɉC ԣhaK:VՋqhΧʼnL8f'8rf-C!5{]S]`{st,IĮiRc9uQLuV/gHg3lYL #_qq3Z )(I[>Vkƴ~?ƋgX9|1}qO}s3%3fVۜl*5^=jS'@_X-j?FbйzㅋN!+xThB y#q m@ʉ qbG!ETjtixgtޙr-Gxf۵ìbȯJ-eJЬD8Gb^k*Gvf|%mhs'YtxT'K۰OS9_gnMkA:=EuO1flD.~ÄT>Җ}.9HK͞uMvLŨb$%M8.rSέɒQX5ӱ-4i ghPս >gDr|[xu3gr(₋7U;6cYؽS6㻭 ${D7t8Hg7]-䕤qnRent+(,TcN\F_Ŕ6}1S\ք!%'9qg%*AbFʿznK"W_oqnXA놊X_^U -PW{}7ҧfLu?DyVl,Hv-q3~SE_ͽZѡMe0Θr gRh6cw8v)GϹ}Ju 0H'8;9! !DOcQZi6}rz5e޿ Nn]IXhؘREE<3Qmۉ{Pc2{,CY:/̻fc(Ihu| L*j&LƯ2,7OG jyg oZ^;.i֞/p-֙[Zz** \C yFz'n&En̰>_)|Nĺ@:\SﵠW0~ǜvxdSSvøEho摷>zS*Lèjt^,@l7ԩ_ktTiTk%4;P7sGT͂2#U~ =*2fxv?w~e+ߜ?M}0{*+EM~6ZN2YG;Hvi-χ`ܖר3cj,jU;g={?#nL?`gxTx@ڵ 9UձvjԯUU_@^1vM[qv́#n{Eq;H#:R䏈HWitMH,"*  Plbi`R-Z>/5ݾd_@*_v+K. #c5RE?NO?-(@ED~0I&XfoPNHfc% iGF`QUl0OaÔFzLgJ+%{f=7p7 ,qD5ݵ7̟f.#']v&zJ9?}΍.DD T*""""""""٠PEDDDDDDD$dBlP"""""""" UDDDDDDDDA@֍. C UDDDDDDDDAH6(T*""""""""٠PEDDDDDDDr+SPEDDDDDDD$;dBlP"""""""" UDDDDDDDDAH6(T*""""""""٠PEDDDDDDD$dMX7HΣPEDDDDDDD$dBl񡊥ujEDDDDDD$񡊈HNPEDDDDDDD$dBlP"""""""" UDDDDDDDDAH6(T*""""""""٠PEDDDDDDD$dBlPr 'O~wk@5rBƿA"!su&ѝOW훈.l i0AA7wTNSDDDDDDO5tP4CzGA}C~>0aMWФ_x1ob]c)yg(&+Fmrg^58f!TDDDDDDn]; 'c)ʃu4ZMa32H쁔hԅwz:j^?B)Z$xW+bbYMt.B>yr'fsW=<(UfG}ؖ2 ԩDq{ԩ8㿳^ͼyr{oc޼7Z/ud}&+Ś3n |޾1dG$; ƌgOO /MCj/Ь{F9ΆyxQezү\[͙`4\^L>ew #M>q<^~'TAN\˨Mç"WCx ƵǹXCܛ@`+6*q15T+bc®y%óu/M2r{ ?֛&yMvgϱ y-rFn;I!zAgw3g~Fc!_Є5=^_=a~|@F { GЉEZᶵORF?a}:>OC[ ,p&T-(TDDDDD$GUbXi` gpS)OŴkZ#Θ11*)Nտ7K_0v7T-Q#OwG5LUsw,9wK:ml(TW-);xJ o:G8 jQ)v&ٛJfX]6=zq{a(e„gR;4&Pol|>w$&-P[om{Y\z2I'pZ~;9gpf~{(]+H[e·X4+ӯDDDDDDzQrX%wL?\. L&!!S=zĄxS ,_z#-2"wǰ'#a~t;y]$ 83_{xP yoB݇sGn8n[gT/tf/}*P!@͠m'\}MX1l̡a9b+;vҪ}Ԃ[ˋZ3˙t-וGc>% e/xN{.tTqIȅKUbKda۰6ORL>ˆcˆԭVى`p~[A#:zSH=#+Մc^vȅA[gC!;ڃ)R6gGdTٶlmR_L{]Ksў? BЙ,$ \ydFGth*-J1QVoŁt'*;t~oXEabP@;$fNə\ oVeby0:[$'>|o6EF浱Sx?O nubOʛ/q nT(imζNlGhն.d@B^[:Ӻf:aziͿ'j}x3_~/އWTz|ܑ' 7[XɎ]kYziE&t ϯ|Z8:_x1c:ӷ\6~p ;W@ґ?1\As!~Lʱk֔nF1Mcx4xP\qUkˏf!av/NZ6'x]) ;\6l6#VnnjS-bO4*wky˖/mFꆌDT|~gqGfF%ɱDDDDDDDuQ-ngYd k7}s<᳌ی1MxHp`KJ4d? 0=x kXy-חn_/ c/en;o % #Cc4B IDATR0z$*""""""""ZS6MR4z.GDDDDDDD2*׈<.CDDDDDD&M*Il]㽮ǵH/khrjT:UCPf`{S?q۳M3%} K{'5aތJWyߓot]}62?>NZˏ_c%o~m7+mި Ur2!430K~n{|@>Įeū (6}7 ߣKKؽ ]"nm/$,scdUZ]PΌYM5~G@ ;ެquFp3(z\^cS0˓L~dX׷MQ'Hqq|72Ι zg(JGd;%gs۳N„;PLJyb~!"Ts;!ǺKMpt^0:Է4+yͩs%gm7/S r*͡#_jz30ªOٛ|{hbQhیgлMMݼ=/C5PN/\2Lˉfӯn1 # G޶/ OxdLБV kQk9vO8XMF)ϦXlcr׫N6qCx2_A>թR.þ>IX3 *ݙs_`nvZ_00 xa%щ?{|ǧeF;ʙ'dzV0(Qsܘjl;6O+֑nAzywOuiM{O؟ri[&ֽ@׳TR/J">Nm^ƈF%04p+=^kFUS>İaqEqCmc{M1`hSF }L8;l3~M9ĚOPaV) /LaU3:qfDNz}ҫ9y*^nWAAEU䑗p27@Z;\./̟ē:Т}ys4){xod;j00(&=;m"iGjV#, W`j4,Njduk&[#0(:Dڅ " Yq0QUf_;c2^>¬U?ncp_0ذ ^l5ͷ⛘ NdD?eү|ImOrilKS\Y~ÙU9c?ۉϗڧ08~?9Z}sb]H>Eś0pbV|>]`X.>0h9{5?lo' nvqhibb5Z?7=ȢTIcƕTS?}ʡ72OggX QC,#y5n#);c~8m]Ӎ'/x^.Mkc?WnLNV>{?\_t1G}T ӣ(x\f+ ㆳ{K8Mxu)lӫ<9m>K?^JQ3ل->L}ݞ&z<ʼnΫH̒~|8qgf4e<^^Sf_Wf귒̯~i2uWԜ \?B.ΊgO8!Gfc}A Ai>>L =WҽY2s gC6jJ̼+SDDDDr>*9^.A(*Cy{F`iOxZӾ4n,; WUxSYWZ0pif 7nkG g-߶Gܙʼ[ h6 yE䯳dDФk3*P{ ݲK?ѵ}J*FH?lμy\ƴBL*h_:V"ZsRvtE)Eνѧå-RP<͟^l=?9sчҩF$.I:2O.?wY#3}EG8R[q2*6l{p)(϶_}B  f=i!uïwTPg.n2Ν)WQ\kzpˉO%C[Nӆ3ϝ_~.\*h >sKɲ6?‹&*ĺ9|^{8]GgsZaRG<ҫtsx.$c9C(XFz}s鹸k#Ҷ%?+Lea8PE/m)9K;blnJNLy?Ń;rƍ ۜ;~1ljDGP$% _]R4,CwgL(-NxZT*ӰT;y kI|~} eH'RTMKsBtx-U?I/8GJxxl[K๝qx">.7vK&NdǛ8bpm*I} xaÎaX/}1+B{(E ||" '"$:(ÅÓ|4_"N8(X(FR$$G}Q-iϝ|]<,9 :gx'93S4$iKY3&_:iAQ>brQ#]LVȨBg8=.do9?׹7 d//Çsm81)أtIӤ[|7o#OP n6o|}KjEv.>VJ  S3۟:?m O')|&T}tHqLUϣ|/[KɡCE,H :A)cL`l7—x itV0. ?y@io!̜2:#` C2. VLw,Gгd#(i1ߺfIq9H f/?| DDDD$S 'wxHz9s~SjS\d/j|8%o6 u48a0&dQ'}k]NP[{3 wF`~vBnׅ-Ub*Mޙnm/~@1'qⷷܲ~. e\%":ƍU܉xN`DAl&1kєq`\EZ+{`AOԾ sUc.fFH& z ǟbۇOt2*~Љ|NX' XTZhJ4sw2-π Lfw(L丯b^xsy=x<xόgyrh>s"VL<_75EK Iqn-HrgfNh>ĥ|5ZSq{,^3`f5(kBV 4~.?`yNqXӚ;sg-nr]G2_Vy} :Lcۦ$]ր38=ĦNɱ[M;yB. x\[ߚZW<7)%4Iؾom9s]\xLVXIٰ1HXX)p,hX)Y=k*iFgV q. '7䝵iL]p Mbuq[xcc{e;QZ+"""rJf? ˌ:yspipp↍-8#3傼1p!Suy?fACqw%΁/Qd#4lݕgs/3gR\,(ֆ/~PpD5e>8?wQ54n1RӅuk;<@>w޾8# QޟH?\1<޸{VwaR0:PƿT{CM|~cͩhA56kX$nHsu!A|5(qfITeK8"̌y̛7zU!o2g^kĦ fKÌT1 䓽i8R""""""ߡ*Wndcw0lv0 Xt|S?zW?<۴Yyr@uDĵߔ1|,r}5፷`n\ˈ=^{Mz؆yc3HkG3{^ߐwBc~gs+^x3ˊ?ŃrNy=IKy}qmKM_dP)ʡ/{cfF$ 51g ^ckf?a}:>OC[ ,ouqS#v=^LT#""""""7 T9>7,?4퀅z}^)n|B'b5͈NUogGZٛ%  ۖ'Ki2usXߖ&7PX2!X>C|VrKKny\~[xCDzʱw*^;K7Ono؉[Ō$ "/ Jzz,LqPT浲cy=xc욌_5(uv#X4Ct]G Zr:R TIX%wL?\. L&!!S=zĄxS ,"wǰ'#a~t;y]$ 83kJM͟oz;xe/\bp(wT.J`jam_av/_lF/VvtmDEK,Lϲ(:?=8Dbq)<5s~\.C~?*p#/nQ9#""""""7;*Wfr2. Gorpv<)^<HJ1Iv[,Nˏ #ZPZxd'N;omULm\ D[HroI-=|a8Mc~GbgFxf`/oMJ0˃SXR-RsH3/Mطg"yc|_G\lюAEg)N{YM旽~߳h~L’Q[۩\* #3xqmԋ+ -9W^F1ܗyeꈳM sa=Z0O7Ç ^ef-?8;>9 "Wx~ +c©;Pm<K.o w.ևeq&aNo{|v;_mOmB*Gh]Gd*ÇSHع/8 ? )lc?PE_@%w3rՇiz7kǣS*UdA 5-w%oӻ|TC\%w IDATc氥`F}ķj׻8)OW0F@qZL!0qgoMteޕ3S.h\\6V'2+P~=v;xc1nϕPſ4]&LUwuhKOr4+&mQ4Ivo\:_؎(/y-)ifv0 ×tXvisz-?fb؝V.`jwr +e{KLS11^En4oeԨQ#[ݐo,6#qèX59n:J%l6;˖,vnf!r/5| eflmbS׻w2^ͨose5-oZ~ѧBOԦJWyos/""""9B{% 㒟Jd|_LZ[_bw=;ݻޠ5 *,Mr2'?FV5 ̘*[0|p ]kwrC5k5i` c+tvVzA=d,pڦ7#B(=>Aۍ ޗap|UH\׳~_-'MJ&z^s*\a!eeKԮ)7x9—F#_jz30ªOٛ|&ZFX`=6㾪sC{7o_FP*TӋٰaٰ;(XX$YS'ffT20W_sҷUp|ssMx8v=j&((0d̍Iz{m/X,aFY%?$xMe :}ӉkhL+HZXVr* ","i}<7֞qxdO}xEح J | cG5@ }>TŚlaT?'L<{ X~+5x/bMXg\?{7}]i7MZ1H{}Ȁvr+?瘣 .g콏0k[.ןg0L6lD`[fMg&&/G0uS+;{_*zm\g8")m֬p.pkv%<2e$Vwl~ow|s:?g2 _O#6j#3|.Z^6 Hi+l[o*m赱Xm|MyM}3Zo#L{e^[ƆxRN?ׇja>=x30!*]೻z[}h^&՗8vcٵ&HJ8rWV\f v]?D`DG~΁qb>=.#9-0M u+^K1p8޽1X (@s8x؞;#~Qڛ }ޣW(#.KFPF 6cTЖJToߋE3""""洛rBtx-U9SOzԉwΖ\~@)Ǐ'㢡xc7dD}# GF~r'x{h8g68&n2|>C}hR'p.Bϭb8\8<ɗO%r섃Ͻ~[`$EBNr4!Ւ6yECJ>ɾC}gJ}Ӛp)+g2~RL{IwZPT!Ͻ\(H=w4:2PNC7.do8?׹7 d//Çsm81)أtIJe~g [^|ϛm[B/yft4qmD\a1ߟ yap-WBZY>kfNJy0CQ\N36/B0׹kZrn?[硭$x %+$cQ0W.bPecg؇g=}*~nb9e^3c' :wL{HA """"P%dzN4Yr1<30զع$n^ 9pKF/Xm\;n'ipz`Mģt׺C9$)g;l#_-(k$_/0/.;Ә:r)LV&/;e5?[Ƭ"8Ap4ëLr]N<4VJ #6lyp1n(FW+eLҍXlE%lm 70p){wUuqsΝLa (tQuUZuK{սbkZw k L{I$~=O3ssN's˗ȋ^N/1C1L\+)#)Z6C:PlU}+ 9brjWk^g~wщ}P'n-)yԕVR*YyU+˴ n﷠p+u;CKHe}J|u՜yr;e%gkNE_(Li(TD=[s.zR=;%fֈ{|nu*X,ϩd*NsרuknLZc񯯴J(P~=MW_>,0I]g*afMUL6~??yFvS.m}͔OhIIXmrK#>n}UNտyBER9Cz٪t+4gdCM6[I塼IMq{&dMm5xA5χⴆR= #VyT1UtVʶ;Ѩ%|XW/XytfI΂x3~J)g5r^o[tb]7]U_Q<| "#NOJX-7Ec5u%kk4/Xvg}qJWL>I-]F+HġsJ:K\{^X;%Cy*iHh~Ygv5뗯-\wbݙeMyUzyJáLOu6hQ.'W8GHk1O;G۾+N҉7mHp֐R#.ԾoBko>Ӻ`ov_g VZdl5f bvDwJHJ8]>:_uv5& =a__i+oӴ&0F{8Ho =>!րuorWڷG c{j؃mtǪg#T>/,8TB9nJ ӓn_N٦?)|n|te2\}#w(jޝk7$5tŲd~TA|GSϸTK^ Ny '-묁25z1ez X# $FQ-I_ue .33;f&M*H5A"sA W%>HڤMF&(Ukӑ\~mlMvAv澋/]X5U}}wrn3z^MkgiNׇwFѬuqt[ՠ`9ro?gm^CwZv;販^0[{8ι.984+JyJ\¸Ѕ.LFA^}QIE.g&Α/ .fՑN'7OUI>;Ko=xJ;T[Ň*ۜ@mbz/У":gdTt#G6w!hIZ| @KD*M@*M@*M@*򛻀"ThB& ThB& ThBUP UP ZA V: ThyUP UP UP UP31G9_SPeRb`7k>>c[r&O߫+8A I'IM7Le߮+J_tNS-"-a]4lQI.U1~*6FC?_*'IB\qtֱ:b쬷t߅;=뾏G^γS_cױ˫;7EvnzA]A2=-\Y`Lc_N4HeMT|ҧtAW_s~4Ln?Lu疏ճ9RwOKe PQ'\*'E\{W:娽4`KҌ?|yeѮ'ߡwˢF^ZYz7IrctQC7J5oiҾC +ԂO' U_c 憫j:vezZ+Y纮|ݗSԡs{>i%/jRӵW#<\׍T\>Q#n{۹ Q}Sr5odzs'}tST~@cl_/Fb`+.YL"ZqSҐny2 U6z )i{c^Us>~;$)Sśā/?ޭޣ㦪ώr&j={kZ=t']gߝ~HWSϺ^3=/7QŘt򹣴_Ĩ\/3A^~ X^8w[i]uY}E?ax/fD?k)T٨O5~zNш_3?W+P/ %VUZse*c-DO~NݣXnӯ^-U 5KoIB_$~GW׫U ^t"aDs^n廓>DEھVݍ+gî~ھCBhĴnSx,qSmT`\h}}mUh%jT9r?N~I}Z;FWjJX^%n~]otmﵛBm݃*zgm*Myj6]rpI$T<0WjI^&>q&O:] up |b =G[]CEm t]:)H~4_9EZ8n*dH2J* IDATLȚuW1aݲ|6*} g _\g~کsRi8 p[QB TLm)meݴ!{("_gue}cmTiݭ:uGǛ Pezzٕ^amwU:zb%6fӤZFZ8Kt%JIs]Lkfh~:$e h{h؅e<._v镖mnN4JuCG>EʛڷҊ\e?L?6eٜfuzUΝҊ -_ʙ VF+_Mn;{(UR}(hdcuu tyuv0aLmђ1zjGSMMݙ4eẠi+oy7j rUZT1D7?֝&uݹh|5rUDr +)w';!Zc:kݷQ;t\ن\SVj:(0>yzN l޵:\.5?4s.Ըݵ%JJ߸C=CtIz㷮T>~usp:wդrb% V׉4`Kz2Uy5wxנau皩}Ӆk33hԓW~'ۦc)nQ|U^zkTy޹ڽLRm gk_?:$*,*[:A.XCKT674<|i7qz}<=o- U)m﬒vj׮S߽ұxf+W함hcO_Pe²1gWuKIgjȪ|^mv,QCz&}GVYf<{ꑔ=uĽYڮnG^쪁zꤟJR[ȗqR Xvޭ OZْ]u^So`YAe* :j Ҁ[ك e3za6R>ʓ4}a?PQ#cdMMjΓ+)h.ԗ^ W~?~ϑގ;'߮êxZIE iJ]ԳN:Zpv5|u{Gkz㷶"U|\wJpɺErJkQ+?v%iUika)rjդz|R3EQ>?ͥGkPK uv)OCV]V_9OMWUCJv,Q4 :a`4|F\{ltԣu{Iho [&dla_~&o?hFm[Y֪mq{]> &v co9e2'WfEB6S\6/rY)KЅ( }T83l<9%_x^cou:7`Cec4`ub PiUտNk{Ī7w4?:UP UP U@ !ThB& ThB& ThBUP UP ZA V: ThyUP UP UP UP U*~sP_UZ B& ThB& ThB&HlZ#Gn@+UosZ!4 @oP UP U ؘ 6w ` ņ*/>.lPeȐ6w ` E*EmljŇ*~s6P%"ThB& ThB& ThB& Th.bY 7w)BΝTTF[mcsQ3gR:P|.UyU:kzn.+*tA{KiU?6@47Ba…r@ , e4;B6+KhUh$ʆ"T{B F**4T4S.kW Vz3TdtlN$oesO^'Ym '{众|[՝* [nٙzkt뎮md3 44RvZ_U7T5ml[WAUh$]wzZ=GGn)KGաʪN)둻_ߞCtiIW;ަ??JwQ]~^GYEZ2fQYr]_^_ 6dK^PFrS%7W1K9;x2k~μY nOg=O詊>շ(,+rΩjڳwm{:ɔ}/T~w{5*[&Y ͟#uTPӉ }ec3B+%;?H]9/%dԴZI6]u|G:WΚٟV}jc_@y}V9fެg TZA@ ἚOܷ}#w׹SXsVNҲȫ(QSe3kv3Cԕ:Pqi}W}#[Lj:U+OOB'͹F(]L.ٚ屉zWl\4HZ}sVı|yC'#-ƕ.QUdRj׮P)k$ߑ';QT;8e)Oi ꖀN;'i~cu/y|a? =jN8;_Piο\=r:vpt%]ţW "]}پlLtmcf(#N:%l**4^n#-bkSOmǼ^'tuέz5Zz}+Pہttn'j?[**4Tْѩm΋}]ϼzMl**4zmfͽ&m}}Uh;ڠ"TE$#Ǻ*bUj߾xsQm4v0x 93VmnR6 Ba{id]Nо}ڪWٯ&MKlʚGU`ݻ.a߾wYZEV0jwxPOk 6W&mqzZG BVT`KT{o;,?`S{Oj[~;UZC2gmS~Ni y@UT`˱)?d 4ڦԝߩ"[,*6SlLsR+HаLo*-~OkH5fO?!h*Tm5=TIWM}誗H %Ibygx{99x&54h?xzc#9Du~8by)d'"[]q2pudW^))V4q%|wNq+QɹP^ٷ}>r7cfIm7J^Y9(Xa{]hbq oMT(lV <ʜben!g4T-UD|I0~^>LY#g"E&QLq2/Sدgw?X*[[@*[T7ռSWx 'fgr&Y#MT AsH>W%4B%'Jˬ^^[+yoyA r.KNyZ&mR.LBJ)2I IjYsT ZNؤs*Jy<[<39T:9%5ۼ=~iDH*''_孵>a.R.%A 9V`#F6|(kƹ[h5T\LJrRal(6'lyY]WE򉴼|_u}6>/iPڴ/WuIILYۤOI7zGy\.yG&lD>؜:C)罫2 5A3n>(Drr ػ8%wΆŶS%}`z LJ*}Ij}/U9*4i}oqÏ_=[n2w~ɒ?z{' Ryq^ָ( e؅a2Hq*0.LW)[ KM\0pʥdrΪ*lbA0t&l2Γ]:/cfOλ%R5֚t|fN3pI+U{)@֛@>r޹wAB>[dr9xc@es)rqhH [08>QdBT8Qʹ\${c9c%},ՙbz*9TY9h|)@Eo˼ VZk2.VM060JbG>e>boB&MJJ8kSlWhŢyDq>LQB.g> :` wN99WP+qlQԟt_&՟ 4=Tڦgc_u>AB&2EHaNVR"HF9cm8ɹH6ecK [4Y#85T ┫Tl#|$SQWx[Š.e˜/ƾ\TfT=hl$-2p.Y*XJ% $yeIx+gCc T` {op83G(MM"X}C]{Tw$zElQ󗇾}NH4TY.@RM F_Qꗦ"WL`LZkNޚ(%0'78)t5QSABkFɸ䪷K8ἓMV|$S2>>rq98vT䊳EZݥL:,IC0Hl̀23lmRwH>gKUsAe_JcBfRN@Zs}+٥OwE2)k rRyWi坕 R1L~_%T^ Z(d%y|`ycy'" Ϥ"W;@ )PSeWpiLmҔ&Lꮕ\1Q5)c1aLAjQjؒ%~UQ>Y y_>Q|eYzE.?%ZIDAT/}Qk*zAԶqB:$1hxS!eԿ2 WZSjE S)|TÕAJ^[f+v~UҥפI*Zס1ic*:I۵"I%, LU~u2`h5ke"IyW)T;E6e"mPEjx:Ӂ$iesEZHIUK W6+v^sF3&LuN6Z"mPEj0XwH$ XS Ej):SH"TZYتexAVS>w +Ij}ATN6}"mPEHuIuiu]j( EZG"m@EڔJ +RT?d%j)& SVnSl k WKmE[Զ Eaʪna Zm0e7@c3)+ H-&DT`eIɶIENDB`qdirstat-1.4/screenshots/README.md000077700000000000000000000000001311502036700216432Screenshots.mdustar00rootroot00000000000000qdirstat-1.4/screenshots/Screenshots.md000066400000000000000000000107041311502036700203730ustar00rootroot00000000000000# QDirStat Screenshots Qt-based directory statistics: KDirStat without any KDE -- from the original KDirStat author. (c) 2015-2017 Stefan Hundhammer Target Platforms: Linux, BSD, Unix-like systems License: GPL V2 ## QDirStat Main Window ![Main Window Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-main-win.png) ## Output During Cleanup Actions ![Cleanup Action Output Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-cleanup-output.png) _Screenshot of output during cleanup actions. Of course this window is purely optional._ ## File Type Statistics ![File Type Statistics Window Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-file-type-stats.png) _Menu View -> File Type Statistics..._ ## Locating Files by Type ![Locate Files Window](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-locate-file-types-window.png) _Results after clicking on the "Locate" button in the "File Type Statistics" window._ ![Locating Files](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-locating-file-types.png) _Locating files with a specific extension. That branch is automatically opened in the tree view in the main window, and all matching files in that directory are selected._ ## Configuration ![Cleanup Action Configuration Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-cleanup-config.png) _Screenshot of cleanup actions configuration._ ![MIME Categories Configuration Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-mime-config.png) _Screenshot of MIME category configuration where you can set the treemap colors for different file types (MIME types), complete with a real treemap widget as preview._ ![Exclude Rules Configuration Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-exclude-rules-config.png) _Screenshot of the exclude rules configuration where you can define rules which directories to exclude when reading directory trees._ ------------------ ![Tree Column Configuration Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-column-config.png) _Context menu of the tree header where you can configure the columns._ ----------------- ## File Size Statistics ![File Size Histogram Screenshot](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram.png) _File size histogram for a directory_ ![Histogram with only JPGs](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-jpg-work.png) _File size histogram for all files of type .jpg (start from the File Type Statistics window)_ ![Histogram Options](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-options.png) _Histogram settings can be tweaked_ ![Logarithmic Scale](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-log-scale.png) _Logarithmic scale for the vertical axis if needed_ ![Histogram with P100](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P100.png) _Degenerated histogram if the last percentiles are too far spread out_ ![Histogram with P99](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-histogram-P99.png) _Just one percentile less makes all the difference: Scaled down from P100 to P99_ ![Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-table.png) _Numeric percentiles table_ ![Full Percentiles Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-table-full.png) _Full percentiles table_ ![Extreme Percentiles](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-percentiles-extreme.png) _Notice the leap from P99 to P100_ ![Buckets Table](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-buckets-table.png) _Buckets table (information also available by tooltips in the histogram)_ ![File Size Help](https://github.com/shundhammer/qdirstat/blob/master/screenshots/QDirStat-stats-help.png) _Dedicated help start page for file size statistics_ -------------------- ## Navigation [Top: QDirStat home page](https://github.com/shundhammer/qdirstat) [Statistics help page](https://github.com/shundhammer/qdirstat/blob/master/doc/stats/Statistics.md) qdirstat-1.4/scripts/000077500000000000000000000000001311502036700146765ustar00rootroot00000000000000qdirstat-1.4/scripts/README.md000066400000000000000000000051641311502036700161630ustar00rootroot00000000000000# QDirStat / scripts ## qdirstat-cache-writer This is a Perl script that can be used by system administrators to scan directory trees in cron jobs over night and view the result with QDirStat whenever it is convenient - without creating I/O load on the machine you are scanning. You can also use that script to scan directories on a server and view the result on any machine that has an X11 desktop running. The server doesn't need any more infrastructure than a normal Perl installation (i.e., no X11 / KDE / Gnome required). Using those cache files considerably speeds up QDirStat's reading proces. To give some rough numbers, on my laptop it takes QDirStat about 3 minutes to scan /usr. Reading the same information from a cache file takes 3-5 seconds. On the downside, the disk content may have changed in the meantime. A cache file is outdated by definition. But it may still give you some rough ideas. And there are large directory trees that hardly ever change. Or you may be a system administrator with a NFS server that houses home directories, and every now and then you have to check exactly who of your users again managed to fill up that file system to 95%. One thing you cannot do (or your users will hate you for it) is start QDirStat during working hours to scan all those home directories. So do that with the qdirstat-cache-writer Perl script in a cron job running in the middle of the night and view the result with QDirStat during your normal office hours. For large directories (archives etc.) that don't change that much, you can also generate a QDirStat cache file (either with the Perl script or with QDirStat itself) and save it to that corresponding directory. If QDirStat finds a file .qdirstat.cache.gz in a directory, it checks if the toplevel directory in that cache file is the same as the current directory, and if it is, it uses the cache file for that directory rather than reading all subdirectories from disk. If you or the users that machine user QDirStat often, this might take a lot of I/O load from the server. There is currently no indication that cached values are displayed. This will have to change. When you click the "Reload" button, the directory tree is really scanned (just in case you might have thought the cache file is read again). This is intentional. Tip: If you generate cache files with "qdirstat-cache-writer -l", they will become somewhat (~20%) larger, but you can also use them as a replacement for "locate". Simply use "zgrep" in such a file and ignore the size, mtime etc. fields. See also [QDirStat-for-Servers.md] (https://github.com/shundhammer/qdirstat/blob/master/doc/QDirStat-for-Servers.md) qdirstat-1.4/scripts/qdirstat-cache-writer000077500000000000000000000304051311502036700210340ustar00rootroot00000000000000#!/usr/bin/perl -w # # qdirstat-cache-writer - script to write QDirStat cache files from cron jobs # # QDirStat can read its information from cache files. This is a lot faster than # reading all the directories in a directory tree and obtaining detailed # information (size, type, last modification time) for each file and directory # with the opendir() / readdir() and lstat() system calls for each individual # file and directory. # # QDirStat can also write those cache files ("Write Cache File..." from the # "File" menu), but the whole point of cache files is being able to do that in # the background when the user does not have to wait for it - like in a cron # job running in the middle of the night. QDirStat itself cannot be used to do # that because it is a KDE program and thus an X program that needs access to # an X display - which cron does not provide. # # This is what this Perl script is for. # # Usage: # qdirstat-cache-writer [-lvdh] [] # # If not specified, defaults to ".qdirstat.cache.gz" # in . # # If ends with ".gz", it will be compressed with gzip. # qdirstat can read gzipped and plain text cache files. # # -l long format - always add full path, even for plain files # -m scan mounted file systems (cross file system boundaries) # -v verbose # -d debug # -h help (usage message) # # Author: Stefan Hundhammer # # This script is freeware. Fuck the lawyers and their legalese bullshit. # All they ever contribute to software is those legalese headers that are just # in the way of people working with the code. # TO DO: # # - ensure to use UTF-8 use strict; use English; use Getopt::Std; use Fcntl ':mode'; use Encode; use URI::Escape qw(uri_escape); use vars qw( $opt_l $opt_m $opt_v $opt_d $opt_h ); # Forward declarations. sub main(); # Global variables. my $long_format = 0; my $scan_mounted = 0; my $verbose = 0; my $debug = 0; my $default_cache_file_name = ".qdirstat.cache.gz"; my $toplevel_dev_no = undef; my $toplevel_dev_name = undef; my $unsafe_chars = "\x00-\x20%"; # Call the main function and exit. # DO NOT enter any other code outside a sub - # any variables would otherwise be global. main(); exit 0; #----------------------------------------------------------------------------- sub main() { # Extract command line options. # This will set a variable opt_? for any option, # e.g. opt_v if option '-v' is passed on the command line. getopts('lmvdh'); usage() if $opt_h; $long_format = 1 if $opt_l; $scan_mounted = 1 if $opt_m; $verbose = 1 if $opt_v; $debug = 1 if $opt_d; # One or two parameters are required # (yes, Perl does weird counting) usage() if $#ARGV < 0 || $#ARGV > 1; my $toplevel_dir = shift @ARGV; $toplevel_dir = absolute_path( $toplevel_dir ); my $cache_file_name; if ( $#ARGV < 0 ) # No more command line arguments? { $cache_file_name = $toplevel_dir . "/" . $default_cache_file_name; } else { $cache_file_name = shift @ARGV; } write_cache_file( $toplevel_dir, $cache_file_name ); compress_file( $cache_file_name ); } #----------------------------------------------------------------------------- # Write a QDirStat cache. # # Parameters: # $toplevel_dir # $cache_file_name sub write_cache_file() { my ( $toplevel_dir, $cache_file_name ) = @_; my $start_time = time(); open( CACHE, ">" . $cache_file_name ) or die "Can't open $cache_file_name"; binmode( CACHE, ":bytes" ); write_cache_header(); write_cache_tree( $toplevel_dir ); my $elapsed = time() - $start_time; my ( $sec, $min, $hours ) = gmtime( $elapsed ); printf CACHE "# Elapsed time: %d:%02d:%02d\n", $hours, $min, $sec; close( CACHE ); } #----------------------------------------------------------------------------- # Compress a file if its extension is ".gz". # # Parameters: # $file_name sub compress_file() { my ( $file_name ) = @_; if ( $file_name =~ /.*\.gz$/ ) { my $uncompressed_name = $file_name; $uncompressed_name =~ s/\.gz$//; # Cut off ".gz" extension rename( $file_name, $uncompressed_name ); logf( "Compressing $file_name" ); system( "gzip $uncompressed_name" ); } } #----------------------------------------------------------------------------- # Write the cache file header # # Parameters: # --- sub write_cache_header() { print CACHE <<'EOF'; [qdirstat 1.0 cache file] # Generated by qdirstat-cache-writer # Do not edit! # # Type path size mtime EOF } #----------------------------------------------------------------------------- # Write cache entries for a directory tree. # # Parameters: # $dir Starting directory sub write_cache_tree($); # Need prototype for calling recursively sub write_cache_tree($) { my ( $dir ) = @_; logf( "Reading $dir" ); my @files; my @subdirs; my $success = opendir( DIR, $dir ); if ( ! $success ) { my $msg = "Can't open $dir: $ERRNO\n"; print CACHE "# $msg\n"; logf( $msg ); return; } my $entry; while ( $entry = readdir( DIR ) ) { if ( $entry ne "." and $entry ne ".." ) { my $full_path = $dir . "/" . $entry; if ( -d $full_path && ! -l $full_path ) { push @subdirs, $entry; } else { push @files, $entry; } } } closedir( DIR ); if ( write_dir_entry( $dir ) ) { my $file; foreach $file ( @files ) { write_file_entry( $dir, $file ); } my $subdir; foreach $subdir ( @subdirs ) { write_cache_tree( $dir . "/" . $subdir ); } } } #----------------------------------------------------------------------------- # Write a cache entry for a directory. # # If the device of this directory is not the same as the toplevel device # (i.e., if this is a mount point and thus file system boundaries would be # crossed) only a comment line is written and an error value '0' is returned # unless the "-m" command line option was used. # # Parameters: # $dir directory # # Return value: # 1 OK to continue # 0 don't continue, file system boundary would be crossed sub write_dir_entry() { my ( $dir ) = @_; my @lstat_result = lstat( $dir ); if ( scalar @lstat_result == 0 ) # Empty array -> lstat() failed { my $msg = "lstat() failed for $dir"; print CACHE "# $msg\n"; logf( $msg ); return; } my ( $dev_no, $ino, $mode, $links, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = @lstat_result; $dir =~ s://+:/:g; # Replace multiple // with one my $escaped_dir = uri_escape( $dir, $unsafe_chars ); # Write cache file entry for this directory (even if it's a mount point) print CACHE "D $escaped_dir"; print CACHE "\t$size"; printf CACHE "\t0x%x\n", $mtime; if ( ! defined( $toplevel_dev_no ) ) { $toplevel_dev_no = $dev_no; $toplevel_dev_name = device_name( $dir ); print CACHE "# Device: $toplevel_dev_name\n\n"; } if ( $dev_no == $toplevel_dev_no || $scan_mounted ) { return 1; } my $dev_name = device_name( $dir ); my $fs_boundary = $dev_name ne $toplevel_dev_name; my $msg; if ( $fs_boundary ) { $msg = "File system boundary at mount point $dir on device $dev_name"; } else { $msg = "Mount point $dir is still on the same device $dev_name"; } print CACHE "# $msg\n\n"; logf( $msg ); return ! $fs_boundary; } #----------------------------------------------------------------------------- # Get the device name where a directory is on from the 'df' command. # # Parameters: # $dir directory # # Return value: # device name ("/dev/sda3", "/dev/system/root") sub device_name() { my ( $dir ) = @_; my @df_output = `df "$dir" 2>/dev/null`; return "" if scalar @df_output < 1; shift @df_output; # Remove header line my ( $line ) = @df_output; my ( $device_name ) = split( '\s+', $line ); deb( "Directory $dir is on device $device_name" ); return $device_name; } #----------------------------------------------------------------------------- # Write a cache entry for a plain file (or other non-directory i-node) # # Parameters: # $dir directory # $name file name (without path) sub write_file_entry() { my ( $dir, $name ) = @_; my @lstat_result = lstat( $dir . "/" . $name ); if ( scalar @lstat_result == 0 ) # Empty array -> lstat() failed { my $msg = "lstat() failed for $dir/$name"; print CACHE "# $msg\n"; logf( $msg ); return; } my ( $dev, $ino, $mode, $links, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = @lstat_result; my $type = "F"; if ( S_ISREG ( $mode ) ) { $type = "F"; } elsif ( S_ISLNK ( $mode ) ) { $type = "L"; } elsif ( S_ISBLK ( $mode ) ) { $type = "BlockDev"; } elsif ( S_ISCHR ( $mode ) ) { $type = "CharDev"; } elsif ( S_ISFIFO( $mode ) ) { $type = "FIFO"; } elsif ( S_ISSOCK( $mode ) ) { $type = "Socket"; } print CACHE "$type"; $name = uri_escape( $name, $unsafe_chars ); if ( $long_format ) { $dir = uri_escape( $dir, $unsafe_chars ); my $full_path = $dir . "/" . $name; $full_path =~ s://+:/:g; # Replace multiple // with one print CACHE " $full_path"; } else { print CACHE "\t$name"; } print CACHE "\t$size"; printf CACHE "\t0x%x", $mtime; print CACHE "\tblocks: $blocks" if $blocks > 0 && $blocks * 512 < $size; # Sparse file? print CACHE "\tlinks: $links" if $links > 1; print CACHE "\n"; } #----------------------------------------------------------------------------- # Make an absolute path of a possible relative path. # # Parameters: # $dir relative or absolute path # # Return value: # absolute path sub absolute_path() { my ( $dir ) = @_; return $dir if ( $dir =~ '^/' ); my $save_dir = $ENV{'PWD'}; chdir( $dir ); $dir = $ENV{'PWD'}; chdir $save_dir; return $dir; } #----------------------------------------------------------------------------- # Log a message to stdout if verbose mode is set # (command line option '-v'). # # Parameters: # Messages to write (any number). sub logf() { my $msg; if ( $verbose ) { foreach $msg( @_ ) { print $msg . " "; } $OUTPUT_AUTOFLUSH = 1; # inhibit buffering print "\n"; } } #----------------------------------------------------------------------------- # Log a debugging message to stdout if debug mode is set # (command line option '-d'). # # Parameters: # Messages to write (any number). sub deb() { my $msg; if ( $debug ) { foreach $msg( @_ ) { print $msg . " "; } $OUTPUT_AUTOFLUSH = 1; # inhibit buffering print "\n"; } } #----------------------------------------------------------------------------- # Print usage message and abort program. # # Parameters: # --- sub usage() { die <<"USAGE-END"; qdirstat-cache-writer - script to write QDirStat cache files from cron jobs QDirStat can read its information from cache files. This is a lot faster than reading all the directories in a directory tree and obtaining detailed information (size, type, last modification time) for each file and directory with the opendir() / readdir() and lstat() system calls for each individual file and directory. QDirStat can also write those cache files (\"Write Cache File...\" from the \"File\" menu), but the whole point of cache files is being able to do that in the background when the user does not have to wait for it - like in a cron job running in the middle of the night. QDirStat itself cannot be used to do that because it is a KDE program and thus an X program that needs access to an X display - which cron does not provide. This is what this Perl script is for. Usage: $0 [-ldvh] [] If not specified, defaults to \"$default_cache_file_name\" in . If ends with \".gz\", it will be compressed with gzip. qdirstat can read gzipped and plain text cache files. -l long format - always add full path, even for plain files -m scan mounted file systems (cross file system boundaries) -v verbose -d debug -h help (this usage message) USAGE-END } qdirstat-1.4/scripts/scripts.pro000066400000000000000000000003631311502036700171110ustar00rootroot00000000000000# qmake .pro file for qdirstat/scripts TEMPLATE = app TARGET = $(nothing) QMAKE_STRIP = /bin/true # prevent stripping the script(s) scripts.files = qdirstat-cache-writer scripts.path = /usr/bin INSTALLS += scripts qdirstat-1.4/src/000077500000000000000000000000001311502036700137765ustar00rootroot00000000000000qdirstat-1.4/src/.gitignore000066400000000000000000000000611311502036700157630ustar00rootroot00000000000000Makefile qdirstat ui_*.h qrc_icons.cpp .obj .moc qdirstat-1.4/src/ActionManager.cpp000066400000000000000000000027071311502036700172200ustar00rootroot00000000000000/* * File name: ActionManager.h * Summary: Common access to QActions defined in a .ui file * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "ActionManager.h" #include "Exception.h" #include "Logger.h" using namespace QDirStat; ActionManager * ActionManager::_instance = 0; ActionManager * ActionManager::instance() { if ( ! _instance ) { _instance = new ActionManager(); CHECK_NEW( _instance ); } return _instance; } void ActionManager::addWidgetTree( QObject * tree ) { CHECK_PTR( tree ); _widgetTrees << QPointer( tree ); } QAction * ActionManager::action( const QString & actionName ) { foreach ( QPointer tree, _widgetTrees ) { if ( tree ) // might be destroyed in the meantime { QAction * action = tree->findChild( actionName ); if ( action ) return action; } } logError() << "No action with name " << actionName << " found" << endl; return 0; } bool ActionManager::addActions( QMenu * menu, const QStringList & actionNames ) { bool foundAll = true; CHECK_PTR( menu ); foreach ( const QString & actionName, actionNames ) { if ( actionName.startsWith( "---" ) ) menu->addSeparator(); else { QAction * act = action( actionName ); if ( act ) menu->addAction( act ); else foundAll = false; } } return foundAll; } qdirstat-1.4/src/ActionManager.h000066400000000000000000000040061311502036700166570ustar00rootroot00000000000000/* * File name: ActionManager.h * Summary: Common access to QActions defined in a .ui file * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef ActionManager_h #define ActionManager_h #include #include #include /** * Container class for QActions that are defined in a Qt Designer .ui file, but * that are also needed in context menus e.g. in context menus of views. * * This is a singleton class that is populated by the class that builds the * widget tree from the .ui file by simpling passing the toplevel widget of * that tree to this class; the ActionManager uses Qt's introspection to find * the matching QActions. **/ namespace QDirStat { class ActionManager { public: /** * Return the singleton instance of this class. **/ static ActionManager * instance(); /** * Add a widget tree. This does not transfer ownership of that widget * tree. The ActionManager will keep the pointer of this tree (with a * guarded pointer so it doesn't matter if it is destroyed) to search * for QActions when requested. **/ void addWidgetTree( QObject * tree ); /** * Search the known widget trees for the first QAction with the Qt * object name 'actionName'. Return 0 if there is no such QAction. **/ QAction * action( const QString & actionName ); /** * Add all the actions in 'actionNames' to a menu. Return 'true' if * success, 'false' if any of the actions were not found. * * If an action name in actionNames starts with "---", a separator is * added to the menu instead of an action. **/ bool addActions( QMenu * menu, const QStringList & actionNames ); protected: /** * Constructor. Protected because this is a singleton class. * Use instance() instead. **/ ActionManager() {} // // Data members // static ActionManager * _instance; QList > _widgetTrees; }; // class ActionManager } // namespace QDirStat #endif // ActionManager_h qdirstat-1.4/src/BucketsTableModel.cpp000066400000000000000000000067121311502036700200410ustar00rootroot00000000000000/* * File name: BucketsTableModel.h * Summary: Data model for buckets table * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "BucketsTableModel.h" #include "HistogramView.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; BucketsTableModel::BucketsTableModel( QWidget * parent, HistogramView * histogram ): QAbstractTableModel( parent ), _histogram( histogram ) { // logDebug() << "init" << endl; } BucketsTableModel::~BucketsTableModel() { // logDebug() << "destroying" << endl; } void BucketsTableModel::reset() { beginResetModel(); endResetModel(); } int BucketsTableModel::rowCount( const QModelIndex & parent ) const { return parent.isValid() ? 0 : _histogram->bucketCount(); } int BucketsTableModel::columnCount( const QModelIndex & parent ) const { Q_UNUSED( parent ); return ColCount; } QVariant BucketsTableModel::data( const QModelIndex & index, int role ) const { if ( ! index.isValid() ) return QVariant(); switch ( role ) { case Qt::DisplayRole: { int row = index.row(); if ( row < 0 || row >= _histogram->bucketCount() ) return QVariant(); QString result; switch ( index.column() ) { case StartCol: result = formatSize( _histogram->bucketStart( row ) ); break; case EndCol: result = formatSize( _histogram->bucketEnd ( row ) ); break; case ValueCol: result = QString::number( _histogram->bucket( row ) ); break; default: return QVariant(); } return " " + result + " "; // Maintain some margin } case Qt::TextAlignmentRole: return (int) Qt::AlignVCenter | Qt::AlignRight; default: return QVariant(); } /*NOTREACHED*/ return QVariant(); } QVariant BucketsTableModel::headerData( int section, Qt::Orientation orientation, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( orientation == Qt::Horizontal ) { QString result; switch ( section ) { case StartCol: result = tr( "Start" ); break; case EndCol: result = tr( "End" ); break; case ValueCol: result = tr( "Files" ); break; default: return QVariant(); } return " " + result + " "; // Maintain some margin } else { if ( section < _histogram->bucketCount() ) return " " + QString::number( section + 1 ) + " "; else return QVariant(); } case Qt::TextAlignmentRole: { if ( orientation == Qt::Horizontal ) return (int) Qt::AlignVCenter | Qt::AlignHCenter; else return (int) Qt::AlignVCenter | Qt::AlignRight; } default: return QVariant(); } } Qt::ItemFlags BucketsTableModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = QAbstractTableModel::flags( index ); flags |= Qt::ItemIsSelectable; return flags; } qdirstat-1.4/src/BucketsTableModel.h000066400000000000000000000042501311502036700175010ustar00rootroot00000000000000/* * File name: BucketsTableModel.h * Summary: Data model for buckets table * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef BucketsTableModel_h #define BucketsTableModel_h #include namespace QDirStat { class HistogramView; /** * Data model for the buckets table in the file size statistics window. * This displays the data of that window's histogram view in a table. **/ class BucketsTableModel: public QAbstractTableModel { Q_OBJECT public: enum Column { StartCol, EndCol, ValueCol, ColCount }; /** * Constructor. **/ BucketsTableModel( QWidget * parent, HistogramView * histogram ); /** * Destructor. **/ virtual ~BucketsTableModel(); /** * Return the associated histogram view. **/ HistogramView * histogram() const { return _histogram; } /** * Notification that data in the histogram have been reset. **/ void reset(); // // Overloaded model methods // /** * Return the number of rows (direct tree children) for 'parent'. **/ virtual int rowCount ( const QModelIndex & parent ) const Q_DECL_OVERRIDE; /** * Return the number of columns for 'parent'. **/ virtual int columnCount( const QModelIndex & parent ) const Q_DECL_OVERRIDE; /** * Return data to be displayed for the specified model index and role. **/ virtual QVariant data( const QModelIndex & index, int role ) const Q_DECL_OVERRIDE; /** * Return header data for the specified section. **/ virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const Q_DECL_OVERRIDE; /** * Return item flags for the specified model index. This specifies if * the item can be selected, edited etc. **/ virtual Qt::ItemFlags flags( const QModelIndex &index ) const Q_DECL_OVERRIDE; protected: HistogramView * _histogram; }; } #endif // BucketsTableModel_h qdirstat-1.4/src/Cleanup.cpp000066400000000000000000000270741311502036700161030ustar00rootroot00000000000000/* * File name: Cleanup.cpp * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include "Cleanup.h" #include "FileInfo.h" #include "DirTree.h" #include "DirSaver.h" #include "OutputWindow.h" #include "Process.h" #include "Logger.h" #include "Exception.h" #define SIMULATE_COMMAND 1 #define WAIT_TIMEOUT_MILLISEC 30000 using namespace QDirStat; Cleanup::Cleanup( QString command, QString title, QObject * parent ): QAction( title, parent ), _command( command ), _title( title ) { _active = true; _worksForDir = true; _worksForFile = true; _worksForDotEntry = false; _recurse = false; _askForConfirmation = false; _refreshPolicy = RefreshThis; _outputWindowPolicy = ShowAfterTimeout; _outputWindowTimeout = 500; _outputWindowAutoClose = false; QAction::setEnabled( true ); } void Cleanup::setTitle( const QString &title ) { _title = title; QAction::setText( _title ); } void Cleanup::setIcon( const QString & iconName ) { _iconName = iconName; QAction::setIcon( QPixmap( _iconName ) ); } bool Cleanup::worksFor( FileInfo *item ) const { if ( ! _active || ! item ) return false; if ( item->isDotEntry() ) return worksForDotEntry(); if ( item->isDir() ) return worksForDir(); return worksForFile(); } void Cleanup::execute( FileInfo *item, OutputWindow * outputWindow ) { if ( worksFor( item ) ) { DirTree * tree = item->tree(); executeRecursive( item, outputWindow ); switch ( _refreshPolicy ) { case NoRefresh: // Do nothing (by definition). break; case RefreshThis: case RefreshParent: // Done from CleanupCollection::execute() via a Refresher // object that is triggered by the // OutputWindow::lastProcessFinished() signal. // // Nothing left to do here. break; case AssumeDeleted: // Assume the cleanup action has deleted the item. // Modify the DirTree accordingly. tree->deleteSubtree( item ); break; } } } void Cleanup::executeRecursive( FileInfo *item, OutputWindow * outputWindow ) { if ( worksFor( item ) ) { if ( _recurse ) { // Recurse into all subdirectories. FileInfo * subdir = item->firstChild(); while ( subdir ) { if ( subdir->isDir() ) { /** * Recursively execute in this subdirectory, but only if it * really is a directory: File children might have been * reparented to the directory (normally, they reside in * the dot entry) if there are no real subdirectories on * this directory level. **/ executeRecursive( subdir, outputWindow ); } subdir = subdir->next(); } } // Perform cleanup for this directory. runCommand( item, _command, outputWindow ); } } const QString Cleanup::itemDir( const FileInfo *item ) const { QString dir = item->url(); if ( ! item->isDir() && ! item->isDotEntry() ) { dir.replace ( QRegExp ( "/[^/]*$" ), "" ); } return dir; } QString Cleanup::cleanTitle() const { // Use the cleanup action's title, if possible. QString title = _title; if ( title.isEmpty() ) title = _command; // Get rid of any "&" characters in the text that denote keyboard // shortcuts in menus. title.replace( QRegExp( "&" ), "" ); return title; } QString Cleanup::expandVariables( const FileInfo * item, const QString & unexpanded ) const { QString expanded = expandDesktopSpecificApps( unexpanded ); QString dirName = ""; if ( item->isDir() ) dirName = item->url(); else if ( item->parent() ) dirName = item->parent()->url(); expanded.replace( "%p", quoted( escaped( item->url() ) ) ); expanded.replace( "%n", quoted( escaped( item->name() ) ) ); if ( ! dirName.isEmpty() ) expanded.replace( "%d", quoted( escaped( dirName ) ) ); // logDebug() << "Expanded: \"" << expanded << "\"" << endl; return expanded; } QString Cleanup::quoted( const QString & unquoted) const { return "'" + unquoted + "'"; } QString Cleanup::escaped( const QString & unescaped ) const { QString escaped = unescaped; // Escape single quote characters (') in the string. // // While any sane person would expect this should be done with a backslash // in front of the single quote, i.e. \', this is not how shells do it. // Instead, you have to terminate the string with one single quote, then // put the single quote in a new quoted string that, but this time using // double quotes, and finally reopen the original string with another // single quote. // // Thus, 'Don't do this' becomes 'Don'"'"'t do this'. // // This does not exactly become any prettier with the C compiler requiring // a backslash for an embedded double quote. escaped.replace( "'", "'\\''" ); return escaped; } QString Cleanup::chooseShell( OutputWindow * outputWindow ) const { QString errMsg; QString shell = this->shell(); if ( ! shell.isEmpty() ) { logDebug() << "Using custom shell " << shell << endl; if ( ! isExecutable( shell ) ) { errMsg = tr( "ERROR: Shell %1 is not executable" ).arg( shell ); shell = defaultShell(); if ( ! shell.isEmpty() ) errMsg += "\n" + tr( "Using fallback %1" ).arg( shell ); } } if ( shell.isEmpty() ) { shell = defaultShell(); logDebug() << "No custom shell configured - using " << shell << endl; } if ( ! errMsg.isEmpty() ) { outputWindow->show(); // Show error regardless of user settings outputWindow->addStderr( errMsg ); } return shell; } void Cleanup::runCommand( const FileInfo * item, const QString & command, OutputWindow * outputWindow ) const { QString shell = chooseShell( outputWindow ); if ( shell.isEmpty() ) { outputWindow->show(); // Regardless of user settings outputWindow->addStderr( tr( "No usable shell - aborting cleanup action" ) ); logError() << "ERROR: No usable shell" << endl; return; } QString cleanupCommand( expandVariables( item, command )); Process * process = new Process( parent() ); CHECK_NEW( process ); process->setProgram( shell ); process->setArguments( QStringList() << "-c" << cleanupCommand ); process->setWorkingDirectory( itemDir( item ) ); // logDebug() << "New process \"" << process << endl; outputWindow->addProcess( process ); // The CleanupCollection will take care about refreshing if this is // configured for this cleanup. } QMap Cleanup::refreshPolicyMapping() { QMap mapping; mapping[ NoRefresh ] = "NoRefresh"; mapping[ RefreshThis ] = "RefreshThis"; mapping[ RefreshParent ] = "RefreshParent"; mapping[ AssumeDeleted ] = "AssumeDeleted"; return mapping; } QMap Cleanup::outputWindowPolicyMapping() { QMap mapping; mapping[ ShowAlways ] = "ShowAlways"; mapping[ ShowIfErrorOutput ] = "ShowIfErrorOutput"; mapping[ ShowAfterTimeout ] = "ShowAfterTimeout"; mapping[ ShowNever ] = "ShowNever"; return mapping; } bool Cleanup::isExecutable( const QString & programName ) { if ( programName.isEmpty() ) return false; QFileInfo fileInfo( programName ); return fileInfo.isExecutable(); } QString Cleanup::loginShell() { static bool cached = false; static QString shell; if ( ! cached ) { cached = true; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); shell = env.value( "SHELL", "" ); if ( ! isExecutable( shell ) ) { logError() << "ERROR: Shell \"" << shell << "\" is not executable" << endl; shell = ""; } } return shell; } const QStringList & Cleanup::defaultShells() { static bool cached = false; static QStringList shells; if ( ! cached ) { cached = true; QStringList candidates; candidates << loginShell() << "/bin/bash" << "/bin/sh"; foreach ( const QString & shell, candidates ) { if ( isExecutable( shell ) ) shells << shell; else if ( ! shell.isEmpty() ) { logWarning() << "Shell " << shell << " is not executable" << endl; } } if ( ! shells.isEmpty() ) logDebug() << "Default shell: " << shells.first() << endl; } if ( shells.isEmpty() ) logError() << "ERROR: No usable shell" << endl; return shells; } QString Cleanup::defaultShell() { return defaultShells().isEmpty() ? QString() : defaultShells().first(); } const QMap & Cleanup::desktopSpecificApps() { static QMap apps; if ( apps.isEmpty() ) { QString desktop = QString::fromUtf8( qgetenv( "QDIRSTAT_DESKTOP" ) ); if ( desktop.isEmpty() ) desktop = QString::fromUtf8( qgetenv( "XDG_CURRENT_DESKTOP" ) ); else { logDebug() << "Overriding $XDG_CURRENT_DESKTOP with $QDIRSTAT_DESKTOP (\"" << desktop << "\")" << endl; } if ( desktop.isEmpty() ) { logWarning() << "$XDG_CURRENT_DESKTOP is not set - using fallback apps" << endl; apps = fallbackApps(); } else { logInfo() << "Detected desktop \"" << desktop << "\"" << endl; desktop = desktop.toLower(); if ( desktop == "kde" ) { // KDE konsole misbehaves in every way possible: // // It cannot be started in the background from a cleanup action, // it will terminate when QDirStat terminates, // and it doesn't give a shit about its current working directory. // // After having wasted four hours to get that thing to cooperate, // I simply don't care any more: The other terminals will get // the & added here rather than in the cleanup command line // where it would be appropriate. All this just because KDE // konsole doesn't comply with any standards whatsoever. apps[ "%terminal" ] = "konsole --workdir %d"; apps[ "%filemanager" ] = "konqueror --profile filemanagement"; } else if ( desktop == "gnome" || desktop == "unity" ) { apps[ "%terminal" ] = "gnome-terminal &"; apps[ "%filemanager" ] = "nautilus"; } else if ( desktop == "xfce" ) { apps[ "%terminal" ] = "xfce4-terminal &"; apps[ "%filemanager" ] = "thunar"; } else if ( desktop == "lxde" ) { apps[ "%terminal" ] = "lxterminal &"; apps[ "%filemanager" ] = "pcmanfm"; } else if ( desktop == "enlightenment" ) { apps[ "%terminal" ] = "eterm &"; apps[ "%filemanager" ] = "xdg-open"; } if ( apps.isEmpty() ) { logWarning() << "No mapping available for this desktop - using fallback apps" << endl; apps = fallbackApps(); } } for ( QMap::const_iterator it = apps.constBegin(); it != apps.constEnd(); ++it ) { logInfo() << it.key() << " => \"" << it.value() << "\"" << endl; } } return apps; } const QMap & Cleanup::fallbackApps() { static QMap apps; if ( apps.isEmpty() ) { #ifdef Q_OS_MAC apps[ "%terminal" ] = "open -a Terminal.app ."; apps[ "%filemanager" ] = "open"; #else apps[ "%terminal" ] = "xterm"; apps[ "%filemanager" ] = "xdg-open"; #endif } return apps; } QString Cleanup::expandDesktopSpecificApps( const QString & unexpanded ) const { QString expanded = unexpanded; const QMap & apps = desktopSpecificApps(); for ( QMap::const_iterator it = apps.constBegin(); it != apps.constEnd(); ++it ) { expanded.replace( it.key(), it.value() ); } return expanded; } qdirstat-1.4/src/Cleanup.h000066400000000000000000000337241311502036700155470ustar00rootroot00000000000000/* * File name: Cleanup.h * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Cleanup_h #define Cleanup_h #include #include #include class OutputWindow; namespace QDirStat { class FileInfo; /** * Cleanup action to be performed for DirTree items. **/ class Cleanup: public QAction { Q_OBJECT public: enum RefreshPolicy { NoRefresh, RefreshThis, RefreshParent, AssumeDeleted }; enum OutputWindowPolicy { ShowAlways, ShowIfErrorOutput, ShowAfterTimeout, // This includes ShowIfErrorOutput ShowNever }; /** * Constructor. * * 'title' is the human readable menu title. * 'command' is the shell command to execute. **/ Cleanup( QString command = "", QString title = "", QObject * parent = 0 ); /** * Return the command line that will be executed upon calling * Cleanup::execute(). This command line may contain %p for the * complete path of the directory or file concerned or %n for the pure * file or directory name without path. **/ const QString & command() const { return _command; } /** * Return the user title of this command as displayed in menus. * This may include '&' characters for keyboard shortcuts. * See also @ref cleanTitle() . **/ const QString & title() const { return _title; } /** * Return the cleanup action's title without '&' keyboard shortcuts. * Uses the ID as fallback if the name is empty. **/ QString cleanTitle() const; /** * Return the icon name of this cleanup action. **/ QString iconName() const { return _iconName; } /** * Return whether or not this cleanup action is generally active. **/ bool active() const { return _active; } /** * Return whether or not this cleanup action works for this particular * FileInfo. Checks all the other conditions (active(), * worksForDir(), worksForFile(), ...) accordingly. **/ bool worksFor( FileInfo * item ) const; /** * Return whether or not this cleanup action works for directories, * i.e. whether or not @ref Cleanup::execute() will be successful if * the object passed is a directory. **/ bool worksForDir() const { return _worksForDir; } /** * Return whether or not this cleanup action works for plain files. **/ bool worksForFile() const { return _worksForFile; } /** * Return whether or not this cleanup action works for QDirStat's * special '' items, i.e. the pseudo nodes created in most * directories that hold the plain files. **/ bool worksForDotEntry() const { return _worksForDotEntry; } /** * Return whether or not the cleanup action should be performed * recursively in subdirectories of the initial FileInfo. **/ bool recurse() const { return _recurse; } /** * Return whether or not this cleanup should ask the user for * confirmation when it is executed. * * The default is 'false'. Use with caution - not only can this become * very annoying, people also tend to automatically click on 'OK' when * too many confirmation dialogs pop up! **/ bool askForConfirmation() const { return _askForConfirmation; } /** * Return the shell to use to invoke the command of this cleanup. * If this is is empty, use defaultShells().first(). * * Regardless of which shell is used, the command is always started * with the shell and the "-c" option. **/ QString shell() const { return _shell; } /** * Return the full path name to the user's login shell. * The $SHELL environment variable is used to obtain this value. * If this is empty, this defaults to defaultShells().first(). **/ static QString loginShell(); /** * Return the full paths to the available (and executable) shells: * loginShell() ($SHELL) * /bin/bash * /bin/sh **/ static const QStringList & defaultShells(); /** * Return the first default shell or an empty string if there is no * usable shell at all. **/ static QString defaultShell(); /** * Return 'true' if programName is non-empty and executable. **/ static bool isExecutable( const QString & programName ); /** * Return the refresh policy of this cleanup action - i.e. the action * to perform after each call to Cleanup::execute(). This is supposed * to bring the corresponding DirTree back into sync after the cleanup * action - the underlying file tree might have changed due to that * cleanup action. * * NoRefresh: Don't refresh anything. Assume nothing has changed. * This is the default. * * RefreshThis: Refresh the DirTree from the item on that was passed * to Cleanup::execute(). * * RefreshParent: Refresh the DirTree from the parent of the item on * that was passed to Cleanup::execute(). If there is no such parent, * refresh the entire tree. * * AssumeDeleted: Do not actually refresh the DirTree. Instead, * blindly assume the cleanup action has deleted the item that was * passed to Cleanup::execute() and delete the corresponding subtree * in the DirTree accordingly. This will work well for most deleting * actions as long as they can be performed without problems. If there * are any problems, however, the DirTree might easily run out of sync * with the directory tree: The DirTree will show the subtree as * deleted (i.e. it will not show it any more), but it still exists on * disk. This is the tradeoff to a very quick response. On the other * hand, the user can easily at any time hit one of the explicit * refresh buttons and everything will be back into sync again. **/ enum RefreshPolicy refreshPolicy() const { return _refreshPolicy; } /** * Return the policy when an output window (see also OutputWindow) for * this clean action is shown. Since cleanup actions start shell * commands, the output of those shell commands might be important, * especially if they report an error. In addition to that, if a * cleanup action takes a while, it might be a good idea to show the * user what is going on. Notice that there will always be only one * output window for all cleanup tasks that are to be started in one * user action; if multiple items are selected, the corresponding * command will be started for each of the selected items individually * one after another, but the output window will remain open and * collect the output of each one. Likewise, if a command is recursive, * it is started for each directory level, and the output is also * collected in the same output window. * * Possible values: * * ShowAlways: Always open an output window. This makes sense for * cleanup actions that take a while, like compressing files, recoding * videos, recompressing JPG images. * * ShowIfErrorOutput: Leave the output window hidden, but open it if * there is any error output (i.e. output on its stderr channel). This * is useful for most cleanup tasks that are typically quick, but that * might also go wrong - for example, due to insufficient permissions * in certain directories. * * ShowAfterTimeout: (This includes ShowIfErrorOutput) Leave the output * window hidden for a certain timeout (3 seconds by default), but open * it if it takes any longer than that. If there is error output, it is * opened immediately. This is the default and recommended setting. The * output can be configured with setOutputWindowTimeout(). * * ShowNever: Never show the output window, no matter how long the * cleanup task takes or if there is any amount of error output, or * even if the cleanup process crashes or could not be started. **/ enum OutputWindowPolicy outputWindowPolicy() const { return _outputWindowPolicy; } /** * Return the timeout (in milliseconds) for the ShowAfterTimeout output * window policy. The default is 0 which means to use the * OutputWindow dialog class default. **/ int outputWindowTimeout() const { return _outputWindowTimeout; } /** * Return 'true' if the output window is closed automatically when the * cleanup task is done and there was no error. **/ bool outputWindowAutoClose() const { return _outputWindowAutoClose; } /** * Return a mapping from RefreshPolicy to string. **/ static QMap refreshPolicyMapping(); /** * Return a mapping from OutputWindowPolicy to string. **/ static QMap outputWindowPolicyMapping(); /** * Return a mapping from macros to applications that may be specific * for different desktops (KDE, GNOME, Xfce, Unity, LXDE). * Incomplete list: * * %terminal * KDE: "konsole --workdir %d" * GNOME: "gnome-terminal" * Unity: "gnome-terminal" * Xfce: "xfce4-terminal" * LXDE: "lxterminal" * * %filemanager * KDE: "konqueror --profile filemanagement" // not that dumbed-down Dolphin * GNOME: "nautilus" * Unity: "nautilus" * Xfcd: "thunar" * LXDE: "pcmanfm" * * What deskop is currently used is guessed from $XDG_CURRENT_DESKTOP. **/ static const QMap & desktopSpecificApps(); /** * Return a mapping from macros to fallback applications in case the * current desktop cannot be determined: * * %terminal "xterm" * %filemanager "xdg-open" **/ static const QMap & fallbackApps(); // // Setters (see the corresponding getter for documentation) // void setTitle ( const QString & title ); void setCommand ( const QString & command) { _command = command; } void setIcon ( const QString & iconName ); void setActive ( bool active ) { _active = active; } void setWorksForDir ( bool canDo ) { _worksForDir = canDo; } void setWorksForFile ( bool canDo ) { _worksForFile = canDo; } void setWorksForDotEntry ( bool canDo ) { _worksForDotEntry = canDo; } void setRecurse ( bool recurse ) { _recurse = recurse; } void setAskForConfirmation ( bool ask ) { _askForConfirmation = ask; } void setShell ( const QString & sh ) { _shell = sh; } void setRefreshPolicy ( RefreshPolicy policy ) { _refreshPolicy = policy; } void setOutputWindowPolicy ( OutputWindowPolicy policy ) { _outputWindowPolicy = policy; } void setOutputWindowTimeout ( int timeoutMillisec ) { _outputWindowTimeout = timeoutMillisec; } void setOutputWindowAutoClose( bool autoClose ) { _outputWindowAutoClose = autoClose; } public slots: /** * The heart of the matter: Perform the cleanup with the FileInfo * specified. * * 'outputWindow' is the optional dialog to watch the commands and * their stdout and stderr output as they are executed. **/ void execute( FileInfo * item, OutputWindow * outputWindow ); protected: /** * Recursively perform the cleanup. **/ void executeRecursive( FileInfo *item, OutputWindow * outputWindow ); /** * Retrieve the directory part of a FileInfo's path. **/ const QString itemDir( const FileInfo * item ) const; /** * Choose a suitable shell. Try this->shell() and fall back to * defaultShell(). Return an empty string if no usable shell is found. **/ QString chooseShell( OutputWindow * outputWindow ) const; /** * Expand some variables in string 'unexpanded' to information from * within 'item'. Multiple expansion is performed as needed, i.e. the * string may contain more than one variable to expand. The resulting * string is returned. * * %p expands to item->path() (in single quotes), i.e. the item's * full path name. * * '/usr/local/bin' for that directory * '/usr/local/bin/doit' for a file within it * * %n expands to item->name() (in single quotes), i.e. the last * component of the pathname. The examples above would expand to: * * 'bin' * 'doit' * * %d expands to the directory name with full path. For directories, * this is the same as %p. For files or dot entries, this is the same * as their parent's %p: * * '/usr/local/bin' for a file /usr/local/bin/doit * '/usr/local/bin' for directory /usr/local/bin. * * * %terminal "konsole" or "gnome-terminal" or "xfce4-terminal" ... * * %filemanager "konqueror" or "nautilus" or "thunar" ... * * * For commands that are to be executed from within the 'Clean up' * menu, you might specify something like: * * "xdg-open %p" * "tar cjvf %n.tar.bz2 && rm -rf %n" **/ QString expandVariables ( const FileInfo * item, const QString & unexpanded ) const; /** * Expand some variables in string 'unexpanded' to application that are * typically different from one desktop (KDE, Gnome, Xfce) to the next: * * %terminal "konsole" or "gnome-terminal" or "xfce4-terminal" ... * %filemanager "konqueror" or "nautilus" or "thunar" ... **/ QString expandDesktopSpecificApps( const QString & unexpanded ) const; /** * Return a string with all occurences of a single quote escaped with * backslash. **/ QString escaped( const QString & unescaped ) const; /** * Return a string in single quotes. **/ QString quoted( const QString & unquoted ) const; /** * Run a command with 'item' as base to expand variables. **/ void runCommand( const FileInfo * item, const QString & command, OutputWindow * outputWindow) const; // // Data members // QString _command; QString _title; QString _iconName; bool _active; bool _worksForDir; bool _worksForFile; bool _worksForDotEntry; bool _recurse; bool _askForConfirmation; QString _shell; RefreshPolicy _refreshPolicy; OutputWindowPolicy _outputWindowPolicy; int _outputWindowTimeout; bool _outputWindowAutoClose; }; typedef QList CleanupList; typedef CleanupList::const_iterator CleanupListIterator; inline QTextStream & operator<< ( QTextStream & stream, const Cleanup * cleanup ) { if ( cleanup ) stream << cleanup->cleanTitle(); else stream << ""; return stream; } } // namespace QDirStat #endif // ifndef Cleanup_h qdirstat-1.4/src/CleanupCollection.cpp000066400000000000000000000364231311502036700201150ustar00rootroot00000000000000/* * File name: CleanupCollection.cpp * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "CleanupCollection.h" #include "Cleanup.h" #include "StdCleanup.h" #include "Settings.h" #include "SettingsHelpers.h" #include "SelectionModel.h" #include "OutputWindow.h" #include "Refresher.h" #include "Logger.h" #include "Exception.h" #define MAX_URLS_IN_CONFIRMATION_POPUP 7 using namespace QDirStat; CleanupCollection::CleanupCollection( SelectionModel * selectionModel, QObject * parent ): QObject( parent ), _selectionModel( selectionModel ), _listMover( _cleanupList ) { readSettings(); // Just initialize to show the current status in the log; // the contents are cached anyway. (void) Cleanup::desktopSpecificApps(); if ( _cleanupList.isEmpty() ) addStdCleanups(); updateActions(); connect( selectionModel, SIGNAL( selectionChanged() ), this, SLOT ( updateActions() ) ); } CleanupCollection::~CleanupCollection() { writeSettings(); clear(); } void CleanupCollection::add( Cleanup * cleanup ) { CHECK_PTR( cleanup ); _cleanupList << cleanup; connect( cleanup, SIGNAL( triggered() ), this, SLOT ( execute() ) ); updateMenusAndToolBars(); } void CleanupCollection::remove( Cleanup * cleanup ) { int index = indexOf( cleanup ); if ( index == -1 ) { logError() << "No such cleanup: " << cleanup << endl; return; } _cleanupList.removeAt( index ); delete cleanup; // No need for updateMenusAndToolBars() since QObject/QWidget will take care of // deleted actions all by itself. } void CleanupCollection::addStdCleanups() { foreach ( Cleanup * cleanup, StdCleanup::stdCleanups( this ) ) { add( cleanup ); } } int CleanupCollection::indexOf( Cleanup * cleanup ) const { int index = _cleanupList.indexOf( cleanup ); if ( index == -1 ) logError() << "Cleanup " << cleanup << " is not in this collection" << endl; return index; } Cleanup * CleanupCollection::at( int index ) const { if ( index >= 0 && index < _cleanupList.size() ) return _cleanupList.at( index ); else return 0; } void CleanupCollection::clear() { qDeleteAll( _cleanupList ); _cleanupList.clear(); // No need for updateMenusAndToolBars() since QObject/QWidget will take // care of deleted actions all by itself. } void CleanupCollection::updateMenusAndToolBars() { updateMenus(); updateToolBars(); } void CleanupCollection::updateActions() { FileInfoSet sel = _selectionModel->selectedItems(); bool dirSelected = sel.containsDir(); bool fileSelected = sel.containsFile(); bool dotEntrySelected = sel.containsDotEntry(); bool busy = sel.containsBusyItem(); bool treeBusy = sel.treeIsBusy(); foreach ( Cleanup * cleanup, _cleanupList ) { if ( ! cleanup->active() || sel.isEmpty() ) cleanup->setEnabled( false ); else { bool enabled = ! busy; if ( treeBusy && cleanup->refreshPolicy() != Cleanup::NoRefresh ) enabled = false; if ( dirSelected && ! cleanup->worksForDir() ) enabled = false; if ( dotEntrySelected && ! cleanup->worksForDotEntry() ) enabled = false; if ( fileSelected && ! cleanup->worksForFile() ) enabled = false; cleanup->setEnabled( enabled ); } } } void CleanupCollection::updateMenus() { _menus.removeAll( 0 ); // Remove QPointers that have become invalid foreach ( QMenu * menu, _menus ) { if ( menu ) { // Remove all Cleanups from this menu foreach ( QAction * action, menu->actions() ) { Cleanup * cleanup = dynamic_cast( action ); if ( cleanup ) menu->removeAction( cleanup ); } // Add the current cleanups in the current order addToMenu( menu ); } } } void CleanupCollection::updateToolBars() { _toolBars.removeAll( 0 ); // Remove QPointers that have become invalid foreach ( QToolBar * toolBar, _toolBars ) { if ( toolBar ) { // Remove all Cleanups from this tool bar foreach ( QAction * action, toolBar->actions() ) { Cleanup * cleanup = dynamic_cast( action ); if ( cleanup ) toolBar->removeAction( cleanup ); } // Add the current cleanups in the current order addToToolBar( toolBar ); } } } void CleanupCollection::execute() { Cleanup * cleanup = qobject_cast( sender() ); if ( ! cleanup ) { logError() << "Wrong sender type: " << sender()->metaObject()->className() << endl; return; } FileInfoSet selection = _selectionModel->selectedItems(); if ( selection.isEmpty() ) { logWarning() << "Nothing selected" << endl; return; } if ( cleanup->askForConfirmation() && ! confirmation( cleanup, selection ) ) { logDebug() << "User declined confirmation" << endl; return; } emit startingCleanup( cleanup->cleanTitle() ); OutputWindow * outputWindow = new OutputWindow( qApp->activeWindow() ); CHECK_NEW( outputWindow ); outputWindow->setAutoClose( cleanup->outputWindowAutoClose() ); switch ( cleanup->outputWindowPolicy() ) { case Cleanup::ShowAlways: outputWindow->show(); break; case Cleanup::ShowAfterTimeout: outputWindow->showAfterTimeout( cleanup->outputWindowTimeout() ); break; case Cleanup::ShowIfErrorOutput: // showOnStderr is default break; case Cleanup::ShowNever: outputWindow->setShowOnStderr( false ); break; } if ( cleanup->refreshPolicy() == Cleanup::RefreshThis || cleanup->refreshPolicy() == Cleanup::RefreshParent ) { FileInfoSet refreshSet = cleanup->refreshPolicy() == Cleanup::RefreshParent ? Refresher::parents( selection ) : selection; _selectionModel->prepareRefresh( refreshSet ); Refresher * refresher = new Refresher( refreshSet, this ); CHECK_NEW( refresher ); connect( outputWindow, SIGNAL( lastProcessFinished( int ) ), refresher, SLOT ( refresh() ) ); } connect( outputWindow, SIGNAL( lastProcessFinished( int ) ), this, SIGNAL( cleanupFinished ( int ) ) ); foreach ( FileInfo * item, selection ) { if ( cleanup->worksFor( item ) ) { cleanup->execute( item, outputWindow ); } else { logWarning() << "Cleanup " << cleanup << " does not work for " << item << endl; } } outputWindow->noMoreProcesses(); } bool CleanupCollection::confirmation( Cleanup * cleanup, const FileInfoSet & items ) { QString msg = ""; QString title = cleanup->cleanTitle(); if ( items.size() == 1 ) // The most common case { FileInfo * item = items.first(); if ( item->isDir() || item->isDotEntry() ) msg += tr( "

%1

for directory %2" ).arg( title ).arg( item->url() ); else msg += tr( "

%1

for file %2" ).arg( title ).arg( item->url() ); msg += "
"; } else // Multiple items selected { QStringList urls; bool isMixed = items.containsDir() && items.containsFile(); if ( isMixed ) { QStringList dirs = filteredUrls( items, true, false, // dibs, nonDirs true ); // extraHighlight QStringList nonDirs = filteredUrls( items, false, true ); // dirs, nonDirs dirs = dirs.mid ( 0, MAX_URLS_IN_CONFIRMATION_POPUP ); nonDirs = nonDirs.mid( 0, MAX_URLS_IN_CONFIRMATION_POPUP ); urls << dirs << "" << nonDirs; } else // ! isMixed { // Build a list of the first couple of selected items (7 max) urls = filteredUrls( items, true, true ); // dirs, nonDirs urls = urls.mid( 0, MAX_URLS_IN_CONFIRMATION_POPUP ); } if ( urls.size() < items.size() ) // Only displaying part of the items? { urls << "..."; urls << tr( "(%1 items total)" ).arg( items.size() ); } msg += tr( "

%1

for:
\n%2
" ).arg( title ).arg( urls.join( "
" ) ); } int ret = QMessageBox::question( qApp->activeWindow(), tr( "Please Confirm" ), // title msg, // text QMessageBox::Yes | QMessageBox::No ); return ret == QMessageBox::Yes; } QStringList CleanupCollection::filteredUrls( const FileInfoSet & items, bool dirs, bool nonDirs, bool extraHighlight ) const { QStringList urls; for ( FileInfoSet::const_iterator it = items.begin(); it != items.end(); ++it ) { if ( ( dirs && (*it)->isDir() ) || ( nonDirs && ! (*it)->isDir() ) ) { QString name = (*it)->url(); if ( (*it)->isDir() ) { if ( extraHighlight ) urls << tr( "Directory %1" ).arg( name ); else urls << tr( "Directory %1" ).arg( name ); } else urls << name; } } return urls; } void CleanupCollection::addToMenu( QMenu * menu, bool keepUpdated ) { CHECK_PTR( menu ); foreach ( Cleanup * cleanup, _cleanupList ) { if ( cleanup->active() ) menu->addAction( cleanup ); } if ( keepUpdated && ! _menus.contains( menu ) ) _menus << menu; } void CleanupCollection::addToToolBar( QToolBar * toolBar, bool keepUpdated ) { CHECK_PTR( toolBar ); foreach ( Cleanup * cleanup, _cleanupList ) { if ( cleanup->active() && ! cleanup->icon().isNull() ) { // Add only cleanups that have an icon to avoid overcrowding the // toolbar with actions that only have a text. toolBar->addAction( cleanup ); } } if ( keepUpdated && ! _toolBars.contains( toolBar ) ) _toolBars << toolBar; } void CleanupCollection::moveUp( Cleanup * cleanup ) { _listMover.moveUp( cleanup ); updateMenusAndToolBars(); } void CleanupCollection::moveDown( Cleanup * cleanup ) { _listMover.moveDown( cleanup ); updateMenusAndToolBars(); } void CleanupCollection::moveToTop( Cleanup * cleanup ) { _listMover.moveToTop( cleanup ); updateMenusAndToolBars(); } void CleanupCollection::moveToBottom( Cleanup * cleanup ) { _listMover.moveToBottom( cleanup ); updateMenusAndToolBars(); } void CleanupCollection::readSettings() { CleanupSettings settings; QStringList cleanupGroups = settings.findGroups( settings.groupPrefix() ); if ( ! cleanupGroups.isEmpty() ) // Keep defaults (StdCleanups) if settings empty { clear(); // Read all settings groups [Cleanup_xx] that were found foreach ( const QString & groupName, cleanupGroups ) { settings.beginGroup( groupName ); // Read one cleanup QString command = settings.value( "Command" ).toString(); QString title = settings.value( "Title" ).toString(); QString iconName = settings.value( "Icon" ).toString(); QString hotkey = settings.value( "Hotkey" ).toString(); QString shell = settings.value( "Shell" ).toString(); bool active = settings.value( "Active" , true ).toBool(); bool worksForDir = settings.value( "WorksForDir" , true ).toBool(); bool worksForFile = settings.value( "WorksForFile" , true ).toBool(); bool worksForDotEntry = settings.value( "WorksForDotEntry" , true ).toBool(); bool recurse = settings.value( "Recurse" , false ).toBool(); bool askForConfirmation = settings.value( "AskForConfirmation" , false ).toBool(); bool outputWindowAutoClose = settings.value( "OutputWindowAutoClose", false ).toBool(); int outputWindowTimeout = settings.value( "OutputWindowTimeout" , 0 ).toInt(); int refreshPolicy = readEnumEntry( settings, "RefreshPolicy", Cleanup::NoRefresh, Cleanup::refreshPolicyMapping() ); int outputWindowPolicy = readEnumEntry( settings, "OutputWindowPolicy", Cleanup::ShowAfterTimeout, Cleanup::outputWindowPolicyMapping() ); if ( ! command.isEmpty() && ! title.isEmpty() ) { Cleanup * cleanup = new Cleanup( command, title, this ); CHECK_NEW( cleanup ); add( cleanup ); cleanup->setActive ( active ); cleanup->setWorksForDir ( worksForDir ); cleanup->setWorksForFile ( worksForFile ); cleanup->setWorksForDotEntry( worksForDotEntry ); cleanup->setRecurse ( recurse ); cleanup->setShell ( shell ); cleanup->setAskForConfirmation ( askForConfirmation ); cleanup->setOutputWindowAutoClose( outputWindowAutoClose ); cleanup->setOutputWindowTimeout ( outputWindowTimeout ); cleanup->setRefreshPolicy ( static_cast( refreshPolicy ) ); cleanup->setOutputWindowPolicy( static_cast( outputWindowPolicy ) ); if ( ! iconName.isEmpty() ) cleanup->setIcon( iconName ); if ( ! hotkey.isEmpty() ) cleanup->setShortcut( hotkey ); // if ( ! shell.isEmpty() ) // logDebug() << "Using custom shell " << shell << " for " << cleanup << endl; } else { logError() << "Need at least Command and Title for a cleanup" << endl; } settings.endGroup(); // [Cleanup_01], [Cleanup_02], ... } } } void CleanupCollection::writeSettings() { CleanupSettings settings; // Remove all leftover cleanup descriptions settings.removeGroups( settings.groupPrefix() ); // Using a separate group for each cleanup for better readability in the // file. // // Settings arrays are hard to read and to edit if there are more than, // say, 2-3 entries for each array index. Plus, a user editing the file // would have to take care of the array count - which is very error prone. // // We are using [Cleanup_01], [Cleanup_02], ... here just because that's // easiest to generate automatically; upon reading, the numbers are // irrelevant. It's just important that each group name is // unique. readSettings() will happily pick up any group that starts with // "Cleanup_". for ( int i=0; i < _cleanupList.size(); ++i ) { QString groupName; groupName.sprintf( "Cleanup_%02d", i+1 ); settings.beginGroup( groupName ); Cleanup * cleanup = _cleanupList.at(i); settings.setValue( "Command" , cleanup->command() ); settings.setValue( "Title" , cleanup->title() ); settings.setValue( "Active" , cleanup->active() ); settings.setValue( "WorksForDir" , cleanup->worksForDir() ); settings.setValue( "WorksForFile" , cleanup->worksForFile() ); settings.setValue( "WorksForDotEntry" , cleanup->worksForDotEntry() ); settings.setValue( "Recurse" , cleanup->recurse() ); settings.setValue( "AskForConfirmation" , cleanup->askForConfirmation() ); settings.setValue( "OutputWindowAutoClose", cleanup->outputWindowAutoClose() ); if ( cleanup->outputWindowTimeout() > 0 ) settings.setValue( "OutputWindowTimeout" , cleanup->outputWindowTimeout() ); writeEnumEntry( settings, "RefreshPolicy", cleanup->refreshPolicy(), Cleanup::refreshPolicyMapping() ); writeEnumEntry( settings, "OutputWindowPolicy", cleanup->outputWindowPolicy(), Cleanup::outputWindowPolicyMapping() ); if ( ! cleanup->shell().isEmpty() ) settings.setValue( "Shell", cleanup->shell() ); if ( ! cleanup->iconName().isEmpty() ) settings.setValue( "Icon", cleanup->iconName() ); if ( ! cleanup->shortcut().isEmpty() ) settings.setValue( "Hotkey" , cleanup->shortcut().toString() ); settings.endGroup(); // [Cleanup_01], [Cleanup_02], ... } } qdirstat-1.4/src/CleanupCollection.h000066400000000000000000000121161311502036700175530ustar00rootroot00000000000000/* * File name: CleanupCollection.h * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef CleanupCollection_h #define CleanupCollection_h #include #include #include #include #include "ListMover.h" #include "Cleanup.h" class QMenu; class QToolBar; namespace QDirStat { class SelectionModel; class FileInfoSet; /** * Set of Cleanup actions to be performed for DirTree items, consisting of * a number of predefined and a number of user-defined cleanups. **/ class CleanupCollection: public QObject { Q_OBJECT public: /** * Constructor. **/ CleanupCollection( SelectionModel * selectionModel, QObject * parent = 0 ); /** * Destructor **/ virtual ~CleanupCollection(); /** * Add the standard cleanups to this collection. **/ void addStdCleanups(); /** * Add a cleanup to this collection. The collection assumes ownerwhip * of this cleanup. **/ void add( Cleanup * cleanup ); /** * Remove a cleanup from this collection and delete it. **/ void remove( Cleanup * cleanup ); /** * Add all actions to the specified menu. * * If 'keepUpdated' is false, the cleanup collection will keep the * pointer to the menu (as guarded pointer, so it may safely be * deleted) and update the menu whenever cleanups are added, removed, * or reordered. That means that for every such operation, all cleanups * in the menu will be removed and added to the end of the menu in the * current order of the cleanup collection. **/ void addToMenu( QMenu * menu, bool keepUpdated = false ); /** * Add all actions that have an icon to the specified tool bar. * The semantics of 'keepUpdated' are analog to addToMenu(). **/ void addToToolBar( QToolBar * toolBar, bool keepUpdated = false ); /** * Return the index of a cleanup or -1 if it is not part of this * collection. **/ int indexOf( Cleanup * cleanup ) const; /** * Return the cleanup with the specified index or 0 if the index is out * of range. **/ Cleanup * at( int index ) const; /** * Return the number of cleanup actions in this collection. **/ int size() const { return _cleanupList.size(); } /** * Return 'true' if this collection is empty. **/ bool isEmpty() const { return _cleanupList.isEmpty(); } /** * Remove all cleanups from this collection. **/ void clear(); /** * Return the internal cleanup list. **/ const CleanupList & cleanupList() const { return _cleanupList; } /** * Return the ListMover for this object that takes care of moving * cleanups up, down, to the top, or to the bottom of this cleanup * list. **/ ListMover * listMover() { return &_listMover; } signals: /** * Emitted when a cleanup is started. **/ void startingCleanup( const QString & cleanupName ); /** * Emitted when the last process of a cleanup is finished. * * 'errorCount' is the total number of errors reported by all processes * that were started. **/ void cleanupFinished( int errorCount ); public slots: /** * Update the enabled/disabled state of all cleanup actions depending * on the SelectionModel. **/ void updateActions(); /** * Move a cleanup one position up in the list. **/ void moveUp( Cleanup * cleanup ); /** * Move a cleanup one position down in the list. **/ void moveDown( Cleanup * cleanup ); /** * Move a cleanup to the top of the list. **/ void moveToTop( Cleanup * cleanup ); /** * Move a cleanup to the bottom of the list. **/ void moveToBottom( Cleanup * cleanup ); /** * Read configuration for all cleanups. **/ void readSettings(); /** * Write configuration for all cleanups. **/ void writeSettings(); protected slots: /** * Execute a cleanup. This uses sender() to find out which cleanup it * was. **/ void execute(); protected: /** * Ask user for confirmation to execute a cleanup action for * 'items'. Returns 'true' if user accepts, 'false' otherwise. **/ bool confirmation( Cleanup * cleanup, const FileInfoSet & items ); /** * Return the URLs for the selected item types in 'items': * Directories, non-directories, or both. * * 'extraHighlight' indicates that some very strong extra highlighting * should be done to mark directories. **/ QStringList filteredUrls( const FileInfoSet & items, bool dirs, bool nonDirs, bool extraHighlight = false ) const; /** * Update all menus that have the 'keepUpdated' flag set. **/ void updateMenus(); /** * Update all tool bars that have the 'keepUpdated' flag set. **/ void updateToolBars(); /** * Update all menus that have the 'keepUpdated' flag set. **/ void updateMenusAndToolBars(); // // Data members // SelectionModel * _selectionModel; CleanupList _cleanupList; ListMover _listMover; QList > _menus; QList > _toolBars; }; } // namespace QDirStat #endif // ifndef CleanupCollection_h qdirstat-1.4/src/CleanupConfigPage.cpp000066400000000000000000000150141311502036700200150ustar00rootroot00000000000000/* * File name: CleanupConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "CleanupConfigPage.h" #include "CleanupCollection.h" #include "Cleanup.h" #include "SettingsHelpers.h" #include "Logger.h" #include "Exception.h" #define DEFAULT_OUTPUT_WINDOW_SHOW_TIMEOUT 500 // This is a mess that became necessary because Qt's moc cannot handle template // classes. Yes, this is ugly. #define CLEANUP_CAST(VOID_PTR) (static_cast(VOID_PTR)) using namespace QDirStat; CleanupConfigPage::CleanupConfigPage( QWidget * parent ): ListEditor( parent ), _ui( new Ui::CleanupConfigPage ), _cleanupCollection( 0 ) { CHECK_NEW( _ui ); _ui->setupUi( this ); setListWidget( _ui->listWidget ); setMoveUpButton ( _ui->moveUpButton ); setMoveDownButton ( _ui->moveDownButton ); setMoveToTopButton ( _ui->moveToTopButton ); setMoveToBottomButton( _ui->moveToBottomButton ); setAddButton ( _ui->addButton ); setRemoveButton ( _ui->removeButton ); connect( _ui->titleLineEdit, SIGNAL( textChanged ( QString ) ), this, SLOT ( titleChanged( QString ) ) ); } CleanupConfigPage::~CleanupConfigPage() { // logDebug() << "CleanupConfigPage destructor" << endl; } void CleanupConfigPage::setCleanupCollection( CleanupCollection * collection ) { _cleanupCollection = collection; } void CleanupConfigPage::setup() { fillListWidget(); _ui->toolBox->setCurrentIndex( 0 ); updateActions(); } void CleanupConfigPage::applyChanges() { logDebug() << endl; save( value( listWidget()->currentItem() ) ); _cleanupCollection->writeSettings(); } void CleanupConfigPage::discardChanges() { logDebug() << endl; listWidget()->clear(); _cleanupCollection->clear(); _cleanupCollection->addStdCleanups(); _cleanupCollection->readSettings(); } void CleanupConfigPage::fillListWidget() { CHECK_PTR( _cleanupCollection ); listWidget()->clear(); foreach ( Cleanup * cleanup, _cleanupCollection->cleanupList() ) { QListWidgetItem * item = new ListEditorItem( cleanup->cleanTitle(), cleanup ); CHECK_NEW( item ); listWidget()->addItem( item ); } QListWidgetItem * firstItem = listWidget()->item(0); if ( firstItem ) listWidget()->setCurrentItem( firstItem ); } void CleanupConfigPage::titleChanged( const QString & newTitle ) { QListWidgetItem * currentItem = listWidget()->currentItem(); if ( currentItem ) { Cleanup * cleanup = CLEANUP_CAST( value( currentItem ) ); cleanup->setTitle( newTitle ); currentItem->setText( cleanup->cleanTitle() ); } } void CleanupConfigPage::save( void * value ) { Cleanup * cleanup = CLEANUP_CAST( value ); // logDebug() << cleanup << endl; if ( ! cleanup || updatesLocked() ) return; cleanup->setActive ( _ui->activeGroupBox->isChecked() ); cleanup->setTitle ( _ui->titleLineEdit->text() ); cleanup->setCommand( _ui->commandLineEdit->text() ); if ( _ui->shellComboBox->currentText().startsWith( "$SHELL" ) ) cleanup->setShell( "" ); else cleanup->setShell( _ui->shellComboBox->currentText() ); cleanup->setRecurse( _ui->recurseCheckBox->isChecked() ); cleanup->setAskForConfirmation( _ui->askForConfirmationCheckBox->isChecked() ); cleanup->setWorksForDir ( _ui->worksForDirCheckBox->isChecked() ); cleanup->setWorksForFile ( _ui->worksForFilesCheckBox->isChecked() ); cleanup->setWorksForDotEntry ( _ui->worksForDotEntriesCheckBox->isChecked() ); int policy = _ui->outputWindowPolicyComboBox->currentIndex(); cleanup->setOutputWindowPolicy( static_cast( policy ) ); int timeout = qRound( _ui->outputWindowTimeoutSpinBox->value() * 1000.0 ); if ( timeout == DEFAULT_OUTPUT_WINDOW_SHOW_TIMEOUT ) // FIXME: Get this from OutputWindow timeout = 0; cleanup->setOutputWindowTimeout( timeout ); cleanup->setOutputWindowAutoClose( _ui->outputWindowAutoCloseCheckBox->isChecked() ); policy = _ui->refreshPolicyComboBox->currentIndex(); cleanup->setRefreshPolicy( static_cast( policy ) ); } void CleanupConfigPage::load( void * value ) { Cleanup * cleanup = CLEANUP_CAST( value ); // logDebug() << cleanup << endl; if ( ! cleanup || updatesLocked() ) return; _ui->activeGroupBox->setChecked( cleanup->active() ); _ui->titleLineEdit->setText( cleanup->title() ); _ui->commandLineEdit->setText( cleanup->command() ); if ( cleanup->shell().isEmpty() ) _ui->shellComboBox->setCurrentIndex( 0 ); else _ui->shellComboBox->setEditText( cleanup->shell() ); _ui->recurseCheckBox->setChecked ( cleanup->recurse() ); _ui->askForConfirmationCheckBox->setChecked( cleanup->askForConfirmation() ); _ui->worksForDirCheckBox->setChecked ( cleanup->worksForDir() ); _ui->worksForFilesCheckBox->setChecked ( cleanup->worksForFile() ); _ui->worksForDotEntriesCheckBox->setChecked( cleanup->worksForDotEntry() ); _ui->outputWindowPolicyComboBox->setCurrentIndex( cleanup->outputWindowPolicy() ); int timeout = cleanup->outputWindowTimeout(); if ( timeout == 0 ) timeout = DEFAULT_OUTPUT_WINDOW_SHOW_TIMEOUT; // FIXME: Get this from OutputWindow _ui->outputWindowTimeoutSpinBox->setValue( timeout / 1000.0 ); _ui->outputWindowAutoCloseCheckBox->setChecked( cleanup->outputWindowAutoClose() ); _ui->refreshPolicyComboBox->setCurrentIndex( cleanup->refreshPolicy() ); } void * CleanupConfigPage::createValue() { Cleanup * cleanup = new Cleanup(); CHECK_NEW( cleanup ); _cleanupCollection->add( cleanup ); return cleanup; } void CleanupConfigPage::removeValue( void * value ) { Cleanup * cleanup = CLEANUP_CAST( value ); CHECK_PTR( cleanup ); _cleanupCollection->remove( cleanup ); } QString CleanupConfigPage::valueText( void * value ) { Cleanup * cleanup = CLEANUP_CAST( value ); CHECK_PTR( cleanup ); return cleanup->cleanTitle(); } QString CleanupConfigPage::deleteConfirmationMessage( void * value ) { Cleanup * cleanup = CLEANUP_CAST( value ); return tr( "Really delete cleanup \"%1\"?" ).arg( cleanup->cleanTitle() ); } void CleanupConfigPage::moveValue( void * value, const char * operation ) { Cleanup * cleanup = CLEANUP_CAST( value ); QMetaObject::invokeMethod( _cleanupCollection, operation, Qt::DirectConnection, Q_ARG( Cleanup *, cleanup ) ); } qdirstat-1.4/src/CleanupConfigPage.h000066400000000000000000000064311311502036700174650ustar00rootroot00000000000000/* * File name: CleanupConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef CleanupConfigPage_h #define CleanupConfigPage_h #include "ListEditor.h" #include "ui_cleanup-config-page.h" #include "Cleanup.h" namespace QDirStat { class CleanupCollection; /** * Configuration page (tab) for cleanups: * Edit, add, delete, reorder cleanups in the cleanup collection. **/ class CleanupConfigPage: public ListEditor { Q_OBJECT public: CleanupConfigPage( QWidget * parent = 0 ); virtual ~CleanupConfigPage(); /** * Set the CleanupCollection to work on. **/ void setCleanupCollection( CleanupCollection * collection ); /** * Return the internal CleanupCollection. **/ CleanupCollection * cleanupCollection() const { return _cleanupCollection; } public slots: /** * Populate the widgets. **/ void setup(); /** * Write changes back to the settings. **/ void applyChanges(); /** * Abandon changes and revert everything to the original settings. **/ void discardChanges(); protected slots: /** * Notification that the user changed the "Title" field of the * current cleanup. **/ void titleChanged( const QString & newTitle ); protected: /** * Fill the cleanup list widget from the cleanup collection. * * Implemented from ListEditor. **/ virtual void fillListWidget() Q_DECL_OVERRIDE; /** * Save the contents of the widgets to the specified value. * * Implemented from ListEditor. **/ virtual void save( void * value ) Q_DECL_OVERRIDE; /** * Load the content of the widgets from the specified value. * * Implemented from ListEditor. **/ virtual void load( void * value ) Q_DECL_OVERRIDE; /** * Create a new value with default values. * This is called when the 'Add' button is clicked. * * Implemented from ListEditor. **/ virtual void * createValue() Q_DECL_OVERRIDE; /** * Remove a value from the internal list and delete it. * * This is called when the 'Remove' button is clicked and the user * confirms the confirmation pop-up. * * Implemented from ListEditor. **/ virtual void removeValue( void * value ); /** * Return a text for the list item of 'value'. * * Implemented from ListEditor. **/ virtual QString valueText( void * value ) Q_DECL_OVERRIDE; /** * Return the message for the 'really delete?' message for the current * item ('value'). If this returns an empty string, the item cannot be * deleted. * * Implemented from ListEditor. **/ virtual QString deleteConfirmationMessage( void * value ) Q_DECL_OVERRIDE; /** * Move a value in the internal list. This is called from moveUp(), * moveDown() etc.; 'operation' is one of 'moveUp()', moveDown() * etc. that can be called with QMetaObject::invokeMethod(). * * Implemented from ListEditor. * * This is a kludge - a workaround of not being able to use C++ * templates. **/ virtual void moveValue( void * value, const char * operation ) Q_DECL_OVERRIDE; // // Data members // Ui::CleanupConfigPage * _ui; CleanupCollection * _cleanupCollection; }; // class CleanupConfigPage } // namespace QDirStat #endif // CleanupConfigPage_h qdirstat-1.4/src/ConfigDialog.cpp000066400000000000000000000053261311502036700170350ustar00rootroot00000000000000/* * File name: ConfigDialog.cpp * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "ConfigDialog.h" #include "CleanupConfigPage.h" #include "MimeCategoryConfigPage.h" #include "ExcludeRulesConfigPage.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; ConfigDialog::ConfigDialog( QWidget * parent ): QDialog( parent ), _ui( new Ui::ConfigDialog ) { CHECK_NEW( _ui ); _ui->setupUi( this ); _cleanupConfigPage = new CleanupConfigPage(); CHECK_NEW( _cleanupConfigPage ); _ui->pagesTabWidget->addTab( _cleanupConfigPage, tr( "Cleanup Actions" ) ); _mimeCategoryConfigPage = new MimeCategoryConfigPage(); CHECK_NEW( _mimeCategoryConfigPage ); _ui->pagesTabWidget->addTab( _mimeCategoryConfigPage, tr( "MIME Categories" ) ); _excludeRulesConfigPage = new ExcludeRulesConfigPage(); CHECK_NEW( _excludeRulesConfigPage ); _ui->pagesTabWidget->addTab( _excludeRulesConfigPage, tr( "Exclude Rules" ) ); connect( _ui->applyButton, SIGNAL( clicked() ), this, SLOT ( apply() ) ); // // Connect cleanup config page // connect( this, SIGNAL( reinit() ), _cleanupConfigPage, SLOT ( setup() ) ); connect( this, SIGNAL( applyChanges() ), _cleanupConfigPage, SLOT ( applyChanges() ) ); connect( this, SIGNAL( discardChanges() ), _cleanupConfigPage, SLOT ( discardChanges() ) ); // // Connect mime category config page // connect( this, SIGNAL( reinit() ), _mimeCategoryConfigPage, SLOT ( setup() ) ); connect( this, SIGNAL( applyChanges() ), _mimeCategoryConfigPage, SLOT ( applyChanges() ) ); connect( this, SIGNAL( discardChanges() ), _mimeCategoryConfigPage, SLOT ( discardChanges() ) ); // // Connect exclude rules config page // connect( this, SIGNAL( reinit() ), _excludeRulesConfigPage, SLOT ( setup() ) ); connect( this, SIGNAL( applyChanges() ), _excludeRulesConfigPage, SLOT ( applyChanges() ) ); connect( this, SIGNAL( discardChanges() ), _excludeRulesConfigPage, SLOT ( discardChanges() ) ); } ConfigDialog::~ConfigDialog() { // logDebug() << "ConfigDialog destructor" << endl; delete _cleanupConfigPage; delete _mimeCategoryConfigPage; delete _excludeRulesConfigPage; } void ConfigDialog::setup() { emit reinit(); } void ConfigDialog::apply() { emit applyChanges(); } void ConfigDialog::accept() { apply(); done( Accepted ); } void ConfigDialog::reject() { emit discardChanges(); done( Rejected ); } qdirstat-1.4/src/ConfigDialog.h000066400000000000000000000051571311502036700165040ustar00rootroot00000000000000/* * File name: ConfigDialog.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef ConfigDialog_h #define ConfigDialog_h #include #include "ui_config-dialog.h" namespace QDirStat { class GeneralConfigPage; class CleanupConfigPage; class MimeCategoryConfigPage; class ExcludeRulesConfigPage; /** * Configuration dialog for QDirStat. * * This class is only the wrapper for the individual config pages; it * maintains the tab widget to switch between the pages (the tabs) and the * dialog buttons ("OK", "Apply", "Cancel"). * * Each page is pretty much self-sufficient. **/ class ConfigDialog: public QDialog { Q_OBJECT public: /** * Constructor. Create the dialog and all pages. **/ ConfigDialog( QWidget * parent ); /** * Destructor. **/ virtual ~ConfigDialog(); /** * Return the cleanup config page. **/ CleanupConfigPage * cleanupConfigPage() const { return _cleanupConfigPage; } /** * Return the mime category config page. **/ MimeCategoryConfigPage * mimeCategoryConfigPage() const { return _mimeCategoryConfigPage; } public slots: /** * Notification to reinitialize and populate the widgets of config * pages. **/ void setup(); /** * Apply the changes in dialog contents, but leave the dialog open. **/ void apply(); /** * Accept the dialog contents, i.e. the user clicked the "OK" button. * * Reimplemented from QDialog. **/ virtual void accept() Q_DECL_OVERRIDE; /** * Reject the dialog contents, i.e. the user clicked the "Cancel" * button. * * Reimplemented from QDialog. **/ virtual void reject() Q_DECL_OVERRIDE; signals: /** * Emitted in setup(). * * This is the signal to reinitialize and populate the widgets of * config pages. **/ void reinit(); /** * Emitted when the "OK" or the "Apply" button was clicked: * * This is the signal to apply all changes to the settings and/or the * widgets. **/ void applyChanges(); /** * Emitted when the "Cancel" button was clicked: * * This is the signal to discard all changes and re-apply the old * settings. **/ void discardChanges(); protected: // // Data members // Ui::ConfigDialog * _ui; // GeneralConfigPage * _generalConfigPage; CleanupConfigPage * _cleanupConfigPage; MimeCategoryConfigPage * _mimeCategoryConfigPage; ExcludeRulesConfigPage * _excludeRulesConfigPage; }; // class ConfigDialog } // namespace QDirStat #endif // ConfigDialog_h qdirstat-1.4/src/DataColumns.cpp000066400000000000000000000106451311502036700167220ustar00rootroot00000000000000/* * File name: DataColumns.cpp * Summary: Data column mapping * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "DataColumns.h" #include "Settings.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; DataColumns * DataColumns::_instance = 0; DataColumns * DataColumns::instance() { if ( ! _instance ) { _instance = new DataColumns(); CHECK_NEW( _instance ); } return _instance; } DataColumns::DataColumns(): QObject() { _columns = defaultColumns(); #if 0 // Reading and writing settings for the columns has been taken over by the // HeaderTweaker which works with the DirTreeView's QHeaderView. There, the // user can choose the columns interactively, move them around, resize them // etc. without any model->reset() which would be required with the // DataColumns. readSettings(); // Write settings immediately back since the destructor of this singleton // is very likely never called. writeSettings(); #endif } const DataColumnList DataColumns::defaultColumns() const { DataColumnList columns; columns << NameCol << PercentBarCol << PercentNumCol << TotalSizeCol << OwnSizeCol << TotalItemsCol << TotalFilesCol << TotalSubDirsCol << LatestMTimeCol; return columns; } void DataColumns::readSettings() { Settings settings; settings.beginGroup( "DataColumns" ); QStringList strColList = settings.value( "Columns" ).toStringList(); settings.endGroup(); _columns = fromStringList( strColList ); if ( _columns.isEmpty() ) _columns = defaultColumns(); else _columns = fixup( _columns ); } void DataColumns::writeSettings() { Settings settings; settings.beginGroup( "DataColumns" ); settings.setValue( "Columns", toStringList( _columns ) ); settings.endGroup(); } void DataColumns::setColumns( const DataColumnList & newColumns ) { _columns = newColumns; emit columnsChanged(); } DataColumn DataColumns::mappedCol( DataColumn viewCol ) const { if ( viewCol < 0 || viewCol >= colCount() ) { logError() << "Invalid view column no.: " << viewCol << endl; return UndefinedCol; } return _columns.at( viewCol ); } DataColumn DataColumns::reverseMappedCol( DataColumn modelCol ) const { if ( modelCol < 0 || modelCol >= colCount() ) return UndefinedCol; return static_cast( _columns.indexOf( modelCol ) ); } QString DataColumns::toString( DataColumn col ) { switch ( col ) { case NameCol: return "NameCol"; case PercentBarCol: return "PercentBarCol"; case PercentNumCol: return "PercentNumCol"; case TotalSizeCol: return "TotalSizeCol"; case OwnSizeCol: return "OwnSizeCol"; case TotalItemsCol: return "TotalItemsCol"; case TotalFilesCol: return "TotalFilesCol"; case TotalSubDirsCol: return "TotalSubDirsCol"; case LatestMTimeCol: return "LatestMTimeCol"; case ReadJobsCol: return "ReadJobsCol"; case UndefinedCol: return "UndefinedCol"; // Intentionally omitting 'default' so the compiler // can catch unhandled enum values } logError() << "Unknown DataColumn " << col << endl; return QString( "" ).arg( (int) col ); } DataColumn DataColumns::fromString( const QString & str ) { for ( int i = DataColumnBegin; i <= DataColumnEnd; ++i ) { DataColumn col = static_cast( i ); if ( str == toString( col ) ) return col; } logError() << "Undefined DataColumn \"" << str << "\"" << endl; return UndefinedCol; } QStringList DataColumns::toStringList( const DataColumnList & colList ) { QStringList strList; foreach ( DataColumn col, colList ) { strList << toString( col ); } return strList; } DataColumnList DataColumns::fromStringList( const QStringList & strList ) { DataColumnList colList; foreach ( const QString & str, strList ) { DataColumn col = fromString( str ); if ( col != UndefinedCol ) colList << col; } return colList; } DataColumnList DataColumns::fixup( const DataColumnList & colList ) { DataColumnList fixedList = colList; if ( fixedList.first() != NameCol ) { logError() << "NameCol is required to be first!" << endl; fixedList.removeAll( NameCol ); fixedList.prepend( NameCol ); logError() << "Fixed column list: " << toStringList( fixedList ) << endl; } return fixedList; } qdirstat-1.4/src/DataColumns.h000066400000000000000000000112771311502036700163710ustar00rootroot00000000000000/* * File name: DataColumns.h * Summary: Data column mapping * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DataColumns_h #define DataColumns_h #include #include #include #include namespace QDirStat { /** * Data columns for data model, view and sorting. **/ enum DataColumn { NameCol = 0, // File / directory name PercentBarCol, // Graphical percentage bar PercentNumCol, // Numeric percentage Value TotalSizeCol, // Total subtree size OwnSizeCol, // Own size of file / directory TotalItemsCol, // Total number of items in subtree TotalFilesCol, // Total number of files in subtree TotalSubDirsCol, // Total number of subdirs in subtree LatestMTimeCol, // Latest modification time in subtree ReadJobsCol, // Number of pending read jobs in subtree UndefinedCol }; // For use in loops #define DataColumnBegin NameCol #define DataColumnEnd UndefinedCol typedef QList DataColumnList; /** * Singleton class for data columns. * * This class keeps track what columns should be displayed and in what * order and how to map view columns to model columns and vice versa. * * The model uses the DataColumn enum internally. For the view, however, * the columns may be rearranged, and any column may be ommitted (not * displayed at all). This class handles that mapping. **/ class DataColumns: public QObject { Q_OBJECT public: /** * Return the singleton instance for this class. This will create the * singleton upon the first call. **/ static DataColumns * instance(); /** * Map a view column to the corresponding model column. * (static version) **/ static DataColumn fromViewCol( int viewCol ) { return instance()->mappedCol( static_cast( viewCol ) ); } /** * Map a model column to the corresponding view column. * (static version) **/ static DataColumn toViewCol( int modelCol ) { return instance()->reverseMappedCol( static_cast( modelCol ) ); } /** * Map a view column to the corresponding model column. **/ DataColumn mappedCol( DataColumn viewCol ) const; /** * Map a model column to the corresponding view column. **/ DataColumn reverseMappedCol( DataColumn modelCol ) const; /** * Set the column order and what columns to display. * * Example: * * DataColumnList col; * col << QDirStat::NameCol, * << QDirStat::PercentBarCol, * << QDirStat::PercentNumCol, * << QDirStat::TotalSizeCol; * DataColumns->instance()->setColumns( col ); * * NOTICE: If a data view is active, use DirTreeModel::setColumns() * instead (which will call this function in turn) so the view is * correctly notified about this change. * * This will emit a columnsChanged() signal. */ void setColumns( const DataColumnList & columns ); /** * Return the model colums that are currently being displayed. **/ const DataColumnList & columns() const { return _columns; } /** * Return the default model columns. **/ const DataColumnList defaultColumns() const; /** * Return the number of columns that are curently displayed. **/ int colCount() const { return _columns.size(); } /** * Convert a column to string. **/ static QString toString( DataColumn col ); /** * Convert string to column. **/ static DataColumn fromString( const QString & str ); /** * Convert a list of columns to a string list. **/ static QStringList toStringList( const DataColumnList & colList ); /** * convert a string list to a list of columns. **/ static DataColumnList fromStringList( const QStringList & strList ); /** * Fix a data column list to make sure it contains NameCol at the first * position. **/ static DataColumnList fixup( const DataColumnList & colList ); public slots: /** * Read parameters from the settings file. **/ void readSettings(); /** * Write parameters to the settings file. **/ void writeSettings(); signals: /** * Emitted when the columns changed (after setColumns() ). **/ void columnsChanged(); protected: /** * Constructor. This is not meant for general use; use * DataColumns::instance() and the static methods instead. **/ DataColumns(); // Data members static DataColumns * _instance; DataColumnList _columns; }; // class DataColumns /** * Print a DataColumn in text form to a debug stream. **/ inline QTextStream & operator<< ( QTextStream & stream, DataColumn col ) { stream << DataColumns::toString( col ); return stream; } } // namespace QDirStat #endif // DataColumns_h qdirstat-1.4/src/DebugHelpers.cpp000066400000000000000000000053671311502036700170660ustar00rootroot00000000000000/* * File name: DebugHelpers.cpp * Summary: Debugging helper functions for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "DebugHelpers.h" #include "DirTree.h" #include "FileInfoIterator.h" #include "ExcludeRules.h" namespace Debug { using namespace QDirStat; void dumpDirectChildren( FileInfo * dir ) { if ( ! dir ) return; FileInfoIterator it( dir ); if ( dir->hasChildren() ) { logDebug() << "Children of " << dir << " (" << (void *) dir << ")" << endl; int count = 0; while ( *it ) { logDebug() << " #" << count++ << ": " << (void *) *it << " " << *it << endl; ++it; } } else { logDebug() << " No children in " << dir << endl; } } void dumpChildrenList( FileInfo * dir, const FileInfoList & children ) { logDebug() << "Children of " << dir << endl; for ( int i=0; i < children.size(); ++i ) { logDebug() << " #" << i << ": " << children.at(i) << endl; } } void dumpChildrenBySize( FileInfo * dir ) { logDebug() << "Direct children of " << dir << " by size:" << endl; QDirStat::FileInfoSortedBySizeIterator it( dir ); while ( *it ) { logDebug() << " " << formatSize( (*it)->totalSize() ) << " " << *it << endl; ++it; } } void dumpModelTree( const QAbstractItemModel * model, const QModelIndex & index, const QString & indent ) { int rowCount = model->rowCount( index ); QVariant data = model->data( index, Qt::DisplayRole ); if ( data.isValid() ) { if ( rowCount > 0 ) logDebug() << indent << data.toString() << ": " << rowCount << " rows" << endl; else logDebug() << indent << data.toString() << endl; } else { logDebug() << " " << rowCount << " rows" << endl; } for ( int row=0; row < rowCount; row++ ) { QModelIndex childIndex = model->index( row, 0, index ); Debug::dumpModelTree( model, childIndex, indent + QString( 4, ' ' ) ); } } QStringList modelTreeAncestors( const QModelIndex & index ) { QStringList parents; QModelIndex parent = index; while ( parent.isValid() ) { QVariant data = index.model()->data( parent, 0 ); if ( data.isValid() ) parents.prepend( data.toString() ); parent = index.model()->parent( parent ); } return parents; } void dumpExcludeRules() { if ( ExcludeRules::instance()->isEmpty() ) logDebug() << "No exclude rules defined" << endl; for ( ExcludeRuleListIterator it = ExcludeRules::instance()->begin(); it != ExcludeRules::instance()->end(); ++it ) { logDebug() << *it << endl; } } } // namespace qdirstat-1.4/src/DebugHelpers.h000066400000000000000000000031621311502036700165220ustar00rootroot00000000000000/* * File name: DebugHelpers.h * Summary: Debugging helper functions for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DebugHelpers_h #define DebugHelpers_h #include #include #include #include "FileInfo.h" class QAbstractItemModel; namespace Debug { using QDirStat::FileInfo; using QDirStat::FileInfoList; /** * Dump the direct children of 'dir' to the log. **/ void dumpDirectChildren(FileInfo * dir); /** * Dump the direct children of 'dir' sorted by size to the log. **/ void dumpChildrenBySize( FileInfo * dir ); /** * Dump a children list to the log. If specified, use 'dirName' as the * directory name for the heading line. This mostly makes sense with an * unnamed directory like the DirTreeModel's pseudo root. **/ void dumpChildrenList( FileInfo * dir, const FileInfoList & children ); /** * Recursively dump the model tree from 'index' on to the log. * Indent each line with 'indent' (typically a string consisting of * blanks). **/ void dumpModelTree( const QAbstractItemModel * model, const QModelIndex & index, const QString & indent ); /** * Dump the exclude rules to the log. **/ void dumpExcludeRules(); /** * Return a string list of data(0) of the tree ancestors of 'index'. * The list will start with the tree's root. **/ QStringList modelTreeAncestors( const QModelIndex & index ); } // namespace #endif // DebugHelpers_h qdirstat-1.4/src/DelayedRebuilder.cpp000066400000000000000000000020261311502036700177070ustar00rootroot00000000000000/* * File name: DelayedRebuilder.cpp * Summary: Utility class to handle delayed rebuilding of widgets * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "DelayedRebuilder.h" #include "Logger.h" #define DefaultRebuildDelayMillisec 200 using namespace QDirStat; DelayedRebuilder::DelayedRebuilder( QObject * parent ): QObject( parent ), _firstRebuild( true ), _pendingRebuildCount(0), _delayMillisec( DefaultRebuildDelayMillisec ) { } DelayedRebuilder::~DelayedRebuilder() { } void DelayedRebuilder::scheduleRebuild() { ++_pendingRebuildCount; QTimer::singleShot( _delayMillisec, this, SLOT( rebuildDelayed() ) ); } void DelayedRebuilder::rebuildDelayed() { if ( --_pendingRebuildCount > 0 ) // Yet another rebuild scheduled (by timer)? return; // -> do nothing, it will be in vain anyway _pendingRebuildCount = 0; _firstRebuild = false; emit rebuild(); } qdirstat-1.4/src/DelayedRebuilder.h000066400000000000000000000044001311502036700173520ustar00rootroot00000000000000/* * File name: DelayedRebuilder.h * Summary: Utility class to handle delayed rebuilding of widgets * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DelayedRebuilder_h #define DelayedRebuilder_h #include namespace QDirStat { /** * This is a utility class to handle delayed rebuilding for widgets: * * Rebuilds are not executed right away, but delayed for a few milliseconds * in case another rebuild is requested immediately. This is useful for * resize events to prevent doing expensive widget rebuilds more often than * necessary. **/ class DelayedRebuilder: public QObject { Q_OBJECT public: /** * Constructor. **/ DelayedRebuilder( QObject * parent = 0 ); /** * Destructor. **/ virtual ~DelayedRebuilder(); /** * Return 'true' if this is the first rebuild ever. **/ bool firstRebuild() const { return _firstRebuild; } /** * Return the number of pending rebuilds. **/ int pendingRebuildCount() const { return _pendingRebuildCount; } /** * Change the default 200 millisec delay to a new value. **/ void setDelay( int delayMillisec ) { _delayMillisec = delayMillisec; } public slots: /** * Schedule a rebuild after the timeout is over. Repeated calls to this * while the timeout is still running will result in all scheduled * rebuilds except the last one to be ignored. **/ void scheduleRebuild(); signals: /** * Emitted when the rebuild should really be done: When the timeout is * over and there are no more other pending rebuilds scheduled. **/ void rebuild(); protected slots: /** * Slot that is called when the timeout is over: This will emit a * rebuild() signal if there are no more pending rebuilds. **/ void rebuildDelayed(); protected: bool _firstRebuild; int _pendingRebuildCount; int _delayMillisec; }; } // namespace QDirStat #endif // ifndef DelayedRebuilder_h qdirstat-1.4/src/DirInfo.cpp000066400000000000000000000334461311502036700160460ustar00rootroot00000000000000/* * File name: DirInfo.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "DirInfo.h" #include "DirTree.h" #include "FileInfoIterator.h" #include "FileInfoSorter.h" #include "Exception.h" using namespace QDirStat; DirInfo::DirInfo( DirTree * tree, DirInfo * parent, bool asDotEntry ) : FileInfo( tree, parent ) { init(); if ( asDotEntry ) { _isDotEntry = true; _name = dotEntryName(); if ( parent ) _device = parent->device(); } else { _readState = DirFinished; } } DirInfo::DirInfo( const QString & filenameWithoutPath, struct stat * statInfo, DirTree * tree, DirInfo * parent ) : FileInfo( filenameWithoutPath, statInfo, tree, parent ) { init(); _dotEntry = new DirInfo( tree, this, true ); } DirInfo::DirInfo( DirTree * tree, DirInfo * parent, const QString & filenameWithoutPath, mode_t mode, FileSize size, time_t mtime ) : FileInfo( tree, parent, filenameWithoutPath, mode, size, mtime ) { init(); _dotEntry = new DirInfo( tree, this, true ); } void DirInfo::init() { _isDotEntry = false; _isMountPoint = false; _isExcluded = false; _summaryDirty = false; _deletingAll = false; _locked = false; _touched = false; _pendingReadJobs = 0; _dotEntry = 0; _firstChild = 0; _totalSize = _size; _totalBlocks = _blocks; _totalItems = 0; _totalSubDirs = 0; _totalFiles = 0; _latestMtime = _mtime; _readState = DirQueued; _sortedChildren = 0; _lastSortCol = UndefinedCol; _lastSortOrder = Qt::AscendingOrder; } DirInfo::~DirInfo() { clear(); } void DirInfo::clear() { _deletingAll = true; // Recursively delete all children. while ( _firstChild ) { FileInfo * nextChild = _firstChild->next(); if ( _parent ) _parent->deletingChild( _firstChild ); delete _firstChild; _firstChild = nextChild; // unlink the old first child } // Delete the dot entry. if ( _dotEntry ) { delete _dotEntry; _dotEntry = 0; } _summaryDirty = true; dropSortCache(); } void DirInfo::reset() { if ( _isDotEntry ) return; if ( _firstChild || _dotEntry ) clear(); _readState = DirQueued; _pendingReadJobs = 0; _summaryDirty = true; if ( ! _dotEntry ) { _dotEntry = new DirInfo( _tree, this, true ); _tree->childAddedNotify( _dotEntry ); } recalc(); dropSortCache(); } void DirInfo::recalc() { // logDebug() << this << endl; _totalSize = _size; _totalBlocks = _blocks; _totalItems = 0; _totalSubDirs = 0; _totalFiles = 0; _latestMtime = _mtime; FileInfoIterator it( this ); while ( *it ) { _totalSize += (*it)->totalSize(); _totalBlocks += (*it)->totalBlocks(); _totalItems += (*it)->totalItems() + 1; _totalSubDirs += (*it)->totalSubDirs(); _totalFiles += (*it)->totalFiles(); if ( (*it)->isDir() ) _totalSubDirs++; if ( (*it)->isFile() ) _totalFiles++; time_t childLatestMtime = (*it)->latestMtime(); if ( childLatestMtime > _latestMtime ) _latestMtime = childLatestMtime; ++it; } _summaryDirty = false; } void DirInfo::setMountPoint( bool isMountPoint ) { _isMountPoint = isMountPoint; } FileSize DirInfo::totalSize() { if ( _summaryDirty ) recalc(); return _totalSize; } FileSize DirInfo::totalBlocks() { if ( _summaryDirty ) recalc(); return _totalBlocks; } int DirInfo::totalItems() { if ( _summaryDirty ) recalc(); return _totalItems; } int DirInfo::totalSubDirs() { if ( _summaryDirty ) recalc(); return _totalSubDirs; } int DirInfo::totalFiles() { if ( _summaryDirty ) recalc(); return _totalFiles; } time_t DirInfo::latestMtime() { if ( _summaryDirty ) recalc(); return _latestMtime; } bool DirInfo::isFinished() { return ! isBusy(); } void DirInfo::setReadState( DirReadState newReadState ) { // "aborted" has higher priority than "finished" if ( _readState == DirAborted && newReadState == DirFinished ) return; _readState = newReadState; } bool DirInfo::isBusy() { if ( _pendingReadJobs > 0 && _readState != DirAborted ) return true; if ( readState() == DirReading || readState() == DirQueued ) return true; return false; } void DirInfo::setDotEntry( FileInfo *newDotEntry ) { if ( newDotEntry ) _dotEntry = newDotEntry->toDirInfo(); else _dotEntry = 0; } void DirInfo::insertChild( FileInfo *newChild ) { CHECK_PTR( newChild ); if ( newChild->isDir() || _dotEntry == 0 || _isDotEntry ) { /** * Only directories are stored directly in pure directory nodes - * unless something went terribly wrong, e.g. there is no dot entry to use. * If this is a dot entry, store everything it gets directly within it. * * In any of those cases, insert the new child in the children list. * * We don't bother with this list's order - it's explicitly declared to * be unordered, so be warned! We simply insert this new child at the * list head since this operation can be performed in constant time * without the need for any additional lastChild etc. pointers or - * even worse - seeking the correct place for insertion first. This is * none of our business; the corresponding "view" object for this tree * will take care of such niceties. **/ newChild->setNext( _firstChild ); _firstChild = newChild; newChild->setParent( this ); // make sure the parent pointer is correct childAdded( newChild ); // update summaries } else { /* * If the child is not a directory, don't store it directly here - use * this entry's dot entry instead. */ _dotEntry->insertChild( newChild ); } } void DirInfo::childAdded( FileInfo *newChild ) { if ( ! _summaryDirty ) { _totalSize += newChild->size(); _totalBlocks += newChild->blocks(); _totalItems++; if ( newChild->isDir() ) _totalSubDirs++; if ( newChild->isFile() ) _totalFiles++; if ( newChild->mtime() > _latestMtime ) _latestMtime = newChild->mtime(); } else { // NOP /* * Don't bother updating the summary fields if the summary is dirty * (i.e. outdated) anyway: As soon as anybody wants to know some exact * value a complete recalculation of the entire subtree will be * triggered. On the other hand, if nobody wants to know (which is very * likely) we can save this effort. */ } if ( _lastSortCol != ReadJobsCol ) dropSortCache(); if ( _parent ) _parent->childAdded( newChild ); } void DirInfo::deletingChild( FileInfo * child ) { /** * When children are deleted, things go downhill: Marking the summary * fields as dirty (i.e. outdated) is the only thing that can be done here. * * The accumulated sizes could be updated (by subtracting this deleted * child's values from them), but the latest mtime definitely has to be * recalculated: The child now being deleted might just be the one with the * latest mtime, and figuring out the second-latest cannot easily be * done. So we merely mark the summary as dirty and wait until a recalc() * will be triggered from outside - which might as well never happen when * nobody wants to know some summary field anyway. **/ _summaryDirty = true; if ( _parent ) _parent->deletingChild( child ); if ( child->parent() == this ) { if ( ! _deletingAll ) { /** * Unlink the child from the children's list - but only if this * doesn't happen recursively for all children of this object: No * use bothering about the validity of the children's list if this * will all be history anyway in a moment. **/ unlinkChild( child ); } else { dropSortCache(); } } } void DirInfo::unlinkChild( FileInfo *deletedChild ) { if ( deletedChild->parent() != this ) { logError() << deletedChild << " is not a child of " << this << " - cannot unlink from children list!" << endl; return; } dropSortCache(); if ( deletedChild == _firstChild ) { logDebug() << "Unlinking first child " << deletedChild << endl; _firstChild = deletedChild->next(); return; } FileInfo *child = firstChild(); while ( child ) { if ( child->next() == deletedChild ) { logDebug() << "Unlinking " << deletedChild << endl; child->setNext( deletedChild->next() ); return; } child = child->next(); } logError() << "Couldn't unlink " << deletedChild << " from " << this << " children list" << endl; } void DirInfo::readJobAdded() { _pendingReadJobs++; if ( _lastSortCol == ReadJobsCol ) dropSortCache(); if ( _parent ) _parent->readJobAdded(); } void DirInfo::readJobFinished() { _pendingReadJobs--; if ( _lastSortCol == ReadJobsCol ) dropSortCache(); if ( _parent ) _parent->readJobFinished(); } void DirInfo::readJobAborted() { _readState = DirAborted; if ( _parent ) _parent->readJobAborted(); } void DirInfo::finalizeLocal() { // logDebug() << this << endl; cleanupDotEntries(); } void DirInfo::finalizeAll() { if ( _isDotEntry ) return; FileInfo *child = firstChild(); while ( child ) { if ( child->isDirInfo() && ! child->isDotEntry() ) { child->toDirInfo()->finalizeAll(); } child = child->next(); } // Optimization: As long as this directory is not finalized yet, it does // (very likely) have a dot entry and thus all direct children are // subdirectories, not plain files, so we don't need to bother checking // plain file children as well - so do finalizeLocal() only after all // children are processed. If this step were the first, for directories // that don't have any subdirectories finalizeLocal() would immediately // get all their plain file children reparented to themselves, so they // would need to be processed in the loop, too. _tree->sendFinalizeLocal( this ); // Must be sent _before_ finalizeLocal()! finalizeLocal(); } DirReadState DirInfo::readState() const { if ( _isDotEntry && _parent ) return _parent->readState(); else return _readState; } void DirInfo::cleanupDotEntries() { if ( ! _dotEntry || _isDotEntry ) return; // Reparent dot entry children if there are no subdirectories on this level if ( ! _firstChild ) { FileInfo *child = _dotEntry->firstChild(); if ( child ) { // logDebug() << "Reparenting children of solo dot entry " << this << endl; _firstChild = child; // Move the entire children chain here. _dotEntry->setFirstChild( 0 ); // _dotEntry will be deleted below. while ( child ) { child->setParent( this ); child = child->next(); } } } // Delete dot entries without any children. // // This also affects dot entries that were just disowned because they had // no siblings (i.e., there are no subdirectories on this level). if ( ! _dotEntry->firstChild() ) { // logDebug() << "Removing empty dot entry " << this << endl; delete _dotEntry; _dotEntry = 0; } } void DirInfo::clearTouched( bool recursive ) { _touched = false; if ( recursive && ! _isDotEntry ) { FileInfo * child = _firstChild; while ( child ) { if ( child->isDirInfo() ) child->toDirInfo()->clearTouched(); child = child->next(); } if ( _dotEntry ) _dotEntry->clearTouched(); } } const FileInfoList & DirInfo::sortedChildren( DataColumn sortCol, Qt::SortOrder sortOrder ) { if ( _sortedChildren && sortCol == _lastSortCol && sortOrder == _lastSortOrder ) return *_sortedChildren; // Clean old sorted children list and create a new one dropSortCache( true ); // recursive _sortedChildren = new FileInfoList(); CHECK_NEW( _sortedChildren ); // Populate with unsorted children list FileInfo * child = _firstChild; while ( child ) { _sortedChildren->append( child ); child = child->next(); } if ( _dotEntry ) _sortedChildren->append( _dotEntry ); // Sort // logDebug() << "Sorting children of " << this << " by " << sortCol << endl; std::stable_sort( _sortedChildren->begin(), _sortedChildren->end(), FileInfoSorter( sortCol, sortOrder ) ); _lastSortCol = sortCol; _lastSortOrder = sortOrder; return *_sortedChildren; } void DirInfo::dropSortCache( bool recursive ) { if ( _sortedChildren ) { // logDebug() << "Dropping sort cache for " << this << endl; // Intentionally deleting the list and creating a new one since // QList never shrinks, it always just grows (this is documented): // QList.clear() would not free the allocated space. // // If we get lucky, we won't even need the _sortedChildren list any // more if nobody asks for it. This prevents pathological cases where // the user opened all tree branches at once (there are menu entries to // open to a certain tree level), then closed them again and now opens // select branches manually. delete _sortedChildren; _sortedChildren = 0; // Optimization: If this dir didn't have any sort cache, there won't be // any in the subtree, either. And dot entries don't have dir children // that could have a sort cache. if ( recursive && ! _isDotEntry ) { FileInfo * child = _firstChild; while ( child ) { if ( child->isDirInfo() ) child->toDirInfo()->dropSortCache( recursive ); child = child->next(); } if ( _dotEntry ) _dotEntry->dropSortCache( recursive ); } } } const DirInfo * DirInfo::findNearestMountPoint() const { const DirInfo * dir = this; while ( dir && ! dir->isMountPoint() ) dir = dir->parent(); return dir; } qdirstat-1.4/src/DirInfo.h000066400000000000000000000271351311502036700155110ustar00rootroot00000000000000/* * File name: DirInfo.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirInfo_h #define DirInfo_h #include "Logger.h" #include "FileInfo.h" #include "DataColumns.h" namespace QDirStat { // Forward declarations class DirTree; /** * A more specialized version of @ref FileInfo: This class can actually * manage children. The base class (@ref FileInfo) has only stubs for the * respective methods to integrate seamlessly with the abstraction of a * file / directory tree; this class fills those stubs with life. * * @short directory item within a @ref DirTree. **/ class DirInfo: public FileInfo { public: /** * Default constructor. * * If "asDotEntry" is set, this will be used as the parent's * "dot entry", i.e. the pseudo directory that holds all the parent's * non-directory children. This is the only way to create a "dot * entry"! **/ DirInfo( DirTree * tree, DirInfo * parent = 0, bool asDotEntry = false ); /** * Constructor from a stat buffer (i.e. based on an lstat() call). **/ DirInfo( const QString & filenameWithoutPath, struct stat * statInfo, DirTree * tree, DirInfo * parent = 0 ); /** * Constructor from the bare neccessary fields * for use from a cache file reader **/ DirInfo( DirTree * tree, DirInfo * parent, const QString & filenameWithoutPath, mode_t mode, FileSize size, time_t mtime ); /** * Destructor. **/ virtual ~DirInfo(); /** * Returns the total size in bytes of this subtree. * * Reimplemented - inherited from @ref FileInfo. **/ virtual FileSize totalSize() Q_DECL_OVERRIDE; /** * Returns the total size in blocks of this subtree. * * Reimplemented - inherited from @ref FileInfo. **/ virtual FileSize totalBlocks() Q_DECL_OVERRIDE; /** * Returns the total number of children in this subtree, excluding this * item. * * Reimplemented - inherited from @ref FileInfo. **/ virtual int totalItems() Q_DECL_OVERRIDE; /** * Returns the total number of subdirectories in this subtree, * excluding this item. Dot entries and "." or ".." are not counted. * * Reimplemented - inherited from @ref FileInfo. **/ virtual int totalSubDirs() Q_DECL_OVERRIDE; /** * Returns the total number of plain file children in this subtree, * excluding this item. * * Reimplemented - inherited from @ref FileInfo. **/ virtual int totalFiles() Q_DECL_OVERRIDE; /** * Returns the latest modification time of this subtree. * * Reimplemented - inherited from @ref FileInfo. **/ virtual time_t latestMtime() Q_DECL_OVERRIDE; /** * Returns 'true' if this had been excluded while reading. **/ virtual bool isExcluded() const Q_DECL_OVERRIDE { return _isExcluded; } /** * Set the 'excluded' status. **/ virtual void setExcluded( bool excl =true ) Q_DECL_OVERRIDE { _isExcluded = excl; } /** * Returns whether or not this is a mount point. * * This will return 'false' only if this information can be obtained at * all, i.e. if local directory reading methods are used. * * Reimplemented - inherited from @ref FileInfo. **/ virtual bool isMountPoint() const Q_DECL_OVERRIDE { return _isMountPoint; } /** * Sets the mount point state, i.e. whether or not this is a mount * point. * * Reimplemented - inherited from @ref FileInfo. **/ virtual void setMountPoint( bool isMountPoint = true ) Q_DECL_OVERRIDE; /** * Find the nearest parent that is a mount point or 0 if there is * none. This may return this DirInfo itself. **/ const DirInfo * findNearestMountPoint() const; /** * Returns true if this subtree is finished reading. * * Reimplemented - inherited from @ref FileInfo. **/ virtual bool isFinished() Q_DECL_OVERRIDE; /** * Returns true if this subtree is busy, i.e. it is not finished * reading yet. * * Reimplemented - inherited from @ref FileInfo. **/ virtual bool isBusy() Q_DECL_OVERRIDE; /** * Returns the number of pending read jobs in this subtree. When this * number reaches zero, the entire subtree is done. * * Reimplemented - inherited from @ref FileInfo. **/ virtual int pendingReadJobs() Q_DECL_OVERRIDE { return _pendingReadJobs; } /** * Returns the first child of this item or 0 if there is none. * Use the child's next() method to get the next child. **/ virtual FileInfo * firstChild() const Q_DECL_OVERRIDE { return _firstChild; } /** * Set this entry's first child. * Use this method only if you know exactly what you are doing. * * Reimplemented - inherited from @ref FileInfo. **/ virtual void setFirstChild( FileInfo *newfirstChild ) Q_DECL_OVERRIDE { _firstChild = newfirstChild; } /** * Insert a child into the children list. * * The order of children in this list is absolutely undefined; * don't rely on any implementation-specific order. **/ virtual void insertChild( FileInfo *newChild ) Q_DECL_OVERRIDE; /** * Get the "Dot Entry" for this node if there is one (or 0 otherwise): * This is a pseudo entry that directory nodes use to store * non-directory children separately from directories. This way the end * user can easily tell which summary fields belong to the directory * itself and which are the accumulated values of the entire subtree. **/ virtual DirInfo * dotEntry() const Q_DECL_OVERRIDE { return _dotEntry; } /** * Set a "Dot Entry". This makes sense for directories only. **/ virtual void setDotEntry( FileInfo *newDotEntry ) Q_DECL_OVERRIDE; /** * Returns true if this is a "Dot Entry". See @ref dotEntry() for * details. * * Reimplemented - inherited from @ref FileInfo. **/ virtual bool isDotEntry() const Q_DECL_OVERRIDE { return _isDotEntry; } /** * Notification that a child has been added somewhere in the subtree. * * Reimplemented - inherited from @ref FileInfo. **/ virtual void childAdded( FileInfo *newChild ) Q_DECL_OVERRIDE; /** * Remove a child from the children list. * * IMPORTANT: This MUST be called just prior to deleting an object of * this class. Regrettably, this cannot simply be moved to the * destructor: Important parts of the object might already be destroyed * (e.g., the virtual table - no more virtual methods). * * Reimplemented - inherited from @ref FileInfo. **/ virtual void unlinkChild( FileInfo *deletedChild ) Q_DECL_OVERRIDE; /** * Notification that a child is about to be deleted somewhere in the * subtree. * * Reimplemented - inherited from @ref FileInfo. **/ virtual void deletingChild( FileInfo *deletedChild ) Q_DECL_OVERRIDE; /** * Notification of a new directory read job somewhere in the subtree. **/ void readJobAdded(); /** * Notification of a finished directory read job somewhere in the * subtree. **/ void readJobFinished(); /** * Notification of an aborted directory read job somewhere in the * subtree. **/ void readJobAborted(); /** * Finalize this directory level after reading it is completed. * This does _not_ mean reading reading all subdirectories is completed * as well! * * Clean up unneeded dot entries. **/ virtual void finalizeLocal(); /** * Recursively finalize all directories from here on - * call finalizeLocal() recursively. **/ void finalizeAll(); /** * Get the current state of the directory reading process: * * DirQueued waiting in the directory read queue * DirReading reading in progress * DirFinished reading finished and OK * DirAborted reading aborted upon user request * DirError error while reading * * Reimplemented - inherited from @ref FileInfo. **/ virtual DirReadState readState() const Q_DECL_OVERRIDE; /** * Set the state of the directory reading process. * See @ref readState() for details. **/ void setReadState( DirReadState newReadState ); /** * Return a list of (direct) children sorted by 'sortCol' and * 'sortOrder' (Qt::AscendingOrder or Qt::DescendingOrder). * * This might return cached information if the sort column and order * are the same as for the last call to this function, and there were * no children added or removed in the meantime. **/ const FileInfoList & sortedChildren( DataColumn sortCol, Qt::SortOrder sortOrder ); /** * Drop all cached information about children sorting. **/ void dropSortCache( bool recursive = false ); /** * Check if this directory is locked. This is purely a user lock * that can be used by the application. The DirInfo does not care * about it at all. **/ bool isLocked() const { return _locked; } /** * Set the user lock. **/ void lock() { _locked = true; } /** * Unlock the user lock. **/ void unlock() { _locked = false; } /** * Recursively delete all children, including the dot entry. **/ void clear(); /** * Reset to the same status like just after construction in preparation * of refreshing the tree from this point on: * * Delete all children if there are any, delete the dot entry's * children if there are any, restore the dot entry if it was removed * (e.g. in finalizeLocal()), set the read state to DirQueued. **/ void reset(); /** * Mark this directory as 'touched'. Item models can use this to keep * track of which items were ever used by a connected view to minimize * any update events: If no information about an item was ever * requested by the view, it is not necessary to tell it that that that * data is now outdated. **/ void touch() { _touched = true; } /** * Check the 'touched' flag. **/ bool isTouched() const { return _touched; } /** * Recursively clear the 'touched' flag. **/ void clearTouched( bool recursive = false ); /** * Returns true if this is a @ref DirInfo object. * * Don't confuse this with @ref isDir() which tells whether or not this * is a disk directory! Both should return the same, but you'll never * know - better be safe than sorry! * * Reimplemented - inherited from @ref FileInfo. **/ virtual bool isDirInfo() const Q_DECL_OVERRIDE { return true; } protected: /** * Recursively recalculate the summary fields when they are dirty. * * This is a _very_ expensive operation since the entire subtree may * recursively be traversed. **/ void recalc(); /** * Clean up unneeded / undesired dot entries: * Delete dot entries that don't have any children, * reparent dot entry children to the "real" (parent) directory if * there are not subdirectory siblings at the level of the dot entry. **/ void cleanupDotEntries(); // // Data members // bool _isDotEntry:1; // Flag: is this entry a "dot entry"? bool _isMountPoint:1; // Flag: is this a mount point? bool _isExcluded:1; // Flag: was this directory excluded? bool _summaryDirty:1; // dirty flag for the cached values bool _deletingAll:1; // Deleting complete children tree? bool _locked:1; // App lock bool _touched:1; // App 'touch' flag int _pendingReadJobs; // number of open directories in this subtree // Children management FileInfo * _firstChild; // pointer to the first child DirInfo * _dotEntry; // pseudo entry to hold non-dir children // Some cached values FileSize _totalSize; FileSize _totalBlocks; int _totalItems; int _totalSubDirs; int _totalFiles; time_t _latestMtime; FileInfoList * _sortedChildren; DataColumn _lastSortCol; Qt::SortOrder _lastSortOrder; DirReadState _readState; private: void init(); }; // class DirInfo } // namespace QDirStat #endif // ifndef DirInfo_h qdirstat-1.4/src/DirReadJob.cpp000066400000000000000000000271171311502036700164570ustar00rootroot00000000000000/* * File name: DirReadJob.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include #include "DirTree.h" #include "DirReadJob.h" #include "DirTreeCache.h" #include "ExcludeRules.h" #include "MountPoints.h" #include "Exception.h" using namespace QDirStat; DirReadJob::DirReadJob( DirTree * tree, DirInfo * dir ): _tree( tree ), _dir( dir ), _queue( 0 ) { _started = false; if ( _dir ) _dir->readJobAdded(); } DirReadJob::~DirReadJob() { if ( _dir ) _dir->readJobFinished(); } /** * Default implementation - derived classes should overwrite this method or * startReading() (or both). **/ void DirReadJob::read() { if ( ! _started ) { _started = true; startReading(); // Don't do anything after startReading() - startReading() might call // finished() which in turn makes the queue destroy this object } } void DirReadJob::setDir( DirInfo * dir ) { _dir = dir; } void DirReadJob::finished() { if ( _queue ) _queue->jobFinishedNotify( this ); else logError() << "No job queue for " << _dir << endl; } void DirReadJob::childAdded( FileInfo *newChild ) { _tree->childAddedNotify( newChild ); } void DirReadJob::deletingChild( FileInfo *deletedChild ) { _tree->deletingChildNotify( deletedChild ); } bool DirReadJob::crossingFileSystems( DirInfo * parent, DirInfo * child ) { if ( parent->device() == child->device() ) return false; QString childDevice = device( child ); QString parentDevice = device( parent->findNearestMountPoint() );; if ( parentDevice.isEmpty() ) parentDevice = _tree->device(); bool crossing = true; if ( ! parentDevice.isEmpty() && ! childDevice.isEmpty() ) crossing = parentDevice != childDevice; if ( crossing ) { logInfo() << "File system boundary at mount point " << child << " on device " << ( childDevice.isEmpty() ? "" : childDevice ) << endl; } else { logInfo() << "Mount point " << child << " is still on the same device " << childDevice << endl; } return crossing; } QString DirReadJob::device( const DirInfo * dir ) const { QString device; if ( dir ) { const MountPoint * mountPoint = MountPoints::findByPath( dir->url() ); if ( mountPoint ) device = mountPoint->device(); } return device; } LocalDirReadJob::LocalDirReadJob( DirTree * tree, DirInfo * dir ) : DirReadJob( tree, dir ) , _diskDir( 0 ) { } LocalDirReadJob::~LocalDirReadJob() { } void LocalDirReadJob::startReading() { struct dirent * entry; struct stat statInfo; QString dirName = _dir->url(); QString defaultCacheName = DEFAULT_CACHE_NAME; // logDebug() << _dir << endl; bool ok = true; if ( access( dirName.toUtf8(), X_OK | R_OK ) != 0 ) { ok = false; logWarning() << "No permission to read directory " << dirName << endl; _dir->setReadState( DirError ); finishReading( _dir ); } if ( ok ) { _diskDir = opendir( dirName.toUtf8() ); if ( ! _diskDir ) { ok = false; _dir->setReadState( DirError ); logWarning() << "opendir(" << dirName << ") failed" << endl; // opendir() doesn't set 'errno' according to POSIX :-( finishReading( _dir ); } } if ( ok ) { _dir->setReadState( DirReading ); while ( ( entry = readdir( _diskDir ) ) ) { QString entryName = QString::fromUtf8( entry->d_name ); if ( entryName != "." && entryName != ".." ) { QString fullName = dirName + "/" + entryName; if ( lstat( fullName.toUtf8(), &statInfo ) == 0 ) // lstat() OK { if ( S_ISDIR( statInfo.st_mode ) ) // directory child? { DirInfo *subDir = new DirInfo( entryName, &statInfo, _tree, _dir ); CHECK_NEW( subDir ); _dir->insertChild( subDir ); childAdded( subDir ); if ( ExcludeRules::instance()->match( fullName, entryName ) ) { subDir->setExcluded(); subDir->setReadState( DirOnRequestOnly ); finishReading( subDir ); } else // No exclude rule matched { if ( ! crossingFileSystems(_dir, subDir ) ) // normal case { LocalDirReadJob * job = new LocalDirReadJob( _tree, subDir ); CHECK_NEW( job ); _tree->addJob( job ); } else // The subdirectory we just found is a mount point. { subDir->setMountPoint(); if ( _tree->crossFileSystems() ) { LocalDirReadJob * job = new LocalDirReadJob( _tree, subDir ); CHECK_NEW( job ); _tree->addJob( job ); } else { subDir->setReadState( DirOnRequestOnly ); finishReading( subDir ); } } } } else // non-directory child { if ( entryName == defaultCacheName ) // .qdirstat.cache.gz found? { logDebug() << "Found cache file " << defaultCacheName << endl; // // Read content of this subdirectory from cache file // CacheReadJob * cacheReadJob = new CacheReadJob( _tree, _dir->parent(), fullName ); CHECK_NEW( cacheReadJob ); QString firstDirInCache = cacheReadJob->reader()->firstDir(); if ( firstDirInCache == dirName ) // Does this cache file match this directory? { logDebug() << "Using cache file " << fullName << " for " << dirName << endl; cacheReadJob->reader()->rewind(); // Read offset was moved by firstDir() _tree->addJob( cacheReadJob ); // Job queue will assume ownership of cacheReadJob if ( _dir->parent() ) _dir->parent()->setReadState( DirReading ); // // Clean up partially read directory content // DirTree * tree = _tree; // Copy data members to local variables: DirInfo * dir = _dir; // This object will be deleted soon by killAll() _queue->killAll( _dir, cacheReadJob ); // Will delete this job as well! // All data members of this object are invalid from here on! logDebug() << "Deleting subtree " << dir << endl; tree->deleteSubtree( dir ); return; } else { logWarning() << "NOT using cache file " << fullName << " with dir " << firstDirInCache << " for " << dirName << endl; delete cacheReadJob; } } else { FileInfo *child = new FileInfo( entryName, &statInfo, _tree, _dir ); CHECK_NEW( child ); _dir->insertChild( child ); childAdded( child ); } } } else // lstat() error { logWarning() << "lstat(" << fullName << ") failed: " << formatErrno() << endl; /* * Not much we can do when lstat() didn't work; let's at * least create an (almost empty) entry as a placeholder. */ DirInfo *child = new DirInfo( _tree, _dir, entryName, 0, // mode 0, // size 0 ); // mtime CHECK_NEW( child ); child->finalizeLocal(); child->setReadState( DirError ); _dir->insertChild( child ); childAdded( child ); } } } closedir( _diskDir ); _dir->setReadState( DirFinished ); finishReading( _dir ); } finished(); // Don't add anything after finished() since this deletes this job! } void LocalDirReadJob::finishReading( DirInfo * dir ) { // logDebug() << dir << endl; _tree->sendFinalizeLocal( dir ); dir->finalizeLocal(); _tree->sendReadJobFinished( dir ); } FileInfo * LocalDirReadJob::stat( const QString & url, DirTree * tree, DirInfo * parent ) { struct stat statInfo; logDebug() << "url: \"" << url << "\"" << endl; if ( lstat( url.toUtf8(), &statInfo ) == 0 ) // lstat() OK { if ( S_ISDIR( statInfo.st_mode ) ) // directory? { DirInfo * dir = new DirInfo( url, &statInfo, tree, parent ); CHECK_NEW( dir ); if ( parent ) parent->insertChild( dir ); if ( dir && parent && ! tree->isTopLevel( dir ) && dir->device() != parent->device() ) { logDebug() << dir << " is a mount point" << endl; dir->setMountPoint(); } return dir; } else // no directory { FileInfo * file = new FileInfo( url, &statInfo, tree, parent ); CHECK_NEW( file ); if ( parent ) parent->insertChild( file ); return file; } } else // lstat() failed { THROW( SysCallFailedException( "lstat", url ) ); return 0; // NOTREACHED } } CacheReadJob::CacheReadJob( DirTree * tree, DirInfo * parent, CacheReader * reader ) : ObjDirReadJob( tree, parent ) , _reader( reader ) { if ( _reader ) _reader->rewind(); init(); } CacheReadJob::CacheReadJob( DirTree * tree, DirInfo * parent, const QString & cacheFileName ) : ObjDirReadJob( tree, parent ) { _reader = new CacheReader( cacheFileName, tree, parent ); CHECK_NEW( _reader ); init(); } void CacheReadJob::init() { if ( _reader ) { if ( _reader->ok() ) { connect( _reader, SIGNAL( childAdded ( FileInfo * ) ), this, SLOT ( slotChildAdded( FileInfo * ) ) ); } else { delete _reader; _reader = 0; } } } CacheReadJob::~CacheReadJob() { if ( _reader ) delete _reader; } void CacheReadJob::read() { /* * This will be called repeatedly from DirTree::timeSlicedRead() until * finished() is called. */ if ( ! _reader ) finished(); // logDebug() << "Reading 1000 cache lines" << endl; _reader->read( 1000 ); if ( _reader->eof() || ! _reader->ok() ) { // logDebug() << "Cache reading finished - ok: " << _reader->ok() << endl; finished(); } } DirReadJobQueue::DirReadJobQueue() : QObject() { connect( &_timer, SIGNAL( timeout() ), this, SLOT ( timeSlicedRead() ) ); } DirReadJobQueue::~DirReadJobQueue() { clear(); } void DirReadJobQueue::enqueue( DirReadJob * job ) { if ( job ) { _queue.append( job ); job->setQueue( this ); if ( ! _timer.isActive() ) { // logDebug() << "First job queued" << endl; emit startingReading(); _timer.start( 0 ); } } } DirReadJob * DirReadJobQueue::dequeue() { DirReadJob * job = _queue.first(); _queue.removeFirst(); if ( job ) job->setQueue( 0 ); return job; } void DirReadJobQueue::clear() { qDeleteAll( _queue ); _queue.clear(); } void DirReadJobQueue::abort() { foreach ( DirReadJob * job, _queue ) { if ( job->dir() ) job->dir()->readJobAborted(); } clear(); } void DirReadJobQueue::killAll( DirInfo * subtree, DirReadJob * exceptJob ) { if ( ! subtree ) return; QMutableListIterator it( _queue ); while ( it.hasNext() ) { DirReadJob * job = it.next(); if ( exceptJob && job == exceptJob ) { logDebug() << "NOT killing read job " << job->dir() << endl; continue; } if ( job->dir() && job->dir()->isInSubtree( subtree ) ) { // logDebug() << "Killing read job " << job->dir() << endl; it.remove(); delete job; } } } void DirReadJobQueue::timeSlicedRead() { if ( ! _queue.isEmpty() ) _queue.first()->read(); } void DirReadJobQueue::jobFinishedNotify( DirReadJob *job ) { // Get rid of the old (finished) job. _queue.removeOne( job ); delete job; // The timer will start a new job when it fires. if ( _queue.isEmpty() ) // No new job available - we're done. { _timer.stop(); // logDebug() << "No more jobs - finishing" << endl; emit finished(); } } qdirstat-1.4/src/DirReadJob.h000066400000000000000000000227061311502036700161230ustar00rootroot00000000000000/* * File name: DirReadJob.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirReadJob_h #define DirReadJob_h #include #include #include "Logger.h" namespace QDirStat { // Forward declarations class FileInfo; class DirInfo; class DirTree; class CacheReader; class DirReadJobQueue; /** * A directory read job that can be queued. This is mainly to prevent * buffer thrashing because of too many directories opened at the same time * because of simultaneous reads or even system resource consumption * (directory handles in this case). * * Objects of this kind are transient by nature: They live only as long as * the job is queued or executed. When it is done, the data is contained in * the corresponding @ref DirInfo subtree of the corresponding @ref * DirTree. * * For each entry automatically a @ref FileInfo or @ref DirInfo will be * created and added to the parent @ref DirInfo. For each directory a new * @ref DirReadJob will be created and added to the @ref DirTree 's job * queue. * * Notice: This class contains pure virtuals - you cannot use it * directly. Derive your own class from it or use one of * @ref LocalDirReadJob or @ref CacheReadJob. * * @short Abstract base class for directory reading. **/ class DirReadJob { public: /** * Constructor. * * This does not read anything yet. Call read() for that. **/ DirReadJob( DirTree *tree, DirInfo *dir = 0 ); /** * Destructor. **/ virtual ~DirReadJob(); /** * Read the next couple of items from the directory. * Call finished() when there is nothing more to read. * * Derived classes should overwrite this method or startReading(). * This default implementation calls startReading() if it has not been * called yet. **/ virtual void read(); /** * Returns the corresponding @ref DirInfo item. * Caution: This may be 0. **/ virtual DirInfo * dir() { return _dir; } /** * Set the corresponding @ref DirInfo item. **/ virtual void setDir( DirInfo * dir ); /** * Return the job queue this job is in or 0 if it isn't queued. **/ DirReadJobQueue * queue() const { return _queue; } /** * Set the job queue this job is in. **/ void setQueue( DirReadJobQueue * queue ) { _queue = queue; } protected: /** * Initialize reading. * * Derived classes should overwrite this method or read(). **/ virtual void startReading() {} /** * Notification that a new child has been added. * * Derived classes are required to call this whenever a new child is * added so this notification can be passed up to the @ref DirTree * which in turn emits a corresponding signal. **/ void childAdded( FileInfo *newChild ); /** * Notification that a child is about to be deleted. * * Derived classes are required to call this just before a child is * deleted so this notification can be passed up to the @ref DirTree * which in turn emits a corresponding signal. * * Derived classes are not required to handle child deletion at all, * but if they do, calling this method is required. **/ void deletingChild( FileInfo *deletedChild ); /** * Send job finished notification to the associated tree. * This will delete this job. **/ void finished(); /** * Check if going from 'parent' to 'child' would cross a file system * boundary. This take Btrfs subvolumes into account. **/ bool crossingFileSystems( DirInfo * parent, DirInfo * child ); /** * Return the device name where 'dir' is on if it's a mount point. * This uses MountPoints which reads /proc/mounts. **/ QString device( const DirInfo * dir ) const; DirTree * _tree; DirInfo * _dir; DirReadJobQueue * _queue; bool _started; }; // class DirReadJob /** * Wrapper class between DirReadJob and QObject **/ class ObjDirReadJob: public QObject, public DirReadJob { Q_OBJECT public: ObjDirReadJob( DirTree *tree, DirInfo *dir = 0 ) : QObject(), DirReadJob( tree, dir ) {}; virtual ~ObjDirReadJob() {} protected slots: void slotChildAdded ( FileInfo *child ) { childAdded( child ); } void slotDeletingChild( FileInfo *child ) { deletingChild( child ); } void slotFinished() { finished(); } }; // ObjDirReadJob /** * Impementation of the abstract @ref DirReadJob class that reads a local * directory. * * This will use lstat() system calls rather than KDE's network transparent * directory services since lstat() unlike the KDE services can obtain * information about the device (i.e. file system) a file or directory * resides on. This is important if you wish to limit directory scans to * one file system - which is most desirable when that one file system runs * out of space. * * @short Directory reader that reads one local directory. **/ class LocalDirReadJob: public DirReadJob { public: /** * Constructor. **/ LocalDirReadJob( DirTree * tree, DirInfo * dir ); /** * Destructor. **/ virtual ~LocalDirReadJob(); /** * Obtain information about the URL specified and create a new @ref * FileInfo or a @ref DirInfo (whatever is appropriate) from that * information. Use @ref FileInfo::isDirInfo() to find out which. * Returns 0 if such information cannot be obtained (i.e. the * appropriate stat() call fails). **/ static FileInfo * stat( const QString & url, DirTree * tree, DirInfo * parent = 0 ); protected: /** * Read the directory. Prior to this nothing happens. * * Inherited and reimplemented from @ref DirReadJob. **/ virtual void startReading(); /** * Finish reading the directory: Send signals and finalize the * directory (clean up dot entries etc.). **/ void finishReading( DirInfo * dir ); DIR * _diskDir; }; // LocalDirReadJob class CacheReadJob: public ObjDirReadJob { Q_OBJECT public: /** * Constructor for a cache reader that is already open. * * The CacheReadJob takes over ownership of the CacheReader. In * particular, the CacheReader will be destroyed with 'delete' when * the read job is done. * * If 'parent' is 0, the content of the cache file will replace all * current tree items. **/ CacheReadJob( DirTree * tree, DirInfo * parent, CacheReader * reader ); /** * Constructor that uses a cache file that is not open yet. * * If 'parent' is 0, the content of the cache file will replace all * current tree items. **/ CacheReadJob( DirTree * tree, DirInfo * parent, const QString & cacheFileName ); /** * Destructor. **/ virtual ~CacheReadJob(); /** * Start reading the cache. Prior to this nothing happens. * * Inherited and reimplemented from @ref DirReadJob. **/ virtual void read(); /** * Return the associated cache reader. **/ CacheReader * reader() const { return _reader; } protected: /** * Initializations common for all constructors. **/ void init(); CacheReader * _reader; }; // class CacheReadJob /** * Queue for read jobs * * Handles time-sliced reading automatically. **/ class DirReadJobQueue: public QObject { Q_OBJECT public: /** * Constructor. **/ DirReadJobQueue(); /** * Destructor. **/ virtual ~DirReadJobQueue(); /** * Add a job to the end of the queue. Begin time-sliced reading if not * in progress yet. **/ void enqueue( DirReadJob * job ); /** * Remove the head of the queue and return it. **/ DirReadJob * dequeue(); /** * Get the head of the queue (the next job that is due for processing). **/ DirReadJob * head() const { return _queue.first();} /** * Count the number of pending jobs in the queue. **/ int count() const { return _queue.count(); } /** * Check if the queue is empty. **/ bool isEmpty() const { return _queue.isEmpty(); } /** * Clear the queue: Remove all pending jobs from the queue and destroy them. **/ void clear(); /** * Abort all jobs in the queue. **/ void abort(); /** * Delete all jobs for a subtree except 'exceptJob'. **/ void killAll( DirInfo * subtree, DirReadJob * exceptJob = 0 ); /** * Notification that a job is finished. * This takes that job out of the queue and deletes it. * Read jobs are required to call this when they are finished. **/ void jobFinishedNotify( DirReadJob *job ); signals: /** * Emitted when job reading starts, i.e. when a new job is inserted * into a queue that was empty **/ void startingReading(); /** * Emitted when reading is finished, i.e. when the last read job of the * queue is finished. **/ void finished(); protected slots: /** * Time-sliced work procedure to be performed while the application is * in the main loop: Read some directory entries, but relinquish * control back to the application so it can maintain some * responsiveness. This method uses a timer of minimal duration to * activate itself as soon as there are no more user events to * process. Call this only once directly after inserting a read job * into the job queue. **/ void timeSlicedRead(); protected: QList _queue; QTimer _timer; }; } // namespace QDirStat #endif // ifndef DirReadJob_h qdirstat-1.4/src/DirSaver.cpp000066400000000000000000000012271311502036700162230ustar00rootroot00000000000000/* * File name: DirSaver.cpp * Summary: Utility object to save current working directory * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "Logger.h" #include "DirSaver.h" DirSaver::DirSaver( const QString & newPath ) { _oldWorkingDir = QDir::currentPath(); cd( newPath ); } DirSaver::~DirSaver() { restore(); } void DirSaver::cd( const QString & newPath ) { if ( newPath.isEmpty() ) { logWarning() << "Empty path" << endl; return; } chdir( newPath.toUtf8() ); } void DirSaver::restore() { cd( _oldWorkingDir ); } qdirstat-1.4/src/DirSaver.h000066400000000000000000000025251311502036700156720ustar00rootroot00000000000000/* * File name: DirSaver.h * Summary: Utility object to save current working directory * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirSaver_h #define DirSaver_h #include /** * Helper class to change directories without losing the current context. * Will change back to the old working directory when destroyed. * * @short Directory changer with automatic restore **/ class DirSaver { public: /** * Constructor. Will save the current working directory and change to the * path supplied. The old working directory will be restored when this * object is destroyed. **/ DirSaver( const QString & newPath = "" ); /** * Destructor. Restores the original working directory. **/ virtual ~DirSaver(); /** * Change directory. Unlike @ref QDir::cd(), this method really performs a * system chdir() so subsequent system calls will have the directory * specified as the new current working directory. **/ void cd( const QString & newPath ); /** * (Prematurely) restore the working directory. Unnecessary when this * object will be destroyed anyway since the destructor does exactly that. **/ void restore(); protected: QString _oldWorkingDir; }; #endif // DirSaver_h qdirstat-1.4/src/DirTree.cpp000066400000000000000000000157161311502036700160520ustar00rootroot00000000000000/* * File name: DirTree.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "DirTree.h" #include "FileInfoSet.h" #include "Exception.h" #include "DirTreeCache.h" #include "MountPoints.h" using namespace QDirStat; DirTree::DirTree() : QObject() { _isBusy = false; _crossFileSystems = false; _root = new DirInfo( this ); CHECK_NEW( _root ); connect( & _jobQueue, SIGNAL( finished() ), this, SLOT ( slotFinished() ) ); } DirTree::~DirTree() { if ( _root ) delete _root; } void DirTree::setRoot( DirInfo *newRoot ) { if ( _root ) { emit deletingChild( _root ); delete _root; emit childDeleted(); } _root = newRoot; } FileInfo * DirTree::firstToplevel() const { return _root ? _root->firstChild() : 0; } bool DirTree::isTopLevel( FileInfo *item ) const { return item && item->parent() && ! item->parent()->parent(); } QString DirTree::url() const { FileInfo * realRoot = firstToplevel(); return realRoot ? realRoot->url() : ""; } void DirTree::clear() { _jobQueue.clear(); if ( _root ) { emit clearing(); _root->clear(); } _isBusy = false; _device.clear(); } void DirTree::startReading( const QString & rawUrl ) { QFileInfo fileInfo( rawUrl ); QString url = fileInfo.absoluteFilePath(); // logDebug() << "rawUrl: \"" << rawUrl << "\"" << endl; logInfo() << " url: \"" << url << "\"" << endl; const MountPoint * mountPoint = MountPoints::findNearestMountPoint( url ); _device = mountPoint ? mountPoint->device() : ""; logInfo() << "device: " << _device << endl; if ( _root->hasChildren() ) clear(); _isBusy = true; emit startingReading(); FileInfo * item = LocalDirReadJob::stat( url, this, _root ); CHECK_PTR( item ); if ( item ) { childAddedNotify( item ); if ( item->isDirInfo() ) { addJob( new LocalDirReadJob( this, item->toDirInfo() ) ); emit readJobFinished( _root ); } else { _isBusy = false; emit readJobFinished( _root ); emit finished(); } } else // stat() failed { logWarning() << "stat(" << url << ") failed" << endl; _isBusy = false; emit finished(); emit finalizeLocal( 0 ); } } void DirTree::refresh( const FileInfoSet & refreshSet ) { FileInfoSet items = refreshSet.invalidRemoved().normalized(); foreach ( FileInfo * item, items ) { // Need to check the magic number here again because a previous // iteration step might have made the item invalid already if ( item && item->checkMagicNumber() ) { if( item->isDirInfo() ) refresh( item->toDirInfo() ); else if ( item->parent() ) refresh( item->parent() ); } } } void DirTree::refresh( DirInfo * subtree ) { if ( ! _root ) return; if ( ! subtree->checkMagicNumber() ) { // Not using CHECK_MAGIC() here which would throw an exception since // this might easily happen after cleanup actions with multi selection // if one selected item is in the subtree of another, and that parent // was already refreshed. logWarning() << "Item is no longer valid - not refreshing subtree" << endl; return; } if ( subtree->isDotEntry() ) subtree = subtree->parent(); if ( ! subtree || ! subtree->parent() ) // Refresh all (from first toplevel) { try { startReading( QDir::cleanPath( firstToplevel()->url() ) ); } catch ( const SysCallFailedException & ex ) { CAUGHT( ex ); } } else // Refresh subtree { // logDebug() << "Refreshing subtree " << subtree << endl; if ( subtree->hasChildren() ) { emit clearingSubtree( subtree ); subtree->clear(); emit subtreeCleared( subtree ); } subtree->reset(); subtree->setExcluded( false ); _isBusy = true; subtree->setReadState( DirReading ); emit startingReading(); addJob( new LocalDirReadJob( this, subtree ) ); } } void DirTree::abortReading() { if ( _jobQueue.isEmpty() ) return; _jobQueue.abort(); _isBusy = false; emit aborted(); } void DirTree::slotFinished() { _isBusy = false; emit finished(); } void DirTree::childAddedNotify( FileInfo * newChild ) { emit childAdded( newChild ); if ( newChild->dotEntry() ) emit childAdded( newChild->dotEntry() ); } void DirTree::deletingChildNotify( FileInfo * deletedChild ) { logDebug() << "Deleting child " << deletedChild << endl; emit deletingChild( deletedChild ); if ( deletedChild == _root ) _root = 0; } void DirTree::childDeletedNotify() { emit childDeleted(); } void DirTree::deleteSubtree( FileInfo *subtree ) { // logDebug() << "Deleting subtree " << subtree << endl; DirInfo * parent = subtree->parent(); // Send notification to anybody interested (e.g., to attached views) deletingChildNotify( subtree ); if ( parent ) { if ( parent->isDotEntry() && ! parent->hasChildren() ) // This was the last child of a dot entry { // Get rid of that now empty and useless dot entry if ( parent->parent() ) { if ( parent->parent()->isFinished() ) { // logDebug() << "Removing empty dot entry " << parent << endl; deletingChildNotify( parent ); parent->parent()->setDotEntry( 0 ); delete parent; parent = 0; } } else // no parent - this should never happen (?) { logError() << "Internal error: Killing dot entry without parent " << parent << endl; // Better leave that dot entry alone - we shouldn't have come // here in the first place. Who knows what will happen if this // thing is deleted now?! // // Intentionally NOT calling: // delete parent; } } } if ( parent ) { // Give the parent of the child to be deleted a chance to unlink the // child from its children list and take care of internal summary // fields parent->deletingChild( subtree ); } delete subtree; if ( subtree == _root ) { _root = 0; } emit childDeleted(); } void DirTree::addJob( DirReadJob * job ) { _jobQueue.enqueue( job ); } void DirTree::sendFinalizeLocal( DirInfo *dir ) { emit finalizeLocal( dir ); } void DirTree::sendStartingReading() { emit startingReading(); } void DirTree::sendFinished() { emit finished(); } void DirTree::sendAborted() { emit aborted(); } void DirTree::sendStartingReading( DirInfo * dir ) { emit startingReading( dir ); } void DirTree::sendReadJobFinished( DirInfo * dir ) { // logDebug() << dir << endl; emit readJobFinished( dir ); } bool DirTree::writeCache( const QString & cacheFileName ) { CacheWriter writer( cacheFileName.toUtf8(), this ); return writer.ok(); } void DirTree::readCache( const QString & cacheFileName ) { _isBusy = true; emit startingReading(); addJob( new CacheReadJob( this, 0, cacheFileName ) ); } // EOF qdirstat-1.4/src/DirTree.h000066400000000000000000000216611311502036700155130ustar00rootroot00000000000000/* * File name: DirTree.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirTree_h #define DirTree_h #include #include #include #include #include "Logger.h" #include "DirInfo.h" #include "DirReadJob.h" namespace QDirStat { class DirReadJob; class FileInfoSet; /** * This class provides some infrastructure as well as global data for a * directory tree. It acts as the glue that holds things together: The root * item from which to descend into the subtrees, the read queue and some * global policies (like whether or not to cross file systems while reading * directories). * * Notice that this class uses a "pseudo root" to better conform with Qt's * notion of tree views and the corresponding data models: They use an * invisible root item to support multiple toplevel items. * * @short Directory tree global data and infrastructure **/ class DirTree: public QObject { Q_OBJECT public: /** * Constructor. * * Remember to call @ref startReading() after the constructor and * setting up connections. **/ DirTree(); /** * Destructor. **/ virtual ~DirTree(); public slots: /** * Actually start reading. * * It's not very pretty this is required as an extra method, but this * cannot simply be done in the constructor: We need to give the caller * a chance to set up Qt signal connections, and for this the * constructor must return before any signals are sent, i.e. before * anything is read. **/ void startReading( const QString & path ); /** * Forcefully stop a running read process. **/ void abortReading(); /** * Refresh a subtree, i.e. read its contents from disk again. * * All children of the old subtree will be deleted and rebuilt from * scratch, i.e. all pointers to elements within this subtree will * become invalid (a @ref subtreeDeleted() signal will be emitted to * notify about that fact). * * When 0 is passed, the entire tree will be refreshed, i.e. from the * first toplevel element on. **/ void refresh( DirInfo * subtree = 0 ); /** * Refresh a number of subtrees. **/ void refresh( const FileInfoSet & refreshSet ); /** * Delete a subtree. **/ void deleteSubtree( FileInfo * subtree ); public: /** * Return the URL of this tree if it has any elements or an empty * string if it doesn't. **/ QString url() const; /** * Return the root item of this tree. Notice that this is a pseudo * root that doesn not really correspond to a filesystem object. **/ DirInfo * root() const { return _root; } /** * Sets the root item of this tree. **/ void setRoot( DirInfo * newRoot ); /** * Return the first toplevel item of this tree or 0 if there is * none. This is the logical root item. **/ FileInfo * firstToplevel() const; /** * Return 'true' if 'item' is a toplevel item, i.e. a direct child of * the root item. **/ bool isTopLevel( FileInfo *item ) const; /** * Return the device of this tree's root item ("/dev/sda3" etc.). **/ QString device() const { return _device; } /** * Clear all items of this tree. **/ void clear(); /** * Locate a child somewhere in the tree whose URL (i.e. complete path) * matches the URL passed. Returns 0 if there is no such child. * * Notice: This is a very expensive operation since the entire tree is * searched recursively. * * 'findDotEntries' specifies if locating "dot entries" (".../") * is desired. * * This is just a convenience method that maps to * DirTree::root()->locate( url, findDotEntries ) **/ FileInfo * locate( QString url, bool findDotEntries = false ) { return _root ? _root->locate( url, findDotEntries ) : 0; } /** * Add a new directory read job to the queue. **/ void addJob( DirReadJob * job ); /** * Should directory scans cross file systems? * * Notice: This can only be avoided with local directories where the * device number a file resides on can be obtained. * Remember, that's what this QDirStat business is all about. ;-) **/ bool crossFileSystems() const { return _crossFileSystems; } /** * Set or unset the "cross file systems" flag. **/ void setCrossFileSystems( bool doCross ) { _crossFileSystems = doCross; } /** * Notification that a child has been added. * * Directory read jobs are required to call this for each child added * so the tree can emit the corresponding @ref childAdded() signal. **/ virtual void childAddedNotify( FileInfo *newChild ); /** * Notification that a child is about to be deleted. * * Directory read jobs are required to call this for each deleted child * so the tree can emit the corresponding @ref deletingChild() signal. **/ virtual void deletingChildNotify( FileInfo *deletedChild ); /** * Notification that one or more children have been deleted. * * Directory read jobs are required to call this when one or more * children are deleted so the tree can emit the corresponding @ref * deletingChild() signal. For multiple deletions (e.g. entire * subtrees) this should only happen once at the end. **/ virtual void childDeletedNotify(); /** * Send a @ref startingReading() signal. **/ void sendStartingReading(); /** * Send a @ref finished() signal. **/ void sendFinished(); /** * Send a @ref aborted() signal. **/ void sendAborted(); /** * Send a @ref startingReading( DirInfo * ) signal. **/ void sendStartingReading( DirInfo * dir ); /** * Send a @ref readJobFinished( DirInfo * ) signal. **/ void sendReadJobFinished( DirInfo * dir ); /** * Send a @ref finalizeLocal() signal to give views a chance to * finalize the display of this directory level - e.g. clean up dot * entries, set the final "expandable" state etc. **/ void sendFinalizeLocal( DirInfo *dir ); /** * Returns 'true' if directory reading is in progress in this tree. **/ bool isBusy() { return _isBusy; } /** * Write the complete tree to a cache file. * * Returns true if OK, false upon error. **/ bool writeCache( const QString & cacheFileName ); /** * Read a cache file. **/ void readCache( const QString & cacheFileName ); signals: /** * Emitted when a child has been added. **/ void childAdded( FileInfo * newChild ); /** * Emitted when the tree is about to be cleared. **/ void clearing(); /** * Emitted when a child is about to be deleted. **/ void deletingChild( FileInfo * deletedChild ); /** * Emitted after a child is deleted. If you are interested which child * it was, better use the @ref deletingChild() signal. * @ref childDeleted() is only useful to rebuild a view etc. completely. * If possible, this signal is sent only once for multiple deletions - * e.g., when entire subtrees are deleted. **/ void childDeleted(); /** * Emitted when a subtree is about to be cleared, i.e. all its children * will be deleted (but not the subtree node itself). **/ void clearingSubtree( DirInfo * subtree ); /** * Emitted when clearing a subtree is finished. **/ void subtreeCleared( DirInfo * subtree ); /** * Emitted when reading is started. **/ void startingReading(); /** * Emitted when reading this directory tree is completely finished. **/ void finished(); /** * Emitted when reading this directory tree has been aborted. **/ void aborted(); /** * Emitted when reading the specified directory is started. **/ void startingReading( DirInfo * dir ); /** * Emitted when reading the specified directory has been finished. * This is sent AFTER finalizeLocal( DirInfo * dir ). **/ void readJobFinished( DirInfo * dir ); /** * Emitted when reading a directory is finished. * This does _not_ mean reading all subdirectories is finished, too - * only this directory level is complete! * * WARNING: 'dir' may be 0 if the the tree's root could not be read. * * Use this signal to do similar cleanups like * @ref DirInfo::finalizeLocal(), e.g. cleaning up unused / undesired * dot entries like in @ref DirInfo::cleanupDotEntries(). * * Notice that the dot entry might be removed and its children * reparented after this signal. **/ void finalizeLocal( DirInfo * dir ); /** * Single line progress information, emitted when the read status * changes - typically when a new directory is being read. Connect to a * status bar etc. to keep the user entertained. **/ void progressInfo( const QString & infoLine ); protected slots: /** * Notification that all jobs in the job queue are finished. * This will emit the finished() signal. **/ void slotFinished(); protected: DirInfo * _root; DirReadJobQueue _jobQueue; bool _crossFileSystems; bool _isBusy; QString _device; }; // class DirTree } // namespace QDirStat #endif // ifndef DirTree_h qdirstat-1.4/src/DirTreeCache.cpp000066400000000000000000000365461311502036700170020ustar00rootroot00000000000000/* * File name: DirTreeCache.cpp * Summary: QDirStat cache reader / writer * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "Logger.h" #include "DirTreeCache.h" #include "DirTree.h" #include "ExcludeRules.h" #include "Exception.h" #define KB 1024LL #define MB (1024LL*1024) #define GB (1024LL*1024*1024) #define TB (1024LL*1024*1024*1024) #define MAX_ERROR_COUNT 1000 #define VERBOSE_READ 0 #define VERBOSE_CACHE_DIRS 0 #define VERBOSE_CACHE_FILE_INFOS 0 #define DEBUG_LOCATE_PARENT 0 using namespace QDirStat; CacheWriter::CacheWriter( const QString & fileName, DirTree *tree ) { _ok = writeCache( fileName, tree ); } CacheWriter::~CacheWriter() { // NOP } bool CacheWriter::writeCache( const QString & fileName, DirTree *tree ) { if ( ! tree || ! tree->root() ) return false; gzFile cache = gzopen( (const char *) fileName.toUtf8(), "w" ); if ( cache == 0 ) { logError() << "Can't open " << fileName << ": " << formatErrno() << endl; return false; } gzprintf( cache, "[qdirstat %s cache file]\n", CACHE_FORMAT_VERSION ); gzprintf( cache, "# Do not edit!\n" "#\n" "# Type\tpath\t\tsize\tmtime\t\t\n" "\n" ); writeTree( cache, tree->root()->firstChild() ); gzclose( cache ); return true; } void CacheWriter::writeTree( gzFile cache, FileInfo * item ) { if ( ! item ) return; // // Write entry for this item // if ( ! item->isDotEntry() ) writeItem( cache, item ); // // Write file children // if ( item->dotEntry() ) writeTree( cache, item->dotEntry() ); // // Recurse through subdirectories // FileInfo * child = item->firstChild(); while ( child ) { writeTree( cache, child ); child = child->next(); } } void CacheWriter::writeItem( gzFile cache, FileInfo * item ) { if ( ! item ) return; // Write file type const char * file_type = ""; if ( item->isFile() ) file_type = "F"; else if ( item->isDir() ) file_type = "D"; else if ( item->isSymLink() ) file_type = "L"; else if ( item->isBlockDevice() ) file_type = "BlockDev"; else if ( item->isCharDevice() ) file_type = "CharDev"; else if ( item->isFifo() ) file_type = "FIFO"; else if ( item->isSocket() ) file_type = "Socket"; gzprintf( cache, "%s", file_type ); // Write name if ( item->isDirInfo() && ! item->isDotEntry() ) { // Use absolute path gzprintf( cache, " %s", urlEncoded( item->url() ).data() ); } else { // Use relative path gzprintf( cache, "\t%s", urlEncoded( item->name() ).data() ); } // Write size gzprintf( cache, "\t%s", formatSize( item->size() ).toUtf8().data() ); // Write mtime gzprintf( cache, "\t0x%lx", (unsigned long) item->mtime() ); // Optional fields if ( item->isSparseFile() ) gzprintf( cache, "\tblocks: %lld", item->blocks() ); if ( item->isFile() && item->links() > 1 ) gzprintf( cache, "\tlinks: %u", (unsigned) item->links() ); gzputc( cache, '\n' ); } QByteArray CacheWriter::urlEncoded( const QString & path ) { // Using a protocol ("scheme") part to avoid directory names with a colon // ":" being cut off because it looks like a URL protocol. QUrl url; url.setScheme( "foo" ); url.setPath( path ); QByteArray encoded = url.toEncoded( QUrl::RemoveScheme ); if ( encoded.isEmpty() ) { logError() << "Invalid file/dir name: " << path << endl; } return encoded; } QString CacheWriter::formatSize( FileSize size ) { QString str; if ( size >= TB && size % TB == 0 ) { str.sprintf( "%lldT", size / TB ); return str; } if ( size >= GB && size % GB == 0 ) { str.sprintf( "%lldG", size / GB ); return str; } if ( size >= MB && size % MB == 0 ) { str.sprintf( "%lldM", size / MB ); return str; } if ( size >= KB && size % KB == 0 ) { str.sprintf( "%lldK", size / KB ); return str; } str.sprintf( "%lld", size ); return str; } CacheReader::CacheReader( const QString & fileName, DirTree * tree, DirInfo * parent ): QObject(), _multiSlash( "//+" ) // cache regexp for multiple use { _fileName = fileName; _buffer[0] = 0; _line = _buffer; _lineNo = 0; _ok = true; _errorCount = 0; _tree = tree; _toplevel = parent; _lastDir = 0; _lastExcludedDir = 0; _cache = gzopen( fileName.toUtf8(), "r" ); if ( _cache == 0 ) { logError() << "Can't open " << fileName << ": " << formatErrno() << endl; _ok = false; emit error(); return; } // logDebug() << "Opening " << fileName << " OK" << endl; checkHeader(); } CacheReader::~CacheReader() { if ( _cache ) gzclose( _cache ); logDebug() << "Cache reading finished" << endl; if ( _toplevel ) { // logDebug() << "Finalizing recursive for " << _toplevel << endl; finalizeRecursive( _toplevel ); _toplevel->finalizeAll(); } emit finished(); } void CacheReader::rewind() { if ( _cache ) { gzrewind( _cache ); checkHeader(); // skip cache header } } bool CacheReader::read( int maxLines ) { while ( ! gzeof( _cache ) && _ok && ( maxLines == 0 || --maxLines > 0 ) ) { if ( readLine() ) { splitLine(); addItem(); } } return _ok && ! gzeof( _cache ); } void CacheReader::addItem() { if ( fieldsCount() < 4 ) { logError() << "Syntax error in " << _fileName << ":" << _lineNo << ": Expected at least 4 fields, saw only " << fieldsCount() << endl; setReadError( _lastDir ); if ( ++_errorCount > MAX_ERROR_COUNT ) { logError() << "Too many syntax errors. Giving up." << endl; _ok = false; emit error(); } return; } int n = 0; char * type = field( n++ ); char * raw_path = field( n++ ); char * size_str = field( n++ ); char * mtime_str = field( n++ ); char * blocks_str = 0; char * links_str = 0; while ( fieldsCount() > n+1 ) { char * keyword = field( n++ ); char * val_str = field( n++ ); if ( strcasecmp( keyword, "blocks:" ) == 0 ) blocks_str = val_str; if ( strcasecmp( keyword, "links:" ) == 0 ) links_str = val_str; } // Type mode_t mode = S_IFREG; if ( strcasecmp( type, "F" ) == 0 ) mode = S_IFREG; else if ( strcasecmp( type, "D" ) == 0 ) mode = S_IFDIR; else if ( strcasecmp( type, "L" ) == 0 ) mode = S_IFLNK; else if ( strcasecmp( type, "BlockDev" ) == 0 ) mode = S_IFBLK; else if ( strcasecmp( type, "CharDev" ) == 0 ) mode = S_IFCHR; else if ( strcasecmp( type, "FIFO" ) == 0 ) mode = S_IFIFO; else if ( strcasecmp( type, "Socket" ) == 0 ) mode = S_IFSOCK; // Path if ( *raw_path == '/' ) _lastDir = 0; // Size char * end = 0; FileSize size = strtoll( size_str, &end, 10 ); if ( end ) { switch ( *end ) { case 'K': size *= KB; break; case 'M': size *= MB; break; case 'G': size *= GB; break; case 'T': size *= TB; break; default: break; } } // MTime time_t mtime = strtol( mtime_str, 0, 0 ); // Blocks FileSize blocks = blocks_str ? strtoll( blocks_str, 0, 10 ) : -1; // Links int links = links_str ? atoi( links_str ) : 1; // // Create a new item // QString fullPath = unescapedPath( raw_path ); QString path; QString name; splitPath( fullPath, path, name ); if ( _lastExcludedDir ) { if ( path.startsWith( _lastExcludedDirUrl ) ) { // logDebug() << "Excluding " << path << "/" << name << endl; return; } } // Find parent in tree DirInfo * parent = _lastDir; if ( ! parent && _tree->root() ) { if ( ! _tree->root()->hasChildren() ) parent = _tree->root(); // Try the easy way first - the starting point of this cache if ( ! parent && _toplevel ) parent = dynamic_cast ( _toplevel->locate( path ) ); #if DEBUG_LOCATE_PARENT if ( parent ) logDebug() << "Using cache starting point as parent for " << fullPath << endl; #endif // Fallback: Search the entire tree if ( ! parent ) { parent = dynamic_cast ( _tree->locate( path ) ); #if DEBUG_LOCATE_PARENT if ( parent ) logDebug() << "Located parent " << path << " in tree" << endl; #endif } if ( ! parent ) // Still nothing? { logError() << _fileName << ":" << _lineNo << ": " << "Could not locate parent \"" << path << "\" for " << name << endl; #if DEBUG_LOCATE_PARENT THROW( Exception( "Could not locate cache item parent" ) ); #endif return; // Ignore this cache line completely } } if ( strcasecmp( type, "D" ) == 0 ) { QString url = ( parent == _tree->root() ) ? buildPath( path, name ) : name; #if VERBOSE_CACHE_DIRS logDebug() << "Creating DirInfo for " << url << " with parent " << parent << endl; #endif DirInfo * dir = new DirInfo( _tree, parent, url, mode, size, mtime ); dir->setReadState( DirReading ); _lastDir = dir; if ( parent ) parent->insertChild( dir ); if ( ! _tree->root() ) { _tree->setRoot( dir ); _toplevel = dir; } if ( ! _toplevel ) _toplevel = dir; _tree->childAddedNotify( dir ); if ( dir != _toplevel ) { if ( ExcludeRules::instance()->match( dir->url(), dir->name() ) ) { logDebug() << "Excluding " << name << endl; dir->setExcluded(); dir->setReadState( DirOnRequestOnly ); _tree->sendFinalizeLocal( dir ); dir->finalizeLocal(); _tree->sendReadJobFinished( dir ); _lastExcludedDir = dir; _lastExcludedDirUrl = _lastExcludedDir->url(); _lastDir = 0; } } } else { if ( parent ) { #if VERBOSE_CACHE_FILE_INFOS logDebug() << "Creating FileInfo for " << buildPath( parent->debugUrl(), name ) << endl; #endif FileInfo * item = new FileInfo( _tree, parent, name, mode, size, mtime, blocks, links ); parent->insertChild( item ); _tree->childAddedNotify( item ); } else { logError() << _fileName << ":" << _lineNo << ": " << "No parent for item " << name << endl; } } } bool CacheReader::eof() { if ( ! _ok || ! _cache ) return true; return gzeof( _cache ); } QString CacheReader::firstDir() { while ( ! gzeof( _cache ) && _ok ) { if ( ! readLine() ) return ""; splitLine(); if ( fieldsCount() < 2 ) return ""; int n = 0; char * type = field( n++ ); char * path = field( n++ ); if ( strcasecmp( type, "D" ) == 0 ) return QString( path ); } return ""; } bool CacheReader::checkHeader() { if ( ! _ok || ! readLine() ) return false; // logDebug() << "Checking cache file header" << endl; QString line( _line ); splitLine(); // Check for [qdirstat cache file] // or [kdirstat cache file] if ( fieldsCount() != 4 ) _ok = false; if ( _ok ) { if ( ( strcmp( field( 0 ), "[qdirstat" ) != 0 && strcmp( field( 0 ), "[kdirstat" ) != 0 ) || strcmp( field( 2 ), "cache" ) != 0 || strcmp( field( 3 ), "file]" ) != 0 ) { _ok = false; logError() << _fileName << ":" << _lineNo << ": Unknown file format" << endl; } } if ( _ok ) { QString version = field( 1 ); // currently not checking version number // for future use if ( ! _ok ) logError() << _fileName << ":" << _lineNo << ": Incompatible cache file version" << endl; } // logDebug() << "Cache file header check OK: " << _ok << endl; if ( ! _ok ) emit error(); return _ok; } bool CacheReader::readLine() { if ( ! _ok || ! _cache ) return false; _fieldsCount = 0; do { _lineNo++; if ( ! gzgets( _cache, _buffer, MAX_CACHE_LINE_LEN-1 ) ) { _buffer[0] = 0; _line = _buffer; if ( ! gzeof( _cache ) ) { _ok = false; logError() << _fileName << ":" << _lineNo << ": Read error" << endl; emit error(); } return false; } _line = skipWhiteSpace( _buffer ); killTrailingWhiteSpace( _line ); // logDebug() << "line[ " << _lineNo << "]: \"" << _line<< "\"" << endl; } while ( ! gzeof( _cache ) && ( *_line == 0 || // empty line *_line == '#' ) ); // comment line return true; } void CacheReader::splitLine() { _fieldsCount = 0; if ( ! _ok || ! _line ) return; if ( *_line == '#' ) // skip comment lines *_line = 0; char * current = _line; char * end = _line + strlen( _line ); while ( current && current < end && *current && _fieldsCount < MAX_FIELDS_PER_LINE-1 ) { _fields[ _fieldsCount++ ] = current; current = findNextWhiteSpace( current ); if ( current && current < end ) { *current++ = 0; current = skipWhiteSpace( current ); } } } char * CacheReader::field( int no ) { if ( no >= 0 && no < _fieldsCount ) return _fields[ no ]; else return 0; } char * CacheReader::skipWhiteSpace( char * cptr ) { if ( cptr == 0 ) return 0; while ( *cptr != 0 && isspace( *cptr ) ) cptr++; return cptr; } char * CacheReader::findNextWhiteSpace( char * cptr ) { if ( cptr == 0 ) return 0; while ( *cptr != 0 && ! isspace( *cptr ) ) cptr++; return *cptr == 0 ? 0 : cptr; } void CacheReader::killTrailingWhiteSpace( char * cptr ) { char * start = cptr; if ( cptr == 0 ) return; cptr = start + strlen( start ) -1; while ( cptr >= start && isspace( *cptr ) ) *cptr-- = 0; } void CacheReader::splitPath( const QString & fileNameWithPath, QString & path_ret, QString & name_ret ) const { bool absolutePath = fileNameWithPath.startsWith( "/" ); QStringList components = fileNameWithPath.split( "/", QString::SkipEmptyParts ); if ( components.isEmpty() ) { path_ret = ""; name_ret = absolutePath ? "/" : ""; } else { name_ret = components.takeLast(); path_ret = components.join( "/" ); if ( absolutePath ) path_ret.prepend( "/" ); } } QString CacheReader::buildPath( const QString & path, const QString & name ) const { if ( path.isEmpty() ) return name; else if ( name.isEmpty() ) return path; else if ( path == "/" ) return path + name; else return path + "/" + name; } QString CacheReader::unescapedPath( const QString & rawPath ) const { // Using a protocol part to avoid directory names with a colon ":" // being cut off because it looks like a URL protocol. QString protocol = "foo:"; QString url = protocol + cleanPath( rawPath ); return QUrl::fromEncoded( url.toUtf8() ).path(); } QString CacheReader::cleanPath( const QString & rawPath ) const { QString clean = rawPath; return clean.replace( _multiSlash, "/" ); } void CacheReader::finalizeRecursive( DirInfo * dir ) { if ( dir->readState() != DirOnRequestOnly ) { if ( dir->readState() != DirError ) dir->setReadState( DirCached ); _tree->sendFinalizeLocal( dir ); dir->finalizeLocal(); _tree->sendReadJobFinished( dir ); } FileInfo * child = dir->firstChild(); while ( child ) { if ( child->isDirInfo() ) finalizeRecursive( child->toDirInfo() ); child = child->next(); } } void CacheReader::setReadError( DirInfo * dir ) { logDebug() << "Setting read error for " << dir << endl; while ( dir ) { dir->setReadState( DirError ); if ( dir == _toplevel ) return; dir = dir->parent(); } } qdirstat-1.4/src/DirTreeCache.h000066400000000000000000000147711311502036700164430ustar00rootroot00000000000000/* * File name: DirTreeCache.h * Summary: QDirStat cache reader / writer * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirTreeCache_h #define DirTreeCache_h #include #include #include "DirTree.h" #define DEFAULT_CACHE_NAME ".qdirstat.cache.gz" #define CACHE_FORMAT_VERSION "1.0" #define MAX_CACHE_LINE_LEN 1024 #define MAX_FIELDS_PER_LINE 32 namespace QDirStat { class CacheWriter { public: /** * Write 'tree' to file 'fileName' in gzip format (using zlib). * * Check CacheWriter::ok() to see if writing the cache file went OK. **/ CacheWriter( const QString & fileName, DirTree *tree ); /** * Destructor **/ virtual ~CacheWriter(); /** * Returns true if writing the cache file went OK. **/ bool ok() const { return _ok; } /** * Format a file size as string - with trailing "G", "M", "K" for * "Gigabytes", "Megabytes, "Kilobytes", respectively (provided there * is no fractional part - 27M is OK, 27.2M is not). **/ QString formatSize( FileSize size ); protected: /** * Write cache file in gzip format. * Returns 'true' if OK, 'false' upon error. **/ bool writeCache( const QString & fileName, DirTree *tree ); /** * Write 'item' recursively to cache file 'cache'. * Uses zlib to write gzip-compressed files. **/ void writeTree( gzFile cache, FileInfo * item ); /** * Write 'item' to cache file 'cache' without recursion. * Uses zlib to write gzip-compressed files. **/ void writeItem( gzFile cache, FileInfo * item ); /** * Return the 'path' in an URL-encoded form, i.e. with some special * characters escaped in percent notation (" " -> "%20"). **/ QByteArray urlEncoded( const QString & path ); // // Data members // bool _ok; }; class CacheReader: public QObject { Q_OBJECT public: /** * Begin reading cache file 'fileName'. The cache file remains open * until this object is destroyed. **/ CacheReader( const QString & fileName, DirTree * tree, DirInfo * parent = 0 ); /** * Destructor **/ virtual ~CacheReader(); /** * Read at most maxLines from the cache file (check with eof() if the * end of file is reached yet) or the entire file (if maxLines is 0). * * Returns true if OK and there is more to read, false otherwise. **/ bool read( int maxLines = 0 ); /** * Returns true if the end of the cache file is reached (or if there * was an error). **/ bool eof(); /** * Returns true if writing the cache file went OK. **/ bool ok() const { return _ok; } /** * Resets the reader so all data lines of the cache can be read with * subsequent read() calls. **/ void rewind(); /** * Returns the absolute path of the first directory in this cache file * or an empty string if there is none. * * This method expects the cache file to be just opened without any * previous read() operations on the file. If this is not the case, * call rewind() immediately before firstDir(). * * After firstDir(), some records of the cache file will be read. * Make sure to call rewind() if you intend to read from this cache * file afterwards. **/ QString firstDir(); /** * Returns the tree associated with this reader. **/ DirTree * tree() const { return _tree; } /** * Skip leading whitespace from a string. * Returns a pointer to the first character that is non-whitespace. **/ static char * skipWhiteSpace( char * cptr ); /** * Find the next whitespace in a string. * * Returns a pointer to the next whitespace character * or a null pointer if there is no more whitespace in the string. **/ static char * findNextWhiteSpace( char * cptr ); /** * Remove all trailing whitespace from a string - overwrite it with 0 * bytes. * * Returns the new string length. **/ static void killTrailingWhiteSpace( char * cptr ); signals: /** * Emitted when a child has been added. **/ void childAdded( FileInfo *newChild ); /** * Emitted when reading this cache is finished. **/ void finished(); /** * Emitted if there is a read error. **/ void error(); protected: /** * Check this cache's header (see if it is a QDirStat cache at all) **/ bool checkHeader(); /** * Use _fields to add one item to _tree. **/ void addItem(); /** * Read the next line that is not empty or a comment and store it in * _line. * * Returns true if OK, false if error. **/ bool readLine(); /** * split the current input line into fields separated by whitespace. **/ void splitLine(); /** * Returns the start of field no. 'no' in the current input line * after splitLine(). **/ char * field( int no ); /** * Split up a file name with path into its path and its name component * and return them in path_ret and name_ret, respectively. * * Example: * "/some/dir/somewhere/myfile.obj" * -> "/some/dir/somewhere", "myfile.obj" **/ void splitPath( const QString & fileNameWithPath, QString & path_ret, QString & name_ret ) const; /** * Build a full path from path + file name (without path). **/ QString buildPath( const QString & path, const QString & name ) const; /** * Return an unescaped version of 'rawPath'. **/ QString unescapedPath( const QString & rawPath ) const; /** * Clean a path: Replace duplicate (or triplicate or more) slashes with * just one. QUrl doesn't seem to handle those well. **/ QString cleanPath( const QString & rawPath ) const; /** * Returns the number of fields in the current input line after * splitLine(). **/ int fieldsCount() const { return _fieldsCount; } /** * Recursively set the read status of all dirs from 'dir' on, send tree * signals and finalize local (i.e. clean up empty or unneded dot * entries). **/ void finalizeRecursive( DirInfo * dir ); /** * Cascade a read error up to the toplevel directory node read by this * cache file. **/ void setReadError( DirInfo * dir ); // // Data members // DirTree * _tree; gzFile _cache; char _buffer[ MAX_CACHE_LINE_LEN ]; char * _line; int _lineNo; QString _fileName; char * _fields[ MAX_FIELDS_PER_LINE ]; int _fieldsCount; bool _ok; int _errorCount; DirInfo * _toplevel; DirInfo * _lastDir; DirInfo * _lastExcludedDir; QString _lastExcludedDirUrl; QRegExp _multiSlash; }; } // namespace QDirStat #endif // ifndef DirTreeCache_h qdirstat-1.4/src/DirTreeModel.cpp000066400000000000000000000600121311502036700170200ustar00rootroot00000000000000/* * File name: DirTreeModel.cpp * Summary: Qt data model for directory tree * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "DirTreeModel.h" #include "DirTree.h" #include "FileInfoIterator.h" #include "DataColumns.h" #include "SelectionModel.h" #include "Settings.h" #include "Logger.h" #include "Exception.h" #include "DebugHelpers.h" using namespace QDirStat; DirTreeModel::DirTreeModel( QObject * parent ): QAbstractItemModel( parent ), _tree(0), _selectionModel(0), _readJobsCol( PercentBarCol ), _updateTimerMillisec( 333 ), _slowUpdateMillisec( 3000 ), _slowUpdate( false ), _sortCol( NameCol ), _sortOrder( Qt::AscendingOrder ) { createTree(); readSettings(); loadIcons(); _updateTimer.setInterval( _updateTimerMillisec ); connect( &_updateTimer, SIGNAL( timeout() ), this, SLOT ( sendPendingUpdates() ) ); } DirTreeModel::~DirTreeModel() { writeSettings(); if ( _tree ) delete _tree; } void DirTreeModel::readSettings() { Settings settings; settings.beginGroup( "DirectoryTree" ); _tree->setCrossFileSystems( settings.value( "CrossFileSystems", false ).toBool() ); _treeIconDir = settings.value( "TreeIconDir" , ":/icons/tree-medium/" ).toString(); _updateTimerMillisec = settings.value( "UpdateTimerMillisec", 333 ).toInt(); _slowUpdateMillisec = settings.value( "SlowUpdateMillisec", 3000 ).toInt(); settings.endGroup(); } void DirTreeModel::writeSettings() { Settings settings; settings.beginGroup( "DirectoryTree" ); settings.setValue( "CrossFileSystems", _tree ? _tree->crossFileSystems() : false ); settings.setValue( "TreeIconDir" , _treeIconDir ); settings.setValue( "UpdateTimerMillisec", _updateTimerMillisec ); settings.setValue( "SlowUpdateMillisec", _slowUpdateMillisec ); settings.endGroup(); } void DirTreeModel::setSlowUpdate( bool slow ) { _slowUpdate = slow; _updateTimer.setInterval( _slowUpdate ? _slowUpdateMillisec : _updateTimerMillisec ); if ( slow ) logInfo() << "Display update every " << _updateTimer.interval() << " millisec" << endl; } void DirTreeModel::createTree() { _tree = new DirTree(); CHECK_NEW( _tree ); connect( _tree, SIGNAL( startingReading() ), this, SLOT ( busyDisplay() ) ); connect( _tree, SIGNAL( finished() ), this, SLOT ( readingFinished() ) ); connect( _tree, SIGNAL( aborted() ), this, SLOT ( readingFinished() ) ); connect( _tree, SIGNAL( readJobFinished( DirInfo * ) ), this, SLOT ( readJobFinished( DirInfo * ) ) ); connect( _tree, SIGNAL( deletingChild( FileInfo * ) ), this, SLOT ( deletingChild( FileInfo * ) ) ); connect( _tree, SIGNAL( clearingSubtree( DirInfo * ) ), this, SLOT ( clearingSubtree( DirInfo * ) ) ); connect( _tree, SIGNAL( subtreeCleared( DirInfo * ) ), this, SLOT ( subtreeCleared( DirInfo * ) ) ); connect( _tree, SIGNAL( childDeleted() ), this, SLOT ( childDeleted() ) ); } void DirTreeModel::clear() { if ( _tree ) { beginResetModel(); // logDebug() << "After beginResetModel()" << endl; // dumpPersistentIndexList(); _tree->clear(); endResetModel(); // logDebug() << "After endResetModel()" << endl; // dumpPersistentIndexList(); } } void DirTreeModel::openUrl( const QString &url ) { CHECK_PTR( _tree ); if ( _tree->root() && _tree->root()->hasChildren() ) clear(); _updateTimer.start(); _tree->startReading( url ); } void DirTreeModel::loadIcons() { if ( _treeIconDir.isEmpty() ) { logWarning() << "No tree icons" << endl; return; } if ( ! _treeIconDir.endsWith( "/" ) ) _treeIconDir += "/"; _dirIcon = QPixmap( _treeIconDir + "dir.png" ); _dotEntryIcon = QPixmap( _treeIconDir + "dot-entry.png" ); _fileIcon = QPixmap( _treeIconDir + "file.png" ); _symlinkIcon = QPixmap( _treeIconDir + "symlink.png" ); _unreadableDirIcon = QPixmap( _treeIconDir + "unreadable-dir.png" ); _mountPointIcon = QPixmap( _treeIconDir + "mount-point.png" ); _stopIcon = QPixmap( _treeIconDir + "stop.png" ); _excludedIcon = QPixmap( _treeIconDir + "excluded.png" ); _blockDeviceIcon = QPixmap( _treeIconDir + "block-device.png" ); _charDeviceIcon = QPixmap( _treeIconDir + "char-device.png" ); _specialIcon = QPixmap( _treeIconDir + "special.png" ); } void DirTreeModel::setColumns( const DataColumnList & columns ) { beginResetModel(); DataColumns::instance()->setColumns( columns ); endResetModel(); } FileInfo * DirTreeModel::findChild( DirInfo * parent, int childNo ) const { CHECK_PTR( parent ); const FileInfoList & childrenList = parent->sortedChildren( _sortCol, _sortOrder ); if ( childNo < 0 || childNo >= childrenList.size() ) { logError() << "Child #" << childNo << " is out of range: 0.." << childrenList.size()-1 << " children for " << parent << endl; Debug::dumpChildrenList( parent, childrenList ); return 0; } // Debug::dumpChildrenList( parent, childrenList ); return childrenList.at( childNo ); } int DirTreeModel::rowNumber( FileInfo * child ) const { if ( ! child->parent() ) return 0; const FileInfoList & childrenList = child->parent()->sortedChildren( _sortCol, _sortOrder ); int row = childrenList.indexOf( child ); if ( row < 0 ) { // Not found logError() << "Child " << child << " (" << (void *) child << ")" << " not found in \"" << child->parent() << "\"" << endl; Debug::dumpDirectChildren( child->parent() ); } return row; } int DirTreeModel::countDirectChildren( FileInfo * parent ) const { FileInfoIterator it( parent ); return it.count(); } // // Reimplented from QAbstractItemModel // int DirTreeModel::rowCount( const QModelIndex &parentIndex ) const { if ( ! _tree ) return 0; int count = 0; FileInfo * item = 0; if ( parentIndex.isValid() ) { item = static_cast( parentIndex.internalPointer() ); CHECK_MAGIC( item ); } else item = _tree->root(); if ( ! item->isDirInfo() ) return 0; if ( item->toDirInfo()->isLocked() ) { // logDebug() << item << " is locked - returning 0" << endl; return 0; } switch ( item->readState() ) { case DirQueued: count = 0; // Nothing yet break; case DirReading: // Don't mess with directories that are currently being read: If we // tell our view about them, the view might begin fetching model // indexes for them, and when the tree later sends the // readJobFinished() signal, the beginInsertRows() call in our // readJobFinished() slot will confuse the view; it would assume // that the number of children reported in that beginInsertRows() // call needs to be added to the number reported here. We'd have to // keep track how many children we already reported, and how many // new ones to report later. // // Better keep it simple: Don't report any children until they // are complete. count = 0; break; case DirError: // This is a hybrid case: Depending on the dir reader, the dir may // or may not be finished at this time. For a local dir, it most // likely is; for a cache reader, there might be more to come. if ( _tree->isBusy() ) count = 0; else count = countDirectChildren( item ); break; case DirFinished: case DirOnRequestOnly: case DirCached: case DirAborted: count = countDirectChildren( item ); break; // intentionally omitting 'default' case so the compiler can report // missing enum values } // logDebug() << dirName << ": " << count << endl; return count; } int DirTreeModel::columnCount( const QModelIndex &parent ) const { Q_UNUSED( parent ); return DataColumns::instance()->colCount(); } QVariant DirTreeModel::data( const QModelIndex &index, int role ) const { if ( ! index.isValid() ) return QVariant(); DataColumn col = DataColumns::fromViewCol( index.column() ); switch ( role ) { case Qt::DisplayRole: { FileInfo * item = static_cast( index.internalPointer() ); CHECK_PTR( item ); CHECK_MAGIC( item ); QVariant result = columnText( item, col ); if ( item && item->isDirInfo() ) { // logDebug() << "Touching " << col << "\tof " << item << endl; item->toDirInfo()->touch(); } return result; } case Qt::DecorationRole: { FileInfo * item = static_cast( index.internalPointer() ); CHECK_MAGIC( item ); QVariant result = columnIcon( item, col ); return result; } case Qt::TextAlignmentRole: { int alignment = Qt::AlignVCenter; switch ( col ) { case PercentBarCol: case PercentNumCol: case TotalSizeCol: case OwnSizeCol: case TotalItemsCol: case TotalFilesCol: case TotalSubDirsCol: alignment |= Qt::AlignRight; break; case NameCol: case LatestMTimeCol: default: alignment |= Qt::AlignLeft; break; } return alignment; } case RawDataRole: // Send raw data to our item delegate (the PercentBarDelegate) { FileInfo * item = static_cast( index.internalPointer() ); CHECK_PTR( item ); CHECK_MAGIC( item ); switch ( col ) { case NameCol: return item->name(); case PercentBarCol: { if ( ( item->parent() && item->parent()->isBusy() ) || item == _tree->firstToplevel() ) { return -1.0; } else { return item->subtreePercent(); } } case PercentNumCol: return item->subtreePercent(); case TotalSizeCol: return item->totalSize(); case OwnSizeCol: return item->size(); case TotalItemsCol: return item->totalItems(); case TotalFilesCol: return item->totalFiles(); case TotalSubDirsCol: return item->totalSubDirs(); case LatestMTimeCol: return (qulonglong) item->latestMtime(); default: return QVariant(); } } default: return QVariant(); } /*NOTREACHED*/ return QVariant(); } QVariant DirTreeModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation != Qt::Horizontal ) return QVariant(); switch ( role ) { case Qt::DisplayRole: switch ( DataColumns::fromViewCol( section ) ) { case NameCol: return tr( "Name" ); case PercentBarCol: return tr( "Subtree Percentage" ); case PercentNumCol: return tr( "Percentage" ); case TotalSizeCol: return tr( "Subtree Total" ); case OwnSizeCol: return tr( "Own Size" ); case TotalItemsCol: return tr( "Items" ); case TotalFilesCol: return tr( "Files" ); case TotalSubDirsCol: return tr( "Subdirs" ); case LatestMTimeCol: return tr( "Last Modified" ); default: return QVariant(); } case Qt::TextAlignmentRole: return Qt::AlignLeft; default: return QVariant(); } } Qt::ItemFlags DirTreeModel::flags( const QModelIndex &index ) const { if ( ! index.isValid() ) return Qt::NoItemFlags; FileInfo * item = static_cast( index.internalPointer() ); CHECK_PTR( item ); CHECK_MAGIC( item ); Qt::ItemFlags baseFlags = Qt::ItemIsEnabled; #if (QT_VERSION >= QT_VERSION_CHECK( 5, 1, 0 )) if ( ! item->isDirInfo() ) baseFlags |= Qt::ItemNeverHasChildren; #endif // logDebug() << "Flags for " << index << endl; DataColumn col = DataColumns::fromViewCol( index.column() ); switch ( col ) { case PercentBarCol: return baseFlags; default: return baseFlags | Qt::ItemIsSelectable; } } QModelIndex DirTreeModel::index( int row, int column, const QModelIndex & parentIndex ) const { if ( ! _tree || ! _tree->root() || ! hasIndex( row, column, parentIndex ) ) return QModelIndex(); FileInfo *parent; if ( parentIndex.isValid() ) { parent = static_cast( parentIndex.internalPointer() ); CHECK_MAGIC( parent ); } else parent = _tree->root(); if ( parent->isDirInfo() ) { FileInfo * child = findChild( parent->toDirInfo(), row ); CHECK_PTR( child ); if ( child ) return createIndex( row, column, child ); } return QModelIndex(); } QModelIndex DirTreeModel::parent( const QModelIndex &index ) const { if ( ! index.isValid() ) return QModelIndex(); FileInfo * child = static_cast( index.internalPointer() ); CHECK_PTR( child ); CHECK_MAGIC( child ); FileInfo * parent = child->parent(); CHECK_PTR( parent ); if ( ! parent || parent == _tree->root() ) return QModelIndex(); int row = rowNumber( parent ); // logDebug() << "Parent of " << child << " is " << parent << " #" << row << endl; return createIndex( row, 0, parent ); } void DirTreeModel::sort( int column, Qt::SortOrder order ) { logDebug() << "Sorting by " << static_cast( column ) << ( order == Qt::AscendingOrder ? " ascending" : " descending" ) << endl; // logDebug() << "Before layoutAboutToBeChanged()" << endl; // dumpPersistentIndexList(); emit layoutAboutToBeChanged(); _sortCol = DataColumns::fromViewCol( column ); _sortOrder = order; updatePersistentIndexes(); emit layoutChanged(); // logDebug() << "After layoutChanged()" << endl; // dumpPersistentIndexList(); } //--------------------------------------------------------------------------- void DirTreeModel::busyDisplay() { emit layoutAboutToBeChanged(); _sortCol = NameCol; // logDebug() << "Sorting by " << _sortCol << " during reading" << endl; updatePersistentIndexes(); emit layoutChanged(); } void DirTreeModel::idleDisplay() { emit layoutAboutToBeChanged(); _sortCol = PercentNumCol; // logDebug() << "Sorting by " << _sortCol << " after reading is finished" << endl; updatePersistentIndexes(); emit layoutChanged(); } QModelIndex DirTreeModel::modelIndex( FileInfo * item, int column ) const { CHECK_PTR( _tree ); CHECK_PTR( _tree->root() ); if ( ! item || ! item->checkMagicNumber() || item == _tree->root() ) return QModelIndex(); else { int row = rowNumber( item ); // logDebug() << item << " is row #" << row << " of " << item->parent() << endl; return row < 0 ? QModelIndex() : createIndex( row, column, item ); } } QVariant DirTreeModel::columnText( FileInfo * item, int col ) const { CHECK_PTR( item ); if ( col == _readJobsCol && item->isBusy() ) return tr( "[%1 Read Jobs]" ).arg( item->pendingReadJobs() ); switch ( col ) { case NameCol: return item->name(); case PercentBarCol: return item->isExcluded() ? tr( "[Excluded]" ) : QVariant(); case OwnSizeCol: return ownSizeColText( item ); case PercentNumCol: return item == _tree->firstToplevel() ? QVariant() : formatPercent( item->subtreePercent() ); case LatestMTimeCol: return formatTime( item->latestMtime() ); } if ( item->isDirInfo() || item->isDotEntry() ) { QString prefix = item->readState() == DirAborted ? ">" : ""; switch ( col ) { case TotalSizeCol: return prefix + formatSize( item->totalSize() ); case TotalItemsCol: return prefix + QString( "%1" ).arg( item->totalItems() ); case TotalFilesCol: return prefix + QString( "%1" ).arg( item->totalFiles() ); case TotalSubDirsCol: if ( item->isDotEntry() ) return QVariant(); else return prefix + QString( "%1" ).arg( item->totalSubDirs() ); } } return QVariant(); } QVariant DirTreeModel::ownSizeColText( FileInfo * item ) const { if ( item->isDevice() || item->isDotEntry() ) return QVariant(); QString text; if ( item->isFile() && ( item->links() > 1 ) ) // Regular file with multiple links { if ( item->isSparseFile() ) { text = tr( "%1 / %2 Links (allocated: %3)" ) .arg( formatSize( item->byteSize() ) ) .arg( formatSize( item->links() ) ) .arg( formatSize( item->allocatedSize() ) ); } else { text = tr( "%1 / %2 Links" ) .arg( formatSize( item->byteSize() ) ) .arg( item->links() ); } } else // No multiple links or no regular file { if ( item->isSparseFile() ) { text = tr( "%1 (allocated: %2)" ) .arg( formatSize( item->byteSize() ) ) .arg( formatSize( item->allocatedSize() ) ); } else { text = formatSize( item->size() ); } } return text; } QVariant DirTreeModel::columnIcon( FileInfo * item, int col ) const { if ( col != NameCol ) return QVariant(); QPixmap icon; if ( item->isDotEntry() ) icon = _dotEntryIcon; else if ( item->isExcluded() ) icon = _excludedIcon; else if ( item->isDir() ) { if ( item->readState() == DirAborted ) icon = _stopIcon; else if ( item->readState() == DirError ) icon = _unreadableDirIcon; else if ( item->isMountPoint() ) icon = _mountPointIcon; else icon = _dirIcon; } else // ! item->isDir() { if ( item->readState() == DirError ) icon = _unreadableDirIcon; else if ( item->isFile() ) icon = _fileIcon; else if ( item->isSymLink() ) icon = _symlinkIcon; else if ( item->isBlockDevice() ) icon = _blockDeviceIcon; else if ( item->isCharDevice() ) icon = _charDeviceIcon; else if ( item->isSpecial() ) icon = _specialIcon; } return icon.isNull() ? QVariant() : icon; } void DirTreeModel::readJobFinished( DirInfo * dir ) { // logDebug() << dir << endl; delayedUpdate( dir ); if ( anyAncestorBusy( dir ) ) { logDebug() << "Ancestor busy - ignoring readJobFinished for " << dir << endl; } else { newChildrenNotify( dir ); } } bool DirTreeModel::anyAncestorBusy( FileInfo * item ) const { while ( item ) { if ( item->readState() == DirQueued || item->readState() == DirReading ) { return true; } item = item->parent(); } return false; } void DirTreeModel::newChildrenNotify( DirInfo * dir ) { // logDebug() << dir << endl; if ( ! dir ) { logError() << "NULL DirInfo *" << endl; return; } if ( ! dir->isTouched() && dir != _tree->root() && dir != _tree->firstToplevel() ) { // logDebug() << "Remaining silent about untouched dir " << dir << endl; return; } QModelIndex index = modelIndex( dir ); int count = countDirectChildren( dir ); // Debug::dumpDirectChildren( dir ); if ( count > 0 ) { // logDebug() << "Notifying view about " << count << " new children of " << dir << endl; dir->lock(); beginInsertRows( index, 0, count - 1 ); dir->unlock(); endInsertRows(); } // If any readJobFinished signals were ignored because a parent was not // finished yet, now is the time to notify the view about those children, // too. FileInfoIterator it( dir ); while ( *it ) { if ( (*it)->isDirInfo() && (*it)->readState() != DirReading && (*it)->readState() != DirQueued ) { newChildrenNotify( (*it)->toDirInfo() ); } ++it; } } void DirTreeModel::delayedUpdate( DirInfo * dir ) { while ( dir && dir != _tree->root() ) { if ( dir->isTouched() ) _pendingUpdates.insert( dir ); dir = dir->parent(); } } void DirTreeModel::sendPendingUpdates() { // logDebug() << "Sending " << _pendingUpdates.size() << " updates" << endl; foreach ( DirInfo * dir, _pendingUpdates ) { dataChangedNotify( dir ); } _pendingUpdates.clear(); } void DirTreeModel::dataChangedNotify( DirInfo * dir ) { if ( ! dir || dir == _tree->root() ) return; if ( dir->isTouched() ) // only if the view ever requested data about this dir { QModelIndex topLeft = modelIndex( dir, 0 ); QModelIndex bottomRight = createIndex( topLeft.row(), DataColumns::instance()->colCount() - 1, dir ); #if (QT_VERSION < QT_VERSION_CHECK( 5, 1, 0)) emit dataChanged( topLeft, bottomRight ); #else QVector roles; roles << Qt::DisplayRole; emit dataChanged( topLeft, bottomRight, roles ); #endif // logDebug() << "Data changed for " << dir << endl; // If the view is still interested in this dir, it will fetch data, and // then the dir will be touched again. For all we know now, this dir // might easily be out of scope for the view, so let's not bother the // view again about this dir until it's clear that the view still wants // updates about it. dir->clearTouched(); } } void DirTreeModel::readingFinished() { _updateTimer.stop(); idleDisplay(); sendPendingUpdates(); // dumpPersistentIndexList(); // Debug::dumpDirectChildren( _tree->root(), "root" ); } void DirTreeModel::dumpPersistentIndexList() const { QModelIndexList persistentList = persistentIndexList(); logDebug() << persistentList.size() << " persistent indexes" << endl; for ( int i=0; i < persistentList.size(); ++i ) { QModelIndex index = persistentList.at(i); FileInfo * item = static_cast( index.internalPointer() ); CHECK_MAGIC( item ); logDebug() << "#" << i << " Persistent index " << index << endl; } } void DirTreeModel::updatePersistentIndexes() { QModelIndexList persistentList = persistentIndexList(); for ( int i=0; i < persistentList.size(); ++i ) { QModelIndex oldIndex = persistentList.at(i); if ( oldIndex.isValid() ) { FileInfo * item = static_cast( oldIndex.internalPointer() ); QModelIndex newIndex = modelIndex( item, oldIndex.column() ); #if 0 logDebug() << "Updating #" << i << " " << item << " col " << oldIndex.column() << " row " << oldIndex.row() << " --> " << newIndex.row() << endl; #endif changePersistentIndex( oldIndex, newIndex ); } } } void DirTreeModel::deletingChild( FileInfo * child ) { logDebug() << "Deleting child " << child << endl; if ( child->parent() && ( child->parent() == _tree->root() || child->parent()->isTouched() ) ) { QModelIndex parentIndex = modelIndex( child->parent(), 0 ); int row = rowNumber( child ); logDebug() << "beginRemoveRows for " << child << " row " << row << endl; beginRemoveRows( parentIndex, row, row ); } invalidatePersistent( child, true ); } void DirTreeModel::childDeleted() { logDebug() << "endRemoveRows()" << endl; endRemoveRows(); } void DirTreeModel::clearingSubtree( DirInfo * subtree ) { // logDebug() << "Deleting all children of " << subtree << endl; if ( subtree == _tree->root() || subtree->isTouched() ) { QModelIndex subtreeIndex = modelIndex( subtree, 0 ); int count = countDirectChildren( subtree ); if ( count > 0 ) { // logDebug() << "beginRemoveRows for " << subtree << " row 0 to " << count - 1 << endl; beginRemoveRows( subtreeIndex, 0, count - 1 ); } } invalidatePersistent( subtree, false ); } void DirTreeModel::subtreeCleared( DirInfo * subtree ) { Q_UNUSED( subtree ); // logDebug() << "endRemoveRows()" << endl; endRemoveRows(); } void DirTreeModel::invalidatePersistent( FileInfo * subtree, bool includeParent ) { foreach ( const QModelIndex & index, persistentIndexList() ) { FileInfo * item = static_cast( index.internalPointer() ); CHECK_PTR( item ); if ( ! item->checkMagicNumber() || item->isInSubtree( subtree ) ) { if ( item != subtree || includeParent ) { #if 1 logDebug() << "Invalidating " << index << endl; #endif changePersistentIndex( index, QModelIndex() ); } } } } QVariant DirTreeModel::formatPercent( float percent ) const { if ( percent < 0.0 ) // Invalid percentage? return QVariant(); QString text; text.sprintf( "%.1f%%", percent ); return text; } void DirTreeModel::refreshSelected() { CHECK_PTR( _selectionModel ); FileInfo * sel = _selectionModel->selectedItems().first(); if ( sel && sel->isDirInfo() ) { logDebug() << "Refreshing " << sel << endl; busyDisplay(); _tree->refresh( sel->toDirInfo() ); } else { logWarning() << "NOT refreshing " << sel << endl; } } qdirstat-1.4/src/DirTreeModel.h000066400000000000000000000274571311502036700165050ustar00rootroot00000000000000/* * File name: DirTreeModel.h * Summary: Qt data model for directory tree * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirTreeModel_h #define DirTreeModel_h #include #include #include #include #include #include "DataColumns.h" #include "FileInfo.h" namespace QDirStat { class DirTree; class DirInfo; class SelectionModel; enum CustomRoles { RawDataRole = Qt::UserRole }; class DirTreeModel: public QAbstractItemModel { Q_OBJECT public: /** * Constructor. * * 'parent' is just the parent in the QObject / QWidget hierarchy that * will take of deleting this model upon shutdown. It is typically NOT * the corresponding view. As a matter of fact, there might be any * number of views connected. **/ DirTreeModel( QObject * parent = 0 ); /** * Destructor. **/ virtual ~DirTreeModel(); /** * Returns the internal @ref DirTree this view works on. * * Handle with caution: This might be short-lived information. The * model might choose to create a new tree shortly after returning * this, so don't store this pointer internally. **/ DirTree *tree() { return _tree; } /** * Set the column order and what columns to display. * * Example: * * DataColumnList col; * col << QDirStat::NameCol, * << QDirStat::PercentBarCol, * << QDirStat::PercentNumCol, * << QDirStat::TotalSizeCol; * dirTreeModel->setColumns( col ); */ void setColumns( const DataColumnList & columns ); /** * This is protected in the base class, but it's the only reasonable * way for the view to figure out what items are expanded: The * QTreeViewPrivate knows, but IT DOESN'T TELL that secret. * * Trolltech, you fucked up big time here. Seriously, that QTreeView is * the most limiting tree widget you ever made. It's a far cry of the * Qt3 QListView: It can't do shit. No wonder all apps using it suffer * from poor usability! No way to set a separate icon for expanded * vs. collapsed items, no way to close all branches except the current * one. * * I am not going to reimplement all that stuff the private class * already does. Seriously, life is too short for that kind of * bullshit. I am not going to do my own bookkeeping based on * expanded() and collapsed() signals and always suffer from not * receiving the odd one and being out of sync with lists that are kept * in the private class. No fucking way. * * Trolls, if you ever actually used your own stuff like you did in the * old days before you abandoned the X11 widgets and spent all your * time and energy on that QML crap, you'd know that this QTreeView is * a sorry excuse for the old QListView. * * Didn't it ever occur to you that if you are constantly using * d->expandedIndexes in your QTreeView.cpp, derived classes might have * the same need to know about that? Why hide it in the private class * if it's that obvious that this is frequently needed information? * * It doesn't happen often in Qt - in all other aspects, it's a great, * well thought-out and very practical oriented framework. But * QTreeView is poorly designed in many aspects; hiding this * d->expandedIndexes is just one example. * * OK, I'm fed up with working around this poor design. Let's make our * own kludge to find out what items are expanded: Check the persisten * model indexes: The private class creates a persistend model index * for each item that is expanded. **/ QModelIndexList persistentIndexList() const { return QAbstractItemModel::persistentIndexList(); } public slots: /** * Open a directory URL. **/ void openUrl( const QString &url ); /** * Clear this view's contents. **/ void clear(); /** * Debugging: Dump list of persistent model indexes to the log. **/ void dumpPersistentIndexList() const; /** * Read parameters from settings file. **/ void readSettings(); /** * Write parameters to settings file. **/ void writeSettings(); /** * Return this data model's selection model. * * The data model doesn't strictly need a selection model, but certain * operations it provides (like refreshSelected()) do. **/ SelectionModel * selectionModel() const { return _selectionModel; } /** * Set the selection model. This is required for all methods with * '..Selected()' in their name. **/ void setSelectionModel( SelectionModel * selModel ) { _selectionModel = selModel; } /** * Refresh the selected items: Re-read their contents from disk. * This requires a selection model to be set. **/ void refreshSelected(); /** * Set the update speed to slow (3 sec instead of 333 millisec). **/ void setSlowUpdate( bool slow = true ); /** * Return the slow update flag. **/ bool slowUpdate() const { return _slowUpdate; } public: // Mapping of tree items to model rows and vice versa. // // This is in the model and not in the FileInfo class to encapsulate // handling of the "dot entry". In this case, it is handled as a // separate subdirectory. But this might change in the future, or it // might even become configurable. /** * Find the child number 'childNo' among the children of 'parent'. * Return 0 if not found. **/ FileInfo * findChild( DirInfo * parent, int childNo ) const; /** * Find the row number (the index, starting with 0) of 'child' among * its parent's children. **/ int rowNumber( FileInfo * child ) const; /** * Count the direct children (including the "dot entry") of 'parent'. **/ int countDirectChildren( FileInfo * parent ) const; /** * Return a model index for 'item' and 'column'. **/ QModelIndex modelIndex( FileInfo * item, int column = 0 ) const; /** * Return the current sort column. **/ DataColumn sortColumn() const { return _sortCol; } /** * Return the current sort order * (Qt::AscendingOrder or Qt::DescendingOrder). **/ Qt::SortOrder sortOrder() const { return _sortOrder; } // // Reimplented from QAbstractItemModel: // /** * Return the number of rows (direct tree children) for 'parent'. **/ virtual int rowCount ( const QModelIndex & parent ) const Q_DECL_OVERRIDE; /** * Return the number of columns for 'parent'. **/ virtual int columnCount( const QModelIndex & parent ) const Q_DECL_OVERRIDE; /** * Return data to be displayed for the specified model index and role. **/ virtual QVariant data( const QModelIndex & index, int role ) const Q_DECL_OVERRIDE; /** * Return header data (in this case: column header texts) for the * specified section (column number). **/ virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const Q_DECL_OVERRIDE; /** * Return item flags for the specified model index. This specifies if * the item can be selected, edited etc. **/ virtual Qt::ItemFlags flags( const QModelIndex &index ) const Q_DECL_OVERRIDE; /** * Return the model index for the specified row (direct tree child * number) and column of item 'parent'. **/ virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const Q_DECL_OVERRIDE; /** * Return the parent model index of item 'index'. **/ virtual QModelIndex parent( const QModelIndex & index ) const Q_DECL_OVERRIDE; /** * Sort the model. **/ virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) Q_DECL_OVERRIDE; protected slots: /** * Fix up sort order while reading: Sort by read jobs if the sort * column is the PercentBarCol. **/ void busyDisplay(); /** * Fix up sort order after reading is finished: No longer Sort by read * jobs if the sort column is the PercentBarCol. **/ void idleDisplay(); /** * Process notification that the read job for 'dir' is finished. * Other read jobs might still be pending. **/ void readJobFinished( DirInfo *dir ); /** * Process notification that reading the dir tree is completely * finished. **/ void readingFinished(); /** * Delayed update of the data fields in the view for 'dir': * Store 'dir' and all its ancestors in _pendingUpdates. * * The updates will be sent several times per second to the views with * 'sendPendingUpdates()'. **/ void delayedUpdate( DirInfo * dir ); /** * Send all pending updates to the connected views. * This is triggered by the update timer. **/ void sendPendingUpdates(); /** * Notification that a subtree is about to be deleted. **/ void deletingChild( FileInfo * child ); /** * Notification that deleting a subtree is done. **/ void childDeleted(); /** * Notification that a subtree is about to be cleared. **/ void clearingSubtree( DirInfo * subtree ); /** * Notification that clearing a subtree is done. **/ void subtreeCleared( DirInfo * subtree ); /** * Invalidate all persistent indexes in 'subtree'. 'includeParent' * indicates if 'subtree' itself will become invalid. **/ void invalidatePersistent( FileInfo * subtree, bool includeParent ); protected: /** * Create a new tree (and delete the old one if there is one) **/ void createTree(); /** * Load all required icons. **/ void loadIcons(); /** * Notify the view (with beginInsertRows() and endInsertRows()) about * new children (all the children of 'dir'). This might become * recursive if any of those children in turn are already finished. **/ void newChildrenNotify( DirInfo * dir ); /** * Notify the view about changed data of 'dir'. **/ void dataChangedNotify( DirInfo * dir ); /** * Update the persistent indexes with current row after sorting etc. **/ void updatePersistentIndexes(); /** * Return 'true' if 'item' or any ancestor (parent or parent's parent * etc.) is still busy, i.e. the read job for the directory itself (not * any children!) is still queued or currently reading. **/ bool anyAncestorBusy( FileInfo * item ) const; /** * Return the text for (model) column 'col' for 'item'. **/ QVariant columnText( FileInfo * item, int col ) const; /** * Return the icon for (model) column 'col' for 'item'. **/ QVariant columnIcon( FileInfo * item, int col ) const; /** * Return the text for the own size column for 'item' **/ QVariant ownSizeColText( FileInfo * item ) const; /** * Format a percentage value as string if it is non-negative. * Return QVariant() if it is negative. **/ QVariant formatPercent( float percent ) const; // // Data members // DirTree * _tree; SelectionModel * _selectionModel; QString _treeIconDir; int _readJobsCol; QSet _pendingUpdates; QTimer _updateTimer; int _updateTimerMillisec; int _slowUpdateMillisec; bool _slowUpdate; DataColumn _sortCol; Qt::SortOrder _sortOrder; // The various icons QPixmap _dirIcon; QPixmap _dotEntryIcon; QPixmap _fileIcon; QPixmap _symlinkIcon; QPixmap _unreadableDirIcon; QPixmap _mountPointIcon; QPixmap _stopIcon; QPixmap _excludedIcon; QPixmap _blockDeviceIcon; QPixmap _charDeviceIcon; QPixmap _specialIcon; }; // class DirTreeModel /** * Print a QModelIndex of this model in text form to a debug stream. **/ inline QTextStream & operator<< ( QTextStream & stream, const QModelIndex & index ) { if ( ! index.isValid() ) stream << ""; else { FileInfo * item = static_cast( index.internalPointer() ); stream << "checkMagicNumber() ) stream << " "; else stream << " " << item; stream << " >"; } return stream; } } // namespace QDirStat #endif // DirTreeModel_h qdirstat-1.4/src/DirTreeView.cpp000066400000000000000000000065501311502036700167010ustar00rootroot00000000000000/* * File name: DirTreeView.cpp * Summary: Tree view widget for directory tree * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "DirTreeView.h" #include "DirTreeModel.h" #include "SelectionModel.h" #include "ActionManager.h" #include "CleanupCollection.h" #include "PercentBar.h" #include "HeaderTweaker.h" #include "DirTree.h" #include "Exception.h" #include "Logger.h" using namespace QDirStat; DirTreeView::DirTreeView( QWidget * parent ): QTreeView( parent ), _cleanupCollection(0) { _percentBarDelegate = new PercentBarDelegate( this ); CHECK_NEW( _percentBarDelegate ); setItemDelegate( _percentBarDelegate ); setRootIsDecorated( true ); setSortingEnabled( true ); setSelectionMode( ExtendedSelection ); setContextMenuPolicy( Qt::CustomContextMenu ); setTextElideMode( Qt::ElideMiddle ); _headerTweaker = new HeaderTweaker( header(), this ); CHECK_NEW( _headerTweaker ); connect( this , SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT ( contextMenu ( const QPoint & ) ) ); } DirTreeView::~DirTreeView() { delete _percentBarDelegate; delete _headerTweaker; } void DirTreeView::currentChanged( const QModelIndex & current, const QModelIndex & oldCurrent ) { // logDebug() << "Setting new current to " << current << endl; QTreeView::currentChanged( current, oldCurrent ); scrollTo( current ); } void DirTreeView::contextMenu( const QPoint & pos ) { QModelIndex index = indexAt( pos ); if ( ! index.isValid() ) { // logDebug() << "No item at this position" << endl; return; } QMenu menu; QStringList actions; actions << "actionGoUp" << "actionCopyUrlToClipboard" << "---" << "actionRefreshSelected" << "actionReadExcludedDirectory" << "actionContinueReadingAtMountPoint" << "---" << "actionFileSizeStats" << "actionFileTypeStats" << "---" << "actionMoveToTrash" ; ActionManager::instance()->addActions( &menu, actions ); if ( _cleanupCollection && ! _cleanupCollection->isEmpty() ) { menu.addSeparator(); _cleanupCollection->addToMenu( &menu ); } menu.exec( mapToGlobal( pos ) ); } QModelIndexList DirTreeView::expandedIndexes() const { QModelIndexList expandedList; if ( ! model() ) return QModelIndexList(); DirTreeModel * dirTreeModel = dynamic_cast( model() ); if ( ! dirTreeModel ) { logError() << "Wrong model type to get this information" << endl; return QModelIndexList(); } foreach ( const QModelIndex & index, dirTreeModel->persistentIndexList() ) { if ( isExpanded( index ) ) expandedList << index; } return expandedList; } void DirTreeView::closeAllExcept( const QModelIndex & branch ) { QModelIndexList branchesToClose = expandedIndexes(); // Remove all ancestors of 'branch' from branchesToClose QModelIndex index = branch; while ( index.isValid() ) { // logDebug() << "Not closing " << index << endl; branchesToClose.removeAll( index ); index = index.parent(); } // Close all items in branchesToClose foreach ( index, branchesToClose ) { // logDebug() << "Closing " << index << endl; collapse( index ); } scrollTo( currentIndex() ); } qdirstat-1.4/src/DirTreeView.h000066400000000000000000000054411311502036700163440ustar00rootroot00000000000000/* * File name: DirTreeView.h * Summary: Tree view widget for directory tree * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef DirTreeView_h #define DirTreeView_h #include class QAction; namespace QDirStat { class PercentBarDelegate; class HeaderTweaker; class SelectionModelProxy; class CleanupCollection; /** * Tree view widget for the QDirStat directory tree. * * This is a thin wrapper around TreeView that takes care about basic setup * and configuration of the tree view and adds support for synchronizing * current / selected items between the DirTree, the DirTreeMap and this * DirTreeView. * * The Qt model / view abstraction is kept up as good as possible, but this * widget is really meant to be used with a QDirStat::DirTreeModel and not * just any random subclass of QAbstractItemModel. **/ class DirTreeView: public QTreeView { Q_OBJECT public: /** * Constructor **/ DirTreeView( QWidget * parent = 0 ); /** * Destructor **/ virtual ~DirTreeView(); /** * Set the cleanup collection. If set, all cleanup actions from that * collection will be added to the item context menu. **/ void setCleanupCollection( CleanupCollection * collection ) { _cleanupCollection = collection; } /** * Return the cleanup collection or 0 if it is not set. **/ CleanupCollection * cleanupCollection() const { return _cleanupCollection; } /** * Return the list of items that are currently expanded. * * This is well-known in the base class, but due to poor design that * information is not accessible in derived classes. Well, I got * creative. * * This method being public is more to spite the "masterminds" who in * their infinite wisdom considered this information not worthy of * being exported to the public because "it doesn't kneed to * know". WTF? **/ QModelIndexList expandedIndexes() const; public slots: /** * Close (collapse) all branches except the one that 'branch' is in. **/ void closeAllExcept( const QModelIndex & branch ); protected slots: /** * Post a context menu for the item at 'pos'. **/ void contextMenu( const QPoint & pos ); protected: /** * Change the current item. Overwritten from QTreeView to make sure * the branch of the new current item is expanded and scrolled to * the visible area. **/ virtual void currentChanged( const QModelIndex & current, const QModelIndex & oldCurrent ) Q_DECL_OVERRIDE; // Data members PercentBarDelegate * _percentBarDelegate; HeaderTweaker * _headerTweaker; CleanupCollection * _cleanupCollection; }; // class DirTreeView } // namespace QDirStat #endif // DirTreeView_h qdirstat-1.4/src/Exception.cpp000066400000000000000000000032131311502036700164370ustar00rootroot00000000000000/* * File name: Exception.cpp * Summary: Exception classes for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "Exception.h" void Exception::setSrcLocation( const QString &srcFile, int srcLine, const QString &srcFunction ) const { // This is why those member variables are 'mutable': // We need to be able to set the source location from RETHROW even after // the exception was caught as const reference. // // This is not 100% elegant, but it keeps in line with usual conventions - // conventions like "catch exception objects as const reference". _srcFile = srcFile; _srcLine = srcLine; _srcFunction = srcFunction; } QString SysCallFailedException::errMsg( const QString & sysCall, const QString & resourceName ) const { QString msg; if ( errno != 0 ) { msg = QObject::tr( "%1( \"%2\" ) failed: %3" ) .arg( sysCall ) .arg( resourceName ) .arg( formatErrno() ); } else { msg = QObject::tr( "%1( \"%2\" ) failed" ) .arg( sysCall ) .arg( resourceName ); } return msg; } QString IndexOutOfRangeException::errMsg( int invalidIndex, int validMin, int validMax, const QString & prefix ) const { QString msg = prefix; if ( msg.isEmpty() ) msg = "Index out of range"; msg += QString( ": %1 valid: %2..%3" ).arg( invalidIndex ) .arg( validMin ).arg( validMax ); return msg; } qdirstat-1.4/src/Exception.h000066400000000000000000000235471311502036700161200ustar00rootroot00000000000000/* * File name: Exception.h * Summary: Exception classes for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Exception_h #define Exception_h #include "Logger.h" #include /** * Generic exception. * * Unlike std::exception, this class uses QString rather than const char * */ class Exception { public: /** * Constructor. */ Exception( const QString &msg = QString() ): _what( msg ), _srcLine(0) {} /** * Destructor. */ virtual ~Exception() throw() {} /** * Return a text description of what was wrong. * * Notice this text is intended for developers or admins, not for end * users. */ virtual QString what() const { return _what; } /** * Return the class name of this exception as string. * * Derived classes should reimplement this and return their own name. */ virtual QString className() const { return "Exception"; } /** * Return the source file name where the exception was thrown. * This works only if it was thrown with THROW. */ QString srcFile() const { return _srcFile; } /** * Return the line number in the source file where the exception was * thrown. This works only if it was thrown with THROW. */ int srcLine() const { return _srcLine; } /** * Return the function name where the exception was thrown. * This works only if it was thrown with THROW. */ QString srcFunction() const { return _srcFunction; } /** * Set the source location where the exception was thrown. * This is used in the THROW and RETHROW macros. */ void setSrcLocation( const QString &srcFile, int srcLine, const QString &srcFunction ) const; protected: QString _what; mutable QString _srcFile; mutable int _srcLine; mutable QString _srcFunction; }; /** * Exception class for null pointers. * Use with CHECK_PTR(). */ class NullPointerException: public Exception { public: NullPointerException(): Exception( "Null pointer" ) {} virtual ~NullPointerException() throw() {} }; /** * Exception class for "out of memory" ('new' failed). * Use with CHECK_NEW(). */ class OutOfMemoryException: public Exception { public: OutOfMemoryException(): Exception( "Null pointer" ) {} virtual ~OutOfMemoryException() throw() {} }; class FileException: public Exception { public: FileException( const QString &filename, const QString &msg ): Exception( msg ), _filename( filename ) {} virtual ~FileException() throw() {} QString filename() const { return _filename; } private: QString _filename; }; class SysCallFailedException: public Exception { public: SysCallFailedException( const QString & sysCall, const QString & resourceName ): Exception( errMsg( sysCall, resourceName ) ), _sysCall( sysCall ), _resourceName( resourceName ) {} virtual ~SysCallFailedException() throw() {} /** * Return the resource for which this syscall failed. This is typically a * file name. **/ QString resourceName() const { return _resourceName; } QString sysCall() const { return _sysCall; } protected: QString errMsg( const QString & sysCall, const QString & resourceName ) const; private: QString _sysCall; QString _resourceName; }; class DynamicCastException: public Exception { public: DynamicCastException( const QString &expectedType ): Exception( "dynamic_cast failed; expected: " + expectedType ) {} virtual ~DynamicCastException() throw() {} }; class BadMagicNumberException: public Exception { public: BadMagicNumberException( void * badPointer ): Exception( QString( "Magic number check failed for address 0x%1" ) .arg( (qulonglong) badPointer, 0, 16 ) ) {} virtual ~BadMagicNumberException() throw() {} }; /** * Exception class for "index out of range" **/ class IndexOutOfRangeException : public Exception { public: /** * Constructor. * * 'invalidIndex' is the offending index value. It should be between *'validMin' and 'validMax': * * validMin <= index <= validMax **/ IndexOutOfRangeException( int invalidIndex, int validMin, int validMax, const QString & msg = "" ) : Exception( errMsg( invalidIndex, validMin, validMax, msg ) ) , _invalidIndex( invalidIndex ) , _validMin( validMin ) , _validMax( validMax ) {} virtual ~IndexOutOfRangeException() throw() {} /** * Return the offending index value. **/ int invalidIndex() const { return _invalidIndex; } /** * Return the valid minimum index. **/ int validMin() const { return _validMin; } /** * Return the valid maximum index. **/ int validMax() const { return _validMax; } protected: QString errMsg( int invalidIndex, int validMin, int validMax, const QString & msg = "" ) const; private: int _invalidIndex; int _validMin; int _validMax; }; // // Helper macros // /** * Throw an exception and write it to the log, together with the source code * location where it was thrown. This makes it MUCH easier to find out where * a problem occurred. * * Use this as a substitute for normal 'throw( exception )'. */ #define THROW( EXCEPTION ) \ _throw_helper( ( EXCEPTION ), 0, __FILE__, __LINE__, __FUNCTION__ ) /** * Write a log notification that an exception has been caught. * This is not a substitute for a 'catch' statement. Rather, use it inside * a 'catch' block. * * Example: * * try * { * ...do something... * THROW( Exception( "Catastrophic failure" ) ); * ... * } * catch( const Exception &exception ) * { * CAUGHT( exception ); * ...clean up to prevent memory leaks etc. ... * RETHROW( exception ); // equivalent of throw without args * } * * This will leave 3 lines for that exception in the log file: One for * THROW, one for CAUGHT, one for RETHROW. Each log line contains the * source file, the line number, and the function of the THROW or CAUGHT * or RETHROW calls. */ #define CAUGHT( EXCEPTION ) \ _caught_helper( ( EXCEPTION ), 0, __FILE__, __LINE__, __FUNCTION__ ) /** * Write a log notification that an exception that has been caught is * being thrown again inside a 'catch' block. Use this as a substitute for * plain 'throw' without arguments. Unlike a plain 'throw', this macro does * have an argument. */ #define RETHROW( EXCEPTION ) \ _rethrow_helper( ( EXCEPTION ), 0, __FILE__, __LINE__, __FUNCTION__ ) /** * Check the result of 'new' and throw exception if it returned 0. * * The do..while() loop is used because it syntactically allows to put a * semicolon (without nasty side effects) after the macro when it is used. */ #define CHECK_NEW( PTR ) \ do \ { \ if ( ! (PTR) ) \ { \ THROW( OutOfMemoryException() ); \ } \ } while( 0 ) /** * Check a pointer and throw an exception if it returned 0. */ #define CHECK_PTR( PTR ) \ do \ { \ if ( ! (PTR) ) \ { \ THROW( NullPointerException() ); \ } \ } while( 0 ) /** * Check the result of a dynamic_cast and throw an exception if it returned 0. */ #define CHECK_DYNAMIC_CAST( PTR, EXPECTED_TYPE ) \ do \ { \ if ( ! (PTR) ) \ { \ THROW( DynamicCastException( EXPECTED_TYPE) ); \ } \ } while( 0 ) /** * Check the magic number of an object and throw an exception if it returned false. */ #define CHECK_MAGIC( PTR ) \ do \ { \ if ( ! (PTR) ) \ { \ THROW( NullPointerException() ); \ } \ \ if ( ! PTR->checkMagicNumber() ) \ { \ THROW( BadMagicNumberException( PTR ) ); \ } \ } while( 0 ) /** * Check if an index is in range: * VALID_MIN <= INDEX <= VALID_MAX * * Throws InvalidWidgetException if out of range. **/ #define CHECK_INDEX_MSG( INDEX, VALID_MIN, VALID_MAX, MSG ) \ do \ { \ if ( (INDEX) < (VALID_MIN) || \ (INDEX) > (VALID_MAX) ) \ { \ THROW( IndexOutOfRangeException( (INDEX), (VALID_MIN), (VALID_MAX), (MSG) ) ); \ } \ } while( 0 ) #define CHECK_INDEX( INDEX, VALID_MIN, VALID_MAX ) \ CHECK_INDEX_MSG( (INDEX), (VALID_MIN), (VALID_MAX), "") // // Helper functions. Do not use directly; use the corresponding macros instead. // template void _throw_helper( const EX_t &exception, Logger * logger, const QString &srcFile, int srcLine, const QString &srcFunction ) { exception.setSrcLocation( srcFile, srcLine, srcFunction ); Logger::log( logger, srcFile, srcLine, srcFunction, LogSeverityWarning ) << "THROW " << exception.className() << ": " << exception.what() << endl; throw( exception ); } template void _caught_helper( const EX_t &exception, Logger * logger, const QString &srcFile, int srcLine, const QString &srcFunction ) { Logger::log( logger, srcFile, srcLine, srcFunction, LogSeverityWarning ) << "CAUGHT " << exception.className() << ": " << exception.what() << endl; } template void _rethrow_helper( const EX_t &exception, Logger * logger, const QString &srcFile, int srcLine, const QString &srcFunction ) { exception.setSrcLocation( srcFile, srcLine, srcFunction ); Logger::log( logger, srcFile, srcLine, srcFunction, LogSeverityWarning ) << "RETHROW " << exception.className() << ": " << exception.what() << endl; throw; } #endif // Exception_h qdirstat-1.4/src/ExcludeRules.cpp000066400000000000000000000124341311502036700171120ustar00rootroot00000000000000/* * File name: ExcludeRules.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "ExcludeRules.h" #include "Settings.h" #include "SettingsHelpers.h" #include "Logger.h" #include "Exception.h" #define VERBOSE_EXCLUDE_MATCHES 1 using namespace QDirStat; ExcludeRule::ExcludeRule( const QRegExp & regexp, bool useFullPath ): _regexp( regexp ), _useFullPath( useFullPath ) { // NOP } ExcludeRule::ExcludeRule( const QString & regexp, bool useFullPath ): _regexp( QRegExp( regexp ) ), _useFullPath( useFullPath ) { // NOP } ExcludeRule::~ExcludeRule() { // NOP } bool ExcludeRule::match( const QString & fullPath, const QString & fileName ) { QString matchText = _useFullPath ? fullPath : fileName; if ( matchText.isEmpty() ) return false; if ( _regexp.pattern().isEmpty() ) return false; return _regexp.exactMatch( matchText ); } // //--------------------------------------------------------------------------- // ExcludeRules::ExcludeRules(): QObject(), _listMover( _rules ) { _lastMatchingRule = 0; } ExcludeRules::~ExcludeRules() { clear(); } ExcludeRules * ExcludeRules::instance() { static ExcludeRules * singleton = 0; if ( ! singleton ) { singleton = new ExcludeRules(); } return singleton; } void ExcludeRules::clear() { qDeleteAll( _rules ); _rules.clear(); _lastMatchingRule = 0; } void ExcludeRules::add( ExcludeRule * rule ) { CHECK_PTR( rule ); _rules << rule; } void ExcludeRules::add( const QRegExp & regexp, bool useFullPath ) { ExcludeRule * rule = new ExcludeRule( regexp, useFullPath ); CHECK_NEW( rule ); instance()->add( rule ); } void ExcludeRules::add( const QString & regexp, bool useFullPath ) { add( QRegExp( regexp ), useFullPath ); } void ExcludeRules::remove( ExcludeRule * rule ) { CHECK_PTR( rule ); _rules.removeAll( rule ); delete rule; } bool ExcludeRules::match( const QString & fullPath, const QString & fileName ) { _lastMatchingRule = 0; if ( fullPath.isEmpty() || fileName.isEmpty() ) return false; foreach ( ExcludeRule * rule, _rules ) { if ( rule->match( fullPath, fileName ) ) { _lastMatchingRule = rule; #if VERBOSE_EXCLUDE_MATCHES logDebug() << fullPath << " matches " << rule << endl; #endif return true; } } return false; } const ExcludeRule * ExcludeRules::matchingRule( const QString & fullPath, const QString & fileName ) { if ( fullPath.isEmpty() || fileName.isEmpty() ) return 0; foreach ( ExcludeRule * rule, _rules ) { if ( rule->match( fullPath, fileName ) ) return rule; } return 0; } void ExcludeRules::moveUp( ExcludeRule * rule ) { _listMover.moveUp( rule ); } void ExcludeRules::moveDown( ExcludeRule * rule ) { _listMover.moveDown( rule ); } void ExcludeRules::moveToTop( ExcludeRule * rule ) { _listMover.moveToTop( rule ); } void ExcludeRules::moveToBottom( ExcludeRule * rule ) { _listMover.moveToBottom( rule ); } void ExcludeRules::readSettings() { ExcludeRuleSettings settings; QStringList excludeRuleGroups = settings.findGroups( settings.groupPrefix() ); if ( ! excludeRuleGroups.isEmpty() ) // Keep defaults if settings empty { clear(); // Read all settings groups [ExcludeRule_xx] that were found foreach ( const QString & groupName, excludeRuleGroups ) { settings.beginGroup( groupName ); // Read one exclude rule QString pattern = settings.value( "Pattern" ).toString(); bool caseSensitive = settings.value( "CaseSensitive", true ).toBool(); bool useFullPath = settings.value( "UseFullPath", false ).toBool(); int syntax = readEnumEntry( settings, "Syntax", QRegExp::RegExp, patternSyntaxMapping() ); QRegExp regexp( pattern, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, static_cast( syntax ) ); if ( ! pattern.isEmpty() && regexp.isValid() ) add( regexp, useFullPath ); else { logError() << "Invalid regexp: \"" << regexp.pattern() << "\": " << regexp.errorString() << endl; } settings.endGroup(); // [ExcludeRule_01], [ExcludeRule_02], ... } } } void ExcludeRules::writeSettings() { ExcludeRuleSettings settings; // Remove all leftover cleanup descriptions settings.removeGroups( settings.groupPrefix() ); // Similar to CleanupCollection::writeSettings(), using a separate group // for each exclude rule for better readability in the settings file. for ( int i=0; i < _rules.size(); ++i ) { ExcludeRule * rule = _rules.at(i); QRegExp regexp = rule->regexp(); if ( ! regexp.pattern().isEmpty() ) { QString groupName; groupName.sprintf( "ExcludeRule_%02d", i+1 ); settings.beginGroup( groupName ); settings.setValue( "Pattern", regexp.pattern() ); settings.setValue( "CaseSensitive", regexp.caseSensitivity() == Qt::CaseSensitive ); settings.setValue( "UseFullPath", rule->useFullPath() ); writeEnumEntry( settings, "Syntax", regexp.patternSyntax(), patternSyntaxMapping() ); settings.endGroup(); // [ExcludeRule_01], [ExcludeRule_02], ... } } } qdirstat-1.4/src/ExcludeRules.h000066400000000000000000000137041311502036700165600ustar00rootroot00000000000000/* * File name: ExcludeRules.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef ExcludeRules_h #define ExcludeRules_h #include #include #include #include #include #include "ListMover.h" namespace QDirStat { /** * One single exclude rule to check text (file names) against. **/ class ExcludeRule { public: /** * Constructor from a QRegExp. * * 'useFullPath' indicates if this exclude rule uses the full path * ('true') or only the file name without path ('false') for matching. **/ ExcludeRule( const QRegExp & regexp, bool useFullPath = false ); /** * Constructor from a QString. The string will be used as a regexp. * * 'useFullPath' indicates if this exclude rule uses the full path * ('true') or only the file name without path ('false') for matching. **/ ExcludeRule( const QString & regexp, bool useFullPath = false ); /** * Destructor. **/ virtual ~ExcludeRule(); /** * Check a file name with or without its full path against this exclude * rule: If useFullPath() is 'true', the 'fullPath' parameter is used * for matching, if it is 'false', 'fileName' is used. * * Returns 'true' if the string matches, i.e. the file should be * excluded. **/ bool match( const QString & fullPath, const QString & fileName ); /** * Returns this rule's regular expression. **/ const QRegExp & regexp() const { return _regexp; } /** * Change this rule's regular expression. **/ void setRegexp( const QRegExp & regexp ) { _regexp = regexp; } /** * Return 'true' if this exclude rule uses the full path to match * against, 'false' if it only uses the file name without path. **/ bool useFullPath() const { return _useFullPath; } /** * Set the 'full path' flag. **/ void setUseFullPath( bool useFullPath ) { _useFullPath = useFullPath; } private: QRegExp _regexp; bool _useFullPath; }; typedef QList ExcludeRuleList; typedef ExcludeRuleList::const_iterator ExcludeRuleListIterator; /** * Container for multiple exclude rules. This is a singleton class. Use the * static methods or instance() to access the singleton. * * Normal usage: * * ExcludeRules::instance()->add( new ExcludeRule( ... ) ); * ... * if ( ExcludeRules::instance()->match( filename ) ) * { * // exclude this file * } **/ class ExcludeRules: public QObject { Q_OBJECT protected: /** * Constructor. * * Most applications will want to use instance() instead to create * and use a singleton object of this class. **/ ExcludeRules(); public: /** * Destructor. **/ virtual ~ExcludeRules(); /** * Return the singleton object of this class. * This will create one if there is none yet. **/ static ExcludeRules * instance(); /** * Add an exclude rule to this rule set. * This transfers ownership of that rule to this rule set; * it will be destroyed with 'delete' after use. **/ void add( ExcludeRule * rule ); /** * Remove an exclude rule from this rule set and delete it. **/ void remove( ExcludeRule * rule ); /** * Create a new rule with 'regexp' and 'useFullPath' and add it to this * rule set. **/ static void add( const QRegExp & regexp, bool useFullPath = false ); static void add( const QString & regexp, bool useFullPath = false ); /** * Check a file name against the exclude rules. Each exclude rule * decides individually based on its configuration if it checks against * the full path or against the file name without path, so both have to * be provided here. * * This will return 'true' if the text matches any rule. * * Note that this operation will move current(). **/ bool match( const QString & fullPath, const QString & fileName ); /** * Find the exclude rule that matches 'text'. * Return 0 if there is no match. * * This is intended to explain to the user which rule matched. **/ const ExcludeRule * matchingRule( const QString & fullPath, const QString & fileName ); /** * Return the last matching rule or 0 if there was none. * Each call to match() will reset this. **/ ExcludeRule * lastMatchingRule() const { return _lastMatchingRule; } /** * Clear (delete) all exclude rules. **/ void clear(); /** * Return 'true' if the exclude rules are empty, i.e. if there are no * exclue rules, 'false' otherwise. **/ bool isEmpty() { return _rules.isEmpty(); } /** * Return a const iterator for the first exclude rule. **/ ExcludeRuleListIterator begin() { return _rules.constBegin(); } /** * Return a const iterator for the last exclude rule. **/ ExcludeRuleListIterator end() { return _rules.constEnd(); } public slots: /** * Move an exclude rule one position up in the list. **/ void moveUp( ExcludeRule * rule ); /** * Move an exclude rule one position down in the list. **/ void moveDown( ExcludeRule * rule ); /** * Move an exclude rule to the top of the list. **/ void moveToTop( ExcludeRule * rule ); /** * Move an exclude rule to the bottom of the list. **/ void moveToBottom( ExcludeRule * rule ); /** * Clear all existing exclude rules and read exclude rules from the * settings file. **/ void readSettings(); /** * Write all exclude rules to the settings file. **/ void writeSettings(); private: ExcludeRuleList _rules; ListMover _listMover; ExcludeRule * _lastMatchingRule; }; /** * Print the regexp of a @ref FileInfo in a debug stream. **/ inline QTextStream & operator<< ( QTextStream & stream, const ExcludeRule * rule ) { if ( rule ) stream << "regexp().pattern() << "\">"; else stream << ""; return stream; } } // namespace QDirStat #endif // ifndef ExcludeRules_h qdirstat-1.4/src/ExcludeRulesConfigPage.cpp000066400000000000000000000122241311502036700210320ustar00rootroot00000000000000/* * File name: ExcludeRulesConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "ExcludeRulesConfigPage.h" #include "Logger.h" #include "Exception.h" // This is a mess that became necessary because Qt's moc cannot handle template // classes. Yes, this is ugly. #define EXCLUDE_RULE_CAST(VOID_PTR) (static_cast(VOID_PTR)) using namespace QDirStat; ExcludeRulesConfigPage::ExcludeRulesConfigPage( QWidget * parent ): ListEditor( parent ), _ui( new Ui::ExcludeRulesConfigPage ) { CHECK_NEW( _ui ); _ui->setupUi( this ); setListWidget( _ui->listWidget ); setMoveUpButton ( _ui->moveUpButton ); setMoveDownButton ( _ui->moveDownButton ); setMoveToTopButton ( _ui->moveToTopButton ); setMoveToBottomButton( _ui->moveToBottomButton ); setAddButton ( _ui->addButton ); setRemoveButton ( _ui->removeButton ); connect( _ui->patternLineEdit, SIGNAL( textChanged ( QString ) ), this, SLOT ( patternChanged( QString ) ) ); } ExcludeRulesConfigPage::~ExcludeRulesConfigPage() { // logDebug() << "ExcludeRulesConfigPage destructor" << endl; } void ExcludeRulesConfigPage::setup() { fillListWidget(); updateActions(); } void ExcludeRulesConfigPage::applyChanges() { logDebug() << endl; save( value( listWidget()->currentItem() ) ); ExcludeRules::instance()->writeSettings(); } void ExcludeRulesConfigPage::discardChanges() { logDebug() << endl; listWidget()->clear(); ExcludeRules::instance()->clear(); ExcludeRules::instance()->readSettings(); } void ExcludeRulesConfigPage::fillListWidget() { listWidget()->clear(); for ( ExcludeRuleListIterator it = ExcludeRules::instance()->begin(); it != ExcludeRules::instance()->end(); ++it ) { QListWidgetItem * item = new ListEditorItem( (*it)->regexp().pattern(), (*it) ); CHECK_NEW( item ); listWidget()->addItem( item ); } QListWidgetItem * firstItem = listWidget()->item(0); if ( firstItem ) listWidget()->setCurrentItem( firstItem ); } void ExcludeRulesConfigPage::patternChanged( const QString & newPattern ) { QListWidgetItem * currentItem = listWidget()->currentItem(); if ( currentItem ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value( currentItem ) ); QRegExp regexp = excludeRule->regexp(); regexp.setPattern( newPattern ); excludeRule->setRegexp( regexp ); currentItem->setText( excludeRule->regexp().pattern() ); } } void ExcludeRulesConfigPage::save( void * value ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); // logDebug() << excludeRule << endl; if ( ! excludeRule || updatesLocked() ) return; QRegExp regexp; if ( _ui->regexpRadioButton->isChecked() ) regexp.setPatternSyntax( QRegExp::RegExp ); else if ( _ui->wildcardsRadioButton->isChecked() ) regexp.setPatternSyntax( QRegExp::Wildcard ); else if ( _ui->fixedStringRadioButton->isChecked() ) regexp.setPatternSyntax( QRegExp::FixedString ); regexp.setPattern( _ui->patternLineEdit->text() ); excludeRule->setRegexp( regexp ); excludeRule->setUseFullPath( _ui->fullPathRadioButton->isChecked() ); } void ExcludeRulesConfigPage::load( void * value ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); // logDebug() << excludeRule << endl; if ( ! excludeRule || updatesLocked() ) return; _ui->patternLineEdit->setText( excludeRule->regexp().pattern() ); switch ( excludeRule->regexp().patternSyntax() ) { case QRegExp::RegExp: _ui->regexpRadioButton->setChecked( true ); break; case QRegExp::Wildcard: _ui->wildcardsRadioButton->setChecked( true ); break; case QRegExp::FixedString: _ui->fixedStringRadioButton->setChecked( true ); break; default: break; } if ( excludeRule->useFullPath() ) _ui->fullPathRadioButton->setChecked( true ); else _ui->dirNameWithoutPathRadioButton->setChecked( true ); } void * ExcludeRulesConfigPage::createValue() { ExcludeRule * excludeRule = new ExcludeRule( "" ); CHECK_NEW( excludeRule ); ExcludeRules::instance()->add( excludeRule ); return excludeRule; } void ExcludeRulesConfigPage::removeValue( void * value ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); CHECK_PTR( excludeRule ); ExcludeRules::instance()->remove( excludeRule ); } QString ExcludeRulesConfigPage::valueText( void * value ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); CHECK_PTR( excludeRule ); return excludeRule->regexp().pattern(); } QString ExcludeRulesConfigPage::deleteConfirmationMessage( void * value ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); return tr( "Really delete exclude rule \"%1\"?" ).arg( excludeRule->regexp().pattern() ); } void ExcludeRulesConfigPage::moveValue( void * value, const char * operation ) { ExcludeRule * excludeRule = EXCLUDE_RULE_CAST( value ); QMetaObject::invokeMethod( ExcludeRules::instance(), operation, Qt::DirectConnection, Q_ARG( ExcludeRule *, excludeRule ) ); } qdirstat-1.4/src/ExcludeRulesConfigPage.h000066400000000000000000000060651311502036700205050ustar00rootroot00000000000000/* * File name: ExcludeRulesConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef ExcludeRulesConfigPage_h #define ExcludeRulesConfigPage_h #include "ListEditor.h" #include "ui_exclude-rules-config-page.h" #include "ExcludeRules.h" namespace QDirStat { class CleanupCollection; /** * Configuration page (tab) for cleanups: * Edit, add, delete, reorder cleanups in the cleanup collection. **/ class ExcludeRulesConfigPage: public ListEditor { Q_OBJECT public: ExcludeRulesConfigPage( QWidget * parent = 0 ); virtual ~ExcludeRulesConfigPage(); public slots: /** * Populate the widgets. **/ void setup(); /** * Write changes back to the settings. **/ void applyChanges(); /** * Abandon changes and revert everything to the original settings. **/ void discardChanges(); protected slots: /** * Notification that the user changed the "Pattern" field of the * current exclude rule. **/ void patternChanged( const QString & newPattern ); protected: /** * Fill the exclude rule list widget from the ExcludeRules. * * Implemented from ListEditor. **/ virtual void fillListWidget() Q_DECL_OVERRIDE; /** * Save the contents of the widgets to the specified value. * * Implemented from ListEditor. **/ virtual void save( void * value ) Q_DECL_OVERRIDE; /** * Load the content of the widgets from the specified value. * * Implemented from ListEditor. **/ virtual void load( void * value ) Q_DECL_OVERRIDE; /** * Create a new value with default values. * This is called when the 'Add' button is clicked. * * Implemented from ListEditor. **/ virtual void * createValue() Q_DECL_OVERRIDE; /** * Remove a value from the internal list and delete it. * * This is called when the 'Remove' button is clicked and the user * confirms the confirmation pop-up. * * Implemented from ListEditor. **/ virtual void removeValue( void * value ); /** * Return a text for the list item of 'value'. * * Implemented from ListEditor. **/ virtual QString valueText( void * value ) Q_DECL_OVERRIDE; /** * Return the message for the 'really delete?' message for the current * item ('value'). If this returns an empty string, the item cannot be * deleted. * * Implemented from ListEditor. **/ virtual QString deleteConfirmationMessage( void * value ) Q_DECL_OVERRIDE; /** * Move a value in the internal list. This is called from moveUp(), * moveDown() etc.; 'operation' is one of 'moveUp()', moveDown() * etc. that can be called with QMetaObject::invokeMethod(). * * Implemented from ListEditor. * * This is a kludge - a workaround of not being able to use C++ * templates. **/ virtual void moveValue( void * value, const char * operation ) Q_DECL_OVERRIDE; // // Data members // Ui::ExcludeRulesConfigPage * _ui; }; // class ExcludeRulesConfigPage } // namespace QDirStat #endif // ExcludeRulesConfigPage_h qdirstat-1.4/src/FileInfo.cpp000066400000000000000000000204731311502036700162030ustar00rootroot00000000000000/* * File name: FileInfo.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include "FileInfo.h" #include "DirInfo.h" #include "DirTree.h" #include "Logger.h" #include "Exception.h" // Some file systems (NTFS seems to be among them) may handle block fragments // well. Don't report files as "sparse" files if the block size is only a few // bytes less than the byte size - it may be due to intelligent fragment // handling. #define FRAGMENT_SIZE 2048 using namespace QDirStat; FileInfo::FileInfo( DirTree * tree, DirInfo * parent, const char * name ) : _parent( parent ) , _next( 0 ) , _tree( tree ) { _isLocalFile = true; _isSparseFile = false; _name = name ? name : ""; _device = 0; _mode = 0; _links = 0; _size = 0; _blocks = 0; _mtime = 0; _magic = FileInfoMagic; } FileInfo::FileInfo( const QString & filenameWithoutPath, struct stat * statInfo, DirTree * tree, DirInfo * parent ) : _parent( parent ) , _next( 0 ) , _tree( tree ) { CHECK_PTR( statInfo ); _isLocalFile = true; _name = filenameWithoutPath; _device = statInfo->st_dev; _mode = statInfo->st_mode; _links = statInfo->st_nlink; _mtime = statInfo->st_mtime; _magic = FileInfoMagic; if ( isSpecial() ) { _size = 0; _blocks = 0; _isSparseFile = false; } else { _size = statInfo->st_size; _blocks = statInfo->st_blocks; _isSparseFile = isFile() && _blocks >= 0 // if file system can report blocks && allocatedSize() + FRAGMENT_SIZE < _size; // allow for intelligent fragment handling if ( _isSparseFile ) { logDebug() << "Found sparse file: " << this << " Byte size: " << formatSize( byteSize() ) << " Allocated: " << formatSize( allocatedSize() ) << " (" << (int) _blocks << " blocks)" << endl; } #if 0 if ( isFile() && _links > 1 ) { logDebug() << _links << " hard links: " << this << endl; } #endif } } FileInfo::FileInfo( DirTree * tree, DirInfo * parent, const QString & filenameWithoutPath, mode_t mode, FileSize size, time_t mtime, FileSize blocks, nlink_t links ) : _parent( parent ) , _next( 0 ) , _tree( tree ) { _name = filenameWithoutPath; _isLocalFile = true; _device = 0; _mode = mode; _size = size; _mtime = mtime; _links = links; _magic = FileInfoMagic; if ( blocks < 0 ) { _isSparseFile = false; _blocks = _size / blockSize(); if ( ( _size % blockSize() ) > 0 ) _blocks++; } else { _isSparseFile = true; _blocks = blocks; } // logDebug() << "Created FileInfo " << this << endl; } FileInfo::~FileInfo() { _magic = 0; /** * The destructor should also take care about unlinking this object from * its parent's children list, but regrettably that just doesn't work: At * this point (within the destructor) parts of the object are already * destroyed, e.g., the virtual table - virtual methods don't work any * more. Thus, somebody from outside must call deletingChild() just prior * to the actual "delete". * * This sucks, but it's the C++ standard. **/ } bool FileInfo::checkMagicNumber() const { return _magic == FileInfoMagic; } FileSize FileInfo::allocatedSize() const { return blocks() * blockSize(); } FileSize FileInfo::size() const { FileSize sz = _isSparseFile ? allocatedSize() : _size; if ( _links > 1 && ! isDir() ) sz /= _links; return sz; } QString FileInfo::url() const { if ( _parent ) { QString parentUrl = _parent->url(); if ( isDotEntry() ) // don't append "/." for dot entries return parentUrl; if ( ! parentUrl.endsWith( "/" ) && ! _name.startsWith( "/" ) ) parentUrl += "/"; return parentUrl + _name; } else return _name; } QString FileInfo::debugUrl() const { if ( this == _tree->root() ) return ""; if ( isDotEntry() ) return url() + "/" + dotEntryName(); return url() ; } int FileInfo::treeLevel() const { int level = 0; FileInfo * parent = _parent; while ( parent ) { level++; parent = parent->parent(); } return level; } bool FileInfo::hasChildren() const { return firstChild() || dotEntry(); } bool FileInfo::isInSubtree( const FileInfo *subtree ) const { const FileInfo * ancestor = this; while ( ancestor ) { if ( ancestor == subtree ) return true; ancestor = ancestor->parent(); } return false; } FileInfo * FileInfo::locate( QString url, bool findDotEntries ) { if ( ! url.startsWith( _name ) && this != _tree->root() ) return 0; else // URL starts with this node's name { if ( this != _tree->root() ) // The root item is invisible { url.remove( 0, _name.length() ); // Remove leading name of this node if ( url.length() == 0 ) // Nothing left? return this; // Hey! That's us! if ( url.startsWith( "/" ) ) // If the next thing a path delimiter, url.remove( 0, 1 ); // remove that leading delimiter. else // No path delimiter at the beginning { if ( _name.right(1) != "/" && // and this is not the root directory ! isDotEntry() ) // or a dot entry: return 0; // This can't be any of our children. } } // Search all children FileInfo *child = firstChild(); while ( child ) { FileInfo *foundChild = child->locate( url, findDotEntries ); if ( foundChild ) return foundChild; else child = child->next(); } // Special case: The dot entry is requested. if ( findDotEntries && dotEntry() && url == dotEntryName() ) return dotEntry(); // Search the dot entry if there is one - but only if there is no more // path delimiter left in the URL. The dot entry contains files only, // and their names may not contain the path delimiter, nor can they // have children. This check is not strictly necessary, but it may // speed up things a bit if we don't search the non-directory children // if the rest of the URL consists of several pathname components. if ( dotEntry() && ! url.contains( "/" ) ) // No (more) "/" in this URL { return dotEntry()->locate( url, findDotEntries ); } } return 0; } float FileInfo::subtreePercent() { if ( ! parent() || // only if there is a parent as calculation base parent()->pendingReadJobs() > 0 || // not before subtree is finished reading parent()->totalSize() == 0 || // avoid division by zero isExcluded() ) // not if this is an excluded object (dir) { return -1.0; } return ( 100.0 * totalSize() ) / (float) parent()->totalSize(); } QString FileInfo::dotEntryName() { return QObject::tr( "" ); } //--------------------------------------------------------------------------- QString QDirStat::formatSize( FileSize lSize ) { QString sizeString; int unitIndex = 0; static QStringList units; if ( units.isEmpty() ) { units << QObject::tr( "Bytes" ) << QObject::tr( "kB" ) << QObject::tr( "MB" ) << QObject::tr( "GB" ) << QObject::tr( "TB" ) << QObject::tr( "PB" ) << QObject::tr( "EB" ) << QObject::tr( "ZB" ) << QObject::tr( "YB" ); } if ( lSize < 1024 ) { sizeString.sprintf( "%lld ", lSize ); sizeString += units.at( unitIndex ); } else { double size = lSize; while ( size >= 1024.0 && unitIndex < units.size() - 1 ) { size /= 1024.0; ++unitIndex; } sizeString.sprintf( "%.1f ", size ); sizeString += units.at( unitIndex ); } return sizeString; } DirInfo * FileInfo::toDirInfo() { DirInfo * dirInfo = dynamic_cast( this ); return dirInfo; } QString QDirStat::formatTime( time_t rawTime ) { if ( rawTime == (time_t) 0 ) return ""; QDateTime time = QDateTime::fromTime_t( rawTime ); return time.toString( Qt::DefaultLocaleShortDate ); } QString QDirStat::baseName( const QString & fileName ) { QStringList segments = fileName.split( '/', QString::SkipEmptyParts ); return segments.isEmpty() ? "" : segments.last(); } qdirstat-1.4/src/FileInfo.h000066400000000000000000000461661311502036700156570ustar00rootroot00000000000000/* * File name: FileInfo.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileInfo_h #define FileInfo_h #include #include #include #include #include #include "Logger.h" namespace QDirStat { typedef long long FileSize; #define FileSizeMax LLONG_MAX // 0x7FFFFFFFFFFFFFFFLL == 9223372036854775807LL #define FileInfoMagic 4242 // Forward declarations class DirInfo; class DirTree; /** * Status of a directory read job. **/ enum DirReadState { DirQueued, // Waiting in the directory read queue DirReading, // Reading in progress DirFinished, // Reading finished and OK DirOnRequestOnly, // Will be read upon explicit request only (mount points) DirCached, // Content was read from a cache DirAborted, // Reading aborted upon user request DirError // Error while reading }; /** * The most basic building block of a @ref DirTree: * * Information about one single directory entry. This is the type of info * typically obtained by stat() / lstat() or similar calls. * * This class is tuned for size rather than speed: A typical Linux system * easily has 150,000+ file system objects, and at least one entry of this * sort is required for each of them. * * This class provides stubs for children management, yet those stubs all * are default implementations that don't really deal with children. * Derived classes need to take care of that. * * @short Basic file information (like obtained by the lstat() sys call) **/ class FileInfo { public: /** * Default constructor. **/ FileInfo( DirTree * tree, DirInfo * parent = 0, const char * name = 0 ); /** * Constructor from a stat buffer (i.e. based on an lstat() call). **/ FileInfo( const QString & filenameWithoutPath, struct stat * statInfo, DirTree * tree, DirInfo * parent = 0 ); /** * Constructor from the bare neccessary fields * for use from a cache file reader * * If 'blocks' is -1, it will be calculated from 'size'. **/ FileInfo( DirTree * tree, DirInfo * parent, const QString & filenameWithoutPath, mode_t mode, FileSize size, time_t mtime, FileSize blocks = -1, nlink_t links = 1 ); /** * Destructor. * * Don't forget to call @ref FileInfo::unlinkChild() when deleting * objects of this class! **/ virtual ~FileInfo(); /** * Check with the magic number if this object is valid. * Return 'true' if it is valid, 'false' if invalid. * * Notice that this is intentionally not a virtual function to avoid * a segfault via the vptr if it is not valid. **/ bool checkMagicNumber() const; /** * Returns whether or not this is a local file (protocol "file:"). * It might as well be a remote file ("ftp:", "smb:" etc.). **/ bool isLocalFile() const { return _isLocalFile; } /** * Returns the file or directory name without path, i.e. only the last * path name component (i.e. "printcap" rather than "/etc/printcap"). * * If a directory scan doesn't begin at the root directory and this is * the top entry of this directory scan, it will also contain the base * path, i.e. "/usr/share/man" rather than just "man" if a scan was * requested for "/usr/share/man". Notice, however, that the entry for * "/usr/share/man/man1" will only return "man1" in this example. **/ QString name() const { return _name; } /** * Returns the full URL of this object with full path. * * This is a (somewhat) expensive operation since it will recurse up * to the top of the tree. **/ QString url() const; /** * Very much like @ref FileInfo::url(), but with "/" appended * if this is a dot entry. Useful for debugging. * Notice: You can simply use the @ref QTextStream operator<< to * output exactly this: * * logDebug() << "Found fileInfo " << info << endl; **/ QString debugUrl() const; /** * Returns the major and minor device numbers of the device this file * resides on or 0 if this is a remote file. **/ dev_t device() const { return _device; } /** * The file permissions and object type as returned by lstat(). * You might want to use the repective convenience methods instead: * @ref isDir(), @ref isFile(), ... **/ mode_t mode() const { return _mode; } /** * The number of hard links to this file. Relevant for size summaries * to avoid counting one file several times. **/ nlink_t links() const { return _links; } /** * The file size in bytes. This does not take unused space in the last * disk block (cluster) into account, yet it is the only size all kinds * of info functions can obtain. This is also what most file system * utilities (like "ls -l") display. **/ FileSize byteSize() const { return _size; } /** * The number of bytes actually allocated on the file system. Usually * this will be more than @ref byteSize() since the last few bytes of a * file usually consume an additional cluster on the file system. * * In the case of sparse files, however, this might as well be * considerably less than @ref byteSize() - this means that this file * has "holes", i.e. large portions filled with zeros. This is typical * for large core dumps for example. The only way to create such a file * is to lseek() far ahead of the previous file size and then writing * data. Most file system utilities will however disregard the fact * that files are sparse files and simply allocate the holes as well, * thus greatly increasing the disk space consumption of such a * file. Only some few file system utilities like "cp", "rsync", "tar" * have options to handle this more graciously - but usually only when * specifically requested. See the respective man pages. **/ FileSize allocatedSize() const; /** * The file size, taking into account multiple links for plain files or * the true allocated size for sparse files. For plain files with * multiple links this will be size/no_links, for sparse files it is * the number of bytes actually allocated. **/ FileSize size() const; /** * The file size in 512 byte blocks. **/ FileSize blocks() const { return _blocks; } /** * The size of one single block that @ref blocks() returns. * Notice: This is _not_ the blocksize that lstat() returns! **/ FileSize blockSize() const { return 512L; } /** * The modification time of the file (not the inode). **/ time_t mtime() const { return _mtime; } /** * Returns the total size in bytes of this subtree. * Derived classes that have children should overwrite this. **/ virtual FileSize totalSize() { return size(); } /** * Returns the total size in blocks of this subtree. * Derived classes that have children should overwrite this. **/ virtual FileSize totalBlocks() { return _blocks; } /** * Returns the total number of children in this subtree, excluding this * item. * Derived classes that have children should overwrite this. **/ virtual int totalItems() { return 0; } /** * Returns the total number of subdirectories in this subtree, * excluding this item. Dot entries and "." or ".." are not counted. * Derived classes that have children should overwrite this. **/ virtual int totalSubDirs() { return 0; } /** * Returns the total number of plain file children in this subtree, * excluding this item. * Derived classes that have children should overwrite this. **/ virtual int totalFiles() { return 0; } /** * Returns the latest modification time of this subtree. * Derived classes that have children should overwrite this. **/ virtual time_t latestMtime() { return _mtime; } /** * Return the percentage of this subtree in regard to its parent * (0.0..100.0). Return a negative value if for any reason this cannot * be calculated or it would not make any sense. * * Derived classes are free to overwrite this, but this default * implementation should work well enough. **/ virtual float subtreePercent(); /** * Returns 'true' if this had been excluded while reading. * Derived classes may want to overwrite this. **/ virtual bool isExcluded() const { return false; } /** * Set the 'excluded' status. * * This default implementation silently ignores the value passed and * does nothing. Derived classes may want to overwrite this. **/ virtual void setExcluded( bool excl ) { Q_UNUSED( excl); return; } /** * Returns whether or not this is a mount point. * Derived classes may want to overwrite this. **/ virtual bool isMountPoint() const { return false; } /** * Sets the mount point state, i.e. whether or not this is a mount * point. * * This default implementation silently ignores the value passed and * does nothing. Derived classes may want to overwrite this. **/ virtual void setMountPoint( bool isMountPoint = true ) { Q_UNUSED( isMountPoint ); return; } /** * Returns true if this subtree is finished reading. * * This default implementation always returns 'true'; * derived classes should overwrite this. **/ virtual bool isFinished() { return true; } /** * Returns true if this subtree is busy, i.e. it is not finished * reading yet. * * This default implementation always returns 'false'; * derived classes should overwrite this. **/ virtual bool isBusy() { return false; } /** * Returns the number of pending read jobs in this subtree. When this * number reaches zero, the entire subtree is done. * Derived classes that have children should overwrite this. **/ virtual int pendingReadJobs() { return 0; } // // Tree management // /** * Returns a pointer to the @ref DirTree this entry belongs to. **/ DirTree * tree() const { return _tree; } /** * Returns a pointer to this entry's parent entry or 0 if there is * none. **/ DirInfo * parent() const { return _parent; } /** * Set the "parent" pointer. **/ void setParent( DirInfo *newParent ) { _parent = newParent; } /** * Returns a pointer to the next entry on the same level * or 0 if there is none. **/ FileInfo * next() const { return _next; } /** * Set the "next" pointer. **/ void setNext( FileInfo *newNext ) { _next = newNext; } /** * Returns the first child of this item or 0 if there is none. * Use the child's next() method to get the next child. * * This default implementation always returns 0. **/ virtual FileInfo * firstChild() const { return 0; } /** * Set this entry's first child. * Use this method only if you know exactly what you are doing. * * This default implementation does nothing. * Derived classes might want to overwrite this. **/ virtual void setFirstChild( FileInfo *newFirstChild ) { Q_UNUSED( newFirstChild ); } /** * Returns true if this entry has any children. **/ virtual bool hasChildren() const; /** * Returns true if this entry is in subtree 'subtree', i.e. if this is * a child or grandchild etc. of 'subtree'. **/ bool isInSubtree( const FileInfo *subtree ) const; /** * Locate a child somewhere in this subtree whose URL (i.e. complete * path) matches the URL passed. Returns 0 if there is no such child. * * Notice: This is a very expensive operation since the entire subtree * is searched recursively. * * Derived classes might or might not wish to overwrite this method; * it's only advisable to do so if a derived class comes up with a * different method than brute-force searching all children. * * 'findDotEntries' specifies if locating "dot entries" (".../") * is desired. **/ virtual FileInfo * locate( QString url, bool findDotEntries = false ); /** * Insert a child into the children list. * * The order of children in this list is absolutely undefined; * don't rely on any implementation-specific order. * * This default implementation does nothing. **/ virtual void insertChild( FileInfo *newChild ) { Q_UNUSED( newChild ); } /** * Return the "Dot Entry" for this node if there is one (or 0 * otherwise): This is a pseudo entry that directory nodes use to store * non-directory children separately from directories. This way the end * user can easily tell which summary fields belong to the directory * itself and which are the accumulated values of the entire subtree. * * This default implementation always returns 0. **/ virtual FileInfo *dotEntry() const { return 0; } /** * Set a "Dot Entry". This makes sense for directories only. * * This default implementation does nothing. **/ virtual void setDotEntry( FileInfo *newDotEntry ) { Q_UNUSED( newDotEntry ); } /** * Returns true if this is a "Dot Entry". * See @ref dotEntry() for details. * * This default implementation always returns false. **/ virtual bool isDotEntry() const { return false; } /** * (Translated) user-visible string for a "Dot Entry" (""). **/ static QString dotEntryName(); /** * Returns the tree level (depth) of this item. * The topmost level is 0. * * This is a (somewhat) expensive operation since it will recurse up * to the top of the tree. **/ int treeLevel() const; /** * Notification that a child has been added somewhere in the subtree. * * This default implementation does nothing. **/ virtual void childAdded( FileInfo *newChild ) { Q_UNUSED( newChild ); } /** * Remove a child from the children list. * * IMPORTANT: This MUST be called just prior to deleting an object of * this class. Regrettably, this cannot simply be moved to the * destructor: Important parts of the object might already be destroyed * (e.g., the virtual table - no more virtual methods). * * This default implementation does nothing. * Derived classes that can handle children should overwrite this. **/ virtual void unlinkChild( FileInfo *deletedChild ) { Q_UNUSED( deletedChild ); } /** * Notification that a child is about to be deleted somewhere in the * subtree. **/ virtual void deletingChild( FileInfo *deletedChild ) { Q_UNUSED( deletedChild ); } /** * Get the current state of the directory reading process: * * This default implementation always returns DirFinished. * Derived classes should overwrite this. **/ virtual DirReadState readState() const { return DirFinished; } /** * Returns true if this is a @ref DirInfo object. * * Don't confuse this with @ref isDir() which tells whether or not this * is a disk directory! Both should return the same, but you'll never * know - better be safe than sorry! * * This default implementation always returns 'false'. Derived classes * (in particular, those derived from @ref DirInfo) should overwrite this. **/ virtual bool isDirInfo() const { return false; } /** * Try to convert this to a @ref DirInfo pointer. This returns null if * this is not a DirInfo. **/ DirInfo * toDirInfo(); /** * Returns true if this is a sparse file, i.e. if this file has * actually fewer disk blocks allocated than its byte size would call * for. * * This is a cheap operation since it relies on a cached flag that is * calculated in the constructor rather than doing repeated * calculations and comparisons. * * Please not that @ref size() already takes this into account. **/ bool isSparseFile() const { return _isSparseFile; } // // File type / mode convenience methods. // These are simply shortcuts to the respective macros from // . // /** * Returns true if this is a directory. **/ bool isDir() const { return S_ISDIR( _mode ) ? true : false; } /** * Returns true if this is a regular file. **/ bool isFile() const { return S_ISREG( _mode ) ? true : false; } /** * Returns true if this is a symbolic link. **/ bool isSymLink() const { return S_ISLNK( _mode ) ? true : false; } /** * Returns true if this is a (block or character) device. **/ bool isDevice() const { return ( S_ISBLK ( _mode ) || S_ISCHR ( _mode ) ) ? true : false; } /** * Returns true if this is a block device. **/ bool isBlockDevice() const { return S_ISBLK ( _mode ) ? true : false; } /** * Returns true if this is a block device. **/ bool isCharDevice() const { return S_ISCHR ( _mode ) ? true : false; } /** * Returns true if this is a FIFO. **/ bool isFifo() const { return S_ISFIFO ( _mode ) ? true : false; } /** * Returns true if this is a socket. **/ bool isSocket() const { return S_ISSOCK ( _mode ) ? true : false; } /** * Returns true if this is a "special" file, i.e. a (block or character) * device, a FIFO (named pipe) or a socket. **/ bool isSpecial() const { return ( S_ISBLK ( _mode ) || S_ISCHR ( _mode ) || S_ISFIFO( _mode ) || S_ISSOCK( _mode ) ) ? true : false; } protected: // Data members. // // Keep this short in order to use as little memory as possible - // there will be a _lot_ of entries of this kind! short _magic; // magic number to detect if this object is valid QString _name; // the file name (without path!) bool _isLocalFile :1; // flag: local or remote file? bool _isSparseFile :1; // (cache) flag: sparse file (file with "holes")? dev_t _device; // device this object resides on mode_t _mode; // file permissions + object type nlink_t _links; // number of links FileSize _size; // size in bytes FileSize _blocks; // 512 bytes blocks time_t _mtime; // modification time DirInfo * _parent; // pointer to the parent entry FileInfo * _next; // pointer to the next entry DirTree * _tree; // pointer to the parent tree }; // class FileInfo typedef QList FileInfoList; //---------------------------------------------------------------------- // Static Functions //---------------------------------------------------------------------- /** * Format a file / subtree size human readable, i.e. in "GB" / "MB" * etc. rather than huge numbers of digits. * * Note: For logDebug() etc., operator<< is overwritten to do exactly that: * * logDebug() << "Size: " << x->totalSize() << endl; **/ QString formatSize ( FileSize lSize ); /** * Format a timestamp (like the latestMTime()) human-readable. **/ QString formatTime( time_t rawTime ); /** * Return the last pathname component of a file name. * * Examples: * * "/home/bob/foo.txt" -> "foo.txt" * "foo.txt" -> "foo.txt" * "/usr/bin" -> "bin" * "/usr/bin/" -> "bin" **/ QString baseName( const QString & fileName ); /** * Print the debugUrl() of a @ref FileInfo in a debug stream. **/ inline QTextStream & operator<< ( QTextStream & stream, const FileInfo * info ) { if ( info ) { if ( info->checkMagicNumber() ) stream << info->debugUrl(); else stream << ""; } else stream << ""; return stream; } /** * Human-readable output of a file size in a debug stream. **/ inline QTextStream & operator<< ( QTextStream & stream, FileSize lSize ) { stream << formatSize( lSize ); return stream; } } // namespace QDirStat #endif // ifndef FileInfo_h qdirstat-1.4/src/FileInfoIterator.cpp000066400000000000000000000046541311502036700177200ustar00rootroot00000000000000/* * File name: FileInfoIterator.cpp * Summary: Support classes for QDirStat - DirTree iterator classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "FileInfoIterator.h" #include "FileInfoSorter.h" #include "Exception.h" using namespace QDirStat; FileInfoIterator::FileInfoIterator( FileInfo * parent ) { init( parent, true ); // callNext } FileInfoIterator::FileInfoIterator( FileInfo * parent, bool callNext ) { init( parent, callNext ); } void FileInfoIterator::init( FileInfo * parent, bool callNext ) { _parent = parent; _current = 0; _directChildrenProcessed = false; _dotEntryProcessed = false; if ( callNext ) next(); } void FileInfoIterator::next() { if ( ! _directChildrenProcessed ) { // Process direct children _current = _current ? _current->next() : _parent->firstChild(); if ( ! _current ) { _directChildrenProcessed = true; next(); } } else // _directChildrenProcessed { if ( ! _dotEntryProcessed ) { // Process dot entry _current = _parent->dotEntry(); _dotEntryProcessed = true; } else // Dot entry already processed { _current = 0; } } } int FileInfoIterator::count() { int cnt = 0; // Count direct children FileInfo * child = _parent->firstChild(); while ( child ) { cnt++; child = child->next(); } // Handle the dot entry if ( _parent->dotEntry() ) cnt++; return cnt; } FileInfoSortedBySizeIterator::FileInfoSortedBySizeIterator( FileInfo * parent, FileSize minSize, Qt::SortOrder sortOrder ) { _currentIndex = 0; FileInfoIterator it( parent ); while ( *it ) { if ( (*it)->totalSize() >= minSize ) _sortedChildren << *it; ++it; } std::stable_sort( _sortedChildren.begin(), _sortedChildren.end(), FileInfoSorter( TotalSizeCol, sortOrder ) ); } FileInfo * FileInfoSortedBySizeIterator::current() { if ( _currentIndex >= 0 && _currentIndex < _sortedChildren.size() ) return _sortedChildren.at( _currentIndex ); else return 0; } void FileInfoSortedBySizeIterator::next() { // Intentionally letting _currentIndex move one position after the last so // current() will return 0 to indicate we are finished. if ( _currentIndex < _sortedChildren.size() ) _currentIndex++; } qdirstat-1.4/src/FileInfoIterator.h000066400000000000000000000065131311502036700173610ustar00rootroot00000000000000/* * File name: FileInfoIterator.h * Summary: Support classes for QDirStat - DirTree iterators * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileInfoIterator_h #define FileInfoIterator_h #include #include "FileInfo.h" namespace QDirStat { /** * Iterator class for children of a @ref FileInfo object. For optimum * performance, this iterator class does NOT return children in any * specific sort order. * * Sample usage: * * FileInfoIterator it( node ); * * while ( *it ) * { * logDebug() << *it << ":\t" << (*it)->totalSize() << endl; * ++it; * } * * This will output the URL (path+name) and the total size of each (direct) * subdirectory child and each (direct) file child of 'node'. * Notice: This does not recurse into subdirectories! * * @short (unsorted) iterator for @ref FileInfo children. **/ class FileInfoIterator { public: /** * Constructor: Initialize an iterator object to iterate over the * children of 'parent' (unsorted!). The dot entry is treated as a * subdirectory. **/ FileInfoIterator( FileInfo * parent ); protected: /** * Alternate constructor to be called from derived classes: Those can * choose not to call next() in the constructor. **/ FileInfoIterator( FileInfo * parent, bool callNext ); private: /** * Internal initialization called from any constructor. **/ void init( FileInfo * parent, bool callNext ); public: /** * Return the current child object or 0 if there is no more. * Same as @ref operator*() . **/ FileInfo * current() { return _current; } /** * Return the current child object or 0 if there is no more. * Same as @ref current(). **/ FileInfo * operator*() { return current(); } /** * Advance to the next child. Same as @ref operator++(). **/ void next(); /** * Advance to the next child. Same as @ref next(). **/ void operator++() { next(); } /** * Return the number of items that will be processed. * This is an expensive operation. **/ int count(); protected: FileInfo * _parent; FileInfo * _current; bool _directChildrenProcessed; bool _dotEntryProcessed; }; // class FileInfoIterator class FileInfoSortedBySizeIterator { public: /** * Constructor. Children below 'minSize' will be ignored by this iterator. **/ FileInfoSortedBySizeIterator( FileInfo * parent, FileSize minSize = 0, Qt::SortOrder sortOrder = Qt::DescendingOrder ); /** * Return the current child object or 0 if there is no more. * Same as @ref operator*() . **/ FileInfo * current(); /** * Return the current child object or 0 if there is no more. * Same as @ref current(). **/ FileInfo * operator*() { return current(); } /** * Advance to the next child. Same as @ref operator++(). **/ void next(); /** * Advance to the next child. Same as @ref next(). **/ void operator++() { next(); } /** * Return the number of items that will be processed. **/ int count() { return _sortedChildren.size(); } protected: FileInfoList _sortedChildren; int _currentIndex; }; // } // namespace QDirStat #endif // ifndef FileInfoIterator_h qdirstat-1.4/src/FileInfoSet.cpp000066400000000000000000000046701311502036700166600ustar00rootroot00000000000000/* * File name: FileInfoSet.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "FileInfoSet.h" #include "FileInfo.h" #include "DirInfo.h" #include "DirTree.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; bool FileInfoSet::containsAncestorOf( FileInfo * item ) const { while ( item ) { item = item->parent(); if ( contains( item ) ) return true; } return false; } FileInfoSet FileInfoSet::normalized() const { FileInfoSet normalized; foreach ( FileInfo * item, *this ) { if ( ! containsAncestorOf( item ) ) normalized << item; #if 0 else logDebug() << "Removing " << item << " with ancestors in the set" << endl; #endif } return normalized; } FileInfoSet FileInfoSet::invalidRemoved() const { FileInfoSet result; foreach ( FileInfo * item, *this ) { if ( item->checkMagicNumber() ) { logDebug() << "Keeping " << item << endl; result << item; } else { logDebug() << "Removing invalid item" << endl; } } return result; } FileInfo * FileInfoSet::first() const { if ( isEmpty() ) return 0; else return *begin(); } bool FileInfoSet::containsDotEntry() const { foreach ( FileInfo * item, *this ) { if ( item && item->isDotEntry() ) return true; } return false; } bool FileInfoSet::containsDir() const { foreach ( FileInfo * item, *this ) { if ( item && item->isDir() ) return true; } return false; } bool FileInfoSet::containsFile() const { foreach ( FileInfo * item, *this ) { if ( item && item->isFile() ) return true; } return false; } bool FileInfoSet::containsSpecial() const { foreach ( FileInfo * item, *this ) { if ( item && item->isSpecial() ) return true; } return false; } bool FileInfoSet::containsBusyItem() const { foreach ( FileInfo * item, *this ) { if ( item && item->isBusy() ) return true; } return false; } bool FileInfoSet::treeIsBusy() const { if ( isEmpty() ) return false; return first()->tree()->isBusy(); } FileSize FileInfoSet::totalSize() const { FileSize sum = 0LL; foreach ( FileInfo * item, *this ) { if ( item ) sum += item->totalSize(); } return sum; } qdirstat-1.4/src/FileInfoSet.h000066400000000000000000000050201311502036700163130ustar00rootroot00000000000000/* * File name: FileInfoSet.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileInfoSet_h #define FileInfoSet_h #include #include "FileInfo.h" namespace QDirStat { /** * Container for FileInfo pointers. This is a wrapper around QSet with a * few add-on functions. **/ class FileInfoSet: public QSet { public: FileInfoSet(): QSet() {} /** * Return the first item in this set or 0 if the set is empty. * * This makes most sense if there is only one item at all; * otherwise it would be completely random which item would be * returned as the first. **/ FileInfo * first() const; /** * Return 'true' if the set contains any dot entry. **/ bool containsDotEntry() const; /** * Return 'true' if the set contains any directory item. **/ bool containsDir() const; /** * Return 'true' if the set contains any file item. **/ bool containsFile() const; /** * Return 'true' if the set contains any special file, * i.e., a char or block device, a FIFO, or a socket. **/ bool containsSpecial() const; /** * Return the sum of all total sizes in the set. * * It is desirable to call this on a normalized() set to avoid * duplicate accounting of sums. **/ FileSize totalSize() const; /** * Return 'true' if this set contains any ancestor (parent, parent's * parent etc.) of 'item'. This does not check if 'item' itself is in * the set. **/ bool containsAncestorOf( FileInfo * item ) const; /** * Return 'true' if any item in this set is busy. **/ bool containsBusyItem() const; /** * Return 'true' if this set is non-empty and the dir tree is busy. **/ bool treeIsBusy() const; /** * Return a set with all the invalid items removed, i.e. without items * where checkMagicNumber() returns 'false'. * * If there is reason to believe that any items of the set might have * become invalid, call this first before any other operations. * * Notice that this does not modify the existing set, but you can * of course assign the result of this to the set. **/ FileInfoSet invalidRemoved() const; /** * Return a 'normalized' set, i.e. with all items removed that have * ancestors in the set. **/ FileInfoSet normalized() const; }; // class FileInfoSet } // namespace QDirStat #endif // FileInfoSet_h qdirstat-1.4/src/FileInfoSorter.cpp000066400000000000000000000027771311502036700174110ustar00rootroot00000000000000/* * File name: FileInfoSorter.cpp * Summary: Functor to handle sorting FileInfo objects * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "FileInfoSorter.h" using namespace QDirStat; bool FileInfoSorter::operator() ( FileInfo * a, FileInfo * b ) { if ( !a || !b ) return false; if ( _sortOrder == Qt::DescendingOrder ) std::swap( a, b ); // Now we only need to handle the a < b case switch ( _sortCol ) { case NameCol: { // The dot entry (there can only be one) should always come last if ( a->isDotEntry() ) return false; if ( b->isDotEntry() ) return true; return a->name() < b->name(); } case PercentBarCol: return a->subtreePercent() < b->subtreePercent(); case PercentNumCol: return a->subtreePercent() < b->subtreePercent(); case TotalSizeCol: return a->totalSize() < b->totalSize(); case OwnSizeCol: return a->size() < b->size(); case TotalItemsCol: return a->totalItems() < b->totalItems(); case TotalFilesCol: return a->totalFiles() < b->totalFiles(); case TotalSubDirsCol: return a->totalSubDirs() < b->totalSubDirs(); case LatestMTimeCol: return a->latestMtime() < b->latestMtime(); case ReadJobsCol: return a->pendingReadJobs() < b->pendingReadJobs(); case UndefinedCol: return false; // Intentionally omitting the 'default' branch // so the compiler can warn about unhandled enum values } return false; } qdirstat-1.4/src/FileInfoSorter.h000066400000000000000000000033071311502036700170440ustar00rootroot00000000000000/* * File name: FileInfoSorter.h * Summary: Functor to handle sorting FileInfo objects * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileInfoSorter_h #define FileInfoSorter_h #include "FileInfo.h" #include "DataColumns.h" namespace QDirStat { /** * Functor class for sorting FileInfo objects with C++ STL sorting * algorithms like std::sort(), std::stable_sort(). * * Those STL algorithms expect two iterators and either a sort function * that works like a normal operator<() or a functor object that has an * overloaded operator() that will then be called with the two objects to * compare. The latter is what this class provides. * * Example: * * FileInfoList childrenList; * std::sort( childrenList.begin(), * childrenList.end(), * FileInfoSorter( LatestMtimeCol, Qt::DescendingOrder ) ); * * For each element pair to compare, the FileInfoSorter's operator() will * be called with that pair as arguments. **/ class FileInfoSorter { public: /** * Constructor. This sets the sort column and sort order that will be * used in subsequent calls. **/ FileInfoSorter( DataColumn sortCol, Qt::SortOrder sortOrder ): _sortCol( sortCol ), _sortOrder( sortOrder ) {} /** * Overloaded operator() that does the comparison. * returns 'true' if a < b, false otherwise (i.e., if a >= b). **/ bool operator() ( FileInfo * a, FileInfo * b ); private: DataColumn _sortCol; Qt::SortOrder _sortOrder; }; // class FileInfoSorter } // namespace QDirStat #endif // FileInfoSorter_h qdirstat-1.4/src/FileSizeStats.cpp000066400000000000000000000175171311502036700172460ustar00rootroot00000000000000/* * File name: FileSizeStats.cpp * Summary: Statistics classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include // ceil() #include #include "FileSizeStats.h" #include "FileInfoIterator.h" #include "DirTree.h" #include "Exception.h" #define VERBOSE_SORT_THRESHOLD 50000 using namespace QDirStat; FileSizeStats::FileSizeStats(): _sorted( false ) { } void FileSizeStats::clear() { // Just _data.clear() does not free any memory; we need to assign an empty // list to _data. _data = FileSizeList(); } void FileSizeStats::collect( DirTree * tree ) { Q_CHECK_PTR( tree ); collect( tree->root() ); } void FileSizeStats::collect( FileInfo * subtree ) { Q_CHECK_PTR( subtree ); if ( _data.isEmpty() ) _data.reserve( subtree->totalFiles() ); if ( subtree->isFile() ) _data << subtree->size(); FileInfoIterator it( subtree ); while ( *it ) { FileInfo * item = *it; if ( item->hasChildren() ) { collect( item ); } else if ( item->isFile() ) { _data << item->size(); } // Disregard symlinks, block devices and other special files ++it; } } void FileSizeStats::collect( DirTree * tree, const QString & suffix ) { Q_CHECK_PTR( tree ); if ( ! suffix.startsWith( "." ) ) { logError() << "Suffix should start with \".\" - got \"" << suffix << "\"" << endl; } collect( tree->root(), suffix ); } void FileSizeStats::collect( FileInfo * subtree, const QString & suffix ) { Q_CHECK_PTR( subtree ); if ( _data.isEmpty() ) _data.reserve( subtree->totalFiles() ); if ( subtree->isFile() && subtree->name().toLower().endsWith( suffix ) ) _data << subtree->size(); FileInfoIterator it( subtree ); while ( *it ) { FileInfo * item = *it; if ( item->hasChildren() ) { collect( item, suffix ); } else if ( item->isFile() ) { if ( item->name().toLower().endsWith( suffix ) ) _data << item->size(); } // Disregard symlinks, block devices and other special files ++it; } } void FileSizeStats::sort() { if ( _data.size() > VERBOSE_SORT_THRESHOLD ) logDebug() << "Sorting " << _data.size() << " elements" << endl; std::sort( _data.begin(), _data.end() ); _sorted = true; if ( _data.size() > VERBOSE_SORT_THRESHOLD ) logDebug() << "Sorting done." << endl; } FileSize FileSizeStats::median() { if ( _data.isEmpty() ) return 0; if ( ! _sorted ) sort(); int centerPos = _data.size() / 2; // Since we are doing integer division, the center is already rounded down // if there is an odd number of data items, so don't use the usual -1 to // compensate for the index of the first data element being 0, not 1: if // _data.size() is 5, we get _data[2] which is the center of // [0, 1, 2, 3, 4]. FileSize result = _data.at( centerPos ); if ( _data.size() % 2 == 0 ) // Even number of data { // Use the average of the two center items. We already accounted for // the upper one with the above integer division, so now we need to // account for the lower one: If _data.size() is 6, we already got // _data[3], and now we need to average this with _data[2] of // [0, 1, 2, 3, 4, 5]. // // Since our value type FileSize is also an integer type, it is // arbitrary if we round this average up or down, so let's keep the // default "round down" result. result = ( result + _data.at( centerPos - 1 ) ) / 2; } return result; } FileSize FileSizeStats::average() { if ( _data.isEmpty() ) return 0; int count = _data.size(); FileSize sum = 0; for ( int i=0; i < count; ++i ) sum += _data.at(i); return sum / count; } FileSize FileSizeStats::min() { if ( _data.isEmpty() ) return 0; if ( ! _sorted ) sort(); return _data.first(); } FileSize FileSizeStats::max() { if ( _data.isEmpty() ) return 0; if ( ! _sorted ) sort(); return _data.last(); } FileSize FileSizeStats::quantile( int order, int number ) { if ( _data.isEmpty() ) return 0; if ( number > order ) { QString msg = QString( "Cannot determine quantile #%1" ).arg( number ); msg += QString( " for %1-quantile" ).arg( order ); THROW( Exception( msg ) ); } if ( order < 2 ) { QString msg = QString( "Invalid quantile order %1" ).arg( order ); THROW( Exception( msg ) ); } if ( ! _sorted ) sort(); if ( number == 0 ) return _data.first(); if ( number == order ) return _data.last(); int pos = ( _data.size() * number ) / order; // Same as in median(): The integer division already cut off any non-zero // decimal place, so don't subtract 1 to compensate for starting _data with // index 0. FileSize result = _data.at( pos ); if ( ( _data.size() * number ) % order == 0 ) { // Same as in median: We hit between two elements, so use the average // between them. result = ( result + _data.at( pos - 1 ) ) / 2; } return result; } QRealList FileSizeStats::fillBuckets( int bucketCount, int startPercentile, int endPercentile ) { CHECK_INDEX( startPercentile, 0, 100 ); CHECK_INDEX( endPercentile, 0, 100 ); if ( startPercentile >= endPercentile ) THROW( Exception( "startPercentile must be less than endPercentile" ) ); if ( bucketCount < 1 ) THROW( Exception( QString( "Invalid bucket count %1" ).arg( bucketCount ) ) ); QRealList buckets; buckets.reserve( bucketCount ); for ( int i=0; i < bucketCount; ++i ) buckets << 0; if ( _data.isEmpty() ) return buckets; // The first call to percentile() or quantile() will cause the data to be // sorted, so there is no need to sort them again here. qreal startVal = percentile( startPercentile ); qreal endVal = percentile( endPercentile ); qreal bucketWidth = ( endVal - startVal ) / bucketCount; #if 1 logDebug() << "startPercentile: " << startPercentile << " endPercentile: " << endPercentile << " startVal: " << formatSize( startVal ) << " endVal: " << formatSize( endVal ) << " bucketWidth: " << formatSize( bucketWidth ) << endl; #endif for ( int i=0; i < _data.size(); ++i ) { qreal val = _data.at( i ); if ( val < startVal ) continue; if ( val > endVal ) break; // TO DO: Optimize this by taking into account that the data are sorted // already. We don't really need that many divisions; just when leaving // the current bucket would be sufficient. int index = qMin( ( val - startVal ) / bucketWidth, bucketCount - 1.0 ); ++buckets[ index ]; } return buckets; } QRealList FileSizeStats::percentileList() { QRealList percentiles; percentiles.reserve( 100 ); for ( int i=0; i <= 100; ++i ) percentiles << percentile( i ); return percentiles; } QRealList FileSizeStats::percentileSums() { QRealList sums; sums.reserve( 100 ); for ( int i=0; i <= 100; ++i ) sums << 0.0; if ( ! _sorted ) sort(); qreal percentileSize = _data.size() / 100.0; for ( int i=0; i < _data.size(); ++i ) { int percentile = qMax( 1, (int) ceil( i / percentileSize ) ); sums[ percentile ] += _data.at(i); } #if 0 for ( int i=0; i < sums.size(); ++i ) logDebug() << "sum[ " << i << " ] : " << formatSize( sums[i] ) << endl; #endif return sums; } qdirstat-1.4/src/FileSizeStats.h000066400000000000000000000107261311502036700167060ustar00rootroot00000000000000/* * File name: FileSizeStats.h * Summary: Statistics classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileSizeStats_h #define FileSizeStats_h #include "FileInfo.h" #include "HistogramView.h" namespace QDirStat { class DirTree; typedef QList FileSizeList; /** * Helper class for extended file size statistics. * * This collects file size data for trees or subtrees for later use for * calculating a median or quantiles or histograms. * * Notice that one data item (one FileSize, i.e. one 64 bit long long) is * stored for each file (or each matching file) in this object, so this is * expensive in terms of memory usage. Also, since data usually need to be * sorted for those calculations and sorting has at least logarithmic cost * O( n * log(n) ), this also has heavy performance impact. **/ class FileSizeStats { public: /** * Constructor. **/ FileSizeStats(); /** * Clear the collected data and shrink the list. **/ void clear(); /** * Recurse through all file elements in the tree and append the own * size for each file to the data collection. Notice that the data are * unsorted after this. **/ void collect( DirTree * tree ); /** * Recurse through all file elements in the subtree and append the own * size for each file to the data collection. Notice that the data are * unsorted after this. **/ void collect( FileInfo * subtree ); /** * Recurse through all file elements in the tree and append the own * size for each file with the specified suffix to the data * collection. Notice that the data are unsorted after this. * * 'suffix' should start with ".", e.g. ".jpg". **/ void collect( DirTree * tree, const QString & suffix ); /** * Recurse through all file elements in the subtree and append the own * size for each file with the specified suffix to the data * collection. Notice that the data are unsorted after this. * * 'suffix' should start with ".", e.g. ".jpg". **/ void collect( FileInfo * subtree, const QString & suffix ); /** * Sort the collected data in ascending order. * This is necessary after all collect() calls. * The **/ void sort(); /** * Return the size of the collected data, i.e. the number of data * points. **/ int dataSize() const { return _data.size(); } /** * Return a reference to the collected data. **/ FileSizeList & data() { return _data; } // All calculation functions below will sort the internal data first if // they are not sorted yet. This is why they are not const. /** * Calculate the median. **/ FileSize median(); /** * Calculate the arithmetic average based on the collected data. * * Notice that this is probably the most expensive way of doing this: * The FileInfo class already collected sums and counts during * directory reading that might also be used. **/ FileSize average(); /** * Find the minimum value. **/ FileSize min(); /** * Find the maximum value. **/ FileSize max(); /** * Calculate a quantile: Find the quantile no. 'number' of order * 'order'. * * The median is quantile( 2, 1 ), the minimum is quantile( 2, 0 ), the * maximum is quantile( 2, 2 ). The first quartile is quantile( 4, 1 ), * the first percentile is quantile( 100, 1 ). **/ FileSize quantile( int order, int number ); /** * Calculate a percentile. **/ FileSize percentile( int number ) { return quantile( 100, number ); } /** * Calculate a quartile. **/ FileSize quartile( int number ) { return quantile( 4, number ); } /** * Fill buckets for a histogram from 'startPercentile' to * 'endPercentile'. **/ QRealList fillBuckets( int bucketCount, int startPercentile, int endPercentile ); /** * Return a list of all percentiles from 0 to 100. **/ QRealList percentileList(); /** * Return a list (0..100) of all accumulated sizes between one * percentile and the previous one. **/ QRealList percentileSums(); protected: FileSizeList _data; bool _sorted; }; } // namespace QDirStat #endif // ifndef FileSizeStats_h qdirstat-1.4/src/FileSizeStatsWindow.cpp000066400000000000000000000311761311502036700204330ustar00rootroot00000000000000/* * File name: FileSizeStatsWindow.cpp * Summary: QDirStat size type statistics window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include #include "FileSizeStatsWindow.h" #include "FileSizeStats.h" #include "HistogramView.h" #include "BucketsTableModel.h" #include "DirTree.h" #include "MainWindow.h" #include "SettingsHelpers.h" #include "HeaderTweaker.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; QPointer FileSizeStatsWindow::_sharedInstance = 0; FileSizeStatsWindow::FileSizeStatsWindow( QWidget * parent ): QDialog( parent ), _ui( new Ui::FileSizeStatsWindow ), _subtree( 0 ), _suffix( "" ), _stats( 0 ) { // logDebug() << "init" << endl; CHECK_NEW( _ui ); _ui->setupUi( this ); initWidgets(); readWindowSettings( this, "FileSizeStatsWindow" ); _stats = new FileSizeStats(); CHECK_NEW( _stats ); _bucketsTableModel = new BucketsTableModel( this, _ui->histogramView ); CHECK_NEW( _bucketsTableModel ); _ui->bucketsTable->setModel( _bucketsTableModel ); QList helpButtons = _ui->helpPage->findChildren(); foreach ( QCommandLinkButton * helpButton, helpButtons ) { connect( helpButton, SIGNAL( clicked() ), this, SLOT ( showHelp() ) ); } } FileSizeStatsWindow::~FileSizeStatsWindow() { // logDebug() << "destroying" << endl; writeWindowSettings( this, "FileSizeStatsWindow" ); } FileSizeStatsWindow * FileSizeStatsWindow::sharedInstance() { if ( ! _sharedInstance ) { QWidget * parent = 0; QWidgetList toplevel = QApplication::topLevelWidgets(); for ( QWidgetList::const_iterator it = toplevel.constBegin(); it != toplevel.constEnd() && ! parent; ++it ) { parent = qobject_cast( *it ); } if ( ! parent ) logWarning() << "NULL parent for shared instance" << endl; _sharedInstance = new FileSizeStatsWindow( parent ); CHECK_NEW( _sharedInstance ); } return _sharedInstance; } void FileSizeStatsWindow::clear() { _stats->clear(); } void FileSizeStatsWindow::initWidgets() { QFont font = _ui->heading->font(); font.setBold( true ); _ui->heading->setFont( font ); _ui->optionsPanel->hide(); connect( _ui->percentileFilterComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT ( fillPercentileTable() ) ); connect( _ui->optionsButton, SIGNAL( clicked() ), this, SLOT ( toggleOptions() ) ); connect( _ui->autoButton, SIGNAL( clicked() ), this, SLOT ( autoPercentiles() ) ); connect( _ui->startPercentileSlider, SIGNAL( valueChanged( int ) ), this, SLOT ( applyOptions() ) ); connect( _ui->startPercentileSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT ( applyOptions() ) ); connect( _ui->endPercentileSlider, SIGNAL( valueChanged( int ) ), this, SLOT ( applyOptions() ) ); connect( _ui->endPercentileSpinBox, SIGNAL( valueChanged( int ) ), this, SLOT ( applyOptions() ) ); } void FileSizeStatsWindow::calc() { _stats->clear(); if ( _suffix.isEmpty() ) _stats->collect( _subtree ); else _stats->collect( _subtree, _suffix ); _stats->sort(); } void FileSizeStatsWindow::populateSharedInstance( FileInfo * subtree, const QString & suffix ) { sharedInstance()->populate( subtree, suffix ); sharedInstance()->show(); } void FileSizeStatsWindow::populate( FileInfo * subtree, const QString & suffix ) { _subtree = subtree; _suffix = suffix; if ( _suffix.startsWith( "*." ) ) _suffix.remove( 0, 1 ); if ( ! _subtree ) { logWarning() << "No tree" << endl; return; } QString url = subtree->debugUrl(); if ( url == "" ) url = subtree->tree()->url(); if ( _suffix.isEmpty() ) _ui->heading->setText( tr( "File Size Statistics for %1" ).arg( url ) ); else _ui->heading->setText( tr( "File Size Statistics for %1 in %2" ) .arg( suffix ).arg( url ) ); calc(); fillHistogram(); fillPercentileTable(); } void FileSizeStatsWindow::fillPercentileTable() { int step = _ui->percentileFilterComboBox->currentIndex() == 0 ? 5 : 1; fillQuantileTable( _ui->percentileTable, 100, "P", _stats->percentileSums(), step, 2 ); } QStringList FileSizeStatsWindow::quantile( int order, const QString & name ) { QStringList text; if ( _stats->dataSize() < 2 * order ) return text; for ( int i=1; i < order; ++i ) { text << QString( "%1. %2: %3" ).arg( i ) .arg( name ) .arg( formatSize( _stats->quantile( order, i ) ) ); } text << ""; return text; } void FileSizeStatsWindow::fillQuantileTable( QTableWidget * table, int order, const QString & namePrefix, const QRealList & sums, int step, int extremesMargin ) { enum TableColumns { NumberCol, ValueCol, NameCol, SumCol }; table->clear(); table->setColumnCount( sums.isEmpty() ? 3 : 4 ); table->setRowCount( order + 1 ); QStringList header; switch ( order ) { case 100: header << tr( "Percentile" ); break; case 10: header << tr( "Decile" ); break; case 4: header << tr( "Quartile" ); break; default: header << tr( "%1-Quantile" ).arg( order ); break; } header << tr( "Value" ) << tr( "Name" ); if ( ! sums.isEmpty() ) header << tr( "Sum %1(n-1)..%2(n)" ).arg( namePrefix ).arg( namePrefix ); for ( int col = 0; col < header.size(); ++col ) { QString text = " " + header[ col ] + " "; table->setHorizontalHeaderItem( col, new QTableWidgetItem( text ) ); } int median = order / 2; int quartile_1 = -1; int quartile_3 = -1; if ( order % 4 == 0 ) { quartile_1 = order / 4; quartile_3 = quartile_1 * 3; } int row = 0; for ( int i=0; i <= order; ++i ) { if ( step > 1 && i > extremesMargin && i < order - extremesMargin && i % step != 0 ) { continue; } addItem( table, row, NumberCol, namePrefix + QString::number( i ) ); addItem( table, row, ValueCol, formatSize( _stats->quantile( order, i ) ) ); if ( i > 0 && i < sums.size() ) addItem( table, row, SumCol, formatSize( sums.at( i ) ) ); if ( i == 0 || i == median || i == order || i == quartile_1 || i == quartile_3 ) { QString text; if ( i == 0 ) text = tr( "Min" ); else if ( i == order ) text = tr( "Max" ); else if ( i == median ) text = tr( "Median" ); else if ( i == quartile_1 ) text = tr( "1. Quartile" ); else if ( i == quartile_3 ) text = tr( "3. Quartile" ); addItem( table, row, NameCol, text ); setRowBold( table, row ); setRowForeground( table, row, QBrush( QColor( Qt::blue ) ) ); } else if ( order > 20 && i % 10 == 0 && step <= 1 ) { addItem( table, row, NameCol, "" ); // Fill the empty cell setRowBackground( table, row, QBrush( QColor( 0xE0, 0xE0, 0xF0 ), Qt::SolidPattern ) ); } ++row; } table->setRowCount( row ); setColAlignment( table, NumberCol, Qt::AlignRight | Qt::AlignVCenter ); setColAlignment( table, ValueCol, Qt::AlignRight | Qt::AlignVCenter ); setColAlignment( table, NameCol, Qt::AlignCenter | Qt::AlignVCenter ); setColAlignment( table, SumCol, Qt::AlignRight | Qt::AlignVCenter ); HeaderTweaker::resizeToContents( table->horizontalHeader() ); } QTableWidgetItem * FileSizeStatsWindow::addItem( QTableWidget * table, int row, int col, const QString & text ) { QTableWidgetItem * item = new QTableWidgetItem( text ); CHECK_NEW( item ); table->setItem( row, col, item ); return item; } void FileSizeStatsWindow::setRowBold( QTableWidget * table, int row ) { for ( int col=0; col < table->columnCount(); ++col ) { QTableWidgetItem * item = table->item( row, col ); if ( item ) { QFont font = item->font(); font.setBold( true ); item->setFont( font ); } } } void FileSizeStatsWindow::setRowForeground( QTableWidget * table, int row, const QBrush & brush ) { for ( int col=0; col < table->columnCount(); ++col ) { QTableWidgetItem * item = table->item( row, col ); if ( item ) item->setForeground( brush ); } } void FileSizeStatsWindow::setRowBackground( QTableWidget * table, int row, const QBrush & brush ) { for ( int col=0; col < table->columnCount(); ++col ) { QTableWidgetItem * item = table->item( row, col ); if ( item ) item->setBackground( brush ); } } void FileSizeStatsWindow::setColAlignment( QTableWidget * table, int col, int alignment ) { for ( int row=0; row < table->rowCount(); ++row ) { QTableWidgetItem * item = table->item( row, col ); if ( item ) item->setTextAlignment( alignment ); } } void FileSizeStatsWindow::fillHistogram() { HistogramView * histogram = _ui->histogramView; CHECK_PTR( histogram ); histogram->clear(); histogram->setPercentiles( _stats->percentileList() ); histogram->setPercentileSums( _stats->percentileSums() ); histogram->autoStartEndPercentiles(); updateOptions(); fillBuckets(); histogram->autoLogHeightScale(); histogram->rebuild(); } void FileSizeStatsWindow::fillBuckets() { HistogramView * histogram = _ui->histogramView; int startPercentile = histogram->startPercentile(); int endPercentile = histogram->endPercentile(); int percentileCount = endPercentile - startPercentile; int dataCount = _stats->dataSize() * ( percentileCount / 100.0 ); int bucketCount = histogram->bestBucketCount( dataCount ); QRealList buckets = _stats->fillBuckets( bucketCount, startPercentile, endPercentile ); histogram->setBuckets( buckets ); fillBucketsTable(); } void FileSizeStatsWindow::fillBucketsTable() { _bucketsTableModel->reset(); HeaderTweaker::resizeToContents( _ui->bucketsTable->horizontalHeader() ); } void FileSizeStatsWindow::reject() { deleteLater(); } void FileSizeStatsWindow::toggleOptions() { if ( _ui->optionsPanel->isVisible() ) { _ui->optionsPanel->hide(); _ui->optionsButton->setText( tr( "&Options >>" ) ); } else { _ui->optionsPanel->show(); _ui->optionsButton->setText( tr( "<< &Options" ) ); updateOptions(); } } void FileSizeStatsWindow::applyOptions() { HistogramView * histogram = _ui->histogramView; int newStart = _ui->startPercentileSlider->value(); int newEnd = _ui->endPercentileSlider->value(); if ( newStart != histogram->startPercentile() || newEnd != histogram->endPercentile() ) { logDebug() << "New start: " << newStart << " new end: " << newEnd << endl; histogram->setStartPercentile( newStart ); histogram->setEndPercentile ( newEnd ); fillBuckets(); histogram->autoLogHeightScale(); // FIXME histogram->rebuild(); } } void FileSizeStatsWindow::autoPercentiles() { _ui->histogramView->autoStartEndPercentiles(); updateOptions(); fillBuckets(); _ui->histogramView->autoLogHeightScale(); // FIXME _ui->histogramView->rebuild(); } void FileSizeStatsWindow::updateOptions() { HistogramView * histogram = _ui->histogramView; _ui->startPercentileSlider->setValue ( histogram->startPercentile() ); _ui->startPercentileSpinBox->setValue( histogram->startPercentile() ); _ui->endPercentileSlider->setValue ( histogram->endPercentile() ); _ui->endPercentileSpinBox->setValue( histogram->endPercentile() ); } void FileSizeStatsWindow::showHelp() { QString topic = "Statistics.md"; QObject * button = sender(); if ( button == _ui->medianPercentilesHelpButton ) topic = "Median-Percentiles.md"; else if ( button == _ui->histogramsInGeneralHelpButton ) topic = "Histograms-in-General.md"; else if ( button == _ui->fileSizeHistogramHelpButton ) topic = "File-Size-Histogram.md"; else if ( button == _ui->overflowAreaHelpButton ) topic = "Overflow-Area.md"; else if ( button == _ui->histogramOptionsHelpButton ) topic = "Histogram-Options.md"; else if ( button == _ui->percentilesTableHelpButton ) topic = "Percentiles-Table.md"; else if ( button == _ui->bucketsTableHelpButton ) topic = "Buckets-Table.md"; logInfo() << "Help topic: " << topic << endl; QString helpUrl = "https://github.com/shundhammer/qdirstat/blob/master/doc/stats/" + topic; QString program = "/usr/bin/xdg-open"; logInfo() << "Starting " << program << " " << helpUrl << endl; QProcess::startDetached( program, QStringList() << helpUrl ); } qdirstat-1.4/src/FileSizeStatsWindow.h000066400000000000000000000141231311502036700200710ustar00rootroot00000000000000/* * File name: FileSizeStatsWindow.h * Summary: QDirStat file size statistics window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileSizeStatsWindow_h #define FileSizeStatsWindow_h #include #include #include "ui_file-size-stats-window.h" #include "FileInfo.h" class QTableWidget; namespace QDirStat { class DirTree; class FileSizeStats; class BucketsTableModel; /** * Modeless dialog to display file size statistics: * median, min, max, quartiles; histogram; percentiles table. **/ class FileSizeStatsWindow: public QDialog { Q_OBJECT public: /** * Constructor. * * Notice that this widget will destroy itself upon window close. * * It is advised to use a QPointer for storing a pointer to an instance * of this class. The QPointer will keep track of this window * auto-deleting itself when closed. **/ FileSizeStatsWindow( QWidget * parent ); /** * Destructor. **/ virtual ~FileSizeStatsWindow(); /** * Populate with new content. **/ void populate( FileInfo * subtree, const QString & suffix = "" ); /** * Return the corresponding subtree. **/ FileInfo * subtree() const { return _subtree; } /** * Return the filename suffix to filter the collected information. **/ QString suffix() const { return _suffix; } /** * Static method for using one shared instance of this class between * multiple parts of the application. This will create a new instance * if there is none yet (or anymore). * * Do not hold on to this pointer; the instance destroys itself when * the user closes the window, and then the pointer becomes invalid. * * After getting this shared instance, call populate() and show(). **/ static FileSizeStatsWindow * sharedInstance(); /** * Convenience function for creating, populating and showing the shared * instance. **/ static void populateSharedInstance( FileInfo * subtree, const QString & suffix = "" ); public slots: /** * Reject the dialog contents, i.e. the user clicked the "Cancel" * or WM_CLOSE button. * * Reimplemented from QDialog. **/ virtual void reject() Q_DECL_OVERRIDE; protected slots: /** * Fill the percentiles table depending on the content of the filter * combo box in the same tab. **/ void fillPercentileTable(); /** * Make the histogram options visible or invisible. **/ void toggleOptions(); /** * Check the options widgets for any new values, apply them and rebuild * the histogram. **/ void applyOptions(); /** * Calculate automatic values for the start and end percentiles, apply * them and rebuild the histogram. **/ void autoPercentiles(); /** * Show help for a topic determinded by the sender of this signal. **/ void showHelp(); protected: /** * Clear all data and widget contents. **/ void clear(); /** * Calculate the statistics from the tree. **/ void calc(); /** * One-time initialization of the widgets in this window. **/ void initWidgets(); /** * Update the values for the option widgets from the current ones from * the histogram. **/ void updateOptions(); /** * Return text for all quantiles of 'order' named 'name'. **/ QStringList quantile( int order, const QString & name ); /** * Fill a quantile table for 'order' quantiles with content. * * 'sums' (if non-empty) is a list of accumulated sums between one * quantile and its previous one. * * 'step' is the step width; 'extremesMargin' specifies how far from * the extremes (min, max) the step width should be 1 instead. **/ void fillQuantileTable( QTableWidget * table, int order, const QString & namePrefix = "", const QRealList & sums = QRealList(), int step = 1, int extremesMargin = 1 ); /** * Add an item to a table. **/ QTableWidgetItem * addItem( QTableWidget * table, int row, int col, const QString & text ); /** * Set the font to bold for all items in a table row. **/ void setRowBold( QTableWidget * table, int row ); /** * Set the forground (the text color) for all items in a table row. **/ void setRowForeground( QTableWidget * table, int row, const QBrush & brush ); /** * Set the background for all items in a table row. **/ void setRowBackground( QTableWidget * table, int row, const QBrush & brush ); /** * Set the text alignment for all items in a table column. **/ void setColAlignment( QTableWidget * table, int col, int alignment ); /** * Fill the histogram with content. **/ void fillHistogram(); /** * Fill the buckets table with content. **/ void fillBucketsTable(); /** * Provide data for the histogram. **/ void fillBuckets(); // // Data members // Ui::FileSizeStatsWindow * _ui; FileInfo * _subtree; QString _suffix; FileSizeStats * _stats; BucketsTableModel * _bucketsTableModel; static QPointer _sharedInstance; }; } // namespace QDirStat #endif // FileSizeStatsWindow_h qdirstat-1.4/src/FileTypeStats.cpp000066400000000000000000000153431311502036700172500ustar00rootroot00000000000000/* * File name: FileTypeStats.cpp * Summary: Statistics classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "FileTypeStats.h" #include "DirTree.h" #include "FileInfoIterator.h" #include "MimeCategorizer.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; FileTypeStats::FileTypeStats( QObject * parent ): QObject( parent ), _totalSize( 0LL ) { _mimeCategorizer = new MimeCategorizer( this ); CHECK_NEW( _mimeCategorizer ); _otherCategory = new MimeCategory( tr( "Other" ) ); CHECK_NEW( _otherCategory ); } FileTypeStats::~FileTypeStats() { clear(); delete _otherCategory; } void FileTypeStats::clear() { _suffixSum.clear(); _suffixCount.clear(); _categorySum.clear(); _categoryCount.clear(); _totalSize = 0LL; } int FileTypeStats::suffixCount( const QString & suffix ) const { return _suffixCount.value( suffix, 0 ); } FileSize FileTypeStats::suffixSum( const QString & suffix ) const { return _suffixSum.value( suffix, 0LL ); } int FileTypeStats::categoryCount( MimeCategory * category ) const { return _categoryCount.value( category, 0 ); } FileSize FileTypeStats::categorySum( MimeCategory * category ) const { return _categorySum.value( category, 0LL ); } MimeCategory * FileTypeStats::category( const QString & suffix ) const { return _mimeCategorizer->category( "x." + suffix ); } double FileTypeStats::percentage( FileSize size ) const { FileSize total = totalSize(); if ( total == 0LL ) return 0.0; else return (100.0 * size) / (double) total; } void FileTypeStats::calc( FileInfo * subtree ) { clear(); if ( subtree && subtree->checkMagicNumber() ) { collect( subtree ); _totalSize = subtree->totalSize(); removeCruft(); removeEmpty(); sanityCheck(); } emit calcFinished(); } void FileTypeStats::collect( FileInfo * dir ) { if ( ! dir ) return; FileInfoIterator it( dir ); while ( *it ) { FileInfo * item = *it; if ( item->hasChildren() ) { collect( item ); } else if ( item->isFile() ) { QString suffix; // First attempt: Try the MIME categorizer. // // If it knows the file's suffix, it can much easier find the // correct one in case there are multiple to choose from, for // example ".tar.bz2", not ".bz2" for a bzipped tarball. But on // Linux systems, having multiple dots in filenames is very common, // e.g. in .deb or .rpm packages, so the longest possible suffix is // not always the useful one (because it might contain version // numbers and all kinds of irrelevant information). // // The suffixes the MIME categorizer knows are carefully // hand-crafted, so if it knows anything about a suffix, it's the // best choice. MimeCategory * category = _mimeCategorizer->category( item->name(), &suffix ); if ( ! category ) category = _otherCategory; _categorySum[ category ] += item->size(); ++_categoryCount[ category ]; if ( suffix.isEmpty() ) { if ( item->name().contains( '.' ) && ! item->name().startsWith( '.' ) ) { // Fall back to the last (i.e. the shortest) suffix if the // MIME categorizer didn't know it: Use section -1 (the // last one, ignoring any trailing '.' separator). // // The downside is that this would not find a ".tar.bz", // but just the ".bz" for a compressed tarball. But it's // much better than getting a ".eab7d88df-git.deb" rather // than a ".deb". suffix = item->name().section( '.', -1 ); } } suffix = suffix.toLower(); if ( suffix.isEmpty() ) suffix = NO_SUFFIX; _suffixSum[ suffix ] += item->size(); ++_suffixCount[ suffix ]; } // Disregard symlinks, block devices and other special files ++it; } } void FileTypeStats::removeCruft() { // Make sure those two already exist to avoid confusing the iterator // (QMap::operator[] auto-inserts with default ctor if not already there) _suffixSum [ NO_SUFFIX ] += 0LL; _suffixCount[ NO_SUFFIX ] += 0; FileSize totalMergedSum = 0LL; int totalMergedCount = 0; QStringList cruft; QMap::iterator it = _suffixCount.begin(); while ( it != _suffixCount.end() ) { QString suffix = it.key(); bool merge = false; if ( isCruft( suffix ) ) { cruft << "*." + suffix; merge = true; } if ( merge ) { _suffixSum [ NO_SUFFIX ] += _suffixSum [ suffix ]; _suffixCount[ NO_SUFFIX ] += _suffixCount[ suffix ]; totalMergedSum += _suffixSum [ suffix ]; totalMergedCount += _suffixCount[ suffix ]; it = _suffixCount.erase( it ); _suffixSum.remove( suffix ); } else { ++it; } } #if 1 logDebug() << "Merged " << cruft.size() << " suffixes to : " << cruft.join( ", " ) << endl; #endif logDebug() << "Merged: " << totalMergedCount << " files " << "(" << formatSize( totalMergedSum ) << ")" << endl; } void FileTypeStats::removeEmpty() { QMap::iterator it = _suffixCount.begin(); while ( it != _suffixCount.end() ) { QString suffix = it.key(); int count = it.value(); bool remove = count == 0; if ( remove ) { logDebug() << "Removing empty suffix *." << suffix << endl; it = _suffixCount.erase( it ); _suffixSum.remove( suffix ); } else { ++it; } } } bool FileTypeStats::isCruft( const QString & suffix ) const { if ( suffix == NO_SUFFIX ) return false; // Whatever the MIME categorizer knows is good enough for us: // It is a preconfigured suffix for a well-known file type. if ( _mimeCategorizer->category( "x." + suffix ) ) return false; int count = _suffixCount[ suffix ]; int len = suffix.size(); int letters = suffix.count( QRegExp( "[a-zA-Z]" ) ); float lettersPercent = len > 0 ? (100.0 * letters) / len : 0.0; if ( letters == 0 ) return true; if ( suffix.contains( ' ' ) ) return true; // The most common case: 3-letter suffix if ( len == 3 && letters == 3 ) return false; if ( len > 6 && count < len ) return true; // Forget long suffixes with mostly non-letters if ( lettersPercent < 70.0 && count < len ) return true; return false; } void FileTypeStats::sanityCheck() { FileSize categoryTotal = 0LL; foreach ( FileSize sum, _categorySum ) categoryTotal += sum; FileSize missing = totalSize() - categoryTotal; logDebug() << "Unaccounted in categories: " << formatSize( missing ) << " of " << formatSize( totalSize() ) << " (" << QString::number( percentage( missing ), 'f', 2 ) << "%)" << endl; } qdirstat-1.4/src/FileTypeStats.h000066400000000000000000000110501311502036700167040ustar00rootroot00000000000000/* * File name: FileTypeStats.h * Summary: Statistics classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileTypeStats_h #define FileTypeStats_h #include #include #include "ui_file-type-stats-window.h" #include "DirInfo.h" #define NO_SUFFIX "//" // A slash is illegal in Linux/Unix filenames namespace QDirStat { class DirTree; class MimeCategorizer; class MimeCategory; typedef QMap StringFileSizeMap; typedef QMap StringIntMap; typedef QMap CategoryFileSizeMap; typedef QMap CategoryIntMap; typedef StringFileSizeMap::const_iterator StringFileSizeMapIterator; typedef CategoryFileSizeMap::const_iterator CategoryFileSizeMapIterator; /** * Class to calculate file type statistics for a subtree, such as how much * disk space is used for each kind of filename extension (*.jpg, *.mp4 * etc.). **/ class FileTypeStats: public QObject { Q_OBJECT public: /** * Constructor. **/ FileTypeStats( QObject * parent = 0 ); /** * Destructor. **/ virtual ~FileTypeStats(); public slots: /** * Calculate the statistics from a new subtree. **/ void calc( FileInfo * subtree ); /** * Clear all data. **/ void clear(); signals: /** * Emitted when the calculation is finished. This is useful when the * calc() slot is connected to some outside signal to recalculate the * contents. calc() itself is synchronous, i.e. it only returns when * the calculation is finished. **/ void calcFinished() const; public: /** * Return the number of files in the tree with the specified suffix. **/ int suffixCount( const QString & suffix ) const; /** * Return the total file size of files in the tree with the specified * suffix. **/ FileSize suffixSum( const QString & suffix ) const; /** * Return the number of files in the tree with the specified category. **/ int categoryCount( MimeCategory * category ) const; /** * Return the total file size of files in the tree with the specified * category. **/ FileSize categorySum( MimeCategory * category ) const; /** * Return the category for the specified suffix or 0 if there is none. **/ MimeCategory * category( const QString & suffix ) const; /** * Return the special category for "other", i.e. unclassified files. **/ MimeCategory * otherCategory() const { return _otherCategory; } /** * Return the total size of the tree. **/ FileSize totalSize() const { return _totalSize; } /** * Return the percentage of 'size' of the tree total size. **/ double percentage( FileSize size ) const; // // Iterators // StringFileSizeMapIterator suffixSumBegin() const { return _suffixSum.constBegin(); } StringFileSizeMapIterator suffixSumEnd() const { return _suffixSum.constEnd(); } CategoryFileSizeMapIterator categorySumBegin() const { return _categorySum.constBegin(); } CategoryFileSizeMapIterator categorySumEnd() const { return _categorySum.constEnd(); } protected: /** * Collect information from the associated widget tree: * * Recursively go through the tree and collect sizes for each file type * (filename extension). **/ void collect( FileInfo * dir ); /** * Remove useless content from the maps. On a Linux system, there tend * to be a lot of files that have a '.' in the name, but it's not a * meaningful suffix but a general-purpose separator for dates, SHAs, * version numbers or whatever. All that stuff accumulates in the maps, * and it's typically just a single file with that non-suffix. This * function tries a best effort to get rid of that stuff. **/ void removeCruft(); /** * Remove empty suffix entries from the internal maps. **/ void removeEmpty(); /** * Check if a suffix is cruft, i.e. a nonstandard suffix that is not * useful for display. * * Notice that this is a highly heuristical algorithm that might give * false positives. **/ bool isCruft( const QString & suffix ) const; /** * Check if the sums add up and how much is unaccounted for. **/ void sanityCheck(); // // Data members // MimeCategory * _otherCategory; MimeCategorizer * _mimeCategorizer; StringFileSizeMap _suffixSum; StringIntMap _suffixCount; CategoryFileSizeMap _categorySum; CategoryIntMap _categoryCount; FileSize _totalSize; }; } #endif // FileTypeStats_h qdirstat-1.4/src/FileTypeStatsWindow.cpp000066400000000000000000000255461311502036700204460ustar00rootroot00000000000000/* * File name: FileTypeStatsWindow.cpp * Summary: QDirStat file type statistics window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "FileTypeStatsWindow.h" #include "FileTypeStats.h" #include "FileSizeStatsWindow.h" #include "LocateFilesWindow.h" #include "DirTree.h" #include "MimeCategory.h" #include "SettingsHelpers.h" #include "HeaderTweaker.h" #include "Logger.h" #include "Exception.h" // Number of suffixes in the "other" category #define TOP_X 20 using namespace QDirStat; QPointer FileTypeStatsWindow::_locateFilesWindow = 0; FileTypeStatsWindow::FileTypeStatsWindow( SelectionModel * selectionModel, QWidget * parent ): QDialog( parent ), _ui( new Ui::FileTypeStatsWindow ), _selectionModel( selectionModel ) { // logDebug() << "init" << endl; CHECK_NEW( _ui ); _ui->setupUi( this ); initWidgets(); readWindowSettings( this, "FileTypeStatsWindow" ); connect( _ui->treeWidget, SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ), this, SLOT ( enableActions ( QTreeWidgetItem * ) ) ); connect( _ui->treeWidget, SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int ) ), this, SLOT ( locateCurrentFileType() ) ); connect( _ui->refreshButton, SIGNAL( clicked() ), this, SLOT ( refresh() ) ); connect( _ui->actionLocate, SIGNAL( triggered() ), this, SLOT ( locateCurrentFileType() ) ); connect( _ui->actionSizeStats, SIGNAL( triggered() ), this, SLOT ( sizeStatsForCurrentFileType() ) ); _stats = new FileTypeStats( this ); CHECK_NEW( _stats ); } FileTypeStatsWindow::~FileTypeStatsWindow() { // logDebug() << "destroying" << endl; writeWindowSettings( this, "FileTypeStatsWindow" ); } void FileTypeStatsWindow::clear() { _stats->clear(); _ui->treeWidget->clear(); enableActions(0); } void FileTypeStatsWindow::initWidgets() { QFont font = _ui->heading->font(); font.setBold( true ); _ui->heading->setFont( font ); _ui->treeWidget->setColumnCount( FT_ColumnCount ); _ui->treeWidget->setHeaderLabels( QStringList() << tr( "Name" ) << tr( "Number" ) << tr( "Total Size" ) << tr( "Percentage" ) ); _ui->treeWidget->header()->setStretchLastSection( false ); HeaderTweaker::resizeToContents( _ui->treeWidget->header() ); // Create the menu for the menu button QMenu * menu = new QMenu( this ); CHECK_NEW( menu ); menu->addAction( _ui->actionLocate ); menu->addAction( _ui->actionSizeStats ); _ui->menuButton->setMenu( menu ); } void FileTypeStatsWindow::refresh() { populate( _subtree() ); } void FileTypeStatsWindow::populate( FileInfo * newSubtree ) { clear(); _subtree = newSubtree; _stats->calc( newSubtree ? newSubtree : _subtree() ); _ui->heading->setText( tr( "File Type Statistics for %1" ) .arg( _subtree.url() ) ); _ui->treeWidget->setSortingEnabled( false ); // // Create toplevel items for the categories // QMap categoryItem; CategoryFileTypeItem * otherCategoryItem = 0; for ( CategoryFileSizeMapIterator it = _stats->categorySumBegin(); it != _stats->categorySumEnd(); ++it ) { MimeCategory * category = it.key(); if ( category ) { FileSize sum = it.value(); int count = _stats->categoryCount( category ); double percentage = _stats->percentage( sum ); CategoryFileTypeItem * item = new CategoryFileTypeItem( category, count, sum, percentage ); CHECK_NEW( item ); _ui->treeWidget->addTopLevelItem( item ); item->setBold(); categoryItem[ category ] = item; if ( category == _stats->otherCategory() ) otherCategoryItem = item; } } // Prepare to collect items for a category "other" QList otherItems; int otherCount = 0; FileSize otherSum = 0LL; // // Create items for each individual suffix (below a category) // for ( StringFileSizeMapIterator it = _stats->suffixSumBegin(); it != _stats->suffixSumEnd(); ++it ) { QString suffix = it.key(); FileSize sum = it.value(); int count = _stats->suffixCount( suffix ); double percentage = _stats->percentage( sum ); MimeCategory * parentCategory = _stats->category( suffix ); SuffixFileTypeItem * item = new SuffixFileTypeItem( suffix, count, sum, percentage ); CHECK_NEW( item ); if ( parentCategory ) { QTreeWidgetItem * parentItem = categoryItem.value( parentCategory, 0 ); if ( parentItem ) parentItem->addChild( item ); else { logError() << "ERROR: No parent category item for " << suffix << endl; otherItems << item; otherCount += count; otherSum += sum; } } else // No category for this suffix { otherItems << item; otherCount += count; otherSum += sum; } } // Put remaining "other" items below a separate category if ( ! otherItems.isEmpty() ) { FileTypeItemCompare cmp; std::sort( otherItems.begin(), otherItems.end(), cmp ); double percentage = _stats->percentage( otherSum ); QString name = otherItems.size() > TOP_X ? tr( "Other (Top %1)" ).arg( TOP_X ) : tr( "Other" ); if ( ! otherCategoryItem ) { otherCategoryItem = new CategoryFileTypeItem( _stats->otherCategory(), otherCount, otherSum, percentage ); CHECK_NEW( otherCategoryItem ); } otherCategoryItem->setText( 0, name ); otherCategoryItem->setBold(); _ui->treeWidget->addTopLevelItem( otherCategoryItem ); int top_x = qMin( TOP_X, otherItems.size() ); for ( int i=0; i < top_x; ++i ) { FileTypeItem * item = otherItems.takeFirst(); otherCategoryItem->addChild( item ); } if ( ! otherItems.empty() ) { #if 1 QStringList suffixes; foreach ( FileTypeItem * item, otherItems ) suffixes << item->text(0); logDebug() << "Discarding " << otherItems.size() << " suffixes below : " << suffixes.join( ", " ) << endl; #endif qDeleteAll( otherItems ); } } _ui->treeWidget->setSortingEnabled( true ); _ui->treeWidget->sortByColumn( FT_TotalSizeCol, Qt::DescendingOrder ); } void FileTypeStatsWindow::locateCurrentFileType() { QString suffix = currentSuffix(); if ( suffix.isEmpty() ) { if ( _locateFilesWindow ) _locateFilesWindow->hide(); return; } // logDebug() << "Locating " << current->suffix() << endl; if ( ! _locateFilesWindow ) { _locateFilesWindow = new LocateFilesWindow( _selectionModel, qobject_cast( parent() ) ); CHECK_NEW( _locateFilesWindow ); _locateFilesWindow->show(); // Not using 'this' as parent so the user can close the file types // stats window, but keep the locate files window open; if 'this' were // used, the destructor of the file type stats window would // automatically delete the locate files window, too since it would be // part of its children hierarchy. // // On the downside, that means we have to actively raise() it because // it might get hidden behind the stats window. } else // Reusing existing window { _locateFilesWindow->show(); _locateFilesWindow->raise(); } _locateFilesWindow->populate( suffix, _subtree() ); } void FileTypeStatsWindow::sizeStatsForCurrentFileType() { QString suffix = currentSuffix().toLower(); FileInfo * dir = _subtree(); if ( suffix.isEmpty() || ! dir ) return; logDebug() << "Size stats for " << suffix << endl; FileSizeStatsWindow::populateSharedInstance( dir, suffix ); } QString FileTypeStatsWindow::currentSuffix() const { SuffixFileTypeItem * current = dynamic_cast( _ui->treeWidget->currentItem() ); if ( ! current ) return QString(); if ( current->suffix() == NO_SUFFIX ) { logWarning() << "NO_SUFFIX selected" << endl; return QString(); } return current->suffix(); } void FileTypeStatsWindow::enableActions( QTreeWidgetItem * currentItem ) { bool enabled = false; if ( currentItem ) { SuffixFileTypeItem * suffixItem = dynamic_cast( currentItem ); enabled = suffixItem && suffixItem->suffix() != NO_SUFFIX; } _ui->actionLocate->setEnabled( enabled ); _ui->actionSizeStats->setEnabled( enabled ); _ui->menuButton->setEnabled( enabled ); } void FileTypeStatsWindow::reject() { deleteLater(); } CategoryFileTypeItem::CategoryFileTypeItem( MimeCategory * category, int count, FileSize totalSize, float percentage ): FileTypeItem( category->name(), count, totalSize, percentage ), _category( category ) { } SuffixFileTypeItem::SuffixFileTypeItem( const QString & suffix, int count, FileSize totalSize, float percentage ): FileTypeItem( "*." + suffix, count, totalSize, percentage ), _suffix( suffix ) { if ( suffix == NO_SUFFIX ) setText( FT_NameCol, QObject::tr( "" ) ); else _suffix = "*." + suffix; } FileTypeItem::FileTypeItem( const QString & name, int count, FileSize totalSize, float percentage ): QTreeWidgetItem( QTreeWidgetItem::UserType ), _name( name ), _count( count ), _totalSize( totalSize ), _percentage( percentage ) { QString percentStr; percentStr.sprintf( "%02.2f%%", percentage ); setText( FT_NameCol, name ); setText( FT_CountCol, QString( "%1" ).arg( count ) ); setText( FT_TotalSizeCol, formatSize( totalSize ) ); setText( FT_PercentageCol, percentStr ); setTextAlignment( FT_NameCol, Qt::AlignLeft ); setTextAlignment( FT_CountCol, Qt::AlignRight ); setTextAlignment( FT_TotalSizeCol, Qt::AlignRight ); setTextAlignment( FT_PercentageCol, Qt::AlignRight ); } bool FileTypeItem::operator<(const QTreeWidgetItem & rawOther) const { // Since this is a reference, the dynamic_cast will throw a std::bad_cast // exception if it fails. Not catching this here since this is a genuine // error which should not be silently ignored. const FileTypeItem & other = dynamic_cast( rawOther ); int col = treeWidget() ? treeWidget()->sortColumn() : FT_TotalSizeCol; switch ( col ) { case FT_NameCol: return name() < other.name(); case FT_CountCol: return count() < other.count(); case FT_TotalSizeCol: return totalSize() < other.totalSize(); case FT_PercentageCol: return percentage() < other.percentage(); default: return QTreeWidgetItem::operator<( rawOther ); } } void FileTypeItem::setBold() { QFont boldFont = font( 0 ); boldFont.setBold( true ); for ( int col=0; col < FT_ColumnCount; ++col ) setFont( col, boldFont ); } qdirstat-1.4/src/FileTypeStatsWindow.h000066400000000000000000000124411311502036700201010ustar00rootroot00000000000000/* * File name: FileTypeStatsWindow.h * Summary: QDirStat file type statistics window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef FileTypeStatsWindow_h #define FileTypeStatsWindow_h #include #include #include #include #include "ui_file-type-stats-window.h" #include "Subtree.h" namespace QDirStat { class DirTree; class FileInfo; class FileTypeStats; class MimeCategory; class SelectionModel; class LocateFilesWindow; /** * Modeless dialog to display file type statistics, such as how much disk * space is used for each kind of filename extension (*.jpg, *.mp4 etc.). **/ class FileTypeStatsWindow: public QDialog { Q_OBJECT public: /** * Constructor. * * This creates a file type statistics window, but it does not populate * it with content yet. * * Notice that this widget will destroy itself upon window close. * * It is advised to use a QPointer for storing a pointer to an instance * of this class. The QPointer will keep track of this window * auto-deleting itself when closed. **/ FileTypeStatsWindow( SelectionModel * selectionModel, QWidget * parent ); /** * Destructor. **/ virtual ~FileTypeStatsWindow(); public: /** * Obtain the subtree from the last used URL. **/ const Subtree & subtree() const { return _subtree; } /** * Populate the widgets for a subtree. **/ void populate( FileInfo * subtree ); public slots: /** * Refresh (reload) all data. **/ void refresh(); /** * Open a "Locate File Type" window for the currently selected file * type or re-populate it if it is still open. **/ void locateCurrentFileType(); /** * Open a "File Size Statistics" window for the currently selected file * type or re-popuolate it if it is still open. **/ void sizeStatsForCurrentFileType(); /** * Reject the dialog contents, i.e. the user clicked the "Cancel" * or WM_CLOSE button. * * Reimplemented from QDialog. **/ virtual void reject() Q_DECL_OVERRIDE; protected slots: /** * Enable or disable the actions depending on the current item. **/ void enableActions( QTreeWidgetItem * currentItem ); protected: /** * Clear all data and widget contents. **/ void clear(); /** * One-time initialization of the widgets in this window. **/ void initWidgets(); /** * Return the suffix of the currently selected file type or an empty * string if no suffix is selected. **/ QString currentSuffix() const; // // Data members // Ui::FileTypeStatsWindow * _ui; Subtree _subtree; SelectionModel * _selectionModel; FileTypeStats * _stats; static QPointer _locateFilesWindow; }; /** * Column numbers for the file type tree widget **/ enum FileTypeColumns { FT_NameCol = 0, FT_CountCol, FT_TotalSizeCol, FT_PercentageCol, FT_ColumnCount }; /** * Item class for the file type tree widget, representing either a MIME * category or a suffix. **/ class FileTypeItem: public QTreeWidgetItem { public: /** * Constructor. After creating, this item has to be inserted into the * tree at the appropriate place: Toplevel for categories, below a * category for suffixes. **/ FileTypeItem( const QString & name, int count, FileSize totalSize, float percentage ); // // Getters // QString name() const { return _name; } int count() const { return _count; } FileSize totalSize() const { return _totalSize; } float percentage() const { return _percentage; } /** * Set the font to bold face for all columns. **/ void setBold(); /** * Less-than operator for sorting. **/ virtual bool operator<(const QTreeWidgetItem & other) const Q_DECL_OVERRIDE; protected: QString _name; int _count; FileSize _totalSize; float _percentage; }; /** * Specialized item class for MIME categories. **/ class CategoryFileTypeItem: public FileTypeItem { public: /** * Constructor. **/ CategoryFileTypeItem( MimeCategory * category, int count, FileSize totalSize, float percentage ); /** * Return the MIME category of this item. **/ MimeCategory * category() const { return _category; } protected: MimeCategory * _category; }; /** * Specialized item class for suffix file types. **/ class SuffixFileTypeItem: public FileTypeItem { public: /** * Constructor. **/ SuffixFileTypeItem( const QString & suffix, int count, FileSize totalSize, float percentage ); /** * Return this file type's suffix. **/ QString suffix() const { return _suffix; } protected: QString _suffix; }; /** * Functor for std::sort to compare FileTypeItems by size descending. **/ struct FileTypeItemCompare { bool operator() ( FileTypeItem * a, FileTypeItem * b ) { return a->totalSize() > b->totalSize(); } }; } // namespace QDirStat #endif // FileTypeStatsWindow_h qdirstat-1.4/src/HeaderTweaker.cpp000066400000000000000000000267421311502036700172300ustar00rootroot00000000000000/* * File name: HeaderTweaker.cpp * Summary: Helper class for DirTreeView * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "HeaderTweaker.h" #include "DirTreeView.h" #include "Settings.h" #include "Qt4Compat.h" #include "Logger.h" #include "Exception.h" #include "SignalBlocker.h" using namespace QDirStat; HeaderTweaker::HeaderTweaker( QHeaderView * header, DirTreeView * parent ): QObject( parent ), _treeView( parent ), _header( header ), _currentSection( -1 ) { CHECK_PTR( _header ); _header->setSortIndicator( NameCol, Qt::AscendingOrder ); _header->setStretchLastSection( false ); _header->setContextMenuPolicy( Qt::CustomContextMenu ); setAllColumnsAutoSize( true ); createActions(); connect( _header, SIGNAL( sectionCountChanged( int, int ) ), this, SLOT ( initHeader() ) ); connect( _header, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT ( contextMenu ( const QPoint & ) ) ); } HeaderTweaker::~HeaderTweaker() { writeSettings(); } void HeaderTweaker::initHeader() { // Initialize stuff when the header actually has sections: It's constructed // empty. It is only populated when the tree view model requests header // data from the data model. // logDebug() << "Header count: " << _header->count() << endl; readSettings(); } #define CONNECT_ACTION(ACTION, RECEIVER, RCVR_SLOT) \ connect( (ACTION), SIGNAL( triggered() ), (RECEIVER), SLOT( RCVR_SLOT ) ) void HeaderTweaker::createActions() { _actionHideCurrentCol = new QAction( tr( "&Hide" ), this ); CONNECT_ACTION( _actionHideCurrentCol, this, hideCurrentCol() ); _actionShowAllHiddenColumns = new QAction( tr( "Show &All Hidden Columns" ), this ); CONNECT_ACTION( _actionShowAllHiddenColumns, this, showAllHiddenColumns() ); _actionAutoSizeCurrentCol = new QAction( tr( "A&uto Size" ), this ); _actionAutoSizeCurrentCol->setCheckable( true ); connect( _actionAutoSizeCurrentCol, SIGNAL( toggled ( bool ) ), this, SLOT ( autoSizeCurrentCol() ) ); _actionAllColumnsAutoSize = new QAction( tr( "&Auto Size" ), this ); CONNECT_ACTION( _actionAllColumnsAutoSize, this, setAllColumnsAutoSize() ); _actionAllColumnsInteractiveSize = new QAction( tr( "&Interactive Size" ), this ); CONNECT_ACTION( _actionAllColumnsInteractiveSize, this, setAllColumnsInteractiveSize() ); _actionResetToDefaults = new QAction( tr( "&Reset to Defaults" ), this ); CONNECT_ACTION( _actionResetToDefaults, this, resetToDefaults() ); } void HeaderTweaker::updateActions( int section ) { _actionHideCurrentCol->setEnabled( section != 0 ); { SignalBlocker sigBlocker( _actionAutoSizeCurrentCol ); _actionAutoSizeCurrentCol->setChecked( autoSizeCol( section ) ); } } void HeaderTweaker::contextMenu( const QPoint & pos ) { _currentSection = _header->logicalIndexAt( pos ); QString colName = this->colName( _currentSection ); updateActions( _currentSection ); QMenu menu; menu.addAction( tr( "Column \"%1\"" ).arg( colName ) ); menu.addSeparator(); menu.addAction( _actionAutoSizeCurrentCol ); menu.addAction( _actionHideCurrentCol ); menu.addSeparator(); menu.addMenu( createHiddenColMenu( &menu ) ); QMenu allColMenu( tr( "&All Columns" ) ); menu.addMenu( &allColMenu ); allColMenu.addAction( _actionAllColumnsAutoSize ); allColMenu.addAction( _actionAllColumnsInteractiveSize ); allColMenu.addAction( _actionResetToDefaults ); menu.exec( _header->mapToGlobal( pos ) ); } QMenu * HeaderTweaker::createHiddenColMenu( QWidget * parent ) { int actionCount = 0; QMenu * hiddenColMenu = new QMenu( tr( "Hi&dden Columns" ), parent ); for ( int section = 0; section < _header->count(); ++section ) { if ( _header->isSectionHidden( section ) ) { ++actionCount; QString text = tr( "Show Column \"%1\"" ).arg( this->colName( section ) ); QAction * showAction = new QAction( text, hiddenColMenu ); CHECK_NEW( showAction ); showAction->setData( section ); hiddenColMenu->addAction( showAction ); connect( showAction, SIGNAL( triggered() ), this, SLOT ( showHiddenCol() ) ); } } if ( actionCount == 0 ) hiddenColMenu->setEnabled( false ); else if ( actionCount > 1 ) { hiddenColMenu->addSeparator(); hiddenColMenu->addAction( _actionShowAllHiddenColumns ); } return hiddenColMenu; } QString HeaderTweaker::colName( int section ) const { DataColumn col = DataColumns::instance()->reverseMappedCol( static_cast( section ) ); QString name = _treeView->model()->headerData( col, Qt::Horizontal, Qt::DisplayRole ).toString(); if ( col == UndefinedCol ) logError() << "No column at section " << section << endl; return name; } bool HeaderTweaker::autoSizeCol( int section ) const { return resizeMode( section ) == QHeaderView::ResizeToContents; } void HeaderTweaker::hideCurrentCol() { if ( _currentSection >= 0 ) { logDebug() << "Hiding column \"" << colName( _currentSection ) << "\"" << endl; _header->setSectionHidden( _currentSection, true ); } _currentSection = -1; } void HeaderTweaker::autoSizeCurrentCol() { if ( _currentSection >= 0 ) { setResizeMode( _currentSection, _actionAutoSizeCurrentCol->isChecked() ? QHeaderView::ResizeToContents : QHeaderView::Interactive ); } else logWarning() << "No current section" << endl; _currentSection = -1; } void HeaderTweaker::setAllColumnsAutoSize( bool autoSize ) { QHeaderView::ResizeMode resizeMode = autoSize ? QHeaderView::ResizeToContents : QHeaderView::Interactive; for ( int section = 0; section < _header->count(); ++section ) { setResizeMode( section, resizeMode ); } } void HeaderTweaker::setAllColumnsInteractiveSize() { setAllColumnsAutoSize( false ); } void HeaderTweaker::showHiddenCol() { QAction * action = qobject_cast( sender() ); if ( ! action ) { logError() << "Wrong sender type: " << sender()->metaObject()->className() << endl; return; } if ( action->data().isValid() ) { int section = action->data().toInt(); if ( section >= 0 && section < _header->count() ) { logDebug() << "Showing column \"" << colName( section ) << "\"" << endl; _header->setSectionHidden( section, false ); } else logError() << "Section index out of range: " << section << endl; } else { logError() << "No data() set for this QAction" << endl; } } void HeaderTweaker::showAllHiddenColumns() { for ( int section = 0; section < _header->count(); ++section ) { if ( _header->isSectionHidden( section ) ) { logDebug() << "Showing column \"" << colName( section ) << "\"" << endl; _header->setSectionHidden( section, false ); } } } void HeaderTweaker::resetToDefaults() { showAllHiddenColumns(); setAllColumnsAutoSize( true ); clearSettings(); setColumnOrder( DataColumns::instance()->defaultColumns() ); // Restore column order: Make sure logical and visual index are the same. for ( int section = 0; section < _header->count(); ++section ) { _header->moveSection( _header->visualIndex( section ), section ); } } void HeaderTweaker::setColumnOrder( const DataColumnList & colOrderList) { int visualIndex = 0; foreach ( DataColumn col, colOrderList ) { if ( visualIndex < _header->count() ) { // logDebug() << "Moving " << col << " to position " << visualIndex << endl; _header->moveSection( _header->visualIndex( col ), visualIndex++ ); } else logWarning() << "More columns than header sections" << endl; } } void HeaderTweaker::clearSettings() { Settings settings; settings.beginGroup( "TreeViewColumns" ); (void) remove( "" ); // Remove all keys in this settings group settings.endGroup(); } void HeaderTweaker::readSettings() { Settings settings; settings.beginGroup( "TreeViewColumns" ); QStringList strList = settings.value( "ColumnOrder" ).toStringList(); DataColumnList colOrderList = DataColumns::fromStringList( strList ); if ( colOrderList.isEmpty() ) { // logDebug() << "Falling back to default column order" << endl; colOrderList = DataColumns::instance()->defaultColumns(); } else { colOrderList = DataColumns::fixup( colOrderList ); addMissingColumns( colOrderList ); } setColumnOrder( colOrderList); strList = settings.value( "VisibleColumns" ).toStringList(); DataColumnList visibleColList = DataColumns::fromStringList( strList ); if ( visibleColList.isEmpty() ) { // logDebug() << "Falling back to all columns visible" << endl; visibleColList = colOrderList; } else visibleColList = DataColumns::fixup( visibleColList ); // // Set all columns to hidden that are not in visibleColList // for ( int section = 0; section < _header->count(); ++section ) { DataColumn col = static_cast( section ); if ( ! visibleColList.contains( col ) ) { logDebug() << "Hiding " << col << endl; _header->setSectionHidden( section, true ); } } // // Set all column widths that are specified // for ( int section = 0; section < _header->count(); ++section ) { DataColumn col = static_cast( section ); QString colName = DataColumns::toString( col ); QString widthKey = QString( "Width_%1" ).arg( colName ); int width = settings.value( widthKey, -1 ).toInt(); if ( width > 0 ) { setResizeMode( section, QHeaderView::Interactive ); _header->resizeSection( section, width ); } else { setResizeMode( section, QHeaderView::ResizeToContents ); } } settings.endGroup(); } void HeaderTweaker::writeSettings() { Settings settings; settings.beginGroup( "TreeViewColumns" ); QStringList colOrderList; QStringList visibleColList; for ( int visualIndex = 0; visualIndex < _header->count(); ++visualIndex ) { // // Collect column order and visibility for all columns // int logicalIndex = _header->logicalIndex( visualIndex ); DataColumn col = static_cast( logicalIndex ); QString colName = DataColumns::toString( col ); colOrderList << colName; if ( ! _header->isSectionHidden( logicalIndex ) ) visibleColList << colName; // // Write column width for all columns that don't have auto size // QString widthKey = QString( "Width_%1" ).arg( colName ); if ( autoSizeCol( logicalIndex ) ) settings.setValue( widthKey, "auto" ); else settings.setValue( widthKey, _header->sectionSize( logicalIndex ) ); } settings.setValue( "ColumnOrder", colOrderList ); settings.setValue( "VisibleColumns", visibleColList ); settings.endGroup(); } void HeaderTweaker::addMissingColumns( DataColumnList & colList ) { foreach ( const DataColumn col, DataColumns::instance()->defaultColumns() ) { if ( ! colList.contains( col ) ) colList << col; } } QHeaderView::ResizeMode HeaderTweaker::resizeMode( int section ) const { return _header->sectionResizeMode( section ); } void HeaderTweaker::setResizeMode( int section, QHeaderView::ResizeMode resizeMode ) { _header->setSectionResizeMode( section, resizeMode ); } void HeaderTweaker::resizeToContents( QHeaderView * header ) { for ( int col = 0; col < header->count(); ++col ) header->setSectionResizeMode( col, QHeaderView::ResizeToContents ); } qdirstat-1.4/src/HeaderTweaker.h000066400000000000000000000074151311502036700166710ustar00rootroot00000000000000/* * File name: HeaderTweaker.h * Summary: Helper class for DirTreeView * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef HeaderTweaker_h #define HeaderTweaker_h #include #include "DataColumns.h" class QHeaderView; class QAction; class QMenu; namespace QDirStat { class DirTreeView; /** * Decorator class for a DirTreeView's QHeaderView that takes care about * the header's context menu and the corresponding actions and saving and * restoring state. **/ class HeaderTweaker: public QObject { Q_OBJECT public: /** * Constructor. **/ HeaderTweaker( QHeaderView * header, DirTreeView * parent ); /** * Destructor. **/ virtual ~HeaderTweaker(); /** * Order the columns according to 'colOrderList'. **/ void setColumnOrder( const DataColumnList & colOrderList); /** * Resize a header view to contents. **/ static void resizeToContents( QHeaderView * header ); public slots: /** * Set auto size mode for all columns on or off. **/ void setAllColumnsAutoSize( bool autoSize = true ); /** * Set interactive size mode (i.e. auto size mode off) for all columns. **/ void setAllColumnsInteractiveSize(); /** * Make all hidden columns visible again. **/ void showAllHiddenColumns(); /** * Reset all columns to defaults: Column order, visibility, auto size. **/ void resetToDefaults(); /** * Read parameters from the settings file. **/ void readSettings(); /** * Write parameters to the settings file. **/ void writeSettings(); protected slots: /** * Initialize the header view. This makes sense only when it has * columns, i.e. when the model is set, and the parent QTreeView * requested header data. It makes most sense to connect this slot with * the header's sectionCountChanged() signal. **/ void initHeader(); /** * Post a context menu for the header at 'pos'. **/ void contextMenu( const QPoint & pos ); /** * Hide the current column. **/ void hideCurrentCol(); /** * Show the hidden column from sender()->data(). **/ void showHiddenCol(); /** * Toggle auto size of the current column. **/ void autoSizeCurrentCol(); /** * Reset this settings section to defaults. **/ void clearSettings(); protected: /** * Create internally used actions and connect them to the appropriate * slots. **/ void createActions(); /** * Update all actions for a context menu for logical section * 'section'. **/ void updateActions( int section ); /** * Create a submenu for the currently hidden columns. **/ QMenu * createHiddenColMenu( QWidget * parent ); /** * Return the column name for the specified logical section number. **/ QString colName( int section ) const; /** * Return 'true' if logical section no. 'section' has auto resize mode. **/ bool autoSizeCol( int section ) const; /** * Add any columns that are missing from the default columns to * 'colList'. **/ void addMissingColumns( DataColumnList & colList ); /** * Return the resize mode for the specified section. **/ QHeaderView::ResizeMode resizeMode( int section ) const; /** * Set the resize mode for the specified section. **/ void setResizeMode( int section, QHeaderView::ResizeMode resizeMode ); // // Data members // DirTreeView * _treeView; QHeaderView * _header; QAction * _actionAllColumnsAutoSize; QAction * _actionAllColumnsInteractiveSize; QAction * _actionAutoSizeCurrentCol; QAction * _actionHideCurrentCol; QAction * _actionShowAllHiddenColumns; QAction * _actionResetToDefaults; int _currentSection; }; // class HeaderTweaker } // namespace QDirStat #endif // HeaderTweaker_h qdirstat-1.4/src/HistogramDraw.cpp000066400000000000000000000215451311502036700172640ustar00rootroot00000000000000/* * File name: HistogramDraw.cpp * Summary: Draw routines for file size histogram * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "HistogramView.h" #include "HistogramItems.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" #define UnicodeMathSigma 0x2211 // 'n-ary summation' using namespace QDirStat; void HistogramView::addHistogram() { addHistogramBackground(); addAxes(); addYAxisLabel(); addXAxisLabel(); addXStartEndLabels(); addQuartileText(); addHistogramBars(); addMarkers(); } void HistogramView::addHistogramBackground() { QRectF rect( -_leftBorder, _bottomBorder, _histogramWidth + _leftBorder + _rightBorder, -( _histogramHeight + _topBorder + _bottomBorder ) ); _histogramPanel = scene()->addRect( rect, QPen( Qt::NoPen ), _panelBackground ); _histogramPanel->setZValue( PanelBackgroundLayer ); } void HistogramView::addAxes() { QPen pen( QColor( Qt::black ), 1 ); QGraphicsItem * xAxis = scene()->addLine( 0, 0, _histogramWidth, 0, pen ); QGraphicsItem * yAxis = scene()->addLine( 0, 0, 0, -_histogramHeight, pen ); xAxis->setZValue( AxisLayer ); yAxis->setZValue( AxisLayer ); } void HistogramView::addYAxisLabel() { QString labelText = _useLogHeightScale ? "log2(n) -->" : "n"; QGraphicsTextItem * item = scene()->addText( "" ); item->setHtml( labelText ); QFont font( item->font() ); font.setBold( true ); item->setFont( font ); qreal textWidth = item->boundingRect().width(); qreal textHeight = item->boundingRect().height(); QPointF labelCenter = QPoint( -_leftBorder / 2, -_histogramHeight / 2 ); if ( _useLogHeightScale ) { item->setRotation( 270 ); item->setPos( labelCenter.x() - textHeight / 2, labelCenter.y() + textWidth / 2 ); } else { item->setPos( labelCenter.x() - textWidth / 2, labelCenter.y() - textHeight / 2 ); } item->setZValue( TextLayer ); } void HistogramView::addXAxisLabel() { QString labelText = tr( "File Size" ) + " -->"; QGraphicsSimpleTextItem * item = scene()->addSimpleText( labelText ); QFont font( item->font() ); font.setBold( true ); item->setFont( font ); qreal textWidth = item->boundingRect().width(); qreal textHeight = item->boundingRect().height(); QPointF labelCenter = QPoint( _histogramWidth / 2, _bottomBorder ); item->setPos( labelCenter.x() - textWidth / 2, labelCenter.y() - textHeight ); // Align bottom item->setZValue( TextLayer ); } void HistogramView::addXStartEndLabels() { QString startLabel = tr( "Min" ); if ( _startPercentile > 0 ) startLabel = QString( "P%1" ).arg( _startPercentile ); startLabel += "\n" + formatSize( percentile( _startPercentile ) ); QString endLabel = _endPercentile == 100 ? tr( "Max" ) : QString( "P%1" ).arg( _endPercentile ); QString endSizeLabel = formatSize( percentile( _endPercentile ) ); QGraphicsSimpleTextItem * startItem = scene()->addSimpleText( startLabel ); QGraphicsSimpleTextItem * endItem = scene()->addSimpleText( endLabel ); QGraphicsSimpleTextItem * endSizeItem = scene()->addSimpleText( endSizeLabel ); qreal endTextHeight = endItem->boundingRect().height(); qreal endTextWidth = endItem->boundingRect().width(); qreal endSizeWidth = endSizeItem->boundingRect().width(); qreal y = _bottomBorder - 2 * endTextHeight; startItem->setPos( 0, _bottomBorder - startItem->boundingRect().height() ); endItem->setPos( _histogramWidth - endTextWidth, y ); endSizeItem->setPos( _histogramWidth - endSizeWidth, y + endTextHeight ); startItem->setZValue( TextLayer ); endItem->setZValue( TextLayer ); endSizeItem->setZValue( TextLayer ); } void HistogramView::addQuartileText() { qreal textBorder = 10.0; qreal textSpacing = 30.0; qreal x = 0; qreal y = -_histogramHeight - _topBorder - textBorder; qreal n = bucketsTotalSum(); if ( n > 0 ) // Only useful if there are any data at all { QString q1Text = tr( "Q1: %1" ).arg( formatSize( percentile( 25 ) ) ); QString q3Text = tr( "Q3: %1" ).arg( formatSize( percentile( 75 ) ) ); QString medianText = tr( "Median: %1" ).arg( formatSize( percentile( 50 ) ) ); QGraphicsSimpleTextItem * q1Item = scene()->addSimpleText( q1Text ); QGraphicsSimpleTextItem * q3Item = scene()->addSimpleText( q3Text ); QGraphicsSimpleTextItem * medianItem = scene()->addSimpleText( medianText ); q1Item->setBrush( _quartilePen.color() ); q3Item->setBrush( _quartilePen.color() ); medianItem->setBrush( _medianPen.color() ); QFont font( medianItem->font() ); font.setBold( true ); medianItem->setFont( font ); q1Item->setFont( font ); q3Item->setFont( font ); y -= medianItem->boundingRect().height(); qreal q1Width = q1Item->boundingRect().width(); qreal q3Width = q3Item->boundingRect().width(); qreal medianWidth = medianItem->boundingRect().width(); q1Item->setPos( x, y ); x += q1Width + textSpacing; medianItem->setPos( x, y ); x += medianWidth + textSpacing; q3Item->setPos( x, y ); x += q3Width + textSpacing; q1Item->setZValue( TextLayer ); q3Item->setZValue( TextLayer ); medianItem->setZValue( TextLayer ); } // // Add text for the total number of files // QString nText = tr( "Files (n): %1" ).arg( n ); QGraphicsSimpleTextItem * nTextItem = scene()->addSimpleText( nText ); QFont font( nTextItem->font() ); font.setBold( true ); nTextItem->setFont( font ); QFontMetrics metrics( font ); QChar sigma( UnicodeMathSigma ); if ( metrics.inFont( sigma ) ) nTextItem->setText( QString( "%1n: %2" ).arg( sigma ).arg( n ) ); if ( n == 0 ) y -= nTextItem->boundingRect().height(); nTextItem->setPos( x, y ); nTextItem->setZValue( TextLayer ); } void HistogramView::addHistogramBars() { qreal barWidth = _histogramWidth / _buckets.size(); qreal maxVal = _bucketMaxValue; if ( _useLogHeightScale ) maxVal = log2( maxVal ); for ( int i=0; i < _buckets.size(); ++i ) { // logDebug() << "Adding bar #" << i << " with value " << _buckets[ i ] << endl; QRectF rect; rect.setX( i * barWidth ); rect.setY( 0 ); rect.setHeight( -_histogramHeight ); rect.setWidth( barWidth ); qreal val = _buckets[i]; if ( _useLogHeightScale && val > 1.0 ) val = log2( val ); qreal fillHeight = maxVal == 0 ? 0.0 : val / maxVal * _histogramHeight; HistogramBar * bar = new HistogramBar( this, i, rect, fillHeight ); CHECK_NEW( bar ); } } void HistogramView::addMarkers() { qreal totalWidth = _percentiles[ _endPercentile ] - _percentiles[ _startPercentile ]; if ( totalWidth < 1 ) return; QLineF zeroLine( 0, _markerExtraHeight, 0, -( _histogramHeight + _markerExtraHeight ) ); // Show ordinary percentiles (all except Q1, Median, Q3) for ( int i = _startPercentile + 1; i < _endPercentile; ++i ) { if ( i == 0 || i == 100 ) continue; if ( i == 50 && _showMedian ) continue; if ( ( i == 25 || i == 75 ) && _showQuartiles ) continue; if ( _percentileStep != 1 ) { bool skip = true; if ( i <= _startPercentile + _leftMarginPercentiles && i < 25 ) skip = false; if ( i >= _endPercentile - _rightMarginPercentiles && i > 75 ) skip = false; if ( skip && _percentileStep != 0 && i % _percentileStep == 0 ) skip = false; if ( skip ) continue; } QPen pen = _percentilePen; if ( _percentileStep != 0 && _percentileStep != 5 && i % 10 == 0 ) pen = _decilePen; // logDebug() << "Adding marker for P" << i << endl; new PercentileMarker( this, i, "", zeroLine, pen ); } if ( _showQuartiles ) { if ( percentileDisplayed( 25 ) ) new PercentileMarker( this, 25, tr( "Q1 (1st Quartile)" ), zeroLine, _quartilePen ); if ( percentileDisplayed( 75 ) ) new PercentileMarker( this, 75, tr( "Q3 (3rd Quartile)" ), zeroLine, _quartilePen ); } if ( _showMedian && percentileDisplayed( 50 ) ) { new PercentileMarker( this, 50, tr( "Median" ), zeroLine, _medianPen ); } } QPointF HistogramView::addText( const QPointF & pos, const QStringList & lines ) { QGraphicsTextItem * textItem = scene()->addText( lines.join( "\n" ) ); textItem->setPos( pos ); return QPoint( pos.x(), pos.y() + textItem->boundingRect().height() ); } QPointF HistogramView::addBoldText( const QPointF & pos, const QString & text ) { QGraphicsTextItem * textItem = scene()->addText( text ); textItem->setPos( pos ); QFont boldFont( textItem->font() ); boldFont.setBold( true ); textItem->setFont( boldFont ); return QPoint( pos.x(), pos.y() + textItem->boundingRect().height() ); } qdirstat-1.4/src/HistogramItems.cpp000066400000000000000000000077221311502036700174510ustar00rootroot00000000000000/* * File name: HistogramViewItems.cpp * Summary: QGraphicsItems for file size histogram for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "HistogramItems.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; HistogramBar::HistogramBar( HistogramView * parent, int number, const QRectF & rect, qreal fillHeight ): QGraphicsRectItem( rect ), _parentView( parent ), _number( number ) { setPen( Qt::NoPen ); // Setting NoPen so this rectangle remains invisible: This full-height // rectangle is just for clicking. For the bar content, we create a visible // separate child item with the correct height. QRectF childRect = rect; childRect.setHeight( -fillHeight ); QGraphicsRectItem * filledRect = new QGraphicsRectItem( childRect, this ); CHECK_NEW( filledRect ); filledRect->setPen( _parentView->barPen() ); filledRect->setBrush( _parentView->barBrush() ); // setFlags( ItemIsSelectable ); _parentView->scene()->addItem( this ); _startVal = _parentView->bucketStart( _number ); _endVal = _parentView->bucketEnd ( _number ); QString tooltip = QObject::tr( "Bucket #%1:\n%2 Files\n%3 .. %4" ) .arg( _number + 1 ) .arg( _parentView->bucket( _number ) ) .arg( formatSize( _startVal ) ) .arg( formatSize( _endVal ) ); setToolTip( tooltip ); filledRect->setToolTip( tooltip ); setZValue( HistogramView::InvisibleBarLayer ); filledRect->setZValue( HistogramView::BarLayer ); } void HistogramBar::mousePressEvent( QGraphicsSceneMouseEvent * event ) { switch ( event->button() ) { case Qt::LeftButton: { QGraphicsRectItem::mousePressEvent( event ); #if 0 // FIXME: This does not work. Why? QPointF pos( event->scenePos() ); QToolTip::showText( QPoint( pos.x(), pos.y() ), toolTip(), _parentView ); #endif logDebug() << "Histogram bar #" << _number << ": " << _parentView->bucket( _number ) << " items;" << " range: " << formatSize( _startVal ) << " .. " << formatSize( _endVal ) << endl; } break; default: QGraphicsRectItem::mousePressEvent( event ); break; } } PercentileMarker::PercentileMarker( HistogramView * parent, int percentileIndex, const QString & name, const QLineF & zeroLine, const QPen & pen ): QGraphicsLineItem( translatedLine( zeroLine, percentileIndex, parent ) ), _parentView( parent ), _name( name ), _percentileIndex( percentileIndex ) { if ( _name.isEmpty() ) { _name = QObject::tr( "Percentile P%1" ).arg( _percentileIndex ); setZValue( HistogramView::MarkerLayer ); } else { setZValue( HistogramView::SpecialMarkerLayer ); } setToolTip( _name + "\n" + formatSize( _parentView->percentile( percentileIndex ) ) ); setPen( pen ); // setFlags( ItemIsSelectable ); _parentView->scene()->addItem( this ); } QLineF PercentileMarker::translatedLine( const QLineF & zeroLine, int percentileIndex, HistogramView * parent ) const { qreal value = parent->percentile( percentileIndex ); qreal x = parent->scaleValue( value ); return zeroLine.translated( x, 0 ); } qreal PercentileMarker::value() const { return _parentView->percentile( _percentileIndex ); } void PercentileMarker::mousePressEvent( QGraphicsSceneMouseEvent * event ) { switch ( event->button() ) { case Qt::LeftButton: QGraphicsLineItem::mousePressEvent( event ); logDebug() << "Percentile marker #" << _percentileIndex << ": " << _name << ": " << formatSize( _parentView->percentile( _percentileIndex ) ) << endl; break; default: QGraphicsLineItem::mousePressEvent( event ); break; } } qdirstat-1.4/src/HistogramItems.h000066400000000000000000000046021311502036700171100ustar00rootroot00000000000000/* * File name: HistogramView.h * Summary: View widget for histogram rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef HistogramItems_h #define HistogramItems_h #include #include #include "HistogramItems.h" #include "HistogramView.h" namespace QDirStat { /** * GraphicsItem class for a histogram bar. * * This creates an invisible full-height item so it is clickable, even for * very small values, and a visible child rectangle to display the correct * height. **/ class HistogramBar: public QGraphicsRectItem { public: /** * Constructor. 'number' is the number of the bar (0 being the * leftmost) in the histogram. **/ HistogramBar( HistogramView * parent, int number, const QRectF & rect, qreal fillHeight ); /** * Return the number of this bar. **/ int number() const { return _number; } protected: /** * Mouse press event * * Reimplemented from QGraphicsItem. **/ virtual void mousePressEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE; HistogramView * _parentView; int _number; qreal _startVal; qreal _endVal; }; /** * GraphicsItem for a percentile marker (including median or quartiles). **/ class PercentileMarker: public QGraphicsLineItem { public: PercentileMarker( HistogramView * parent, int percentileIndex, const QString & name, const QLineF & zeroLine, const QPen & pen ); /** * Return the name of this marker; something like "P1", "Min", "Max", * "Median", "Q1", "Q3". **/ QString name() const { return _name; } /** * Return the percentile index (0..100) for this marker. **/ int percentileIndex() const { return _percentileIndex; } /** * Return the percentile value for this marker. **/ qreal value() const; protected: QLineF translatedLine( const QLineF & zeroLine, int percentileIndex, HistogramView * parent ) const; /** * Mouse press event * * Reimplemented from QGraphicsItem. **/ virtual void mousePressEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE; HistogramView * _parentView; QString _name; int _percentileIndex; }; } // namespace QDirStat #endif // ifndef HistogramItems_h qdirstat-1.4/src/HistogramOverflowPanel.cpp000066400000000000000000000127021311502036700211450ustar00rootroot00000000000000/* * File name: HistogramOverflowPanel.cpp * Summary: Overflow panel drawing for file size histogram * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "HistogramView.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; void HistogramView::addOverflowPanel() { if ( ! needOverflowPanel() ) return; // Panel for the overflow area QRectF histPanelRect = _histogramPanel->boundingRect().normalized(); QRectF rect( histPanelRect.topRight().x() + _overflowSpacing, histPanelRect.topRight().y(), _overflowWidth + _overflowLeftBorder + _overflowRightBorder, histPanelRect.height() ); QGraphicsRectItem * cutoffPanel = scene()->addRect( rect, QPen( Qt::NoPen ), _panelBackground ); // Headline QPointF nextPos( rect.x() + _overflowLeftBorder, rect.y() ); nextPos = addBoldText( nextPos, tr( "Cut off" ) ); // Text about cut-off percentiles and size qreal filesInHistogram = bucketsTotalSum(); qreal totalFiles = bucketsTotalSum() / ( _endPercentile - _startPercentile ) * 100.0; int missingFiles = totalFiles - filesInHistogram; QStringList lines; if ( _startPercentile > 0 ) { lines << ""; lines << tr( "Min (P0) .. P%1" ).arg( _startPercentile ); lines << tr( "%1 .. %2" ) .arg( formatSize( percentile( 0 ) ) ) .arg( formatSize( percentile( _startPercentile ) ) ); } if ( _endPercentile < 100 ) { lines << ""; lines << tr( "P%1 .. Max (P100)" ).arg( _endPercentile ); lines << tr( "%1 .. %2" ) .arg( formatSize( percentile( _endPercentile ) ) ) .arg( formatSize( percentile( 100 ) ) ); } nextPos = addText( nextPos, lines ); // Upper pie chart: Number of files cut off nextPos.setY( nextPos.y() + _pieSliceOffset ); QRectF pieRect( QRectF( nextPos, QSizeF( _pieDiameter, _pieDiameter ) ) ); int cutoff = _startPercentile + 100 - _endPercentile; nextPos = addPie( pieRect, 100 - cutoff, cutoff, _barBrush, _overflowSliceBrush ); // Caption for the upper pie chart lines.clear(); lines << tr( "%1% of all files" ).arg( cutoff ); lines << ( missingFiles == 1 ? tr( "1 file total" ) : tr( "%1 files total" ).arg( missingFiles ) ); lines << ""; nextPos = addText( nextPos, lines ); // Lower pie chart: Disk space disregarded qreal histogramDiskSpace = percentileSum( _startPercentile, _endPercentile ); qreal cutoffDiskSpace = percentileSum( 0, _startPercentile ); if ( _endPercentile < 100 ) cutoffDiskSpace += percentileSum( _endPercentile, 100 ); qreal cutoffSpacePercent = 100.0 * cutoffDiskSpace / ( histogramDiskSpace + cutoffDiskSpace ); nextPos.setY( nextPos.y() + _pieSliceOffset ); pieRect = QRectF( nextPos, QSizeF( _pieDiameter, _pieDiameter ) ); if ( cutoffDiskSpace > histogramDiskSpace ) { nextPos = addPie( pieRect, cutoffDiskSpace, histogramDiskSpace, _overflowSliceBrush, _barBrush ); } else { nextPos = addPie( pieRect, histogramDiskSpace, cutoffDiskSpace, _barBrush, _overflowSliceBrush ); } // Caption for the lower pie chart lines.clear(); lines << tr( "%1% of disk space" ).arg( cutoffSpacePercent, 0, 'f', 1 ); lines << tr( "%1 total" ).arg( formatSize( cutoffDiskSpace ) ); lines << ""; nextPos = addText( nextPos, lines ); // Make sure the panel is tall enough to fit everyting in if ( nextPos.y() > cutoffPanel->rect().bottom() ) { QRectF rect( cutoffPanel->rect() ); rect.setBottomLeft( QPointF( rect.x(), nextPos.y() ) ); cutoffPanel->setRect( rect ); } } QPointF HistogramView::addPie( const QRectF & rect, qreal val1, qreal val2, const QBrush & brush1, const QBrush & brush2 ) { if ( val1 + val2 == 0.0 ) return rect.topLeft(); const qreal FullCircle = 360.0 * 16.0; // Qt uses 1/16 degrees qreal angle1 = val1 / ( val1 + val2 ) * FullCircle; qreal angle2 = FullCircle - angle1; QGraphicsEllipseItem * slice1 = scene()->addEllipse( rect ); slice1->setStartAngle( angle2 / 2.0 ); slice1->setSpanAngle( angle1 ); slice1->setBrush( brush1 ); slice1->setPen( _piePen ); QRectF rect2( rect ); rect2.moveTopLeft( rect.topLeft() + QPoint( _pieSliceOffset, 0.0 ) ); QGraphicsEllipseItem * slice2 = scene()->addEllipse( rect2 ); slice2->setStartAngle( -angle2 / 2.0 ); slice2->setSpanAngle( angle2 ); slice2->setBrush( brush2 ); slice2->setPen( _piePen ); QList slices; slices << slice1 << slice2; QGraphicsItemGroup * pie = scene()->createItemGroup( slices ); QPointF pieCenter = rect.center(); // Figuring out the following arcane sequence took me well over 2 hours. // // Seriously, trolls, WTF?! One of the most common things to do is to // rotate a QGraphicsItem around its center. But this is the most difficult // thing to do, and, adding insult to injury, IT IS NOT EXPLAINED IN THE // DOCUMENTATION! QTransform transform; transform.translate( pieCenter.x(), pieCenter.y() ); transform.rotate( -45.0 ); transform.translate( -pieCenter.x(), -pieCenter.y() ); pie->setTransform( transform ); return QPoint( rect.x(), rect.y() + pie->boundingRect().height() ); } qdirstat-1.4/src/HistogramView.cpp000066400000000000000000000311211311502036700172700ustar00rootroot00000000000000/* * File name: HistogramView.cpp * Summary: View widget for histogram rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "HistogramView.h" #include "DelayedRebuilder.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" // See also HistogramDraw.cpp and HistogramOverflowPanel.cpp #define CHECK_PERCENTILE_INDEX( INDEX ) \ CHECK_INDEX_MSG( (INDEX), 0, 100, "Percentile index out of range" ); #define MinHistogramWidth 150.0 #define MinHistogramHeight 80.0 using namespace QDirStat; HistogramView::HistogramView( QWidget * parent ): QGraphicsView( parent ) { init(); _rebuilder = new DelayedRebuilder(); CHECK_NEW( _rebuilder ); connect( _rebuilder, SIGNAL( rebuild() ), this, SLOT ( rebuild() ) ); setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); // Improve graphics quality from C64 style to 21st century style setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing ); } HistogramView::~HistogramView() { delete _rebuilder; } void HistogramView::init() { _histogramPanel = 0; _geometryDirty = true; _bucketMaxValue = 0; _startPercentile = 0; // data min _endPercentile = 100; // data max _useLogHeightScale = false; _showMedian = true; _showQuartiles = true; _percentileStep = 0; _leftMarginPercentiles = 0; _rightMarginPercentiles = 5; // TO DO: read from and write to QSettings _histogramHeight = 250.0; _histogramWidth = 600.0; _leftBorder = 40.0; _rightBorder = 10.0; _topBorder = 30.0; _bottomBorder = 50.0; _viewMargin = 10.0; _markerExtraHeight = 15.0; _overflowWidth = 150.0; _overflowLeftBorder = 10.0; _overflowRightBorder = 10.0; _overflowSpacing = 15.0; _pieDiameter = 60.0; _pieSliceOffset = 10.0; _panelBackground = QBrush( QColor( 0xF0, 0xF0, 0xF0 ) ); _barBrush = QBrush( QColor( 0xB0, 0xB0, 0xD0 ) ); _barPen = QPen( QColor( 0x40, 0x40, 0x50 ), 1 ); _medianPen = QPen( Qt::magenta, 2 ); _quartilePen = QPen( Qt::blue, 2 ); _percentilePen = QPen( QColor( 0xA0, 0xA0, 0xA0 ), 1 ); _decilePen = QPen( QColor( 0x30, 0x80, 0x30 ), 1 ); _piePen = QPen( Qt::black, 2 ); _overflowSliceBrush = QBrush( QColor( 0xD0, 0x40, 0x20 ) ); } void HistogramView::clear() { _buckets.clear(); _percentiles.clear(); _percentileSums.clear(); init(); if ( scene() ) { scene()->clear(); scene()->invalidate( scene()->sceneRect() ); } } qreal HistogramView::bestBucketCount( int n ) { if ( n < 2 ) return 1; // Using the "Rice Rule" which gives more reasonable values for the numbers // we are likely to encounter in the context of QDirStat. qreal result = 2 * pow( n, 1.0/3.0 ); if ( result > MAX_BUCKET_COUNT ) { logInfo() << "Limiting bucket count to " << MAX_BUCKET_COUNT << " instead of " << result << endl; // Enforcing an upper limit so each histogram bar remains wide enough // to be clicked on or for tooltips etc. result = MAX_BUCKET_COUNT; } else if ( result < 1.0 ) { result = 1.0; } return result; } qreal HistogramView::bucketWidth( qreal min, qreal max, int bucketCount ) { if ( bucketCount < 1 ) return 0; return ( max - min ) / (qreal) bucketCount; } qreal HistogramView::bucketStart( int index ) const { qreal offset = percentile( _startPercentile ); return offset + index * bucketWidth(); } qreal HistogramView::bucketEnd( int index ) const { qreal offset = percentile( _startPercentile ); return offset + ( index + 1 ) * bucketWidth(); } void HistogramView::setBuckets( const QRealList & newBuckets ) { _buckets = newBuckets; _bucketMaxValue = 0; for ( int i=0; i < _buckets.size(); ++i ) _bucketMaxValue = qMax( _bucketMaxValue, _buckets[i] ); } void HistogramView::setPercentiles( const QRealList & newPercentiles ) { CHECK_INDEX_MSG( newPercentiles.size(), 101, 101, "Percentiles size out of range" ); _percentiles = newPercentiles; } void HistogramView::setPercentile( int index, qreal value ) { CHECK_PERCENTILE_INDEX( index ); _percentiles[ index ] = value; } qreal HistogramView::percentile( int index ) const { CHECK_PERCENTILE_INDEX( index ); return _percentiles[ index ]; } void HistogramView::setStartPercentile( int index ) { CHECK_PERCENTILE_INDEX( index ); bool oldNeedOverflowPanel = needOverflowPanel(); _startPercentile = index; if ( oldNeedOverflowPanel != needOverflowPanel() ) _geometryDirty = true; } void HistogramView::setEndPercentile( int index ) { CHECK_PERCENTILE_INDEX( index ); bool oldNeedOverflowPanel = needOverflowPanel(); _endPercentile = index; if ( oldNeedOverflowPanel != needOverflowPanel() ) _geometryDirty = true; if ( _startPercentile >= _endPercentile ) { logError() << "startPercentile must be less than endPercentile: " << _startPercentile << ".." << _endPercentile << endl; } } bool HistogramView::percentileDisplayed( int index ) const { return index >= _startPercentile && index <= _endPercentile; } void HistogramView::setPercentileSums( const QRealList & newPercentileSums ) { CHECK_INDEX_MSG( newPercentileSums.size(), 101, 101, "Percentile sums size out of range" ); _percentileSums = newPercentileSums; } qreal HistogramView::percentileSum( int index ) const { CHECK_PERCENTILE_INDEX( index ); if ( _percentileSums.isEmpty() ) return 0.0; return _percentileSums[ index ]; } qreal HistogramView::percentileSum( int fromIndex, int toIndex ) const { CHECK_PERCENTILE_INDEX( fromIndex ); CHECK_PERCENTILE_INDEX( toIndex ); if ( _percentileSums.isEmpty() ) return 0.0; qreal sum = 0.0; for ( int i=fromIndex; i <= toIndex; ++i ) sum += _percentileSums[i]; return sum; } qreal HistogramView::bucket( int index ) const { CHECK_INDEX( index, 0, _buckets.size() - 1 ); return _buckets[ index ]; } qreal HistogramView::bucketWidth() const { if ( _buckets.isEmpty() || _percentiles.isEmpty() ) return 0; qreal startVal = percentile( _startPercentile ); qreal endVal = percentile( _endPercentile ); if ( startVal > endVal ) THROW( Exception( "Invalid percentile data" ) ); return ( endVal - startVal ) / (qreal) _buckets.size(); } qreal HistogramView::bucketsTotalSum() const { qreal sum = 0; for ( int i=0; i < _buckets.size(); ++i ) sum += _buckets[i]; return sum; } void HistogramView::autoStartEndPercentiles() { if ( _percentiles.isEmpty() ) { logError() << "No percentiles set" << endl; return; } qreal q1 = percentile( 25 ); qreal q3 = percentile( 75 ); qreal qDist = q3 - q1; qreal minVal = qMax( q1 - 3 * qDist, 0.0 ); qreal maxVal = qMin( q3 + 3 * qDist, percentile( 100 ) ); bool oldNeedOverflowPanel = needOverflowPanel(); for ( _startPercentile = 0; _startPercentile <= 25; ++_startPercentile ) { if ( percentile( _startPercentile ) >= minVal ) break; } for ( _endPercentile = 100; _endPercentile >= 75; --_endPercentile ) { if ( percentile( _endPercentile ) <= maxVal ) break; } if ( oldNeedOverflowPanel != needOverflowPanel() ) _geometryDirty = true; logInfo() << "Q1: " << formatSize( q1 ) << " Q3: " << formatSize( q3 ) << " minVal: " << formatSize( minVal ) << " maxVal: " << formatSize( maxVal ) << endl; logInfo() << "startPercentile: " << _startPercentile << " " << formatSize( percentile( _startPercentile ) ) << " endPercentile: " << _endPercentile << " " << formatSize( percentile( _endPercentile ) ) << endl; } bool HistogramView::autoLogHeightScale() { if ( _buckets.isEmpty() ) { logError() << "No buckets set" << endl; return false; } _useLogHeightScale = false; if ( _buckets.size() > 3 ) { QRealList data = _buckets; std::sort( data.begin(), data.end() ); qreal largest = data.last(); // We compare the largest bucket with the P90 percentile of the buckets // (not to confuse with the P90 percentile with the data the buckets // were collected from!) int referencePercentile = 85; int pos = data.size() / 100.0 * referencePercentile; qreal referencePercentileValue = data.at( pos ); _useLogHeightScale = largest > referencePercentileValue * 10; logInfo() << "Largest bucket: " << largest << " bucket P" << referencePercentile << ": " << referencePercentileValue << " -> use log height scale: " << _useLogHeightScale << endl; } return _useLogHeightScale; } void HistogramView::calcGeometry( const QSize & newSize ) { _histogramWidth = newSize.width(); _histogramWidth -= _leftBorder + _rightBorder + 2 * _viewMargin; if ( needOverflowPanel() ) { _histogramWidth -= _overflowSpacing + _overflowWidth; _histogramWidth -= _overflowLeftBorder + _overflowRightBorder; } if ( _histogramWidth < MinHistogramWidth ) _histogramWidth = MinHistogramWidth; _histogramHeight = newSize.height(); _histogramHeight -= _bottomBorder + _topBorder + 2 * _viewMargin; _histogramHeight -= 30.0; // compensate for text above _histogramHeight = qBound( MinHistogramHeight, _histogramHeight, 1.5 * _histogramWidth ); _geometryDirty = false; #if 0 logDebug() << "Histogram width: " << _histogramWidth << " height: " << _histogramHeight << endl; #endif } bool HistogramView::needOverflowPanel() const { return _startPercentile > 0 || _endPercentile < 100; } void HistogramView::autoResize() { calcGeometry( viewport()->size() ); } void HistogramView::resizeEvent( QResizeEvent * event ) { // logDebug() << "Event size: " << event->size() << endl; QGraphicsView::resizeEvent( event ); calcGeometry( event->size() ); _rebuilder->scheduleRebuild(); } void HistogramView::fitToViewport() { // This is the black magic that everybody hates from the bottom of his // heart about that drawing stuff: Making sure the graphics actually is // visible on the screen without unnecessary scrolling. // // You would think that a widget as sophisticated as QGraphicsView does // this all by itself, but no: Everybody has to waste hours upon hours of // life time with this crap. QRectF rect = scene()->sceneRect().normalized(); // logDebug() << "Old scene rect: " << rect << endl; scene()->setSceneRect( rect ); rect.adjust( -_viewMargin, -_viewMargin, _viewMargin, _viewMargin ); // logDebug() << "New scene rect: " << rect << endl; // logDebug() << "Viewport size: " << viewport()->size() << endl; QSize visibleSize = viewport()->size(); if ( rect.width() <= visibleSize.width() && rect.height() <= visibleSize.height() ) { logDebug() << "Histogram in " << rect.size() << " fits into visible size " << visibleSize << endl; setTransform( QTransform() ); // Reset scaling etc. ensureVisible( rect, 0, 0 ); } else { logDebug() << "Scaling down histogram in " << rect.size() << " to fit into visible size " << visibleSize << endl; fitInView( rect, Qt::KeepAspectRatio ); } } void HistogramView::rebuild() { if ( _rebuilder->firstRebuild() ) { _rebuilder->scheduleRebuild(); return; } logInfo() << "Rebuilding histogram" << endl; if ( _geometryDirty ) autoResize(); // QGraphicsScene never resets the min and max in both dimensions where it // ever created QGraphicsItems, which makes its sceneRect() call pretty // useless. Let's create a new one without those bad old memories. if ( scene() ) delete scene(); QGraphicsScene * newScene = new QGraphicsScene( this ); CHECK_NEW( newScene); setScene( newScene ); if ( _buckets.size() < 1 || _percentiles.size() != 101 ) { scene()->addText( "No data yet" ); logInfo() << "No data yet" << endl; return; } addHistogram(); addOverflowPanel(); fitToViewport(); } qreal HistogramView::scaleValue( qreal value ) { qreal startVal = _percentiles[ _startPercentile ]; qreal endVal = _percentiles[ _endPercentile ]; qreal totalWidth = endVal - startVal; qreal result = ( value - startVal ) / totalWidth * _histogramWidth; // logDebug() << "Scaling " << formatSize( value ) << " to " << result << endl; return result; } qdirstat-1.4/src/HistogramView.h000066400000000000000000000321031311502036700167360ustar00rootroot00000000000000/* * File name: HistogramView.h * Summary: View widget for histogram rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef HistogramView_h #define HistogramView_h #include #include #define MAX_BUCKET_COUNT 100 class QGraphicsSceneMouseEvent; typedef QList QRealList; namespace QDirStat { class DelayedRebuilder; /** * Histogram widget. * * This widget is based on buckets and percentiles, both of which have to * be fed from the outside, i.e. the data collection is abstracted. * * The histogram can be displayed in a traditional way, i.e. from the * minimum data value (percentile 0 or P0) to the maximum data value * (percentile 100 or P100). But in many cases, this greatly distorts the * display because of outliers (data points way outside the range of * "normal" data points), so this histogram can also display from a given * percentile (startPercentile) to another given percentile * (endPercentile). * * In many cases, those outliers are only a very small percentage, so * displaying not from P0..P100, but from P3..P97 instead gives a much more * meaningful histogram, while still displaying 96% of all data: By * definition, each percentile contains 1% of all data points, so you lose * one percent at the left and one percent at the right for each percentile * omitted like this. * * That "cutoff" should be clearly communicated to the user so he does not * get the impression that this histogram in that mode displays all data; * it does not. It does display the meaningful part of the data, though. * * In addition to that, the percentiles (or at least every 5th of them, * depending on configuration) as well as the median, the 1st and the 3rd * quartile (Q1 and Q3) can be displayed as an overlay to the histogram. **/ class HistogramView: public QGraphicsView { Q_OBJECT public: /** * zValue (altitude) for the different graphics elements **/ enum GraphicsItemLayers { PanelBackgroundLayer = -100, MiscLayer = 0, // Default if no zValue specified InvisibleBarLayer, BarLayer, AxisLayer, MarkerLayer, SpecialMarkerLayer, TextLayer }; /** * Constructor. **/ HistogramView( QWidget * parent = 0 ); /** * Destructor. **/ virtual ~HistogramView(); /** * Clear all data and all displayed graphics. **/ void clear(); /** * Set the percentiles for the data points all at once. Unlike the * buckets, these have a value; in the context of QDirStat, this is the * FileSize. * * The definition of a percentile n is "the data value where n percent * of all sorted data are taken into account". The median is the 50th * percentile. By a little stretch of the definition, percentile 0 is * the data minimum, percentile 100 is the data maximum. * * The inverval between one percentile and the next contains exactly 1% * of the data points. **/ void setPercentiles( const QRealList & newPercentiles ); /** * Set one percentile value. If you use that, make sure you iterate * over all of them (0..100) to set them all. **/ void setPercentile( int index, qreal value ); /** * Return the stored value for percentile no. 'index' (0..100). **/ qreal percentile( int index ) const; /** * Set the percentile (0..100) from which on to display data, i.e. set * the left border of the histogram. The real value to use is taken * from the stored percentiles. **/ void setStartPercentile( int index ); /** * Return the percentile from which on to display data, i.e. the left * border of the histogram. Use percentile() with the result of this to * get the numeric value. **/ int startPercentile() const { return _startPercentile; } /** * Set the percentile (0..100) until which on to display data, i.e. set * the right border of the histogram. The real value to use is taken * from the stored percentiles. **/ void setEndPercentile( int index ); /** * Return the percentile until which on to display data, i.e. the right * border of the histogram. Use percentile() with the result of this to * get the numeric value. **/ int endPercentile() const { return _endPercentile; } /** * Automatically determine the best start and end percentile. **/ void autoStartEndPercentiles(); /** * Calculate the best bucket count according to the "Rice Rule" for n * data points, but limited to MAX_BUCKET_COUNT. * * See also https://en.wikipedia.org/wiki/Histogram **/ static qreal bestBucketCount( int n ); /** * Calculate the bucket width from min to max for 'bucketCount' * buckets. **/ static qreal bucketWidth( qreal min, qreal max, int bucketCount ); /** * Set the data as "buckets". Each bucket contains the number of data * points (not their value!) from one interval of bucketWidth width. * * The type of the buckets is qreal even though by mathematical * definition it should be int, but QGraphicsView uses qreal * everywhere, so this is intended to minimize the hassle converting * back and forth. The bucket values can safely be converted to int * with no loss of precision. **/ void setBuckets( const QRealList & newBuckets ); /** * Return the current number of data buckets, i.e. the number of * histogram bars. **/ int bucketCount() const { return _buckets.size(); } /** * Return the number of data points in bucket no. 'index'. **/ qreal bucket( int index ) const; /** * Return the width of a bucket. All buckets have the same width. * * Notice that this value can only be obtained after all relevant data * are set: buckets, percentiles, startPercentile, endPercentile. **/ qreal bucketWidth() const; /** * Return the start value of bucket no. 'index'. **/ qreal bucketStart( int index ) const; /** * Return the end value of bucket no. 'index'. **/ qreal bucketEnd( int index ) const; /** * Return the total sum of all buckets. **/ qreal bucketsTotalSum() const; /** * Set the percentile sums. **/ void setPercentileSums( const QRealList & newPercentileSums ); /** * Return the percentile sum for percentile no. 'index' (0..100), * i.e. the accumulated values between percentile index-1 and index. **/ qreal percentileSum( int index ) const; /** * Return the percentile sums from 'fromIndex' including to 'toIndex'. **/ qreal percentileSum( int fromIndex, int toIndex ) const; /** * Enable or disable showing the median (percentile 50) as an overlay * over the histogram. **/ void setShowMedian( bool show = true ) { _showMedian = show; } /** * Return 'true' if the median is shown as an overlay, 'false' if not. **/ bool showMedian() const { return _showMedian; } /** * Enable or disable showing the 1st and 3rd quartiles (Q1 and Q3, * percentile 25 and 75, respectively) as an overlay over the * histogram. **/ void setShowQuartiles( bool show = true ) { _showQuartiles = show; } /** * Return 'true' if the 1st and 3rd quartiles are shown as an overlay, * 'false' if not. **/ bool showQuartiles() const { return _showQuartiles; } /** * Enable or disable showing percentiles as an overlay over the * histogram. 'step' specifies how many of them to display; with the * default '5' it will display P5, P10, P15 etc.; step = 0 disables * them completely. **/ void setPercentileStep( int step = 5 ) { _percentileStep = step; } /** * Return the percentile step or 0 if no percentiles are shown. **/ int percentileStep() const { return _percentileStep; } /** * Set how many percentiles to display as an overlay at the left margin * in addition to those shown with showPercentiles(). * * A value of 2 with a histogram showing data from min to max means * show also P1 and P2. * * A value of 2 with a histogram showing data from P3 to P97 means show * also P4 and P5. * * A value of 0 means show no additional percentiles. **/ void setLeftMarginPercentiles( int number = 0 ) { _leftMarginPercentiles = number; } /** * Return the left margin percentiles or 0 if none are shown. **/ int leftMarginPercentiles() { return _leftMarginPercentiles; } /** * Set how many percentiles to display as an overlay at the right * margin in addition to those shown with showPercentiles(). * * A value of 2 with a histogram showing data from min to max means * show also P98 and P99. * * A value of 2 with a histogram showing data from P3 to P97 means show * also P95 and P96. * * A value of 0 means show no additional percentiles. **/ void setRightMarginPercentiles( int number= 2 ) { _leftMarginPercentiles = number; } /** * Return the right margin percentiles or 0 if none are shown. **/ int rightMarginPercentiles() { return _rightMarginPercentiles; } /** * Enable or disable a logarithmic (log2) height scale. **/ void setUseLogHeightScale( bool enable ) { _useLogHeightScale = enable; } /** * Return 'true' if a logarithmic height scale is used or 'false' if * not. **/ bool useLogHeightScale() const { return _useLogHeightScale; } /** * Automatically determine if a logarithmic height scale should be * used. Set the internal _useLogHeightScale variable accordingly and * return it. **/ bool autoLogHeightScale(); /** * Convert a data value to the corresponding X axis point in the * histogram. **/ qreal scaleValue( qreal value ); // Pens and brushes for the various elements of the histograms QBrush barBrush() const { return _barBrush; } QPen barPen() const { return _barPen; } QPen medianPen() const { return _medianPen; } QPen quartilePen() const { return _quartilePen; } QPen percentilePen() const { return _percentilePen; } QPen decilePen() const { return _decilePen; } public slots: /** * Rebuild the histogram based on the current data. **/ void rebuild(); protected: /** * Common one-time initializations **/ void init(); /** * Return 'true' if percentile no. 'index' is in range for being * displayed, i.e. if it is between _startPercentile and * _endPercentile. **/ bool percentileDisplayed( int index ) const; // Graphical Elements void addHistogram(); void addHistogramBackground(); void addAxes(); void addYAxisLabel(); void addXAxisLabel(); void addXStartEndLabels(); void addQuartileText(); void addHistogramBars(); void addMarkers(); void addOverflowPanel(); /** * Add a text item at 'pos' and return the bottom left of its bounding * rect. **/ QPointF addText( const QPointF & pos, const QStringList & lines ); /** * Add a bold font text item at 'pos' and return the bottom left of its * bounding rect. **/ QPointF addBoldText( const QPointF & pos, const QString & text ); /** * Add a pie diagram with two values val1 and val2. * Return the bottom left of the bounding rect. **/ QPointF addPie( const QRectF & rect, qreal val1, qreal val2, const QBrush & brush1, const QBrush & brush2 ); /** * Fit the graphics into the viewport. **/ void fitToViewport(); /** * Resize the view. * * Reimplemented from QFrame. **/ virtual void resizeEvent( QResizeEvent * event ) Q_DECL_OVERRIDE; /** * Calculate the content geometry to fit into 'newSize'. **/ void calcGeometry( const QSize & newSize ); /** * Resize the widget content to the current window size. **/ void autoResize(); /** * Return 'true' if an overflow ("cutoff") panel is needed. **/ bool needOverflowPanel() const; // // Data Members // DelayedRebuilder * _rebuilder; QGraphicsItem * _histogramPanel; bool _geometryDirty; // Statistics Data QRealList _buckets; QRealList _percentiles; QRealList _percentileSums; qreal _bucketMaxValue; int _startPercentile; int _endPercentile; bool _useLogHeightScale; // Flags and Settings bool _showMedian; bool _showQuartiles; int _percentileStep; int _leftMarginPercentiles; int _rightMarginPercentiles; // Brushes and Pens QBrush _panelBackground; QBrush _barBrush; QPen _barPen; QPen _medianPen; QPen _quartilePen; QPen _percentilePen; QPen _decilePen; QPen _piePen; QBrush _overflowSliceBrush; // Geometry qreal _histogramWidth; qreal _histogramHeight; qreal _leftBorder; // left of histogram qreal _rightBorder; qreal _topBorder; qreal _bottomBorder; qreal _markerExtraHeight; qreal _overflowWidth; qreal _overflowLeftBorder; qreal _overflowRightBorder; qreal _overflowSpacing; // between histogram and overflow area qreal _pieDiameter; qreal _pieSliceOffset; qreal _viewMargin; // around all elements of the view }; } // namespace QDirStat #endif // ifndef HistogramView_h qdirstat-1.4/src/ListEditor.cpp000066400000000000000000000134601311502036700165700ustar00rootroot00000000000000/* * File name: ListEditor.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "ListEditor.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; ListEditor::ListEditor( QWidget * parent ): QWidget( parent ), _listWidget(0), _firstRow(0), _updatesLocked(false), _moveUpButton(0), _moveDownButton(0), _moveToTopButton(0), _moveToBottomButton(0), _addButton(0), _removeButton(0) { } ListEditor::~ListEditor() { } void ListEditor::setListWidget( QListWidget * listWidget ) { _listWidget = listWidget; connect( _listWidget, SIGNAL( currentItemChanged( QListWidgetItem *, QListWidgetItem * ) ), this, SLOT ( currentItemChanged( QListWidgetItem *, QListWidgetItem * ) ) ); } #define CONNECT_BUTTON(BUTTON, RCVR_SLOT) \ connect( (BUTTON), SIGNAL( clicked() ), this, SLOT( RCVR_SLOT ) ) void ListEditor::setMoveUpButton( QAbstractButton * button ) { _moveUpButton = button; CONNECT_BUTTON( button, moveUp() ); } void ListEditor::setMoveDownButton( QAbstractButton * button ) { _moveDownButton = button; CONNECT_BUTTON( button, moveDown() ); } void ListEditor::setMoveToTopButton( QAbstractButton * button ) { _moveToTopButton = button; CONNECT_BUTTON( button, moveToTop() ); } void ListEditor::setMoveToBottomButton( QAbstractButton * button ) { _moveToBottomButton = button; CONNECT_BUTTON( button, moveToBottom() ); } void ListEditor::setAddButton( QAbstractButton * button ) { _addButton = button; CONNECT_BUTTON( button, add() ); } void ListEditor::setRemoveButton( QAbstractButton * button ) { _removeButton = button; CONNECT_BUTTON( button, remove() ); } void ListEditor::moveUp() { QListWidgetItem * currentItem = _listWidget->currentItem(); int currentRow = _listWidget->currentRow(); if ( ! currentItem ) return; if ( currentRow > 0 ) { _updatesLocked = true; _listWidget->takeItem( currentRow ); _listWidget->insertItem( currentRow - 1, currentItem ); _listWidget->setCurrentItem( currentItem ); moveValue( value( currentItem ), "moveUp" ); _updatesLocked = false; } } void ListEditor::moveDown() { QListWidgetItem * currentItem = _listWidget->currentItem(); int currentRow = _listWidget->currentRow(); if ( ! currentItem ) return; if ( currentRow < _listWidget->count() - 1 ) { _updatesLocked = true; _listWidget->takeItem( currentRow ); _listWidget->insertItem( currentRow + 1, currentItem ); _listWidget->setCurrentItem( currentItem ); moveValue( value( currentItem ), "moveDown" ); _updatesLocked = false; } } void ListEditor::moveToTop() { QListWidgetItem * currentItem = _listWidget->currentItem(); int currentRow = _listWidget->currentRow(); if ( ! currentItem ) return; if ( currentRow > 0 ) { _updatesLocked = true; _listWidget->takeItem( currentRow ); _listWidget->insertItem( 0, currentItem ); _listWidget->setCurrentItem( currentItem ); moveValue( value( currentItem ), "moveToTop" ); _updatesLocked = false; } } void ListEditor::moveToBottom() { QListWidgetItem * currentItem = _listWidget->currentItem(); int currentRow = _listWidget->currentRow(); if ( ! currentItem ) return; if ( currentRow < _listWidget->count() - 1 ) { _updatesLocked = true; _listWidget->takeItem( currentRow ); _listWidget->addItem( currentItem ); _listWidget->setCurrentItem( currentItem ); moveValue( value( currentItem ), "moveToBottom" ); _updatesLocked = false; } } void ListEditor::add() { void * value = createValue(); CHECK_NEW( value ); ListEditorItem * item = new ListEditorItem( valueText( value ), value ); CHECK_NEW( item ); _listWidget->addItem( item ); _listWidget->setCurrentItem( item ); } void ListEditor::remove() { QListWidgetItem * currentItem = _listWidget->currentItem(); int currentRow = _listWidget->currentRow(); if ( ! currentItem ) return; void * value = this->value( currentItem ); // // Confirmation popup // QString msg = deleteConfirmationMessage( value ); if ( ! msg.isEmpty() ) { int ret = QMessageBox::question( window(), tr( "Please Confirm" ), // title msg ); if ( ret == QMessageBox::Yes ) { // // Delete current cleanup // _updatesLocked = true; _listWidget->takeItem( currentRow ); delete currentItem; removeValue( value ); _updatesLocked = false; load( this->value( _listWidget->currentItem() ) ); } } } void ListEditor::updateActions() { int currentRow = _listWidget->currentRow(); int lastRow = _listWidget->count() - 1; enableButton( _moveToTopButton, currentRow > _firstRow ); enableButton( _moveUpButton, currentRow > _firstRow ); enableButton( _moveDownButton, currentRow < lastRow ); enableButton( _moveToBottomButton, currentRow < lastRow ); } void ListEditor::currentItemChanged( QListWidgetItem * current, QListWidgetItem * previous) { save( value( previous ) ); load( value( current ) ); updateActions(); } void * ListEditor::value( QListWidgetItem * item ) { if ( ! item ) return 0; ListEditorItem * editorItem = dynamic_cast( item ); CHECK_DYNAMIC_CAST( editorItem, "ListEditorItem *" ); return editorItem->value(); } void ListEditor::enableButton( QAbstractButton * button, bool enabled ) { if ( button ) button->setEnabled( enabled ); } void ListEditor::moveValue( void * value, const char * operation ) { Q_UNUSED( value ); Q_UNUSED( operation ); } qdirstat-1.4/src/ListEditor.h000066400000000000000000000162721311502036700162410ustar00rootroot00000000000000/* * File name: ListEditor.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef ListEditor_h #define ListEditor_h #include #include class QAbstractButton; namespace QDirStat { /** * This is an abstract widget base class for config pages that have a list * of items on the left and details for one item (the current item) on the * right. * * This base class manages selecting an item in the list and displaying its * contents (load()), saving any user changes (save()), adding and removing * list items, and optionally moving the current item up, down, to the * top, and to the bottom of the list. * * This class does not own, create or destroy any widgets; it only uses * widgets that have been created elsewhere, typically via a Qt Designer * .ui file. The widgets should be set with any of the appropriate setter * methods. * * This class contains pure virtual methods; derived classes are required * to implement them. * * This class was first designed as a template class, but since even in * 2016 Qt's moc still cannot handle templates, ugly void * and nightmarish * type casts had to be used. This is due to deficiencies of the underlying * tools, not by design. Yes, this is ugly. But it's the best that can be * done with that moc preprocessor that dates back to 1995 or so. You'd * think that with C++11 and whatnot those limitations could be lifted, but * it doesn't look like anybody cares enough. **/ class ListEditor: public QWidget { Q_OBJECT public: /** * Constructor. **/ ListEditor( QWidget * parent ); /** * Destructor. **/ virtual ~ListEditor(); protected: // // Pure virtual methods that are required to be implemented by a // derived class // /** * Fill the list widget: Create a ListEditorItem for each value. * * Derived classes are required to implement this. **/ virtual void fillListWidget() = 0; /** * Save the contents of the widgets to the specified value. * * Derived classes are required to implement this. **/ virtual void save( void * value ) = 0; /** * Load the content of the widgets from the specified value. * * Derived classes are required to implement this. **/ virtual void load( void * value ) = 0; /** * Create a new Value_t item with default values and add it to the * internal list. * * This is called when the 'Add' button is clicked. * * Derived classes are required to implement this. **/ virtual void * createValue() = 0; /** * Remove a value from the internal list and delete it. * * This is called when the 'Remove' button is clicked and the user * confirms the confirmation pop-up. * * Derived classes are required to implement this. **/ virtual void removeValue( void * value ) = 0; /** * Return a text for the list item of 'value'. * * Derived classes are required to implement this. **/ virtual QString valueText( void * value ) = 0; /** * Return the message for the 'really delete?' message for the current * item ('value'). If this returns an empty string, the item cannot be * deleted. * * Derived classes are required to implement this. **/ virtual QString deleteConfirmationMessage( void * value ) = 0; /** * Move a value in the internal list. This is called from moveUp(), * moveDown() etc.; 'operation' is one of 'moveUp()', moveDown() * etc. that can be called with QMetaObject::invokeMethod(). * * Derived classes that should implement this if the move operations * are to be supported. They should cast 'value' to the proper type and * pass it to the operation that is invoked. * * This is a kludge - a workaround of not being able to use C++ * templates. **/ virtual void moveValue( void * value, const char * operation ); //-------------------------------------------------------------------- public: /** * Set the QListWidget to work on. **/ void setListWidget( QListWidget * listWidget ); /** * Return the QListWidget. **/ QListWidget * listWidget() const { return _listWidget; } /** * Return 'true' if updates are currently locked. save() and load() * should check this and do nothing if updates are locked. **/ bool updatesLocked() const { return _updatesLocked; } /** * Lock or unlock updates. **/ void setUpdatesLocked( bool locked ) { _updatesLocked = locked; } /** * Return the first row for moveUp() and moveToTop(). Normally this is * row 0, but this can be set to another value to freeze the rows * before this logical first row. **/ int firstRow() const { return _firstRow; } /** * Set the first row for moveUp() and moveToTop(). **/ void setFirstRow( int newFirstRow ) { _firstRow = newFirstRow; } // // Set the various buttons and connect them to the appropriate slot. // void setMoveUpButton ( QAbstractButton * button ); void setMoveDownButton ( QAbstractButton * button ); void setMoveToTopButton ( QAbstractButton * button ); void setMoveToBottomButton( QAbstractButton * button ); void setAddButton ( QAbstractButton * button ); void setRemoveButton ( QAbstractButton * button ); public slots: /** * Move the current list item one position up. **/ void moveUp(); /** * Move the current list item one position down. **/ void moveDown(); /** * Move the current list item to the top of the list. **/ void moveToTop(); /** * Move the current list item to the bottom of the list. **/ void moveToBottom(); /** * Create a new list item. **/ void add(); /** * Remove the current list item. **/ void remove(); protected slots: /** * Enable or disable buttons depending on internal status. **/ virtual void updateActions(); /** * Notification that the current item in the list widget changed. **/ virtual void currentItemChanged( QListWidgetItem * current, QListWidgetItem * previous); protected: /** * Convert 'item' to a ListEditorItem and return its value. **/ void * value( QListWidgetItem * item ); /** * Enable or disable a button if it is non-null. **/ void enableButton( QAbstractButton * button, bool enabled ); private: // // Data members // QListWidget * _listWidget; int _firstRow; bool _updatesLocked; QAbstractButton * _moveUpButton; QAbstractButton * _moveDownButton; QAbstractButton * _moveToTopButton; QAbstractButton * _moveToBottomButton; QAbstractButton * _addButton; QAbstractButton * _removeButton; }; // class ListEditor /** * Item class for the QListWidget in a ListEditor. This connects the * QListWidgetItem with the void * pointer. **/ class ListEditorItem: public QListWidgetItem { public: /** * Create a new item with the specified text and store the value. **/ ListEditorItem( const QString & text, void * value ): QListWidgetItem( text ), _value( value ) {} /** * Return the associated value. **/ void * value() const { return _value; } protected: void * _value; }; } // namespace QDirStat #endif // ListEditor_h qdirstat-1.4/src/ListMover.h000066400000000000000000000030561311502036700160770ustar00rootroot00000000000000#ifndef ListMover_h #define ListMover_h namespace QDirStat { /** * Template class to move items in a QList up, down, to the top, * or to the bottom. **/ template class ListMover { public: ListMover( QList & list ): _list( list ) {} void moveUp( Value_t item ) { int oldPos = _list.indexOf( item ); if ( oldPos > 0 ) { _list.removeAt( oldPos ); _list.insert( oldPos - 1, item ); } } void moveDown( Value_t item ) { int oldPos = _list.indexOf( item ); if ( oldPos < _list.size() - 1 ) { _list.removeAt( oldPos ); _list.insert( oldPos + 1, item ); } } void moveToTop( Value_t item ) { int oldPos = _list.indexOf( item ); if ( oldPos > 0 ) { _list.removeAt( oldPos ); _list.insert( 0, item ); } } void moveToBottom( Value_t item ) { int oldPos = _list.indexOf( item ); if ( oldPos < _list.size() - 1 ) { _list.removeAt( oldPos ); _list.insert( _list.size(), item ); } } protected: QList & _list; }; typedef ListMover PtrListMover; } // namespace QDirStat #endif // ListMover_h qdirstat-1.4/src/LocateFilesWindow.cpp000066400000000000000000000165121311502036700200710ustar00rootroot00000000000000/* * File name: LocateFilesWindow.cpp * Summary: QDirStat file type statistics window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "LocateFilesWindow.h" #include "DirTree.h" #include "SelectionModel.h" #include "FileInfoIterator.h" #include "SettingsHelpers.h" #include "HeaderTweaker.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; LocateFilesWindow::LocateFilesWindow( SelectionModel * selectionModel, QWidget * parent ): QDialog( parent ), _ui( new Ui::LocateFilesWindow ), _selectionModel( selectionModel ) { // logDebug() << "init" << endl; CHECK_NEW( _ui ); _ui->setupUi( this ); initWidgets(); readWindowSettings( this, "LocateFilesWindow" ); connect( _ui->refreshButton, SIGNAL( clicked() ), this, SLOT ( refresh() ) ); connect( _ui->treeWidget, SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ), this, SLOT ( selectResult ( QTreeWidgetItem * ) ) ); } LocateFilesWindow::~LocateFilesWindow() { // logDebug() << "destroying" << endl; writeWindowSettings( this, "LocateFilesWindow" ); } void LocateFilesWindow::clear() { _searchSuffix.clear(); _ui->treeWidget->clear(); } void LocateFilesWindow::refresh() { populate( searchSuffix(), _subtree() ); } void LocateFilesWindow::initWidgets() { QFont font = _ui->heading->font(); font.setBold( true ); _ui->heading->setFont( font ); _ui->treeWidget->setColumnCount( SSR_ColumnCount ); _ui->treeWidget->setHeaderLabels( QStringList() << tr( "Number" ) << tr( "Total Size" ) << tr( "Directory" ) ); _ui->treeWidget->header()->setStretchLastSection( false ); HeaderTweaker::resizeToContents( _ui->treeWidget->header() ); } void LocateFilesWindow::reject() { deleteLater(); } QString LocateFilesWindow::searchSuffix() const { return QString( "*" ) + _searchSuffix; } void LocateFilesWindow::populate( const QString & suffix, FileInfo * newSubtree ) { clear(); _searchSuffix = suffix; _subtree = newSubtree; if ( _searchSuffix.startsWith( '*' ) ) _searchSuffix.remove( 0, 1 ); // Remove the leading '*' if ( ! _searchSuffix.startsWith( '.' ) ) _searchSuffix.prepend( '.' ); _ui->heading->setText( tr( "Directories with %1 Files below %2" ) .arg( searchSuffix() ) .arg( _subtree.url() ) ); logDebug() << "Locating all files ending with \"" << _searchSuffix << "\" below " << _subtree.url() << endl; // For better Performance: Disable sorting while inserting many items _ui->treeWidget->setSortingEnabled( false ); locate( newSubtree ? newSubtree : _subtree() ); _ui->treeWidget->setSortingEnabled( true ); _ui->treeWidget->sortByColumn( SSR_PathCol, Qt::AscendingOrder ); logDebug() << _ui->treeWidget->topLevelItemCount() << " directories" << endl; // Make sure something is selected, even if this window is not the active // one (for example because the user just clicked on another suffix in the // file type stats window). When the window is activated, the tree widget // automatically uses the topmost item as the current item, and in the // default selection mode, this item is also selected. When the window is // not active, this does not happen yet - until the window is activated. // // In the context of QDirStat, this means that this is also signaled to the // SelectionModel, the corresponding branch in the main window's dir tree // is opened, and the matching files are selected in the dir tree and in // the treemap. // // It is very irritating if this only happens sometimes - when the "locate // files" window is created, but not when it is just populated with new // content from the outside (from the file type stats window). // // So let's make sure the topmost item is always selected. _ui->treeWidget->setCurrentItem( _ui->treeWidget->topLevelItem( 0 ) ); } void LocateFilesWindow::locate( FileInfo * dir ) { if ( ! dir ) return; FileInfoSet matches = matchingFiles( dir ); if ( ! matches.isEmpty() ) { // Create a search result for this path FileSize totalSize = 0LL; foreach ( FileInfo * file, matches ) totalSize += file->size(); SuffixSearchResultItem * searchResultItem = new SuffixSearchResultItem( dir->url(), matches.size(), totalSize ); CHECK_NEW( searchResultItem ); _ui->treeWidget->addTopLevelItem( searchResultItem ); } // Recurse through any subdirectories FileInfo* child = dir->firstChild(); while ( child ) { if ( child->isDir() ) locate( child ); child = child->next(); } // Notice that unlike in FileTypeStats, there is no need to recurse through // any dot entries: They are handled in matchingFiles() already. } FileInfoSet LocateFilesWindow::matchingFiles( FileInfo * item ) { FileInfoSet result; if ( ! item || ! item->isDirInfo() ) return result; DirInfo * dir = item->toDirInfo(); if ( dir->dotEntry() ) dir = dir->dotEntry(); FileInfo * child = dir->firstChild(); while ( child ) { if ( child->isFile() && child->name().endsWith( _searchSuffix, Qt::CaseInsensitive ) ) { result << child; } child = child->next(); } return result; } void LocateFilesWindow::selectResult( QTreeWidgetItem * item ) { if ( ! item ) return; SuffixSearchResultItem * searchResult = dynamic_cast( item ); CHECK_DYNAMIC_CAST( searchResult, "SuffixSearchResultItem" ); CHECK_PTR( _subtree.tree() ); FileInfo * dir = _subtree.tree()->locate( searchResult->path() ); FileInfoSet matches = matchingFiles( dir ); // logDebug() << "Selecting " << searchResult->path() << " with " << matches.size() << " matches" << endl; if ( ! matches.isEmpty() ) _selectionModel->setCurrentItem( matches.first(), true ); _selectionModel->setSelectedItems( matches ); } SuffixSearchResultItem::SuffixSearchResultItem( const QString & path, int count, FileSize totalSize ): QTreeWidgetItem( QTreeWidgetItem::UserType ), _path( path ), _count( count ), _totalSize( totalSize ) { setText( SSR_CountCol, QString( "%1" ).arg( count ) ); setText( SSR_TotalSizeCol, formatSize( totalSize ) ); setText( SSR_PathCol, path ); setTextAlignment( SSR_CountCol, Qt::AlignRight ); setTextAlignment( SSR_TotalSizeCol, Qt::AlignRight ); setTextAlignment( SSR_PathCol, Qt::AlignLeft ); } bool SuffixSearchResultItem::operator<(const QTreeWidgetItem & rawOther) const { // Since this is a reference, the dynamic_cast will throw a std::bad_cast // exception if it fails. Not catching this here since this is a genuine // error which should not be silently ignored. const SuffixSearchResultItem & other = dynamic_cast( rawOther ); int col = treeWidget() ? treeWidget()->sortColumn() : SSR_PathCol; switch ( col ) { case SSR_PathCol: return path() < other.path(); case SSR_CountCol: return count() < other.count(); case SSR_TotalSizeCol: return totalSize() < other.totalSize(); default: return QTreeWidgetItem::operator<( rawOther ); } } qdirstat-1.4/src/LocateFilesWindow.h000066400000000000000000000122321311502036700175310ustar00rootroot00000000000000/* * File name: LocateFilesWindow.h * Summary: QDirStat "locate files" window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef LocateFilesWindow_h #define LocateFilesWindow_h #include #include #include "ui_locate-files-window.h" #include "FileInfo.h" #include "FileInfoSet.h" #include "Subtree.h" namespace QDirStat { class DirTree; class FileTypeStats; class MimeCategory; class SelectionModel; /** * Modeless dialog to display search results after clicking "locate" in the * file type stats window. * * This window shows a directory entry for each directory that contains * files of the requested type (with the requested suffix). When the user * clicks on a search result, that directory is opened in the QDirStat main * window's tree view (and all other open branches of the tree are closed), * and the matching files in that directory are selected. * * As a next step, the user can then start cleanup actions on those files * from the main window - in the tree view or in the treemap view. **/ class LocateFilesWindow: public QDialog { Q_OBJECT public: /** * Constructor. * * Notice that this widget will destroy itself upon window close. * * It is advised to use a QPointer for storing a pointer to an instance * of this class. The QPointer will keep track of this window * auto-deleting itself when closed. **/ LocateFilesWindow( SelectionModel * selectionModel, QWidget * parent ); /** * Destructor. **/ virtual ~LocateFilesWindow(); public: /** * Obtain the subtree from the last used URL or 0 if none was found. **/ const Subtree & subtree() const { return _subtree; } /** * Return the current search suffix (with leading '*.') **/ QString searchSuffix() const; public slots: /** * Populate the window: Locate files with 'suffix' in 'subtree'. * * This clears the old search results first, then searches the subtree * and populates the search result list with the directories where * matching files were found. **/ void populate( const QString & suffix, FileInfo * subtree = 0 ); /** * Refresh (reload) all data. **/ void refresh(); /** * Reject the dialog contents, i.e. the user clicked the "Cancel" or * WM_CLOSE button. This not only closes the dialog, it also deletes * it. * * Reimplemented from QDialog. **/ virtual void reject() Q_DECL_OVERRIDE; protected slots: /** * Select one of the search results in the main window's tree and * treemap widgets via their SelectionModel. **/ void selectResult( QTreeWidgetItem * item ); protected: /** * Clear all data and widget contents. **/ void clear(); /** * One-time initialization of the widgets in this window. **/ void initWidgets(); /** * Recursively locate directories that contain files matching the * search suffix and create a search result item for each one. **/ void locate( FileInfo * dir ); /** * Return all direct file children matching the current search suffix. **/ FileInfoSet matchingFiles( FileInfo * dir ); // // Data members // Ui::LocateFilesWindow * _ui; Subtree _subtree; QString _searchSuffix; SelectionModel * _selectionModel; }; /** * Column numbers for the file type tree widget **/ enum SuffixSearchResultColumns { SSR_CountCol = 0, SSR_TotalSizeCol, SSR_PathCol, SSR_ColumnCount }; /** * Item class for the locate list (which is really a tree widget), * representing one directory that contains files with the desired suffix. * * Notice that this item intentionally does not store a FileInfo or DirInfo * pointer for each search result, but its path. This is more expensive to * store, and the corresponding DirInfo * has to be fetched again with * DirTree::locate() (which is an expensive operation), but it is a lot * safer in case the tree is modified, i.e. if the user starts cleanup * operations or refreshes the tree from disk: Not only are no pointers * stored that might become invalid, but the search result remains valid * even after such an operation since the strings (the paths) will still * match an object in the tree in most cases. * * In the worst case, the search result won't find the corresponding * DirInfo * anymore (if that directory branch was deleted), but for sure * it will not crash. **/ class SuffixSearchResultItem: public QTreeWidgetItem { public: /** * Constructor. **/ SuffixSearchResultItem( const QString & path, int count, FileSize totalSize ); // // Getters // QString path() const { return _path; } int count() const { return _count; } FileSize totalSize() const { return _totalSize; } /** * Less-than operator for sorting. **/ virtual bool operator<(const QTreeWidgetItem & other) const Q_DECL_OVERRIDE; protected: QString _path; int _count; FileSize _totalSize; }; } // namespace QDirStat #endif // LocateFilesWindow_h qdirstat-1.4/src/Logger.cpp000066400000000000000000000304441311502036700157260ustar00rootroot00000000000000/* * File name: Logger.cpp * Summary: Logger class for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #define DONT_DEPRECATE_STRERROR #include "Logger.h" #include #include #include #include #include #include #include #include #include #include // stderr, fprintf() #include // abort(), mkdtemp() #include // getpid() #include #include // getpwuid() #include // pid_t, getpwuid() #define VERBOSE_ROTATE 0 static LogSeverity toLogSeverity( QtMsgType msgType ); #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) static void qt_logger( QtMsgType msgType, const char *msg); #else static void qt_logger( QtMsgType msgType, const QMessageLogContext & context, const QString & msg ); #endif Logger * Logger::_defaultLogger = 0; Logger::Logger( const QString &filename ): _logStream( stderr, QIODevice::WriteOnly ), _nullStream( stderr, QIODevice::WriteOnly ) { init(); createNullStream(); openLogFile( filename ); } Logger::Logger( const QString & rawLogDir, const QString & rawFilename, bool doRotate, int logRotateCount ): _logStream( stderr, QIODevice::WriteOnly ), _nullStream( stderr, QIODevice::WriteOnly ) { init(); createNullStream(); QString logDir = expandVariables( rawLogDir ); QString filename = expandVariables( rawFilename ); logDir = createLogDir( logDir ); if ( doRotate ) logRotate( logDir, filename, logRotateCount ); openLogFile( logDir + "/" + filename ); } Logger::~Logger() { if ( _logFile.isOpen() ) { logInfo() << "-- Log End --\n" << endl; _logFile.close(); } if ( this == _defaultLogger ) { _defaultLogger = 0; #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) qInstallMsgHandler(0); #else qInstallMessageHandler(0); // Restore default message handler #endif } } void Logger::init() { _logLevel = LogSeverityVerbose; _nullDevice.setFileName( "/dev/null" ); } void Logger::createNullStream() { // Open the null device to suppress output below the log level: This is // necessary because each call to operator<<() for QTextStream returns the // QTextStream, so we really need to return _nullStream (connected with // /dev/null) to actually suppress anything; otherwise, it's just the // logger time stamp etc. that gets suppressed, not the real logging // output. if ( _nullDevice.open( QIODevice::WriteOnly | QIODevice::Text ) ) { _nullStream.setDevice( &_nullDevice ); } else { fprintf( stderr, "ERROR: Can't open /dev/null to suppress log output\n" ); } } void Logger::openLogFile( const QString & filename ) { if ( ! _logFile.isOpen() || _logFile.fileName() != filename ) { _logFile.setFileName( filename ); if ( _logFile.open( QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append ) ) { if ( ! _defaultLogger ) setDefaultLogger(); fprintf( stderr, "Logging to %s\n", qPrintable( filename ) ); _logStream.setDevice( &_logFile ); _logStream << "\n\n"; log( __FILE__, __LINE__, __FUNCTION__, LogSeverityInfo ) << "-- Log Start --" << endl; } else { fprintf( stderr, "ERROR: Can't open log file %s\n", qPrintable( filename ) ); } } } void Logger::setDefaultLogger() { _defaultLogger = this; #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) qInstallMsgHandler( qt_logger ); #else qInstallMessageHandler( qt_logger ); #endif } QTextStream & Logger::log( Logger * logger, const QString &srcFile, int srcLine, const QString &srcFunction, LogSeverity severity ) { static QTextStream stderrStream( stderr, QIODevice::WriteOnly ); if ( ! logger ) logger = Logger::defaultLogger(); if ( logger ) return logger->log( srcFile, srcLine, srcFunction, severity ); else return stderrStream; } QTextStream & Logger::log( const QString &srcFile, int srcLine, const QString &srcFunction, LogSeverity severity ) { if ( severity < _logLevel ) return _nullStream; QString sev; switch ( severity ) { case LogSeverityVerbose: sev = ""; break; case LogSeverityDebug: sev = " "; break; case LogSeverityInfo: sev = " "; break; case LogSeverityWarning: sev = ""; break; case LogSeverityError: sev = " "; break; // Intentionally omitting 'default' branch so the compiler can // complain about unhandled enum values } _logStream << Logger::timeStamp() << " " << "[" << (int) getpid() << "] " << sev << " "; if ( ! srcFile.isEmpty() ) { _logStream << srcFile; if ( srcLine > 0 ) _logStream << ":" << srcLine; _logStream << " "; if ( ! srcFunction.isEmpty() ) _logStream << srcFunction << "(): "; } return _logStream; } void Logger::newline( Logger *logger ) { if ( ! logger ) logger = Logger::defaultLogger(); if ( logger ) logger->newline(); } LogSeverity Logger::logLevel( Logger *logger ) { if ( ! logger ) logger = Logger::defaultLogger(); if ( logger ) return logger->logLevel(); else return LogSeverityVerbose; } void Logger::setLogLevel( Logger *logger, LogSeverity newLevel ) { if ( ! logger ) logger = Logger::defaultLogger(); if ( logger ) logger->setLogLevel( newLevel ); } void Logger::newline() { _logStream << endl; } QString Logger::timeStamp() { return QDateTime::currentDateTime().toString( "yyyy-MM-dd hh:mm:ss.zzz" ); } QString Logger::prefixLines( const QString &prefix, const QString &multiLineText ) { QStringList lines = multiLineText.split( "\n" ); QString result = lines.isEmpty() ? QString() : prefix; result += lines.join( QString( "\n" ) + prefix ); return result; } QString Logger::indentLines( int indentWidth, const QString &multiLineText ) { QString prefix( indentWidth, ' ' ); return prefixLines( prefix, multiLineText ); } static LogSeverity toLogSeverity( QtMsgType msgType ) { LogSeverity severity = LogSeverityVerbose; switch ( msgType ) { case QtDebugMsg: severity = LogSeverityVerbose; break; case QtWarningMsg: severity = LogSeverityWarning; break; case QtCriticalMsg: severity = LogSeverityError; break; case QtFatalMsg: severity = LogSeverityError; break; #if QT_VERSION >= 0x050500 case QtInfoMsg: severity = LogSeverityInfo; break; #endif } return severity; } #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) // Qt 4.x static void qt_logger( QtMsgType msgType, const char *msg) { Logger::log( 0, // use default logger "[Qt]", 0, "", // file, line, function toLogSeverity( msgType ) ) << msg << endl; if ( msgType == QtFatalMsg ) { fprintf( stderr, "FATAL: %s\n", qPrintable( msg ) ); abort(); } if ( msgType == QtWarningMsg && QString( msg ).contains( "cannot connect to X server" ) ) { fprintf( stderr, "FATAL: %s\n", qPrintable( msg ) ); exit( 1 ); } } #else // Qt 5.x static void qt_logger( QtMsgType msgType, const QMessageLogContext & context, const QString & msg ) { Logger::log( 0, // use default logger context.file, context.line, context.function, toLogSeverity( msgType ) ) << msg << endl; if ( msgType == QtFatalMsg ) { fprintf( stderr, "FATAL: %s\n", qPrintable( msg ) ); if ( msg.contains( "Could not connect to display" ) ) exit( 1 ); else abort(); } } #endif // Qt 5.x QString Logger::userName() { // Not using getuid() because that function relies on the user owning the // controlling terminal which is wrong in many aspects: // // - There might not be a controlling terminal at all. // - The user owning the controlling terminal may or may not be the one // starting this program. struct passwd * pw = getpwuid( getuid() ); if ( pw ) return pw->pw_name; else return QString::number( getuid() ); } QString Logger::createLogDir( const QString & rawLogDir ) { QString logDir( rawLogDir ); QDir rootDir( "/" ); bool created = false; if ( ! rootDir.exists( logDir ) ) { rootDir.mkpath( logDir ); created = true; } QFileInfo dirInfo( logDir ); if ( (uid_t) dirInfo.ownerId() != getuid() ) { logError() << "ERROR: Directory " << logDir << " is not owned by " << userName() << endl; QByteArray nameTemplate( QString( logDir + "-XXXXXX" ).toUtf8() ); char * result = mkdtemp( nameTemplate.data() ); if ( result ) { created = true; logDir = QString::fromUtf8( result ); } else { logError() << "Could not create log dir " << nameTemplate << ": " << formatErrno() << endl; logDir = "/"; // No permissions to write to /, // i.e. the log will go to stderr instead } } if ( created ) { QFile dir( logDir ); dir.setPermissions( QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner ); } return logDir; } QString Logger::oldName( const QString & filename, int no ) { QString oldName = filename; if ( oldName.endsWith( ".log" ) ) oldName.remove( QRegExp( "\\.log$" ) ); oldName += QString( "-%1.old" ).arg( no, 2, 10, QChar( '0' ) ); return oldName; } QString Logger::oldNamePattern( const QString & filename ) { QString pattern = filename; if ( pattern.endsWith( ".log" ) ) pattern.remove( QRegExp( "\\.log$" ) ); pattern += "-??.old"; return pattern; } void Logger::logRotate( const QString & logDir, const QString & filename, int logRotateCount ) { QDir dir( logDir ); QStringList keepers; keepers << filename; for ( int i = logRotateCount - 1; i >= 0; --i ) { QString currentName = i > 0 ? oldName( filename, i-1 ) : filename; QString newName = oldName( filename, i ); if ( dir.exists( newName ) ) { bool success = dir.remove( newName ); #if VERBOSE_ROTATE logDebug() << "Removing " << newName << ( success ? "" : " FAILED" ) << endl; #else Q_UNUSED( success ); #endif } if ( dir.exists( currentName ) ) { bool success = dir.rename( currentName, newName ); #if VERBOSE_ROTATE logDebug() << "Renaming " << currentName << " to " << newName << ( success ? "" : " FAILED" ) << endl; #else Q_UNUSED( success ); #endif keepers << newName; } } QStringList matches = dir.entryList( QStringList() << oldNamePattern( filename ), QDir::Files ); foreach ( const QString & match, matches ) { if ( ! keepers.contains( match ) ) { bool success = dir.remove( match ); #if VERBOSE_ROTATE logDebug() << "Removing leftover " << match << ( success ? "" : " FAILED" ) << endl; #else Q_UNUSED( success ); #endif } } } QString Logger::expandVariables( const QString & unexpanded ) { QString expanded = unexpanded; expanded.replace( "$USER", userName() ); expanded.replace( "$UID" , QString::number( getuid() ) ); return expanded; } QTextStream & operator<<( QTextStream & str, bool val ) { str << ( val ? "true" : "false" ); return str; } QTextStream & operator<<( QTextStream & str, const QStringList &stringList ) { str << stringList.join( ", " ); return str; } QTextStream & operator<<( QTextStream & str, const QRectF & rect ) { str << "QRectF(" << " x: " << rect.x() << " y: " << rect.y() << " width: " << rect.width() << " height: " << rect.height() << " )"; return str; } QTextStream & operator<<( QTextStream & str, const QPointF & point ) { str << "QPointF(" << " x: " << point.x() << " y: " << point.y() << " )"; return str; } QTextStream & operator<<( QTextStream & str, const QSizeF & size ) { str << "QSizeF(" << " width: " << size.width() << " height: " << size.height() << " )"; return str; } QTextStream & operator<<( QTextStream & str, const QSize & size ) { str << "QSize(" << " width: " << size.width() << " height: " << size.height() << " )"; return str; } // Un-deprecate strerror() just for this one call. #ifdef strerror # undef strerror #endif QString formatErrno() { return QString::fromUtf8( strerror( errno ) ); } qdirstat-1.4/src/Logger.h000066400000000000000000000221321311502036700153660ustar00rootroot00000000000000/* * File name: Logger.h * Summary: Logger class for QDirstat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Logger_h #define Logger_h #include #include #include #include // Intentionally not using LogDebug, LogMilestone etc. to avoid confusion // because of simple typos: logDebug() vs. LogDebug() // // ...well knowing that C++ compilers will throw all kinds of crazy and // impossible to understand error messages if somebody confuses very different // types like a function (logDebug()) vs. an enum value. enum LogSeverity { LogSeverityVerbose, LogSeverityDebug, LogSeverityInfo, LogSeverityWarning, LogSeverityError }; // Log macros for stream (QTextStream) output. // // Unlike qDebug() etc., they also record the location in the source code that // wrote the log entry. // // These macros all use the default logger. Create similar macros to use your // own class-specific logger. #define logVerbose() Logger::log( 0, __FILE__, __LINE__, __FUNCTION__, LogSeverityVerbose ) #define logDebug() Logger::log( 0, __FILE__, __LINE__, __FUNCTION__, LogSeverityDebug ) #define logInfo() Logger::log( 0, __FILE__, __LINE__, __FUNCTION__, LogSeverityInfo ) #define logWarning() Logger::log( 0, __FILE__, __LINE__, __FUNCTION__, LogSeverityWarning ) #define logError() Logger::log( 0, __FILE__, __LINE__, __FUNCTION__, LogSeverityError ) #define logNewline() Logger::newline( 0 ) /** * Logging class. Use one of the macros above for stream output: * * logDebug() << "Debug logging demo " << myString << ": " << 42 << endl; * logError() << "Can't open file " << filename << ": " << errno << endl; * * Remember to terminate each log line with 'endl'. * Unlike qDebug() etc., this class does NOT add spaces or quotes. * There are overloads for most common types (QString, const char *, * QByteArray, int). * * This class also redirects Qt logging (qDebug() etc.) to the same log file. */ class Logger { public: /** * Constructor: Create a logger that logs to the specified file. * The first logger created is also implicitly used as the default * logger. This can be changed later with setDefaultLogger(). */ Logger( const QString & filename ); /** * Constructor: Create a logger that logs to 'filename' in directory * 'logDir'. $USER and $UID are expanded in both to the login user name or * the numeric user ID, respectively. * * If 'doRotate' is 'true, rotate any old logs in that directory * before opening the log and keep a maximum of 'logRotateCount' old logs * in that directory. * * The first logger created is also implicitly used as the default * logger. This can be changed later with setDefaultLogger(). **/ Logger( const QString & logDir, const QString & filename, bool doRotate = true, int logRotateCount = 3 ); /** * Destructor. */ ~Logger(); /** * Internal logging function. In most cases, better use the logDebug(), * logWarning() etc. macros instead. */ QTextStream & log( const QString & srcFile, int srcLine, const QString & srcFunction, LogSeverity severity ); /** * Static version of the internal logging function. * Use the logDebug(), logWarning() etc. macros instead. * * If 'logger' is 0, the default logger is used. */ static QTextStream & log( Logger * logger, const QString & srcFile, int srcLine, const QString & srcFunction, LogSeverity severity ); /** * Log a plain newline without any prefix (timestamp, source file name, * line number). */ void newline(); static void newline( Logger * logger ); /** * Return a timestamp string in the format used in the log file: * "yyyy-MM-dd hh:mm:ss.zzz" */ static QString timeStamp(); /** * Prefix each line of a multi-line text with 'prefix'. */ static QString prefixLines( const QString & prefix, const QString & multiLineText ); /** * Indent each line of a multi-line text with 'indentWith' blanks. */ static QString indentLines( int indentWidth, const QString & multiLineText ); /** * Set this as the default logger. That one will be used whenever log() is * called with a 0 'logger' argument. * * The first logger created will implicitly be the default logger until * another one is set with setDefaultLogger. */ void setDefaultLogger(); /** * Return the default logger. * * If no default logger is explicitly set, this is the first logger that * was created. */ static Logger * defaultLogger() { return _defaultLogger; } /** * Return the QTextStream associated with this logger. Not for general use. */ QTextStream & logStream() { return _logStream; } /** * Return the current log level, i.e. the severity that will actually be * logged. Any lower severity will be suppressed. * * Notice that due to the way C++ evaluates expressions, the runtime cost * will not change significantly, only the log file size: * * logDebug() << "Result: " << myObj->result() << endl; * * Even if the log level is higher than logDebug(), this will still call * myObj->result() and its operator<<(). If you want to avoid that, use * your own 'if' around the log output: * * if ( logLevel() >= LogSeverityDebug ) * logDebug() ... */ LogSeverity logLevel() const { return _logLevel; } /** * Set the log level. */ void setLogLevel( LogSeverity newLevel ) { _logLevel = newLevel; } /** * Return the log level of the specified logger. * * If 'logger' is 0, the default logger is used. */ static LogSeverity logLevel( Logger *logger ); /** * Set the log level of the specified logger. * * If 'logger' is 0, the default logger is used. */ static void setLogLevel( Logger *logger, LogSeverity newLevel ); /** * Return the user name (the login name) of the user owning this process. * If that information cannot be obtained, this returns the UID as string. **/ static QString userName(); /** * Rotate the logs in directory 'logDir' based on future log file * 'filename' (without path). Keep at most 'logRotateCount' old logs and * delete all other old logs. **/ static void logRotate( const QString & logDir, const QString & filename, int logRotateCount ); protected: /** * Common initialization for all constructors. **/ void init(); /** * Create the null log stream to suppress messages below the current log * level. **/ void createNullStream(); /** * Actually open the log file. **/ void openLogFile( const QString & filename ); /** * Create log directory 'logDir' and return the name of the directory * actually used. That might be different from the requested name if the * directory already exists and is not owned by the current user. **/ QString createLogDir( const QString & logDir ); /** * Expand variables in 'unexpanded' and return the expanded string: * * $USER the login user name of the current user * $UID the numeric user ID of the current user **/ static QString expandVariables( const QString & unexpanded ); /** * Return the name for an old log file based on 'filename' for old log * no. 'no'. **/ static QString oldName( const QString & filename, int no ); /** * Return the glob pattern for old log files based on 'filename'. * This pattern can be used for QDir matches. **/ static QString oldNamePattern( const QString & filename ); private: static Logger * _defaultLogger; QFile _logFile; QTextStream _logStream; QFile _nullDevice; QTextStream _nullStream; LogSeverity _logLevel; }; QTextStream & operator<<( QTextStream & str, bool val ); QTextStream & operator<<( QTextStream & str, const QStringList &stringList ); QTextStream & operator<<( QTextStream & str, const QSizeF & size ); QTextStream & operator<<( QTextStream & str, const QRectF & rect ); QTextStream & operator<<( QTextStream & str, const QPointF & point ); QTextStream & operator<<( QTextStream & str, const QSize & size ); /** * Format errno as a QString. * This is a replacement for strerror() that handles UTF-8 well: * In Qt 5.x, const char * is automatically converted to UTF-8 for QString. * In Qt 4.x, however, it uses simply fromAscii() which is almost never correct. **/ QString formatErrno(); #ifndef DONT_DEPRECATE_STRERROR // Use formatErrno() instead which deals with UTF-8 issues char * strerror(int) __attribute__ ((deprecated)); #endif #endif // Logger_h qdirstat-1.4/src/MainWindow.cpp000066400000000000000000000634441311502036700165710ustar00rootroot00000000000000/* * File name: MainWindow.cpp * Summary: QDirStat main window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include #include #include #include "MainWindow.h" #include "ActionManager.h" #include "CleanupCollection.h" #include "CleanupConfigPage.h" #include "ConfigDialog.h" #include "DataColumns.h" #include "DebugHelpers.h" #include "DirTree.h" #include "DirTreeCache.h" #include "DirTreeModel.h" #include "Exception.h" #include "ExcludeRules.h" #include "FileInfo.h" #include "FileSizeStatsWindow.h" #include "Logger.h" #include "MimeCategorizer.h" #include "MimeCategoryConfigPage.h" #include "OutputWindow.h" #include "Refresher.h" #include "SelectionModel.h" #include "Settings.h" #include "SettingsHelpers.h" #include "Trash.h" #include "Version.h" using namespace QDirStat; using QDirStat::DataColumns; using QDirStat::DirTreeModel; using QDirStat::SelectionModel; using QDirStat::CleanupCollection; MainWindow::MainWindow(): QMainWindow(), _ui( new Ui::MainWindow ), _configDialog(0), _modified( false ), _verboseSelection( false ), _statusBarTimeout( 3000 ), // millisec _treeLevelMapper(0) { CHECK_PTR( _ui ); _ui->setupUi( this ); ActionManager::instance()->addWidgetTree( this ); readSettings(); _dirTreeModel = new DirTreeModel( this ); CHECK_NEW( _dirTreeModel ); _selectionModel = new SelectionModel( _dirTreeModel, this ); CHECK_NEW( _selectionModel ); _ui->dirTreeView->setModel( _dirTreeModel ); _ui->dirTreeView->setSelectionModel( _selectionModel ); _ui->treemapView->setDirTree( _dirTreeModel->tree() ); _ui->treemapView->setSelectionModel( _selectionModel ); _dirTreeModel->setSelectionModel( _selectionModel ); _cleanupCollection = new CleanupCollection( _selectionModel ); CHECK_NEW( _cleanupCollection ); _cleanupCollection->addToMenu ( _ui->menuCleanup, true ); // keepUpdated _cleanupCollection->addToToolBar( _ui->toolBar, true ); // keepUpdated _ui->dirTreeView->setCleanupCollection( _cleanupCollection ); _ui->treemapView->setCleanupCollection( _cleanupCollection ); _mimeCategorizer = new MimeCategorizer(); CHECK_NEW( _mimeCategorizer ); _ui->treemapView->setMimeCategorizer( _mimeCategorizer ); #ifdef Q_OS_MACX // this makes the application to look like more "native" on macOS setUnifiedTitleAndToolBarOnMac(true); _ui->toolBar->setMovable(false); #endif connect( _selectionModel, SIGNAL( currentBranchChanged( QModelIndex ) ), _ui->dirTreeView, SLOT ( closeAllExcept ( QModelIndex ) ) ); connect( _dirTreeModel->tree(), SIGNAL( startingReading() ), this, SLOT ( startingReading() ) ); connect( _dirTreeModel->tree(), SIGNAL( finished() ), this, SLOT ( readingFinished() ) ); connect( _dirTreeModel->tree(), SIGNAL( aborted() ), this, SLOT ( readingAborted() ) ); connect( _selectionModel, SIGNAL( selectionChanged() ), this, SLOT ( updateActions() ) ); connect( _selectionModel, SIGNAL( currentItemChanged( FileInfo *, FileInfo * ) ), this, SLOT ( updateActions() ) ); connect( _ui->treemapView, SIGNAL( treemapChanged() ), this, SLOT ( updateActions() ) ); connect( _cleanupCollection, SIGNAL( startingCleanup( QString ) ), this, SLOT ( startingCleanup( QString ) ) ); connect( _cleanupCollection, SIGNAL( cleanupFinished( int ) ), this, SLOT ( cleanupFinished( int ) ) ); connect( _ui->treemapView, SIGNAL( hoverEnter ( FileInfo * ) ), this, SLOT ( showCurrent( FileInfo * ) ) ); connect( _ui->treemapView, SIGNAL( hoverLeave ( FileInfo * ) ), this, SLOT ( showSummary() ) ); // Debug connections connect( _ui->dirTreeView, SIGNAL( clicked ( QModelIndex ) ), this, SLOT ( itemClicked( QModelIndex ) ) ); connect( _selectionModel, SIGNAL( selectionChanged() ), this, SLOT ( selectionChanged() ) ); connect( _selectionModel, SIGNAL( currentItemChanged( FileInfo *, FileInfo * ) ), this, SLOT ( currentItemChanged( FileInfo *, FileInfo * ) ) ); connectActions(); if ( ExcludeRules::instance()->isEmpty() ) { ExcludeRules::add( QRegExp( ".snapshot", Qt::CaseSensitive, QRegExp::FixedString ) ); } Debug::dumpExcludeRules(); if ( ! _ui->actionShowTreemap->isChecked() ) _ui->treemapView->disable(); toggleVerboseSelection(); updateActions(); } MainWindow::~MainWindow() { writeSettings(); ExcludeRules::instance()->writeSettings(); // Relying on the QObject hierarchy to properly clean this up resulted in a // segfault; there was probably a problem in the deletion order. if ( _configDialog ) delete _configDialog; delete _ui->dirTreeView; delete _cleanupCollection; delete _mimeCategorizer; delete _selectionModel; delete _dirTreeModel; } #define CONNECT_ACTION(ACTION, RECEIVER, RCVR_SLOT) \ connect( (ACTION), SIGNAL( triggered() ), (RECEIVER), SLOT( RCVR_SLOT ) ) void MainWindow::connectActions() { // "File" menu CONNECT_ACTION( _ui->actionOpen, this, askOpenUrl() ); CONNECT_ACTION( _ui->actionRefreshAll, this, refreshAll() ); CONNECT_ACTION( _ui->actionRefreshSelected, this, refreshSelected() ); CONNECT_ACTION( _ui->actionReadExcludedDirectory, this, refreshSelected() ); CONNECT_ACTION( _ui->actionContinueReadingAtMountPoint, this, refreshSelected() ); CONNECT_ACTION( _ui->actionStopReading, this, stopReading() ); CONNECT_ACTION( _ui->actionAskWriteCache, this, askWriteCache() ); CONNECT_ACTION( _ui->actionAskReadCache, this, askReadCache() ); CONNECT_ACTION( _ui->actionQuit, qApp, quit() ); // "View" menu _treeLevelMapper = new QSignalMapper( this ); connect( _treeLevelMapper, SIGNAL( mapped ( int ) ), this, SLOT ( expandTreeToLevel( int ) ) ); mapTreeExpandAction( _ui->actionExpandTreeLevel0, 0 ); mapTreeExpandAction( _ui->actionExpandTreeLevel1, 1 ); mapTreeExpandAction( _ui->actionExpandTreeLevel2, 2 ); mapTreeExpandAction( _ui->actionExpandTreeLevel3, 3 ); mapTreeExpandAction( _ui->actionExpandTreeLevel4, 4 ); mapTreeExpandAction( _ui->actionExpandTreeLevel5, 5 ); mapTreeExpandAction( _ui->actionExpandTreeLevel6, 6 ); mapTreeExpandAction( _ui->actionExpandTreeLevel7, 7 ); mapTreeExpandAction( _ui->actionExpandTreeLevel8, 8 ); mapTreeExpandAction( _ui->actionExpandTreeLevel9, 9 ); mapTreeExpandAction( _ui->actionCloseAllTreeLevels, 0 ); CONNECT_ACTION( _ui->actionFileSizeStats, this, showFileSizeStats() ); CONNECT_ACTION( _ui->actionFileTypeStats, this, showFileTypeStats() ); _ui->actionFileTypeStats->setShortcutContext( Qt::ApplicationShortcut ); // "Edit" menu CONNECT_ACTION( _ui->actionCopyUrlToClipboard, this, copyCurrentUrlToClipboard() ); CONNECT_ACTION( _ui->actionMoveToTrash, this, moveToTrash() ); // "Go To" menu CONNECT_ACTION( _ui->actionGoUp, this, navigateUp() ); CONNECT_ACTION( _ui->actionGoToToplevel, this, navigateToToplevel() ); // "Treemap" menu connect( _ui->actionShowTreemap, SIGNAL( toggled( bool ) ), this, SLOT ( showTreemapView() ) ); connect( _ui->actionTreemapAsSidePanel, SIGNAL( toggled( bool ) ), this, SLOT ( treemapAsSidePanel() ) ); CONNECT_ACTION( _ui->actionTreemapZoomIn, _ui->treemapView, zoomIn() ); CONNECT_ACTION( _ui->actionTreemapZoomOut, _ui->treemapView, zoomOut() ); CONNECT_ACTION( _ui->actionResetTreemapZoom, _ui->treemapView, resetZoom() ); CONNECT_ACTION( _ui->actionTreemapRebuild, _ui->treemapView, rebuildTreemap() ); // "Settings" menu CONNECT_ACTION( _ui->actionConfigure, this, openConfigDialog() ); // "Help" menu CONNECT_ACTION( _ui->actionHelp, this, showHelp() ); CONNECT_ACTION( _ui->actionAbout, this, showAboutDialog() ); CONNECT_ACTION( _ui->actionAboutQt, qApp, aboutQt() ); // Invisible debug actions addAction( _ui->actionVerboseSelection ); addAction( _ui->actionDumpSelection ); connect( _ui->actionVerboseSelection, SIGNAL( toggled( bool ) ), // Shift-F7 this, SLOT ( toggleVerboseSelection() ) ); CONNECT_ACTION( _ui->actionDumpSelection, _selectionModel, dumpSelectedItems() ); // F7 } void MainWindow::mapTreeExpandAction( QAction * action, int level ) { CONNECT_ACTION( action, _treeLevelMapper, map() ); _treeLevelMapper->setMapping( action, level ); } void MainWindow::updateActions() { bool reading = _dirTreeModel->tree()->isBusy(); _ui->actionStopReading->setEnabled( reading ); _ui->actionRefreshAll->setEnabled ( ! reading ); _ui->actionAskReadCache->setEnabled ( ! reading ); _ui->actionAskWriteCache->setEnabled( ! reading ); bool haveCurrentItem = ( _selectionModel->currentItem() != 0 ); bool treeNotEmpty = ( _dirTreeModel->tree()->firstToplevel() != 0 ); _ui->actionCopyUrlToClipboard->setEnabled( haveCurrentItem ); _ui->actionGoUp->setEnabled( haveCurrentItem ); _ui->actionGoToToplevel->setEnabled( treeNotEmpty ); FileInfoSet selectedItems = _selectionModel->selectedItems(); FileInfo * sel = selectedItems.first(); bool oneDirSelected = ( selectedItems.size() == 1 ) && sel && sel->isDir(); _ui->actionMoveToTrash->setEnabled( sel && ! sel->isDotEntry() ); _ui->actionRefreshSelected->setEnabled( oneDirSelected && ! sel->isExcluded() && ! sel->isMountPoint() ); _ui->actionContinueReadingAtMountPoint->setEnabled( oneDirSelected && sel->isMountPoint() ); _ui->actionReadExcludedDirectory->setEnabled ( oneDirSelected && sel->isExcluded() ); bool nothingOrOneDir = selectedItems.isEmpty() || ( selectedItems.size() == 1 && sel && ( sel->isDir() || sel->isDotEntry() ) ); _ui->actionFileSizeStats->setEnabled( ! reading && nothingOrOneDir ); _ui->actionFileTypeStats->setEnabled( ! reading && nothingOrOneDir ); bool showingTreemap = _ui->treemapView->isVisible(); _ui->actionTreemapAsSidePanel->setEnabled( showingTreemap ); _ui->actionTreemapZoomIn->setEnabled ( showingTreemap && _ui->treemapView->canZoomIn() ); _ui->actionTreemapZoomOut->setEnabled ( showingTreemap && _ui->treemapView->canZoomOut() ); _ui->actionResetTreemapZoom->setEnabled( showingTreemap && _ui->treemapView->canZoomOut() ); _ui->actionTreemapRebuild->setEnabled ( showingTreemap ); } void MainWindow::readSettings() { QDirStat::Settings settings; settings.beginGroup( "MainWindow" ); _statusBarTimeout = settings.value( "StatusBarTimeoutMillisec", 3000 ).toInt(); bool showTreemap = settings.value( "ShowTreemap" , true ).toBool(); bool treemapOnSide = settings.value( "TreemapOnSide" , false ).toBool(); _verboseSelection = settings.value( "VerboseSelection" , false ).toBool(); settings.endGroup(); _ui->actionShowTreemap->setChecked( showTreemap ); _ui->actionTreemapAsSidePanel->setChecked( treemapOnSide ); treemapAsSidePanel(); _ui->actionVerboseSelection->setChecked( _verboseSelection ); readWindowSettings( this, "MainWindow" ); ExcludeRules::instance()->readSettings(); } void MainWindow::writeSettings() { QDirStat::Settings settings; settings.beginGroup( "MainWindow" ); settings.setValue( "StatusBarTimeoutMillisec", _statusBarTimeout ); settings.setValue( "ShowTreemap" , _ui->actionShowTreemap->isChecked() ); settings.setValue( "TreemapOnSide" , _ui->actionTreemapAsSidePanel->isChecked() ); settings.setValue( "VerboseSelection" , _verboseSelection ); settings.endGroup(); writeWindowSettings( this, "MainWindow" ); } void MainWindow::showTreemapView() { if ( _ui->actionShowTreemap->isChecked() ) _ui->treemapView->enable(); else _ui->treemapView->disable(); } void MainWindow::treemapAsSidePanel() { if ( _ui->actionTreemapAsSidePanel->isChecked() ) _ui->mainWinSplitter->setOrientation(Qt::Horizontal); else _ui->mainWinSplitter->setOrientation(Qt::Vertical); } void MainWindow::closeEvent( QCloseEvent *event ) { if ( _modified ) { int button = QMessageBox::question( this, tr( "Unsaved changes" ), tr( "Save changes?" ), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel ); if ( button == QMessageBox::Cancel ) { event->ignore(); return; } if ( button == QMessageBox::Save ) { // saveFile(); } event->accept(); } else { event->accept(); } } void MainWindow::busyDisplay() { _ui->treemapView->disable(); updateActions(); // It would be nice to sort by read jobs during reading, but this confuses // the hell out of the Qt side of the data model; so let's sort by name // instead. int sortCol = QDirStat::DataColumns::toViewCol( QDirStat::NameCol ); _ui->dirTreeView->sortByColumn( sortCol, Qt::AscendingOrder ); if ( ! _selectionModel->currentBranch() ) { // Wait until the toplevel entry has some children, then expand to level 1 QTimer::singleShot( 200, _ui->actionExpandTreeLevel1, SLOT( trigger() ) ); } } void MainWindow::idleDisplay() { updateActions(); int sortCol = QDirStat::DataColumns::toViewCol( QDirStat::PercentNumCol ); _ui->dirTreeView->sortByColumn( sortCol, Qt::DescendingOrder ); if ( ! _selectionModel->currentBranch() ) { logDebug() << "No current branch - expanding tree to level 1" << endl; expandTreeToLevel( 1 ); } showTreemapView(); } void MainWindow::startingReading() { _stopWatch.start(); busyDisplay(); } void MainWindow::readingFinished() { logInfo() << endl; idleDisplay(); _ui->statusBar->showMessage( tr( "Finished. Elapsed time: %1") .arg( formatTime( _stopWatch.elapsed() ) ) ); // Debug::dumpModelTree( _dirTreeModel, QModelIndex(), "" ); } void MainWindow::readingAborted() { logInfo() << endl; idleDisplay(); _ui->statusBar->showMessage( tr( "Aborted. Elapsed time: %1") .arg( formatTime( _stopWatch.elapsed() ) ) ); } void MainWindow::openUrl( const QString & url ) { try { _dirTreeModel->openUrl( url ); } catch ( const SysCallFailedException & ex ) { CAUGHT( ex ); QMessageBox errorPopup( QMessageBox::Warning, // icon tr( "Error" ), // title tr( "Could not open directory %1" ).arg( ex.resourceName() ), // text QMessageBox::Ok, // buttons this ); // parent errorPopup.setDetailedText( ex.what() ); errorPopup.exec(); askOpenUrl(); } updateActions(); expandTreeToLevel( 1 ); } void MainWindow::askOpenUrl() { QString url = QFileDialog::getExistingDirectory( this, // parent tr("Select directory to scan") ); if ( ! url.isEmpty() ) openUrl( url ); } void MainWindow::refreshAll() { QString url = _dirTreeModel->tree()->url(); if ( ! url.isEmpty() ) { logDebug() << "Refreshing " << url << endl; _dirTreeModel->openUrl( url ); updateActions(); } else { askOpenUrl(); } } void MainWindow::refreshSelected() { busyDisplay(); _dirTreeModel->refreshSelected(); updateActions(); } void MainWindow::stopReading() { if ( _dirTreeModel->tree()->isBusy() ) { _dirTreeModel->tree()->abortReading(); _ui->statusBar->showMessage( tr( "Reading aborted." ) ); } } void MainWindow::readCache( const QString & cacheFileName ) { _dirTreeModel->clear(); if ( ! cacheFileName.isEmpty() ) _dirTreeModel->tree()->readCache( cacheFileName ); } void MainWindow::askReadCache() { QString fileName = QFileDialog::getOpenFileName( this, // parent tr( "Select QDirStat cache file" ), DEFAULT_CACHE_NAME ); if ( ! fileName.isEmpty() ) readCache( fileName ); } void MainWindow::askWriteCache() { QString fileName = QFileDialog::getSaveFileName( this, // parent tr( "Enter name for QDirStat cache file"), DEFAULT_CACHE_NAME ); if ( ! fileName.isEmpty() ) { bool ok = _dirTreeModel->tree()->writeCache( fileName ); QString msg = ok ? tr( "Directory tree written to file %1" ).arg( fileName ) : tr( "ERROR writing cache file %1").arg( fileName ); _ui->statusBar->showMessage( msg, _statusBarTimeout ); } } void MainWindow::expandTreeToLevel( int level ) { logDebug() << "Expanding tree to level " << level << endl; if ( level < 1 ) _ui->dirTreeView->collapseAll(); else _ui->dirTreeView->expandToDepth( level - 1 ); } void MainWindow::showProgress( const QString & text ) { _ui->statusBar->showMessage( text, _statusBarTimeout ); } void MainWindow::showCurrent( FileInfo * item ) { if ( item ) { _ui->statusBar->showMessage( QString( "%1 (%2)" ) .arg( item->debugUrl() ) .arg( formatSize( item->totalSize() ) ) ); } else { _ui->statusBar->clearMessage(); } } void MainWindow::showSummary() { FileInfoSet sel = _selectionModel->selectedItems(); int count = sel.size(); if ( count <= 1 ) showCurrent( _selectionModel->currentItem() ); else { sel = sel.normalized(); _ui->statusBar->showMessage( tr( "%1 items selected (%2 total)" ) .arg( count ) .arg( formatSize( sel.totalSize() ) ) ); } } void MainWindow::startingCleanup( const QString & cleanupName ) { showProgress( tr( "Starting cleanup action %1" ).arg( cleanupName ) ); } void MainWindow::cleanupFinished( int errorCount ) { logDebug() << "Error count: " << errorCount << endl; if ( errorCount == 0 ) showProgress( tr( "Cleanup action finished successfully." ) ); else showProgress( tr( "Cleanup action finished with %1 errors." ).arg( errorCount ) ); } void MainWindow::notImplemented() { QMessageBox::warning( this, tr( "Error" ), tr( "Not implemented!" ) ); } void MainWindow::copyCurrentUrlToClipboard() { FileInfo * currentItem = _selectionModel->currentItem(); if ( currentItem ) { QClipboard * clipboard = QApplication::clipboard(); QString url = currentItem->url(); clipboard->setText( url ); showProgress( tr( "Copied to system clipboard: %1" ).arg( url ) ); } else { showProgress( tr( "No current item" ) ); } } void MainWindow::navigateUp() { FileInfo * currentItem = _selectionModel->currentItem(); if ( currentItem && currentItem->parent() && currentItem->parent() != _dirTreeModel->tree()->root() ) { _selectionModel->setCurrentItem( currentItem->parent(), true ); // select } } void MainWindow::navigateToToplevel() { FileInfo * toplevel = _dirTreeModel->tree()->firstToplevel(); if ( toplevel ) { expandTreeToLevel( 1 ); _selectionModel->setCurrentItem( toplevel, true ); // select } } void MainWindow::moveToTrash() { FileInfoSet selectedItems = _selectionModel->selectedItems().normalized(); // Prepare output window OutputWindow * outputWindow = new OutputWindow( qApp->activeWindow() ); CHECK_NEW( outputWindow ); // Prepare refresher FileInfoSet refreshSet = Refresher::parents( selectedItems ); _selectionModel->prepareRefresh( refreshSet ); Refresher * refresher = new Refresher( refreshSet, this ); CHECK_NEW( refresher ); connect( outputWindow, SIGNAL( lastProcessFinished( int ) ), refresher, SLOT ( refresh() ) ); outputWindow->showAfterTimeout(); // Move all selected items to trash foreach ( FileInfo * item, selectedItems ) { bool success = Trash::trash( item->url() ); if ( success ) outputWindow->addStdout( tr( "Moved to trash: %1" ).arg( item->url() ) ); else outputWindow->addStderr( tr( "Move to trash failed for %1" ).arg( item->url() ) ); } outputWindow->noMoreProcesses(); } void MainWindow::openConfigDialog() { if ( _configDialog && _configDialog->isVisible() ) return; // For whatever crazy reason it is considerably faster to delete that // complex dialog and recreate it from scratch than to simply leave it // alive and just show it again. Well, whatever - so be it. // // And yes, I added debug logging here, in the dialog's setup(), in // showEvent(); I added update(). No result whatsoever. // Okay, then let's take the long way around. if ( _configDialog ) delete _configDialog; _configDialog = new ConfigDialog( this ); CHECK_PTR( _configDialog ); _configDialog->cleanupConfigPage()->setCleanupCollection( _cleanupCollection ); _configDialog->mimeCategoryConfigPage()->setMimeCategorizer( _mimeCategorizer ); if ( ! _configDialog->isVisible() ) { _configDialog->setup(); _configDialog->show(); } } void MainWindow::showFileTypeStats() { if ( ! _fileTypeStatsWindow ) { // This deletes itself when the user closes it. The associated QPointer // keeps track of that and sets the pointer to 0 when it happens. _fileTypeStatsWindow = new QDirStat::FileTypeStatsWindow( _selectionModel, this ); } _fileTypeStatsWindow->populate( selectedDirOrRoot() ); _fileTypeStatsWindow->show(); } void MainWindow::showFileSizeStats() { FileInfo * sel = selectedDirOrRoot(); if ( ! sel || ! sel->hasChildren() ) return; FileSizeStatsWindow::populateSharedInstance( sel ); } FileInfo * MainWindow::selectedDirOrRoot() const { FileInfoSet selectedItems = _selectionModel->selectedItems(); FileInfo * sel = selectedItems.first(); if ( ! sel ) sel = _dirTreeModel->tree()->firstToplevel(); return sel; } void MainWindow::toggleVerboseSelection() { // Verbose selection is toggled with Shift-F7 _verboseSelection = _ui->actionVerboseSelection->isChecked(); if ( _selectionModel ) _selectionModel->setVerbose( _verboseSelection ); logInfo() << "Verbose selection is now " << ( _verboseSelection ? "on" : "off" ) << ". Change this with Shift-F7." << endl; } void MainWindow::showHelp() { QString helpUrl = "https://github.com/shundhammer/qdirstat/blob/master/README.md"; QString program = "/usr/bin/xdg-open"; logInfo() << "Starting " << program << " " << helpUrl << endl; QProcess::startDetached( program, QStringList() << helpUrl ); } void MainWindow::showAboutDialog() { QString homePage = "https://github.com/shundhammer/qdirstat"; QString mailTo = "qdirstat@gmx.de"; QString text = "

QDirStat " QDIRSTAT_VERSION "

"; text += "

"; text += tr( "Qt-based directory statistics -- showing where all your disk space has gone " " and trying to help you to clean it up." ); text += "

"; text += "(c) 2015-2017 Stefan Hundhammer"; text += "

"; text += QString( "

%2

" ).arg( homePage ).arg( homePage ); text += tr( "License: GPL V2 (GNU Public License Version 2)" ); text += "

"; text += tr( "This is free Open Source software, provided to you hoping that it might be " "useful for you. It does not cost you anything, but on the other hand there " "is no warranty or promise of anything." ); text += "

"; text += tr( "This software was made with the best intentions and greatest care, but still " "there is the off chance that something might go wrong which might damage " "data on your computer. Under no circumstances will the authors of this program " "be held responsible for anything like that. Use this program at your own risk." ); text += "

"; QMessageBox::about( this, tr( "About QDirStat" ), text ); } //--------------------------------------------------------------------------- // Debugging Helpers //--------------------------------------------------------------------------- void MainWindow::itemClicked( const QModelIndex & index ) { if ( ! _verboseSelection ) return; if ( index.isValid() ) { FileInfo * item = static_cast( index.internalPointer() ); logDebug() << "Clicked row " << index.row() << " col " << index.column() << " (" << QDirStat::DataColumns::fromViewCol( index.column() ) << ")" << "\t" << item << endl; // << " data(0): " << index.model()->data( index, 0 ).toString() // logDebug() << "Ancestors: " << Debug::modelTreeAncestors( index ).join( " -> " ) << endl; } else { logDebug() << "Invalid model index" << endl; } // _dirTreeModel->dumpPersistentIndexList(); } void MainWindow::selectionChanged() { showSummary(); if ( _verboseSelection ) { logDebug() << endl; _selectionModel->dumpSelectedItems(); } } void MainWindow::currentItemChanged( FileInfo * newCurrent, FileInfo * oldCurrent ) { showSummary(); if ( _verboseSelection ) { logDebug() << "new current: " << newCurrent << endl; logDebug() << "old current: " << oldCurrent << endl; _selectionModel->dumpSelectedItems(); } } QString MainWindow::formatTime( qint64 millisec ) { QString formattedTime; int hours; int min; int sec; hours = millisec / 3600000L; // 60*60*1000 millisec %= 3600000L; min = millisec / 60000L; // 60*1000 millisec %= 60000L; sec = millisec / 1000L; millisec %= 1000L; if ( hours < 1 && min < 1 && sec < 60 ) { formattedTime.sprintf ( "%2d.%03lld ", sec, millisec ); formattedTime += tr( "sec" ); } else { formattedTime.sprintf ( "%02d:%02d:%02d", hours, min, sec ); } return formattedTime; } qdirstat-1.4/src/MainWindow.h000066400000000000000000000156141311502036700162320ustar00rootroot00000000000000/* * File name: MainWindow.h * Summary: QDirStat main window * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef MainWindow_h #define MainWindow_h #include #include #include #include #include "ui_main-window.h" #include "FileTypeStatsWindow.h" class QCloseEvent; class QSortFilterProxyModel; class QSignalMapper; namespace QDirStat { class CleanupCollection; class ConfigDialog; class DirTreeModel; class FileInfo; class MimeCategorizer; class SelectionModel; } using QDirStat::FileInfo; using QDirStat::FileTypeStatsWindow; class MainWindow: public QMainWindow { Q_OBJECT public: MainWindow(); virtual ~MainWindow(); /** * Return the DirTreeModel used in this window. **/ QDirStat::DirTreeModel * dirTreeModel() const { return _dirTreeModel; } public slots: /** * Open an URL (start reading that directory). **/ void openUrl( const QString & url ); /** * Open a directory selection dialog and open the selected URL. **/ void askOpenUrl(); /** * Re-read the complete directory tree. **/ void refreshAll(); /** * Re-read the selected branch of the tree. **/ void refreshSelected(); /** * Stop reading if reading is in process. **/ void stopReading(); /** * Clear the current tree and replace it with the content of the specified * cache file. **/ void readCache( const QString & cacheFileName ); /** * Open a file selection dialog to ask for a cache file, clear the * current tree and replace it with the content of the cache file. **/ void askReadCache(); /** * Open a file selection dialog and save the current tree to the selected * file. **/ void askWriteCache(); /** * Expand the directory tree's branches to depth 'level'. **/ void expandTreeToLevel( int level ); /** * Show progress text in the status bar for a few seconds. **/ void showProgress( const QString & text ); /** * Show the URL of 'item' and its total size in the status line. **/ void showCurrent( FileInfo * item ); /** * Show a summary of the current selection in the status line. **/ void showSummary(); /** * Copy the URL of the current item (if there is one) to the system * clipboard for use in other applications. **/ void copyCurrentUrlToClipboard(); /** * Move the selected items to the trash bin. **/ void moveToTrash(); /** * Navigate one directory level up. **/ void navigateUp(); /** * Navigate to the toplevel directory of this tree. **/ void navigateToToplevel(); /** * Show the "about" dialog. **/ void showAboutDialog(); /** * Read parameters from the settings file. **/ void readSettings(); /** * Write parameters to the settings file. **/ void writeSettings(); /** * Show online help. **/ void showHelp(); protected slots: /** * Switch display to "busy display" after reading was started and restart * the stopwatch. **/ void startingReading(); /** * Finalize display after reading is finished. **/ void readingFinished(); /** * Finalize display after reading has been aborted. **/ void readingAborted(); /** * Change display mode to "busy" (while reading a directory tree): * Sort tree view by read jobs, hide treemap view. **/ void busyDisplay(); /** * Change display mode to "idle" (after reading the directory tree is * finished): If the tree view is still sorted by read jobs, now sort it by * subtree percent, show the treemap view if enabled. **/ void idleDisplay(); /** * Enable or disable actions depending on current status. **/ void updateActions(); /** * Enable or disable the treemap view, depending on the value of * the corresponding action. **/ void showTreemapView(); /** * Switch between showing the treemap view beside the file directory * or below it, depending on the corresponding action. **/ void treemapAsSidePanel(); /** * Notification that a cleanup action was started. **/ void startingCleanup( const QString & cleanupName ); /** * Notification that the last process of a cleanup action is finished. * * 'errorCount' is the total number of errors reported by all processes * that were started. **/ void cleanupFinished( int errorCount ); /** * Open the config dialog. **/ void openConfigDialog(); /** * Show file type statistics for the currently selected directory. **/ void showFileTypeStats(); /** * Show file size statistics for the currently selected directory. **/ void showFileSizeStats(); /** * Switch verbose logging for selection changes on or off. * * This is normally done by the invisible checkable action * _ui->actionVerboseSelection in the main window UI file. * * The hotkey for this is Shift-F7. **/ void toggleVerboseSelection(); /** * Open a popup dialog with a message that this feature is not implemented. **/ void notImplemented(); #if 1 // // Debugging slots // /** * Debug: Item clicked in the tree widget. **/ void itemClicked( const QModelIndex & index ); void selectionChanged(); void currentItemChanged( FileInfo * newCurrent, FileInfo * oldCurrent ); #endif protected: /** * Return the first selected directory or, if none is selected, the root * directory. **/ FileInfo * selectedDirOrRoot() const; /** * Set up QObject connections to the actions from the .ui file **/ void connectActions(); /** * Set up the _treeLevelMapper to map an "expand tree to level x" action to * the correct slot. **/ void mapTreeExpandAction( QAction * action, int level ); /** * Window close event ([x] icon in the top right window) **/ virtual void closeEvent( QCloseEvent *event ) Q_DECL_OVERRIDE; /** * Format a millisecond-based time **/ QString formatTime( qint64 millisec ); private: Ui::MainWindow * _ui; QDirStat::DirTreeModel * _dirTreeModel; QDirStat::SelectionModel * _selectionModel; QDirStat::CleanupCollection * _cleanupCollection; QDirStat::MimeCategorizer * _mimeCategorizer; QDirStat::ConfigDialog * _configDialog; QPointer _fileTypeStatsWindow; QElapsedTimer _stopWatch; bool _modified; bool _verboseSelection; int _statusBarTimeout; // millisec QSignalMapper * _treeLevelMapper; }; #endif // MainWindow_H qdirstat-1.4/src/MimeCategorizer.cpp000066400000000000000000000236601311502036700175770ustar00rootroot00000000000000/* * File name: MimeCategorizer.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "MimeCategorizer.h" #include "FileInfo.h" #include "Settings.h" #include "SettingsHelpers.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; MimeCategorizer::MimeCategorizer( QObject * parent ): QObject( parent ), _mapsDirty( true ) { readSettings(); } MimeCategorizer::~MimeCategorizer() { writeSettings(); clear(); } void MimeCategorizer::clear() { qDeleteAll( _categories ); _categories.clear(); _mapsDirty = true; } MimeCategory * MimeCategorizer::category( FileInfo * item ) { CHECK_PTR ( item ); CHECK_MAGIC( item ); if ( item->isDir() || item->isDirInfo() ) return 0; else return category( item->name() ); } MimeCategory * MimeCategorizer::category( const QString & filename, QString * suffix_ret ) { if ( suffix_ret ) *suffix_ret = ""; if ( filename.isEmpty() ) return 0; // Build suffix maps for fast lookup if ( _mapsDirty ) buildMaps(); MimeCategory * category = 0; // Find the filename suffix: Section #1 // (ignoring any leading '.' separator) QString suffix = filename.section( '.', 1 ); while ( ! suffix.isEmpty() ) { // Try case sensitive first category = _caseSensitiveSuffixMap.value( suffix, 0 ); if ( ! category ) category = _caseInsensitiveSuffixMap.value( suffix.toLower(), 0 ); if ( category && suffix_ret ) *suffix_ret = suffix; // No match so far? Try the next suffix. Some files might have more // than one, e.g., "tar.bz2" - if there is no match for "tar.bz2", // there might be one for just "bz2". suffix = suffix.section( '.', 1 ); } if ( ! category ) // No match yet? category = matchPatterns( filename ); #if 0 if ( category ) logVerbose() << "Found " << category << " for " << filename << endl; #endif return category; } MimeCategory * MimeCategorizer::matchPatterns( const QString & filename ) const { foreach ( MimeCategory * category, _categories ) { if ( category ) { foreach ( const QRegExp & pattern, category->patternList() ) { if ( pattern.exactMatch( filename ) ) return category; } } } return 0; // No match } void MimeCategorizer::add( MimeCategory * category ) { CHECK_PTR( category ); _categories << category; _mapsDirty = true; } void MimeCategorizer::remove( MimeCategory * category ) { CHECK_PTR( category ); _categories.removeAll( category ); delete category; _mapsDirty = true; } void MimeCategorizer::buildMaps() { _caseInsensitiveSuffixMap.clear(); _caseSensitiveSuffixMap.clear(); foreach ( MimeCategory * category, _categories ) { CHECK_PTR( category ); addSuffixes( _caseInsensitiveSuffixMap, category, category->caseInsensitiveSuffixList() ); addSuffixes( _caseSensitiveSuffixMap, category, category->caseSensitiveSuffixList() ); } _mapsDirty = false; } void MimeCategorizer::addSuffixes( QMap & suffixMap, MimeCategory * category, const QStringList & suffixList ) { foreach ( const QString & suffix, suffixList ) { if ( suffixMap.contains( suffix ) ) { logError() << "Duplicate suffix: " << suffix << " for " << suffixMap.value( suffix ) << " and " << category << endl; } else { suffixMap[ suffix ] = category; } } } void MimeCategorizer::readSettings() { MimeCategorySettings settings; QStringList mimeCategoryGroups = settings.findGroups( settings.groupPrefix() ); clear(); // Read all settings groups [MimeCategory_xx] that were found foreach ( const QString & groupName, mimeCategoryGroups ) { settings.beginGroup( groupName ); QString name = settings.value( "Name", groupName ).toString(); QColor color = readColorEntry( settings, "Color", QColor( "#b0b0b0" ) ); QStringList patternsCaseInsensitive = settings.value( "PatternsCaseInsensitive" ).toStringList(); QStringList patternsCaseSensitive = settings.value( "PatternsCaseSensitive" ).toStringList(); MimeCategory * category = new MimeCategory( name, color ); CHECK_NEW( category ); add( category ); category->addPatterns( patternsCaseInsensitive, Qt::CaseInsensitive ); category->addPatterns( patternsCaseSensitive, Qt::CaseSensitive ); settings.endGroup(); // [MimeCategory_01], [MimeCategory_02], ... } if ( _categories.isEmpty() ) addDefaultCategories(); } void MimeCategorizer::writeSettings() { MimeCategorySettings settings; // Remove all leftover cleanup descriptions settings.removeGroups( settings.groupPrefix() ); for ( int i=0; i < _categories.size(); ++i ) { QString groupName; groupName.sprintf( "MimeCategory_%02d", i+1 ); settings.beginGroup( groupName ); MimeCategory * category = _categories.at(i); settings.setValue( "Name", category->name() ); writeColorEntry( settings, "Color", category->color() ); QStringList patterns = category->humanReadablePatternList( Qt::CaseInsensitive ); if ( patterns.isEmpty() ) patterns << ""; settings.setValue( "PatternsCaseInsensitive", patterns ); patterns = category->humanReadablePatternList( Qt::CaseSensitive ); if ( patterns.isEmpty() ) patterns << ""; settings.setValue( "PatternsCaseSensitive", patterns ); settings.endGroup(); // [MimeCategory_01], [MimeCategory_02], ... } } void MimeCategorizer::addDefaultCategories() { MimeCategory * junk = new MimeCategory( tr( "Junk" ), Qt::red ); CHECK_NEW( junk ); add( junk ); junk->addSuffix( "~" ); junk->addSuffix( "bak" ); junk->addPattern( "core", Qt::CaseSensitive ); MimeCategory * archives = new MimeCategory( tr( "Compressed Archives" ), Qt::green ); CHECK_NEW( archives ); add( archives ); archives->addSuffixes( QStringList() << "7z" << "arj" << "cab" << "cpio.gz" << "deb" << "jar" << "rar" << "rpm" << "tar.bz2" << "tar.gz" << "tgz" << "zip" ); MimeCategory * uncompressedArchives = new MimeCategory( tr( "Uncompressed Archives" ), QColor( 128, 128, 0 ) ); CHECK_NEW( uncompressedArchives ); add( uncompressedArchives ); uncompressedArchives->addSuffix( "tar" ); uncompressedArchives->addSuffix( "cpio" ); MimeCategory * compressed = new MimeCategory( tr( "Compressed Files" ), Qt::green ); CHECK_NEW( compressed ); add( compressed ); compressed->addSuffix( ".bz2" ); compressed->addSuffix( ".gz" ); MimeCategory * images = new MimeCategory( tr( "Images" ), Qt::cyan ); CHECK_NEW( images ); add( images ); images->addSuffixes( QStringList() << "gif" << "jpeg" << "jpg" << "png" << "tif" << "tiff" << "xcf.bz2" << "xcf.gz" << "xpm" // uncompressed, buy typically tiny ); MimeCategory * uncompressedImages = new MimeCategory( tr( "Uncompressed Images" ), Qt::red ); CHECK_NEW( uncompressedImages ); add( uncompressedImages ); uncompressedImages->addSuffixes( QStringList() << "bmp" << "pbm" << "pgm" << "pnm" << "ppm" << "xcf" ); MimeCategory * videos = new MimeCategory( tr( "Videos" ), QColor( 0xa0, 0xff, 0x00 ) ); CHECK_NEW( videos ); add( videos ); videos->addSuffixes( QStringList() << "asf" << "avi" << "divx" << "flc" << "fli" << "flv" << "mk3d" << "mkv" << "mng" << "mov" << "mp2" << "mp4" << "mpeg" << "mpg" << "ogm" << "ogv" << "rm" << "vdr" << "vob" << "webm" << "wmp" << "wmv" ); MimeCategory * music = new MimeCategory( tr( "Music" ), Qt::yellow ); CHECK_NEW( music ); add( music ); music->addSuffixes( QStringList() << "aac" << "f4a" << "f4b" << "m4a" << "m4b" << "mid" << "mka" << "mp3" << "oga" << "ogg" << "ra" << "rax" << "wav" << "wma" ); MimeCategory * doc = new MimeCategory( tr( "Documents" ), Qt::blue ); CHECK_NEW( doc ); add( doc ); doc->addSuffixes( QStringList() << "doc" << "docx" << "dotx" << "dvi" << "dvi.bz2" << "epub" << "htm" << "html" << "md" << "odb" << "odc" << "odg" << "odp" << "ods" << "odt" << "otc" << "otp" << "ots" << "pdf" << "potx" << "ppsx" << "ppt" << "pptx" << "ps" << "sdc" << "sdc.gz" << "sdd" << "sdp" << "sdw" << "sla" << "sla.gz" << "slaz" << "sxi" << "txt" << "xls" << "xlsx" << "xlt" << "css" << "csv" << "latex" << "tex" << "xml" ); MimeCategory * src = new MimeCategory( tr( "Source Files" ), Qt::cyan ); CHECK_NEW( src ); add( src ); src->addSuffixes( QStringList() << "c" << "cpp" << "cc" << "cxx" << "h" << "hpp" << "ui" << "pl" << "py" << "rb" << "el" << "pro" << "cmake" , Qt::CaseSensitive ); MimeCategory * obj = new MimeCategory( tr( "Object or Generated Files" ), QColor( 0xff, 0xa0, 0x00 ) ); CHECK_NEW( obj ); add( obj ); obj->addSuffixes( QStringList() << "o" << "lo" << "Po" << "al" << "la" << "moc" << "elc" << "log" , Qt::CaseSensitive ); obj->addPatterns( QStringList() << "moc_*.cpp" << "ui_*.cpp" << "qrc_*.cpp" , Qt::CaseSensitive ); MimeCategory * libs = new MimeCategory( tr( "Libraries" ), QColor( 0xff, 0xa0, 0x00 ) ); CHECK_NEW( libs ); add( libs ); libs->addPattern( "lib*.so.*", Qt::CaseSensitive ); libs->addPattern( "lib*.so", Qt::CaseSensitive ); libs->addPattern( "lib*.a", Qt::CaseSensitive ); libs->addSuffix ( "dll" ); } qdirstat-1.4/src/MimeCategorizer.h000066400000000000000000000060311311502036700172350ustar00rootroot00000000000000/* * File name: MimeCategorizer.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef MimeCategorizer_h #define MimeCategorizer_h #include #include "MimeCategory.h" namespace QDirStat { class FileInfo; /** * Class to determine the MimeCategory of filenames. * * This class is optimized for performance since the names of all files in * QDirStat's DirTree need to be checked (something in the order of 200,000 * in a typical Linux root file system). **/ class MimeCategorizer: public QObject { Q_OBJECT public: /** * Constructor. **/ MimeCategorizer( QObject * parent = 0 ); /** * Destructor. **/ virtual ~MimeCategorizer(); /** * Return the MimeCategory for a FileInfo item or 0 if it doesn't fit * into any of the available categories. **/ MimeCategory * category( FileInfo * item ); /** * Return the MimeCategory for a filename or 0 if it doesn't fit into * any of the available categories. * * If 'suffix_ret' is non-null, it returns the suffix used if the * category was found by a suffix rule. If the category was not found * or if a regexp (rather than a suffix rule) matched, this returns an * empty string. **/ MimeCategory * category( const QString & filename, QString * suffix_ret = 0 ); /** * Add a MimeCategory. **/ void add( MimeCategory * category ); /** * Remove and delete a MimeCategory. **/ void remove( MimeCategory * category ); /** * Return the number of MimeCategories. **/ int size() const { return _categories.size(); } /** * Return the MimeCategories list. **/ const MimeCategoryList & categories() const { return _categories; } /** * Clear all categories. **/ void clear(); public slots: /** * Read the MimeCategory parameter from the settings. **/ void readSettings(); /** * Write the MimeCategory parameter to the settings. **/ void writeSettings(); protected: /** * Build the internal maps and clear the _mapsDirty flag. **/ void buildMaps(); /** * Add all suffixes in 'suffixList' as key to 'suffixMap' with value * 'category'. * * This provides a really fast map lookup for each suffix. **/ void addSuffixes( QMap & suffixMap, MimeCategory * category, const QStringList & suffixList ); /** * Iterate over all categories and try all patterns until the first * match. Return the matched category or 0 if none matched. **/ MimeCategory * matchPatterns( const QString & filename ) const; /** * Add default categories in case none were read from the settings. **/ void addDefaultCategories(); // // Data members // bool _mapsDirty; MimeCategoryList _categories; QMap _caseInsensitiveSuffixMap; QMap _caseSensitiveSuffixMap; }; // class MimeCategorizer } // namespace QDirStat #endif // MimeCategorizer_h qdirstat-1.4/src/MimeCategory.cpp000066400000000000000000000072611311502036700170750ustar00rootroot00000000000000/* * File name: MimeCategory.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "MimeCategory.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; MimeCategory::MimeCategory( const QString & name, const QColor & color ): _name( name ), _color( color ) { if ( ! _color.isValid() ) _color = Qt::white; } MimeCategory::~MimeCategory() { // NOP } void MimeCategory::addSuffix( const QString & rawSuffix, Qt::CaseSensitivity caseSensitivity ) { // Normalize suffix: Remove leading "*." or "." QString suffix = rawSuffix.trimmed(); if ( suffix.startsWith( "*." ) ) suffix.remove( 0, 2 ); else if ( suffix.startsWith( "." ) ) suffix.remove( 0, 1 ); if ( caseSensitivity == Qt::CaseInsensitive ) suffix = suffix.toLower(); // Pick the correct suffix list QStringList & suffixList = caseSensitivity == Qt::CaseSensitive ? _caseSensitiveSuffixList : _caseInsensitiveSuffixList; // Append suffix if not empty and not already there if ( ! suffix.isEmpty() && ! suffixList.contains( suffix ) ) suffixList << suffix; } bool MimeCategory::isSuffixPattern( const QString & pattern ) { if ( ! pattern.startsWith( "*." ) ) return false; QString rest = pattern.mid( 2, -1 ); // Without leading "*." if ( rest.contains( '*' ) || rest.contains( '?' ) || rest.contains( '[' ) ) // No use to check for "]", too, if there is no "[" { return false; } else return true; } void MimeCategory::addPattern( const QString & rawPattern, Qt::CaseSensitivity caseSensitivity ) { QString pattern = rawPattern.trimmed(); if ( isSuffixPattern( pattern ) ) addSuffix( pattern, caseSensitivity ); else { _patternList << QRegExp ( ( caseSensitivity == Qt::CaseInsensitive ? pattern.toLower() : pattern ), caseSensitivity, QRegExp::Wildcard ); } } void MimeCategory::addPatterns( const QStringList & patterns, Qt::CaseSensitivity caseSensitivity ) { foreach ( const QString & rawPattern, patterns ) { QString pattern = rawPattern.trimmed(); if ( ! pattern.isEmpty() ) addPattern( pattern, caseSensitivity ); } } void MimeCategory::addSuffixes( const QStringList & suffixes, Qt::CaseSensitivity caseSensitivity ) { foreach ( const QString & rawSuffix, suffixes ) { QString suffix = rawSuffix.trimmed(); if ( ! suffix.isEmpty() ) addSuffix( suffix, caseSensitivity ); } } void MimeCategory::clear() { _caseInsensitiveSuffixList.clear(); _caseSensitiveSuffixList.clear(); _patternList.clear(); } QStringList MimeCategory::humanReadablePatternList( Qt::CaseSensitivity caseSensitivity ) { QStringList result = caseSensitivity == Qt::CaseSensitive ? _caseSensitiveSuffixList : _caseInsensitiveSuffixList; result = humanReadableSuffixList( result ); result << humanReadablePatternList( _patternList, caseSensitivity ); #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) result.sort(); #else result.sort( caseSensitivity ); #endif return result; } QStringList MimeCategory::humanReadableSuffixList( const QStringList & suffixList ) { QStringList result; foreach ( const QString & suffix, suffixList ) result << ( "*." + suffix ); return result; } QStringList MimeCategory::humanReadablePatternList( const QRegExpList & patternList, Qt::CaseSensitivity caseSensitivity ) { QStringList result; foreach ( const QRegExp & pattern, patternList ) { if ( pattern.caseSensitivity() == caseSensitivity ) result << pattern.pattern(); } return result; } qdirstat-1.4/src/MimeCategory.h000066400000000000000000000127471311502036700165470ustar00rootroot00000000000000/* * File name: MimeCategory.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef MimeCategory_h #define MimeCategory_h #include #include #include #include #include #include namespace QDirStat { typedef QList QRegExpList; /** * Class that represents a category of MIME types like video, music, * images, summarizing more detailed MIME types like video/mp4, video/mpeg, * video/x-flic etc. * * The idea is to collect those detailed types in one category to give it * common attributes like the QDirStat treemap color so the user can get an * impression how much disk space each type consumes. If there are too many * different colors, it is difficult to tell which is which, so we are * summarizing similar MIME types into their common category. * * To match files against a MimeCategory, simple wildcard regexps are * used. It does not try any fancy file content matching, it just checks * the filename. In most cases this will be a filename extension (a * suffix), and in most cases this comparison will be case * insensitive. This class tries to optimize for this for improved * performance. **/ class MimeCategory { public: /** * Create a MimeCategory with the specified name and optional color. **/ MimeCategory( const QString & name, const QColor & color = QColor() ); /** * Destructor. **/ ~MimeCategory(); /** * Set the color for this category. **/ void setColor( const QColor & color ) { _color = color; } /** * Return the color for this category. **/ QColor color() const { return _color; } /** * Return the name of this category. **/ QString name() const { return _name; } /** * Set the name of this category. **/ void setName( const QString & newName ) { _name = newName; } /** * Add a filename suffix (extension) to this category. * A leading "*." or "*" is cut off. **/ void addSuffix( const QString & suffix, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive ); /** * Add a filename pattern to this category. If the pattern starts with * "*." and does not contain any other wildcard characters, add it as a * suffix. Otherwise, this will become a QRegExp::Wildcard regexp. **/ void addPattern( const QString & pattern, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive ); /** * Add a list of patterns. See addPattern() for details. **/ void addPatterns( const QStringList & patterns, Qt::CaseSensitivity caseSensitivity ); /** * Add a list of filename suffixes (extensions) to this category. * A leading "*." or "*" is cut off. **/ void addSuffixes( const QStringList & suffixes, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive ); /** * Clear any suffixes or patterns for this category. **/ void clear(); /** * Return the list of case-insensitive suffixes for this category. * The suffixes do not contain any leading wildcard or dot, * i.e. it will be "tar.bz2", not ".tar.bz2" or "*.tar.bz2". **/ const QStringList & caseInsensitiveSuffixList() const { return _caseInsensitiveSuffixList; } /** * Return the list of case-sensitive suffixes for this category. * The suffixes do not contain any leading wildcard or dot, * i.e. it will be "tar.bz2", not ".tar.bz2" or "*.tar.bz2". **/ const QStringList & caseSensitiveSuffixList() const { return _caseSensitiveSuffixList; } /** * Return the list of patterns for this category that are not simple * suffix patterns. **/ const QRegExpList & patternList() const { return _patternList; } /** * Return a sorted list of all either case sensitive or case * insensitive suffixes and patterns for this category in human * readable form, i.e. prepend suffixes with "*.": * "tar.bz2" -> "*.tar.bz2". * * This is useful for populating widgets. **/ QStringList humanReadablePatternList( Qt::CaseSensitivity caseSensitivity ); /** * Convert a suffix list into the commonly used human readable form, * i.e. prepend it with "*.": "tar.bz2" -> "*.tar.bz2". **/ static QStringList humanReadableSuffixList( const QStringList & suffixList ); /** * Filter out either case sensitive or case insensitive patterns from a * pattern list and convert them into human readable form. **/ static QStringList humanReadablePatternList( const QRegExpList & patternList, Qt::CaseSensitivity caseSensitivity ); protected: /** * Return 'true' if 'pattern' is a simple suffix pattern, i.e. it * starts with "*." and does not contain any more wildcard characters. **/ bool isSuffixPattern( const QString & pattern ); // // Data members // QString _name; QColor _color; QStringList _caseInsensitiveSuffixList; QStringList _caseSensitiveSuffixList; QRegExpList _patternList; }; // class MimeCategory typedef QList MimeCategoryList; /** * Human-readable output of a MimeCategory in a debug stream. **/ inline QTextStream & operator<< ( QTextStream & str, MimeCategory * category ) { if ( category ) str << "name() << ">"; else str << ""; return str; } } // namespace QDirStat #endif // MimeCategory_h qdirstat-1.4/src/MimeCategoryConfigPage.cpp000066400000000000000000000176061311502036700210240ustar00rootroot00000000000000/* * File name: MimeCategoryConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include // time() #include // random(), srandom() #include #include #include "MimeCategoryConfigPage.h" #include "DirTree.h" #include "DirInfo.h" #include "FileInfo.h" #include "FileInfo.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; // This is a mess that became necessary because Qt's moc cannot handle template // classes. Yes, this is ugly. #define CATEGORY_CAST(VOID_PTR) (static_cast(VOID_PTR)) MimeCategoryConfigPage::MimeCategoryConfigPage( QWidget * parent ): ListEditor( parent ), _ui( new Ui::MimeCategoryConfigPage ), _categorizer( 0 ), _dirTree( 0 ) { CHECK_NEW( _ui ); _ui->setupUi( this ); setListWidget ( _ui->listWidget ); setAddButton ( _ui->addButton ); setRemoveButton( _ui->removeButton ); _ui->treemapView->setFixedColor( Qt::white ); populateTreemapView(); connect( _ui->nameLineEdit, SIGNAL( textChanged ( QString ) ), this, SLOT ( nameChanged( QString ) ) ); connect( _ui->colorLineEdit, SIGNAL( textChanged ( QString ) ), this, SLOT ( colorChanged( QString ) ) ); connect( _ui->colorButton, SIGNAL( clicked() ), this, SLOT ( pickColor() ) ); } MimeCategoryConfigPage::~MimeCategoryConfigPage() { logDebug() << "MimeCategoryConfigPage destructor" << endl; _ui->treemapView->setDirTree(0); if ( _dirTree ) delete _dirTree; } void MimeCategoryConfigPage::setup() { fillListWidget(); updateActions(); } void MimeCategoryConfigPage::applyChanges() { logDebug() << endl; save( value( listWidget()->currentItem() ) ); _categorizer->writeSettings(); } void MimeCategoryConfigPage::discardChanges() { logDebug() << endl; listWidget()->clear(); _categorizer->clear(); _categorizer->readSettings(); } void MimeCategoryConfigPage::fillListWidget() { CHECK_PTR( _categorizer ); listWidget()->clear(); foreach ( MimeCategory * category, _categorizer->categories() ) { QListWidgetItem * item = new ListEditorItem( category->name(), category ); CHECK_NEW( item ); listWidget()->addItem( item ); } QListWidgetItem * firstItem = listWidget()->item(0); if ( firstItem ) listWidget()->setCurrentItem( firstItem ); } void MimeCategoryConfigPage::nameChanged( const QString & newName ) { QListWidgetItem * currentItem = listWidget()->currentItem(); if ( currentItem ) { MimeCategory * category = CATEGORY_CAST( value( currentItem ) ); category->setName( newName ); currentItem->setText( newName ); } } void MimeCategoryConfigPage::colorChanged( const QString & newColor ) { QListWidgetItem * currentItem = listWidget()->currentItem(); if ( currentItem ) { QColor color( newColor ); if ( color.isValid() ) { MimeCategory * category = CATEGORY_CAST( value( currentItem ) ); category->setColor( color ); _ui->treemapView->setFixedColor( color ); _ui->treemapView->rebuildTreemap(); } } } void MimeCategoryConfigPage::pickColor() { QListWidgetItem * currentItem = listWidget()->currentItem(); if ( currentItem ) { MimeCategory * category = CATEGORY_CAST( value( currentItem ) ); QColor color = category->color(); color = QColorDialog::getColor( color, window(), // parent tr( "Category Color" ) ); if ( color.isValid() ) { category->setColor( color ); _ui->colorLineEdit->setText( color.name() ); _ui->treemapView->setFixedColor( color ); _ui->treemapView->rebuildTreemap(); } } } void MimeCategoryConfigPage::save( void * value ) { MimeCategory * category = CATEGORY_CAST( value ); // logDebug() << category << endl; if ( ! category || updatesLocked() ) return; category->clear(); QString patterns = _ui->caseInsensitivePatternsTextEdit->toPlainText(); category->addPatterns( patterns.split( "\n" ), Qt::CaseInsensitive ); patterns = _ui->caseSensitivePatternsTextEdit->toPlainText(); category->addPatterns( patterns.split( "\n" ), Qt::CaseSensitive ); } void MimeCategoryConfigPage::load( void * value ) { MimeCategory * category = CATEGORY_CAST( value ); // logDebug() << category << endl; if ( ! category || updatesLocked() ) return; _ui->nameLineEdit->setText( category->name() ); QColor color = category->color(); _ui->colorLineEdit->setText( color.isValid() ? category->color().name() : "" ); setPatternList( _ui->caseInsensitivePatternsTextEdit, category->humanReadablePatternList( Qt::CaseInsensitive ) ); setPatternList( _ui->caseSensitivePatternsTextEdit, category->humanReadablePatternList( Qt::CaseSensitive ) ); _ui->treemapView->setFixedColor( color.isValid() ? color : Qt::red ); _ui->treemapView->rebuildTreemap(); } void MimeCategoryConfigPage::setPatternList( QPlainTextEdit * textEdit, const QStringList & patternList ) { QString text = patternList.join( "\n" ); if ( ! text.isEmpty() ) text += "\n"; // Let the user begin writing on a new line textEdit->setPlainText( text ); } void * MimeCategoryConfigPage::createValue() { MimeCategory * category = new MimeCategory( "", Qt::white ); CHECK_NEW( category ); _categorizer->add( category ); return category; } void MimeCategoryConfigPage::removeValue( void * value ) { MimeCategory * category = CATEGORY_CAST( value ); CHECK_PTR( category ); _categorizer->remove( category ); } QString MimeCategoryConfigPage::valueText( void * value ) { MimeCategory * category = CATEGORY_CAST( value ); CHECK_PTR( category ); return category->name(); } QString MimeCategoryConfigPage::deleteConfirmationMessage( void * value ) { MimeCategory * category = CATEGORY_CAST( value ); return tr( "Really delete category \"%1\"?" ).arg( category->name() ); } void MimeCategoryConfigPage::populateTreemapView() { _dirTree = new DirTree(); CHECK_NEW( _dirTree ); DirInfo * root = _dirTree->root(); mode_t mode = 0755; FileSize dirSize = 4096; time_t mtime = 0; // Create a very basic directory structure: // // demo // dir1 // dir2 // dir21 DirInfo * topDir = new DirInfo( _dirTree, root, "demo", mode, dirSize, mtime ); CHECK_NEW( topDir ); root->insertChild( topDir ); DirInfo * dir1 = new DirInfo( _dirTree, topDir, "dir1", mode, dirSize, mtime ); CHECK_NEW( dir1 ); topDir->insertChild( dir1 ); DirInfo * dir2 = new DirInfo( _dirTree, topDir, "dir2", mode, dirSize, mtime ); CHECK_NEW( dir2 ); topDir->insertChild( dir2 ); DirInfo * dir21 = new DirInfo( _dirTree, dir2, "dir21", mode, dirSize, mtime ); CHECK_NEW( dir21 ); dir2->insertChild( dir21 ); // Collect all directories in a list to pick from at random QList dirs; dirs << topDir << dir1 << dir2 << dir21; srandom( (unsigned) time(0) ); // Seed random number generator int fileCount = random() % 30 + 12; FileSize maxSize = 100*1024*1024; // 100 MB // Generate a random number of files with random sizes for ( int i=0; i < fileCount; i++ ) { // Pick a random directory as parent int dirNo = random() % dirs.size(); DirInfo * parent = dirs.at( dirNo ); // Select a random file size FileSize fileSize = random() % maxSize; // Create a FileInfo item and add it to the parent FileInfo * file = new FileInfo( _dirTree, parent, QString( "File_%1" ).arg( i ), mode, fileSize, mtime ); CHECK_NEW( file ); parent->insertChild( file ); } logDebug() << "Demo tree: " << fileCount << " files with " << formatSize( topDir->totalSize() ) << " total" << endl; _ui->treemapView->setDirTree( _dirTree ); } qdirstat-1.4/src/MimeCategoryConfigPage.h000066400000000000000000000066431311502036700204700ustar00rootroot00000000000000/* * File name: MimeCategoryConfigPage.h * Summary: QDirStat configuration dialog classes * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef MimeCategoryConfigPage_h #define MimeCategoryConfigPage_h #include "ListEditor.h" #include "ui_mime-category-config-page.h" #include "MimeCategorizer.h" namespace QDirStat { /** * Configuration page (tab) for MimeCategories: * Edit, add, delete categories in the MimeCategorizer. **/ class MimeCategoryConfigPage: public ListEditor { Q_OBJECT public: MimeCategoryConfigPage( QWidget * parent = 0 ); virtual ~MimeCategoryConfigPage(); /** * Set the MimeCategorizer to work on. **/ void setMimeCategorizer( MimeCategorizer * categorizer ) { _categorizer = categorizer; } /** * Return the internal MimeCategorizer. **/ MimeCategorizer * mimeCategorizer() const { return _categorizer; } public slots: /** * Populate the widgets. **/ void setup(); /** * Write changes back to the settings. **/ void applyChanges(); /** * Abandon changes and revert everything to the original settings. **/ void discardChanges(); protected slots: /** * Notification that the user changed the "Name" field of the * current category. **/ void nameChanged( const QString & newName ); /** * Notification that the user changed the "Color" field of the * current category. **/ void colorChanged( const QString & newColor ); protected slots: /** * Open a color dialog and let the user pick a color for the current * category. **/ void pickColor(); protected: /** * Fill the category list widget from the category collection. * * Implemented from ListEditor. **/ virtual void fillListWidget() Q_DECL_OVERRIDE; /** * Save the contents of the widgets to the specified category. **/ virtual void save( void * value ) Q_DECL_OVERRIDE; /** * Load the content of the widgets from the specified category. **/ virtual void load( void * value ) Q_DECL_OVERRIDE; /** * Create a new value with default values. * This is called when the 'Add' button is clicked. * * Implemented from ListEditor. **/ virtual void * createValue() Q_DECL_OVERRIDE; /** * Remove a value from the internal list and delete it. * * This is called when the 'Remove' button is clicked and the user * confirms the confirmation pop-up. * * Implemented from ListEditor. **/ virtual void removeValue( void * value ); /** * Return a text for the list item of 'value'. * * Implemented from ListEditor. **/ virtual QString valueText( void * value ) Q_DECL_OVERRIDE; /** * Return the message for the 'really delete?' message for the current * item ('value'). If this returns an empty string, the item cannot be * deleted. * * Implemented from ListEditor. **/ virtual QString deleteConfirmationMessage( void * value ) Q_DECL_OVERRIDE; /** * Convert 'patternList' into a newline-separated string and set it as * text of 'textEdit'. **/ void setPatternList( QPlainTextEdit * textEdit, const QStringList & patternList ); /** * Add demo content to the tremap view. **/ void populateTreemapView(); // Data Ui::MimeCategoryConfigPage * _ui; MimeCategorizer * _categorizer; DirTree * _dirTree; }; // class MimeCategoryConfigPage } // namespace QDirStat #endif // MimeCategoryConfigPage_h qdirstat-1.4/src/MountPoints.cpp000066400000000000000000000121051311502036700170000ustar00rootroot00000000000000/* * File name: MountPoints.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "MountPoints.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; MountPoint::MountPoint( const QString & device, const QString & path, const QString & filesystemType, const QString & mountOptions ) : _device( device ), _path( path ), _filesystemType( filesystemType ) { _mountOptions = mountOptions.split( "," ); } QString MountPoint::mountOptionsStr() const { return _mountOptions.join( "," ); } bool MountPoint::isBtrfs() const { return _filesystemType.toLower() == "btrfs"; } MountPoints * MountPoints::_instance = 0; MountPoints * MountPoints::instance() { if ( ! _instance ) { _instance = new MountPoints(); CHECK_NEW( _instance ); } return _instance; } MountPoints::MountPoints() { init(); } MountPoints::~MountPoints() { init(); } void MountPoints::init() { qDeleteAll( _mountPointMap ); _mountPointMap.clear(); _isPopulated = false; _hasBtrfs = false; _checkedForBtrfs = false; } void MountPoints::clear() { if ( _instance ) _instance->init(); } bool MountPoints::isEmpty() { instance()->ensurePopulated(); return instance()->_mountPointMap.isEmpty(); } const MountPoint * MountPoints::findByPath( const QString & path ) { instance()->ensurePopulated(); return instance()->_mountPointMap.value( path, 0 ); } const MountPoint * MountPoints::findNearestMountPoint( const QString & startPath ) { QFileInfo fileInfo( startPath ); QString path = fileInfo.canonicalFilePath(); // absolute path without symlinks or .. if ( path != startPath ) logDebug() << startPath << " canonicalized is " << path << endl; const MountPoint * mountPoint = findByPath( path ); if ( ! mountPoint ) { QStringList pathComponents = startPath.split( "/", QString::SkipEmptyParts ); while ( ! mountPoint && !pathComponents.isEmpty() ) { // Try one level upwards pathComponents.removeLast(); path = QString( "/" ) + pathComponents.join( "/" ); mountPoint = instance()->_mountPointMap.value( path, 0 ); } } // logDebug() << "Nearest mount point for " << startPath << " is " << mountPoint << endl; return mountPoint; } bool MountPoints::hasBtrfs() { instance()->ensurePopulated(); if ( ! _instance->_checkedForBtrfs ) { _instance->_hasBtrfs = _instance->checkForBtrfs(); _instance->_checkedForBtrfs = true; } return _instance->_hasBtrfs; } void MountPoints::ensurePopulated() { if ( _isPopulated ) return; read( "/proc/mounts" ) || read( "/etc/mtab" ); if ( ! _isPopulated ) logError() << "Could not read either /proc/mounts or /etc/mtab" << endl; _isPopulated = true; } bool MountPoints::read( const QString & filename ) { QFile file( filename ); if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { logWarning() << "Can't open " << filename << endl; return false; } QTextStream in( &file ); int lineNo = 0; int count = 0; QString line = in.readLine(); while ( ! line.isNull() ) // in.atEnd() always returns true for /proc/* { ++lineNo; QStringList fields = line.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); if ( fields.isEmpty() ) // allow empty lines continue; if ( fields.size() < 4 ) { logError() << "Bad line " << filename << ":" << lineNo << ": " << line << endl; continue; } // File format (/proc/mounts or /etc/mtab): // // /dev/sda6 / ext4 rw,relatime,errors=remount-ro,data=ordered 0 0 // /dev/sda7 /work ext4 rw,relatime,data=ordered 0 0 // nas:/share/work /nas/work nfs rw,local_lock=none 0 0 QString device = fields[0]; QString path = fields[1]; QString fsType = fields[2]; QString mountOpts = fields[3]; // ignoring fsck and dump order (0 0) MountPoint * mountPoint = new MountPoint( device, path, fsType, mountOpts ); CHECK_NEW( mountPoint ); _mountPointMap[ path ] = mountPoint; ++count; line = in.readLine(); } if ( count < 1 ) logWarning() << "Not a single mount point in " << filename << endl; else _isPopulated = true; return _isPopulated; } bool MountPoints::checkForBtrfs() { ensurePopulated(); foreach ( const MountPoint * mountPoint, _mountPointMap ) { if ( mountPoint && mountPoint->isBtrfs() ) return true; } return false; } void MountPoints::dump() { foreach ( const MountPoint * mountPoint, instance()->_mountPointMap ) { logDebug() << mountPoint << endl; } } qdirstat-1.4/src/MountPoints.h000066400000000000000000000130131311502036700164440ustar00rootroot00000000000000/* * File name: MountPoints.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef MountPoints_h #define MountPoints_h #include #include #include #include namespace QDirStat { /** * Helper class to represent one mount point of a Linux/Unix filesystem. **/ class MountPoint { public: /** * Constructor. **/ MountPoint( const QString & device, const QString & path, const QString & filesystemType, const QString & mountOptions ); /** * Return the device that is mounted, someting like "/dev/sda3", * "/dev/mapper/crypto", "nas:/share/work". **/ QString device() const { return _device; } /** * Return the path where the device is mounted to. **/ QString path() const { return _path; } /** * Return the filesystem type as string ("ext4", "btrfs", "none". **/ QString filesystemType() const { return _filesystemType; } /** * Return the individual mount options as a list of strings * ["rw", "nosuid", "nodev", "relatime", "rsize=32768"]. **/ QStringList mountOptions() const { return _mountOptions; } /** * Return the mount options as one comma-separated string. **/ QString mountOptionsStr() const; /** * Return 'true' if the filesystem type of this mount point is "btrfs". **/ bool isBtrfs() const; protected: QString _device; QString _path; QString _filesystemType; QStringList _mountOptions; }; // class MountPoint /** * Singleton class to access the current mount points. **/ class MountPoints { public: /** * Return the singleton object for this class. The first use will * create the singleton. Notice that most of the static methods access * the singleton, too, so the first call to most of those static * methods will already create the singleton. **/ static MountPoints * instance(); /** * Clear the content of the singleton. This is useful whenever the * mount points in the system might have changed, i.e. when a * filesystem might have been mounted or unmounted. * * This does not create the singleton if it doesn't exist yet. **/ static void clear(); /** * Return 'true' if there are no mount points at all. **/ static bool isEmpty(); /** * Return the mount point for 'path' if there is one or 0 if there is * not. Ownership of the returned object is not transferred to the * caller, i.e. the caller should not delete it. The pointer remains * valid until the next call to clear(). **/ static const MountPoint * findByPath( const QString & path ); /** * Find the nearest mount point upwards in the directory hierarchy * starting from 'path'. 'path' itself might be that mount point. * Ownership of the returned object is not transferred to the caller. * * This might return 0 if none of the files containing mount * information (/proc/mounts, /etc/mtab) could be read. **/ static const MountPoint * findNearestMountPoint( const QString & path ); /** * Return 'true' if any mount point has filesystem type "btrfs". **/ static bool hasBtrfs(); /** * Ensure the mount points are populated with the content of * /proc/mounts, falling back to /etc/mtab if /proc/mounts cannot be * read. **/ void ensurePopulated(); /** * Dump all current mount points to the log. This does not call * ensurePopulated() first. **/ static void dump(); protected: /** * Constructor. Not for public use. Use instance() or the static * methods instead. **/ MountPoints(); /** * Destructor. **/ virtual ~MountPoints(); /** * Clear the content of this class. **/ void init(); /** * Read 'filename' (in /proc/mounts or /etc/mnt syntax) and populate * the mount points with the content. Return 'true' on success, 'false' * on failure. **/ bool read( const QString & filename ); /** * Check if any of the mount points has filesystem type "btrfs". **/ bool checkForBtrfs(); // // Data members // static MountPoints * _instance; QMap _mountPointMap; bool _isPopulated; bool _hasBtrfs; bool _checkedForBtrfs; }; // class MountPoints inline QTextStream & operator<< ( QTextStream & stream, const MountPoint * mp ) { if ( mp ) { stream << "device() << " at " << mp->path() << " type " << mp->filesystemType() << ">"; } else stream << ""; return stream; } } // namespace QDirStat #endif // MountPoints_h qdirstat-1.4/src/OutputWindow.cpp000066400000000000000000000300321311502036700171700ustar00rootroot00000000000000/* * File name: OutputWindow.cpp * Summary: Terminal-like window to watch output of an external process * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "OutputWindow.h" #include "Settings.h" #include "SettingsHelpers.h" #include "Logger.h" #include "Exception.h" using QDirStat::readColorEntry; using QDirStat::writeColorEntry; using QDirStat::readFontEntry; using QDirStat::writeFontEntry; #define CONNECT_ACTION(ACTION, RECEIVER, RCVR_SLOT) \ connect( (ACTION), SIGNAL( triggered() ), (RECEIVER), SLOT( RCVR_SLOT ) ) OutputWindow::OutputWindow( QWidget * parent ): QDialog( parent ), _ui( new Ui::OutputWindow ), _showOnStderr( true ), _noMoreProcesses( false ), _closed( false ), _killedAll( false ), _errorCount( 0 ) { _ui->setupUi( this ); logDebug() << "Creating" << endl; readSettings(); _ui->terminal->clear(); setAutoClose( false ); CONNECT_ACTION( _ui->actionZoomIn, this, zoomIn() ); CONNECT_ACTION( _ui->actionZoomOut, this, zoomOut() ); CONNECT_ACTION( _ui->actionResetZoom, this, resetZoom() ); CONNECT_ACTION( _ui->actionKillProcess, this, killAll() ); updateActions(); } OutputWindow::~OutputWindow() { logDebug() << "Destructor" << endl; if ( ! _processList.isEmpty() ) { logWarning() << _processList.size() << " processes left over" << endl; foreach ( Process * process, _processList ) logWarning() << "Left over: " << process << endl; qDeleteAll( _processList ); } writeSettings(); } void OutputWindow::addProcess( Process * process ) { CHECK_PTR( process ); if ( _killedAll ) { logInfo() << "User killed all processes - " << "no longer accepting new processes" << endl; process->kill(); process->deleteLater(); } _processList << process; // logDebug() << "Adding " << process << endl; connect( process, SIGNAL( readyReadStandardOutput() ), this, SLOT ( readStdout() ) ); connect( process, SIGNAL( readyReadStandardError() ), this, SLOT ( readStderr() ) ); connect( process, SIGNAL( error ( QProcess::ProcessError ) ), this, SLOT ( processError( QProcess::ProcessError ) ) ); connect( process, SIGNAL( finished ( int, QProcess::ExitStatus ) ), this, SLOT ( processFinished( int, QProcess::ExitStatus ) ) ); if ( ! hasActiveProcess() ) startNextProcess(); } void OutputWindow::addCommandLine( const QString commandline ) { addText( commandline, _commandTextColor ); } void OutputWindow::addStdout( const QString output ) { addText( output, _stdoutColor ); } void OutputWindow::addStderr( const QString output ) { _errorCount++; addText( output, _stderrColor ); logWarning() << output << ( output.endsWith( "\n" ) ? "" : "\n" ); if ( _showOnStderr && ! isVisible() && ! _closed ) show(); } void OutputWindow::addText( const QString & rawText, const QColor & textColor ) { if ( rawText.isEmpty() ) return; QString text = rawText; if ( ! text.endsWith( "\n" ) ) text += "\n"; _ui->terminal->moveCursor( QTextCursor::End ); QTextCursor cursor( _ui->terminal->textCursor() ); QTextCharFormat format; format.setForeground( QBrush( textColor ) ); cursor.setCharFormat( format ); cursor.insertText( text ); } void OutputWindow::clearOutput() { _ui->terminal->clear(); } Process * OutputWindow::senderProcess( const char * function ) const { Process * process = qobject_cast( sender() ); if ( ! process ) { if ( sender() ) { logError() << "Expecting QProcess as sender() in " << function <<" , got " << sender()->metaObject()->className() << endl; } else { logError() << "NULL sender() in " << function << endl; } } return process; } void OutputWindow::readStdout() { Process * process = senderProcess( __FUNCTION__ ); if ( process ) addStdout( QString::fromUtf8( process->readAllStandardOutput() ) ); } void OutputWindow::readStderr() { Process * process = senderProcess( __FUNCTION__ ); if ( process ) addStderr( QString::fromUtf8( process->readAllStandardError() ) ); } void OutputWindow::processFinished( int exitCode, QProcess::ExitStatus exitStatus ) { switch ( exitStatus ) { case QProcess::NormalExit: logDebug() << "Process finished normally." << endl; addCommandLine( tr( "Process finished." ) ); break; case QProcess::CrashExit: if ( exitCode == 0 ) { // Don't report an exit code of 0: Since we are starting all // processes with a shell, that exit code would be the exit // code of the shell; that would only be useful if the shell // crashed or could not be started. logError() << "Process crashed." << endl; addStderr( tr( "Process crashed." ) ); } else { logError() << "Process crashed. Exit code: " << exitCode << endl; addStderr( tr( "Process crashed. Exit code: %1" ).arg( exitCode ) ); } break; } Process * process = senderProcess( __FUNCTION__ ); if ( process ) { _processList.removeAll( process ); if ( _processList.isEmpty() && _noMoreProcesses ) { logDebug() << "Emitting lastProcessFinished() err: " << _errorCount << endl; emit lastProcessFinished( _errorCount ); } process->deleteLater(); closeIfDone(); } startNextProcess(); // this also calls updateActions() } void OutputWindow::processError( QProcess::ProcessError error ) { QString msg; switch ( error ) { case QProcess::FailedToStart: msg = tr( "Error: Process failed to start." ); break; case QProcess::Crashed: // Already reported via processFinished() break; case QProcess::Timedout: msg = tr( "Error: Process timed out." ); break; case QProcess::ReadError: msg = tr( "Error reading output from the process." ); break; case QProcess::WriteError: msg = tr( "Error writing data to the process." ); break; case QProcess::UnknownError: msg = tr( "Unknown error." ); break; } if ( ! msg.isEmpty() ) { logError() << msg << endl; addStderr( msg ); } Process * process = senderProcess( __FUNCTION__ ); if ( process ) { _processList.removeAll( process ); if ( _processList.isEmpty() && _noMoreProcesses ) { logDebug() << "Emitting lastProcessFinished() err: " << _errorCount << endl; emit lastProcessFinished( _errorCount ); } process->deleteLater(); } startNextProcess(); // this also calls updateActions() if ( ! _showOnStderr && ! isVisible() ) closeIfDone(); } void OutputWindow::closeIfDone() { if ( _processList.isEmpty() && _noMoreProcesses ) { if ( ( autoClose() && _errorCount == 0 ) || _closed || ! isVisible() ) { logDebug() << "No more processes to watch. Auto-closing." << endl; this->deleteLater(); // It is safe to call this multiple times } } } void OutputWindow::noMoreProcesses() { _noMoreProcesses = true; if ( _processList.isEmpty() && _noMoreProcesses ) { logDebug() << "Emitting lastProcessFinished() err: " << _errorCount << endl; emit lastProcessFinished( _errorCount ); } closeIfDone(); } void OutputWindow::zoom( double factor ) { QFont font = _ui->terminal->font(); if ( font.pixelSize() != -1 ) { int pixelSize = qRound( font.pixelSize() * factor ); logDebug() << "New font size: " << pixelSize << " pixels" << endl; font.setPixelSize( pixelSize ); } else { qreal pointSize = font.pointSize() * factor; logDebug() << "New font size: " << pointSize << " points" << endl; font.setPointSize( pointSize ); } _ui->terminal->setFont( font ); } void OutputWindow::zoomIn() { zoom( 1.1 ); } void OutputWindow::zoomOut() { zoom( 1.0/1.1 ); } void OutputWindow::resetZoom() { logDebug() << "Resetting font to normal" << endl; _ui->terminal->setFont( _terminalDefaultFont ); } void OutputWindow::killAll() { int killCount = 0; foreach ( Process * process, _processList ) { logInfo() << "Killing process " << process << endl; process->kill(); _processList.removeAll( process ); process->deleteLater(); ++killCount; } _killedAll = true; addCommandLine( killCount == 1 ? tr( "Process killed." ) : tr( "Killed %1 processes." ).arg( killCount ) ); } #if 0 void OutputWindow::setTerminalBackground( const QColor & newColor ) { // TO DO // TO DO // TO DO } #endif bool OutputWindow::hasActiveProcess() const { foreach ( Process * process, _processList ) { if ( process->state() == QProcess::Starting || process->state() == QProcess::Running ) { return true; } } return false; } Process * OutputWindow::pickQueuedProcess() { foreach ( Process * process, _processList ) { if ( process->state() == QProcess::NotRunning ) return process; } return 0; } Process * OutputWindow::startNextProcess() { Process * process = pickQueuedProcess(); if ( process ) { QString dir = process->workingDirectory(); if ( dir != _lastWorkingDir ) { addCommandLine( "cd " + dir ); _lastWorkingDir = dir; } addCommandLine( command( process ) ); logInfo() << "Starting: " << process << endl; process->start(); qApp->processEvents(); // Keep GUI responsive } updateActions(); return process; } QString OutputWindow::command( Process * process ) { // The common case is to start an external command with // /bin/sh -c theRealCommand arg1 arg2 arg3 ... QStringList args = process->arguments(); if ( ! args.isEmpty() ) args.removeFirst(); // Remove the "-c" if ( args.isEmpty() ) // Nothing left? return process->program(); // Ok, use the program name else return args.join( " " ); // output only the real command and its args } bool OutputWindow::autoClose() const { return _ui->autoCloseCheckBox->isChecked(); } void OutputWindow::setAutoClose( bool autoClose ) { _ui->autoCloseCheckBox->setChecked( autoClose ); } void OutputWindow::closeEvent( QCloseEvent * event ) { _closed = true; if ( _processList.isEmpty() && _noMoreProcesses ) this->deleteLater(); // If there are any more processes, wait until the last one is finished and // then deleteLater(). event->accept(); } void OutputWindow::updateActions() { _ui->killButton->setEnabled( hasActiveProcess() ); } void OutputWindow::showAfterTimeout( int timeoutMillisec ) { if ( timeoutMillisec <= 0 ) timeoutMillisec = _defaultShowTimeout; QTimer::singleShot( timeoutMillisec, this, SLOT( timeoutShow() ) ); } void OutputWindow::timeoutShow() { if ( ! isVisible() && ! _closed ) show(); } void OutputWindow::readSettings() { QDirStat::Settings settings; settings.beginGroup( "OutputWindow" ); _terminalBackground = readColorEntry( settings, "TerminalBackground", QColor( Qt::black ) ); _commandTextColor = readColorEntry( settings, "CommandTextColor" , QColor( Qt::white ) ); _stdoutColor = readColorEntry( settings, "StdoutTextColor" , QColor( 0xff, 0xaa, 0x00 ) ); _stderrColor = readColorEntry( settings, "StdErrTextColor" , QColor( Qt::red ) ); _terminalDefaultFont = readFontEntry ( settings, "TerminalFont" , _ui->terminal->font() ); _defaultShowTimeout = settings.value( "DefaultShowTimeoutMillisec", 500 ).toInt(); settings.endGroup(); _ui->terminal->setFont( _terminalDefaultFont ); } void OutputWindow::writeSettings() { QDirStat::Settings settings; settings.beginGroup( "OutputWindow" ); writeColorEntry( settings, "TerminalBackground", _terminalBackground ); writeColorEntry( settings, "CommandTextColor" , _commandTextColor ); writeColorEntry( settings, "StdoutTextColor" , _stdoutColor ); writeColorEntry( settings, "StdErrTextColor" , _stderrColor ); writeFontEntry ( settings, "TerminalFont" , _terminalDefaultFont ); settings.setValue( "DefaultShowTimeoutMillisec", _defaultShowTimeout ); settings.endGroup(); } qdirstat-1.4/src/OutputWindow.h000066400000000000000000000227211311502036700166430ustar00rootroot00000000000000/* * File name: OutputWindow.h * Summary: Terminal-like window to watch output of an external process * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef OutputWindow_h #define OutputWindow_h #include #include #include #include #include "ui_output-window.h" #include "Process.h" class QCloseEvent; using QDirStat::Process; /** * Terminal-like window to watch output of external processes started via * QProcess. The command invoked by the process, its stdout and stderr output * are displayed in different colors. * * This class can watch more than one process: It can watch a sequence of * processes, such as QDirStat cleanup actions as they are invoked for each * selected item one after another, or even multiple processes running in * parallel (which may make the output a bit messy, of course). * * If this dialog is created, but now shown, it will (by default) show itself * as soon as there is any output on stderr. **/ class OutputWindow: public QDialog { Q_OBJECT public: /** * Constructor. **/ OutputWindow( QWidget * parent ); /** * Destructor. **/ virtual ~OutputWindow(); /** * Add a process to watch. Ownership of the process is transferred to this * object. If the process is not started yet, it will be started as soon as * there is no other one running. **/ void addProcess( Process * process ); /** * Tell this dialog that no more processes will be added, so when the last * one is finished and the "auto close" checkbox is checked, it may close * itself. **/ void noMoreProcesses(); /** * Return the number of errors the processes reported. **/ int errorCount() const { return _errorCount; } /** * Return 'true' if this dialog closes itself automatically after the last * process finished successfully. **/ bool autoClose() const; /** * Set if this dialog should close itself automatically after the last * process finished successfully. **/ void setAutoClose( bool autoClose ); /** * Set if this dialog should show itself if there is any output on * stderr. The default is 'true'. * * This means an application can create the dialog and leave it hidden, and * if there is any error output, it will automatically show itself -- with * all previous output of the watched processes on stdout and stderr. * If the user closes the dialog, however, it will remain closed. **/ void setShowOnStderr( bool show ) { _showOnStderr = show; } /** * Return 'true' if this dialog shows itself if there is any output on * stderr. **/ bool showOnStderr() const { return _showOnStderr; } /** * Show window (if not already shown) after the specified timeout has * elapsed. This is useful for operations that might be very short, so no * output window is desired, but that sometimes might also take a while. * * If 'timeoutMillisec' is 0, defaultShowTimeout() is used. **/ void showAfterTimeout( int timeoutMillisec = 0 ); /** * Return the default show timeout in milliseconds. **/ int defaultShowTimeout() const { return _defaultShowTimeout; } /** * set the default show timeout (in milliseconds). **/ void setDefaultShowTimeout( int newTimeoutMillisec ) { _defaultShowTimeout = newTimeoutMillisec; } /** * Return the text color for commands in the terminal area. **/ QColor commandTextColor() const { return _commandTextColor; } /** * Set the text color for commands in the terminal area. **/ void setCommandTextColor( const QColor & newColor ) { _commandTextColor = newColor; } /** * Return the text color for stdout output in the terminal area. **/ QColor stdoutColor() const { return _stdoutColor; } /** * Set the text color for stdout output in the terminal area. **/ void setStdoutColor( const QColor & newColor ) { _stdoutColor = newColor; } /** * Return the text color for stderr output in the terminal area. **/ QColor stderrColor() const { return _stderrColor; } /** * Set the text color for stderr output in the terminal area. **/ void setStderrColor( const QColor & newColor ) { _stderrColor = newColor; } #if 0 /** * Return the background color of the terminal area. **/ QColor terminalBackground() const { return _terminalBackground; } /** * Set the background color of the terminal area. **/ void setTerminalBackground( const QColor & newColor ); #endif /** * Return the internal process list. **/ const QList & processList() const { return _processList; } /** * Return 'true' if any process in the internal process is still active. **/ bool hasActiveProcess() const; /** * Get the command of the process. Since usually processes are started via * a shell ("/bin/sh -c theRealCommand arg1 arg2 ..."), this is typically * not QProcess::program(), but the arguments minus the "-c". **/ static QString command( Process * process ); public slots: /** * Add a command line to show in the output area. * This is typically displayed in white. **/ void addCommandLine( const QString commandline ); /** * Add one or more lines of stdout to show in the output area. * This is typically displayed in amber. **/ void addStdout( const QString output ); /** * Add one or more lines of stderr to show in the output area. * This is typically displayed in red. **/ void addStderr( const QString output ); /** * Kill all processes this class watches. **/ void killAll(); /** * Clear the output area, i.e. remove all previous output and commands. **/ void clearOutput(); /** * Enable or disable actions based on the internal status of this object. **/ void updateActions(); /** * Read parameters from the settings. **/ void readSettings(); /** * Write parameters to the settings. **/ void writeSettings(); protected slots: /** * Read output on one of the watched process's stdout channel. **/ void readStdout(); /** * Read output on one of the watched process's stderr channel. **/ void readStderr(); /** * One of the watched processes finished. **/ void processFinished( int exitCode, QProcess::ExitStatus exitStatus ); /** * One of the watched processes terminated with an error. **/ void processError( QProcess::ProcessError error ); /** * Zoom the output area in, i.e. make its font larger. **/ void zoomIn(); /** * Zoom the output area out, i.e. make its font smaller. **/ void zoomOut(); /** * Reset the output area zoom, i.e. restore its default font. **/ void resetZoom(); /** * Show after timeout has elapsed (unless the user closed this dialog * before) **/ void timeoutShow(); signals: /** * Emitted when the last process finished, no matter if that was successful * or with an error. 'totalErrorCount' is the accumulated error count of * all processes this OutputWindow watched. **/ void lastProcessFinished( int totalErrorCount ); protected: /** * Close event: Invoked upon QDialog::close(), i.e. the "Close" button, the * window manager close button (the [x] at the top right), or when this * dialog decides to auto-close itself after the last process finishes * successfully. * * This object will delete itself in this event if there are no more * processes to watch. * * Reimplemented from QDialog / QWidget. **/ void closeEvent( QCloseEvent * event ) Q_DECL_OVERRIDE; /** * Close if there are no more processes and there is no error to show. **/ void closeIfDone(); /** * Add one or more lines of text in text color 'textColor' to the output * area. **/ void addText( const QString & text, const QColor & textColor ); /** * Obtain the process to use from sender(). Return 0 if this is not a * QProcess. **/ Process * senderProcess( const char * callingFunctionName ) const; /** * Pick the next inactive process that can be started. Return 0 if there is * none. **/ Process * pickQueuedProcess(); /** * Try to start the next inactive process, if there is any. Return that * process or 0 if there is none. **/ Process * startNextProcess(); /** * Zoom the terminal font by the specified factor. **/ void zoom( double factor = 1.0 ); // // Data members // Ui::OutputWindow * _ui; QList _processList; bool _showOnStderr; bool _noMoreProcesses; bool _closed; bool _killedAll; int _errorCount; QString _lastWorkingDir; QColor _terminalBackground; QColor _commandTextColor; QColor _stdoutColor; QColor _stderrColor; QFont _terminalDefaultFont; int _defaultShowTimeout; }; // class OutputWindow inline QTextStream & operator<< ( QTextStream & stream, Process * process ) { if ( process ) stream << OutputWindow::command( process ); else stream << ""; return stream; } #endif // OutputWindow_h qdirstat-1.4/src/PercentBar.cpp000066400000000000000000000150761311502036700165400ustar00rootroot00000000000000/* * File name: PercentBar.cpp * Summary: Functions and item delegate for percent bar * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include "PercentBar.h" #include "DirTreeModel.h" #include "Settings.h" #include "SettingsHelpers.h" #include "Exception.h" #include "FileInfo.h" #include "Logger.h" using namespace QDirStat; PercentBarDelegate::PercentBarDelegate( QTreeView * treeView ): QStyledItemDelegate( 0 ), _treeView( treeView ) { _percentBarCol = DataColumns::toViewCol( PercentBarCol ); readSettings(); connect( DataColumns::instance(), SIGNAL( columnsChanged() ), this, SLOT ( columnsChanged() ) ); } PercentBarDelegate::~PercentBarDelegate() { writeSettings(); } ColorList PercentBarDelegate::defaultFillColors() const { ColorList colors; colors << QColor( 0, 0, 255 ) << QColor( 128, 0, 128 ) << QColor( 231, 147, 43 ) << QColor( 4, 113, 0 ) << QColor( 176, 0, 0 ) << QColor( 204, 187, 0 ) << QColor( 162, 98, 30 ) << QColor( 0, 148, 146 ) << QColor( 217, 94, 0 ) << QColor( 0, 194, 65 ) << QColor( 194, 108, 187 ) << QColor( 0, 179, 255 ); return colors; } void PercentBarDelegate::readSettings() { Settings settings; settings.beginGroup( "PercentBar" ); _fillColors = readColorListEntry( settings, "Colors" , defaultFillColors() ); _barBackground = readColorEntry ( settings, "Background", QColor( 160, 160, 160 ) ); _sizeHintWidth = settings.value( "PercentBarColumnWidth", 180 ).toInt(); settings.endGroup(); } void PercentBarDelegate::writeSettings() { Settings settings; settings.beginGroup( "PercentBar" ); writeColorListEntry( settings, "Colors" , _fillColors ); writeColorEntry ( settings, "Background", _barBackground ); settings.setValue( "PercentBarColumnWidth", _sizeHintWidth ); settings.endGroup(); } void PercentBarDelegate::columnsChanged() { _percentBarCol = DataColumns::toViewCol( PercentBarCol ); } void PercentBarDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { if ( ! index.isValid() || index.column() != _percentBarCol ) return QStyledItemDelegate::paint( painter, option, index ); QVariant data = index.data( RawDataRole ); if ( data.isValid() ) { bool ok = true; float percent = data.toFloat( &ok ); if ( ok && percent >= 0.0 ) { if ( percent > 100.0f ) { if ( percent > 103.0f ) logError() << "Percent maxed out: " << percent << endl; percent = 100.0f; } int depth = treeLevel( index ) - 2; // compensate for invisible root and toplevel int indentPixel = ( depth * _treeView->indentation() ) / 2; QColor fillColor = _fillColors.at( depth % _fillColors.size() ); paintPercentBar( percent, painter, indentPixel, option.rect, fillColor, _barBackground ); } else // percent < 0.0 => tree is busy => use as read job column { return QStyledItemDelegate::paint( painter, option, index ); } } } int PercentBarDelegate::treeLevel( const QModelIndex & index ) const { int level = 0; QModelIndex item = index; while ( item.isValid() ) { item = item.parent(); ++level; } return level; } QSize PercentBarDelegate::sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index) const { QSize size = QStyledItemDelegate::sizeHint( option, index ); if ( ! index.isValid() || index.column() != _percentBarCol ) return size; size.setWidth( _sizeHintWidth ); return size; } namespace QDirStat { void paintPercentBar( float percent, QPainter * painter, int indentPixel, const QRect & cellRect, const QColor & fillColor, const QColor & barBackground ) { int penWidth = 2; int extraMargin = 4; int itemMargin = 4; int x = cellRect.x() + itemMargin; int y = cellRect.y() + extraMargin; int w = cellRect.width() - 2 * itemMargin; int h = cellRect.height() - 2 * extraMargin; int fillWidth; painter->eraseRect( cellRect ); w -= indentPixel; x += indentPixel; if ( w > 0 ) { QPen pen( painter->pen() ); pen.setWidth( 0 ); painter->setPen( pen ); painter->setBrush( Qt::NoBrush ); fillWidth = (int) ( ( w - 2 * penWidth ) * percent / 100.0); // Fill bar background. painter->fillRect( x + penWidth, y + penWidth, w - 2 * penWidth + 1, h - 2 * penWidth + 1, barBackground ); /* * Notice: The Xlib XDrawRectangle() function always fills one * pixel less than specified. Altough this is very likely just a * plain old bug, it is documented that way. Obviously, Qt just * maps the fillRect() call directly to XDrawRectangle() so they * inherited that bug (although the Qt doc stays silent about * it). So it is really necessary to compensate for that missing * pixel in each dimension. * * If you don't believe it, see for yourself. * Hint: Try the xmag program to zoom into the drawn pixels. **/ // Fill the desired percentage. painter->fillRect( x + penWidth, y + penWidth, fillWidth+1, h - 2 * penWidth+1, fillColor ); // Draw 3D shadows. QColor background = painter->background().color(); pen.setColor( contrastingColor ( Qt::black, background ) ); painter->setPen( pen ); painter->drawLine( x, y, x+w, y ); painter->drawLine( x, y, x, y+h ); pen.setColor( contrastingColor( barBackground.dark(), background ) ); painter->setPen( pen ); painter->drawLine( x+1, y+1, x+w-1, y+1 ); painter->drawLine( x+1, y+1, x+1, y+h-1 ); pen.setColor( contrastingColor( barBackground.light(), background ) ); painter->setPen( pen ); painter->drawLine( x+1, y+h, x+w, y+h ); painter->drawLine( x+w, y, x+w, y+h ); pen.setColor( contrastingColor( Qt::white, background ) ); painter->setPen( pen ); painter->drawLine( x+2, y+h-1, x+w-1, y+h-1 ); painter->drawLine( x+w-1, y+1, x+w-1, y+h-1 ); } } QColor contrastingColor( const QColor &desiredColor, const QColor &contrastColor ) { if ( desiredColor != contrastColor ) { return desiredColor; } if ( contrastColor != contrastColor.lighter() ) { // try a little lighter return contrastColor.lighter(); } else { // try a little darker return contrastColor.darker(); } } } // namespace QDirStat qdirstat-1.4/src/PercentBar.h000066400000000000000000000060661311502036700162040ustar00rootroot00000000000000/* * File name: PercentBar.h * Summary: Functions and item delegate for percent bar * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef PercentBar_h #define PercentBar_h #include #include #include typedef QList ColorList; class QTreeView; namespace QDirStat { /** * Item delegate class to paint the percent bar in the PercentBarCol. * * This class uses the custom RawDataRole to obtain the data (the subtree * percent) in numeric format from the model. **/ class PercentBarDelegate: public QStyledItemDelegate { Q_OBJECT public: /** * Constructor. * 'percentBarCol' is the (view) column to paint the percent bar in. **/ PercentBarDelegate( QTreeView * treeView ); /** * Destructor. **/ virtual ~PercentBarDelegate(); /** * Paint one cell in the view. * Inherited from QStyledItemDelegate. **/ void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const Q_DECL_OVERRIDE; /** * Return a size hint for one cell in the view. * Inherited from QStyledItemDelegate. **/ QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index) const Q_DECL_OVERRIDE; /** * Return the percent bar fill colors for each tree level. If there * are more tree levels than colors, the colors will wrap around. * * This object reference can be used directly to add, remove or change * colors. **/ ColorList & fillColors() { return _fillColors; } /** * Return the default fill colors. **/ ColorList defaultFillColors() const; /** * Return the percent bar column. **/ int percentBarCol() const { return _percentBarCol; } /** * Set the percent bar column. **/ void setPercentBarCol( int newCol ) { _percentBarCol = newCol; } public slots: /** * Notification that the columns have changed. **/ void columnsChanged(); /** * Read parameters from the settings file. **/ void readSettings(); /** * Write parameters to the settings file. **/ void writeSettings(); protected: /** * Find out the tree depth level of item 'index' by following its * parent, parent's parent etc. to the top. **/ int treeLevel( const QModelIndex & index ) const; // // Data Members // QTreeView * _treeView; ColorList _fillColors; QColor _barBackground; int _sizeHintWidth; int _percentBarCol; }; // class PercentBarDelegate /** * Paint a percent bar into a widget. * 'indentPixel' is the number of pixels to indent the bar. **/ void paintPercentBar( float percent, QPainter * painter, int indentPixel, const QRect & cellRect, const QColor & fillColor, const QColor & barBackground ); /** * Return a color that contrasts with 'contrastColor'. **/ QColor contrastingColor( const QColor &desiredColor, const QColor &contrastColor ); } // namespace QDirStat #endif // PercentBar_h qdirstat-1.4/src/Process.cpp000066400000000000000000000007651311502036700161300ustar00rootroot00000000000000/* * File name: Process.cpp * Summary: Qt4/5 compatibility layer for QProcess * License: GPL V2 - See file LICENSE for details. * * Authors: Michael Matz * Stefan Hundhammer */ #include using namespace QDirStat; Process::Process( QObject *parent ): QProcess( parent ) { // NOP } #if (QT_VERSION < QT_VERSION_CHECK( 5, 1, 0)) void Process::start() { QProcess::start( _prog, _arglist ); } #endif // Qt < 5.1.0 qdirstat-1.4/src/Process.h000066400000000000000000000022261311502036700155670ustar00rootroot00000000000000/* * File name: Process.h * Summary: Qt4/5 compatibility layer for QProcess * License: GPL V2 - See file LICENSE for details. * * Authors: Michael Matz * Stefan Hundhammer */ #ifndef Process_h #define Process_h #include namespace QDirStat { /** * Thin compatibility layer around QProcess to maintain backwards * compatibility to Qt4: Enable creating a process with program to start * and arguments supplied in the constructor and store them for later use * with a plain start() without any more arguments. **/ class Process: public QProcess { Q_OBJECT public: explicit Process( QObject *parent = 0 ); #if (QT_VERSION < QT_VERSION_CHECK( 5, 1, 0)) void start(); const QStringList & arguments() { return _arglist; } const QString & program() { return _prog; } void setProgram( const QString & prog ) { _prog = prog; } void setArguments( const QStringList & args ) { _arglist = args; } private: QString _prog; QStringList _arglist; #endif // Qt < 5.1.0 }; // class Process } // namespace QDirStat #endif // Process_h qdirstat-1.4/src/Qt4Compat.h000066400000000000000000000006211311502036700157620ustar00rootroot00000000000000/* * File name: Qt4Compat.h * Summary: Helpers for Qt4 compatibility * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Qt4Compat_h #define Qt4Compat_h #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) # define setSectionResizeMode setResizeMode # define sectionResizeMode resizeMode #endif #endif // Qt4Compat_h qdirstat-1.4/src/Refresher.cpp000066400000000000000000000030741311502036700164330ustar00rootroot00000000000000/* * File name: Refresher.h * Summary: Helper class to refresh a number of subtrees * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "Refresher.h" #include "DirTree.h" #include "FileInfoSet.h" #include "Logger.h" using namespace QDirStat; Refresher::Refresher( const FileInfoSet items, QObject * parent ): QObject( parent ), _items( items ), _tree( 0 ) { // logDebug() << "Creating refresher for " << _items.size() << " items" << endl; // Storing the tree right now in a separate variable because by the time we // need it (in refresh()) any (or even all) of the items might have become // invalid already, so any attempt to dereference them to obtain the tree // from there might result in a segfault. if ( ! _items.isEmpty() ) _tree = _items.first()->tree(); } void Refresher::refresh() { if ( ! _items.isEmpty() && _tree ) { logDebug() << "Refreshing " << _items.size() << " items" << endl; _tree->refresh( _items ); } else { logWarning() << "No items to refresh" << endl; } this->deleteLater(); } FileInfoSet Refresher::parents( const FileInfoSet children ) { FileInfoSet parents; foreach ( FileInfo * child, children ) { if ( child && child->parent() ) { FileInfo * parent = child->parent(); if ( parent->isDotEntry() ) parent = parent->parent(); if ( parent ) parents << parent; } } return parents.normalized(); } qdirstat-1.4/src/Refresher.h000066400000000000000000000034361311502036700161020ustar00rootroot00000000000000/* * File name: Refresher.h * Summary: Helper class to refresh a number of subtrees * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Refresher_h #define Refresher_h #include #include "FileInfoSet.h" namespace QDirStat { class FileInfo; /** * Helper class to refresh a number of subtrees: * * Store a FileInfoSet and when a signal is received (typically * OutputWindow::lastProcessFinished()), trigger refreshing all stored * subtrees. * * Do not hold on to pointers to instances of this class since each * instance will destroy itself at the end of refresh(). On the other hand, * if the signal triggering refresh() never arrives, this object will stay * forever, so give it a QObject parent (so it will be destroyed when its * parent is destroyed) to avoid a memory leak. **/ class Refresher: public QObject { Q_OBJECT public: /** * Create a Refresher that will refresh all subtrees in 'items' it its * refresh() slot. * * All items are assumed to belong to the same DirTree. **/ Refresher( const FileInfoSet items, QObject * parent ); /** * Return a FileInfoSet of all parents of all items of 'children'. * If a parent is a dot entry, use the true parent, i.e. the dot * entry's parent. **/ static FileInfoSet parents( const FileInfoSet children ); public slots: /** * Refresh all subtrees in the internal FileInfoSet. * After this is done, this object will delete itself. **/ void refresh(); protected: /** * Convert the items to string for logging. **/ QString itemsToString() const; FileInfoSet _items; DirTree * _tree; }; } // namespace QDirStat #endif // Refresher_h qdirstat-1.4/src/SelectionModel.cpp000066400000000000000000000157671311502036700174300ustar00rootroot00000000000000/* * File name: SelectionModel.cpp * Summary: Handling of selected items * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "SelectionModel.h" #include "DirTreeModel.h" #include "DirTree.h" #include "SignalBlocker.h" #include "Exception.h" #include "Logger.h" #define VERBOSE_SELECTION 0 using namespace QDirStat; SelectionModel::SelectionModel( DirTreeModel * dirTreeModel, QObject * parent ): QItemSelectionModel( dirTreeModel, parent ), _dirTreeModel( dirTreeModel ), _currentItem(0), _currentBranch(0), _selectedItemsDirty(false), _verbose(false) { connect( this, SIGNAL( currentChanged ( QModelIndex, QModelIndex ) ), this, SLOT ( propagateCurrentChanged( QModelIndex, QModelIndex ) ) ); connect( this, SIGNAL( selectionChanged ( QItemSelection, QItemSelection ) ), this, SLOT ( propagateSelectionChanged( QItemSelection, QItemSelection ) ) ); connect( dirTreeModel->tree(), SIGNAL( deletingChild ( FileInfo * ) ), this, SLOT ( deletingChildNotify( FileInfo * ) ) ); connect( dirTreeModel->tree(), SIGNAL( clearing() ), this, SLOT ( clear() ) ); } SelectionModel::~SelectionModel() { // NOP } void SelectionModel::clear() { _selectedItems.clear(); _selectedItemsDirty = true; _currentItem = 0; _currentBranch = 0; clearSelection(); } FileInfoSet SelectionModel::selectedItems() { if ( _selectedItemsDirty ) { // Build set of selected items from the selected model indexes _selectedItems.clear(); foreach ( const QModelIndex index, selectedIndexes() ) { if ( index.isValid() ) { FileInfo * item = static_cast( index.internalPointer() ); CHECK_MAGIC( item ); // logDebug() << "Adding " << item << " col " << index.column() << " to selected items" << endl; _selectedItems << item; } } _selectedItemsDirty = false; } return _selectedItems; } void SelectionModel::propagateCurrentChanged( const QModelIndex & newCurrentIndex, const QModelIndex & oldCurrentIndex ) { _currentItem = 0; if ( newCurrentIndex.isValid() ) { _currentItem = static_cast( newCurrentIndex.internalPointer() ); CHECK_MAGIC( _currentItem ); } FileInfo * oldCurrentItem = 0; if ( oldCurrentIndex.isValid() ) { oldCurrentItem = static_cast( oldCurrentIndex.internalPointer() ); CHECK_MAGIC( oldCurrentItem ); } emit currentItemChanged( _currentItem, oldCurrentItem ); } void SelectionModel::propagateSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected ) { Q_UNUSED( selected ); Q_UNUSED( deselected ); _selectedItemsDirty = true; emit selectionChanged(); emit selectionChanged( selectedItems() ); } void SelectionModel::selectItem( FileInfo * item ) { extendSelection( item, true ); // clear } void SelectionModel::extendSelection( FileInfo * item, bool clear ) { if ( item ) { QModelIndex index = _dirTreeModel->modelIndex( item, 0 ); if ( index.isValid() ) { logDebug() << "Selecting " << item << endl; SelectionFlags flags = Select | Rows; if ( clear ) flags |= Clear; select( index, flags ); // emits selectionChanged() } } else { if ( clear ) clearSelection(); // emits selectionChanged() } } void SelectionModel::setSelectedItems( const FileInfoSet & selectedItems ) { if ( _verbose ) logDebug() << "Selecting " << selectedItems.size() << " items" << endl; QItemSelection sel; foreach ( FileInfo * item, selectedItems ) { QModelIndex index = _dirTreeModel->modelIndex( item, 0 ); if ( index.isValid() ) sel.merge( QItemSelection( index, index ), Select ); } select( sel, Clear | Select | Rows ); } void SelectionModel::setCurrentItem( FileInfo * item, bool select ) { if ( _verbose ) logDebug() << item << " select: " << select << endl; if ( select ) clear(); _currentItem = item; if ( item ) { QModelIndex index = _dirTreeModel->modelIndex( item, 0 ); if ( index.isValid() ) { if ( _verbose ) logDebug() << "Setting current to " << index << endl; setCurrentIndex( index, select ? ( Current | Select | Rows ) : Current ); } else { logError() << "NOT FOUND in dir tree: " << item << endl; } } else { #if (QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )) setCurrentIndex( QModelIndex(), Current ); #else clearCurrentIndex(); #endif } } void SelectionModel::setCurrentBranch( FileInfo * item ) { _currentBranch = item; QModelIndex index = _dirTreeModel->modelIndex( item, 0 ); emit currentBranchChanged( item ); emit currentBranchChanged( index ); } void SelectionModel::prepareRefresh( const FileInfoSet & refreshSet ) { FileInfo * current = _currentItem ? _currentItem : refreshSet.first(); DirInfo * dir = 0; if ( current ) { dir = current->isDirInfo() ? current->toDirInfo() : current->parent(); if ( dir && dir->isDotEntry() ) dir = dir->parent(); // Go one directory up from the current item as long as there is an // ancestor (but not that item itself) in the refreshSet. while ( dir && refreshSet.containsAncestorOf( dir ) ) { dir = dir->parent(); } } if ( _verbose ) logDebug() << "Selecting " << dir << endl; setCurrentItem( dir, true ); setCurrentBranch( dir ); } void SelectionModel::deletingChildNotify( FileInfo * deletedChild ) { _selectedItemsDirty = true; _selectedItems.clear(); if ( _currentItem->isInSubtree( deletedChild ) ) setCurrentItem( 0 ); } void SelectionModel::dumpSelectedItems() { logDebug() << "Current item: " << _currentItem << endl; logDebug() << selectedItems().size() << " items selected" << endl; foreach ( FileInfo * item, selectedItems() ) { logDebug() << " Selected: " << item << endl; } logNewline(); } SelectionModelProxy::SelectionModelProxy( SelectionModel * master, QObject * parent ): QObject( parent ) { connect( master, SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ), this, SIGNAL( selectionChanged( QItemSelection, QItemSelection ) ) ); connect( master, SIGNAL( currentChanged( QModelIndex, QModelIndex ) ), this, SIGNAL( currentChanged( QModelIndex, QModelIndex ) ) ); connect( master, SIGNAL( currentColumnChanged( QModelIndex, QModelIndex ) ), this, SIGNAL( currentColumnChanged( QModelIndex, QModelIndex ) ) ); connect( master, SIGNAL( currentRowChanged ( QModelIndex, QModelIndex ) ), this, SIGNAL( currentRowChanged ( QModelIndex, QModelIndex ) ) ); connect( master, SIGNAL( selectionChanged() ), this, SIGNAL( selectionChanged() ) ); connect( master, SIGNAL( selectionChanged( FileInfoSet ) ), this, SIGNAL( selectionChanged( FileInfoSet ) ) ); connect( master, SIGNAL( currentItemChanged( FileInfo *, FileInfo * ) ), this, SIGNAL( currentItemChanged( FileInfo *, FileInfo * ) ) ); } qdirstat-1.4/src/SelectionModel.h000066400000000000000000000207241311502036700170620ustar00rootroot00000000000000/* * File name: SelectionModel.h * Summary: Handling of selected items * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef SelectionModel_h #define SelectionModel_h #include #include "FileInfoSet.h" namespace QDirStat { class FileInfo; class DirTreeModel; /** * Selection model that can translate between QModelIndex and FileInfo * pointers for use with a QModelIndex based Qt item view (e.g., a * TreeView) and any QDirStat::DirTree based view (e.g., the * QDirStat::TreeMapView). * * This is only a thin wrapper around QItemSelectionModel. The * QItemSelectionModel base class is the master with its QModelIndex based * selection; this subclass fetches that QModelIndex selection and * translates each item into a FileInfo pointer on demand. **/ class SelectionModel: public QItemSelectionModel { Q_OBJECT public: /** * Create a SelectionModel that uses the DirTree in 'dirTreeModel'. * This object does not take ownership of 'dirTreeModel'. **/ SelectionModel( DirTreeModel * dirTreeModel, QObject * parent = 0 ); /** * Destructor. **/ virtual ~SelectionModel(); /** * Return all currently selected items as a set. **/ FileInfoSet selectedItems(); /** * Return the current item (the one that has the keyboard focus). * This might return 0 if currently no item has the keyboard focus. **/ FileInfo * currentItem() const { return _currentItem; } /** * Return the DirTreeModel of this object. **/ DirTreeModel * dirTreeModel() const { return _dirTreeModel; } /** * Set 'verbose' mode: Log each selection change. **/ void setVerbose( bool verbose ) { _verbose = verbose; } /** * Return 'true' if verbose mode is set. **/ bool verbose() const { return _verbose; } public slots: /** * Replace the current selection with one item. * If this item is 0, everything is deselected. * This does NOT change the current item. **/ void selectItem( FileInfo * item ); /** * Extend the current selection with one item: Add this item to the set * of selected items. If this item is 0, the selection remains * unchanged. * * This does NOT change the current item. * * If 'clear' is 'true', this will clear the old selection first, so * this has the same effect as selectItem(). **/ void extendSelection( FileInfo * item, bool clear = false ); /** * Set the selected items, i.e., replace the complete selection. **/ void setSelectedItems( const FileInfoSet & selectedItems ); /** * Make 'item' the current item. This is different from the selection: * There is one current item (mostly for the keyboard focus), but there * can be any number of selected items. * * The current item can change the selection: In the tree view in * 'extended selection' mode, [Shift]+[Click] extends the range of * selected items (and makes the clicked item the current item), * [Ctrl]+[Click] toggles the selected state of an item (and makes it * the current item). * * 'item' may be 0. In that case, there is no current item. * * If 'select' is 'true', this also implicitly replaces the selection * with this item, i.e. only this item is selected afterwards. If * 'select' is 'false', the selection remains unchanged. **/ void setCurrentItem( FileInfo * item, bool select = false ); /** * Make 'item' the current branch. This is meant to notify connected * tree views to close all other branches. See also the * currentBranchChanged() signal. **/ void setCurrentBranch( FileInfo * item ); /** * Return the current branch or 0 if there is none. **/ FileInfo * currentBranch() const { return _currentBranch; } /** * Prepare refreshing a set of items: Select a suitable item that will * still be in the tree after refreshing is finished. The idea is to * avoid having no selected item or branch which means having the tree * widget jumping wildly and thus disorienting the user. * * This is done in preparation of refreshing subtrees after cleanup * actions are finished. Refreshing subtrees means deleting the items * in the subtrees. * * 'refreshSet' is the set of items that will be refreshed. Depending * on the refresh policy in a cleanup action, this might be the items * on which the cleanup action is performed, or their respective * parents. **/ void prepareRefresh( const FileInfoSet & refreshSet ); /** * For debugging: Dump the currently selected items and the current * item to the log. **/ void dumpSelectedItems(); signals: /** * Emitted when the current item changes. 'newCurrent' is the new * current item, 'oldCurrent' the previous one. Any of them might be 0. **/ void currentItemChanged( FileInfo * newCurrent, FileInfo * oldCurrent ); /** * Emitted when the selection changes. **/ void selectionChanged(); void selectionChanged( const FileInfoSet & selectedItems ); /** * Emitted when the current branch changes. Tree views can use this to * close all other branches. **/ void currentBranchChanged( const QModelIndex & newCurrentBranch ); void currentBranchChanged( FileInfo * newCurrentBranch ); protected slots: /** * Propagate the QModelIndex based currentChanged() signal to * the FileInfo * based one **/ void propagateCurrentChanged( const QModelIndex & newCurrent, const QModelIndex & oldCurrent ); /** * Propagate the QModelIndex based selectionChanged() signal to * the FileInfo * based one **/ void propagateSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected ); /** * Clear all old contents. **/ void clear(); /** * Notification that a child is about to be deleted. **/ void deletingChildNotify( FileInfo *deletedChild ); protected: // Data members DirTreeModel * _dirTreeModel; FileInfo * _currentItem; FileInfo * _currentBranch; FileInfoSet _selectedItems; bool _selectedItemsDirty; bool _verbose; }; // class SelectionModel /** * Proxy class for SelectionModel: Forward the relevant selection signals * to a receiver. * * The basic idea behind this is to avoid signal ping-pong between the * SelectionModel and any number of conncected view widgets: * * View A sends a "selectionChanged()" signal to the SelectionModel, the * SelectionModel sends that signal to all connected widgets - including * back to view A which initiated it, which then sends the signal again to * the model etc. etc. * * With this proxy class, the view connects the "changed" signals not from * the SelectionModel to itself, but from the SelectionModelProxy (which in * turn connects the signals transparently from the master SelectionModel). * * Now if view A sends the signal, it first blocks signals from its * SelectionModelProxy (preferably using a SignalBlocker), sends the signal * and unblocks signals again from the proxy. This means that view A does * not receive its own signals, but all other connected widgets do. * * If we'd just block all signals from the SelectionModel, the other * widgets would not get notified at all. With this approach, only the * connections from one widget are disabled temporarily. * * Of course, each view has to create and set up its own proxy. They cannot * be shared among views. **/ class SelectionModelProxy: public QObject { Q_OBJECT public: /** * Creates a SelectionModelProxy. This automatically connects the * master SelectionModel's signals to the matching signals of this * object. * * 'parent' is the QObject tree parent for automatic deletion * of this object when the parent is deleted. **/ SelectionModelProxy( SelectionModel * master, QObject * parent = 0 ); signals: // From QItemSelectionModel void selectionChanged( const QItemSelection & selected, const QItemSelection & deselected ); void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); void currentColumnChanged( const QModelIndex & current, const QModelIndex & previous ); void currentRowChanged ( const QModelIndex & current, const QModelIndex & previous ); // from SelectionModel void selectionChanged(); void selectionChanged( const FileInfoSet & selectedItems ); void currentItemChanged( FileInfo * newCurrent, FileInfo * oldCurrent ); }; // class SelectionModelProxy } // namespace QDirStat #endif // SelectionModel_h qdirstat-1.4/src/Settings.cpp000066400000000000000000000064521311502036700163110ustar00rootroot00000000000000/* * File name: Settings.cpp * Summary: Specialized settings classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include "Settings.h" #include "SettingsHelpers.h" #include "Logger.h" #include "Exception.h" using namespace QDirStat; Settings::Settings( const QString & name ): QSettings( QCoreApplication::organizationName(), name.isEmpty()? QCoreApplication::applicationName() : name ), _name( name ) { } Settings::~Settings() { } void Settings::ensureToplevel() { while ( ! group().isEmpty() ) // ensure using toplevel settings endGroup(); } QStringList Settings::findGroups( const QString & groupPrefix ) { QStringList result;; ensureToplevel(); foreach ( const QString & group, childGroups() ) { if ( group.startsWith( groupPrefix ) ) result << group; } return result; } bool Settings::hasGroup( const QString & groupPrefix ) { ensureToplevel(); foreach ( const QString & group, childGroups() ) { if ( group.startsWith( groupPrefix ) ) return true; } return false; } void Settings::removeGroups( const QString & groupPrefix ) { ensureToplevel(); foreach ( const QString & group, childGroups() ) { if ( group.startsWith( groupPrefix ) ) remove( group ); } } void Settings::moveGroups( const QString & groupPrefix, Settings * from, Settings * to ) { CHECK_PTR( from ); CHECK_PTR( to ); if ( ! hasGroup( groupPrefix ) ) { logInfo() << "Migrating " << groupPrefix << "* to " << to->name() << endl; QStringList groups = from->findGroups( groupPrefix ); foreach ( const QString & group, groups ) { // logVerbose() << " Migrating " << group << endl; from->beginGroup( group ); to->beginGroup( group ); QStringList keys = from->allKeys(); foreach( const QString & key, keys ) { // logVerbose() << " Copying " << key << endl; to->setValue( key, from->value( key ) ); } to->endGroup(); from->endGroup(); } } else { #if 0 logVerbose() << "Target settings " << to->name() << " have group " << groupPrefix << " - nothing to migrate" << endl; #endif } from->removeGroups( groupPrefix ); } CleanupSettings::CleanupSettings(): Settings( QCoreApplication::applicationName() + "-cleanup" ) { _groupPrefix = "Cleanup_"; migrate(); } CleanupSettings::~CleanupSettings() { } void CleanupSettings::migrate() { Settings commonSettings; moveGroups( _groupPrefix, &commonSettings, this ); } MimeCategorySettings::MimeCategorySettings(): Settings( QCoreApplication::applicationName() + "-mime" ) { _groupPrefix = "MimeCategory_"; migrate(); } MimeCategorySettings::~MimeCategorySettings() { } void MimeCategorySettings::migrate() { Settings commonSettings; moveGroups( _groupPrefix, &commonSettings, this ); } ExcludeRuleSettings::ExcludeRuleSettings(): Settings( QCoreApplication::applicationName() + "-exclude" ) { _groupPrefix = "ExcludeRule_"; migrate(); } ExcludeRuleSettings::~ExcludeRuleSettings() { } void ExcludeRuleSettings::migrate() { Settings commonSettings; moveGroups( _groupPrefix, &commonSettings, this ); } qdirstat-1.4/src/Settings.h000066400000000000000000000075321311502036700157560ustar00rootroot00000000000000/* * File name: Settings.h * Summary: Specialized settings classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Settings_h #define Settings_h #include #include namespace QDirStat { /** * Specialized QSettings subclass for generic settings, i.e. the main * config file ~/.config/QDirStat/QDirStat.conf * * This class takes care of cleaning up leftovers of previous config file * formats, for example when certain settings groups (cleanups, mime * categories) were moved out from the main config file to specialized * config files. **/ class Settings: public QSettings { Q_OBJECT public: /** * Create a settings object with the specified name. If 'name' is * empty, the application name is used, i.e. the settings are stored in * the main config file. **/ Settings( const QString & name = QString() ); /** * Destructor. **/ virtual ~Settings(); /** * Name of this settings object. This returns an empty string for the * generic settings, i.e. the main config file. **/ const QString & name() const { return _name; } /** * Name of the group prefix of this settings object, e.g. "Cleanup_" * for a derived class that uses settings groups [Cleanup_01], * [Cleanup_02] etc. **/ const QString & groupPrefix() const { return _groupPrefix; } /** * Find all settings groups that start with 'groupPrefix'. **/ QStringList findGroups( const QString & groupPrefix ); /** * Return true if this settings object has any settings group that * starts with 'groupPrefix'. **/ bool hasGroup( const QString & groupPrefix ); /** * Remove all settings groups that start with 'groupPrefix'. **/ void removeGroups( const QString & groupPrefix ); /** * Go to the settings top level **/ void ensureToplevel(); protected: /** * Mmove all settings groups starting with 'groupPrefix' from settings * object 'from' to settings object 'to'. **/ void moveGroups( const QString & groupPrefix, Settings * from, Settings * to ); // Data members QString _name; QString _groupPrefix; }; /** * Specialized settings class for cleanup actions. * * The general idea is that those settings are stored in a separate file so * that entire file can easily replaced by a site administrator. **/ class CleanupSettings: public Settings { Q_OBJECT public: /** * Constructor. **/ CleanupSettings(); /** * Destructor. **/ virtual ~CleanupSettings(); protected: /** * Migrate settings of the common settings (the main config file) to * this one. **/ void migrate(); }; /** * Specialized settings class for MIME categories. * * The general idea is that those settings are stored in a separate file so * that entire file can easily replaced by a site administrator. **/ class MimeCategorySettings: public Settings { Q_OBJECT public: /** * Constructor. **/ MimeCategorySettings(); /** * Destructor. **/ virtual ~MimeCategorySettings(); protected: /** * Migrate settings of the common settings (the main config file) to * this one. **/ void migrate(); }; /** * Specialized settings class for exclude rules. * * The general idea is that those settings are stored in a separate file so * that entire file can easily replaced by a site administrator. **/ class ExcludeRuleSettings: public Settings { Q_OBJECT public: /** * Constructor. **/ ExcludeRuleSettings(); /** * Destructor. **/ virtual ~ExcludeRuleSettings(); protected: /** * Migrate settings of the common settings (the main config file) to * this one. **/ void migrate(); }; } // namespace QDirStat #endif // Settings_h qdirstat-1.4/src/SettingsHelpers.cpp000066400000000000000000000111171311502036700176260ustar00rootroot00000000000000/* * File name: SettingsHelpers.cpp * Summary: Helper functions for QSettings for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include "SettingsHelpers.h" #include "Settings.h" #include "Exception.h" #include "Logger.h" namespace QDirStat { QColor readColorEntry( const QSettings & settings, const char * entryName, const QColor & fallback ) { QString colorName = settings.value( entryName ).toString(); QColor color( colorName ); if ( ! color.isValid() ) { color = fallback; #if 0 logDebug() << "Using fallback for " << entryName << ": " << color.name() << endl; #endif } return color; } void writeColorEntry( QSettings & settings, const char * entryName, const QColor & color ) { settings.setValue( entryName, color.name() ); } QList readColorListEntry( const QSettings & settings, const char * entryName, const QList & fallback ) { QStringList strList = settings.value( entryName ).toStringList(); QList colorList; colorList.clear(); foreach ( const QString & rgb, strList ) { QColor color( rgb ); if ( color.isValid() ) colorList << color; else { logError() << "ERROR in " << entryName << ": \"" << rgb << "\" is not a valid color" << endl; } } if ( colorList.isEmpty() ) colorList = fallback; return colorList; } void writeColorListEntry( QSettings & settings, const char * entryName, const QList & colors ) { QStringList strList; foreach ( const QColor & color, colors ) { strList << color.name(); } settings.setValue( entryName, strList ); } QFont readFontEntry( const QSettings & settings, const char * entryName, const QFont & fallback ) { if ( settings.contains( entryName ) ) { QString fontName = settings.value( entryName ).toString(); QFont font; if ( font.fromString( fontName ) ) return font; } return fallback; } void writeFontEntry( QSettings & settings, const char * entryName, const QFont & font ) { settings.setValue( entryName, font.toString() ); } int readEnumEntry( const QSettings & settings, const char * entryName, int fallback, const QMap & enumMapping ) { if ( ! settings.contains( entryName ) ) return fallback; QString str = settings.value( entryName ).toString(); QMap::const_iterator it = enumMapping.constBegin(); while ( it != enumMapping.constEnd() ) { if ( it.value() == str ) return it.key(); ++it; } logError() << "Invalid value for " << entryName << ": \"" << str << "\"" << endl; return fallback; } void writeEnumEntry( QSettings & settings, const char * entryName, int enumValue, const QMap & enumMapping ) { if ( ! enumMapping.contains( enumValue ) ) { logError() << "No string for enum value " << enumValue << endl; return; } settings.setValue( entryName, enumMapping.value( enumValue ) ); } QMap patternSyntaxMapping() { static QMap mapping; if ( mapping.isEmpty() ) { mapping[ QRegExp::RegExp ] = "RegExp"; mapping[ QRegExp::Wildcard ] = "Wildcard"; mapping[ QRegExp::FixedString ] = "FixedString"; mapping[ QRegExp::RegExp2 ] = "RegExp2"; mapping[ QRegExp::WildcardUnix ] = "WildcardUnix"; mapping[ QRegExp::W3CXmlSchema11 ] = "W3CXmlSchema11"; } return mapping; } void readWindowSettings( QWidget * widget, const QString & settingsGroup ) { QDirStat::Settings settings; settings.beginGroup( settingsGroup ); QPoint winPos = settings.value( "WindowPos" , QPoint( -99, -99 ) ).toPoint(); QSize winSize = settings.value( "WindowSize", QSize ( 0, 0 ) ).toSize(); if ( winSize.height() > 100 && winSize.width() > 100 ) widget->resize( winSize ); if ( winPos.x() != -99 && winPos.y() != -99 ) widget->move( winPos ); } void writeWindowSettings( QWidget * widget, const QString & settingsGroup ) { QDirStat::Settings settings; settings.beginGroup( settingsGroup ); settings.setValue( "WindowPos" , widget->pos() ); settings.setValue( "WindowSize", widget->size() ); settings.endGroup(); } } // namespace QDirStat qdirstat-1.4/src/SettingsHelpers.h000066400000000000000000000057501311502036700173010ustar00rootroot00000000000000/* * File name: SettingsHelpers.h * Summary: Helper functions for QSettings for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef SettingsHelpers_h #define SettingsHelpers_h #include #include #include class QSettings; namespace QDirStat { /** * Read a color in RGB format (#RRGGBB) from the settings. **/ QColor readColorEntry( const QSettings & settings, const char * entryName, const QColor & fallback ); /** * Write a color in RGB format (#RRGGBB) to the settings. **/ void writeColorEntry( QSettings & settings, const char * entryName, const QColor & color ); /** * Read a list of colors in RGB format (#RRGGBB, #RRGGBB, ...) from the * settings. **/ QList readColorListEntry( const QSettings & settings, const char * entryName, const QList & fallback ); /** * Write a list of colors in RGB format (#RRGGBB, #RRGGBB, ...) to the * settings. **/ void writeColorListEntry( QSettings & settings, const char * entryName, const QList & colors ); /** * Read a font in string format from the settings. * Example: "DejaVu Sans Mono,10,-1,5,50,0,0,0,0,0" **/ QFont readFontEntry( const QSettings & settings, const char * entryName, const QFont & fallback ); /** * Write a font in string format to the settings. * Example: "DejaVu Sans Mono,10,-1,5,50,0,0,0,0,0" **/ void writeFontEntry( QSettings & settings, const char * entryName, const QFont & font ); /** * Read an enum value in string format from the settings. * 'enumMapping' maps each valid enum value to the corresponding string. **/ int readEnumEntry( const QSettings & settings, const char * entryName, int fallback, const QMap & enumMapping ); /** * Write an enum value in string format to the settings. * 'enumMapping' maps each valid enum value to the corresponding string. **/ void writeEnumEntry( QSettings & settings, const char * entryName, int enumValue, const QMap & enumMapping ); /** * Return the enum mapping for QRegExp::PatternSyntax. **/ QMap patternSyntaxMapping(); /** * Read window settings (size and position) from the settings and apply * them. **/ void readWindowSettings( QWidget * widget, const QString & settingsGroup ); /** * Write window settings (size and position) to the settings. **/ void writeWindowSettings( QWidget * widget, const QString & settingsGroup ); } // namespace QDirStat #endif // SettingsHelpers_h qdirstat-1.4/src/SignalBlocker.h000066400000000000000000000014121311502036700166640ustar00rootroot00000000000000/* * File name: SignalBlocker.h * Summary: Helper class to block undesired Qt signals * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef SignalBlocker_h #define SignalBlocker_h #include /** * Helper class to block signals for an object while this object exists. * The old signal blocking state is automatically restored once the * SignalBlocker goes out of scope. */ class SignalBlocker { public: SignalBlocker( QObject *obj ): _obj( obj ) { _oldBlocked = obj->signalsBlocked(); obj->blockSignals( true ); } ~SignalBlocker() { _obj->blockSignals( _oldBlocked ); } private: QObject *_obj; bool _oldBlocked; }; #endif // SignalBlocker_h qdirstat-1.4/src/StdCleanup.cpp000066400000000000000000000155061311502036700165530ustar00rootroot00000000000000/* * File name: StdCleanup.cpp * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "Cleanup.h" #include "StdCleanup.h" #include "Exception.h" #include "Logger.h" using namespace QDirStat; CleanupList StdCleanup::stdCleanups( QObject * parent ) { CleanupList cleanups; cleanups << openFileManagerHere( parent ) << openTerminalHere ( parent ) << compressSubtree ( parent ) << makeClean ( parent ) << gitClean ( parent ) << deleteJunk ( parent ) << hardDelete ( parent ) << clearDirContents ( parent ) #if USE_DEBUG_ACTIONS << echoargs ( parent ) << echoargsMixed ( parent ) << segfaulter ( parent ) << commandNotFound ( parent ) << sleepy ( parent ) #endif ; return cleanups; } Cleanup * StdCleanup::openFileManagerHere( QObject * parent ) { Cleanup *cleanup = new Cleanup( "%filemanager %d &", QObject::tr( "Open &File Manager Here" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); cleanup->setIcon( ":/icons/file-manager.png" ); cleanup->setShortcut( Qt::CTRL + Qt::Key_F ); cleanup->setOutputWindowPolicy( Cleanup::ShowNever ); return cleanup; } Cleanup * StdCleanup::openTerminalHere( QObject * parent ) { Cleanup *cleanup = new Cleanup( "%terminal", QObject::tr( "Open &Terminal Here" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); cleanup->setIcon( ":/icons/terminal.png" ); cleanup->setShortcut( Qt::CTRL + Qt::Key_T ); cleanup->setOutputWindowPolicy( Cleanup::ShowNever ); // Make KDE konsole shut up return cleanup; } Cleanup * StdCleanup::compressSubtree( QObject * parent ) { Cleanup *cleanup = new Cleanup( "cd ..; tar cjvf %n.tar.bz2 %n && rm -rf %n", QObject::tr( "&Compress" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( false ); cleanup->setWorksForDotEntry( false ); cleanup->setRefreshPolicy( Cleanup::RefreshParent ); return cleanup; } Cleanup * StdCleanup::makeClean( QObject * parent ) { Cleanup *cleanup = new Cleanup( "make clean", QObject::tr( "&make clean" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( false ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::RefreshThis ); return cleanup; } Cleanup * StdCleanup::gitClean( QObject * parent ) { Cleanup *cleanup = new Cleanup( "git clean -dfx", QObject::tr( "&git clean" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( false ); cleanup->setWorksForDotEntry( true ); cleanup->setAskForConfirmation( true ); cleanup->setRefreshPolicy( Cleanup::RefreshThis ); cleanup->setOutputWindowPolicy( Cleanup::ShowAlways ); return cleanup; } Cleanup * StdCleanup::deleteJunk( QObject * parent ) { Cleanup *cleanup = new Cleanup( "rm -f *.o *~ *.bak *.auto core", QObject::tr( "Delete &Junk Files" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( false ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::RefreshThis ); cleanup->setRecurse( true ); cleanup->setShell( "/bin/bash" ); return cleanup; } Cleanup * StdCleanup::hardDelete( QObject * parent ) { Cleanup *cleanup = new Cleanup( "rm -rf %p", QObject::tr( "&Delete (no way to undelete!)" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( false ); cleanup->setAskForConfirmation( true ); cleanup->setRefreshPolicy( Cleanup::RefreshParent ); cleanup->setIcon( ":/icons/delete.png" ); cleanup->setShortcut( Qt::CTRL + Qt::Key_Delete ); return cleanup; } Cleanup * StdCleanup::clearDirContents( QObject * parent ) { Cleanup *cleanup = new Cleanup( "rm -rf %d/*", QObject::tr( "Clear Directory C&ontents" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( false ); cleanup->setWorksForDotEntry( false ); cleanup->setAskForConfirmation( true ); cleanup->setRefreshPolicy( Cleanup::RefreshThis ); return cleanup; } #if USE_DEBUG_ACTIONS Cleanup * StdCleanup::echoargs( QObject * parent ) { Cleanup *cleanup = new Cleanup( "echoargs %p", QObject::tr( "echoargs" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setAskForConfirmation( false ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); return cleanup; } Cleanup * StdCleanup::echoargsMixed( QObject * parent ) { Cleanup *cleanup = new Cleanup( "echoargs_mixed %n one two three four", QObject::tr( "Output on stdout and stderr" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setAskForConfirmation( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); return cleanup; } Cleanup * StdCleanup::segfaulter( QObject * parent ) { Cleanup *cleanup = new Cleanup( "segfaulter", QObject::tr( "Segfaulter" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); return cleanup; } Cleanup * StdCleanup::commandNotFound( QObject * parent ) { Cleanup *cleanup = new Cleanup( "wrglbrmpf", QObject::tr( "Nonexistent command" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); return cleanup; } Cleanup * StdCleanup::sleepy( QObject * parent ) { Cleanup *cleanup = new Cleanup( "sleep 1; echoargs %p", QObject::tr( "Sleepy echoargs" ), parent ); CHECK_NEW( cleanup ); cleanup->setWorksForDir ( true ); cleanup->setWorksForFile ( true ); cleanup->setWorksForDotEntry( true ); cleanup->setRefreshPolicy( Cleanup::NoRefresh ); return cleanup; } #endif qdirstat-1.4/src/StdCleanup.h000066400000000000000000000034161311502036700162150ustar00rootroot00000000000000/* * File name: StdCleanup.h * Summary: QDirStat classes to reclaim disk space * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef StdCleanup_h #define StdCleanup_h #include #include #define USE_DEBUG_ACTIONS 0 namespace QDirStat { class Cleanup; /** * Create any of the predefined standard @ref Cleanup actions to be * performed on DirTree items. Ownership of the objects is passed to the * caller. * * This class is not meant to be ever instantiated - use the static methods * only. **/ class StdCleanup { public: static Cleanup * openFileManagerHere( QObject * parent = 0 ); static Cleanup * openTerminalHere ( QObject * parent = 0 ); static Cleanup * compressSubtree ( QObject * parent = 0 ); static Cleanup * makeClean ( QObject * parent = 0 ); static Cleanup * gitClean ( QObject * parent = 0 ); static Cleanup * deleteJunk ( QObject * parent = 0 ); static Cleanup * hardDelete ( QObject * parent = 0 ); static Cleanup * clearDirContents ( QObject * parent = 0 ); #if USE_DEBUG_ACTIONS static Cleanup * echoargs ( QObject * parent = 0 ); static Cleanup * echoargsMixed ( QObject * parent = 0 ); static Cleanup * segfaulter ( QObject * parent = 0 ); static Cleanup * commandNotFound ( QObject * parent = 0 ); static Cleanup * sleepy ( QObject * parent = 0 ); #endif /** * Create all of the above and return them in a list. **/ static CleanupList stdCleanups( QObject * parent ); private: /** * Prevent instances of this class - private constructor / destructor. **/ StdCleanup() {} ~StdCleanup() {} }; } // namespace QDirStat #endif // ifndef StdCleanup_h qdirstat-1.4/src/Subtree.cpp000066400000000000000000000021051311502036700161110ustar00rootroot00000000000000/* * File name: Subtree.cpp * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include "Subtree.h" using namespace QDirStat; FileInfo * Subtree::subtree() { FileInfo * dir = locate(); if ( ! dir && _useRootFallback && _tree ) dir = _tree->root(); return dir; } QString Subtree::url() const { if ( _url == "" && _tree ) return _tree->url(); else return _url; } void Subtree::set( FileInfo * subtree ) { if ( subtree ) { _tree = subtree->tree(); _url = subtree->debugUrl(); } else { _url.clear(); } } FileInfo * Subtree::locate() { if ( ! _tree || _url.isEmpty() ) return 0; return _tree->locate( _url, true ); // findDotEntries; } void Subtree::clone( const Subtree & other ) { if ( &other == this ) return; _tree = other.tree(); _url = other.url(); _useRootFallback = other.useRootFallback(); } qdirstat-1.4/src/Subtree.h000066400000000000000000000117111311502036700155610ustar00rootroot00000000000000/* * File name: Subtree.h * Summary: Support classes for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Subtree_h #define Subtree_h #include "FileInfo.h" #include "DirTree.h" namespace QDirStat { /** * Class to store information about a subtree of a DirTree. * * This is basically a wrapper around a FileInfo pointer that takes the * very limited life time of such a pointer into account: Whenever a part * of the DirTree is refreshed (e.g. after cleanup actions), all pointers * in that subtree become invalid. While the DirTree does send signals when * that happens, in many cases it is overkill to connect to those signals * and monitor all the time for the off-chance that the one FileInfo * pointer we keep is affected. * * This class simply stores the URL of the subtree and locates the FileInfo * item in the tree when needed. In addition to that, it can also fall back * to the tree's root if that URL no longer exists in the tree. * * Not using Qt's signals and slots has the added benefit of not needing to * inherit QObject which means that instances of this class do not need to * be created on the heap with 'new', and they can be aggregated in other * classes. **/ class Subtree { public: /** * Constructor. **/ Subtree( DirTree * tree = 0 ): _tree( tree ), _useRootFallback( true ) {} /** * Return the DirTree. **/ DirTree * tree() const { return _tree; } /** * Return the URL. **/ QString url() const; /** * Return 'true' if the tree's root item should be used as a fallback * if no URL is set or if no item with that URL can be located. The * default is 'true'. **/ bool useRootFallback() const { return _useRootFallback; } /** * Enable or disable using the tree's root as a fallback. **/ void setUseRootFallback( bool val ) { _useRootFallback = val; } /** * Get the corresponding subtree item from the DirTree via the URL. * * If a URL was set before (typically by setting the subtree), this * traverses the DirTree to find the item with that URL. This is an * expensive operation. * * If no URL was set or if no item with that URL could be found and the * 'useRootFallback' flag is set, the root item of the DirTree is used. * * This might return 0 if no tree was set (also typically by setting * the subtree) or if using the root as a fallback is disabled and the * URL could not be found in the DirTree. **/ FileInfo * subtree(); /** * Dereference operator. This is an alias for subtree(): Get the * subtree via the URL. **/ FileInfo * operator()() { return subtree(); } /** * Set the subtree. This also sets the tree and the URL which both can * be obtained from 'subtree'. This pointer is not stored internally, * just the URL and the tree. * * Setting the subtree to 0 clears the URL, but not the tree. That * means if using the root as a fallback is enabled the next call to * subtree() will return the tree's root. **/ void set( FileInfo * subtree ); /** * Assignment Operator for a FileInfo pointer. This is an alias for * set(). **/ Subtree & operator=( FileInfo * subtree ) { set( subtree ); return *this; } /** * Normal assignment operator. **/ Subtree & operator=( const Subtree & other ) { clone( other ); return *this; } /** * Copy constructor. **/ Subtree( const Subtree & other ) { clone( other ); } /** * Set the DirTree. * * This is typically not necessary; it is implicitly done in set(). **/ void setTree( DirTree * tree ) { _tree = tree; } /** * Set the URL. * * This is typically not necessary; it is implicitly done in set(). **/ void setUrl( const QString & newUrl ) { _url = newUrl; } protected: /** * Locate the FileInfo item with the stored URL in the stored tree. **/ FileInfo * locate(); /** * Clone subtree 'other' to this one. This is what both the assignment * operator (for Subtrees) and the copy constructor do internally. **/ void clone( const Subtree & other ); // // Data members // DirTree * _tree; QString _url; bool _useRootFallback; }; // class Subtree } // namespace QDirStat #endif // ifndef Subtree_h qdirstat-1.4/src/Trash.cpp000066400000000000000000000151711311502036700155700ustar00rootroot00000000000000/* * File name: Trash.h * Summary: Implemementation of the XDG Trash spec for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include #include "Trash.h" #include "Logger.h" #include "Exception.h" Trash * Trash::_instance = 0; Trash * Trash::instance() { if ( ! _instance ) { _instance = new Trash(); CHECK_NEW( _instance ); } return _instance; } Trash::Trash(): _homeTrashDir(0) { _homeDevice = device( QDir::homePath() ); QByteArray xdg_data_home = qgetenv( "XDG_DATA_HOME" ); QString homeTrash = xdg_data_home.isEmpty() ? QDir::homePath() + "/.local/share" : QString::fromUtf8( xdg_data_home ); homeTrash += "/Trash"; _homeTrashDir = new TrashDir( homeTrash, _homeDevice ); CHECK_NEW( _homeTrashDir ); _trashDirs[ _homeDevice ] = _homeTrashDir; } Trash::~Trash() { // NOP } dev_t Trash::device( const QString & path ) { dev_t dev = 0; struct stat statBuf; int result = stat( path.toUtf8(), &statBuf ); dev = statBuf.st_dev; if ( result < 0 ) { logError() << "stat( " << path << " ) failed: " << formatErrno() << endl; dev = static_cast( -1 ); } return dev; } QString Trash::toplevel( const QString & rawPath ) { dev_t dev = device( rawPath ); QFileInfo fileInfo( rawPath ); QString path = fileInfo.canonicalPath(); QStringList components = path.split( "/", QString::SkipEmptyParts ); QString lastPath; // Go one directory level up as long as we are on the same device while ( ! components.isEmpty() && device( path ) == dev ) { lastPath = path; components.removeLast(); path = "/" + components.join( "/" ); } if ( components.isEmpty() && device( "/" ) == dev ) lastPath = "/"; return lastPath; } TrashDir * Trash::trashDir( const QString & path ) { dev_t dev = device( path ); if ( _trashDirs.contains( dev ) ) return _trashDirs[ dev ]; QString topDir = toplevel( path ); try { // Check if there is $TOPDIR/.Trash QString trashPath = topDir + "/.Trash"; struct stat statBuf; int result = stat( trashPath.toUtf8(), &statBuf ); if ( result < 0 && errno == ENOENT ) // No such file or directory { // No $TOPDIR/.Trash: Use $TOPDIR/.Trash-$UID logInfo() << "No " << trashPath << endl; trashPath = topDir + QString( "/.Trash-%1" ).arg( getuid() ); logInfo() << "Using " << trashPath << endl; } else if ( result < 0 ) { // stat() failed for some other reason (not "no such file or directory") THROW( FileException( trashPath, "stat() failed for " + trashPath + ": " + formatErrno() ) ); } else // stat() was successful { mode_t mode = statBuf.st_mode; if ( S_ISDIR( mode ) && ( mode & S_ISVTX ) ) // Check sticky bit { // Use $TOPDIR/.Trash/$UID trashPath += QString( "/%1" ).arg( getuid() ); logInfo() << "Using " << trashPath << endl; } else // Not a directory or sticky bit not set { if ( ! S_ISDIR( mode ) ) THROW( FileException( trashPath, trashPath + " is not a directory" ) ); else THROW( FileException( trashPath, "Sticky bit required on " + trashPath ) ); } } TrashDir * trashDir = new TrashDir( trashPath, dev ); CHECK_NEW( trashDir ); _trashDirs[ dev ] = trashDir; return trashDir; } catch ( const FileException &ex ) { CAUGHT( ex ); logWarning() << "Falling back to home trash dir: " << _homeTrashDir->path() << endl; return _homeTrashDir; } } bool Trash::trash( const QString & path ) { try { TrashDir * trashDir = instance()->trashDir( path ); if ( ! trashDir ) return false; QString targetName = trashDir->uniqueName( path ); trashDir->createTrashInfo( path, targetName ); trashDir->move( path, targetName ); } catch ( const FileException & ex ) { CAUGHT( ex ); logError() << "Move to trash failed for " << path << endl; return false; } logInfo() << "Successfully moved to trash: " << path << endl; return true; } bool Trash::restore( const QString & path ) { Q_UNUSED( path ) // TO DO // TO DO // TO DO return true; } void Trash::empty() { // TO DO // TO DO // TO DO } TrashDir::TrashDir( const QString & path, dev_t device ): _path( path ), _device( device ) { // logDebug() << "Created TrashDir " << path << endl; ensureDirExists( path, 0700, true ); ensureDirExists( filesPath(), 0700, true ); ensureDirExists( infoPath(), 0700, true ); } QString TrashDir::uniqueName( const QString & path ) { QFileInfo file( path ); QDir filesDir( filesPath() ); QString baseName = file.baseName(); QString extension = file.completeSuffix(); int count = 0; QString name = baseName; if ( ! extension.isEmpty() ) name += "." + extension; while ( filesDir.exists( name ) ) { name = QString( "%1_%2" ).arg( baseName ).arg( ++count ); if ( ! extension.isEmpty() ) name += "." + extension; } // We don't care if a .trashinfo file with that name already exists in the // Trash/info directory: Without a corresponding file or directory in the // Trash/files directory, that .trashinfo file is worthless anyway and can // safely be overwritten. return name; } bool TrashDir::ensureDirExists( const QString & path, mode_t mode, bool doThrow ) { QDir dir( path ); if ( dir.exists() ) return true; logInfo() << "mkdir " << path << endl; int result = mkdir( path.toUtf8(), mode ); if ( result < 0 && doThrow ) { THROW( FileException( path, QString( "Could not create directory %1: %2" ) .arg( path ).arg( formatErrno() ) ) ); } return result >= 0; } void TrashDir::createTrashInfo( const QString & path, const QString & targetName ) { QFile trashInfo( infoPath() + "/" + targetName + ".trashinfo" ); if ( ! trashInfo.open( QIODevice::WriteOnly | QIODevice::Text ) ) THROW( FileException( trashInfo.fileName(), "Can't open " + trashInfo.fileName() ) ); QTextStream str( &trashInfo ); str << "[Trash Info]" << endl; str << "Path=" << path << endl; str << "DeletionDate=" << QDateTime::currentDateTime().toString( Qt::ISODate ) << endl; } void TrashDir::move( const QString & path, const QString & targetName ) { QFile file( path ); QString targetPath = filesPath() + "/" + targetName; bool success = file.rename( targetPath ); if ( ! success ) THROW( FileException( path, "Could not move " + path + " to " + targetPath ) ); } qdirstat-1.4/src/Trash.h000066400000000000000000000125461311502036700152400ustar00rootroot00000000000000/* * File name: Trash.h * Summary: Implemementation of the XDG Trash spec for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Trash_h #define Trash_h #include #include #include #include #include class TrashDir; typedef QMap TrashDirMap; /** * This class implements the XDG Trash specification: * * http://standards.freedesktop.org/trash-spec/trashspec-1.0.html * * Basically, this is a desktop trashcan that works just like the trashcan in * KDE, Gnome, Xfce and other major Linux desktops. It should integrate well * with any of them, i.e., files or directories moved to this trash can should * appear in the desktop's native trashcan implementation (the window you get * when you click on the trashcan icon on the desktop or in the file manager). * * Most of the important functions of this class are static. They use the * singleton of this class internally that can be accessed with instance(). **/ class Trash { public: /** * Throw a file or directory into the trash. * Return 'true' on success, 'false' on error. **/ static bool trash( const QString & path ); /** * Restore a file or directory from the trash to its original location. * Return 'true' on success, 'false' on error. **/ static bool restore( const QString & path ); /** * Empty the trash can, i.e. delete all its contents permanently. * * This does not just affect files or directories moved to the trash with * this class, but everything in all known trash directories, i.e. all * trash directories that were used during the life time of the singleton * of this class. **/ static void empty(); /** * Return the singleton object for this class. The first use will create * the singleton. Notice that the static methods all access the singleton, * too, so the first call to any of those static methods will already * create the singleton. **/ static Trash * instance(); /** * Return the device of file or directory 'path'. **/ static dev_t device( const QString & path ); protected: /** * Constructor. Not for public use. Use instance() or the static methods * instead. **/ Trash(); /** * Destructor. **/ virtual ~Trash(); /** * Find the toplevel directory (the mount point) for the device that 'path' * is on. **/ static QString toplevel( const QString & path ); /** * Return the trash dir for 'path'. **/ TrashDir * trashDir( const QString & path ); // // Data members // static Trash * _instance; dev_t _homeDevice; TrashDir * _homeTrashDir; TrashDirMap _trashDirs; }; // class Trash /** * One trash directory. There might be several on a system: * * - One in the user's home directory in $XDG_DATA_HOME/Trash * or ~/.local/share/Trash if $XDG_DATA_HOME is not set or empty * * - One in the toplevel directory (the mount point) of each file system: * $TOPLEVEL/.Trash/$UID * * - If $TOPLEVEL/.Trash does not exist or does not pass some checks, one in * $TOPLEVEL/.Trash-$UID **/ class TrashDir { public: /** * Constructor. This will create the trash directory and its required * subdirectories if it doesn't exist yet. * * This might throw a FileException if the corresponding disk directories * could not be created. **/ TrashDir( const QString & _path, dev_t device ); /** * Return the full path for this trash directory. **/ QString path() const { return _path; } /** * Return the device (as returned from stat()) for this trash directory. **/ dev_t device() const { return _device; } /** * Return the path of the "files" subdirectory of this trash dir. **/ QString filesPath() const { return _path + "/files"; } /** * Return the path of the "info" subdirectory of this trash dir. **/ QString infoPath() const { return _path + "/info"; } /** * Create a name that is unique within this trash directory. * If no file or directory with 'name' exists yet in Trash/files or * Trash/info, append a number. **/ QString uniqueName( const QString & name ); /** * Create a .trashinfo file for a file or directory 'path' that will be * named 'targetName' (the unique name) in the trash dir. * * This might throw a FileException. **/ void createTrashInfo( const QString & path, const QString & targetName ); /** * Move a file or directory 'path' to to targetName in the trash dir's * /files subdirectory. If both are on different devices, copy the file and * then delete the original. * * This might throw a FileException. **/ void move( const QString & path, const QString & targetName ); protected: /** * Create a directory if it doesn't exist. This throws an exception if * 'doThrow' is 'true'. * * Return 'true' if success, 'false' if error (and doThrow is 'false'). **/ static bool ensureDirExists( const QString & dir, mode_t mode, bool doThrow = false ); // // Data members // QString _path; dev_t _device; }; #endif // Trash_h qdirstat-1.4/src/TreemapTile.cpp000066400000000000000000000533041311502036700167220ustar00rootroot00000000000000/* * File name: TreemapTile.cpp * Summary: Treemap rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include #include #include "TreemapTile.h" #include "TreemapView.h" #include "FileInfoIterator.h" #include "SelectionModel.h" #include "ActionManager.h" #include "CleanupCollection.h" #include "Exception.h" #include "Logger.h" using namespace QDirStat; TreemapTile::TreemapTile( TreemapView * parentView, TreemapTile * parentTile, FileInfo * orig, const QRectF & rect, Orientation orientation ): QGraphicsRectItem( rect, parentTile ), _parentView( parentView ), _parentTile( parentTile ), _orig( orig ) { // logDebug() << "Creating tile without cushion for " << orig << " " << rect << endl; init(); if ( parentTile ) _cushionSurface = parentTile->cushionSurface(); createChildren( rect, orientation ); } TreemapTile::TreemapTile( TreemapView * parentView, TreemapTile * parentTile, FileInfo * orig, const QRectF & rect, const CushionSurface & cushionSurface, Orientation orientation ): QGraphicsRectItem( rect, parentTile ), _parentView( parentView ), _parentTile( parentTile ), _orig( orig ), _cushionSurface( cushionSurface ) { // logDebug() << "Creating cushioned tile for " << orig << " " << rect << endl; init(); // Intentionally not copying the parent's cushion surface! createChildren( rect, orientation ); } TreemapTile::~TreemapTile() { // DO NOT try to delete the _highlighter: It is owned by the TreemapView / // QGraphicsScene and deleted together with all other QGraphicsItems // in the TreemapView destructor. } void TreemapTile::init() { // Set up height (z coordinate) - one level higher than the parent so this // will be closer to the foreground. setZValue( _parentTile ? ( _parentTile->zValue() + 1.0 ) : 0.0 ); setBrush( QColor( 0x60, 0x60, 0x60 ) ); setPen( Qt::NoPen ); if ( _orig->isDir() || _orig->isDotEntry() ) { if ( _parentView->useDirGradient() ) { if ( qMax( rect().width(), rect().height() ) < _parentView->minTileSize() ) { setBrush( Qt::NoBrush ); } else { QLinearGradient gradient( rect().topLeft(), rect().bottomRight() ); gradient.setColorAt( 0.0, _parentView->dirGradientStart() ); gradient.setColorAt( 1.0, _parentView->dirGradientEnd() ); setBrush( gradient ); } } } setFlags( ItemIsSelectable ); _highlighter = 0; setAcceptHoverEvents(true); if ( ! _parentTile ) _parentView->scene()->addItem( this ); // logDebug() << "Creating treemap tile for " << this // << " size " << formatSize( _orig->totalSize() ) << endl; } void TreemapTile::createChildren( const QRectF & rect, Orientation orientation ) { if ( _orig->totalSize() == 0 ) // Prevent division by zero return; if ( _parentView->squarify() ) createSquarifiedChildren( rect ); else createChildrenSimple( rect, orientation ); } void TreemapTile::createChildrenSimple( const QRectF & rect, Orientation orientation ) { Orientation dir = orientation; Orientation childDir = orientation; if ( dir == TreemapAuto ) dir = rect.width() > rect.height() ? TreemapHorizontal : TreemapVertical; if ( orientation == TreemapHorizontal ) childDir = TreemapVertical; if ( orientation == TreemapVertical ) childDir = TreemapHorizontal; int offset = 0; int size = dir == TreemapHorizontal ? rect.width() : rect.height(); int count = 0; double scale = (double) size / (double) _orig->totalSize(); _cushionSurface.addRidge( childDir, _cushionSurface.height(), rect ); FileSize minSize = (FileSize) ( _parentView->minTileSize() / scale ); FileInfoSortedBySizeIterator it( _orig, minSize ); while ( *it ) { int childSize = 0; childSize = (int) ( scale * (*it)->totalSize() ); if ( childSize >= _parentView->minTileSize() ) { QRectF childRect; if ( dir == TreemapHorizontal ) childRect = QRectF( rect.x() + offset, rect.y(), childSize, rect.height() ); else childRect = QRectF( rect.x(), rect.y() + offset, rect.width(), childSize ); TreemapTile * tile = new TreemapTile( _parentView, this, *it, childRect, childDir ); CHECK_NEW( tile ); tile->cushionSurface().addRidge( dir, _cushionSurface.height() * _parentView->heightScaleFactor(), childRect ); offset += childSize; } ++count; ++it; } } void TreemapTile::createSquarifiedChildren( const QRectF & rect ) { if ( _orig->totalSize() == 0 ) { logError() << "Zero totalSize()" << endl; return; } double scale = rect.width() * (double) rect.height() / _orig->totalSize(); FileSize minSize = (FileSize) ( _parentView->minTileSize() / scale ); FileInfoSortedBySizeIterator it( _orig, minSize ); QRectF childrenRect = rect; while ( *it ) { FileInfoList row = squarify( childrenRect, scale, it ); childrenRect = layoutRow( childrenRect, scale, row ); } } FileInfoList TreemapTile::squarify( const QRectF & rect, double scale, FileInfoSortedBySizeIterator & it ) { // logDebug() << "squarify() " << this << " " << rect << endl; FileInfoList row; int length = qMax( rect.width(), rect.height() ); if ( length == 0 ) // Sanity check { logWarning() << "Zero length" << endl; if ( *it ) // Prevent endless loop in case of error: ++it; // Advance iterator. return row; } bool improvingAspectRatio = true; double lastWorstAspectRatio = -1.0; double sum = 0; // This is a bit ugly, but doing all calculations in the 'size' dimension // is more efficient here since that requires only one scaling before // doing all other calculations in the loop. const double scaledLengthSquare = length * (double) length / scale; while ( *it && improvingAspectRatio ) { sum += (*it)->totalSize(); if ( ! row.isEmpty() && sum != 0 && (*it)->totalSize() != 0 ) { double sumSquare = sum * sum; double worstAspectRatio = qMax( scaledLengthSquare * row.first()->totalSize() / sumSquare, sumSquare / ( scaledLengthSquare * (*it)->totalSize() ) ); if ( lastWorstAspectRatio >= 0.0 && worstAspectRatio > lastWorstAspectRatio ) { improvingAspectRatio = false; } lastWorstAspectRatio = worstAspectRatio; } if ( improvingAspectRatio ) { // logDebug() << "Adding " << *it << " size " << (*it)->totalSize() << endl; row.append( *it ); ++it; } else { // logDebug() << "Getting worse after adding " << *it << " size " << (*it)->totalSize() << endl; } } return row; } QRectF TreemapTile::layoutRow( const QRectF & rect, double scale, FileInfoList & row ) { if ( row.isEmpty() ) return rect; // Determine the direction in which to subdivide. // We always use the longer side of the rectangle. Orientation dir = rect.width() > rect.height() ? TreemapHorizontal : TreemapVertical; // This row's primary length is the longer one. int primary = qMax( rect.width(), rect.height() ); // This row's secondary length is determined by the area (the number of // pixels) to be allocated for all of the row's items. FileSize sum = 0; foreach ( FileInfo * item, row ) sum += item->totalSize(); int secondary = (int) ( sum * scale / primary ); if ( sum == 0 ) // Prevent division by zero. return rect; if ( secondary < _parentView->minTileSize() ) // We don't want tiles that small. return rect; // Set up a cushion surface for this layout row: // Add another ridge perpendicular to the row's direction // that optically groups this row's tiles together. CushionSurface rowCushionSurface = _cushionSurface; rowCushionSurface.addRidge( dir == TreemapHorizontal ? TreemapVertical : TreemapHorizontal, _cushionSurface.height() * _parentView->heightScaleFactor(), rect ); int offset = 0; int remaining = primary; FileInfoList::const_iterator it = row.constBegin(); FileInfoList::const_iterator end = row.constEnd(); while ( it != end ) { int childSize = (int) ( (*it)->totalSize() / (double) sum * primary + 0.5 ); if ( childSize > remaining ) // Prevent overflow because of accumulated rounding errors childSize = remaining; remaining -= childSize; if ( childSize >= _parentView->minTileSize() ) { QRectF childRect; if ( dir == TreemapHorizontal ) childRect = QRectF( rect.x() + offset, rect.y(), childSize, secondary ); else childRect = QRectF( rect.x(), rect.y() + offset, secondary, childSize ); TreemapTile * tile = new TreemapTile( _parentView, this, *it, childRect, rowCushionSurface ); CHECK_NEW( tile ); tile->cushionSurface().addRidge( dir, rowCushionSurface.height() * _parentView->heightScaleFactor(), childRect ); offset += childSize; } ++it; } // Subtract the layouted area from the rectangle. QRectF newRect; if ( dir == TreemapHorizontal ) newRect = QRectF( rect.x(), rect.y() + secondary, rect.width(), rect.height() - secondary ); else newRect = QRectF( rect.x() + secondary, rect.y(), rect.width() - secondary, rect.height() ); // logDebug() << "Left over:" << " " << newRect << " " << this << endl; return newRect; } void TreemapTile::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget ) { // logDebug() << this << " " << rect() << endl; QSizeF size = rect().size(); if ( size.height() < 1.0 || size.width() < 1.0 ) return; if ( _parentView->doCushionShading() ) { if ( _orig->isDir() || _orig->isDotEntry() ) { QGraphicsRectItem::paint( painter, option, widget ); } else { if ( _cushion.isNull() ) _cushion = renderCushion(); QRectF rect = QGraphicsRectItem::rect(); if ( ! _cushion.isNull() ) painter->drawPixmap( rect.topLeft(), _cushion ); if ( isSelected() && ! _orig->hasChildren() ) { // Highlight this tile. This makes only sense if this is a leaf // tile (i.e., if the corresponding FileInfo doesn't have any // children), because otherwise the children will obscure this // tile anyway. In that case, we have to rely on a // HighlightRect to be created. But we can save some memory if // we don't do that for every tile, so we draw that highlight // frame manually if this is a leaf tile. QRectF selectionRect = rect; selectionRect.setSize( rect.size() - QSize( 1.0, 1.0 ) ); painter->setBrush( Qt::NoBrush ); painter->setPen( QPen( _parentView->selectedItemsColor(), 1 ) ); painter->drawRect( selectionRect ); } if ( _parentView->forceCushionGrid() ) { // Draw a clearly visible boundary painter->setPen( QPen( _parentView->cushionGridColor(), 1 ) ); if ( rect.x() > 0 ) painter->drawLine( rect.topLeft(), rect.bottomLeft() ); if ( rect.y() > 0 ) painter->drawLine( rect.topLeft(), rect.topRight() ); } } } else // No cushion shading, use plain tiles { painter->setPen( QPen( _parentView->outlineColor(), 1 ) ); if ( _orig->isDir() || _orig->isDotEntry() ) { if ( ! _parentView->useDirGradient() ) setBrush( _parentView->dirFillColor() ); } else { setBrush( _parentView->tileColor( _orig ) ); } QGraphicsRectItem::paint( painter, option, widget ); } } QPixmap TreemapTile::renderCushion() { QRectF rect = QGraphicsRectItem::rect(); if ( rect.width() < 1.0 || rect.height() < 1.0 ) return QPixmap(); // logDebug() << endl; double nx; double ny; double cosa; int x, y; int red, green, blue; // Cache some values. They are used for each loop iteration, so let's try // to keep multiple indirect references down. int ambientLight = parentView()->ambientLight(); double lightX = parentView()->lightX(); double lightY = parentView()->lightY(); double lightZ = parentView()->lightZ(); double xx2 = cushionSurface().xx2(); double xx1 = cushionSurface().xx1(); double yy2 = cushionSurface().yy2(); double yy1 = cushionSurface().yy1(); int x0 = rect.x(); int y0 = rect.y(); QColor color = parentView()->tileColor( _orig ); int maxRed = qMax( 0, color.red() - ambientLight ); int maxGreen = qMax( 0, color.green() - ambientLight ); int maxBlue = qMax( 0, color.blue() - ambientLight ); QImage image( qRound( rect.width() ), qRound( rect.height() ), QImage::Format_RGB32 ); for ( y = 0; y < rect.height(); y++ ) { for ( x = 0; x < rect.width(); x++ ) { nx = 2.0 * xx2 * (x+x0) + xx1; ny = 2.0 * yy2 * (y+y0) + yy1; cosa = ( nx * lightX + ny * lightY + lightZ ) / sqrt( nx*nx + ny*ny + 1.0 ); red = (int) ( maxRed * cosa + 0.5 ); green = (int) ( maxGreen * cosa + 0.5 ); blue = (int) ( maxBlue * cosa + 0.5 ); if ( red < 0 ) red = 0; if ( green < 0 ) green = 0; if ( blue < 0 ) blue = 0; red += ambientLight; green += ambientLight; blue += ambientLight; image.setPixel( x, y, qRgb( red, green, blue) ); } } if ( _parentView->ensureContrast() ) ensureContrast( image ); return QPixmap::fromImage( image ); } void TreemapTile::ensureContrast( QImage & image ) { if ( image.width() > 5 ) { // Check contrast along the right image boundary: // // Compare samples from the outmost boundary to samples a few pixels to // the inside and count identical pixel values. A number of identical // pixels are tolerated, but not too many. int x1 = image.width() - 6; int x2 = image.width() - 1; int interval = qMax( image.height() / 10, 5 ); int sameColorCount = 0; // Take samples for ( int y = interval; y < image.height(); y+= interval ) { if ( image.pixel( x1, y ) == image.pixel( x2, y ) ) sameColorCount++; } if ( sameColorCount * 10 > image.height() ) { // Add a line at the right boundary QRgb val = contrastingColor( image.pixel( x2, image.height() / 2 ) ); for ( int y = 0; y < image.height(); y++ ) image.setPixel( x2, y, val ); } } if ( image.height() > 5 ) { // Check contrast along the bottom boundary int y1 = image.height() - 6; int y2 = image.height() - 1; int interval = qMax( image.width() / 10, 5 ); int sameColorCount = 0; for ( int x = interval; x < image.width(); x += interval ) { if ( image.pixel( x, y1 ) == image.pixel( x, y2 ) ) sameColorCount++; } if ( sameColorCount * 10 > image.height() ) { // Add a grey line at the bottom boundary QRgb val = contrastingColor( image.pixel( image.width() / 2, y2 ) ); for ( int x = 0; x < image.width(); x++ ) image.setPixel( x, y2, val ); } } } QRgb TreemapTile::contrastingColor( QRgb col ) { if ( qGray( col ) < 128 ) return qRgb( qRed( col ) * 2, qGreen( col ) * 2, qBlue( col ) * 2 ); else return qRgb( qRed( col ) / 2, qGreen( col ) / 2, qBlue( col ) / 2 ); } QVariant TreemapTile::itemChange( GraphicsItemChange change, const QVariant & value) { // logDebug() << this << endl; if ( change == ItemSelectedChange ) { bool selected = value.toBool(); // logDebug() << this << ( selected ? " is selected" : " is deselected" ) << endl; if ( _orig->hasChildren() ) { if ( ! selected && _highlighter ) _highlighter->hide(); if ( selected && this != _parentView->rootTile() ) // don't highlight the root tile { if ( ! _highlighter ) { // logDebug() << "Creating highlighter for " << this << endl; _highlighter = new SelectedItemHighlighter( this, _parentView->selectedItemsColor() ); CHECK_NEW( _highlighter ); } if ( ! _highlighter->isVisible() ) _highlighter->show(); } } } return QGraphicsRectItem::itemChange( change, value ); } void TreemapTile::mousePressEvent( QGraphicsSceneMouseEvent * event ) { switch ( event->button() ) { case Qt::LeftButton: // isSelected() is unreliable here since in QGraphicsItem some // stuff is done in the mousePressEvent, while some other stuff is // done in the mouseReleaseEvent. Just setting the current item // here to avoid having a yellow highlighter rectangle upon mouse // press and then a red one upon mouse release. No matter if the // item ends up selected or not, the mouse press makes it the // current item, so let's update the red highlighter rectangle // here. QGraphicsRectItem::mousePressEvent( event ); // logDebug() << this << " mouse pressed" << endl; _parentView->setCurrentItem( this ); break; case Qt::RightButton: // logDebug() << this << " right mouse pressed" << endl; _parentView->setCurrentItem( this ); break; default: QGraphicsRectItem::mousePressEvent( event ); break; } } void TreemapTile::mouseReleaseEvent( QGraphicsSceneMouseEvent * event ) { switch ( event->button() ) { case Qt::LeftButton: { // The current item was already set in the mouse press event, // but it might have changed its 'selected' status right now, // so let the view update it. QGraphicsRectItem::mouseReleaseEvent( event ); _parentView->setCurrentItem( this ); // logDebug() << this << " clicked; selected: " << isSelected() << endl; } break; case Qt::MidButton: { logDebug() << "Selecting parent" << endl; TreemapTile * oldCurrentTile = _parentView->currentItem(); TreemapTile * newCurrentTile = this; // Select the next-higher ancestor if possible if ( oldCurrentTile && oldCurrentTile->parentTile() && _orig->isInSubtree( oldCurrentTile->parentTile()->orig() ) ) { newCurrentTile = oldCurrentTile->parentTile(); } _parentView->currentItem()->setSelected( false ); newCurrentTile->setSelected( true ); _parentView->setCurrentItem( newCurrentTile ); } break; default: QGraphicsRectItem::mouseReleaseEvent( event ); break; } _parentView->sendSelection(); } void TreemapTile::mouseDoubleClickEvent( QGraphicsSceneMouseEvent * event ) { switch ( event->button() ) { case Qt::LeftButton: logDebug() << "Zooming treemap in" << endl; _parentView->zoomIn(); break; case Qt::MidButton: logDebug() << "Zooming treemap out" << endl; _parentView->zoomOut(); break; case Qt::RightButton: // This doesn't work at all since the first click already opens the // context menu which grabs the focus to that pop-up menu. break; default: break; } } void TreemapTile::wheelEvent( QGraphicsSceneWheelEvent * event ) { if ( event->delta() > 0 ) { if ( ! _parentView->currentItem() ) // can only zoom in with a current item _parentView->setCurrentItem( this ); _parentView->zoomIn(); } else if ( event->delta() < 0 ) { _parentView->zoomOut(); } } void TreemapTile::contextMenuEvent( QGraphicsSceneContextMenuEvent * event ) { if ( ! _parentView->selectionModel() ) return; FileInfoSet selectedItems = _parentView->selectionModel()->selectedItems(); if ( ! selectedItems.contains( _orig ) ) { logDebug() << "Abandoning old selection" << endl; _parentView->selectionModel()->setCurrentItem( _orig, true ); selectedItems = _parentView->selectionModel()->selectedItems(); } if ( _parentView->selectionModel()->verbose() ) _parentView->selectionModel()->dumpSelectedItems(); logDebug() << "Context menu for " << this << endl; QMenu menu; QStringList actions; actions << "actionGoUp" << "actionCopyUrlToClipboard" << "---" << "actionTreemapZoomIn" << "actionTreemapZoomOut" << "actionResetTreemapZoom" << "---" << "actionMoveToTrash" ; ActionManager::instance()->addActions( &menu, actions ); if ( _parentView->cleanupCollection() && ! _parentView->cleanupCollection()->isEmpty() ) { menu.addSeparator(); _parentView->cleanupCollection()->addToMenu( &menu ); } menu.exec( event->screenPos() ); } void TreemapTile::hoverEnterEvent( QGraphicsSceneHoverEvent * event ) { Q_UNUSED( event ); // logDebug() << "Hovering over " << this << endl; _parentView->sendHoverEnter( _orig ); } void TreemapTile::hoverLeaveEvent( QGraphicsSceneHoverEvent * event ) { Q_UNUSED( event ); // logDebug() << " Leaving " << this << endl; _parentView->sendHoverLeave( _orig ); } // //--------------------------------------------------------------------------- // CushionSurface::CushionSurface() { _xx2 = 0.0; _xx1 = 0.0; _yy2 = 0.0; _yy1 = 0.0; _height = CushionHeight; } void CushionSurface::addRidge( Orientation dim, double height, const QRectF & rect ) { _height = height; if ( dim == TreemapHorizontal ) { _xx2 = squareRidge( _xx2, _height, rect.left(), rect.right() ); _xx1 = linearRidge( _xx1, _height, rect.left(), rect.right() ); } else { _yy2 = squareRidge( _yy2, _height, rect.top(), rect.bottom() ); _yy1 = linearRidge( _yy1, _height, rect.top(), rect.bottom() ); } } double CushionSurface::squareRidge( double squareCoefficient, double height, int x1, int x2 ) { if ( x2 != x1 ) // Avoid division by zero squareCoefficient -= 4.0 * height / ( x2 - x1 ); return squareCoefficient; } double CushionSurface::linearRidge( double linearCoefficient, double height, int x1, int x2 ) { if ( x2 != x1 ) // Avoid division by zero linearCoefficient += 4.0 * height * ( x2 + x1 ) / ( x2 - x1 ); return linearCoefficient; } qdirstat-1.4/src/TreemapTile.h000066400000000000000000000241161311502036700163660ustar00rootroot00000000000000/* * File name: TreemapTile.h * Summary: Treemap rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef TreemapTile_h #define TreemapTile_h #include #include #include "FileInfoIterator.h" class QGraphicsSceneMouseEvent; class QGraphicsSceneHoverEvent; namespace QDirStat { class FileInfo; class TreemapView; class HighlightRect; enum Orientation { TreemapHorizontal, TreemapVertical, TreemapAuto }; /** * Helper class for cushioned treemaps: This class holds the polynome * parameters for the cushion surface. The height of each point of such a * surface is defined as: * * z(x, y) = a*x^2 + b*y^2 + c*x + d*y * or * z(x, y) = xx2*x^2 + yy2*y^2 + xx1*x + yy1*y * * to better keep track of which coefficient belongs where. **/ class CushionSurface { public: /** * Constructor. All polynome coefficients are set to 0. **/ CushionSurface(); /** * Adds a ridge of the specified height in dimension 'dim' within * rectangle 'rect' to this surface. It's real voodo magic. * * Just kidding - read the paper about "cushion treemaps" by Jarke * J. van Wiik and Huub van de Wetering from the TU Eindhoven, NL for * more details. * * If you don't want to get all that involved: The coefficients are * changed in some way. **/ void addRidge( Orientation dim, double height, const QRectF & rect ); /** * Set the cushion's height. **/ void setHeight( double newHeight ) { _height = newHeight; } /** * Returns the cushion's height. **/ double height() const { return _height; } /** * Returns the polynomal coefficient of the second order for X * direction. **/ double xx2() const { return _xx2; } /** * Returns the polynomal coefficient of the first order for X direction. **/ double xx1() const { return _xx1; } /** * Returns the polynomal coefficient of the second order for Y * direction. **/ double yy2() const { return _yy2; } /** * Returns the polynomal coefficient of the first order for Y direction. **/ double yy1() const { return _yy1; } protected: /** * Calculate a new square polynomal coefficient for adding a ridge of * specified height between x1 and x2. **/ double squareRidge( double squareCoefficient, double height, int x1, int x2 ); /** * Calculate a new linear polynomal coefficient for adding a ridge of * specified height between x1 and x2. **/ double linearRidge( double linearCoefficient, double height, int x1, int x2 ); // Data members double _xx2, _xx1; double _yy2, _yy1; double _height; }; // class CushionSurface /** * This is the basic building block of a treemap view: One single tile of a * treemap. If it corresponds to a leaf in the tree, it will be visible as * one tile (one rectangle) of the treemap. If it has children, it will be * subdivided again. * * @short Basic building block of a treemap **/ class TreemapTile: public QGraphicsRectItem { public: /** * Constructor: Create a treemap tile from 'fileinfo' that fits into a * rectangle 'rect' inside 'parent'. * * 'orientation' is the direction for further subdivision. 'Auto' * selects the wider direction inside 'rect'. **/ TreemapTile( TreemapView * parentView, TreemapTile * parentTile, FileInfo * orig, const QRectF & rect, Orientation orientation = TreemapAuto ); protected: /** * Alternate constructor: Like the above, but explicitly specify a * cushion surface rather than using the parent's. **/ TreemapTile( TreemapView * parentView, TreemapTile * parentTile, FileInfo * orig, const QRectF & rect, const CushionSurface & cushionSurface, Orientation orientation = TreemapAuto ); public: /** * Destructor. **/ virtual ~TreemapTile(); /** * Returns the original @ref FileInfo item that corresponds to this * treemap tile. **/ FileInfo * orig() const { return _orig; } /** * Returns the parent @ref TreemapView. **/ TreemapView * parentView() const { return _parentView; } /** * Returns the parent @ref TreemapTile or 0 if there is none. **/ TreemapTile * parentTile() const { return _parentTile; } /** * Returns this tile's cushion surface parameters. **/ CushionSurface & cushionSurface() { return _cushionSurface; } protected: /** * Create children (sub-tiles) of this tile. **/ void createChildren( const QRectF & rect, Orientation orientation ); /** * Create children (sub-tiles) using the simple treemap algorithm: * Alternate between horizontal and vertical subdivision in each * level. Each child will get the entire height or width, respectively, * of the specified rectangle. This algorithm is very fast, but often * results in very thin, elongated tiles. **/ void createChildrenSimple( const QRectF & rect, Orientation orientation ); /** * Create children using the "squarified treemaps" algorithm as * described by Mark Bruls, Kees Huizing, and Jarke J. van Wijk of the * TU Eindhoven, NL. * * This algorithm is not quite so simple and involves more expensive * operations, e.g., sorting the children of each node by size first, * try some variations of the layout and maybe backtrack to the * previous attempt. But it results in tiles that are much more * square-like, i.e. have more reasonable width-to-height ratios. It is * very much less likely to get thin, elongated tiles that are hard to * point at and even harder to compare visually against each other. * * This implementation includes some improvements to that basic * algorithm. For example, children below a certain size are * disregarded completely since they will not get an adequate visual * representation anyway (it would be way too small). They are * summarized in some kind of 'misc stuff' area in the parent treemap * tile - in fact, part of the parent directory's tile can be "seen * through". * * In short, a lot of small children that don't have any useful effect * for the user in finding wasted disk space are omitted from handling * and, most important, don't need to be sorted by size (which has a * cost of O(n*ln(n)) in the best case, so reducing n helps a lot). **/ void createSquarifiedChildren( const QRectF & rect ); /** * Squarify as many children as possible: Try to squeeze members * referred to by 'it' into 'rect' until the aspect ratio doesn't get * better any more. Returns a list of children that should be laid out * in 'rect'. Moves 'it' until there is no more improvement or 'it' * runs out of items. * * 'scale' is the scaling factor between file sizes and pixels. **/ FileInfoList squarify( const QRectF & rect, double scale, FileInfoSortedBySizeIterator & it ); /** * Lay out all members of 'row' within 'rect' along its longer side. * Returns the new rectangle with the layouted area subtracted. **/ QRectF layoutRow( const QRectF & rect, double scale, FileInfoList & row ); /** * Paint this tile. * * Reimplemented from QGraphicsRectItem. **/ virtual void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) Q_DECL_OVERRIDE; /** * Notification that item attributes (such as the 'selected' state) * have changed. * * Reimplemented from QGraphicsItem. **/ virtual QVariant itemChange( GraphicsItemChange change, const QVariant & value) Q_DECL_OVERRIDE; /** * Mouse press event: Handle setting the current item. * * Reimplemented from QGraphicsItem. **/ virtual void mousePressEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE; /** * Mouse release event: Handle marking item selection. * * Reimplemented from QGraphicsItem. **/ virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE; /** * Mouse double click event: * Left button double-click zooms in, * right button double-click zooms out, * middle button double-click rebuilds treemap. * * Reimplemented from QGraphicsItem. **/ virtual void mouseDoubleClickEvent( QGraphicsSceneMouseEvent * event ) Q_DECL_OVERRIDE; /** * Mouse wheel event: Zoom in or out * * Reimplemented from QGraphicsItem. **/ virtual void wheelEvent( QGraphicsSceneWheelEvent * event) Q_DECL_OVERRIDE; /** * Context menu event. * * Reimplemented from QGraphicsItem. **/ virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE; /** * Hover enter event. * * Reimplemented from QGraphicsItem. **/ virtual void hoverEnterEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE; /** * Hover enter event. * * Reimplemented from QGraphicsItem. **/ virtual void hoverLeaveEvent( QGraphicsSceneHoverEvent * event ) Q_DECL_OVERRIDE; /** * Render a cushion as described in "cushioned treemaps" by Jarke * J. van Wijk and Huub van de Wetering of the TU Eindhoven, NL. **/ QPixmap renderCushion(); /** * Check if the contrast of the specified image is sufficient to * visually distinguish an outline at the right and bottom borders * and add a grey line there, if necessary. **/ void ensureContrast( QImage & image ); /** * Returns a color that gives a reasonable contrast to 'col': Lighter * if 'col' is dark, darker if 'col' is light. **/ QRgb contrastingColor( QRgb col ); private: /** * Initialization common to all constructors. **/ void init(); protected: // Data members TreemapView * _parentView; TreemapTile * _parentTile; FileInfo * _orig; CushionSurface _cushionSurface; QPixmap _cushion; HighlightRect * _highlighter; }; // class TreemapTile inline QTextStream & operator<< ( QTextStream & stream, TreemapTile * tile ) { if ( tile ) stream << tile->orig(); else stream << ""; return stream; } } // namespace QDirStat #endif // ifndef TreemapTile_h qdirstat-1.4/src/TreemapView.cpp000066400000000000000000000442601311502036700167400ustar00rootroot00000000000000/* * File name: TreemapView.cpp * Summary: View widget for treemap rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include #include #include #include "TreemapView.h" #include "DirTree.h" #include "Exception.h" #include "Logger.h" #include "SelectionModel.h" #include "Settings.h" #include "SettingsHelpers.h" #include "SignalBlocker.h" #include "TreemapTile.h" #include "MimeCategorizer.h" #include "DelayedRebuilder.h" #define UpdateMinSize 20 using namespace QDirStat; TreemapView::TreemapView( QWidget * parent ): QGraphicsView( parent ), _tree(0), _selectionModel(0), _selectionModelProxy(0), _cleanupCollection(0), _mimeCategorizer(0), _rebuilder(0), _rootTile(0), _currentItem(0), _currentItemRect(0), _newRoot(0), _useFixedColor(false), _useDirGradient(true) { // logDebug() << endl; readSettings(); // Default values for light sources taken from Wiik / Wetering's paper // about "cushion treemaps". _lightX = 0.09759; _lightY = 0.19518; _lightZ = 0.9759; setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff ); _rebuilder = new DelayedRebuilder( this ); CHECK_NEW( _rebuilder ); connect( _rebuilder, SIGNAL( rebuild() ), this, SLOT ( rebuildTreemapDelayed() ) ); } TreemapView::~TreemapView() { // Write settings back to file so the user can change them in that file: // There is no settings dialog for this class because the settings are all // pretty obscure - strictly for experts. writeSettings(); } void TreemapView::clear() { if ( scene() ) qDeleteAll( scene()->items() ); _currentItem = 0; _currentItemRect = 0; _rootTile = 0; } void TreemapView::setDirTree( DirTree * newTree ) { // logDebug() << endl; _tree = newTree; if ( ! _tree ) return; if ( _tree->firstToplevel() ) { if ( ! _rootTile ) { // The treemap might already be created indirectly by // rebuildTreemap() called from resizeEvent() triggered by resize() // above. If this is so, don't do it again. rebuildTreemap( _tree->firstToplevel() ); } } connect( _tree, SIGNAL( deletingChild ( FileInfo * ) ), this, SLOT ( deleteNotify ( FileInfo * ) ) ); connect( _tree, SIGNAL( childDeleted() ), this, SLOT ( rebuildTreemap() ) ); connect( _tree, SIGNAL( clearing() ), this, SLOT ( clear() ) ); connect( _tree, SIGNAL( finished() ), this, SLOT ( rebuildTreemap() ) ); } void TreemapView::setSelectionModel( SelectionModel * selectionModel ) { logDebug() << endl; _selectionModel = selectionModel; CHECK_PTR( _selectionModel ); if ( _selectionModelProxy ) delete _selectionModelProxy; _selectionModelProxy = new SelectionModelProxy( selectionModel, this ); CHECK_PTR( _selectionModelProxy ); connect( this, SIGNAL( selectionChanged( FileInfo * ) ), _selectionModel, SLOT ( selectItem ( FileInfo * ) ) ); connect( this, SIGNAL( currentItemChanged( FileInfo * ) ), _selectionModel, SLOT ( setCurrentItem ( FileInfo * ) ) ); connect( this, SIGNAL( currentItemChanged( FileInfo * ) ), _selectionModel, SLOT ( setCurrentBranch ( FileInfo * ) ) ); // Use the proxy for all receiving signals! connect( _selectionModelProxy, SIGNAL( currentItemChanged( FileInfo *, FileInfo * ) ), this, SLOT ( updateCurrentItem ( FileInfo * ) ) ); connect( _selectionModelProxy, SIGNAL( selectionChanged( FileInfoSet ) ), this, SLOT ( updateSelection ( FileInfoSet ) ) ); } void TreemapView::readSettings() { Settings settings; settings.beginGroup( "Treemaps" ); _ambientLight = settings.value( "AmbientLight" , DefaultAmbientLight ).toInt(); _heightScaleFactor = settings.value( "HeightScaleFactor", DefaultHeightScaleFactor ).toDouble(); _squarify = settings.value( "Squarify" , true ).toBool(); _doCushionShading = settings.value( "CushionShading" , true ).toBool(); _ensureContrast = settings.value( "EnsureContrast" , true ).toBool(); _forceCushionGrid = settings.value( "ForceCushionGrid" , false ).toBool(); _useDirGradient = settings.value( "UseDirGradient" , true ).toBool(); _minTileSize = settings.value( "MinTileSize" , DefaultMinTileSize ).toInt(); _currentItemColor = readColorEntry( settings, "CurrentItemColor" , Qt::red ); _selectedItemsColor = readColorEntry( settings, "SelectedItemsColor", Qt::yellow ); _cushionGridColor = readColorEntry( settings, "CushionGridColor" , QColor( 0x80, 0x80, 0x80 ) ); _outlineColor = readColorEntry( settings, "OutlineColor" , Qt::black ); _fileFillColor = readColorEntry( settings, "FileFillColor" , QColor( 0xde, 0x8d, 0x53 ) ); _dirFillColor = readColorEntry( settings, "DirFillColor" , QColor( 0x10, 0x7d, 0xb4 ) ); _dirGradientStart = readColorEntry( settings, "DirGradientStart" , QColor( 0x60, 0x60, 0x70 ) ); _dirGradientEnd = readColorEntry( settings, "DirGradientEnd" , QColor( 0x70, 0x70, 0x80 ) ); settings.endGroup(); } void TreemapView::writeSettings() { logDebug() << endl; Settings settings; settings.beginGroup( "Treemaps" ); settings.setValue( "AmbientLight" , _ambientLight ); settings.setValue( "HeightScaleFactor" , _heightScaleFactor ); settings.setValue( "Squarify" , _squarify ); settings.setValue( "CushionShading" , _doCushionShading ); settings.setValue( "EnsureContrast" , _ensureContrast ); settings.setValue( "ForceCushionGrid" , _forceCushionGrid ); settings.setValue( "UseDirGradient" , _useDirGradient ); settings.setValue( "MinTileSize" , _minTileSize ); writeColorEntry( settings, "CurrentItemColor" , _currentItemColor ); writeColorEntry( settings, "SelectedItemsColor", _selectedItemsColor ); writeColorEntry( settings, "CushionGridColor" , _cushionGridColor ); writeColorEntry( settings, "OutlineColor" , _outlineColor ); writeColorEntry( settings, "FileFillColor" , _fileFillColor ); writeColorEntry( settings, "DirFillColor" , _dirFillColor ); writeColorEntry( settings, "DirGradientStart" , _dirGradientStart ); writeColorEntry( settings, "DirGradientEnd" , _dirGradientEnd ); settings.endGroup(); } void TreemapView::zoomIn() { if ( ! canZoomIn() ) return; TreemapTile * newRootTile = _currentItem; while ( newRootTile && newRootTile->parentTile() != _rootTile && newRootTile->parentTile() ) // This should never happen, but who knows? { newRootTile = newRootTile->parentTile(); } if ( newRootTile ) { FileInfo * newRoot = newRootTile->orig(); if ( newRoot->isDir() || newRoot->isDotEntry() ) rebuildTreemap( newRoot ); } } void TreemapView::zoomOut() { if ( ! canZoomOut() ) return; FileInfo * newRoot = _rootTile->orig(); if ( newRoot->parent() && newRoot->parent() != _tree->root() ) newRoot = newRoot->parent(); rebuildTreemap( newRoot ); } void TreemapView::resetZoom() { if ( _tree && _tree->firstToplevel() ) rebuildTreemap( _tree->firstToplevel() ); } bool TreemapView::canZoomIn() const { if ( ! _currentItem || ! _rootTile ) return false; if ( _currentItem == _rootTile ) return false; TreemapTile * newRootTile = _currentItem; while ( newRootTile->parentTile() != _rootTile && newRootTile->parentTile() ) // This should never happen, but who knows? { newRootTile = newRootTile->parentTile(); } if ( newRootTile ) { FileInfo * newRoot = newRootTile->orig(); if ( newRoot->isDir() || newRoot->isDotEntry() ) return true; } return false; } bool TreemapView::canZoomOut() const { if ( ! _rootTile || ! _tree->firstToplevel() ) return false; return _rootTile->orig() != _tree->firstToplevel(); } void TreemapView::rebuildTreemap() { FileInfo * root = 0; if ( ! _savedRootUrl.isEmpty() ) { // logDebug() << "Restoring old treemap with root " << _savedRootUrl << endl; root = _tree->locate( _savedRootUrl, true ); // node, findDotEntries } if ( ! root ) root = _rootTile ? _rootTile->orig() : _tree->firstToplevel(); rebuildTreemap( root, sceneRect().size() ); _savedRootUrl = ""; } void TreemapView::rebuildTreemap( FileInfo * newRoot, const QSizeF & newSz ) { // logDebug() << endl; QSizeF newSize = newSz; if ( newSz.isEmpty() ) newSize = visibleSize(); // Delete all old stuff. clear(); if ( ! scene() ) { QGraphicsScene * scene = new QGraphicsScene( this ); CHECK_NEW( scene); setScene( scene ); } QRectF rect = QRectF( 0.0, 0.0, (double) newSize.width(), (double) newSize.height() ); scene()->setSceneRect( rect ); if ( newSize.width() >= UpdateMinSize && newSize.height() >= UpdateMinSize ) { // The treemap contents is displayed if larger than a certain minimum // visible size. This is an easy way for the user to avoid // time-consuming delays when deleting a lot of files: Simply make the // treemap (sub-) window very small. // Fill the new scene if ( newRoot ) { _rootTile = new TreemapTile( this, // parentView 0, // parentTile newRoot, // orig rect, TreemapAuto ); } // Synchronize selection with other views if ( _selectionModel ) { updateSelection( _selectionModel->selectedItems() ); updateCurrentItem( _selectionModel->currentItem() ); } } else { // logDebug() << "Too small - suppressing treemap contents" << endl; } emit treemapChanged(); } void TreemapView::scheduleRebuildTreemap( FileInfo * newRoot ) { _newRoot = newRoot; _rebuilder->scheduleRebuild(); } void TreemapView::rebuildTreemapDelayed() { rebuildTreemap( _newRoot ); } void TreemapView::deleteNotify( FileInfo * ) { if ( _rootTile ) { if ( _rootTile->orig() != _tree->firstToplevel() ) { // If the user zoomed the treemap in, save the root's URL so the // current state can be restored upon the next rebuildTreemap() // call (which is triggered by the childDeleted() signal that the // tree emits after deleting is done). // // Intentionally using debugUrl() here rather than just url() so // the correct zoom can be restored even when a dot entry is the // current treemap root. _savedRootUrl = _rootTile->orig()->debugUrl(); } else { // A shortcut for the most common case: No zoom. Simply use the // tree's root for the next treemap rebuild. _savedRootUrl = ""; } } else { // Intentionally leaving _savedRootUrl alone: Otherwise multiple // deleteNotify() calls might cause a previously saved _savedRootUrl to // be unnecessarily deleted, thus the treemap couldn't be restored as // it was. } clear(); } void TreemapView::resizeEvent( QResizeEvent * event ) { // logDebug() << endl; QGraphicsView::resizeEvent( event ); if ( ! _tree ) return; bool tooSmall = event->size().width() < UpdateMinSize || event->size().height() < UpdateMinSize; if ( tooSmall && _rootTile ) { // logDebug() << "Suppressing treemap contents" << endl; scheduleRebuildTreemap( _rootTile->orig() ); } else if ( ! tooSmall && ! _rootTile ) { if ( _tree && _tree->firstToplevel() ) { // logDebug() << "Redisplaying suppressed treemap contents" << endl; scheduleRebuildTreemap( _tree->firstToplevel() ); } } else if ( _rootTile ) { // logDebug() << "Auto-resizing treemap" << endl; scheduleRebuildTreemap( _rootTile->orig() ); } } void TreemapView::disable() { // logDebug() << "Disabling treemap view" << endl; clear(); resize( width(), 1 ); hide(); emit treemapChanged(); } void TreemapView::enable() { if ( ! isVisible() ) { // logDebug() << "Enabling treemap view" << endl; show(); QWidget * parentWidget = qobject_cast( parent() ); if ( parentWidget ) resize( parentWidget->height(), width() ); scheduleRebuildTreemap( _tree->firstToplevel() ); } } void TreemapView::setCurrentItem( TreemapTile * tile ) { // logDebug() << tile << endl; TreemapTile * oldCurrent = _currentItem; _currentItem = tile; if ( _currentItem ) { if ( ! _currentItemRect ) _currentItemRect = new CurrentItemHighlighter( scene(), _currentItemColor ); } if ( _currentItemRect ) { if ( _currentItem == _rootTile ) _currentItemRect->hide(); // Don't highlight the root tile else _currentItemRect->highlight( _currentItem ); } if ( oldCurrent != _currentItem && _selectionModelProxy ) { // logDebug() << "Sending currentItemChanged " << _currentItem << endl; SignalBlocker sigBlocker( _selectionModelProxy ); // Prevent signal ping-pong emit currentItemChanged( _currentItem ? _currentItem->orig() : 0 ); } } void TreemapView::setCurrentItem( FileInfo * node ) { // logDebug() << node << endl; if ( node && _rootTile ) { FileInfo * treemapRoot = _rootTile->orig(); // Check if the new current item is inside the current treemap // (it might be zoomed). while ( ! node->isInSubtree( treemapRoot ) && treemapRoot->parent() && treemapRoot->parent() != _tree->root() ) { treemapRoot = treemapRoot->parent(); // try one level higher } if ( treemapRoot != _rootTile->orig() ) // need to zoom out? { logDebug() << "Zooming out to " << treemapRoot << " to make current item visible" << endl; rebuildTreemap( treemapRoot ); } } setCurrentItem( findTile( node ) ); } void TreemapView::updateSelection( const FileInfoSet & newSelection ) { if ( ! scene() ) return; // logDebug() << newSelection.size() << " items selected" << endl; SignalBlocker sigBlocker( this ); scene()->clearSelection(); foreach ( const FileInfo * item, newSelection ) { // logDebug() << " Selected: " << item << endl; TreemapTile * tile = findTile( item ); if ( tile ) tile->setSelected( true ); } updateCurrentItem( _currentItem ? _currentItem->orig() : 0 ); } void TreemapView::sendSelection() { if ( ! scene() || ! _selectionModel ) return; SignalBlocker sigBlocker( _selectionModelProxy ); QList selectedTiles = scene()->selectedItems(); if ( selectedTiles.size() == 1 && selectedTiles.first() == _currentItem ) { // This is the most common case: One tile is selected. // Reduce number of signals in that case. _selectionModel->setCurrentItem( _currentItem->orig(), true ); // select } else // Multi-selection { FileInfoSet selectedItems; foreach ( QGraphicsItem * item, selectedTiles ) { TreemapTile * tile = dynamic_cast( item ); if ( tile ) selectedItems << tile->orig(); } _selectionModel->setSelectedItems( selectedItems ); _selectionModel->setCurrentItem( _currentItem ? _currentItem->orig() : 0 ); } } void TreemapView::updateCurrentItem( FileInfo * currentItem ) { if ( ! scene() ) return; SignalBlocker sigBlocker( this ); setCurrentItem( currentItem ); } TreemapTile * TreemapView::findTile( const FileInfo * fileInfo ) { if ( ! fileInfo || ! scene() ) return 0; foreach ( QGraphicsItem * graphicsItem, scene()->items() ) { TreemapTile * tile = dynamic_cast(graphicsItem); if ( tile && tile->orig() == fileInfo ) return tile; } return 0; } QSize TreemapView::visibleSize() { QSize size = viewport()->size(); // logDebug() << "Visible size: " << size.width() << " x " << size.height() << endl; return size; } void TreemapView::setMimeCategorizer( MimeCategorizer * newCategorizer ) { if ( _mimeCategorizer ) delete _mimeCategorizer; _mimeCategorizer = newCategorizer; } void TreemapView::setFixedColor( const QColor & color ) { _fixedColor = color; _useFixedColor = _fixedColor.isValid(); } QColor TreemapView::tileColor( FileInfo * file ) { if ( _useFixedColor ) return _fixedColor; if ( file ) { if ( file->isFile() ) { if ( ! _mimeCategorizer ) { _mimeCategorizer = new MimeCategorizer( this ); CHECK_NEW( _mimeCategorizer ); } MimeCategory * category = _mimeCategorizer->category( file ); if ( category ) return category->color(); else { // Special case: Executables if ( ( file->mode() & S_IXUSR ) == S_IXUSR ) return Qt::magenta; // TO DO: Configurable } } else // Directories { // TO DO return Qt::blue; } } return Qt::white; } void TreemapView::sendHoverEnter( FileInfo * node ) { emit hoverEnter( node ); } void TreemapView::sendHoverLeave( FileInfo * node ) { emit hoverLeave( node ); } HighlightRect::HighlightRect( QGraphicsScene * scene, const QColor & color, int lineWidth ): QGraphicsRectItem() { QPen pen( color, lineWidth ); pen.setStyle( Qt::DotLine ); setPen( QPen( color, lineWidth ) ); setPen( pen ); setZValue( 1e10 ); // Higher than everything else hide(); scene->addItem( this ); } HighlightRect::HighlightRect( TreemapTile * tile, const QColor & color, int lineWidth ): QGraphicsRectItem() { CHECK_PTR( tile ); setPen( QPen( color, lineWidth ) ); setZValue( 1e8 ); // Not quite as high as the scene-wide highlight rect tile->scene()->addItem( this ); highlight( tile ); } void HighlightRect::highlight( TreemapTile * tile ) { if ( tile ) { QRectF tileRect = tile->rect(); tileRect.moveTo( mapFromScene( tile->mapToScene( tileRect.topLeft() ) ) ); setRect( tileRect ); if ( ! isVisible() ) show(); } else { if ( isVisible() ) hide(); } } void HighlightRect::setPenStyle( Qt::PenStyle style ) { QPen highlightPen = pen(); highlightPen.setStyle( style ); setPen( highlightPen ); } void HighlightRect::setPenStyle( TreemapTile * tile ) { if ( tile && tile->isSelected() ) setPenStyle( Qt::SolidLine ); else setPenStyle( Qt::DotLine ); } void CurrentItemHighlighter::highlight( TreemapTile * tile ) { HighlightRect::highlight( tile ); setPenStyle( tile ); } qdirstat-1.4/src/TreemapView.h000066400000000000000000000407601311502036700164060ustar00rootroot00000000000000/* * File name: TreemapView.h * Summary: View widget for treemap rendering for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef TreemapView_h #define TreemapView_h #include #include #include "FileInfo.h" #define MinAmbientLight 0 #define MaxAmbientLight 200 #define DefaultAmbientLight 40 #define MinHeightScalePercent 10 #define MaxHeightScalePercent 200 #define DefaultHeightScalePercent 100 #define DefaultHeightScaleFactor ( DefaultHeightScalePercent / 100.0 ) #define DefaultMinTileSize 3 #define CushionHeight 1.0 class QMouseEvent; class QSettings; namespace QDirStat { class TreemapTile; class HighlightRect; class DirTree; class SelectionModel; class SelectionModelProxy; class CleanupCollection; class FileInfoSet; class MimeCategorizer; class DelayedRebuilder; /** * View widget that displays a DirTree as a treemap. **/ class TreemapView: public QGraphicsView { Q_OBJECT public: /** * Constructor. Remember to set the directory tree with setDirTree() * and the selection model with setSelectionModel() after creating this * widget. **/ TreemapView( QWidget * parent = 0 ); /** * Destructor. **/ virtual ~TreemapView(); /** * Set the directory tree to work on. Without this, this widget will * not display anything. **/ void setDirTree( DirTree * tree ); /** * Returns the minimum recommended size for this widget. * Reimplemented from QWidget. **/ virtual QSize minimumSizeHint() const { return QSize( 0, 0 ); } /** * Returns this treemap view's current item tile or 0 if there is none. **/ TreemapTile * currentItem() const { return _currentItem; } /** * Returns this treemap view's root treemap tile or 0 if there is none. **/ TreemapTile * rootTile() const { return _rootTile; } /** * Returns this treemap view's @ref DirTree. **/ DirTree * tree() const { return _tree; } /** * Set the selection model. This is important to synchronize current / * selected items between a DirTreeView and this TreemapView. **/ void setSelectionModel( SelectionModel * selectionModel ); /** * Return this treemap view's SelectionModel. **/ SelectionModel * selectionModel() const { return _selectionModel; } /** * Set the cleanup collection. If set, all cleanup actions from that * collection will be added to the item context menu. **/ void setCleanupCollection( CleanupCollection * collection ) { _cleanupCollection = collection; } /** * Return the cleanup collection or 0 if it is not set. **/ CleanupCollection * cleanupCollection() const { return _cleanupCollection; } /** * Search the treemap for a tile that corresponds to the specified * FileInfo node. Returns 0 if there is none. * * Notice: This is an expensive operation since all treemap tiles need * to be searched. **/ TreemapTile * findTile( const FileInfo * node ); /** * Returns a suitable color for 'file' based on a set of internal rules * (according to filename extension, MIME type or permissions). **/ QColor tileColor( FileInfo * file ); /** * Return the MimeCategorizer (the class that maps filenames to treemap * colors) or 0 if it is not created yet. The MimeCategorizer is * created lazily when needed. **/ MimeCategorizer * mimeCategorizer() const { return _mimeCategorizer; } /** * Set the MimeCategorizer (the class that maps filenames to treemap * colors). **/ void setMimeCategorizer( MimeCategorizer * categorizer ); /** * Use a fixed color for all tiles. To undo this, set an invalid QColor * with the QColor default constructor. **/ void setFixedColor( const QColor & fixedColor ); public slots: /** * Update the selected items that have been selected in another view. **/ void updateSelection( const FileInfoSet & newSelection ); /** * Update the current item that has been changed in another view. **/ void updateCurrentItem( FileInfo * currentItem ); /** * Make a treemap tile this treemap's current item. * 'tile' may be 0. In this case, only the previous selection is * deselected. **/ void setCurrentItem( TreemapTile * tile ); /** * Search the treemap for a tile with the specified FileInfo node and * make that tile the current item if it is found. If nothing is found * or if 'node' is 0, the highlighting is removed from the previous * current item. **/ void setCurrentItem( FileInfo * node ); /** * Zoom in one level towards the currently selected treemap tile: * The entire treemap will be rebuilt with the near-topmost ancestor of * the selected tile as the new root. **/ void zoomIn(); /** * Zoom out one level: The parent (if there is any) FileInfo node of * the current treemap root becomes the new root. This usually works * only after zoomIn(). **/ void zoomOut(); /** * Reset the zoom level: Zoom out as far as possible. **/ void resetZoom(); /** * Completely rebuild the entire treemap from the internal tree's root * on. **/ void rebuildTreemap(); /** * Clear the treemap contents. **/ void clear(); /** * Disable this treemap view: Clear its contents, resize it to below * the update threshold and hide it. **/ void disable(); /** * Re-enable this treemap view after disabling it: Show it, resize it * to half the height of its parent widget and redisplay its content. **/ void enable(); /** * Notification that a dir tree node has been deleted. **/ void deleteNotify( FileInfo * node ); /** * Sync the selected items and the current item to the selection model. **/ void sendSelection(); /** * Send a hoverEnter() signal for 'node'. **/ void sendHoverEnter( FileInfo * node ); /** * Send a hoverLeave() signal for 'node'. **/ void sendHoverLeave( FileInfo * node ); /** * Read parameters from the settings file. **/ void readSettings(); /** * Write parameters to the settings file. * * Unlike other classes in this program, this is not done from the * corresponding settings dialog - because there is none. The settings * here are very obscure - strictly for experts; nothing to bother a * normal user with. * * Experts can edit them in the settings file, typically in * ~/.config/QDirStat/QDirStat.conf ; this class writes the settings to * that file in its destructor so those experts can find and edit them. * * If you misconfigured things and want to go back to the defaults, * simply delete that one setting or the section in the settings or the * complete settings file; missing settings are restored to the * defaults when the program exits the next time. **/ void writeSettings(); public: /** * Rebuild the treemap with 'newRoot' as the new root and the specified * size. If 'newSize' is (0, 0), visibleSize() is used. **/ void rebuildTreemap( FileInfo * newRoot, const QSizeF & newSize = QSize() ); /** * Schedule a rebuild of the treemap with 'newRoot'. If another rebuild * is scheduled before the timout is over, nothing will happen until * the last scheduled timeout has elapsed. * * The purpose of this is to avoid unnecessary rebuilds when the user * resizes the window or the treemap subwindow: Only the last rebuild * is really executed (when all the resizing has settled somehow). **/ void scheduleRebuildTreemap( FileInfo * newRoot ); /** * Returns the visible size of the viewport presuming no scrollbars are * needed - which makes a lot more sense than fiddling with scrollbars * since treemaps can be scaled to make scrollbars unnecessary. **/ QSize visibleSize(); /** * Returns the visible width of the viewport presuming no scrollbars * are needed. * * This uses visibleSize() which is a somewhat expensive operation, so * if you need both visibleWidth() and visibleHeight(), better call * visibleSize() once and access its width() and height() methods. **/ int visibleWidth() { return visibleSize().width(); } /** * Returns the visible height of the viewport presuming no scrollbars * are needed. * * This uses visibleSize() which is a somewhat expensive operation, so * if you need both visibleWidth() and visibleHeight(), better call * visibleSize() once and access its width() and height() methods. **/ int visibleHeight() { return visibleSize().height(); } /** * Returns true if it is possible to zoom in with the currently * selected tile, false if not. **/ bool canZoomIn() const; /** * Returns true if it is possible to zoom out with the currently * selected tile, false if not. **/ bool canZoomOut() const; /** * Returns 'true' if treemap tiles are to be squarified upon creation, * 'false' if not. **/ bool squarify() const { return _squarify; } /** * Returns 'true' if cushion shading is to be used, 'false' if not. **/ bool doCushionShading() const { return _doCushionShading; } /** * Returns 'true' if directories should be rendered with a gradient, * 'false' if not. **/ bool useDirGradient() const { return _useDirGradient; } /** * Returns 'true' if cushion shaded treemap tiles are to be separated * by a grid, 'false' if not. **/ bool forceCushionGrid() const { return _forceCushionGrid; } /** * Returns 'true' if tile boundary lines should be drawn for cushion * treemaps, 'false' if not. **/ bool ensureContrast() const { return _ensureContrast; } /** * Returns the minimum tile size in pixels. No treemap tiles less than * this in width or height are desired. **/ int minTileSize() const { return _minTileSize; } /** * Returns the cushion grid color. **/ const QColor & cushionGridColor() const { return _cushionGridColor; } /** * Return the frame color for selected items. **/ const QColor & selectedItemsColor() const { return _selectedItemsColor; } /** * Returns the outline color to use if cushion shading is not used. **/ const QColor & outlineColor() const { return _outlineColor; } /** * Returns the fill color for non-directory treemap tiles when cushion * shading is not used. **/ const QColor & fileFillColor() const { return _fileFillColor; } /** * Returns the fill color for directory (or "dotentry") treemap tiles * when cushion shading is not used. **/ const QColor & dirFillColor() const { return _dirFillColor; } /** * Returns the start color for directory (or "dotentry") treemap tiles * if a directory gradient should be used. **/ const QColor & dirGradientStart() const { return _dirGradientStart; } /** * Returns the end color for directory (or "dotentry") treemap tiles * if a directory gradient should be used. **/ const QColor & dirGradientEnd() const { return _dirGradientEnd; } /** * Returns the intensity of ambient light for cushion shading * [0..255] **/ int ambientLight() const { return _ambientLight; } /** * Returns the X coordinate of a directed light source for cushion * shading. **/ double lightX() const { return _lightX; } /** * Returns the Y coordinate of a directed light source for cushion * shading. **/ double lightY() const { return _lightY; } /** * Returns the Z coordinate of a directed light source for cushion * shading. **/ double lightZ() const { return _lightZ; } /** * Returns cushion ridge height degradation factor (0 .. 1.0) for each * level of subdivision. **/ double heightScaleFactor() const { return _heightScaleFactor; } signals: /** * Emitted when the currently selected item changes. * Caution: 'item' may be 0 when the selection is cleared. **/ void selectionChanged( FileInfo * item ); /** * Emitted when the current item changes. **/ void currentItemChanged( FileInfo * newCurrent ); /** * Emitted when the treemap changes, e.g. is rebuilt, zoomed in, or * zoomed out. **/ void treemapChanged(); /** * Emitted when a context menu for this tile should be opened. * (usually on right click). 'pos' contains the click's mouse * coordinates. **/ void contextMenu( TreemapTile * tile, const QPoint & pos ); /** * Emitted when the mouse cursor enters a hover over 'item'. **/ void hoverEnter( FileInfo * item ); /** * Emitted when the mouse cursor leaves the hover over 'item'. **/ void hoverLeave( FileInfo * item ); protected slots: /** * Rebuild the treemap if no more pendung rebuilds are scheduled. **/ void rebuildTreemapDelayed(); protected: /** * Resize the treemap view. Suppress the treemap contents if the size * falls below a minimum size, redisplay it if it grows above that * minimum size. * * Reimplemented from QFrame. **/ virtual void resizeEvent( QResizeEvent * event ) Q_DECL_OVERRIDE; // Data members DirTree * _tree; SelectionModel * _selectionModel; SelectionModelProxy * _selectionModelProxy; CleanupCollection * _cleanupCollection; MimeCategorizer * _mimeCategorizer; DelayedRebuilder * _rebuilder; TreemapTile * _rootTile; TreemapTile * _currentItem; HighlightRect * _currentItemRect; FileInfo * _newRoot; QString _savedRootUrl; bool _squarify; bool _doCushionShading; bool _forceCushionGrid; bool _ensureContrast; bool _useFixedColor; int _minTileSize; bool _useDirGradient; QColor _currentItemColor; QColor _selectedItemsColor; QColor _cushionGridColor; QColor _outlineColor; QColor _fileFillColor; QColor _dirFillColor; QColor _dirGradientStart; QColor _dirGradientEnd; QColor _fixedColor; int _ambientLight; double _lightX; double _lightY; double _lightZ; double _heightScaleFactor; }; // class TreemapView /** * Transparent rectangle to make a treemap tile clearly visible as the * current item or as selected. * * Leaf tiles can do that themselves, but directory tiles are typically * completely obscured by their children, so no highlight border they draw * themselves will ever become visible. * * This highlight rectangle simply draws a colored red outline on top * (i.e., great z-height) of everything else. The rectangle is transparent, * so the treemap tile contents remain visible. **/ class HighlightRect: public QGraphicsRectItem { public: /** * Create a highlight rectangle for the entire scene. This is most * useful for the current item. **/ HighlightRect( QGraphicsScene * scene, const QColor & color, int lineWidth = 2 ); /** * Create a highlight rectangle for one specific tile and highlight it * right away. This is most useful for selected items if more than one * item is selected. The z-height of this is lower than for the * scene-wide highlight rectangle. **/ HighlightRect( TreemapTile * tile, const QColor & color, int lineWidth = 2 ); /** * Highlight the specified treemap tile: Resize this selection * rectangle to match this tile and move it to this tile's * position. Show the selection rectangle if it is currently * invisible. **/ virtual void highlight( TreemapTile * tile ); /** * Set the pen style. Recommended: Qt::SolidLine or Qt::DotLine. **/ void setPenStyle( Qt::PenStyle style = Qt::SolidLine ); /** * Set the pen style according to the 'selected' status of 'tile'. **/ void setPenStyle( TreemapTile * tile ); }; // class TreemapSelectionRect /** * Highlighter for the treemap view's current tile. * This one is shared; it moves around from tile to tile. **/ class CurrentItemHighlighter: public HighlightRect { public: CurrentItemHighlighter( QGraphicsScene * scene, const QColor & color, int lineWidth = 2 ): HighlightRect( scene, color, lineWidth ) {} virtual void highlight( TreemapTile * tile ); }; /** * Highlighter for the treemap view's current item. * * This one is created on demand for each directory when the directory is * selected; this cannot be done in the tile's paint() method since the * tile will mostly be obscured by its children. This highlighter hovers * above the children as long as the directory is selected. **/ class SelectedItemHighlighter: public HighlightRect { public: SelectedItemHighlighter( TreemapTile * tile, const QColor & color, int lineWidth = 2 ): HighlightRect( tile, color, lineWidth ) {} }; } // namespace QDirStat #endif // ifndef TreemapView_h qdirstat-1.4/src/Version.h000066400000000000000000000004361311502036700155770ustar00rootroot00000000000000/* * File name: Version.h * Summary: Version number header for QDirStat * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #ifndef Version_h #define Version_h #define QDIRSTAT_VERSION "1.4" #endif // Version_h qdirstat-1.4/src/cleanup-config-page.ui000066400000000000000000000617421311502036700201530ustar00rootroot00000000000000 CleanupConfigPage 0 0 654 569 Form Qt::Horizontal 13 false 200 300 Move the current cleanup action to the top of the list. ... :/icons/go-top.png:/icons/go-top.png Move the current cleanup action one position up in the list. ... :/icons/go-up.png:/icons/go-up.png Qt::Vertical 20 40 Create a new cleanup action. You can create as many as you like. ... :/icons/add.png:/icons/add.png Remove the current cleanup action. ... :/icons/remove.png:/icons/remove.png Qt::Vertical 20 40 Move the current cleanup action one position down in the list. ... :/icons/go-down.png:/icons/go-down.png Move the current cleanup action to the bottom of the list. ... :/icons/go-bottom.png:/icons/go-bottom.png 310 0 Uncheck to disable this cleanup action completely. &Active true 1 0 &Title: titleLineEdit 1 0 Check this if a confirmation dialog should be opened before executing the command. There will be only one confirmation dialog, even if multiple items are selected or if the command is executed recursively. As&k For Confirmation 2 0 Enter a title for this cleanup action. This will show up in the menus. You can add a hotkey with "&". Qt::Horizontal QSizePolicy::Preferred 34 20 These are the macros you can use in the command. Both %p and %n always contain only one item. If multiple items are selected, the command will be executed multiple times. %p Full Path %n File / Directory Name Without Path %d Directory Name With Full Path Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 40 20 1 0 &Command Line: commandLineEdit Enter the command to be executed here. Each command will be executed with a shell. If multiple items are selected, the command will be executed once for each selected item. 1 0 Select if the command should be executed recursively for each directory in the selected branch. The command will be called separately for each directory level. &Recurse Into Subdirectories 2 0 This specifies if and how the directory tree should be re-read from disk after the cleanup action is finished. 1 No Refresh Refresh This Item Refresh This Item's Parent Assume Item Has Been Deleted 1 0 R&efresh Policy: refreshPolicyComboBox Qt::Vertical QSizePolicy::Preferred 20 20 0 0 0 0 0 330 147 Works For... Check this if the command can be applied to directories. &Directories Check this if the command can be applied to files. &Files Check this if the command can be applied to the <Files> entries in the tree. Note that they don't really have a counterpart on the disk. <Files> Pse&udo Entries Qt::Vertical 20 40 0 0 330 152 Output Window 1 0 &Policy: outputWindowPolicyComboBox 4 0 Select if and when to open a window for the output of the command. If there is an error, the output window is always opened unless "Never Show" is selected here. "Show After Timeout" is a useful setting for most cases. 2 Show Always Show If Error Output Show After Timeout Never Show 1 0 Ti&meout: outputWindowTimeoutSpinBox 2 0 Set the timeout for the "Show After Timeout" setting. Don't underestimate your computer: It can get more done in half a second than you might think. On the other hand, waiting for half a second feels longer than you might think. sec 1 300.000000000000000 0.500000000000000 Check this to automatically close the output window if there was no error. If you are interested in the output of your command, uncheck this. Auto C&lose If No Error true Qt::Vertical QSizePolicy::MinimumExpanding 20 40 0 0 330 142 Shell 1 1 &Shell: shellComboBox 3 0 Select a shell here or enter your favourite one. Each command is executed with a shell and the "-c" option. Shells may behave differently for wildcards and special characters. If you are setting this up for other users, better stay on the safe side and select a shell with a well-known behaviour like /bin/bash. true $SHELL (Login Shell) /bin/bash /bin/sh Each command is executed with a shell and the '-c' option. Qt::Vertical QSizePolicy::MinimumExpanding 20 20 qdirstat-1.4/src/config-dialog.ui000066400000000000000000000046131311502036700170430ustar00rootroot00000000000000 ConfigDialog 0 0 586 630 QDirStat Configuration true 13 -1 Qt::Horizontal 298 20 OK Apply Cancel okButton clicked() ConfigDialog accept() 487 687 354 354 cancelButton clicked() ConfigDialog reject() 659 687 354 354 qdirstat-1.4/src/exclude-rules-config-page.ui000066400000000000000000000221751311502036700213020ustar00rootroot00000000000000 ExcludeRulesConfigPage 0 0 520 481 Form Qt::Horizontal 24 false 180 200 Move the current exclude rule to the top of the list. ... :/icons/go-top.png:/icons/go-top.png Move the current exclude rule one position up in the list. ... :/icons/go-up.png:/icons/go-up.png Qt::Vertical 20 40 Create a new exclude rule. You can create as many as you like. ... :/icons/add.png:/icons/add.png Remove the current exclude rule. ... :/icons/remove.png:/icons/remove.png Qt::Vertical 20 40 Move the current exclude rule one position down in the list. ... :/icons/go-down.png:/icons/go-down.png Move the current exclude rule to the bottom of the list. ... :/icons/go-bottom.png:/icons/go-bottom.png Exclude Directories With &Pattern patternLineEdit Qt::Vertical 20 28 Pattern &Syntax &Fixed String &Wildcards &Regular Expression Qt::Vertical 20 18 &Match Against &Directory Name Without Path F&ull Path Qt::Vertical 20 40 Qt::Vertical 20 40 Qt::Vertical 20 40 qdirstat-1.4/src/file-size-stats-window.ui000066400000000000000000001011051311502036700206630ustar00rootroot00000000000000 FileSizeStatsWindow 0 0 811 723 File Size Statistics true File size statistics QTabWidget::North 0 &Histogram &Options >> Qt::Horizontal 248 20 7 0 5 0 0 12 9 24 Qt::Horizontal 0 0 A&uto 76 100 90 Qt::Horizontal 0 0 P 24 &Start Percentile startPercentileSpinBox &End Percentile Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter endPercentileSpinBox 0 0 P 76 100 90 &Percentiles Qt::Horizontal 40 20 false Interesting only Show all 100 3 false &Buckets &Help 0 0 0 255 255 255 255 255 255 255 255 255 127 127 127 170 170 170 0 0 0 255 255 255 0 0 0 255 255 255 255 255 255 0 0 0 255 255 255 255 255 220 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 127 127 127 170 170 170 0 0 0 255 255 255 0 0 0 255 255 255 255 255 255 0 0 0 255 255 255 255 255 220 0 0 0 127 127 127 255 255 255 255 255 255 255 255 255 127 127 127 170 170 170 127 127 127 255 255 255 127 127 127 255 255 255 255 255 255 0 0 0 255 255 255 255 255 220 0 0 0 true 0 0 272 750 <h3>Statistics Basics</h3> Median, Quartiles and Percentiles Basic statistics terms explained in a way that everybody can understand. Histograms in General What is a histogram? What is it good for? Qt::Vertical QSizePolicy::Minimum 20 20 <h3>QDirStat File Size Statistics</h3> The File Size Histogram QDirStat's "File Size" histogram in particular: What is it? What does it tell you? The Overflow Area Explaining the "Cut off" panel with the pie charts at the right side of the histogram. Histogram Options Explanation of the sliders, input fields and buttons in the panel that opens when you click the "Options" button below the histogram. Qt::Vertical QSizePolicy::Minimum 20 15 The Percentiles Table Explanation of the table on the "Percentiles" page in this dialog. The Buckets Table Explanation of the table on the "Buckets" table in this dialog. Qt::Vertical QSizePolicy::Minimum 20 10 <i>All links are opened in an external browser.</i> Qt::Vertical QSizePolicy::MinimumExpanding 20 24 5 Qt::Horizontal 40 20 0 0 &Close QDirStat::HistogramView QGraphicsView
HistogramView.h
tabWidget histogramView optionsButton startPercentileSlider autoButton endPercentileSlider startPercentileSpinBox endPercentileSpinBox percentileFilterComboBox percentileTable closeButton closeButton clicked() FileSizeStatsWindow reject() 627 621 199 149 endPercentileSlider valueChanged(int) endPercentileSpinBox setValue(int) 457 520 647 553 startPercentileSlider valueChanged(int) startPercentileSpinBox setValue(int) 72 520 48 549 endPercentileSpinBox valueChanged(int) endPercentileSlider setValue(int) 631 563 412 517 startPercentileSpinBox valueChanged(int) startPercentileSlider setValue(int) 27 554 67 527
qdirstat-1.4/src/file-type-stats-window.ui000066400000000000000000000056771311502036700207130ustar00rootroot00000000000000 FileTypeStatsWindow 0 0 535 605 File Type Statistics true File type statistics true true 1 5 &Refresh File &Type Qt::Horizontal 40 20 0 0 &Close &Locate Si&ze Statistics F2 closeButton clicked() FileTypeStatsWindow reject() 349 277 199 149 qdirstat-1.4/src/general-config-page.ui000066400000000000000000000137201311502036700201320ustar00rootroot00000000000000 generalPage 0 0 671 435 Form Qt::Vertical 20 58 Qt::Horizontal 28 20 12 15 &Cross file system boundaries while reading Tree icon &theme: treeIconThemeComboBox Medium Small Tree &update interval while reading: treeUpdateIntervalSpinBox millisec 50 5000 333 Timeout for status bar &messages: statusBarTimeoutSpinBox sec 1 0.500000000000000 300.000000000000000 3.000000000000000 Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Vertical 20 58 Qt::Vertical 20 58 Qt::Vertical 20 58 qdirstat-1.4/src/icons.qrc000066400000000000000000000034271311502036700156260ustar00rootroot00000000000000 icons/qdirstat.png icons/add.png icons/delete.png icons/document-export.png icons/document-import.png icons/edit-copy.png icons/file-manager.png icons/go-bottom.png icons/go-down.png icons/go-top.png icons/go-up.png icons/hard-disk.png icons/open-dir.png icons/preferences.png icons/refresh.png icons/remove.png icons/stop.png icons/terminal.png icons/trashcan.png icons/window-close.png icons/zoom-best-fit.png icons/zoom-in.png icons/zoom-out.png icons/tree-medium/dir.png icons/tree-medium/dot-entry.png icons/tree-medium/excluded.png icons/tree-medium/file.png icons/tree-medium/mount-point.png icons/tree-medium/stop.png icons/tree-medium/symlink.png icons/tree-medium/unreadable-dir.png icons/tree-medium/block-device.png icons/tree-medium/char-device.png icons/tree-medium/special.png icons/tree-small/dir.png icons/tree-small/dot-entry.png icons/tree-small/excluded.png icons/tree-small/file.png icons/tree-small/mount-point.png icons/tree-small/stop.png icons/tree-small/symlink.png icons/tree-small/unreadable-dir.png icons/tree-small/block-device.png icons/tree-small/char-device.png icons/tree-small/special.png qdirstat-1.4/src/icons/000077500000000000000000000000001311502036700151115ustar00rootroot00000000000000qdirstat-1.4/src/icons/add.png000066400000000000000000000026041311502036700163510ustar00rootroot00000000000000PNG  IHDRw=sRGB pHYs  tIME  /lIDATHǵ]l\3/fؑiL$vH(DC /} O}"x0 @ۧ}P% 5*?"1Ȅ6qb;ޙ]ocd#]݇;9g.IuV)qşu] ?p]+PśIe uҷʑԈ/,5yǀ_+^y*>~{d#t2 oq^&ՁrOJÙLvvZ=w4Yu4Y_ ON'gӦ>@VGtl{ahO_]R3u?::2L`) 1P/]-V v~rs"bX " qF=Z@ւr[ʻ1ٳ_>Y fۊPܪ:hЎ E@ӗ$~xcǎݵ a=5s}Uy@@B)NH⸈"3 G#Sز BĨNQY DI^P.@www3 '{,Ŧ0a*BJEa$fp.twɝF]L+]l uP> CBYX!hh%o'N,i8DDaVe+qb++d HX[:ȗ3#7f_Lm/Xk”0`*Wߐ!׸ Փ:M':3{2 ~$*R )l{&NooϙU<00zc֝a66U~jQUE~ǯv>ɷZ=z3ߵ\j~`B-m71` &Ll}n|߾}OM׺pjPsC8٫!H~Cr[P(?˳{Jk_Wk=cn_5{3prX/FnJv6<9S7Kmڹ6W4Z|Qyc'r_|92~_x:dX(nZ;XH(IENDB`qdirstat-1.4/src/icons/delete.png000066400000000000000000000030411311502036700170570ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATHkL[eFt#YvQA:0Q[`o\6/1̻5~̘t@ƜQt.+,chzZz.o 0=yD?cC㟔?=s\seeލNvȲo߰XlW^i8O\T4t"@s[Zi'qw߷v?BްZm#K=g6{rK)kf1I)U HҝwV|\Ur~Šp!1n>݊2ٰ<ARd)YӐoJͽm\_y /T eJAeX,|uv8T$  ȡIUEJlFԫ/d:]Z`Re9|hXQKaqϞ. ϗ f`Rδ6YZwo$u,CyXnB( dU ߓCCW,MIYTyE׿cjT\<σ*d]?zX8ںճ3c%VA@,/$yN `cy~uC]@!dUs/0_p,f?ݝsl2nB/̙wΌM@ XΎ|lDؙ@d-H}}}ڶ h9{%RިB]qCĔ"J]m0 HHQr xQ Ȯ_Ȼ T.bJ DjEU0DQ Qjwm>LÔ v-}TQURN T2cOwrk.{p :[ hW板x$1ã&~qX@պ_t5[7y^zrEUP(I6 wk<w(KlV46ZXqW`@kp N‰V=@Ceڏh9dH(2hqRmY_[gm-K8Uھj7v|n_M$,, 1O`YqojiLu\oioꁸh}[{J,+G)Me.~m\}b[B{QE2w|?%g. 3}.~ryyyne z;wgISI5=V7Wi6 |ɛtyNw2;;mmmHvttJ\t'׈B{lllNOO ʼnoWQZ1;}rTt:=55_ZHy"BT'''?}$ށaHg2DDC1ZkwlliDu8IENDB`qdirstat-1.4/src/icons/document-import.png000066400000000000000000000020211311502036700207400ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATHMLe;_QE EHScV/jBI8ॆC5^L HDiZ5c_4Qmwmr}_Jjw9L}3pe @tDf޳.rr1}{u &/}3 }{dBaZ J٧T樔iuTdO?y*"nd@9Gn@I* Mkq7_fym'N7M+f>0 p `[ KN45BٻK:~,Ͽ>11cyO!afI&I4Bj~K«שK"ؘ qr_:z' d||Q?JEa/wrv 9IENDB`qdirstat-1.4/src/icons/edit-copy.png000066400000000000000000000015011311502036700175110ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATH?O@Ɵ;;a"Tb!,F*HQۯoбt`P2tC*_j(T:!QVHBY:Ο'qUOܝ>.,1"pwffvaaa6>b۶ٽY}dHZ 5xoq~:IP`A<$\CX3p$H=M;) 2K<%"a"ѯ3;TWJAt@Dll$R}^C)TUdtpKA bqqNJl6 qR D]7DtA( D|;;Cf4qZPJsR0t'''q @Vt5Ku'Eb~ Fh6@.<2Q·-˲ !3999Hz7r055"B<vJ~y._YD}oV? fIyOv!I)hPRC*-˅W,#ZP$JTjJRJӵz剋|zzccz@БYʷ>&1?@:.BIENDB`qdirstat-1.4/src/icons/file-manager.png000066400000000000000000000022061311502036700201460ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs66$tIME !IDATHݕoTU?yM'SI  QtZؚ34,WdVBcBe oq;={{\y~ܹsX(Mҵ7կ.]Μ9rb(HDz}gmu5XYY!$Rvn>ZjVrm/ӧkgEc$E ܩH"5)˟_x7" LHIENDB`qdirstat-1.4/src/icons/go-bottom.png000066400000000000000000000017671311502036700175410ustar00rootroot00000000000000PNG  IHDRw=IDATxb`1b$ ϱ54##jFOe ?pb!`4'vrf`_ 20.-a``````xb"FFa/?!9"H ?3Y"h#_,ZF"&H3c`?M"?!|7?,".0 ſD"h+ÿ 100,a Bhr101C ``e 0 a7~e`+4ԌBσK ,`?F[D5[Sx30ABO3> ]Hb _3ח e`ç . ^"B Ý=?;0&1o) ,~20l,x0{;P3Vر000000htzpUksb``a4/fA –@(m ~B d@3|eC g```•oҲ:G5~g`xTl=+d BOƯӾ-eU/x`f[b \B ÝXXBu8 r10\ t>b`|Ip7 wfB*000(eU}10eɢ _~10l$v4m:P(>–lܼ?2@]/mď%xUp•nиPKď%.Yp"X$fzYGrx"ɒ9E"p"T![" ?a 2X"%1300099`B[(pIENDB`qdirstat-1.4/src/icons/go-top.png000066400000000000000000000017341311502036700170310ustar00rootroot00000000000000PNG  IHDRw=IDATxb`19bDsl e.͎]5#vO20x`d``bAS#a0fN&??07L BwF,N e``E  Bt'yVxsZXjB05Bػu\ad {S8|B"t86_HDž/? fxwm᳗D,Tg˒0G+|am'& 207 ") ") g"HE M"C,abЌH"I|5 "dE`V!tBeIENDB`qdirstat-1.4/src/icons/go-up.png000066400000000000000000000015721311502036700166530ustar00rootroot00000000000000PNG  IHDRw=AIDATxb`19", fi_B&",&4`~b-"}Oqx':0 Xb".WgBa}Oaqfp_Gbg`ng{Oa`o~1ȹ+S(```ep;a=w& [7߿:p! afˢ`n'&&H 1 /? v~CAB֚i( is CL&c2߶@JI]$I BU$xL4|5ﻯAel[>v1OOO4M~Ic̾o O1)w ^s~H.d\zyEyUU!%kmzfٰlXL&?vHQ^x=Ts{y!y79R*:99醇ٳBi|>߉i1k=zZ)e,B`yxlӷ<"<u }@Dvkn,@t{!I 4-}u]3syyl6&!J)`4qssϟwF% #@q\VU ֔eZv !X.|vKNܺZK$t:EQjt: 2)Yx`jbq/dݻ!9Itg-:BιE ć%㠧+8( T3u9_Vk 8<}nK$A NhV(p۩  7s@ 4xasMIENDB`qdirstat-1.4/src/icons/open-dir.png000066400000000000000000000016461311502036700173430ustar00rootroot00000000000000PNG  IHDRw=sBIT|d]IDATH픻E97i/H6K^Kl$HD8‚+2Bb-2`{{ιtU9GH :vw@D``fӫ?ݝl7s//<īcfvttӃTw^z#nHspgggO Uʲ|tppIZ1o~ @/)q3c0vvv333gi]^{#Ji!P5!ns@U13rΈH.aIfl6#LUUU9MP5u]4 Ţ۳.]Wqwfp8DUݼpw"%HnaW*eY2(˒-1c666L&F#"LP})>4  )6sU||Z~#1B %\93i~Ǫu(ifH 2_} Ep7DFl5bk4'#T>%e?,/Nxq<[c^)zƂG& #"n=yDU !pWB;$,‘0w3NH!D#C#AV,GQ3ܾ(@#+ )\.P$<w"/ T4IɈ A؆(GUżxBL&sg!4HlI  Z 'cV7AmE7z7{޾ylNg]ox VeƁIENDB`qdirstat-1.4/src/icons/preferences.png000066400000000000000000000027731311502036700201310ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATHUYPW=( VNUd)(-X[pWvqjǥAP+(mQh:ZDDņ?SA*DLHn\F-3{wK֯_>)H7wޭd9P(Lݼj*7OHH C--JIT*pGGGŎ;VM1tbe_Sw"BNt:QlBoݺu#""&?c4UQQQ.l324z 1@HirppX`N6or%K{{%?5NY5 1 D*^k ꚚR4L>=*...5 `FЧ-Z8(8hCl6hzϓrEҔ}D"S} ֝;wޙaX$aj-&˗/ݭ#>yŊK8(J/`VTw͜93nF9RM2gٲy8|x:BBBa2)ˎ'ɬ]]]G٢vˤҫf;uԹ aǼS\+? 2Y;4nH$?^ѣϟWVnuek׏l6;R)Cѩ c>Z]RYz@'*`xuZ,~$ͅ`he{ >wsN< ^g={5Ly0JIIm߾}&JNAQ|v/WiG5Xzu`FFaI۷[>4/fa]aN{n- +++<==ADm] i+dw|guL{{a=*kZ֭[#/^\~р0>2!##|ĉl!.l8p@q?㳅a4eH~WB%VWWk?t$!dhɒ%;p:!iC*ư.ELyrpxdʧ R$ô423*M ŶR>qi~P͋sHr H Q r+:Ć F9[TT-B@_tHts|)Fc7@-oǹsTVZnZ'σtjQnbxc,nĢ?xXg@la.'$$dsNKp GCy["6ws""`jIII}l6,YWOS_55f~hEF Y .V} bC? ʺ4hC׿V%nsg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o@IDATx#ygaz]rHYvK"_|=?+s'O&> Q]@P@ݙ3ٕc՗y*J<:oe^dGخ2}'+)N?’I8+)$$ptHptUn(IpHp8YNJՊjQy7~oRqWIk0_:q;M+I2I%ذoD!CdyI\W5H`S> DB2K 1 @֌:Lwx:7npbxǍa$ -Dk*D_}龖k5F`8jw{~oo]?[d`'7@BHf} $X_V>f^uggWoݛ/;-**SSUz<ۃ3J!5$%`mQjյF_]]y[ݧ^UZZPv9b1ٶ,5PdfH0zVZ ShW5V$Pd*az^WZ8U&ZӖ@Qi-^w ~_3-I lX(Q@KS˳ ~H`3+fQӂBҚ(u?͟F5|Hu;j=-uAVLh>ִ;}x7*J߸.dǀEC>hg,ARzx>  ~@7WT$]2(y#X.#g3Y+3\.2 od/QCcݷ-hj|TĀ;ۻsw{N^Iz"J֕s$ _OӅqp޹{{+dSD* M؊ G)\k;).1I``Vx a?=?,r4bG~/pǰ@2i JZmLƏD ӑz-KTGPqA#i$=u7s$1W6/]uO ꏑ@7Lo]kc"ϯG0Zz5Xg!09H9@uO0'`N@hq=Lg@ h7QIM#X-# pPq6dEF`k~Q^ Zי֕TW$J+;lš[wFC+3Gzc,sr&Ž- =MOZFoJM*(@D @ yqg0!0䯿@Lɱ^ooch4EZݧ.}SC lZk`9W])EH`/=#ؾekI@X;tg}݌e1f$@m4ԡ?2P2%ֆDC~w@gݨ΅A7~y[4Hzk5i; 8oߺ~Vk>oW?vܹ* !=d)L+//\E#7$P#G]KN# /~ wyymsk6_ ߹o"Dkqn$Bnvvٮ{# qQǵɿ%j)іxq]]]yKovŅ?~StGá{޽Fw<ޏ03SCwuU~PwÖR1l)6xq]_l:,C~HS` TZd@=-C`"`Dt@-[mPD4C)DmDMzSY>%am4o!~LX 20?v pm;m><+㦻aw#HAѕ$=(cxJmz+!B"k' o%[%=ൣ4~ 2l-V]0baq!ց~ӟ>hW6(cHS36B%0 ` q$œuI ?ilzރ] `YjFkDXۿC]g?o,&T,sEH=Y 7 ua}`2D@kYxz~P˫ۚlFlXӄ# OkC@oJ_a!@6 _~CMzsS3%=`?9Nn"of oZ"o\K f>/bݟ~ODSX⬏ޝ SEzvW>9?dI #]kaV=PUlb?곯 INSF1N~Jw S7*+ٵ{bs[a7}3aID*c$p1E7?#0I,j=i3l .s!^Lm犱:?O?J?m䫪uoi\ k9Qz1b25`rEsm .nnv|#sO@MuXw \L"k mDm V1I`ƗJrY/U^UZUoXad7ls}7~`& ƣqKjޗw޺GEρ<bA̐@#X0+^ |"7xɨp$[UѼl6 hJ0w_:s~~5&#; 'u)}9 F#H%? >Z=DTkrw ΫYCj]ћ[bə U4aqG~}8o;}3^D:-E!7}y&(Y6Ipw~z~÷?asn L{DžF>ozf}tBs}0 >ݞxDo-29_jx"R9=Hzt:=~֮e/?Wv~# sY ccnOJ2hXº6Rz #HPb6`R%=DzX}}_] z0"`!,?40lM 9<,Y'Ô %=JMnRe^f+hIM%J픳fYU_XB3;M3#Um5X\ۗ:a6'c}W&>t`"=H/f~Ȟ§D*0ܫS{ $X]MzEN (|qUFFSsu!ݹ_g砢G`vqXI`<=?FSj=?΃ЈZvvsP#H.$vA} |5OZ,4~s]q`>pgGFnMzw3r*ÐjQ\۵Y$XVOo M6A@|Km)F"u$;Կk_ Vk>vuDZV`%HV?IKy9lM e_Iiࡑ 7)%G<6;Cs EaT){e9{P1n5E%#8**l X ?ɃfA kL1)fSxI }o<8O#ÚDK < p>g " CD˳݃Gg}}k1})KM"|R~{Ez7]tb 1l6ؑLJ06a@|wjz3H@zUO(=L"'>j3#ا{*Uzpg-#BoIM< p1Hs$P~#ec^DWsZ-@N*~}{ zޏ4ܫa=P)r|}UKh|n:ƒ< ,RTHy4c?[ H !VuM ]qS7~(L0n@?Vt՚k[M pi߾{>,/9Vo&0v].#<7nzjE%iom{|D|p\^rs6ىb2^lԞTc5,$|1T-مv-`u"=5(S$ëi_׵-v5Bڢ:ͯ-ۑQD/zH"XcZ~ r!o,OsH z^)@v R߇LJ7E|񻁿J1Hۀ_ zPJ`1 WkJczl׿q/n14dBlMجJsSWW5&f @ug:+B!+!45:G7a!̀Z~@aA9ܸ/7x/#5y q@" bii :Oz@z~Z*;& >4yO#91Ȍ ڲxߔGXLXda,;B&8@?-*L3 iʙ'ܕ6 T~,,F1-w|6̓:o`L{x s}sL-~-~ 0{#Ck5 ށodl dTw]>/IK9L+x|:@gdl>U(K?~.bF06؞<@h@L* g1(Dٔ7҂ۈ{˽p)C:k+2_- uTxJNvy)@a㒞X`M-j aBO3 rMXny5?n2mF1E%2n9¿VxQMH`6` !=UO8~lkiy?517 '_ʂ(Wm pm;mRHCrx^g 4貆b5&VvHf} ˲1 7p{P)#͕->n暗G+?_g dA62HO`U1}z\=@F ˧O ؚa>"(cFM RQ>'ĂYS'\u ˂i%f~w2kHE7e@J],=170c=ijyb5<\m$`p?Ȁ z~KW'Pt\4y8A#7:<-o$POU UoEm-~^G^(kn2 Ɔކ#, xFo`nfV1Õ0+aE+.ggw,"l]=<^6VKXVd!^C iqχQ!TogPуkEӽAx1vzz^66;Y7~$UlMo܀wQ,ofgw|q<7e,^/2ggSR @^_H;YZpH=\v3>ںN@¹/zellJ}8%:, z=}~!޻8;BXxV#:KO =+g8k`>5f^ +#`K/}{kS}i o0[44`할>XMo$[yySR7xY^ ІlnzJ^ kȄ 6 @:4j5 vQ@ EzEPGlm+wwwEB*3 6 Əx?,a Fea'ϊ!M jrCHed.Kyx^/q‹0 ˦yRY'=lO~cl4`O6-!&&&/ $4HO>9H?+Rpn/?̘A')9 __E@^v8H eۀFlDCC[O8WؒCNl 7,=!o,i-_@dz Wq[:8K#\={"Uz~8x3$(b(h =g]FQIFe$' 7jcJ7~sMM&W!O@'~<,+`cv-#J'h8#R(E (&Q(#/&WOauC.Ґ5~6ch6\m#6'/,CY[yqQ` &eq X</ōb+#!+٘ꧢ:a)(+c{LJbtj?W xo6IOg Oj_>+- LyF{8|lj^(s_WNm@Z7UGVZ?rҍVOtb[ ysU@,aWP`e,`5Rc>}Qz+2ʶ3 (}|yne<@p,h0muAGr ڽ_]y_̞‰Kn[{F‹z@J@k^tmtT) 0o_4z+dYE5HoO*=^3.gŪgՕg(`<˛h[R#a&F&Rҹpl~t#qaH Q .[+m5 "n/_WB=LPL=/ l C [hq[e^q0uFy X 'cxG*qA1`oȓ)pm4d|dyHʙ|EJji-*[Mqe`W4z+S| l4b 70| !>yY~?na?*}o{%N|/<?p?L*VdL7um Cy1DK.[U'Rr؉nY='ɤGJK*=&Xiky( N 1ܧbhL6'/F,7 ,J?-fV>ie拨Aδ@ȧH ŅN\?dejW&})Ty[Ti6r|PW֠bxUUŶ4/{+2I 6֊j_pB*<Am+a4p˛Vqz*7ta=όX2#@^X3S/?!kNKb^W zz)jemz'%?ª ЇmuPWGg^Eݶ48$e Gj4/8.D X oonVдA@h4(phl>xM%, D0c ~s%3M-qqctz2Ɏ^?.r=LvV wwwFoy"6?q @O>VS$v:>&"xuj uXH_t+~uIܞz Ѥ;ou:!rw: XgFjT>Cq`MHZKo ZCUb˗8E#<OHY`,96("1Ã0QX)P6CORےRz9ڮl.\M~-5tYESщSL%FèO} *۩W*==CG Xd@HE{j5i gMhqz /Ȅ+a!_3v\7MOy W#M=2 uc )2eM=荱 ~Y|cz W#1:RgUszB{MƮ>utx嚵OaU>o:j%3}&I`\CC I*PWkL ߙޟpk`OzFVcI?䁟7fx'4l-ȩ0B |Cc`+sz Y&VGt kH4HE/+ѭI~E#He0nN!]^ߩEUmPǣ* #'cK8?k\q]pzؒe[eifbg=soj3,˾?3 Yi@Ht>Z酅`"6ToCٹ Ǖs57joTZ:I,J`.G.*5Aniō߄`/J9hU~:y$J8o˂0s^8a%ipssg8WgFv$,?Fv%_Ly^48O ?TU"+T, Ä שDpG<^qsc CY[ydOGj ϒ^Er#ga1pǿY"m}I^pmG|=\1Sqiw.Wy|5. B ZR1mΕ0NzhDb|_UֵEڐI"LD3K[oru$@6hQ vM: #/7bB _>b`۴{F]H@-G*ʻtë+7ƾzmOm48,0aq(=w11߻3Yv,ŗ+;?b8g t\2b46I #}QǾs7g̕MϊhHxv"K~̪28QE=9DuHkLc =<f>p6=w1o`n`iTsYl{eϰ_~k~I jՕ{=i`m!o CkH c7oYⷊ@L EGgf#?&E(k 6?W loXٸDzNևꚴv55Qa*󹛈T갎 Ü9m%O ,T{xf lF0FF$o,<^>H^FyӋp+zCL}pЃM= r ' B~qzE& ' ]7w(3) q!_:K?oyk"򢲩@[ŧ ؕHgd`':|(֦r+ e au(0Vi@ ˞pBRWf #&_ky{!z}E_Y $˹J`5gn ʀΕ1{Y6~/ɍ\l3,Y@fnkyſ 㗝>2$XRT UPX~3' C>˘ l@E}"b_<wN+& ~,݃# bB# hcPĤ`JXQzn'.ܧИrDƲjO[v7xN>!҇8~Ni86_<,MуlŲϖoFMkeH9 c~hS Wqccr'XQT[#J[m_Af,nFXˆc \kK -5P%YF9IyC1`WR+G7~sA24TMUyj7j,7rͦpc~uLN~)bs)Ez$@Av?a 4(t?]~!gd:S1G_'Uf7W},a[dqVjv6NkYj 7~{ h d}fa?vtaU-'5SwV#p 63')Ûwb(Jeum4r- xV2;!;X<1/1xA|}lxVOC+FEp̿! /d^N.;^)þ!u#Y- ߫J@ g~l<_LXOѿ5nYW xx/5OoqN 0G+Y}m[]v27JȂX{O< <3kESQ^֬J~@2 "̡nL^d́|2܏G%x!Y\kYMҜZm Ԟs^=,* ,N7k*f!MDC-D~?2+@j'X凉,qkP=0`n,p*[֋Thm'MH ?m~?'yH`N;&Z1`H3k%, z ۡğTɯG9mfCwyFev!:>@$/\af '*mo;@Fr1`O߽ö?v5͛Ļ{ $@zmS*<~6pa/$8~o;9?~z~n՜ш Lyqaײ5s@c䠕qJ^}'ȑJ< ȞpaMv';?L+&=32ya4 - 0&~Ŝ?^v'~u,4G@ 點B֒lZhm@z~_pCa{1s7̂l z Dv,lz󷫥yf"]8Va)pgm﬛~uҗ e8Ɣ n,e& ɗB {&[xô~w mLFF ͼqyH,>sǿk(/~<~?DWvC@ M7 +@)no[+7L:@X5#>:^2%8,O+?|EU٘ ~M?y wB4mAvyDd2s ذp&b*/1ƣ#lQO9C}:D Y /iAL#&o>D@tߕH,J!>#g@Ϗ& sz?zNFvg$@EJMVOӏq𞾭š>3'C}F ~gƤ6R{!i! lfqʼ Xy\m4bew,y$Kolp[B23 5a,/cCGFY$`M'HF̆lLV{ + }Q`*Z}/)D+jeC;?xk$0ᖻ;oT$bϟ'o*SH`I-YC˾q`آїdvx-n Zfsً v**>@NMy->z7P}sK3/{oqh`qK6S8`Gd yG>'KA%sXF&7߸sQ] mUZ]m׵׮jF>!~rj= 3{G9kaV y~LCݻ]luV=sʙG>wJםM\j$_vDF@v1p1_ LvSP m' 7^Mx2-D9°?@ Yv dr^й_bx8|"Lꭷ~ov]_]_C^o(VN#LF'>~Up¢;[O2^-9?|]K/Z~[>~tXOyj6]tZk<3$Ԗ-<ѻOD g"3W]d:ٟ68uL `NTZL~ ШzNyxǟQMr9i/#{23 8y'-yNN& NW~Ke,F ;Y"Tm *OeԀ遑񞓱5+Do~I/YԴz{O( 'l4w+,yeG{F/M"9p7~!\: iF(JUkQIfc;'ri@ykL Д}zH3ӓ6z*F[DoE+T#D#l gb矋vf S5~}wM!{u=AQ5זA>( 8f?>R 칮Mt>HehaEtn{d*E ͽȹQnט¶ᵢH[uA̯#VQ$}H_*z#QB)g4g3@R۳\=_ p|w?tg'~~.fG#ЭVw*='m<@O cst@<<d)H`x__ oEVroe~x-kd?,LL;{x<z_-F<&ԫ:Q 彿TE)+ mTYU~ 7;_jrKw/}1#e;'sHS3z9E7('"-p `gv2VLY[^}#DF` `zJBey-HyUGNpdUghAޟahD`#KS/t@"~v0 $87+(xA 1vj>?X Gx2-DGYh~WqO5 QAF%E^9i fzUNJ&NdۃfS@"@}t4>M0Uז7X" Ȱ_7! RJ  =׻\/u2yCnWOs ב@{JLv25qu&MVe"i=j[I @j$TGſ,7O#Tao@GSZJQ@8c&+uR-FŸ*jj, /Wk|.wC~%F, 5"8 w>M\*DKEbb@BT@ى^=uI[Dz$4@ \`5 )%`c=״FuK;H | v!6$ ȹg襣ޅ]G Tu(B?an#OОuu%_wwI=[x}9c]_G I2ytGsӣxkt#7?;;+g]y O*/ٯ]3^=N"(&63ٿi%?>5hiT@_yR*bρ#>w[-m6} ZB?[H^HDp |!D7ݍ@-qk' hHszjTa:AچO"?osFDrRg]E,T`拀q-D{C˜!qE? Ū):%_@  `c ol#f0p0^0M{ݼCDϡ3~BVkޟ;|Y"u[Nw0 gU w~'; Pˑ&, (<ү'-sހ#p'm}^?@ǞOW(}/G(DHX*#p"? 5gMaH{?Š [I`.DsY$Hu!r,`eDT6a>`şG(DH@1 8"`CaP/-jzȄEG`rJ`Hף$0;3Mb3 +~NzAZm5)$V!jC`0_túN*VEk1]xK#H|z |!vECt_W$=D&t= ~V:^k=tNI:V0g"HzIhecIz@9o{׏G?@mɶ5h"w,L_ M#÷T gs+ZNVT_ V:>RDsY$H)H`9u{Nۀ7"+_ Wkp_( Mx0a\,#zb " $y;E)ۛ/ߊzrOb@#HkOSy3^ ŸdoQ@$h$y-^AwgG/ n*'#`4JyMpHiʐG'mAv\PwyR=9)Im/aJ)O1i֗b ^HF:ؔ_~2~G)Iz~nZLGWx;ʿ}R=ecy L&K|,L>Z '4,Di˅@"'#C3[Q&E Q) c/jzO" <iOG`Oo#-T^mnlz-Xlb_w-S2mmݧ$O-Ǯ"ϱsm0k agy/P.uv1Nz|jCm n|=#eQ0s|R#U ۵G=Wq?6>5ీj$3 0 ǯ#>0 L*_P};_-G kCm`}5m\Izcxޗa[0샫cYC0ַ9%7NH_}š;ݿ`'=%o2݌@#c6ڇ]ֳs4?b^vMK@yQпC={ Â_,c?_utذE ܂*j ^ozizMaשR*rq%|^Q 7/zǮj P -=?ܣc?̃aLd?Od߹Aog={%)27a>kaYBk2I.gO_&Ҍ@ՃYG!WUX%O|:}Mo*0ZQ - BriFvz8__huw٪kD0F,;}\H1y`=?;MÃRR(m.IG(S;Yo c 尷|~@?~w7[,÷5%k7jU??$0MD@>S,@y2lI؛lj=3he,XU x0А^+n"{f&b4 HBqFy#2PyʒKB~3ieR0W< ࿘,*cuTk#VqF t II&I%` dNΐ|mp` &F-f-=#ZpJ8Ӆ"0߶K&IT$@s7 u>viNzH?#]LYâ]!MHx" $x"bA=$ <sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o@IDATxr#GRױ:uƎ]1%FdR"AbǸ/\T(ϲ##="Hc+8x*=W.R*- /&o\9*)- @ iJ$@ ^@ @ x8M @ ^@ @ x8M @ ^@ @ x8M @ ^@ @ %rTVYhz:z)qVH΋yg6+|vL&KHǁ_)5i* =K@ p@ :8+tי6iKLR " ^x}?ͻ3 G)P'ZX mFÇīԃtC*@ :bڬyRA$ir4>ͺZ`8ͅk?yq }H-NMaEajv]>R@ @!^#}WuN,"-,41>Jlj 82og$Zz^D {@ ^j\Ft Efdչ|2 !46+eVZeB+  @ !jO*̾wy\MJ'b^\%.hF>Jthyj4.U5g4!P#;s@ @a_]a I0?|{yq$?H"g^!SҘwYz'o&egċ9 !A@ Eq5yЅX $766#PA)rȼt؄n9e˹/-3ʃr؅ @`gD`gP@ @ snM OmhX )6# UYbg4l6I( k_?M5~~p @ A#<*G0/nz4H:zl|`5 .L+VԧO~7˙zU}Tѫ@ZiP\db@f)Vk /jБ|L _مpXTrP5uHGoa@ @ kD! 煍릣5oߣa<@}uP¬+)SfN@y$Fï$!tg2b5 Y6 HV判IT45ͻ3 ӄ`Jo݁޺t?\%)=!չ|2 !?z/-j=-rr 7@ uZz䶭d,zF ~Y2̿z(&s _4]eP| Ț"K\ӯo 0Ĉt|?? F +iFL[>x]P)5saЈO@ ptѵ-@ kXfjk"# 5e>r^Uͣ>=+b_pfXwQ3 -'0>YzY?YL괼vTV#ccW+"'UBU,ey ,_?CQ!_ј@ @eH^Z_ ։~?k#wUU4#^(r.a^4sX5V Ա i@IyV<^>6`1+LcZ;̗ *_5?] Jy /-,y9de_8t7Q'0ՙf@̾+]0x.tU T|G&,f!h,.Ή?TRtAdCW<)0| աWF_gEWԼ|BS8@`@رp@ @Dn0z>J=HGOtVƃu!B }Ew_(]ܙyh*G=u6&]鹝]Qz 슎牫ԃt"M*  j(N\d `RSo*Y'rǛ+?cr= 0qEc=T (hTA:Fp^zXNN-5]u%vcH\ˠ\ڸJR檲_4$צ:U&gH)Z]-rrZ_@ ^^[U}*mÇ$/.l8`` yscDNHCYow'z]Ũ _2r`wmгR{S]Oo~Y  I O}=r k'na݅P}McϮH[Qǭ5X {:o4tڻ՘_9̟38 ]"P{ߥ@ @DnO"`}*Ҧ#xg?mc"ZӉ` ?zUbe"D*揞\Z}"7;L:9S/Ӈq?Tgqfh|Hؼ{?8m*oH gV T뎤)D"1/ ׁ@ "/`vO_?ݻwTɉ1T$5OOQ3k3o93-W8r'ﯺ|bw.Ahdl!kţ1^̻nRDȥR]V\P1-ߕPVK EB O@&t˹+t.PQ ȯFivCT2@7d  p@ 2yrn;BH}5}HY#>H#V K_1[{q}7GL3d r D5ޞEKx C?Gc=*߽]gT3_-7B^?ǮaG4X_*>{G "{8 @ 59\%P@bA. Ko$M9L:z~&{^__ 'jY m@ E77ZD&"'@gL̞te#EG}byet Rf!,:>*Q`{3'ٺ,]K-gag$Q*JB%ґ}o&,f!h@ƀ pC9~7"T*.z4E-@QX /lZ>UWԼ|B.v[o'Ks^۸n]_XDT|I_h'C¥'{7BLE$ GϹ!Q@ @ >:֞cdAO80t ƁÎ`JYtat|.k_96ٍп.m7N U{\FmwN* =YPۡEB!N+=D{Z]߮=ҷ*.*8PAORu >$߾ct:Hdr{lQt2e>GkAۋ; WxJ\y.3;b+[ !Y0 ,z ?^qcD~+"¯VK1w3|@ #W3% @=o0UF#IGI:zHґ0P!!m^wpɬ]Qp0}ΧW ]ŃJ=H'ФnBzEwAwo!>-ʻ~C[ S3sf<&0&7WJ}8'&96`-J7IIkTA:zbX*QO _>r`o g0כzz d51_|Y?]uB=ח] Iy?Q`oZ FL SM_$c f͹s.gjWww%+%"7.X y1:=KI~r?'ykU9ҷD0@ 7ooQϏ`]$`0 $59;uβD4]t"UөN8 Ž,]!V,@Db .@C\*k89S/lch>]0 B5\#caum&1NOo`̸,B#i LfNvMʣ|^1_@Rߍ$ב13#_n$r/Kj|R{I{q@ u&@ HYF~O3`֜0aHsIJ>$c 4ucBV4#XOu9~ӧn*"EZ/Bv{DﱇHYB "KpI @ u :E+ar0W"4}IW毟a0R$|$!'5kDW1JUpĉOn}1 uR#(@˙9z%PIt䡌NhY( gn(7&HJEYihcC:zر2 t]PY>+v0쓎E+r ]nǞm7N }Z9zn'+%׭Zv읷J=HGwʇ-:ߋcV21K{H>_~w}Cv[rn+=]JA%|t> O٪lYga\tSyo{:!۱ 'xIāޮ\ |L 3$aGDgcS{7&9l*ύq#Tag;y@ @ 8H"p%*UG}0mW?8F$}$!IGS@ȷy6]\[+}a q,6w;x9rv_1t^VR* H@ @HopYxH.-\ZyW/_`h";aSc1ׇ0J$LE @U*W/vYIm.RW"0~t="x2IR_~Ko:r㺻Q1T$pzN0\Dơ"2 Ӻ@N/o/zyz\u%zx''ernϴ J$e* UyIikJRBչ|2y?CJ车GCԥ\J$>ray=dgG֪GQ2(';/ ]#l̄#0n;}#g?t @Sb "WU0|e˙?k_s䇞.ߛzz d5m]˧95rw9]*ާ__"0~v%z$-FQbqk *|_>21GN_!S=Vǿ=׿|O6mkhY|؏awm¯QyO7;OX&7~L-NsV*q@ dž[=DŽBۈЇ c#9;}Eqt۟ X;etĈ{4}0g6zzUNe"D*揞\d1ͥy1E(f u.c~ק ƗA(Kݎ1]?8r6p$DKU8;V T7Zaszy7W3Ǐ$?ERdLCO;D-UTyUA@"9 b B";@ 8Fxc:ƶE3i ƈ$?ꐞa@2@hݘG͊D T=.+OJ_ p̚rq?;y׽0 Z$λ)QJnIulj/xDO'+L$P]h]@եy1+@d|WBYaά47-7.M^v]:(mqa ݛOPHym|B?=>o.lH!V|Um4Y?ϖTB"2שޝ40*ïd-tS>yUdaVu?_XƧ%]J@ @ 8z}3ǀ$̟>}Hf h@D%" >:^wn?Nҗ3k3Y DIH(@0;tEә{ݻ;=JJ-_?̺)#DO*3 },/JudD؝"UMu\z@|L㽶Ѳ@ @`-X MdY<(aO t.Azqq^00/f$]WL{x~#<Q6.Txr(ev5}@g T[AԃtWJzPP~+utWolHr,sc2T3{x:d2OH5m_v]G"H@ eJr#a+[d? @10{ҕg~> 'I:zȶ 2>wAP,[@'G0 Rn}1 uD][>8=V2#, d,ŅϷXsoJ?)/ >oWnZ܎P?"?)"1/2kkFG) .&ju((o竘Zʃ@H;=@rQ@ @ ϿyDسܪӧ?z:v']W"TJ ュ}w_J4 v vCMԉmk/+nǾ2v읷J=HGEV>vh^FJ*fi҇,( YS^AꟘ8YSM۵~s'I^tcMg4hCRÇf)`:O20sczۋmߛ}Dm8@ D裇}ođ0r$#IGI:}}"* =$D]Qp0}ΧW ]ŃJ=H'Ф7>8r]P J~|nf烡r[1AnQ-ܩ)~s7x2Ma0L!}R?? -{GIkTA:| ^@0(J%Ը^?uzy窃^.'DZ~<}ZrWU2W]i]^ρL)߹dQe~A-OkݖW;  .CT:#+ㆹ?|F#IG͍9$=NHև}OO7(@}Lb^(E=Zqb+7y r.2 kc 5QuI*|p @ e%@H!a龎G2k@#5 2@~.Wa`woq_wjY_ (`0LdHA:] C?G2[ o>%f} K%Osk_Cq#O"!@ |E;6 ‬Gճc*%bb_\\1@>;P/Hґص}徖b]}@|DȈ"'*ev!5}@g T j|* oVEU8yۥ%MtN$$P.ŒXIS* =YFn-@ X@DɁ!`@}VOzϘ=3L?CF$=d3M@ATf!,:q>*#g3'Mlb.i9h4~E*I=VcC:zر2 t]P+vʴ8`i_]׾^V:tsvl{Pg(9?us;Y).n5ɳ`\Vzv>~K|Тx 9?#`׷Hݽ-/ _n>5y$`:J3^hV @ x "9~y?~v#aHGt$:ETA:zH|a7p}aWD9x/0tiyAWe%ER҉4P4>8r]"{>Nv_of烡+C_ׂsez_r&NSD@? r`7^FEd6^?uz9dsA/H]%}H-rrY%f*4A/cѶ@CFG]W s~$GțN"IG9gž/=8>~z~1FVxzz]ŨWS;gծHcga}ǽɮ\@Vc q O}^# k'ۮ8qU/ ]m, c~79GDc $$cCPX @ D`(E sGΑo!'=Z?3Aā w:#w}> `4aWiKYY$>+=pyj "7/|gIWsYЧ+}"~*.]LJ"@ Y\ag(nsr IG"gr?;fcѶ@ @` XL$AKU_uH0 k+"!z%O˱=v:=[2+|%3kYT^k?v]y E4J!y>ÍH/x{ }3ю\Lp+9lnGJ&̝دKIf\1qߐaDŊ@ B "B2{FHO?YPEd\Rx @{ |(}9;]APLV7pE eK\j"a;A;o([> /,d_Z+ j?ynߴZD@ !pJ6^K4rxTlUʊUXK{"]z؅ww(?}JR:vMIOMjsIG/?seߤih=eWz'/O(k5(D˯9ϋ^ZwaO;I:Ifi߿{HvCk*P?OvClu"BH@g6fv3|;Tgy;y #Cg{= m^Fx|;ėsKur>ku[$$5}a~Jlnt{Anny\P*YYs>Oԙv# ԃ =ᖻ0u @ CEFz;zskۮrz*^<2 |<zvsY:X"i7_Sʯ u&߂#y`WWPI& *3<2a['=_yivq6;"D8/QcbnFSNa&Uo厖t#ٛ߮(|s!FkV6bگ^>-_}@ =v]XT9y:La0L};~L~qba&/*'.TA:v{d}!?zo'L;G$=I$.- [HA/z-R4,Jh4 7ur]|ꠗK|_MCo].ҵ .@`[Zܟ+@Op>&)|u.LHqJ:) N`| 8;[n}§'ɏ'?2'7p)zj')]^hy{"9-`@~^ۜ3ߺ FYgڶ;E3X,⑌u̟mϦ]6Bc/(eqvfLz͝9pa?$aGāH Z{t @?}$BM . Ca&"@?Ic$cհ=c7/T]jOrwy]*ާ_o"0~[(=O|Ur|=7eb[އX䯩?7BcOj/+{*!@ !lVW!^;IJ3yRM6_ ɟGd#']Ȭ'=[Zn(pK ZK+Yx$A:-K+G%ay$S `0}@A'?䣏s~^{N;\-,2 jǎt4_?/cMb7~iE;n6,%@%V $JO塴O g#w @ 8^gگE 1x1 yI֌GÛIK^1un')]Ӗ*o"h9sMvk`$yZcw$fSŒO`磷N=P.u~^Cb}~P~-n #F,"x6a { P>z rni _ ڳ׏ ul^䞫sU~c,fi @wd=~t\d@s%2[_YRMM[:kU =~}۹;@ @ pq58}4fQ ~*KAԐYètc 3[^}u2Y9@ 땍vf7 I3WtUTI;GsHhHG;dN/@X4MƲݶxlm=yqzjөmE=vmvq־"^_?iqzntwNgr pV '\kʅB4f z"{'1Q]P zmpH:<{",D@ 8k-1?+Q\ΤaأKvӱ[A:vHC=\ͣ|Îzw]$c63M%+Hv;[6oMԋw iײ?b OzuH2=ޟ'R*̓N#5u")gu'zAꚨz1 `wH J>#Kt;^s:);x {eOE{^.@C QFF&}ʼG9(ɇiTLrUZvA{ ]PZ cx~o,P1ckɋ1=pz耱)}ɿ{u 78a,m%TmR>z9U~+E{+z@ @ _f M:t9a!Igt<}䯓-V]ESc]rzz:0hh-wYC@S+A{qc(tA9&ScسiDD`ΤJ:OtܫZv]oz @ #@ "Gp :VZ9ϟt$=g0[ʃ +<I쐹~^<#N-;_<)<^Wzc/lę%P߻3c2YG!cQ(1^$,NJ:A>s"#@ W@DM>ױU%$aji0u_jI5@:${*mS'~XN"H" G{}q}7>ǝi߿rgED18X Y+&q7GD:D-@ ϊFt2K}IB4F  @(@7Yqcϥi0Zd\~5~g=}ߟiFcU"$zص}幖F/=0.G>ydd;@l+rVےr(TtA4]H\X`"5uQs吆L5 vI(=,B伸8=I\^~^zu=!1M#Ng:Җ2hC%Hwv߈TƇ@ @A@#4w՛6RvR񆂝ްg9 eҟft?ʇɒN}`䣏O:ܶ|!c\r'>#~}y9*ՔYz2!n}yc+!|wBݕ [!Sw/v{%'F%ߟTlnpkssLt:HFS<kGa@  }#/h1275I닞J=H@D ]4`0]r]4onz_QD7ifqmnlvThsDUQE,P.ƙa0_RGiC!>6fc$=`/@i9 Cr? ꠗKr}@?Yv:EgUv/Ye~Y~頗˧V:4B٫$UuGUޮҴ %e9z6=:u/kJRUC_0|LR9չ|2 #'zܓ:"fs`dUowwv[wK7p$ &?d|SI:zԗvk?/zCH?Hp\"[ɼ3:m@}ִz2& _۟^~#YqnM~}OOޏ7Ơ O/\n"EBz6DҨtIdG}}ˆg{|~ca` 5 4kyܶg  ןCHs`5"3ESґ.z^<38jHzy=0ϟ=/g<^~cNciR$+|%<;3fne ?>򼫜s,Gʂ>z9#a?A\'1V / a:M-![:ZM; bVp+E.Kp,2?@V[_YsY`И?K7Zq7o~^@ @7Mv/M~9Y:I a)s& mW{-NR'=ݦۖ :Q}H8 jo:M&֧NI: ̽뽸>j~42췕Ѿ?C>0Ԓ0y$o "*?U@dM_dg7& >nHYJ:g:C[nT}9x=hY;_@ ׄuf}M- FaȊyKIϥڪ.$oEz.KO?|omm}s}Lр -k.pX "Ǻ<vzmˠ{.Dze#<2P;h~"w?byoY=K_x#HؗWm[pXzEE-GKp'@zth\#m^4+@ V!۪H aduFW0zy>v=O:L G>Gʧ>ԃzRs}GG/{۟4du ksN1+ N乏 { w~(Etƨu415a0~$?0¾@mmq|wEUQGbFE~pѾ@ @ !K\-)>M[aRkat0uLF=F>cm_1R\>SoE]KMb 1]WS_cvl9]&O:;Wo}NvBHӓy HGmAq+s;ٕn05tOn?rs.=~0}W/N]ȀYO߶l:gmvQl22$CA6-MEM\d @ ["[<X"1)%|z~Hs;ɧ\|GH $vܞs)?E}?|$L~6[2vI>]^*~]C:z![{I:z9/v.f^FVa7q*&LAqw'KC`H~4`>d=$^j׃H'n~UQEZb9vyklzN=sN{u;z۝ɺ1Ɖ;">:hYvR8#v Ga #x7;2 L<8g?QoSyd;y/GT#UՎZD/o4.@ X@DVI5U9χa3;a9#c%I`)'Z/yOm֍lVQ|& \zqh?>D lƘ?v`8%GPrlm/Xc%G9Cn7wb/m%4_\+6~Y>svQl[kzwf[AL3>żI}᛬|T:@ 6C "V2)K3sM鯓,VNbmٕP]܇p^#'0 !a2~x׿V{w]|?BONE(MS7g7@7(1ZGdOnZ'\* <|O׶L}%ǯ\D@"d @ !WhAΧO^#o_drU30\DVLK'=j_My>/-Y_Oϟ3c؃ /}o|HNJ"3/O~n9tU-"y`u -1ءz^3Fr^ z"b Ǘײ#/kfCT˾GP>ydd;@d11_7&jJg6+&tԟ^t쾸<Dvݴt4O03_H YL涖,G<xI@ G};;D7l}W͙G>OYҐY0ef@zt|y8>z G=tmC7cr[q_䒾{YSo :9'>r} VC_7\jP:>c%O}MJCصOguJc(,[E؀e53ݮD=@#3*-RU/J)PD vY8ijO1b2kmM)0É=%@@WwJH @ cC "vEިy7y}7Ж(`1&iUbe^ac"})??Frg4#=B92ƿCB)L1:և+ c:s_ zHC[߽ K #a9r+q0yCDΕ>=5Îvc.'_Ba/}%E}z羍agC\v}E!{1%ul/v@؞nab,Mp)m%ƻ7w?O䫞~?%zMn~杞ioUH @ cD "xUw&ޤy ]EsIw7 &z`*0 UA:z=Y32YQ*iz.OW4JUyؽDg=vyJgUvY^.[+cDh 'xe[鉪^.Ut}y$ņ,}ZGJzuK` 8Y?$Y#Sgӗ1,_},")By0o$asv/P.t>\/C^>bK;HҘ\ Gٱe~p?q #cv羴Zǀt^)r=Ckt{ya(HGP(|_Kxxc哎vE"5ƞ=];nךX볥z;Ǖ0~ŸzSMhB6S@]H_~H獲L_f 4fIŭS{YX@ @ pD/꾚 =iK7 GN}ŭoKxS%c|_3?D&8?t9v/vH_[>v0R~Cp^ྚGqR ι\}qD/R]uv3ڞrt-Ǝv蹟Gv좸(jI?91 =ݐ|"nZBi=caυMV*}@g7v/}A{aޘԢ)7̮?|CWI.-mldbIF&uu= ̛sȥLu[TCRY}@ @ pFqFAzS7X^DyF\y['~mPHg;|THGh,Cmh'ԃt$M.~CpGם|7jN<_\/]|v${/QG?0E:Qs^|obG:T/@0I0*7b#W|,&w>]`0|q=fc75 Jж1-_ pvbBٛ8V[F%75H!怊'dD'@ cE "ze?C`0u掞k嫽_'o詭ўu{ڊ޶+Nrp^9;}> o63\i G cG'=$~+ۉmiJ\7ArqvHfL3^|6"50c @ JFa29.IϥڮbмiSes.1Mrm0Zܦۖn}XsᲔ1JiT#˯-3-魺rk^u^~~iCcNrr 9~u/K*Ն15Eu=-_i?% q[OA>{LM)KRy`|oDl @ 9к 7r<ռ\o4h_y>z }וO}C$s\v1{7,W1"p0tO}Kҫsm!?w}IG.W1dB]9塇vA/{֕y|@:|x> 0>lsa:@d"`ٯķմۖ|7TAJ$ J?^F`/@ @a_oļ7ia9A[ѫM]dWkY|9̛<>??ۖ|?$}ځ?IޔD=?#=Çd 8* =^ҿ̶󟟝 ٓDQ$%ùݏs}oIGo:u_z~?/΍bG~o63>~~X.xa>`/ l-{C@Lwg~Gr-ILJ7mL@?wsk:o5:{"ճۧ3pN@ F "}}vNoyaYM./S}goIدk k{|s@:v!=ϕcA,|ʥG{!s{ɧ<~i J=HG_Gg}8@,ʼyZ~6u:3oI:zY,S@3^x\?Md̑y96H  p{KGDhC-P\z//Xa>~" 4R*`jlUӟx*iAխE?յѩ`S᧞gt8˧SrYyǗ+qzAR7tC.7OtAR"IG9c}|Ϲ%Ǝ{kb*rGi{cj"$_RkˋCV0Db`@! jw @ E "zaZohؾsgJBɭ.y#m#ѷc~ҙ9v/vHוfG?\4OUL.?yMvE`T6ά>[EWt8s6z&G,f7ڋKgT;LRf3U.qjVͻ*/>|_~\o^rt)cV>C4}^^DZ-gi I=aر| {wYEԨ%@.7%L3.}ޠ ǁ@ "ý6[3ޔ]YK&29 7缩Q$Їs  ٶ|ɥ֋ySGۭu)Uy*{IѬo9o{+νܧ lCc6qF(fVO%̛r|D:'?/t Ǟu壇$ro{Neic/h?vH"'rc'CL9ͱ#`Aʿ;`!ʘ?_)#Otw @ pD@/[!d"77aV`$XFjI-?Z+j Y+"@?lz$yjKi@9e0m=NGR/Wy>%vrzHDDN( I|$vԿ뾸 2C=\O|=2"(#@ 80"p`-UG߈l_#aT[}+Yi;RmU7˛6X|R#}S]'%=G.ay:~9>{뛟Ӿzl"'@ 8Z"pv M[Bu?2 w ft?̂T}yc>?soj7'dže>=9F3eW@ 9ω-2-oމ GFf鋯3'捤o=|񳎁cR"IG; 5 y[f$ I:zHEWd?Hʡ\$!E?Hʡ\$!{8NjϾ1M  @ }xM=1_> `Ҷ>ѩ a5#]8 Ic|rBf]4ƣ`…G.7]?|@c>n4ʅ2>g=}>5ЮB3> @  <;1`ȩ>9s! ɠa0#׾ʧyWF}N.?V;GL;X**@C̽yWWByVg\ 9vbAF0"Dm6<(t>τS+=tG)yΟZ?,-Ɩ:<3R y:wI!(]HHy= ˒;}ySJ6FsTGї!g䣜2erǒ,sQXS^iG9e<)#lhJ `hᤫ xYη]{?dH^Zwx(Kxi_SOd&P*sC_?pk>EAᜓ,'.XVC}_J ܪkj߭Z<(um<.o'`iO $)5mi2gvI}Q(9'%=)O2s|_ws`=PZ=u_+9'?([$rjOyU@qhP;o{A8`rDmG6p#_Ğ+w( zU~68ϖ|k,J9Pr?d荷ēz(Ą]?˞7ϑi_ZcAy8IL_'=后 P>vU:zd_N旗D@D@D@ΆJ >'=n tmy:ɅQ-oA8:NXE<۷oM7d QC`Qx qN+ӣ$\AR9_a^z9OWy ?(W+_"b|NHG-KeK(r-V W竔ޑg5`5"JJlTL9ORd#$&{8n8X??"7Ci?h/?LONX+^(|Q0cQ4++q<^oGͿLL]})(<S>+?/'t%[?c<eo'(B[D:BUBD@D@D(cek[[?PJf 3y=  MU.wY=5,dP%䧼Ғtm۲Wy' =PO@? ̆ti؝'f4  6-6Iͥ &$J[E'Ԉ Q,JKJ%9 Ғ,sC*LV=؉F\d/,6$tkB|鸹Л8mS*atQޏ! Ș?|;(sia:sQPF(o 1Cx 8UUoa]qvR6$`Y1p:iui[/cS.((WTēOUD@D@D`'yvQP(V\;t}bDܴq1wߋQ"#_:64?ZdkYptQX7{a\^ڗ9y)OiG1`#0+n ě<)s3ɷ!&ʟX|S"~).:+" " A@}L`(Llb<Q`l0Rs$@5'`S U΋  'GpaĖE<ʟvN9'?˾>k@#>&m,0Y 1? l=ctBxQ(TGї 䣜2erRv<ݻ{BbILS>|uJpSIs Z JTq;OR.&`z}HW;es꿏Ns&l_p+fUÇ?X ,ϭz^Eь=Lm;4 ;dWM6[{~/(r~V"G-G<~ p3sfz <"E)~4Oǻ?&Y>fKD@D@D8P"p>Pm|(XT~=N+*W!V8R/v,MzyrbI,#1-}8fKD@D@D)9q3T@9~h}n~ڏm[a._ziQ(zx'KyulPQsD\y:5ISzo~ݕN%2sX±_1zcԤ:D@D@D@! @5B  ^GWO6GPį9?|}UK}n5[U15ft8Np,X<OQ~BۯA%TG@.$u`9l(^309\Pa?l6'IDATJoq.{(s:cܜN%Or<IOj8(^." " uؼj@+`oToK9=r/)nm[yiygsWs|Snp5j(0y @:Q$y "+" " "pT*'P*^oHg3;~0>>cZY→CCfg sW]f6.G/me3bM?cas>>*XƟߪ5VE@D@Dy!Q\A?բx\-}wD0No=ы5sq?,9~_/y^WE@D@^1y^nQ.h|?t6bLgLW6\.@?bUp,*X&t U+kB 4|M\`ׯpnן_Ol8ǺG $dE@D@D]vX+}0ƪדIic >^qx&xrv:C@/mgmQ(|SS{(4,yȟAwگ?~ɇ ϗoOz#UF@ڮHA`Q,`|}@dCO\ʣ|l(դ<_S5dGYJ[tՋ̮שwwɎ/]e|!U/Qw0\z{qOvi뾟.?R|"p( Pũi(es>FP@1y]L#Uu3IKn%Tu/l>"؏^~ _|Nse;.B|W竔z' 1(<]bYYǘ%#oW3]3~?{xϔ~yzB?v}S%D8(^." " urr G=l_P?{f2oļW({ù_}?~_v`@ VPjXB6!{fєGضگrCgޏ~?S>*"0yX$y:yYө<y 8R=(~?LU ^G#p?P*CDx8k$" " KQoCP(ug[{ L&8Vd!7ϿX s(^"ey{? );~9a_']ZO@3W" " "pr߀ł緙GQ?~Lg#pkO&rx6'oF#پQ]O}y-dl0>./ãsuy\ ^bar33ʣ|렫^p:YD@D@NF@?g]O B"Nc$Oq?(|Q1kPWWY=0<4K8=yN 8:y|+Dԓr˧.4c<;.ji)-+/r:}0li?M:TwI 8<yk@6yL@iY 3e=wz~W5y(R ^hŊ_*{~/=W(S pO} 0Os(_WVE}?PIۮ~~dŏu}G|Pxs{ e=yrbiY܉96?RCʭe;h^g~s([֫s0\UTM@/O][*ܬLf{Ĉw{bBbL|n_ ^&| KIcEՎ_m][YۿW1-"mtw" " "<[(!(;S BM枽B3NUWm\pX_)w9# @GQp *VD@D@j& @WVOvט$}xfd'[5Ufo<}t ?0!%Cd;+J9zf.gx’2)'SSB?c%n [RoD@D@D@$ xLm(}x|EM&kc; %e(~֎=J+u|~Oy[> Tz_~v!>iZMWVEKLo{mE>OipYP, MyΊw2G h(s:cY^{ǣ^/vcqE]M8} 'LJՍ˄a?‡xҹgΥmu+LD}T%@!I&ۓt}MZ!lo9sNgqY _wY_d6 έ9|9}V+E~Cq(cԻIv O]vO 2E1z,c<2xLe3s(A" "CP%&n)bw_=Kyn#T" "  @L;WbUV5ܿo?zMh?e4?lo??sxJ %:K9Q(OB7_R[b2{! 4ҍ.ƒp{=Pɻ9={ *+a(0_lTU" " "P/y6մ44M<$џ'IMn~mtﳵ =,o.AsJ6O`.7Xw7=KO0c^ʿHH%ь0 ;2iy ?@8)vԧ`0\UTM@/Oc_ 09?vOsMo퇝T.WkQOxW|<. yr%xyKI_7:{XO`/wyfxaߜ@y_eTKy3母#]# @׮#" " {`HJ Rx2X a(\<չr(4?i_$s8/&?}_ H"G# P"<\ R(S<i(٦ mjh`^/m`kUlO7=wQ*üuB%ݏ^4}G?rrd~AcQ>gA0=!~ͻl??ْ>c( TD@D@D@<ւVD`~Hfb{5=}/+LȍyeS =s<wgM?y@ _4HCQO@\m:6h.r8`Y_4Y!HѧzAۊ f `,(q_d{9/+"pHJ PQj" ]V?@?r眮*f{֦{ e/bY^pt"v=qݿZדp=X>F:o($OS߉EtKpsȜgq/CD@L@7@*+߾c簳am6͏<]g=>@U, ӌn]O蛼"w)ݛi&{>h}|.-U" " "P/y6jY5x "x0O.+/&O$7ߦ_gWc_7Iȃ }//bP(4ߦOY|0?4˖iJWWX-EA"I'[7y?I}Υk"UVBW6 _{+~lY+b'<egZ2" " X<5_2x!uow{d]mCS1K /h)?:sfy?fKv^%{<%J~.y}a^k.%VL@(\"pn8+@ h.`~|K˛op;Hio|Ħd@ԗ2ED`8Z," " k@G}:m:| ߛ:رcW%<ʧI/" # Ъ`<^L Tyzo+ލcw^ _2G=Fyԃjt<"x@"Tk{n6<M"4f ج n8UTE@.#@/+ 3i^!HRZ(# @.#" " `JJ#"B۰Ob~фu9'tY`ɒol$X 66}?m`?}ߘOM|ށ+DǜȂS[fL(54oLT~eO8Ј8d#absNo}t" " "p<(@D`UVonфm>v74!+n,gn=]ؗRXPHeyKYswd kMo~_eo?)R{icֿGs5>e@O]%G3֙,\]XenO x8$8$]-" " NRFjnSxΞSuׄ$aM2_4hns:9ef'/Q+0x,Hˊ ph*_D@D@*$ @EM&2wy%5&]oHon+R3(_ 0(`LK2r9jGw kND xl~e{؛!{G*'O ؿEySRTBO ɚ<p-@>@x\"pp*P5QD@*$Rg~RQKO@ v8 cp焷uP.nMqKzw<ݺE@0)k%r/-R3?`ސρ.x%C6(u]*FxU&80y XŋtJ1W5B^ˬ [y拝l7@~f>.ߋ !<g}n98+@ h.YM|4_rw4O6W_p<^FQzK:,ϵBX?"#D kG굋UUD@D@D<H" J4fȽ9+_4٢/@P-3@:> ^+s+Ho;J@^XuKD@D@" Ct'" 9q<.HScϏG3w77M(GZ>r|9xX={D" "p y`6{0f4 v/ >JT) ߒ0Ńv36i(9," " /$  *"Bsl]nd  ˒|mY:xos>8k@kh 2[Q? jJsf [//9'iQ~SIx~ϭ1a[>;GQz vE;2ܭi|]n*MD@D@Dv~>@ѣQ9-m,>y,}, =fCy5{m{|f>N踫l?ix>O@uǯm<]ש}\ԥZD@D@D@*!g%Q3D@D.G_ol>oE'Œm,&[?'OZQ/?x޼ { ktGv^Q hE'(%.KWS}h}I}>߼ˊǦyo6?t7>mNd·YIF,[pOL1@cٍO퇵'YaS ^pd0֏<Q Vkt>S("! |l8wvD; VA@7mPT" %Pz~oM/yg.0'@)[So1sx)-e< F+!ȷjޱ !+.s+ڔ)4)VD@D@:B;͎0Q7D@D`Ilz `#i.~ͥ7џv&YS)dy|n O噧 =}9Fa9PK77泰&?H\R>V)_q>?h #yC\SI~ϭec)ڬoS6ˀ~>l <l# 6* Cj@vC[!{ߔ2NK C{nP6?='a9_(>O,t<eZ" " ">/Y%8]Cs)`a"ɧ*T^)a߃g{}:)Yygg7vMwŇtQ*o*5<W"SB!@H  >S(" by5o(q;OHSSWl*ƾS=' q~ n+t0@+=x~X{%6YXFsbnbIVɅR3E@Ζه&ڑ:R=O}C֫+  . "iyV)41i=ٳߣ]@(v%$]qΈ X,F t/k9\%QD@D@Z&fŪ8LAm1ၽ mK1pS|? OM޶0ziM܄gAGڲQÒ" " " wy\@zgE~r~6V<]GD@D@@X<͂n SY).x_nΉ'=)'8?]XK+9'?Q>$秲 K{i?^)IO~ʣ|YǷ K{i?KK^ZW`OCcL{ǵE_Z=6=$}m yj2jw\"Ο5.>"(,ەЪ@) ~K,K{i?\o9'?呞~c ?XKsIO~#=~*KGO޲^Ch/?;Z4X*/ȞFL&pǵ"O̒σ}Y_bY '=]to" " "<<ڸtGX9)wXpN<OzN\w,|NenqN<כrN<ߓ []u~uÖ׏sGo i8c6]OF?YuMt[(ګmdkA{{&lM }ཌྷ _?Wt~L=!FYh9&Y]ޛ^N=xj[lfսvS6>3lwOېg?e;:HX7݁;RiW+w-m-tT9o n^Z?]neּ7|6kj?__>EkHIL6柬a<v_Oa& %9Ty6Y5l.*" " @iW EA{1y=ÄipN<]+~ݼt =pm/~+zwʟ?+ywRnO=l.WS<[R Ò˖.Q}(Oܱv'*e I>nIa?(:z>;FύOc0r+Q·8csGߜd6>-rTji=`T`ǶR4WhmG(y̮#'A YO7;W^_z^?C&BY=deG Ȋx h[{[QV$],5UD@D@"T@B٢Mi'{ϚiNΫ8#|%bR߿?$3m_T'ks3=lb ˗c]#1ϓqߨet'[/ǟbrHh"" " nIa K*(sY@9[)~C8~ xa~/Ξ~PVLk3e~~<ΫD zmԞ3Hw9|6Ԕ9>¿ K|e=ʤ<ʧF8}GE@D@D@H;ƍQi gcQwt"Z" " {AGJ.'A8E^y.5ixEOT^)xnHkNAJg6 RtcO)Klu̾ ys#@_~[z=)" " "-qxHW*qK-TD@D`O̖=n txH.>z]~ vlL>=f6gS='+6&SN,>˗/Y~̲ ?R5w__᰸}ͽ?)x܇,?4b K X=[ڗf^~#Yڼ>ok+H>a[¶ٗvV tܑqSst_J'" `.碁y[$;)o {n?%0^/(OɘՏ-=x'u06? .%HsPA z|5OS26f>a=(y~&opJ)TG)ZD@D@H@7]sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o@IDATxr#ɵ8%؛Ŏ/K|֯y{[p'٨z\/H@#4Ur'wU' f_TvjeWfЋx>_mŗfhUEʮ^T @ML @ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x]x]D @ 47-$@ @x] G4@'tBn޺_n5=nW\ppїUy`YNuXglVܷ[V|Ql9O @ZIh嶑4 @ @`?؏ @ V@+!@ @~H5wx4XBdki4Nns-/7w{jU伪P`2) sM0_<}Rq{Y]_Z~ 8Z@ hKc3%9@ @MF@@ @@{p={E @ g:gGa  pk]uzl-=h8k#reMkͿˋ/%_?kN󠉟Lw;?19=c/=5D V/Z]$ @ @xB0 a |eqqʯHHy/wo7uh!@@yLܸC ߒ&A @ x =B @ZB-(҄ @ 5^Bxkf=VD־~L-W`K]/cjYvH.[,zUv͖m摟SxX^/NaYAaO!Й<(gjMPp~X}XUŲXs(;j ls  [҆ @ @ix @ 7md @ ioz!DqJ~sͯ55N⻿8 霌Ac_y&Qv]I5lehjHL]0 ~ڲ};Vx5n>GP8;=޷2ް4\OU^*0/9EayCgfw iR9jlwq @%KRK&M@ @! }h @ @h)ntH @ g @ 7ڊ"ΫVPxQԭQk:Km:ɮ5j1/_$г;y,iji~+lMQY_??;)_U޷CM p}k!(p,Wp=MJ~yu븄rf) fu oe3P¸4 _+A @ Lx&8A @Dm-r @ <@I>3 Z E4eW=H i=?[~|5j%ei-_VUkm[:cՙ5v/k%_#QS"^o<7j+?4Ar | v7o//䪳/RNL]Ļ}6֓}@vu8ǣHBZF,{҅ @ @`'WFF~gmu V) @e^Ӳ. @ @ ZD8@`'~- r4پ2٧5uED/9߸@=]GW&QӪf7۸\(l^쁍hMӋԵ{^jbXs"n5\XDeCY~7\u%׼?C {akk-?nn^ځ7wL@B ~klK @ @^.!@ @$ vYC @"t{Oo4y`g5?_xW|۳Wd @ @x6n<!@ @! B @Mu@ H. ~sͯ5ܞj`պm7w!?\$ok֥4i%i鶥IE%)W^j7c,q^aU9{0d<*G~?Vq-V!n7"t†]^݄/5^h h5+ޚ0;_o@I?$IA @ 2x?FC @ZA& @ ^f6SUsnkCCڨiO ~ޖv2vZAtQ Qos|Ϛ0gz{߁QVhA,n d*uQ >yL׾1 @q @ 6@w!@ @;p @ 5ڼ{Gۍҗlsƻ\F?G}iQ=]Ǿ,{|b$z^|RgZ:ϊj`L݋(0ͺW:[phZekdo=%~hX/4ǒė )u[wޔHA_b]dUbj,EA2?"xJ'[O @h- Z  @ @)x} @ 7d @ 0)W p k]?g8FmQ{<V֫j(N7ϫL.IUbe\ﵚeS/

vA$iEͷkob (=x'~f<HT{$ŃIߊg^neAq~Rj%[qmkc>쇖m5 Kdw\jg'j؇{{}k\ߺdG*|/WpBMJ~yu!d|\N‘,;zĪzlv oe3P4 xKC%A@ @E @ @@p]E @ g:gE` ppw k/..9l-=h4u;ۮzjVPxn$6Ǿ+o686Noi]>%̗FQc56r -}r^s׳RǀwG߀mnw??>Κ*c8.'Y`X.W|Xdŗ%_?%L󠉟Lw;?19=c/=5DZG. @ @`WqH@+}m۵s?Q:[~j3޾vY[~D3=ʲΖ_SZ]m_V~E*<`?FApI/ngjj5_-?Z@@<޺50 @ @5 @tC [@kӟÇ>==}ҞLD(駟B<]L[O_?}5'5ߖF_5lQqM;Ƿr?)ryϗ'q3{kFl&Ouź~?XC,H_5kx>-ָCY~7*npJ_rͧz~uK<,lmҵ߭K;֟| @h=y) @ @{p @ 7ںs @ @؃@ 1W@A߷&kᇰ'ww쓓Z{0^/>g~"3{Jm, n4|oVaZm[ME(q;Mc ˳j|.`1iS'ηwMYDiT#ĩ^l#sjUmhǢи,qCS FZH ӉP/ȪvSn[w 5rg\J/` 6CME @ g31  @ &hn+ @ @\0 I@Zz尭x%n]ݻp5nQ(jGx4yćdљϥh7(yE{au_ϷsMv/vk9[”4h_GiP]c*bbKiX3HKvI\tmpԭ[͈̯cM*ηW3txN˫pS'`C>+\P",Y=3r PKBCs$-@ @^H/p@ @@p D @ b8 +iKk Q$l6S*V5>QaE$jgXàfya*d>z'R/ag-Yix4:H/.?L/-V+mzIǣa(r06ԍ_vlVX >yL׾1 @qqGz @ @h/nw @ 3n G@ @@{ P{Gh \{K?Z-p5T@yN&{Rlxn/Q CoOgc5>[ =fO=I1)k1Yq}CL݋5R/dHY73y@zV|>Z@6@$]hX/U;;mxng5:?JHy3̫h'9VpͿslCOX%];7 xXJ;_x>3;lmeRyQ]+b |T |z5{ fPVNժX/xU͗d> 5R0_|>ikv*-lw}8o5S~;XJCq3yi`EJ#LlIl=ϗ4f?li?Jܽ@vJ<x~vR}xw} C (_Wr 'd:_/ʗW7BJ$RAfoe3P4PmDl϶Nx]8{Q iVm}(]q5^·//ϧϿ\ ;˃MsaA @ &hn+ @ @Lp  @ ڔ;B !5vؿsCkvvO>'-l-=.ݸSY@ӥ?yR$aw1hl%s[R/lMgz;k^w?΄ff }m,]fX d4xy%g ׏a CMrh =) @ @𻦻è_lE֍~X]Wg{j:w]uܷ+R)(6*uApˈŇ(nZCה.ߺ}&?QK `x beel-5Ye?YL#kU@ dmq(s"G2c[v7Οzf 'z@S!p~k\R"O~}DooNfd4*npϧz~uK<F odww>_ پO٧5u1Ofo<_8`οο߾ o O @ @- @ 0h؆ @ @[pԷwN5k]v w[u\cu{wwlq q_8 .Q"\D{Ҝm, n4|oVe]z'8;|NX7C(\{eԉmi]_eiwڪ37q~\ζ PTƣxG>1gsۺ4q)9׃5<_pۺQ+u=|s_ϷS$E'0!@ @m$ 69C @$ =@ @h#i8<yFY~0m_gx*ˮk!jQԨF^`aRfx4 EUQ uW>U v>& ܯK}+/3}} "?Ӫ~Xn{u^5/m؟y}Yu*- R@ @@ pBN @ W& WJ8@ @@ PBN@jH;ǣ~ 1?~zZJ2d2-?ƻ \F 7¡~/ U=j |{|3ɫۋO5R)͊r$9~ɐz&C2ͺW:[pi=%:gEF|<=?sכE "k *h"hn'Vd yȿ:wu-3~.o*i D99-:MNN3X7|媪P46ϓ 7IIo8/?B #$ @ @="C@ @ p @ @h>&6?a2 tu`Pj%Xre^O~wiu5u<֡vw=ۃa(Y N7ϫVL.Y+;~4+?zKvov* l-=L[p[TtkT׊{A#(Xl}`muZ簯"2h'Y`5"K}p*Fx0 zU S>_qy=|^_>|*JbkEؿmCq7a'JR4N؛@H@ @ZA& @ 7^Ə @ VVdLFJWy=Wڮ5{{v_ƻ\>E ko暩l?]ف؝N,I߸[<_Wr 'd:_/`˫!`rf)~48w'45!|~~C+|zFVߏ5Cƌ|>9ߟr^܆6eZΖ~4o[UL69\V/([|>*p @ @Ix @ 7}d @ ' ΓtB`5qtF/׭kvvO>ץhxn$෶vOe Ms}lKҰ}fQԘo4rM7\n x_jU@s׳54ihucEo5;o4ы.'Y5>\F|5wZs-Ϳo^|y5a9A+Lcj,40{"𻾙ŗtӫ2οj7y\ ^h֟z R&_ @ 4@k4 @{ *!y6=(Ni0Ouź~?'k\R%FkY[>B,wY`㗫)]|I3~?C t_(:<~oK^ ?x[ky{'jaۻxMOW_vU˟7>R?~v0?g @ @- l)B @^J/%x@ @@ ]S %E@#ITz^cܻmqي:V/]Ɓ_ ^`0n\Fr=6H7Wlx>2kkjlD Qvg\˿W(jWO8ߖ5Ygy*P1^K F?.'Arq~V(*-x5ݮѯI1'F "8>j!n7"tĢ#_K}x>\xdMjk_%df[35ۍnϿx&p[Tx~2)5K1qۺSy; _ÆspR=c @ @-# mB @Cϡ@ @@Τe. LƜ\{41v>^Za|5ߪ nGGQ>{ii|;Q7ҖLtri}=>ߖfv+{Gvu LY,Luę& e<IX"K)廊Ge~EfW8o筭ζ;PW7K(O||TWH"E o,8AԨa;= gG!޻~U7jY:ܫ'ٻFF߯0u;z?ϿT;?0W_cB@H @ @]#g@ @'0!@ @m$t7m\9Chiەۮk\[ZlV{_gP(NsӰ΢f5YaP_`3ۼ0gk%i2)5.mk 2n_ZyqoGxzO=?}iGP`P%P7~ GYG^a;E3\wn|7UN[VOvz'@|(RXXUbj, F|c.?ZO@x @ 47C@ @xx @ 4 .A@ &z&J[<n{ Wmxn׏vTʛi`^E;ɱZ`w{5eS/su=Jz|u5E8j=x>5{{v_ƻ\>Eͷko暩l?]ف؝N,I߸~or _jXdlŗ=/t:MduMaXqͿRz!֟z R/hS @ @@c V͒ @: l Snk}x:gՎ#kt}G4CP,l5}u븦ij_-?ڒ@HcK\* GiAk>u;!m=ZG-?xzA4B @ H@# @Ϟ?V@ԟT%5U_q4>~|ܞLD(i駟Ovv2Ida2j?ݖ2H,|Xlo dl߿4p:_ep~eAΗ'q3{0Ouź~?XC`KJ~tkx>~?`֤5:PlvNfႿB r`R]l}񟡿e~@IDAT\bda{/H_c>@xN@ @ xh  @ @rD @ 4@Э4>[ &pcܻmqي:V/]Ɓ_ ^`0n\Fr=6H7Wlx>VQ(k\oŋΎ"4<_M -FQb2M}4_r?;mpPqj"_S0q9)iދx?ֶׇ#ͻj5iڒW7m%x|4*5Յv%7N'j4lm)<ȝq)9׃a?PǍQ @ V@d!@ @# qc @ @U\gѪIO5kֽ51v>^Za|5ߪ nGGQ>{i|;Q?ҖLtri}=>5 =5>_0M2glj4X$ae.X"ɶ*LE=Drѿ -u+miE5ߏUozW3R6n$}x}@+~ W/np_j;Ey5z.y)^A)ɜځ}5u-<.I| @ @hno @ 7n썌 @ O 4u5.lB^3!x6ws|D]HK*[s}8[ߔXM>]فMOTwi`E#lųzv{ \f8D'Y^x>_.JeoZ4HUc NCY_%y~vR.~׷2k˪H˥.\m#+ g@ @j p @ @@ @j P x :{nnJ\kv{6Noi]>e3(j|7yy&YB?]/5Rtz6_zJ зQ<7*~cLgaUi)2E]UU+ 5hɶM @ A } tL_l [75cuq<^&~xuǯoj֡Vyߣc_gxs?Q:[~&_{ @ `'L8A&3 {Gͳj@׸~}V붏͢mxnO&n_^^*uO?=isX-CTO_t}5{/5:o1[:,QÛѾ8dS" +Up)!Ұ|Wg* 4ȹhŨ$`g{V~EMxT(_~lKkWFF_My>S݋!{@ @& p @ ]w, @ 0({؇ H@vνƵݞfa) m uv :a(@9f5YaP_`3ۼ0g+~}?i{?5lzM/<@_~'LX%²XNjE?2=ں%O]E@ @"nDX @ 7meQ @ Huϱ -!:Qss]'ӸL4Lm$Jc㲕~iEiu\q/m}=Z<:.kzJ$];Q\l&\t\kvƵ ֪I @ p`gT8B @K;2 @ L 4v#G9Zl[|t??+lK)7뿳Y1炤qVcn4}]=W{-^(]] Rh]hLK3qx'k]klsq|<__֫q=t: )x F(jL8WUk=݋ߡsm͖{ےV3KܫD_L5tڞ& ͙u|_`zKnw_/! xo^1OK:|?/dbŗz_?x|Z~Y(ċ <[ e4W5KD'ӜӀ#mѭm0 /QvMkޯc}4خp3Cyk{M&k.x<0͹/Y԰~~k~_MOpnakBlZi;˱Z& C>{fBɢ'^Ԍ6輽׈:~?8sjkCaLCu\q|y5܅wwi;M\ W.5"ܾ+߹,b z@C)^2ioU(?ff;|lB Gw2j;o)}6n[8}_σs+J9V>>q[EIu**INlnoy۩ʭUE5ߏ+|t1+ZryuSt'V~ h^Tbʗq}lߞG|-H!@ @ؗ7%? @ @M#e@ @bC\EN)j8qmZk0jWLh y>kGPk}1xҤV֭VyW<֩~3_5۔;k%ҔiȵvxhI`kN$`؄a#6(Bߣܷ_ޞi_{jްGwPm:˿p{7^5cBOߎvZ#i @ @`?؏ @ V@+!@ @~ FQkvMOuU:ͽ}^u_*n]|/mۗu-wfʣvWUkb<{,wZcof۟'{nbVsɫx}﷡vq75˸=f낈8]0dmNx}ES  @ @sL @ @ߌ7ZC @C Ś@wB5vkǫy<bVyqwX*:.{6j`}iSjo^0 a< Wtc|YN'4ƿv%X4vSiek?OhڸIrym*Q9lVG;ˎo7GXsYZq@ @@pAA* @ oEߊ,q!@ @ "a JT @5^4Zku\ks?ۚPmQ:I[f4޽; `;/ߟo4vb 6 O&$c ~yMi}Ctߪ ʡfvx%?Vaf'YN( kv]C+zvE~kg7Y]dB @ p`7!_r=ku|>qvy>xus5/#`Nn^n=VlB(@ @@. <k9ҼdӜ;rx״mx>kw]|۳Ll֫}zp *WׯoպDۍwߺ?T}NX?fmW/c d;ǯap>5Vt߳ߪbx۳]_Pi cOx 3O=hzvBw|w^s,{җN@ @ZJ-8҆ @ C @ R&Ti*HC^^~H˽w״y\nm}> x[Λ}Ve/ W0j|Gr(s}}E\D{K>\ݓ|h`ٸ|_Wi'X`8Ӵ5;ʫ^#Vkco&Vok]8zK?~vz8l<~ϙ1 @ 7$@ @3 @ @P |ouֺk[7N2 {|]~k]W7^yV]7OQgk? j??W$ߕfkL0Ͳ(|qK{TU?nHmW2˧4.pލ~Ggu$ҳIP@P@P@[78;P@P@P@^E7^$ ( ( ( usG95ߚQxϣ (ZTxGyY\юchq5χm ~]Jzq?z?ތFb<%MjYmsӧO=οnyy/r\no&>c<4p(n5_?QHc˫q.q\D~zš\Ϲ,c>5*jkmn_ϒ뒷~C?hJc>85!jcziΞѰijYV{l?f1 1Q\zfxD8p~rOA1x~|+{Uin M0fT?_,SdDŽ~#j:NC>E߿xV%P@P@P@8?5{ᄇ?1R<**ߨuNȶ"O_)x1n#q>Ӷ|m?<7O~隇Jsk;/uߤE1ȋ#XGc8űԾt>=fg|)vktnj͇RPoƹ7O7㌣>.c4-EG|vV@P@P@P@x=^XشeE.")$ (^$kY˚|ns&y)Kך?c;cg>zt|>||13|Oi|~GQ;"f/z9\,r ">Wʚxǿ(֫.tT7pvq~ %DW(r =/:/? _!{$|nb1`?]]l^80 pv8Œ6A7q ( ( ( (ppU( ( ( (onqZ,& ( ( ( (;%s ( ( ( t fP@P@P@Pw{7{' P j`;5X3ۗ7Fqǰ!ۗ7<F|=}Ky5Xw9?Ƕwb; =Y?tovbwS xϧ8VG7Ηў돘".;(h%͖Q ~=~GMs k' Q ?A^n 7bU 7VU!N>hvHø4̷sA^ u٫;YP@P@P@h'l ( ( (@|ח+ ( ( (N7zJPkX#[ּr +xł{&59[Uq~Ƕ~ЃyiW8^\k)|?ȼx}{J֤r}y=>LzqǚG;=`Ƀ]9g0c^Or=<{.pOqi|g}9*rYZw?*t=8c˗_ҒK13cݦ=qwhӋ㇟A|i<Ϙ~5~D9_l?Ry׿fl|1O4M\=q Ek\m ?G3- |0pϚMoā4Exf?6G| ̷?O7/_/& ~W?ۓ+zuf ( ( ( (|x=P@P@P@荀oR9QP@P@P@/ GǞ (@F-m`B&5lϘY5x<24s<·xپq\xx.uٞ8bk?a]}xv6/Egy 6OMƣh}[%~FUj0DcM~ x>PPU,)gR>z9}D?cxDG?^<ߵ]zG:x?|4O.Uu_^$w^LI* ( ( (@W*f{P@P@P@z(=hNYP@P@P@Чko+2|V]s9;yvu7v?7aך/Ϛ`~ؾǸ4hoRq#oi~]|Ƒwߑ/#?}#Ǽ#>#;;5{\D07[\_7}qǫYm*rk21Ey>ұbhG֘?G8rxyƖ~yXs<#׾D;]! ٪i0SgV|/Ӷ4xE|}~Yc3|c>/f?cg>W۸ۧ x5 Wiχmz&ד7|qs|=q5ʟ[K߾Fot_f~x~@>͑8p>/s|Y}lm/_rM5a뫝ߝ6?֥[/Wu$̗_v3Kyju:MKG* ( ( (@|?ʙ* ( ( (lx6P@P@P@@Sϴ kXqu.iZ{Z^TMTS;XȚB0G#3_O7G/x#O#_Q\?3xۗ◮zzz_1Og=*|=r.Ua1kW\|~8"M/4Mf{%\eׇ͘8^)fK/B}K׃홏1a4cg>,?*?-?>=q\Cy|9uZ&s 0x4¯_b9K>?A KϗnA緻_:~3q:_}p75*?6o5&;PP@P@P@#޵ϴ #:m`;."O_)x1n#q>Ӷ|m?<7O~隇Jsk;/) C ~msG=oyJq#68tdru7x>~ <3y? ( ( ( (7oW*p$kXPc5a%jY%fa&aךGD;G(˘e %ǚwl|i}?<xpٞ8Ø5|+pH ~?yֿ~x[_J|lϘ/ǷǴq 9?ǵ6G`{xuԤl|14߿Gq݌홏W˔Z#^nUǷhҠ=qrOyO)?L׼GuWa"qZ=~mjyʯ4|Kw;[>Xl6i`?mۿ`j`G D/ .ZU@P@P@P P@P@P@"]l ( ( (@ORBOPXf嶈~d 7yoNp~?bg~_\"9z&9qqiXđ9>ǣ/s!aOl|9ﶯHخ+ל~5Yαɤ/.{Dy`74[ELWs=y:ƈyO~2 i/o= oA6{ lƃXpY?/ƜDzwb>Ƭ_,r{.;=\Ϛ 7ϗI{Dp8r~דg$h:,{T07V(N4_~.:M0x6xa 6,. ( ( ( (;%s ( ( ( t fP@P@P@PwлK@Ԉő5,B8ƍZ9ֈ3پǸ4hoRq#oi~<}yXw9?Ƕr1B!NjȋL)Ŭ/yuѵ?J1_7g?&:;{D;{_L3=G;{,4[m{=øSs&iz q?7U}8=E~ѿs ( ( ( t X6U@P@P@P+P@P@P@ 5:t (V5T5sMmVE>U ./5E\4ߔGj}5y=8d~qW8qAG8'шcgGS5jl5+ĥ=81ξ#3qigZO<\??w| yKS_U7?4l&N_'<1hoDק#H6/._( ( ( (pp֕) ( ( ( ~ ( ( ( Œ]+S@wح5>Ԥ5A..lǗ)^"hĚoxo-<|>z߬uӃ5q~m8lOo13s>g>ATFYٞeSN;kY^l.8wڏrQ.GZm\`#_{ lqy3?qS^KK[Zό?z]0@c_K#g7BxGO<ַQ/<1jq;z׷/Rf|P@P@P@Pob ( ( ( ~_?g ( ( (@+ O[ kX~J/_Rbs<ƥy>c賆5=YԀFl|iN:5១xؤoxc-X؞b|X=$=17ӣB t5􌯮N[z%oo9}ImJc>wq'AG_˸GwMve ( ( ( oS`P I8~|Khq}sc8_]K?é \nkp)Σ |kuv%߶E8R~/~ ( ( (- H6Q@TP:j1`_F5c 8cg>ǚEGb>p\˘홏ż߸vGvqGg8|ݾNn?Ɨ+ţ't9>|5z26JW|J7KW/@a]d|}2yzǝr 7ﯥ|c13cΏs <`{c0z^l|\_g%_a+)xki׷Zv[ǫl_!2?~/_/~{\bӁ1pr'sIsS@P@P@P| M ( ( (! !_禀 ( ( (+ ‰WJj8m֔.jby[BM)cmk,Sڽ9/ پwlFg<qt#zdko>8ǏqrMx=Xoi1>{tjg5ïJHk챰B0bt;I5iMZ|ܽb*4Mx s22__Lؿs ( ( ( t .ZU@P@P@P P@P@P@"  (R5eQsVQɫƸ5b索曏G̚:gE$F8?cxDYy=mwmD1o5ef=Fe5'59e0EQ0jW\Z"x1=uf5o1-&>߶bְs=]ӛ(ilT?-{Nwѕ =r|IYc=0b~>yLyL !Oy,'J5y~̯+ ( ( ((* ( ( (p\p\( ( ( (@.x*+5dq@cMkbhǚ1"<|1n1N#F;ίkc_<[ h5>QTrQ=u`M5OCy-s5\Oט5ϘD /-qbǸq,͗9^w_Ø{Np/{0f{qGWy7ng)@$075M ;Q>"U9չP@P@P@  ( ( ( oEv ( ( ( xw{8FwYqV5z>(/1n-?ԟc[o7~#]^'9kWc8}mc8RƱ]Yq<*%zU@P@P@P'Г 4P@P@P@xoDϾ ( ( ( D=zr}`[Ƨs׋9U!fc}\ܓ5g٪ٞ~Ώ1#~xPO y,a'cc$7+|.0_?ϧd8ʿcR'zs{CwCsQ@P@P@P@W W4 ( ( (+{m ( ( (&Fi"ݚ\5Qi͢q5x=H1kYsN?<kTٟKy]?>Ο8  ojܢ}]'x?c<R5bָ38% `~ޟ7wzf0./or?>'A2cX~[ o%k^P@P@P@H7b8P@P@P@J7Jּ ( ( ( {p* U5lcuZS+誊1N[-Zmp<n[*<ڵhΧmhs׿8^ã Y{,Mzqq!e&5~FX,ы1Nr=*ysތw~x[_w[3 VP@P@P@/S۱8R:-}qjf/ xs8iۏq>]0_)~xme;P@PX cKP@P@P@ 0R'Ȳf5o5_\cX61;~=?7z_ig;Q8oxhbz1|8_e8Ƴ,(=ףI|PBGԼP?05ٞs?.VxDǘapٞs>13c·12f{c-<_mzm\g`{q<*%zU@P@P@P'Г 4P@P@P@xoDϾ ( ( ( D=zr}`kj=X#>Nrgs|bM:kSG??ϟC5{db{z<|81sRskk^W@o>~Śj< F&2n(;?qx6؎ǯz#Z~>||#5]Tӿ{~7(ͧ ( ( (!q ( ( (o+okvP@P@P@B Ĕ n^bkXxX$"O'7ky5lϘ5d~ΟYշӻG/c_twh5c\OU߭ &?kϦ= ')l]L ( ( ((xU ( ( (, j:P@P@P@Q=8'\ jȚ1X#|1ncMטGxbhuc8F/ƍv_8Ɖc䏘G@Gbo#c~iGއJ1|Jc8a{1nKy=7_)xOGίsQ> }ZUP@P@P@g 3즀 ( ( (@|OW˹* ( ( (L#`hqP} hqdEA{,5zqd8hWKq~g$ۗ⏮!uDZ4c[ T #m۶vy[)f z=Ǹq:xl#Ͽu|h Iܝ ( ( (  P6S@P@P@PP@P@P@h)YeEGi7K_?cjj"E' pd C ~f<qx{XSX~qd = 9>sW8 @?]BUdhO.|<Ƒ8?0nܞlx#V+}y5F |@}UP@P@P@X7 ( ( ( oUp ( ( ( mxM736mF,ٞdKEԬִb# 3Nj~@5zo8??ϳH2RmPyywƳl;+c $k$S3?89c8}uU\"{/Ϙ?J1>~Ǹ4?3?|1P̿ן ٿoz8P@P@P@P|AM ( ( (! !^礀 ( ( (+ ӿk:% Wkmf{Df{EtS,5k>"4l|H0zy濙e7{T?%+?stE0t'i1f =yg %gxx=s<ƥy>XGW?f442/#wcnĸsNc۩ۏ7fGxO]wp?12x{\(_UqN ( ( ( 뾍ʓ.eX5no[1qG; wK`~6?1ΗhR}eQP@Pii* ( ( (p\ kY+/srU1F by;q֔c/"^.sni~qFUo>Ѯ4^8}7vѿtl;h9hW (|}29^5{EͱOy?c?cg>\/W홏q`k*cO(Mٯ/.R\]遘5Qc~6˟Co k18w=?z:|+kQ2fڽ13 @1u38ZE5#qڞ_ŗǸm?> 1Ҷŏ_?Wч9[KgW#3ng]yv|l5zwg{(}\sV@P@P@P@ol ( ( (@|( ( ( (P@m}*kUG;֨ˮ6{D;^./R j(Xq1Vɚ>~sX5ƺxv (p4q߉oyGc19Wđ+/XZ__<賀P@P@P@h)-l ( ( (@|WϹ+ ( ( (RhI`3xo|8.y "sG{>}r0Ugy\k:'( |@??k3ο 9awwL7'PP]Pf<P@P@P@PU|U9M ( ( (a a^g ( ( ( BWMm28U(Fx,,\fqNSfE:?-'oy[u>?/>h4kf ?k)G ug< `5몮x<75b3yO;ƥ 񝲞s<Ϛ|꼫Uο+@ _A節 ( ( (@ hdP@P@P@.}_P@P@P@E(`ưn5oGE\ѿc5N&-X׿_z`{x ٟ5_&Ro=' >\ &1kGϸk-.Sۓ (pXY,(Y_qE&2s+~3Uvח_ h7|8*q|}dhQW uwLP@P@P@ .^P@P@PT|TT@P@P@8i\y.^J`F)n`̈́/|>5Rn2ݚ:h[FM3׫k\dz I5笁KUMCJ5Ϛ\OU'ak%=؞a~lo/Rǿ^W ( ( (I I^v ( ( (pjpjW* ( ( @.l=I-5q㼂"פfs'ɬqݨ·v2_ʚC G5o&5)߇R8R'<|c/Q#_Z9SP@P@P@-Ϧ ( ( ( \+g ( ( (tvT@P@ xCl{ųs}cY޵Kov_Η8!UŘyf>cC58Əy11ǏǶ.ף ( ( (?~ ( ( ( ^Yץ ( ( (,_* (/`F8lw/ 2@VuD|9 {T,pJ1m(﵎hΏzK5fWϚ g1~̓H8z ( ( ( <" ( ( (&vE] ( ( (D)#|HP@&SH홏x2MS\8_(okp~ٟc ̬[1c߷.?Nlvj󫵪.3z y{/?Əys~xCއ\gP@P@P@P`W7vM|DP@P@P@ .HP@P@P@]>P@P`k@GUg]]2Wy1j̣{PUcdcF z 4 wsFgt~ ~~51Ƨ%k=V@T۳Ɵ{{h ( ( ( oUuM ( ( ( @7b ( ( (1 1^Uפ ( 湮f?mzA:,r{櫫HvcA~z=x}Ǟ 8s?/ȳ6oJcr>jJh7>vicji?<ϣasd{3H=?Əyrx<>u.P@P@P@NZ7NxP@P@P@S SҮSP@P@P\ ( kz>/c 6k_KtVzr<]gJ{n\/lSoGOuޜc?cC118qtP@P@P@P`+[ R@P@P@Ph|h/ S@P@P@P`+RR@P@^Y5\g@GeKga;돉1=*Зb5\33yhc8}_P@P@P@ 'p< ( ( (\Iס ( ( (P@Pu\e9E Qn̗?ϢXz@G׏#O#kc;*ޭKqѥ@dپGno]p ( ( ( (o<9P@P@P@D7B P@P@P@pt< (ƚR<U*XƋQxLeۼ~-ż~xwwL@hEhlϘ36,Ev.LP@P@P@S SڮUP@P@Pd|d/ W@P@P@8%8ZP@xcAW60x Gѓ3sjsc59?ONΓ;cØw QďZ ~^V+>Y?qx_ 4?dDsd?p~?M_ͥt! ( ( (  6Q@P@P@Ph|h. Q@P@P@P`K' ( (~;NWQsOZݚ\9^FUg="WШ)PΏaX Ї1}UY\'!E:_z~l8%xǚYS_mU51sOƜ?!]oCΉ+ ( ( (^7[RP@P@P@ @o/W@P@P@PӅxRP@5TWaFTc`\g!7@IDATP՝zl'@? 몾`Y_Xrr*un۶_)k󫧪Xc5!=Ds;x^12V@P@P@P@. R@P@P@P`W7vM|DP@P@P@p.HP@(Մ~)3rᰮ45_:=vׇׯDZEuoQ\$x@#csOYtlSڳ?q8ae8qP@P@P@xJ7 ( ( (G"Gr!] ( ( (O S:S@P@W`M8`Wc~G c*!q8U?yT@ W[U1fC2hVٟqΏq{lGخQ@P@P@PxŇP@P@P@868+zP@P@P@xD=A!P@h'5qԀvNtZu{i{ ZEUom=NʻRϯ֪b~ƿyWt- 㸎BP@P@P@'|IO* ( ( (ppU( ( ( ({I89ـ5Y68KVٞw_Ok#_,|`Q8TT@P@P@8i8P@P@P@NE7NJNP@P@P@p.^`eh _.sMb?_,rUTG}TkYNC3f{c`0XOOR:l|+>i}cU" (pb-* ( ( (p*p*Wu* ( ( ow ( ( ("r](PɌğivix/F5=Ӽl/&_]51{Ll|X蛀з+|P@P@P@xo<. ( ( ( M7vŜ ( ( (ȅwH`P5E|.].hŘ5q~/sdok>|c^S`5]`oBo)YܤԃU"x1ί՟RAcj~4? 9p?*_AE)# (1 䟒ieEP@P@P@|/P@P@P@8^8kP@P@P@xȅt (X>ǣDn82=oc(=$b][R:X  /4OSX-ra_Uo8~Kw.3vъ]]'wg{Po@߮U@P@P@P 4( ( ( (7s ( ( ( [Թ&g?3>%20_ _O|'wT@z._:}P@P@P@@%( ( ( (st ( ( ( p6JQ@'31f2>{07  |.8< /um2gF9Σ t49[1~kl<* (pq) ( ( (ppޅ+ ( ( ov ( ( ('+'{]o'1kj\>1>W|UNx̓cP@PܿWU{T@PxOdz.W ( ( (?~ ( ( ( ^Yץ ( ( (_*X3Ϛ&b1jN4dr)Jr:LINR?8/yT@]fk5 {4= cs884Ώq (=/z~ ( ( (m|mP@P@P@蹀o:}P@P@P@@%(*_r ~G?*8u6MNN/S<髻_ s~?ח3P(g54=x1"/ g#шcπZG^ ( Q 8gP@P@P@( @ ( ( ( _7 ] ( ( (E\WlnP`W`jjS௫ w|>wt5wͮq:؃ :q~?<*kYc5Ugj_`\gg8?w> (@O]3W@P@P@P@'| O) ( ( (p,p,Wu( ( ( ({<)xkYSPs|~t:IMnL߳Yރ`6K+_45±ulF (E5"{ԣģQ~8g{dA ( @{ds9 ( ( ( (P P@P@P@N@7N"DP@P@P@r (3X3_j=\_Ee=@i<7P@NoNncP@z/_P@P@P@P6 ( ( ( _B ( ( (@Y=FP@ ˚|F7{ălUG PWs~1G( DM}|{7qӀ5]`8xj}zꚯkNѮ~/m?rs ^t+W@8kP@P@P@P  O+ ( ( (p p W5( ( ( (PpP,Pf|ى٪w8K-v#i8R3,`M[;O @{Jڟd ( p) ( ( (oj˨q9(js:\NS<]8Ư`G`wt[_?fy1 q>?M&e lGSL|Ƌz.I>ϯSlP@z$ĝ ( ( (  VT@P@P@PKP@P@P@h/  ( Yfj>sB Zwa.|^Ol3r~?חlc71k;vjQý@~LWz׶73y{|zӋ?\O~ǣD=]Xgg}As8i2 ( Ls ( ( ( hༀ/j7JhvDRbP 8"v۔ q- @n 4 @ 0$7ZJ @ȉ{v4l ʡ<R`ZjOyޓ?Wƫ58P-U rW]9#g;=w?>gXZ.YԸ׶?v'@! xVX  @ @n 4 @ 0$7ZJ @P`O8 @͹]9)<+]ooQ~Ie/)~>sK__KR T_skC}㴟w㪚 @(n! @8F7qU͉ @5 H_v4$g-M8\zg\vLΓgߨo7.? G}W~959CGYP4W]c<1Έ8'0Oۗ[?g @Þ @ @p @ @84 @ p@{x@>_syrw3[@ku%+I]$N4In5BjuYS9j5G>OR`^@%m ȹR5v~i?Ob @Ԅ @ @m7nC @N [R"@ @mbhwS~?[/{~Rŗ-eOK_k 8&_gےUB?c[M\/{ۚ3_s#>tfi<\n//$jy:>]R|9\7_+K8Pu*~R}k|RI5H_c @V @ @79L @A cXEs @ @[J @$}p{KOIߖex?JJQI  l~}[r/9ǾuF~[ڟ衖T[,r~9>lv׍S|qNY/K>6G6n65 u.qc^(I58$xU:{f#꺳IN\pOǩx6%ruG98cG;j} 㸾 @`wس0z @ @A7q @DZfA @PA Gh?hRue2wRJ .9R_u5X h'E4݋#Ps#?kNt:MݏF9O%x֕@_`@G/^/{~Ӗ Q;jL @)#4'@ @Cp`f @ @j<LsxXԯsWQqZk<lRrǹC'q\?Gl@q]u. @ @ @,:!@ @-a @ @gPYuB+؜4ո~vs~:q\?t[l5k?jUz.5&"?OJlߪA  @` h @ @`7vQ҆ @ \ / @ @]r".ghC6jtpus.NouI0FR|}Vk,nc5[9&z/=_ @CCZ c!@ @_H /[ @ pHnj  @Bj|!X @ "'ʏ,ھWdGg.[Qnuhe959hb88g]~:9rM,3wqӖ Q @"  @ @1p h @ @`@Ani0Or %]1PrG%VIxJj|woC9s_ y9QkdoPW%@ ǰ@ @a @ p n* @"  @`;Ad[ii_ktnIm;_5;ۯjLn5^&V1]J4Dͦu^y4]nGfr En]7tuQ?:>56=$@[R"@ @mb @8:7nIM @yC^ےO}}2] W,oK%Ǿ*&^>)kMH}"MzqK4jv>9?]ESj2?^݇(-IvK @ e6x%@ @vݜ"@{F,{k\N[>'o_ 0 b* @W;sjՉ{sg9:PU .8-5Ɲ+PcW&t^kD* i湿\M_MW5ibk @``03\ @ 9 @ L - @ @}5tq=|W>&@%_W%Ir7?].$8-4?G] t$KלȹV5./t_,t"/OWjJ\vA_ \;O @vp`%m @ @> @E 'r6 @ wj|'}Gj~Ku9ǿ%Cn}JdK|`|V9ȹyq0[/֝ Y;zN @vp`G( @ @; @Q@ 4#@]jMeSmK2Yؽ(57JMv/C6t3Zj5G̀赎/]\@L;lAM @%]* @ @#pt @ @]jܥb @ͩ979U~q?G~bK z~f<׫7q}˖w* @"  @ @1p h @ @`[&@95i]r,.b 00؂. @G }ԜC @&p  @ @>j @N3s߷9KwĵFUD @`03z @ ;1iD @-  @ @N9nS4"@E95Ǐ}&L')_]]|ڟ935[ 0Dg` @ @V7i@ @/  @ @V5i@'p}}ߕtל?lU__Rc?赎/ V@&[0%@ @s @ @؂. @G@ }ԜC,n]ͩhX$ѧ_9Ej2@0}::立 @`Xe @ @`/7bs @Z/%@ @{ Թ:q @{j\*%.a7-ͧ&<~[[ҝ Z;|O @vp`7' @ @< @M@ ݜ"@9׋R`V:mk󾻨4PFS.&$@%ǵfC @pN;  @ @q p\i6 @ @N5dS ՏEgEZ:^5G]/uu_6ҮIץ?v>>Ѳ];^ }7ױ] ܪpk?UF+֛Q4W}ܷx1n;l  pCq @ @Op xN%@ @Cp`(+e @ @ ) 8x9qw3īݣȻ\eǍNmxy^rw;96jRQ^k(%ȵPkԜZ`47W1u; 0LSqs0j @ @`[&@ @ 19 @ @-)mK[  @Y`[vV5NnvMy_-?i )]}uK_q&@k9=l6]>K)\^FIUDyY*.\xԚq^ Y~Ox&@eCx, @ @ @ p4nR @_  @.pI?+9_w?juh -m׮oLo#^n-km>H5T _zfX ]GUjÇqh}?(5>I^q9:ݻVb㫄Iye\x 0HSvS0h @ @`@Ϲ @ Q)ޕxv|<ޱڟ6Zm-w qՌ @]. ,/ rۧK>9⛜|sųY0q/m-v@77 @ ; iB @.W  @ @j쀤  @ 0rYw)ڽ99u{X-m?}} "OxO jNM~qNӒ㟏ˠ^Uy5j @((դ @ @@p { @ @Q pjR @ @ =D @{ Ԝnrop&z5>9Un(5jnGŧ8"jcx%@pp @ @ l:"@ @+ᮍ @ @gP(uDx]Krs]]_ǥK*׫5fzt5'Un'6Z?lj頀A A @ @&8 @87`M @lP` @; Dny4wD~d_\\DSI~Z㓓tix޽ط_庯&FkY?zx\ss<O^yU_W q R;lM @'㼴&@ @p`f @ @q9qjM E}9U~d-|&us?>Wt5]/LϸwޥQ+%_H w b  @b_!'i)bӧx~s,(K@Psk\ݻXE<1#dzfB @p^ @ @p95jMc<w<+ @ @a pbT @ @YxVN @ @HyM9D"@8DB2}|K%?L~/wGi[5_nZ{+39"طd񈗻[j>'>h9965G_}ժ.l|՚OUqjA-+{./awR~3uA-d׳#@ @%Ps jK lq:q©BOl_Sv8u" @`h+f @ @`) @]KN_7?uϛq+0Zh_^^]\\<5'͛7iBzW{t~k/Z.g r 9ǿٶ,C^=c'@ @; #f @ @`n y @(pyM;A3 @hIZl^Z}:q?]_W]auݿylx:n;[4VS .iS/::OZOr) fٯ^oyXsk\]{FX|HMb) pdpd j:J7IDAT @ @.7R @GC @P. @ OOIje}d^~ۼyo5~<%ngߵυO9ͱ㚳^Va^5/m5ҥkjDNFhgK`03v @ ;BiF @,W  @ @j @&@{.ߖTjs1rS ~Ym]_9w795q/]rk ԚNɐ|A[4ךm)$~a oaO  @ @O~ @ pDnb  @O@ d'@8tJr^:'IwѶyWW9m0~~ymzk֜s~~c~u/w~<FPskW_]mj{:؂vj@Psk_ Sl6Mb1Ou +]:'@ @ xVZ @@Sklj=P @7^:% @r9L @`@4_8嬷)őxX[_fy:ᶜ@N'ܑלaիP#⺍mS;Y @xn' @ @puY @ @+P?L pD5g}^VrxaY0S 6ZzTAi5q/u. 0P6 @xҖ @ T .a @ @s Ts. T͑P礢rPR _8O]h붞_Jt^vVXu [X.|^ѣ2ϳo׮Soң]_=z>>sX,ivl6K]?mYp_\Sx̳HOaO  @ @O~ @ pDnb  @OjԜE5rzQG__\j\}]~u}p=^ϯo^=U[[}z~^WW_ק_]{;翞_ׯ/ իշw{}oG>ju|uۮWzոV>umڷ[}_u}+w`L]徿<]rq ũ}۟XEmd2Y9jDu6m>կV>z^WI뫦m"?GȧZ\w\s:X<g`m @ @cx @ @`n t  @q8ukc+weG}[ [kbH9??oGrSSr@ٯqOq:xGP],! @ @ ; Ʈq,o k[ONpm4Gnkq/umb[b}ǭ6%1mq[m?xVE/Tˣy}Q}1qIn#5oỴbbmv%.]j x @ @vcz9Pq樥FY*hRr]#VV+ۻ?c9es~|ϗY~|v̽[IYݼq!Wno ~{z~jWUc1SO}Gi2S|yy}^o6''mNrmj5Nȫ+%ă)s @@}(SϝvG>qۇW,L9|paoO],Zecf@jxNӴk[́ve=qt#޺-};t9ÊˈWWpGyk8kju|u]έ#-8 @8l7{} @<¨ @ pY&Iԛ Zo ͶyWW  @|IIq͜T8/>8/ڿm^۶.z~jǗ򼖳~kqjOy1ٚ_kx>_ܷ~]6G^$Eor]\9o%SK]p^JME YW_z6-S;s> @ pn @xV7Sg @ @0jSFYo&ԾSIwb?5GƵ @$u9)xcx?zqk>6z(ӿIBԧ߿Z~pyyqtO&_j _\U\gmekNM}}]IENDB`ic11PNG  IHDR szz iCCPICC Profile8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`oKIDATX VR0 u8>Ё=;00w CF'00ϱEqmMteYzz*OzV0n37YX\SܳADCߟ ̸7/nX߷5r{.Wm\j?k߫aD7Cw 6:cAB1\_āuAHGSeY*hՇû#+MHx<ڻ1M=v0SZ[+kVC glغ`ƌ 7ABSi|lk Y:i% 0͓'FTԭsg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o 2IDATx[o~RH0EP@K `Zpnr3:@On=" \=@Ehc'(S(JD~, {o̮D%458xe#+ {fYaɤgi]>`:2餬dSJv3}x PpӑA `L)Ydg4?%]CYHUb b }hLǔ `JQYJOZ,ŶvD@DFadqd-Zd2 dwwWblqMk)cccWOg@ P`47欿v[ɺ!~D81l=̰A2Iy(\ƬYs1xA!I_rUC=CAo*"$Xcfzڶ츳)?=A!ѸTspܼ}_rgxSǵbw`?#YMLHԬ111Χ%ܜB 98vdP9:$RWywnsD&2N ,U)I/@he d2Ca"BDEޝfښRkjGOq^SF((ӑ`!NUnD퐡k" Cŏ*9 Zi]ǶظTt; Nv>%tA CFg N`گKs'OW\Q)8ISH1H"w^/OeXS`#Փ.A2>V$Gw].C\FGGGW$t`mk 1fQ| RbbȰNj]aM\@}L 7 Oc`z* RV>ȷB69a}}COn]eV+DA{m _*j_b;]n6 ^BRf[r]baa~D١}` BYcu)u"ⓈgACN>ϑ)z٤,.p$s]/-v7],<!䌚, N3R͎xea"JO /_.QUDjVm0(-"ђd*edSNkV?j:x) T&2RS,y2I~iH"xBP ;"M_3i 30Nx?2'o$.ey{:b*ؼT utgF;,ouN#X@0X˺f78Q<"h(-Jy,o|t9dj)&PymV|F:\hnmwYNuL\5q3kH1q+&1 =4@wkkY%+SY%ݻk*9Wrq1L#*҉ݹW3TbLG`@ z ~ʇ5pǦpj20ە~~H#a1Vf7uyQ >{% 3pG[5Wd i׃ {^g@L5|Bݓ?֟Rrkt^0<pyZB? GoVX? Tp}t,?6 ؽ ~UgݠVuu-pّ Ž1,%;*<|M>,G{Žc|YM2դ穸~VͺWb4G'dF`'@E}G\5@#8<6 #$L*ZIsąSaqv\˸(h%:fA;B^?])nGk{vN /n%,V $G  #6#Aqr"`ǩ1~c}`\Kg )䈑@Ý*r> +KpVD!75Gl#lniO孷ʅ0^k@K:3x503#B@~[qxs"lk`Kx V'Dp8YE.< wjZ"jiiSy+ycZ{j?#"Yo"> {`=?7FrYFT~=U4c"\~[) @HpK-u!~yZ8 ]#C+sEu=L/Ѝ8;ѐPe+0@_1?rR;TEd~` D}VϙЊvIENDB`ic13YPNG  IHDR\rf iCCPICC Profile8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o@IDATx#ygaz]rHYvK"_|=?+s'O&> Q]@P@ݙ3ٕc՗y*J<:oe^dGخ2}'+)N?’I8+)$$ptHptUn(IpHp8YNJՊjQy7~oRqWIk0_:q;M+I2I%ذoD!CdyI\W5H`S> DB2K 1 @֌:Lwx:7npbxǍa$ -Dk*D_}龖k5F`8jw{~oo]?[d`'7@BHf} $X_V>f^uggWoݛ/;-**SSUz<ۃ3J!5$%`mQjյF_]]y[ݧ^UZZPv9b1ٶ,5PdfH0zVZ ShW5V$Pd*az^WZ8U&ZӖ@Qi-^w ~_3-I lX(Q@KS˳ ~H`3+fQӂBҚ(u?͟F5|Hu;j=-uAVLh>ִ;}x7*J߸.dǀEC>hg,ARzx>  ~@7WT$]2(y#X.#g3Y+3\.2 od/QCcݷ-hj|TĀ;ۻsw{N^Iz"J֕s$ _OӅqp޹{{+dSD* M؊ G)\k;).1I``Vx a?=?,r4bG~/pǰ@2i JZmLƏD ӑz-KTGPqA#i$=u7s$1W6/]uO ꏑ@7Lo]kc"ϯG0Zz5Xg!09H9@uO0'`N@hq=Lg@ h7QIM#X-# pPq6dEF`k~Q^ Zי֕TW$J+;lš[wFC+3Gzc,sr&Ž- =MOZFoJM*(@D @ yqg0!0䯿@Lɱ^ooch4EZݧ.}SC lZk`9W])EH`/=#ؾekI@X;tg}݌e1f$@m4ԡ?2P2%ֆDC~w@gݨ΅A7~y[4Hzk5i; 8oߺ~Vk>oW?vܹ* !=d)L+//\E#7$P#G]KN# /~ wyymsk6_ ߹o"Dkqn$Bnvvٮ{# qQǵɿ%j)іxq]]]yKovŅ?~StGá{޽Fw<ޏ03SCwuU~PwÖR1l)6xq]_l:,C~HS` TZd@=-C`"`Dt@-[mPD4C)DmDMzSY>%am4o!~LX 20?v pm;m><+㦻aw#HAѕ$=(cxJmz+!B"k' o%[%=ൣ4~ 2l-V]0baq!ց~ӟ>hW6(cHS36B%0 ` q$œuI ?ilzރ] `YjFkDXۿC]g?o,&T,sEH=Y 7 ua}`2D@kYxz~P˫ۚlFlXӄ# OkC@oJ_a!@6 _~CMzsS3%=`?9Nn"of oZ"o\K f>/bݟ~ODSX⬏ޝ SEzvW>9?dI #]kaV=PUlb?곯 INSF1N~Jw S7*+ٵ{bs[a7}3aID*c$p1E7?#0I,j=i3l .s!^Lm犱:?O?J?m䫪uoi\ k9Qz1b25`rEsm .nnv|#sO@MuXw \L"k mDm V1I`ƗJrY/U^UZUoXad7ls}7~`& ƣqKjޗw޺GEρ<bA̐@#X0+^ |"7xɨp$[UѼl6 hJ0w_:s~~5&#; 'u)}9 F#H%? >Z=DTkrw ΫYCj]ћ[bə U4aqG~}8o;}3^D:-E!7}y&(Y6Ipw~z~÷?asn L{DžF>ozf}tBs}0 >ݞxDo-29_jx"R9=Hzt:=~֮e/?Wv~# sY ccnOJ2hXº6Rz #HPb6`R%=DzX}}_] z0"`!,?40lM 9<,Y'Ô %=JMnRe^f+hIM%J픳fYU_XB3;M3#Um5X\ۗ:a6'c}W&>t`"=H/f~Ȟ§D*0ܫS{ $X]MzEN (|qUFFSsu!ݹ_g砢G`vqXI`<=?FSj=?΃ЈZvvsP#H.$vA} |5OZ,4~s]q`>pgGFnMzw3r*ÐjQ\۵Y$XVOo M6A@|Km)F"u$;Կk_ Vk>vuDZV`%HV?IKy9lM e_Iiࡑ 7)%G<6;Cs EaT){e9{P1n5E%#8**l X ?ɃfA kL1)fSxI }o<8O#ÚDK < p>g " CD˳݃Gg}}k1})KM"|R~{Ez7]tb 1l6ؑLJ06a@|wjz3H@zUO(=L"'>j3#ا{*Uzpg-#BoIM< p1Hs$P~#ec^DWsZ-@N*~}{ zޏ4ܫa=P)r|}UKh|n:ƒ< ,RTHy4c?[ H !VuM ]qS7~(L0n@?Vt՚k[M pi߾{>,/9Vo&0v].#<7nzjE%iom{|D|p\^rs6ىb2^lԞTc5,$|1T-مv-`u"=5(S$ëi_׵-v5Bڢ:ͯ-ۑQD/zH"XcZ~ r!o,OsH z^)@v R߇LJ7E|񻁿J1Hۀ_ zPJ`1 WkJczl׿q/n14dBlMجJsSWW5&f @ug:+B!+!45:G7a!̀Z~@aA9ܸ/7x/#5y q@" bii :Oz@z~Z*;& >4yO#91Ȍ ڲxߔGXLXda,;B&8@?-*L3 iʙ'ܕ6 T~,,F1-w|6̓:o`L{x s}sL-~-~ 0{#Ck5 ށodl dTw]>/IK9L+x|:@gdl>U(K?~.bF06؞<@h@L* g1(Dٔ7҂ۈ{˽p)C:k+2_- uTxJNvy)@a㒞X`M-j aBO3 rMXny5?n2mF1E%2n9¿VxQMH`6` !=UO8~lkiy?517 '_ʂ(Wm pm;mRHCrx^g 4貆b5&VvHf} ˲1 7p{P)#͕->n暗G+?_g dA62HO`U1}z\=@F ˧O ؚa>"(cFM RQ>'ĂYS'\u ˂i%f~w2kHE7e@J],=170c=ijyb5<\m$`p?Ȁ z~KW'Pt\4y8A#7:<-o$POU UoEm-~^G^(kn2 Ɔކ#, xFo`nfV1Õ0+aE+.ggw,"l]=<^6VKXVd!^C iqχQ!TogPуkEӽAx1vzz^66;Y7~$UlMo܀wQ,ofgw|q<7e,^/2ggSR @^_H;YZpH=\v3>ںN@¹/zellJ}8%:, z=}~!޻8;BXxV#:KO =+g8k`>5f^ +#`K/}{kS}i o0[44`할>XMo$[yySR7xY^ ІlnzJ^ kȄ 6 @:4j5 vQ@ EzEPGlm+wwwEB*3 6 Əx?,a Fea'ϊ!M jrCHed.Kyx^/q‹0 ˦yRY'=lO~cl4`O6-!&&&/ $4HO>9H?+Rpn/?̘A')9 __E@^v8H eۀFlDCC[O8WؒCNl 7,=!o,i-_@dz Wq[:8K#\={"Uz~8x3$(b(h =g]FQIFe$' 7jcJ7~sMM&W!O@'~<,+`cv-#J'h8#R(E (&Q(#/&WOauC.Ґ5~6ch6\m#6'/,CY[yqQ` &eq X</ōb+#!+٘ꧢ:a)(+c{LJbtj?W xo6IOg Oj_>+- LyF{8|lj^(s_WNm@Z7UGVZ?rҍVOtb[ ysU@,aWP`e,`5Rc>}Qz+2ʶ3 (}|yne<@p,h0muAGr ڽ_]y_̞‰Kn[{F‹z@J@k^tmtT) 0o_4z+dYE5HoO*=^3.gŪgՕg(`<˛h[R#a&F&Rҹpl~t#qaH Q .[+m5 "n/_WB=LPL=/ l C [hq[e^q0uFy X 'cxG*qA1`oȓ)pm4d|dyHʙ|EJji-*[Mqe`W4z+S| l4b 70| !>yY~?na?*}o{%N|/<?p?L*VdL7um Cy1DK.[U'Rr؉nY='ɤGJK*=&Xiky( N 1ܧbhL6'/F,7 ,J?-fV>ie拨Aδ@ȧH ŅN\?dejW&})Ty[Ti6r|PW֠bxUUŶ4/{+2I 6֊j_pB*<Am+a4p˛Vqz*7ta=όX2#@^X3S/?!kNKb^W zz)jemz'%?ª ЇmuPWGg^Eݶ48$e Gj4/8.D X oonVдA@h4(phl>xM%, D0c ~s%3M-qqctz2Ɏ^?.r=LvV wwwFoy"6?q @O>VS$v:>&"xuj uXH_t+~uIܞz Ѥ;ou:!rw: XgFjT>Cq`MHZKo ZCUb˗8E#<OHY`,96("1Ã0QX)P6CORےRz9ڮl.\M~-5tYESщSL%FèO} *۩W*==CG Xd@HE{j5i gMhqz /Ȅ+a!_3v\7MOy W#M=2 uc )2eM=荱 ~Y|cz W#1:RgUszB{MƮ>utx嚵OaU>o:j%3}&I`\CC I*PWkL ߙޟpk`OzFVcI?䁟7fx'4l-ȩ0B |Cc`+sz Y&VGt kH4HE/+ѭI~E#He0nN!]^ߩEUmPǣ* #'cK8?k\q]pzؒe[eifbg=soj3,˾?3 Yi@Ht>Z酅`"6ToCٹ Ǖs57joTZ:I,J`.G.*5Aniō߄`/J9hU~:y$J8o˂0s^8a%ipssg8WgFv$,?Fv%_Ly^48O ?TU"+T, Ä שDpG<^qsc CY[ydOGj ϒ^Er#ga1pǿY"m}I^pmG|=\1Sqiw.Wy|5. B ZR1mΕ0NzhDb|_UֵEڐI"LD3K[oru$@6hQ vM: #/7bB _>b`۴{F]H@-G*ʻtë+7ƾzmOm48,0aq(=w11߻3Yv,ŗ+;?b8g t\2b46I #}QǾs7g̕MϊhHxv"K~̪28QE=9DuHkLc =<f>p6=w1o`n`iTsYl{eϰ_~k~I jՕ{=i`m!o CkH c7oYⷊ@L EGgf#?&E(k 6?W loXٸDzNևꚴv55Qa*󹛈T갎 Ü9m%O ,T{xf lF0FF$o,<^>H^FyӋp+zCL}pЃM= r ' B~qzE& ' ]7w(3) q!_:K?oyk"򢲩@[ŧ ؕHgd`':|(֦r+ e au(0Vi@ ˞pBRWf #&_ky{!z}E_Y $˹J`5gn ʀΕ1{Y6~/ɍ\l3,Y@fnkyſ 㗝>2$XRT UPX~3' C>˘ l@E}"b_<wN+& ~,݃# bB# hcPĤ`JXQzn'.ܧИrDƲjO[v7xN>!҇8~Ni86_<,MуlŲϖoFMkeH9 c~hS Wqccr'XQT[#J[m_Af,nFXˆc \kK -5P%YF9IyC1`WR+G7~sA24TMUyj7j,7rͦpc~uLN~)bs)Ez$@Av?a 4(t?]~!gd:S1G_'Uf7W},a[dqVjv6NkYj 7~{ h d}fa?vtaU-'5SwV#p 63')Ûwb(Jeum4r- xV2;!;X<1/1xA|}lxVOC+FEp̿! /d^N.;^)þ!u#Y- ߫J@ g~l<_LXOѿ5nYW xx/5OoqN 0G+Y}m[]v27JȂX{O< <3kESQ^֬J~@2 "̡nL^d́|2܏G%x!Y\kYMҜZm Ԟs^=,* ,N7k*f!MDC-D~?2+@j'X凉,qkP=0`n,p*[֋Thm'MH ?m~?'yH`N;&Z1`H3k%, z ۡğTɯG9mfCwyFev!:>@$/\af '*mo;@Fr1`O߽ö?v5͛Ļ{ $@zmS*<~6pa/$8~o;9?~z~n՜ш Lyqaײ5s@c䠕qJ^}'ȑJ< ȞpaMv';?L+&=32ya4 - 0&~Ŝ?^v'~u,4G@ 點B֒lZhm@z~_pCa{1s7̂l z Dv,lz󷫥yf"]8Va)pgm﬛~uҗ e8Ɣ n,e& ɗB {&[xô~w mLFF ͼqyH,>sǿk(/~<~?DWvC@ M7 +@)no[+7L:@X5#>:^2%8,O+?|EU٘ ~M?y wB4mAvyDd2s ذp&b*/1ƣ#lQO9C}:D Y /iAL#&o>D@tߕH,J!>#g@Ϗ& sz?zNFvg$@EJMVOӏq𞾭š>3'C}F ~gƤ6R{!i! lfqʼ Xy\m4bew,y$Kolp[B23 5a,/cCGFY$`M'HF̆lLV{ + }Q`*Z}/)D+jeC;?xk$0ᖻ;oT$bϟ'o*SH`I-YC˾q`آїdvx-n Zfsً v**>@NMy->z7P}sK3/{oqh`qK6S8`Gd yG>'KA%sXF&7߸sQ] mUZ]m׵׮jF>!~rj= 3{G9kaV y~LCݻ]luV=sʙG>wJםM\j$_vDF@v1p1_ LvSP m' 7^Mx2-D9°?@ Yv dr^й_bx8|"Lꭷ~ov]_]_C^o(VN#LF'>~Up¢;[O2^-9?|]K/Z~[>~tXOyj6]tZk<3$Ԗ-<ѻOD g"3W]d:ٟ68uL `NTZL~ ШzNyxǟQMr9i/#{23 8y'-yNN& NW~Ke,F ;Y"Tm *OeԀ遑񞓱5+Do~I/YԴz{O( 'l4w+,yeG{F/M"9p7~!\: iF(JUkQIfc;'ri@ykL Д}zH3ӓ6z*F[DoE+T#D#l gb矋vf S5~}wM!{u=AQ5זA>( 8f?>R 칮Mt>HehaEtn{d*E ͽȹQnט¶ᵢH[uA̯#VQ$}H_*z#QB)g4g3@R۳\=_ p|w?tg'~~.fG#ЭVw*='m<@O cst@<<d)H`x__ oEVroe~x-kd?,LL;{x<z_-F<&ԫ:Q 彿TE)+ mTYU~ 7;_jrKw/}1#e;'sHS3z9E7('"-p `gv2VLY[^}#DF` `zJBey-HyUGNpdUghAޟahD`#KS/t@"~v0 $87+(xA 1vj>?X Gx2-DGYh~WqO5 QAF%E^9i fzUNJ&NdۃfS@"@}t4>M0Uז7X" Ȱ_7! RJ  =׻\/u2yCnWOs ב@{JLv25qu&MVe"i=j[I @j$TGſ,7O#Tao@GSZJQ@8c&+uR-FŸ*jj, /Wk|.wC~%F, 5"8 w>M\*DKEbb@BT@ى^=uI[Dz$4@ \`5 )%`c=״FuK;H | v!6$ ȹg襣ޅ]G Tu(B?an#OОuu%_wwI=[x}9c]_G I2ytGsӣxkt#7?;;+g]y O*/ٯ]3^=N"(&63ٿi%?>5hiT@_yR*bρ#>w[-m6} ZB?[H^HDp |!D7ݍ@-qk' hHszjTa:AچO"?osFDrRg]E,T`拀q-D{C˜!qE? Ū):%_@  `c ol#f0p0^0M{ݼCDϡ3~BVkޟ;|Y"u[Nw0 gU w~'; Pˑ&, (<ү'-sހ#p'm}^?@ǞOW(}/G(DHX*#p"? 5gMaH{?Š [I`.DsY$Hu!r,`eDT6a>`şG(DH@1 8"`CaP/-jzȄEG`rJ`Hף$0;3Mb3 +~NzAZm5)$V!jC`0_túN*VEk1]xK#H|z |!vECt_W$=D&t= ~V:^k=tNI:V0g"HzIhecIz@9o{׏G?@mɶ5h"w,L_ M#÷T gs+ZNVT_ V:>RDsY$H)H`9u{Nۀ7"+_ Wkp_( Mx0a\,#zb " $y;E)ۛ/ߊzrOb@#HkOSy3^ ŸdoQ@$h$y-^AwgG/ n*'#`4JyMpHiʐG'mAv\PwyR=9)Im/aJ)O1i֗b ^HF:ؔ_~2~G)Iz~nZLGWx;ʿ}R=ecy L&K|,L>Z '4,Di˅@"'#C3[Q&E Q) c/jzO" <iOG`Oo#-T^mnlz-Xlb_w-S2mmݧ$O-Ǯ"ϱsm0k agy/P.uv1Nz|jCm n|=#eQ0s|R#U ۵G=Wq?6>5ీj$3 0 ǯ#>0 L*_P};_-G kCm`}5m\Izcxޗa[0샫cYC0ַ9%7NH_}š;ݿ`'=%o2݌@#c6ڇ]ֳs4?b^vMK@yQпC={ Â_,c?_utذE ܂*j ^ozizMaשR*rq%|^Q 7/zǮj P -=?ܣc?̃aLd?Od߹Aog={%)27a>kaYBk2I.gO_&Ҍ@ՃYG!WUX%O|:}Mo*0ZQ - BriFvz8__huw٪kD0F,;}\H1y`=?;MÃRR(m.IG(S;Yo c 尷|~@?~w7[,÷5%k7jU??$0MD@>S,@y2lI؛lj=3he,XU x0А^+n"{f&b4 HBqFy#2PyʒKB~3ieR0W< ࿘,*cuTk#VqF t II&I%` dNΐ|mp` &F-f-=#ZpJ8Ӆ"0߶K&IT$@s7 u>viNzH?#]LYâ]!MHx" $x"bA=$ <sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|UP`o@IDATxr#GRױ:uƎ]1%FdR"AbǸ/\T(ϲ##="Hc+8x*=W.R*- /&o\9*)- @ iJ$@ ^@ @ x8M @ ^@ @ x8M @ ^@ @ x8M @ ^@ @ %rTVYhz:z)qVH΋yg6+|vL&KHǁ_)5i* =K@ p@ :8+tי6iKLR " ^x}?ͻ3 G)P'ZX mFÇīԃtC*@ :bڬyRA$ir4>ͺZ`8ͅk?yq }H-NMaEajv]>R@ @!^#}WuN,"-,41>Jlj 82og$Zz^D {@ ^j\Ft Efdչ|2 !46+eVZeB+  @ !jO*̾wy\MJ'b^\%.hF>Jthyj4.U5g4!P#;s@ @a_]a I0?|{yq$?H"g^!SҘwYz'o&egċ9 !A@ Eq5yЅX $766#PA)rȼt؄n9e˹/-3ʃr؅ @`gD`gP@ @ snM OmhX )6# UYbg4l6I( k_?M5~~p @ A#<*G0/nz4H:zl|`5 .L+VԧO~7˙zU}Tѫ@ZiP\db@f)Vk /jБ|L _مpXTrP5uHGoa@ @ kD! 煍릣5oߣa<@}uP¬+)SfN@y$Fï$!tg2b5 Y6 HV判IT45ͻ3 ӄ`Jo݁޺t?\%)=!չ|2 !?z/-j=-rr 7@ uZz䶭d,zF ~Y2̿z(&s _4]eP| Ț"K\ӯo 0Ĉt|?? F +iFL[>x]P)5saЈO@ ptѵ-@ kXfjk"# 5e>r^Uͣ>=+b_pfXwQ3 -'0>YzY?YL괼vTV#ccW+"'UBU,ey ,_?CQ!_ј@ @eH^Z_ ։~?k#wUU4#^(r.a^4sX5V Ա i@IyV<^>6`1+LcZ;̗ *_5?] Jy /-,y9de_8t7Q'0ՙf@̾+]0x.tU T|G&,f!h,.Ή?TRtAdCW<)0| աWF_gEWԼ|BS8@`@رp@ @Dn0z>J=HGOtVƃu!B }Ew_(]ܙyh*G=u6&]鹝]Qz 슎牫ԃt"M*  j(N\d `RSo*Y'rǛ+?cr= 0qEc=T (hTA:Fp^zXNN-5]u%vcH\ˠ\ڸJR檲_4$צ:U&gH)Z]-rrZ_@ ^^[U}*mÇ$/.l8`` yscDNHCYow'z]Ũ _2r`wmгR{S]Oo~Y  I O}=r k'na݅P}McϮH[Qǭ5X {:o4tڻ՘_9̟38 ]"P{ߥ@ @DnO"`}*Ҧ#xg?mc"ZӉ` ?zUbe"D*揞\Z}"7;L:9S/Ӈq?Tgqfh|Hؼ{?8m*oH gV T뎤)D"1/ ׁ@ "/`vO_?ݻwTɉ1T$5OOQ3k3o93-W8r'ﯺ|bw.Ahdl!kţ1^̻nRDȥR]V\P1-ߕPVK EB O@&t˹+t.PQ ȯFivCT2@7d  p@ 2yrn;BH}5}HY#>H#V K_1[{q}7GL3d r D5ޞEKx C?Gc=*߽]gT3_-7B^?ǮaG4X_*>{G "{8 @ 59\%P@bA. Ko$M9L:z~&{^__ 'jY m@ E77ZD&"'@gL̞te#EG}byet Rf!,:>*Q`{3'ٺ,]K-gag$Q*JB%ґ}o&,f!h@ƀ pC9~7"T*.z4E-@QX /lZ>UWԼ|B.v[o'Ks^۸n]_XDT|I_h'C¥'{7BLE$ GϹ!Q@ @ >:֞cdAO80t ƁÎ`JYtat|.k_96ٍп.m7N U{\FmwN* =YPۡEB!N+=D{Z]߮=ҷ*.*8PAORu >$߾ct:Hdr{lQt2e>GkAۋ; WxJ\y.3;b+[ !Y0 ,z ?^qcD~+"¯VK1w3|@ #W3% @=o0UF#IGI:zHґ0P!!m^wpɬ]Qp0}ΧW ]ŃJ=H'ФnBzEwAwo!>-ʻ~C[ S3sf<&0&7WJ}8'&96`-J7IIkTA:zbX*QO _>r`o g0כzz d51_|Y?]uB=ח] Iy?Q`oZ FL SM_$c f͹s.gjWww%+%"7.X y1:=KI~r?'ykU9ҷD0@ 7ooQϏ`]$`0 $59;uβD4]t"UөN8 Ž,]!V,@Db .@C\*k89S/lch>]0 B5\#caum&1NOo`̸,B#i LfNvMʣ|^1_@Rߍ$ב13#_n$r/Kj|R{I{q@ u&@ HYF~O3`֜0aHsIJ>$c 4ucBV4#XOu9~ӧn*"EZ/Bv{DﱇHYB "KpI @ u :E+ar0W"4}IW毟a0R$|$!'5kDW1JUpĉOn}1 uR#(@˙9z%PIt䡌NhY( gn(7&HJEYihcC:zر2 t]PY>+v0쓎E+r ]nǞm7N }Z9zn'+%׭Zv읷J=HGwʇ-:ߋcV21K{H>_~w}Cv[rn+=]JA%|t> O٪lYga\tSyo{:!۱ 'xIāޮ\ |L 3$aGDgcS{7&9l*ύq#Tag;y@ @ 8H"p%*UG}0mW?8F$}$!IGS@ȷy6]\[+}a q,6w;x9rv_1t^VR* H@ @HopYxH.-\ZyW/_`h";aSc1ׇ0J$LE @U*W/vYIm.RW"0~t="x2IR_~Ko:r㺻Q1T$pzN0\Dơ"2 Ӻ@N/o/zyz\u%zx''ernϴ J$e* UyIikJRBչ|2y?CJ车GCԥ\J$>ray=dgG֪GQ2(';/ ]#l̄#0n;}#g?t @Sb "WU0|e˙?k_s䇞.ߛzz d5m]˧95rw9]*ާ__"0~v%z$-FQbqk *|_>21GN_!S=Vǿ=׿|O6mkhY|؏awm¯QyO7;OX&7~L-NsV*q@ dž[=DŽBۈЇ c#9;}Eqt۟ X;etĈ{4}0g6zzUNe"D*揞\d1ͥy1E(f u.c~ק ƗA(Kݎ1]?8r6p$DKU8;V T7Zaszy7W3Ǐ$?ERdLCO;D-UTyUA@"9 b B";@ 8Fxc:ƶE3i ƈ$?ꐞa@2@hݘG͊D T=.+OJ_ p̚rq?;y׽0 Z$λ)QJnIulj/xDO'+L$P]h]@եy1+@d|WBYaά47-7.M^v]:(mqa ݛOPHym|B?=>o.lH!V|Um4Y?ϖTB"2שޝ40*ïd-tS>yUdaVu?_XƧ%]J@ @ 8z}3ǀ$̟>}Hf h@D%" >:^wn?Nҗ3k3Y DIH(@0;tEә{ݻ;=JJ-_?̺)#DO*3 },/JudD؝"UMu\z@|L㽶Ѳ@ @`-X MdY<(aO t.Azqq^00/f$]WL{x~#<Q6.Txr(ev5}@g T[AԃtWJzPP~+utWolHr,sc2T3{x:d2OH5m_v]G"H@ eJr#a+[d? @10{ҕg~> 'I:zȶ 2>wAP,[@'G0 Rn}1 uD][>8=V2#, d,ŅϷXsoJ?)/ >oWnZ܎P?"?)"1/2kkFG) .&ju((o竘Zʃ@H;=@rQ@ @ ϿyDسܪӧ?z:v']W"TJ ュ}w_J4 v vCMԉmk/+nǾ2v읷J=HGEV>vh^FJ*fi҇,( YS^AꟘ8YSM۵~s'I^tcMg4hCRÇf)`:O20sczۋmߛ}Dm8@ D裇}ođ0r$#IGI:}}"* =$D]Qp0}ΧW ]ŃJ=H'Ф7>8r]P J~|nf烡r[1AnQ-ܩ)~s7x2Ma0L!}R?? -{GIkTA:| ^@0(J%Ը^?uzy窃^.'DZ~<}ZrWU2W]i]^ρL)߹dQe~A-OkݖW;  .CT:#+ㆹ?|F#IG͍9$=NHև}OO7(@}Lb^(E=Zqb+7y r.2 kc 5QuI*|p @ e%@H!a龎G2k@#5 2@~.Wa`woq_wjY_ (`0LdHA:] C?G2[ o>%f} K%Osk_Cq#O"!@ |E;6 ‬Gճc*%bb_\\1@>;P/Hґص}徖b]}@|DȈ"'*ev!5}@g T j|* oVEU8yۥ%MtN$$P.ŒXIS* =YFn-@ X@DɁ!`@}VOzϘ=3L?CF$=d3M@ATf!,:q>*#g3'Mlb.i9h4~E*I=VcC:zر2 t]P+vʴ8`i_]׾^V:tsvl{Pg(9?us;Y).n5ɳ`\Vzv>~K|Тx 9?#`׷Hݽ-/ _n>5y$`:J3^hV @ x "9~y?~v#aHGt$:ETA:zH|a7p}aWD9x/0tiyAWe%ER҉4P4>8r]"{>Nv_of烡+C_ׂsez_r&NSD@? r`7^FEd6^?uz9dsA/H]%}H-rrY%f*4A/cѶ@CFG]W s~$GțN"IG9gž/=8>~z~1FVxzz]ŨWS;gծHcga}ǽɮ\@Vc q O}^# k'ۮ8qU/ ]m, c~79GDc $$cCPX @ D`(E sGΑo!'=Z?3Aā w:#w}> `4aWiKYY$>+=pyj "7/|gIWsYЧ+}"~*.]LJ"@ Y\ag(nsr IG"gr?;fcѶ@ @` XL$AKU_uH0 k+"!z%O˱=v:=[2+|%3kYT^k?v]y E4J!y>ÍH/x{ }3ю\Lp+9lnGJ&̝دKIf\1qߐaDŊ@ B "B2{FHO?YPEd\Rx @{ |(}9;]APLV7pE eK\j"a;A;o([> /,d_Z+ j?ynߴZD@ !pJ6^K4rxTlUʊUXK{"]z؅ww(?}JR:vMIOMjsIG/?seߤih=eWz'/O(k5(D˯9ϋ^ZwaO;I:Ifi߿{HvCk*P?OvClu"BH@g6fv3|;Tgy;y #Cg{= m^Fx|;ėsKur>ku[$$5}a~Jlnt{Anny\P*YYs>Oԙv# ԃ =ᖻ0u @ CEFz;zskۮrz*^<2 |<zvsY:X"i7_Sʯ u&߂#y`WWPI& *3<2a['=_yivq6;"D8/QcbnFSNa&Uo厖t#ٛ߮(|s!FkV6bگ^>-_}@ =v]XT9y:La0L};~L~qba&/*'.TA:v{d}!?zo'L;G$=I$.- [HA/z-R4,Jh4 7ur]|ꠗK|_MCo].ҵ .@`[Zܟ+@Op>&)|u.LHqJ:) N`| 8;[n}§'ɏ'?2'7p)zj')]^hy{"9-`@~^ۜ3ߺ FYgڶ;E3X,⑌u̟mϦ]6Bc/(eqvfLz͝9pa?$aGāH Z{t @?}$BM . Ca&"@?Ic$cհ=c7/T]jOrwy]*ާ_o"0~[(=O|Ur|=7eb[އX䯩?7BcOj/+{*!@ !lVW!^;IJ3yRM6_ ɟGd#']Ȭ'=[Zn(pK ZK+Yx$A:-K+G%ay$S `0}@A'?䣏s~^{N;\-,2 jǎt4_?/cMb7~iE;n6,%@%V $JO塴O g#w @ 8^gگE 1x1 yI֌GÛIK^1un')]Ӗ*o"h9sMvk`$yZcw$fSŒO`磷N=P.u~^Cb}~P~-n #F,"x6a { P>z rni _ ڳ׏ ul^䞫sU~c,fi @wd=~t\d@s%2[_YRMM[:kU =~}۹;@ @ pq58}4fQ ~*KAԐYètc 3[^}u2Y9@ 땍vf7 I3WtUTI;GsHhHG;dN/@X4MƲݶxlm=yqzjөmE=vmvq־"^_?iqzntwNgr pV '\kʅB4f z"{'1Q]P zmpH:<{",D@ 8k-1?+Q\ΤaأKvӱ[A:vHC=\ͣ|Îzw]$c63M%+Hv;[6oMԋw iײ?b OzuH2=ޟ'R*̓N#5u")gu'zAꚨz1 `wH J>#Kt;^s:);x {eOE{^.@C QFF&}ʼG9(ɇiTLrUZvA{ ]PZ cx~o,P1ckɋ1=pz耱)}ɿ{u 78a,m%TmR>z9U~+E{+z@ @ _f M:t9a!Igt<}䯓-V]ESc]rzz:0hh-wYC@S+A{qc(tA9&ScسiDD`ΤJ:OtܫZv]oz @ #@ "Gp :VZ9ϟt$=g0[ʃ +<I쐹~^<#N-;_<)<^Wzc/lę%P߻3c2YG!cQ(1^$,NJ:A>s"#@ W@DM>ױU%$aji0u_jI5@:${*mS'~XN"H" G{}q}7>ǝi߿rgED18X Y+&q7GD:D-@ ϊFt2K}IB4F  @(@7Yqcϥi0Zd\~5~g=}ߟiFcU"$zص}幖F/=0.G>ydd;@l+rVےr(TtA4]H\X`"5uQs吆L5 vI(=,B伸8=I\^~^zu=!1M#Ng:Җ2hC%Hwv߈TƇ@ @A@#4w՛6RvR񆂝ްg9 eҟft?ʇɒN}`䣏O:ܶ|!c\r'>#~}y9*ՔYz2!n}yc+!|wBݕ [!Sw/v{%'F%ߟTlnpkssLt:HFS<kGa@  }#/h1275I닞J=H@D ]4`0]r]4onz_QD7ifqmnlvThsDUQE,P.ƙa0_RGiC!>6fc$=`/@i9 Cr? ꠗKr}@?Yv:EgUv/Ye~Y~頗˧V:4B٫$UuGUޮҴ %e9z6=:u/kJRUC_0|LR9չ|2 #'zܓ:"fs`dUowwv[wK7p$ &?d|SI:zԗvk?/zCH?Hp\"[ɼ3:m@}ִz2& _۟^~#YqnM~}OOޏ7Ơ O/\n"EBz6DҨtIdG}}ˆg{|~ca` 5 4kyܶg  ןCHs`5"3ESґ.z^<38jHzy=0ϟ=/g<^~cNciR$+|%<;3fne ?>򼫜s,Gʂ>z9#a?A\'1V / a:M-![:ZM; bVp+E.Kp,2?@V[_YsY`И?K7Zq7o~^@ @7Mv/M~9Y:I a)s& mW{-NR'=ݦۖ :Q}H8 jo:M&֧NI: ̽뽸>j~42췕Ѿ?C>0Ԓ0y$o "*?U@dM_dg7& >nHYJ:g:C[nT}9x=hY;_@ ׄuf}M- FaȊyKIϥڪ.$oEz.KO?|omm}s}Lр -k.pX "Ǻ<vzmˠ{.Dze#<2P;h~"w?byoY=K_x#HؗWm[pXzEE-GKp'@zth\#m^4+@ V!۪H aduFW0zy>v=O:L G>Gʧ>ԃzRs}GG/{۟4du ksN1+ N乏 { w~(Etƨu415a0~$?0¾@mmq|wEUQGbFE~pѾ@ @ !K\-)>M[aRkat0uLF=F>cm_1R\>SoE]KMb 1]WS_cvl9]&O:;Wo}NvBHӓy HGmAq+s;ٕn05tOn?rs.=~0}W/N]ȀYO߶l:gmvQl22$CA6-MEM\d @ ["[<X"1)%|z~Hs;ɧ\|GH $vܞs)?E}?|$L~6[2vI>]^*~]C:z![{I:z9/v.f^FVa7q*&LAqw'KC`H~4`>d=$^j׃H'n~UQEZb9vyklzN=sN{u;z۝ɺ1Ɖ;">:hYvR8#v Ga #x7;2 L<8g?QoSyd;y/GT#UՎZD/o4.@ X@DVI5U9χa3;a9#c%I`)'Z/yOm֍lVQ|& \zqh?>D lƘ?v`8%GPrlm/Xc%G9Cn7wb/m%4_\+6~Y>svQl[kzwf[AL3>żI}᛬|T:@ 6C "V2)K3sM鯓,VNbmٕP]܇p^#'0 !a2~x׿V{w]|?BONE(MS7g7@7(1ZGdOnZ'\* <|O׶L}%ǯ\D@"d @ !WhAΧO^#o_drU30\DVLK'=j_My>/-Y_Oϟ3c؃ /}o|HNJ"3/O~n9tU-"y`u -1ءz^3Fr^ z"b Ǘײ#/kfCT˾GP>ydd;@d11_7&jJg6+&tԟ^t쾸<Dvݴt4O03_H YL涖,G<xI@ G};;D7l}W͙G>OYҐY0ef@zt|y8>z G=tmC7cr[q_䒾{YSo :9'>r} VC_7\jP:>c%O}MJCصOguJc(,[E؀e53ݮD=@#3*-RU/J)PD vY8ijO1b2kmM)0É=%@@WwJH @ cC "vEިy7y}7Ж(`1&iUbe^ac"})??Frg4#=B92ƿCB)L1:և+ c:s_ zHC[߽ K #a9r+q0yCDΕ>=5Îvc.'_Ba/}%E}z羍agC\v}E!{1%ul/v@؞nab,Mp)m%ƻ7w?O䫞~?%zMn~杞ioUH @ cD "xUw&ޤy ]EsIw7 &z`*0 UA:z=Y32YQ*iz.OW4JUyؽDg=vyJgUvY^.[+cDh 'xe[鉪^.Ut}y$ņ,}ZGJzuK` 8Y?$Y#Sgӗ1,_},")By0o$asv/P.t>\/C^>bK;HҘ\ Gٱe~p?q #cv羴Zǀt^)r=Ckt{ya(HGP(|_Kxxc哎vE"5ƞ=];nךX볥z;Ǖ0~ŸzSMhB6S@]H_~H獲L_f 4fIŭS{YX@ @ pD/꾚 =iK7 GN}ŭoKxS%c|_3?D&8?t9v/vH_[>v0R~Cp^ྚGqR ι\}qD/R]uv3ڞrt-Ǝv蹟Gv좸(jI?91 =ݐ|"nZBi=caυMV*}@g7v/}A{aޘԢ)7̮?|CWI.-mldbIF&uu= ̛sȥLu[TCRY}@ @ pFqFAzS7X^DyF\y['~mPHg;|THGh,Cmh'ԃt$M.~CpGם|7jN<_\/]|v${/QG?0E:Qs^|obG:T/@0I0*7b#W|,&w>]`0|q=fc75 Jж1-_ pvbBٛ8V[F%75H!怊'dD'@ cE "ze?C`0u掞k嫽_'o詭ўu{ڊ޶+Nrp^9;}> o63\i G cG'=$~+ۉmiJ\7ArqvHfL3^|6"50c @ JFa29.IϥڮbмiSes.1Mrm0Zܦۖn}XsᲔ1JiT#˯-3-魺rk^u^~~iCcNrr 9~u/K*Ն15Eu=-_i?% q[OA>{LM)KRy`|oDl @ 9к 7r<ռ\o4h_y>z }וO}C$s\v1{7,W1"p0tO}Kҫsm!?w}IG.W1dB]9塇vA/{֕y|@:|x> 0>lsa:@d"`ٯķմۖ|7TAJ$ J?^F`/@ @a_oļ7ia9A[ѫM]dWkY|9̛<>??ۖ|?$}ځ?IޔD=?#=Çd 8* =^ҿ̶󟟝 ٓDQ$%ùݏs}oIGo:u_z~?/΍bG~o63>~~X.xa>`/ l-{C@Lwg~Gr-ILJ7mL@?wsk:o5:{"ճۧ3pN@ F "}}vNoyaYM./S}goIدk k{|s@:v!=ϕcA,|ʥG{!s{ɧ<~i J=HG_Gg}8@,ʼyZ~6u:3oI:zY,S@3^x\?Md̑y96H  p{KGDhC-P\z//Xa>~" 4R*`jlUӟx*iAխE?յѩ`S᧞gt8˧SrYyǗ+qzAR7tC.7OtAR"IG9c}|Ϲ%Ǝ{kb*rGi{cj"$_RkˋCV0Db`@! jw @ E "zaZohؾsgJBɭ.y#m#ѷc~ҙ9v/vHוfG?\4OUL.?yMvE`T6ά>[EWt8s6z&G,f7ڋKgT;LRf3U.qjVͻ*/>|_~\o^rt)cV>C4}^^DZ-gi I=aر| {wYEԨ%@.7%L3.}ޠ ǁ@ "ý6[3ޔ]YK&29 7缩Q$Їs  ٶ|ɥ֋ySGۭu)Uy*{IѬo9o{+νܧ lCc6qF(fVO%̛r|D:'?/t Ǟu壇$ro{Neic/h?vH"'rc'CL9ͱ#`Aʿ;`!ʘ?_)#Otw @ pD@/[!d"77aV`$XFjI-?Z+j Y+"@?lz$yjKi@9e0m=NGR/Wy>%vrzHDDN( I|$vԿ뾸 2C=\O|=2"(#@ 80"p`-UG߈l_#aT[}+Yi;RmU7˛6X|R#}S]'%=G.ay:~9>{뛟Ӿzl"'@ 8Z"pv M[Bu?2 w ft?̂T}yc>?soj7'dže>=9F3eW@ 9ω-2-oމ GFf鋯3'捤o=|񳎁cR"IG; 5 y[f$ I:zHEWd?Hʡ\$!E?Hʡ\$!{8NjϾ1M  @ }xM=1_> `Ҷ>ѩ a5#]8 Ic|rBf]4ƣ`…G.7]?|@c>n4ʅ2>g=}>5ЮB3> @  <;1`ȩ>9s! ɠa0#׾ʧyWF}N.?V;GL;X**@C̽yWWByVg\ 9vbAF0"Dm6<(t>τS+=tG)yΟZ?,-Ɩ:<3R y:wI!(]HHy= ˒;}ySJ6FsTGї!g䣜2erǒ,sQXS^iG9e<)#lhJ `hᤫ xYη]{?dH^Zwx(Kxi_SOd&P*sC_?pk>EAᜓ,'.XVC}_J ܪkj߭Z<(um<.o'`iO $)5mi2gvI}Q(9'%=)O2s|_ws`=PZ=u_+9'?([$rjOyU@qhP;o{A8`rDmG6p#_Ğ+w( zU~68ϖ|k,J9Pr?d荷ēz(Ą]?˞7ϑi_ZcAy8IL_'=后 P>vU:zd_N旗D@D@D@ΆJ >'=n tmy:ɅQ-oA8:NXE<۷oM7d QC`Qx qN+ӣ$\AR9_a^z9OWy ?(W+_"b|NHG-KeK(r-V W竔ޑg5`5"JJlTL9ORd#$&{8n8X??"7Ci?h/?LONX+^(|Q0cQ4++q<^oGͿLL]})(<S>+?/'t%[?c<eo'(B[D:BUBD@D@D(cek[[?PJf 3y=  MU.wY=5,dP%䧼Ғtm۲Wy' =PO@? ̆ti؝'f4  6-6Iͥ &$J[E'Ԉ Q,JKJ%9 Ғ,sC*LV=؉F\d/,6$tkB|鸹Л8mS*atQޏ! Ș?|;(sia:sQPF(o 1Cx 8UUoa]qvR6$`Y1p:iui[/cS.((WTēOUD@D@D`'yvQP(V\;t}bDܴq1wߋQ"#_:64?ZdkYptQX7{a\^ڗ9y)OiG1`#0+n ě<)s3ɷ!&ʟX|S"~).:+" " A@}L`(Llb<Q`l0Rs$@5'`S U΋  'GpaĖE<ʟvN9'?˾>k@#>&m,0Y 1? l=ctBxQ(TGї 䣜2erRv<ݻ{BbILS>|uJpSIs Z JTq;OR.&`z}HW;es꿏Ns&l_p+fUÇ?X ,ϭz^Eь=Lm;4 ;dWM6[{~/(r~V"G-G<~ p3sfz <"E)~4Oǻ?&Y>fKD@D@D8P"p>Pm|(XT~=N+*W!V8R/v,MzyrbI,#1-}8fKD@D@D)9q3T@9~h}n~ڏm[a._ziQ(zx'KyulPQsD\y:5ISzo~ݕN%2sX±_1zcԤ:D@D@D@! @5B  ^GWO6GPį9?|}UK}n5[U15ft8Np,X<OQ~BۯA%TG@.$u`9l(^309\Pa?l6'IDATJoq.{(s:cܜN%Or<IOj8(^." " uؼj@+`oToK9=r/)nm[yiygsWs|Snp5j(0y @:Q$y "+" " "pT*'P*^oHg3;~0>>cZY→CCfg sW]f6.G/me3bM?cas>>*XƟߪ5VE@D@Dy!Q\A?բx\-}wD0No=ы5sq?,9~_/y^WE@D@^1y^nQ.h|?t6bLgLW6\.@?bUp,*X&t U+kB 4|M\`ׯpnן_Ol8ǺG $dE@D@D]vX+}0ƪדIic >^qx&xrv:C@/mgmQ(|SS{(4,yȟAwگ?~ɇ ϗoOz#UF@ڮHA`Q,`|}@dCO\ʣ|l(դ<_S5dGYJ[tՋ̮שwwɎ/]e|!U/Qw0\z{qOvi뾟.?R|"p( Pũi(es>FP@1y]L#Uu3IKn%Tu/l>"؏^~ _|Nse;.B|W竔z' 1(<]bYYǘ%#oW3]3~?{xϔ~yzB?v}S%D8(^." " urr G=l_P?{f2oļW({ù_}?~_v`@ VPjXB6!{fєGضگrCgޏ~?S>*"0yX$y:yYө<y 8R=(~?LU ^G#p?P*CDx8k$" " KQoCP(ug[{ L&8Vd!7ϿX s(^"ey{? );~9a_']ZO@3W" " "pr߀ł緙GQ?~Lg#pkO&rx6'oF#پQ]O}y-dl0>./ãsuy\ ^bar33ʣ|렫^p:YD@D@NF@?g]O B"Nc$Oq?(|Q1kPWWY=0<4K8=yN 8:y|+Dԓr˧.4c<;.ji)-+/r:}0li?M:TwI 8<yk@6yL@iY 3e=wz~W5y(R ^hŊ_*{~/=W(S pO} 0Os(_WVE}?PIۮ~~dŏu}G|Pxs{ e=yrbiY܉96?RCʭe;h^g~s([֫s0\UTM@/O][*ܬLf{Ĉw{bBbL|n_ ^&| KIcEՎ_m][YۿW1-"mtw" " "<[(!(;S BM枽B3NUWm\pX_)w9# @GQp *VD@D@j& @WVOvט$}xfd'[5Ufo<}t ?0!%Cd;+J9zf.gx’2)'SSB?c%n [RoD@D@D@$ xLm(}x|EM&kc; %e(~֎=J+u|~Oy[> Tz_~v!>iZMWVEKLo{mE>OipYP, MyΊw2G h(s:cY^{ǣ^/vcqE]M8} 'LJՍ˄a?‡xҹgΥmu+LD}T%@!I&ۓt}MZ!lo9sNgqY _wY_d6 έ9|9}V+E~Cq(cԻIv O]vO 2E1z,c<2xLe3s(A" "CP%&n)bw_=Kyn#T" "  @L;WbUV5ܿo?zMh?e4?lo??sxJ %:K9Q(OB7_R[b2{! 4ҍ.ƒp{=Pɻ9={ *+a(0_lTU" " "P/y6մ44M<$џ'IMn~mtﳵ =,o.AsJ6O`.7Xw7=KO0c^ʿHH%ь0 ;2iy ?@8)vԧ`0\UTM@/Oc_ 09?vOsMo퇝T.WkQOxW|<. yr%xyKI_7:{XO`/wyfxaߜ@y_eTKy3母#]# @׮#" " {`HJ Rx2X a(\<չr(4?i_$s8/&?}_ H"G# P"<\ R(S<i(٦ mjh`^/m`kUlO7=wQ*üuB%ݏ^4}G?rrd~AcQ>gA0=!~ͻl??ْ>c( TD@D@D@<ւVD`~Hfb{5=}/+LȍyeS =s<wgM?y@ _4HCQO@\m:6h.r8`Y_4Y!HѧzAۊ f `,(q_d{9/+"pHJ PQj" ]V?@?r眮*f{֦{ e/bY^pt"v=qݿZדp=X>F:o($OS߉EtKpsȜgq/CD@L@7@*+߾c簳am6͏<]g=>@U, ӌn]O蛼"w)ݛi&{>h}|.-U" " "P/y6jY5x "x0O.+/&O$7ߦ_gWc_7Iȃ }//bP(4ߦOY|0?4˖iJWWX-EA"I'[7y?I}Υk"UVBW6 _{+~lY+b'<egZ2" " X<5_2x!uow{d]mCS1K /h)?:sfy?fKv^%{<%J~.y}a^k.%VL@(\"pn8+@ h.`~|K˛op;Hio|Ħd@ԗ2ED`8Z," " k@G}:m:| ߛ:رcW%<ʧI/" # Ъ`<^L Tyzo+ލcw^ _2G=Fyԃjt<"x@"Tk{n6<M"4f ج n8UTE@.#@/+ 3i^!HRZ(# @.#" " `JJ#"B۰Ob~фu9'tY`ɒol$X 66}?m`?}ߘOM|ށ+DǜȂS[fL(54oLT~eO8Ј8d#absNo}t" " "p<(@D`UVonфm>v74!+n,gn=]ؗRXPHeyKYswd kMo~_eo?)R{icֿGs5>e@O]%G3֙,\]XenO x8$8$]-" " NRFjnSxΞSuׄ$aM2_4hns:9ef'/Q+0x,Hˊ ph*_D@D@*$ @EM&2wy%5&]oHon+R3(_ 0(`LK2r9jGw kND xl~e{؛!{G*'O ؿEySRTBO ɚ<p-@>@x\"pp*P5QD@*$Rg~RQKO@ v8 cp焷uP.nMqKzw<ݺE@0)k%r/-R3?`ސρ.x%C6(u]*FxU&80y XŋtJ1W5B^ˬ [y拝l7@~f>.ߋ !<g}n98+@ h.YM|4_rw4O6W_p<^FQzK:,ϵBX?"#D kG굋UUD@D@D<H" J4fȽ9+_4٢/@P-3@:> ^+s+Ho;J@^XuKD@D@" Ct'" 9q<.HScϏG3w77M(GZ>r|9xX={D" "p y`6{0f4 v/ >JT) ߒ0Ńv36i(9," " /$  *"Bsl]nd  ˒|mY:xos>8k@kh 2[Q? jJsf [//9'iQ~SIx~ϭ1a[>;GQz vE;2ܭi|]n*MD@D@Dv~>@ѣQ9-m,>y,}, =fCy5{m{|f>N踫l?ix>O@uǯm<]ש}\ԥZD@D@D@*!g%Q3D@D.G_ol>oE'Œm,&[?'OZQ/?x޼ { ktGv^Q hE'(%.KWS}h}I}>߼ˊǦyo6?t7>mNd·YIF,[pOL1@cٍO퇵'YaS ^pd0֏<Q Vkt>S("! |l8wvD; VA@7mPT" %Pz~oM/yg.0'@)[So1sx)-e< F+!ȷjޱ !+.s+ڔ)4)VD@D@:B;͎0Q7D@D`Ilz `#i.~ͥ7џv&YS)dy|n O噧 =}9Fa9PK77泰&?H\R>V)_q>?h #yC\SI~ϭec)ڬoS6ˀ~>l <l# 6* Cj@vC[!{ߔ2NK C{nP6?='a9_(>O,t<eZ" " ">/Y%8]Cs)`a"ɧ*T^)a߃g{}:)Yygg7vMwŇtQ*o*5<W"SB!@H  >S(" by5o(q;OHSSWl*ƾS=' q~ n+t0@+=x~X{%6YXFsbnbIVɅR3E@Ζه&ڑ:R=O}C֫+  . "iyV)41i=ٳߣ]@(v%$]qΈ X,F t/k9\%QD@D@Z&fŪ8LAm1ၽ mK1pS|? OM޶0ziM܄gAGڲQÒ" " " wy\@zgE~r~6V<]GD@D@@X<͂n SY).x_nΉ'=)'8?]XK+9'?Q>$秲 K{i?^)IO~ʣ|YǷ K{i?KK^ZW`OCcL{ǵE_Z=6=$}m yj2jw\"Ο5.>"(,ەЪ@) ~K,K{i?\o9'?呞~c ?XKsIO~#=~*KGO޲^Ch/?;Z4X*/ȞFL&pǵ"O̒σ}Y_bY '=]to" " "<<ڸtGX9)wXpN<OzN\w,|NenqN<כrN<ߓ []u~uÖ׏sGo i8c6]OF?YuMt[(ګmdkA{{&lM }ཌྷ _?Wt~L=!FYh9&Y]ޛ^N=xj[lfսvS6>3lwOېg?e;:HX7݁;RiW+w-m-tT9o n^Z?]neּ7|6kj?__>EkHIL6柬a<v_Oa& %9Ty6Y5l.*" " @iW EA{1y=ÄipN<]+~ݼt =pm/~+zwʟ?+ywRnO=l.WS<[R Ò˖.Q}(Oܱv'*e I>nIa?(:z>;FύOc0r+Q·8csGߜd6>-rTji=`T`ǶR4WhmG(y̮#'A YO7;W^_z^?C&BY=deG Ȋx h[{[QV$],5UD@D@"T@B٢Mi'{ϚiNΫ8#|%bR߿?$3m_T'ks3=lb ˗c]#1ϓqߨet'[/ǟbrHh"" " nIa K*(sY@9[)~C8~ xa~/Ξ~PVLk3e~~<ΫD zmԞ3Hw9|6Ԕ9>¿ K|e=ʤ<ʧF8}GE@D@D@H;ƍQi gcQwt"Z" " {AGJ.'A8E^y.5ixEOT^)xnHkNAJg6 RtcO)Klu̾ ys#@_~[z=)" " "-qxHW*qK-TD@D`O̖=n txH.>z]~ vlL>=f6gS='+6&SN,>˗/Y~̲ ?R5w__᰸}ͽ?)x܇,?4b K X=[ڗf^~#Yڼ>ok+H>a[¶ٗvV tܑqSst_J'" `.碁y[$;)o {n?%0^/(OɘՏ-=x'u06? .%HsPA z|5OS26f>a=(y~&opJ)TG)ZD@D@H@7] ^Ϻ]3/CfrT̷ol<Ue.Mɯg0CWve0L _0Ka0]0 g0,[3 it32N  0\gklpqm`:-'#!AoK?;" Ñ {ujPEAA@@Koö;Ñ'dWNB K?LJnbXG @?Æ̆+ʽzneU+!A?Æ+޺{UFAA@@Ko?ÁÇ+幧eWNB K?Ï+蹧j]SB??Î+꽭j]SB??Í+ɼj]SB??Í+½j]SB??ͽj]SB??Íɼj]SB??Î꽭j]SB??ÁÏ 蹧j]SB??Ƹ 蹧j]SB??ب꽭j]SB??ƨW909Tɼj]SB??Ʒ9 9½j]SB??ô0  0½j]SC B?ô0  0ɼj]TF"K?ô0  0꽭j]VN:2Hl?ô0  0蹧j]VQC>Hl?ô0  0꽭j]VN:22 ..  .跥j]SB??P$ *~~*  *~跥j]SB??C (zz(  (z跥j]SB??B &uu&  (z跥j]SB??N#kk# *~跥j]SB??3PddP .跥j]SB??րFXXF /跥j]SB???NN? /跥j]SB??2>>2 .跥j]SB?? *~跥j]SB?? (z跥j]SB?? &u跥j]SB??#k跥j]SB??Pds跥j]SB??FXg跥j]SB???N]~跥j]SB??2>Mq跥j]SB??$P跥j]SB??C跥j]SB??B洡j]SB??N㪕j]SB??3ڏsnxj]SB??ׅgbnj]SB??~]Wej]SB??qMFU{j]SB??P$+Uejnxj]SB??C GX]bnj]SB??B@NSWej]SB??N5?BFU{j]SB??3 +Uejnxj]SB??ր GX]bnj]SB??@NSWeh\SB??5?BFU{e[SB?? +Uejif\YSB?? GX]\YXSB??@NSUVXSB??5?BCHRWSB?? 'GTSB?? CSSB??@NN?<<5?>2 00  0<<0      *474  )|3  3ÁÞ6 6ϨA  3ҲaA74 -γ3 *ЁÞ6   +xϨA  0<=5 0dxҲaA74  0bJ@<0,+-46?Wγ3 <{]NA 4ЁÞ6 #?؉k\M$ +xϨA  3@#?ࠈ|pPD=5 0dxҲaA74  $1303#?bJ@<0,+-46?Wγ3  $-0+#?{]NA 4ЁÞ6  $.10/"?؉k\M$ +xϨA    /7::0?ࠈ|pPD=5 0dxҲaA74  479@RYZU3?bJ@<0,+-46?Wγ3  36?{]NA 4ЁÞ6  6ÁŠ7?؉k\M$ +xϨA AυϨA  ?ࠈ|pPD=5 0dxҲaA7Aa҅ҲaA74 ?bJ@<0,+-46?Wγمγ3 ?{]NA 4ЁۅЁÞ6 ?؉k\M$ +xےϨA ?ࠈ|pPD=5 0dxۑҲaA4* ?bJ@<0,+-46?Wڑγ|) ?{]NA 4ّÜ3 <ԅgXH  *~ֆۊϨA  0 ΌsfZ8,&  *~ͅۉҲaA74 0 <Ò+unb@43>\gklpqm`:-'#0dxŦS4*' 3Ñ {ujPE@<0,3Mxe&  0Ñ'dWNA2x)  0ÅnbXG +x~*  3Å+zneU+0dx~* <ÆT90+7N{UF@<0,2J~* ?ÁÇ9 +1}eWNA2~* ?Ï0 + (zj]SB *~~* <Î0 + *~j]SB *~~*  3Í0 + .j]SB *~~*  0Í0 + /j]SB *~~*  0Í0  /j]SB *~~*  3Í0  .j]SB *~~* <Î0  *~j]SB *~~* ?ÁÏ0 (zj]SB *~~* ?Ƹ0 (zj]SB *~~* <ب0  *~j]SB *~~*  3ƨW909T0  .j]SB *~~*  09 90  /j]SB *~~*  00  0/  /j]SB *~~*  00  0.  .j]SB *~~*  00  0~*  *~j]SB *~~*  00  0z(  (zj]SB *~~*  00  0z(  (zj]SB *~~*  00  0~*  *~j]SB *~~*  00  0.  .j]SB *~~*  00  0/  /j]SB *~~*  //  0/  /j]SB *~~*  ..  0.  .j]SB *~~*  *~~*  0~*  *~j]SB *~~*  (zz(  0z(  (zj]SB *~~*  &uu&  0z(  (xj]SB *~~* #kk# 0~*  (xj]SB *~~* PddP 0.  (xj]SB *~~* FXXF 0/  (xj]SB *~~* ?NN? //  (xj]SB *~~* 2>>2 ..  (xj]SB *~~*  *~~*  (xj]SB *~~*  (zz(  (xj]SB *~~*  &uz(  (xj]SB *~~* #k~*  (xj]SB *~~* Pdlpz~.  (xj]SB *~~* FX`fw}/  (xj]SB *~~* ?NV_t}/  (xj]SB *~~* 2>FRp|.  (xj]SB *~~* 1ey~*  (xj]SB *~~*  $axz(  (xj]SB *~~*  "axu&  (xj]SB *~~*  'fyk# (xj]SB *~~* Jv~~zpldP (xj]SB *~~* Dm~}wf`XF (xj]SB *~~* }t_VN? (xj]SB *~~* |pRF>2 (xj]SB *~~* ye1 (xj]SB *~~* xa$  (xj]SB *~~* xa"  &uj]SB *~~* yf' #kj]SB *~~* ~vJPdnxj]SB *~~* ~mDFXbnj]SB *~~* ?NWej]SB *~~* 2>FU{j]SB *~~* +Uejnxj]SB *~~*  GX]bnj]SB *~~* @NSWej]SB *~~* 5?BFU{j]SB *~~*  +Uejnxj]SB *~~*  GX]bnj]SB *~~* @NSWeh\SB *~~* 5?BFU{e[SB *~~*  +Uejif\YSB *~~*  GX]\YXSB *~~* ww@NSUVXSB *~~* 5?BCHRWSB *~~*  'GTSB *~~*  CSSB *~~* @NN? 'ww' 5?>2_ww_  ((      (*'_w~xe&  'wx) ({2   %oJ2*' Qfp{~xe& FXbpx)    @NWf2  0<=5 !7?EQo{J2*' 0bJ?7!%).;[hp{~xe& <{]N@  HXbpx) #?؉k\M$  @NWf2  3@#?ࠈ|pPD=5 !7?EQo{J2*' $1303#?bJ?7!%).;[hp{~xe&  $-0+#?{]N@  HXbpx)  $.10/"?؉k\M$  @NWf2    ,477,?ࠈ|pPD=5 !7?EQo{J2*''*,3ELNI,?bJ?7!%).;[hp{~xe&  &ex~o* ?{]N@  HXbpx)  )xz* ?؉k\M$  @NWf2 22  ?ࠈ|pPD=5 !7?EQo{J2*2JJ2*'?bJ?7!%).;[hp{~~xe& ?{]N@  HXbpx) ?؉k\M$  @NWf2 ?ࠈ|pPD=5 !7?EQo{J2( ?bJ?7!%).;[hp{w_?{]N@  HXbpw' <ԅgXH BS]j2  0 ΍tg[9-' BS\gJ2*'0]hlmpqm`;.($!7?GWt6  3Ñ+~xmPE?7!,VgjaMD?5 0Ñ'eWN@ GX]ZVSN@ 0ÅobXG @NSUVXSB 3Å+{ofV+!7?CHRWSB<ÆT90+7N}VG?7!'GTSB?ÁÇ9 +2fWN@ CSSB?Ï0 + )}k]SBBSSB<Î0 + *k]SBBSSB 3Í0 + .k]SBBSSB 0Í0 + /k]SBBSSB 0Í0  /k]SBBSSB 3Í0  .k]SBBSSB<Î0  *k]SBBSSB ?ÁÏ0 )}k]SBBSSB?ƇÏ0 )}k]SBBSSB<҆Î0  *k]SBBSSB 3Í0  .k]SBBSSB 0Í0  /k]SBBSSB 0É/  /k]SBBSSB 0É.  .k]SBBSSB 0É*  *k]SBBSSB 0É})  )}k]SBBSSB 0É})  )}k]SBBSSB 0É*  *k]SBBSSB 0É.  .k]SBBSSB 0É/  /k]SBBSSB /ÿ/  /k]SBBSSB .ý.  .k]SBBSSB *÷T907N*  *k]SBBSSB )}ô9 2})  )}k]SBBSSB 'xô0  )}})  ){k]SBBSSB $mô0  **  ){k]SBBSSBQetô0  ..  ){k]SBBSSBFXgô0  //  ){k]SBBSSB?N]~³/  //  ){k]SBBSSB2>Mqʽ.  ..  ){k]SBBSSB$P*  **  ){k]SBBSSBC鼫})  )}})  ){k]SBBSSBB緥x'  )}})  ){k]SBBSSBN䬗m$  **  ){k]SBBSSB3ڐteQ ..  ){k]SBBSSBׅgXF //  ){k]SBBSSB~]N? //  ){k]SBBSSBqM>2 ..  ){k]SBBSSBP$ **  ){k]SBBSSBC )}})  ){k]SBBSSBB 'xx'  ){k]SBBSSBN $mm$  ){k]SBBSSB3QeeQ ){k]SBBSSBրFXXF ){k]SBBSSB?NN? ){k]SBBSSB2>>2 ){k]SBBSSB ){k]SBBSSB ){k]SBBSSB 'xk]SBBSSB $mk]SBBSSBQeozk]SBBSSBFXbok]SBBSSB?NWfk]SBBSSB2>GV}k]SBBSSB+Vfkozk]SBBSSB GX]bok]SBBSSB@NSWfk]SBBSSB5?BGV}k]SBBSSB +Vfkozk]SBBSSB GX]bok]SBBSSB@NSWfi\SBBSSB5?BGV}f\SBBSSB +Vfkjg\YSBBSSB GX]\YXSBBSSB@NSUVXSBBSSB5?BCHRWSBBSSB 'GTSBBSSB CSSBBSSB@NN??NN?5?>22>>2  l8mkname icons8mk^RDK[e}Z=@_SؾεεεݫεݩԺ~sdOO@it8mk@?????K ?oK????<0?0 ?< KK 0Ŧ.q ރO${KKD$ /)\@7->HH9uoF&/)h ZIENDB`qdirstat-1.4/src/icons/refresh.png000066400000000000000000000030201311502036700172500ustar00rootroot00000000000000PNG  IHDRw=IDATxb`1"qGe```#Vb">V^+t-".^1iPXb''I ?3 ;|t%' ãvms>3_ eBh83ÿ gxÁ{/8ef3bhqFF102 expñ{<%bAw9RpA ?F4? gx;<1BOH[$K@GF^p'~2*20011<aM^b``x+BK>BAAVZFpС/n8ÍKVkJ2߸} WBYBZ/#ÿ ~c8uȳWynW}si g```BKDO L |bxwOϬa``x 1BK@?~3<~[d```~u߇13000B ?~gx7L \<_2@'P{GXr_V ^T.TBI~|xsGYظx\l*jS d8|w p B.wy8Խ,= |2yFԅ~P``bae`bae 0B/?o͎S៬Ǘ~6B|K`Kz h.#÷wx^EB.*x yg kr 102020;#X8xy88yYX301|}W.Oih1Bo_>zg2,&l L ̜ B L̬ ,,?#3ό _nҦOna`` 3B/w,`f_ń[/P cb󍣿8_osz f10000B/MT]9Ą89XXXaa۟ {ǖ300g0Z\3@4'U(##$##3 #ӷ?{է.~e |0t!  " &Fū[-=DdT$:2_ [eB}5g I$B200fHb{IIENDB`qdirstat-1.4/src/icons/remove.png000066400000000000000000000024141311502036700171150ustar00rootroot00000000000000PNG  IHDRw=sRGB pHYs  tIME  'IDATHǵV]hW?I4f1&KM6C)*URH)K*҂H`PZ%jZjEXͦ1F$콧3;+؊Ё˝|ߙsh4ZhhQE%kjSܹsy׿]24a+Bs Ιj ƵH{{,ٳwOv}ouWH̀,"B u!|BN='ӧ[>N ’@WDȯ~ٵd3?Gwf^׀r(lW\8ED*EhL'oE\ 1\m,`7nYt Zn;|!5dW&B; i&T+2u:ujiյdW6 s"upkB.AooW-%x(Y0@41y0_ɻ$*@`,y:`ŝ3N—A'nCno?x_`0Psd\e;`10ۡIḰYf]EEO\kB , '|X*ːp %2 얒A+D$)ӆUKshUMyH@L7ERAA'v T/,b]׹X,l޺zO/bAj*Xa`L !\XovAnliET媫8+$X&@se+u-f s`NMgVi?Pd ^.WkEz]y$m1JֺJ u]:͏%b$ش =K%.76XuG<T̒$1F FǛyoO0@.5#7vqfUO yf67%b`l؉{M[n O<8 #v-"^1/6{jEXp|!1Vc+η1Ҵr|,F{v/t7jחZm.d=XAfrukĴa|*'t\#G\/~}6m{y,biY˗~9vX @*R`PM&f<7dg10khwIENDB`qdirstat-1.4/src/icons/stop.png000066400000000000000000000026761311502036700166170ustar00rootroot00000000000000PNG  IHDRw=sRGB pHYs  tIME  b.PIDATHǍmh[%HdŊdɎc{jNF- 82 Д҅%ca[ 6K(Hi5P0Mz㥶g)QZۉlW/^jwY眫?)~\.6t:uiR.54i_~9/9ڽ._r?wD f_LJrghV6wc&1NOz,bk. ǎ!RMM0Np±bvttb`XDO 52],~S+Jr"?Lu/|'nRLA>HxٷOMkگϟt{4=nܺe&&B <4 c>@NM-0}-KV >tPs7"_|}o=W>?tu=і4^U(^c7^?}abb*Wo͎ss6]gu\ ,+ł@_}/<9IENDB`qdirstat-1.4/src/icons/terminal.png000066400000000000000000000015361311502036700174370ustar00rootroot00000000000000PNG  IHDRw=sBIT|dIDATHՔkGǿ3ogtAEҁ '+A,aARJ#JiT 'S%&u)8lLJ#d$[1nBeng g{Ɩ$20~?}w/fggWƢ)BHK=vmmq3!zv}511><FFFqV4+\&c JJN"A:`IQȲ 9p_Y#E`1&U%!dϛ Q{EXEIloov˾#zTi9ZbqqιTMy{g"cccB>yc0`0( E+.Yjuպl6fM}B5B11C]UeD$FIENDB`qdirstat-1.4/src/icons/trashcan.png000066400000000000000000000033271311502036700174270ustar00rootroot00000000000000PNG  IHDRw=IDATxb`1b$<͛[ϟ?֭[ſ޽{m3#hNNׯ_{W^?ť9^^^7mSI]*ëWN>p5_~30$0<OG{*E%""",3OuرT1 @Q:j A9tP0~kߏV:(O!ňn1!xRLxs_i^|bBpqqhg``×/>~{Ǐ3}! ?3߿,-:.'' bA I}ի  ?d͛7޾}OF&F3033AZE7w$ ]vf&B̧/`053`7ӧO޾}```'_ ߾}g`afa`bab`fbfwZXZX^vmLG2N()I$";w^L!@ EҠ8`6`dSc5IH $@63;BrFf[˗G3zWwY3ea$#3 #3 F10/?l_˗0s[ׯoگj'_e`da`䃘#_ϯ ߾2Wbx3B??>%_~``b`5 f_;00\jH:`b`ǯ?T1@@ @ѿ1 ̨:N$ !&H|_#s(+qnzTC!7bAχ?3<B܋nf//#Ï wo L `#z.?dVs301pS_O_p Y92IENDB`qdirstat-1.4/src/icons/tree-medium/000077500000000000000000000000001311502036700173265ustar00rootroot00000000000000qdirstat-1.4/src/icons/tree-medium/block-device.png000066400000000000000000000015331311502036700223650ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8=o]Eݓk_'lt X* @E$>jJ~e HDH$H*N}ڝ8ۢ@Lq><;3 SnE/^}/8w8pރ!fFtK|;`.||ɕ&BQ?)U]svmmހ@TUd2ۛߠb铯sʵW[[[K8FYe{/)%*EQݻC>P *94`EIENDB`qdirstat-1.4/src/icons/tree-medium/char-device.png000066400000000000000000000017261311502036700222140ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8oTU?;sge0XAC QLJ;VNC1Ġ񑐸`A b+C**D%4}PJw~b?V>w۷'o]Y^^>?~a`i dbg;w&3 Gy#G72BH HF`6T݇fV2g>=y_s3տdٽ~7|Г=q-;Vq/O'a9,H5lSnJIENDB`qdirstat-1.4/src/icons/tree-medium/dir.png000066400000000000000000000014201311502036700206070ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8k$UUu&ú IGGxпC2G{}`"")aCn6f2ݯ>ә z,(=z3lfKb2|xxg*jX,~?>>Ύ4*K"t|3L^fRԾe\`k0kh3X|{{#H""2wyyvwwRI~0?z#o g(khj"8{ 4Mb>NIw}IơNdF3 3G,uZc0dl`"e xS ;9@IZ8a, jIrK _Bf kHT9UC֒s!epwzPY B)i#"M  Rnq/݅d\@42\Bi3<F_?N2f 30`ZXB7} s'PEIENDB`qdirstat-1.4/src/icons/tree-medium/dot-entry.png000066400000000000000000000016421311502036700217640ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dYIDAT8͔n\EsfUv*VABT=y}cch}}8=9kcwkA,˯^7σ֢̬w?>8F.\Hr[U߾}O#ŋo?=U C exY__-pU`2!Lߧ 뚔sVU]Z 1LPǓhK, !y9gʲ3ciiNs&-r,Qvfpc$LΙ_G[ *0nJxUw8\Oir?Lfrs"+ * &V?ƿÏbA O ٔR2FHM<qDɨ?YĦYqРM+;?%m,eT8"6pGȖA!,1jDB04d4dBH8 )!h16t"*PS*"DFC@1 لp*3EaXSTQUD0pIg̝N6"?vڵkA~PqT*EEn8N͛8a4/nݷ>.ٹIENDB`qdirstat-1.4/src/icons/tree-medium/excluded.png000066400000000000000000000026401311502036700216330ustar00rootroot00000000000000PNG  IHDRĴl;gIDATxbd898XuEDXYe~ǏW}G_~ ~b"d!)i%/_f% ?8fǏߏ?yӧ><B79^C#DKCXBB۟? ~d`c33##ÇNyfڙ3 B69@^>l*??a/33o߾7?7ܹ0bT5VW`3# ᘑϏ ̜BBNzz03̖,-] /Wc` 322AY$bb```egq L20/|fdd?-!4λ @>!Fqv! `% 8[JtS+-g,TUDoE J[˫qt1 E~&A5N6NtHWpd;J 3ŗ?>!gZO@/lұ @/&9 !HZ7pRًowgpAIR+wtW  \lӱ 0VL-& VR\׷E1yDUi!6ba``0 ?3z%0_66ba``s޿#&10A%h&(9 2C?^^``` bb``WJW|OX08 ff```g``x('~bb``}ʕ vpqp#!n  wܹ bb|YYT"/l`Bd330012234|֭E 41 Чwp O<  ACBzWx n׺~M3-eBV&%;9ȏ(uZTpB\Uqa>U/d`TLN7;FF% Z PbD3A]UI?{YXdiNNo.ʾXybՅ k_zu1WhBOf``fאёQcadffflj;_WB!]m{{{rLh@z ޵i֫476j(< n5_?[[[[!B>%`G|v[(Ҷܶb>+oz333C} #C$n)S雽 Ao*ꝰtΠ1rgg盵Ib[~YoܜsYyccr,:Py yh"BIF"IENDB`qdirstat-1.4/src/icons/tree-medium/locked.png000066400000000000000000000014601311502036700212760ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8MkdEsIQȈ8 W0Y{Ez!Q0F A'qbnӝUEdzۙ Xp:UOvvvt8>c|{/'UN''%[#I|/T(e}ouuuV!"~p8<<ιrѸieeǢZl63Nh4T*]Pէ{ng.mWH:Cz?X[[>z3MZʩόt<qNx+Ce3#M9 cFS,^KSV =pޖǟw~9o#ÿhnOOߓ#JZ 壟-Q}k_<ŚǶ\h`qjRwlB_+z|eL>2X\AdZY,bDCPDHTq6&qĄh`V\S!7PAEPlU>-L{hs.̌Xr!f`pW`6/Fa݈ n} $ D#R$@bmh<-ڌ:)ڤ7]oɻlߖn:1d,8TB8,am~}i @2D6'3s& < @5TIENDB`qdirstat-1.4/src/icons/tree-medium/mount-point.png000066400000000000000000000020261311502036700223250ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8nHm;6}$!%+Y{ic^)B RV ҦݐUYhV,*: nɓ'*˲J)!m}9k-]4M}ttpU%hq?`{O!f^s||߷b4=\,­%Br*ZK]L&$! >˲cnyJ0xH)YVL%I#9 7eQ3!yEQc(m999aww!Dk=dvq(ʲlb<3HӔ$Il6㽧"c(9GS@64[eYZ3Zk(GeY.˲7`=޾}SsDQK7oT (!u])} R?١k?~L㽽$>}Zhi0opnaZ={6 B}qqA$Cu]^l6l6|B]{O$\\\ PӠbjg 'I%ZqR~k׽{{ʲׯA{Rk1]!DJIuE1|1Esшއ}ཧm[̆c0 {ϝ;wfh6 `20n۶ n麎$I껞hЀ43ٌKf1eYRU׼{)%J)q<1f+puAEQ1m۲Z8==E)J=_f>O4My}-ڐsrɧO*e>~X` 5L {{{텦ih(0;6l1J 5*[UK& ,Zo jXVafc\Z;x<]Wߦi@[_4 e,}\ӟIENDB`qdirstat-1.4/src/icons/tree-medium/special.png000066400000000000000000000016461311502036700214630ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|d]IDAT8KcWs?+kL#6JiuK).*.f´ 7.pF(UVEvb tAlB8&w*x3ۅL1/폇=/\.?Epc}aA`B@4!<σ80@)899 OA`Y( c`j^ꑑ00Pb ÀX__,V(4M[۶dN3<(^@aJ)$IАP(B,&R:xǷ(c%Lxx^y^ow[[[mh8iWWW( q,y@)n8H|N>;;+J cށ7GCwl6J~y~agا.]Vߪmҷ&x,Lf%!9_b)aG?5H$+n_⍍ bx"uR aȹ\۳缾#H,LbYbTfgg |W/Mo:CqBjkYW,n~hDmS8XE"FO:+`/(=DMn~U' PX p'j0ڊlnzbɖΈprDED )Q70RSCOtwOU`d'kP8'pd^"+VIgf<% t~.|ɌzL45Ν>LL&. )|** KYh׀5Ii =ƎV,@@0% z(~-j'cZP{?cۖK ay'?\l 771LeeeLfdQ+8o.Y==`~⺤O ZS% :TNX*&ěp3@ϧ%{|s(WfmiK\UTD'OθSw TSC:d@)drϬe˚:uJL}}q.FKю=nO̫n it,덍8wn4 ֗;ocD"5ڳb rǪ=o8p 2DPJMLR$ t|޲ukMp>mm[ulJ1 05q\36}rckau$IENDB`qdirstat-1.4/src/icons/tree-medium/symlink.png000066400000000000000000000012641311502036700215250ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dkIDAT8kAݹ\4B"E4b&.Vr$((&`&<gP#"ޝf~Zl$A^bg^8"]r*XJYV3Rn7kr$[Nj:3?? }:bqq$=p\.ۧ7nT)J(B9u<g&f]ot8NzU+ (P*&V8@@ Xki/ژ] !ɊX{Ss$Fk1di#ƣ&dzw*XkCvx'/S!a SSS_z[V@!j-Z,}_KKK"G4[POܭIENDB`qdirstat-1.4/src/icons/tree-medium/unreadable-dir.png000066400000000000000000000017101311502036700227110ustar00rootroot00000000000000PNG  IHDRĴl;sBIT|dIDAT8ϋ\E?U]ofWeHD AIу+ۻw$j]ů]|ӧ__~}0|7 hxշInܸqayy\XXm1FG'A Я}hgo߾SsssoRouޙ3g Omݙ\<X1\r |f#,*Ifimwqa׮i :[[}!ūfs}'>sP%KR-0)A܏5HY yyDrG=lIl3vNHx*A;*BrA7z[J384 fF*a$7@<3_-bv-f@l w!iH8ItgCY vwϧ` wv'F5Q)ꐵJ@M)8>VE&A  \'+\9Bok {He#2f11hHc!'ͽTɢ(" ÐŢ(czOϸ< p4t/cEpIENDB`qdirstat-1.4/src/icons/tree-small/000077500000000000000000000000001311502036700171565ustar00rootroot00000000000000qdirstat-1.4/src/icons/tree-small/block-device.png000066400000000000000000000010641311502036700222140ustar00rootroot00000000000000PNG  IHDRasBIT|dIDAT8jASݙqN|HĕhJ6>"t/k"Ag23]=]UEL#n,( K@\|M`_IS2Y'C&P >E{2D3hܯ.l!1ձ+cJH?V©uHe@{rU_VJ{m#cV), ؎nu';^GWg3Ǥk kMn?yu}}^DGϲ$J;H "wm>, ^@rFz#Bo?`MCj';>,2'Gh Gҭ޳xf6Zf$yryn$tc%e]%a(^hv$ 34c JZl`&%A O(r2ɜ&WvSRe!3#T*R*uжNEj@GgyX b'B$0(2I ATAuӏjo+++k7 IJ@IENDB`qdirstat-1.4/src/icons/tree-small/dot-entry.png000066400000000000000000000013021311502036700216050ustar00rootroot00000000000000PNG  IHDRasRGBbKGD pHYs  tIME  'BIDAT8˥jTQ}ιQb$@ Icag o>E] y II@mb & {3{Ao!~˵^KGNcdkk2UYVU;;;tee'X]]ԙ "W}& eYcdvv^]aaa&nmmmzqqqϊ mO))%sTUܓV<p" +9Fܤ/vs&DAU766zNUUboE{794 UUMCۋM`kG=V!1*S!sLMMǪBz{YdBzSU1b_=ce1<==K&cGC֌Ɵ\; KtTi/P^@DДrJQP Z,1bI:\ XF؄ucb3b4Ĭ rp`\ėG" QQ2(x<tLo`I4$m@3FI'?JY۷494!:PTIENDB`qdirstat-1.4/src/icons/tree-small/excluded.png000066400000000000000000000013111311502036700214550ustar00rootroot00000000000000PNG  IHDRasBIT|dIDAT8uKTQ{g񎣋 f" @@6?u2?U hעtl}HQ;;2ip^8󼟂:ݮښkVKƷ/A \円٫ BkL w/kEչ֖^;qO㉰RcXƠ}z}' %Y g271&")%J @h'7RKUHvn;ƴG!Rk(c(Ij =8+"6r\&!}L{)K%+< ,@et,x96m!!Ѐ!hS $$T ::;q:XPH `MP0zmM쌏 *VFZ7.aEt:ò`i_kk).my'RJ]*^RzxhZ`0R\/۶nI)w m# mq>Z^5_^p88v>Rj#/ju7MhGцNŢtZ%fwqO9iyz';|t|ʾ޽5yLdlg{DIhuy|"BM%2*_H d>ɼI0M@JpQ*q\ϭo0`7aLX@4@Ӕ!0 i!MZ #nbLP '+v`P Ŀ0 0of64L`ɱ}̦KTbzYwth9XHBZA~='޻ߎ0r)vIENDB`qdirstat-1.4/src/icons/tree-small/mount-point.png000066400000000000000000000012511311502036700221540ustar00rootroot00000000000000PNG  IHDRasBIT|d`IDAT8MN#I2 ՅmhhVxgp50ܡ ^"`YрȬ̜ ^NlߋPx!󹼿s2Ȣ(R!bhۖbr:Nr~~NJ ! D۶YQ5^f_y6)˒~(~,zywRZ1c WWWU'0 ~OQc`@)֚`SZ;nhquK)%~kFxZc$#B9;;{_H@(ƫՊ< !g4 MӰӶ-yZ0ƌ{wZS%J1 5(hc女~ mPR!@eyrm.*>>>!z6ٶm7Md2NfC1/777VsNүzMs @k1,3qww7֏Y4n .z~Cc%89~-`,KBV+7w }@.SĈoIENDB`qdirstat-1.4/src/icons/tree-small/special.png000066400000000000000000000012021311502036700212770ustar00rootroot00000000000000PNG  IHDRasBIT|d9IDAT8Oaǿhsm^ZD&$Be` N.5Kp0#24&XфE ڸvE(GXH[6zWu0ֈRx|_]R L>UB1)*B!9| f!RR\.4 q 1E,..²,I @$A2D4A8=]J@AU }עx+wZXX@oooxhh(W6khT9<GFF ̷Wpι$]j6`nn===l6jƝ+IiwqKm+kk7tl3BheY8>>mܻs{8tT$4D޲ 0@QNɫշZL&CdYUU58B*---=*Xz^Gqυ |i(5M{r{{+ 룦iNTgvhZ>l6/ 'X>tl,7ܱ%(R iXv?:_'l= K  t:WY^ e޴yKDxK$](͉˺8m; c>+/s@\FOo'}*U&qjUOD؛JM(wZ6iY d2Z(R>7G$d`dߋETH]!ꔻ@%#u0]o"mzq1?Ox2E€YJq)<0M+WxtH1FHMCCuh)~fWFFQgqf0Dz:'á!^8sf8h6yqzÄJ!;Wݵ6[I:ES),0]ux6O><~Q2m صV q/. >Mo;vMV#7mDRe4bz][cTΞEI7O&i;_.SF'7HzxOOnKn?ЀDZIst\>߱\H`,дXmqLz/\ox{oD_'FCJ'&rGnzeߚ%IENDB`qdirstat-1.4/src/icons/tree-small/symlink.png000066400000000000000000000007221311502036700213530ustar00rootroot00000000000000PNG  IHDRasBIT|dIDAT8nA3Y[t" iQ!4)A/(h !HQDEuݽ[(Dg)2jgoeDg tu9p e;ަi,βt:/`9M֚VPMR[XcQ?~Կrۨ'R = e(<,E/l}jq]}}/)*!^1hm%fshm0gmX^nD}!ac; 8~쯏7ܲIENDB`qdirstat-1.4/src/icons/tree-small/unreadable-dir.png000066400000000000000000000012361311502036700225440ustar00rootroot00000000000000PNG  IHDRasBIT|dUIDAT8œkWydي$0>a )LH"EʐM44Kg0ƸM9lP &)buNFΖN=}3.$aef>~o df;KKKYj9>|F^[[s^Drkb ef~?dsssCUKU%z_Q+3@U)˒!|SESWU;b!e)b}maMD Chk; "q&\FhI&;͌k$/N-:q| ssl8 ̠}F$Í01!5 E\5v:.sMzXqBkx$Od! CcDݢ;{ O< M򆢈&9?V8S E0 _UU,4|DA,R "Lۥ_^^_\\\,bN>D]߾ NN eٺ`:vMW^v<\ѩnt;plC8WHnIENDB`qdirstat-1.4/src/icons/window-close.png000066400000000000000000000022011311502036700202240ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  tIME !1IDATHǽ]UU{s8xgLf0}hHeeF>HYa(>eCAKQ`R}h8(b3Cuνs{p',kk _a޷(U,qXG&NcI֫w{ ᑱb)2ӊLF)E6)(`8vF0ѽ43ҕx퉃_~~a"|xLv~Tvݻ'صmZճm3-\ z>}eeC`7 .̠Rgil \|u nD_%WR VdP]R)iUXKV K`RgSȦ  J$tߚESR +6cЖCML5ˆ;C#l5:/O 8hl"`x<-J:H4^~-D\i nMR |oJHd 2`&.QqH]趇R\;Kg0MmEQQ1-ة>mLSw9Bg'[m8cg?@+0[Z(: wy;pN kKC܏S*ZO~8~sH08NJvtU#^ sW2w4C͒s3\| 4б~l0 ҈]T((z[`n힩R[upj4Ps(( #c)p0A$Jbn1--GޥKZԊS R_/cXuFdd3:I5MG:}淪McL321It>'Tu̷RȚ<#;>v(G7'u >wCϟ#<IENDB`qdirstat-1.4/src/icons/zoom-best-fit.png000066400000000000000000000025011311502036700203140ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  tIME B3IDATHՔoLwǟӻW  ft&cXfKb^%[N/BNj8_27_l( bdY!(Nۅ=׻qe{ۛ}|aa^dz θ4M0N\&y; ^Npҥ^u .-@UVi&8S\.w6 /$|[}}}à3?֔$'$X0tsSl)d|ׂLNN`(ZN-_0 GU =6@Co65Vr2fymuu5nնr.: o*bQ>|EK"r|8l FFFϮzOfH](DGuQO@*T*NWF}Je=u]_L+@zdG{Fj"p?a>C_>r2R#LtXdYV|_;^-АJ䗥R˲U188xnԚYyXj&, P>hkk٬$yEwY-Xv NUwp 8&LOO'''|9h4 ,fQ(EQ1 MBt: pwjjW,annnh4bYᶂa``0l6 > (:òOh%I^]Hyz{{t{X,҂ill$Fd2 n$IIRJTy< Vx8NknnH$G q=EQ"reu9.`IENDB`qdirstat-1.4/src/icons/zoom-in.png000066400000000000000000000024701311502036700172120ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  tIME  IDATH]lSe=g[;t]k#vCllm:c"D#a^ADƅ&B2 A&8b' Cc;= No_?yy<$<l2hG,v\L&S'MӍ$L.'NwW1h* P(t>N :uP ݹ+r&mm*4-h=^i5H$2  y~Ɔ3D=-6 !TjT*%K+__ ?h'#T*t0t:X[  ~džw2)m2w}.CQԑ6x;<gT%a -*VS?L3o8T̫rU)v[KBh9k4n?EQ"zk5I[M,XUʄ@yyI+/Ƶh!$ge`Xv@zq\EQPRj2]}&h_{Zm͹c'8=_Iq:@q !5.HADo**bDѬ !1j[Y+lz|r-Jekex1f0j`vlUUե Beuoo+{]OLw4 Rj@rUYeYh,˾=;{TAs.j1˴}j,4ܔ[Ny@-߸qǏ.]1Ư oj:nhaabrr }d2%ZZZD"L&!h4Be||`70GUUD'%FIENDB`qdirstat-1.4/src/icons/zoom-out.png000066400000000000000000000024211311502036700174070ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYs  tIME  *ZIDATHOSgC=B;(BAf"lf%@M\6?d'xL݌H;GDGDX–-8= nWcy|ϓ",CemlPfXN455s:{ATU5=;;;fp7l8{΋%MVbpTZ2 W@ Gs>c(^+ƖDΪ P²`kd]M?D"@`Y}~5RYqqj%]֮OKRc#l]MH6حUD WVE&M%yoo۔ҏ7{z!%8= uVZgLF) Ssg%I"n,"PJNS}"k(0&P9Lt4%?MX@bnq`2bCn7RJ*% 7K'sLnsc~,J nSsnRJ! jeG]4MnF.78R ˺QrZDVb~iqꥲ|]mXDf*VV8Rݞ:>)95??꨷\t `@f0pX`o/Yo u)JB˾:s,VvV^`3 f˥3GNn+B,9sf)ƍ-GBL^/ +r>o7ϏkMӇ刢()Ò$$i Uĝ|>)H^---###)//?(ʣMWS'''Rzzzׇ`0$鄢(jv^Fccjjr9 G{|rVu`zzb1455bQW;NsH$"f2u4 G(u!+EQL'37"gIENDB`qdirstat-1.4/src/locate-files-window.ui000066400000000000000000000047151311502036700202200ustar00rootroot00000000000000 LocateFilesWindow 0 0 800 220 Locate Files by Type true Directories with File Type true true 1 5 &Refresh Qt::Horizontal 40 20 0 0 &Close closeButton clicked() LocateFilesWindow reject() 349 277 199 149 qdirstat-1.4/src/main-window.ui000066400000000000000000000452651311502036700166020ustar00rootroot00000000000000 Stefan Hundhammer MainWindow 0 0 1157 650 QDirStat :/icons/qdirstat.png:/icons/qdirstat.png Qt::Vertical 0 0 1157 22 &File &View E&xpand Tree To Level &Edit Tree&map &Go To &Help true &Clean Up &Settings toolBar TopToolBarArea false :/icons/window-close.png:/icons/window-close.png &Quit Exit application Ctrl+Q :/icons/open-dir.png:/icons/open-dir.png &Open... Open a directory to scan. Ctrl+O &Close All Tree Levels Close all branches of the directory tree. Level &0 Expand (open) the directory tree to level 0. Level &1 Expand (open) the directory tree to level 1. Ctrl+1 Level &2 Expand (open) the directory tree to level 2. Ctrl+2 Level &3 Expand (open) the directory tree to level 3. Ctrl+3 Level &4 Expand (open) the directory tree to level 4. Ctrl+4 Level &5 Expand (open) the directory tree to level 5. Ctrl+5 Level &6 Expand (open) the directory tree to level 6. Ctrl+6 Level &7 Expand (open) the directory tree to level 7. Ctrl+7 Level &8 Expand (open) the directory tree to level 8. Ctrl+8 Level &9 Expand (open) the directory tree to level 9. Ctrl+9 :/icons/stop.png:/icons/stop.png &Stop Reading Stop reading directories. Ctrl+C :/icons/document-export.png:/icons/document-export.png &Write To Cache File... Write the current directory tree to a cache file. :/icons/document-import.png:/icons/document-import.png &Read Cache File... Read a directory tree from a cache file. :/icons/refresh.png:/icons/refresh.png Refresh &All Re-read the entire directory tree from disk. F5 :/icons/edit-copy.png:/icons/edit-copy.png &Copy URL Copy the full path of the current item to the system clipboard for use in other applications. Ctrl+C :/icons/zoom-in.png:/icons/zoom-in.png Zoom &In Zoom the treemap in (enlarge) one level. Ctrl++ :/icons/zoom-out.png:/icons/zoom-out.png Zoom &Out Zoom the treemap out one level. Ctrl+- :/icons/zoom-best-fit.png:/icons/zoom-best-fit.png &Reset Zoom Reset the treemap zoom factor to normal. Ctrl+0 Re&build Rebuild the treemap. true true &Show Treemap Enable or disable showing the treemap view. F9 :/icons/go-up.png:/icons/go-up.png &Up One Level Navigate one directory level up. Alt+Up :/icons/go-top.png:/icons/go-top.png &Toplevel Navigate to the toplevel directory of this tree. Ctrl+Home :/icons/qdirstat.png:/icons/qdirstat.png &About QDirStat... Show version, copyright and license information about this program. About &Qt... Show information about the Qt version used for building this program. Re&fresh Selected Reread the selected branch from disk. Read &Excluded Directory Read a directory that was excluded by an exclude rule. :/icons/hard-disk.png:/icons/hard-disk.png Continue Reading at &Mount Point :/icons/preferences.png:/icons/preferences.png &Configure QDirStat Configure QDirStat true Verbose Selection Switch verbose logging of selecting and unselecting items on or off. Shift+F7 :/icons/trashcan.png:/icons/trashcan.png Move to &Trash Move the selected items to the trash bin. Del Dump Selection to Log F7 File &Type Statistics File Type Statistics F3 QDirStat &Help F1 true true Treemap as side panel Show the Treeemap beside the directory tree, otherwise it will be shown beneath. File &Size Statistics F2 QDirStat::DirTreeView QTreeView

DirTreeView.h
QDirStat::TreemapView QGraphicsView
TreemapView.h
qdirstat-1.4/src/main.cpp000066400000000000000000000060601311502036700154300ustar00rootroot00000000000000/* * File name: main.cpp * Summary: QDirStat main program * License: GPL V2 - See file LICENSE for details. * * Author: Stefan Hundhammer */ #include // getuid() #include // uid_t #include // cerr #include #include "MainWindow.h" #include "DirTreeModel.h" #include "Logger.h" #include "Version.h" using std::cerr; static const char * progName = "qdirstat"; static bool fatal = false; void usage( const QStringList & argList ) { cerr << "\n" << "Usage: \n" << "\n" << " " << progName << " [--slow-update|-s] []\n" << " " << progName << " --cache|-c \n" << " " << progName << " --help|-h\n" << std::endl; logError() << "FATAL: Bad command line args: " << argList.join( " " ) << endl; // Simply exit(1) here results in a segfault (?). fatal = true; } void logVersion() { logInfo() << "QDirStat-" << QDIRSTAT_VERSION << " built with Qt " << QT_VERSION_STR << endl; #if (QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )) logWarning() << "WARNING: You are using Qt " << QT_VERSION_STR << ". This may or may not work." << endl; logWarning() << "The supported Qt version for QDirStat is Qt 5.2 or newer." << endl; #endif } /** * Extract a command line switch (a command line argument without any * additional parameter) from the command line and remove it from 'argList'. **/ bool commandLineSwitch( const QString & longName, const QString & shortName, QStringList & argList ) { if ( argList.contains( longName ) || argList.contains( shortName ) ) { argList.removeAll( longName ); argList.removeAll( shortName ); logDebug() << "Found " << longName << endl; return true; } else { // logDebug() << "No " << longName << endl; return false; } } int main( int argc, char *argv[] ) { Logger logger( "/tmp/qdirstat-$USER", "qdirstat.log" ); logVersion(); // Set org/app name for QSettings QCoreApplication::setOrganizationName( "QDirStat" ); QCoreApplication::setApplicationName ( "QDirStat" ); QApplication app( argc, argv); QStringList argList = QCoreApplication::arguments(); argList.removeFirst(); // Remove program name MainWindow mainWin; mainWin.show(); if ( commandLineSwitch( "--slow-update", "-s", argList ) ) mainWin.dirTreeModel()->setSlowUpdate(); if ( argList.isEmpty() ) mainWin.askOpenUrl(); else { QString arg = argList.first(); if ( arg == "--cache" || arg == "-c" ) { if ( argList.size() == 2 ) { QString cacheFileName = argList.at(1); logDebug() << "Reading cache file " << cacheFileName << endl; mainWin.readCache( cacheFileName ); } else usage( argList ); } else if ( arg == "--help" || arg == "-h" ) usage( argList ); else if ( arg.startsWith( "-" ) || argList.size() > 1 ) usage( argList ); else if ( ! arg.isEmpty() ) { mainWin.openUrl( arg ); } } if ( ! fatal ) app.exec(); return fatal ? 1 : 0; } qdirstat-1.4/src/mime-category-config-page.ui000066400000000000000000000204031311502036700212530ustar00rootroot00000000000000 MimeCategoryConfigPage 0 0 531 467 Form Qt::Horizontal 25 false Qt::Vertical 25 false MIME C&ategory listWidget 0 2 80 80 true Edit the name of the current category. 8 Create a new category. ... :/icons/add.png:/icons/add.png Remove the current category. ... :/icons/remove.png:/icons/remove.png Qt::Horizontal 30 20 0 0 Select a color for the current category. C&olor 0 0 Enter color RGB code directly. #RRGGBB 0 0 80 120 Preview Treemap QFrame::StyledPanel QFrame::Sunken Qt::Vertical 20 false &Patterns (Case Insensitive) caseInsensitivePatternsTextEdit 150 0 Add filename patterns here, each one on a separate line. Use * or ? as wildcards. Patterns (Case &Sensitive) caseSensitivePatternsTextEdit 150 0 Add filename patterns here, each one on a separate line. Use * or ? as wildcards. QDirStat::TreemapView QFrame
TreemapView.h
1
qdirstat-1.4/src/output-window.ui000066400000000000000000000262001311502036700172020ustar00rootroot00000000000000 OutputWindow 0 0 660 400 Cleanup Output :/icons/terminal.png:/icons/terminal.png true 255 170 0 0 0 0 255 170 0 0 0 0 128 128 128 255 255 255 DejaVu Sans Mono 50 false QFrame::StyledPanel 1 QTextEdit::NoWrap <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'DejaVu Sans Mono'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is where output of the cleanup action will appear.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ffffff;">cd /some/where/on/the/disk</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" color:#ffffff;">cleanup --force junkfile</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600; color:#aa0000;">This is an error message.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This is normal program output.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">12345678901234567890123456789012345678901234567890123456789012345678901234567890</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 10 20 30 40 50 60 70 80</p></body></html> false Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse ... :/icons/zoom-in.png:/icons/zoom-in.png ... :/icons/zoom-out.png:/icons/zoom-out.png ... :/icons/zoom-best-fit.png:/icons/zoom-best-fit.png Qt::Horizontal 40 20 &Kill Process Qt::Horizontal 40 20 &Auto Close true &Close :/icons/zoom-in.png:/icons/zoom-in.png Zoom In Make the font of the output window larger. Ctrl++ :/icons/zoom-out.png:/icons/zoom-out.png Zoom Out Make the font of the output window smaller. Ctrl+- :/icons/zoom-best-fit.png:/icons/zoom-best-fit.png Reset Zoom Use standard font size for the output window. Ctrl+0 :/icons/stop.png:/icons/stop.png Kill Process Forcefully kill the cleanup process. killButton clicked() actionKillProcess trigger() 271 376 -1 -1 zoomInButton clicked() actionZoomIn trigger() 21 376 -1 -1 zoomOutButton clicked() actionZoomOut trigger() 51 376 -1 -1 resetZoomButton clicked() actionResetZoom trigger() 81 376 -1 -1 closeButton clicked() OutputWindow close() 609 377 329 199 qdirstat-1.4/src/qdirstat.desktop000066400000000000000000000003241311502036700172230ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=QDirStat Exec=qdirstat %u Icon=qdirstat GenericName=QDirStat Directory Statistics Terminal=false MimeType=inode/directory;inode/mount-point; Categories=Qt;System;Filesystem; qdirstat-1.4/src/src.pro000066400000000000000000000072711311502036700153160ustar00rootroot00000000000000# qmake .pro file for qdirstat/src # # Go to the project toplevel dir and build all Makefiles: # # qmake # # Then build with # # make # TEMPLATE = app QT += widgets CONFIG += debug DEPENDPATH += . MOC_DIR = .moc OBJECTS_DIR = .obj LIBS += -lz major_is_less_5 = $$find(QT_MAJOR_VERSION, [234]) !isEmpty(major_is_less_5):DEFINES += 'Q_DECL_OVERRIDE=""' TARGET = qdirstat TARGET.files = qdirstat TARGET.path = /usr/bin INSTALLS += TARGET desktop icons SOURCES = main.cpp \ ActionManager.cpp \ BucketsTableModel.cpp \ Cleanup.cpp \ CleanupCollection.cpp \ CleanupConfigPage.cpp \ ConfigDialog.cpp \ DataColumns.cpp \ DebugHelpers.cpp \ DelayedRebuilder.cpp \ DirInfo.cpp \ DirReadJob.cpp \ DirSaver.cpp \ DirTree.cpp \ DirTreeCache.cpp \ DirTreeModel.cpp \ DirTreeView.cpp \ Exception.cpp \ ExcludeRulesConfigPage.cpp \ ExcludeRules.cpp \ FileInfo.cpp \ FileInfoIterator.cpp \ FileInfoSet.cpp \ FileInfoSorter.cpp \ FileSizeStats.cpp \ FileSizeStatsWindow.cpp \ FileTypeStats.cpp \ FileTypeStatsWindow.cpp \ HeaderTweaker.cpp \ HistogramView.cpp \ HistogramDraw.cpp \ HistogramItems.cpp \ HistogramOverflowPanel.cpp \ ListEditor.cpp \ LocateFilesWindow.cpp \ Logger.cpp \ MainWindow.cpp \ MimeCategorizer.cpp \ MimeCategory.cpp \ MimeCategoryConfigPage.cpp \ MountPoints.cpp \ OutputWindow.cpp \ PercentBar.cpp \ Process.cpp \ Refresher.cpp \ SelectionModel.cpp \ Settings.cpp \ SettingsHelpers.cpp \ StdCleanup.cpp \ Subtree.cpp \ Trash.cpp \ TreemapTile.cpp \ TreemapView.cpp \ HEADERS = \ ActionManager.h \ BucketsTableModel.h \ Cleanup.h \ CleanupCollection.h \ CleanupConfigPage.h \ ConfigDialog.h \ DataColumns.h \ DebugHelpers.h \ DelayedRebuilder.h \ DirInfo.h \ DirReadJob.h \ DirSaver.h \ DirTree.h \ DirTreeCache.h \ DirTreeModel.h \ DirTreeView.h \ Exception.h \ ExcludeRules.h \ ExcludeRulesConfigPage.h \ FileInfo.h \ FileInfoIterator.h \ FileInfoSet.h \ FileInfoSorter.h \ FileSizeStats.h \ FileSizeStatsWindow.h \ FileTypeStats.h \ FileTypeStatsWindow.h \ HeaderTweaker.h \ HistogramView.h \ HistogramItems.h \ ListEditor.h \ ListMover.h \ LocateFilesWindow.h \ Logger.h \ MainWindow.h \ MimeCategorizer.h \ MimeCategory.h \ MimeCategoryConfigPage.h \ MountPoints.h \ OutputWindow.h \ PercentBar.h \ Process.h \ Qt4Compat.h \ Refresher.h \ SelectionModel.h \ Settings.h \ SettingsHelpers.h \ SignalBlocker.h \ StdCleanup.h \ Subtree.h \ Trash.h \ TreemapTile.h \ TreemapView.h \ Version.h \ FORMS = main-window.ui \ output-window.ui \ config-dialog.ui \ cleanup-config-page.ui \ mime-category-config-page.ui \ exclude-rules-config-page.ui \ file-size-stats-window.ui \ file-type-stats-window.ui \ locate-files-window.ui # general-config-page.ui RESOURCES = icons.qrc desktop.files = *.desktop desktop.path = /usr/share/applications icons.files = icons/qdirstat.png icons.path = /usr/share/icons/hicolor/32x32/apps mac:ICON = icons/qdirstat.icns

"; text += tr( "Contact: " ) + QString( "%2" ).arg( mailTo ).arg( mailTo ); text += "