packagesearch-2.7.11build1/0000755000000000000000000000000013507430555012361 5ustar packagesearch-2.7.11build1/.gitignore0000644000000000000000000000127213507430555014353 0ustar doc/html Doxyfile .kdev4 libpackagesearch* .obj .obj_debug .obj_test packagesearch packagesearch.1 release run-tests *.so src/.moc src/plugins/aptplugin-test/Makefile.test src/plugins/debtagsplugin-test/Makefile src/plugins/orphanplugin/Makefile src/plugins/popconplugin/Makefile src/plugins/screenshotplugin/Makefile *-stamp test-src/*.moc translations/*.qm .ui .moc wget-log* src/Makefile src/plugins/Makefile src/plugins/aptplugin/Makefile src/plugins/debtagsplugin/Makefile src/plugins/filenameplugin/Makefile src/Makefile.testlib src/plugins/Makefile.test src/plugins/debtagsplugin-test/Makefile.test test-src/Makefile *.kate-swp *.pro.user *.log debian/files debian/*.substvars .qmake.stash packagesearch-2.7.11build1/CHANGELOG0000644000000000000000000005050313507430555013576 0ustar Changelog started at 2004-03-31 This file is implemented as a stack - removed reference to ept::axi an ept::popcon(Closes: #727627) ------- released version 2.7.3 ------ - disabled C++0x support to avoid crashes when linking against libept (it seems they do not cooperate (crash) when compiled with different c++0x support settings) - fix to show the correct long description (Closes: #676812) -> directly use libapt-pkg now 2012-06-28 ------- released version 2.7.2 ------ - changed RunCommandInXterm to use /usr/bin/uxterm, because only there I can guarantee consistent behaviour (Closes: #676811) 2012-06-12 - make APT default installation tool - inform user to configure to use apt if aptitude is not available (Closes: #676810) 2012-06-11 - fixed displaying file list (multiarch support) 2012-06-10 ------- released version 2.7.1 ------ - fixed COPYRIGHT file to make lintian happy - changed build infrastructure to use "dh" 2012-05-20 ------- released version 2.7 (never officially) ------ - enabled hardening options 2012-05-19 - fixed problem qith QT 4.8: virtual base classes make QT break -> Plugin no longer inherits from QObject, instead each child plugin must inherit from QObject on its own 2012-05-13 - updated help page - updated spanish translation (thanks Frannoe!) 2012-05-12 - fixed bug disallowing translations to translate column title for "Name" or "Score" 2012-01-29 - proxy server settings are now saved 2012-01-18 - added support for configuring proxy server (still no yet saved) 2011-09-07 - Fixed compiler error caused by xapian having a slots member variable (Closes: #639076) - added support for displaying the "Homepage" field (Closes: #598193) 2010-10-07 - completed support for displaying screenshots 2010-08-07 - fixed filtering of Tag-list based on search pattern 2010-08-03 - fixed full text search for excluding patterns 2010-07-18 ------- released version 2.6 ------ 2010-07-03 - searching for similar packages is now based on full text description - switched to apt-xapian search backend 2010-03-XX - added dependency to libdl (Closes: #555881) 2010-02-28 ------- released version 2.5 ------ - Fixed command execution in terminal to use "read dummy" instead of "read" Command execution should now work on dash (and any other posix conform shell) when finished succesfully or unsuccessfully (Closes: #539255) 2009-10-28 - updating apt-database now also uses the configured installation command (instead of hardcoded apt-get) 2009-10-04 - debtags plugin now displays facet name along with tag names in list view 2009-06-14 - added basic support for i18n 2009-04-03 - searching whole words only is disabled by default - search in description now also searches the short description - changed dependency on libept-dev >= 0.5.22 with fixed package iteration this should fix #442310 (Closes: #442310) 2008-08-10 - added support for configuring command to gain root rights 2008-07-10 - implemented support for searching for whole words only 2008-06-29 - fixed problem that package actions where disabled when selecting it from the drop down list, if a selection in the list view was active before 2008-06-29 - file search shows the list delivered by apt-file for packages with residual configuration instead of the list of installed files - fixed file search which showed pathes stating with double / for not installed package 2008-06-28 - fixed crash when disabling the Apt Plugin while a package was selected 2008-06-27 - allow purging of packages - current package can always be installed, independently of whether it is selected or not (bugfix) - added support for "Upgradable" state (searching and display) 2008-06-22 ------- released version 2.4 ------ - nice window title for running "apt-get update" added - updating apt database is now calling "debtags --local update" afterwards 2008-06-19 - allow selecting between aptitude and apt for installation - add "Preferences" section to menu "Packagesearch" - renamed "File" menu to "Packagesearch" - each menu has a character to select it 2008-06-05 - reduced height of entries in the package list (Closes: #470554) 2008-03-16 - prevent crashes when underlying libept changes (Closes: #439938) 2008-03-06 ------- released version 2.3 ------ - fixed const-issues which was revealed by a new compiler version - added various exception catching code to prevent crashing when a plugin throws an exception 2008-03-02 - fixed crash when selecting a tag from a string-filtered tag list 2008-02-17 - fixed text formatting issue of "Package Description" (Closes: #424913) - fixed Makefiles to zero out QMAKE_LFLAGS (removes --no-undefined) so that the plugins compile again (Closes: #458884) - fixed build-script for manpage (Closes: #458577) - tag selection is now triggered by double-clicking (Closes: #447261) - full port to libqt4 ------- released version 2.2.6 ------ - Added support for the new Xapian functions (Requires libept 0.5.3) (thanks Enrico) - ported to libept > 0.5.1 (Closes: #429005) (thanks Enrico) - corrected rule to build makefile (Closes #418770) ------- released version 2.2.5 ------ - fixed crash when selecting non-existent package (caused by the debtags plugin, Closes: #408051) 2007-01-23 ------- released version 2.2.4 ------ - removed DebtagsActionPlugin, since "debtags update" is no longer usefull 2006-12-03 ------- released version 2.2.3 ------ - delete line ending when reading from apt-file list and apt-file search/dpkg -S (Closes: #398692) using "apt-file search -l" now when searching 2006-11-15 ------- released version 2.2.2 ------ - suggest actually shows suggested packages now (and no longer pre-depends) 2006-10-31 - added build dependency on libept >= 0.4.4 which no longer throws an exception if there is no user .debtags directory available (Closes: #395568), also added dependency on apt >= 0.6.46.1, which should remedy failures in loading the apt-plugin 2006-10-30 ------- released version 2.2.1 ------ - removed using apt-index-watcher by using "debtags update --reindex" 2006-10-23 ------- released version 2.2 ------ - ported to libept (from libapt-front), mainly done by Enrico Zini, thanks! 2006-10-07 ------- released version 2.1.1 ------ - made tag selection list show the part before : in a tagname for tagnames of the form group:name - hide tags with empty itemset 2006-08-14 - added .desktop file provided by Vassilis Pandis (Closes: #382197) 2006-08-09 - commands use /etc/alternatives/x-terminal-emulator instead of xterm now, for better compatibility 2006-06-07 ------- released version 2.1 ------ - fixed icons that were broken after the cvs2svn conversion 2006-05-31 - fixed crashes when showing dependency information for a package where no such information is available 2006-03-26 - fixed crashes when selecting an unknown package - added Version information to title - viewing files with "see" works fine again - removed obsolete instantiation.cpp file (Closes: #357355) 2006-03-20 - reimplemented apt-file update 2006-03-19 - switched to SVN! 2006-03-17 - fully switch APT- and Debtags-Plugin to apt-front 2006-03-13 - gone further in using libapt 2006-03-13 ------- released version 2.0.6 ------- this is a fork version, and does not contain all changes listed in this file - build depend on libmysqlclient15-dev now (Closes: #343788) - fixed crashes when using filesearch or listing for non-installed files 2005-02-13 - fixed crash after a "debtags update" - make "clear search" button work for installed filter 2005-12-25 - simplified plugin mechanism -> plugins are now only distiguished by name, having a simple precedence rule by the plugin path 2005-12-18 - nicely format apt descriptions according to the debian policy 2005-12-17 ------- released version 2.0.4 ------- - explicitly use qmake-qt4 for build 2005-12-12 - fixed starting xterm correct again to externally launch an application - fixed crashing when debtags plugin is not enabled - removed arm, hppa and m68k workarounds 2005-12-11 ------- released version 2.0.3 ------- - changed makefile to fix FTBS on arm, hppa and m68k (should close #329884) - changed packagesearch icon to use real transparancy 2005-10-17 - removed PIC dependencies, as it should be used by default now 2005-09-29 - the debtagsplugin removed its copy of the TagCollection and access the libaptfront collection now - got rid of the handlemaker 2005-09-24 ------- released version 2.0.1 ------- - minor bugfixes - forward and backward icons now displayed - build-dep on libmysql15-dev and libtagcoll-pic added - icons are now located in /usr/share/pixmaps/packagesearch 2005-09-11 ------- released version 2.0 ------- - executing programs as root is done via "su -c" now - added symbols for installing and removing packages 2005-09-09 - sort column is choosen by name now 2005-09-08 - filenameplugin compiles without QT3 support 2005-09-02 - sort column and order is saved now 2005-08-30 - mostly finished QT4 transition 2005-08-27 - allow hiding of help toolbar - porting FilenamePlugin, OrphanPlugin and AptPlugin nearly completed - started porting to QT4 2005-08-27 (and before) - activated new ComplexScoreCalculationStrategy with enhanced score calculation 2005-08-06 - switched to use a Strategy Pattern for calculating the apt scores 2005-07-31 - fixed typo in manpage, (Closes: #320560) 2005-07-30 - changed PackageSearchImpl::*PluginContainer to be of type set 2005-07-29 - improve system design to support scoring plugin with fewer hacks (PluginManager simply forwards the {add,remove}Plugin calls from the PluginContainers to its PluginUsers now - ScorePlugin is an own abstract class now 2005-07-22 - added scoring algorithm for packages - added infrastructure to score search results 2005-07-19 ------- released version 1.3 ------- - implemented saving the debtags options using the saveContainerSettings() functions 2005-06-29 - implemented saving of orphan search option - finished implementing BasePluginContainer calling saveSettings for all its plugins - changed all saveable stuff to implement NXml::IXmlStorable 2005-06-28 - added some status message when viewing files - files can be viewed using a double click - implemented "copy all" function for filelist - added clear button to related search 2005-06-21 - implemented case sensitive searching in apt search - added clear button to apt search 2005-06-20 - added nifty clear button to orphan and file search - added createClearButton() to IProvider 2005-06-19 - enhanced error handling for the filenname plugin - disabled the "view" entry if the file is not readable 2005-06-15 - enhanced file viewing with fallback to plain/text if the mime type is not detected 2005-06-14 - implemented a copy and a view action for the files in the filenameplugin - finished migration to lib{tagcoll,debtags}1 2005-06-13 - fixed plugin manager not to allow duplicate disabled entries any more - added orphaner plugin 2005-06-08 - factored out an NXml::IXmlStorable interface 2005-04-26 - on startup every plugin is loaded only once, even if it exists in different versions or directories 2005-04-23 - moved code to show and hide columns into seperate class - implemented saving of column width 2005-04-22 ------- released version 1.2 ------- - fixed RunCommandWidget::replaceLastLine() so even the first line is replaced properly 2005-04-05 --- Celebrating first anniversary :-) --- - added "Reload Package Database" option to system menu 2005-03-31 - replaced QStrings by QCString in NApt::Package saving 7MB RAM 2005-03-28 - if an unknown ShortInformationPlugin is added, the information column is inserted before the first shown plugin with a higher priority value (i.e. a lower priority) than the new one 2005-03-26 - added installed and available version to short information list 2005-03-25 - added --help and --version options (Closes: #299015) 2005-03-22 - implemented "apt-get update" 2005-03-20 - fixed display of command output (correct handling of CR/LF and CR only, no unneccesary scrolling) (Closes: #299015) 2005-03-18 - hidden columns are removed now if the plugins are no longer loaded 2005-03-17 ------- released version 1.1 ------- - gave the columns in the short information view a reasonable width and supressed resizing the columngs when they are changed - added workaround to avoid crashing due to a libdebtags bug 2005-03-14 - customization of columns is saved - allows customizing of column order and hiding columns in short information view 2005-03-13 - apt-get line is copied to global mouse selection and the global clipboard now 2005-03-11 - apt search supports to exclude search expressions now 2005-03-08 - allowed searching for word groups - added highlighting of search expressions in description view 2005-03-07 - show progress dialog when loading and unloading plugins through the control dialog 2005-03-05 - new backend using DumpAvailPackageDB seems to work stable these changes are closing Bug#291761 - reduced memory usage on startup 2005-03-01 - installed state is working again (parsing /var/lib/dpkg/status) 2005-02-26 - fully implemented progress feedback for loading aptPlugin 2005-02-25 - began implementing a plugin progress display infastructure 2005-02-24 - started changing the apt-plugin not to use libapt any more because this resulted in problems when updating or intalling while packagesearch is running 2005-02-23 ------- released version 1.0.1 ------- - plugins will be disabled if they failed to load now, this prevents nagging about a missing plugin over and over again - replace /usr/share/icons by /usr/share/pixmaps as icon directory 2005-01-21 - changed the text that is displayed in the fileview if a package not installed is selected - plugin container initialization returns if it was successfull or not, plugins will be disabled if not 2005-01-20 - the current item stays visible if the tags displayed change 2004-10-31 - some GUI improvements (right clicking does not select items any more) 2004-10-28 - filtering of tags based on selected tags is implemented using recurison now - filtering of tags shows also tags where only the facet matches 2004-10-(12-27) - implemented showing of time consuming file lists only after clicking the show button 2004-10-07 ------- released version 0.6 ------- - updated documentation 2004-09-21 - implemented showing of installed version in the details section - allowed pressing enter for immidiate evaluation of apt and filesearch 2004-09-20 - switched to a listview in the filename information plugin to show the files as this is much faster - filter for files in the filename information plugin is kept on selection of different packages - deselect items in the package list if another package is displayed (e.g. through back or direct selection) - changed the related plugin to show a list of the packages available for selecting - implemented direct selecting of a single package 2004-09-19 - the links to packages in the details page are only shown if the packages are available 2004-09-18 - the IProvider provides a list of all available packages now 2004-09-17 - removed the exclude tags option for the debtags search (simply by hiding the checkbox) - saving and loading for the debtags settings implemented - persistent saving and loading of plugin settings implemented 2004-09-14 - added saving of plugin settings for the plugins - added selecting tags to be shown in the debtags plugin 2004-09-13 - reorganized plugin initialization 2004-09-10 - started reorganizing plugin initialization to make it more structured 2004-09-08 - added saving and loading of the plugin active status ------- released version 0.5 ------- 2004-08-15 - added control dialog for the plugins - fully implemented evalutation of plugin priorities 2004-08-13 - changed to use a dynamic plugin structure 2004-08-11 ------- released version 0.4.1 ------- - fixed compilation error 2004-08-04 ------- released version 0.4 ------- 2004-08-03 - changed to conform with the new tagcoll interface ------- released version 0.3 ------- - updated documentation - added filename feedback widget - added apt-file update to system menu 2004-07-28 - fully integrated fully implemented filename search (using dpkg -S or apt-file) 2004-07-20 - information in the information widget container is only updated if needed - added filename information (for installed and not installed) - set title of the package on selection again - added framework for filename plugin 2004-07-18 - created a homepage ------- released version 0.2 ------- 2004-07-14 - getting ready for version 0.2 - did a total internal rework, the appliction uses plugins to receive its information and search possiblities now 2004-07-13 -fixed clear search - implemented searching for more than one expression 2004-06-18 - allow the application to run without the debtags database - implemented synchronization with debtags update 2004-06-17 - updated the tag listviews after a debtags update - switched to using STL algorithms in some cases 2004-06-10 ------- released version 0.1 ------- - restructured the GUI - implemented showing the current installed state in the resultview - implemented installed/not installed filter 2004-06-06 - added What's This entry to help menu - implemented showing the number of packages found using the current search - added What's this toolbutton - added libdebtags, replaced Vocabulary by Debtags::Vocabulary 2004-06-05 - implemented showing of the number of packages found 2004-06-01 - finished implementing of hiding tags which would produce an empty output 2004-05-29 - started implemented hiding of tags which would produce an empty output - added an iterator to the TagSelectionListView class - this simplifies the operations on it and allows STL algorithms to operate on it. - fixed the bug that on removing an Item from the TagListBoxes the application crashed. 2004-05-28 ------- released version 0.0.3 ------- - completed migration to new tag structure (using facets) including a complete refactoring of the tagselection class hierarchy 2004-05-26 - added checking of UID to be root for "debtags update" - refactored the RunCommand class to alternativly use xterm to run a command - implemented debtags update via the system menu 2004-05-14 - implemented an Exit entry in the File menu - create an apt-get for packages via the context menu - tried to implement a debtags update, but this failed because we need a tty interface for this (if we want to show the output) 2004-05-08 - implemented showing of the tagset for the selected package - changed error handling of descriptions not available to not display a message box - created icons for back and forward 2004-05-01 - prepared for the release of debian archives 2004-04-28 ------- released version 0.0.2 ------- - enhanced error message on startup failure - implemented an about dialog - implemented a helpContents Function - implemented a cursor indicating that the application is busy (overrider cursor) - created a helpfile - Implemented a faster way of getting short descriptions for the packages. This is also done delayed (on evaluation of the first search) now. This allows a faster build up of the main dialog. 2004-04-25 - added first (slow) version of showing short descritions in the result view - increased debtags search speed by applying implications only once - took search algorithm from tagcolledit which does not use the TagcollFilter. It increased the search speed markably, it is not yet implemented for searches including exclude tags - improve resizing of the search input toolbox 2004-04-24 - implemented error handling on startup. This does not work as I expected it, but it catches the error. - added Details section to the package view with links - added Essential, Pre-Depends and Conffiles sections 2004-04-20 - layout update - fixed htmlifying the string we get - implemented a details section - implemented splitters using the designer 2004-04-17 corrected linebreak in description 2004-04-13 Added "clear search" button Implemented delayed evaluation to avoid unnessecary evaluations Implemented related search Fixed apt search - itd does search descriptions now 2004-04-04 implemented the apt search - mainly copying code from apt-cache 2004-04-03 moved "borrowed" code to external directory added description display 2004-03-31 packagesearch-2.7.11build1/COPYING0000644000000000000000000003543313507430555013424 0ustar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS packagesearch-2.7.11build1/INSTALL0000644000000000000000000000055513507430555013417 0ustar Debian Packagesearch Last Change: 2006-03-20 Compiler: gcc 4.1 To compile the package install the dependencies (see build-depencies in debian/control) and change to the packagesearch directory. Run make You should get the latest debtags database using: debtags update The binary is located in the source directory (src) try running: cd src ./packagesearch packagesearch-2.7.11build1/Makefile0000644000000000000000000000727213507430555014031 0ustar #!/usr/bin/make -f ICONDIR = /usr/share/pixmaps/packagesearch RELEASE_ARGS := "CONFIG-=debug" "CONFIG+=release" TEST_ARGS := "CONFIG+=test" "CONFIG+=debug" MAKE_ARGS := "-j2" QMAKE = /usr/bin/qmake QMAKE_ARGS = LRELEASE = /usr/bin/lrelease LRELEASE_ARGS = export QT_SELECT=qt5 all: delete-makefiles translations ( cd src ; $(QMAKE) $(QMAKE_ARGS) $(RELEASE_ARGS) ; make $(MAKE_ARGS)) ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) $(RELEASE_ARGS) ; make $(MAKE_ARGS)) translations: $(LRELEASE) $(LRELEASE_ARGS) src/packagesearch.pro $(LRELEASE) $(LRELEASE_ARGS) src/plugins/debtagsplugin/debtagsplugin.pro $(LRELEASE) $(LRELEASE_ARGS) src/plugins/aptplugin/aptplugin.pro $(LRELEASE) $(LRELEASE_ARGS) src/plugins/filenameplugin/filenameplugin.pro $(LRELEASE) $(LRELEASE_ARGS) src/plugins/orphanplugin/orphanplugin.pro $(LRELEASE) $(LRELEASE_ARGS) src/plugins/screenshotplugin/screenshotplugin.pro delete-translations: rm -f translations/*.qm clean-all: clean clean-debug clean-test delete-translations clean: delete-makefiles delete-translations ( cd src ; $(QMAKE) $(QMAKE_ARGS) $(RELEASE_ARGS) ; make clean ) ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) $(RELEASE_ARGS) ; make clean ) make delete-makefiles rm src/.qmake.stash debug: delete-makefiles translations ( cd src ; $(QMAKE) $(QMAKE_ARGS) ; make $(MAKE_ARGS)) ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) ; make $(MAKE_ARGS)) clean-debug: delete-makefiles delete-translations ( cd src ; $(QMAKE) $(QMAKE_ARGS) ; make clean ) ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) ; make clean ) make delete-makefiles #install: # install -d /usr/lib/packagesearch # install -d /usr/share/doc/packagesearch # install -d /usr/local/bin # install -d $(ICONDIR) # install src/packagesearch /usr/local/bin/ # install -m 644 icons/{packagesearch.png,install-package.png,remove-package.png,forward.png,back.png} $(ICONDIR) # install -m 644 README TODO CHANGELOG doc/content.html doc/COPYING.txt /usr/share/doc/packagesearch/ # install src/plugins/lib*so /usr/lib/packagesearch #uninstall: # rm -f /usr/local/bin/packagesearch # rm -f /usr/share/doc/packagesearch/{README,TODO,CHANGELOG,content.html,COPYING.txt} # rmdir /usr/share/doc/packagesearch # rm -f /usr/lib/packagesearch/libaptplugin.so # rm -f /usr/lib/packagesearch/libdebtagsplugin.so # rm -f /usr/lib/packagesearch/libfilenameplugin.so # rm -f /usr/lib/packagesearch/liborphanplugin.so # rmdir /usr/lib/packagesearch # rm -f $(ICONDIR)/{packagesearch.png,install-package.png,remove-package.png,forward.png,back.png} # rmdir $(ICONDIR) delete-makefiles: rm -f src/Makefile rm -f src/plugins/Makefile rm -f src/plugins/aptplugin/Makefile rm -f src/plugins/debtagsplugin/Makefile rm -f src/plugins/filenameplugin/Makefile rm -f src/plugins/orphanplugin/Makefile rm -f src/plugins/screenshotplugin/Makefile rm -f src/plugins/Makefile.test rm -f src/plugins/aptplugin-test/Makefile test: build-test run-test build-test: debug ( cd src ; $(QMAKE) $(QMAKE_ARGS) "CONFIG+= testlib" ; make $(MAKE_ARGS) -f Makefile.testlib) ( cd test-src ; $(QMAKE) $(QMAKE_ARGS) ; make $(MAKE_ARGS)) ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) plugins-test.pro ; make $(MAKE_ARGS) -f Makefile.test) run-test: build-test ( cd test-src ; export LD_LIBRARY_PATH=../src ; ./run-tests ) ( cd src ; export LD_LIBRARY_PATH=.:plugins ; plugins/aptplugin/run-tests ) clean-test: ( cd src/plugins ; $(QMAKE) $(QMAKE_ARGS) "CONFIG+= testlib" ; make -f src/Makefile.testlib clean ) make -f src/Makefile.test clean make -f src/plugins/Makefile.test clean rm -f src/Makefile.testlib rm -f src/Makefile.test .PHONY : all debug clean clean-all clean-debug clean-test install uninstall delete-makefiles test build-test run-test translations delete-translations packagesearch-2.7.11build1/README0000644000000000000000000000164213507430555013244 0ustar Debian Packagesearch Last Change: 2012-03-21 Author: Benjamin Mesing (bensmail@gmx.net) License: GPL Language: C++ Compiler: gcc Platforms: Debian-Linux Documentation: Doxygen This program provides a UI for package searches on Debian systems. In particular it integrates debtags developed by Enrico Zini. Debtags is a new approach that allows organisation of packages in a more convenient way. Tags are categories that can be added to a package. They characterise the program. Multiple Tags may be assigned to one package. See the programs help page for more information (accessible via Help->Content in the menu). Help Please use the embedded tooltips and what's this function! There is also an extensive content page available via Help->Contents (or in doc/contents.html) Developer Info Checklist when adding new Plugins * add to src/plugins/plugins.pro/plugins-test.pro * add line to Makefile translations-targetpackagesearch-2.7.11build1/TODO0000644000000000000000000000620713507430555013056 0ustar Priorities: HB - high bug NB - normal bug LB - low bug HW - high wish NW - normal wish LW - low wish UN - unclassified/ verify --- [LB] When no config file is available (i.e. packagesearch is startet for the first time), hiding a column always results in hiding the description column and no other column can be hidden (really happens only when without config). [LB] Busy cursor is not reset, if similar seach is performed for a package which does not exist [LB] Column order is not saved in settings [LLB] Crashes when pressing "clear all" after searching for System::accounting (happens only in Debug mode, seems to be caused by involvation of modeltest) [HHW] Make project files include shared stuff [HW] Support predefined debtags profiles: Graphical Application, Widget, Command Line Application, Development Library, I18n, Data [HW] Support "ignore recommends" option for deborphan [HW] Check if Xapian Index is up to date [HW] install/remove multiple files [NW] SearchPlugin should not derive from QObject (not use signals) [NW] add separator in package list context menu after package options [NW] allow copy all content/packages to clipboard for package list [NW] add Essential and Priority to package details as soon as they are available via apt-front [NW] GUI Testing for QT would be interesting [NW] Obsolete status? [LW] Install deb files like "gdebi", i.e. register for file extension/allow "packagesearch xxx.deb" to install foreign packages [LW] Add search-as-you-type and "search term suggestion" (see notes file) [LW] look into sticky search [LW] add maintainer, section, depends, .... search [LW] let apt-file block the file plugin only [LLW] implement "apt-get update" and "debtags update" using libept [LLW] allow showing of NEWS.Debian.[gz] files of installed packages Ideas -------------------------------- Developer profile (facet preselection, visible windows/panes) Not reproducable: -------------------------------- [NB, not reproducable any more] "Hide column" hides wrong columns (select "Hide Column" for "Installed Version" and "Description" will be gone Deferred/ difficult, unimportant -------------------------------- - save the view state of the toolbar -> it seems QT ignores the loading of it :-( - allow pressing of delete in the views of the tags -> assigned minor priority and quite onerous (subclassing QListView and so on) - check backwards compability from debtags plugin loading -> not needed, settings not important enough - create nice tab order -> this is no easy task with very little benefit - update column display after loading plugins -> this only bloats the code, plugins are usually not often enabled/disabled Dismissed -------------------------------- - add changelog and readme -> available by the filename plugin using view -linebreak only on lines with a single dot. -> this is not possible as not every linebreak is symbolized by a single . -reduce the sections to show in the tags search depended of the other filters -> improve this to work together with the apt and related filters For this we need a really good data structure - give it some thought! -> this breaks the plugin structure and will not be incorporated packagesearch-2.7.11build1/debian/0000755000000000000000000000000013626022517013600 5ustar packagesearch-2.7.11build1/debian/changelog0000644000000000000000000003056513626022517015463 0ustar packagesearch (2.7.11build1) focal; urgency=high * No change rebuild against apt 1.9.11. -- Julian Andres Klode Thu, 27 Feb 2020 21:23:43 +0100 packagesearch (2.7.11) unstable; urgency=medium * Prepare for QT5.12, Closes: #930678 -- Benjamin Mesing Thu, 04 Jul 2019 19:03:41 +0200 packagesearch (2.7.10) unstable; urgency=medium * fixed build because of included Makefile -- Benjamin Mesing Fri, 19 Oct 2018 21:50:28 +0200 packagesearch (2.7.9) unstable; urgency=medium * fixed build because of CHAR_WIDTH -- Benjamin Mesing Fri, 28 Sep 2018 16:32:54 +0200 packagesearch (2.7.8) unstable; urgency=medium * fix build for non-amd64, second try -- Benjamin Mesing Sat, 04 Nov 2017 19:52:14 +0100 packagesearch (2.7.7) unstable; urgency=medium * fix build on QT5 (Closes: #880356) -- Benjamin Mesing Wed, 01 Nov 2017 21:35:41 +0100 packagesearch (2.7.6) unstable; urgency=low * updated to QT5, Closes: #875079 * do not show short description in long description field -- Benjamin Mesing Sun, 01 Oct 2017 22:49:32 +0200 packagesearch (2.7.5) unstable; urgency=medium * fixed compile bugs against latest libept (Closes: #798143, #798808) -- Benjamin Mesing Sun, 20 Sep 2015 20:51:40 +0200 packagesearch (2.7.4) unstable; urgency=low * removed reference to ept::axi an ept::popcon(Closes: #727627) * updated dependency to latest version of libwibble (>=1 << 2) -- Benjamin Mesing Mon, 28 Oct 2013 17:27:02 +0100 packagesearch (2.7.3) unstable; urgency=low * fixed packagesearch to show the correct long description (Closes: #676812) -- Benjamin Mesing Thu, 28 Jun 2012 23:00:34 +0200 packagesearch (2.7.2) unstable; urgency=low * changed RunCommandInXterm to use /usr/bin/uxterm, because only there I can guarantee consistent behaviour (Closes: #676811) * make apt default package management tool * inform user to configure to use apt if aptitude is not available (Closes: #676810) * fixed several multiarch issues -- Benjamin Mesing Tue, 12 Jun 2012 21:03:37 +0200 packagesearch (2.7.1) unstable; urgency=medium * changed debian build infrastructure to use debhelper -- Benjamin Mesing Sun, 20 May 2012 11:45:28 +0200 packagesearch (2.7) unstable; urgency=high * compiled against latest version of libept/libapt (Closes: #669215) * fixed compiler error caused by xapian having a slots member variable (Closes: #639076) * added support for displaying the "Homepage" field (Closes: #598193) * Implemented support for viewing screenshots -- Benjamin Mesing Sat, 19 May 2012 21:40:09 +0200 packagesearch (2.6) unstable; urgency=low * New upstream release - explicitly list all required libraries (Closes: #555881) - use apt-xapian as search backend (significantly faster) - searching for similar packages is now based on full text description - ported to libept 1.0 (Closes: #581003) -- Benjamin Mesing Sat, 03 Jul 2010 21:31:05 +0200 packagesearch (2.5) unstable; urgency=low * New upstream release - Command execution should now work on dash (and any other posix conform shell) when finished successfully or unsuccessfully (Closes: #539255) - changed dependency on libept-dev >= 0.5.22 with fixed package iteration this should fix #442310 (Closes: #442310) - other bugfixes and improvements (see CHANGELOG file) -- Benjamin Mesing Sun, 08 Nov 2009 10:01:40 +0100 packagesearch (2.4) unstable; urgency=low * New upstream release - prevent crashes when underlying libept changes (Closes: #439938) - reduced height of entries in the package list (Closes: #470554) - allow selecting between apt and aptitude for installation - fixed typos in README (Closes: #471921) -- Benjamin Mesing Wed, 25 Jun 2008 11:01:06 +0200 packagesearch (2.3) unstable; urgency=medium * New upstream release (fully ported to QT4) - compiled against latest libapt (Closes: #466888) - fixed text formatting issue of "Package Description" (Closes: #424913) - fixed Makefiles to zero out QMAKE_LFLAGS (removes --no-undefined) so that the plugins compile again (Closes: #458884) - fixed build-script for manpage (Closes: #458577) - tag selection is now triggered by double-clicking (Closes: #447261) - updated section for menu entry (changed in recent policy) -- Benjamin Mesing Sun, 02 Mar 2008 10:20:28 +0100 packagesearch (2.2.6) unstable; urgency=medium * ported to libept > 0.5.1 (Closes: #429005) (thanks Enrico) * corrected rule to build makefile (Closes: #418770) -- Benjamin Mesing Sat, 14 Jul 2007 17:26:26 +0200 packagesearch (2.2.5) unstable; urgency=low * fixed crash when selecting non-existent package (caused by the debtags plugin, Closes: #408051) -- Benjamin Mesing Tue, 23 Jan 2007 11:30:15 +0100 packagesearch (2.2.4) unstable; urgency=low * New upstream release -- Benjamin Mesing Sun, 3 Dec 2006 15:24:36 +0100 packagesearch (2.2.3) unstable; urgency=low * New upstream release - delete line ending when reading from apt-file list and apt-file search/dpkg -S (Closes: #398692) -- Benjamin Mesing Wed, 15 Nov 2006 08:47:20 +0100 packagesearch (2.2.2) unstable; urgency=low * Bugfix release - added build dependency on libept >= 0.4.4 which no longer throws an exception if there is no user .debtags directory available (Closes: #395568), also added dependency on apt >= 0.6.46.1, which should remedy failures in loading the apt-plugin (Closes: #395568) -- Benjamin Mesing Mon, 31 Oct 2006 18:29:29 +0100 packagesearch (2.2.1) unstable; urgency=low * does not use apt-index-watcher any more, uses debtags update --reindex instead -- Benjamin Mesing Wed, 25 Oct 2006 20:23:21 +0200 packagesearch (2.2) unstable; urgency=medium * New upstream release - uses libept as new backend (instead of libapt-front) Closes: #389462 debtags handling is improved in libept - added build dependency onto additional -dev library packages libsqlite0-dev libglib2.0-dev required by libqt4 4.2 (Closes: #391933) -- Benjamin Mesing Sat, 9 Oct 2006 23:00:45 +0200 packagesearch (2.1.1-0.1) unstable; urgency=medium * NMU for release critical bug. * Move docbook-to-man from Build-Depends to Build-Depends-Indep (Closes: #389150, #389237). -- Thijs Kinkhorst Fri, 6 Oct 2006 14:24:41 +0200 packagesearch (2.1.1) unstable; urgency=low * Bug fix release - adds a .desktop file (Closes: #319875, 382197) - use x-terminal-emulator instead of hard coded xterm - show the part before the : for grouped tags - build-depends on libapt-front 0.3.10 since this one builds fine on all architectures, and fixes a bug in the vocabulary processing -- Benjamin Mesing Sun, 17 Sep 2006 10:59:31 +0200 packagesearch (2.1) unstable; urgency=low * New upstream release - removed obsolete instantiation.cpp file (Closes: #357355, already fixed before in NMU) - switched backend to use libapt-front in main program and relevant plugins (Closes: #364551, #348493) - prepared for gcc 4.1 (Closes: #369424) - checks for debtags availability before trying to open (Closes: #355625) -- Benjamin Mesing Mon, 1 June 2006 13:49:02 +0100 packagesearch (2.0.6-0.1) unstable; urgency=high * Non-maintainer upload. * Fix duplicate template instantiation, thanks to Ben Hutchings and Martin Michlmayr. (Closes: #357355, #360553). * Urgency set to high due to RC bug fix. -- Pierre Habouzit Thu, 25 May 2006 15:27:25 +0200 packagesearch (2.0.6) unstable; urgency=low * build depend on libmysqlclient15-dev now (Closes: #343788) * fixed crashes when using filesearch or listing for non-installed files -- Benjamin Mesing Mon, 13 Feb 2006 11:34:02 +0100 packagesearch (2.0.5) unstable; urgency=medium * don't try to load a non-available icon for the application (Closes: #346565) * if /usr/X11R6/bin/xterm is not found try /usr/bin/xterm (Closes: #346560) -- Benjamin Mesing Mon, 9 Jan 2006 16:43:19 -0500 packagesearch (2.0.4) unstable; urgency=low * New upstream release * removed arm, hppa and m68k workarounds (closes #343013) -- Benjamin Mesing Sun, 11 Dec 2005 19:37:41 -0500 packagesearch (2.0.3) unstable; urgency=low * changed makefile to fix FTBS on arm, hppa and m68k (should close #329884) -- Benjamin Mesing Mon, 17 Oct 2005 10:14:11 -0400 packagesearch (2.0.2) unstable; urgency=low * New upstream release - changed debtags plugin to use apt-front as backend (thanks Enrico :-) - linking against new libtagcoll and new libapt-front should finally close bug 324032, because they contain PIC code - added workaround for gcc bug, which should close 329884 -> did not work -- Benjamin Mesing Thu, 29 Sep 2005 13:09:35 +0200 packagesearch (2.0.1) unstable; urgency=low * bugfix release - forward and backward icons now displayed - build-dep on libmysql15-dev and libtagcoll-pic added -- Benjamin Mesing Sun, 11 Sep 2005 12:15:14 +0200 packagesearch (2.0) unstable; urgency=low * his links against the -pic versions of debtags/tagcoll, I am not sure if this closes bug 324032, but I believe so - checking back with the submitter * linked against the latest version of libapt (Closes: #323939) * New upstream release -- Benjamin Mesing Fri, 9 Sep 2005 13:54:08 +0200 packagesearch (1.3) unstable; urgency=low * removed dependency to libapt (Closes: #316628) * New upstream release -- Benjamin Mesing Wed, 29 Jun 2005 21:14:01 +0200 packagesearch (1.2) unstable; urgency=low * New upstream release (excerpt from the changelog file) - added --help and --version options (Closes: #299015) - fixed display of command output (correct handling of CR/LF and CR only, no unneccesary scrolling) (Closes: #299015) Thanks to Ross Boylan for his bug reports -- Benjamin Mesing Tue, 22 Mar 2005 11:07:09 +0100 packagesearch (1.1) unstable; urgency=low * New upstream release * the new version comes with a new backend not using libapt any more but using the kpackage approach of parsing the output of apt-get dumpavail now (Closes: #291761) -- Benjamin Mesing Mon, 14 Mar 2005 11:19:20 +0100 packagesearch (1.0.1) unstable; urgency=low * New upstream release -- Benjamin Mesing Fri, 21 Jan 2005 16:13:13 +0100 packagesearch (1.0) unstable; urgency=low * New upstream release -- Benjamin Mesing Sun, 31 Oct 2004 14:04:01 +0100 packagesearch (0.6) unstable; urgency=low * New upstream release -- Benjamin Mesing Tue, 21 Sep 2004 15:18:07 +0200 packagesearch (0.5) unstable; urgency=low * New upstream release -- Benjamin Mesing Mon, 16 Aug 2004 15:16:41 +0200 packagesearch (0.4.1) unstable; urgency=low * New upstream release -- Benjamin Mesing Wed, 4 Aug 2004 14:28:50 +0200 packagesearch (0.4) unstable; urgency=low * New upstream release -- Benjamin Mesing Tue, 3 Aug 2004 20:35:59 +0200 packagesearch (0.3) unstable; urgency=low * New upstream release -- Benjamin Mesing Wed, 28 Jul 2004 13:37:56 +0200 packagesearch (0.2) unstable; urgency=low * New upstream release -- Benjamin Mesing Thu, 15 Jul 2004 14:42:14 +0200 packagesearch (0.1) unstable; urgency=low * New upstream release -- Benjamin Mesing Sun, 6 Jun 2004 16:25:19 +0200 packagesearch (0.0.3) unstable; urgency=low * -- Benjamin Mesing Wed, 26 May 2004 18:48:02 +0200 packagesearch (0.0.2-1) unstable; urgency=low * Initial Release. * -- Benjamin Mesing Tue, 27 Apr 2004 19:40:58 +0200 packagesearch-2.7.11build1/debian/compat0000644000000000000000000000000313507430555015002 0ustar 10 packagesearch-2.7.11build1/debian/control0000644000000000000000000000227713626022517015213 0ustar Source: packagesearch Section: admin Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Benjamin Mesing Build-Depends: debhelper (>= 10.8), libept-dev (>= 1.0.9), libept-dev (<< 2), qtbase5-dev, qttools5-dev-tools, docbook-to-man, pkg-config, libwibble-dev (>= 1.0), libwibble-dev (<< 2.0), libtagcoll2-dev (>= 2.0), libtagcoll2-dev (<< 2.1), libxapian-dev, libapt-pkg-dev Standards-Version: 4.1.0 Vcs-Git: https://git.code.sf.net/p/packagesearch/git Package: packagesearch Architecture: any Depends: apt (>= 0.6.46.1), debtags (>= 1.6.1), apt-xapian-index, xterm, ${shlibs:Depends}, ${misc:Depends} Recommends: apt-file, deborphan Description: GUI for searching packages and viewing package information This tool is aimed to help you search the packages you need. It should make the task of searching a pleasant experience. . Search can be done by * pattern * tags (based on the debtags system) * files * installed status * orphaned packages Additionally a lot of information about the packages is displayed, including screenshots and the files within a package. . It is possible to install or remove packages. packagesearch-2.7.11build1/debian/copyright0000644000000000000000000000114113507430555015533 0ustar Native Debian Package Upstream Author: bensmail@gmx.net Software Copyright 2004-2012 Benjamin Mesing The spanish translation and the icon Copyright 2012-2012 Frannoe You are free to distribute this software under the terms of the GNU General Public License. The icon is and adaption of the icon set from Marco Talamelli 2009f and falls under the Artistic license. On Debian systems, the complete text of the GNU General Public License and Artistic License can be found in the files `/usr/share/common-licenses/GPL' and `/usr/share/common-licenses/Artistic'. packagesearch-2.7.11build1/debian/docs0000644000000000000000000000003513507430555014454 0ustar README TODO doc/content.html packagesearch-2.7.11build1/debian/manpage.sgml0000644000000000000000000001037213507430555016102 0ustar manpage.1'. You may view the manual page with: `docbook-to-man manpage.sgml | nroff -man | less'. A typical entry in a Makefile or Makefile.am is: manpage.1: manpage.sgml docbook-to-man $< > $@ The docbook-to-man binary is found in the docbook-to-man package. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include docbook-to-man in your Build-Depends control field. --> Benjamin"> Mesing"> March 22, 2005"> 1"> bensmail@gmx.net"> PACKAGESEARCH"> Debian"> GNU"> ]>
&dhemail;
&dhfirstname; &dhsurname; 2003 &dhusername; &dhdate;
&dhucpackage; &dhsection; &dhpackage; Program to search for debian packages &dhpackage; [options] DESCRIPTION This manual page documents briefly the &dhpackage; program. There is not much to say about it. Start it by typing &dhpackage; and use the help function offered by the program if necessary. &dhpackage; is aimed to help you searching the packages you need. It should make the task of searching a pleasant experience. Originally I designed it for the purpose of finding a single package where you have a clear imagination of what you want. But you can also use it to simply browse your packages to explore. Perhaps there is something in the database that you simply must have :-). OPTIONS Prints the version information. Prints a usage message. SEE ALSO debtags(1). AUTHOR This manual page was written by &dhusername; <&dhemail;> for the &debian; system (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the &gnu; General Public License, Version 2 any later version published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
packagesearch-2.7.11build1/debian/packageseach.dirs0000644000000000000000000000022513507430555017064 0ustar usr/bin usr/share/pixmaps/packagesearch usr/share/applications usr/share/packagesearch/translations usr/share/doc/packagesearch usr/lib/packagesearchpackagesearch-2.7.11build1/debian/packagesearch.install0000644000000000000000000000060613507430555017756 0ustar src/packagesearch usr/bin icons/back.png icons/forward.png icons/install-package.png icons/remove-package.png icons/clear.png icons/packagesearch.png usr/share/pixmaps/packagesearch icons/packagesearch.xpm icons/packagesearch.png usr/share/pixmaps src/plugins/lib*so usr/lib/packagesearch packagesearch.desktop usr/share/applications translations/*.qm usr/share/packagesearch/translations packagesearch-2.7.11build1/debian/rules0000755000000000000000000000205213507430555014662 0ustar #!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. export DH_VERBOSE=1 export QT_SELECT=qt5 %: dh $@ override_dh_auto_build: docbook-to-man debian/manpage.sgml > debian/packagesearch.1 dh_auto_build # not yet ready for release - no popcon data available rm -f src/plugins/libpopconplugin.so override_dh_auto_clean: dh_auto_clean rm -f debian/packagesearch.1 override_dh_installchangelogs: dh_installchangelogs CHANGELOG override_dh_installman: dh_installman debian/packagesearch.1 # do not run Make test because it is currently broken override_dh_auto_test: # .PHONY: override_dh_auto_build override_dh_auto_clean override_dh_installchangelogs override_dh_installman override_dh_auto_test packagesearch-2.7.11build1/details.rtf0000644000000000000000000000706013507430555014526 0ustar {\rtf1\ansi\deff0\adeflang1025 {\fonttbl{\f0\froman\fprq2\fcharset0 Thorndale{\*\falt Times New Roman};}{\f1\froman\fprq2\fcharset0 Thorndale{\*\falt Times New Roman};}{\f2\fnil\fprq2\fcharset0 Andale Sans UI{\*\falt Arial Unicode MS};}{\f3\fnil\fprq2\fcharset0 Tahoma{\*\falt Lucidasans};}{\f4\fnil\fprq0\fcharset0 Tahoma{\*\falt Lucidasans};}} {\colortbl;\red0\green0\blue0;\red128\green128\blue128;} {\stylesheet{\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031\snext1 Default;} {\s2\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031\sbasedon1\snext2 Text body;} {\s3\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031\sbasedon2\snext3 List;} {\s4\sb120\sa120\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs20\lang255\ai\ltrch\dbch\af2\afs20\langfe255\ai\loch\f0\fs20\lang1031\i\sbasedon1\snext4 Caption;} {\s5\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af4\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031\sbasedon1\snext5 Index;} {\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031\sbasedon2\snext6 Table Contents;} {\s7\cf0\qc{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ai\ab\ltrch\dbch\af2\afs24\langfe255\ai\ab\loch\f0\fs24\lang1031\i\b\sbasedon6\snext7 Table Heading;} } {\info{\creatim\yr2004\mo4\dy4\hr21\min6}{\revtim\yr2004\mo4\dy4\hr21\min8}{\printim\yr1601\mo1\dy1\hr0\min0}{\comment StarWriter}{\vern6450}}\deftab709 {\*\pgdsctbl {\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\pgdscnxt0 Default;}} \paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc \trowd\trql\trhdr\trpaddft3\trpaddt55\trpaddfl3\trpaddl55\trpaddfb3\trpaddb55\trpaddfr3\trpaddr55\clbrdrt\brdrs\brdrw1\brdrcf1\clbrdrl\brdrs\brdrw1\brdrcf1\clbrdrb\brdrs\brdrw1\brdrcf1\cellx4985\clbrdrt\brdrs\brdrw1\brdrcf1\clbrdrl\brdrs\brdrw1\brdrcf1\clbrdrb\brdrs\brdrw1\brdrcf1\clbrdrr\brdrs\brdrw1\brdrcf1\cellx9971 \pard\intbl\pard\plain \intbl\ltrpar\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031 {\loch\f0\fs24\lang1031\i0\b0 Package:} \cell\pard\plain \intbl\ltrpar\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031 {\loch\f0\fs24\lang1031\i0\b0 Planets: 3D} \cell\row\pard \trowd\trql\trpaddft3\trpaddt55\trpaddfl3\trpaddl55\trpaddfb3\trpaddb55\trpaddfr3\trpaddr55\clbrdrl\brdrs\brdrw1\brdrcf1\clbrdrb\brdrs\brdrw1\brdrcf1\cellx4985\clbrdrl\brdrs\brdrw1\brdrcf1\clbrdrb\brdrs\brdrw1\brdrcf1\clbrdrr\brdrs\brdrw1\brdrcf1\clvertalb\cellx9971 \pard\intbl\pard\plain \intbl\ltrpar\s6\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031 {\loch\f0\fs24\lang1031\i0\b0 Version:} \cell\pard\plain \intbl\ltrpar\s6\cf0\qr{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031 {\loch\f0\fs24\lang1031\i0\b0 1.3} \cell\row\pard \pard\plain \ltrpar\s1\cf0{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\rtlch\af3\afs24\lang255\ltrch\dbch\af2\afs24\langfe255\loch\f0\fs24\lang1031 \par }packagesearch-2.7.11build1/doc/0000755000000000000000000000000013507430555013126 5ustar packagesearch-2.7.11build1/doc/COPYING.txt0000644000000000000000000003543313507430555015007 0ustar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS packagesearch-2.7.11build1/doc/content.html0000644000000000000000000002477613507430555015506 0ustar Help - Debian Package Search

Debian Package Search Help Page

This tool is aimed to help you find the packages you need. It should make the task of searching a pleasant experience. Originally I designed it for the purpose of finding a single package where you have a clear imagination of what you want. But you can also use it to simply browse and explore your packages. Perhaps there is something in the database that you simply must have :-).
The program is not meant to be a package managment tool like synaptic, though it is capable of installing individual packages.

The User Interface

The main window is split into two parts:

  1. The upper part where you can enter the search you want to perform.
  2. The lower part which shows the results of your current search on the left, and information about the selected package on the right

The different types of search and informations available are offered by plugins. Every plugin offers a number of different search and information types. In the following we will take a closer look on the search types offerd by the plugins distributed with the application.

A More Detailed View on the Search

In the upper pane you can enter the search criterias you want to search for. The result consists of the packages which match all your active searches. All the active searches are shown in the top left pane, so you always have an overview over the active search.

By default there are five main criterias you can use for searching:

Search by Categories
(Debtags Search)
The main idea here is, that every package is characterised by a number of categories called tags. The tags are organised in a hierarchy, where each tag is inside a so called facet (group of categories).
Each package is given a number of such tags. E.g. the image editor gimp has among others the tags: interface::x11, works-with-format::jpg, uitoolkit::gtk, use::editing. As tagging is still under development not all packages might be tagged completely, and some may not be tagged as you would expect them to be.
You can select the tags you want to search for on the right side under the page Debtags. To select a tag simply double-click it.
The currently selected tags will be shown on the left side. They can be removed by double-clicking them or by using the context menu.
In the list on the right side only the tags that will not produce an empty search result will be shown (this calculation does not take other types of search into account yet). So if you select a tag, the list of tags on the right will be significantly reduced.
Search Similar Packages
(Similar Search)
You can search for packages similar to another package using this search. To do this select the tab Similar in the top-right pane. The search will find packages similar to the one you select. Similarity is calculated based on how similar the descriptions and other aspects are.

This plugin calculates scores for the result packages, based on the degree of similarity.

Search by Pattern
(Apt Search)
On the left side below the Search for pattern text you can enter on or more patterns seperated by a spaces. If the "Search Descriptions" option is not checked, only the package names will be searched for the patterns, otherwise the descriptions will be searched too. All the patterns you have entered must be found.
You can search for exact phrases enclosing them with double quotes and you can exclude patterns or phrases by preceding them with a minus ('-'). The use of wildcards or regular expressions is not supported.
Note: The search uses an index of the packages as backend. This database should get updated on a weekly bases (see apt-xapian-index for more details). So the search results might not contain the latest changes to the archive.

This search calculates scores based on how well the search patterns where matched. Exact matches and a high number of matches results in higher scores.

Search by Filename
(Filename Search)
With this search you can search for patterns in filenames contained in the packages. You can enter the pattern on the right side under the page Filenames. You can check the search installed packages only option if you want to search only in the packages locally installed. This is generally faster than searching all packages.
Additional information: Searching installed packages only uses dpkg -S as backend, while searching all packages uses apt-file search.
Search Orphans
(Orphan Search)
This search allows to search for orphaned packages. Orphaned packages are packages, were no other package depends on.
Additional information: The orphan search uses deborphan as backend so make sure it is installed on your system.

Additionally you can select to search the installed, upgradable or not installed packages only.

The Result View

The bottom left pane shows the results of your current search. The result contains the packages matching all the searches you have specified. The packages are shown with some short information in the list on the left.
If you select a package you can view its details in the bottom right pane. You can either select a package from the result list, or choose it from the dropdown list above the package information.
The result list contains a special column named Scores. This column shows a value, indicating how likely it is, that you where searching for this package. To sort by scores, simply click on the head of the column (like you can do it with all the other columns). The scores are calculated based on criterias offered by the plugins. This can be based on the degree of a match between an active search and the packages found, or data independend of the search (like popcon data).
You can right-click on a package (request a context menu) in the result and choose an action to perform on it (like installing and removing).

Configuring Debian Package Search

Different settings can be customized for packagesearch. The main settings dialog can be reached through the Packagesearch -> Preferences menu.

The columns displayed in the list on the bottom left can be modified by selecting Customise Columns from the context menu of the list. The order can be changed through drag-and-drop.

All settings made within packagesearch are be saved in the file $HOME/.packagesearch.

The Plugin System

Plugins can be controlled through the plugin menu. They can be enabled/disabled through Plugins -> Control Plugins.

The following table shows the plugins distibuted with the application. For information about external plugins consult the documentation distributed together with those. The table lists the search and information types offered by the plugins.

Apt Plugin
  • search by pattern
  • calculate scores based on how well the packages match the search patter
  • show package description
  • show information like author, installed version, available version etc in the detailed section
  • search by installed status
  • show installed status in the package list (i inidicates installed, and u upgradable)
  • allows to install and remove packages
Debtags Plugin
  • search by tags
  • search packages similar to an other
  • calculate scores based on how similar the packages are to the selected one
  • show the tags for packages in the detailed section
Filename Plugin
  • search by filenames
  • show filenames for packages
    The filenames for the packages are displayed in the bottom right under the Files tab. It is possible to view the files by double clicking on their entry or by choosing View file from the context menu. Viewing files depends on the settings in your mailcap file ($HOME/.mailcap and /etc/mailcap).
Orphan Plugin
  • search for orphaned packages
Screenshot Plugin
  • displays screenshot for the selected package
    Screenshots are loaded from http://screenshots.debian.net

Other Plugin Specific Notes

Debtags Plugin

To reduce the complexity of the list of tags, you can hide facets (groups of categories) you are not interested in. Go to Packagesearch -> Preferences and select the Debtags tab there.

Apt-File Plugin

From time to time you should update the file database which is used to perform searches for files. It can be updated either via the command line (apt-file update) or using the GUI choosing System->Update File Database.

If you have further questions please contact me at bensmail@gmx.net.


Date: 2012-05-12
packagesearch-2.7.11build1/doc/index.html0000644000000000000000000001327013507430555015126 0ustar Help - Debian Package Search

Debian Package Search Help Page

This tool is aimed to help you searching the packages you need. It should make the task of searching a pleasant experience. Originally I designed it for the purpose of finding a single package where you have a clear imagination of what you want. But you can also use it to simply browse your packages to explore. Perhaps there is something in the database that you simply must have :-).
The program is not meant to be a package managment tool like synaptic. This is far beyond its purpose. It is not able to install a single package, but if you have found the one you where searching for, you can simply type "apt-get install packagename" and install it.

The program consists of the main dialog only. The main window is split into two parts:

  1. The upper part where you can enter the search you want to perform.
  2. The lower part which shows the results of your current search.

A More Detailed View on the Search

In the upper pane you can enter the search criterias you want to perform.

There are three main criterias you can use for searching:
Search by Categories
(Debtags Search)
The debtags search is based on the debtags system developed by Enrico Zini. The main idea behind it is, that every package is characterized by a number of categories called tags. Each package is given a number of such tags. E.g. the image editor gimp is tagged by junior, media, media::rasterimage, suite, uitoolkit, uitoolkit::gtk.
You can select the tags you want to search for on the right side under the page Debtags. If you want to exclude some tags, check the Exclude Tags box, and a second list will appear. Here you can select the tags you do not want to have on the package.
The tags are organized in a hierarchy, where each tag is inside a so called "facet". As tagging is still under development, not all tags are inside facets yet, but this will change in time.
The tags you selected will be showen on the left side were you can easily remove them again.
Search Related Packages
(Related Search)
You can search for packages related to another package using the related search. You can select this on the right side under the page Related. Here you can enter a package name. The search will find all packages which have similar tags as the given one.
The packages may only differ in the number of "Maximum Distance" tags from the one you entered.
Or more formal:
|(A union B) difference (A intersect B)| <= MaxDistance
Search by Pattern
(Apt Search)
You can enter a pattern to search the package names and descriptions for on the left side below the Search pattern text. The names of all packages available will be searched for the expression you enter there. If the "Search Descriptions" box is checked, the descriptions will be included in the full text search.
Note: Currently the use of regular expressions is not supported.

Additionally you can select to search the installed or not installed packages only.

The Result View

The bottom pane shows the results of your current serach. The result contains all packages matching all the searches you have specified, i.e. debtags search as well as related search as well as apt search. It shows the results in realtime, i.e. every change you perform in the search will be evaluated immidiately (except if you type a text, where it delays the evaluation a little to see if you will type another character). The packages are shown with a short description in the list on the left. If you click an item a full description will be shown in right pane. There you can also choose to see some details like: dependencies, author,...
You can right-click on a package (request a context menu) in a result and choose to generate a apt-get line for it. This creates a line apt-get install packagename and copies the content to your clipboard. Note that this is not the clipboard available via the middle mouse button but the other clipboard often accesable via "Ctrl+C".
In the details view can browse the dependencies by clicking the underlined packages.

Additional Features

You can perform a debtags update via the GUI. This updates your tag database. This is where the information about the tags that are assigned to each package is stored. For accessing this functionality choose System->Debtags Update from the menu.

If you have further questions please contact me at bensmail@gmx.net


Powered by
SourceForge.net Logo

Date: 2004-07-13
packagesearch-2.7.11build1/doc/programming-guidelines.html0000644000000000000000000001446213507430555020473 0ustar Packagesearch Programming Guidelines and Hints

Policy for Plugins

Main Identifier: Plugin Name

Additional Information:

  • Author

  • Version

  • Location (Path, derived from library location)

    • Implicit search path order: plugins/, ../plugins/, /usr/lib/packagesearch

    • If more than one version is available use the one appearing first in the search path

Plugin file names must be of the format: lib<pluginname>.so

Internationalisation i18n

Uses QT-Translation mechanism.
  •  translation files located at packagesearch/translations/
  • one file per plugin, one for main application, names: <pluginname>_<lang>.ts
To add a new language
  • add reference to "ts"-file to each .pro file (i.e. each plugin and packagesearch.pro)
  • run lupdate packagesearch.pro and lupdate plugins/plugins.pro
To compile the translations:
  • run make debug or make release within packagesearch/


Naming Conventions

  • Typenames/Const
    • typenames start with a capital letter - each word in it again
    • constants are written in capital letters, different words are seperated by an underscorde _
  • Variables
    • varibles start with a lower case letter
    • member variables start with a underscore _
    • pointers start with a p
  • Filenames
    • filenames and directories are written lowercase without underscores
    • Source files .cpp, Headerfiles .h
  • Functions
    • if the functions argument list goes over more then two lines, the closing braclet will appear on a separate line and the line with the function name will not contain  a parameter  e.g.
// this is OK
func(aVeryLongVariableName1, aMuchMoreLongerVariableNameWhichFillsAllTheLine2,
aVeryLongVariableNameWhichIsReallyLong3, aVeryLongVariableNameWhichIsReallyLong4);
// if more than this:
func (
aVeryLongVariableNameWhichIsReallyLong1, aMuchMuchLongerVariableName2
aVeryLongVariableNameWhichIsReallyLong3, aMuchMuchLongerVariableName4
aVeryLongVariableNameWhichIsReallyLong5, aMuchMuchLongerVariableName5
);


Documentation

  • tool tips and status tips start with a capital letter, all following words are  capitalized normally e.g. "Choose a package"
  • What's this consist of normal text (i.e. sentences)

User Interface

  • options listed are to be formated as tool tips i.e. with a leading capital character an the rest capitalized normally    

Doxygen

 Doxygen comments look like this:
    /** @brief This holds the package collection ready to be used.
      *
      * Use the output function for your consumers
      */

 If they need only one line the closing */ must be on the same line:

    /** This manages the include widgets (but not the labels belonging to them. */


Includes

    #include <...> proceeds
    #include "..."
    include order:
     - stl includes
     - opengl includes
     - qt includes
     - other global includes (those with <>)
     - the corresponding header for the cpp file ("xmldata.h" for xmldata.cpp)
     - other local includes
    Grouping:
     - local includes from the same namespace are grouped together (followed by an
       empty line
     - includes from the same external library or directory are grouped together
     

Saving

    Saving happens in XML
    Error handling:
        - if something wasn't loaded properly we will try to set a reasonable default value
        - We will not go to the next entry if loading of an element failed, so if there is a
          broken tag (e.g. wrong spelling) this will break all following parts. This is done
          because if we added a new item in the DTD and we have an incorrect XML file where
          this entry is missing, it will use a default value and the next tag will read the
          correct entry.

    Saving in packagesearch:
        - comments in the configuration file are not allowed



packagesearch-2.7.11build1/doc/requirements-test-framework.html0000644000000000000000000002635713507430555021524 0ustar

Test Framework

Launch through single command

Compile in one run

QMake-able

Easy to write tests
++/+/o/-/--

Test grouping

No test registering required

Useful fail messages

QT-Test

x

x

x

+

x

-

x

QUnit1
(seems to require << operator for each tested datatype)

x

x

x

+

x

-

x

TUT2
(no macros!)
lasst version 12 month ago

x

x

x

+

x

x

x

Unit++3
(no activity since 11 month)

x

x

x

+

x

-

x
(I believe so..)

cutee4

?

?

-

?

?

?

?

cppunit5

x

x

x

-

x

-

?

UnitTest++6
(no activity since 10 month)

x

x

x

++

x

x

x


Criteria:

Must

  • tests can be launched through a single command

  • possiblity to compile all test together

  • compilable with qmake

  • easy to write tests

  • no explicit test registering (except for naming the files containing tests)


Should

  • useful error mesages if assertion fails

  • easy setup of compilation


Criteria: Easy to write test:

  • Simple test should have no more than 10 LOC

  • Test for equality available instead of only asserts

  • Rich set of assertion functions

  • Readable syntax

  • Good documentation

Useful fail messages

  • Provide a mechnism for printing the values of a comparison if compare failed



1http://qunit.sourceforge.net/

2http://tut-framework.sourceforge.net/

3http://unitpp.sourceforge.net/

4http://codesink.org/cutee_unit_testing.html

5http://cppunit.sourceforge.net/cppunit-wiki

6http://unittest-cpp.sourceforge.net/

packagesearch-2.7.11build1/doc/uml_models/0000755000000000000000000000000013507430555015266 5ustar packagesearch-2.7.11build1/doc/uml_models/architecture.xmi0000644000000000000000000053506313507430555020503 0ustar umbrello uml modeller http://uml.sf.net 1.5.8 UnicodeUTF8 packagesearch-2.7.11build1/doc/uml_models/debtags-ui.xmi0000644000000000000000000045366613507430555020055 0ustar umbrello uml modeller http://uml.sf.net 1.5.3 UnicodeUTF8
packagesearch-2.7.11build1/doc/uml_models/taglistview.xmi0000644000000000000000000126077713507430555020373 0ustar umbrello uml modeller http://uml.sf.net 1.2.0 UnicodeUTF8
packagesearch-2.7.11build1/doc/uml_models/vocabulary-model.xmi0000644000000000000000000006275513507430555021271 0ustar umbrello uml modeller http://uml.sf.net 1.5.5 UnicodeUTF8 packagesearch-2.7.11build1/homepage/0000755000000000000000000000000013507430555014146 5ustar packagesearch-2.7.11build1/homepage/content.html0000777000000000000000000000000013507430555022023 2../doc/content.htmlustar packagesearch-2.7.11build1/homepage/img/0000755000000000000000000000000013507430555014722 5ustar packagesearch-2.7.11build1/homepage/img/debian_log_transparent_bg.xcf0000644000000000000000000050441313507430555022607 0ustar gimp xcf fileBB/ gimp-commentCreated with The GIMPS gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches)  Pasted Layer      i)9IYiy"&&&'(V()*14h4x4449;Y;?yCEF FIMMPTzTTX[\c@cPc`cpcccdjpjomq u{Qz%5EafO2ԗԧԷB^n#   *K[!'t''',03a3q3336&66>7E|JPVcVsVVX_` ``)bklr{wWgw={J(֓AI/?Okgw  Y i y &&/////00H12222223 9h?@$@4@D@T@d@t@@@@@@@@EHNVNfNvNNNNNNNNOOO&O6TZ]r]]]]]]]]^^^"^2^B^Rch}lll%l5lElUlelulllllllpgv}}}}}}~~~/~?~O~_~o~~~7o?;97?;{9{7{?;]9]QQ7]QQ?";"9"8"=98531 . ,*'%#!!#%'), . 0 2468:={)9k895{3k19 .{ ,k*J'{)%k#J!){kZ!9#)%{'k)k, J. J0 )2)4)6)8{:{=i9ݗQQ8tQQ5]QQ3їQQ1tQ Q.]Q Q,ݗQQ*QQ'iQQ%QQ#рQQ!iQQ]QQQQыQ!QtQ#QiQ%Q]Q'Q]Q)QQ,Q рQ.Q Q0Q iQ2QiQ4QiQ6QiQ8Q]Q:Q]QQ="985 3 1 .,*'"%#!""$&"'")-/ 1 3 579":"=,:865 "$&)+ . 02579=,:k98J6){5{Μ{k l{J9){{J{Z")$k&J){)+ k. 90{2Z5)7k9J=,:t8рQQ6iQQ5]QQݺїQQ ѮQQtQQiţ]QQ]QQыQ"QiQ$Q]Q&QŀQ)QiQ+Q ݗQ.Q tQ0Q]Q2QыQ5QiQ7Q]Q9QQ=Q,":"87"6" " ""#%"&*,"- 1 368"9~d.* & # !#$&( ,};;d{{Zk.l{JJ*޽{kJ {&Μ{J k#kJk Μ{9JΜ{JJJJ)!#{$k&9({޽{ {J{kJ)J{ޭ{JJZ{J),J};J;d.ѮQQ]*ѣQ Q]&ݺ]Q Q#ѮQQ ݺtQQݺQQQQQi!Q]#Q$Q&Qt(Q]ţ Qѣ]QQiQ]ţ]QQQiQ,QQ}Q]Q;QQ;QQQd"." +"&"#! "$"$')" <"8* #)2x5- - 14640  ( -2,' $#" i8ν{*ν{{JJ{ ν{{kJJ9)JJZ{{ス{{kJJ9JJ{{#ス{{ZJ)Jk{)k)Z2ν{{JJ{x{{5έ{Z99JJ{-έ{J) 9Z-{Z {1{)4Z6OZ{4ޭ{J0ν J {J)k( J{-9{2Z,޽Z'{kJ {$ޭ{Z)#ޭ{J{J{J)"9JJ{ {ZJJi8Ѯ*ѺQ ѮtQiѺt#ѣiQQ)iQQ]2ѣxѣ5ţtQQt-ţiQ Qt-ѣ]Q Q1ݣiQQ]4]QQ]6݄4ţQQ0Ѻ  i( Q-Qt2Q,Q'ţ]Q Q]$ţiQQ#ţ]QQѺ]QQiQ"Qt ]QiQ8+!"#"*3y "5.."2 5751 " "("- 3- "'%# T=:752 /     9<T={){:97J5)Z2k Z/ ZkJ{{ Z J{JZ )k{9 9){)Zk9Z<9{T=i:QQt7QQ5iQQ2Q Q/Q QQQQ] Q QQQ QiQQt QtQQiQiQQ]9Q;{;{Q]Q;Q":751. *)' * -& :9850 * "& , 0369;}k:Z7Z5Z1k.J{ *){){J'{ ΌJ*Z ޜZ-ޜk)&{{J Z:)9{8J5J{0)Z{ *J{ "9Jk{JZ{{9k{& )k, Z0Z396k9{;}Q]Q:QQ7Q5Q1Q].Q *Qi)QѣQ'Q ݮQ*Q 躋]Q-Q躗iQQ]Q&Qţ]Q QQ:QiQ9Q8Q5Q0Qi *Q] "QtQ]Qt& Qi, Q0Q3Qt6Q9];} >:"7"4"1 -"*,/ 37""<;":84 /" ) '- 1 "3"6:";"}>9641 / ,*(&%#!  "#%'(*, . 0 1468::::;>){9Z6Z4Z1){ /Z ,k*{({&{%k#J! {9Z )"{#J%'{(J*), ). {0 )1)4J6k8)::{:9:k;>QiQ9QQ6Q4Q1Qi /Q ,Q]*Q](Q]&Q]%Q#Q!Q] QQtQ]Q Qi"Q#Q%Q]'Q(Q*Qi, Qi. Q]0 Qi1Qi4Q6Q8Qi::]QQ:Qt:Q;~9"6"4 1 /,"*"("'%#!"  !#"#&("(+-/ 1 "1 579":"":;":"; 566779: 09Z{9Z{ J{kJ{9kJJ{9{ތ{{{{5k{6ތJk69Z7k){7JJ9{k: 0QttQQ] QQQQtQt讣ѣ56讀6t7ݗi7݀9: 0  """"5"77"88:; 1 &, 16; {ZJ&޽{k9,έ{J 1޽{Z)6{J;Μ{9 ţQQ&ѣtQQ,ţ]Q Q1ѣiQQ6ţ]QQ;ݺt &,1 6";:62 .+'$!"%(*- / 2 469;<{J:{J6{92 {).ތJ+k)'{9$ތ9!Jތ9"ތ9%{(k*9-k /) 2k 4{6)9J;J@=<;:9876543 2 1 0 0 /.-,+*))('&%$##"! @k={<;:9876543 2 91 90 J0 k/{.-,+*))9)k({'&%$9#Z#{"! )J@=Q<Q;Q:Q9Q8Q7Q6Q]5Q]4Q]3 Q]2 Qt1 Qt0 Q0 Q/Q.Q-Q,Q]+Q]*Qi)Qt)Q(Q'Q&Q%Q]$Qt#Q#Q"Q!Q] QiQ@==<;:9876 5 4 "2 "1 "0 10/.-,+")*)('&%"#$#"!"     ?=<<<;;;;:75443 3 2 2 1 0 0 / / . .--,,,++**))((''?=k<<. . )/ 90 {1 2 293k455J677J899{:;J;<J<=J >Q.Q ]Q.Q iQ/Q tQ0Q Q1Q Q2Q ]Q2QtQ3QQ4QQ5Q]Q5QQ6QQ7Q]Q7QQ8QQ9Q]Q9QQ:QQ;QQ;QQQ0 1 "0 2 3 4 5"467889::;":<===  :87642 1 / . ,+)('%$ k:J8)76k492 1Z / .Z ,+Z)(9'{%$J QQ:QQ8Qi7Q]6Q4Qt2Q] 1Q /Q] .Q ,Q]+Q)Q](Qt'Q%Q]$Q >;97"64 3 1 /" .,"+*('%":86532 1 / . -+*)(&%$#"!  "! ' , 0358:}:k8965J32J 1 /9 .k -+)*J)k(&%9$9#Z"k!k  {J)JJ{{{Z){Z)"! k9)J9)Z{' k, ){0k3)5J8k:k}:Q8Qt6Q]5Q3Q]2Q 1Q /Qt .Q -Q+Qi*Q)Q(Q&Q]%Qt$Qt#Q"Q!Q QQQQQ] Q]Q]]Q]iQQQ]݀QQQ]QQ]Q]]QQQ]QQQiѣQQi"Q!Q QQtQ]QitQQQi' Q], Qi0Q3Qi5Q8Q:}<:875 4 2 1 /" .-+"*)('%"$"#"!  ! """ #"#"! " (- 1 4"59;~56789:<<= 5{678999:k @<;:987654 3 2 1 0 /.-,+*)('&%$$#"!  !"##$%&'(()*+,,-./ / 0 @<;:9998979695Z4 k3 k2 k1 k0 k/k.k-k,k+9*9)9(9'&%$$#"k!k 99 !"k#J#9$%&'k(9()*+k,9,-./J / 0 @Q]Q=+**))(('&&%%$$##{+*k*)J)()('&{&%k%$k$#k#+]*Q*Q)Q)Q(Qi(Q'Q]&Q&Q]%Q%Q$Q$Q#Q#+++**))("&'&&%%$$"===3222223 2233343343444556789::!=<<;"===Z{J){3J992J{2J{2J2J2)3 k223k3{3J)433{k49394{4)J45Z95{6k798J{9:)9:k!=J<#{! J{9Z {"#)$9%k'()*9+J,k. {/ 0 1 239495Z6k8k9k:;<>#Q!Q] QQQ]QtQ Q"Q]#Qi$Qt%Q'Q(Q])Q]*Qt+Q,Q. Q/ Q0 Q]1 Q]2Q]3Qt4Qt5Q6Q8Q9Q:Q;Q<>$#!"  " #$%"%()*+,",/0 1 2 3 4"4"5"69:;<=>1 2 2 3 45567789::;<;<== 1{ 2J 2 3 4{5J567Z7)89{:9:;= ==<<;::9887765544 3 2 2 1 1 0 / / ..--,,++**))((''&&%%={=9<<{;9::k988J77{6)55J44 {3 2 2 91 1 k0 / {/ .{.)--9,,J++k**k))k((k''k&&Z%%Q]Q=QQ=QtQ<<=>{kZ 9 )!"#$%k&J'9'()*{+k,9,-. / {0 J1 )1 2 3{4J5567k8989:k;9;<><QQQQ Qt Qi!Q]"Q#Q$Q%Q&Q'Qt'Q](Q)Q*Q+Q,Qt,Q]-Q. Q/ Q0 Q1 Qi1 Q]2 Q3Q4Q5Q]5Q6Q7Q8Qt8Q]9Q:Q;Qt;]<>  !" "!#$%&'("')*+,-",./0 1 2 "1 3 4 56"5789"8:;<";=>"<"<=> :87531 / -+*(&%#"  !"$%&' :k8J7)5)3)1) /) -J+k*{()&J%{#9"{ 9{9{ Z!)"$Z%)&' :]Q8QQ7iQQ5iQQ3iQQ1iQ Q/iQ Q-рQQ+QQ*]QQ(iQQ&݀QQ%QQ#tQQ"QQ tQQQQtQQQ QQ!QiQ"QQ$QQ%QiQ&Q]Q'Q ":975 3 1 /-+"*(&%#" !"""%&"&)*s(" %) , 0258;{51, ($!"%(*s{{Z({J9"Μ{ZJޜ{Jޭ{J {9%ΌZ) k), Z0k2k5{)8Z;){J{59k1J{,9{ ()k$Z!9{Z9){"{%k({*s(tQQ"ݺQQ躣QQţ]Q QţtQ%QݮQ)Q iQ,Q Q0Qŗ]Q2Qї]Q5QiQ8QыQ;QiQ{QQ5Qt1Q,Qt (Qi$Q]!QtQQtQi"Q]%Q(Q]*s" )"!&)- "/ 369<5 0+"($ ""#&)"*@ -$ %)- 0 369<=# 06;?@ J{-)J{{$JZ{ )k%9{)){-Z 0){ 3{6){99<Z=)JZ{{{{J{#޽{{ZJ 0޽{Z96{J;ޜk)?@ -Qi$Q] Qi%Qt)Qi-Q 0Qi 3Q]6Qi9QtR"($06;@ @<:864 2 0 .,*('%#" "$%'))+ @<k:J8)6)4 )2 )0 ).),J*k({')%J#"9 {9ޜk){ޜZ9"Ό9$ތ9Z%ތ9)'{){){J)9+k @======  ! " !!"""#$%&&&'&&'&''&''''&'''''''(''(('(('(('(        J J J J ! ") !)!")""#{$J%k9&&J&9')&{{&)'k&{')'&k'k''9Z'&'kZ'')'9''Z'Z('k'k()({'{(9)('(99('(ZZ   ZZk )  Z{ {) 99k{J9ZQ QQ Q Q Q!Q Q"iQQ QQ!iQQ!QQ"iQQ"QQ"]QQ#QQ]$QQ%QQt&QQ&QQ&QQt'iQQ&QQ&QQi'QQ&QQ'iQQ]'QQ&]QQ'QQ]'QQ'tQQ'QQ&]QQ'QQ'QQ'iQQ'QQt'QQ'QQ'QQ(]QQ'QQ'QQ(iQQ](QQ'QQ(tQQi(QQ'QQ(tQQt(QQ'QQ(QQ QQ QQ QQ iQQ] QQQ QQQ QQQi QtQQQtQQQQQQQQ]QtQQQQQQQQ ! ! " ! " " # # #"$%&'''(''"('(('"(((("&"(("'(((()"'())())())(") " "   "   "    "!""""   !!!"""###$$$%%%&&&'''((()))***+++,,,----... / / / 0 0J"9!J"{{")""9k{JJZ{9{{J Z 9 !)!{)!"{"k)"#{#)#${$)$%{%%&{&)&'{')'({()(){)))**9*++9+,,Z,--k--.{.). / {/ 9/ 0 0QQQ"QtQ!QQ"QQ"QiQ"QQ"QtQQ]QQ]QQQQQQQQQQQQtQQQQQQQQQQQQQ QQQQ QQQtQ QQQQ!QQiQ!QQiQ!QQQ"Q]Q"QiQ"QQ#QQ#QiQ#QQ$QQ$QiQ$QQ%QQ%Q]Q%QQ&QQ&QiQ&QQ'QQ'QiQ'QQ(QQ(QiQ(QQ)QQ)QiQ)QQ*QQ*QtQ*QQ+QQ+QtQ+QQ,QQ,QQ,QQ-QQ-QQ-Q]Q-QQ.QQ.QiQ.Q Q/Q Q/Q tQ/Q Q0Q Q0Q$$%%$"%%%&%"$&%""""###$$$%%%&&&'''((()))***+++,,,---",.."-///000 1 1 1 2 2=;;:;:::9988776655443 3 2 2 1 1 0 0 / / ..--,,++*))((''&&%%$$##""!  =;J;:);::{:9k98k87J76J65)54)43) 3 2) 2 1) 1 0) 0 /9 / .J.-J-,Z,+k+*{)){((')'&)&%J%$J$#k#"k"!{  {{{{=QQ;QQ;QQ:Qi;Q:Q]:Q:Q9Q9Q8Q8Q7Q7Q6Q6Q5Qi5Q4Qi4Q3Qi 3Q 2Qi 2Q 1Qi 1Q 0Qi 0Q /Qt /Q .Q.Q-Q-Q,Q,Q+Q+Q*Q)Q])Q(Q](Q'Qi'Q&Qi&Q%Q%Q$Q$Q#Q#Q"Q"Q!Q Q] QQ]QQ]QQ]Q><=<<;;:"::998877665 5 4 4 3 3 2 2 1 1 00//..--,,+*"*)")((''&&%%$$##"!"! " "" <<;:::98876655443 3 2 2 1 0 / .,+*)('&%$##"!  <) . . / 0 1 2343455677789;<= {) {.J Z.k 9/J 0J 1J {2Jk3Jk493k9499595Z96)97{97)97Z98999;{<= iQ Q.Q Q.ݗQ Qt/рQ Q]0рQ Q1рQ Q2рQQ3рQQ4]QQt3QQt4tQQt5]QQt5QQt6iQQt7QQt7iQQt7QQt8]QQt9tQQ;QQ<]= /".012 3 4 5 "3""4 "5"5"6"7"7"7""8:;"=> @=<<;;;;;;<==@=9<k<k;J{;k;;;9;9Z<9{=k=@=t-...../ / / / / / 00 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 266666666666666666666666666-.).Z.{../ /J /{ / / / 00J 0k 0{ 0 0 0 1 1 1J 1J 1{ 1{ 1 1 1 1 2 2 2 2) 2J 2J 2J 2Z 2ޜk666{6{6{6{6{6{6{6{6{6{6Z6J6J6J6J6J6J6J6J6k6{6{6{6{-QQ.iQQ.QQ.QQ.QQ.QQ/]Q Q/Q Q/Q Q/Q Q/Q Q/Q Q0Q0Q Q0Q Q0Q Q0Q Q0Q Q0Q Q1 Q1]Q Q1Q Q1Q Q1Q Q1Q Q1Q Q1Q Q1Q Q1Q Q2 Q2 Q2 Q2iQ Q2Q Q2Q Q2Q Q2Q Q2躗]QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ-"....."//////00000001 1 1 1 1 1 1 1 1 1" 2 2 2 2 2 2 2 2 2 66666666666666666666666666:9988787668889999:::;;<;;<<===Z9:9999988ZJ78{76k6)8889999Z9::k:;;Z<;;)<<k=={=QtQ:QttQ9Q]tQ9Q]Q8QQ8QQ7Q]Q8QQ7Q]Q6QQ6Qi8Q8Q8Qt9Q9Q9Q9Q]:Q:Q:Q];Q;Q==")*******+*())((('(''&%%$#"!"&''((((((****)Z{Zkk){ZJ{J9{{J9kk{kJ99k{9{kJ)99k){*9Z*{)***k{*Z*)+9*{({)J))k()(ޭ('{('J'&%9%k$#k"!JZ"&k'')(k({((((****QiQ]QQQQ]QQQ]QQQ]QQQQiQQQQQQQQQQtQQQQQQtQQ]QQQQQQQt]QQQQQQtQQQQtQQQ]Qitt]QQ)Q*t*i*Q*]***i+t*(ţ)i)Q(Qi(QQ(QQ]'QQ(Q]'Q'Q&Q]%Qt%Q$Q#Q"Q]!Q"Q&Q'Q'Qi(Q(Q(Q(Q(Q(Q*Q*Q*Q*"""""*"*++"*+++,"*"())())"')(('"%&%$ # "! #'(())))))**** 0 1 1 1 1 2 2 2 3 3 34445555666665554444 5 3 3 3 3 3 3 3 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 J0 1 1 Z1 1 2 k2 )2 3 {3 9344J455k556{6)6J66J55594{444 5 J3 Z3 {3 3 3 3 3 4 4 )2 J2 J2 J2 J2 J2 k2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 {2 Q0Q Q1Q Q1Q Q1Q ]Q1Q Q2Q Q2Q iQ2Q Q3Q Q3Q tQ3QQ4QQ4QQ4QQ5QQ5QQ5Q]Q5QQ6QQ6QiQ6QQ6QQ6QQ5QQ5QQ5QtQ4QQ4QQ4QQ4Q 5Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q 4Q 4Q iQ2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q 2 "1 3 3 3 4 4 4 5 5 5666"57778888877"5666"4 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4  !!""##$$$%%&&&'''(((())))+*******,,,+++++++++--,,,,,,,,..----{  k!!k""9##)${$$Z%%&{&&)'{'')(k((())k)))+9*Z*{*****,,,J+J+J+{+{+++++--J,J,Z,{,{,,,,..J-J-{-{-Q]Q Q Q!Q!Q"Q"Qt#Q#Qi$Q$Q$Q%Q%Q]&Q&Q&Qi'Q'Q'Qi(Q(Q(Q(Qi)Q)Q)Q)Q+Qt*Q*Q*Q*Q*Q*Q*Q,Q,Q,Q+Q+Q+Q+Q+Q+Q+Q+Q+Q-Q-Q,Q,Q,Q,Q,Q,Q,Q,Q.Q.Q-Q-Q-Q-"!!""##$$%%%&&'''((())))****++++++++,,,,,,,,,,,,----------......      J{)){{Z{))Z){k{)9JJ{)JkJ9J){9k{)Z{) ){kZ  kk) Z{9 9{) {J)kk{JkJZQQQQQQiiQQQQ]QQ]QQ]QQQQ]]QQQQiiQQQQiQQQQQQ]QQQQi]QQQQtQQQQQQiQQQQQQQQQQtQQQQiQQtQQ]QQQQiQQQQQQi iQQQQQQ ]QQQQ] QQ]QQQQi QQQQQQt tQQQQQQi ]QQQQQQiQQQQQQQQQQQQQQ]QQQQ]QQ!!!"!!""!"!      " "   "    !  ! ! " ! " !  !    "" ! 977754443  997)k7{75k4{4k4)J3J  t]9]QQ7iQQ7QQ7QQ5QQ4QQ4QQ4iQQ3QQ  :8"8765"5 5 4 66666666666666666667777777777777777777777777777777777777777777766{6{6{6{6{6{6{6{6{666666666677777777777J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J7J777777766QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ6QQ7Q7Q7Q7Q7Q7Q7Q7Q7Q7Q7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7QQ7]QQ7Q7Q7Q7Q7Q7Q6QQ6666666666666666666777777777777777777777777777777777777777777776Q**((((((((())'''''(&&&%%%$          ! !!""###$$$**(((({({({(J(J())''{'Z'9'(&{&J&%%J%$J{{)){kk )9{){)J  k  9   k  ) {  Z! !!k"")#k##$k$$Q*Q*Q(Q(Q(Q(Q(Q(Q(Q(Q(Q)Q)Q'Q'Q'Q'Qt'Q(Q&Q&Q&Q%Q%Q%Q$QQiQiQݗ]QQ QiQQQQtQQQiQQQiQQQQ Q] Q Q Qt Q Q Q Q Qi Q Q Q! Q!Q]!Q"Q"Qi#Q#Q#Q]$Q$Q$**)))))))))))(((((('''"%&&% "" ""   " ! ! ! " " "! # #$$$%%% 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 5 5 5 5 5 5 5 {2 {2 {2 {2 {2 k2 J2 J2 J2 J2 J2 J2 J2 J2 J2 J2 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 {3 {3 {3 {3 {3 {3 {3 {3 {3 k3 J3 J3 J3 J3 J3 J3 J3 J3 J3 J3 J3 J3 5 5 5 5 5 5 5 5 Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q Q2Q 4Q 4Q 4Q 4Q 4Q 4Q 4Q 4Q 4Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q Q3Q 5Q 5Q 5Q 5Q 5Q 5Q 5Q 5Q 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5---//........0 / / / / / / / / 1 0 0 0 0 0 0 0 0 2 1 1 1 1 1 1 1 1 3 3 2 2 2 2 2 2 2 2 4 4 3 3 3 3 3 3 3 3 5 544---//).J.Z.{.{....0 )/ J/ Z/ {/ {/ / / / 1 )0 J0 J0 {0 {0 0 0 0 2 1 J1 J1 {1 {1 1 1 1 3 3 92 J2 Z2 {2 {2 2 2 2 4 4 J3 J3 Z3 {3 {3 3 3 3 5 5)4J4Q-Q-Q-Q/Q/Qi.Q.Q.Q.Q.Q.Q.Q.Q0 Qi/ Q/ Q/ Q/ Q/ Q/ Q/ Q/ Q1 Qi0 Q0 Q0 Q0 Q0 Q0 Q0 Q0 Q2 Q]1 Q1 Q1 Q1 Q1 Q1 Q1 Q1 Q3 Q3 Qt2 Q2 Q2 Q2 Q2 Q2 Q2 Q2 Q4 Q4 Q3 Q3 Q3 Q3 Q3 Q3 Q3 Q3 Q5 Q5Qi4Q4.../////////".00000000 "/ 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5=========<<<<<<<<<<<<===<;;;;;;;;;;;;;;;;;;;;;;;;;==={={=J=J=9==<<<<<{<{<{======== $%%%%%%%%%%%&&&&&&'''''''(&&&''(&&'''('''('''()'(('(((((((())()) $9%%%%%%%{%{%Z%J%9&&&&{&k&J'''''{'J')()&J&{{&J''({)&ZJ&{'''k()J'{''Z('Z'k{')(){J'9{(('ZZ((()(k({((Z(k))Z(9))k $Qt%Q%Q%Q%Q%Q%Q%Q%Q%Q%Q%Qt&Q&Q&Q&Q&Q&Q'Q'Q'Q'Q'Q'Q'Qi(QiQ&QQ&QQ&QQ'QQ'Q(QiQ&QQ&Q]Q'QQ'QQ'Q(QiQ'QQ'QQ'QQ(Q]Q'QQ'QQ'QiQ(Q)QQ'QtQ(QQ(Q]Q'QQ(QQ(QQ(Qi]Q(QQ(QQ(Q]]Q(QQ(QQ)QQ)QQ(QtQ)QQ)Q %%%&&&&&&&&&&'''''''"((((()))))*)))***)****"***+**++*+++++++++""*+,, =<<;;:;;99:::;;:<?=J<= ? - - .                               55568:;<<=)kZkνZ J-9 - ). {    )k k {  9{k 9 kk  kZZ  99 k 99  99) 9 J { {k 9k{Z k9 {) 9{ J J J )9k J)Z k Z{{) )J{   {J kJ{ J99J) 9Z{9{ k9k kJk{{ZZ)k9{9)99{k999kJk{)9kk{{)9{959595996989:k;k<{<=iQQŗQQQQQ Q-tQ Q-]Q Qi.]Q Q  Q Q] iQ Q Q]Q Q tQQQ Qt QQQ Q QQQ Q] ]QQttQ Q QQttQ Q tQQtiQ Qt QQ]Q Q QQ]QQ] tQQ]QQQ QQ]tQQ QQ]QQi tQQQQ ]QQQQ QQ]]QQ QQ]QQ iQQtQQ] QQiQQ QQQQ QQQQi iQQQQ QQ ]QQ QQ]QQ QQ]QQ QQttQQi tQQt]QQ ]QQtQQ QQ]QQQQQQQQQQQQiQQ]]QtQQtQQiQQ]QQ]tQQtQQ]QQtQQttQQQQ]QQ]QQQQ]QQQQQQ]QQQQQiQQtQQQQQQ]]QQQQ]QQ]Q]]QQ]]]QQ]i]QQtݣ]QQt5]QQt5]QQt5tQQt6tQQ8tQQ:QQ;QQ !!"#$%'()*+,-. / 0 0 0 0 0 0 1 112222 1 0 /.-+*)('&&%%!   !!"#$%'()*{+k,k-k.9 / 0 0 0k 09 0) 0 1{ 19192{92992J2 k1 k0 k/.-+*9)9(k'k&&%%9!Z {{Jk)k99Z9{{Z)999k9k999{kkkk9) QQQ Q!Q!Q]"Q]#Q]$Q]%Q]'Q(Q)Q*Q+Q,Q-Q.Qt /Q] 0Q] ]Q0Q ]Q0Q ]Q0Qt ]Q0Qi ]Q0Q] ]Q1Q ]Q1Qt]Q1Q]tQ2QtQ2QttQ2Q]Q2Q Q1Q Q0Q Q/QQ.QQ-Q]Q+Q]Q*QtQ)QtQ(QQ'QQ&QQ&Q]Q%Q]Q%QtQ!Q]QQQ QQQQQQQQQQQ]QQiQQtQQ]QQtQQQQtQQQQ]]QQQQ]iQQtQQtQQt]QQQQt]QQQQtQQt]QQ]QQ]tQQ]QQQQ]QQQQ]QQ]QQtiQ Q  !"#$%&'()*+,-."/" 1 2 3 4 4" 5 5 5 6 6 "4 "5"4 "3 3 2 10/.-,")"())))"'"'! """"""""""""" "   "=<:9764 3 1 / .,*)'%#!!#&(*,/ 2 47:<>={<9:{997{694 {3 J1 {/ ).J,{*)J'k%k#{!{{!){#k&k(J*),k/) 2Z 4{79:9{<){>=Q<Qt:Q9Qt7Q6Qt4 Q3 Q1 Q/ Qi.Q,Q*Q])Q'Q%Q#Q]!Q]Q]Q]!Qi#Q]&Q(Q*Qi,Q]/Qi 2Q 4Q]7Qt:QtQQ==;:87 5 4 2 "//-"**(&"#"!""!#"&(*,"/1" 4 7:==:=k:=Q]:=;6:0-,)&#6:{)0Zk-)J{9,k)J&Z#Z6:]i0ыQQ]Q-iQQtQQ,]QQ)QQ&QQ#QQ6":0".",)"&"#"<:99888777777,++*( '&%$#"!  !#$&(*, . 1369<{9:J99k8988{7k797)777k,{)9+kk+k{*k9k(Z '9&9%9$9#"! k9{ 9!{#$J&J(J*), {. Z1{3ތ96{99{)=<::9988741.+ ( ' %)'%" "$('%$"""###$$%%%$#"" "&),/ 36{=<::k99J8J8k)7{)4k{)1)k.{k+{ k(J Z'Jk k%{9)k)'ΌJ%k)"kΌJ 9Zޜ{9"{Zk$ޜ{99('Z%$k"))")Z"J#JJ#k{#k)${J$)k%Zk%{k%J){$k){#9Z"{)9{"ZJ{ 9"ތ9&{)){),Ό9/ޜZ 3k)6ΌZQQ=QQ:87520 . +)&$!!%(+ .26{>):98J7k5k2{0{ .9 +{)J&){$k!)kZk!){%9{(Z+ k.J{2J{6)k{>QiQ:QtQ8Q7Q5Q2Q]0Q] .Qt +Q])Q&Qi$Q!QiQ]QQ]!Qi%Qt(Q+ Q].Q2Q]6i{~;975 2" 0" .+)&#"!""!&),". 37|()+- / 0 24689 <{({)J+9- )/ {0 k2J496)8{9){ <Q](Q)Q+Qt- Qi/ Q]0 Q2Q4Qt6Qi8Q]9i <)"),.0 "0 "2 579"9" <    ))***++,,,---.../ / 0 0 0 1 1 1 2 2 3 3 3 44555667778899:::;;<;<<<==?))*Z**+k+,,{,-)-{-.9../k / 0) 0{ 0 1J 1 1 2k 2 3) 3 3 4k45)556k67)778k89J9:):{:;k; 9!!)"{"#k$$J%%&{''9(()Z**+Z,,-Z.. /J 0{ 1 1) 2k 3 3495{54k3k 29 19 0 / / .{.9/ / 0k 1 19 2{ 3 3)4Z556798J9k:k;k<Z<9=)> Qt!Q!Qi"Q"Q]#Q$Q$Q%Q%Q]&Q'Q'Qt(Q(Q])Q*Q*Q]+Q,Q,Q]-Q.Q.Q] /Q 0Q 1Q 1Qi 2Q 3Q 3Q]4Qt5Q5Q4Q3Q 2Qt 1Qt 0Q] /Q] /Q .Q.Qt/Q /Q] 0Q 1Q 1Qt 2Q 3Q 3Qi4Q5Q5Q]6Q]7Qt8Q9Q:Q;QQ!"""##"$%%&&"'(()**++",--"./001 2 2" 3 4 5 5"665 4 3" 2" 2 1 0//00" 1 2 2 3 4 4"5 6788"9:;<="="~=<=<=]<==    %%&''(()**+,,-../ / 0 1 1 2 3 3455677899:;;;<<=%{%)&'J'({())*Z*+,J,-{.)./k / 0 1Z 1 2 3J 345J567J789J9:;Z;;?"#$%%&'(()* ++,--./001999:::;;;<;<<===<;;:98765"#J${%%&J'{(()J* +Z+){J,ZJ-k)-.9J/{0)0{k1k)999k:::9;;{;)<;)<<)==)=<;;:98765"Q]#Q$Q%Q%Q]&Q'Q(Q(Q])Q*Q +Q+Qi,QQ-QQi-Q]QQ.QtQQ/QQQ0QiQQ0Q]QQ1Q]QQi9Q9Q9Q:Q:Q:Qt;Q;Q;Qi===<;:987 =<<;;:9988766544 3 2 1 1 0 / ..-,++ =<{<;J;:)9{9898{7696{5494 {3 2 1 J1 {0 / .Z.-,+J+ =]=="::986 5 4 "1 10"-=;:98654 2 1 /-+)'$ !!"#$$%&'(()*+(k=9;9:9{8Z6)5{4 J2 1 9/{-{+)k'9{$Jk Z!)!"#k$9$%&{'9((){*)+k(=Qt;Qt:Q]9Q8Q6Qi5Q4 Q2 Q]1 Qt/Q-Q]+Q])Q]'Qt$Q Q!Qi!Q"Q#Q$Qt$Q]%Q&Q'Qt(Q](Q)Q*Qi+Q](=";;:9"66 5 3 20"-"+")(%!""!#$%"$&'())*+,)    +)('%$"!  !#$&')*,-/ 0 2 35689;<={+)J(')%k$"9!{ Z !Z#$J&'J)*J,{-9/{ 09 2{ 3956Z89{;9<{=Q+Q]Q)QQ(QQ'QiQ%QQ$Q]Q"QtQ!QQ Q]QQQQ ]QQ!QQ#]QQ$QQ&]QQ'QQ)]QQ*QQ,QQ-tQQ/Q Q0tQ Q2Q Q3tQQ5]QQ6QQ8]QQ9QQ;tQQ<]=-,"))("%%$"!" !"#$"&')*,-/02 3 5 689";=>%" "$&(*+,. / 0 2 34679:<==;98643 1 / -,*(&$#! "$&(*,. 0 2 469;k%{"9k 9"){$)&)(J*{+9,.k /9 0 2 3Z4)6{7)9{:<)=JZ=);{9Z8)6{4k3 J1 )/ {-k,J*)(&{$k#Z!JJ J"9$)&)()*J,J.J 0J 2k 4{6{)9);JQ]%Q]"QtQ Qt"Qi$Qi&Qi(Q*Q+Qt,Q].Q /Qt 0Q] 2Q 3Q4Qi6Q7Qi9Q:Q]?=<;9"66 4 2 "//-+)"&"$$" "$&(*,.02 4 6"9;==<<;:9'&% $ #" !   !"#$$%&'()*+,-. / 0 1 2 45678:;;=>==)<k==iQ=>==<":"9""'"&"% "$" "# "" "!" ""  !"#$%&'())"*"+","-"."/" 0" 2 3 4 5 678":;<"=~<J<<=     @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @==k== =;964 2 /-*'%"!$'*- 0 37:=?=);J9k6)4 k2 )/k-)*{'Z%9"{)k!k$k'k*k-{) 0Ό9 3ޜZ7{9:ޜZ=?]Q=QiQ;QŀQ9Q]Q6QiQ4Q їQ2Q iQ/QїQ-QiQ*Qݣ]Q'QŋQ%QtQ"QݣiQQї]QQ!ŗ]QQ$ŗ]QQ'ŗ]QQ*ŗ]QQ-ݣiQ Q0ݮtQ Q3躋]QQ7ѣtQQ:躋]Q=??"=<:"6 5 "10",+("$# !$'*-03 7:>?;9864 2 1 /-+(&# !$'+/ 37<<962 .)$!( 2;J9{8)6k4 {2 1 )/)-)+)(Z&k#k Z!J$9{'Z+9{/9{ 39{7Z{<)Z{{)<{)9{J6{92 ޭ{J.Z))kJ$ν{kJ!{{J9(ュ{{kJJ 2޽{{JQ];Q9Q8Qi6Q4 Q2 Q]1 Qi/Qi-Qi+Qi(Q&Q]#Q] Q!Q$Qt'Q]+Qt/Qt 3Qt7Q]N'packagesearch-2.7.11build1/homepage/img/packageLogo.xcf0000644000000000000000000010261113507430555017641 0ustar gimp xcf fileYXBB/ gimp-commentCreated with The GIMP Unnamed#1BBBBBBD BD BD BUnnamedBBBBBBAPBBBC!B Underline @`@AABABBBCBD8@BD8@BD8@BCACACAS gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) &4HN!ZzY Underline#1     6YY=M]m} e%Ee    @@@@@@    @woow@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:9999{w9o888o8wzs,\ .-8 DebianLogo     %-8-8  ؽ˹ 󹷺ƿ˽¼ÿ߹¾žƿ๬ɹĻẪɴþ彰 辺ɮ÷ ٺ갬ú·ÿܸϳƷļβϻ տٿ Ż ѓ˺潽 䠣Ӹٺ 鱳ն ٳ ٵ׳ ƹ ۸ ޺ ٸ ׺ յ ָ ׹ Ա ۻ ֯ҫ ٱ ެչ 뿤ֹԶ㸡ׯӾDZֶƾųЫ ïĩ¶ ƴ  ͸ !շ!ı!ٷ ʱ޶۲Ȩ˴ʻǯѺڹ Dz Ȯ а±ű 콌u  ݚP( H@509_ɅM&%:eٟU% >DMy8 %VK(@GN\_`]WH/$rIK˜h=fB )gg"\B L ך/ bY v ٿ2j69R bݑ-g܅&%{d 1֟C "t<"N $)oܪm'kFEw(> ?fM",( sI $") nb %U' R k$< (%32 G$?2 y !g#] )j ,$_ *j콤<X$n 6HH (%U M#{ס.'}&7r*5H_'Ӧr+P݋AE;ٳTcr(Sb wܬq0!<ǯK&XXʋnQBlY5+#=.3 ݞz-6/)# "'4Ku9P ~Y * ɕqf7H S  O *3!\m 3 E p"H:}y b f RQ <n6ԁ6) U/g t9",s s65k٣kOlj ̤ȳ  pQHHEOni]W^לpS@9877A@;8:ETbxQ=789877878CeinĔ`?776766778RxkC988776>Tknq~~{xmZE987889Nj7887FnЭbH8897Hf8788@KQɆM<9887C~g;>DU8987DP9;QE9:>?Xh<8Od9:Rv`{B8K C8VR7Az ڸ^7Dwi;7S ŔS]oyys{77VY77f KM67UL88fg77Xb<7fҁjL6UO7<j N7RP88 ։} P:GvO76 s G9IM6Fb CuL7 [ikj s99?s S7;^!|>7G Z9=i ߋE8Mi9<`J6D89Aق8ADӅA9ww=HcΌN@`ߝ^?U yJW ݐ]JR ҐZZ㸆n))*****************************************************)Rband     %"R>%%Rjz%%%%% f=f 3=3hij9h8jihhihg7ih8hg7ghhi7hghhii#ghhghiihhghihhihhghhihghhihhghhgghhg hghhghg hghghhi"hghhihh hihihhhihhihghhhihgihhhhihhhghiihgfihhhihihihhghhigihihhgghf3ihhg4ihhg4ihhi5hg5hg5ghghh5ihh4ihihh3ghhhh1hihhih0hghhhhihhghhihihihhghhigghhghgghhihhihih hihhihghghhi hihhghijhhihiihghihhghiihihhghhgh:hghh:h:ihh:ihh:hi:h;hg5679587655654765854745567545566#455456655456556554556545565545544554 5455454 5454556"5455655 565655565565455565465556565554556654365556565655455646565544533655446554465565545545454555655465655345555156556505455556554556565655455644554544556556565 565565454556 5655455675565665456554566565545545:5455:5:655:655:56:5;54;.!8bx,7'rz27*x|!7 C}g7SU#(++*+*++*+*)*2gs3**++**+*+**$0qxwwxwyxxuvxwxwwu~wvwxwwvwxxwwyw|}?#%$$%$%%$%$%%(O:'$$%$%$%5oT  :q bW"D[`V  SY bWZNaW#s:`U8e *z*aVBn H}kaW$_R HH_U3~q8 _UD|q5aWX~U5ewz?6}|7 6 N#7 [X6tUgW52)eU3;p iO2 ^UkO1 ,q{4kP/Ayp*jO (]{WjPBDjO<>>=?=>>?=??>@?>>?>>?=>>?<>?<>>;& kP%kO:lQ:jO:kP:kO:aE: -; m)6sRpackagepart-right     &sR&4sR&&33-,)m('u%$򍙨#񐟬!t¾!쪎z非蠫譲󸷸񷹻񻾿軽𼺵踹󸹺깻񻼺񽾾꾼q~𺶴u 𹺹"򻸴u#Sx-Pt~,bv);Zz(sn'D{%]y$cr#dw!Bj|"b|}`xIfoqyr耆芌ꐕ𓖘혙蜝蝞螝薔菑蓕ꘙ򘖖藖藔_iꗖs?rOrDpS 𛙒}r"򘒉}}oD# Mk-FTk,3JV]g)+UOU\_e(JD]`Z`afk'Pae`_lqpp%.OVad`_m}$7H_ke^]n#7Odpnb`n~yv! ;P^nrkeo~wmlo!1PZirogm}|riemnT1N^`iqrll{}rifnpe8XVdhkuwpjv}vqosmmBDN`hpuzzvos~ztrsnnpET[cip{}~yrs~~ytrqmgknV]choy~}wpr~yupnnmhhlbdglwyrq}{vrmjorljlefjs}{trz|xtojjmokijginv|zvsy|xurkgghfhhghjovwvrw|xwtngffdgnpfjqussw|vvtqkhigegournrvuw{{rstqnljihiptvvwy{}sruuqliegkpqtv~~vruvri`_elrvz}~zzwstvsfYX[coz{}xrrvssutgY\cdkwunuroqvwqtrh]_krsx{|wrrlmqvzztqg\]ltvyz{{|yz{orvyzyqg][fruxyzyzyx~rsvxxsf__eotxyz{yywx}tuxujbbgnuy{z{zxxvx{~wxwuogehmry}{z{yxvwxxvqywsqkiikow}|{zxuvvwvmk]tqopmmkkq}|zvopwxt_2d@trrqooggw}ztlltwrcL utpleanz}wnikswqbHxumb^jw{wj`empcIxytgbhv}xk^]be`H# zxncfr|xl^YWYUJ"xpdamyyl^VTC#-Kt,&x*H)3z(Q&.y%P#{! 8!} * m F  f!<????????????????M? &? S ? *?b?؍8 !?`"?ږ?#%'{({)*,_ut^%xxa'{bJ(oK)|ttwn*{vkZ\,pk[_gcakwxm_WLJ/%_dnvwn`PO2'nruqkcT7(png]ZXD)]YRJJLB*PJ=*.,C=+_?d%?4 '?i(?7 )?X+)i; -_9)>-packagepart-front     5>-5>-5ҵѮөרܭް֮᳒߳ժۮ۴ڳֱկױֳ겊ձܴ޶ٲ᷋޾ݽ⿊‹Š‹Ìְÿý۱u¿۳{kٳzeشhòֵĿɍeǿֳˑgǷֹÿȐi¿¿ʿhöĿbÿ¿b_]ִ]غ¿]ûֽ\\¿Z¿Y󽼹\þü_Ľ߲^¿Ɛ]Ƽ߽Ξaʲɠ`ĹÙ\ÿְ[ýþ]ز¼ß^ּļ¢aƿ_ǿ؜_陠`ۏ`Xvrx֎WIwy~ؐP?~򑔘O8ؕ];޲k9֓r<֚n@٥]:حU4ٳ]5طi1㧣f-֘`.}؟_-֡b,֣a,֧_,٫yz~]*٦}}e,֡k0֤k1֨q15򬫣欮3֪{.y-熅~/򡪳󙘘髀2֤4֌~2yz2~yux3~t$O$OK&&$i-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z 5$53R Schleife     IjRIN NRIIIMMMMMghihh8hghihhg hghg%hghihghh$ hihhi#ihhghhgihhgh$hhhghhghgg$hgihhghhihhg%ghhghghghihh'hghhghhghh(ghhghgghihhg*hghhihgghh* hihhihgg,ghhihhg,ihhihh1hihghh1hghgghh9fgghhg:h4565585456554 5454%54565455$ 56556#655455465545$5554554544$546554556554%455454545655'5455455455(455454456554*5455654455* 56556544,4556554,6556551565455154544559344554:5&73l &lJ n E!ɠO ,CF"FA&Ocdvgb4ga5hbTWJ 7< $  MDebian Package Search     c Egimp-text-layer)(text "Debian Package Search") (font "Forgotten Futurist Bold Italic") (font-size 71.000000) (font-size-unit points) (hinting yes) (antialias yes) (language "en-ie") (base-direction ltr) (color (color-rgba 0.000000 0.000000 0.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit points) \ M\ M]bg@knojtx8|K%5EUs ԡ\ +`)x(E>'~' &@%&\ 6[%_$[%LW%C7$ |ep` @D  xB{=RFC!e Y-&, t)ba)2o:Mu1 Qs6 gDHn|U{T6E&g_/45WlnTm)cuwq.p7N?H6Q,oXRC&/LWRh0 Mp ` ڹA{ 2i"hk0Z0 OL=P6v6#ppw  ͊/ھGXB}LQG<sx;tG+n3[a85\.{V%=O k 2;^f~q(!z 9GqqK8Aj;2KO h1+Sca$O%vZ[?{SSN [b:lF45fFck0!YQLw ɎFEW' 54!4Y4433:J6r67 vgޫY{ Q SG  Ap53xnlD)<TN*nQ;B?L Mv      5H\- nX#e     gy Q/:@FZ r ~     5N]'r mT%_7     mz  Q46B@O o x    ӞR413 )2 2 -1 g1 4\6~6Kr6RK6z!ھG+tB A L z< KBxp Z ,u3oc 5" ?5k : ~ 2M f  .!z BQ 0~ Aj ٬i;2 0qk:a$OZ {1[L:lMF4E F !p X7 YQ w ' l661h6i06666JQ666443j,r"yھGV.d:BELi < J|xp @E[l }#3}5a5&{k ^D[  [2M |fDC Z !z | ?xAj;2&b _*!8Y?$$/^D'a$O ZAH{z:M[ r:Y:ly q!F4F v!S@x K@YQb w' Fw6.6j660p` B=RR& , t0ug>2o u1 Q6gE`})U{E$[L4ln))9nu)q7.p)Q,! X% R^ Z& "W M `B |{ {jE6665J3344Z56;x*n)3p(J7'D&'&!U24 56h6|p` Br=R<Aexcwn&v, td ͐B@2o u1 Q 6 g %-!R NU{ KEAA; 4lna>E u{ .p[K)Q,:XFRFE&!HW1MYh `w թu3{ 'ھGpH&+tBQAL rp6 5Z!n  30oc5d " 5k QF ~ 2M f  z  BQ 5O ~ jn  2   0q l k: Q3  $O  Z  15Q L lm M 4 E   n p Q5 X7 Q     li"fZ. =Lvj sgޫY.X A|@; t)<TN*nV;B?v   9H\qX#  gyT/:@r   7N]oT%  mzR46Bo   F@@@@@@@@@@@@@@@@@@@55Z@@@a7u@@@@@@@@&D "YSelection Mask iYYeq}Y !%)-159=AEIMQU @@@@@@@@@@@s,\ .packagesearch-2.7.11build1/homepage/img/packageLogo_dark.xcf0000644000000000000000000010243313507430555020644 0ustar gimp xcf fileVDzBB/ gimp-commentCreated with The GIMP Unnamed#1BBBBBBDBDBDBUnnamedBBxBBxBBxBxBBxC BxS gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) 33%h4]H)MY?' Underline#1     IC'''7gw>=>=>=>=%%%%D"4A Debian Logo      4A4A&                           +,,,,,,-----,,,-+,-/PSj[m&  7A ^  _   ! ?0,  "  {  )75    "B   !}- C @  # m@$ %C 6If Hm 0l>@  *E1  Y 06).   !";' pI ,H 0eYw.  ( L' I  &5  (#   4*" 0 ' 6 @ & = I  7t\   ;ffL 3 @ 6B+PP  ,06 `   k = 1, &<} ] T5 3F   ~I `  3 "##8 YP!P  %&1.  5 ,^ k[,'%69  x Z*  ' C  5 8  @/3ip P#@+L  !,,)  +,,9 D, =,-, -  )- ---,, %, , B-% If+ ,0 e-6 Xmaa&cWSQQXV`r_X^V]z ]VQ QSV_^TQQUZWUbcWQQUxnk`SQQTV^dTQQRV][WXVXXVVRQQY aTQQXis\WRQQXq ]SQQS[b dWQQWz `RQQTW]c[RQQYlTQQY{_RQQ\YQQ[y]RQQSe]QQU`\QQXWQQXyYQQRe_cfRQQR[{TQQVrXQQRa_QQUXY~WQQ[ WQQ]nZbQQZxy ]QQWcjWQQV}nZVSQQTW]TQQXnrimSQQ]]TQTX\`c\Y\dWQQVvg[QQ^]QT\ckYQQaVQQV `RWn\QQXlRQQ` hTVhQQU[QQV VSgqQQUWQQ[ iRYdQQS`YQQ] XSqiQQ[ZQQd nTV`hQQSrUQQy cQWgaQQ\[QQT `QWwQQTSQQU bQ\sQQVRQQV [QU vZQQY[QQV pQRy r{VQQjXQQT UQ] knrZQQVŐUQQUXQV]QQR]YQQVwRQcn_XkZQSgvYQQT rZQUp}]SQU\QQ^ aUQW [RQUpbQQX bdeeVQVs XQQVcSQQY fgnlUQUaqVUQQVkVQQW khfWQQV]rt\XTQQSZWQQTj^\]RQQRUURQQSXg \QQ]{ZX`YVUTQQTUW[q sRQQT]ymZ_[pVQQUeY^a^y\QQ\+TQQUc,ZQQ\,iSQQTj,ZQQa,tTQQW|,]QQSw,XQQX-kTQQ]-_RQQSi-\QQTl-ZQQX-YQQR[k,ZQQTf,[RQQT`,_SQQWz-fVQQT`+]TQQX[,nYTQQY-rZVQV\>\9"'8՗Z~zV U NSk)$;fP"ϭwnw 1 ] ;6 . 7l5s J\BCMZ8CD%m +eKo!A? V-Y qJ TrMV;?\5=oKgY ] ~) 6[F 'h'l '{4qH en/ v p 457{ Gw?K{ N.{ = q&{  D6A { Y Y${HNy?A;hD i 5 Y R] |$ uW1~ 1dN 2 { WF[,B  >1X`n'g WU~yn٦` K ~W .ha.Vi+,}d,,|F,  ,O--U-9--d--c!,-rD,I-C+cˎ-- jK0"FnZVY\_d}!kZ! PEmpty Layer#2      %P%P%\P %%%(%8%H ?f=f ?3=3ghij9h8jihhihg7ih8hg7ghhi7hghhii#ghhghiihhghihhihhghhihghhihhghhgghhg hghhghg hghghhi"hghhihh hihihhhihhihghhhihgihhhhihhhghiihgfihhhihihihhghhigihihhgghf3ihhg4ihhg4ihhi5hg5hg5ghghh5ihh4ihihh3ghhhh1hihhih0hghhhhihhghhihihihhghhigghhghgghhihhihih hihhihghghhi hihhghijhhihiihghihhghiihihhghhgh:hghh:h:ihh:ihh:hi:h;hgg5679587655654765854745567545566#455456655456556554556545565545544554 5455454 5454556"5455655 565655565565455565465556565554556654365556565655455646565544533655446554465565545545454555655465655345555156556505455556554556565655455644554544556556565 565565454556 5655455675565665456554566565545545:5455:5:655:655:56:5;54h;.!8bx,7'rz27*x|!7 C}g7SU#(++*+*++*+*)*2gs3**++**+*+**$0qxwwxwyxxuvxwxwwu~wvwxwwvwxxwwyw|}?#%$$%$%%$%$%%(O:'$$%$%$%5oT  :q bW"D[`V  SY bWZNaW#s:`U8e *z*aVBn H}kaW$_R HH_U3~q8 _UD|q5aWX~U5ewz?6}|7 6 N#7 [X6tUgW52)eU3;p iO2 ^UkO1 ,q{4kP/Ayp*jO (]{WjPBDjO<>>=?=>>?=??>@?>>?>>?=>>?<>?<>>;& kP%kO:lQ:jO:kP:kO:aE: -;@@@@OOOOb(1^PTransformation#2     q&^P&-4Q^P&I&Y3g3wmu򍙨񐟬 t¾  쪎z非蠫譲󸷸񷹻񻾿軽𼺵踹󸹺깻񻼺񽾾꾼q~𺶴u  𹺹 򻸴u󳲳SxPt~bv;ZzsnD{]ycrdw Bj| b| }`xIfoqyr耆芌ꐕ𓖘혙蜝蝞螝薔菑蓕ꘙ򘖖藖藔_iꗖs?rOrD pS 𛙒}r 򘒉}}oD󉆆ut^xxa MkFTk3JV]g+UOU\_eJD]`Z`afkPae`_lqpp.OVad`_m}7H_ke^]n7Odpnb`n~yv ;P^nrkeo~wmlo 1PZirogm}|riemn T1N^`iqrll{}rifnpe8XVdhkuwpjv}vqosmmBDN`hpuzzvos~ztrsnnpET[cip{}~yrs~~ytrqmgknV]choy~}wpr~yupnnmhhlbdglwyrq}{vrmjorljlefjs}{trz|xtojjmokijginv|zvsy|xurkgghfhhghjovwvrw|xwtngffdgnpfjqussw|vvtqkhigegournrvuw{{rstqnljihiptvvwy{}sruuqliegkpqtv~~vruvri`_elrvz}~zzwstvsfYX[coz{}xrrvssutgY\cdkwunuroqvwqtrh]_krsx{|wrrlmqvzztqg\]ltvyz{{|yz{orvyzyqg][fruxyzyzyx~rsvxxsf__eotxyz{yywx}tuxujbbgnuy{z{zxxvx{~wxwuogehmry}{z{yxvwxxvqywsqkiikow}|{zxuvvwvmk]tqopmmkkq}|zvopwxt_2d@trrqooggw}ztlltwrcL utpleanz}wnikswqbHxumb^jw{wj`empcI xytgbhv}xk^]be`H# zxncfr|xl^YWYUJ xpdamyyl^VTCgcakwxm_WLJ/_dnvwn`PO2Kt&xH3zQ.yP{  8 } * m F  f!<????????????????M? &? S ? * ?b ?؍8 ?` ?ږ??d?4 {{c{bJoK|ttwn{vkZ\pk[cnruqkcT7png]ZXD]YRJJLBPJ=*.C=+c?i?7 ?X)i; c/(>-Transformation#1     5 >-5>-5.ҵѮөרܭް֮᳒߳ժۮ۴ڳֱկױֳ겊ձܴ޶ٲ᷋޾ݽ⿊‹Š‹Ìְÿý۱u¿۳{kٳzeشhòֵĿɍeǿֳˑgǷֹÿȐi¿¿ʿhöĿbÿ¿b_]ִ]غ¿]ûֽ\\¿Z¿Y󽼹\þü_Ľ߲^¿Ɛ]Ƽ߽Ξaʲɠ`ĹÙ\ÿְ[ýþ]ز¼ß^ּļ¢aƿ_ǿ؜_陠`ۏ`Xvrx֎WIwy~ؐP?~򑔘O8ؕ];޲k9֓r<֚n@٥]:حU4ٳ]5طi1㧣f-֘`.}؟_-֡b,֣a,֧_,٫yz~]*٦}}e,֡k0֤k1֨q15򬫣欮3֪{.y-熅~/򡪳󙘘髀2֤4֌~2yz2~yux3~t$O$OK&&$i-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z-$z 5$53PEmpty Layer#1      HPHMjMvPII+I;M"M2MBMRMbghihh8hghihhg hghg%hghihghh$ hihhi#ihhghhgihhgh$hhhghhghgg$hgihhghhihhg%ghhghghghihh'hghhghhghh(ghhghgghihhg*hghhihgghh* hihhihgg,ghhihhg,ihhihh1hihghh1hghgghh9fgghhg:h4565585456554 5454%54565455$ 56556#655455465545$5554554544$546554556554%455454545655'5455455455(455454456554*5455654455* 56556544,4556554,6556551565455154544559344554:5&73l &lJ n E!ɠO ,CF"FA&Ocdvgb4ga5hbTWJ 7< $  LDebian Package Search     O Egimp-text-layer)(text "Debian Package Search") (font "Forgotten Futurist Bold Italic") (font-size 71.000000) (font-size-unit points) (hinting yes) (antialias yes) (language "en-ie") (base-direction ltr) (color (color-rgba 1.000000 1.000000 1.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit points) [ L['3 L\QaMfjntAw{pp ԡ\ +`)x(E>'~' &@%&\ 6[%_$[%LW%C7$ |ep` @D  xB{=RFC!e Y-&, t)ba)2o:Mu1 Qs6 gDHn|U{T6E&g_/45WlnTm)cuwq.p7N?H6Q,oXRC&/LWRh0 Mp ` ڹA{ 2i"hk0Z0 OL=P6v6#ppw  ͊/ھGXB}LQG<sx;tG+n3[a85\.{V%=O k 2;^f~q(!z 9GqqK8Aj;2KO h1+Sca$O%vZ[?{SSN [b:lF45fFck0!YQLw ɎFEW' 54!4Y4433:J6r67 vgޫY{ Q SG  Ap53xnlD)<TN*nQ;B?L Mv      5H\- nX#e     gy Q/:@FZ r ~     5N]'r mT%_7     mz  Q46B@O o x    ӞR413 )2 2 -1 g1 4\6~6Kr6RK6z!ھG+tB A L z< KBxp Z ,u3oc 5" ?5k : ~ 2M f  .!z BQ 0~ Aj ٬i;2 0qk:a$OZ {1[L:lMF4E F !p X7 YQ w ' l661h6i06666JQ666443j,r"yھGV.d:BELi < J|xp @E[l }#3}5a5&{k ^D[  [2M |fDC Z !z | ?xAj;2&b _*!8Y?$$/^D'a$O ZAH{z:M[ r:Y:ly q!F4F v!S@x K@YQb w' Fw6.6j665@0p` B=RR& , t0ug>2o u1 Q6gE`})U{E$[L4ln))9nu)q7.p)Q,! X% R^ Z& "W M `B |{ {jE6665J3344Z56a7;x*n)3p(J7'D&'&!U24 56h6|p` Br=R<Aexcwn&v, td ͐B@2o u1 Q 6 g %-!R NU{ KEAA; 4lna>E u{ .p[K)Q,:XFRFE&!HW1MYh `w թu3{ '@ھGpH&+tBQAL rp6 5Z!n  30oc5d " 5k QF ~ 2M f  z  BQ 5O ~ jn  2   0q l k: Q3  $O  Z  15Q L lm M 4 E   n p Q5 X7 Q     lI"fZ. =Lvj sgޫY.X A|@; t)<TN*nV;B?v   9H\qX#  gyT/:@r   7N]oT%  mzR46Bo   f5Zu&D "VSelection Mask VVEIMQUY]aeimq         9        g+Y ,packagesearch-2.7.11build1/homepage/img/packageLogo_for_dark_bg.png0000644000000000000000000004472013507430555022172 0ustar PNG  IHDRV0{bKGD pHYs  tIMEыtEXtCommentCreated with The GIMPd%n IDATx^ydGY},}2K̒L$AAEE&* 쾢J@"KD$E^/(H’d&Lfܭ޾}'|?In?}SUO=穧a_&ܸ:7_lʎM]-\rd[>\AAAAAAAAAb( /~\zt<kC3PzPS;eF]Z$pVJ3y뾴_yיYx6+]aLCBf+=2Zʗ ˗vz;w(_^PPPPPPPPP0_yWaǦ[R;/_(Fa3P~{|yAAAAAAAAA|uK6~UtS-"VB.3Pz@S+'ٯjkbLe]Bͨ%N@P3Xe/7zi`.y޺G&I&_vJeo]?x X'ϭʶ+^J}l=-mOɑ6Ogzͦ =O"2 Ϳdg5^W?OjˎØ13T(m5_-[7i=zb\zE@?/g ہ7q:P՛g"rn^8WT2F6/,7JfSD-&Mrz N^TJg˚J.Ytyy#_roJ:iU9/{ F]h'u/"94U:vx7Jxm-r_k'jIH ?'_U ЋG$" ~`U^|\D^U쁢'" fFU9r'Baz80/BUg˧DyaMc"¼/gS`*~ۈZ>ҖW<! ʣuL-ƂdtL{/S#7wr`CǝsGUgqXk9ozbʗOc'ڲk~#@LkR/XlTuwy3yA fFU7;bkH\D{z NT2c3a caQP_m|n(p-_Nx'rxKTy%٬NV:gBg[=),iQge-</lYscS_jit|κ;e} z/TD[EqyA v\𣼰+:\YxR@'}?/n(E@X*MQ4Q \z+(O?% ,5__I80e0>K>o?KUreS^p~Ʀ'G{WE*jDh iTISب' | hD R0q܍7e͵N^^ #tG~gz/g׷EԍhtԎG& <3_'\|y+pq΅ph]u#=vt2*UPDzNv\mt!C"OsxD==qIy#O3MTZmGhԏ)Ry@7?+yˁ_x4HU 6&R r`t.[+\' >=Ϲ'R**Ct?A"DQD4}=׿׾o;L}E_j6/п nϻhSߺ`IPճ>q8ɜssz^H<&=5"y} Rp.[![q-P}//_+ =f m;-J,h03o]XzmWezqepKo ʃO3%^"~iu2캟[𾝤i600Iԯ0Y'? \͏YFOV9Oc ʃ/Dg!i6A2 j| N(sl/[k5{Py~-'s' 8pcsM9ExJzH߾q2tU?OJVb|4@-JugQ3665g0|︟GGߥ:qMgу{=9c3N9U4&Y)*`$y0*|)yUlg<l]O8UwU6_]W`.<2ilkGZS6b.䐈ܗ:$ndqJ\AٗU=xz^?D+\SD\n ٛ<5DDU}ȅbmMcFɱCL1B&kپ?,e <$bnٵ `$IF6tŪڤ CPXzn۵<[qEVuϯ@_}Ǽ#[Nі=IFA)3=)=_uH~m^c(O~~$=vjExWrp pa^dA[y|`%Fn>Uu-xv:+!;y7p py[õl QտX2v{G]d[ }EDjMaC`..&ˉo47S_{ٛEv4;="DD ۱Pkb^$&1"N=o=l$[/ο9GD0ޡ/$߹DNYvd^/i$&_DlATAD-iv܍ aF`rlI̪Sa ,`m(1 ! 1GGIcI b!Z!J 6&1iW[#;e/KG'? [:=׼wuw ^_gohE]-<4S_di9`vγa<("G<j  FUEDv6l!jEkWs WDo++vL xp|},/ao#}>mӽ&ٖ:9U x ٵ·&߫Wq;hy7Sك^1E~͇ *"cyB[k>VqOpxh0,J/XVBc#6 =QHL=̒+Xr5Is`vVY˺MPdσ1d D$ۛYȢ׊`SE\XQO8:'ё5%Vxa瓤IRCUy8zⷵ=Rp< ٲe MïO7~8pyG>Qsg ݺEKom/0dvxx U}pnv\ |NU۵(CI@UOǽ3%-yTWm褓n h;G5v qOET-}}؁K1@U_="ԟ2u!ޡok>|_6~ZdKq;/X ;^O6>]2|Ջ+K?Py^ihd_.`S& &)ĵ)z1+VaYaYb kןM/1X*Sn㞟Qc r*KW1|e+)-[Ei B4䑝XJ0\jPԂW&( ^@iTIqQkI/ӵ<>M 7=}ܗG'o>x{\WC aN=[Anv(U]{܎9TsU9h(ENcN3gW:?H\N|W|A 4W;}hf/WGhb A\l;p煚w} _"Ɯ/3?]8ᡪ>گ9l+&fZz"/.G/lqD hzqX?/n|s{mxg2&\&,!>6M,10b/;_&U `c_i}lIVWk=Ͻea_|{xD;9ݹ9%J2Sļyz ]5iVh$" i_뤅OO ,U{4݌V|lϳk:7?}L/5O.~ݵC[OXp/|z_׮Z}g!/1#Q$q6Ic0Kcl4ckmvl(iTmڷ7lfsT}`N_ yϾV4K{}.D>OD:\Nȣ]7`>\{쪛gH]' x+p5"ɭn~WC/ĽG/D>`,~Z-Ғ.v`!Bn/% t@*iu;ut|qz &()j5A|ZTcǎYsz<π^B82K,N[~X |D 7GC W\Y2(4bZA=$1v>pRuu;7;Zx澖&?<$57դRp|.]jm#9I9ϮDDF74;е|Oٹ^pmzqª*pe XӽΦoq_Q'M j?BKodWK ^{KvcqZ| Z%^Xck}IsgN8f oxU[i6IZ4U2R׉1HbmJGԫS~?q.Ϻ@Gcx(jIf>cFqޘ;4LP Algy&(9(jcP%W={w"Yv-0g~Pugs(_>}4gpOq8BHOv4+Y=ͦj_AzrnfS\?|8-WJi~ZY.c[Z|ptM^79/X:yxL~G[\z8("~7Yd/tП3?|xt@̓~͇NѫTρJXݵ՟Cdυlfg)A,I֣zHCF 6m:x! |DEJCEe>}Q+tWTGJM1bPZ)bS⨁ $/I'4$i\_b`g jqgINbJ˦Z㸔 o_o/[5quۤM4dLt]SR?︭Ȕ^l<;s]ƭM4t_V77˛.ki:Kq_v="pf|[UgɎ` 3˛di f>u˛/"sh'z=6;o!۟_#"q`>AwW s i8ch|i?XO\ ^࿀'mp\]},B}N>?+ʕa"~v xXkIk#ÄmQgh M"PFimv9gpeW6 /D|OEUQ kB:A<5 ibLM|<FUę9 #^\`ݙ2IsQt) -Cl- @P3*x!hƯ ~ M@iG=fd$nKǫqzDS֩un0:\waiMhEyA ?cuO^i!+إ1ܳp'|b|BD'/sנ] Kl睏r|z|/.fԟf\۰yT&_Bw +!W~}~rOUya,phg1J,xW4I29uXK#F QD*IjQ4#6"a 1a $ЌrZi,@iMc@[>:mו#NM:~گ^f`{^8~W]<3M7.˖&];'ݟ5U*`x ԒQNHQb,g`J+( e=wi{̓/0N:LU>Izœ8كNZ+et5wyd>8K+ݍ^f[] Q'def['NTuwDCUED[@ڞFg]V_BD/-zde(ɢlwǘ.ލ{s=Kg@MXMc$4A*x ^yiuR[˜\f1>H!ւe UJ*h'24Wc j.t8F\;J{]}mb<;?8D;Y# `]hvڼl:)ȍ3uPYyyVc኶慭4}~-.CiC^UӲuwϖMf+y} ZNr i^D;9AOű|:"}^Э?+Dd>hg5t^щqYdݵ[BځNcaݟR"zxA%MlLV  A&qZu1hFQHz>^֠T ͈rXK\  e*#T5+ZG|`HS$Q w>& ˌ,]N\Ayb|R<%stK[gdqstݶſuËڼ#ȿK^}jrp5ZmO[q?~ߓGt ֞lՒ~Tұn|q <0:[ĽX?:9y\׀"Ϸ;U 4_6O\Ug -t?[jdsE+&;Ddo^8:Y U+9}ҟmt܎NM\+::A=?f{oӸZ4ݵҩ?>Ӊz9~k4%M# *+ eU6IBjcJ@Z%mHu("N`O 6Y-X3Mc)U_B (aԂ@`$Sc|qzV%T2gD7Qߝ=5'LJDk}ugEjA!=4~ml߷]c6y˚kg|-7|m÷fyvu:NNL/P[,e&6xhJHL;:+{c ﹷO;\1\7Ja 6kf~IYq̅Пv^,vywDĊy5Er-kǢ tJ˖vNbT48D88~/4 `IL:ETbzFJa?(#^db4@IhQ )4: M'=@`|O$.I{衽lNg=%64!M,Vjny.r#}{?uM{+q1ͽ+ѩ6ax韛.[zUn-Wta.f9b^p_9r[t:ylM@Tqo @ (1"\DghuT<?DQ5@mv &6Ͷ 6! Q}$BǠ`lai}.<U6IZk6P8Xy\c#F 1^_^i|w!M1E:\d>2')q;li^j\;9G^Pj,\Ni#+N:q}^|+#z8Wy^:q 1ʹѩ= nhwİ!\SENpهN.p8;/h]?}nw .t׎~9Ә1qh:FR UWDZq5[}џʦr=> m%kBدE9vq^ĕ Kk֘){}29c ;4%q(xȴd{-4u$`MȞ}<<@4s<p\p)6$\"cČ` g3|iZ+W d(QEԂM/8n Nt8pN OǫכrG^Ii#~Rzt3(Kw<9힩RqoՒ??,WD ۡ1B^ЂkV^\vi3 uU݌;;z|+2ض_Nq;T1tEm~-6?;'KyAO] ,/vOB?'^~9ol|AӔ4k dGr j$x!qÇ DMPTA5%R!JR 8ѣe׃[KC#Ytim h ʘJ fHZ'& ֢h_=YsO?pǿVcۛ9ʑ?Ɣ&z1Viߋe;.`ê7;󰧸:@A#[& /1/o*:Ռ<5/o喿;;tM]{'Mڞ7J'-kMݻⅈ:" ٴ+5DYt*vtCZ4/toG.=ܶ/~$%/h2NcQ?jwǘ.X‚Jp뷾pٲAH`g !#"M-UUؑQ4F$2,m >`1ڠk^VOY+O'|FM$0^x% "Fdyf{J hVyƨ38<+9ش"v7[\[ ] y=uUw~Dɿg|Owzi?zC?5*˛|ZDM1u%@)/lrh<X6iISA axE> $ 1"$61#l}u_:]cNQՒq{T{U.4\g-6leB.!HNr,8fG b'׉KBvtڊlAEiƐ `|f;Xx!bBLiHԀH+ØaR4@eh ?ՔN K Ae``RLiRƓG݃fdh4J<@&HjZT&ߝ=]swnuaw(UINrL4~\!"CwAw\OX2+[4.tl:)38b5= <7wLoY~6qՙpo8q>Wihv>K[z d\}dFD#xXL@S$)NjSc2~PCA@El4%G$qsZl@mԱIm IcUl`8J0a*KW.YWFQ6NPNx8s&Ԧ{cWUp>>fh)T QHLDJ4j'5TS11F A# I* Q@1JZhy9eә̽s^~8SCoLg`ݝ=w&瞳}Ynp}^~fՏzQM9M7-Y: >pxLrvөnt Tmy=E)/rDg0"BNV#&#ܬn'Q= 3xjJԿ#Gy{c2qp2ݾ8N}[6}&_OW;˩1?$t,6Q:WoT9@\NRkXTkA4gEoG:yӾtv;N}fT#@h S9 M|K.sUCbhD 6,ȆhhhWkOk4;jW|BgeYsU݂I=h\g#ѱC~?}Ƒd%u N3>_lu>wk_4tM1&&Lk6?pϘ tio⛽$\D\Dy_U͈+v>G>髩Q:S.7A>F{lPtHjeپ2_6z !3zh8٦5ۨD ՔwK]|m}egvmxpY/6Lk1M[5v1sTgxAqI iՎOBIPmjH, 4DUq U ѨZy$*!(N2yNj\:(V(FG[#w;tk{_pGoN:x^ys\yp0ܺ|ť/1Onc;/AcpbE\7΁h@q0}DpNpP@NX.']D(Mj O BC!&>G4iIգT7FH( "%Q)")X"p"82ATi7!#'QW/T}6O(vq1V_p9VbҀacXla[~6q/\⽕:X| H@ L K#"""rʜ'<3JK}g˙ҹպ|g9n䓜#Rq %$Z]J1i !1LWǎٳD…=pvLhwwY{ŕ:.Wk~L)-2L&L0ML`ºۻ8;~ >$9Ǟ,yB25\&eC.z-Φ=ѽ.OrJ ~=Ւ/ |\0cJuݽc_RR2 .ϵ{+Jx{W2)wxqgxlO<=,Y\.oo] x~JINİfDS/)q3>^Ǻ'K,ǰXhj`bL')bZHtbXDDDe]gΟҥ|$ ꁛnn2/Ma_EIyFrRR3SV}ɖ d‹1,ZGU7ownCrRR>˒vT-UX,+z8tθ IMMŒVjZNBBmb.9ىiϮieQn]{#|:O=4s^bW{%!} *Vޛ?ᒶKr\ *v([f-9%> Tbq6?I@b tww<=܉󉈈d|Z"Ym8~&,e\ ?_YLgZa$6NKv;5aiGcT,ʮxbx('3hdcr!@]8 kM:y_Tصb؇'䍧;pC/NƳE2khJtNg2{q {%U/rT]S+5lfۣykv7MtMSm̜f6:-'25mL/֬8(6o*X<ɣA>Vbv3ǥDf3fw3n=0ݸyUKj `%$Hn߃X)IIZsyFrRam;eӗ#-ʵ~dώ^lXK/{}kΔXRqOI;CORDX.}7HJL^旐f:Kv݃g ReK5u^W}3b=7v_+͆myaNQfᛱ{h=iOp Ͽc%͇GNa;mi혷[ҳswErW88mLNw:?ԙCwX,kۗp㼹S1aAޛHΘ*3YtfN3w05Sgٽ_yIc^m:3So8N:s|Scoo%MD_VrާJDDDDfRE_,HL~V2q Imwt[w~{FKpAD;W¹,𮞼6) Tw JgYj_{AH7Awmd? ++{"nbLl;fƌ!ș8z~|LsR2U⫅=7y7.KsbYzò#m/Eʣ׳YC#jw,x\QY;3}vd%ԠS6 2y͏2l]Xb^9_YhΌ3L.%4Y?7b:Q`=qo@rrQ;R{%C_&wݒ0>%yʒPXyxw>7l7>>>z{sb,)iwN\.%)ȳgcI ڦ7JV5PROϿg><3~XG DlcV,~k&FejEe/v6g՟i2'_m_S<߭[);,^nwӇ~v=91s-sLMnDsp>^}7,;;?>""""Rt:?L̩^ٖPUV>칰\:}9[IƜ{]jf;85?kܘ{vSJ+[.~ו͆}U(\y׹jTC([ݿNٲ^l2i^ieY2{0UL\VzWmI+<2UhOb4>*P_3TI0 8}Lf{xZKOO<<)m9>LBb"I9ji٘ yk<1BX;Z""""W/rYkW{D/]ʕ#..0Otm&$\L/ʕ+K\\<Y{݄F{L[-) Xd/qd -[Ȍʔù_'ok]6qBrOV%e/11YS_S ޾f"# +LGEϨnBm'W!T MFDDDDR9M<˝`*"""""R@JDDDDDD H H)) %T""""""JDDDDDP*rYBߚg=eQmffN8Kio\ZRP)_Ixb(/o仍}Y\nkA~L<%Hqqwec7,ʱ-"O`TzmWM*xrc6/)ـYǾkp*@G}o嫍CЧw \:!HqiBeOn2A[3FWwhsk=y^2n+Z6ڲ ?, +O!*AWG?dNM[,o4cҧ&.(OtM,X7ŵcD|ԁ_FPׯO@6>.30*aX5 a~Zu>8=Q[,/lkߏp#X7d-?ּxG䶝?N`8ǥcʐqϿ5aCkϿ5kt_6o{,ɡ<^~Yڳ%KOQzfL MDDD4rp_8{`B\UЇ7xU'y,ҹ8P7J՘ 6>H2Wt!%^CY~ \@Y5jǣi8-niA:ɉ>]'oaԟ 7g5k K#&0q&t3UӖ||ZnwDW-ke,:1},K( Ά3| ?6 ?yqd1y,K=ϿX' 3^ɪz`sc)I.Mlg 5[3"}9B<\ FꫵX~r<ޅ -/r!5w <| Փ/˕=q~hr* H L?ވػ3X*G_Mu:p<W cjX׳._ {}2#pFDΆr`yk&Q@< IWu!GOv=jYǔ\9zYZn #JDDD,E~_fOӫ pz%,d |Y>a<(1`bYN2\8wس0 XquHij5cpj?Gs1yyF ُQ]:֍v[;ު>M`}5x5 3#qF&P3ym';l3s>,ơׁ>Hq*ք*dk:$k'!|St}56ko'|x~0jfީuoTtaڷ!΍ռޕ+nk:K\HnEp7?fk=:5!׹>C$#!s\`?F=FWγ3O#ط xjM1> {i:5߶m'/89c}`&"""R\L>`;>IիHDDDDJ'%TWOJ: JT]NvG|R!9sI """""rRB%"""""R@JDDDDDD H H)) E[q\v&TwXqrslP'y("""""";Ck.$_R\[V**XDDDDDD.+v/'Ec*5/XDDDDDD.+N'TQ?hDDDDDD.J2^ܖd9ߚ<ِc[Td&"""""R, tce_F29dįҥ_~ۤZ ^zuf*;{g%SQm7Lշ篿q`f^*^^LfS/5}H+Uʞ4r3c;{K)DE&bΞw"IlJO)žʟ3ߩrw}3'{/OP.p 'IJU-/>EDDDD*IU/~}eYhܸ9I}u{c'`? WI)"""""%@R.~yE*\NOΞ4mvO O1<-q-^T*:}:_L?x.~p$۾iРji6 fB*)U"""""b[ϑʕg|hڬ9iԩ(.VR5!\54loyOIEgŊ8G[/8DQl۶KVe(_go^cQ GԮͽw7b9~փrc䉧VZ4sbSmx{8z/*ҠA"[DDDDDNg= eޔ\}ps3UO@m_&iaՉSIz{QۃMJ> Is֯2tHYpqEѓ9rT eXVs挔+/V-jh1>e j)DYTHI"&Lie[6m.7ؐի#a0kf+"""""%@ReN:KU\j֨ĢPK_H3 Kqqv}Pbԩ_%_ to*MYQ,H͚܅e|EbR.\ *_ZD=X ^^^@{زe+QaeDDDDD.;N߇*b^ۥ~` Sd]&u¶mVv4hp77m…_sSEҧNɓx/ 5dJDDDDT"0c2%c弽02^XgF^֬rlժUc1RtJDDDD2TleV˦trwlnRd)ƍkѸSvH)xDDDDD(*""""""W"CVEDDDDDRjV>T""""""e7ʼDDDDDD+ UpDc* EH*8}giu;wU"b#T܎VUVm@@޼u=;x7vL0c|k-\ IDAT`Yڛ|3|^wWsѸY=4lC ǎ=;j`70'!|s0O>tfo׹0!# jMKhK=ϴ `hx4OmM`w:]z)|zntx~&Rf zƨXh\`;DDd+صMdpp`Q#""Wv8L"ғlZa 8)yKvcpp >72)^{*-2{6,JFe!""%/ߗH +J据?Ǯ]rJDD{ɦaXϻtǻX 'l^ulۗp^֟s~A:mfvf̹V\}mfMT@ H):&Sֲ'|-sc2Ĝs7ng:4br]*%T"""\_%yn}AiJDDߚ)j8z*nwߊOE#WºJ<6$JM:M܏1i3mh]жP~\HĐY7גzmܰ($vF̌ng)MBU3Ҭ^-lCԩ ^`+/w}UbxFݙ\|j)-sEs \ G|<6OVH3s|J.'.I:]ÀStb?¯ L|MȘ=,d 8˓ !" oLPV=ukܘvLJ*y}یk Q0`^~+ç/nqg2_/#D 'ce |ܰFykwQz!G;iQSk~`YBoQ ay );}4]Ab='\s4S ?[sq8% U`úx#5|zq`{cY63Ps}&.(OtM,X7%~8xl#w{K|S`(zKl7ѧ|:#듵kcƶ=[D Wl4po77fy3ߤ3ϭY;~v+սk,}y Oj0Q!#{ek끱4wøA-keLtN[1!7|#Y^89λN¨?o2kb)Hջ09ߺFn{sCqn̲Y/?.2lu4ucMv^~ԓnsˏh"n x f鈀Bё<؆:LUq4һmk֠,|ȡ9F^GŻ?.nd{:'O8~ml×0]y!~Q2>8w)WE撄jif7Єc3*,ok{ hՆ~ gEXs y,0yM-R$1vɽ|0b<r![Y9|#Htnߗu}܊/ңK?:©rgSLGcyƛͲ3~v0n)~Wm4Ocs]TY?-]'h/ׄ.`J`y"7f;,~(jZNR%O6'N"ϝ 6vβ{phhA=Si1Y*ӿlnnh{Hv{ip9vҨp|*TƿrM%fV^͒ADD.g bOYEwNʥ~K{|s%M4J2II "".rfJ \PrWº<6Ҕ*b^"v+0DD6oD`y(W¹J<4ڄ*b^6}fK:) *M#1y/}]SJWy"K*WIʈlVn,lx""R "aP!}~}+6Yђ\ c +*S' P'S˭ozc*EcnmZj/*)RTx.I PG7b6>=\kJɝ%\AR{-"v5ޥ䴹w/'qɟ ({)ȕe8L8*U,_""""""Pe$D}:c}Xl8 ֆ*T%/+[,fsF5j 22>}g [usɛM6L&nvn6ny[w=m홎 3^%Tg2_l~+=w>}gql;Ce0ioCkrݱc;voG'z=֍wmߑ(めUe dNWN*U֭}ׯB 4mv\d,fqt e!q+HHSP"""""R ۷/[nGԯ_-[УG,Hi8ʼn*94q30w[L&L&3pW MDDDDD!~ 2JDGGs?9jֿ6c8:~{j0Lxo̹\Rz-HǧP^ޜߺ#sr]!s""ũHPթS>Ν;7nÆ Rfxw`ʔv+#i=C+ ""W}K|]([7/tHS'0t|P}@݇ٳ;vÇӻwo4h̙3scÚxf덁Hkׅfl0Me&BYė\UӋgIl:q |@Po &7Ogd}X"іU`Qd8]و QoҞ-Yz"?+l6ci ^>u}q;喗⍦pCtNںv,7ܚ:pQ5ѵ ưqDEñem%߃Xf]̍ce |ܰFykwϼY=zn`1>>?|MHD$/.Kر#^^^\t={УGΞ= Wg钡xye U}e60H?̢וȕmif7Єc3jG$~mnp-Ky?}Y{Ci~jLIs 3YUocku#+qxc [8+yzho˟[,vPaxGpr"~a s߱pcLTtQn'e֬-@F8Oڒ#{3'^G:sCHD$/.:C>Rxuxw`||fwDDDr3^ v4y'ug~.9C|*7vx""RX?F=FW?G~tͅS3Z23[젆i:`?PV[)&1j@B6dù7>~һt|mO}Pח ɭƚxxIcw\SқBOfyb7؂kP;/HȜl;7Gy|~O!}nXG}w#ܙ|1?wy1طs݃CCJMlz Ÿ6O?׺ӭכjWDDJc<}MV,2 c`q/}Yں(D1'hǔD~M]|9܉3~-wD:|jr8>*_&wݒ+x>F6oTpDDDMz5o] 8@M ^;XiD>j lm\vG|R6x??U}^)4w"RD\ UeRZ`Fln'-PDD_A{[t"""Rz3^ w)NmmDDWj*Х"""""RK:˕**%9iyt""""re)|B{_^rED?H.Yb0nL/`򔌥mZY,ADJ]{NU,PDDX ತ% aLV:y!ɲ rm'74q?jĜrʹk"J1Dz/ӻSJg ZI񣙸9'֤⩌h(fZuEG`tfI""rźE(jr$U%Ac5 8NWO #ȷ\bmܰ($vF̌.-:tCf^J犄*evGmrM e bE֞6qFySob!Ħ#ۈް'BDn ͘5p<n`TqQO[b>MY۸lfi?qJpEB5bވ&Sj1?^?}.g&X=z|u$&HW&.'j*b).K&L L&Lԇȥr8@T@ψ p> q/0>Dgi4FV86[{o˚}j[=="lQv pxN¨?o2kBPA]g/dU=0ƿ9œ`,Y gy-+ݲGLR'l(*)H>^϶zǯ {GL碽zxxL{łb).[`$S\δmxׅ3>k3]MBq SDDD8 ի83smgcx֎jO: ?N2uww.;L@]=c¬*`Yĝƺ-_L'o#>hk7ɫ3zkTH؈_~.{q\ы ռQ轅nCe8.kٹs96乘Ռ%5SDDD8|?&SBfYS͑yk[#ƃ+ ڟw>I3XېAjJJX71ܾ͐/r!_olƺ_47,Uڏ'~ +|!ϝc IDAT}mUEDDDɧ^cpl~'Ns};'>alOY }UL~vfg>wNO?ݳvW׋zͦ p}hhߌ{Y;Ks_w돻wK"6bˌ[hk OݶAqZ6]D;a[t>Ԩp|*TƿrM%3Tc`9.YիWCbׁH?tۋ³֩[yz: lވysxiw'%^D[l_FPׯO@6וkc;>-.Ɵv'p·'T-."W:^D[ ,l>pNN/q~3~YNT`_PuK?U˘K.)JT_'/<,} hjVj.容ae./Xj/\L 47\ssÅ9?3 ܟbg3gs왹v;B$BiJ`.˫JпBd/P !4oq7hϫ_U`Sc\_BE*!َGjZaӝ\#ixZj[zM?-!K*'fun+<, p !jߚ_*^_LꐄB!IĐLu혳^:c|>J{zguB!ܜ$TN(WCVsF9>xT*!B$r"UUQU5rB!pqP9$T;!B$r"U$B!ٗ$TN&9A@NӄUfԈP"ۚ(5֞$TNJRP ! ^'BgYӡ9$󯝡YԶ=}hMX޵ٹ#:]e }>`@Y0:&||F*!DFrYOW!]P 8!=vXnەߦzȸRr9bp"]S̗ˎ91Yܩɤ$TBAS/7~PBtPMY7{#^1zoOtw^ } @;xnzx]|9#4}Vѱ^g5nEES6+n(N>zv\x=֍q}:%AYimcR<x-cazLgO#0d@2gOKwp(v B!C!cY'?7h=[F pYodb.nh=$ fO>HwxOɿG>/qmӎϿvʓq#<~>y ]A꩘xķT Z"z*3*3'RTwv !dfJ!+sJB54@q@0}XSyP=jPȷg0p^T3?vv.#*/WNꓛ!*C8?!ǠZ mfn}^Ht-W(X*cs,ov !}rB!K,Jѫ1Eo.ճkb;WOT, ~Ӿ4[&ngޮ|;K vmo.4oJSX `SkkFPU:̚R& c0cVr߳@nɞE)9BAYr\!ʮl=3c:61tmoO*e)XFJKUȖIя钼яS}n2~cl8Bس(E/Gؽ|Bw{q~:9܇J4l]"Q«SR OSBRF>`[#= BdG֩2bm !,SUeo"L<ʠNoNl<$TN&I|Oq]BQt:+ aKn9%D3Lf$hޤ [|p% G#BaϢWp49p-IIOILIgϢihrN Z$!w|ϱq!ܓ3S!Gh_;Kj'kG9'rӿK&K*%_XԦ,ԗ c5'ڶeSY!I|(^)աdwWWB{gfz2شmC ǍKs1LJszj^:y $X^\(S㐄I PFY sMׄ'Rdz O} 7.7UgNzEV1?)R=_,ܩdwݥ3K:X1hNT\O“rKQҫayrף35J-# }ʠf!' ~$ՁU,!%faYR3>{Y}9`i }keO ?:p +Jz2&_3dc [2wV1On,*\ZB@v|ո]ݔry58B8$*/վ}I! BE) {Vw.rށ'œ?X3}If,}3zC>^hPT惤C?c =eG)McRS*y_.AUc~)\x{PGRQU?^";0|/0dqq BԋRhlo4p3xpvK1aV :׋ aMT'or< #< si?)W!0辞JB^Cߢ ݍ>AXt*n9w >*\ Fz+pw%c3IB%"[6Ca k7xo9𤋮=MMQU.E/кG<ɓiZ?'ܸ='У>]|Vѱ^g5nE4qfy,t罉Z71{#o ytGPmwsxn&U-)+b,U?Mڦ\ժ*:%]);׍}9[ouԋa2>WHhX}ߚ@PĿ \eh=$ f@l'ǚ_og#0>'m7X°<ե˓[k2tW̚-ߖeRFh}7KUQi;ONk̭9%kBƽy' ղӱ! z0ݩ GFCv}qڪU8Q2yg67]MzѴm5AcHǴ$_6 <L{Rq<́. x>#ߞy$ͩIp"odDGPȏ>Ҫ?% N[cqK{*OTG J|+XҊ}ŭ5VV(OC)!\íE%SԃC&C|X+ N3M[!((hrzCRzhӄUw!m}r+Y'Ϳz> 5].a޵}g~jcc¬nKG^o?~T^EsuVv̲9?ĝˆRc,)-|=pgh1:B_"?W8SB_2LŝCy_wuvDFqH<򧞼FggR3x=OB|"lە:4 >EP}RgLi1i?Лvo/*bJQd?y}|%Zm/kceJ3Iu_Omz ;V dQ !49%kp*;ڿW4{;ksG2[86vUE ܄m\8wFn\oɘ ^v3O۷ٵ*.SWl.NyBt*ܸql޽Dv}SBd߾jXV;no5U9o.uk2Ҝ}c_NoM/J/gj99waV!\y"~&]m*G'T?>s:s!ZFxtHK2rN "*gkBgwQ{%YFQ,\*\eTuKSB4gϞŕf<ޢB U آ(%\=!= B&Wl"sdk9BAlBۅU {EQ&AnO!y_{«:"!9= NddQ [ Bl7C(|i#BCԈeV%{PDYuƲeiW5k:y߮>d&-[Fnݲ: \mJBᲜ(P.maٿğ>*:::CN\rJ!p&g-J3T:+NӻT~*}&+Tz'5>{I#~ u_ٲ2y.;mykΧ(7h/S;Bp/J.m[uؼ\M`yFx6> D}Lpo D)1f FKqg^ڸQQ[{sg@?iI(?х//wig)YI5X}c wֵ&2st fۊ7عh|3w=_fɘUU}Kt/v,eGL7>_s[ c@⺸0bq] *j qqn"p*IBHΚ2$VZ N^ūAȋ6yhnAU@ Iғh~<:emvaGy Ш?tO9d+.C{ =(2`3EU$|Q>}fZ?U L<ƌƨbq]Z*[M+KEXX610R'1;x4.l)Wyꭕ-(Q;y;Aesp3 }YhrG=uxyK9 E)C$P ?> \ʆ<P` I3V\u륍?.֭d*vP !E)u-M}N'?(Á'̙ה< :@}'/[ES@<OxBs_ T`'?XCP:O&v؀_UIX(}(,1V\ꥍVΙa52h@?<\tMxDmgkroaRЗ>Ҫ?& .$wRr> qIp/B_Caz^v( @@٧<펎Q+.k%r&2aS.u{MbE"PFULN8:MBdqhidcycZ=Vɪ=2J=f`00oXXtZX&ȓO֬?B`upi@*]g1TFb6𴱼cV/m\* U=x C- &U(E)f?|Ѝo "0S| @WXSg\IX~̀ٽ{O?'): xFLSW֝Myx1߳PoH>U[+Zm}egyǘzRasiiV SFT)KAztCcBU^X㟻)>Ð)BӆP¥:k94,)CR gWcagyǘzzbm#f4/\<>ך.Fm w$.Y5)Dm;RI.GYRd V˘fRtC_|CoRMY2 L?Ԩ_vsIv^?? <~o_>u.n͗:ƌh-.{El9ҢxΛnX?4vF>_gZ'p^f]ز~i>]k{l>fe1#1ZzqW-/1CuԊP਎*)&ʦ.PL;1D!|vz%U3E7Z.G"KgN}_a`?2[ChVgQK ܵ1CJbOҺpq:pR'\ubZ\ H]h׹x`-eq Q!DNE)r*8=4,'s;Ę*Ma)Yev9BA?]v) օ#T6TTl uA9OC\'z#,ƗRQWvr"r֢Y} B?xA}3TwNl<+84$T.Md2D-o.\tsP8.L9od9>xT.Bg.J!ɔB$>uuᔄJ\IپEÖ6'f$.xTLZBf½pW15 IDATY6=#2?w0bB̐UUub+ٍj>wlP%$$dnpa;(ɜ(P !{%Gۭ=w4,B8~QZoW)!poNs$&>BթV;KBޜ(P !{s_P !piZB)!por~Y{ P !}j;/ײe֭CY--#Z2zIJtȘJk9\ggptk5{kiVז_1bw6+؞6vkK4n$B(ɖ^ђPeO+As+{S|J,~;1\]E^s. ձɔ%ׂR3u[}ҨFL 1mQ Y2=*Ns5c:nq[0,,Zc_ݵ"u+֞;$TB!rCu1aaaЭBh#^OO/gl>*0[G!0XV;N߾v3O9B٠ 损]GϮUU1]{Ul92{3-|QaiT5trָzc2o8׮˩9r,>w![c .~>5S%xnM/Z*3TB!\pB^ʒ= y6\7cu$w]5իۭ=w4IB4G-J!OBvK:UlC6kϝA*!9E!e+\*!.˙RH2%MUURV;"B!D)@a\D#a:-*V#~]B+6gI{QQtZQQkXx?EQX ZeӒjeWYpsYy̗c}jbfϠxC)+S 9ͥPcC8X@jG|O=@{'|pWM8T)/uZ']v.e9k{N>aZ.Ր;5֢Wni}%o44]9Jq[vtv 'S2C%Bd Gٸ e[7f#ꇆJ1t_Jba5N%۳TVe?+!B[`h0Kr7S/7[]QO^l7udmW قoG(ʞatՈ*|)_~왑Ҏ-Rfuyf"gy3$7#?#cWwTi)4mX:e)\4ek Ėݸ $TB!r$ ~.=bRN[uOL3_BYY=(/ˎw8m'&c]yb|O5άHyҢxΛ6,wtj/czZmS|lg x-ϼ{Wwci!O3f~F+g~UiᮯP5TB!r${@Ǩ%xyyhQ6#t|fdAQTغ.> ( ʫS&!Hu{'A=B#r///x%<˯4 Fy^3gדۍZcܶkTMqkkVcG{5Mck_\T(_6iS~o+6hA@@:V7a:-*V#~]B+6gǿk@4kzSf1&Ĵ!F=7h@dʼ:kbOWjPXGXոD-\Cq}ٯiC Ba 1ӆ鶥O5Y{4wvT2-3=Qc~ SP[7j?VU_*VNAjT*J92%㤵&Tc;FT4txHc!gi۝HUU1{㴥MK37Zk@jvr {v]љ3gf軹?vOwXp 5$Zq/udb;*BL&,av-ø$_aC׸:pRr_t"ŃoB#ƨ;X/TYjq`926 *)j;[MV#/cȳEn@gW:/G(fi4צ ̍Vϑuܷ)}Ti=>a̙|81:4 LZZ?=ڴ֊GkXTub =Ќz'(m6?<@PFڟvܴb*o`l^VfcTmܺ]4ɔKV{P#"!!/~dͬ#b~h8KJxC?h"!ly|K֘mGe?+!B[3{qD]^sތ;2 >Gb Uy9ȏۏ^cޔ>V SFT)KAztȷ` btyٮ'/\͏:o)Nڴ֌XWG?K)>Ð)BӆP¥:X[OpևFTwh0Kr7S/7߸FJS+%7x#fw>P)ށu_ĝ8z`±خޅRg!Q&"{ LxDTv3O۷:ٵ**Wl.DX˼{Z]~!Ȓ'Lf|4z)3_vhXUibtg>URu!V;no5U9o.uk2R,Q%E!r/*!!=eWD={e^b஍ڿ-!FGs*YB!D OY:#Ǻv}bt0BBjk*<2 'F!v+k^= } UuRBgY3Ӯɕ=5TB@)!pO6C%P !ȑ*!pOn} B] B_/J i]?t|,P !ȑ*!pO!Q ޜx;6ȟBI)!pOI7)dJ!D0VX?>;[{gr-[nݺe$\LCQj4]ֿ)|0 g$%:@*!9Z54&OT_tt`#2m|0 gJB%B#ٳ߽(:F-+ehQ6#$o\'*jݫP%<˯4 Fy>ULDӺ7l ! a5QA"kTձSǣѿi!s˖ڻB{|Q&˙~Wux}ZI)hv$)Igח BaE8X E;*}@=ɨXQhɔ8$B!B̡1 gI)ob辔}zbqʞatՈ*|)_~aq`PxjDByx|o춹l}=\jc.\xL<'i>28{r㐄J!Dd}L˧}b:qWҢxΛZbAS Tٿk˱+f{#qg4:N K-{l]!>pl2$ BÖ{Q !L͇>Z0#"WY6]*!9{P !4t~9)J!$SB8+Gܾ"SI|m<* BdB˦*@'c(YJ !{sۄ 䏐# !DqOe,Q3Z23ҾvOZy`-e˖ѭ[nov ѭ=2Ÿ= \nP$ c(RdK%DNdbhMI u\GEiq1NǨ%ƸLc4}k@4kzSfsҼD6GhJ iQZ9Nb]Kl啪/(HL޹e II:t\^ cd89D][k\[G\\fRhbߡc4UNwc}`R6䙀IM *[.U^?[M2x/d >T6w@ anf^?1 4 ae{,{$ eIt!JK\I Gd1;// zvo 88G\Ǔ&᝗s?MP !D0qsŘcdnby4CG.r, Q.WJ3x1~ܮpOx^->oa[( Wk=WEσN jjɬ 86kM3*@q$xrQ٪d*P) Uvm9t l!꛺Tk]>gp<Cpt)R^1ؕ߷VP~Ohe:Ս<hϚ~{|"|&hP !D0պxݰ>4ϫ2J=fH?70~LeCEΦe-N6oT+ҕM@ *mzK|rf8lK,BͽPe˿:q5GM@k;<-K]_XeSѹ ~;Eςnzl5!;>LL 9 3ʫ?PSL3gRWŠ@g˨T}t^SchVh j{`ϸHB%=.v r̉y2v۲ _Ck4,m,趩>&/ѥ|^ԋw|F?AR Gx77|*Ҏ㽵 :Qx)v>UÿhDvӉ*+ʔ(S6EB8֢B!\[xDl;j_ʄGTCGp%ܾ]GTG>?y$BW!!!B!DZ%*!K9&i&iJBWeI%M$MҒ&TCٻQ-N긄Ç;HI9&%P|&WԪ]ɀJ!B!lan@%_B!BɀJ!B!$*!B!pjֈE9=jfB!Bgp աk9tp ۖqvL  !B!P/^ŋP/M"߲-yߢ`ŁۧϏG@mM)7WL ^Ħ̵ϑ0B!"E942|/wI4]9z}$ϣ矠\=:7ؼ܎HB!B)t7jV6izmZll:Ƽèa)|7/uۍ2S2&B!͡犝?5Ij6W]﷒W-tB! <.~}mw?_oD]3ݒm7,4ܮcDWj=a !B!}v}M^;2.s#el9}B!B8򗚴oVAWG!B!ɭIB!B P !B!d@%B!B!B8HTB!B P !B!d@%B!B!B8HTB!B P !B!<)B!B'9]s7B!B%wn9]*{*B!BC%B!B!B8HTB!B P !B!d@%B!B!B8ȮǦ9R"!JV.k5!eΖR+iGTGGk!+dk!B!5v&&?BW /ؠh~ Gf{m}l9JY4&R[m7{cr:[۹[$kt]39W0`ȯ )z>ju. :Gt}?jkmc5G?Xjq%sYh1_v"pB7^_gX2._u8xc}Ϗ*Ú6KA13KcΛ]Yn;[Xon/%TЯTuq+B2 6խWkעjxT%k@Hx<:ޘY^/\HP08_FgsK?0#"DZt'hΥNV w3 {;yi9;^7m-xTi8?pm)Eng&ƺVCwnkFtyAΧ} E1}zy+3g5%D L?APeMVOQq6(GU,d]me3~Pցsa55׮ on/LT7_D.trNoIeWχW.aς4[n~`R  (h u"cƌSy<(1UjG@t;ڑù?gSB|MVqu[ B@._\<7߭* SiKvx^v)1r*2٢K;^xZ O <[z({BbF <~? =Q8w2m-'5}F?71p5TZ,EQF|4w56wp9+}#ۗevb=VD,o:WG/9o[S03iPj+F72v儦x2 b U<מv;0#mb]|hZ$~w5$KmAs8oxZv'61&;I4",`lSEu `ȴ<=B c":Q˹9{sB36S:^_G/AXt ?9~p{3s̓êgЀ~ y=^\]*?0lcbi혞Fv^*ĝ`7_e !Dr{/L\͍49^nJL>wgB뢡(~  eAt>[(=C7#uMnμBp[+i5׳ycRf=h$QsE 5Y{|@>tڪR>`кt@!;?ԛܝos2Dݰ˪4mE׵ 8Ю/a>"I'm3:E x#cE`00"6|~V mds]. Or0u>:lɕjWeeʟHqUvm!܃N:;ۋp4aIX ú/ӆЮS3Jc._ !RJZR,Q+5#}e_i;n7{cr:[۹*ǹ][׻|ߤ30 !Hk½# ` t!J|eH#Ti+ޔ W^A c- \Cs9rV?\ B[{ d@ r&*Ǹ[6Y9tFm2W Mx+ƶjOY)hbՓP18Mo&lixXߴ=mSz$*!"|j!s[xp69,,Eh4#G9d8UD4M#(RTDKr+wjծʂP=cmI3E:fΞn|cYG)U ?p4ORd4+E6iPJEӈw)*&=tV%͖ͬi><@cĦg1פ>\)%o*| Q4?J%:wC)N'T-mYӳ igS'ѹ\}3_3cZ, lgVRc- iyӶ2RnۿY`]̵M#Quʟa2B ~_6YSрG9{q^?a??B) C\|wgNZLk#]77 f'{U ЯQ.-h?OmrJxoc_X\T=X: nۿY`O(w_ߡBrx@W%ToD|ɚsB56<%FL0דZfߦft6-8Qm\EK@o@?B/RlNşquBBdK{bbTpUJŋwP_nkVʬYN%YɑyZQ2d@%"R UL\ b?@!*5ȝ+.8kSݦÎűS98ssfFCoPxuɀJ!DMbh?y?'op1}Wm]ͦM"ZΝ(W:xV`J{^;.BOx>(LVuW.[݃(넲alar\="%ɀJ!D*Ng4/J,GǏ>'yӓř9%aCf@>5CXzƣ+̕( 7m3X.0–eXC"f|P 3wveJ -sg͌4 "(JgUjdzs`I9Wi, K+TDOrM GsDv'_.iħ#iwd$g0=1L9?I+0_a0,e8Yd@%"R =W_'|:euv3q:Σ] KY`3~Au)׶h~,(ZRzۀ,/"mgdYX6ڌϏ"?p}Emg(ʂtM)Zcg::Sb@ =trxӛNgTno<̏|mԏFŠAvE$^B}`Ryҡi_/_N=4 T4[9"9e_~89QK02{[w(~p1^=blMmw5Gֲ_S/ӬiUVAr9XRq!s1Ω/^Ω]xi=Tes0֐Ŷ/0%xAʵhżzMCZ|iPS ǯob]AAFf㘫Pؼ@B*h~p^~W)~}?A避1\jt_[yK̂fk.# ,ЍQmv73cy_H*7)(UT7'O$J)l^Åv3 ϗNQUr4mE`-_26jm -6h\tj}ce2^LAϓ'OqqJMsd@&~gO~8*=ps7a,pkaRoj 6 A;x܌֫;-yz/otx(d't} M_H34ۏ|ٽ{w?kW|rn`u ![iUtKسm4Mcc|qg.۶T ZúuȘ1#:tfzV8}v4[BEɐM\<|͛Xc"~JRȩx7qz6o1%K^yP0+cO)oZej{~͵Z8ڴ)yXSk!2H&Lȟؘ~R\rl ҥ-KƦ+9𶱗2nj?E.TUD82f)mٳz 7}J)tq0rnkiv9{^[vf[Ǝ+ǜG}O砥c?oIҧ~΄-/OZ qWmȘ1c*^Rv]ja/>|~MNSȳFk+m3fg}ypTcNΘ:QF;cJ >}!+TrJWWS fCDݺƃ{8uhaa/E۠L9ϑ0&;I4"JŠiA"ZQ*J7J03$~0i?cC "ۣ_R^(du"uGPSk4S_.wB+ҍfoW+n]ޭ&Z[iL~}M+R1FNi?ΐb1iZ¯A y ɹ^"uE]egn '|ȑ4)@ 5Mc E+hZaV(:y\B0?f Ke:mI4&kǾ!O?t,+צi3e]̵GR}=mSC{\p!Yxpҷoλ>Sˍ"%s wxxru(N;Eۖ%IoB/P|&WԪ]9~jX Џ!gtވ(ʮegquMSl 1(F_CFg05=tV%](\ElXXf~X) *p(uQX iP K77ZeK}°Zٖt.jY&'G"3 .V-}Vmqވtwd<:xKKK,_?@u~{%M65HߡRtwҦone66-(H ʶr<Ӎz A WN ϩ4*W\gL z>O~XP'j͖V may@,sGI}Ӷs\u u+&Q&mdoʖcV?ݥ%箐pAKpmrcd-ZUik Icc m9 ieCHtժ﷎u˸^im@BjeJtވ5W焺Ի󔋗|wgr56u60/km.NnT.Zzk=1Yꛍw}j+~|zMVܻ+VZ9V_-twOZ4(U Z<r[a h&i[UV-&~hHNY,Rܾ]0 =BJo?7wn:t]1Ybme_8x7c}'Y"m^}1:NoIoR^V)I?3RtoBz.ҐbϘG3&J3=e>;wRnjZi(WP8"ilTZ@)_=3 z P$z攙mT4n9k_CaM}fh"}غɧ%&>rb.z4W_26]ɹOg.Hx ZחcyFͩiyc~{7̎oS7ih~ViQ5+mGL>6/=ᴵzzۧtZj8`r&4Kxoֶa= eL[\:Y@!vo,0?4`OkQ;b vDZ]eNiGśwC9[VR_ ވ70qt }W|>s* c[=fߘh7?l @z.v=/ oK쫃T`}@Z:0$.p),|.W($ŮPWS]7Q%*5UUQ 2D_RJ #FwT ((.}EEyX;n,kF\RJS͋ʂ3߿fP}PP}czR$M{ԮjꝊ19;z/DzϧS{ F !D:ezR]\h3`:JBql 2DnjϮVߏJTj7Q#B(ߡV%=c"__+T~`5^&n%zL} =EC[ LNTwrfL ?lxe&G"Zr7~ @$P)Q8NcAkMӸy-ioʖYa-\.]X 1I;u pc֤1cv5"@>rkOGPw\ZRXb87D;ܶOvI~M2݆hr3 rso<EyPbecs_T~8X,fk:o`.K}[Bs/7Z62y2 X tp=MsWڳhcoƼ]5w%}(-~\YB?Z%Jek=lFd+ !DZf_f*֏;w^* jMu0=N8P:i+J)ӠZq1}f;T-n mΐ1T37HxĚiT6.(~j~̜4f˼ΦEe Cqg(mP7c_WLE)ԓAjIYKnjt[Zڮk֓0qn\Zl7!CoqiW&4VE3 ߪŞ(nM̬F*=*wjˋE7P> Uv?SJ)ΪB`nR̞( b俪hJAih*eTU &l'kl}q8m+B U䙹v ^Ree'k:t uԻ󔋗|1XC^Oj}:M o5ж\q'GQqa*-I 'FS| K}/C'RُOOi*{||vE\Q?'ʽ37gWz9s֡mTQZU)Oy^Ryrat͖eC<Zr:70=jO"k^<|R'@GvkF͙ s [,3IGn>zqno>~ak㱡LW_)Ըe(QcΟ/eӶ`yM$8%lZO']OSK1,},TO]Z`2?6U !˸Ci3[-\/W*!Wur>Bq=TB!^mn)&Ce@%" BW \C/P !x=TB!\%Ğ B$+ȄBWؓBd+TB!\ɕ'*!&P !ps;9rbC)'*!O4-~WV Wi͈zG~ٴl^G/Yz#((u֥29zA}*;7eˀJ!Dŋz3br.CXΛ/PˀJ!L{[^fC|r̞i-yKQvMJV 牳NJԮ_kh;KfE֯S*ujP<kԙnj֯M5~ U˵')_ ˥qeYj9s^=TzWH_>>x@vqszc|BHHp5CS@5O2-K++NkeglM{ hhZzƦa\Q?32+Vy*dܬ)'h{Z5Uz~^=a4X})R0E9ƊBRu@l~I4ΖmiٿggCDy:3Ǐg׏8هm7 ؽk/'W?{lXiO9`+웶-jp}p,ofkq*ԖCS=Oǽ)>Z󜭜}k:~n|_Jl3q}3y7ަOx9vXh#*sq"#/sԙTֱ粴9Pq ~3[  l| $Sl=5LW0nWt2a# <TǷB7Uuvo7I@ iG Z@ƌiN;EZ[- 4ZAuh+yXS_=8@̀ ; |VTG+nt.32>Ao^?MO_J%~:sA׮^%+ǃiYUӫӦzV c[Eլl2;ӦM7yKC)RcboTGdh[*UC [%&cZ^'K}Ob;-ߖҢt֯M1\NvlemY_wNWW<^˄s_̩Қo'|5[IlRӥJ{i gM* %mOrǽk/J] PNE0= FzY;kh S,}Vmcc]'K}쟾(]߅b /m̓L%e}݁;<Ϡ#[}mA Wh].kz/T?@1<ǏOtBPs\- zHWYU]qzE ̸>k-<KO9^ǽ@F%pZDu4ffΞnOX`xr Hx;!MquzQl,~@'n lZPt$S3]:E+x#e\ܒ_+AiLOj[%,kwzʟ#w{2x7_/MyŒ. S w&DGmgG^Ի w厗bŊBʹjP?HztͿUWgiUC2 &7rxӁF% 1"K2dNNS%O%m&!f8u1LE!^v)es4H0{"5ܻũCf xQ/Ͱ\"Hr.^AՃ;'X~};?,,^~wyJSRMYxmh75t(%5Wm3F,}iلkJP{Uk-UmQ]Z[%ؗb <%oM^tO̜9s̝yo;b\ Ȗ?*L(Z̃za>guJBp j|<ljqqtDP([dmSO✭RP(2'*gU\vP(MaF?P(w BJ B0jJP(U BP(2ZR( tPi8B BpDWBkjfqM B$#ZR( EɌ*jJP(!N@CP( wjRHPWDP( Q+T B0Bu67;"RLQris~5i=p;2VH"## aM4-cJ@zlxV( BP( ݻx(> &i 1e 纥[ܹs3gN.BxݫEfeъrU`lGvC".^`^lЍm=2y/<:e4!_mCiKgBYMN&ؼv+cˆ9dlV6w6)3;$㲳g+Tv0lLacuߦg>诏3~xfY΃Z2ݙ~*%>jrdzVӥ|diu"** %[R#-H 9g׭dmBh?'_ es˫ ~u2]v);4xsI^MYErFդR%J tI%z%z6V( #tB5~kù[tVSu0̋YKM: ]y]0|:yrMvIj? S+ S9Eʹ%=]}}IَnJ?ewG8t0c}\MJߦ9f!2气܆TL p(RA|2&e!MQo[^V<וBDߜvVM*\?5_uMէ0L4* U " YW[S('5=y2oG7}[DF|.A|б\/=V% ?uiߟc5g2퐓ِ?&D亮*)jBidvl?BF–MҵWЮŇ ԇk:;x (9g7I^Ԉ?&3&<;yW3|x1{$~XXnZKڈ`B _[-MbI k1+*HڈGRztl8w+CHv7x#n)T[k<maNOfCȻU#&GD4$iM|vŀ9 +!&=_|1qU|U u4 ӽ5ro\B4)aBP<9d*)>Z0C FQaˁ@{ìP@sOѠ\OשnK_?d״j[ܼ2/)fˉ,;٪ϢHgot ׁiekw H6( &Kd/tMy9`ģ}=pOY[ T0kG|19>*r<bCszB(!+$=_L8V3sEe&V|'f}yB/aE+WV6ȧz I7F5o5ԏw93Gd56ݻwoUȟ2h}x|W)_7) "H;T caU zc o>c6W_+ jf10ސ}(-]~gp'$ݎb+ Zid$CW@Srv/d$E|@`]Z ;xc3-d6'S 84mvWaBhn9;dw}lgc@x[6ۃ@77<0wS`^>K7Y`>lg) M=~M)Zŧ7og٭#/wҲtvfh#ԧz؋gg޿q/Umv4~wg <#+js_2_c~}`ȯeio>giojio<֑ +W* p](~7207>JRʳ2cs97 B9{aѶW9=nşb5M`kaW0!p!W"ђU6a~&3|ÎMtKc{!VYUwM+SwJ.vdGq-gf;v$rvۑ_0rU5c& }T-U\FV̆}x=Gux vʍJv=oZ׏-sf9clN;nmB۔"ȾG\o/e\i2iq$f7{c!g̕|۹y8IOSRS<;p{D1ic볷\kr B#;TFM;z7rpGfg\NYW^dey{X*y C&~l_wM[mW^gnIω]34}}O);]3٭2={_U( ab`6f7់YiF*‹-r1tH"[Ǜ|S`,Fb 9þǏ_wJB4]#OOivud 3~WP(*?RP:jnCiRh?_bߞ8cӂP\؋Ǭ&3V_ۖ)RxCJp-@9 $:A(K%wC"ޮGQhZ]eU vA˙ 讍o As-@L?vy?'.nҬoӳDt@?~<\ **(j8زu +sC&y] OF\ % _( E6 B3TУGw4}Go38Ѕ>Kc&2_wyh™.[8]Ȧ2TWj9po[&l ;t&]ڡwPLu5hD[35AƼ@D2,ɧp{i9xҺ\EoܜVX oVߩh] d RZekeYLc]-idny.9xmL^-l;;M/+U]j;Ɏrm\c`@"SN}O.8?k~=hW+?RO;+1XiU:Sa &Mu@U7 J@+Z֓8f=8{j)2q]Ov3SV z Eʗ7+_ |J؁Xy*kN<`RiŨxeZЭDx򟲋fxz]a̡hV6 ^czg n@ժU|fܴiWZJ8y!o`{X\iU_( ޡ2,s4JKIr-~#&zXOZ`6L&\OɱOŐD^IK\䮺Xne?΁t>␾9 Mt?l' 9,Hַ.OWkH{m]Nt ӤGJUu NsZI^\TgWG̹#"""' 82,@&-m*OYm5S-ڪ8f=8qBoIq3$&zfwl!=&z\>7W^l1Q56ksM9aL]^VP_hY|t&/U[Z<>r(6Vb+"R^/ɠaK"" A?Ƒe *yM7Aܚy;-D$/|A 5m BD_ʕs:"1уɋ-&ʦ |>JRi \{S7.J ^gsyp%'l^^܁ hhZјR~P:JM٭ot}FO .abnI;T }ÇC{ łàf_3Jps@J3CS_,5(ƕ_R:3bh7-\KJ:A֔}ˁGzκƸߦ Kc$_sX* ݩyObi},H{Ǭ'PݾD_fmJѼҁYb>r ؒF&0F+C5CzPU>v7Xޢ=z,V7Р$Gzqn^':BVNI{:T9oqlx] i$}8lxn{],GAM #lQDW;A؎CiquB Kc@`%yׁTh[wj[Gp؏YO7nHd;Tٔ?,|ZӭasEumqM ;deZ mDܐTݕ{1,ebj皔X6/g>3u_|z3vƛ:rL,-Og)Iԯ__w,n@j[s?`E[`M_̾4RywÓ[ǁCK YF%P3r7rӢn f3$^ɐuk{|3fq~7.a5lX3Ղ]܍{r2dl7CNq:,75'j)|:XXyfka?Ẽu;?,X۾4 L="|_Um87BRy>?7}ƬgPWТ+i(s{Yˋc'Yi|d:&E;02/V̥B4-۬;̯l[Ӓne) -wvl6ݡrN[2e|x4.ȴ P(ds Mn_ӧ#aC'[ez̏!9[+ db`ABߵ1+7YiF*‹-r1tH"[>RS`,Fb 9ȟ#fjyŇZE^DGW(m{zɌߡn1MP( d3N}o=! YwbSW(m{zqPe֦ BxɎϲmBP(x*3WP(O)0R*BPdgP) BmP) Py1BP(3jBP( C6P( œP) "8{Fp ~jS BP8F6zJP('3ޡRV) I@P) "dP9iCCܻ8!$22ҩ:ɭFЦz) .3yKR(&ڗ7j{4q!D;P) "8lJqásaΜ96Νܹsiu幎'i=o]ɿ[\i6M,2eIAhqN3lRBBBu(cӆSˬ- m9ΉS9s"{)ןIv`ɇڶ MRfξ`m(O,Qg \PzV$yְ[?;/P3e+’⳱0-w ,*_\;uw\BHH-*R7j^`mcgiE¾/f傦cCGIe .F>>H&pYfPwSA pOBaA.h9Q7W^l1Q56V)Ed--CHyEkdê44:,eӛ!kH=23@.ym{J.@M`2""g~9mUA Se绅&vZD@K@! { F|kt(WN}r7/}%PXDDTFJ~vZEDHI JJMm͚&>0[Ku[ ڭSDx}6K]KyUˠTN?+~Ɋ'=i)Il[m__ ?!DD$VæUw? muUU_ַϧ3Ii^]jv-7_;{$㿔q8gD'/(6(WSKQ2,s*NP sۅIRLCǶ*Jx{wCo6tF2NjǎHǎMdI>ņ[K䪈ȩi+J[j7zm?9#Wreɉbj0L*%{j|".P+mt"_c@Gi2 uAvh5^."ydKf3BۚRT53r{ʵ0Y~? 0Q3xCa@zwB{˅2Ҫf~hUҠAhOe׺奚 ߋi߶4.X(ǘ;}sm֣JA>Hpkrk[Ӕo--?|2$SꘗM[4%-흑ɔPwB%"xݕ2Ј\K>G[Ti'?KfӜ$7(fknJqf߾-wDo>&'}%,YEfJ͛*ϵ˪_?1ʁ^.)Vl͚,,)"Īv7pw|A4(_Q|!ɒ_=h{Zk' _Y 9" JȥlJ&ʦ.scGr&T$>#9}e꩙PEFȸad\ yL䵘4z$/ZI^H.fiwP^6ȼ!:IТEDH褥M) 8!@ vu庻. אb97D,Bs+HaWg㒐tG/$6\{|9Տu{I+ ڄˇ""I""'\djd$ 5ᾈ C7mi\0WX+ǜl~$R| 29^ÑG̹&4X Ȉ$+boճ%&zPg;wBB`Lil:;o7yڲ׮ɏ4gχX:'fqI* OHuSp@)l a|ȢBtI/-_2sُn.9x!$1#}{Vl͚^[ufδ~=KeZ$K~ɲ'=i)Ilg@BAߔ{dj› y2R6u1xa^Xi. $_m* d. 9݄!冀ft Gtn MNaWW T !K -yD$ \9\D=-&ݗ6]N)W:nS:ʵUH{Ǟieq:~'ɮ_@򦮇=VtX[r͖irޑ82$-,X,xOeʹu59U^YzAi&TkWϖgoB%'ō\r$^;?*>nHKNþ g#4I +CrehCs*K3Nj2}%IypZV]T(-EdWRh.j@zP/ŕ HD~M@49K(oŏBκYkٲXn_uИGb߃ِRT 8snhOk˞]7PzƖ>4'ĮOh-|jK_K_vN_wb#A @`hӦNB "AD*ibgn& JP 'Hak?Am}LІ0?@*m!! }6]e׫PvaМ9YrRR {)qAqU7\ o?]>DW;窖Y}»#mJ_b\z]"ȰuU\t:ր.m 0A_S6IBL bғ3uFyn$y8ļNYc٧~lin6duXK!9Y:NbnJ^%; lwsM6 F/Vst;šR굻b/柝E~+YUf>!pg @Z}(.$t`vutҔ(Cyf+̧ p]BT){udiU J&pwJhy+{Ԝ}0;fM9x=z՘ʻv(ۯ*ӷ)}=@'Γ`/ў- =-?m"6 $k|s:QHqU׺~<酇XUN02T=˖[Wd7#ޡ7oAܾy;9s9e}\i1YY(K:6`ĝ,H5xlAE,YE]?N&lIz|{'O˪+'+gk-dOQwi&ТbnxP̳ +翆H~E)G!^_A'=; q|~:QߣhG}pA0 DUgFV`]kp<c>rR|yoqw{ϐx%'F.pw!]Hs0f9Nn~XOqlkxՁ>3ssjI"7T2V]_oo%4MVZx2CFݼw:^Ѥ$=ԡ}.,MhI×אY{7<uil/,e_;Y4=ʢO^Uav+fi,h{Db@$%Y^dztXӧOGCZdm̜n2?:Hvntr6vn/jye-ǂ3grOZbCӢٕaw|֢E0u}dC'M(_"Ie*jw߃ fb`;m+>QExE.Idx#c*L(Z̃za>g~&T/ʟhݒ)#35 WwģqiDTBxjpt쵗I?ʘnBP"FBqtZ+|8?Hu;U4d ʸK叿9y>9 bH&GL]s趃kNPٳ)JjiCw[yQ ѱa?WS(ܾ{;QH[QL=Id m6}#-TdÍ=nJP(6"H BPdٶBP(qҭ.;) B\ԄJP(ÉZ\y B ;^U*BP8APP( !5R( p|JmJP(t6S'Ɍ IDATP( œ =IZjS BP< BP(F U`7,-Q#8_lJ!ihtdOe+-22 ,=¸P(h<(?BP8*Wи{!Vڔ"'c@!$9%Ι3p>w\> tBrv7okYB`\-:USσQ:a WҊ$@x 6v@=~h*p1o;q*"<ֆLD6azte;šBHH-*R7jlg&rї18{m7>UgUzb>Փ%UJYU<)J߫!xȍZ]z,CBqϣh%:ξ @TTQQQ|dSͲ /͵eB3TIBfN[k嚿~5JS/2ե˴lxYP(o*ɒpF U=oSu>ob-~ct|S:ͦ h(1y=k㔑 ?՝;ظwvFM2ق=aaGV)Bvm߾wAwEwQ;`O&$$+#8c|qY7Nn|nFꎔ?kaKy1u@_i4t6-+ӶשE;5K֭G߉_s xx_3I.Ytl mld>~ޝFZ{I㘟빉Krio.[P(Pz UT^FԯYo5Yj;tDD,SӪ|u7 J7U0*>,MX߯jdz1/UO,ikvFK!.ȡ۶z^ 9K{|?q?m/c h3ل=bV렅y;c!g >u:4lNp1->FjĨ}Lnnnv4Uƫ1&.=A5iبkV٨æ㋑Z1S_s:3]ղS0 ؛zZjWcSÚ9!UimwRSp;TM)o}sM 0./xD*݁F^fl/̈́ntZmV|yye8ImjT1ZZUVMÇVk9|Ȼg.[P(;8tD=g+ޡ7oAܾy;>2+b2 N3hZ5D48a/ȁ6T$i\5:#,texjyk<%|Q8 w <Ґo}aTh"I&i+B.47D\]\S1gS~{s\j&5mI:YS. 56V9v[.v!I?+UD$:dJ=4Md0;h$Z1 8ﯥ4*Kݏ$SY[.bo g@eڲݜ?q',νjg|-ҋ}jpG(߸ʟOӹcy/?L> i)׶1sr"Ug"i\_@exN? <,Mp@rݺ0#ot~-F;)j婒{h23|`2 6GIKPL^@P(7& f@ܼyCG]tHݜq_V|b\ Ȗ>5Qj1}oJ1fn{AwEfk A܁&yG%EwݹKjVy. Ri3<I9 ǩHÇqu͇$? ~A_ϾeroYb\/C;ʓ=d]4K COhFh017R>iO-1LeiGHbwlQ)3W_ˤsF$,gj{st@LMjߏL ^RӁE64ZZ9p{QmJn;5ŗ7hPS•fs}_jKXʕ;郞x/Ѽq*pY_2ZJH*4(AZ,?96-F`fy-Mr͘o`&Yyy̕|۹WLZG\ڹL@+96H`uX)׬<<;p{DӫP(3GukFv3JߡP=cP(O'ZdʈL )ȕh\ivM=֧<~cL޺`];[_ ߡR( ϡ7{L ;kᛷ*K:[BP(28҇'_y-κV#8E~BP(+M6L gO✭RP(A;a X8z\۽VmJP( E?P(*LͰBP(D={%gP) iw"W2%v<`ؘBP( ytKVGM B-'x%ڟoCJp-@9 wyJC_G6ri.wHDgj~-A1ww?23KC.~~#$]w7G?P)1d7!`ͼ`Ɇ={8TAr;K9Cǁ=S$&z!1уytubDl"C&E{:]կQ[̖TiUh5"j}#&{͕qryƹ9%l4@oYTnŠhO!O7lB ЉO/<{SD{qHuRcWpͼyw :4Z/9cލLg6ˏ=|MȠKݹ~+(`DZz\RC ȣFiJ֝UW^cԅ5㈾ jk `-PyVm0͛pΉfGnU҄"9lb֠۲Rڬ[+f3[l+1AsO7$Ok ^Y+{ iw`DzySZqw;v$vʐq1lzY>Sz6`.!O*ʐѧhM;hw[{IS퉛媱n m0'(ۓm\lGjU\V;b~KTQjBv柙VmvBudBprfxJw:dἢn]ŵ*z$g)|$ekr?R..PaLs&!)߽#:УlK~s:g. I;Ui8^88zۋ7 IR r}>-^qAN<%MG / g'WAFfp4yLx(FL_s.z $oN!>w I>5[nc6.~*EAem\<$Q &&3*5OѸ+~flm;6Cb`Ȁ}`ks`+I?84r 0R"-O[~<j=%2";/fc=y 2U஧r >R9Z̍Fmc #d ľ%\Gm><]6x0xSww=)} f_geeԋ,!HP|RiW 3\;SCFtjʛԴysGePS^Kj?d&6Cub ڵmm&e&t9 smEÝz|}?Z jY- +0*+Hb2J`; Wbi?tpFP]&#"cqt?9@+dO_o/vMuZUlכ>] &ʦ~L$4cOgot%۰æ\3C9J2z<t2Ly30:[s_P7T>4˭vE׻dvw?Jxb,^%z| (ko@-~Go#Y,YegMs֏=Aulmm1 k7Z25)Zë5I2Ƀcǎ: pX(M*2M+ey*r4p-`tG@` ΂L5ecs% |wѻ{5fz# 8]e9ԁ-gP>mmCiȧJ)j~;'N $eB no /ܮS_&b+/7I@2mzYYpn M eCiP@JΟS,!ڶo-P$5\P zS J[( r將NK`#qš-e6GX*27[c$؞}G$2, zhO p~FC8vԭ'jζ'0$xhݳ)ʰnW N%zQW)ŴFUpe+k$KӦq m* 9:tNl[l֛Ԍ(@LO\2xГQf.qM?tm:c50 TبdG-Naf?=>64z&>O~?7wK  V$ҟ挮U SVS6)FgGRN-ӄmO1۳Ȋ YJ'SQM"H/wl r_<5>-=tZ(Id dy}WmQGL[(2XwU=\|kt/s wû8uxk( :}c"gp/Pzp($]c$p'R/:' [~- 7Wf?GeDnفIer:eUWƮZ9G^˟_*cih|#i WŐp#/C'mq=ɝRDxt Q;a6Xk IDAT+]P-O8yģhbItCyˈ 6$bC AִR:~z1TBh"X9m.pq,ZysApUpRI=Vб{|ےӫdn 6|wڍQ96]>~(\<3 oCJ|x8{ڜ/F*Fu$s2-_ѵcIZ{?`ZD(>}o-A.ɈW_E|~\:I/'KYbgB߿Ί6C>dz޴2 LABت|O>Ǧ_1rTA4oO&QC0 @U1/vlPR=kYp[^ u dUlZ60#,^ gYΘ 6cX۶RA)bBA$ɶ!om??4-F{YmeOhl'(_|{Rgf }yU?@ wɔܗB+_! @ I^ UfL -" +T@ 0^MAP  ü*@ %+>R(V@a @ U @ 2XXAyV$IX%?0NXkz3h_N ǙdTٓt7wE{xyXΘ}jCaG>w:!쀘P  ݩy{f AzuQT-1Yq1U FzP.;y)F[{7k$)vZ,;j/xYuFM=+TzL&cXrBʖ5zbXJ΁a(CB.6߆YE){~+˷;;B߸eT |P~9$IѡUy[c}]bB p{1k94*0ag]DAł9\@s@Of^(^>>pxnʕ_FXRps.#.kItJ~Z 3c#Ŋ r]Y,e|-m7CPDD/y",(bĤZ=|QFq0qixãXyO;o|曆Z6e1ED30 ^۔Ƀn|x:UΔ}w$SUUs$݋(}]!%^Wo Գoa25kpIJI:=.j5n+Xށ ;Y5n:"6h,?11LWw1.]{ M 9e`ןWyL639^?x @'>M#\3/Bwƺ۸sK.< W 7kt2MkAѣG2v$WHDckJ.3 ORڈs 'I6 bK|ˣ=ª:s 2Z6l"ɓAԐdwtC>5JSjA|ʗ-hԎIG(6A硻Fҝ9B0 g['׸.]~h6L 9Vm'NɃ L`1ܳs[@4ah.5h䶬T6֫ʥ1 ImYٷ'ۄн j՞-У<5%+xfz Z58*GG0Ns)W#P*CNee:ڮ̚P<0"Ʃ͚6?GLBe0ˢ*-X9U|MRp}IU)$G >NyNc8;ZDKBb^I@G/ gIUpPvsWc ܮ"Srh6d`$6YyP;-uev`CD^\@6E=\^t+^/uJ#$yI_X-MjMݴ:1u%kewGmWnP=~M:M.kesT\Ň|#5N_*?qRmѸ.k|<9$:PY'@6y~}ۯVrˁc iQxp/WdqLR07ILF7ԟڬ0L5?s#<TU9fMgOJ6)M>6e S`UT[<!gd'ĔD^ދBwɺI&wN=ql 0t:]F+620 r2-GsZ=Mݴ:I=>O_ 0u+t;|,#olKȐ*?եtl_jkui^9^*Kq=~=8#sodUy̬dט%'ӂ~sL IZZȿ$yD"/H>b1N/$M&C?Dӕ-K269?^>/Bcsdw2E.\;9D9|.ylmz?ڭ{)g{/0$p7iʠ˛K<"{^7rB5Hn>I?_ql4Vwu>۞XrǂK_gT j}@\."g,I27&P2ej|WJ HMj D[zTaDѿR5 DT}q61ig0wlI&M[scNBIѺ'VS֕aݩ$-cT%K.jol3kI{hn2&PI}8.,O~eBAeO0@>9]r2-W*e푟y[sbfb^e[q]O0tџߞՑ݋?˔ƮSwqjS)Tc*ӥAN,T2Omzbao fELVK[:ڮv $%lm9Q +FO6pkz7]+126!]@ؖ QO.mf [{aH{ ũ3!ǂkQ/u D/^ HX?$$;Q-? G ߛ=4m'l S$f?GeDnفIe +[X Ct2=!F^N(<]Țs sm."2|>nڹ]oHrͅ緲֬_ÒPzSwƬ'vcGMW၏ ĦeA&ՒԎkJmOPߕ jYQ/XQ=ʣOyy"sx&.d1S`PPܺ|ϟ'c/9 7u'CqPL!pW {V 6O215dXqe3L 3ΎhrVWCfO?\LT"xz I[!.dTZ#ϛ`Ul(r"@Γc_L05Cp;~Tjl3?J{طo_VF&^"ozBu…6A dXQz_:%m|&S4;{ャ6Mӛl@d ~E  ]~f^*@ *@ *@ dB%wB% #V@"V@a @ ^ H6; V@a @ U @ 2LP؋iQ]$889h@p>J&$ $e\1+%\g]4w A](WZc!"Ľ\QRg̾n_mE|O o$YB5ߣ6>KJsjM<SfǦsW{ 666MK$H8s N5g_bW#x+8<7c&/ Q'F~@ dL_]B:֡OhIT]A!}ixcB(Q 3})j#ػƿJr/FJSw7l2}+mU 4]bl$!,, aaURE/-Xkϫuu W%h'>ۣSAEL4 DGG#::YU: f`] )[^xySuX^nZWkvL r4/p9"WR G L_JLL4 2e;`\?89KJsAI {|]N+:"bF 5;Юs\ΤRa΀x x0?$Q_%9+Gb_n[z9CKC鎞cyٷFA֓+T? ACagTA(Q Ȉ@ģvcw\:} `;:M§S;ڼ@OFnG5kV5Q(^@rtXsC3 jo^Y+T%Gh9$ !IV] G*A!_\R_ePlM{wz3iݡjB/izf /j_+t'rTFm|9:\hdAtIWINRf͹0B^S : IUzmh FU³zH{4Bi1ϕ+vii_eW/I}UGڞJN7^.,v_2||cqS͍7$aǀ^h[śN~r~Pyy*Z:Qg02׶Gfː`.ҘgiUSk`O%IG?}B|֥sW m4qpWű}}%Lp.{ ZUCHkPbŊLE'pU<oke:t5A&b U?s&ju{H)k1Dj-u7A${Ux~foϞ|9%'5\ qľ%\Gms@ 0 loxXLŠc= 1 D6d12;`Q q/Q-ʬbxCc>+&H;$ 7HSY2Gw ]gOBL83E9:xf9m},ӿc^.}\WA*;u/NOɁK~,N<`&QVn:[ uB5f #%R::m y|3nA;Rʯ4)T:_'qS/Tn%f/t *[:6B8`I|LmSoMWLFx!DbL'[S6mącǎ)R=@[+9(BtqOVGx<s@ 2'Tlx4;="\'L9MV'2!6"P AjxPGi'z!r5w:f$IӲx4J񯒜y3^N:3bww0~zՐrWhƩ.5EDuL$p}b}) @c@7d~c]dz& ƙH(kato_J2?0P k|0g ^eb~1Oɧ`m-)h~9Ü#x\|rw48fu6I{b{P.p?*=u_yp% R:(F]NEDsW>Y+WzP@ xKG)V6pM_" oBY!ʺGBQ);ͼjIhڠjpHe(5:aU*G1$\'S'=Ji޻ jV*\Hl˪bd >c6(*5IjK3N$ǧR:y9(g3Y{?j!5^ ͔VOj爻''7Hԫ6|?#P'}aaaG#l!.ׁrz1.ø3Ldo#Q/0{

sVňF|+ݐ?"B^b ڙ^ !lo\Ip*Tm~hO^۷cR#y;|U2lhBBha j1)Q8I>[<컖mђӪ˰,LS',  EDr68+3Cs+K?o^꘩dpu$ЀIpMET󭢝܋bB@0qixãXyźRnnsuf bRp-y,Rj .58lbVf`HTὄ?d)sꏩ'11Jhc>\~[ ,s#$ݗ8:ͭz`{$I^D ;ay'IζطPE.dz^N~E!M+ /_;Z-`/Ƀ^n_]Mc>3@?2Mm]XyJ1 96e ]X̶ܻqFQVp͂NCGc]z]}4 䵘Ϙ[^_NJf—t_ 5ePJ&o4:ȅEݹfjB}Xܾ8 .vG%}zX[%;OSC x A N\6%yJ6."z2y0'|gX<:S&&0͛pΉfGnU҄"9lb`&Txj\KV f:^9>k[Ҷ6녇ۻGI>>.̓^6ˇc̻;j/FW称E [K6LU%{ 48~jLfrrt_k+0$5-BQ2ȓAٻ? jLO$5q!cwcxI徥OW90-Ucݺ` O5'GmYrm֭WK3b2N^I6"ϟ/1IG0Ns) ʌ?} 4]ʻ_-K٤mC&V7K㝬,d/dlPG>O$Or1Pm6F❗ɼ6NG_\7G@uəv| 2$j OH\5)!$& pp4efY|h$CM*5}Lϙ& "27g8㾯FH-577;i;Ǘ}<_>6V ƷݿD&>ݶ#}ҖMIR%˦J1xDUP 1zx'T b 8:zDK#M3)#2e*u;d4=iQ7o_Β8N ց,r~L/i} I8S4RÉμî.9jiоS6ra'jϚA,]'{D }RyNg:ӫ5'G/%w\eLfeR?OKqGb^ӂ9*2 T#5N_&5>ӭ/Cz9YJ6Ջ=uBuBiJ`$PbBM}_>..!O\zqp>m\dkWOe'Tr6PߣnF"I8$$R>CH0ז0u//2?MUb̈́J.SnL,c8K l<ML QͷJvFMX }EcUm.±cdýV@گ=pikc8}|vGll"oKĪ{[KE,'fUG֮_] -q{s$P8}eU֛NJv-,4_vژ$%Ph*}V`hHhA.f/FzfN\%a Jugst*=|!2B pf瓍&w:nGHSM#FKYWewSQ>x% iB:KuRD( ߲@|nN03CTŜL5$I&5#=P3+`?}?x@#Y;ǖIBlǵ錑yTœ={L}w|mc&ƚWnۑГQf.q𫽭29YJ6Ջ=L̪핬P .\9=m&ih]%7@gOv6&Bɢe=9HD¬+T̩lWE݋Hp&wD7`h*ɗ 㑟yr#2PWVoޯInpwQƔ+PN\p(NɮğiR,FEXܜRUOPӋ=V4]7BtwSeJe3#O6ܒFia )sD@Wl4ᄺalCͰj [{aH{ ũ3e'_ E lh+Q!|$#QH/Ib4<{-b.Ixæh*_ Ct2=!F^N(ߔ<]Țs smn5+%{ʻ\F9p/'*[.LeHP ٣Re^9xh8""DB'Ts8SL2g߆Aq c9:)99z.@_Cv뱾Eنk3$avZs]vATƌF rck>vcGMW၏ ĦeA&!IBY8ZQzgc L%f DO[*sCl%];Īgѯ_Gt ET6~rJ@ R_wrb#Hb/9 7u'CqPL!pW {V OR@VZL\kCfLԲXapgGGx49+N/dOj:sVL{J8!᱘P  dwg+Bm.v?S\?r"(.7jBq _;T@ x[fkYLƻyV \p!s&e$ʅ \#&Q@ xW@ Гјlq;7]\FL@c @ i{™>@ d Yy1'@ k @ 솘P ]CL@`744@5_%zńJ &4 f/8Mʷxj ;AhHly6*@ deYhHV.g̀0 aqgLĖH=::uš5k̦Q[gjdɱ" cmun E@`}V.V3}BuA$m,P;MywА2nbb/Y1.'DvR?tF"VGtt4 66VP)kLz$&&f טkZmCjdsM< :@`ݴy2U`5mmӄJ/꼳 1i؛gոϛe)=-;O!߆Yŕ{krh@U "\ǒ;ՇO/4G6!s~;O\"jj gϞ,YĔEǘpIيuX9 . sޅSkW$?MvbJr\z p`z W\;$֬Vh,=AcO!8}T89" (`8= mXٯi=`<9IYNbZn{ȝ37DQqF5鋵"I>Tp%6,Xj|f\f|h>ePU*dټ,, ])iC&Nd ܟUCN*>:aayhuM({vmooж~'>G}1ot0_W}[Z]`6Ey@@?ZҢ76r*'Tfh%vX ?k: UĂٹ8h+S f7]Z&mP#qw0z@R #E @_8upp-DHU|Qg[_tG4.b7Are[Dl>v! w]pYOU}q{^(=@E;:Aʲ.-5ȍ{;6Ĝ Ǖ/p|BO+ױ%+9˗2XY 9{:ޒC);LKNV,S=q2N< k|JMePvvmoG{?1՟ceB"LpG mW`_l1$ {Fkx.N)x( /Ġ~Vlۻ85cF%Brq\FKBJN7R$!I*KB֤PS 1Œܘa={>{~|kw];z>'|X|^ױcY:1cWu +p%>\v1c{\Ivxɏ;w s#G480W :)lxc?}eI;ۀIwVc}x!<:1/:>jqժ$f}uׂc/}EֺL. s0׫ }r޸w=w,Z0%`Cgbfݽ:z} 0c/֠IeU0ErrQ:RG`YgKē} NjF|o\u(~:Ys:p41_b;Z8,h.Y,6\fvwU^c&6o)wUcY V_|9Ŧr[sξ{ :WOZOZug*ߗO5}̿tc317=iNTgfkdtWjӧ3ݫ_ty)_?dSвRlNJPiևןˮ(/Py1c8 w/7'먈ܹ݇0f } ,049R,eȝFx=f[sՍGtʻW:4<۫yyz]@^忽@W4te'%q|eh+8Psۇ.TEPgX\NRFyY1z04M#R,e2r^Y񽒷Ԩ3rw`l4{<{ \>Iװ m(́}Zw0.M6ua[c@҈xIDAT6@*Kr m+c_Lӱ5h2ԏPV]Y4m1έT"$]3,CUeGWP{vc=Lses9AccbI1Mr`l *vtA/Klt'IghSi]NDD"}g%2K]BuiuFʱs>{/'V+TPIDD*3|AUP]:18r4gIghSe%""WiPŶbm+N>teE~/}aŶz"""kPuq{<_6כeE~Ob[$]3r\lu.xǾ۶}̓.q""r9{}6ztt8+?ú5ٶݻ 6q)^GWl_tꒈTy0 TPn |P.y{N޵܆v)׾Ttڟ yۘ*\6=/õCDDD._dI;/WѷVCcxwݬʴހ2--""RAWP̯xzPoLzuh}˓l'sSnjIӦ_:>}<j7"f}Oa"md+: 40tѣ<_2|NԩYԳ nWԣa& Ѥau"d2NojkHƍ״+CgԾu6䟝֕zv[;OmBh2t3[7NqOy;?6t}ʭc\)M<# tmEtX]m;W- _RJDD.]eWaoׅW{_$nmvJ]7_ARR2G/%~Z>YG9tb [&p }֛w=I`h9lnLfwy sfz3s׽[e~wv3QCq|\ρçoxUjFn෣9x0#Y<+{|-%l^lkG'ǎ9z\Ǯ]8vt 3'Wt&}ʝcĝK'sֻc/dۛxGiCp$6ء mY;8vbG/_"""C) 4 04i]0w'1 i47 s3y<4g2Mz{Wa50~T1"k 31Mc~ qSrZ͘ef3Fign0OY߆>e IlF[/FLRڳHJ g^_SLuw8o&$<4:޸;ާ\#0 j:5=}=cX~l3ԽcYxvzTҞnđsRbd:%R \6l'Y;9ҧM3{0).Nf!O7'kÃoR>MNaF'}áӒҍ)GSIk}6v̢ZH5M<<-gIǛz΃ۯl=ʯp T?5h.)} o#E;ۻ9<);ާ\#ެ?r)fwZXf{>j۹ocB\vssl;\^*㬟'pgWcm#a8fG^˟ž&w%ojĭg[<*?Źouwn^J*SQ z9z*M=/k ='#&oq|7.N෷zU'>s*WV| Ջ7wwxx]#=A̛?0d]GNszp,ۮ,ż<.QH/[yiPyǾ"""Y <81u 8ODl[*]+ث'^4ɍC +2]v_5 L 7> }q&{Vgin"AqS)᫸|(ݝn1娜[ܙ0y W߹nSE{yQmw>peYVJQ!F0wަ4ɪ [ؾ9bNhh$mzKL>o椶חzf[;1J6Y~uuxw3]}xoFSmW}S(y4h2_ٕ) O[rg4^bv5Ց\j>TNetl9;]qPEEwᡇػn/Xl\/4/I9BrMu$Rvyy7f[ux"zEѺ"v&J>{TW)}׬HI?w5Ցm~EyԠ0Ȫ ?cȂ2E>wO_hIBa6$4.WxSeve+~㍛鼦͜ HτթRz[ZҔdJĖww|1z|QNNN\Ț 7mW^2_`I@a][ͫ8SDDDDD<NxԠ:>e<卽Q0Fâ5['NZJwϐjpG26 t?a5-w~boS̙[Ư{ɬFw2JުkWnHF0עw KM+;ևT\"hPyԇj4 ZAQy KOKM$-u-dl;D6Ƞ5m>q7J XO?DR/?59rnXIKc'=s+nxL^MGAnn_y .p"YvƮ0nvнi':M !8ϒi\SKwG, |q ti[dq2Yn{w(#Q7z4<ߙC[k &Sg"""""?q5wonr+W' Hzݕ|x ޠV1""zl8s*+mͶ{j}s={#A嵏FIoTkA`qMfKm`n)#z|Ai0D{b%LՈc¸vYD֡Zts' raTt1.l`Np(`iH8߈[6$=^?:-J|܀SZ|:8lfScJDDDDDhc\h=֭R%Kc5yu[:]8Z'@<{wa-Q@.-3鱗\3@,@3KM&WyAم3H+{xhcɧNe#se&X-X,32E H~HA1rCzH\z%S>TELK @k0 y\Wܙڌ:}k}ZZT{A$4!-ڂ\^5g7EƔ}0Y0 vX,ARb26h3TίE'̴Nυ<ί_=>hDDDDDD|qc*=3@ *KK d{v_8cU8kL=Tfʿ@% K@*̺ArFw"""""{1eCY(AzfBwSY ,/L'"""""RyҘ0W Hu?A J!"""""r91eCIm*03)g6l}J,<<#zGQ=:T^T$"2ը^-DV m^Xc&3$ ͙鼿4gNFX;9s /gN/ L)dkƙT ǟLpp(C %((0C2ypԽ~)HNs'''#'<rϓs #=3駩N RX1,zuW _SDDDDDDWZC J;M1 m(˩:IxxFO/H!Yk3H=y̅~c' Z0`S'9}63;}*:agˮNdN:@rB,g,KacoIENDB`packagesearch-2.7.11build1/homepage/img/packagesearch.png0000777000000000000000000000000013507430555025236 2../../icons/packagesearch.pngustar packagesearch-2.7.11build1/homepage/img/patent_square.png0000644000000000000000000000505313507430555020306 0ustar PNG  IHDR} gAMA acPLTE @TI`TIdG-YXo&@/6C$3l*3@*$g@~%@k @X-2N6E4o# ]oLT`@ ] pHYs  ~tIME4m KIDATx[ w* cIߖ-K+ >$,l'n;].BHۨmҿ (QCt!bc.lP?8I±A;L80 d$rLazH4<~BNm J~R{b ]cB-@4wNָla(u0͑i~N HI`[*)B%sjy:IY)$%NɁNp'׎݄ ,1dzx,߁ .c?Up^_z:⟑mN~MVe6xc7S7wtt5VnZpiSn?v9Wސ#e]`nw:f D~y~i~3awG7iV}m'eo13`8rۘpb[5|};8>Ti{*=ԯ!mfy!ޏ7?fm8L~Y @Fìu~4شB8 P.*JH>l_)^t0n63P X|/ xM#g3&( dF;YG6 d+u(&!]xG'pb 6״ا 5hU}/:N`mLuuf>Q;IR#Î5hATg07ч;Kθ/.j(Å>I6&l13!ſmXEM~ K}+%1%"&`0C͏yzMj@U|Z"6w?oDZ4orJǶ`ej~JW%#̈CR0%Pr͐^#=#m>HSbyZ ?H s~DẔn C &m'E6-*L?7gN?i+s?ܩ)ˈYG iԿ d3 chdN]z:E|M Js1|Tc[7CCLdmkݩ'Yw MOXipՁP"v <\ɍM_c}:㭗i-`&i B”}d ʍ6GSK 95ʫP7,-$Zw^MMzE-7T΁'Ⱔra);Cbm4O>!\'8)K.p)[v kx*\½wbK!7k1U+>&UuUPژHR9m"ܤ+^[H|cLqZ:ҋRl^. b`bpSp,m+nqZphsŜ8kVBή<\Cn$OUx|z;.o_DjՍ5=1%.Y.|e[>Y]5Lqf 2q5{7'|b drZBY٘_~EaX5~љwq/d c-{PYFnx:v{nvTOvx(p- ڪ6~tD?E˛wB ow$;7~;<yF"; O9ӓ qn:awvKJ <&ػS{Y/*T#Kyru옽6ݝ]@>{s)BwGif \w;R'򏎛g=vˁ[bDhXEPt=/.;Ǯ*Ѡ2=v}$O;װsZ.nGYwa]"*-$vSj{Jӥ `t^K}bV[_yqGcZ]﨡{;~-ezgvvMx|vkaOѪ:|/tu}+@Ž 4c:bcZ|\z2sսԟ>j=_bߡvKo'ڦWO,$5Vh"!Mh%1~fφ=#"-}1Rb Ͱ6MvbjFz#D_6-;S%b xz|}(u+kLȀ=ۗK;!%> WO~ >0A®[fXfnYLq4#T_<`m/+Aվ|0v( hXiq{}3浿 xXnBwABy]TIENDB`packagesearch-2.7.11build1/homepage/img/screenshot_ice.png0000644000000000000000000020661413507430555020436 0ustar PNG  IHDRU pHYsaa?itIME &{L IDATxgxU3BHAz&)EP)"(bQ"|X;{-TBuc²l6ݐy͓gvνg9NDXVN3(RD5$_!BP(=~"lF*Gq =VQrdB=˷232zJ%W@T~;JZ[oE5B!txxe2fLJ*R(&%D"RD*bD"KbJ֭sQ"+B[&ӌv+M39lѬAc`g@i\R QZPpFk4 FY!P|8cI zѠu:A ^?vJe -B >*hTFIM0c-ھV2}'"B' x),K@TeB@:NR`]t5 s>EpGD0qZuMC> BGx +p @ƾ{B)WL'Bc0jFgL5[6+m9Vz^tfKs>`ÇZ`0F`|Uʕ ߝ-\՛ (ڞz; H I HPT%*B~}M&UI NӶ<߶W%rg2[&|Ch \%p8 z )[zW?:_W,{!}??{hYJ9< Kq4q 㳢ZEfZ²,2,r,N0,˲,C)ͮy|v۴j]agd}>B>Vv{uhd}}%Oobj̤Ywd޼GfWziQ6M,)R$P(DLYxCR)glr~=cOtɹǁӨPG;/w΍u=ҙؤfNH~o M۝@TG3{T?湭XV?Xl·fK;Q_5uT'ڻk 3~`Ov os{t{}6kR$Z;'*:f RhHiV;I$ER"$)u}GDGKzAáѨPhÅ^y}?w <2՞wutS˴dyPUBf8bhXhfnw86nپ;r,HQb1Bhv8>kƻtl4k.:B|m'?1惯ǖYӗV4` y+Ҩtαrlۃ'6ƭ{3fLDSn;o;:w @.m |kڥě6ck_Ūp轑*W_VmeX FӶ=G:Vab]KLTDa {}z>n]mvGVֽإwtkwrv߰o?ҿ.aY;Ǘͤ5h&֨s&?p,%4JG[4moپݫhЎ}M/aiFG9Ѵݵ<Ԧבi{FVnQT@8Iӎ2!,K1 +)Ԫ'&[X奾,^drOJrK3 sDzpM;8=}!{u#@ӆ=VR㺃v[j` >!2cᡟLq\[ ժscݼZ=c}/nZ7kؼiZ+W\~hnvz;C|tY|Bo&, B("2$Xp7mmM[tNѸyW (Q Ot^t{A{G.[)A=:5Wgo|pl}aXaz }xu,|%\o~~b]i?[w *2 VFrc/~_Ltw/\}^"qa}a}f  l.2"rtcBJaQ0[:(Tr9p1<4xaSvN|'6ӣ@Jaa!<計kIAӎOM:8o5gFGE 9aηz_uy˧_H:4FvM]+TٴiCEaN5ltvV35Z?r~'Dz%ٟ溗[7-@v>:2,N'%BAfvޯ&|t>%%>6  ~0':>ܽS7M?-]xlrBti^Y9f׽p{v_:iX=`*<Szt9[\̕O3qoJUiP *\feݺm&΢k ;0pgkhTjZRLFa_uh8skfL3\ܡMˋW#>z}Gx^ڷl$Cj˕ѣc17w'vcu]vz㵞KR`6Wc԰]jrd*{nBt/S̈́*a{t"IR~p!EEE-OWGWӜy˻7XqY0OLT'}$ܶE>a;r)&\s'nض/;G#4`Riޮe!};KN7Zkk[Wxbnns7wԹ ֨'6ˣ'}ZCp9?ЭCfZZQk͢~پ{ukU`0>v˿TaOls4RުY #huvN!6x﬏%BOipp9>ؾ\.drT.2L&20_XyXb1%2L&dRT.dL&I]˻r| DB%bH2\$L$mv;QLfKҝ޺6;:}2i\&3Mo;rsq޲YÙ[&2oڶg6Q4}79m?-[-^g!)$QpPQs8:[wIIKu-cZe2B0jgURz׵H$"IRK$\{S*4j JL2w8K;PW?߄Re:(\u}_Æm\#nг߄R|9I:u{#I!B=E $ ?9`߮e^Sg>kPFm*hw088,H9w ?熃ݢ^W;֋ UiuNeZo58s553=Z<~-SkСB&u;< P3^ (J$!HLDkw9{ [QKn;zu«-L۵{2}֪P&Dk 3ٸ΀tѼGukVH]!hos#P|ebLhs0.?I$Gj*,)"ɑ=OxŬ unV݇ 2^MM}h?A.ijPԕRVM S>u%[4cF!U 4o{͊Ӈ=zԮ5mXmǮ~_qtZ!Թ^J^g% $T{sNB1}㜝Z5~\},`۶֘~qSrIu7mebg^XFU>_cƍ7g!Pi#}?sdqH E$Aȥ_f4mgOQLV?vʗogN|TPQFToݾ%I̶5ʞҺ WR Sr.%eN HE^B~: 2` _Lz `;8{!)%UBܾr.cuڽ,q?{Inݻ`b o_$II U]\?vgg$Iwzf&z r? V+D$뇽] (,v_w2 ՠz3 ə'n֭=eH˽gn)/.FF:9N|nͫ -۸ȵsӄ$ f8gD[!EL29gnݛc>͋^iŽ U͝صsQ,m"I"X-5B|a? E„by~w[-v$L:=䶬ڵ9%߿YrQ8 t$I)A'S>yM㚱Vs=9 IXrUIW5A&1l\+i_k_MF*ad+b"4U=xbu=a;/ᚴ,#Ąkx7Yi!J?7{Fy$ wZڈ Wrkj+f8t ߵ9=}5m|w_J6^j$}h$I&?0a]?{  Ĕ[Y}NV&x@&Hz7K^r~e3в #zӷtkb#^Prw+󽬻1 Y]'o;OĈ \KwF{!Jynv'Q^(|;vlG$~xYO)ɗR>ܲmyql&A*⸘ǮJN]MѢaړ0w 4Sgu9͒$ynoi 73^MvK~eҫ^Ա ?V*.΋B:B]ŸQo>jguysFUnרis\Ux䋧ۋUu*GRwʢERy1, Q~;oBWmPm&=]#(ݣcsTmDR~يU.P!}T_BF)&LշMӋjǼW,;TvҷBy eC>wWӋ.>*-X4ePZ)՛lo:zV{̣ecK)>)B1\66 JӏG 7…] n?tufbY`1˛ҊQzz^_6g\bB̘BbKO_ Yzx8˽JtUbŘBBXBX{aC!܏8Q3əUa%B@7ݸ:eY-xBґ7ᰥ!|_x.ߕW']?!Bne|SL~#f5&N=qqBT 2,Tˮ=f@aߧww3_5`vW ;qqBy>[.?Ozy眡XIB!T'L%,B9j 2?V~W+)A!|Rd fYߴ2ku&!*]Ey'X뿻%A!гyy3M?2 {!Pq/u{wxBYS:[$LX8"?Bi:ߡ_ʄ؟|ij1R !*ry\IC"]UPI0!*-O./8ϋW?^Wym[B!?BE IDATB_?9A B!Tb%ֶ*,B!\?B!?BB@!P B(aC!0! DB"!"IWV.x^n۱{iǜ!4hJ! C;}cm=KŢ%\!*翮ͪ{w%@/LڢgBwr1σh>xO!sӸ /86X-{GFc4JJ_`ٖs9&xtb'jxB2}2au\q=ڼNQ=+}8m|CCtB$oҨ{VaDWs+QRdpu*ʆ)xN%L(:|W!2Tyx!rWuM.Z^L*&\;NL2~d _xBĞS>ZaNNFj"yl)ٰZjp]|Ҩzf~tf!P ![CYF}VJ;$B]ز@^u.*B"!?BB@!P B(aC!0! DB"!?Bo[P2q BEAwoo. u}" !*!Ig|[@0B!B"!?BB@!P B(Ct%B87A /p>Mu);a5`#$r*,&!1J;T "w~,7߶A /IVvmzWVAf9Yf{&ס#BzhӓO^gܪr`ؘ+`U)V_ Q%'lhl  Y'Ld'_QVdRtc+1e"4RTo/`/6MVaX3 SȈ2a <(CͺҎɴFK추H3K""%"Iz2lФR΋6:״UW2 vFꕧDd|bNvиNuC:mkH3GFhMޥ^*$փEO;y֩ɛmʄ۲^:DTRNM_aX{K6u0[[^u.mz:V̵k㽄bFogs4qm:wkzǜ!_jU [Bu0,ò4úiA?flZF*^}ne)yf߻/??٭y ɶn_kмN-_ V,v!G}W)jJtRҳ2)u2մfl5#BzmˑG.bJĸ,@'[)3G߮f W6Qcgo;{R&29I5;v~XybDjs~^ignPIͲ~;ˍc2Vd~:4q`[<#fnI v_IRﶾ`w CVޕzI婋?g{J8/az9Vc=[U#}{v5Bx9cYq"(a>2,#,4S]D4c%P#{4vhߨO뎏;û5dF*&ՔqoZ1 ),_!:xҬZxJYnmI)rd&k^μ޵",p(0}wF37W,\jte|.{Y*58½0֟^jjg|-SgqЬhTs"? GBm L$gHV2rL^+X%gyCVS|Y<2ΏAJ$k2&0.0lG F5mZ(_[)/٦ֈMS3&킂fG䴡-? s&IH6$bQl&%SK򃅻&U: &[d*95n9qvPp0:T5=>b.y^oy;=~M#T`9aY㉫}6G-LhV_ -;+qV)2oˍ{ :-׆Ogے)]$I4~܌: ќ$soϿfإ޲^ E.&e69<\x"D-0 nL<rؾ)'F"5A* Ɔjg⯤8B8aqдC3 1,G/ۿF)U4շ^sAcE$i;8۾QŲWcX1^$"8ywKѳsWֵԡCrSWƏi=D$qFwɶrOlf72~xӀ׺U箋1ûR*V >֞|ӥ`8๻R'RM"RSŤwpTiг yݞ8lq?k}6$Wm[?;}'zؖb[ov (Ҳ ~c8 bܨ7J5ut&]ځ T,o[]Cd7L)7OlDV(S-qX 8,J!eki SMyJ"OzKJ;(TB.lY  /ۺMK 8$I^N0\.J; JTC,˱l@]#|/zәlמ,(*QN$ $\>b \xP!E[?x GQ'py R$$2vgXJD=G8Q o !YmG? IIbE<A2D+}9]v&)eQ^~_#P8{OSTL*'(p#pDc9<s89J(x3G(2eRD$4M#FWb q<ϋDҎJ,9 E$Iys,AA`41 #K4.P9oXPҬ^9dj5,{#BNB"!?BB@!P B(aC!0!RjtF~gW~W܎9CbW &\cΐnp͗y{YXJJK^Ķ?^(ٲ~'K)>޺zu_Sl65>^JK1JaCT'vsS&VvΪˇes`/~^($A,%"F[%ψץKl!ޡImtF[id^Z+Oԟ76СqD*u&C9; fő=n;v}kw)J.I`iYFXQ٦LJk-zĄ󻿎գF);s-ux/H"R1y W[ RIn`Xa+ïvU1&$[ot[,lY!fX˖ !>ٲN_9}v5E9׷R&;{ە2@LzٱKX#7p=Xş֟{,;þh0;&j,өiO7}ͮIy&.w*ٻ⼴!tSϗy`Xc eTM{ ~ƒ}ۼvF 't9{:ZRd*QޑIU ۘL~ (Ado$x,ߖ?$9mh;i:nl$(4<l@"FjR2*d-?Xl ZZsW5"CUət9+&\-,[6Bl˯] _}Z)]<{/<7r 46R#LR Ű$ѸF̧ozJۣNF5bjUujZ `lj~l?:Zh0yBUµPd1!O#-/_ۑsϞ:VB,q_o릳) AJ頗k_Lmp,!y|e[ϱ?GER"RD Q"_ۚ Dykg  B'?ׯ"?xBdҐGn|F:Ikzƨ^f4 ew/,n3{@D3nٲ7y6Q]|bGZ=ԙuFۅƱ,wjZ5=^!:Zh3WRi`mTB Z๻ !ߖOnA=>1kC=>1u?母׷ɯzH܍::m垄;̺odnu]%bw;˥T­+ )&vIS {iٮ ojkXw )+nړ0yps/=`ы72EZm+j R[ҳZdu3W.:pړo jg9*3<}Rq~$YgNybCx]_2Պ1M ׈߿_o*|R-hvauPxXxm~^D!>ܼBt$^(xEгbw*\Y7A*1H%1X_bGP(-!,ҙlמ,im߶+FQ!Ֆ/ńBU>=cri}M!*a-H%@ry?E`!P1/iZ!HVߖ_AŔVՈHnBR_f ܠ(ov3m3IU!nRjXz-fMv<s5kKZ8ve[9TFg˗/~}i BIq& h~`f9*T+ >zf䅻3$j̙y9k7˸]٦gpdKznm=*REņE /oI7z]kfgحkGC=!~9-Xwj€ vf\Kz̋aW7_릳^;d~GyrpJ3=]Gtү!(=׆FFxM B]mG ?aљ a|'JWng|Mb)N&S7da{Z=s[x'/<c3)%9rlݻA'/-F՚80)$gqڕ">=[V/gJ c{R"W; nzӎ9C&-؝e W;KN'DoU*>rho=4[_X[XAr!W/*BO;5 IDATy=lF3N1 ,pKB=HQ84-n%nb#5ˆ~$%&8gbAi8tBN֙`)216]t|j*98؞;e]"bx9f*aAJ1! cl:l RčݘAq`Zur tdUcJ~A*iZW-cCK$ݢF[%J*9G,D 5S8滍2+("LLe>-ܦ u>39,0{-J܄D&6dT]냐WBnZ㗅iEP8A_n͑)[&_(_õ*$Jq7| 0d\]qs\+qG~Rd∘OPk=o)~cN7/H.q<K{E!0aTcv$I^ pдo_ yxzaaxWbBd*/%sL4A`+2 my8 l!Dh_}-Ѩ˯Np.pjaqN:b4Y]X$lly8xyMRjl"Mf˕A^2Q!T; yw|swM[* e=eEB'*(CDEdO@{CNnte_/H]>LTJRA9D9Y|r>$ƹXaSZ< I qu@AEy0J9Gy{ɷdff:R͞^O' )Eq2FGeHo7>]רmeɃg@&՞S>TakK?sv]Gް|h@ɶnߥ5{<~YJn܀fcr,{!~_vBb~jw)WV*^tk^U`^"Pp gUߚ*͏nb2*T#Ax^p]xlHk4gbȶghzϣլ6VrՃ>ZCkxDI>&<'B\Sʻ _&ӽUMFyzku4kX܇c:Veln\mt3ۯi`bO"֥~6aWRm ;Dio&dwqڨv@yM PM|e˺Qw 'ee/or~~]A.!E.Ͽ%gQ{VF T$J_J* v]w؅,*UJs mI0}fZeOK Fդ_6Լo^pߒ#OʟK &7`)$)hοKen7q$Q|^cJbW7ry# ugTDwٰ]yA?yqC?X=u!--ԊWgmyu֖bȶ o:sgg8b&z(ysúoQF`vL[g-k~]赩Zm+y}+w!'v?_o{>{ sqǡ] Pgc|w){5Il ֩'me| !0{jΤ 3C? pON{/iu hjX\T|#r (hN2O<^|VbV9 qS=rT>YDQȹpk5Y=$s{V Jx^/s.<6$:x?L͛e չ9QYˉWRyzmQޔ|ӵkzRNɲ8xѹ$ob@~߻ӆ-UrVll 8}1,oޓFuo詵YЕ>:@F'6 'ʂ5[VSJ6O~ޣP-ַc{ny*!`lU@w f;P.T'f+i@Ozb6 X)>*^_f_Q|Y+czZҼ{_)d[Iݗ}4!qWfOb%Joj`͞ [\}mx??2߶.zTi$I?R j=q9q}&Q ^Zs]xIy^s8fs:%)U$ _xb \dd)o6UN`[M m^3ehS.7_ݸJd`NR+KZ^Z.˹(o˧4U6[U4wvS^R3KĽ2y`S ^yy@QZ^{7 /{AÃ"x[>gdlo .'?#zsy3w{p!{#Itγ+vuݠ{&Ե湭K9B"?J)ۛ~\1-# O $H#`8{*uޞdpEqV8xy;zCtsw [8ːWMI!}A\eR̞C^O§P_xjF~ ؈<z,3ݜeJw_^[ P(@qZZr(?<~q2oҺ~ `d芓|ր\uۺ~ ?T8q5PD;q>(<,R]l$I O+!0!,%\ͦV%>JI7Užh +PY\u iTZ2i _qH0IrgC\cVV*|nxL fb'*Q:R_*H0Xtk1e>A|oFU {O3O3GnPpU8W of"* mW}ޔ sЀ4yowI4G:Fî7S=0@zmBGSmVy&z|7S5tyKުN<{=&d kpL LM'ڞ_svOlY JnCsյvE&ۿS[ZFŐla^:h5\J4PVl>xeB!T <'Vxː r~4apY[^%@6-7F>tΰV^qžM\'Ow`]o ZEJ:3miO~wצk=/o{>kUqfnz}ގjl./r)YuXv`+w!7{g6nϖҹ^/|#bu!*^qW_፹;_JlDEx\f57-ےa~͢+J]w؅,*w=q)!d޲-&ggl?m8ugeNe[D8};@6k]'R,R ˶Դz޺|ﬧNɟ J{Oޒ潳k\pˉfy/{)Anvu!*^Qq-U ]lV§c;o>t%@`ǧC\5FKvol1L]N&y!"XiѺ#3Mj!II0ޟZ`C0J yљuٗB?a?̈́;;3 8`SJ}l@`+GKiӟ{;.I'Z3dl) R'%BAvJ\N>vX>4 `StSz-޺BECgܓ1ʇi*L,j;iH m^3ehS ˰ Dca]cz7Sԯia ~` <bpM|l/^"Z]]pd߶bBr!嫳S#,_sd'~ݪVZi׾gS!J fN I>Շ:NV-ߪ\YU^ lHKX3cB!TwO4&/k a>۔nM{9jkz]H̤[U}'|ZHn.ETNq&Z][ ZB!Sgm!gJka9S3ye~VhmKsɜeѴ3 ZHA@6s6_w^۳GoWS BPz/B!o0~92f ZM}ÛzYTOjC+3G\\Y,)+:=vW}'"6.|dB~?}G.Mʜ'}w Tk*/;\wMZMa菜5} SB'B!!?BaC! vMP;B҄?BB!!?߶FN;BҔOkwJ!TB6+& (!?BB!!?BaC!0!G>ZU 5J%8hu$gXGY!T/LѲD 6fFCxADJaj&"4X*ҍ8!T flAu .@8Vicbdd%&<FVf8D *BEϚj26`ZC C}qx^HMp qk0֮҅1, @ʺ!GIT / h5j Q*lf5Kr,kYNÖuBȏD!DI;x! g,>@@R6IA0TSY!T`CpPI`;aŝ $IDPJ$TC9I1!Pio'8$IDD);xQvJ+QJ($I$ F}B%$+kJl%$P"Iǿ@mvѵFhT\zܝ=ǯK}g.ݓe.Jh[Q *qfʖC֒Ʈ@]`e$IEi !'R*fyeF/4;s-aV;_R.![^8x^W>ӣNZpЯCz7b"߻ $JrzJ%#Bt;SJ)@)PJ%IE ߻][+L0Jd((JXW6Uaֲ)`4ۖn jl+Z\$3RJEB|5P$9xbJsc4KwYm⮝o$*%7Gr,sr,vhտcÈٶȥrf~2jú7}]+5YVaw`GEeK:ǴoZSV^ۖS2rB^&2Tmy;G/T$Q<A2s3eJ!ƻ#jp4N^ hwm`Yj3k.F[߸lT/tj*gѶ Gn&ZO;m/J>w=1݄lҳmF+Xd?ק؁m>iQ_ogڧ}:r憗1y 92!JO?G!P?YT^N =BNqV)2pڃn$hXm׼:ќY|veY&1%g4)ՐjE޼v^ݧ֭+}8U+RKxιmy SΐЇ3xG@ Py'Y IO^ۡᗿlsNx6~^|gf)__d@*q/5@zn\uV!dǢvojwǒi/tr+vbΙ+wa(J-K^sN2 5saO/ՙU,"P."x^A~\qt7GwQ),4H۩GtZ;.5 `?quz>@5yTWut2@vo X9c2 ';wB^{k;)"ֲQdjv+ e4$JAy!g|q!D?ID) Ii>_1~X9ӆkʤUۏ%֙Q@KSKgasOm$e^w[cO\=gzO1o_mO~rРlSNYZ~렂c;RRr~ܒ V9R{>I+Ix|!P!&eA͖M L(D,(<,R$@CCB)W4!aB|+>|Q<7lR?* ð҃GSB|#޸w(! PaRI*;!Q>Sj)T :o\)OdŠc)aaX°ogX|B|j#lt rJ°<cYWqVjT # ǰ B՘PPFR\cj3U(YNIH)IAqtZZ!",d6(&saUL!JY>/bWWiA) {1q,fٜ|n]h]XeVb|~!Wݪ1.Cԃ Ri5b+sZ!JOݐJGv3o5R≟EC² BSρXZz}7ZУiaXVq $ xC1! 1,GIIn\~(h-ަlf/Ht4cVB|K1K1$E6Unl%ڬEo[n!?'7sPr{5}B5 !*q?[YTLkT~ePz#,67n9DtQHO]Mixx'geg nfԨO*!P!Zի3 0@OEW w+>0CaFkD 7S$giP孑m}%! /K1HT*P B!_:()6 Pĺ!߿ٻKr*-Rr(Mn!J6Mn|ҍs+B!T|R 0$"8@R4SڕC^̙Fl˩ITizk2Ւh=B!T8>Jdi[ri]ȕ_iXKVU9EJ?"r- BK5@Zy˷y:**/J1}'?uoXEW SJ9֦fY,W=A!|WG)03ѯ l *2PjYҍ̣@ȁu5yt:UH9r7=@֫f^YfӧCµ!kbiO)&DU ݦ6ː69BԩAa:tl%Y:ng.Xs[B豅@!0!GB#!?BB!!?BaC!0!G,niB!TvG|_זkcBRtO3#BQx!?BaC!0!GB#!^k˒wsv^*˅jía$Ցa1Z^_8X?}CeR|To?I%Qq~Q"],٩>&E@yY\]y^S-aAlcm49KL ZyJAdFoQ㧗BJߐ=S۵,WQŞ'~ E@3m?[pEPID 5#O<(ɉYRJ%QXNywPQRٚ/Zd>?_C]^K3/B"?GcNŗ\JE$ / %@T$f$cvQA|^(#I$xxR~sY{2׼<(W7^!eck 4_ѹ9įVQA <(b&;w}5?%v;ORJAJ%/~xdD 4*E5^Xj.o\:B>@բnQ=bo8fzi,pm|cd_72Z}IMs: RI$04=P Dhb1>fWf FUF'@ަ^2/C+l9#"/{]1Y\bY)ol.sҳӞݼU*_,ֻ=b5* ×Ɯ !o1-x|PY u}uM1o`OZQS)( :x2 " M+wmDHduㅇV  jK0g4j吮1N^ؕB^sS-ԩc@džCYr S֭p,U롄v5slj Aú5I4Rpv %fS1)p}ArS載i/}Ѩú5m뱫wRkT ӿub\>}/9KʹLѕ:nMwjlK2!عe^Knѥe-˅nT}Xֵ:7t 'H.?Iv,ؖ_;zmaxZ03y՛Mk7pboY k}-Bٸˈj9_$^?^Y:)=Jv^p}5?^%IKifvkר4o}GտhM|[{xd_9# ;Qug R Cx^hQ]3NիYڀnv #/4% / R8+EC*7 %CSX[?E仄RrL#lnXw qBJݭu`Tܞw'< |P_]c1#OO\_\>y}D^iN߻푹O[FJp77yJOoj+h-9ԠO-i"#{`F^{J(bp6% i0vfR6u\z.!,8 !%ن,:N0<@0 v2jA/Xdd%)}]Z9&%KgƻR}yEQҲӝRBjj;LV !)r CNlpZII)*}5+2ֹRyW Jr8 ,( )azJiLL @mJBF`Q]x!cy^0-J2k`aؼ+R}z??씻ak˹V)}KvRX+D*/U*nJ"Ї^}pN(<>xwdrr|r %_;eKAs_p< 8aG@%n޿cl>S`MVɺCjz]QݖOŧ66MʨT._Frv;û7_$ѡݛuGA 0>vǼ*Vp`[˅,^{K_g:}4BJjs\mGn兡ݛ-paȈO^cp^H3܌S>ݵҍG odžGOpv!oYTdJE/ JJv6u#z5b Q/fDQqElZnrCm[^Ha[MH'J׶Snٶ&OI(Tꚦov/~3o.camw{&{L8car*p]EZ\zsذap?5\MI[r଼eyA5Nu5ejYtoРV דv$Xf,cεMVcb>ӕ)ہvhlslJ|X`N_/&ɫUňaG$Ip7S]Iz֞2tM+ʕ ÒR҇^8f־%ӜH+I*eܾ:a۫ ]O㸲\{>vY&Ӫ &X:M" S%o1D)ܭ2ozI@#QuʺE!\ !aa|Y*(H-]-J]> .Qoi\K*Jbd>U@ * $17rBTߋףu3uŞR I!<Ǫ a?c@_a ͯS(\_}Es*OBV~ lJ(Q"?Il%Z%/B%UE*a$9C`Umې-ax^" !@Èo7RU*Tj8w|=$Eɋwj?Q~6C.")ETzaW/_Хfӊ^>*Qrs}DZZ X(DN>g5+:J%2N-_ۖBCaE龟*!^Blq=v}6X唔*m$8iwmY ҨUEFr}1| a&sDd6/ ZPJX]"ï8B~*bWWiA)9R > QnjR )i`6͙wօVЅUf*BqU5>Z¥C7vv\K˯WUI6yoFOB ݶ$vRЅ>&&$~>3°,òCwsOh->>e130[PR);LlSaʺ]t.[Q`oFr,QY5oy- z5Y }hy 8~y?f潹~=nBa8A.՚u딫Y3e f#@fUK'z߿;}5]ϞϜ^ Oh}j#ROF3LU!Ua3fGBCznG~7tL)ǷSiJ{V|5cx]c\_u.:k`1z|/o_N ^2`}+g{oYc.M^x;|Փ?qU^ʛm< ĻW|uȖW?^py?Y=cy~9WS^6gh U(/Dѽ_DCb,=Z:'?YA&])byM]Q9B-|lŘLiDԅD^'^ިF穴#?VMI`ح6<78JD:=_rn#Hhus' E/-eydLDA2PyBb: ;wuNS~ i k8)K,iJ3/*D:Y.bHWiܝ)qv]ɱuJx]9 ޿y>y.||| ;@AF)g Wn1'8Ʋą(5z]XB*>Q--Y3ݒRKYSV?goI0:4v⺭z6(M Ի#F;{]/*>*҂"*'8Y1/B2ok䌤ZNY5R^fX#;Be&ݒk1'cf 8N?ofʝBw7zmޡhx-8Cn9OF* :68F7%acx^H3g&ߎiL[5k6Ƨ'$ ޕn-=(fظ3^qiĴ`JUitJkrr%vvg1,Ƿ3n:w3XI`X ?^x*uW6~: JݖNoE*^LOe<5SHstPiru)qm[^Ha[MH0: NiQIv.ص\@]W=/6٭|܎}A2/g']j+֎Uʰ=q箄BtanZ9:l%ç 6S+GN'?V.s_i>5)0G6pOVs Ոw0ct^k4rTn!`[?;iu%I|Ype]EΉp[ZgE~/3*lx,\N[vՑt|52b66^~^[7x@{}?j080go5bƝu\Υos yp|ۼC˟(FNlJeO ]XO ԛV* S\ĵxθ{ h71Ŧqyo[VC_=~XJ+;Πb;N^vJ!ի*80YwPC޹ ))Lg<âH\3QsΞ;s΢#9# L &D1πsV wB?u ȼ>:ޮ:;Gxw7#J)M'jI/!rYAשpqhց޾mE>ppOhmmq=[k;*5X[gMaW`ZufwqIHBd܈~|Q-pbEf˞Gedf99'bRD$ER\ T*bq.E 7NoWeL}eno/m8wmED2}AS)B(*8a~a8)IE$n8( 0Ib\w$~ix>ғx9u~i(Z BT!6~`8N4i H$')(hhHqp_hp V Tj5BRĢDRI!@J qp_(xiD#hR]=xJ-IpujƆ3̊WR3e\B4 !6n$q]R'`Rv[M/ߧ}]:;Lic.' 9U 'sy׉8  !t!g}VMP4M^4Mh1 H(ƠH=PLF κy*cDflAː)Tn=k˂qB\Hϒ"/a`H@jM罚@EQԷ=YDm _|$&gi=DN.@\^"SdI):ҳUO%2EeBfbp`|cs*ѩY|uiv0$IEA tnN+w∦H&5yKjhZlֵK8dIWĿ1b#5 ?!Y#4 "^umK$ BW/?;[T@;7h#*W8un^׺DWR)E]Ѻ^|=C.Gu;yG6V%S}zDNLNfZ,ظV$E{DL<8cߑrwu̖)N^KbYѬB«OkW6Rn=LKԬZ`rE7F R&H`%)$IrDFBo<xt&k.ۈ=~ JL2[`ǀF4S9ּ¤ثV\krϹ]ĺBiڲeg-,yhhc r+aI"t$5$d89X3wDA]a5;sg~H37<;6XkTrvnIQ\9KSVF܌%h\¦g:ic%ӡAG dO߲AX~r;6*AG/ >x~V88O`Ѭ u{b!%̊~Z"ʖ,yܾ'hJTVF*ST })凔ЈiJ"WB4MgI/9-[Z*m~?뒧񟕭c;/c)q*kiE]l& X#H2ʩd7,7ao!ߚ{ yv_H_s@J 53Q2 kW_wH*W@ky8AcJ^Yٴ^CoKLCoԭVyG/>@ g{F3sCo$f1x ="nղ[&e@^8{Q~r|bJ&ܸKzz+hEuLbKQt뱌,ARY0LjN.5x9,BҚ31pbjN9ĔawlD<߽hCrg=crј=2ETA!8vʸ EZϦ N+qWMd+c4ϊA$M0[s!/+ R󸋃mZ H{+g~Uh%$dԼ^NMR3O_['{LFOZͯ)${Hf 4ìD\ Xa'dZ'e3ۄ4TA |bs2el)-y<鼵^"3[R3 LQZMja2Bh^B BOiB_R/zDZ&-qwDDŽO|}̔CAu8|yIk|?LfGz?= #9yx/th-E9[-y$z 8# 4 EҌkǙ^S-j6V5>jS73Md]/^u_&RʐzQ%>zgv-d/\o&]=2EGC&*Y3w>R|!KYu߀6[Yg,hƕ6o70IB%w q٩/2 .3a7ަb>W(zr<G{rrqjHgQri/BM_ޯSSv6AWL P%K:xi}k6(3WB&⟼ҳM)W޸"o0sY3 >Ѧu%b h(f?@kfH% MkҡVe;P4-+7 7OnYn*[Iy^'z7Oӿ˨C/kG~{@4|Q]M4UPa'wZ!tk;gSHݏJ v%@% [EVF6X;:=׺ߝs~i_de0SY2썛Ǡ\d0ˠg6\[*5ŇeG3sOcأBR%+E^;urzփJegny# 9ZtR@Scq?{702_~\8ߦ}?%gqagS}=YęFO,vf&9vJMtы]CTڀKͭX$DL01%=nH; G>}{\/$IO+"?lb\8g6,-Yۺ:`Hpp- 3ƒ#7Ow+W9u{h6i0MSҌdgJTئUGO4wYU iRtxߙs{4ﭓ*7 0 !"^Yq)StkY檒f$훃韭Mq&~x`7ElbA;4I)|/&v^x/0bY2MVw+;X ɆѓߘE.Wm=K7.&Aȫ#95+g}p.|uJʍ5Crs17_Ynk@8oT2+7:muD#]B% Vii\} a!qtF7XS?<0X43u{[?7$[ Q[fwժT"u[4xt};RgX#m-GnIe|hs{$~WR/ڰ}زߗ (̎"k:>o@d8ߦuR&&Ҥ8 ^kJi֐? `{aVw<~ðv=@ Jq2bw# ڊ| [Nej*9Z $"wkîŵL6Bȁ$T Iƍm+h[LB e9A@`k+pvdcP3 !?OpP S!0 h BtfZ21?g'o]ϛaECJ ':]}vIޏ!Y&hZ  )Ɍ5?w}>SI0< Ha"3a6oGA[a!/ҕ*TUyW*@7>O enA'w-( ~ίs< }HӴHpalƬϣ//l _9|)ppA D*EVig|88$:&nLI^\<鷟'|Ai 84Y>b8fog-$JUmݰ#\QU3˽ܽ_j B@ <0o]9mHOҋ[R5WKb;1Xٻ`#80(pGq~ԏ?.ï~X^Gf`5#h%ͣ?wz{ܸXQT2/?I9WBɲRmr8;Yly//T LYu֛lףEiUߩ:PX[% tD8lK9{LkkcW$E=yDc:u~"մتTNdͳE6YlYD&I䕃~8I$% *B,`^QI̶٤3:%˖ʲ$)G{[>`'m|>$ r29=3s Y/K"|[3oDgU Ovp9qꁕޓ6]1Z9{B%0̮=ƭf\={qkGM$Æ-:TqKVF0 H3w>HHȄCFBө٬[ ]xS72B 36< F4nnܸSIʵнaaCo祃kMRzcL!= _V?*i%heѪmn1~,#GFUT(e"oTH2%R$)S(\llUqC|'2%5]R<>˖pJdx̒&2E橿1N ]9\nmG ͢u> 7OnYn-nLv/wDVv?r*Y/9\bTRdYFjjKj4 6$#z oHxK`LoG%+#jT($IS$AS$I$ fm%&RX>E 2kVTJ9 l1sTɬ.0vΥrYC~ʒD[yf]gKvȜ:=+iF2M=ݾ9qlZfA ,4 ئUGO4w{ΌHB{dND|IXMkj^Gg7B29 -3IW6Yf<[PKVa3 j6|9F5m88CjG4ES$A$ 06JI$I*_(ogT2#[O` k\1 KO||Q'.!JG8AӸ ,:9%H8RZ|M t' A|~:=_-Q>e~8_5iSlMgDŽ32ze1!_ I&>bBL,%#YoU`A3acˌaTp[5F40HJ 8x7 $I4M1i"BRS)ӿMgâwK~Drrp'Y)R><1aGcY(sVw/*Z%psU"׺`߬o\ NP~fA ՠŇ䒌ˇMq&Iz$=)۳ۻv(Q"q"VVrk!,0P)tmι}iZC0UhʛVY ]HuKb<(RM4ihJMPRi&I(U*5hшiH5MS̘zm˨RB*BMP$@.oԫ,Ȕ{[6X 1KbB9@4c9fI޹ZhZzio>|I޳QW8avSC_鿷. 6AQFM#@S4{B=χG"D_?Ć/;36{&F,tr|IoHsV_Z+C4kk=rts;VxU)BS]/Z>œ5#>;h-rPr H" $Hc?6Un3[N6)h٠g}_f὚!o=UGIyVIcVhn=~k$RT ^TGfvge #r-"54t, 6ovBf=g~ttaOZXbX#Yv i3h !RP}~-E.iT΍ym^Lq :5ʒ"A&cr&9q}6"._ܳ}J]ӥ[ϚիT(W$epO kd\s;mE<gIoY1_dLYH[<&٬Tkԡoоf]xBL A:2X$NūwC *p\SWJ*HM( b ÒRSmOi:UU-sHȯ_ aޑ@wHFf-S!.)  xe?$Dy0MYHۀOgwKUg-_y$E@SW I2/#[v31V+`'.4mh ӳI$ lZ ߁mJ؍ۿqػ/!MNϾu+]a!$ ~i3\GpE҆ݖCqmN/yON8׸6j5M|q6Ds hNDFi:/+GrOg,Z5ϲhmf.EQ7vQrcrfFϐB\X]l"-IOrKQ,)ip&aP7]vATA v7KX w`Ѵ_Ìg+*譈v ԟsX=ca<׼^/ek]DNΩUXau^G6;)a83ٚ6pa3`Wx?sY5-kF\0cלӢem9MZĐGHK5alaN{W;1x9]xq~Wֆu Hιeem9MԻX w9 !̛8ΣzG1* 0!6{54EFijN~H<;%uYȺL0_88eŝa\ Z)X;va/y]m gZ6D:I\>%$IѵIoYBK>Wc ͺ}v߫n s!WUE _S^7!6/" 5p/2m+|>a8c8zgv-d08,62\ <ݭ\Cia\ H3i\Ϗc#2 ?hU6M=~ҠJ//{Fqc x|aVzS$ZZ~0wuskj*CqPKy\!G7#Ǐıt?^nkkG7@ _Jօ>}JN IDATL&[gw[<1$Q[IoĘ{NXkaXzk[,=_z&*9O MSOw/\X;bp"I8N)(_ӭB&]G6W L>oyO #}F;)7KSF!ؿkҦr5"Dώ 7fuf8 &anMc?m+rp|Nv>=}} $'YەpT޵,_d#׸JUw9/= DV{4?*y ;1?gu2l_*98m} yfg$K0kCɮad[СQ {uY2Cm7Yfʖݵur3" ;5{zқhL!YE9N2wusk*bMQk?zm~o`a5x|AÎCZjDھϔ aˇJғ\JWorUc' ETƝWtkFz䖴O/- Dlڦfn*5u &5]|,%"n&Gm4tmz0c Ͳut0tJ+ئݐ9w<(=,Xì·-GNהgGj!osp|0m1M#`8n?̮R >#/_KK(Jm1Eݨ 3巭ye*B@ Y B 0 }yiƀnf$P2i_?mޤRlsp}Fmh->rkmnŅY888nԆ6#0Wqppp OMy0(kbM:98888~>rs RsI$ܿ& s#Ź(}?G%zTz0%c0$ܿz3sp1sQlyxX}1Qk_98~ ŹasGalN`ȗ[ߩ2BdқW3dˬ<JDlJd(}Řź_pv+T-s CN@v2&F 0}}JHғͣk =3ޘį{d;On}xϒ]benݻ,22$bp95~67emFf(촿 fa/#3iVlHޯvR JO~fVQoш5ō{w,3ň*CAaVxUJO|miPװ|T+eY%ʂF^v_;SϚz-k*‚&@0sGAVv4iw׳ar c1YC>a_ `W)C`, D^3٬[+{NTYz?oOˆeb}xmށ7K".ZrIU#p"}ޓfK2~膌 _;rAsw/Lܞ%,Sl3^V6CQ,Kf}297Za kMҤpCfq\Z܏ w)FQe(6s{nkBև&V\:WIS&[Ҩ̠("ZqZ>}]lLef;;-1r44hcfa524 6BkHNk`籯glӱI ,^e' HGP:͓[Vۢa/s4K kgh5[ ٬RY"k;;Kز!#CWl\A[}_ZuYh02n񲦇T ޓ;+QF'WuFӮ6% aʹbuu ѥt5NMK 23-8k}n2FӇ&V\\>\uNܒ֛At8xS/ڗI,3VOo8OSNPʲKdv{1g((^~MJG}>gp^}{5=%lX mZztAsw[G /1m_ၕIUV7ddH>ӫjlU6V9Wی5=%JEvq캸W%/.e7PimuuaBɳӜJUԫJolՃ+5~rnOQkY)4f̦MLLD̦ 2a 9Xpw9#aZh,5Je;JesW%:?EvOif}48~oH * I^6Ŗ!zvL7uBF]?K`=SaY'ҙJV 59eaXzkHOzmT2Rlj CUf@1㕌wZHw[):4 2i195&0ZfD v2^oՇ߃kܵuOWl\yvcRǤCJ\T nhTq^'>5iwja+&CJP f@:9&R9D^lI^O!t(pT^CK2. ߫PAS$PB*`憘+s҉3^ݿgyc#oH{|2"7O7r ,qppb˗R?JRxL<}7jCӸ\PH2G"KUr2AI\uxSF}_~*[PǖPd%y|>/0L7x{iƀnf$P2i_?mޤQ?j=#79iݦY]/(Zx߁>yDSdZPu6sTGäŶ d : [@ftf&ۻnP1s/V9sԂabKz_s|1Z Q "ss8Ga|ߠgg9r ܄Zb*G888!zTz0%1ֱ5͜lF?oxxX}Qb}*#bfN6T#pߏ =<\fR4MQڪ}kxX\,S6ՃD#b)wy/˱?gvL\*"f RH#7M[6%%&P+ejΩ$9P_VVM ʜ}1lAtYI)]S a({ffCqﻓq߬lǭȀ+^\v/Eܻxи{z]F6;3= D UI'|x,6][x8OSZd IkH 4"iBWFZr=|^[cC9~Y%Z0zj6fm\QAI57{nf 0^Њ,F,,+p pX9;N{@,B(pX[w,@E/SB猤7&i~Lx˾߼Ҡ;0pdbl\1gm]YҿUԖYSdķnkF;Jyte4E·\Cj\BW"BV 8`&wݯ7^jcrR9\yViTZszr Z)Ju(Q4r3C*4._o_M%Z0%;S*R_V ׼TÆke`0n!5~;ɇ׎$z 8# ifv$Trx^z%XϼPYmQ+eW٩TEf~R)*< JUdrɼߞˎzڼoD\:Vsw`8oo{㒮e̮Zkx‚Z)S)*4P޵ sJ3n- E _;rAsw/Lܞ%z 8gKv9 qUzC w/ZM}qJWk4FY'qE|>= $]/s=gF/Г6_/QkW6Y+]OJV U[J_8R>AgG:kBaY6ZDm-`81X7/EZJLG3srif ?CG/]"2tFQu\S 313GKx|MNK'焵)0#fԏ/0 q,A8/ ߳ejͺiMi1[I6g*ĩTf29;o`a5Rɋu(O TۘLOʑgiL #S6cu)wHLMzp?ˇe|([qGzw _ –.IOqp[~3r7VnޫO ^;ES{I?J"ph5bÃF1ByѵHR̪ܿ}dyޘ7`,Ź\#]R#PIғnDnȂxV MkAf,R `!? \Mlcߴh':]}v"s- Tm3:H3]Jo7ۘ0G%?[G~RV D=ǯ9~M0Gх[쇃8(pGq88888#\Q^as=w-S5 y̧*֤SO 6IO|}j[LRkf@T^˾ӷh.W]x8+]xNmK~bjG;B1{0vȺs: F~~|6][x8񏈏 E֛&6Cdԏ&fe8n]F\ _wnb͟n%{@ cלaߢޮi~~+[v^s,SRTJK4h?xf=| HglK9w)]f.SQ?fȺ]VxU)h1ogɹD:~|_/X6g?ͮn,{dxVOF4L~׍Ǥ6gd༮6 {9Y7T+g~1Lbe*x#W Y|rkCxbejg/͛{cQ|0x~3.:{zw>YO5>p!lUCbwL(_/M/H>v8 |)~8}&>{Con ƒƨ{L3/.\5^'=m8i&^$Xv,@ۇx$ҡoC`"{gȀa&888co8?%TT܋Uu ΊōVZ+Uܻ="⪭jcz IDATj Z?q+  $|?|͇ܽ{s-5n >7xuS{[jRZtrfpnd^񵓺C٦gl *W&F=q? ց By->%JF&ZٻiW+dlyUOOƷ4cZu ,y\%Vv׍jQ[v5*.b6=ݴ}?['"sBٻػz@qK;`v"6@)wdu6Z6l|PBKv'W*6fkd/mWX?.2SIO^X.٩78.k&ZF*Nut\u^}54%}fUcιƂ "?>v|tWF#6k/j5fbVM=>dؼE[WSuJhGcoTB4_pOTF ,Ztz?@3h(:g3ɽ.ɽD)|RA5m#Ƌ"xQؼr>_ۮ ~@2 gR3}]W)LO+X;T'ǻj 9IQ;q-;)m;>=A]YV|]:RPv^_w5N+|J0v V{~<"s&lhR_KUl{Yw/k(8bƩmM6OR^^:nĂ+GW%uhȱ"O{|sA@nLö_@׹Ι ̤W =3 xϒW<{3vNA ð+G3^n>'F*nAY 7MyF.|s&|9R;]Fow_U³S^9h&Yۻ E^o^ևMl7݈$nƩi i NoUw=i4V)ZuaJ`۰XXsF?碕+d1*Y E3B8?9i.79v_]\M! )~nR"Ƶqt<Ԉ{.G/ϞEt;YlLػ؝}~G7Y1n4{{ V)rxiV\;%#EqKIJ8|s;%zhC/dp-| 餍W8޵Vƫ*t+=n2i.i ϼ{Ս䘷0CfoUE{nyKwyJC<(E7MȎ71Y{ZYiT]Іminq&7}V9E9B0qK72J[ims2bRYo@Rw$% )J ($$ED{ȷ/5r:f"m3rT})P$_&U, I/WE\*W~ڽx<'8p$3] w'viqj뜫6/ 6 ˓[fiѽnyq/Yv^@ёr/v?:΃^>{w ߻V?+ }ّE= q?:ryg5 _iw/[5nҡ7NmU}KԜbt6<'ECeouaٰag<\ \ _> mG6 A-Nu?uá_w3k#TeqG'Jg`˾Z=f*W耩5g{k'_-=oW(2Z6T\Ӹ;H >>שs$U*L5oih/Gf3 VHķNov}mwCkwpJdή7_0y| իG6^:nؼgOZwn"]zGPah&q1 c܇G h?{ndo _4Ъ[`͢ 9вq;?P**yiDljqw[ :3 an8T#t|gнIO"[b)]'gn*Qϯ E66@)p=FȻ\i 0A(Ro,w\Tkglyt*WTH]9z{WF-ѻ,H= [VNǯ`9 .N>reҬԂfOhӼ!FS€<}K3SD6 NY2ly)>+iĝsQ~|Ÿmư㫥5nكH/sn~/]V* >3R($zoEFM;l>9ըeWqOg4գt]k5j5Rq*A urPu0ZF %V63Ž:;T&7UqΙ xOd]JE.4+e]Kea1B31/޿rDbP k#:^rI>7hb+=kWD̽PDgI`+F;GLQXiRΧcj57NX0#s#"33_Y YN)o^ڛXvdpqQH`!d.NbBKk/‚$ɇ&0 a۲k %KJe(8uABKkg)Yu^>"&x4w5k44cj4V)ZuaJ5!)_Q2狘RR ݑII/ n)]M85;-!-m߷>9m! Ħ/_ʕ?rzwlŽ +AWtʛ' ,G~G7Y1n4{{-/z[JRw۹(Òm(bN1 Ĝkn5ZtY-?ެQ wyJC<(E7MȽb&; ){}C3۾~7{;m_ؑCfoUE{nyK ζ~'Z ~? p|A0l2B1 Aaa1odd?9ḓ7ʪrʲ׎dή'3!mܪ/Xz?{t{]/}E'0kz}s?"`MVVEJJNiT&F8;_<էÃ')eYҌMەw͂G:?߫[svrӹ_W($XXٵ0_uE*-HQ'|p^>8؛=w~bFt: Ø|.UQXXzW%vV*&Juޢ0q}]m:BL;<>q*k{!f$%횾߮)yVO\*1Ul+w]*lPBUEBUEx OcB?BU?BUƿ d0uٰZsC9 X/݅HWpo~O_fvOOx^&3ivb՗ um*ʔD2o|Gƿ7tH4t/>O)j衤"n-c:\-slǼ,Dޥ2q?wHziVKþYsK/a3C$%P;_>nj7|ԢzAӷb\/Od9Ss\[7qcTֹ,دV%sv=nDQ}Yx̭Â,㋦NJ+ˎs!߭BWp{}5L|˶.˺1;_iP=?)^K_ 'z_?HSzѕc\;Yвa۞8Z6nJ )M;iޡU@symt@+w0uKMGwρ6<#d黍ZVOR`Oc#^V.BKY;jPdcX r%[IF/9l4+ZpOP*?yG^Ɯ`P*<>YVM{ u_;Ad뤛ZX)be^8n;,Ʒ#MkT4i`*p@d) E|*##eMu_]k7џ\h8I?\ ,: zd}Ȱy;hT]hiz-}^K_;}RqV^wuif\kctxz) }+4jZNv*'0Z'һוd$qOg4գ_|Z9^=w3;`-K+Sp{m3Iv'`gu `oTeUe⟭{ʛ'&Vj8Z =A[9HR^֬!Qɖ]c'sݻ9oLrZH/֥Vw \O;*$=KC6^h09QEj IF|= ̤W;3C5r>%Vqzǂ?I1*Q)?sfn- Zز2kDN(4i hHIMT*Srb +;[&|pzwSOyjqoG675ZQFڿt Obae wh$=i{cJ)?VGFeVq+NlV<O*x<ϠȰ M\Q - Zز2&JP9P Ƴc.EH+No韧.˳ӸQdbkYDfk8Pu=z-' Dv.5ŭ~A~v┲,iFkJ&91s,BXU<;g'>mu?yvZcTzPhMVS?׍+LJY$&jgww{}-BU*ZRj>b3<؏6sePIhZKQ0̈O*Q\=BEX"B$P6"kFbyQ+Xžj8A-9&nARq9j̒C'H+H:/'['(xY91g[k[\?.gI)2в 냸5K_C?B ( "lg!/Vտ)#3}XQP( SHJTL5:3ۯY a'<BEaat=Mw9JjG+U"r|Ș)-7tHwb?ʉB%_ Jv]^wC/Xjc muMjZ*T4HqhUr)`[g>ʒɣFR.ZC0FC5ɗ4z_-1UICTEQ*~v%eQcyA>K~Cv>t\7T Ms4V3UКY>E"UamMQЪo[L5Χ!* ʐJ^╉>$Krfqtw/SŽZ-mU (x!O@($Jjʃ LS$@Sk'BܘuHeV'x!>gme0moam;[yZ%pY&z-;Dj*P6\tԼTLL*p!SSh<"I]i7 lFDoO:ɭಢ+I;JQcT1PpO"i΃k}TJeLzߎZߦP1Qe]G B4";7/sp-۶lpp򙲮BPA ]L#TL?iJU&^ʺ!SL?]G!PeRnT"BB>!T*v-'6ˆ\,y-K>5i]|Z,N|^e\B@o. (Jo& {m+ߩPRƕCq,=nf>iV.wTZj E"88uD[zd2dqi-E0#{@ҫ>iZ"/⺛6 IDAT%>?AD2HdhMMUe[ YCԲiSe z,I0!PJ$xcOCQ$эW8*[<% ~֩]]aa"Ӎ-K .q'9! (?3=PԇVտ)RnmP<* t%0Lf:3ۯY a''9D !T\=+niZ zA+U"rȘ)wHAd Bv%_ Jv]^woBM[%V0kaihZтŞvT4h }*wY/2 ygr7ST bo'9zG@0FC5ɗ4z_1U{R*|WT4]j |~!>ɍ׭MݯzgGİnz}V_@N_D!>v,b٦CLR֎=s7n%GQlKſ$&BE)~r4V37+Y`%RA%Rnf| F0q};4lѠڤ5*jY A@n改u*!!! +$su#_,ŪYoĥYho^zmY h琴V-s7">ɑz:n % >q:{!=7'k<Ë1 s#:ZپL =M.Wug{]\nNuF݉ڭY{l-gbP>r^\O#Ăkf߹|a|ly7 7#S.8swW횮Fut jF"B@%QTV4oLZyx.$Z]ZjsD0k75.Oq4tyܹU_vibi#E_wR6⯵#Lٺu^ԝxg;?rAmo=IwqM`:sk˘2]\m};4dOv{Oӫ9Z->aՉi> YWbj |Onw'ibWKem5i] go2yfǂ?m@ۨ;ibƚFܳLNHLNco hķy_ 0o2@QYE}R>DrC%NI$Ϥ$GڿDǼN.*&" 7N5].{SO7u;|jf5W#eբ^U o8-|Nv$ ] ֭MhÝ? (l ܋KQk|.qaq?*Z.ϥHRך.`M "["0QZґN}VtTt`ⴛ?}}{ះ8>ҳg;?hpƳ霞%(dҍ#t]dIYț>4`.[wy 0?['[LbŮ5\lz ڌ"y E[5k]ý]+#o ,HsDo]SV,cփvL6MW5UEy]z5(&%.}=s1:4|` eˆn_-9%mĥKO[wӧ3lʧ=~'b_ԝH֦+Ϻd?xگCCQq2]O';nx*-bz/viͷo>Iam-= 8>E=Ѷ"(Dv.f>_dR\v|n_>St^ٹtĝ|i6|u}mw{ FgeKs2Q<޿țGvD"W]?qzpo.k[: ܭl⍑7fߩT D^|6 Pњs6hCɃw.ۿkqވ+,Gnй?_, oڮu 6&s)FF[IvzK)e]%{y<|#SY ʺFU$1'#')eYҌMەwPI9Ѫovxs 6ܾhۤ(.!P0o-Y1]?ZBIi-B\q7=TV5A<0!TN9 +PycB*?BaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!TaC!Too ?B[6Ã$En6N55:uXC!J.ZT?a8zob;S.˺!PqV}\J;^3OH&HeYGBX?.ґ$ < kB|Vs >#)@Hd+B!T, ?d| Hc@*!*<}'H y<2yV!*‚O.LxIJ!Pd2$REdR|B;;$Irކײu_6B(.gIҬOgHrU;9;;;''>=x@ $)rfKD4@ ,HJ(E KJ HC&S BăK7\ZT4Tѹ*RM+U\J@H%lI$ $T.ޱu֥!j>P| Jh!;iӒ !)RL Sֶ<ʦ* -H[BUG!>ڙ''dmim8]L ر RIk; g%Yf@B"IV;X@)uZH1D5m=IENDB`packagesearch-2.7.11build1/homepage/img/screenshot_kde.png0000644000000000000000000007720513507430555020443 0ustar PNG  IHDR' pHYs a&ZtIME #$ IDATxyeGuqYJ҆@F `mih2o̴{LO{Yc>.67F02`$Z(T[VVfU[#2oE>Oq=qDqn,^zi@zi1N;v ! B]GT̙3abIBZ]qJ)?@CQ !sq}e}fZ,UxNt(ӡ=Cח76+FOiXr+&LJ'džL4z~n  kٌ99>Rl6c..:26RC,!qSwĒ;wi10ɱdz2V֊KkחףK5 u%c/xz3+7K"Jwyue> cX2.\ N@8vhf$WϜ얡ݷOWta"Kd zm셀ёBRs6x&ٛ rKka'X!),,._ys +dFԓy֕zr ȡg^Tk'#9B2u\!1!|NpNGWk?|w4}e[kg\ѱBNu]3e\p.8eUjNReL:ҩg杛^KpQuȄE8'^}ZW(u-/=]^\_-iR2H>k\¸pDYV-kLvlmB!%V66zڂZi!1nhZ48U\#Øp(!&.y晋^,27H UF^|AXg7_n$A-.yJIS,ٹ]Sj%K V6GbgL#c!F%ܩrJTdܕ3S7?Ƿ%+y%Y:e A !YqRE״|6C4Rs2Va!DTi頄qQaȵ2̒*t^#\$RJ?WǾ2_}oy5!ĕ$GF$%Ұ4ɶ^Tkc#l&lja 7]chE)4MN+QJ Å]]^+:0{ !r3SҧƆ!/,f_/|O.]XZcʑ{ Cp*CnZvrŕҞgyrlH2mZmӻ_2|ydY$>'{g!oו:q]!gcܣ+yҷd⾷ԗ/.}cfjϚBto=yOozmKxai})♳+.PZ٨6MsǪij͎kƹxkSdz+g6*ԨKbq!}{~u޹A)O@20YԌRӟ<"KD-T7 K?yo[|R<'rlB^ֲYOllr!35FF'8c3.+&jv <췟$;ZijQ:!? yx@T,Uj63 q~nnzZL Y^\[ߨVL6Hv ]uEdqiY}͛ ?9X;e'uzO}o#,8s !y'b ~Ǿ#}]{{}q"1+af^r8P<#Ս2%r΁pN AژK JF<}=e҉r-nŌi|x앻o9@K b蚦irivFTfV'N(R3"J'ʅ00hO\X8R箭B7e(3 s8%B'k+dǘoT\Xa0sV/}?Ђ?~櫪C|_UVsZ-N8-ݲ>xxsk)ɭ_?¸:v?JHRr!,zLXc3{&'L L٬eA֋e!Z]/o,e::;qhl + _Ώ ]LqXv.B4J5jQ7^L*3Mȝ\lE3ral"/Ƈ~N@k^f?7o= @(UjrJ NF|4Jd3S!HRBx~NqhVgpB*՝QޕueML=/?4"<}37s?M 'TXBr#Tq h7}21-P~ʼnnگiˏ/W6,t.>A{$F9-Da.f\BToٿR,90l._ kfka!5ηK_$~'@#@1γ$o1 mo| $<9>+kr}o6-+f_y iؼ7xw?xcf6+չ\VNn`. ]#SJ;{/ο8:>/ !DhBew !o>;ퟙ !ὄ!c h q{R  cS|A>'`Iu zS3I ٳk AbyeysjŲf2٬AF/KVWZ2v9+],?39s&pl40LQYZ0@Jn︷C1毭?roR @c h %h znpv-;-dnndawͤ$ 2s\m냺k[F%|A)%-v5r 0zɍI.Ucfq˧g|Z*D,&-.͖e\`Zz7[b_.`qQBr G{foV&df$aӽ=7;JbJ71mrεPBdʙh?"asʙ{%@0bV8܀j.ou)(vЭ8^A>îzvuܳ7E$-yvSw=#Sj8*TyjoINH=%$d`BkNW.SG!2}+ T *~STSG\LK 07ѩae)O_IBUմ {FUK%!h\_eg=ީFf}8#2JTg"ay82$q0b[2ʍyf}>F]/ }ʵ r7a dqEdzڅ]ef?~k92ae\aUn]chK|a;y/F19ziY]Ʀ:?ᏪNpqI06 rocXK ;KR^%ؿ|)h@K}<~%a\.*6K`"$hGщ+sYBLߙ_ݵZ^_HFgU~g"QuIk&R( {V4~w +0P6V <44P18X~wnJ ;UF|`NW*)oL-x T'L!@9Wc ;(M^:`<.BI+l:94G 벹q4^Rۏt| h%;KZ)&aM)Q ;MͪWM)"bq(t Y/ [}oUJךLv8VԨuޒu) 2;Kdwк*y~So9YoKdv}6vs}Oo9[z9.KE@#A4MoOO|绷y=-ވ%sy'\%@`, *o^ =ژgzk!]~HJ,nN?t9?SԩZ dee>Th,`@ZK@ZK@ZK%tOL;~]Zٯמ{GKB94(z[q[Jq dN|c'?y}o}᱉:ΜC}G'%Bzgowڝ$Oca]&ob h bXYY?w+ Z-Yy/A|}UX@RN{]rysغB₮o>d?uکOQGBH b Iarj*#B2 Rr9BH.G]A?o%t])mBvڡ9gJjV<}BGcbf;-(IҟV;!0 Ƙm;FhIxBak$h(2%6"6; !<ؐ$zx~竒h?M^z+QtUku &ޛD|+-R~ˁ1#VX=ʞ)=Tv2g/u_>*BS2푻OF7(w R}]{M;_&tBk=aFOEԽ^Q&Gbo@'B C9&}Jaal?B\zQUݪ +^BT{ G],ٚ ;e駞O=QdTO= z'KON퐰au}zy6PVg;L}yB.qӍ9ơX s a~؂"鉭Z] iպ: b I,ӝrg:3(BJ Tg駤ڡ t,,L&a*iDY jCS;b=@"hi;#EޯTSv584&%'O-Рy2Ղl6뺮r-T^4e1Uin' }-%N=:?,W^f3a9Ӵ C;i~jwUuE` r9ιio= K&鑣+4qFz<1MBX@, )Cm;i2cjbIRdEܝO^@~j0oUUE.c4 zb=jׯ_u}dd\.;ȣi~m;zuyxٮ%){VVޣ Y&!+ZJL%R_,Q7EXwB6܇ =4y}hU4 C@S_,qۣ]X0`&o#?If}n``,c,uZ}s3h =?b !3\N; ~b s4y.nx[GQ0}t/ZUz%+rp L(hy`duGO@لutZ!B($Q < @=Nː .]_fW [=qD%ԯ/Sh \r*o¢KZH"ov*qIW<>@mS{H'6l-}jpѬ6L]>t?zIgg*<]R'>^ $tk;DB.nl$%>P0h4]vnl\?@D)+"R^4zIX`y`$c{@ e즣Ժ*t9P9hyц gՅAM(QFI,x^j&_lկ$_Zhc aW@, u1a: dQ>''1x*B'PcOӀQ{zZS}&%; a3%@єyA0i,Y:1zr #=Qum0i,Y^Z:l}a:KKL&Ӷdwg .5 %i,YY]%B}0s}ޟC+{x&tTK%dy+rGyriC !IͩJ[m.'T=DXr}iI&eb;MSKK7'$ʺumN +{TTo*X74VkHI=kknZBn  jx1+ GIf̛XjWq$t\R,T:Q#nt0#sͪ^5̂쇄>$\r] 9yNz|Gg%%%8&(K:%?u`;vbr@7pcvt;>̷qÝk$D 94V*q$aiѣn}Ft?Kn,QHԵBfh!,Sr҄:nX@T*v2>>.%nqbqT '|MStUt\ڠ ڀakeҤ:M'W\)JjxI5J5BZvfv#rӛ'!z=?«Wa$k,يOh3R9'&SG,)B6K%4uݨj]7 fsaX"!(Ph?I\^Fb7EXCcEP~ƒO|;ޛDS@_6Uǎu ,<ʞ[\JTl};~B?@Ic??933eS;@ϣX3y"MPEjpBx㽊c/]5Ecsa$7Fܬ'"rO.NH:bI&?AaGcuw- Vёm@Y B|>SUY$Wað~h)%\M4t{<{`@!Һ'Mr]ݿWBLM/IIX0Pjqnꝉ K|ׯ b >'~ԩVV#4]3뺆̓ lX} ?|tڋ`qڟ<0ڪ'X\VoĒ&SA8B!YTcN|~i醦BaH ֭P_ʗ^ԣh^ᓟz,%i)KE6nYmc4!Zi1GF;C`&ڪW[C,IKqcͮt]gj|` G3,Sy14MuMZ.WL4tRTq2h QU@KҲcjM(BpNuJuFu}}qaj0Fnü\.s|Nt}c:>>a]C<ۋ^h.16KlֱjfqtB 1 ò,!8Z0ZZuֆ2l}єB5D]t)sɎjuQK^D]G.1FiͶu1A !93!s!Rʹ`S5˲Йmw^A#`%WJzH~RdGќG|"|e. $#\0 1 C(D#3TWՌj13y^q!83cJE(?UG~6QYm]FZhkUH4iXҔ-D[@g<4VJ18c&cZa9):)By v+R8~&H)q[!sft88v x~}c2,;M>.!Ⱥ{amsD^r=J[ԵuVW)H=l;g.s0Gٰq`;P8_grzL0sh"n;w! w!,Οs]i{nJ"BO%ڔ0.0zeED}ڧn_G"*yLl~*z9wl9!d ϻ:s>VU*36#sg)JU69:wf^4t1iUYډ(..Xo{ ^"7&Lv44@Bȁ ޓ5{']=)m !,nOyͱ$[%{f_~2fU!P>f).WujzڄM6K`E>_V]4=zfKF%V=!B~XP?x}O 0O#w;t+%C V3VvJ$sg:w/e:yiYkjg%LS{aĕ߂r>٧>{ӵQBb cJ7ܙs&HunI3B) C4EX|ӟ5֝0=]y+~^[~oPA.'-WTk53aFCׅoBJ g~G9t|޲Vz hĒ&N|sFB}N8166:>>fV]%U箻Z__[^^t>)PJ C## Bh%An]/ # YiYݼ/0 4 J.+^+@ZKhb H b i%҂X -%\ H b HKݱdbb6ϥPJ7;AoivkhWX"+_lKg[Ͳ;ml @o\t| x!3={ͨ I)#OXi6=G[Eץ]?V0IyG4o_zoo[mEZ}:%Zg/O^" RWh)ڂ=B_?\.5 #0cO~ K9HSJg.̦js}BkWͱ-J f-ߊ7\:H#s\%ai4MٰP9l%e/ҾOGhJK%0fDw3Q)++w-VAvNpY\ '$ЀZ7mnXd=蕀;ˠw@oOpsw$}gss{hkhU1ϻn?r! i !'ݙj)k~OY-GXh-VJn3ٺZW-t'$$BSAo?Q>.wY݇(BË+ѽ@RBFB @OԶ«P?HoYߣK ;Q$tɠշ{$/<0zm ZsR?bIII.o#Ь1Ik7=q?;N(xck 4^lyw3]cgrR,VA } ϬN\+nwc_V%=enc; J,H): ܐ_P#D(wg';h0@ KN|~YNzleefq :Nzu~З`0@ A b -$z Z@XҔ~&@H3.-o"fd\}}VWݐ\O^ih%m•-v\M]aYT}]H'?ݳ 鹪xͥZs V%.ޟzyځz!;w7(?7h:m!G|DQ[6'.(WIIbVqwx*U#v>>lQZQxMzE؉͛\.=r\.R{1N%iՒi.jГK @[%og IY0fۮَRIVss;zG&ILmY_VJXBN@Ӕ&Ygᚂ'JE҆cm%6>{.̈́bjv@Oij4ҩ@+687 wpRbn\M⛼ÊP&[݋@iC?^65|9k@?DJb- J7r+%F$9.O*P*S0p h60K]"Z}Y<,jK0#lMع 6 O#^Foψ[Pc[ %4mvIr{}a F"iЄ4ZclDKW *"`^ t 0Nq HOO\ Bz =%KX@  Koe *B?s] %`@{wIxN{mXB}vx.:nPf |gt%yI \wcNk-Gݡo1Gj6s Z} @AowFU\IH9%_S1hAo ܃++L3,hў\"n1ӊnf; 4$ˎک,0lVD)4nHLs Z}~xJ]γHuU4~W ~@sX@?p:AN{Zq+`=%t)=b ]J%G=Ib ]JK%m?Vo&vA,KIWңu=Bϧ?kcY/T43BiZ b ]JOvoʱ'*HʁzZk"aO#!!%.% &o0"*P=4蝌]Eo b ]:8O/ IDAT+` ۨ+|WiJIo- D7A,q7\[{JҊwϛ$잒@z MXwaa{"Jin/QQ0.Ġ`zh^NK1ͤu9xj; ^?b Q qH b H b H b H b $%N=R?.I{_YozqH b HKzN?.?N?6N|.3` @ZK@ZK@ZK@Zbz2u](mC 1VٌNM#*DιFnȩnV*j0Ƙ6{8L M74 Cf0!:4X™S.!l6;B-uݲ,J@?۶ōbq1fRTL wBcIqcͮt]gj|` G3,RB།N6&_[]-+e^V*e'4ls9XZ4ʹSR$Q I( cxuιiol0B'L3; JR6kJ,ۮ1'B0L&#ٶ^L˪V*+ %^'O3pNƶ.ezhtBܴgw5]RQ.9/mczXRTeB ۱uГݥ#]ZxI^>]Ud/4,ya3lEt[zXY0ǡ4&J@h ϻfe:})&qC;ϐлƒrB"b$D?d={s~CտϩRXh햔%O1J)!%>Э> ӕ8ۏtByX}x\ KQ݂"t.7NX'm(d1!sbB=U!2ejrFNPJ^븑X44)"Ascv 4 o YcP !rοN6PM !B C7Mc}}VV;]A.^L)e3e28c J+neZˢvQ o{[>C.\qB>h]uC5uRl`ahHq.⣟̽WlАW7~#/tѡT>D7%u널R™xG?~s>,@Zn>?O(nS/7ĉccciu)HKTի^u]wݵ8 ;RB)5 =OLi@(Oޱ<\T'p΅0rCNuRT+e1Ɯ: :gsgF !]3 IT,yk+_2|S6iܸ)KE6-wYXlsy׻k4l.7 Ƙi0BHR1M+2L3*ce5M.=XDhO)$:b 6e s 9++2QXk5]cZ5_(XK={۷NXYY1n0Mt]2 ]T+jmhtܲL2*8OSnBS %hQqjvN4z>cժ5MLڳg?NÚaB/.LV?( cxuιiol0B'L3|{J!q&?5F9M^l6vVLql6IrQ]&aYvZffZ:kCCCaDfўRHXrJss@ؗlNa&|Gn纾>FiͶu-z-x>"8B) 85],\v38 VrT/PS%uЮ)RogB5Q`y$'OvC{НWJ1wGw O,ȭ;45#j5Θ܂8[B8c01VTt@O[#uxAF 6;Jw(wZP,d1q3ժ WcGgqRTQ?f8-`qƘ0677 F&mS 8{UI&? Kn:PrKI{ 9hzzK5RW#\_*W !n]Namh(6e!{ ێAtNa$t)~scs9g CQ*mF#q gP6ti}A3I7(ws[L~omg1֋<_[QK WFd| aT\p! ;\:%utl0!Hb6LTu6Ve߅p!RrJOW|z]zÿ61{g ΫsRauy&f݌:M̺[H"ALc02-ϗEZK˿r*vnu5UvpplRV?[؎%;(Wb@vX-5kU]v|_XADE zvjSc/xN%M̆9CPJLU'0oĸ4 SSWmsD^rZdgJ{[aZ9W?ӇådqΘF)t-ssKA/$(?t>GR4k*gBϹf`sSuYpu9P{`&gK)ay]atJ6 ?ZkZRQ?f$CJ#dkPF,4?7XoXssruzM=ǮΝ«sgv-D{MHP].0PyF:wf.$zne  mԋI#Զm!0B@,4kх+/֕%&=6B̾U@{^ ~ku5lr`^b$fݬ^.2 IIe{|rEK#m;3S9x}n%\8CKMl}MaBvV8YX R#Dncb zġչ{f~M_;) 2oC- Աy6!f k4)F|w#$K{n@ X{uV]f`#_Pٌ9ꧪsSGܟܙ3$A, \ɸthnzz CxxGv rGK4Ə3A= -.E+Av3I\5،a ߝt#H"xP)׏D&`ذ5Ca6Bxɛ#\PzcmHZta;.39l +e~ $b%z1grBҵn.5CIJt-ZQJs6bT_D:Z0G '/~R&<TRRĒAz/!?XAZ'V&gep;tčRV5Mu~^^} $.BDuMbw}zZ⇊7\;rVka,AA(ɟs\mi@}\YAk{aYYm{dh5^w]sUiaPJ->R=m|,$7Tx; P(lK#Ce9ޛvǏw70rFτ)BC7 cX}ow'=X2w?|;c`qp; G\tN䲙 %w=+++ãw4!ۚA)[E)vQ- P,u1}{&/-{o|.8o1]t(Ȏt-n9 3av9V+ib?sku-" P,wk%u߫oy-gg!,~ bDq`Rh 1/F$DʼnQx #L6"# lYqH #J|.9]=S[S]]}_ES誇?'?_|}-Zx?2{a(:clcc㻯gnZ=r[\\[wI3"0ypd2AQџhNJJkPYa%#QR{m9O?I[\l6Ο?55V~hvtG+я 3%_(/%]J@ƷfŘ'q뿆lFk"e\[\ OkbVu!EKDC*PcIvCmFJ()G^tuskE<륕 q0HE}J^=<3Ě3()0͑Zqn;|]&:̈́pR ?׫~s]M8W/B^}???XZZHqeeem8WcyNM'X*wBlmm0y{]g0}g3q;UWr^⥋O>[.$I0 _3KcsssB텅$IQ=t /ɧ~ i ]o41Ƙ 0&BχaX_} Y)=_:Ndɶ`zIFqpA1IL9&H)e)e$^"F ¹?/IK ȗ8$2%F8 -zJ$sG{K!$I%q}kߤ:VD%KizzMׅcʺsê \"L/C^?߻RT[o|;K̤otqS궎Q87}-]8X}zrxc˻8l^H>u0D:Hu*szxy!լdnXFq Սf}wὯN#T[&MTʄT* ÓI)n־^;O:4}87^YJe'ߏRx٥ X;7T֥s֥s ŕKtCX)(HCmQӰM;y#<YW2f%NbtJrWZq๯s:}3;cc(ut-궵ƪmP^Kt=YXؓv$BFC]`8dsą};ԻNes9t/<t$1Ӫ9J<+^Y. y2RK'"w4H(RCV7 MS,e"=WRy55ѝѭБn-Y]a븼jb%\ʳj;$wwڛq2~RҽQ\l%uvV%r5]ume҃׾7vooY pЙ)T :Xdƒ_mgҖ'CIRhq{͕}"}AB$JyZ̲v懇yU8ՓՐٚ%\mJ.WYϪoZwޯ~YCwm)(Í{]y}yv8617Ɨ ^ zQJ.GC8K\i ќ{cs_JJݨΚM;:V+KÉu>"[ ]]\˦}ϳHg[f-E)tZi$uO7WZA&mb-0؝XB9]g^XN ƈz]rXˮCܜo:KkcAl7DQo"< ]+e܎ڎP :pZF A@Ka:s&~?IvCsss]*M F C,\Qbֽ~'ӆZsSsAV545nG\ @eaaAE;kvdd,Ͳ(v|;:_$ $q b T--FqEI"$ K1)d~qӵzI{/ @eyy9I(;,ۣqVnl]?F}P˄^ڑ$ c,0 ӳR啕x4"jC,JĤ qkp'Rѡ\Lʱt^'MpLU#}'B_9e+;}Ւ c#nK@3 f_G)bG">g G58<ei\P7kԻ6dI1<³kgvؿ$%k^u*/`5j8Y럽tF^Ӓ'lp ?;4WtVx,1 dL" WH t1I)á u*Mg1^YKBYX3ƘHcR&1!b%y9Toy(Wϐg8pS5kDM< .vq4(j-'_ډ}ny9иD0$fB۬a6N!FX桮Iuo=z<5PMt5@2b, 5x=7^w|%VJ\龛n,{kd]:ovI sljad m-i^hQWi7]6Y}c$.*3̳b湭gU1akGV+c^XF5Xər%kbԫPp6YP>%BƿZY`Mt;bthSy XBӭՋ^=*5Ž Xby)Ja+Y{AY#Api:AVFb+Um +a_Cӄ _Œ^Z"-^Utr{i5WH嬗S|5u^:*PHӣҖ^kt Qw^՝2N|1Zvgȶ+&3vX% ٝ7Tzcts;e%U&moT^n2~GQB ΃zA*T]rNVU ˽g]&:\;c8gae/,%,YEw.tMiSA:gHy%bQK5HRJq|/^y lafDq@- 1ޚ}뻆҉vkid5[?H{A, dݳv+X tV:|VhK/ 8^!nAű^cy'޽4z\0Ƥd1!eA9reaa6jCge3=C7[?V_xy *[zqncNǞx"v(b%T2_2)JԌ9f%*k)|0`v_|h6΂v @%P ªKT%v "o-z&O-LMEDM-_kTZCuJv KBPx u/۷=?<ƲDܶQ]>IyXvaԄ']&=BpUIrRW^ m卼'nP4821.0^@0;la X5UUNa-*e6[SB[ړF^]@> DtxVuqiȋO Kޱ03A5.`Q3n%1Y#?xOvY-G8I)ϟ=;sLP/UZj]*$EU]/kM%T%[w_!3_ 3Z(У'!J8*y>Ӻ)SO^"%,yV M1PUA,PUA,P@W ~:b `@LjUTB4B͚^(LOt{W(Go:( Aݝ+;.V Wk^L#ݪ⃗Q b UQ{B1K^Y*f-[m9v@KO*TT75C-FAK"y{խSh7}@ A|Vכ*, `R@,*`5]Ot/qxUB#D(F |AUE;2,gC鉅^ybJmOl:ݖl:E3X@ dk%J#p~0r=˥Ҡ WFKQP b hF9ӄB/E$I8cRKlBU>Oj+]mȐ=qrꏅWɹ~qiqa~>y1d/*Dn㶅 u:V)rQP@vɜM,W b -^gJ*0 hq jJBhb+bן>.R}(kbάݥ\,3e<Kv"nUx\{BY*%X@%C,P~'Nux篫z4\cvaڸbې#/7KN8'EDžZ^onn3W-_GsצoG?xwxm}IW판l4,$(A:$KKJq^?m<g+O̵ (xA@5=_AzQYlޢy67H:B =pFBn\:?s~g$Z@$ bI~n~>w^x$!2xҫoXl&sQ7됔+o%TOCz8'sz+!9okR=Oeo-F.qR 58 d(,;^m΋/<WWY qX]<ةwhdd2SxEd’['e,W+FL&zZ>F{8Ke{ܜNO2վeq-y,sd.U(VgQbU@%ʑin+M6Dq| ƥ8"%L&Rιsh4I#$~I!B2boCJ% KbhX"׿r4l. %{my5gqf)|8 ;]'KUtͨ }+cD-$0O㌇<`i83[<~X<^"ti4Bc,;B(13)ŞZ ߄O΃%_ JZ5ޔ2+LR&s&%drI!dR2@JFal=%vD]:R%RzۨW&<_ -XWcx;X\F:#H;y/[RPKg̦ǣQ@厣skoQ$^?{i^ݴpMCX>DT_ىgB߶H9(V| U"Pï>Xs[)%QEh_X{}Ѝ k+ʹqǭ Q7ylbtPpnomeuelI&"'2Y1lUG٭Pe,Tn2ZЯ0)tK4<0G) bInn…ww<'|/{as QtKڙ !T%Ϝ9Ӱ??dmH'c)ky*$ӱV^)twvl(*F)'y[2(WJg+ҲC7<2]O0bSWWlsK%y?u&/j#+≛ƒ6Sm`\H͒8Gi=d5%B^'4Vb 4Rl0%*%>.uuc% F@UKTJ`]eΝ{+gJjA[[C~@_2t1V%FMܱ׿`X?m '^ڿ$.HɊU"E@wr20R݁|xc4ST:vmVOyK_ D҆/)h=@`n,)lQb}ԩS˚-\hb/}?tը+k; /G><&G:]%!k;//? +*%X*%X*%X*%X*e{klFӁ:}\" hNOwۈvLWS` `8p8$ v*,86+3חe@Vn O,J# @bԷE$%nqupKGHnJDMRZt}*W6ݪ@pV8^Xy25;S'J+k; :H^ y.2]H/iD@:.) IKߗP(/o3N~&.i 0RVo1v 쌗,c Debian Package Search Home Page

Title: Debian Package Search


Debian Package Search is a GUI for searching packages and showing package information.
It is aimed to help you search for the packages you need. It should make the task of searching a pleasant experience. Additionally it offers a convenient way to display the information available for a package. Originally I designed it to find a single package where you have a clear imagination of what you want — and it is really good for this ;-). But it can also be used to simply browse the packages available. Perhaps there is something in the database you simply must have.

No software patents in europe

Debian Package Search provides a single interface for different types of search including a full text search (apt-cache search) and searching by categories (debtags search). Debtags is a new approach for categorizing the Debian packages developed by Enrico Zini (see http://debtags.alioth.debian.org/ for more information). Once you have found an interesting package you can install from within the user interface.

For some more information consider taking a look at the program's help page.
Please tell me if you like or dislike the application by voting with either good or bad (this is on www.kde-apps.org).
Thanks!

Installation

Debian Package Search was accepted into the official Debian unstable, testing and stable release. The easiest way to install the package is simply using apt-get install packagesearch.

If you like to do things manually, download the .deb file from the sourceforge download area and install it via dpkg -i packagesearch_filename.deb or your favourite package manager.

If you want to compile the program from source, download the sources and follow the instructions in the INSTALL file.

Screenshots

Screenshot 2.0.2

Screenshot IceWM

Note: As the name suggests, this program is useful for Debian (or Debian like) distributions only.

If you have further questions do not hesitate to contact me at bensmail@gmx.net

My GPG public key can be downloaded at http://mesing.de/benjamin/public_key.txt
SourceForge.net Logo Valid CSS! Valid HTML 4.01!
packagesearch-2.7.11build1/homepage/stylesheets/0000755000000000000000000000000013507430555016522 5ustar packagesearch-2.7.11build1/homepage/stylesheets/mesing.css0000644000000000000000000000155013507430555020517 0ustar .footer { margin-top:15px; padding-left:6px; padding-right:6px; background-color:#0B1149; color:white; border-style:ridge; border-color:#8BBFFF; border-width:3px; } .document .footer { /* compensate the 8px padding */ margin-left:-8px; } .footer .date { font-size:smaller; text-align:right;} h1 { padding-left:6px; padding-right:6px; color:white; border-style:ridge; background-color:#0B1149; border-color:#8BBFFF; border-width:4px; } h2 { padding-left:6px; padding-right:6px; border-style:ridge; border-color:#0B1149; background-color:#8BBFFF; border-width:3px; } .document h2 { /* compensate the 8px padding */ margin-left:-8px; } .document { padding-left:8px } .footer a:visited { font-weight:bold; color:#D814FF } .footer a:link { font-weight:bold; color:#00BFFF } .footer a:hover { font-weight:bold; color:#00D5FF } packagesearch-2.7.11build1/icons/0000755000000000000000000000000013507430555013474 5ustar packagesearch-2.7.11build1/icons/back.png0000644000000000000000000000136513507430555015107 0ustar PNG  IHDR ޜbKGD pHYs  IDATxu44444444/%c,IENDB`packagesearch-2.7.11build1/icons/clear.png0000644000000000000000000000065113507430555015272 0ustar PNG  IHDRabKGD pHYs  tIMEI+tEXtCommentCreated with The GIMPd%n IDAT8ՓjP#QPH`S1pT>C^G|ET ]@~ h𤊸4-~0\+{p 4BeYs)MdB:af d]$v˦iHq Zlu]fYH,8}~?yCU%O>ضͪHeY( H2't]mya\Ojf⧋T* IENDB`packagesearch-2.7.11build1/icons/clear.xcf0000644000000000000000000000402613507430555015266 0ustar gimp xcf fileBB/ gimp-commentCreated with The GIMP" Unnamed#3@8A) !@8A) !A@A@A@ Unnamed#2  @Y @@Y @AA)8AA)8AA)8@d-A+!d@d-A+!d@d-A+!d@zo@M@zo@M@zo@M Unnamed#1@Szo@@Szo@A A6A A6A A6?Szo??Szo??Szo?UnnamedA @EA @EAk!d@zAk!d@zAk!d@zAAM7AAM7AAM7S gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) #Ex New Layer      C_ DEEC_ DEEC_ DEEC )'G9 "E Background     ),, $     #Selection Mask packagesearch-2.7.11build1/icons/forward.png0000644000000000000000000000136513507430555015653 0ustar PNG  IHDR ޜbKGD pHYs  IDATxu44444444/a%@i#IENDB`packagesearch-2.7.11build1/icons/forward.xcf0000644000000000000000000000234213507430555015643 0ustar gimp xcf file BB / gimp-commentCreated with The GIMPS gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) t  Pasted Layert       4444444444   Background      / ?4 444    4 444        packagesearch-2.7.11build1/icons/install-package.png0000644000000000000000000000204613507430555017243 0ustar PNG  IHDR szzbKGD pHYs  tIME  -9,tEXtCommentCreated with The GIMPd%nIDATXoU;1(AU#7*v*Z6,( Z QZxH(B^TPPbk<z\Qlg33g;91_`ܻh֌a9^z sH)2ɩ3BY*|ɝ<ʹqᶕMQ,BSg8MB>r$!֤ #2oQì2ɤ6p'geSIiP`M jmlZ=@iz@)J?H&.pyfM TuxI>xﭑoߞ&R766Z؀^0 ^i>Er[%V?0$!xn4Sςi6~V^£O>hgM,,2Ͻoc i67o~E |HT`oooQKU]5\Rّ߀{O$JgIENDB`packagesearch-2.7.11build1/icons/install-package.xcf0000644000000000000000000001207313507430555017240 0ustar gimp xcf file BB/ gimp-commentCreated with The GIMPS gimp-commentCreated with The GIMPgimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) 6  arrow               computer     I]m9 ‘99~99blxq99lxn99rxf99x`99瀈V99爒M99޷M99¾B99B9qf`ZM6&999~~~xqgf9xqqgffR>>B>>662G ~GGzGGqGGjGGbGGꔙ`GG噡VGG塦KGGܿKGGºBGGBGqb`ZK6&GG~~Gzz~zxqfbGxqqfbbR>>B>>662e zeeveepeefeebee_eeVeeKeeKee¶BeeBepb_ZK6&eezzevvzvspebesppebbR>>B>>662             package     33 3333n}3bb3bb:b3bbXfb3b3b3b3bbtX3b3b3A3A3b33bwwb3A3A3b3A3b3wwb3bbAw3wwb3bbw3w33w3w3w3w3ww3w3ww3w3w3ww33w3ww3 3w3w3w3w3w33w3w333 3 3333dd3dd:d3ddhd3d3d3d3ddv3d3d3A3A3d33dyyd3A3A3d3A3d3yyd3ddAy3yyd3ddy3y33y3y3y3y3yy3y3yy3y3y3yy33y3yy3 3y3y3y3y3y33y3y333 3R3333FF3FF5F3FFHF3F3F3F3FFR3F3F38383F33FTTF38383F383F3TTF3FF8T3TTF3FFT3T3ff3ffT3T3Tff3ffT3TTff3ffT3TTff3ffT3T3TTff3ff3T3TT3 3T3Tff3ffT3Tf3ffT3f3ffTf3ffTf3ff        Background        hihgh j|zrnsq쨹g񎲣ÿŴȺתԺԼ٬ؽۭ޾تױӨؼݭݼ׻ްԷ޲׹߳ӳ56545 |7KJ@};A?w~woly4n{uwzX_}v]QRjksz|}xypp|xvyvt~qüʌªopǻ|e¿œvo¾xxh||}|Æǿu|üǏɹoyoǹ{h뵺ºýwkĻqR Z{S QwbcdTihNs^]tDAgQzuf`cGsxtYcUNQpSg|skbhlX1dWaa`aP/""@AKRTVPap~fu{}}zrPEYERmruqeOm|onmy|ztqntjKdni`zxlrR{umZyy~jY|np{t[siKJVmzw|[`F`ijrv|yFEbkr\~zT9`nw~\|oNYDe|vXdQb`Puz{}etsqpiee FRd" ivu҃[01_iP`s[n0)(`eڌ/eʠYBwGOac֖J8w2ƣ*g)"/$'SJ?я]b6Nwσh䓞5Ak5 pN\sc흛p75|hG{H9N)u|:O[F&Ώ6#h| $D PݕRPJC0tͻp 9=p/]o3x」kK{{޿߉/Nۓu:f+9F+pK\r|>}i8Wx_#aww+;~3M]> f'Ϝ`-`tf[_^r/%`F![!2B`Gm6L”E3 'OCQ8{.\"y¡$K؏?sw)AmݧTvm4Fǎr >Gqu>sgM۾k^(%F)_4L㐓 /,n 4kOX8!{ )gk,(lƔ0`aw `4Lø?w@ <|e7QO<Њ5 EiqmK ᣿A\tM=A&My Xs-Ҷ\KLl_pyBȁ }f010%,bylnΝ/ IKHtf߹Fu+fݿ?<so VVz8~O?qL o?@.ci|Ա_R`_  0&AZg=B%iHFq1v-x Kq&~{{30;_eķ#} [k SP̳'aLøp,WqH1M#Jt:<{g' ")@@"D(ŗ;xh{vwviDŽ0.C;11L&2*|;@z53p.0@P%e,/Ƒ#8zt .]ZP`𔡈\R7q|~_$/Fե ZkXʼn;8zcL6^ lU}_(f\ӆ. ҍPƘzY>I2uWa (L4+HHH@TBL DXჁs:9Ķˑ$#ƈMиSĉM{}<ԓm™I׿s7g_{9 RA X]cm>Ϡsk{BC@(l1T~P RHN+:c ~[1yMQKKKo־ j2g!,>(I15t=I=&k""sf-S^y SI.u,,5]<! "ruy4_{3zX)h1} ]#8S" bopX'!%I+egLC}iZ.3I ,^DD@Hf3'fe-׸3U]_ !RN@F)e]w4WGaR`z-b-P__,2,|;3=7A$Ջx'>G4/]k?_?(r{be`snv[pMē~DY6`wD➂RrHYXz׳j͓ S#Fߎ/ IDJ1ށr8uve/> X9D>o{ɹK3lxǿ[|V0Z8v7Ïzijz;?gž"!z-J~O?CDI)Jɹ&HZfl0Xx5'k伛 M3/!Ft{=رs1'Wb9'uMof [jBXNʴ.`i6t:K8qbj{!CL[2 >3s1U<"ԭ|+AY8yj{kjSD@/3CDRJ~vyx479cR*i/U$X66R¬D)~c6Ƽ6@u]gO$K}%t Ksh 9 0. <1p,֎uqB-6Ŗ,x?@e 0 .rě~N~f%NᩧOz *R@SA ")5cjEiX6YkXZֆY"fZ+ZCi&,k(VdSY( ji0PKjyiIu{;w3b Z*B kcm :e$S%jiF@)@L%GV9@ۉPRҐV$3S["8,..aaa [3bЋk@k}sx1HI -ilVQ ZkEO?iVPZAefϟxӨf[>nYMB.<;`*E_lY4C1ZX%xI`BDViF)nJ5YЀS$7ДbL9#:N<~~eeƓTUUjIvDbɧD"/+H b2Fy1pU1D$Kc:9Dp<˹3' Pj=}?9<ԣh1?AYT`^~#0>:^XYZBwi.9 _X3HY~V*# gđDD "!(NLjNY`yAZ!@+Rn`|Lո U]&TUFaLI(% !u=*BLi\>Hici!ll;qSHh:,_C\flo{?{ޛU{6N\ƥKO೟{MP׹%ŧf€n}Sb\XF,Ew]vRJJbh ðb#B`>%gzht! 0& s*s")6M XbPAUkX<feAҔBHuBL6@)$_塧Ѹ,oF|~L)!#)$. J|]w|L[3MѠi:3~R taL?D3>$Ɠ}Y[E"䝟~ |=fBK[nZ^n^_c<څ be[k`L嵯MFCzA&D2Y 1z`EiKX[)iP,3F(ަۖ)@l4 Cz++K1gG! C@5Q5j ceu e@P9 >)4#A" ]!fJfHfPBQ\ǨzR v\=B4]1 ]7p]xgѸz s7'?3.um@Yb ;~~\|M3nI>kF`Ӎfnlx7I"Ih %LBw=y}/D}VZca(a- E[Zt [,;(eע(J,..b~n0BBy`L&ݽ1B4U Ɵ >…Ap! |@xΉog":#3k1˸zY4]I1c0h|'+ M,.-ϟ{" YAA[G|~s'nFmWXc|x?oF_D`ЯD@Xqlo;%Vk&XQ FAiBccLH! z<\Y5 @1VS_ 5ʲ*66&`mM|hXh $45ۨ&cL4Yyh'Ը(s4x Ǒ=Tm]+ΠL( Rb J֏|(ZUT.]Ñ5L&v-t@pX" 0#-dyS6AZR0wׯַ?C ;ZWXxz*䑒@ FO0Ϧ؈g- ހ4w5(Qt{e c2;,  bIRPTf` T N:et{](oeR+;;[[rn\poq]9SKG}}L!gM,ۍ)%D1!z.c4PH;f;6!Mm 9laM-WQv8d2l@<(h.dK[v5 &"r4CBHLcP3Өntp=cԡCy6yرe<s >LZ]fkGi?!o<7an9h=:.uX<mLv~ʛm}) XI/ba_PP$CG+(6`$X<TN Jm 434`0gR3BSҝ|N N< +1ƘǘT &jxx WkuITɂ*@ʲnקH>]z2-&> =(T`fL-ő#~<27/>swdб`$Dj c/ݜȾ!&pvpO9_h}ٹk2|^}:y/ȧ5%`CM35bd({Q1zБ#d}cuDѤɣą͵;OWl_CqXvYk6 1y;`aEi~;("h7o\sϞV,\rIP7BS5m`4c<a#<ہ@ڀ)̤]l;hN+eǭØ.:2r|\>?!(1w*1)aְEAJ)40TRU(˲⣝q+?~߾Ӏw2VD`eu^{m= c*jYxyNk_{ʲOkGq&(VK&;?1&@l}HQ:,SJP/1I{ hZ36~(lV.>nqv`L)#B!"%-8<@!<]Ib&_O14omq b0сC4+5W4/>w`aG\ZtaANY,.,akxwM1\SûUMTyz-4u}SV'T55OALL6:w6V5(]ū_yv:E]M2W!QU %mvwx<.#k !iE,.[vPX-Fk2ZDٸf-ox3|{ K4;X=,0.耙p3H>:DJ-X,>/6' m^ʲ̬5h&\x?.Sv!B斍]=n.pg 1$(IH Bmᬁn;J)h[@)(uWťe^&)u`ONߧx2p8dR^f\H N€pٷ]rH !;s0Ii\4urfƝwq\칔j@\d=D`2ayi7@}-FD;',h4k7Q5u@Eu:!5qe|M|6N+510I+-DDwkM]PJ K Ko|U˖X\XpoW>|5#(يlkza})zmSlv&8HrneIBVi<uC^O [ [=0cMY/ :QUvpel]-8 x !﹮cڔPlAlTZFR"ĈcBλ٦$D)vvi,<ۡDFgh4񲻎~5ag#֎Sj?<9T G7YᩧpnXtעd%5vvhooXi~g2H_o'B4sggZAq+ ݏsc 'fNᘔ/ {햳V !1l nνv瓕YB0Tm`LX40ڀ+ L! PM]UGANDWpMj2Ψ| 8:g NB᧊-^S&eg,{QLSKB !J1!@CO\ ?4{ AL FC>Sx7bDԌ {{WqY66VW6U|x |sOwߍ DK0J!"'j</?0Uv,QU5楝)ˌgR^}`fɰIp.yf8V*MTaBIZY %ĔUtbNgc|{ Вa(H>}0ܡ]eقlarXXm hm U*0N<%( !Q 1Bbd@02qbV7S[Nd vI3*eAՔj1q瞘jk. U\XE]؆SC>wP%^l_Bdf@0,614@ U[D yN@R\!(> >x^]]tv4F {=ԍ 65tzKXvMSfs2;Wܽۅ0cXUЬ`%/7Mo; I"빦'C @02'݅Ǎl sR̉<39fJII,4b(P0RdHESn}VVVQy/;="Sb lU{ o?IS`(;%]BݴP YOY)]`Џb6N̒UIi^I5$fN-@V+Y!'*@;J/*bi'Pq*j9S0Ƞ{NyG>;޻Xz]gbZϥ]d(dS-Q([#q&c2A^ <y A<$d`yIb  30&"YEB{s>mhvXukebgVsbd'=w57ÍwoWfG0+<> <_ 6-N~}Ͻ">W}tbpa &=~?}WWW|7~~͓?5X'O\ifj~dq4?K;4MPf4M)I*)д 5mkQC%:)l.1 sDVفӃD >ل>nc`FYyec|| "D#R# {HC^!>H"60ɋD(!-܄D`vvApBÉa/gC/phevO~?IGGɹv gxB''3$0L8,D !$?>Ii,! a$*}1^6좞фo>@M"#w6gAANVK.ɭu~@/XZERu\"U4d@%@D1Mzk!/[ z3 VdD{@8嵐s w/^v&;+ =|U=R\ _mS]%=x=gΑfOp>H,6oc6ַI*X6nc\n'?:?Eet~z|Ƈ@o}W1QnY/7? o<^""%j4 Mh4M1a4Ph&PA"#j3?Y@KuiN\+U]ma rz`M DA m="$&4*?a ))D@|Ucm81E4SRFPX"0<>±}~^N r S(@}c2|qPھ#|xvunDc#N$i>̏Aq,qy6¹Msph0nF8x?yC%bnp<:+3 1w' >.L'{mim/$Q 1&'Php&$JbB^sܚ Vq2~& (~!EpO.¼`6e ;O A$&JEU[].`_Q5@ J4{ԻLYSo]z>YIIH!B@ 侪 =81?5"X]t ?](gm\$b:ZXTLME%(]J`1 l4]xu'O!vALm5|&&2R:d:IdܓIv?nHdԆSbT#b H5)FLॐ:7!kdP;1.djJ>K6XFkDž{dd`0oaov+ ф>:1 DG1iEˑz`a+N;Xs@+b IDATJ欭A/?[}:YCE'8훰Yl>C"i;B iӕ n&|V>#Ɠ_%&nm;|1C9XD;!iíַ*!Ҵ"D?9PµyhAD+P~)~_ f)6': rP>y* 7x΀Ԕ R _ax`0,S ޥ ؙu fjڀRb+'%v m>)r&#E-T~1,s7ңm`fĸh4ɼG-b0 t@#0p>!>N:@"&)G??A;;xz[=900$Q5LbR 0YJ_ΆTZ\ >Y ߰- QX #0 4v3j8=(G{3mʕ6!K0޹@nA= '߽VZuV]7HcRl$XlMn^Y#I7>pDuL 0D@ @˰ N7 뫄Ǐ +4lHhI}a:ڊY3{,s,'bt9'1TuIf'3|}9Gǩ* "4Gb );"fD@)&D>rD§ʝ@B]|@f2'7KM-_no `(~{e[gfgb kJc2Y5 bV$*509"&Rb*67X!=!c5cc2wz ¹sBPľnjnA^w!'LbEh'#$$Ho ll3~iHgGroBԙ,hIBYm;E[BO̢!JDQ:.B 7m/%ASo-cl?FiQs2Ϸw5ѣJ2\Y競 L'" {k{ k63 =5i*!!I(ETwNA^m)@RNv2Bm7ڜ̭nVb4w#E"89Ɠɪ%ELW6WAPQq& po ||%UP Cb 3 p^<v1B :F#U%?rɝ6[#l[[/r!-:(CԵm{m;MMmUiE5٥ IF=}Zv o!e7r62o5߰A1ӨS\@!.6꣎ {ۙ[ȿ.XC57P99yKP 4+"L&;^8F9અǠE05 )p<4M#41ROǘV F+/ʴ \@5[drKy'pC3HQ3C fSQ@XaYeaQ JҕW,Rnt\ 3)nʩ躡ݒ鼥PNzSJo-8٭[ֆê*ap1+D&a*򮑜;E" +I0 U%g+f 5OMIϊ,sYRpxSfiD[d/\Jd 2zD1*@`Ņ7U#%UM@ #0Ing-IK#iBPb IWϊ'<гϑT T>lMhPWop2Ȃ i" IP%z͖jJ9ܐw:a A FƑ!d,9G2"EǤJV dJ0(++ػlVP4ٿã T9*b\jG }IbR{X4)v򍕁+o^8WjC ns@XamnDTw`Yi))2 #NmrЧ$W,J*: iP yݧy79JyNj%.Ӫ+c݄1A_ǭ5D!掂",7`+ Bz.!/9گח( eqcw%]hT8)uK@h9+nv-ok] po|Ai_Aj*HJ"YիQ !HШ**>djFru]/OPr"/c%T5`4a4a:bksqeLS#hsb~!>C,3pN`[t΄(Fێ17 0.]_/\1nߺ[7o #MW_Zwf2BP`2t ^*KM3d (CaYU8̗pVWW,KfegIX25BfY  U: J 0L0DlZLRjI8 !h`31R RGhE>:&sveo{ qtx?G7n_/OKbѶ %F1T/_¥K1muwюFX[[.c{m'ǟ@`um;;;٩tZ؄lv'OwbeeG'x籱(IMC#UN>Y0 8R0jY[gyה7Ab+O(,!z-.,3uT)(]AnAM.n AF(w#$Ƣ="n(~ DS!!P&>£cLX__Wx;;;EV6H@}C0/۷np]ܿ>Çqt|\z2$%#\t/nXt|Mگ}++k3iC89>d:jaMc -++x[ob1_u퀈غD٢c#yY"Y|PIsry@-A$fJzͅlsLIvshqAO`8 A}\ D[ B3ӟ"eߓS)B(#؟CnCPhI$)J#eU\afa3)R >NjX\c>;q4 5ژ8yyl;#*q\^{D&́ 'OOG+/667rb Dag"<6@Thp6o>bL {>wVb=,2T3g%ZS\w0Y$3 ST9(;HBbP@k?BZC$ht"I{%&pBPYCw @Kv^G)p*S"T D-Q/Kq1ϑ{󖛦AqppEoXt2&Ӊ}[k*j ne`^׊HU*`!?+Ђxn\O0ڧQ&6 E`3ӯu-@n(h_̈́XB¤),"B`!1tuw*{5mv8*]:[`/rP>PLx簶 89N0N)hwywn˩~cs^{k@GRٓ[u' =UEƋTo34;5W6 5~kgs͎V)Ä *yP^[5Eho3 7$Ng7@!@c}kAkV hY چV[>,Nbc2*(2|9& %yas)fK) ͥȇHBtcc )潗pDkL2677pU4M(W`X]]D'9$/j y oonbM\r;;O&躅ѱU4ǡS3[?V(1&Q?049BҴ0Cٚz9;CUVYR-] nyf^4SYsdc?? agc 牞Ef*7RS>T4eFm?3c2iBB9逸ux F C$3:pRjf"UkmP 2e.t@J?ᅦ>Nx_ygf}wz`\? r@`M*&+mMy^Cމ@لA AKY;ȑɥ/o(0&+mB7t2ٌOݼ:z3[sP-!-+4IFO+.\ 橾Tv2_*;31st:)N8!SGG, k5`O՛֐B -gaF }q2`ӕ)/Wasc1 ԕe6>s&n(#p-EG7DdKAUo/}XB.&h]||-pFoo%:*նas: c_>yԏ"+Y}9(|tQ#>RVg g߶9-yW>oW좈D"DF!Eo,HPtD}|^:s%Rտ`o4*۾dz=Z:bL+}юF޾;g#L/K P?pzqn#p \:޻GGF Y K)Fu.ggnQ128w_$uX !$}j^7F)Mf _`[ThZDP"&To@)'@埢YIDlqc\{w#~nzBp !Z&wf$pxx#KtqTzr ^U 9ӑ082Y"8::;Op-#FKb6VY<^TFm$=黓ҢxL46֫j]{}𖥶u0R2 TOtXژp<~i.aeuxSa'ڑY0'|"k>TbqmhM`ggNx?~|cܸq+|ӯa?.Rj &d8zKL+I-IA D{JC2#b1jA%?+ cbc@- PK-IJ!HPдkEMLn ?/C ]V", U  0i~w9f~7o`2Ĩ/VaI"qBQp7z>?97Օ |7o Ĺ-s2(&pEF `YVH\Vc`[)CRQ>X$7BB3Q-\2IB…uo|MeHȌdj00{Ad Z$XX TMP@BD +w'„?DEC8BGӌŀ1&B-%p,JQ}/(@@BB)hD# !HL=b:J.iȝ`1?G\j}ܽ?bx /aks.^Ĺs[f]=Հg0!P$zvUs>ƣ1v.n㝟xo…s)W~;Kt2Ɔmǂ%XmLKU|1ǓGOGqfhFSLV.ˠ@RZ$en{O@\JU|@GԠДCU!|xS@bD|&ǪC{ـD45~EICC|A.6j%픻)a< S@TICK:#˅hM|bc}}Q[n`<`>8.]UW>Nr5hK~_!*$hۀW`eu6~Gk_] iONGG͏={!I|@v 5=eu};'{W4Vf jB> B;Ka?waU~@Ըlr*AŲU!'@Y̏@韉IB@p0d.i͇7og1QGVE~-Z)'ZB*V??5m@ӶϮO"A$ZtK\YskeaTa&\:7VqqGM.F16qq X=0NqsP`ww_UV,yb\ylm];} }#!ZT'&eGlT}w|Cj? k`H Nh1bA g|BDh1sP,`eUx)-Nfwu|膴B)!GL& h\fkOBg^i(Z.bc2!?h|x̳m8r4U2QfqBRNLFtWqnk  88@ca}m , {!F#\|bȻ E#$ct{Q`?S+;.`F'M) )\4-_y ΝpO6#rO` \\, $J=6a<6?+-zǁ&:%2&]Z&*__|{gS hy%ezMEm@r<̕TXn|1rQjd4=*Me&m2q | ~`U)B!hG @q)p#J{>!u }GyńDŽ;ĔbD NN~pH.U=gRD"B3gCpG5oJ#k(>\P=r$҂D4 ͫ`_Ybss/\3?m Î$!Pkm<(\c޽?  i M`-%2t`g-͚|SKAH4T5͖OҺV\堐f}DnW^f Z!HxWns-1ZlxR{݊ b4w{% V2d<U|0'6_BSE3vɓ-$6xR1Zkݴ-77 r .?wL }e(y#)i=v gs[T "DBmRbQHN=.)%ZRCJ*v\_YyGt*YEI1iIv:x~\/C' f&˖mQ''ן`-l8_ĆӄЂ3 ` P75/G1pQa_j̍E_ϡS8sq/9\ GOܲy8!˰Pƛ*lL{`cAS tu0Cӄ3 #8$,t^: `7⑓c'p3\$]}7@Ӷs&TQ)Tɻf@Gw;I.fC2&د嶝*;Ȫcut 9^0i66T Ռ^Pc5'd8 )A %??) ;<<~|\Rh`.6]L};6,}[[HyD2zP< n0Ӑ&XwF F;c< !!Jh "zE<~?PEb*fSg28G \PSfP^_w#H1WE/ WA"c?@VqVp ֚LZtdSE2>kJf*mi"YD1cW\8:b%_e >򄎎'́7fچȹVJqn?ozIco7 \F L߅R[Тi}lK@a9P(90_ԃH!he:$M 7Ŏ 8<"gAʷF5ԫP-)J( S}Br.cv?& 0(yY#Oa^ aCy 3s`j.emCG~ȓ ( #13pNNFX|G8PGkEO܀?ρʗַ~[>cmrjʦ* (-Y! hSB؄ƙb??.E1EcI:0D68>ǎ* H)BE>yЮO[ iA2( ,MiʳB\koA)b|0a/DwS-7,P*(Kt1l K; tUD7o?Zi(Cm8谌b<6 ڿ BBe'd iM[mqM(fH )xm`R2ڮVaoCӳ䲮7s!7;ܰjh]z.;W z0\B58A۬-[l̼U%{(ˮJpŘ9KJI)%.6Ʀ7.v*(U]յJW/i\`ƀ1 <,34Cpc m,[Ԭ9{{bLtZ |&ļ~x^/>~Fn:FP@)m, Sqɱxws0''IOXoYo4^a@(J[$ IDATKgf7~?7=/y wکtLRX<n䧴Yư4^/栔-Dž^EQ7/G%zE_"E^D ˖U~ޕƃxիc45~*77daҦ28e<)^և6KqF:c=H_EHܒIc2G2N , /͊plߢa3h3?\Y\iC-m-`c-YdF\!ʧnt$s9 ty1c[N8,qe$1Tra-zb40jˠ[k,8}'XV\f0>YΌ h݃Rm0tyU?yKwRZ[-b*aqYAܩG ekp1ybwI1Xnx卣F[>Au/~!]=i?"(u/WΤ~y6u Q#S7! :1Dz{BsR,,2׶¿'y t_es^qd}gYVaw7?$GNw\L8/ ,A?^MwB+gKR |߳8 7vp˜}Aܹ.G ~{^o+_癓/auEp"9$`VW} B¯jpO|~J5נP{(hn)?[ZW)(MFřmP%1y+&N JY*d W n xeyp-%5@ ƏybSp5{1)]j>up  +˧V^d^iP_0Nbk`a]EӃ-"ycuyJ1>$f %c%0%8zUtۋFᵠTl֨b3/k_beiNO-fn~%~/ r e9Zk+q 4Lf[E~)4cM7eU䮛<'۬;Q ,Tdjbeu,Y%LqggW{EέC),WstzrMA0Xp``ȱ q>2eDrh 8JqhCNP:9rju}Rԃe]) ]+Y{ƍ#Ж~*'YαR M BT0*Ц!uX/ݡoyKDZN`lb MBRŽJl' AD83A6ryROsAǑ b X0&=hVQ i: )RRө ^! g?,; 6g ,ʕ(FaN ѾstcG-X+ P걥qaouË T֥qSR#L]y_b!!4VZeDXz*X{/(,/D! t{K0:AC oc|b` NGSⓟ.+dۍ1PJ!s(y05Mlpl.Nפn%'?_pK*"+M ( 5va m%? G8yNNY~?Gr<CH)|fJ cLMZH|}  +}|/mM7)ZGtU6`,s?9z@}.U X\sߤd](~$ |CNI96 +m}_J8 q} ☷ ?un!"4{m97ƳO=ngQ$G1:une,=7+tڍŶ%-ނ²Pqr,301(/"uzo~?y#K8Kh?N!icYߧSR)4)x d kal /|aO$y::Loׄ]!YUh;Jh1|WeA kǓa~|Wt <{M]Ƭ&VWKѻ.ڝHwv  )\%8G~kAo"qq$]&8uX_w'/G:~c }2PFR![0h.7_~ BD)b;MybC}GbgA o:Ϭar2~`G*5F JD7 d@q‘dLeCBٸs Z6^N84*9dt*e}cIσ)$$WVaL^.o ^`ey32S),T렴BY>xlD03zGZ[ۂ d )ˆ#x9nR3̎20/v9dēO-bb">|Mk%JkkK96"+ O4hO`i ZkZ"sZ]k")'g 3 g@HȹUyNNuQnrbJe8xz{h/=xl?d:^?0\Tr WnB}fX]]D3MpQ@i,Ŀz-%[x = *' M.h4[%]: 23-ĔA3ǿrm{N̬AIu`a=)x*\jQW^‹֖o$Y8z1-=Ż UY[{=Կ\v]~ H1¹sg!G`m Ȳ@>m7}Yr)QО=%u;X<7G/CshT o}CK17Rj G?[obDNa!|fdxR UsՒ38 ^彶gAه8Z+58N 4G$-TBf+8hD D4TZ5Z"5dubu~B8? B Jc>Μd:Vy"v{ZwsU@>pCےTD'|A0?7CG,cn~G Ǡ_ L+@3c.o-M1A&H&8Ȳ`bO\@04F OO!V]U :ry)8X"Qtv # c,=ab/U֧C[GLewމs ˻xϢY@$pK(݇ %78v$c@DĪjEzSHAgY8r1cXZ:;ŭ2([` cP y;~vҹ QinAB$YR( + <$TƐij! xzc{5Hh( Z/rOHWK@O-$+!2GIp"TBP` Rp~>?a*ㄅůb܃ˢD)v6AϯXÁ}L$+dlNsȊUTYqŷ>Tvm`?8f1T%3";Yzˮcϱemhs3~k|#az|L`2Dqǂ0v~ U>,ŁCGAǛ &el8??Qg'N7_I0fS[P$ )l wE8tsmFl=0#dYQd!Eka G_Fn6-x/p 5 c@T6VAHbRNSˬm*U97X^yGqp.!D ~r}Ճ@p$ژ_CF.e\ļ1 {6AL!c澿1!*cBtY_>w@Xc}#sI !]`k?W“?[o3``֥I[! 2F#t{ e4d9'fF A&gR#BZH<ppo)/ V HU]g`|BLȧ7w{0; !$h G"ZwנC\|ܼ>11 dbM{6:,wiHw! n@$.0&9t4?CH(MX+)IbH!`%y? j}7r3IHلRmg D4BO pn_hqhØX|F~[jgaɎ3W!R1 48o:p f"~-hU$]k̝̝:9#<*Zthd06lT#00X@ڌ)d܀ѧ|zP~뙑E $ /ȇYl@]LDŽbQ1,͟Eoa[XAq4Sy8k4ܦ51c삵wLU Wޡn-6ʈ24!1II:6t:HI}1ߠr| .* J0^<(*!ȅ%{&,g/E^rڪШ-9̝{ (RR&BX~YކVީنtߠlc.F2n J\ `6&|N|@~9{˧Pl >P@Y8x Y䫧!ǡ87$SʐcccMJ(,u6>wl W9}'/nȀaQ1"BĈI0<_1iiv^]'O+MIkmm72ofT*޸ހ-~``Zb k8Gg 3F'n0pEY]62 mJ7M D@\&R_,c52*Pn>9' UՖr!\O7tbU6wr2%}S)ZObە`i2 g*e %B50ݟMi}(uq@-=,,T94cqdy^ND3\0cnO,//^?NW ~-d~ЉIW8n@0}*!eq<8n"&  ʫ>޿ 3Ii9u]A!Sv ΢=V{dW)NL:\zcU@JuxeFcd ;NMȲع3Hic ͱ $c1WBIYip| Ap?ddHY@qj IDATA 9U]\p!9NV,#$IEeCGY ÚNcb٧'3ΞywVп  n`8{Q8@^ g)A;R}X=x[ԯq<8wl:o"S)h6QPy Jwm(Fwr c*cz&9qD~oiC N8v]ǮXƈO?? $14'&4s)Q3|*rF-ÓȀYFvuGdfjC_z_dW9-oNfx 8to𡏊ݲa{րuF ~P Y*n3QxY^)H08\5ief=:InDR !"$Ii@'q^ӏ:j|9$ i"P0YG,QW  R q8N1(fBk} s}mp;;vݑu_Coqc`6Yו— Q%fEA7 T.HzBTA+~ܾQt~QX`kj{ kͽ*l֭q7@VZ_Y"_gN0ƧR4m1'qģ8mIceli8H&d0lU\Prhv=2`V!X |•Q!NqHFQsg )}{:ܯ&N3|a ^7쏂طKŋ3'qA/6}({+{(F_D[Xnxow7k[Tܙ?=L qM1ySY7O )Rƀ[ 쎉f<1VqZ>k0Xcu Vz{ ( RyauWA8,/aCssg홹/oH[sdΉosD}13g聋B&v;]wuZ{k6ќ@!Jm@U[rL蚄~cg 2gCMB!")X0'' d}3mq,#_\@ ;>] z!@wn&+zQ1X Syz@2sx} {3u_ߒ$ KhO iADk Q! nIϠ/d`x`A?$7exq@ ?nȕz c~G!b3 #4C`s R`@,=ƞ0&3S>?V{(cch4]_ NU΀(z~w x0`p*04&;#(1 uE?#?k>{( ~|ekyS h6@CA.lۋ~p=TCpD!+B#2+ Iƃq8Bbz ͝A吂wS:P=xkfx/6witl85RА1G r @ Y7=`r 7 t8qAD>~ٳ8?O_ P@}Ϋ$YqᛃMK0!*%6} XlpL8$RH؍57,a,,_kxj FN]䏫<ϻ:5z]hjb l ߆t"nk NzW`c 8Tެ6h\!syv'"$š#'1?[~˰sAJ߽`i14cI )oC%CIv)?y-. rp_|9DD,!~Yssgg`2:y1:[_ƯEJnV vel͌%~ׁ% Vķax$@xLk rRй1KEЄ/}e5炕h~i~v-tZkuZ]hr|0Q%jny4*N̕Y\NF\[.#b:| IZ; %@}.JI[nny6HcH&i :AeAhu { YH"NbH)4*YW0͏k3\oS^bAsnv :g0F }lhO @h RQ`cCp(+(+ \jU2¡G_2YfsQJ"~S>xOzj0MbW3^/D0Xӂ8On*1"hbb| YzM՜ %@}oH$iF8iBƱ]AZaH@TW~}-- !*RpD^ZsI1?w~C>KIw<Rtmʝ1Y3TcBLp Y/LJ @i7sƢjApİӟxwj-jSm?C_nn~ `UҪ0}J@rA]Vƃ*T55h!ǡ#G6bM??_A._?.?O*$IHR$&$i lX_(DG9<; e"G"b@>,+2G0$1?7n?dCOTPKP]~#˲HIp~Q%=spxˏ1` a=XFɊ]!=H8DN9> 5͹c~~5璵Nz'[뽏q&4Eh InHJZ݇^AyA p!lz,׉#14a>g?j%/ N?yVʒ%I$i$m Nn8š,/ s݇6L*B3(y'H)4 ̝;~)G?NW/nҦѣu;G;it6 - ?!农30010&a+<n G)c:uꊎ:eDng2mH8v%p}p'H {NE:>&bATDpWYHKoh4`,a~z>c^Wj&P@}.3 v^>JGcC/ߪp)=^{@ub׉!i4@ϡ3Jsyw̴[ke3Ib$I"3":7!`^SXD!97 DRpk @6`0n 'nz7|ϩSt * no(bI"MS'>E  H FP1 YXPlR HHI(;L"ڽ.`ox˕5n<~?ϲqHԻE/6 PdǠh%(Y1d(M 9w껮>WD6plj/]$I6C Yq&b DPp(JCl@^|TPwb)YAJ8an/qy=S Z}sg/Nq"Iq7 ]oؚ$ P pB8s@dU$aciin9s;.w>W\IpcdYq$YHQ@Q/mÅA)#+`\`p_`+8dTEDI":ء[p9@ "K_^?si$IEWLI*嘐{^|h20H雂.#`!cFq?S~7>;oCIA Awp((݈*H*D!P ] D$D$!c "/9D:ϕzW'O+\]O[17 o9띊UmYi>nh]` i 5TnZ:}׿kO}.i=Zg\ZˬgšbD|sm5Sp mוRl!nCB%@[lG0g0!9 J\Kއ{~5\Ad{Gh?0s`ߟ߬n/!+XabWm!*R`f}͑7kq,'bCJJLG7j (}O huhw: Gɫg[:BRvMOOUB"'M| ]wA m6*RL@\wzߗTB~kS ܿo[%bdҠ-PyMBPT3Yr}3 ڼw{ ' ~M5-Jf-v_CPNׇf{$f!<^K+ֿXYNoi=z{Lߒ+}D Ƽ`&>̶G`6 HH6(wyM϶7#woE vK`8Nn~p\/&k۟}Q?dl_ E  @kOݷu#=697[{M@`'p!n~Ì:oz m̷cdP('+mGbA)n#7>s5,^ؓ}>c Wo%| X7eW'wjeO`_`k c85ՉNxk?v5\vBm~l'@0b|nV4\E1!u9P*Prt+<_}1g^Jv;촚.طcy<]7V[}n}b,>ιxz@q!9= 7- I3Sӟ}'wߩ?ÀKo'iv4+M>mr-&< uzY;7_>NdĘ7d/Q3v"-Ȳ;7آj&5; x<em>.F1@FԒRlh`Ƕͱm~2"GGzu]~6MBl([nz1黎J}s;t`ߗi-!=`c+.P+Zly YXmYm{2w ֳ^G1m\Rk=/|~įSABr7c0尠(|Rd*W`g$??w46vNw};͊Bi [ݬf/7ւ 1 /`*}RxPeEG5+Y\}n^ENlUQh/ Af͚|bD@h gbg mw4%KwYk_"E^jbjB͙2: K-;J׺ *v Fa5K|9 ! 盍.mL,@i *sp5X,y7!ut=sK+_C5UM>^`7 Bm-b F?QAT DZ;/6ƚcs%(+6ڝ.Oe=4-ݤX8`A.|>vM؍;x:8 `ǭ%gKlXȲv^/./W |6U;ݖۍ t v D8-cpRIDAThs%&ka-Z m 6 s^nZgOXU;PUN>ݡ;Y6QZ80Li1F+(mq+y~e@>wv^kY 3ULvϕY\fvNQoh*n܄MJ&pSP?>A ;9&/$0eyrewƘ93U&5\[)+Hl|u/}Q6ylQ9@!<H u!{m8PPSkp!@BN~ӛNfᨬAG~@x0CW>T#jB^a/ ; Cu( ß_GXĺr[>Bx\\pA`n񭚏[=7Un_ڤyw[,b(b+l*aԍ?upNbn`v"ոa?(čme``#}ToF\ `?{[m <9> &^joe vso7g ۭpToFӭǰݍ? 5\ p1` g{ZvbNz}c=gU nnw${S7kU=^|~@`<>*Cy6{67GsͷiJ>W)\, YnB;QAvGش@hlk  zavmk Vg]O{|.s4QPL7s8Bi A [; h/\@b.|nۋj w!q2y^Y@ E%z]=oT¥|KR|_uPo+@տS@}5o_@5J|]8ׯԯk82lF,IENDB`packagesearch-2.7.11build1/icons/packagesearch.png0000644000000000000000000001327013507430555016766 0ustar PNG  IHDR@@iqsRGBbKGD pHYs B(xtIME0 U`K8IDATxy]W}?s޻%K-l' LƩJdH1SSd*C(2) Ȃ !c1x .o,XmmMKw97" 3sN{ϻ{>]m] %o T5w}미V磯n_H|U[TU<={zU/uCJ\kyu{`>ȍ`hʕ!E(Pxo՛LMlP_y_}{:x4 (MDn6nLL>?C6s! "(appno5Al6D\z蓯\\seػ 9{^EƘkր110[6Z.wn7kc.?|^y5qĺ|yY}{lIQuk Q/#ͳP P)py݌O)}ǿફicX*UTkr'aP k֬<֐ƴJr=/zKN%gT_{f;\MturKߣ=ctf\?'.]lMp՘wx3<\iӻjCR*#!bJa)5cUTVwzcfvhwvE2† 11[U/G?pŝwk6#l(o|* sUj*184k<˘UX .0y0v ic~J;k5+VáC͹OޱpGgp;oscOnGZSpś8{Jze)uuS!jrL,[6ȋW[XG,jQi=,Ԕ4cٲscsG}1EQhff~ooR'\~n{E,#sY7")|>M[q`Z6DR*O8f+QB^8jZ)}kHyf[j)=q961{xh#?rp|WGN,){`~Aļî5d_=49؎gX1@@}+B;M!KM Iϊpft>7Mky]kGk. o k:2!:~pJz>ޫ}=r6njG XV.20Qx5#50;wpeÌƪuYTh0ypzN٢^Qk4sG4ZMWs4Qz{Vp1t[xk,5ѩo[[|{ZfǮG)ŅV#vw\^7^zQբh>|1 "D@S9iM"W%se,gt(yޠ8FtGvZLOlsik y/Nx-}QY*c"ovw׃|'U8;+?x Gh;G)y&m4q] ȋ4R<[cr>xտʆxa<o1n0*bQRJrBE(T A TDQx:s8ɲwuﻖ,ϸwÇ^|x;auK/y+O<8G1ŹY`MbPc0%ཿpMy)SȥR!3l X@Ȳo>-Fj>!`l'EQUW 23sE$dY4x"bA+bN^y `nyK'h@N_D|q> Xv-]w-7LNM~c+Ȳɲ%.%$am b!R\M#aXN Җ#G]S=<<(*KY?!n.288j'--DIB0U׽AD gZ/ca6 7\D7*)%Ӝ5ǟh..xͨ bmD%G2rlHg6tYb[1"%w p( W ڭ1#c;x b#¸L\ j or=j58צ^[/y Z !Q QmL=&6X8`tFjss^"Cj/sSs6CD.zo㹿xw5Z1G홞ogǩ7Z҂4Wrii]rZvZt>94'K[Dl޽38g0v3 q8Wm%C%i7iQoH]=E*m_f_jNVGen~}OEsLO2wF=;#86C`v2::J?\r΃P,9;ٛnjyl6>*i[`ɓaݓSA, bF= ϛykYTA=vB' T ˆ5<_?:~Z53]r{|{{Nf=G$PY4X&'/nNp)Jn[ueoKJUw9;12Pzz?i}OlsJU@K+#Jh=#s4 #xۭ߼W=сS#WEIQ%J$9ErB__ ˿v}ř?TmML~^o (VUTA[ ($ Vo:kЏط_F3g wwŻ8Raރ*9]5u{^fv5#Kۿđx5rUq%8$-+fc:UEg[PI8 \.x~خ1|fi`d5cKg~gWdǞtrҌ$@jm60ajߨ ;PKIUv0@N ?n$x=h=i98 mQ /z$MV l) 9]bU)O?qt/e6|g2!"1/i?xc}H_I!9A埐ҟ]Nwj>DIENDB`packagesearch-2.7.11build1/icons/packagesearch.xcf0000644000000000000000000001576313507430555016773 0ustar gimp xcf file BBB$gimp-image-grid(style intersections) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) A 6{ magnifier transparent     7Y m }_PVXXbuXXZr|aYTo{cXsxzúXcjmyz~ķX6ajsyƨm\Aiuun|sdipvyljkYv{}}vtl3z}}{3a}}3}}q3}}~}qq3}}||qbwqqqqqqqqq   ˼  ν  ʾ  ׼  ͼ ɼ  ǵ 3 ſ 3 3ʴ _3  __3 __d y_________RRRRRRRRRRRRRR RR R R R R R R 3R R3R R3V R?3RR??3RR?FRT?????????ֽԠؠҼ˩Բɞ 񺵭⭓ Зڨ ں ʯ² tŚeepe$c tt  magnifier     0   X}XX}}}XXX}}X}}}XX}}}XX}h}}X)XX}}}X)XX}hXX)XX}}h}XX3hX}}}}}}X3))X}X}}X33)h}}}nX3)hhh}}Eq3))hh}Eqq3)qbwqqqqqqqqq    ܼ  ˼  ˼˼  ܼ     ˼ 3żܼ 3  3 3˸ 3 ˚ _3 ˚ __3  _d y_________RRRRRR RR RR RR R R R R R R R R3R 3RR3R3R3RR?3RR??3RR?FRT?????????  tee tt package       333333n}3bb3bb:b3bbXfb3b3b3b3bbtX3b3b3A3A3b33bwwb3A3A3b3A3b3wwb3bbAw3ww b3bbw3w3 3w3w3w 3w3ww 3w3ww 3w3w3ww 33w3ww 3w3w 3w3w 3w33w3w31333 3333dd3dd:d3ddhd3d3d3d3ddv3d3d3A3A3d33dyyd3A3A3d3A3d3yyd3ddAy3yy d3ddy3y3 3y3y3y 3y3yy 3y3yy 3y3y3yy 33y3yy 3y3y 3y3y 3y33y3y31333R3333FF3FF5F3FFHF3F3F3F3FFR3F3F38383F33FTTF38383F383F3TTF3FF8T3TT F3FFT3T3 f3ffT3T3T f3ffT3TT f3ffT3TT f3ffT3T3TT f3ff3T3TT 3T3T f3ffT3T f3ffT3f3ffTf3ffTf3ff1             1  white-bg     =x              1            1            1     ! .<   @N  1  Background       lX}XX}}}XXX}}X}}}XX}}}XX}h}}X)XX}}}X)XX}hXX)XX}}h}XX3hX}}3}}}}X3)3)3X}3X}}X33)h3b}bb}b}XXb3)3h3hbhb}}Xq 3b3b33))bh3hwwqq b3b3b3b)b3wqq b3bbwqqb3bbw3w3qq3w3w3wqq3w3wwq3w3wwq3w3w3wwq33w3wwq 3w3wq3w3w 3w33w3w31L    ܼ  ˼  ˼˼  ܼ     ˼ 3ż3ܼ 3 333 3 33dddd˼ d3 33dd˼ _ 3d3d3 3d3yy __ d3d3d3 dd3y __ d3dd y__d3ddy3y3__3y3y3y__3y3yy_3y3yy_3y3y3yy_33y3yy_ 3y3y_3y3y 3y33y3y31LRRRRRR RR RR RR R R R R R R R R33R 3R333R3R33FFFFR F3R33FFR? 3F3F3R3F3TTR?? F3F3F3RFF3TRR?? F3FFRT??F3FFT3T3??f3ffT3T3T??f3ffT3TT?f3ffT3TT?f3ffT3T3TT?f3ff3T3TT? 3T3T?f3ffT3T f3ffT3f3ffTf3ffTf3ff1 Selection Mask        ! .<   @N  1packagesearch-2.7.11build1/icons/packagesearch.xpm0000644000000000000000000002031513507430555017004 0ustar /* XPM */ static char * packagesearch_xpm[] = { "32 32 385 2", " c None", ". c #4C4CAC", "+ c #494AA8", "@ c #4646A1", "# c #5858BD", "$ c #6666BA", "% c #555695", "& c #4B4C81", "* c #48497F", "= c #4E4E8D", "- c #5656A2", "; c #4F50A4", "> c #3E3F90", ", c #5151B3", "' c #5E5FB2", ") c #383968", "! c #161832", "~ c #181A2E", "{ c #1D1E2F", "] c #202132", "^ c #1D1E35", "/ c #1B1C3B", "( c #2A2B5A", "_ c #4B4C93", ": c #424392", "< c #5151B0", "[ c #4F5097", "} c #1F2043", "| c #252537", "1 c #2D2B34", "2 c #524F4D", "3 c #32312E", "4 c #363634", "5 c #303035", "6 c #292A3A", "7 c #212244", "8 c #383979", "9 c #41428E", "0 c #4A4AA5", "a c #4C4D98", "b c #222345", "c c #4A4954", "d c #6D7375", "e c #758284", "f c #8D9A9F", "g c #A5ACB3", "h c #9B9A98", "i c #919295", "j c #7A8189", "k c #566069", "l c #47505D", "m c #242643", "n c #333574", "o c #3A3B83", "p c #5050A8", "q c #272851", "r c #656572", "s c #A09C9C", "t c #AAA8A8", "u c #B7B6B6", "v c #CCCBCC", "w c #FAFAFA", "x c #FFFFFF", "y c #BDBCB9", "z c #817D7B", "A c #544F4D", "B c #3D3A39", "C c #252549", "D c #3A3A83", "E c #434375", "F c #85817D", "G c #847E7D", "H c #574A45", "I c #45459B", "J c #3A3B7E", "K c #353552", "L c #ABA8A5", "M c #7E716A", "N c #7A6960", "O c #816F66", "P c #978882", "Q c #C3BBB6", "R c #EFECEB", "S c #F6F5F4", "T c #D5D2D1", "U c #B6B2B2", "V c #9F9D9F", "W c #8E8D90", "X c #5E5F6B", "Y c #26275B", "Z c #31337D", "` c #B7B5C7", " . c #B2AFAD", ".. c #60564E", "+. c #6F6A63", "@. c #494AA3", "#. c #2E2F5A", "$. c #B8B6B3", "%. c #A49F9C", "&. c #A49E9D", "*. c #9E9898", "=. c #948D8B", "-. c #948986", ";. c #998F8A", ">. c #9C918C", ",. c #958981", "'. c #86766E", "). c #7A6D64", "!. c #70635D", "~. c #655B57", "{. c #29294D", "]. c #36377F", "^. c #767491", "/. c #998E88", "(. c #8C8683", "_. c #79726C", ":. c #434499", "<. c #38395E", "[. c #C4C0BE", "}. c #B2AEAA", "|. c #B1AEAA", "1. c #B0AFAD", "2. c #B0B0AD", "3. c #B0AFAF", "4. c #B0AEAE", "5. c #AEACAD", "6. c #ABAAAC", "7. c #A2A0A2", "8. c #929091", "9. c #787676", "0. c #404054", "a. c #313378", "b. c #32315E", "c. c #66533F", "d. c #877970", "e. c #504842", "f. c #383983", "g. c #3F4092", "h. c #424264", "i. c #CBC8C5", "j. c #B5B1AE", "k. c #B2AEAB", "l. c #8E8C88", "m. c #9A9794", "n. c #8C8B87", "o. c #A1A09C", "p. c #878682", "q. c #9F9E9A", "r. c #92908E", "s. c #8A8986", "t. c #8F8E8C", "u. c #797776", "v. c #535361", "w. c #2E2F6F", "x. c #313267", "y. c #9A917E", "z. c #644E3F", "A. c #4E4744", "B. c #36377E", "C. c #3E3F8F", "D. c #454669", "E. c #D0CDCA", "F. c #B8B5B3", "G. c #B2AFAA", "H. c #666460", "I. c #BBB8B3", "J. c #BCB9B4", "K. c #64635F", "L. c #63625D", "M. c #A2A19C", "N. c #B3B2AE", "O. c #706F6A", "P. c #A4A39F", "Q. c #6D6C69", "R. c #575863", "S. c #2E2F6E", "T. c #2E2F64", "U. c #A29988", "V. c #5F483B", "W. c #524A46", "X. c #3D3E91", "Y. c #42426A", "Z. c #CDC8C4", "`. c #BBB9B7", " + c #B3B0AA", ".+ c #65645F", "++ c #B9B6B1", "@+ c #B0ACA8", "#+ c #83807C", "$+ c #BAB7B2", "%+ c #615F5B", "&+ c #7F7E79", "*+ c #71706C", "=+ c #4D4E5C", "-+ c #2F3073", ";+ c #383864", ">+ c #A39C8B", ",+ c #5F483C", "'+ c #534C47", ")+ c #3B3B89", "!+ c #3C3D6D", "~+ c #C7C2BF", "{+ c #BFBCBB", "]+ c #676460", "^+ c #7C7A75", "/+ c #B8B5B0", "(+ c #888681", "_+ c #A09D98", ":+ c #BDBAB3", "<+ c #716E69", "[+ c #ACABA4", "}+ c #676560", "|+ c #393A5C", "1+ c #2E3072", "2+ c #545571", "3+ c #A09B8F", "4+ c #5E483B", "5+ c #534B49", "6+ c #34357C", "7+ c #393A77", "8+ c #4F5075", "9+ c #BEBAB5", "0+ c #C4C1C0", "a+ c #B3B1AB", "b+ c #8E8B87", "c+ c #A5A39D", "d+ c #B8B6B1", "e+ c #B5B2AD", "f+ c #B7B4AE", "g+ c #9B9893", "h+ c #B2B0AC", "i+ c #84827E", "j+ c #90908A", "k+ c #5C5B68", "l+ c #303066", "m+ c #262767", "n+ c #8B8E98", "o+ c #A19F9C", "p+ c #624D41", "q+ c #54504F", "r+ c #2B2C6A", "s+ c #363782", "t+ c #3F3F6D", "u+ c #9897A2", "v+ c #C9C6C6", "w+ c #B6B3AE", "x+ c #B9B8B3", "y+ c #B8B7B2", "z+ c #B7B5B1", "A+ c #B5B3B0", "B+ c #B1B0AD", "C+ c #A8A7A5", "D+ c #969598", "E+ c #424372", "F+ c #33347C", "G+ c #2E305E", "H+ c #B8BBBD", "I+ c #A7A9AC", "J+ c #6D5C54", "K+ c #7E7D7D", "L+ c #2E3071", "M+ c #323375", "N+ c #454670", "O+ c #A7A6AE", "P+ c #B1B0AF", "Q+ c #AEAEAE", "R+ c #B0B0B1", "S+ c #B1B2B3", "T+ c #B1B2B4", "U+ c #AEB0B3", "V+ c #AAABB0", "W+ c #A2A5A8", "X+ c #92949F", "Y+ c #535387", "Z+ c #3C3D8A", "`+ c #21235F", " @ c #807F8A", ".@ c #A6A9B4", "+@ c #ADB0B9", "@@ c #686467", "#@ c #7B7B7D", "$@ c #2F3072", "%@ c #313271", "&@ c #434477", "*@ c #6F708F", "=@ c #95989F", "-@ c #9C9FA5", ";@ c #9EA0A8", ">@ c #9DA0A5", ",@ c #9698A6", "'@ c #7B7CA9", ")@ c #555599", "!@ c #47479F", "~@ c #2A2B6B", "{@ c #464150", "]@ c #8E816C", "^@ c #9C9B9D", "/@ c #9FA5B2", "(@ c #636775", "_@ c #797979", ":@ c #2B2D6C", "<@ c #424385", "[@ c #505090", "}@ c #65659B", "|@ c #7172A6", "1@ c #7475AE", "2@ c #6E6FB7", "3@ c #6464BB", "4@ c #5F5FC1", "5@ c #4546A4", "6@ c #262864", "7@ c #2C2D42", "8@ c #544E45", "9@ c #645848", "0@ c #867966", "a@ c #949396", "b@ c #636979", "c@ c #757676", "d@ c #25265D", "e@ c #2C2D6D", "f@ c #373886", "g@ c #424296", "h@ c #4C4CA5", "i@ c #5253B2", "j@ c #5252B8", "k@ c #494AAD", "l@ c #2D2E6F", "m@ c #262853", "n@ c #2A2B33", "o@ c #424B53", "p@ c #474E53", "q@ c #504B43", "r@ c #615647", "s@ c #837664", "t@ c #67676A", "u@ c #727172", "v@ c #23255C", "w@ c #25265E", "x@ c #24255C", "y@ c #222358", "z@ c #1C1E4C", "A@ c #2B2D2F", "B@ c #3F474E", "C@ c #43494E", "D@ c #4D4840", "E@ c #5F5345", "F@ c #7F7362", "G@ c #232323", "H@ c #393D41", "I@ c #404447", "J@ c #4A443D", "K@ c #5C5143", "L@ c #7A6E5D", "M@ c #323334", "N@ c #3C3F41", "O@ c #46413A", "P@ c #594F41", "Q@ c #756959", "R@ c #2B2A29", "S@ c #393A39", "T@ c #443E36", "U@ c #564D3F", "V@ c #716555", "W@ c #242320", "X@ c #343431", "Y@ c #3F3A32", "Z@ c #544A3E", "`@ c #6B6050", " # c #1F1D19", ".# c #2E2C28", "+# c #3C372F", "@# c #51483C", "## c #675B4C", "$# c #2A2721", "%# c #3A342C", "&# c #4E463A", "*# c #625749", "=# c #26231D", "-# c #38332B", ";# c #4C4338", "># c #5D5244", ",# c #1C1A16", "'# c #343029", ")# c #463F35", "!# c #0B0A09", " ", " . + @ ", " # $ % & * = - ; > ", " , ' ) ! ~ { ] ^ / ( _ : ", " < [ } | 1 2 3 4 5 6 7 8 9 ", " 0 a b c d e f g h i j k l m n o ", " p q r s t u v w x x y z A B C D E F G H ", " I J K L M N O P Q R S T U V W X Y Z ` ...+. ", " @.#. $.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._. ", " :.<. [.}.|.1.2.3.4.5.5.6.7.8.9.0.a.b.c.d.e. ", " f.g.h. i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A. ", " B.C.D. E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W. ", " X.Y. Z.`. +.+++@+#+H.$+J.%+&+*+=+-+;+>+,+'+ ", " )+!+ ~+{+G.]+$+^+/+(+_+:+<+[+}+|+1+2+3+4+5+ ", " 6+7+8+9+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+ ", " r+s+t+u+v+w+++$+x+y+z+A+B+C+D+E+F+G+H+I+J+K+ ", " L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+`+ @.@+@@@#@ ", " $@%@&@*@=@-@;@;@>@,@'@)@!@~@{@]@^@/@(@_@ ", " :@F+<@[@}@|@1@2@3@4@5@6@7@8@9@0@a@b@c@ ", " d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@ ", " v@w@x@y@z@ A@B@C@D@E@F@ ", " G@H@I@J@K@L@ ", " M@N@O@P@Q@ ", " R@S@T@U@V@ ", " W@X@Y@Z@`@ ", " #.#+#@### ", " $#%#&#*# ", " =#-#;#># ", " ,#'#)# ", " !# ", " ", " "}; packagesearch-2.7.11build1/icons/remove-package.png0000644000000000000000000000300013507430555017061 0ustar PNG  IHDR szzbKGD pHYs  tIME + F/ttEXtCommentCreated with The GIMPd%ndIDATX͗klU;e]ۥZ|bE %" C H4A JRILT$jE !>JY`kJsKQff֤[/Ι9{?V1|w,wk4lOl~/[*wZA"] uOwz+i@ͭfF{42So t%.G\[pTVZ@0eԑ>r\L%$IK,%%UUpU/!Rb@.ϧXIdzx|l17Ū Yͷ-Etr$pƌ!1:ɥ*>:vuѶjq]I#CE&PfdncDRJ1讎>XzMvo_TL < qk}Au -esbn|f}}mnL&C2ѣ;> ά;Rdٍoجl)5z^9v,ʦM̻綷o-^dZM_do}Lڼ2Ƴ~{W,bݷ,GŪkġ?f Oo =9/+jk=̥xz;4cJ*P>y78*.DrPѨ{Z存FFnr65#=W~n_l6Wƀ h@gR897֚%m bD/J;nNYv`gR,IENceBա`nenS 4`<ɉ1q3S<ٵN@z] j~,3S1zH'60+d94$2+qt@i9i?&2,ًֈXJxP)2,ڏݬ]MyP)2+~؍ݬ]MxD(2'C^ڬ]M](#2BzDl5.4ۨBJ>,3R1yG'50+b8<`0Ķw0ݛbW0sQqэugB(s14IgoklW92*M6*/ >4$2+ps@i9i?&2,ًՈWJxP)2,ڎݫ]MyP)2+~؍ݫ]MxD(2'C^ګ]M](#2AzDl5.4إBJ>,3mC1c>$,n0+˞Y51P0κb0qDžQG0qCb|`U6 q1/BadbZH/2!=.%)  6)2"e`3X-]22#|xM:h? 2#~ҕP=i? 2"s}ѕP=h5 2;SΕP=Q 28wi:[*(4"^_acfhiihfca__^!(),1:DKNOONKD:1,))(!  &;Q`giig`Q;&   ! :``; !0^η^1!E۶F' #T̕T# ' %YӜY% ' #UЗU# 'JʼnJ'; chomp($version); print "Did you remember to run dch -v $version and commit the changes? (y/n)?\n"; my $decide = ; if ( $decide =~ /n/ ) { die "aborting"; } my $headmodule = "packagesearch"; # toplevel module my $releaseDir = "../packagesearch-release"; mkdir("$releaseDir"); my $src_filename = "packagesearch_$version.tar.gz"; createSourceTarball(); sub createSourceTarball() { my $targetSourceDir = "$releaseDir/$headmodule-$version"; my $doCheckout = 1; if (-e $targetSourceDir ) { print "There is already a directory $targetSourceDir available, would you like to overwrite this?\n"; my $decide = ; if ( $decide =~ /n/ ) { $doCheckout = 0; } else { system("rm -rf $targetSourceDir"); } } if ($doCheckout) { print "Cloning git version\n"; (system("git clone ./ $targetSourceDir")==0) || die("Could not clone git version.\n"); } print "creating source tarball $src_filename \n"; `rm -rf $targetSourceDir/.git`; (system("GZIP=-9 tar -C $releaseDir -czf $releaseDir/$src_filename $headmodule-$version\n")==0) || die("Could not create archive.\n"); print "source tarball $src_filename created\n"; } packagesearch-2.7.11build1/notes0000644000000000000000000003573113507430555013445 0ustar I am currently pondering, on how to give the user a valid popcon database to use. [19:43] It would require a package popcon-data, which regularly fetches the popcon data and would somehow need to trigger apt-xapian-index [20:38] indeed [20:38] a-x-i can already index popcon [20:39] the only thing to do is to download the data [20:39] uhm, I thought it could index popcon but I can't find the plugin, maybe it was some prototype in libept [20:39] anyway, it's trivial to index popcon in a-x-i [20:40] question is, how (if) popcon-data should invoke axi [20:40] it shouldn't: it should just add a plugin to /usr/share/apt-xapian-index/plugins/ that reads the data and adds it to the indexed documents [20:41] similarly to how /usr/share/apt-xapian-index/plugins/sizes.py does [20:41] Yeah, but then popcon data would only be available after the next cron job has run? [20:42] yes [20:42] Besides, basically this would be two packages: "popcon-data" and "apt-capian-popcon-plugin" [20:42] although popcon-data can run update-apt-xapian-index on its first install [20:42] no, you just do popcon-data which includes a plugin [20:43] I tried to keep things conceptually clean, hence two packages.. [20:43] just like software-center includes some xapian plugins [20:43] well, the plugin would be less than 1kb, no point making a package just for it [20:43] it'd be like packages providing hooks for logcheck, for example [20:43] you don't do apache and apache-logcheck [20:43] ok, sounds about right. Current version of libept: git clone git://git.debian.org/debtags/libept.git [19:56] queries are better being generated by Xapian's QueryParser, which does a better job than libept did [19:56] it'S more like database design.. [19:57] so now there's just an ept::axi namespace with 4 tiny functions to basically tell you where the Xapian database is and when it's last been updated [19:58] you can compare the axi timestamp and the apt timestamp to see if things are fully up to date, if you want [19:59] and if not, you call update-xapian-index -u [19:59] if the index was not generated at all, you can run update-xapian-indxe [20:01] the user runs packagesearch after install, and apt-xapian-index hasn't finished updating the index [20:01] in that case, you can display a "hang on a minute until the index is created" sort of message Xapian-Discussion [20:40] Hi. I am done with ripping out ept::debtags. Is there a faster way to compute companian tags for a given tag-set then to brute force (i.e. calculating the result-set for the tagset ANDed with each available tag and checking if it is empty)? [20:43] definitely doable with xapian, and you get better results, even [20:43] link coming [20:43] http://www.enricozini.org/2007/debtags/axi-query-expand/ [20:43] Better results? There is only one correct result. [20:44] better int hat you get them sorted by relevance [20:44] so you build a query using your tags (and maybe even other keywords, if you like) and then ask for the expand set, filtered to only give you XT terms [20:45] Ok, didn't yet know about expand set and filtering. Thanks. The result is complete? [20:46] I think so, if you pull results until Xapian gives them [20:50] Thanks, I will try it out. Currently I have the brute-forcing, which is still quite fast (approx. 1s). Xapian-Discussion [15:10] you basically use libxapian instead of libept [15:10] which you almost already do [15:11] and with libxapian you get package names in the end, as the "document.get_data()" [15:11] Ok, so I have to learn the xapian stuff. And besides I have to use libapt-pkg right? [15:11] yes. However, if you think ept::Apt is useful, just keep it for now [15:12] I'd like to remove the TextSearch bits from libept because I think they're useless, but I have less of a problem with ept::Apt [15:12] Ok, so first I'll rip of everything except ept::pt? [15:12] yes, that'd be good [15:12] I think ept::apt is the most useful bit [15:13] Are there any examples out there on how to use apt-xapian? [15:13] Perhaps inside libept or so? [15:13] ept::debtags is less useful now with apt-xapian-index, so I'd like at least to get rid of all the debtags custom indexing code [15:13] examples? Sure. http://www.enricozini.org/2007/debtags/apt-xapian-index/ [15:13] from there, every post links to a "next" post [15:14] it uses the python API, but it's very, very similar to the C++ one [15:14] Great, I think I can go from there. [15:14] also, there's a "jibel" in #xapian who's redoing synaptic's quick search function with xapian [15:15] he's worked more with xapian's queryparser and had interesting results, but I don't know the details [15:16] I would also like to take it the other way round - e.g. get the tags for a given package. As far as I understand it now, this is not what xapian is for? [15:16] you can do it with xapian [15:17] but if you don't have the xapian index, you can still do it by loading /var/lib/debtags/package-tags [15:17] I'd really rather stick to libraries... [15:18] to get the tags with xapian, you search for "XPpackagename" and get all the terms starting with "XT" in the resulting document [15:19] but well, for now just get rid of ept::textsearch [15:19] then I'll see if I can get rid of the Debtags custom indexing in libept but still keep the functions to load /var/lib/debtags/package-tags [15:19] Let's see if I am using that one at all.. [15:20] Ok, it is there, shouldn't be much of a problem.. [15:21] uhh, there is some xapian code in there, within a "#if 0" block. You did this some time ago I suppose ;) [15:22] you really can't use ept::textsearch without using xapian things [15:22] basically, in ept::Textsearch I put a kind of queryparser [15:22] but xapian has a better one [15:22] so... [15:23] in fact, ept::textsearch makes matters more complicated, because it introduces a useless layer and one in the end uses xapian anyway [15:23] and the xapian API is, IMHO, really quite nice. Doesn't need extra layers on top [15:42] Do I understand it right, that each package is a document and has some terms assigned to it (e.g. XTrole::program and Zgraphic). Quering happens using those terms and returns a set of package names? [15:51] querying is a boolean expression of those terms, and returns a list of documents sorted by relevance [15:51] "document" is an object from which you can retrieve the indexed terms, as well as the "document data", which is an opaque (to xapian) piece of information, which in case of apt-xapian-index I fill with the package name [15:51] What I meant was the idea of packages being the documents [15:52] "sorted by relevance" is very important: it means you don't have to make exact queries and yhou'll still get good results [15:52] Ok, so I got this right [15:52] for example, for stemming you just build an OR query with the terms and their stemmed forms. The result will be the best match, that is the document that match most OR terms [15:53] so it's quite allright to put all sorts of things in OR, and let Xapian satisfy it the best it can [15:53] I do not like to much hidden logic [15:53] OR queries really are approximate AND queries [15:53] it's not very hidden, really [15:53] its behaviour is predictable and reasonable [15:53] No, but you might not get what you'd expect [15:54] just, it's important (imo) to consider xapian OR queries as approximate AND queries, because it allows you to be more creative [15:54] like, you can OR searches with sets of tags, and still get reasonable results if the description matches well but a tag is missing [15:55] one of the examples in my blog series is first using the terms to look for tags, then add those tags to the proper package query. that way you get packages that make sense even if they don't contain the searched keywords in the description [15:55] (the "gimp is not an image editor" problem) [15:56] Yeah, that's what you did with your smart search [15:56] xapian is fast enough that you can do all that on the fly, as one types [15:57] and, search-as-you-type you can just do it by taking the last, partially typed word, expand it with xapian as a prefix, then OR all the expanded terms [15:57] I think xapian's queryparser does that transparently if you do I don't know what [15:57] I really should study xapian's queryparser better. It does many useful things [16:06] Damn, coding time finished, time to wake up my daugther :) [16:07] have fun :) [16:08] Yeah, thanks for your help [19:55] --- Disconnected (Connection reset by peer). [21:09] Done [21:10] I'll have to rip out the "Whole words only" and "Case sensitive" feature though. Probably they didn't make much sense after all [21:13] And I'll have to tolower() all my search terms [20:14] * Loaded log from Sun Mar 7 21:21:43 2010 [20:14] [20:18] So you will keep the ept::debtags interface? [20:19] I'd like to keep it very, very minimal [20:20] Main classes I am using are Vocabulary and Debtags, what are to you want to change there? [20:20] Vocabulary can stay, but I intend to get rid of the index [20:20] Debtags can stay, but I intend to also get rid of the index and just load /var/lib/debtags/package-tags in memory [20:21] You mean by inedx the int values (ID)? [20:21] yes [20:21] Debtags I'd like it to be bascically a two-way string->set mapping [20:21] Vocabulary, just indexed by facet or tag name [20:22] Ok, in that case I believe there is no need for doing changes in my vocabulary [20:23] s/vocabulary/program( [20:23] cool [20:23] also, it may take me 6 months to get any time to do it [20:23] On the other hand, I could change the search to use Xapian, right? [20:23] so a good stategy is also use libept for squeeze as it is, and postpone thinking about it after squeeze [20:24] you could change the search to use xapian indeed [20:24] which is the best bet if you can still work (maybe without debtags) if xapian isn't there [20:24] This way I would only depend on vocabulary and I would use a common search mechanism... [20:24] exactly [20:24] I've added a depend on xapian [20:25] I am also exiting packagesearch when the index is not present [20:25] ... don't like to many ifs.. [20:25] ok. which makes sense, because packagesearch is not indended for embedded which are pretty much the only platforms where a-x-i is too heavy to make sense [20:26] even aptitude's too heavy for my freerunner, to give an idea [20:26] No, the GUI is to large for embedded ;) [20:28] Great, I think I will try Xapian. Using the combined search means merging the search strings of both the apt and the debtags plugins in the central application... Just some implementation thoughts ;) [20:33] Does every Debian system has the debtags database available or does this depend on debtags? [20:36] And does the apt-xapian system accesses all sources listed in /etc/debtags/sources.list or only those from the package database? [20:36] it depends on debtags [20:37] apt-xapian gets data from the package database [20:37] or whatever is pulled by its plugins [20:37] but so far only the package database [20:37] Ok, so if you have no debtags installed, you won't have a vocabulary, but the package tags from the database, right? [20:56] which will also mean, that when I display the vocabulary and someone has added custom sources, the search results will be wrong, because the additional sources are not considered by xapian :( [22:05] with no debtags, you'll have the tags from the Packages file, but no vocabulary, yes [22:05] xapian considers all the package sources, though, because apt merges all of them in a single Packages file [22:06] update-apt-xapian-index' plugins simply iterate the package database with apt [22:06] Yeah, but not the debtags sources [22:06] I am totally getting rid of ept::Debtags now, because otherwise I will work with inconsistent data sets. Xapian discussion [12:38] enrico: Actually that being an index search, it is quite logical. [12:38] bmesing: it has upsides and downsides: you can search for "mc" easily, but you have a problem searching for foo in libfoo [12:38] Probably some kind of tree structure. [12:39] bmesing: I'm exploring the idea of a debian-specific stemmer that would handle cases like libfoo, but I haven't found a decent solution on how to make the stemmer code usable from all sorts of laguuages [12:39] I have to do some testing on the performance gain, if it is worth keeping it in. [12:39] programming lancuages, that is [12:39] bmesing: synaptics in experimental has apt-xapian-index search-as-you-type support [12:40] enrico: That's cool. [12:40] bmesing: if you see apt-xapian-index, you should consider using it for searhc-as-you-type [12:40] bmesing: and for suggesting keywords and tags, possible also while doing search-as-you-type (it's performing enough for that) [12:40] link coming... [12:41] http://www.enricozini.org/2007/debtags/axi-searchasyoutype.html [12:41] http://www.enricozini.org/2007/debtags/axi-query-expand.html [12:41] bmesing: ^ you can gdb it and set a breakpoint on __cxa_throw, to see where the exception is actually thrown "break __cxa_throw" # to generate the release version use "CONFIG += my_release" as arguemnt for qmake on # the command line - this was neccessary because "release" is declared # by default - so it must be removed manually using "CONFIG -= release" # however using kdevelop this is not possible so I've created this workaround libtagcoll tagcoll Vocabulary - can read the tag database including the implications and description, it maps the tags to the associated data Open questions for libapt-front How to update the database? - is it simply aptFront::cache::Cache.reopen()? - will anybody be notified? - what are the observers observing? - what does aptFront::cache::component::Packages::packageByName return if there is no such package? getCompanionTags : shouldn't it contain the tag itself?packagesearch-2.7.11build1/packagesearch.desktop0000644000000000000000000000034413507430555016536 0ustar [Desktop Entry] Version=1.0 Encoding=UTF-8 Name=Debian Package Search Comment=Search for packages and view package information Exec=packagesearch Icon=packagesearch Type=Application Categories=PackageManager;System;Settings;Qt; packagesearch-2.7.11build1/packagesearch.kdev40000644000000000000000000000007313507430555016101 0ustar [Project] Manager=KDevCustomMakeManager Name=packagesearch packagesearch-2.7.11build1/src/0000755000000000000000000000000013507430555013150 5ustar packagesearch-2.7.11build1/src/.kdev4/0000755000000000000000000000000013507430555014243 5ustar packagesearch-2.7.11build1/src/.kdev4/packagesearch.kdevelop0000644000000000000000000000046213507430555020561 0ustar [Buildset] BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00,\x00p\x00a\x00c\x00k\x00a\x00g\x00e\x00s\x00e\x00a\x00r\x00c\x00h\x00.\x00k\x00d\x00e\x00v\x00e\x00l\x00o\x00p) [MakeBuilder] Number Of Jobs=2 [Project] VersionControlSupport=kdevsubversion packagesearch-2.7.11build1/src/.kdev4/src.kdev40000644000000000000000000000127113507430555015772 0ustar [Buildset] BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00s\x00r\x00c) [Launch] Launch Configurations=Launch Configuration 0 [Launch][Launch Configuration 0] Configured Launch Modes=execute Configured Launchers=nativeAppLauncher Name=New Native Application Configuration Type=Native Application [Launch][Launch Configuration 0][Data] Arguments= Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x00) Dependency Action=Nothing EnvironmentGroup=default Executable=file:///home/ben/packagesearch/src/packagesearch Working Directory= isExecutable=true [MakeBuilder] Number Of Jobs=2 [Project] VersionControlSupport=kdevsubversion packagesearch-2.7.11build1/src/.kdev_include_paths0000644000000000000000000000016513507430555017006 0ustar /usr/include/qt4/Qt /usr/include/qt4/QtCore /usr/include/qt4/QtXml /usr/include/qt4/QtGui /usr/include/qt4/QtNetwork packagesearch-2.7.11build1/src/.moc/0000755000000000000000000000000013507430555014004 5ustar packagesearch-2.7.11build1/src/.obj/0000755000000000000000000000000013507430555014000 5ustar packagesearch-2.7.11build1/src/.ui/0000755000000000000000000000000013507430555013643 5ustar packagesearch-2.7.11build1/src/Doxyfile0000644000000000000000000002020113507430555014651 0ustar # Doxyfile 1.3.6-20040222 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = "Debian Package Search" PROJECT_NUMBER = OUTPUT_DIRECTORY = /home/ben/lang/c++/packagesearch/doc/ OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = YES TAB_SIZE = 3 ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = /home/ben/lang/c++/packagesearch/src/plugins/aptplugin/ \ /home/ben/lang/c++/packagesearch/src/plugins/debtagsplugin/ \ /home/ben/lang/c++/packagesearch/src/plugins/filenameplugin/ \ /home/ben/lang/c++/packagesearch/src/ FILE_PATTERNS = RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = __USE_KDE_LIBS EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 0 GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO packagesearch-2.7.11build1/src/action.cpp0000644000000000000000000000063013507430555015130 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Wed Aug 31 2005 at 10:43:44 // #include namespace NPlugin { Action::Action(QAction* pAction, bool packageAction, QString menu, QString toolBar) { _pAction = pAction; _packageAction = packageAction; _menu = menu; _toolBar = toolBar; } } packagesearch-2.7.11build1/src/action.h0000644000000000000000000000457613507430555014612 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Wed Aug 31 2005 at 10:43:44 // #ifndef __NPLUGIN_ACTION_H_2005_08_31 #define __NPLUGIN_ACTION_H_2005_08_31 #include #include class QAction; /** * Namespace */ namespace NPlugin { /** @brief Class that holds a QAction object and some details about it. * * The details are the #_menu and #_toolBar where the action should be added to, * and if it is this action acts on selected packages (#_packageAction). * * The QAction object will not be deleted by this class. Normally it should be * autodeleted by its parent object. Otherwise, you have to delete it manually. */ class Action { public: Action(QAction* pAction, bool packageAction=false, QString menu="", QString toolBar=""); /** @brief Returns the QAction object used for this action. */ QAction* action () const { return _pAction; } /** @brief Sets the QAction object used for this action. */ void setAction (QAction* value ) { _pAction = value; } /** @brief Returns the #_menu property. */ QString menu() const { return _menu; } /** @brief Sets the _menu property. */ void setMenu (QString value ) { _menu = value; } /** @brief Returns the #_toolBar property. */ QString toolBar() const { return _toolBar; } /** @brief Sets the #_toolBar property. */ void setToolBar(QString value ) { _toolBar = value; } /** @brief Returns the #_packageAction property. */ bool packageAction() const { return _packageAction; } /** @brief Sets the #_packageAction property. */ void setPackageAction (bool value ) { _packageAction = value; } private: /** @brief Holds which menu this action belongs to. * * If it is empty, the action will be added to no menu. * * Default: empty */ QString _menu; /** @brief Holds which toolBar this action should be added to. * * If it is empty, the action will not be added to a toolBar. * * Default: empty */ QString _toolBar; /** @brief Holds if this action is performed to packages. * * Setting this to true, results in the action being disabled if * no package is selected. * * Default: false */ bool _packageAction; /** @brief The QAction for this action. */ QAction* _pAction; }; } #endif // __NPLUGIN_ACTION_H_2005_08_31 packagesearch-2.7.11build1/src/actionplugin.cpp0000644000000000000000000000045413507430555016353 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Wed Aug 31 2005 at 10:43:44 // #include "string" #include "plugin.h" #include "action.h" /** * Constructors/Destructors */ /** * Methods */ packagesearch-2.7.11build1/src/actionplugin.h0000644000000000000000000000112313507430555016012 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Wed Aug 31 2005 at 10:43:44 // #ifndef __NPLUGIN_ACTIONPLUGIN_H_2005_08_31 #define __NPLUGIN_ACTIONPLUGIN_H_2005_08_31 #include // NPlugin #include "plugin.h" #include "action.h" using namespace std; namespace NPlugin { class ActionPlugin : public Plugin { public: /** @brief Returns the Actions offered by this plugin. */ virtual vector actions() const = 0; }; } #endif // __NPLUGIN_ACTIONPLUGIN_H_2005_08_31 packagesearch-2.7.11build1/src/applicationfactory.cpp0000644000000000000000000000157513507430555017557 0ustar // // C++ Implementation: applicationfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "applicationfactory.h" #ifdef __USE_KDE_LIBS #include "runcommandinwindow.h" #else #include "runcommandinxterm.h" #endif namespace NApplication { ApplicationFactory* ApplicationFactory::_pFactory = new ApplicationFactory(); ApplicationFactory::ApplicationFactory() { } ApplicationFactory::~ApplicationFactory() { } RunCommand* ApplicationFactory::getRunCommand(const QString& name) { #ifdef __USE_KDE_LIBS return new RunCommandInWindow(0, name); #else return new RunCommandInXterm(); #endif } ApplicationFactory* ApplicationFactory::getInstance() { return _pFactory; } void ApplicationFactory::setInstance(ApplicationFactory* pFactory) { _pFactory = pFactory; } }; packagesearch-2.7.11build1/src/applicationfactory.h0000644000000000000000000000300313507430555017210 0ustar // // C++ Interface: applicationfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __APPLICATIONFACTORY_H_2004_05_13 #define __APPLICATIONFACTORY_H_2004_05_13 #include #include "gainroot.h" namespace NApplication { class RunCommand; /** @brief Factory class responsible for creating run commands. * * This class is a Singleton, though it allows subclasses to be defined. * * By default the factory will create RunCommandInXterm instances. * @author Benjamin Mesing */ class ApplicationFactory { static ApplicationFactory* _pFactory; protected: ApplicationFactory(); public: virtual ~ApplicationFactory(); /** @brief Returns the global application factory. */ static ApplicationFactory* getInstance(); /** @brief Sets the global application factory. */ static void setInstance(ApplicationFactory* pFactory); /** @brief Returns an instance of RunCommand, created by new. * * The exact type of this instance depends on the implentation of this * function, so it is determinded at compile time. It is your responsibility * to delete the command created by this function. * @param name this is used to give the created instance a name, * if naming is supported by the implementing RunCommand. This name is * only internal (e.g. a QObject name). */ virtual RunCommand* getRunCommand(const QString& name); }; }; #endif // __APPLICATIONFACTORY_H_2004_05_13 packagesearch-2.7.11build1/src/baseplugincontainer.cpp0000644000000000000000000001137413507430555017716 0ustar #include "baseplugincontainer.h" #include #include "plugin.h" #include "iprovider.h" #include "ipluginfactory.h" #include "helpers.h" namespace NPlugin { BasePluginContainer::~BasePluginContainer() { } void BasePluginContainer::unloadAllPlugins() { for (PluginMap::iterator it = _plugins.begin(); it != _plugins.end(); ++it) { if (it->second != 0) _pluginInformer.informRemovePlugin(it->second); } // delete the plugins only, after everyone was informed about all remoals, because // there may be interdependencies between the plugins (one plugin using the other) // that might otherwise still be used for (PluginMap::iterator it = _plugins.begin(); it != _plugins.end(); ++it) { delete it->second; } } ///////////////////////////////////////////////////// // PluginContainer Interface ///////////////////////////////////////////////////// bool BasePluginContainer::init(IProvider* pProvider, IPluginFactory* pFactory) { _pFactory = pFactory; _pProvider = pProvider; return true; } Plugin* BasePluginContainer::requestPlugin(const string& name) { if (_pProvider==0 || _pFactory==0) { cerr << "Programming error: Requesting plugin while (_pProvider==0 || _pFactory==0) " << " please file a bug report." << endl; return 0; } // find the entry for the plugin with this name PluginMap::iterator it = _plugins.find(name); if (it == _plugins.end()) return 0; Plugin* pPlugin = it->second; if (!pPlugin) { pPlugin = _pFactory->createPlugin(name); if (pPlugin == 0) qDebug("Warning, plugin %s could not be created", name.c_str()); it->second = pPlugin; } else return pPlugin; if (pPlugin) { pPlugin->init(_pProvider); _pluginInformer.informAddPlugin(pPlugin); } return pPlugin; } void BasePluginContainer::releasePlugin(Plugin* pPlugin) { // find the plugin in the _plugins map PluginMap::iterator it = _plugins.begin(); while (it != _plugins.end() && it->second != pPlugin) ++it; if (it == _plugins.end()) return; _pluginInformer.informRemovePlugin(pPlugin); it->second = 0; delete pPlugin; } vector BasePluginContainer::getLoadedPlugins() const { vector result; for (PluginMap::const_iterator it = _plugins.begin(); it != _plugins.end(); ++it) { if (it->second != 0) result.push_back(it->second); } return result; } ///////////////////////////////////////////////////// // IXmlStorable Interface ///////////////////////////////////////////////////// QDomElement BasePluginContainer::loadSettings(const QDomElement source) { // if the settings are not for this node if (source.tagName() != toQString(name())) return source; float settingsVersion; NXml::getAttribute(source, settingsVersion, "settingsVersion", 0.0); // for old settings treat the element as we used to if (settingsVersion < 0.1) { return loadContainerSettings(source); } QDomElement pluginContainerElement = NXml::getFirstElement(source.firstChild()); QDomElement singlePluginElement = loadContainerSettings(pluginContainerElement); // iterate over all SinglePlugin entries and load them while (!singlePluginElement.isNull()) { QString pluginName; NXml::getAttribute(singlePluginElement, pluginName, "name", ""); // qStrDebug("Loaded settings"); if (_plugins.find(toString(pluginName)) != _plugins.end()) { Plugin* pPlugin = _plugins[toString(pluginName)]; pPlugin->loadSettings( NXml::getFirstElement(singlePluginElement.firstChild()) ); } else { qStrWarning("found unknown settings entry"); } singlePluginElement = NXml::getNextElement(singlePluginElement); } return NXml::getNextElement(source); } void BasePluginContainer::saveSettings(NXml::XmlData& outData, QDomElement parent) const { QDomElement pluginContainerElement = outData.addElement(parent, toQString(name())); outData.addAttribute(pluginContainerElement, 0.1f, "settingsVersion"); saveContainerSettings(outData, pluginContainerElement); vector plugins = getLoadedPlugins(); for (vector::iterator it = plugins.begin(); it != plugins.end(); ++it) { Plugin* pPlugin = *it; QDomElement singlePluginElement = outData.addElement(pluginContainerElement, "SinglePlugin"); outData.addAttribute(singlePluginElement, pPlugin->name(), "name"); pPlugin->saveSettings(outData, singlePluginElement); } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// QDomElement BasePluginContainer::loadContainerSettings(const QDomElement source) { return source; } void BasePluginContainer::saveContainerSettings(NXml::XmlData&, QDomElement) const { } void BasePluginContainer::addPlugin(const string& name) { _plugins[name] = 0; _pluginNames.push_back(name); } } // namespace NPlugin packagesearch-2.7.11build1/src/baseplugincontainer.h0000644000000000000000000001240513507430555017357 0ustar #ifndef __BASEPLUGINCONTAINER_H_2004_09_08 #define __BASEPLUGINCONTAINER_H_2004_09_08 #include #include #include #include "plugincontainer.h" #include "plugininformer.h" using namespace std; namespace NPlugin { class IPluginFactory; class IProvider; /** Call init() before using the requestPlugin() function. */ class BasePluginContainer : public PluginContainer { typedef map PluginMap; /** @brief This maps the plugin names to the corresponding plugins. * * If the plugin is not already loaded it maps to 0.*/ PluginMap _plugins; /** @brief This holds the names of all plugins offered. * * This equals keys(_plugins) and is only used for convenience. */ vector _pluginNames; /** The factory which is used to create the plugins. */ IPluginFactory* _pFactory; /** The provider to be used. */ IProvider* _pProvider; protected: /** This informer used to inform plugin users about changes in the plugins. */ PluginInformer _pluginInformer; /** @brief This adds a new plugin type to the available ones. * * It should be supported by the plugin factory used. The pointer will * be set to 0.\n * @pre No plugin with this name must have been added before. */ void addPlugin(const string& name); /** Returns #_pFactory. */ IPluginFactory* pluginFactory() const { return _pFactory; } /** Returns #_pProvider. */ IProvider* provider() const { return _pProvider; } /** @brief This deletes all plugins owned by this container. * * The plugin users will be informed about the remove. */ void unloadAllPlugins(); public: /** @brief Constructs a PluginContainer which uses the given factory to create * the plugins. * * Call init() before using the requestPlugin() function. */ BasePluginContainer() {} virtual ~BasePluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ // documented in base class virtual Plugin* requestPlugin(const string& name); // documented in base class virtual void releasePlugin(Plugin* pPlugin); // documented in base class virtual vector getLoadedPlugins() const; // documented in base class virtual vector offeredPlugins() const { return _pluginNames; } /** @brief This makes the plugin container ready for use. * * @param pProvider sets #_pProvider * @param pFactory sets #_pFactory */ virtual bool init(IProvider* pProvider, IPluginFactory* pFactory); /** @brief Default implementation for actions, returning an empty list. */ vector< pair > actions() { return vector< pair >(); }; //@} /** @name IXmlStorable interface * * Implementation of the IXmlStorable interface. * * Both functions do nothing in the default implementation. */ //@{ /** @brief Save the data for this object into the given XML tree. * * The implementation for this creates a new element beneath parent with the * name name(NXml::XmlData&, QDomElement). Afterwards it calls * saveContainerSettigns(NXml::XmlData&, QDomElement) with the created element * as parent. Finally it creates a <SinglePlugin> element for each * loaded plugin. An attribute "name" is added for each <SinglePlugin> element * with the value of the plugins name (Plugin::name()) and saves each plugin in * this element via the Plugin::saveSettings() function. * * @see IXmlStorable::saveSettings() for details how to save. */ virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; /** @brief Loads the data for this object from the given XML node. * * The implementation for this creates a new element beneath parent with the * name name(NXml::XmlData&, QDomElement). Afterwards it calls * saveContainerSettings(NXml::XmlData&, QDomElement) with the created element * as parent. Finally it creates a <SinglePlugin> element for each * loaded plugin. An attribute "name" is added for each <SinglePlugin> element * with the value of the plugins name (Plugin::name()) and saves each plugin in * this element via the Plugin::saveSettings() function. * * @see IXmlStorable::saveSettings() for details how to save. */ virtual QDomElement loadSettings(const QDomElement source); //@} /** @brief Saves the settings for the whole container here. * * Overload this function to save settings affecting the container, * individual settings for each plugin are saved in the saveSettigns(NXml::XmlData&, QDomElement). */ virtual void saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const; /** @brief Load the settings for the whole container here. * * Overload this function to load settings affecting the container, * individual settings for each plugin are loaded in the loadSettigns(const QDomElement). */ virtual QDomElement loadContainerSettings(const QDomElement source); /** @name IPluginInformer interface * * Implementation of the IPluginInformer interface. */ //@{ virtual void addPluginUser(IPluginUser* pUser) { _pluginInformer.addPluginUser(pUser); } virtual void removePluginUser(IPluginUser* pUser) { _pluginInformer.removePluginUser(pUser); }; //@} }; } // namespace NPlugin #endif // __BASEPLUGINCONTAINER_H_2004_09_08 packagesearch-2.7.11build1/src/code-templates/0000755000000000000000000000000013507430555016056 5ustar packagesearch-2.7.11build1/src/code-templates/heading.cpp0000644000000000000000000000025513507430555020163 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on %date% at %time% // packagesearch-2.7.11build1/src/code-templates/heading.h0000644000000000000000000000025513507430555017630 0ustar // // Author: Benjamin Mesing // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on %date% at %time% // packagesearch-2.7.11build1/src/columncontroldlg.cpp0000644000000000000000000000277013507430555017247 0ustar // // C++ Implementation: columncontrol // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "columncontroldlg.h" ColumnControlDlg::ColumnControlDlg(QWidget* parent) : QDialog(parent) { setupUi(this); } ColumnControlDlg::~ColumnControlDlg() { } void ColumnControlDlg::setContent(const QStringList & shown, const QStringList & hidden) { _pShownList->addItems(shown); _pHiddenList->addItems(hidden); } QStringList ColumnControlDlg::shownColumns() { QStringList result; for (int i=0; i<_pShownList->count(); ++i) result.push_back(_pShownList->item(i)->text()); return result; } QStringList ColumnControlDlg::hiddenColumns() { QStringList result; for (int i=0; i<_pHiddenList->count(); ++i) result.push_back(_pHiddenList->item(i)->text()); return result; } void ColumnControlDlg::on__pHideButton_clicked() { if (_pShownList->selectedItems().size() == 0) return; QListWidgetItem* pItem = _pShownList->selectedItems().first(); int row = _pShownList->row(pItem); pItem = _pShownList->takeItem(row); _pHiddenList->insertItem(_pHiddenList->count(), pItem); } void ColumnControlDlg::on__pShowButton_clicked() { if (_pHiddenList->selectedItems().size() == 0) return; QListWidgetItem* pItem = _pHiddenList->selectedItems().first(); int row = _pHiddenList->row(pItem); pItem = _pHiddenList->takeItem(row); _pShownList->insertItem(_pShownList->count(), pItem); } packagesearch-2.7.11build1/src/columncontroldlg.h0000644000000000000000000000143113507430555016705 0ustar // // C++ Interface: columncontrol // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __COLUMNCONTROLDLG_H_2004_08_24 #define __COLUMNCONTROLDLG_H_2004_08_24 #include "ui_columncontroldlg.h" #include /** Implementing Ui::ColumnControl @author Benjamin Mesing */ class ColumnControlDlg : public QDialog, Ui::ColumnControlDlg { Q_OBJECT public: ColumnControlDlg(QWidget* parent=0); ~ColumnControlDlg(); void setContent(const QStringList & shown, const QStringList & hidden); QStringList shownColumns(); QStringList hiddenColumns(); protected slots: void on__pHideButton_clicked(); void on__pShowButton_clicked(); }; #endif // __COLUMNCONTROLDLG_H_2004_08_24 packagesearch-2.7.11build1/src/columncontroldlg.ui0000644000000000000000000001474513507430555017107 0ustar ColumnControlDlg 0 0 476 356 Control Columns 6 10 10 10 10 6 0 0 0 0 6 0 0 0 0 0 0 Shown 6 0 0 0 0 0 0 >> << 6 0 0 0 0 0 0 Hidden 6 0 0 0 0 Qt::Horizontal QSizePolicy::Expanding 141 20 &OK Alt+O &Cancel Alt+C qPixmapFromMimeSource _pHideButton _pShowButton _pOkButton _pCancelButton _pOkButton clicked() ColumnControlDlg accept() 322 327 267 350 _pCancelButton clicked() ColumnControlDlg reject() 437 322 474 334 packagesearch-2.7.11build1/src/configure0000755000000000000000000000366313507430555015067 0ustar #!/usr/bin/perl -w $usage = "usage: configure [--help] [--exclude-kdelibs]\n"; sub evaluateArguments() { $help = 0; $excludeKde = 0; foreach(@ARGV) { if ($_ eq "--help") { $help = 1; } elsif ($_ eq "--exclude-kdelibs") { $excludeKde = 1; } else # not one of the keywords { print $usage; exit (1); } } } evaluateArguments(); if ($help) { print "configure [--exclude-kdelibs]\n"; print "\t--exclude-kdelibs - use this flag to compile without using the kde library\n"; print "\t some nifty features like debtags update might be implemented\n"; print "\t in a bad way"; exit(0); } my $additionalOptions; if ($excludeKde) { $additionalOptions .= "\"USE_KDE_LIBS=false\""; } else { $additionalOptions .= "\"USE_KDE_LIBS=true\""; } system("qmake \"CONFIG+=release\" $additionalOptions packagesearch.pro"); # print "Do you want to download the debtags database which is needed to "; # print "run Debian Package Seach now? You need to be online to do this "; # print "and need the debtags tool (apt-get install debtags).\n"; # print "If you say no, you will be able to build the packagesearch utility, "; # print "but will get an error starting it. You can allways download (or "; # print "update) it manually using 'debtags update'.\n"; print "You have to download the debtags database which is needed to "; print "run Debian Package Seach. You "; print "need the program debtags (apt-get install debtags) for this.\n"; print "Get the database e.g. while packagesearch is compiling using "; print "'debtags update'.\n"; # $decide = ""; # while ( ($decide ne "y") && ($decide ne "n")) # { # print "\nDownload it now (y/n) (you will have to become root to do this.)\n"; # print "If unsure say y.\n"; # $decide = ; # chomp($decide); # # read( STDIN,$decide); # $decide = lc($decide); # } # print ("OK, getting package database."); # system("debtags update") if ($decide eq "y"); packagesearch-2.7.11build1/src/count_lines.sh0000755000000000000000000000011313507430555016024 0ustar wc -l *.cpp *.h plugins/{debtagsplugin,aptplugin,filenameplugin}/*.{cpp,h} packagesearch-2.7.11build1/src/exception.cpp0000644000000000000000000000045613507430555015657 0ustar // // C++ Implementation: exception // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "exception.h" namespace NException { Exception::Exception() { } Exception::~Exception() { } }; packagesearch-2.7.11build1/src/exception.h0000644000000000000000000000257413507430555015327 0ustar // // C++ Interface: exception // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __EXCEPTION_H_2004_06_15 #define __EXCEPTION_H_2004_06_15 #include using namespace std; namespace NException { /** Base class for custom exceptions. * * @author Benjamin Mesing */ class Exception{ public: Exception(); virtual ~Exception(); /** @returns a string descibing the problem. */ virtual string description() const =0; }; /** Class that stores the error message in a simple string. * * @author Benjamin Mesing */ class SimpleString : virtual public Exception { string _description; public: /** Create an exception containing a simple string. */ SimpleString(const string& description) { _description = description; } virtual string description() const { return _description; } }; /** @brief Errors which result from wrong code - which are not caused by user interaction. */ class ProgrammerException : virtual public SimpleString { public: ProgrammerException(const string& description) : SimpleString(description) {} }; /** @brief Errors which result from user interaction. */ class RuntimeException : virtual public SimpleString { public: RuntimeException(const string& description) : SimpleString(description) {} }; }; #endif // __EXCEPTION_H_2004_06_15 packagesearch-2.7.11build1/src/extalgorithm.cpp0000644000000000000000000000030313507430555016357 0ustar // // C++ Implementation: extalgorithm // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // packagesearch-2.7.11build1/src/extalgorithm.h0000644000000000000000000000502713507430555016034 0ustar // // C++ Interface: extalgorithm // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __EXTALGORITHM_2004_06_22 #define __EXTALGORITHM_2004_06_22 #include #include namespace NExtStd { /** * @brief Apply a function to every element of a sequence. * @param __first An input iterator. * @param __last An input iterator. * @param __f A unary method function object. * @param o the class the method should be called for * @return @p f. * * Applies the function object @p f to each element in the range * @p [first,last). @p f must not modify the order of the sequence. * If @p f has a return value it is ignored. * @note this function is based on the GNU libcpp foreach function. */ template _Function for_each_ref(_InputIter __first, _InputIter __last, _Function __f, Object& o) { // concept requirements // __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) for ( ; __first != __last; ++__first) (o.*__f)(*__first); return __f; } template _Function for_each(_InputIter __first, _InputIter __last, _Function __f, Object* o) { // concept requirements // __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) for ( ; __first != __last; ++__first) (o->*__f)(*__first); return __f; } /** Copy algorithm as taken from Stroustrup2000 (Fourth Edition) page 566 (german translation) */ template Out copy_if(In anf, In end, Out res, Pred p) { while (anf!=end) { if (p(*anf)) *res++ = *anf; ++anf; } return res; } } // namespace NExtStd namespace std // add some neccessary partial specilisations { /** Partial specialisation allowing handing parameters by reference. * * See: Adapters and Binders - Overcoming problems in the design and implementation of the C++-STL * Volker Simonis1 * Universitt Tbingen * @author Volker Simonis1 * Copyright 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds. * Copyright 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney. */ template struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }; } // namespace std #endif // __EXTALGORITHM_2004_06_22 packagesearch-2.7.11build1/src/fix_umbrello_generated.pl0000755000000000000000000000355213507430555020222 0ustar #!/usr/bin/perl -w # this script fixes the include guards for umbrello generated files # enter the files to process as input, a backup will be save under filename~ sub fixMacro; sub fixVirtual; fixVirtual(); fixMacro(); exit 0; sub fixVirtual { foreach $filename (@ARGV) { if ($filename =~ /\.h$/) # if we have a header file { print "Processing file $filename\n"; open( FILE, $filename); @lines = ; `cp $filename $filename.0~`; close( FILE ); open(FILE, ">$filename"); # overwrite the exiting file foreach $line (@lines) { if ( $line !~ /^\s*virtual/) # if the line doesn't declare a virtual function { $line =~ s/\t \*/\t \*/; # fix doxygen comments $line =~ s/(\w) \(/$1\(/; # remove space before braces if ( $line =~ /(\s*)(.*)=\s*0(.*)/ ) # but we have an = 0 anywhere { $line =~ s/(\s*)(.*)/$1virtual $2/; # insert a virtual before the first nonspace $line =~ s/ / /; # remove double spaces as I don't like them } } print FILE $line; # print $line; } print "\n--------------\n\n"; } } } sub fixMacro { foreach $filename (@ARGV) { if ($filename =~ /\.h$/) # if we have a header file { print "Processing file $filename\n"; open( FILE, $filename); @lines = ; `cp $filename $filename.1~`; close( FILE ); open(FILE, ">$filename"); # overwrite the exiting file $datestring = "2004_06_23"; foreach $line (@lines) { if ( $line =~ /#/ ) { if ($line =~ /#ifndef.*_H$/) { $line =~ s/(#ifndef\s*)(.*_H)$/$1__$2_$datestring/; } elsif ($line =~ /#define.*_H$/) { $line =~ s/(#define\s*)(.*_H)$/$1__$2_$datestring/; } elsif ($line =~ /#endif.*_H$/) { $line =~ s/(#endif)\s*\/\/(.*_H)$/$1\t\/\/ __$2_$datestring/; } } print FILE $line; } print "\n--------------\n\n"; } } }packagesearch-2.7.11build1/src/fixinclude.pl0000755000000000000000000000337513507430555015652 0ustar #!/usr/bin/perl -w # this script fixes the include guards for umbrello generated files # enter the files to process as input, a backup will be save under filename~ sub fixMacro; sub fixVirtual; fixVirtual(); exit 0; sub fixVirtual { foreach $filename (@ARGV) { if ($filename =~ /\.h$/) # if we have a header file { print "Processing file $filename\n"; open( FILE, $filename); @lines = ; `cp $filename $filename~`; close( FILE ); open(FILE, ">$filename"); # overwrite the exiting file foreach $line (@lines) { if ( $line !~ /^\s*virtual/) # if the line doesn't declare a virtual function { $line =~ s/\t \*/\t \*/; # fix doxygen comments if ( $line =~ /(\s*)(.*)=\s*0(.*)/ ) # but we have an = 0 anywhere { $line =~ s/(\s*)(.*)/$1virtual $2/; # insert a virtual before the first nonspace $line =~ s/ / /; # remove double spaces as I don't like them } } print FILE $line; # print $line; } print "\n--------------\n\n"; } } } sub fixMacro; { foreach $filename (@ARGV) { if ($filename =~ /\.h$/) # if we have a header file { print "Processing file $filename\n"; open( FILE, $filename); @lines = ; `cp $filename $filename~`; close( FILE ); open(FILE, ">$filename"); # overwrite the exiting file foreach $line (@lines) { if ( $line =~ /#/ ) { if ($line =~ /#ifndef.*_H$/) { $line =~ s/(#ifndef\s*)(.*_H)$/$1__$2_2004_06_21/; } elsif ($line =~ /#define.*_H$/) { $line =~ s/(#define\s*)(.*_H)$/$1__$2_2004_06_21/; } elsif ($line =~ /#endif.*_H$/) { $line =~ s/(#endif)\s*\/\/(.*_H)$/$1 \/\/\t__$2_2004_06_21/; } } print FILE $line; } print "\n--------------\n\n"; } } }packagesearch-2.7.11build1/src/gainroot.cpp0000644000000000000000000000054413507430555015501 0ustar // // C++ Implementation: gainroot // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "gainroot.h" namespace NApplication { QString GainRootPaths::su = "/bin/su"; QString GainRootPaths::sudo = "/usr/bin/sudo"; } // namespace NApplication packagesearch-2.7.11build1/src/gainroot.h0000644000000000000000000000070413507430555015144 0ustar // // C++ Interface: gainroot // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __GAINROOT_20080719 #define __GAINROOT_20080719 #include namespace NApplication { enum GainRoot { SU, SUDO }; struct GainRootPaths { static QString su; static QString sudo; }; } // namespace NApplication #endif // __GAINROOT_20080719 packagesearch-2.7.11build1/src/globals.h0000644000000000000000000000063313507430555014746 0ustar // // C++ Interface: globals // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPACKAGESEARCH_GLOBALS_H_2005_09_30 #define __NPACKAGESEARCH_GLOBALS_H_2005_09_30 #include namespace NPackageSearch { const QString VERSION("2.7.11"); } #endif // __NPACKAGESEARCH_GLOBALS_H_2005_09_30 packagesearch-2.7.11build1/src/helpers.h0000644000000000000000000000503113507430555014762 0ustar // // C++ Interface: helpers // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __HELPERS_H_2004_06_23 #define __HELPERS_H_2004_06_23 #include #include // for tolower #include #include #undef slots #include #include #include /** Gets the Document for the given package. * * @returns as first argument a boolean indicating if the package was found and the document * itself as second argument */ inline std::pair documentForPackage(const std::string& package, const Xapian::Database& xapian) { Xapian::Enquire enq(xapian); Xapian::Query queryPackage(std::string("XP")+package); enq.set_query(queryPackage); Xapian::MSet packageMatch = enq.get_mset(0, 1); if (packageMatch.size()==0) { return std::make_pair(false, Xapian::Document()); } return std::make_pair(true, packageMatch.begin().get_document()); } /** Converts the given string to a QString. This should mean no more overhead than * doing it manually. */ inline QString toQString(const std::string& str) { return QString::fromStdString(str); } inline QString& toQString(QString& str) { return str; } inline std::string toString(const QString& str) { // return str.operator std::string(); return std::string(str.toLatin1()); } /** Avoid accidental conversions like toString(str) where str already is a std::string */ inline std::string& toString(std::string& str) { return str; } inline int myToLower(int a) { return tolower(a); } inline void qStrDebug(const QString& string) { qDebug("%s", string.toLatin1().data()); } inline void qStrWarning(const QString& string) { qWarning("%s", string.toLatin1().data()); } /** @brief Makes the given string lower case - modifies the handed string. * @returns a reference to the transformed string (which is the one handed). */ inline std::string& makeLower(std::string& trans) { std::transform(trans.begin(), trans.end(), trans.begin(), myToLower); return trans; } /** Creates a string that differs from the given one only in being lower case. */ inline std::string toLower(const std::string& in) { using namespace std; string result; std::transform(in.begin(), in.end(), back_inserter(result), myToLower); return result; } /** Operator for outputting QStrings. */ inline std::ostream& operator<< (std::ostream& out, const QString& str) { out << str.toLatin1().data(); return out; } #endif // __HELPERS_H_2004_06_23 packagesearch-2.7.11build1/src/history.cpp0000644000000000000000000000035713507430555015362 0ustar // // C++ Implementation: history // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "history.h" namespace NBrowser { }; packagesearch-2.7.11build1/src/history.h0000644000000000000000000000440213507430555015022 0ustar // // C++ Interface: history // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __HISTORY_H_2004_04_18 #define __HISTORY_H_2004_04_18 #include using namespace std; namespace NBrowser { /** The history is characterized by a list of entries and a current position. In this it is similar to the * ADT table. * @invariant _entries.empty() -> _current.end() * @author Benjamin Mesing */ template class History { typedef list Entries; Entries _entries; typename list::iterator _current; public: History(); /** @returns if forward is possible i.e. we are not at the end of the history. * @todo is --end() valid??*/ bool forwardPossible() const { return !_entries.empty() && (_current != (--_entries.end())); }; /** @returns if back is possible i.e. we are not at the start of the history. */ bool backPossible() const { return !_entries.empty() && (_current!=_entries.begin()); }; /** Make the next recent entry the current one and returns it. * @pre forward must be possible */ const T& forward() { return *(++_current); }; /** Make the last recent entry the current one and returns it. * @pre back must be possible */ const T& back() { return *(--_current); }; /** @brief Returns the current entry which must exist. * * @pre empty() != 0 */ const T& current() const { return *_current; } /** @brief Returns if the history is empty. */ bool empty() const { return _entries.empty(); } /** @brief Appends an entry after the current position. * * If the current position is not the last one, all * following entries will be removed. The current entry will be the one appended. */ void append(const T& t); /** Clears the history. */ void clear(); }; template History::History() { _current = _entries.end(); } template void History::append(const T& t) { if (_current != _entries.end()) { // delete all entries after the current one _entries.erase(++_current, _entries.end()); } _current = _entries.insert(_entries.end(), t); } template void History::clear() { _entries.clear(); _current=_entries.end(); } }; #endif // __HISTORY_H_2004_04_18 packagesearch-2.7.11build1/src/informationplugin.h0000644000000000000000000000540113507430555017065 0ustar #ifndef __INFORMATIONPLUGIN_H_2004_06_21 #define __INFORMATIONPLUGIN_H_2004_06_21 #include #include class QWidget; #include "plugin.h" using namespace std; namespace NPlugin { /** @brief Interface for plugins, providing information about packages. * * An information plugin can provide short information about packages * in a single string, which will be shown in a common widget accumulating * such information from all plugins. It can also provide extended information * by providing a separate widget where information can be displayed. * * For plugins providing short information, offersInformationText() must * return true, and informationText() must return the information string * for the package. * * To provide information in a separate widget, the plugin * must create a widget, return a pointer to it on * informationWidget(), and provide the title for the widget through * informationWidgetTitle(). The widget must be updated with new * package information on updateInformationWidget(). * * @author Benjamin Mesing */ class InformationPlugin : virtual public Plugin { public: /** Returns a widget for displaying information about the package. * * @returns a widget where the information offered by this plugin is shown, or * 0 if no information widget is provided by this plugin. * * @see informationWidgetTitle() */ virtual QWidget* informationWidget() const = 0; /** @brief Returns the title of the information widget. * @note Can only be called, if (informationWidget() != 0) * @see informationWidget() */ virtual QString informationWidgetTitle() const = 0; /** @brief Updates the information widget to display the information about the * given package. * * @param package the name of the package to display information for. */ virtual void updateInformationWidget(const string& package) = 0; /** @brief Clears the content of the information widget. */ virtual void clearInformationWidget() = 0; /** @brief Returns if this plugin offers information which should be shown in * the details section of the search windows result view. */ virtual bool offersInformationText() const = 0; /** @brief Returns an information text for the given package * * @param package the name of the package for which information shall be returned. * @returns the information text for the given package * @see offersInformationText() */ virtual QString informationText (const string& package) = 0; /** @brief Returns the priority of this information plugin. * * Lower values mean that the plugins output will be shown most visible (e.g. on top). */ virtual uint informationPriority() const = 0; }; } // namespace NPlugin #endif // __INFORMATIONPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/ipluginfactory.h0000644000000000000000000000144013507430555016357 0ustar // // C++ Interface: ipluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __IPLUGINFACTORY_H_2004_09_09 #define __IPLUGINFACTORY_H_2004_09_09 #include using namespace std; namespace NPlugin { class Plugin; /** @brief This class can be used to create plugins by name. * @author Benjamin Mesing */ class IPluginFactory { public: IPluginFactory() {}; virtual ~IPluginFactory() {}; /** @brief Use this function to create a plugin for the given name. * * @returns the plugin created, 0 if no plugin type is known for the given name. */ virtual Plugin* createPlugin(const string& name) const = 0; }; }; #endif // __IPLUGINFACTORY_H_2004_09_09 packagesearch-2.7.11build1/src/iplugininformer.h0000644000000000000000000000256013507430555016535 0ustar // // C++ Interface: iplugininformer // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __IPLUGININFORMER_H_2004_09_08 #define __IPLUGININFORMER_H_2004_09_08 namespace NPlugin { class IPluginUser; class Plugin; /** @brief Interface to manage and inform plugin users. * * All added plugin users will be informed about added or removed plugins * when the informAddPlugin() / informRemovePlugin() function is called. * @author Benjamin Mesing */ class IPluginInformer { public: IPluginInformer() {}; virtual ~IPluginInformer() {}; /** @brief Adds a plugin user. Plugin users will be informed about loading * and unloading of plugins. * * Each plugin user can be added only once, if it is added a second time, nothing will happen. * @param pUser the user to add * @see removePluginUser() */ virtual void addPluginUser(IPluginUser* pUser) = 0; /** @brief Removes the handed plugin user. * * If it is not in the list of users nothing will happen. * * @param pUser the user to remove * @see addPluginUser() */ virtual void removePluginUser(IPluginUser* pUser) = 0; // virtual void informAddPlugin(Plugin* pPlugin) = 0; // virtual void informRemovePlugin(Plugin* pPlugin) = 0; }; }; #endif // __IPLUGININFORMER_H_2004_09_08 packagesearch-2.7.11build1/src/ipluginuser.h0000644000000000000000000000155113507430555015671 0ustar // // C++ Interface: ipluginuser // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __IPLUGINUSER_H_2004_08_11 #define __IPLUGINUSER_H_2004_08_11 namespace NPlugin { class Plugin; /** @brief This interface must be implemented if the class wants to register * itself at the pluginmanager to be informed about changes in the loaded plugin. * * @author Benjamin Mesing */ class IPluginUser{ public: IPluginUser() {}; virtual ~IPluginUser() {}; /** This method is called by the PluginManager whenever a new plugin is loaded. */ virtual void addPlugin(Plugin* pPlugin) = 0; /** This method is called by the PluginManager whenever a plugin is removed. */ virtual void removePlugin(Plugin* pPlugin) = 0; }; }; #endif // __IPLUGINUSER_H_2004_08_11 packagesearch-2.7.11build1/src/iprogressobserver.h0000644000000000000000000000517113507430555017112 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NUTIL_IPROGRESSOBSERVER_H_2005_02_22 #define __NUTIL_IPROGRESSOBSERVER_H_2005_02_22 #include #include using namespace std; namespace NUtil { /** @author Benjamin Mesing */ class IProgressObserver { /** The lower bound of the current range. * * Default: 0 * @invariant 0 <= _lowerBound <= 100 * @invariant _lowerBound <= _upperBound */ int _lowerBound; /** The lower bound of the current range. * * Default: 100 * @invariant 0 <= _lowerBound <= 100 * @invariant _lowerBound <= _upperBound */ int _upperBound; protected: /** Sets the absolute progress of the loading state in %. * * @pre 0 <= progress <= 100 */ virtual void setAbsoluteProgress(int progress)=0; public: IProgressObserver() { _lowerBound = 0; _upperBound = 100; }; virtual ~IProgressObserver() {}; /** Sets the progress range currently active. * * While a range is set each call of setProgress(int) will be interpreted as being in this * range. * * @param lower lower bound of the range * @param upper upper bound of the range * @param setToLower if this is true, the progress will be set to the lower bound * @pre 0 <= lower * @pre upper <= 100 * @pre lower <= upper * @see setProgress(int) */ void setProgressRange(int lower, int upper, bool setToLower = true) { _lowerBound = lower; _upperBound = upper; if (setToLower) setAbsoluteProgress(lower); }; /** Returns #_lowerBound. */ int lowerBound() const { return _lowerBound; }; /** Returns #_lowerBound. */ int upperBound() const { return _upperBound; }; /** Sets the progress of the plugin. * * The progress will be interpreted as % of the current range. I.e. the real progress * will be computed by #_lowerBound + (#_upperBound - #_lowerBound) / 100 * progress * * @param progress progress of the reporting plugin in % should be in [0..100] * if it is out of range it will be clamped */ void setProgress(int progress) { progress = max(0, progress); progress = min(100, progress); setAbsoluteProgress(_lowerBound + int(float(_upperBound - _lowerBound) / 100.0f * float(progress))); } /** Sets an arbitatry text to be displayed. * * @param text the text will be displayed, it can be used to describe what is * currently done */ virtual void setText(const QString& text)=0; }; }; #endif // __NUTIL_IPROGRESSOBSERVER_H_2005_02_22 packagesearch-2.7.11build1/src/iprovider.h0000644000000000000000000000704013507430555015325 0ustar #ifndef __PLUGINMANAGER_H_2004_06_21 #define __PLUGINMANAGER_H_2004_06_21 #include #include #include #include #include class QNetworkAccessManager; class QPushButton; class QStatusBar; class QWidget; namespace Xapian { class Database; } namespace ept { namespace apt { class Apt; } namespace debtags { class Vocabulary; } } namespace Xapian { class Database; } using namespace std; namespace NUtil { class IProgressObserver; } namespace NPlugin { class IPluginUser; class PluginContainer; class Plugin; /** @brief This is the interface which provides informations for the plugins. * * */ class IProvider { public: virtual ~IProvider() {} /** @brief Returns the path were the icons are located. */ virtual QString iconDir() const = 0; /** * @brief Disables the whole search window. * * This might be used if all updating should be locked. * @param enabled */ virtual void setEnabled (bool enabled) = 0; /** Returns the currently active package. */ virtual QString currentPackage() const = 0; /** @brief Creates a button which can be used as to clear the input of a line. * * The button will only have an icon which looks like this: *
	  +------
	  |      \
	  |  \/   \
	  |  /\   /
	  |      /
	  +------
	 
*/ virtual QPushButton* createClearButton(QWidget* pParent = 0, const char* name = 0) const = 0; /** * @brief Reports an error to the user. * @param title a title for the error * @param message a description of what went wrong */ virtual void reportError (const QString& title, const QString& message) = 0; /** * @brief Reports a warning to the user. * @param title a title for the warning * @param message a description of what happened */ virtual void reportWarning(const QString& title, const QString& message) = 0; /** @brief This can be used by the plugins to report that they are currently busy. * * It must be followed by a report ready. * @param pPlugin the plugin which report busy * @param message a short description of the activity (it can be used to display * whats currently going on, e.g. using the status bar). */ virtual void reportBusy(Plugin* pPlugin, const QString& message) = 0; /** This can be used by a busy plugins to report that it is ready. * It must be procceeded by a report ready. */ virtual void reportReady(Plugin* pPlugin) = 0; /** @brief Returns a list of all packages available. * * Only real packages will be listed here i.e. no virtuals, or missing dependencies. */ virtual const set& packages() const = 0; /** Returns a pointer to the main window for the plugins. */ virtual QMainWindow* mainWindow() = 0; /** Returns a pointer to the status bar. */ virtual QStatusBar* statusBar() = 0; /** Allows access to the loader interface to report back loading progress. */ virtual NUtil::IProgressObserver* progressObserver() const = 0; /** Returns a reference to the apt object. */ virtual const ept::apt::Apt& apt() const = 0; /** Returns a reference to the debtags vocabulary object. */ virtual const ept::debtags::Vocabulary& vocabulary() const = 0; /** Returns a reference to the apt-xapian database. */ virtual const Xapian::Database& xapian() const = 0; /** @brief Returns the central network manager which can be used to access the network. */ virtual QNetworkAccessManager* network() = 0; /** @brief Reloads the package database. */ virtual void reloadAptFrontCache() = 0; }; } // namespace NPlugin #endif // __PLUGINMANAGER_H_2004_06_21 packagesearch-2.7.11build1/src/iscorecalculationstrategy.h0000644000000000000000000000334613507430555020615 0ustar // // C++ Interface: iscorecalculationstrategy // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_ISCORECALCULATIONSTRATEGY_H_2005_07_30 #define __NPLUGIN_ISCORECALCULATIONSTRATEGY_H_2005_07_30 #include #include using namespace std; namespace NPlugin { /** @brief This class provides the interface to calculate scores for plugins. * * Using the score strategy, you must call calculateScore() first and afterwards * you can get the result with getScore(package) or getScore. * * This is intended to be used by the ScorePlugins to realize score * calculation. However ScorePlugins are not required to use this interface. * * Note that you would probably want to inherit ScoreCalculationStrategyBase * instead of inheriting this interface directly. * @see ScoreCalculationStrategyBase * @author Benjamin Mesing */ class IScoreCalculationStrategy { public: IScoreCalculationStrategy() {}; virtual ~IScoreCalculationStrategy() {}; /** @brief Calculates the scores for the handed set of packages. * * Old calculations will be cleared. */ virtual void calculateScore(const set& packages) = 0; /** @brief Returns the score for the handed package. * * @pre the score for this package must have been calculated */ virtual float getScore(const string& package) const = 0; /** @brief Returns a map, mapping the packageId to the scores calculated. * * @see calculateScore() */ virtual const map& getScore() const = 0; /** @brief Clears the scores calculated. */ virtual void clear() = 0; }; } #endif // __NPLUGIN_ISCORECALCULATIONSTRATEGY_H_2005_07_30 packagesearch-2.7.11build1/src/ixmlstorable.h0000644000000000000000000000710313507430555016027 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NXML_IXMLSTORABLE_H_2005_04_23 #define __NXML_IXMLSTORABLE_H_2005_04_23 #include namespace NXml { class XmlData; /** @brief Implement this interface if your class can be stored in an XML file * * The saveSettings(NXml::XmlData& outData, QDomElement parent) function is used * to store the data of the implementing object. For this purpose it should * create exactly one node as child of parent whereunder the data is added. * If the object does not need to save any settings, it is also possible to * add no node. The loadSettings(QDomElement source) * routine is called when loading with the node created in saveSettings() as * source. If no node was create by saveSettings(), the loadSettings() * function is called nevertheless - with source being an arbitary element. * Therefor the loadSettings() function should perform a test if the handed node * did actually is the expected one. * * A class Container that handles IXmlStorable objects could be implemented like this: @code void Container::saveSettings() { NXml::XmlData xmlData("container"); QDomElement root = xmlData.root(); _pFirstStorable->saveSettings(xmlData, root); _pSecondStorable->saveSettings(xmlData, root); ... if ( !xmlData.writeFile(_settingsFilename) ) cerr << "Unable to write settings to "<< _settingsFilename <loadSettings(element); element = _pSecondStorable->loadSettings(element); ... } @endcode * Where the implementation of a class implementing IXmlStorable could look like this: @code class MyStorable : public IXmlStorable { virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) { // nothing to save? if (_settings1.isEmpty()) return; QDomElement myStorable = outData.addElement(parent, "myStorable"); outData.addAttribute(pluginManager, _settings1, "_settings1"); }; virtual QDomElement loadSettings(QDomElement source) { // noting was saved if (source.tagName() != "myStorable") return source; NXml::getAttribute(source, _settings1, "settings1", "default"); return NXml::getNextElement(source); } @endcode * @author Benjamin Mesing */ class IXmlStorable { public: IXmlStorable() {}; virtual ~IXmlStorable() {}; /** @brief Save the data for this object into the given XML tree. * * You should create exactly one new node as child of parent * When loading the XML file later this node will be handed as the source * parameter to the loadSettings() function. You can also add no node here, * where the loadSettings routine should return immidiately. * * @param outData XML Document which owns parent * @param parent the parent where to add the settings */ virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const = 0; /** @brief Loads the settings for this object from inData. * * @param source the element where the information is stored * @returns the next sibling element of source or source if * source did not contain information for this object. */ virtual QDomElement loadSettings(QDomElement source) = 0; }; }; #endif // __NXML_IXMLSTORABLE_H_2005_04_23 packagesearch-2.7.11build1/src/main.cpp0000644000000000000000000000657013507430555014610 0ustar // // C++ Implementation: main // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include #include #include #include #include "packagesearchimpl.h" #include "helpers.h" #include "globals.h" using namespace std; #include #include void releaseMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { switch ( type ) { case QtDebugMsg: // do nothing break; case QtWarningMsg: // do noting either break; case QtCriticalMsg: case QtFatalMsg: fprintf( stderr, "%s\n", msg ); abort(); // deliberately core dump } } void debugMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { switch ( type ) { case QtDebugMsg: // Some QT Debug noise (QT 5.9.1) if (msg.contains("XI2") || msg.contains("QGestureManager:Recognizer")) return; cerr << "[Debug] " << msg << endl; break; case QtWarningMsg: cerr << "[Warning] " << msg << endl; break; case QtCriticalMsg: case QtFatalMsg: fprintf( stderr, "%s\n", msg ); abort(); // deliberately core dump } } int main(int argc, char* argv[]) { QString usage(QApplication::translate("MainProgram", "Usage: packagesearch [options]\n" "\t-h, --help prints this message\n" "\t-v, --version prints the version information\n" "If started without options the UI is launched\n")); #ifdef __DEBUG qInstallMessageHandler( debugMessageOutput ); #else qInstallMessageHandler( releaseMessageOutput ); #endif QApplication a(argc, argv); // TODO: this makes packagesearch not finding the translations if there is a translations directory anywhere // replace by search for the concrete translation files // setup translation QDir translationDir; if ( QFile("../translations/packagesearch_de.qm").exists() ) translationDir = "../translations/"; else if ( QFile("../translations/packagesearch_de.qm").exists() ) translationDir = "translations/"; else if ( QFile("../translations/packagesearch_de.qm").exists() ) translationDir = "/usr/share/packagesearch/translations"; else qWarning("Unable to locate translation directory, translations must be located in " "/usr/share/packagesearch/translations, ../translations or translations/."); QString locale = QLocale::system().name(); QTranslator translator; translator.load(translationDir.filePath(QString("packagesearch_") + locale)); a.installTranslator(&translator); if (argc > 1) { for (int i=1; i < argc; ++i) { QString arg(argv[i]); if (arg == "--version" || arg == "-v") { cout << toString(NPackageSearch::VERSION) << endl; return 0; } if (arg == "--help" || arg == "-h") { cout << usage; return 0; } cerr << a.translate("MainProgram", "Unknown option ") << argv[i] << endl; cerr << usage << endl; return 1; } } PackageSearchImpl search(0, "MainWindow"); search.setWindowTitle(a.translate("MainProgram", "Debian Package Search - Version ") + NPackageSearch::VERSION); search.setTranslationDir(translationDir); search.show(); search.initialize(); return a.exec(); } packagesearch-2.7.11build1/src/make_map.pl0000755000000000000000000000054413507430555015265 0ustar #!/usr/bin/perl -w @names = <>; # reads the entries to convert chomp(@names); foreach (@names) { next if (!/^\s*(\w+)\s*_?(\w+)\s*;\s*$/); my ($type, $identifier) = /(\w+)\s*_?(\w+)/; # $identifier=lc($_); # print "\t\tstringToEntry[\"$identifier\"]=".uc($_).";\n"; # $name = ucfirst($identifier); print ("virtual $type $identifier() const;\n"); } packagesearch-2.7.11build1/src/networksettings.cpp0000644000000000000000000000550313507430555017131 0ustar /* Copyright (C) 2012 Benjamin Mesing This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "networksettings.h" #include #include #include "helpers.h" #include "xmldata.h" namespace NUtil { NetworkSettings::NetworkSettings() : _port(-1) { _pNetwork = new QNetworkAccessManager(); setProxyType(NO_PROXY); } NetworkSettings::NetworkSettings(ProxyType type, string host, int port) { _pNetwork = new QNetworkAccessManager(); _host = host; _port = port; setProxyType(type); } NetworkSettings::~NetworkSettings() { delete _pNetwork; } bool NetworkSettings::loadSystemProxy() { QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); if (env.contains("http_proxy")) { QUrl proxyUrl(env.value("http_proxy")); _host = proxyUrl.host().toStdString(); _port = proxyUrl.port(); return true; } else return false; } void NetworkSettings::setProxyType(ProxyType type) { _proxyType = type; switch (type) { case NO_PROXY: _useProxy = false; break; case SYSTEM_PROXY: _useProxy = loadSystemProxy(); break; case CUSTOM_PROXY: _useProxy = true; break; } updateQProxy(); } void NetworkSettings::updateQProxy() { //_qNetworkProxy; _pNetwork->setProxy(*(new QNetworkProxy(_useProxy ? QNetworkProxy::HttpProxy : QNetworkProxy::NoProxy, toQString(_host), _port))); } QNetworkAccessManager* NetworkSettings::network() { return _pNetwork; } QDomElement NetworkSettings::loadSettings ( QDomElement source ) { if (source.tagName() != "network") return source; int type; NXml::getAttribute(source, type, "proxyType", (int) SYSTEM_PROXY); NXml::getAttribute(source, _host, "httpProxyHost", ""); NXml::getAttribute(source, _port, "httpProxyPort", 0); setProxyType((ProxyType) type); return NXml::getNextElement(source); } void NetworkSettings::saveSettings ( NXml::XmlData& outData, QDomElement parent ) const { QDomElement element = outData.addElement(parent, "network"); outData.addAttribute(element, _proxyType, "proxyType"); if (_host != "") { outData.addAttribute(element, _host, "httpProxyHost"); outData.addAttribute(element, _port, "httpProxyPort"); } } } // namespace NUtil packagesearch-2.7.11build1/src/networksettings.h0000644000000000000000000001024513507430555016575 0ustar /* Copyright (C) 2012 Benjamin Mesing This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __NETWORKSETTINGS_H_2012_01_31 #define __NETWORKSETTINGS_H_2012_01_31 #include #include #include #include "ixmlstorable.h" using namespace std; namespace NUtil { /** * @Brief Stores the proxy network settings. * * Different types of proxies can be configured: *
    *
  1. NO_PROXY: speaks for itself
  2. *
  3. SYSTEM_PROXY: use the system configuration (this will access the value of the http_proxy * variable)
  4. *
  5. CUSTOM_PROXY: use a custom proxy configuration
  6. *
* * * */ class NetworkSettings : public NXml::IXmlStorable { public: enum ProxyType { NO_PROXY = 0, SYSTEM_PROXY, CUSTOM_PROXY }; private: ProxyType _proxyType; string _host; int _port; bool _useProxy; /** @brief The QNetworkManager. * * Should be configured for local network connection. */ QNetworkAccessManager* _pNetwork; QNetworkProxy _qNetworkProxy; public: NetworkSettings(); /** Returns true if a proxy shall be used. * *
    *
  • if type() == NO_PROXY returns false
  • *
  • if type() == SYSTEM_PROXY returns true if a system proxy was configured, else false *
  • if type() == CUSTOM_PROXY returns true
  • *
*/ bool useProxy() const { return _useProxy; }; /** Initialises the network settings. * * If (type == SYSTEM_PROXY), host and port will be ignored and * loadSystemProxy() will be called instead. */ NetworkSettings(ProxyType type, string host="", int port=-1); ~NetworkSettings(); /** Returns the current proxy typ. */ ProxyType proxyType() const { return _proxyType; } /** Returns the host, or an empty string if no host is configured. */ string host() const { return _host; } /** Returns the port, or -1 if no port is configured. */ int port() const { return _port; } /** @brief Returns the network manager corresponding to this configuration. */ QNetworkAccessManager* network(); /** @name IXmlStorable interface * * Implementation of the IXmlStorable interface. * * Both functions do nothing in the default implementation. */ //@{ /** @brief Save the data for this object into the given XML tree. * * The implementation for this creates a new element beneath parent with the * name "network". All attributes are stored below this node. * * @see IXmlStorable::saveSettings() for details how to save. */ virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; /** @brief Loads the data for this object from the given XML node. * * @see IXmlStorable::loadSettings() on the loading process. */ virtual QDomElement loadSettings(const QDomElement source); //@}}; protected: /** * Sets the proxy type. * * If CUSTOM_PROXY or NO_PROXY are handed, _host and _port remain untouched. * If SYSTEM_PROXY is handed and a system proxy is configured, _host * and _port will be set to the values of the system proxy. * * Also updates the QNetworkProxy for the QNetworkAccessManager. */ void setProxyType(ProxyType type); /** Updates the internal QNetworkProxy configuration. */ void updateQProxy(); /** Loads the system proxy from the environment variable. * * Modifies _host and _port if a system proxy is configured. * * @returns true if a system proxy is available (i.e. http_proxy is set) else false; */ bool loadSystemProxy(); }; } // NUtil #endif // __NETWORKSETTINGS_H_2012_01_31 packagesearch-2.7.11build1/src/packagedisplaywidget.cpp0000644000000000000000000003542313507430555020050 0ustar // // C++ Implementation: packagedisplaywidget // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "packagedisplaywidget.h" #include #include #include #include #include #include #include // NXml #include // NPlugin #include "shortinformationplugin.h" #include "actionplugin.h" #include "packagenotfoundexception.h" #include "columncontroldlg.h" #include namespace NPackageSearch { /* const int PackageDisplayWidget::WIDGET_CHAR_WIDTH = 7; const int PackageDisplayWidget::MARGIN = 10; */ PackageDisplayWidget::PackageDisplayWidget(QWidget * pParent) : QTableWidget(pParent) { WIDGET_CHAR_WIDTH = 7; MARGIN = 10; verticalHeader()->hide(); QFontMetrics font = fontMetrics(); verticalHeader()->setDefaultSectionSize(1.07*font.height()); horizontalHeader()->setSectionsClickable(true); horizontalHeader()->setSortIndicatorShown(true); horizontalHeader()->setSectionsMovable(true); connect(this, SIGNAL(itemSelectionChanged()), SLOT(onItemSelectionChanged())); setSelectionMode(SingleSelection); setSelectionBehavior(SelectRows); horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(horizontalHeader(), SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onHeaderContextMenuRequested(const QPoint&))); _pCustomizeColumnsAction = new QAction(tr("Customize Columns"), this); connect(_pCustomizeColumnsAction, SIGNAL(triggered()), SLOT(showColumnControlDialog())); setShowGrid(false); } PackageDisplayWidget::~PackageDisplayWidget() { } void PackageDisplayWidget::setPackages(const set& packages) { using namespace NPlugin; // TODO: reimplement selecting the package which was selectd before clearContents(); // temporary deactivate sorting because of 1. performance reasons and 2. a stable item order setSortingEnabled(false); setRowCount(packages.size()); int row = 0; for (set::const_iterator it = packages.begin(); it != packages.end(); ++it) { const string& package = *it; // add the item with its name int column = 0; const vector& plugins = _siPlugins; for (vector::const_iterator jt = plugins.begin(); jt != plugins.end(); ++jt) { try { // TODO: do not set the text for columns which are hidden QString text = (*jt)->shortInformationText(package); setItem(row, column, new QTableWidgetItem(text)); } // simply ignore it if the package was not available for this plugin catch (NPlugin::PackageNotFoundException& e) {} catch (std::exception& e) { qWarning() << "Plugin " << (*jt)->name() << " failed provide short information\n" << "e.what(): " << e.what(); } catch (...) { qWarning() << "Plugin " << (*jt)->name() << " failed provide short information description (unknown exception thrown)"; } ++column; } ++row; } /* if (pSelectItem) { _pPackageView->ensureItemVisible(pSelectItem); _pPackageView->setSelected(pSelectItem, true); } // select the first item of the site to be shown else if (_pPackageView->firstChild()) { _pPackageView->setSelected(_pPackageView->firstChild(), true); }*/ setSortingEnabled(true); } ///////////////////////////////////////////////////// // IPluginUser Interface ///////////////////////////////////////////////////// void PackageDisplayWidget::addPlugin(NPlugin::Plugin* pPlugin) { qStrDebug("PackageDisplayWidget::addPlugin(" + pPlugin->name() + ")"); using namespace NPlugin; if (dynamic_cast(pPlugin) != 0) { ShortInformationPlugin* pSIPlugin = dynamic_cast(pPlugin); _siPlugins.push_back(pSIPlugin); updateColumnDisplay(); int loadedColumnPosition = -1; int columnIndex = columnForName(pSIPlugin->shortInformationCaption()); // if there are loaded settings for the column available if (_loadedColumnSettings.find(pSIPlugin->shortInformationCaption()) != _loadedColumnSettings.end()) { //qDebug("Applying settings for column " + pSIPlugin->shortInformationCaption() ); Column column = _loadedColumnSettings.find(pSIPlugin->shortInformationCaption())->second; setColumnWidth(columnIndex, column._width); loadedColumnPosition = column._position; horizontalHeader()->setSectionHidden(columnIndex, column._hidden); } else { setColumnWidth(columnIndex, pSIPlugin->preferredColumnWidth() * WIDGET_CHAR_WIDTH + MARGIN); } //qDebug("Order before reordering"); //debugPrintOrder(); int visualIndex = columnPosition(loadedColumnPosition, columnIndex, pSIPlugin); //qDebug("Target visual Index of " + pSIPlugin->shortInformationCaption() + " is %d", visualIndex); if (visualIndex != -1) { horizontalHeader()->moveSection(horizontalHeader()->visualIndex(columnIndex), visualIndex); //qDebug("Order after reordering"); //debugPrintOrder(); } } if (dynamic_cast(pPlugin)) { _actionPlugins.push_back(dynamic_cast(pPlugin)); } } void PackageDisplayWidget::removePlugin(NPlugin::Plugin* pPlugin) { using namespace NPlugin; ShortInformationPlugin* pSIPlugin = dynamic_cast(pPlugin); if (pSIPlugin) { vector::iterator it = std::find(_siPlugins.begin(), _siPlugins.end(), pSIPlugin); if (it != _siPlugins.end()) _siPlugins.erase(it); updateColumnDisplay(); } ActionPlugin* pAPlugin = dynamic_cast(pPlugin); if (pAPlugin) { vector::iterator it = std::find(_actionPlugins.begin(), _actionPlugins.end(), pAPlugin); if (it != _actionPlugins.end()) _actionPlugins.erase(it); } } ///////////////////////////////////////////////////// // Other funtions ///////////////////////////////////////////////////// void PackageDisplayWidget::initialize() { int scoreColumn = columnForName("Score"); // (Qt::SortOrder) sortOrder if (scoreColumn != -1) sortByColumn(scoreColumn, Qt::DescendingOrder); else sortByColumn(0, Qt::AscendingOrder); setSortingEnabled(true); } void PackageDisplayWidget::onItemSelectionChanged() { emit(packageSelected(selectedPackage())); } void PackageDisplayWidget::onHeaderContextMenuRequested(const QPoint& pos) { QMenu menu; QAction* pHideColumn = menu.addAction(tr("Hide Column")); menu.insertAction(0, _pCustomizeColumnsAction); QPoint globalPos = mapToGlobal(pos); QAction* pAction = menu.exec(globalPos); QHeaderView* pHeader = horizontalHeader(); if (pAction == pHideColumn) { int column = pHeader->logicalIndexAt(globalPos); if (column == -1) qWarning("Unexpected column selected"); else pHeader->hideSection(column); } } void PackageDisplayWidget::showColumnControlDialog() { QHeaderView* pHeader = horizontalHeader(); ColumnControlDlg dlg(this); QStringList shownColumns; QStringList hiddenColumns; for (int i = 0; i < pHeader->count(); ++i) { int logicalIndex = pHeader->logicalIndex(i); QString colCaption = horizontalHeaderItem(logicalIndex)->text(); if (pHeader->isSectionHidden(logicalIndex)) hiddenColumns.push_back(colCaption); else shownColumns.push_back(colCaption); } dlg.setContent(shownColumns, hiddenColumns); dlg.exec(); shownColumns = dlg.shownColumns(); hiddenColumns = dlg.hiddenColumns(); for (QStringList::const_iterator it = shownColumns.begin(); it != shownColumns.end(); ++it) { int col = columnForName(*it); if (pHeader->isSectionHidden(col)) { pHeader->showSection(col); if (pHeader->sectionSize(col)==0) { ShortInformationPlugin* pSIPlugin = _siPlugins[col]; int width = pSIPlugin->preferredColumnWidth() * WIDGET_CHAR_WIDTH + MARGIN; setColumnWidth(col, width); } } } for (QStringList::const_iterator it = hiddenColumns.begin(); it != hiddenColumns.end(); ++it) { int col = columnForName(*it); if (!pHeader->isSectionHidden(col)) pHeader->hideSection(col); } } QString PackageDisplayWidget::selectedPackage() const { // TODO the const_casts here are neccessary because QT fails to declare selectedItems() as const // currently this method assumes a maximum of one selected item if (!const_cast(this)->selectedItems().isEmpty()) { QTableWidgetItem* pSelectedItem = const_cast(this)->selectedItems().first(); return packageForRow(pSelectedItem->row()); } else { return QString(); } } QString PackageDisplayWidget::packageForRow(int row) const { // TODO this relies on the package name column to be present and filled // translation _must_ match the translation of the column title! int nameColumn = columnForName(tr("Name")); QString packageName = item(row, nameColumn)->text(); return packageName; } bool PackageDisplayWidget::scoreColumnVisible() const { // translation _must_ match the translation of the column title! int scoreColumn = columnForName(tr("Score")); if (scoreColumn == -1) return false; else return !horizontalHeader()->isSectionHidden(scoreColumn); } void PackageDisplayWidget::contextMenuEvent(QContextMenuEvent * pEvent) { QList actions = packageActions(); actions.push_back(_pCustomizeColumnsAction); QMenu::exec(actions, pEvent->globalPos()); } void PackageDisplayWidget::updateColumnDisplay() { const vector& plugins = _siPlugins; QStringList labels; setColumnCount(_siPlugins.size()); for (vector::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { labels.push_back((*it)->shortInformationCaption()); } setHorizontalHeaderLabels(labels); } ///////////////////////////////////////////////////// // IXmlStorable Interface ///////////////////////////////////////////////////// void PackageDisplayWidget::saveSettings(NXml::XmlData& outData, QDomElement parent) const { QDomElement listView = outData.addElement(parent, "customListView"); // in settings version 1, we had a shownColumns and and a hiddenColumns element outData.addAttribute(listView, QString("2"), "settingsVersion"); QDomElement columns = outData.addElement(listView, "columns"); const vector& plugins = _siPlugins; for (vector::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { QDomElement column = outData.addElement(columns, "column"); int columnIndex = columnForName((*it)->shortInformationCaption()); outData.addAttribute(column, (*it)->shortInformationCaption(), "caption"); outData.addAttribute(column, columnWidth(columnIndex), "width"); outData.addAttribute(column, horizontalHeader()->visualIndex(columnIndex), "position"); outData.addAttribute(column, horizontalHeader()->isSectionHidden(columnIndex), "hidden"); } } QDomElement PackageDisplayWidget::loadSettings(const QDomElement source) { if (source.tagName() != "customListView") return source; QString settingsVersion; NXml::getAttribute(source, settingsVersion, "settingsVersion", "0.1"); // dismiss old settings, we don't want to carry around backward compatibility for an eternity if (settingsVersion >= QString("2")) { //qDebug("Loading column setup"); QDomElement element = NXml::getFirstElement(source.firstChild()); assert(element.tagName() == "columns"); // iterate over each element QDomElement e = NXml::getFirstElement(element.firstChild()); while (!e.isNull()) { Column column; NXml::getAttribute(e, column._caption, "caption", ""); NXml::getAttribute(e, column._width, "width", 50); NXml::getAttribute(e, column._position, "position", 0); NXml::getAttribute(e, column._hidden, "hidden", false); _loadedColumnSettings.insert(make_pair(column._caption, column)); e = NXml::getNextElement(e); //qDebug("Settings for column " + column._caption + ": width %d, position %d", column._width, column._position); } // note that we set the sort column, _after_ adding all the columns. // QString sortColumn; // int sortOrder; // NXml::getAttribute(element, sortColumn, "shortSortColumn", _sortColumn); // NXml::getAttribute(element, sortOrder, "shortSortOrder", _sortOrder); // if (!sortColumn.isEmpty()) // setSorting(sortColumn, (Qt::SortOrder) sortOrder); } return NXml::getNextElement(source); } ///////////////////////////////////////////////////// // Query functions ///////////////////////////////////////////////////// int PackageDisplayWidget::columnPosition(int position, int logicalIndex, const NPlugin::ShortInformationPlugin* pPlugin) const { // iterate over all columns by visual index (i.e. starting with the one with visible index 0) for (int visualColIndex = 0; visualColIndex < columnCount(); ++visualColIndex) { int logicalColIndex = horizontalHeader()->logicalIndex(visualColIndex); // skip the column if it is the requested column if (logicalColIndex == logicalIndex) continue; QString colCaption = horizontalHeaderItem(logicalColIndex)->text(); // if the requested column has no position information or the current column has no position information if (position == -1 || _loadedColumnSettings.find(colCaption) == _loadedColumnSettings.end()) { uint colPriority = pluginForCaption(colCaption)->shortInformationPriority(); if (colPriority > pPlugin->shortInformationPriority()) return visualColIndex; } else { int colPosition = _loadedColumnSettings.find(colCaption)->second._position; // if the given position is before the current one, return the index of the current column if (colPosition > position) { return visualColIndex; } } } return -1; } int PackageDisplayWidget::columnForName(const QString& name) const { for (int i=0; i < columnCount(); ++i) { if (horizontalHeaderItem(i)->text() == name) return i; } return -1; } NPlugin::ShortInformationPlugin* PackageDisplayWidget::pluginForCaption(const QString& caption) const { for (vector::const_iterator it = _siPlugins.begin(); it != _siPlugins.end(); ++it) { if ((*it)->shortInformationCaption() == caption) return *it; } return 0; } QList PackageDisplayWidget::packageActions() const { QList result; for (vector::const_iterator it = _actionPlugins.begin(); it != _actionPlugins.end(); ++it) { vector actions = (*it)->actions(); for (vector::const_iterator jt = actions.begin(); jt != actions.end(); ++jt) { const NPlugin::Action* pAction = *jt; if (pAction->packageAction()) result.push_back(pAction->action()); } } return result; } void PackageDisplayWidget::debugPrintOrder() const { QHeaderView& header = *horizontalHeader(); QString headerLabel; for (int i=0; i < header.count(); ++i) { int index = header.logicalIndex(i); headerLabel += horizontalHeaderItem(index)->text() + " | "; } qStrDebug(headerLabel); } } packagesearch-2.7.11build1/src/packagedisplaywidget.h0000644000000000000000000001463413507430555017516 0ustar // // C++ Interface: packagedisplaywidget // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPACKAGESEARCH_PACKAGEDISPLAYWIDGET_H_2007_10_30 #define __NPACKAGESEARCH_PACKAGEDISPLAYWIDGET_H_2007_10_30 #include #include class QAction; #include #include #include #include // NXml #include // NPlugin #include "ipluginuser.h" namespace NPlugin { class ShortInformationPlugin; class ActionPlugin; } using namespace std; namespace NPackageSearch { /** * @brief This class is a widget which displays package information in a Table. * * The package information displayed is taken from all ShortInformationPlugins and * the action which can be performed are taken from the ActionPlugins. To get to know * about the plugins, this class implements the IPluginUser interface and needs to be * registered to all plugin providers. * @author Benjamin Mesing */ class PackageDisplayWidget : public QTableWidget, public NPlugin::IPluginUser, public NXml::IXmlStorable { typedef NPlugin::ShortInformationPlugin ShortInformationPlugin; typedef NPlugin::ActionPlugin ActionPlugin; Q_OBJECT vector _actionPlugins; vector _siPlugins; QAction* _pCustomizeColumnsAction; /** The state for one column. */ struct Column { Column() {} Column(QString caption, int width, int position, bool hidden ) : _caption(caption), _width(width), _position(position), _hidden(hidden) { } QString _caption; int _width; int _position; bool _hidden; }; /** This contains the column settings that were loaded during loadSettings(). * * It maps the column title to the stored settings. * The appropriate data will be applied a column when it is added. */ map _loadedColumnSettings; int WIDGET_CHAR_WIDTH; int MARGIN; public: PackageDisplayWidget(QWidget * pParent = 0); ~PackageDisplayWidget(); /** @name IPluginUser interface * * These functions implement the IPluginUser interface. */ //@{ // documented in base class virtual void addPlugin(NPlugin::Plugin* pPlugin); /** @brief Finds every reference to plugin and remove it so that pPlugin can be safely deleted. * * @param pPlugin the plugin to be removed */ void removePlugin(NPlugin::Plugin* pPlugin); //@} public slots: /** @brief Sets the packages to be displayed. */ void setPackages(const set& packages); /** Shows a dialog to control the settings of the columns (which columns are shown). */ void showColumnControlDialog(); protected: /** @brief Updates the columns displayed. * * This includes updating of the number of columns, the column caption and the ordering. */ void updateColumnDisplay(); protected slots: virtual void onItemSelectionChanged(); void onHeaderContextMenuRequested(const QPoint& pos); signals: /** Emitted whenever a package was selected. * * Emitted with an empty string, if no package was selected. */ void packageSelected(QString package); ////////////////////////////////////////////////// // Column display control ////////////////////////////////////////////////// public: virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; virtual QDomElement loadSettings(QDomElement source); /** @brief To be called once all columns are added, so that the loaded settings can be applied. * * Applies all non-column specfic settings. */ virtual void initialize(); ////////////////////////////////////////////////// // Query Methods ////////////////////////////////////////////////// /** @name Query Methods * * These methods query some information without changing the class. */ //@{ begin Query Methods /** @brief Returns the package that is currently selected. * * @return the name of the package or a null string, if no package was selected. */ QString selectedPackage() const; /** @brief Returns if the score column is visible. * * This is useful to determine if score calculation should be performed. */ bool scoreColumnVisible() const; /** @brief Returns the package referred to by the given row. */ QString packageForRow(int row) const; /** Debug Method: Prints the name of the columns in order of their visible index using qDebug(). */ void debugPrintOrder() const; protected: /** Returns the logical index of the column where the header has the given name. * * @returns the index of the column or -1 if no such column was found. */ virtual int columnForName(const QString& name) const; /** Returns the plugin with the given caption. * * @returns the plugin or 0 if no such plugin exists. */ virtual ShortInformationPlugin* pluginForCaption(const QString& name) const; /** @brief Returns the position that the requested short information column shall have. * * The position will be determined as follows: *
    *
  • if (position == -1) the position of the first column where the corresponding plugin has * a priority larger than the request plugin
  • *
  • if (position != -1) the position of the first column where either the column has a larger * position value in the stored setting or with a priority larger than the request plugin (the * latter will only be considered if the added column has no saved settings
  • *
  • the column itself will not be considered
  • *
  • -1 will be returned if the position should be at the end of the table
  • *
* * @param position the position of the requested column stored in the settings, -1 if the column has no * settings * @param logicalIndex the current logical index of the column for the plugin * @param pPlugin the plugin for which the column shall be deterined * @returns the visual index of that column or -1 if it shall be at the end. */ virtual int columnPosition(int position, int logicalIndex, const NPlugin::ShortInformationPlugin* pPlugin) const; /** @brief Returns the list of all actions provided by all action plugins. */ virtual QList packageActions() const; //@} end Query Methods /** @brief Diplays a context menu showing the possible actions. * * Reimplements QWidget::contextMenuEvent() */ virtual void contextMenuEvent(QContextMenuEvent * pEvent); }; } #endif // __NPACKAGESEARCH_PACKAGEDISPLAYWIDGET_H_2007_10_30 packagesearch-2.7.11build1/src/packagenameplugin.cpp0000644000000000000000000000151413507430555017330 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "packagenameplugin.h" #include "helpers.h" namespace NPlugin { const QString PackageNamePlugin::PLUGIN_NAME = "PackageNamePlugin"; PackageNamePlugin::PackageNamePlugin() : ShortInformationPlugin(), _title(tr("Package Name Plugin")), _briefDescription(tr("Displays the package names")), _description(tr("Displays the package names")) { } PackageNamePlugin::~PackageNamePlugin() { } ///////////////////////////////////////////////////// // Short Information Plugin Interface ///////////////////////////////////////////////////// const QString PackageNamePlugin::shortInformationText(const string& package) { return toQString(package); } }; packagesearch-2.7.11build1/src/packagenameplugin.h0000644000000000000000000000337113507430555017000 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_PACKAGENAMEPLUGIN_H_2005_03_13 #define __NPLUGIN_PACKAGENAMEPLUGIN_H_2005_03_13 #include #include #include "shortinformationplugin.h" using namespace std; namespace NPlugin { /** This plugin is simply for a unified handling showing the package names. * * @author Benjamin Mesing */ class PackageNamePlugin : public QObject, public ShortInformationPlugin { const QString _title; const QString _briefDescription; const QString _description; public: const static QString PLUGIN_NAME; PackageNamePlugin(); ~PackageNamePlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* ) {}; /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 0; } virtual const QString shortInformationText(const string& package); /** @brief Returns Name */ virtual QString shortInformationCaption() const { return tr("Name"); }; // documented in base class virtual int preferredColumnWidth() const { return 20; } //@} }; }; #endif // __NPLUGIN_PACKAGENAMEPLUGIN_H_2005_03_13 packagesearch-2.7.11build1/src/packagenotfoundexception.cpp0000644000000000000000000000046013507430555020743 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "packagenotfoundexception.h" namespace NPlugin { PackageNotFoundException::~PackageNotFoundException() { } }; packagesearch-2.7.11build1/src/packagenotfoundexception.h0000644000000000000000000000204513507430555020411 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_PACKAGENOTFOUNDEXCEPTION_H_2005_03_01 #define __NPLUGIN_PACKAGENOTFOUNDEXCEPTION_H_2005_03_01 #include #include "exception.h" using namespace std; namespace NPlugin { /** @brief This exception is thrown if information for the requested package was not * found in a plugin. * * @author Benjamin Mesing */ class PackageNotFoundException : public NException::Exception { /** The name of the package not found. */ string _name; public: /** @param packageName the name of the package that was not found*/ PackageNotFoundException(const string& packageName) : _name(packageName) {} virtual ~PackageNotFoundException(); virtual string description() const { return "Package " + _name + "not found\n"; } /** Returns #_name. */ const string& name() { return _name; } }; }; #endif // __NPLUGIN_PACKAGENOTFOUNDEXCEPTION_H_2005_03_01 packagesearch-2.7.11build1/src/packagesearch-german.sh0000755000000000000000000000034513507430555017541 0ustar #!/bin/bash export LANG=de_DE.UTF-8 export LC_ALL=de_DE.UTF-8 export LC_MESSAGES=de_DE.UTF-8 export LC_CTYPE=de_DE.UTF-8 export LC_MONETARY=de_DE.UTF-8 export LC_TIME=de_DE.UTF-8 export LC_NUMERIC=de_DE.UTF-8 ./packagesearch $@ packagesearch-2.7.11build1/src/packagesearch.pro0000644000000000000000000001100213507430555016445 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: . # Target is an application: FORMS += packagesearch.ui \ packagesearchaboutdlg.ui \ plugincontrol.ui \ columncontroldlg.ui \ settingsdlg.ui HEADERS += packagesearchimpl.h \ history.h \ runcommand.h \ runcommandinxterm.h \ extalgorithm.h \ applicationfactory.h \ exception.h \ helpers.h \ informationplugin.h \ plugin.h \ iprovider.h \ searchplugin.h \ plugincontainer.h \ singleton.h \ shortinformationplugin.h \ runcommandforoutput.h \ xmldata.h \ pluginmanager.h \ ipluginuser.h \ settingsdlg.h \ plugininformer.h \ baseplugincontainer.h \ ipluginfactory.h \ iplugininformer.h \ packagenotfoundexception.h \ packagenameplugin.h \ iprogressobserver.h \ progressdisplaydlg.h \ ixmlstorable.h \ processcontainer.h \ scoredisplayplugin.h \ scoreplugin.h \ plugincompare.h \ iscorecalculationstrategy.h \ scorecalculationstrategybase.h \ columncontroldlg.h \ action.h \ actionplugin.h \ globals.h \ packagesearchaboutdlg.h \ packagedisplaywidget.h \ plugincontroldlgmeditator.h \ gainroot.h \ networksettings.h SOURCES += main.cpp \ packagesearchimpl.cpp \ history.cpp \ runcommandinxterm.cpp \ extalgorithm.cpp \ applicationfactory.cpp \ exception.cpp \ plugincontainer.cpp \ plugin.cpp \ singleton.cpp \ runcommandforoutput.cpp \ xmldata.cpp \ pluginmanager.cpp \ settingsdlg.cpp \ plugininformer.cpp \ baseplugincontainer.cpp \ packagenotfoundexception.cpp \ packagenameplugin.cpp \ progressdisplaydlg.cpp \ processcontainer.cpp \ scoredisplayplugin.cpp \ scorecalculationstrategybase.cpp \ columncontroldlg.cpp \ action.cpp \ actionplugin.cpp \ packagesearchaboutdlg.cpp \ packagedisplaywidget.cpp \ plugincontroldlgmeditator.cpp \ gainroot.cpp \ runcommand.cpp \ networksettings.cpp # libdl required for dl{open,..}() LIBS += -ldl LANGUAGE = C++ TEMPLATE = app CONFIG += warn_on \ qt \ thread \ stl \ link_pkgconfig TRANSLATIONS = ../translations/packagesearch_de.ts \ ../translations/packagesearch_es.ts UI_DIR = .ui MOC_DIR = .moc # libraries used by packagesearch which offer pkg-config PKGCONFIG += libept libtagcoll2 INCLUDEPATH += ./ QT += xml network widgets isEmpty(USE_KDE_LIBS){ message("USE_KDE_LIBS not set, assuming false by default") USE_KDE_LIBS = false } contains(USE_KDE_LIBS, true){ message("KDE support enabled") INCLUDEPATH += /usr/include/kde LIBS += -lkdecore DEFINES += __USE_KDE_LIBS } debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } # creating Makefile for test cases (CONFIG += test) # build a library from the packagesearch application here, to allow # plugins to use the library for their test cases testlib { OBJECTS_DIR = .obj_debug DEFINES += __DEBUG message("generating test library") TEMPLATE = lib QMAKE_MAKEFILE = Makefile.testlib SOURCES -= main.cpp INCLUDEPATH += .moc/ # object files for libraries are build differently from applications # thus we require another object dir # we do not distinguish between debug and release here OBJECTS_DIR = .obj_test } # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) # export-dynamic is required to export all symbols (not only used ones) to symbol tables # it is required because of the use of dlopen # -Wl,--no-add-needed prevents the linker from transitively infering library relationships QMAKE_LFLAGS_THREAD += -Wl,-export-dynamic -Wl,--no-add-needed # QMAKE_CXX = g++-4.6 packagesearch-2.7.11build1/src/packagesearch.ui0000644000000000000000000004316513507430555016301 0ustar PackageSearch 0 0 608 600 Debian Package Search 6 6 6 6 6 Qt::Vertical 6 0 0 0 5 0 0 <b>Search</b> Qt::Horizontal 6 0 0 0 0 QFrame::StyledPanel QFrame::Raised 2 3 3 3 3 Qt::Vertical QSizePolicy::Expanding 20 147 6 0 0 0 0 Clear Search Qt::Horizontal QSizePolicy::Expanding 101 21 Dummy 9 40 67 27 Qt::Horizontal 9 40 67 27 Qt::Horizontal 6 0 5 0 0 0 0 <b>Result</b> Qt::Horizontal 6 0 0 0 0 QFrame::NoFrame QFrame::Plain 0 0 0 0 0 <font size="-1">No search active</font> 6 0 0 0 0 6 0 0 0 0 0 0 Choose a package <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Nimbus Sans L; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Here you can choose to display information about a package, from all packages available.</p></body></html> true true Qt::Horizontal QSizePolicy::Preferred 20 20 Back Forward Details 6 0 0 0 0 false 0 0 767 30 309 151 128 130 &Packagesearch 544 151 123 52 &System 667 151 123 111 &Help &View Pa&ckages &Contents... Contents &About About &Exit Exit &Control Plugins Control Plugins Control plugins Enable and disable plugins &Preferences packagesearch-2.7.11build1/src/packagesearchaboutdlg.cpp0000644000000000000000000000167113507430555020164 0ustar // // C++ Implementation: packagesearchaboutdlg // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "packagesearchaboutdlg.h" #include #include // NPackageSearch #include "globals.h" using namespace std; namespace NPackageSearch { PackageSearchAboutDlg::PackageSearchAboutDlg() { setupUi(this); _pTitleLabel->setText("Debian Package Search " + VERSION + ""); QFile licenseFile("/usr/share/common-licenses/GPL"); if (licenseFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QString licenseString(licenseFile.readAll()); _pLicenceDisplay->setHtml("
"+licenseString+"
"); } else { cerr << "Could not open /usr/share/common-licenses/GPL" << endl; } } PackageSearchAboutDlg::~PackageSearchAboutDlg() { } } // NPackageSearch packagesearch-2.7.11build1/src/packagesearchaboutdlg.h0000644000000000000000000000124613507430555017627 0ustar // // C++ Interface: packagesearchaboutdlg // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPACKAGESEARCH_PACKAGESEARCHABOUTDLG_H_2005_09_30 #define __NPACKAGESEARCH_PACKAGESEARCHABOUTDLG_H_2005_09_30 #include #include namespace NPackageSearch { /** @author Benjamin Mesing */ class PackageSearchAboutDlg : public QDialog, public Ui::PackageSearchAboutDlg { public: PackageSearchAboutDlg(); ~PackageSearchAboutDlg(); }; } // namespace NPackageSearch #endif // __NPACKAGESEARCH_PACKAGESEARCHABOUTDLG_H_2005_09_30 packagesearch-2.7.11build1/src/packagesearchaboutdlg.ui0000644000000000000000000002426013507430555020016 0ustar PackageSearchAboutDlg 0 0 406 372 Debian Package Search 6 10 10 10 10 <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Nimbus Sans L'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Debian Package Search</span></p></body></html> 0 Author 6 10 10 10 10 <!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:'Noto Sans'; 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;"><span style=" font-family:'Nimbus Sans L'; font-weight:600;">Debian Package Search</span><span style=" font-family:'Nimbus Sans L';"><br />(c) 2004-2017, Benjamin Mesing<br />Email: </span><a href="mailto:bensmail@gmx.net"><span style=" font-family:'Nimbus Sans L'; text-decoration: underline; color:#0000ff;">bensmail@gmx.net</span></a></p></body></html> Qt::RichText Homepage: <a href=http://packagesearch.sourceforge.net>http://packagesearch.sourceforge.net</a> Qt::Vertical QSizePolicy::Expanding 20 161 Thanks To 6 10 10 10 10 <!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:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Enrico Zini</span> for the wonderful Debtags System and his tips regarding this application. Enrico does also sponsor the updates to the debian server.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Frannoe </span>for the Spanish translation and icon.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The <span style=" font-weight:600;">Bug reporters</span> who provided a lot of help tracking down the bugs: </p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Thomas Kabelmann</li> <li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ross Boylan</li></ul></body></html> true Qt::Vertical QSizePolicy::Expanding 20 81 Licence 6 10 10 10 10 <!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:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <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; font-family:'Nimbus Sans L';"><br /></p></body></html> 6 0 0 0 0 Qt::Horizontal QSizePolicy::Expanding 249 20 OK qPixmapFromMimeSource _pAuthorTab pushButton3 pushButton3 clicked() PackageSearchAboutDlg accept() 340 325 232 350 packagesearch-2.7.11build1/src/packagesearchimpl.cpp0000644000000000000000000010011013507430555017310 0ustar // // C++ Implementation: packagesearchimpl // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "packagesearchimpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // NApplication #include "applicationfactory.h" #include "runcommand.h" #include "runcommandforoutput.h" #include "gainroot.h" // namespace NPlugin #include "plugin.h" #include "searchplugin.h" #include "actionplugin.h" #include "informationplugin.h" #include "shortinformationplugin.h" #include "plugincontainer.h" #include "pluginmanager.h" #include "packagenotfoundexception.h" #include "plugincompare.h" #include "settingsdlg.h" #include "packagenameplugin.h" #include "scoredisplayplugin.h" // NXml #include "xmldata.h" // NException #include "exception.h" #include "extalgorithm.h" // NPackageSearch #include "packagesearchaboutdlg.h" #include "packagedisplaywidget.h" // NUtil #include "helpers.h" #undef slots #include #include #include #include #include #include using namespace std; template bool LesserPriority::operator()(PluginType* p1, PluginType* p2) { return (*p1) < (*p2); } template class LesserPriority; template class LesserPriority; template class LesserPriority; PackageSearchImpl::PackageSearchImpl( QWidget* parent, const char* name, Qt::WindowFlags fl ) : QMainWindow(parent, fl), _DETAILS_INFORMATION_PRIORITY(2), _network(NUtil::NetworkSettings::SYSTEM_PROXY) //_network(NUtil::NetworkSettings::ProxyType::SYSTEM_PROXY), no C++11 :( { setObjectName(name); setupUi(this); _pApt = 0; _pVocabulary = 0; _pXapianDatabase = 0; // set up what's this actions _pWhatsThisAction = QWhatsThis::createAction(this); _pWhatsThisAction->setShortcut(QKeySequence("Shift+F1")); initDirectories(); // don't change order, because initMenus relies on an initialized toolbar initToolbars(); initMenus(); // delete placeholder ListViewWidget and replace by a custom class delete _pPackageView; _pPackageView = new NPackageSearch::PackageDisplayWidget(_pPackageViewFrame); _pPackageView->setWhatsThis(tr("Displays the packages matching the search entered above.")); _pPackageViewFrame->layout()->addWidget(_pPackageView); _pPackageNamePlugin = 0; _pScoreDisplayPlugin = 0; _settingsFilename = QDir::homePath()+"/.packagesearch"; _pInformationDetailsPage = _pInformationContainer->widget(0); // setting up window geometry (must happen before loading settings // since otherwise stored geometry would be overridden) uint width = 700; uint height = 600; QList sizes; sizes.push_back(width/2); sizes.push_back((width+1)/2); resize(width, height); _pUpperVSplitter->setSizes(sizes); _pLowerVSplitter->setSizes(sizes); vector pluginDirectories; pluginDirectories.push_back("plugins/"); pluginDirectories.push_back("/usr/lib/packagesearch/"); _pPluginManager = new NPlugin::PluginManager(pluginDirectories, this); _pPluginManager->addPluginUser(this); _pPluginManager->addPluginUser(packageView()); loadSettings(); // must be called after setting _pPluginManager but before calling loadPlugins QPixmap appIcon(_iconDir+"packagesearch.png"); setWindowIcon(appIcon); connect(_pClearSearchButton, SIGNAL(clicked()), SLOT(onClearSearch())); connect(_pBackButton, SIGNAL(clicked()), SLOT(onBack())); connect(_pForwardButton, SIGNAL(clicked()), SLOT(onForward())); connect(_pControlPluginsAction, SIGNAL(triggered()), SLOT(onControlPlugins())); connect(_pPreferencesAction, SIGNAL(triggered()), SLOT(onPreferences())); connect(_pExitAction, SIGNAL(triggered()), SLOT(close())); connect(_pHelpAboutAction, SIGNAL(triggered()), SLOT(onHelpAboutAction())); connect(_pHelpContentsAction, SIGNAL(triggered()), SLOT(onHelpContentsAction())); connect(_pPackageView, SIGNAL(packageSelected(QString)), SLOT(onPackageSelectionChanged(QString))); connect(_pPackageSelection, SIGNAL(activated(const QString&)), SLOT(selectNewPackage(QString))); connect(_pDetailsView, SIGNAL(anchorClicked(const QUrl&)), SLOT(onLinkClicked(const QUrl&))); connect(_pInformationContainer, SIGNAL(currentChanged(int)), SLOT(onInformationPageChanged())); // query aptDB for updates every 2s connect(&timer, SIGNAL(timeout()), SLOT(checkAptDbForUpdates())); timer.start(2000); } PackageSearchImpl::~PackageSearchImpl() { delete _pPackageNamePlugin; delete _pScoreDisplayPlugin; delete _pApt; delete _pVocabulary; delete _pXapianDatabase; } ///////////////////////////////////////////////////// // Initialisation ///////////////////////////////////////////////////// void PackageSearchImpl::initDirectories() { // search for doc path if ( QFile("../doc/content.html").exists() ) { QDir docDir = QDir::current(); docDir.cd("../doc/"); _docDir = docDir.absolutePath()+"/"; } else if ( QFile("doc/content.html").exists() ) { QDir docDir = QDir::current(); docDir.cd("doc/"); _docDir = docDir.absolutePath()+"/"; } else if ( QFile("/usr/share/doc/packagesearch/content.html").exists() ) _docDir = "/usr/share/doc/packagesearch/"; else cerr << "Could not find doc directory. It must be located at " "/usr/share/doc/packagesearch/, ../doc/ or doc/."<setIconSize(QSize(16,16)); _pMainToolBar->addAction(_pWhatsThisAction); _nameToToolBar["Main"] = _pMainToolBar; // setting up brows toolbar QIcon backIcon(_iconDir + "back.png"); QIcon forwardIcon(_iconDir + "forward.png"); _pBackButton->setIcon(backIcon); _pForwardButton->setIcon(forwardIcon); updateBrowseToolbar(); } void PackageSearchImpl::initMenus() { _pViewMenu->addAction(_pMainToolBar->toggleViewAction()); _pHelpMenu->insertAction(_pHelpContentsAction, _pWhatsThisAction); _nameToMenu["Packagesearch"] = _pPackagesearchMenu; _nameToMenu["View"] = _pViewMenu; _nameToMenu["Packages"] = _pPackagesMenu; _nameToMenu["System"] = _pSystemMenu; _nameToMenu["Help"] = _pHelpMenu; } void PackageSearchImpl::initialize() { _pApt = new ept::apt::Apt; _pVocabulary = new ept::debtags::Vocabulary; // TODO: check if the database is up-to-date (though // apt-xapian-index by default updates the index after installation and weekly bool success = false; // try running until Xapian::Database can be constructed do { try { _pXapianDatabase = new Xapian::Database("/var/lib/apt-xapian-index/index"); success = true; } catch (Xapian::RuntimeError& e) { if ( QMessageBox::critical(this, tr("Error trying to open Xapian database"), tr("

An error occurred trying to open the xapian database at " "/var/lib/apt-xapian-index/index please make sure the file is " "readable and valid. You may try to run update-apt-xapian-index " "to fix this problem. The orginal error message was:
\"") + toQString(e.get_msg()) + "\"

" + tr("Would you like to run update-apt-xapian-index now? Otherwise " "packagesearch will be terminated."), QMessageBox::Yes, QMessageBox::No) == QMessageBox::No ) exit(2); updateXapianDatabase(); } } while (!success); makeHandleVisible(_pHSplitter->handle(1)); makeHandleVisible(_pUpperVSplitter->handle(1)); makeHandleVisible(_pLowerVSplitter->handle(1)); // create the hard coded plugins _pPackageNamePlugin = new NPlugin::PackageNamePlugin(); this->addPlugin(_pPackageNamePlugin); packageView()->addPlugin(_pPackageNamePlugin); _pScoreDisplayPlugin = new NPlugin::ScoreDisplayPlugin(); _pPluginManager->addPluginUser(_pScoreDisplayPlugin); this->addPlugin(_pScoreDisplayPlugin); packageView()->addPlugin(_pScoreDisplayPlugin); _pPluginManager->loadPlugins(); packageView()->initialize(); _pInformationContainer->setCurrentIndex(0); const set& packages_ = packages(); for (set::const_iterator it = packages_.begin(); it != packages_.end(); ++it) { _pPackageSelection->addItem(toQString(*it)); } _pPackageSelection->setMinimumWidth(100); setPackageActionsEnabled(false); } ///////////////////////////////////////////////////// // IXmlStorable Interface ///////////////////////////////////////////////////// void PackageSearchImpl::saveSettings() { NXml::XmlData xmlData("packagesearch"); QDomElement root = xmlData.root(); xmlData.addAttribute(root, QString("3"), "settingsVersion"); // changes: // settings version 2: added "system" node // settings version 3: added "network" node xmlData.addAttribute(root, _pMainToolBar->toggleViewAction()->isChecked(), "showMainToolbar"); QDomElement window = xmlData.addElement(xmlData.root(), "geometry"); xmlData.addAttribute(window, width(), "width"); xmlData.addAttribute(window, height(), "height"); QList sizes = _pHSplitter->sizes(); xmlData.addAttribute(window, sizes[0], "hSplitterSize1"); xmlData.addAttribute(window, sizes[1], "hSplitterSize2"); sizes = _pUpperVSplitter->sizes(); xmlData.addAttribute(window, sizes[0], "upperVSplitterSize1"); xmlData.addAttribute(window, sizes[1], "upperVSplitterSize2"); sizes = _pLowerVSplitter->sizes(); xmlData.addAttribute(window, sizes[0], "lowerVSplitterSize1"); xmlData.addAttribute(window, sizes[1], "lowerVSplitterSize2"); xmlData.addAttribute(root, _pMainToolBar->toggleViewAction()->isChecked(), "showMainToolbar"); packageView()->saveSettings(xmlData, root); QDomElement system = xmlData.addElement(xmlData.root(), "system"); xmlData.addAttribute(system, NApplication::RunCommand::gainRootCommand(), "gainRootCommand"); _network.saveSettings(xmlData, root); _pPluginManager->saveSettings(xmlData, root); if ( !xmlData.writeFile(_settingsFilename) ) reportError(tr("Unable to write settings"), tr("Unable to write settings to") + _settingsFilename + "\nPersonal settings were not saved."); } void PackageSearchImpl::loadSettings() { NXml::XmlData xmlData; if (!xmlData.loadFile(_settingsFilename)) { // sort by the first column by default // _pPackageView->setSorting(1, false); return; } QDomElement root = xmlData.root(); QString settingsVersion; NXml::getAttribute(root, settingsVersion, "settingsVersion", ""); QDomElement element = NXml::getFirstElement(xmlData.root().firstChild()); bool showMainToolbar; NXml::getAttribute(root, showMainToolbar, "showMainToolbar", true); // TODO this does not work, even though showMainToobar is read correctly _pMainToolBar->toggleViewAction()->setChecked(showMainToolbar); if (element.tagName() == "geometry") { uint width; uint height; NXml::getAttribute(element, width, "width", 600); NXml::getAttribute(element, height, "height", 600); QList sizes; int size; NXml::getAttribute(element, size, "hSplitterSize1", height/2); sizes.push_back(size); NXml::getAttribute(element, size, "hSplitterSize2", height/2); sizes.push_back(size); _pHSplitter->setSizes(sizes); sizes.clear(); NXml::getAttribute(element, size, "upperVSplitterSize1", width/2); sizes.push_back(size); NXml::getAttribute(element, size, "upperVSplitterSize2", width/2); sizes.push_back(size); _pUpperVSplitter->setSizes(sizes); sizes.clear(); NXml::getAttribute(element, size, "lowerVSplitterSize1", width/2); sizes.push_back(size); NXml::getAttribute(element, size, "lowerVSplitterSize2", width/2); sizes.push_back(size); _pLowerVSplitter->setSizes(sizes); element = NXml::getNextElement(element); resize(width, height); } // node since version 0.3 if (settingsVersion >= QString("0.3")) { element = packageView()->loadSettings(element); } // dismiss old setting version else { if (element.tagName() == "shownShortInformation") { //_shownShortInformation = NXml::getTextList(element); element = NXml::getNextElement(element); } if (element.tagName() == "hiddenShortInformation") { //_hiddenShortInformation = NXml::getTextList(element); element = NXml::getNextElement(element); } } // if preferences contain a "system" node if (element.tagName() == "system") { int gainRootCommand; NXml::getAttribute(element, gainRootCommand, "gainRootCommand", 0); NApplication::RunCommand::setGainRootCommand((NApplication::GainRoot) gainRootCommand); element = NXml::getNextElement(element); } element = _network.loadSettings(element); _pPluginManager->loadSettings(element); } ///////////////////////////////////////////////////// // IProvider Interface ///////////////////////////////////////////////////// void PackageSearchImpl::setEnabled(bool enabled) { QMainWindow::setEnabled(enabled); } QPushButton* PackageSearchImpl::createClearButton(QWidget* pParent, const char* name) const { QPushButton* pButton = new QPushButton(pParent); pButton->setObjectName(name); pButton->setFixedSize(20, 20); QPixmap clearIcon(_iconDir+"clear.png"); pButton->setIcon(clearIcon); return pButton; } void PackageSearchImpl::reportError(const QString& title, const QString& message) { QMessageBox::critical(this, title, message, "OK"); } void PackageSearchImpl::reportWarning(const QString& title, const QString& message) { QMessageBox::warning(this, title, message, "OK"); } void PackageSearchImpl::reportBusy(NPlugin::Plugin*, const QString& message) { // order is important here, since setOverrideCursor() triggers an update of the UI, // and thus immediately updates the statusbar statusBar()->showMessage(message); qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); } void PackageSearchImpl::reportReady(NPlugin::Plugin* ) { // order is important here, since setOverrideCursor() triggers an update of the UI, // and thus immediately updates the statusbar statusBar()->clearMessage(); qApp->restoreOverrideCursor(); } NUtil::IProgressObserver* PackageSearchImpl::progressObserver() const { return _pPluginManager->progressObserver(); } const set& PackageSearchImpl::packages() const { static bool initialized = false; if (!initialized) { typedef ept::apt::Apt Apt; initialized = true; for (Apt::Iterator it = _pApt->begin(); it != _pApt->end(); ++it) { _packages.insert(*it); } } return _packages; } void PackageSearchImpl::reloadAptFrontCache() { delete _pApt; _pApt = new ept::apt::Apt; } QNetworkAccessManager* PackageSearchImpl::network() { return _network.network(); } ///////////////////////////////////////////////////// // IPluginUser Interface ///////////////////////////////////////////////////// void PackageSearchImpl::addPlugin(NPlugin::Plugin* pPlugin) { using namespace NPlugin; SearchPlugin* pSearchPlugin = dynamic_cast(pPlugin); if (pSearchPlugin != 0) { _searchPlugins.insert(pSearchPlugin); updateSearchPluginGui(); connect(pSearchPlugin, SIGNAL(searchChanged(NPlugin::SearchPlugin*)), SLOT(onSearchChanged(NPlugin::SearchPlugin*))); /// @todo connect selectionChanged signal } InformationPlugin* pInformationPlugin = dynamic_cast(pPlugin); if (pInformationPlugin != 0) { _informationPlugins.insert(pInformationPlugin); updateInformationPluginGui(); } ShortInformationPlugin* pShortInformationPlugin = dynamic_cast(pPlugin); if (pShortInformationPlugin != 0) { addShortInformationPlugin(dynamic_cast(pPlugin)); } if (dynamic_cast(pPlugin)) { addActionPlugin(dynamic_cast(pPlugin)); } } void PackageSearchImpl::addPlugin(NPlugin::PluginContainer* pPlugin) { assert(pPlugin!= 0); // add all plugins offered by this container vector offeredPlugins = pPlugin->offeredPlugins(); for ( vector::iterator it = offeredPlugins.begin(); it != offeredPlugins.end(); ++it) addPlugin(pPlugin->requestPlugin(*it)); } void PackageSearchImpl::removePlugin(NPlugin::Plugin* pPlugin) { qDebug() << "Removing plugin " << pPlugin->name(); using namespace NPlugin; SearchPlugin* pSPlugin = dynamic_cast(pPlugin); if (pSPlugin) { _searchPlugins.erase(pSPlugin); updateSearchPluginGui(); } InformationPlugin* pIPlugin = dynamic_cast(pPlugin); if (pIPlugin) { _informationPlugins.erase(pIPlugin); updateInformationPluginGui(); } ShortInformationPlugin* pSIPlugin = dynamic_cast(pPlugin); if (pSIPlugin) { _shortInformationPlugins.erase(pSIPlugin); // _pPackageListViewControl->removeColumn(pSIPlugin->shortInformationCaption()); } ActionPlugin* pAPlugin = dynamic_cast(pPlugin); if (pAPlugin) { vector actions = pAPlugin->actions(); for (vector::const_iterator it = actions.begin(); it != actions.end(); ++it) { const NPlugin::Action* pAction = *it; if (pAction->packageAction()) _packageActions.erase( std::find(_packageActions.begin(), _packageActions.end(), pAction->action()) ); } } } ///////////////////////////////////////////////////// // IPluginUser Helper Methods /////////////////////// ///////////////////////////////////////////////////// void PackageSearchImpl::addShortInformationPlugin(NPlugin::ShortInformationPlugin* pPlugin) { _shortInformationPlugins.insert(pPlugin); } void PackageSearchImpl::addActionPlugin(NPlugin::ActionPlugin* pPlugin) { vector actions = pPlugin->actions(); for (vector::const_iterator it = actions.begin(); it != actions.end(); ++it) { const NPlugin::Action* pAction = *it; if (!pAction->menu().isEmpty()) { map::const_iterator jt = _nameToMenu.find(pAction->menu()); QMenu* pMenu; if (jt != _nameToMenu.end()) { pMenu = jt->second; } else { qWarning() << "Requested to add to an unknown menu \"" << pAction->menu() << "\" in plugin " << pPlugin->name() << ".\n" << "Added to system menu instead."; pMenu = _pSystemMenu; } pMenu->addAction(pAction->action()); } if (!pAction->toolBar().isEmpty()) { map::const_iterator jt = _nameToToolBar.find(pAction->toolBar()); QToolBar* pToolBar; if (jt != _nameToToolBar.end()) { pToolBar = jt->second; } else { qWarning() << "Requested to add to an unknown toolbar \"" << pAction->toolBar() << "\" in plugin " << pPlugin->name() << "\n" << "Added to main toolbar instead."; pToolBar = _pMainToolBar; } pToolBar->addAction(pAction->action()); } if (pAction->packageAction()) { _packageActions.push_back(pAction->action()); } } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// NPackageSearch::PackageDisplayWidget* PackageSearchImpl::packageView() { return static_cast(_pPackageView); } void PackageSearchImpl::updateSearchPluginGui() { // remove all pages _pInputWidgetsContainer->clear(); // the next lines create a new layout for the _pShortSearchFrame so // to have an empty frame so adding the information widgets will result in the // correct order delete _pShortSearchFrame->layout(); QVBoxLayout* pLayout = new QVBoxLayout(_pShortSearchFrame); pLayout->setMargin(5); pLayout->setSpacing(10); NExtStd::for_each(_searchPlugins.begin(), _searchPlugins.end(), &PackageSearchImpl::addSearchPluginToGui, this); if (_pInputWidgetsContainer->count()>0) _pInputWidgetsContainer->setCurrentIndex(0); } void PackageSearchImpl::addSearchPluginToGui(NPlugin::SearchPlugin* pPlugin) { assert(pPlugin); // add the input widget if (pPlugin->inputWidget() != 0) { _pInputWidgetsContainer->addTab(pPlugin->inputWidget(), pPlugin->inputWidgetTitle()); } // add the short input widget if (pPlugin->shortInputAndFeedbackWidget()!=0) { QWidget* pWidget = pPlugin->shortInputAndFeedbackWidget(); // store if the widget was shown to as reparenting destroys this state bool hidden = pWidget->isHidden(); // reparenting was the only way which seemed to work to get the widgets where I wanted them :-( pWidget->setParent(_pShortSearchFrame); _pShortSearchFrame->layout()->addWidget(pWidget); pWidget->setHidden(hidden); } } void PackageSearchImpl::updateInformationPluginGui() { _pInformationContainer->clear(); bool detailPageAdded = false; // add all information plugins in order of their priorities, inserting the details // information page between for (InformationPluginContainer::const_iterator it = _informationPlugins.begin(); it != _informationPlugins.end(); ++it) { NPlugin::InformationPlugin* pPlugin = *it; if ( !detailPageAdded && (pPlugin->informationPriority() >= _DETAILS_INFORMATION_PRIORITY) ) { _pInformationContainer->addTab(_pDetailsView, tr("Details")); detailPageAdded = true; } if (pPlugin->informationWidget() != 0) // if the plugin offers an information widget { _pInformationContainer->addTab( pPlugin->informationWidget(), pPlugin->informationWidgetTitle() ); } } if (!detailPageAdded) _pInformationContainer->addTab(_pDetailsView, tr("Details")); _pInformationContainer->setCurrentIndex(0); updatePackageInformation(_currentPackage); } NPlugin::ShortInformationPlugin* PackageSearchImpl::getShortInformationPluginWithCaption( const QString caption) const { NPlugin::ShortInformationCaptionEquals predicat(caption); ShortInformationPluginContainer::const_iterator it = find_if(_shortInformationPlugins.begin(), _shortInformationPlugins.end(), predicat); if (it == _shortInformationPlugins.end()) return 0; else return *it; } void PackageSearchImpl::onClearSearch() { for_each(_searchPlugins.begin(), _searchPlugins.end(), mem_fun(&NPlugin::SearchPlugin::clearSearch)); } bool PackageSearchImpl::FilterPackages::operator()(const string& package) { return _pPlugin->filterPackage(package); } void PackageSearchImpl::onSearchChanged(NPlugin::SearchPlugin*) { reportBusy(0, tr("Evaluating searches")); using namespace NPlugin; using namespace wibble::operators; std::set result; bool first = true; // keeps track if this is the first search which produces results // evaluate plugins which do not uses filter technique for (SearchPluginContainer::iterator it = _searchPlugins.begin(); it != _searchPlugins.end(); ++it) { SearchPlugin* pPlugin = *it; if (!pPlugin->isInactive()) { if (!pPlugin->usesFilterTechnique()) { if (first) { result = pPlugin->searchResult(); first = false; } else result &= pPlugin->searchResult(); // create the intersection } } } // filter the resulting packages through the filter plugins for (SearchPluginContainer::iterator it = _searchPlugins.begin(); it != _searchPlugins.end(); ++it) { SearchPlugin* pPlugin = *it; if (!pPlugin->isInactive()) { // if we had no search which returned a result set if (first) { // the result set contains all packages available for (set::const_iterator it = _packages.begin(); it != _packages.end(); ++it) result.insert(*it); first = false; } if (pPlugin->usesFilterTechnique()) { std::set newResult; FilterPackages fp(pPlugin); // copy the packages which are matched by the package filter to newResult NExtStd::copy_if( result.begin(), result.end(), inserter(newResult, newResult.begin()), fp ); swap(newResult, result); } } } // if at least one search was active if (!first) { setPackagesFound(result.size()); if (packageView()->scoreColumnVisible()) _pScoreDisplayPlugin->updateScores(result); } else { setPackagesFound(-1); result.clear(); } packageView()->setPackages(result); reportReady(0); } void PackageSearchImpl::updatePackageInformation(const QString & package) { qDebug() << "updatePackageInformation(" << package << ")"; _pDetailsView->clear(); QString detailedText; // information text for "Details" tab (in HTML) for ( InformationPluginContainer::iterator it = _informationPlugins.begin(); it != _informationPlugins.end(); ++it ) { NPlugin::InformationPlugin* pPlugin = (*it); if (package.isEmpty()) { pPlugin->clearInformationWidget(); } else { if ( pPlugin->offersInformationText()) { try { detailedText += pPlugin->informationText(toString(package)); } // simply ignore it if the package was not available for this plugin catch (NPlugin::PackageNotFoundException& e) {} catch (std::exception& e) { qWarning() << "Plugin " << (*it)->name() << " failed to provide detailed information\n" << "e.what(): " << e.what(); } catch (...) { qWarning() << "Plugin " << (*it)->name() << " failed to provide detailed information (unknown exception thrown)"; } } if (_pInformationContainer->currentWidget() == pPlugin->informationWidget()) { // update the tab only if it is currenly active try { pPlugin->updateInformationWidget(toString(package)); } catch (std::exception& e) { qWarning() << "Plugin " << (*it)->name() << " failed to update information\n" << "e.what(): " << e.what(); } catch (...) { qWarning() << "Plugin " << (*it)->name() << " failed to update information (unknown exception thrown)"; } } } } _pDetailsView->setHtml("

" + detailedText + "

"); } void PackageSearchImpl::onInformationPageChanged() { if (_currentPackage.isEmpty()) // if no package was selected return; for ( InformationPluginContainer::iterator it = _informationPlugins.begin(); it != _informationPlugins.end(); ++it ) { if (_pInformationContainer->currentWidget() == (*it)->informationWidget()) // show the page only if it is currenly active { try { (*it)->updateInformationWidget(toString(_currentPackage)); } catch (std::exception& e) { qWarning() << "Plugin " << (*it)->name() << " failed to update information\n" << "e.what(): " << e.what(); } catch (...) { qWarning() << "Plugin " << (*it)->name() << " failed to update information (unknown exception thrown)"; } } } } void PackageSearchImpl::onControlPlugins() { _pPluginManager->showControlDialog(this); } void PackageSearchImpl::onPreferences() { NPackageSearch::SettingsDlg dlg(_network, this); // TODO grey out SUDO button if sudo is not available switch (NApplication::RunCommand::gainRootCommand()) { case NApplication::SU: dlg._pSuButton->setChecked(true); break; case NApplication::SUDO: dlg._pSudoButton->setChecked(true); break; } // if sudo is not executable if (! (QFile::permissions(NApplication::GainRootPaths::sudo) & QFile::ExeUser) ) dlg._pSudoButton->setEnabled(false); vector plugins = _pPluginManager->getLoadedPlugins(); for_each(plugins.begin(), plugins.end(), bind1st( mem_fun(&NPackageSearch::SettingsDlg::addPlugin), &dlg) ); if ( dlg.exec() == QDialog::Accepted ) { if (dlg._pSuButton->isChecked()) NApplication::RunCommand::setGainRootCommand(NApplication::SU); else if (dlg._pSudoButton->isChecked()) NApplication::RunCommand::setGainRootCommand(NApplication::SUDO); _network = dlg.networkSettings(); for_each( plugins.begin(), plugins.end(), mem_fun(&NPlugin::PluginContainer::applySettings) ); } } void PackageSearchImpl::closeEvent(QCloseEvent* pE) { saveSettings(); pE->accept(); } void PackageSearchImpl::onLinkClicked( const QUrl& link) { if ( link.scheme() == QString("package") ) { selectNewPackage(link.path()); } else { QDesktopServices::openUrl(link); } } void PackageSearchImpl::onForward() { setCurrentPackage(_viewHistory.forward()); updateBrowseToolbar(); } void PackageSearchImpl::onBack() { setCurrentPackage(_viewHistory.back()); updateBrowseToolbar(); } void PackageSearchImpl::selectNewPackage(const QString& package) { qDebug() << "selectNewPackage(" << package << ") called"; if (package.isEmpty()) { setPackageActionsEnabled(false); _pDetailsView->clear(); } else { // reselect the package even if already selected to reflect changes due to a changed search setCurrentPackage(package); if ( _viewHistory.empty() || _viewHistory.current() != package) { _viewHistory.append(package); updateBrowseToolbar(); } } } void PackageSearchImpl::onPackageSelectionChanged(QString package) { if (!package.isEmpty()) { selectNewPackage(package); } } void PackageSearchImpl::updateBrowseToolbar() { _pForwardButton->setEnabled(_viewHistory.forwardPossible()); _pBackButton->setEnabled(_viewHistory.backPossible()); } void PackageSearchImpl::onHelpContentsAction() { static QDialog* pDlg = new QDialog(this); static QVBoxLayout* pMainLayout = new QVBoxLayout(pDlg); static QTextBrowser *pHelpWindow = new QTextBrowser(pDlg); pHelpWindow->setWindowTitle(tr("Package Search Help Page")); pHelpWindow->setSource(_docDir+"content.html"); pMainLayout->addWidget(pHelpWindow); pDlg->resize(520,560); pDlg->show(); } void PackageSearchImpl::onHelpAboutAction() { NPackageSearch::PackageSearchAboutDlg dlg; dlg.exec(); } void PackageSearchImpl::setPackagesFound(int number) { QString output(""); if (number == -1) output += "No Search Active"; else output += QString().setNum(number)+" Packages Found"; output += (""); _pPackagesFoundDisplay->setText(output); } void PackageSearchImpl::setCurrentPackage( const QString & package ) { setPackageActionsEnabled(true); // if the package to be shown is not the one selected in the package view, deselect the // one in the package view if (packageView()->selectedPackage() != package) packageView()->clearSelection(); if (package != _currentPackage) { _currentPackage = package; // select the package in the package selection combo box // this triggers a selectNewPackage() call but it returns immidiately because // package == _currentPackage int i = _pPackageSelection->findText(package); // if we have a package which is in the package list, select it from there if (i != -1) _pPackageSelection->setCurrentIndex(i); // if the package is not in the package list, change the text to reflect // the current package else _pPackageSelection->setEditText(package); } // update the package information even if the current package did not change // to reflect changes due to a changed search updatePackageInformation(package); } void PackageSearchImpl::setPackageActionsEnabled(bool enabled) { for (list::iterator it = _packageActions.begin(); it != _packageActions.end(); ++it) (*it)->setEnabled(enabled); } void PackageSearchImpl::checkAptDbForUpdates() { _pApt->checkCacheUpdates(); } void PackageSearchImpl::setTranslationDir(const QDir& dir) { _pPluginManager->setTranslationDir(dir); } void PackageSearchImpl::updateXapianDatabase() { setEnabled(false); NApplication::RunCommand* pCommand = NApplication::ApplicationFactory::getInstance()->getRunCommand(""); pCommand->addArgument("/usr/sbin/update-apt-xapian-index"); pCommand->addArgument("-f"); pCommand->startAsRoot(); while (!pCommand->finished()) { pCommand->waitForFinished(500); qApp->processEvents(); } // reload new xapian database delete _pXapianDatabase; _pXapianDatabase = new Xapian::Database(ept::axi::path_db()); setEnabled(true); } void PackageSearchImpl::makeHandleVisible(QSplitterHandle* pSplitterHandle) { QVBoxLayout *layout = new QVBoxLayout(pSplitterHandle); layout->setSpacing(0); layout->setMargin(0); QFrame *line = new QFrame(pSplitterHandle); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); layout->addWidget(line); } packagesearch-2.7.11build1/src/packagesearchimpl.h0000644000000000000000000003020713507430555016766 0ustar // // C++ Interface: packagesearchimpl // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __PACKAGESEARCHIMPL_H_2004_03_21 #define __PACKAGESEARCHIMPL_H_2004_03_21 #include #include #include #include #include "ui_packagesearch.h" // NPlugin #include "iprovider.h" #include "ipluginuser.h" // NBrowser #include "history.h" #include "networksettings.h" class QCloseEvent; class QDir; class QToolBar; class QSplitterHandle; class TagSelection; namespace NPlugin { class Plugin; class ActionPlugin; class SearchPlugin; class InformationPlugin; class ShortInformationPlugin; class PluginManager; class ScoreDisplayPlugin; } namespace NPackageSearch { class PackageDisplayWidget; } namespace Xapian { class Database; } namespace ept { namespace apt { class Apt; } namespace debtags { class Vocabulary; } } using namespace std; /** Predicate to compare pointer to plugins by priority. */ template class LesserPriority : binary_function { public: bool operator()(PluginType* p1, PluginType* p2); }; /** @brief The central class for the application, creating all the relevant objects. * * @author Benjamin Mesing */ class PackageSearchImpl : public QMainWindow, public Ui::PackageSearch, public NPlugin::IProvider, public NPlugin::IPluginUser { Q_OBJECT public: typedef set PluginContainer; typedef set > SearchPluginContainer; typedef set > InformationPluginContainer; typedef set > ShortInformationPluginContainer; PackageSearchImpl( QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::Window ); ~PackageSearchImpl(); struct Exception { Exception(const string& errorMsg) : _errorMsg(errorMsg) {} Exception(const char* errorMsg) : _errorMsg(errorMsg) {} string _errorMsg; }; /** @name IProvider interface * * These functions implement the IProvider interface. */ //@{ virtual QString iconDir() const { return _iconDir; }; virtual void setEnabled(bool enabled); virtual QString currentPackage() const { return _currentPackage; }; virtual QPushButton* createClearButton(QWidget* pParent = 0, const char* name = 0) const; virtual void reportError(const QString& title, const QString& message); virtual void reportWarning(const QString& title, const QString& message); virtual void reportBusy(NPlugin::Plugin* pPlugin, const QString& message); virtual void reportReady(NPlugin::Plugin* pPlugin); virtual QMainWindow* mainWindow() { return this; } virtual QStatusBar* statusBar() { return QMainWindow::statusBar(); } virtual const set& packages() const; virtual NUtil::IProgressObserver* progressObserver() const; virtual void reloadAptFrontCache(); const ept::apt::Apt& apt() const { return *_pApt; } const ept::debtags::Vocabulary& vocabulary() const { return *_pVocabulary; } const Xapian::Database& xapian() const { return *_pXapianDatabase; } virtual QNetworkAccessManager* network(); //@} /** @name IPluginUser interface * * These functions implement the IPluginUser interface. */ //@{ // documented in base class virtual void addPlugin(NPlugin::Plugin* pPlugin); /** @brief Finds every reference to plugin and remove it so that pPlugin can be safely deleted. * * @param pPlugin the plugin to be removed */ void removePlugin(NPlugin::Plugin* pPlugin); //@} /** @brief Adds the given plugin to the SearchWindow. * * @param pPlugin the plugin to be added */ virtual void addPlugin(NPlugin::PluginContainer* pPlugin); /** @brief Sets the directory were translations are stored. */ virtual void setTranslationDir(const QDir& dir); public slots: /** Call this function after the dialog is shown to initialize the whole system. */ void initialize(); /** @brief This method checks, if the apt-cache has changed and if neccessary reloads * the apt database. * * Currently it is periodically called by a timer. */ void checkAptDbForUpdates(); protected slots: /** @brief This let the views show all information available about the package. * * This request all plugins to update their information widgets and gets their * information text.\n * If package is empty, the views will be cleared. * @note Do not call this function directly, but call setCurrentPackage() instead. */ virtual void updatePackageInformation(const QString & package); /** @brief Evaluates the plugin search results and displays them in the GUI. * * This is called whenever the search of a SearchPlugin changes. * @param pPlugin the plugin where the search changed or 0 if no originator is known */ virtual void onSearchChanged(NPlugin::SearchPlugin* pPlugin); virtual void onClearSearch(); /** This is called whenever the user selects another information page. */ virtual void onInformationPageChanged(); /** This shows the control dialog for the plugins. */ virtual void onControlPlugins(); /** This shows a settings dialog. */ virtual void onPreferences(); virtual void saveSettings(); /** @brief Loads the settings for packagesearch and the plugins. * * Must be called after setting _pPluginManager but before calling loadPlugins(). * The settings will be stored in a data structure, and applied when the plugins * are loaded. */ virtual void loadSettings(); void onLinkClicked(const QUrl& link); void onForward(); void onBack(); /** @brief Called, whenever the selected package in the package list changes. * * It calls selectNewPackage if package is not empty, otherwise it does nothing * (and thus _currentPackage remains unchanged). */ void onPackageSelectionChanged(QString package); /** @brief This chooses the given package to be shown and adds it to the history if * different from the current entry. * * If it is called with an empty or a null string, it deselect the currently selected * package and set the current package to be empty. * @see setCurrentPackage() */ void selectNewPackage(const QString & package); /** @brief This sets the package selected for display to package. * * It updates the combobox which shows the package which triggers the showPackageInformation() * function. It does not add an entry to the history. * * @param package the new current package, should be a valid package * @see selectNewPackage() */ void setCurrentPackage( const QString & package ); /** @brief Enables/ Disables the browse buttons */ void updateBrowseToolbar(); void onHelpContentsAction(); void onHelpAboutAction(); /** @brief Sets the number of packages that were found. * * This information is displayed in the dialog. * @param number number of packages found, hand -1 if no search is active */ void setPackagesFound( int number ); protected: /** @brief Returns the package view (which is a QTableWidget) casted to PackageDisplayWidget. */ NPackageSearch::PackageDisplayWidget* packageView(); /** @brief Called by addPlugin(NPlugin::Plugin*) if the plugin is an short information plugin. * * This was added to improve readability of the addPlugin() function. */ void addShortInformationPlugin(NPlugin::ShortInformationPlugin* pPlugin); /** @brief Called by addPlugin(NPlugin::Plugin*) if the plugin is an short information plugin. * * This was added to improve readability of the addPlugin() function. */ void addActionPlugin(NPlugin::ActionPlugin* pPlugin); /** Actions to perform on close. */ virtual void closeEvent(QCloseEvent* pE); /** @brief Funtion object to filter search results with plugins which uses the filter * technique. */ class FilterPackages { NPlugin::SearchPlugin* _pPlugin; public: /** @param pPlugin the plugin to be used for filtering. * @pre pPlugin.isInactive() == false ^ pPlugin.usesFilterTechnique() == true */ FilterPackages(NPlugin::SearchPlugin* pPlugin) : _pPlugin(pPlugin) {}; bool operator()(const string& package); /** Call this after you've finished all filtering - the results will be written to the * OpSet handed in the constructor. */ // void finishFiltering(); }; /** @brief Updates search interface. * * Shows the search input for all available search plugins in the correct order, * removing outdated inputs. */ void updateSearchPluginGui(); /** @brief Adds the widgets of the search plugin to the GUI. * * @pre pPlugin != 0 */ void addSearchPluginToGui(NPlugin::SearchPlugin* pPlugin); /** @brief Updates information interface. * * Shows the information widget for all available information plugins in the correct * order, removing outdated widgets. */ void updateInformationPluginGui(); /** @brief Sets all the actions operating on packages to be enabled/disabled. * * @see #_packageActions */ void setPackageActionsEnabled(bool enabled); /** @brief Returns the ShortInformationPlugin with caption. * * @returns the plugin found or 0 if no plugin was found*/ NPlugin::ShortInformationPlugin* getShortInformationPluginWithCaption(const QString caption) const; /** @brief Runs update-apt-xapian-index as root and returns only after it is finished. */ void updateXapianDatabase(); private: /** @brief Sets up the missing toobar icons. */ void initToolbars(); /** @brief Sets up the missing menu entries. * * @pre initToolbars() must have been called, because it relies on it to be initialized. */ void initMenus(); /** @brief Determines the directories for icons, help files, etc. */ void initDirectories(); void makeHandleVisible(QSplitterHandle* pSplitterHandle); ept::apt::Apt* _pApt; ept::debtags::Vocabulary* _pVocabulary; Xapian::Database* _pXapianDatabase; QString _iconDir; QString _docDir; /** Holds the name of the package currently shown in the information container. */ QString _currentPackage; NBrowser::History _viewHistory; /** @brief Maps the toolbar names to the corresponding toolbar. */ map _nameToToolBar; /** @brief Maps the menu names to the corresponding menu. */ map _nameToMenu; QToolBar* _pMainToolBar; QAction* _pWhatsThisAction; /** @brief Holds all the actions that operate on packages. * * Those will be enabled and disabled, depending if a package was selected. */ list _packageActions; /** @brief This object takes care of the plugins loading and unloading. * * this will be added to it as a IPluginUser, so it will be informed about * changes in the plugin. */ NPlugin::PluginManager* _pPluginManager; /** All search plugins currently installed. * * They are kept sorted by there priority in ascending order. */ SearchPluginContainer _searchPlugins; /** @brief All information plugins currently installed. * * They are kept sorted by there priority in ascending order. */ InformationPluginContainer _informationPlugins; /** @brief All short information plugins currently installed. * * They are kept sorted by there priority in decending order. */ ShortInformationPluginContainer _shortInformationPlugins; /** @brief This holds a pointer to the page for the details section. */ QWidget* _pInformationDetailsPage; /** Holds the priority for the details page. */ const uint _DETAILS_INFORMATION_PRIORITY; /** Holds the name of the settings file to be used ($HOME/.packagesearch)*/ QString _settingsFilename; /** @brief This holds all packages available on the system. * * It bases on the apt-cache so it assumes those packages as all. It is * lazy initialized. */ mutable set _packages; /** @brief This plugin is used to display the package names in the short description. */ NPlugin::Plugin* _pPackageNamePlugin; /** @brief This plugin is used to display and calculate the scores for the packages. */ NPlugin::ScoreDisplayPlugin* _pScoreDisplayPlugin; /** @brief Timer used to periodically call checkAptDbForUpdates(). */ QTimer timer; NUtil::NetworkSettings _network; }; #endif // __PACKAGESEARCHIMPL_H_2004_03_21 packagesearch-2.7.11build1/src/plugin.cpp0000644000000000000000000000067113507430555015156 0ustar // // C++ Implementation: plugin // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "plugin.h" #include namespace NPlugin { const QString Plugin::_emptyString; QDomElement Plugin::loadSettings(const QDomElement source) { return source; } void Plugin::saveSettings(NXml::XmlData&, QDomElement) const { } } packagesearch-2.7.11build1/src/plugin.h0000644000000000000000000000473613507430555014631 0ustar #ifndef __PLUGIN_H_2004_06_21 #define __PLUGIN_H_2004_06_21 #include #include "ixmlstorable.h" namespace NPlugin { class IProvider; /** * @author Benjamin Mesing */ class Plugin : NXml::IXmlStorable { protected: /** This offers an empty string for its children. */ static const QString _emptyString; public: virtual ~Plugin() {}; /** * * @param pProvider provides information needed by the plugin */ virtual void init(IProvider* pProvider) = 0; /** * Enables/Disables all widgets that belong to this plugin. * @param enabled */ virtual void setEnabled(bool enabled) = 0; /** * Shows or hides the given plugin. * @param visible */ virtual void setVisible(bool visible) = 0; /** @brief Returns the name of the plugin, this should be unique in the whole application. * * This name should be used in the IPluginFactory to create the plugins for * the container. * * You will probably want code like this: * @code class MyPlugin : SearchPlugin // SearchPlugin inherits Plugin { public: static const QString PLUGIN_NAME = "MyPlugin"; // note that you can't initialize this way in C++ virtual QString name() const { return PLUGIN_NAME; } [...] }; * @endcode * It is probably sufficient to make the name unique in the plugin container it belongs * to, but I'm not sure about this. */ virtual QString name() const = 0; /** @brief Returns the title of the plugin, this is how it will be shown in configuration * dialogs or similar. * */ virtual QString title() const = 0; /** @returns a brief description for this plugin. */ virtual QString briefDescription() const = 0; /** @returns a description for this plugin. */ virtual QString description() const = 0; /** @brief Loads the settings from the element node. * * Does nothing in its default implementation. * @param source data used as source for loading */ virtual QDomElement loadSettings(const QDomElement source); /** @brief Save the settings from this plugin container into the given XML tree * * Does nothing in its default implementation.\n * If settings are to be saved they must contain of a single tree with a * QDomElement in the root which must be added under parent. * @param parent the parent under which to add the settings * @param outData XML Document which owns parent */ virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; }; } // namespace NPlugin #endif // __PLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/plugincompare.h0000644000000000000000000000425213507430555016171 0ustar // // C++ Interface: plugincompare // // Description: // I had to remove the operators from the interface files, because I got // multiple definition linker errors with the functions in the interface // files. (I think it has something to do with the Q_OBJECT macro present // in both files which triggered the linker error (plugin.h and searchplugin.h) // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __PLUGINCOMPARE_H_2004_08_12 #define __PLUGINCOMPARE_H_2004_08_12 #include "searchplugin.h" #include "informationplugin.h" #include "shortinformationplugin.h" namespace NPlugin { /** @brief Compares the plugins by priority, or if the priority is equal compares the * adresses of the objects. * * Ensures: \f$(pPlugin1 < pPlugin2) \wedge (pPlugin2 < pPlugin1) \Rightarrow (pPlugin1 == pPlugin2)\f$ */ bool operator<(const SearchPlugin& plugin1, const SearchPlugin& plugin2) { if (plugin1.searchPriority() == plugin2.searchPriority()) return &plugin1 < &plugin2; else return plugin1.searchPriority() < plugin2.searchPriority(); } /** @brief Compares the plugins by priority, or if the priority is equal compares the * adresses of the objects. * * Ensures: \f$(pPlugin1 < pPlugin2) \wedge (pPlugin2 < pPlugin1) \Rightarrow (pPlugin1 == pPlugin2)\f$ */ bool operator<(const InformationPlugin& plugin1, const InformationPlugin& plugin2) { if (plugin1.informationPriority() == plugin2.informationPriority()) return &plugin1 < &plugin2; else return plugin1.informationPriority() < plugin2.informationPriority(); } /** @brief Compares the plugins by priority, or if the priority is equal compares the * adresses of the objects. * * Ensures: \f$(pPlugin1 < pPlugin2) \wedge (pPlugin2 < pPlugin1) \Rightarrow (pPlugin1 == pPlugin2)\f$ */ bool operator<(const ShortInformationPlugin& plugin1, const ShortInformationPlugin& plugin2) { if (plugin1.shortInformationPriority() == plugin2.shortInformationPriority()) return &plugin1 < &plugin2; else return plugin1.shortInformationPriority() < plugin2.shortInformationPriority(); } } #endif // __PLUGINCOMPARE_H_2004_08_12 packagesearch-2.7.11build1/src/plugincontainer.cpp0000644000000000000000000000030413507430555017052 0ustar #include "plugincontainer.h" namespace NPlugin { QWidget* PluginContainer::getSettingsWidget(QWidget*) { return 0; } void PluginContainer::applySettings() { return; } } // namespace NPlugin packagesearch-2.7.11build1/src/plugincontainer.h0000644000000000000000000000750413507430555016530 0ustar #ifndef __PLUGINCONTAINER_H_2004_06_23 #define __PLUGINCONTAINER_H_2004_06_23 #include #include #include #include "iplugininformer.h" #include "ixmlstorable.h" #include "xmldata.h" using namespace std; class QWidget; class QAction; namespace NPlugin { class Plugin; class IProvider; /** This collects the information about a plugin. * * It should be offered by every plugin via a get_pluginInformation() * function. */ struct PluginInformation { PluginInformation(const string& name_="", const string& version_="", const string& author_="") { name = name_; version = version_; author = author_; } string name; string version; string author; /** Compares to plugins are identical by comparing all available attributes. */ bool operator==(const PluginInformation& p) const { return name == p.name && version == p.version && author == p.author; } }; // Interface PluginContainer // // class PluginContainer : public IPluginInformer, public NXml::IXmlStorable { public: virtual ~PluginContainer() {}; /** @brief Loads and initializes all offered plugins. * * @param pProvider the provider which offers information for the plugins * @returns if the plugin was successfully initialized, if it returns false, * the plugin container should be deleted by the plugin user as the plugin * container is in an undefined state and function calls might crash the * application. */ virtual bool init(IProvider* pProvider) = 0; /** This returns the names of all plugins offered by this container. */ virtual vector offeredPlugins() const = 0; /** @brief Get the plugin with the given name. The plugin is not * initialized so call Plugin::init() for it. * * Release the requested plugins with releasePlugin(). * @param name name of the plugin to be requested * @returns the plugin with this name, or 0 if no such plugin exists */ virtual Plugin* requestPlugin(const string& name) = 0; /** Gets a list of all plugins currently loaded. */ virtual vector getLoadedPlugins() const = 0; /** @brief This signals that a user of the Plugin no longer uses it. * * It is used to see if we can delete shared resources. The plugin * will be deleted by this function. If the plugin is not owned by this * container the function will return immidiately. * @param pPlugin the plugin to be released */ virtual void releasePlugin(Plugin* pPlugin) = 0; /** Returns the title of this container. */ virtual QString title() const = 0; /** @brief Returns the name of this plugin. * * This must correspond to the name of the library where the plugin is stored in. * It is case sensitive. It should be a unique identifier from all available plugins. */ virtual string name() const = 0; /** @brief This will return a widget to control the Plugin Container * (i.e. enabling/disabling parts of the plugin container and make * settings for the plugins). * * The PluginContainer will cease control about the widget to the calling * function and if this does not care, the widget will be deleted with its * parent (through the QT Garbage collection).\n * The Widget will be connected to the container, so the container can * handle the input from the widget.\n * The default implementation (if not overloaded) is to return 0. * @param pParent the parent for this control widget. It will delete the * widget returned if destroyed */ virtual QWidget* getSettingsWidget(QWidget* pParent); /** @brief Call this to apply the settings configured in the settings widget. * * Call this function only after getSettingsWidget() was called and before * the widget is deleted.\n * The default implementation is empty. */ virtual void applySettings(); }; } // namespace NPlugin #endif // __PLUGINCONTAINER_H_2004_06_23 packagesearch-2.7.11build1/src/plugincontrol.ui0000644000000000000000000000623613507430555016415 0ustar PluginControl 0 0 505 274 PluginControl 6 10 10 10 10 QAbstractItemView::SelectRows 0 4 Enabled Version Author Location 0 0 0 0 0 Qt::Horizontal QSizePolicy::Expanding 61 20 0 0 Close qPixmapFromMimeSource pushButton3 clicked() PluginControl accept() 456 257 446 272 packagesearch-2.7.11build1/src/plugincontroldlgmeditator.cpp0000644000000000000000000000527213507430555021161 0ustar // // C++ Implementation: plugincontroldlgmeditator // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "plugincontroldlgmeditator.h" #include #include #include #include // NPlugin #include "pluginmanager.h" #include #include "ui_plugincontrol.h" using namespace std; namespace NPlugin { PluginControlDlgMeditator::PluginControlDlgMeditator(PluginManager* pPluginManager) { _pPluginManager = pPluginManager; _pPluginDisplay = 0; } PluginControlDlgMeditator::~PluginControlDlgMeditator() { } QString PluginControlDlgMeditator::pluginName(int row) { return _pPluginDisplay->item(row, 0)->text(); } QString PluginControlDlgMeditator::pluginDirectory(int row) { return _pPluginDisplay->item(row, 3)->text(); } void PluginControlDlgMeditator::displayDialog(QWidget* pParent) { typedef PluginManager::PluginData PluginData; QDialog dlg(pParent); Ui::PluginControl uiDlg; uiDlg.setupUi(&dlg); _pPluginDisplay = uiDlg._pPluginDisplay; _pPluginDisplay->verticalHeader()->hide(); vector plugins = _pPluginManager->getAvailablePlugins(); _pPluginDisplay->setRowCount(plugins.size()); int row = 0; for (vector::iterator it = plugins.begin(); it != plugins.end(); ++it, ++row) { const PluginData& pd = *it; QTableWidgetItem* pItem = new QTableWidgetItem(toQString(pd.name())); _pPluginDisplay->setItem(row, 0, pItem); pItem->setFlags(Qt::ItemIsUserCheckable | pItem->flags()); pItem->setCheckState( (pd.pPlugin == 0) ? Qt::Unchecked : Qt::Checked); pItem = new QTableWidgetItem(toQString(pd.version())); _pPluginDisplay->setItem(row, 1, pItem); pItem = new QTableWidgetItem(toQString(pd.author())); _pPluginDisplay->setItem(row, 2, pItem); pItem = new QTableWidgetItem(toQString(pd.directory)); _pPluginDisplay->setItem(row, 3, pItem); } connect(_pPluginDisplay, SIGNAL(cellChanged(int, int)), SLOT(onCellChanged(int, int))); dlg.exec(); _pPluginDisplay = 0; } void PluginControlDlgMeditator::onCellChanged(int row, int column) { QString pluginName = this->pluginName(row); QTableWidgetItem* pItem = _pPluginDisplay->item(row, column); // if the plugin was requested to be loaded, and it was not loaded before if (pItem->checkState() == Qt::Checked && !_pPluginManager->isLoaded(pluginName)) { if (_pPluginManager->loadPlugin(toString(pluginDirectory(row)), toString(pluginName)) == 0) pItem->setCheckState(Qt::Unchecked); } else if (pItem->checkState() == Qt::Unchecked && _pPluginManager->isLoaded(pluginName)) { _pPluginManager->unloadPlugin(toString(pluginName)); } } } packagesearch-2.7.11build1/src/plugincontroldlgmeditator.h0000644000000000000000000000327713507430555020631 0ustar // // C++ Interface: plugincontroldlgmeditator // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_PLUGINCONTROLDLGMEDITATOR_H_2007_12_27 #define __NPLUGIN_PLUGINCONTROLDLGMEDITATOR_H_2007_12_27 #include class QWidget; class QTableWidget; namespace NPlugin { class PluginManager; /** @brief This class is responsible for displaying the dialog control dialog and * handling events caused by the dialog (e.g. unselecting a plugin by a user). * * Hand the PluginManager to the constructor and call displayDialog to show the * plugin control dialog. This will show the plugin to enable and disable plugins. * * @author Benjamin Mesing */ class PluginControlDlgMeditator : public QObject { Q_OBJECT PluginManager* _pPluginManager; /** @brief This points to the list displaying the plugins. * * While the plugin control dialog is not shown, this is set to 0. */ QTableWidget* _pPluginDisplay; // typedef PluginManager::PluginData PluginData; public: PluginControlDlgMeditator(PluginManager* pPluginManager); ~PluginControlDlgMeditator(); void displayDialog(QWidget* pParent); /** Returns the name of the plugin at the given row. * * @pre _pPluginDisplay != 0 */ QString pluginName(int row); /** Returns the directory of the plugin at the given row. * * @pre _pPluginDisplay != 0 */ QString pluginDirectory(int row); private slots: /** This should be called only when a plugin was selected or deselected. */ void onCellChanged(int row, int column); }; } #endif // __NPLUGIN_PLUGINCONTROLDLGMEDITATOR_H_2007_12_27 packagesearch-2.7.11build1/src/plugininformer.cpp0000644000000000000000000000144613507430555016721 0ustar // // C++ Implementation: plugininformer // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include "plugininformer.h" #include "ipluginuser.h" namespace NPlugin { PluginInformer::PluginInformer() { } PluginInformer::~PluginInformer() { } void PluginInformer::removePluginUser(IPluginUser* pUser) { _users.erase(pUser); } void PluginInformer::informAddPlugin(Plugin* pPlugin) { for_each(_users.begin(), _users.end(), bind2nd(mem_fun(&IPluginUser::addPlugin), pPlugin) ); } void PluginInformer::informRemovePlugin(Plugin* pPlugin) { for_each(_users.begin(), _users.end(), bind2nd(mem_fun(&IPluginUser::removePlugin), pPlugin) ); } }; packagesearch-2.7.11build1/src/plugininformer.h0000644000000000000000000000205613507430555016364 0ustar // // C++ Interface: plugininformer // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __PLUGININFORMER_H_2004_09_08 #define __PLUGININFORMER_H_2004_09_08 #include #include "iplugininformer.h" using namespace std; namespace NPlugin { class IPluginUser; class Plugin; /** @brief Used to manage and inform plugin users. * * Do not have too many observers as it has linear complexity in * the operation. * @author Benjamin Mesing */ class PluginInformer : public IPluginInformer { typedef set PluginUserContainer; PluginUserContainer _users; public: PluginInformer(); ~PluginInformer(); // documented in base class virtual void addPluginUser(IPluginUser* pUser) { _users.insert(pUser); }; // documented in base class virtual void removePluginUser(IPluginUser* pUser); virtual void informAddPlugin(Plugin* pPlugin); virtual void informRemovePlugin(Plugin* pPlugin); }; }; #endif // __PLUGININFORMER_H_2004_09_08 packagesearch-2.7.11build1/src/pluginmanager.cpp0000644000000000000000000003022113507430555016503 0ustar // // C++ Implementation: pluginmanager // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include #include #include #include #include #include #include #include #include #include // for dl*() #include "extalgorithm.h" // NPlugin #include "pluginmanager.h" #include "plugincontainer.h" #include "ipluginuser.h" #include "iprovider.h" #include "plugincontroldlgmeditator.h" // NXml #include "xmldata.h" // NUtil #include "progressdisplaydlg.h" #include "helpers.h" namespace NPlugin { PluginManager::PluginManager(vector directories, IProvider* pProvider) : _settingsVersion("0.2") { _pProvider = pProvider; _pProgressDlg = 0; _directories = directories; _pControlDialog = 0; } PluginManager::~PluginManager() { } ///////////////////////////////////////////////////// // IPluginUser Interface ///////////////////////////////////////////////////// void PluginManager::addPlugin(Plugin* pPlugin) { informAddPlugin(pPlugin); } void PluginManager::removePlugin(Plugin* pPlugin) { informRemovePlugin(pPlugin); } ///////////////////////////////////////////////////// // Other functions ///////////////////////////////////////////////////// void PluginManager::loadPlugins() { NUtil::ProgressDisplayDlg dlg(_pProvider->mainWindow(), "PluginProgressDlg", true); _pProgressDlg = &dlg; dlg.show(); vector plugins = getAvailablePlugins(); for (vector::const_iterator it = plugins.begin(); it != plugins.end(); ++it) { // if the plugin is not disabled and no such plugin is already loaded if (_disabledPlugins.find(it->name())==_disabledPlugins.end() && it->pPlugin==0) { dlg.setText("Loading " + toQString(it->name())); dlg.setProgress(0); qApp->processEvents(); loadPlugin(it->directory, it->name()); dlg.setProgressRange(0, 100, false); dlg.setProgress(100); dlg.setText(""); qApp->processEvents(); } } _pProgressDlg = 0; } vector PluginManager::getLoadedPlugins() const { vector result; for (map::const_iterator it = _plugins.begin(); it != _plugins.end(); ++it) { if (it->second.pPlugin != 0) result.push_back(it->second.pPlugin); } return result; } // This function first collects the plugins available in the plugin directories. // Afterwards it checks the loaded plugins and searches those in the ones collected // above where it appends the load specific information. If a loaded plugin is // not available in the available ones it will be appended at the result. vector PluginManager::getAvailablePlugins() const { vector result; set collectedPlugins; // iterate through the plugins and add the loaded plugins to result and loadedPlugins { for (map::const_iterator it = _plugins.begin(); it != _plugins.end(); ++it ) { // if the plugin is loaded if (it->second.pPlugin != 0) { result.push_back(it->second); collectedPlugins.insert(it->first); } } } for (vector::const_iterator it = _directories.begin(); it != _directories.end(); ++it) { const string& directory = *it; dlerror(); // clear error messages QDir pluginDir(toQString(directory), "lib*.so"); // only care for library files QStringList pluginFiles = pluginDir.entryList(QDir::Files); // try to load the library and fetch the creator function for each file // in the current directory, if both is possible the plugin is available for (QStringList::iterator jt = pluginFiles.begin(); jt != pluginFiles.end(); ++jt) { qStrDebug("opening plugin file " + pluginDir.absolutePath() + "/" + *jt); PluginData pluginData; string libraryFile = toString(*jt); string pluginName = libraryFile.substr(3,libraryFile.length() - 6); // remove "lib" and ".so" // skip this library file if the plugin was already found if (collectedPlugins.find(pluginName) != collectedPlugins.end()) continue; void* libraryHandle = dlopen((directory + libraryFile).c_str(), RTLD_NOW); checkDlError(); if (libraryHandle) // loading was possible { typedef PluginInformation (*GetPluginDataFkt)(); GetPluginDataFkt getInformation = GetPluginDataFkt(dlsym(libraryHandle, "get_pluginInformation")); // if the function could be received this libary seems to contain a plugin if (getInformation != 0) { pluginData.directory = directory; if (getInformation != 0) pluginData.information = getInformation(); result.push_back(pluginData); // this prevents a reload of the plugin information, if the plugin is also // existent in a plugin path later in the list collectedPlugins.insert(pluginData.name()); } dlclose(libraryHandle); // close the library again } } dlerror(); // dismiss possible error messages } return result; } PluginContainer* PluginManager::loadPlugin( const string& directory, const string& pluginName) { if (isLoaded(toQString(pluginName))) return 0; typedef PluginContainer* (*NewPluginFkt)(); typedef PluginInformation (*GetPluginDataFkt)(); // holds if a progress dialog was available when calling this method bool progressDialogAvailable = (_pProgressDlg != 0); if (!progressDialogAvailable) { _pProgressDlg = new NUtil::ProgressDisplayDlg(_pProvider->mainWindow(), "PluginProgressDlg", true); // _pProgressDlg->show(); } PluginContainer* pPlugin = 0; dlerror(); // dismiss pending errors void* libraryHandle = dlopen((directory + "lib" + pluginName + ".so").c_str(), RTLD_LAZY); if (!checkDlError()) // if no error occured { assert(libraryHandle != 0); PluginData pluginData; // get the function for creating the plugin NewPluginFkt func = NewPluginFkt(dlsym(libraryHandle, ("new_" + pluginName).c_str() )); if (func != 0) // if no error occured on load (i.e. the symbol was present) { // setup translation QString locale = QLocale::system().name(); qDebug() << "Translation dir " << _translationDir.path(); QTranslator* pTranslator = new QTranslator(); if (pTranslator->load(_translationDir.filePath( toQString(pluginName) + "_" + locale))) { qDebug() << "Loaded translation " << toQString(pluginName) + "_" + locale; QApplication::installTranslator(pTranslator); pluginData.pTranslator = pTranslator; } else { delete pTranslator; pTranslator = 0; // warn if we have non-english and no translation if (!locale.startsWith("en_")) qWarning() << tr("No translation for plugin ") << toQString(pluginName) << tr(" found for current locale ") << locale; } pPlugin = func(); // fetch the plugin qDebug() << "Loaded plugin: " << pPlugin->title(); pluginData.directory = directory; pluginData.libraryHandle = libraryHandle; GetPluginDataFkt getInformation = GetPluginDataFkt( dlsym(libraryHandle, "get_pluginInformation")); if (getInformation != 0) pluginData.information = getInformation(); if (pPlugin) // if loading was successful, add the plugin to the map // and remove it from the disbled plugins if necessary { pPlugin->addPluginUser(this); if (pPlugin->init(_pProvider)) // if the container initializes successfully { pluginData.pPlugin = pPlugin; map::const_iterator it = _pluginSettings.find(pPlugin->name()); if ( it != _pluginSettings.end() ) pPlugin->loadSettings(it->second); _plugins[pluginName] = pluginData; } else { QApplication::removeTranslator(pluginData.pTranslator); delete pluginData.pTranslator; pluginData.pTranslator = 0; delete pPlugin; pPlugin = 0; } } } else // an error while trying to load the lib.so file { dlclose(libraryHandle); dlerror(); // dismiss possible errors } } if (!progressDialogAvailable) { delete _pProgressDlg; _pProgressDlg = 0; } return pPlugin; } void PluginManager::unloadPlugin(PluginContainer* pPlugin) { QString pluginTitle = pPlugin->title(); map::iterator it = _plugins.find(pPlugin->name()); PluginData& pluginData = it->second; assert(pluginData.pPlugin != 0); delete pluginData.pTranslator; pluginData.pTranslator = 0; // add the settings of the plugin in _pluginSettings { NXml::XmlData data("SettingsDocument"); pPlugin->saveSettings(data, data.root()); // if the plugin has settings if (!data.root().firstChild().isNull()) // can not use operator[] because this would have violated the const specification _pluginSettings.insert( make_pair(pPlugin->name(), data.root().firstChild().toElement()) ); } delete pPlugin; pluginData.pPlugin = 0; dlclose(pluginData.libraryHandle); _pProvider->statusBar()->showMessage("Unloaded plugin " + pluginTitle, 3000); } void PluginManager::unloadPlugin(const string& pluginName) { PluginToDataMap::iterator it = _plugins.find(pluginName); unloadPlugin(it->second.pPlugin); } void PluginManager::saveSettings(NXml::XmlData& outData, QDomElement parent) const { // take a look at the pluginmanager.dtd file for the XML structure QDomElement pluginManager = outData.addElement(parent, "PluginManager"); outData.addAttribute(pluginManager, _settingsVersion, "settingsVersion"); QDomElement disabledPlugins = outData.addElement(pluginManager, "DisabledPlugins"); QDomElement pluginSettings = outData.addElement(pluginManager, "PluginSettings"); vector availablePlugins = getAvailablePlugins(); for (vector::const_iterator it = availablePlugins.begin(); it != availablePlugins.end(); ++it) { const PluginData& pluginData = *it; // if the plugin was loaded if (pluginData.pPlugin != 0) { qDebug() << "Saving " << pluginData.name().c_str(); pluginData.pPlugin->saveSettings(outData, pluginSettings); } // the plugin was not loaded else { QDomElement plugin = outData.addElement(disabledPlugins, "Plugin"); { outData.addAttribute(plugin, pluginData.name(), "name"); } // store the loaded settings for the disabled plugins if available map::const_iterator jt = _pluginSettings.find(pluginData.name()); if ( jt != _pluginSettings.end() ) { outData.importNode(jt->second, pluginSettings, true); } } } } QDomElement PluginManager::loadSettings(QDomElement source) { if (source.tagName() != "PluginManager") return source; // take a look at the pluginmanager.dtd file for the XML structure QDomElement disabledPlugins = NXml::getFirstElement(source.firstChild()); { QDomElement plugin = NXml::getFirstElement(disabledPlugins.firstChild()); while (!plugin.isNull()) { string disabledPlugin; NXml::getAttribute(plugin, disabledPlugin, "name"); _disabledPlugins.insert(disabledPlugin); plugin = NXml::getNextElement(plugin); } } // the node which holds all settings of the different plugins QDomElement pluginSettings = NXml::getNextElement(disabledPlugins); { QDomElement settings = NXml::getFirstElement(pluginSettings.firstChild()); while (!settings.isNull()) { // qDebug() << "Loaded " << settings.tagName() << " settings"; // the settings for the current plugin _pluginSettings.insert( make_pair(toString(settings.tagName()),settings) ); settings = NXml::getNextElement(settings); } } return NXml::getNextElement(source); } void PluginManager::showControlDialog(QWidget* pParent) { PluginControlDlgMeditator mediator(this); mediator.displayDialog(pParent); } bool PluginManager::checkDlError() const { const char* error = dlerror(); if (error) { cerr << "Dynamic Library error: " << error <second.pPlugin != 0 ) return true; return false; } void PluginManager::setTranslationDir(const QDir& dir) { _translationDir = dir; } } // namespace NPlugin packagesearch-2.7.11build1/src/pluginmanager.dtd0000644000000000000000000000200013507430555016466 0ustar packagesearch-2.7.11build1/src/pluginmanager.h0000644000000000000000000002552613507430555016164 0ustar // // C++ Interface: pluginmanager // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __PLUGINMANAGER_H_2004_08_11 #define __PLUGINMANAGER_H_2004_08_11 #include #include #include #include #include #include #include #include // NXml #include #include // NPlugin #include "plugininformer.h" #include "ipluginuser.h" #include "plugincontainer.h" // also for PluginInformation using namespace std; class QDialog; class QDir; class QWidget; class QTableWidget; class QTranslator; class PluginProgressDlg; namespace NXml { class XmlData; } namespace NUtil { class IProgressObserver; class ProgressDisplayDlg; } namespace NPlugin { class IProvider; class PluginListItem; /** @brief The PluginManager can be used to load and manage plugins. * * It informs all IPluginUser instances registered via the * addPluginUser() function about loading and unloading of plugins. * * The settings for all plugins will be loaded on loadSettings() and stored * in the PluginManager. If a plugin is loaded, the plugin manager will * search for the settings of this plugin and call its loadSettings function. * * The settings of the manager and the plugins can be stored via the saveSettings * function, where the settings for all active plugins and the plugins * which are disabled will be stored. If a plugin is no longer available * (i.e. neither disabled nor active) its settings will not be saved even * if they were loaded before. * * Only one plugin of a given name can be loaded at a time, however multiple * plugins with that name can be available in different directories. * * @author Benjamin Mesing */ class PluginManager : public QObject, public PluginInformer, public NXml::IXmlStorable, public IPluginUser { Q_OBJECT friend class PluginControlDlgMeditator; private: typedef vector PluginUserContainer; PluginUserContainer _users; /** Stores the location were to search for translation file for the plugins. */ QDir _translationDir; protected: /** @brief This holds information about the plugin. */ struct PluginData { PluginData() : information() { libraryHandle = 0; pPlugin = 0; pTranslator = 0; } PluginInformation information; string directory; bool informationEquals(const PluginData& pd) const { return information == pd.information; } /** Accessors for convenience */ const string& name() const { return information.name; } /** Accessors for convenience */ const string& version() const { return information.version; } /** Accessors for convenience */ const string& author() const { return information.author; } /** @brief A pointer to the instance of the plugin, 0 if the plugin is not loaded. */ PluginContainer* pPlugin; /** @brief The translator for the plugin (if any, otherwise 0). */ QTranslator* pTranslator; /** @brief A handle of the loaded library for this plugin, 0 if the plugin is not loaded. */ void* libraryHandle; /** @brief operator so it can be used in sets */ bool operator<(const PluginData& pd) const { if (name() != pd.name()) return name() < pd.name(); if (version() != pd.version()) return version() < pd.version(); if (author() != pd.author()) return author() < pd.author(); // if (directoy != pd.directoy) return directory < pd.directory; } }; /** @brief Function object to find plugins with equal information. */ struct PluginInformationEquals { PluginInformationEquals(const PluginData& pd) : _pd(pd) {} bool operator()(const PluginData& pd) const { return pd.information == _pd.information; } bool operator()(const pair& p) const { return p.second.information == _pd.information; } private: const PluginData& _pd; }; /** @brief Function object to find plugins which are equal. */ struct PluginEquals { PluginEquals(const PluginData& pd) : _pd(pd) {} bool operator()(const PluginData& pd) const { return pd.information == _pd.information && pd.directory == _pd.directory; } private: const PluginData& _pd; }; /** @brief Function object to find plugins point to the same plugin. */ struct SamePlugin { SamePlugin(const PluginData& pd) : _pd(pd) {} bool operator()(const PluginData& pd) const { return _pd.name() == pd.name() && _pd.author() == pd.author(); } private: const PluginData& _pd; }; /** This returns all plugins currently available. * * These are plugins that are in the plugin directories and plugins * which are loaded but not longer in any directory. */ vector getAvailablePlugins() const; /** @brief This loads the plugin and informs the plugin users about the loading. * * The plugin will be added to the list of loaded plugins. If a plugin with * the same pluginName is already loaded, loading will be aborted. * @param directory the directory where the plugin is located * @param pluginName the name of the plugin * @returns a pointer to the plugin loaded, 0 if loading failed or a plugin of * the given name was already loaded. * @note You should have called loadSettings before because else * this function will be unloaded. */ PluginContainer* loadPlugin( const string& directory, const string& pluginName); /** @brief This unloads the plugin and informs the plugin users about the unloading. * * It will delete the plugin and close the library, so make sure that every reference * is removed in the plugin users. * @param pPlugin the plugin to be unloaded * @pre the plugin must be loaded */ void unloadPlugin(PluginContainer* pPlugin); /** @brief This unloads the plugin and informs the plugin users about the unloading. * * It will delete the plugin and close the library, so make sure that every reference * is removed in the plugin users. * @param pluginName the name of the plugin to be unloaded * @pre the plugin must be loaded */ void unloadPlugin(const string& pluginName); private: friend class PluginListItem; /** @brief The directories the plugin manager searches for plugins. */ vector _directories; /** @brief The provider which provides informations for the plugins. */ IProvider* _pProvider; /** @brief This holds the settings for all available plugins. * * This is done to hold the settings for plugins which are not * loaded so they can also be saved. * * Implementation note: The QDomElements here come from the QDomTree * loaded on loadSettings(). Because of the QDom semantics (including * garbage collection) they won't be deleted. So it is save to access * them. */ map _pluginSettings; /** @brief The version of the settings tree used by this class. */ const QString _settingsVersion; /** @brief This holds a pointer to the dialog displaying the status of the plugin * loading process * * This is only set if the dialog is currently active, else it holds 0. */ NUtil::ProgressDisplayDlg* _pProgressDlg; /** @brief This holds a pointer to the control dialog. * * This is only set if the dialog is currently active, else it holds 0. */ QDialog* _pControlDialog; /** @brief This check if an error occured in a dl* function and if so prints * the error message to stderr. * @returns true if an error occured, else false */ bool checkDlError() const; typedef map PluginToDataMap; /** @brief This datastructure maps all plugins that were loaded at least once * to their plugin data. * * When plugins are unloaded the will not be removed from this map. */ PluginToDataMap _plugins; // typedef map PluginToDataMap; /** @brief This holds the plugins currently loaded. * * It maps them to the corresponding data. */ // PluginToDataMap _loadedPlugins; /** @brief Holds the plugins which were marked as disabled in the settings. * * This is not kept up to date, but only set on loadSettings(). It is * used by loadPlugins() to not load the plugins disabled according to * the settings. */ set _disabledPlugins; /** Holds the listview where the plugins are shown to the user, only set * while the plugin dialog is shown. */ QTableWidget* _pPluginDisplay; public: /** * * @param directories the directories the the manager searches for plugins * @param pProvider the provider which provides informations for the plugins * @param pUser the user that cares for the plugin changes */ PluginManager(vector directories, IProvider* pProvider); ~PluginManager(); /** Returns true if a plugin with the given name is already loaded, else false. */ bool isLoaded(QString name) const; /** @brief Save the settings from this plugin container into the given XML tree * * Currently the only information is the plugins which are disabled. * @param outData XML Document which owns parent * @param parent the parent where under to add the settings */ virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; /** @brief Loads the settings for the plugins from inData. * * Currently the only information is the plugins which are disabled. * @param source the element where the information is stored * @returns the next sibling of source or source if source did was not a * node which contains information for the pluginmanager */ virtual QDomElement loadSettings(QDomElement source); /** @brief This shows a dialog which can be used to control the plugins. * * It allows to enable and disable the different plugins. * * @param pParent the widget this dialog should be have as parent, * hand 0 if it should be a top level dialog */ void showControlDialog(QWidget* pParent); /** @brief This loads all available plugins excluding the disabled ones. * * This loads all plugins found in the plugin directories. It does not load plugins * which are disabled.\n * Use loadSettings() to read the disabled plugins. */ void loadPlugins(); /** This returns the plugins currently loaded * */ vector getLoadedPlugins() const; /** @brief Returns the observer where to report progress to. * * @returns 0 if no observer is available */ NUtil::IProgressObserver* progressObserver(); /** @name IPluginUser Interface * * Implementation of the IPluginUser interface. This works as a multiplex, * forwarding each addPlugin/removePlugin from the controlled PluginContainers * to all IPluginUsers registered. */ //@{ virtual void addPlugin(Plugin* pPlugin); virtual void removePlugin(Plugin* pPlugin); //@} /** @brief Sets the directory were translations are stored. */ void setTranslationDir(const QDir& dir); }; }; #endif // __PLUGINMANAGER_H_2004_08_11 packagesearch-2.7.11build1/src/plugins/0000755000000000000000000000000013507430555014631 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin/0000755000000000000000000000000013507430555016634 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin/.moc/0000755000000000000000000000000013507430555017470 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin/.obj/0000755000000000000000000000000013507430555017464 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin/.ui/0000755000000000000000000000000013507430555017327 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin/aptactionplugin.cpp0000644000000000000000000001404613507430555022546 0ustar // // C++ Implementation: aptactionplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "aptactionplugin.h" #include #include #include // NApplication #include "applicationfactory.h" #include "runcommand.h" // NPlugin #include #include "iaptmediator.h" #include "helpers.h" namespace NPlugin { const QString AptActionPlugin::PLUGIN_NAME = "AptActionPlugin"; AptActionPlugin::AptActionPlugin(IAptMediator* pMediator) : _title("Apt-Action Plugin"), _briefDescription("Offers the menu and toolbar entries"), _description("This plugin offers the menu and toolbar entries for the APT plugin. " "This includes the possibilities to install and remove packages."), _pMediator(pMediator) { QAction* pQAptUpdateAction = new QAction(tr("Update Apt-Package Database"), this); pQAptUpdateAction->setStatusTip(tr("Updates the package database")); _pUpdateAction = new Action(pQAptUpdateAction, false, "System"); connect(pQAptUpdateAction, SIGNAL(triggered(bool)), SLOT(onUpdateAction())); QAction* pQReloadDbAction = new QAction(QObject::tr("Reload Package Database"), this); pQReloadDbAction->setStatusTip(tr("Reloads the package database from disk " "(e.g. if apt-get update was performed externally).")); _pReloadDbAction = new Action(pQReloadDbAction, false, "System"); connect(pQReloadDbAction, SIGNAL(triggered(bool)), SLOT(onReloadAction())); QAction* pQAptGetLineAction = new QAction(tr("Copy Command Line for Installing Package to Clipboard"), this); pQAptGetLineAction->setToolTip(tr("Creates a command line to install the selected package, and copies it to the clipboard")); pQAptGetLineAction->setStatusTip(tr("Creates a command line to install the selected package, and copies it to the clipboard")); connect(pQAptGetLineAction, SIGNAL(triggered(bool)), SLOT(onCreateInstallLineAction())); _pCreateInstallLineAction = new Action(pQAptGetLineAction, true); QAction* pQAptGetInstallAction = new QAction(tr("Install/Update Package"), this); pQAptGetInstallAction->setToolTip(tr("Installs/updates the package")); pQAptGetInstallAction->setStatusTip(tr("Installs/updates the package")); connect(pQAptGetInstallAction, SIGNAL(triggered(bool)), SLOT(onInstallAction())); _pInstallAction = new Action(pQAptGetInstallAction, true, "Packages", "Main"); QAction* pQAptGetRemoveAction = new QAction(tr("Remove Package"), this); pQAptGetRemoveAction->setToolTip(tr("Removes the package")); pQAptGetRemoveAction->setStatusTip(tr("Removes the package")); connect(pQAptGetRemoveAction, SIGNAL(triggered(bool)), SLOT(onRemoveAction())); _pRemoveAction = new Action(pQAptGetRemoveAction, true, "Packages", "Main"); QAction* pQPurgeAction = new QAction(tr("Purge Package"), this); pQPurgeAction->setToolTip(tr("Removes package including configuration")); pQPurgeAction->setStatusTip(tr("Removes package including configuration")); connect(pQPurgeAction, SIGNAL(triggered(bool)), SLOT(onPurgeAction())); _pPurgeAction = new Action(pQPurgeAction, true, "Packages"); QAction* pQSeparatorAction = new QAction(this); pQSeparatorAction->setSeparator(true); _pSeparatorAction = new Action(pQSeparatorAction, true, "System"); } AptActionPlugin::~AptActionPlugin() { delete _pUpdateAction; delete _pReloadDbAction; delete _pSeparatorAction; delete _pCreateInstallLineAction; delete _pInstallAction; delete _pRemoveAction; delete _pPurgeAction; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void AptActionPlugin::init(IProvider* pProvider) { _pProvider = pProvider; QIcon installIcon(_pProvider->iconDir()+"install-package.png"); _pInstallAction->action()->setIcon(installIcon); QIcon removeIcon(_pProvider->iconDir()+"remove-package.png"); _pRemoveAction->action()->setIcon(removeIcon); }; ///////////////////////////////////////////////////// // ActionPlugin Interface ///////////////////////////////////////////////////// vector AptActionPlugin::actions() const { vector actions; actions.push_back(_pSeparatorAction); actions.push_back(_pUpdateAction); actions.push_back(_pReloadDbAction); actions.push_back(_pCreateInstallLineAction); actions.push_back(_pInstallAction); actions.push_back(_pRemoveAction); actions.push_back(_pPurgeAction); return actions; } ///////////////////////////////////////////////////// // Other Methods ///////////////////////////////////////////////////// void AptActionPlugin::onCreateInstallLineAction() { QClipboard *pCb = QApplication::clipboard(); pCb->setText(installationToolCommand() + " install "+_pProvider->currentPackage(), QClipboard::Clipboard); pCb->setText(installationToolCommand() + " install "+_pProvider->currentPackage(), QClipboard::Selection); } void AptActionPlugin::onInstallAction() { installOrRemove(true); } void AptActionPlugin::onRemoveAction() { installOrRemove(false); } void AptActionPlugin::onPurgeAction() { installOrRemove(false, true); } void AptActionPlugin::onUpdateAction() { _pMediator->updateAptDatabase(); } void AptActionPlugin::onReloadAction() { _pMediator->reloadAptDatabase(); } void AptActionPlugin::installOrRemove(bool install, bool purge) { NApplication::RunCommand* pCommand = NApplication::ApplicationFactory::getInstance()->getRunCommand(""); pCommand->addArgument(installationToolCommand()); if (install) pCommand->addArgument("install"); else { if (purge) pCommand->addArgument("purge"); else pCommand->addArgument("remove"); } pCommand->addArgument(_pProvider->currentPackage()); try { pCommand->startAsRoot(); } catch (const NException::RuntimeException& e) { _pProvider->reportError(tr("Unable to launch command"), toQString(e.description()) + QString(tr("\nPlease configure to use \"apt\" as package administration tool " "(Packagesearch->Settings->Apt Plugins)")) ); delete pCommand; } } QString AptActionPlugin::installationToolCommand() { return _pMediator->installationToolCommand(); } } packagesearch-2.7.11build1/src/plugins/aptplugin/aptactionplugin.h0000644000000000000000000000572713507430555022221 0ustar // // C++ Interface: aptactionplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_APTACTIONPLUGIN_H_2005_08_31 #define __NPLUGIN_APTACTIONPLUGIN_H_2005_08_31 #include #include #include "installationtool.h" namespace NPlugin { class IAptMediator; /** @brief Plugin offerings actions realted to apt. * * The actions offered are: *

    *
  • update database
  • *
  • reload package database
  • *
  • install package
  • *
  • remove package
  • *
* * @author Benjamin Mesing */ class AptActionPlugin : public QObject, public NPlugin::ActionPlugin { Q_OBJECT const QString _title; const QString _briefDescription; const QString _description; /** @brief Action used to update the apt database. */ Action* _pUpdateAction; /** @brief Action used to reload the apt database. */ Action* _pReloadDbAction; Action* _pCreateInstallLineAction; /** @name Package Actions * * @brief Actions for installing/removing packages. */ //@{ Action* _pInstallAction; Action* _pRemoveAction; Action* _pPurgeAction; //@} Action* _pSeparatorAction; IProvider* _pProvider; IAptMediator* _pMediator; protected Q_SLOTS: void onCreateInstallLineAction(); void onInstallAction(); void onRemoveAction(); void onPurgeAction(); void onUpdateAction(); void onReloadAction(); protected: /** @brief Installs or removes the current package. * * @param install if true, the package will be installed, if false it will be removed * @param purge determines if the package shall be purged on removal (no effect for * installing) */ void installOrRemove(bool install, bool purge = false); public: static const QString PLUGIN_NAME; AptActionPlugin(IAptMediator* pMediator); ~AptActionPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @brief Returns the QAction object for the #_pAptUpdateAction. */ QAction* qAptUpdateAction() const { return _pUpdateAction->action(); } /** @brief Returns the QAction object for the #_pReloadDbAction. */ QAction* qReloadDbAction() const { return _pReloadDbAction->action(); } /** @name ActionPlugin Interface * * Implementation of the ActionPlugin Interface. */ //@{ virtual vector actions() const; //@} private: /** @brief Shortcut for calling _aptMediator->installationToolCommand() */ QString installationToolCommand(); }; } #endif // __NPLUGIN_APTACTIONPLUGIN_H_2005_08_31 packagesearch-2.7.11build1/src/plugins/aptplugin/aptfrontpackage.cpp0000644000000000000000000001113513507430555022512 0ustar // // C++ Implementation: aptfrontpackage // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "aptfrontpackage.h" #include #include #include #include #include namespace NApt { QString AptFrontPackage::_emptyString; AptFrontPackage::AptFrontPackage(const ept::apt::Apt& pApt, const std::string& sourcePackage) : _pApt(&pApt), _source(sourcePackage), m_rec(0) { } AptFrontPackage::~AptFrontPackage() { delete m_rec; } const ept::apt::PackageRecord& AptFrontPackage::rec() const { if (!m_rec) m_rec = new ept::apt::PackageRecord(_pApt->rawRecord(_source)); return *m_rec; } QString AptFrontPackage::name() const { return toQString(_source);; } QString AptFrontPackage::essential() const { return _emptyString; } QString AptFrontPackage::priority() const { return _emptyString; } QString AptFrontPackage::section() const { return toQString(rec().section(string()));; } QString AptFrontPackage::installedSize() const { return toQString(rec()["Installed-Size"]); } uint AptFrontPackage::getInstalledSize() const { return rec().installedSize(); } QString AptFrontPackage::maintainer() const { return toQString(rec().maintainer(string())); } QString AptFrontPackage::architecture() const { return toQString(rec().architecture(string())); } QString AptFrontPackage::source() const { return toQString(rec().source(string()));; } QString AptFrontPackage::version() const { ept::apt::Version ver = _pApt->candidateVersion(_source); // FIXME: I used candidateVersion, but there is also anyVersion //if (_source.candidateVersion().valid()) //return toQString(_source.candidateVersion().versionString()); return toQString(ver.version()); } QString AptFrontPackage::replaces() const { return toQString(rec().replaces(string()));; //return AptFrontPackage::getRelation(Relation::Replaces); } QString AptFrontPackage::provides() const { return toQString(rec().provides(string()));; } QString AptFrontPackage::preDepends() const { return toQString(rec().preDepends(string()));; } QString AptFrontPackage::depends() const { return toQString(rec().depends(string()));; } QString AptFrontPackage::recommends() const { return toQString(rec().recommends(string()));; } QString AptFrontPackage::suggests() const { return toQString(rec().suggests(string()));; } QString AptFrontPackage::conflicts() const { return toQString(rec().conflicts(string()));; } QString AptFrontPackage::filename() const { return toQString(rec().filename(string()));; } QString AptFrontPackage::size() const { return toQString(rec()["Size"]); } uint AptFrontPackage::getSize() const { return rec().size(); } QString AptFrontPackage::md5sum() const { return toQString(rec().md5sum(string()));; } QString AptFrontPackage::conffiles() const { return _emptyString; } QString AptFrontPackage::description() const { // source code taken from libapt, and slightly adapted pkgCache* pPkgCache = const_cast(_pApt->aptPkgCache()); pkgCache::PkgIterator pi = pPkgCache->FindPkg(toString(name())); if (pi.end()) return QString(); for (pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); vi++) { const char* v = vi.VerStr(); if (v == 0) continue; if (rec().version() != v) continue; // Get the translated record pkgRecords Recs(*pPkgCache); pkgCache::DescIterator Desc = vi.TranslatedDescription(); pkgRecords::Parser &P = Recs.Lookup(Desc.FileList()); // TODO currently the language code is not added here // this would break the packagerecord parsing algorithm, should be implemented // in the future though //result << "Description" << ( (strcmp(Desc.LanguageCode(),"") != 0) ? "-" : "" ) << Desc.LanguageCode() << ": " << P.LongDesc(); QString longDescription = toQString(P.LongDesc()); longDescription = longDescription.remove(0, longDescription.indexOf("\n")); return longDescription; } return QString(); } AptFrontPackage::InstalledState AptFrontPackage::installedState() const { ept::apt::PackageState state = _pApt->state(_source); if (state.upgradable()) return UPGRADABLE; if (state.installed()) return INSTALLED; return NOT_INSTALLED; } QString AptFrontPackage::installedVersion() const { ept::apt::Version ver = _pApt->installedVersion(_source); return toQString(ver.version()); } QString AptFrontPackage::shortDescription() const { return toQString(rec().shortDescription(string()));; } QString AptFrontPackage::homepage() const { return toQString(rec().lookup("Homepage")); } } packagesearch-2.7.11build1/src/plugins/aptplugin/aptfrontpackage.h0000644000000000000000000000462413507430555022164 0ustar // // C++ Interface: aptfrontpackage // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_APTFRONTPACKAGE_H_2005_12_26 #define __NAPT_APTFRONTPACKAGE_H_2005_12_26 #include #include namespace ept { class Aggregator; namespace apt { class Apt; class PackageRecord; } } namespace NApt { /** @brief A package class using libept. * * Note that accessing the package remains valid only as long as * the underlying ept::apt::Apt objekt does not change. * It also holds a pointer to the corresponding ept::apt::PackageRecord * object which also must not become invalid. * * @author Benjamin Mesing */ class AptFrontPackage : public IPackage { const ept::apt::Apt* _pApt; //typedef ept::configuration::apt::cache::Relation Relation; std::string _source; mutable ept::apt::PackageRecord* m_rec; const ept::apt::PackageRecord& rec() const; public: AptFrontPackage(const ept::apt::Apt& pApt, const std::string& sourcePackage); ~AptFrontPackage(); virtual QString name() const; virtual QString essential() const; virtual QString priority() const; virtual QString section() const; virtual QString installedSize() const; virtual QString maintainer() const; virtual QString architecture() const; virtual QString source() const; virtual QString version() const; virtual QString replaces() const; virtual QString provides() const; virtual QString preDepends() const; virtual QString depends() const; virtual QString recommends() const; virtual QString suggests() const; virtual QString conflicts() const; virtual QString filename() const; virtual QString size() const; virtual QString md5sum() const; virtual QString conffiles() const; virtual QString description() const; virtual InstalledState installedState() const; virtual QString installedVersion() const; virtual QString shortDescription() const; virtual QString homepage() const; virtual uint getInstalledSize() const; virtual uint getSize() const; /** @brief Returns if the source apt-front package is valid. */ bool isValid() const { return !_source.empty(); } protected: /** @brief Returns a string representation for all relations of the handed type. */ //QString getRelation(Relation::Type type) const; private: static QString _emptyString; }; } #endif // __NAPT_APTFRONTPACKAGE_H_2005_12_26 packagesearch-2.7.11build1/src/plugins/aptplugin/aptfrontpackagedb.cpp0000644000000000000000000001460613507430555023026 0ustar // // C++ Implementation: aptfrontpackagedb // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "aptfrontpackagedb.h" #include #include #include #include // NPlugin #include #include #include #include #include namespace NApt { AptFrontPackageDB::AptFrontPackageDB(NPlugin::IProvider* pProvider) : _pProvider(pProvider), _currentPackage(_pProvider->apt(), std::string()) { } AptFrontPackageDB::~AptFrontPackageDB() { } const AptFrontPackage& AptFrontPackageDB::getPackageRecord(const QString& pkg) const { return getPackageRecord(toString(pkg)); } const AptFrontPackage& AptFrontPackageDB::getPackageRecord(const string& package) const { _currentPackage = AptFrontPackage ( _pProvider->apt(), _pProvider->apt().validate(package) ); if (!_currentPackage.isValid()) throw NPlugin::PackageNotFoundException(package); return _currentPackage; } const QString AptFrontPackageDB::getShortDescription(const string& package) const { return getPackageRecord(package).shortDescription(); } IPackage::InstalledState AptFrontPackageDB::getState(const string& package) const { return getPackageRecord(package).installedState(); } void AptFrontPackageDB::reloadPackageInformation(NUtil::IProgressObserver* pObserver) { _pProvider->reloadAptFrontCache(); if (pObserver) pObserver->setProgress(100); } ///////////////////////////////////////////////////// // IAptSearch Interface ///////////////////////////////////////////////////// bool AptFrontPackageDB::search(std::set& result, const QString& pattern, bool searchDescr) const { QStringList includePatterns; includePatterns.push_back(pattern); return search(result, includePatterns, QStringList(), searchDescr); } bool AptFrontPackageDB::search(std::set& result, const QStringList& includePatterns, const QStringList& excludePatterns, bool searchDescr) const { typedef ept::apt::Apt Apt; const Apt& packages = _pProvider->apt(); if (searchDescr) // perform a full text search within the descriptions { try { Xapian::Enquire enq(_pProvider->xapian()); vector incs; // Get the weighted OR include query for (QStringList::const_iterator jt = includePatterns.begin(); jt != includePatterns.end(); ++jt) incs.push_back(jt->toLower().toStdString()); Xapian::Query inc(Xapian::Query::OP_AND, incs.begin(), incs.end()); if (excludePatterns.empty()) { // Build the normal OR query enq.set_query(inc); } else { vector excs; for (QStringList::const_iterator jt = excludePatterns.begin(); jt != excludePatterns.end(); ++jt) // the Xapian index requires all search terms to be lower case excs.push_back(jt->toLower().toStdString()); Xapian::Query exc(Xapian::Query::OP_OR, excs.begin(), excs.end()); // Build the combined AND NOT query enq.set_query(Xapian::Query(Xapian::Query::OP_AND_NOT, inc, exc)); } // Get the 25k best results out of Xapian Xapian::MSet matches = enq.get_mset(0, 25000); for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) { // Filter out results that apt doesn't know if (!packages.isValid(i.get_document().get_data())) continue; result.insert(i.get_document().get_data()); // For reference, this would be the Xapian relevance // i.get_percent(); } // Shouldn't happen } catch (Xapian::Error& e) { qFatal( "%s: %s (%s)\n", e.get_type(), e.get_msg().c_str(), e.get_context().c_str()); } } // search in the package names in both cases (since Xapian-search cannot search within the title, // it can only search for the title starting with the given word (by XPterm*), but that does not find // the search term occuring at the end of the title (e.g. search term "apt" in "python-apt") for ( Apt::iterator it = packages.begin(); it != packages.end(); ++it ) { if (result.find(*it) != result.end()) // if the package is already in the result list continue; QString name = toQString(*it); // will be set to false when one of the include patterns was not found in the package description bool included = true; // check if each included pattern occurs in the package for (QStringList::const_iterator jt = includePatterns.begin(); jt != includePatterns.end(); ++jt) { if ( !searchString(name, *jt, false, false) ) { included = false; break; } } if (included) result.insert(*it); } for (std::set::iterator it = result.begin(); it != result.end();) { bool erase = false; QString name = toQString(*it); for (QStringList::const_iterator jt = excludePatterns.begin(); jt != excludePatterns.end(); ++jt) { if ( searchString(name, *jt, false, false) ) { erase = true; break; } } if (erase) // we cannot erase the current iterator without causing harm, so we do it a little // more complicated result.erase(it++); else ++it; } return result.empty(); } bool AptFrontPackageDB::searchString(const QString& text, const QString& searchPattern, bool caseSensitive, bool wholeWords) { Qt::CaseSensitivity qCaseSensitive = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; if (!wholeWords) // the easy case { return text.contains(searchPattern, qCaseSensitive); } int startIndex = 0; while (startIndex <= text.length()) { int findIndex = text.indexOf(searchPattern, startIndex, qCaseSensitive); // if the search pattern was not found in the remaining string if (findIndex == -1) return false; bool startsAtBoundary = false; // holds if the match started at a word boundary if (findIndex == 0) startsAtBoundary = true; else { QChar characterBefore = text.at(findIndex - 1); startsAtBoundary = !characterBefore.isLetter(); } // if the match starts at a boundary, check if it also ends at one if (startsAtBoundary) { int endIndex = findIndex + searchPattern.length(); // if the match is the end of the text it is a match if (endIndex == text.length()) return true; QChar characterAfter = text.at(endIndex); // if there is a non-letter-character following the match, the search matches if (!characterAfter.isLetter()) return true; } startIndex = findIndex + searchPattern.length(); } assert(false); return false; } } packagesearch-2.7.11build1/src/plugins/aptplugin/aptfrontpackagedb.h0000644000000000000000000000516613507430555022474 0ustar // // C++ Interface: aptfrontpackagedb // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_APTFRONTPACKAGEDB_H_2005_12_26 #define __NAPT_APTFRONTPACKAGEDB_H_2005_12_26 #include #include #include #include "aptfrontpackage.h" namespace NPlugin { class IProvider; } namespace NApt { /** @author Benjamin Mesing */ class AptFrontPackageDB : public IPackageDB, public IAptSearch { // typedef ept::configuration::apt::cache::Package Package; /** @brief The provider instance offering the apt-front cache. */ NPlugin::IProvider* _pProvider; /** @todo TODO currently we return a reference to the current package * in getPackageRecord() -- which changes all the time * * Ensure a sane semantic here. */ mutable AptFrontPackage _currentPackage; public: /** @brief Constructs a new apt-front database, using the apt-front cache of the provider. * * @param pProvider The provider instance offering the apt-front cache. */ AptFrontPackageDB(NPlugin::IProvider* pProvider); ~AptFrontPackageDB(); /** @name IPackageDB Interface * * Implementation of the IPackageDB */ //@{ virtual const AptFrontPackage& getPackageRecord(const QString& pkg) const; virtual const AptFrontPackage& getPackageRecord(const string& package) const; virtual const QString getShortDescription(const string& package) const; virtual IPackage::InstalledState getState(const string& package) const; virtual void reloadPackageInformation(NUtil::IProgressObserver* pObserver); //@} /** @name IAptSearch Interface * * Implementation of the IAptSearch */ //@{ virtual bool search(std::set& result, const QStringList& includePatterns, const QStringList& excludePatterns, bool searchDescr) const; virtual bool search(std::set& result, const QString& pattern, bool searchDescr) const; //@} /** @brief Searches searchPattern within sourceString. * * If searching for whole words only, any non alphabetic character is considered * to be a word boundary. * * @param text the string to search in * @param searchPattern the string to search for * @param caseSensitive if true, the search is case sensitive. * @param wholeWords if true, searching only for whole words within * sourceString to match the search pattern. * * @returns true if the search was successful, else false */ /// @todo add test case static bool searchString(const QString& text, const QString& searchPattern, bool caseSensitive, bool wholeWords); }; } #endif // packagesearch-2.7.11build1/src/plugins/aptplugin/aptplugin.kdev40000644000000000000000000000006713507430555021601 0ustar [Project] Manager=KDevCustomMakeManager Name=aptplugin packagesearch-2.7.11build1/src/plugins/aptplugin/aptplugin.kdevelop0000644000000000000000000000543513507430555022401 0ustar Benjamin Mesing bensmail@gmx.net $VERSION$ KDevTrollProject C++ Qt false false *.o,*.lo,CVS false bash bash_bugs clanlib w3c-dom-level2-html fortran_bugs_gcc gnome1 gnustep gtk gtk_bugs haskell haskell_bugs_ghc java_bugs_gcc java_bugs_sun kde2book opengl pascal_bugs_fp php php_bugs perl perl_bugs python python_bugs qt-kdev3 ruby ruby_bugs sdl stl w3c-svg sw w3c-uaag10 wxwidgets_bugs KDE Libraries (Doxygen) executable true true true false true true true 250 400 250 packagesearch-2.7.11build1/src/plugins/aptplugin/aptplugin.pro0000644000000000000000000000524513507430555021367 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./aptplugin # Target is a library: FORMS += aptsearchpluginshortinputwidget.ui \ installedfilterwidget.ui \ aptsettingswidget.ui HEADERS += aptplugincontainer.h \ aptsearchplugin.h \ packagedescriptionplugin.h \ packagestatusplugin.h \ aptpluginfactory.h \ ipackagedb.h \ iaptsearch.h \ installedversionplugin.h \ availableversionplugin.h \ aptsearchscorecalculationstrategy.h \ complexscorecalculationstrategy.h \ installedfilterwidget.h \ aptsearchpluginshortinputwidget.h \ aptactionplugin.h \ ipackage.h \ aptfrontpackagedb.h \ aptfrontpackage.h \ aptsettingswidget.h \ installationtool.h \ iaptmediator.h SOURCES += aptplugincontainer.cpp \ aptsearchplugin.cpp \ packagedescriptionplugin.cpp \ packagestatusplugin.cpp \ aptpluginfactory.cpp \ ipackagedb.cpp \ iaptsearch.cpp \ installedversionplugin.cpp \ availableversionplugin.cpp \ aptsearchscorecalculationstrategy.cpp \ complexscorecalculationstrategy.cpp \ installedfilterwidget.cpp \ aptsearchpluginshortinputwidget.cpp \ aptactionplugin.cpp \ ipackage.cpp \ aptfrontpackagedb.cpp \ aptfrontpackage.cpp \ aptsettingswidget.cpp \ installationtool.cpp TRANSLATIONS = ../../../translations/aptplugin_de.ts \ ../../../translations/aptplugin_es.ts TEMPLATE = lib VERSION = 0.0.1 INCLUDEPATH = . \ ../../ LIBS += -lapt-pkg PKGCONFIG = libept # Uncomment to see warnings for all unresolved symbols, to catch locations of # missing template instantiations #LIBS += -Wl,--unresolved-symbols=report-all # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined DESTDIR = ../ CONFIG += warn_on \ qt \ thread \ plugin \ stl \ link_pkgconfig MOC_DIR = .moc UI_DIR = .ui QT += xml widgets debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) packagesearch-2.7.11build1/src/plugins/aptplugin/aptplugincontainer.cpp0000644000000000000000000002030013507430555023241 0ustar #include "aptplugincontainer.h" #include #include #include // NPlugin #include #include #include // NUtil #include // NApplication #include "applicationfactory.h" #include "runcommand.h" // NPlugin #include "aptpluginfactory.h" #include "aptsearchplugin.h" #include "aptactionplugin.h" #include "packagestatusplugin.h" #include "packagedescriptionplugin.h" #include "installedversionplugin.h" #include "availableversionplugin.h" #include "aptsettingswidget.h" #include #include extern "C" { NPlugin::PluginContainer* new_aptplugin() { return new NPlugin::AptPluginContainer; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("aptplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } namespace NPlugin { ///////////////////////////////////////////////////// // Constructors/ Destructors ///////////////////////////////////////////////////// AptPluginContainer::AptPluginContainer( ) : BasePluginContainer() { addPlugin("AptSearchPlugin"); addPlugin("AptActionPlugin"); addPlugin("PackageStatusPlugin"); addPlugin("PackageDescriptionPlugin"); addPlugin("InstalledVersionPlugin"); addPlugin("AvailableVersionPlugin"); _pAptSearchPlugin = 0; _pAptActionPlugin = 0; _pPackageStatusPlugin = 0; _pPackageDescriptionPlugin = 0; _pInstalledVersionPlugin = 0; _pAvailableVersionPlugin = 0; _pAptSearch = 0; _pPackageDB = 0; setInstallationTool(NApt::APT); } AptPluginContainer::~AptPluginContainer( ) { unloadAllPlugins(); delete pluginFactory(); delete _pAptSearch; // do not delete, _pAptSearch and _pPackageDB point to the same object // delete _pPackageDB; } ///////////////////////////////////////////////////// // Plugin Container Interface ///////////////////////////////////////////////////// bool AptPluginContainer::init(IProvider* pProvider) { // qDebug("Opening aptfront cache for packages"); // aptFront::cache::Global::get().openPackages(); NUtil::IProgressObserver* pObserver = pProvider->progressObserver(); pObserver->setProgressRange(0, 97, true); NApt::AptFrontPackageDB* aptFrontPackageDB = new NApt::AptFrontPackageDB(pProvider); _pAptSearch = aptFrontPackageDB; _pPackageDB = aptFrontPackageDB; //_pPackageDB = new NApt::DumpAvailPackageDB(pObserver, pProvider->packages().size()); BasePluginContainer::init(pProvider, new AptPluginFactory(pProvider, this, _pPackageDB, _pAptSearch)); pObserver->setProgressRange(97, 98, true); _pAptSearchPlugin = dynamic_cast(requestPlugin("AptSearchPlugin")); _pAptActionPlugin = dynamic_cast(requestPlugin("AptActionPlugin")); _pPackageStatusPlugin = dynamic_cast(requestPlugin("PackageStatusPlugin")); pObserver->setProgressRange(98, 99, true); _pPackageDescriptionPlugin = dynamic_cast(requestPlugin("PackageDescriptionPlugin")); _pInstalledVersionPlugin = dynamic_cast(requestPlugin("InstalledVersionPlugin")); _pAvailableVersionPlugin = dynamic_cast(requestPlugin("AvailableVersionPlugin")); pObserver->setProgressRange(99, 100, true); return true; } QWidget* AptPluginContainer::getSettingsWidget(QWidget* pParent) { _pSettingsWidget = new AptSettingsWidget(pParent); _pSettingsWidget->setInstallationTool(_installationTool); return _pSettingsWidget; } void AptPluginContainer::applySettings() { setInstallationTool(_pSettingsWidget->installationTool()); } ///////////////////////////////////////////////////// // BasePluginContainer Interface ///////////////////////////////////////////////////// QDomElement AptPluginContainer::loadContainerSettings(const QDomElement source) { if (source.tagName() != "ContainerSettings") return source; float settingsVersion; NXml::getAttribute(source, settingsVersion, "settingsVersion", 0.0f); int tool; NXml::getAttribute(source, tool, "installationTool", (int) 0); setInstallationTool((NApt::InstallationTool) tool); return NXml::getNextElement(source); } void AptPluginContainer::saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const { QDomElement containerElement = outData.addElement(parent, "ContainerSettings"); outData.addAttribute(containerElement, 0.1f, "settingsVersion"); outData.addAttribute(containerElement, _installationTool, "installationTool"); } ///////////////////////////////////////////////////// // IAptMediator Interface ///////////////////////////////////////////////////// QStringList AptPluginContainer::searchPatterns() { if (!_pAptSearchPlugin) return QStringList(); return _pAptSearchPlugin->searchPatterns(); } void AptPluginContainer::setInstallationTool(NApt::InstallationTool tool) { _installationTool = tool; } QString AptPluginContainer::installationToolCommand() { return NApt::getInstallationToolCommand(_installationTool); } void AptPluginContainer::updateAptDatabase() { _pAptActionPlugin->qAptUpdateAction()->setEnabled(false); // this will fetch us the update of the db _pCommand = NApplication::ApplicationFactory::getInstance()->getRunCommand("AptUpdateProcess"); connect(_pCommand, SIGNAL(quit()), SLOT(onAptUpdateFinished()) ); QString shell = "/bin/sh"; QString arg1 = "-c"; // this is really ugly, I need to protect this argument, so it is not interpreted // as multiple arguments // first apt-get update is run and then the debtags index is updated, since the // apt database also contains information relevant for the debtags database QString arg2 = "'echo Updateing apt database && " + installationToolCommand() + " update && echo Updateing debtags index && /usr/bin/debtags --local update'"; _pCommand->addArgument(shell); _pCommand->addArgument(arg1); _pCommand->addArgument(arg2); _pCommand->setTitle("Updateing apt database"); try { if ( !_pCommand->startAsRoot() ) { provider()->reportError( tr("Command not executed"), tr("For an unknwon reason, the command could " "not be executed.") ); delete _pCommand; _pCommand = 0; _pAptActionPlugin->qAptUpdateAction()->setEnabled(true); } } catch (const NException::RuntimeException& e) { provider()->reportError(tr("Command not executed"), toQString(e.description())); delete _pCommand; _pCommand = 0; _pAptActionPlugin->qAptUpdateAction()->setEnabled(true); } } void AptPluginContainer::reloadAptDatabase() { _pAptSearch->reloadPackageInformation(0); _pPackageDB->reloadPackageInformation(0); } ///////////////////////////////////////////////////// // AptPluginContainer functions ///////////////////////////////////////////////////// void AptPluginContainer::onAptUpdateFinished() { if (_pCommand->processExitedSuccessful()) { reloadAptDatabase(); } delete _pCommand; _pCommand = 0; _pAptActionPlugin->qAptUpdateAction()->setEnabled(true); // Mornfalls update code via apt-front // [16:36] ben_vos: check aptFront::Manager // [16:36] ben_vos: specifically update() method // [16:37] ben_vos: my update code looks like this: http://rafb.net/paste/results/DQKiGJ84.html // [16:38] ben_vos: just note that it invalidates any entities you may be holding // [16:38] ben_vos: (stable entities will survive the reopen though) // [16:38] stable entities are a lot more expensive though, so don't overdo it with those // [16:39] Cool, thanks, I'll take a look. // [16:39] i also think there are only package/version stable entities implemented /* void TestApp::update() { closeModes(); setActionsEnabled( false ); aptFront::Manager m; m.setProgressCallback( m_progress->callback() ); m.setUpdateInterval( 100000 ); try { m_stack->raiseWidget( m_progress ); m.update(); } catch ( exception::OperationCancelled ) { // ignore } catch (...) { KMessageBox::sorry( this, i18n( "There was an error downloading updates. " ), i18n( "Could not fetch updates" ) ); } kdDebug() << "closing progress widget" << endl; m_stack->raiseWidget( m_list ); setActionsEnabled( true ); notifyPostChange( 0 ); }*/ } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/aptplugin/aptplugincontainer.h0000644000000000000000000000665613507430555022730 0ustar #ifndef __APTPLUGINCONTAINER_H_2004_06_23 #define __APTPLUGINCONTAINER_H_2004_06_23 #include #include #include "aptfrontpackagedb.h" #include "iaptmediator.h" #include "installationtool.h" class QAction; class ExtPackageDB; using namespace std; namespace NApplication { class RunCommand; } namespace NApt { class IAptSearch; class IPackageDB; } class AptSettingsWidget; namespace NPlugin { class AptSearchPlugin; class AptActionPlugin; class PackageDescriptionPlugin; class PackageStatusPlugin; class InstalledVersionPlugin; class AvailableVersionPlugin; // Class AptPluginContainer // // class AptPluginContainer : public QObject, public BasePluginContainer, public IAptMediator { Q_OBJECT /** @brief The plugins in the container */ //@{ AptSearchPlugin* _pAptSearchPlugin; AptActionPlugin* _pAptActionPlugin; PackageDescriptionPlugin* _pPackageDescriptionPlugin; PackageStatusPlugin* _pPackageStatusPlugin; InstalledVersionPlugin* _pInstalledVersionPlugin; AvailableVersionPlugin* _pAvailableVersionPlugin; //@} /** @brief This pointer is used to run the apt-get update command. */ NApplication::RunCommand* _pCommand; /** @brief This holds the interface to access the information of the packages. */ NApt::IPackageDB* _pPackageDB; /** @brief This holds the interface to search the packages. */ NApt::IAptSearch* _pAptSearch; /** @brief This holds a pointer to the settings widget currently active. * * This pointer must not be deleted and should only be used in applySettings(). */ AptSettingsWidget* _pSettingsWidget; /** @brief Holds the installation tool to be used for installation (APT). */ NApt::InstallationTool _installationTool; public: /** * Default Constructor */ AptPluginContainer(); virtual ~AptPluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ // documened in base class virtual bool init(IProvider* pProvider); /** @brief This gets a plugin with the given name. The plugin is not * initialized so call Plugin::init() for it. * * Accepted names are: * \li AptSearchPlugin * \li PackageDescriptionPlugin * \li PackageStatusPlugin * * @see PluginContainer::requestPlugin() */ // virtual Plugin* requestPlugin(const QString& name); /** @returns "aptplugin" */ virtual string name() const { return "aptplugin"; }; virtual QString title() const { return QString("Apt Plugins"); }; virtual QWidget* getSettingsWidget(QWidget* pParent); virtual void applySettings(); //@} /** @name BasePluginContainer Overloads * * These functions implement saving and loading of the container settings * as described in BasePluginContainer. */ //@{ virtual QDomElement loadContainerSettings(const QDomElement source); virtual void saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const; //@} /** @name IAptMediator Overloads * */ // documened in base class //@{ virtual void setInstallationTool(NApt::InstallationTool tool); virtual QString installationToolCommand(); virtual QStringList searchPatterns(); virtual void updateAptDatabase(); virtual void reloadAptDatabase(); //@} protected Q_SLOTS: /** @brief This function will be called if the update finished. * * It will update the database used. */ void onAptUpdateFinished(); }; } // namespace NPlugin #endif // __APTPLUGINCONTAINER_H_2004_06_23 packagesearch-2.7.11build1/src/plugins/aptplugin/aptpluginfactory.cpp0000644000000000000000000000277013507430555022741 0ustar // // C++ Implementation: aptpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "aptpluginfactory.h" #include #include // plugins offered #include "aptsearchplugin.h" #include "aptactionplugin.h" #include "packagestatusplugin.h" #include "packagedescriptionplugin.h" #include "installedversionplugin.h" #include "availableversionplugin.h" namespace NPlugin { AptPluginFactory::AptPluginFactory(IProvider*, IAptMediator* pMediator, NApt::IPackageDB* pPackageDB, NApt::IAptSearch* pAptSearch) : IPluginFactory() { qDebug("Constructing AptPluginFactory"); _pPackageDB = pPackageDB; _pAptSearch = pAptSearch; _pMediator = pMediator; } AptPluginFactory::~AptPluginFactory() { qDebug("Deleting AptPluginFactory"); } Plugin* AptPluginFactory::createPlugin(const string& name) const { if (name=="AptSearchPlugin") { return new AptSearchPlugin(_pAptSearch, _pPackageDB); } if (name=="AptActionPlugin") { return new AptActionPlugin(_pMediator); } if (name=="PackageStatusPlugin") { return new PackageStatusPlugin(_pPackageDB); } if (name=="PackageDescriptionPlugin") { return new PackageDescriptionPlugin(_pPackageDB, _pMediator); } if (name=="InstalledVersionPlugin") { return new InstalledVersionPlugin(_pPackageDB); } if (name=="AvailableVersionPlugin") { return new AvailableVersionPlugin(_pPackageDB); } return 0; } }; packagesearch-2.7.11build1/src/plugins/aptplugin/aptpluginfactory.h0000644000000000000000000000244513507430555022405 0ustar // // C++ Interface: aptpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __APTPLUGINFACTORY_H_2004_09_11 #define __APTPLUGINFACTORY_H_2004_09_11 #include namespace NApt { class DumpAvailPackageDB; class IAptSearch; class IPackageDB; } namespace NPlugin { class IProvider; class IAptMediator; /** @brief Factory for creating apt plugins. * * @author Benjamin Mesing */ class AptPluginFactory : public IPluginFactory { /** This holds the interface to access the information of the packages * and for searching. */ NApt::IPackageDB* _pPackageDB; /** This holds the interface to access the information of the packages * and for searching. */ NApt::IAptSearch* _pAptSearch; /** Holds the mediator object to allow the plugins to communicate with each other. */ IAptMediator* _pMediator; public: AptPluginFactory(IProvider* pProvider, IAptMediator* pMediator, NApt::IPackageDB* pPackageDB, NApt::IAptSearch* pAptSearch); virtual ~AptPluginFactory(); /** @name IPluginFactory interface */ //@{ // documented in base class virtual Plugin* createPlugin(const string& name) const; //@} }; }; #endif // __APTPLUGINFACTORY_H_2004_09_11 packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchplugin.cpp0000644000000000000000000001356113507430555022537 0ustar #include #include #include #include #include #include #include #include #include #include #include #include // NPlugin #include // NApt #include "iaptsearch.h" #include "ipackagedb.h" #include "complexscorecalculationstrategy.h" #include "aptsearchplugin.h" #include "aptsearchpluginshortinputwidget.h" namespace NPlugin { const QString AptSearchPlugin::PLUGIN_NAME = "AptSearchPlugin"; AptSearchPlugin::AptSearchPlugin(NApt::IAptSearch* pAptSearch, NApt::IPackageDB* pPackageDb) : _title(tr("Apt-Search Plugin")), _briefDescription(tr("Performs a full text search")), _description(tr("This plugin can be used to search the packages for expressions.")), _pAptSearch(pAptSearch), _pPackageDb(pPackageDb) { _pShortInputWidget = 0; _pStatusBar = 0; _pDelayTimer = new QTimer(this); _pDelayTimer->setObjectName("delayTimer"); _delayTime=1000; connect(_pDelayTimer, SIGNAL(timeout()), SLOT(evaluateSearch())); _pScoreCalculationStrategy = new NApt::ComplexScoreCalculationStrategy(_pPackageDb); } AptSearchPlugin::~AptSearchPlugin() { delete _pShortInputWidget; delete _pDelayTimer; delete _pScoreCalculationStrategy; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void AptSearchPlugin::init(IProvider* pProvider) { _pProvider = pProvider; QMainWindow* pWindow = _pProvider->mainWindow(); _pShortInputWidget = new AptSearchPluginShortInputWidget(pWindow, "AptSearchShortInputWIdget"); _pShortInputWidget->setClearButton( pProvider->createClearButton(_pShortInputWidget, "AptClearButton"), 0); _pShortInputWidget->show(); _pStatusBar = pWindow->statusBar(); connect( _pShortInputWidget->_pClearButton, SIGNAL(clicked()), SLOT (onClearSearch()) ); connect( _pShortInputWidget->_pAptSearchTextInput, SIGNAL(textChanged(const QString&)), SLOT(onInputTextChanged(const QString&)) ); connect( _pShortInputWidget->_pAptSearchTextInput, SIGNAL(returnPressed()), SLOT(evaluateSearch()) ); connect( _pShortInputWidget->_pSearchDescriptionsCheck, SIGNAL(toggled(bool)), SLOT(evaluateSearch()) ); } ///////////////////////////////////////////////////// // Search Plugin Interface ///////////////////////////////////////////////////// QWidget* AptSearchPlugin::shortInputAndFeedbackWidget() const { return _pShortInputWidget; } void AptSearchPlugin::clearSearch() { _pShortInputWidget->_pAptSearchTextInput->clear(); _pDelayTimer->stop(); evaluateSearch(); } bool AptSearchPlugin::isInactive() const { return _includePatterns.isEmpty() && _excludePatterns.isEmpty(); } ///////////////////////////////////////////////////// // ScorePlugin Interface ///////////////////////////////////////////////////// map AptSearchPlugin::getScore(const set& packages) const { assert(!_includePatterns.empty()); _pScoreCalculationStrategy->clear(); _pScoreCalculationStrategy->setIncludePatterns(_includePatterns); _pScoreCalculationStrategy->calculateScore(packages); return _pScoreCalculationStrategy->getScore(); } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void AptSearchPlugin::onInputTextChanged(const QString&) { _pStatusBar->showMessage(tr("Delayed evaluation - waiting for further input"), _delayTime ); _pDelayTimer->setSingleShot(true); _pDelayTimer->start(_delayTime); } void AptSearchPlugin::evaluateSearch() { // stop the delay timer in case that this evaluateSearch() was triggered by // another event _pDelayTimer->stop(); _pProvider->reportBusy(this, tr("Performing full text search on package database")); _searchResult.clear(); parseSearchExpression(_pShortInputWidget->_pAptSearchTextInput->text()); if ( !isInactive() ) // if the search is not empty { QStringList patterns = this->searchPatterns(); try { _pAptSearch->search( _searchResult, _includePatterns, _excludePatterns, _pShortInputWidget->_pSearchDescriptionsCheck->isChecked() ); } catch (...) { qWarning("Search threw an exception -> reloading apt-database"); _pProvider->reloadAptFrontCache(); try { // retrying search _pAptSearch->search( _searchResult, _includePatterns, _excludePatterns, _pShortInputWidget->_pSearchDescriptionsCheck->isChecked() ); } catch (...) { qCritical("apt-search threw an exception -> expect corrupted results"); } } } _pProvider->reportReady(this); emit searchChanged(this); } QStringList AptSearchPlugin::searchPatterns() { return _includePatterns; } void AptSearchPlugin::parseSearchExpression(const QString& expression) { _includePatterns.clear(); _excludePatterns.clear(); if (expression.isEmpty()) return; QStringList patterns = expression.split('"', QString::KeepEmptyParts); // status flags bool minus = false; bool inGroup = (expression == QString("\"")); for (QStringList::iterator it = patterns.begin(); it != patterns.end(); ++it ) { if (!inGroup) { QStringList newPatterns = it->split(' ', QString::KeepEmptyParts); for (QStringList::iterator jt = newPatterns.begin(); jt != newPatterns.end(); ++jt ) { QString p = (*jt); if (p.isEmpty()) continue; if (p[0] == '+') { minus = false; p = p.mid(1); } else if (p[0] == '-') { minus = true; p = p.mid(1); } if (p.isEmpty()) continue; if (!minus) { _includePatterns.push_back(p); } else { _excludePatterns.push_back(p); minus = false; } } } else { if ((*it).isEmpty()) continue; if (!minus) { _includePatterns.push_back(*it); } else { _excludePatterns.push_back(*it); minus = false; } } inGroup = !inGroup; } } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchplugin.h0000644000000000000000000001071113507430555022176 0ustar #ifndef __APTSEARCHPLUGIN_H_2004_06_21 #define __APTSEARCHPLUGIN_H_2004_06_21 #include #include #include // NPlugin #include #include class QTimer; class QStatusBar; class AptSearchPluginShortInputWidget; using namespace std; namespace NApt { class IAptSearch; class IPackageDB; class AptSearchScoreCalculationStrategy; } namespace NPlugin { // Class AptSearchPlugin // // class AptSearchPlugin : public SearchPlugin, public ScorePlugin { Q_OBJECT const QString _title; const QString _briefDescription; const QString _description; /** @brief This holds the result of the currently active search. */ std::set _searchResult; /** @brief This holds a link to the manager which manages the plugin. */ IProvider* _pProvider; /** @brief Holds a pointer to the main widgets status bar. */ QStatusBar* _pStatusBar; /** @brief This timer is used to delay the evaluation of the search a little * to avoid unneccessary operations e.g. on text input. */ QTimer* _pDelayTimer; /** @brief Holds the strategy object used to calculate the scores. */ NApt::AptSearchScoreCalculationStrategy* _pScoreCalculationStrategy; /** @brief This is the delay time in ms the delay timer waits for another input. */ uint _delayTime; /** @brief The cache access data structure this plugin uses to access the apt database. */ // const CacheAccess& _ca; /** @brief The short widget used for getting the user input. */ AptSearchPluginShortInputWidget* _pShortInputWidget; /** @brief Holds the interface used for searching. */ NApt::IAptSearch* _pAptSearch; /** @brief Holds the interface used to access the package database directly. */ NApt::IPackageDB* _pPackageDb; /** @brief Holds the patterns that must be contained in the text to be searched. */ QStringList _includePatterns; /** @brief Holds the patterns that must not be contained in the text to be searched. */ QStringList _excludePatterns; protected Q_SLOTS: /** @brief Evaluates the search as specified in the input widgets. */ virtual void evaluateSearch(); /** @brief Called whenever the text of the widget where to insert the * search pattern changes. */ void onInputTextChanged(const QString&); /** @brief Slot that calls clearSearch() */ void onClearSearch() { clearSearch(); }; protected: /** @brief Parses the handed search expression. * * It fills #_includePatterns and #_excludePatterns; */ void parseSearchExpression(const QString& expression); public: static const QString PLUGIN_NAME; AptSearchPlugin(NApt::IAptSearch* pAptSearch, NApt::IPackageDB* pPackageDb); virtual ~AptSearchPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ /** * * @param pluginManager the search window this plugin is added to */ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ /** @brief This plugin offers no input widgets. */ virtual QWidget* inputWidget() const { return 0; }; /** @brief This plugin offers no input widgets. */ virtual QString inputWidgetTitle() const { return _emptyString; }; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return false; }; virtual const std::set& searchResult() const { return _searchResult; }; virtual bool filterPackage(const string&) const { return true; }; virtual bool isInactive() const; virtual uint searchPriority() const { return 1; }; //@} /** @name ScorePlugin interface * * Implementation of the ScorePlugin interface */ //@{ virtual map getScore(const set& packages) const; virtual bool offersScore() const { return !_includePatterns.isEmpty(); } //@} /** @brief Returns the list of patterns currently searched for by the AptSearchPlugin. * * @returns the list of patterns currently searched for or an empty list if no searched * is active */ QStringList searchPatterns(); }; } // namespace NPlugin #endif // __APTSEARCHPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchpluginshortinputwidget.cpp0000644000000000000000000000126213507430555026076 0ustar // // C++ Implementation: aptsearchpluginshortinputwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "aptsearchpluginshortinputwidget.h" AptSearchPluginShortInputWidget::AptSearchPluginShortInputWidget(QWidget *parent, const char *name) : QWidget(parent) { setupUi(this); setObjectName(name); } AptSearchPluginShortInputWidget::~AptSearchPluginShortInputWidget() { } void AptSearchPluginShortInputWidget::setClearButton( QPushButton * pButton, int index) { delete(_pClearButton); _pClearButton = pButton; _pInputLayout->insertWidget(index,_pClearButton); } packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchpluginshortinputwidget.h0000644000000000000000000000140513507430555025542 0ustar // // C++ Interface: aptsearchpluginshortinputwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __APTSEARCHPLUGINSHORTINPUTWIDGET_H_2005_08_27 #define __APTSEARCHPLUGINSHORTINPUTWIDGET_H_2005_08_27 #include #include /** @author Benjamin Mesing */ class AptSearchPluginShortInputWidget : public QWidget, public Ui::AptSearchPluginShortInputWidget { Q_OBJECT public: AptSearchPluginShortInputWidget(QWidget *parent = 0, const char *name = 0); ~AptSearchPluginShortInputWidget(); void setClearButton( QPushButton * pButton, int index ); }; #endif // __APTSEARCHPLUGINSHORTINPUTWIDGET_H_2005_08_27 packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchpluginshortinputwidget.ui0000644000000000000000000000561713507430555025741 0ustar AptSearchPluginShortInputWidget 0 0 438 85 Form1 3 0 Search for pattern 2 0 Search the package database for the given expression This searches the package names and descriptions for the given pattern. If you enter more than one word all words must be contained.<br> You can search for phrases by using double quotes around the phrase. To enter patterns or phrases which should not appear in the package precede them with a minus ('-'). Clear 0 Search the package descriptions Check this if you want to search in the package descriptions. The search will search the package name, the long description and the short description.<br />If not checked only the package names will be searched. Search Descriptions true Qt::Horizontal qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchscorecalculationstrategy.cpp0000644000000000000000000000070513507430555026352 0ustar // // C++ Implementation: aptsearchscorecalculationstrategy // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "aptsearchscorecalculationstrategy.h" namespace NApt { AptSearchScoreCalculationStrategy::AptSearchScoreCalculationStrategy() { _cs = false; } AptSearchScoreCalculationStrategy::~AptSearchScoreCalculationStrategy() { } } packagesearch-2.7.11build1/src/plugins/aptplugin/aptsearchscorecalculationstrategy.h0000644000000000000000000000202313507430555026012 0ustar // // C++ Interface: aptsearchscorecalculationstrategy // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_APTSEARCHSCORECALCULATIONSTRATEGY_H_2005_07_31 #define __NAPT_APTSEARCHSCORECALCULATIONSTRATEGY_H_2005_07_31 #include #include namespace NApt { /** @author Benjamin Mesing */ class AptSearchScoreCalculationStrategy : public NPlugin::ScoreCalculationStrategyBase { protected: /** @brief Holds of the search was performed case sensitve. * * Default is false. */ bool _cs; QStringList _includePatterns; public: AptSearchScoreCalculationStrategy(); virtual ~AptSearchScoreCalculationStrategy(); void setCaseSensitive(bool cs) { _cs = cs; } bool isCaseSensitive() { return _cs; } void setIncludePatterns(const QStringList& includePatterns) { _includePatterns = includePatterns; } }; } #endif // __NAPT_APTSEARCHSCORECALCULATIONSTRATEGY_H_2005_07_31 packagesearch-2.7.11build1/src/plugins/aptplugin/aptsettingswidget.cpp0000644000000000000000000000135613507430555023116 0ustar // // C++ Implementation: aptsettingswidget // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "aptsettingswidget.h" AptSettingsWidget::AptSettingsWidget(QWidget* pParent) : QWidget(pParent) { setupUi(this); } AptSettingsWidget::~AptSettingsWidget() { } NApt::InstallationTool AptSettingsWidget::installationTool() { if (_pAptButton->isChecked()) return NApt::APT; return NApt::APTITUDE; } void AptSettingsWidget::setInstallationTool(NApt::InstallationTool tool) { switch (tool) { case NApt::APT: _pAptButton->setChecked(true); break; case NApt::APTITUDE: _pAptitudeButton->setChecked(true); break; } } packagesearch-2.7.11build1/src/plugins/aptplugin/aptsettingswidget.h0000644000000000000000000000136713507430555022565 0ustar // // C++ Interface: aptsettingswidget // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __APTSETTINGSWIDGET_H_20080605 #define __APTSETTINGSWIDGET_H_20080605 #include #include "ui_aptsettingswidget.h" #include "installationtool.h" /** @author Benjamin Mesing */ class AptSettingsWidget : public QWidget, public Ui::AptSettingsWidget { public: AptSettingsWidget(QWidget* pParent); ~AptSettingsWidget(); /** Returns the installation tool selected by the user. */ NApt::InstallationTool installationTool(); void setInstallationTool(NApt::InstallationTool tool); }; #endif // __APTSETTINGSWIDGET_H_20080605 packagesearch-2.7.11build1/src/plugins/aptplugin/aptsettingswidget.ui0000644000000000000000000000314613507430555022750 0ustar AptSettingsWidget 0 0 274 137 Form The selected tool will be used to install/remove the selected packages For package installation Debian Package Search relies on an external program. You can select wether to use apt or aptitude here. Package Administration Tool apt-get aptitude Qt::Vertical 20 40 packagesearch-2.7.11build1/src/plugins/aptplugin/availableversionplugin.cpp0000644000000000000000000000267413507430555024116 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "availableversionplugin.h" #include #include "ipackagedb.h" namespace NPlugin { const QString AvailableVersionPlugin::PLUGIN_NAME = "AvailableVersionPlugin"; AvailableVersionPlugin::AvailableVersionPlugin(NApt::IPackageDB* pPackageDB) : _title(tr("Available Version Plugin")), _briefDescription(tr("Shows the version for the package available for download")), _description(tr("Shows the version for the package available for download")), _pPackageDB(pPackageDB) { } AvailableVersionPlugin::~AvailableVersionPlugin() { } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void AvailableVersionPlugin::init(IProvider*) { } ///////////////////////////////////////////////////// // ShortInformationPlugin Interface ///////////////////////////////////////////////////// const QString AvailableVersionPlugin::shortInformationText(const string& package) { try { return QString(_pPackageDB->getPackageRecord(package).version()); } catch (const PackageNotFoundException& e) { return _emptyString; } } ///////////////////////////////////////////////////// // AvailableVersionPlugin functions ///////////////////////////////////////////////////// }; packagesearch-2.7.11build1/src/plugins/aptplugin/availableversionplugin.h0000644000000000000000000000345513507430555023561 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_AVAILABLEVERSIONPLUGIN_H_2005_03_25 #define __NPLUGIN_AVAILABLEVERSIONPLUGIN_H_2005_03_25 #include #include using namespace std; namespace NApt { class IPackageDB; } namespace NPlugin { /** @author Benjamin Mesing */ class AvailableVersionPlugin : public QObject, public ShortInformationPlugin { Q_OBJECT const QString _title; const QString _briefDescription; const QString _description; /** @brief Package database to be used. */ NApt::IPackageDB* _pPackageDB; public: static const QString PLUGIN_NAME; AvailableVersionPlugin(NApt::IPackageDB* pPackageDB); ~AvailableVersionPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 4; } virtual const QString shortInformationText(const string& package); virtual QString shortInformationCaption() const { return tr("Available Version"); }; // documented in base class virtual int preferredColumnWidth() const { return 6; } //@} }; }; #endif // __NPLUGIN_AVAILABLEVERSIONPLUGIN_H_2005_03_25 packagesearch-2.7.11build1/src/plugins/aptplugin/complexscorecalculationstrategy.cpp0000644000000000000000000001346213507430555026053 0ustar // // C++ Implementation: complexscorecalculationstrategy // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "complexscorecalculationstrategy.h" #include #include #include // NApt #include // NPlugin #include namespace NApt { const float ComplexScoreCalculationStrategy::Scores::DIRECT_CS_MATCH = 20; const float ComplexScoreCalculationStrategy::Scores::DIRECT_MATCH = 18; const float ComplexScoreCalculationStrategy::Scores::WHOLE_CS_WORD = 15; const float ComplexScoreCalculationStrategy::Scores::WHOLE_WORD = 14; const float ComplexScoreCalculationStrategy::Scores::BORDER_MATCH = 8; const float ComplexScoreCalculationStrategy::Scores::INNER_MATCH = 3; float ComplexScoreCalculationStrategy::ScoreInformation::_maximumDescriptionScore = 0; ComplexScoreCalculationStrategy::ComplexScoreCalculationStrategy(IPackageDB* pPackageDb) { _pPackageDb = pPackageDb; } ComplexScoreCalculationStrategy::~ComplexScoreCalculationStrategy() { } ///////////////////////////////////////////////////// // IScoreCalculationStrategy Interface ///////////////////////////////////////////////////// void ComplexScoreCalculationStrategy::calculateScore(const set& packages) { qDebug("Calculating Score"); assert(_includePatterns.size() != 0); vector scoreInformation; scoreInformation.reserve(packages.size()); // reset the maximum description count ScoreInformation::clearMaximumDescriptionScore(); // collect the relevant information for each package for (set::const_iterator it = packages.begin(); it != packages.end(); ++it) { try { ScoreInformation si = getScoreInformation(*it, _cs); scoreInformation.push_back(si); } // if the package was not found, add it with a score of 1 catch (NPlugin::PackageNotFoundException e) { qDebug("PackageNotFoundException"); setScore(*it, 1.0f); } } // calculate the scores for each package { const float includeNum = _includePatterns.size(); float maxDescriptionScore = ScoreInformation::getMaximumDescriptionScore(); // if maxDescriptionScore is 0 every description score is null, so we can choose any number // except 0 here... if (maxDescriptionScore == 0) maxDescriptionScore = 1; for (vector::const_iterator it = scoreInformation.begin(); it != scoreInformation.end(); ++it ) { const ScoreInformation& si = *it; // normalize the scores by the maximum scores possible float nameScores = si.getNameScore() / (includeNum * Scores::DIRECT_CS_MATCH); float descriptionScores = si.getDescriptionScore() / maxDescriptionScore; float score = (3 * nameScores + descriptionScores) / 4.0f; setScore(si.package(), score); } } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// ComplexScoreCalculationStrategy::ScoreInformation ComplexScoreCalculationStrategy::getScoreInformation(const string& package, bool) const { ScoreInformation info(package); const IPackage& packageStruct = _pPackageDb->getPackageRecord(package); for (QStringList::const_iterator it = _includePatterns.begin(); it != _includePatterns.end(); ++it) { info.addNameScore(getNameScore(packageStruct, *it)); info.addDescriptionScore(getDescriptionScore(packageStruct, *it)); } return info; } float ComplexScoreCalculationStrategy::getNameScore(const IPackage& package, const QString& pattern) const { // if the pattern does not match at all if (package.name().indexOf(pattern, 0, Qt::CaseInsensitive) == -1) return 0; // if the package name equals (case insensitve) the pattern // (this is because it was found in the pattern and they have the same size) if (package.name().length() == pattern.length()) { // if it equals case sensitive if (package.name() == pattern) return Scores::DIRECT_CS_MATCH; else return Scores::DIRECT_MATCH; } // the pattern was found, but does not equal the package name // take the highest rated match we found Matches m = findMatches(package.name(), pattern); if (m.wholeWordCsMatches > 0) return Scores::WHOLE_CS_WORD; if (m.wholeWordMatches > 0) return Scores::WHOLE_WORD; if (m.borderMatches) return Scores::BORDER_MATCH; if (m.innerMatches) return Scores::INNER_MATCH; assert(false); return 0; } float ComplexScoreCalculationStrategy::getDescriptionScore(const IPackage& package, const QString& pattern) const { Matches m = findMatches(package.description(), pattern); return (m.wholeWordCsMatches * Scores::WHOLE_CS_WORD + m.wholeWordMatches * Scores::WHOLE_WORD + m.innerMatches * Scores::INNER_MATCH + m.borderMatches * Scores::BORDER_MATCH) / pattern.length(); } ComplexScoreCalculationStrategy::Matches ComplexScoreCalculationStrategy::findMatches(const QString& string, const QString& pattern) const { Matches matches; int i = 0; while ( (i = string.indexOf(pattern, i, Qt::CaseInsensitive)) != -1 ) { // holds if the pattern was matched at the front boundary of a word bool front = false; if (i==0) front = true; else { QChar c = string.at(i-1); // if the character before is not a letter we have a boundary front = !c.isLetter(); } // holds if the pattern was matched at the back boundary of a word bool back = false; if ( i + pattern.length() == string.length() ) back = true; else { QChar c = string.at(i + pattern.length()); back = !c.isLetter(); } if (front && back) { QString substring = string.mid(i, pattern.length()); if (substring == pattern) ++matches.wholeWordCsMatches; else ++matches.wholeWordMatches; } else if (front || back) ++matches.borderMatches; else ++matches.innerMatches; i += pattern.length(); } return matches; } } packagesearch-2.7.11build1/src/plugins/aptplugin/complexscorecalculationstrategy.h0000644000000000000000000001262713507430555025522 0ustar // // C++ Interface: complexscorecalculationstrategy // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_COMPLEXSCORECALCULATIONSTRATEGY_H_2005_08_06 #define __NAPT_COMPLEXSCORECALCULATIONSTRATEGY_H_2005_08_06 #include namespace NApt { class IPackageDB; class IPackage; /** @brief Calculates the scores for each package. * * The scores will be calculated based on the search of the patterns in the * names and descriptions of the packages. * * For each package, a score based on the names and one based on the description * is calculated, each being being in [0..1]. They are combined by as a weighted * average, where the name scores are weighted with 3, and the description scores * with 1. * * The include patterns are searched in the package descriptions and the package names. * Each type of match is assigned a score, where a Scores::DIRECT_CS_MATCH * gives the highest score, and Scores::INNER_MATCH the lowest. * * For the name scores, for each include pattern the highest match type is determined and * those values are accumulated (a no match means 0). For the description scores, * all matches are accumulated and divided by the number of characters. * Finally both, description and name scores, will be normalized and combined * as described above. * * @author Benjamin Mesing */ class ComplexScoreCalculationStrategy : public AptSearchScoreCalculationStrategy { struct Scores { /** @brief Scores if the search pattern equals the package name (case sensitive). * * Only used in descriptions. */ static const float DIRECT_CS_MATCH; /** @brief Scores if the search pattern equals the package name (case insensitive). * * Only used in descriptions. */ static const float DIRECT_MATCH; /** @brief Scores if the search pattern matches a whole word in the package name or * description (case sensitive). */ static const float WHOLE_CS_WORD; /** @brief Scores if the search pattern matches a whole word in the package name or * description (case insensitive). */ static const float WHOLE_WORD; /** @brief Scores if the search pattern matches the borders of a word in the package * name or description (case insensitive). * * Example:
* Search pattern: apt
* Word: aptitude */ static const float BORDER_MATCH; /** @brief Scores if the search pattern matches inside a word. * * Example:
* Search pattern: apt
* Word: laptop */ static const float INNER_MATCH; }; /** @brief Holds the interface used to access the package database directly. */ IPackageDB* _pPackageDb; public: ComplexScoreCalculationStrategy(IPackageDB* pPackageDb); virtual ~ComplexScoreCalculationStrategy(); /** @name IScoreCalculationStrategy interface * * Implementation of the IScoreCalculationStrategy interface */ //@{ /** @brief Calculates the scores for the handed set of packages. * * Old calculations will be cleared. * @pre _includePatterns.size() != 0 * @see setIncludePatterns() */ virtual void calculateScore(const set& packages); //@} float getNameScore(const IPackage& package, const QString& pattern) const; float getDescriptionScore(const IPackage& package, const QString& pattern) const; protected: /** Information used to calculate the scores for a package. */ struct ScoreInformation { public: ScoreInformation(const string& package) { _package = package; _nameScore = 0; _descriptionScore = 0; } const string& package() const { return _package; } float getNameScore() const { return _nameScore; } /** Accumulated matches divided by the number of characters in the description. */ float getDescriptionScore() const { return _descriptionScore; } void clearScore(); void addNameScore(float score) { _nameScore += score; } void addDescriptionScore(float score) { _descriptionScore += score; if (_descriptionScore > _maximumDescriptionScore) _maximumDescriptionScore = _descriptionScore; } static void clearMaximumDescriptionScore() { _maximumDescriptionScore = 0; } static float getMaximumDescriptionScore() { return _maximumDescriptionScore; } private: string _package; /** @brief The score calculated for the name. */ float _nameScore; /** @brief The score calculated for the description. */ float _descriptionScore; /** @brief Holds the maximum description scores reached. */ static float _maximumDescriptionScore; }; /** @brief Structure to count the matches for one word in a text. * * Meaning of members as in Scores. */ struct Matches { int wholeWordCsMatches; int wholeWordMatches; int borderMatches; int innerMatches; Matches() : wholeWordCsMatches(0), wholeWordMatches(0), borderMatches(0), innerMatches(0) { } }; /** @brief Searchs for pattern in string. * * @returns the result of the search as Matches structure. */ Matches findMatches(const QString& string, const QString& pattern) const; /** @brief Returns the score information for the handed package. * * @throws NPlugin::PackageNotFoundException if no data was available for the handed package. */ ScoreInformation getScoreInformation(const string& package, bool cs) const; }; } #endif // __NAPT_COMPLEXSCORECALCULATIONSTRATEGY_H_2005_08_06 packagesearch-2.7.11build1/src/plugins/aptplugin/extpackagedb.cpp0000644000000000000000000000730713507430555021771 0ustar // // C++ Implementation: extpackagedb // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include #include #include "extpackagedb.h" #include "helpers.h" namespace NApt { ExtPackageDB::ExtPackageDB() : PackageDB() { } ExtPackageDB::~ExtPackageDB() { } NApt::Package ExtPackageDB::getPackageRecord(const QString& pkg, const QString& linebreak) { Package result; QString record(toQString( PackageDB::getPackageRecord(toString(pkg)) )); map sectionToString; { // init the map sectionToString["Package"]=&result.package; sectionToString["Essential"]=&result.essential; sectionToString["Priority"]=&result.priority; sectionToString["Section"]=&result.section; sectionToString["Installed-Size"]=&result.installedSize; sectionToString["Maintainer"]=&result.maintainer; sectionToString["Architecture"]=&result.architecture; sectionToString["Source"]=&result.source; sectionToString["Version"]=&result.version; sectionToString["Replaces"]=&result.replaces; sectionToString["Provides"]=&result.provides; sectionToString["Pre-Depends"]=&result.preDepends; sectionToString["Depends"]=&result.depends; sectionToString["Recommends"]=&result.recommends; sectionToString["Suggests"]=&result.suggests; sectionToString["Conflicts"]=&result.conflicts; sectionToString["Filename"]=&result.filename; sectionToString["Size"]=&result.size; sectionToString["MD5sum"]=&result.md5sum; sectionToString["Conffiles"]=&result.conffiles; sectionToString["Description"]=&result.description; } if (record.isEmpty()) return result; // the default record QStringList lines = QStringList::split('\n', record); // search all lines for the keywords QString dummy; // this string is used for the first pass of the loop, to avoid a special variable // first_pass_through variable QString* pCurrentSection=&dummy; QString currentText; for (QStringList::iterator it=lines.begin(); it!=lines.end(); ++it) { QRegExp reg("^([\\w\\-]*): (.*)"); // get the Section out of it if (reg.search(*it) != -1) // we have probably found a new section { QStringList captured = reg.capturedTexts(); const QString& key = captured[1]; // key becomes the part before the : const QString& value = captured[2]; // value the one after it map::iterator jt = sectionToString.find(key); // check if it really is a new section i.e. its key is known if ( jt != sectionToString.end() ) { (*pCurrentSection) = currentText; pCurrentSection = jt->second; // point to the next section currentText = value; } else { currentText += linebreak + (*it); } } else { currentText += linebreak + (*it); } } // the last section should be a description if (pCurrentSection != &result.description) cerr << "Error in ExtPackageDB::getPackageRecord(string) last section must be a description" << endl; else { result.description=currentText; result.shortDescription=currentText.section('\n',0,0); // get the first line } return result; } QString ExtPackageDB::getShortDescription(const string& pkg) { string record( PackageDB::getPackageRecord(pkg) ); const int DESCRIPTION_STRING_LENGTH = 13; // including the following space int first = record.find("Description:"); first += DESCRIPTION_STRING_LENGTH; int second = record.find("\n", first); return toQString(record.substr(first, second - first)); } QString ExtPackageDB::getShortDescription(int packageHandle) { return getShortDescription(SingleHandleMaker::instance()->getItem(packageHandle)); }; } // namespace NApt packagesearch-2.7.11build1/src/plugins/aptplugin/extpackagedb.h0000644000000000000000000000356413507430555021437 0ustar // // C++ Interface: extpackagedb // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __EXTPACKAGEDB_H_2004_03_31 #define __EXTPACKAGEDB_H_2004_03_31 #include #include #include #include #include #include "ipackagedb.h" using namespace std; namespace NApt { /** This class extents the PackageDB class in the way, that getPackageRecord() function * parses the string description it get an creates a struct for easy access. * @author Benjamin Mesing */ class ExtPackageDB : public IPackageDB, protected Debtags::PackageDB { public: /** @brief This gets the information about the given package from the database. * * @param pkg the name of the package the information should be retrieved * @param linebreak the linebreak command (e.g. "\n" or "
" * * It might throw a PackageDBException. See PacakgeDB::getPackageRecord(). */ virtual Package getPackageRecord(const QString& pkg, const QString& linebreak="\n"); /** @brief This gets the short description from requested package from the database. * * @param pkg the name of the package the information should be retrieved * * It might throw a PackageDBException. See PacakgeDB::getPackageRecord(). */ virtual QString getShortDescription(const string& pkg); // documented in base class virtual QString getShortDescription(int packageHandle); /** @warning this version does not work any more - returns always installed*/ virtual Package::InstalledState getState(int packageHandle) { // TODO verify this cast! (Probably not working any more! // return (Package::State) Debtags::PackageDB::getState(pkg); return Package::INSTALLED; } ExtPackageDB(); virtual ~ExtPackageDB(); }; } // namespace NApt #endif // __EXTPACKAGEDB_H_2004_03_31 packagesearch-2.7.11build1/src/plugins/aptplugin/iaptmediator.h0000644000000000000000000000245713507430555021477 0ustar #ifndef NPLUGIN_IAPTMEDIATOR_H_2005_03_06 #define NPLUGIN_IAPTMEDIATOR_H_2005_03_06 #include #include "installationtool.h" namespace NPlugin { /** @brief This interface is used to allow the Apt-Plugins to communicate with * each other without having to know each other. * * Also defines configuration options, shared among all apt-plugins (e.g. the * installation command configured). * * @author Benjamin Mesing */ class IAptMediator { public: virtual ~IAptMediator() {}; /** @brief Returns the list of patterns currently searched for by the AptSearchPlugin. * * @returns the list of patterns currently searched for, an empty list if no searched * is active or the plugin is not available */ virtual QStringList searchPatterns() = 0; /** @brief Sets the installation tool to be used. */ virtual void setInstallationTool(NApt::InstallationTool tool) = 0; /** @brief Returns the command to execute the configured installation tool (e.g. /usr/bin/apt). */ virtual QString installationToolCommand() = 0; /** @brief Requests an update of the apt-database. */ virtual void updateAptDatabase() = 0; /** @brief Requests an update of the apt-database. */ virtual void reloadAptDatabase() = 0; }; } // namespace NPlugin #endif // NPLUGIN_IAPTMEDIATOR_H_2005_03_06 packagesearch-2.7.11build1/src/plugins/aptplugin/iaptsearch.cpp0000644000000000000000000000044113507430555021462 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "iaptsearch.h" namespace NApt { IAptSearch::IAptSearch() { } IAptSearch::~IAptSearch() { } }; packagesearch-2.7.11build1/src/plugins/aptplugin/iaptsearch.h0000644000000000000000000000507113507430555021133 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_IAPTSEARCH_H_2005_02_20 #define __NAPT_IAPTSEARCH_H_2005_02_20 #include #include #include using namespace std; class QStringList; class QString; namespace NUtil { class IProgressObserver; } namespace NApt { /** @author Benjamin Mesing */ class IAptSearch { public: IAptSearch(); virtual ~IAptSearch(); /** This exception is thrown if something is wrong with Apt.*/ class AptException { /** This holds the error message. * @warning we can't use _error here because there is a MACRO in APT's "error.h" with this name!\n * I hate Makros especially if they have such a common name! */ string _merror; public: AptException(const string& error) { _merror=error; } const string& error() const { return _merror; } }; /** @brief Searches for the given patterns in the package database. * * For a package it is neccessary to match all expressions from the given pattern list. * @param result the set where the search result should be inserted. The names of the matching packages * will be added to result. * @param includePatterns list of patterns that must occur in the packages. * @param excludePatterns list of patterns that must not occur in the packages. * @param searchDescr defines if the description should be searched too, else only the * names will be serached * @returns if at least one package was found. * @pre !patterns.empty() */ virtual bool search(std::set& result, const QStringList& includePatterns, const QStringList& excludePatterns, bool searchDescr) const = 0; /** @brief Searches for the given pattern in the package database. * @param result the set where the search result should be inserted. The names of the matching packages * will be added to result. * @param pattern the patters to be searched. * @param searchDescr defines if the description should be searched too, else only the * names will be serached * @returns if at least one package was found. */ virtual bool search(std::set& result, const QString& pattern, bool searchDescr) const = 0; /** @brief This reloads the package information search upon. * @param pLoader the observer where to report the reload progress, 0 if no progress should be reported */ virtual void reloadPackageInformation(NUtil::IProgressObserver* pObserver) = 0; }; }; #endif // __NAPT_IAPTSEARCH_H_2005_02_20 packagesearch-2.7.11build1/src/plugins/aptplugin/installationtool.cpp0000644000000000000000000000106113507430555022735 0ustar // // C++ Implementation: installationtool // // Description: // // // Author: Benjamin Mesing , (C) 2009 // // Copyright: See COPYING file that comes with this distribution // // #include "installationtool.h" namespace NApt { /** @brief Returns the command to execute the given installation tool (e.g. /usr/bin/apt). */ QString getInstallationToolCommand(InstallationTool tool) { switch (tool) { case APT: return "/usr/bin/apt-get"; break; case APTITUDE: default: return "/usr/bin/aptitude"; } } } // namespace NAptpackagesearch-2.7.11build1/src/plugins/aptplugin/installationtool.h0000644000000000000000000000106713507430555022410 0ustar // // C++ Interface: installationtool // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __INSTALLATIONTOOL_20080605 #define __INSTALLATIONTOOL_20080605 #include namespace NApt { enum InstallationTool { APT, APTITUDE }; /** @brief Returns the command to execute the given installation tool (e.g. /usr/bin/apt). */ QString getInstallationToolCommand(InstallationTool tool) ; } // namespace NApt #endif // __INSTALLATIONTOOL_20080605 packagesearch-2.7.11build1/src/plugins/aptplugin/installedfilterwidget.cpp0000644000000000000000000000061513507430555023733 0ustar // // C++ Implementation: installedfilterwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "installedfilterwidget.h" InstalledFilterWidget::InstalledFilterWidget(QWidget *parent) : QWidget(parent) { setupUi(this); } InstalledFilterWidget::~InstalledFilterWidget() { } packagesearch-2.7.11build1/src/plugins/aptplugin/installedfilterwidget.h0000644000000000000000000000111313507430555023372 0ustar // // C++ Interface: installedfilterwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __INSTALLEDFILTERWIDGET_H_2005_08_27 #define __INSTALLEDFILTERWIDGET_H_2005_08_27 #include /** * @author Benjamin Mesing */ class InstalledFilterWidget : public QWidget, public Ui::InstalledFilterWidget { Q_OBJECT public: InstalledFilterWidget(QWidget *parent = 0); ~InstalledFilterWidget(); }; #endif // __INSTALLEDFILTERWIDGET_H_2005_08_27 packagesearch-2.7.11build1/src/plugins/aptplugin/installedfilterwidget.ui0000644000000000000000000000361013507430555023564 0ustar InstalledFilterWidget 0 0 458 33 Form1 6 0 Installed Filter Search packages by installed state Search packages by installed state. All Installed Upgradable Not Installed Qt::Horizontal QSizePolicy::Expanding 385 20 qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/aptplugin/installedversionplugin.cpp0000644000000000000000000000323013507430555024142 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "installedversionplugin.h" #include #include "ipackage.h" #include "ipackagedb.h" namespace NPlugin { const QString InstalledVersionPlugin::PLUGIN_NAME = "InstalledVersionPlugin"; InstalledVersionPlugin::InstalledVersionPlugin(NApt::IPackageDB* pPackageDB) : _title(tr("Installed Version Plugin")), _briefDescription(tr("Shows the version of the installed package in the package list")), _description(tr("Shows the version of the installed package in the package list")), _pPackageDB(pPackageDB) { } InstalledVersionPlugin::~InstalledVersionPlugin() { } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void InstalledVersionPlugin::init(IProvider*) { } ///////////////////////////////////////////////////// // ShortInformationPlugin Interface ///////////////////////////////////////////////////// const QString InstalledVersionPlugin::shortInformationText(const string& package) { try { const NApt::IPackage& packageStruct(_pPackageDB->getPackageRecord(package)); if (packageStruct.installedState() == NApt::IPackage::INSTALLED) return QString(packageStruct.installedVersion()); else return packageStruct.installedVersion(); } catch (const PackageNotFoundException& e) { return _emptyString; } } ///////////////////////////////////////////////////// // InstalledVersionPlugin functions ///////////////////////////////////////////////////// }; packagesearch-2.7.11build1/src/plugins/aptplugin/installedversionplugin.h0000644000000000000000000000344213507430555023614 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_INSTALLEDVERSIONPLUGIN_H_2005_03_25 #define __NPLUGIN_INSTALLEDVERSIONPLUGIN_H_2005_03_25 #include #include using namespace std; namespace NApt { class IPackageDB; } namespace NPlugin { /** @author Benjamin Mesing */ class InstalledVersionPlugin : public QObject, public ShortInformationPlugin { const QString _title; const QString _briefDescription; const QString _description; /** @brief Package database to be used. */ NApt::IPackageDB* _pPackageDB; public: static const QString PLUGIN_NAME; InstalledVersionPlugin(NApt::IPackageDB* pPackageDB); ~InstalledVersionPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 4; } virtual const QString shortInformationText(const string& package); virtual QString shortInformationCaption() const { return tr("Installed Version"); }; // documented in base class virtual int preferredColumnWidth() const { return 6; } //@} }; }; #endif // __NPLUGIN_INSTALLEDVERSIONPLUGIN_H_2005_03_25 packagesearch-2.7.11build1/src/plugins/aptplugin/ipackage.cpp0000644000000000000000000000257513507430555021115 0ustar // // C++ Implementation: ipackage // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "ipackage.h" namespace NApt { IPackage::IPackage() { } IPackage::~IPackage() { } IPackage::BorderList IPackage::getPackageList(const QString& s) { BorderList result; if (s.isEmpty()) return result; pair currentPair; // inWord and inPar (in paranthesis) can never both be true bool inWord=true; uint inPar=0; // a simple parser... currentPair.first=0; for (int i=0; i, (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NAPT_IPACKAGE_H_2005_12_26 #define __NAPT_IPACKAGE_H_2005_12_26 #include #include using namespace std; namespace NApt { /** @author Benjamin Mesing */ class IPackage { public: enum InstalledState { NOT_INSTALLED, UPGRADABLE, INSTALLED }; IPackage(); virtual ~IPackage(); virtual QString name() const = 0; virtual QString essential() const = 0; virtual QString priority() const = 0; virtual QString section() const = 0; virtual QString installedSize() const = 0; virtual QString maintainer() const = 0; virtual QString architecture() const = 0; virtual QString source() const = 0; virtual QString version() const = 0; virtual QString replaces() const = 0; virtual QString provides() const = 0; virtual QString preDepends() const = 0; virtual QString depends() const = 0; virtual QString recommends() const = 0; virtual QString suggests() const = 0; virtual QString conflicts() const = 0; virtual QString filename() const = 0; virtual QString size() const = 0; virtual QString md5sum() const = 0; virtual QString conffiles() const = 0; virtual QString description() const = 0; virtual InstalledState installedState() const = 0; virtual QString installedVersion() const = 0; virtual QString homepage() const = 0; /** This should be filled with the first line of the description. */ virtual QString shortDescription() const = 0; virtual uint getSize() const = 0; virtual uint getInstalledSize() const = 0; typedef list< pair > BorderList; /** @brief This function returns a list of the packages contained in the string. * * It is based on some simple parsing rules and might fail if the text is not * formatted as expected. See the source for details (the list is assumed to * have the form like the dependencies) * @returns a list of the packages in the current string. The pairs contain * the first char and the one after the last for the package. */ static BorderList getPackageList(const QString& s); }; } #endif // __NAPT_IPACKAGE_H_2005_12_26 packagesearch-2.7.11build1/src/plugins/aptplugin/ipackagedb.cpp0000644000000000000000000000046213507430555021414 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "ipackagedb.h" namespace NApt { IPackageDB::IPackageDB() { } IPackageDB::~IPackageDB() { } } // namespace NApt packagesearch-2.7.11build1/src/plugins/aptplugin/ipackagedb.h0000644000000000000000000000377013507430555021066 0ustar #ifndef __IPACKAGEDB_H_2004_02_19 #define __IPACKAGEDB_H_2004_02_19 #include "ipackage.h" namespace NUtil { class IProgressObserver; } namespace NApt { /** @brief This is the interface for all implementations of a package database. @author Benjamin Mesing */ class IPackageDB { public: IPackageDB(); virtual ~IPackageDB(); /** @brief This gets the information about the given package from the database. * * @param pkg the name of the package the information should be retrieved * @throws PackageNotFoundException if no package with such name was in the database */ virtual const IPackage& getPackageRecord(const QString& pkg) const = 0; /** @brief This gets the information about the given package from the database. * * @param packageHandle the handle of the package the information should be retrieved * @param linebreak the linebreak command (e.g. "\n" or "<br>") * @throws PackageNotFoundException if no package with such name was in the database */ virtual const IPackage& getPackageRecord(const string& package) const = 0; /** @brief This gets the short description for the requested package. * * @param packageHandle the handle for the package the information should be retrieved for * @throws PackageNotFoundException if no package with this handle was in the database */ virtual const QString getShortDescription(const string& package) const = 0; /** @brief Returns the installed state for the package referenced. * * @param package the package the information should be retrieved for * @throws PackageNotFoundException if no package with this handle was in the database */ virtual IPackage::InstalledState getState(const string& package) const = 0; /** @brief This reloads the package information. * @param pLoader the observer where to report the reload progress, 0 if no progress should be reported */ virtual void reloadPackageInformation(NUtil::IProgressObserver* pObserver) = 0; }; } // NApt #endif // __IPACKAGEDB_H_2004_02_19 packagesearch-2.7.11build1/src/plugins/aptplugin/packagedescriptionplugin.cpp0000644000000000000000000002463413507430555024427 0ustar #include #include #include #include #include #include "packagedescriptionplugin.h" #include "ipackagedb.h" #include "iaptmediator.h" #include "packagenotfoundexception.h" namespace NPlugin { const QString PackageDescriptionPlugin::PLUGIN_NAME = "PackageDescriptionPlugin"; const QString PackageDescriptionPlugin::_emptyString; /** Converts the handed string to html. * * It replaces linebreaks by <br> and </> * by their HTML encoding. * * @param string the string to be converted * @param preserveWs if set to true, spaces will be replace by &nbsp; * * This function should be static at one point. */ QString toHtml(const QString& input, bool preserveWs = false) { list< pair > replacements; replacements.push_back(make_pair(QChar('<'),QString("<"))); replacements.push_back(make_pair(QChar('>'),QString(">"))); // _repl.push_back(make_pair(QChar('\n'),QString("
"))); QString result = input; if (preserveWs) replacements.push_back(make_pair(QChar('>'),QString(" "))); for (auto it = replacements.begin(); it != replacements.end(); ++it) result.replace(it->first, it->second); return result; } /** Converts the description to html code according to Debian Policy Section 5.6.13. * * This function should be static at one point. */ QString descriptionToHtml(const QString& description) { QStringList lines = description.split("\n"); bool inParagraph = false; QString result; for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it) { QString line = *it; if (line.startsWith(" ")) // a verbatim line { QString line = toHtml(*it, true); if (inParagraph) { result.append("

"); result.append("
"); // work around QT bug in QTextBrowser which puts a // line after a paragraph on the same line as the paragraph inParagraph = false; } result.append(line).append("
"); } else if (line.startsWith(" .")) // an empty line { QString line = toHtml(*it); if (inParagraph) { result.append("

"); inParagraph = false; } else result.append("
"); } else { QString line = toHtml(*it); if (!inParagraph) { result.append("

"); inParagraph = true; } result.append(line); } } if (inParagraph) result.append("

"); return result; } /** * Constructors/Destructors */ PackageDescriptionPlugin::PackageDescriptionPlugin(NApt::IPackageDB* pPackageDB, IAptMediator* pMediator) : _pPackageDB(pPackageDB), _pMediator(pMediator) { _pDescriptionView = 0; _pProvider = 0; } PackageDescriptionPlugin::~PackageDescriptionPlugin() { delete _pDescriptionView; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void PackageDescriptionPlugin::init(IProvider* pProvider) { _pProvider = pProvider; QMainWindow* pWindow = pProvider->mainWindow(); _pDescriptionView = new QTextBrowser(pWindow); _pDescriptionView->setObjectName("DescriptionView"); } ///////////////////////////////////////////////////// // InformationPlugin Interface ///////////////////////////////////////////////////// QWidget* PackageDescriptionPlugin::informationWidget() const { return _pDescriptionView; } QString PackageDescriptionPlugin::informationWidgetTitle() const { return tr("Description"); } void PackageDescriptionPlugin::updateInformationWidget(const string& package) { QString text=""; try { const NApt::IPackage& pkg = _pPackageDB->getPackageRecord(package); if (!pkg.description().isEmpty()) { QString description = pkg.description(); description = descriptionToHtml(description); QStringList patterns = _pMediator->searchPatterns(); for (QStringList::const_iterator it = patterns.begin(); it != patterns.end(); ++it ) { int index = description.indexOf(*it, 0, Qt::CaseInsensitive); while ( index != -1 ) { description.insert(index + (*it).length(), ""); // insert the last part first description.insert(index, ""); // point behind the inserted string index += (*it).length() + 29; // 29 == strlen("") index = description.indexOf(*it, index, Qt::CaseInsensitive); } } text = description; } } catch(PackageNotFoundException e) // the package information could not be retrieved { text = tr("

Package not found

" "

Could not find a valid description for ") + toQString(package) + tr(".
") + // tr required to add something afterwards e.g. for German tr("This could mean either that you have selected a virtual package or that the package description " " was not found for an unknown reason.

"); // "The original error message was:
" + QString(e.desc().c_str()) // ); } _pDescriptionView->setHtml(text); } void PackageDescriptionPlugin::clearInformationWidget() { _pDescriptionView->clear(); } QString PackageDescriptionPlugin::informationText(const string& package) { const NApt::IPackage& pkg = _pPackageDB->getPackageRecord(package); QString details; QTextStream os(&details, QIODevice::WriteOnly); { // fill the details string if (!pkg.installedVersion().isEmpty()) os << tr("Installed Version: ") << pkg.installedVersion() << "
"; if (!pkg.version().isEmpty()) os << tr("Available Version: ") << pkg.version() << "
"; else os << tr("Available Version: not available
"); if (!pkg.essential().isEmpty()) os << tr("Essential: ") << toHtml(pkg.essential()) << "
"; /* else os << "Essential: not available
";*/ if (!pkg.priority().isEmpty()) os << tr("Priority: ") << toHtml(pkg.priority()) << "
"; /* else os << "Priority: not available
";*/ if (!pkg.section().isEmpty()) os << tr("Section: ") << toHtml(pkg.section()) << "
"; else os << tr("Section: not available
"); if (!pkg.installedSize().isEmpty()) os << tr("Installed Size: ") << pkg.installedSize() << "
"; else os << tr("Installed Size: not available
"); if (!pkg.maintainer().isEmpty()) os << tr("Maintainer: ") << toHtml(pkg.maintainer()) << "
"; else os << tr("Maintainer: not available
"); if (!pkg.architecture().isEmpty()) os << tr("Architecture: ") << pkg.architecture() << "
"; else os << tr("Architecture: not available
"); if (!pkg.source().isEmpty()) os << tr("Source: ") << pkg.source() << "
"; if (!pkg.replaces().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.replaces())); os << tr("Replaces: ") << createLinks(borderList, pkg.replaces()) << "
"; } if (!pkg.provides().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.provides())); os << tr("Provides: ") << createLinks(borderList, pkg.provides()) << "
"; } if (!pkg.preDepends().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.preDepends())); os << tr("Pre-Depends: ") << createLinks(borderList, pkg.preDepends()) << "
"; } if (!pkg.depends().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.depends())); os << tr("Depends: ") << createLinks(borderList, pkg.depends()) << "
"; } if (!pkg.recommends().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.recommends())); os << tr("Recommends: ") << createLinks(borderList, pkg.recommends()) << "
"; } if (!pkg.suggests().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.suggests())); os << tr("Suggests: ") << createLinks(borderList, pkg.suggests()) << "
"; } if (!pkg.conflicts().isEmpty()) { NApt::IPackage::BorderList borderList = pkg.getPackageList(toHtml(pkg.conflicts())); os << tr("Conflicts: ") << createLinks(borderList, pkg.conflicts()) << "
"; } if (!pkg.filename().isEmpty()) os << tr("Filename: ") << pkg.filename() << "
\n"; else os << tr("Filename: not available
\n"); if (!pkg.size().isEmpty()) os << tr("Size: ") << pkg.size() << "
"; else os << tr("Size: not available
"); if (!pkg.md5sum().isEmpty()) os << tr("MD5sum: ") << pkg.md5sum() << "
"; else os << tr("MD5sum: not available
"); if (!pkg.conffiles().isEmpty()) os << tr("Conffiles: ") << toHtml(pkg.conffiles()) << "
"; if (!pkg.homepage().isEmpty()) os << tr("Homepage:
" << pkg.homepage() << "
"; } return details; } ///////////////////////////////////////////////////// // ShortInformationPlugin Interface ///////////////////////////////////////////////////// const QString PackageDescriptionPlugin::shortInformationText(const string& package) { try { return _pPackageDB->getShortDescription(package); } catch (const PackageNotFoundException& e) { return _emptyString; } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// QString PackageDescriptionPlugin::createLinks( NApt::IPackage::BorderList packages, const QString & s) { typedef NApt::IPackage::BorderList BL; QString result = s; // iterate from behind to not destroy the order for (BL::reverse_iterator it = packages.rbegin(); it!=packages.rend(); ++it) { QString package = result.mid(it->first, it->second - it->first); const set& allPackages = _pProvider->packages(); if (allPackages.find(toString(package)) != allPackages.end()) { result.insert(it->second,""); // insert behind the package name result.insert(it->first,""); // insert before the package name } } return result; } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/aptplugin/packagedescriptionplugin.h0000644000000000000000000000650513507430555024071 0ustar #ifndef __PACKAGEDESCRIPTIONPLUGIN_H_2004_06_24 #define __PACKAGEDESCRIPTIONPLUGIN_H_2004_06_24 #include #include #include #include #include #include "ipackage.h" class QTextBrowser; using namespace std; namespace NApt { class IPackageDB; } namespace NPlugin { class IProvider; class IAptMediator; class PackageDescriptionPlugin : public QObject, public InformationPlugin, public ShortInformationPlugin { Q_OBJECT QTextBrowser* _pDescriptionView; NApt::IPackageDB* _pPackageDB; IProvider* _pProvider; /** Holds the mediator object to allow the plugins to communicate with each other. */ IAptMediator* _pMediator; static const QString _emptyString; public: static const QString PLUGIN_NAME; /** * @param pPackageDB package database to be used */ PackageDescriptionPlugin(NApt::IPackageDB* pPackageDB, IAptMediator* pMediator); ~PackageDescriptionPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } /** @returns "PackageDescriptionPlugin" */ virtual QString title() const { return tr("PackageDescriptionPlugin"); }; /// @todo to be implemented virtual QString briefDescription() const { return ""; }; /// @todo to be implemented virtual QString description() const { return ""; }; //@} /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 0; } /** @returns a widget which shows a description of this package. */ virtual QWidget* informationWidget() const; /** @returns "Description" */ virtual QString informationWidgetTitle() const; virtual void updateInformationWidget(const string& package); virtual void clearInformationWidget(); /** This plugin offers an information text. */ virtual bool offersInformationText() const { return true; }; virtual QString informationText (const string& package); //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 7; }; /** This returns a short description about the package. * @param packageID a handle of the package to show information for */ virtual const QString shortInformationText(const string& package); /** The caption for the short information is Description. */ virtual QString shortInformationCaption() const { return tr("Description"); }; // documented in base class virtual int preferredColumnWidth() const { return 60; } //@} /** @brief This creates the link for the given BorderList and QString. * * It extracts all the names specified by the borderlist and for each checks * if they * are really packages (i.e. in _pProvider->packages()) and if so creates * a link for the package to itself (i.e. * <a href="packagename">packagename</a>) */ QString createLinks( NApt::IPackage::BorderList packages, const QString & s); }; } // namespace NPlugin #endif // __PACKAGEDESCRIPTIONPLUGIN_H_2004_06_24 packagesearch-2.7.11build1/src/plugins/aptplugin/packagestatusplugin.cpp0000644000000000000000000000671313507430555023425 0ustar #include #include #include #include #include "packagestatusplugin.h" #include "installedfilterwidget.h" #include "ipackagedb.h" namespace NPlugin { const QString PackageStatusPlugin::PLUGIN_NAME = "PackageStatusPlugin"; PackageStatusPlugin::PackageStatusPlugin(NApt::IPackageDB* pPackageDB) : _title(tr("Package Status Plugin")), /// @todo implement descriptions here _briefDescription(tr("")), _description(tr("")), _installedFilter(ALL), _pPackageDB(pPackageDB) { _pInstalledFilterWidget = 0; _stateToText[NApt::IPackage::INSTALLED] = "i"; _stateToText[NApt::IPackage::UPGRADABLE] = "u"; _stateToText[NApt::IPackage::NOT_INSTALLED] = ""; } PackageStatusPlugin::~PackageStatusPlugin() { delete _pInstalledFilterWidget; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void PackageStatusPlugin::init(IProvider* pProvider) { QMainWindow* pWindow = pProvider->mainWindow(); _pInstalledFilterWidget = new InstalledFilterWidget(pWindow); _pInstalledFilterWidget->setObjectName("InstalledFilterInput"); _pInstalledFilterWidget->show(); connect(_pInstalledFilterWidget->_pInstalledFilterInput, SIGNAL(activated(int)), SLOT(onInstalledFilterChanged(int)) ); } ///////////////////////////////////////////////////// // SearchPlugin Interface ///////////////////////////////////////////////////// QWidget* PackageStatusPlugin::shortInputAndFeedbackWidget() const { return _pInstalledFilterWidget; } bool PackageStatusPlugin::filterPackage(const string& package) const { try { NApt::IPackage::InstalledState state = getState(package); if (_installedFilter == INSTALLED) return state == NApt::IPackage::INSTALLED || state == NApt::IPackage::UPGRADABLE; else return _installedFilter == (InstalledState) state; // does the state of the package match the on filtered by? } catch (const PackageNotFoundException& e) // if the package is not in the database, it is not installed { return _installedFilter == NOT_INSTALLED; } } void PackageStatusPlugin::clearSearch() { _pInstalledFilterWidget->_pInstalledFilterInput->setCurrentIndex(0); // this should not be neccessary, because setCurrentIndex(0) should trigger // onInstalledFilterChanged onInstalledFilterChanged(0); } bool PackageStatusPlugin::isInactive() const { return _installedFilter == ALL; } ///////////////////////////////////////////////////// // ShortInformationPlugin Interface ///////////////////////////////////////////////////// const QString PackageStatusPlugin::shortInformationText(const string& package) { return _stateToText[getState(package)]; // returns the text for the state of the package } ///////////////////////////////////////////////////// // PackageStatusPlugin functions ///////////////////////////////////////////////////// NApt::IPackage::InstalledState PackageStatusPlugin::getState(const string& package) const { try { return _pPackageDB->getState(package); } catch (const PackageNotFoundException& e) { return NApt::IPackage::NOT_INSTALLED; } } void PackageStatusPlugin::onInstalledFilterChanged(int activated) { switch (activated) { case 0: _installedFilter = ALL; break; case 1: _installedFilter = INSTALLED; break; case 2: _installedFilter = UPGRADABLE; break; case 3: _installedFilter = NOT_INSTALLED; break; } emit searchChanged(this); } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/aptplugin/packagestatusplugin.h0000644000000000000000000001024613507430555023066 0ustar #ifndef __PACKAGESTATUSPLUGIN_H_2004_06_21 #define __PACKAGESTATUSPLUGIN_H_2004_06_21 #include #include #include #include #include #include "ipackage.h" using namespace std; class InstalledFilterWidget; namespace NApt { class IPackageDB; } namespace NPlugin { /** @brief This Plugin offers information about the installed State of the package. * * It offers short information (an x if the package is installed and an empty string * if not) and allows searching by installed status using the filter search technique. * * @author Benjamin Mesing */ // take care to keep the order of the subclasses (SearchPlugin must be first as it // is the QT class class PackageStatusPlugin : public SearchPlugin, public ShortInformationPlugin { Q_OBJECT const QString _title; const QString _briefDescription; const QString _description; /** @brief This enum must always match NApt::Package::InstalledState except for ALL. */ enum InstalledState { NOT_INSTALLED = NApt::IPackage::NOT_INSTALLED, UPGRADABLE = NApt::IPackage::UPGRADABLE, INSTALLED = NApt::IPackage::INSTALLED, ALL = 100 }; /** This holds the currently selected installed state filter. */ InstalledState _installedFilter; NApt::IPackageDB* _pPackageDB; /** The widget where to select which packages should be shown. */ InstalledFilterWidget* _pInstalledFilterWidget; /** The text to mark an installed package ("x") */ QString _installedText; /** The text to mark a not installed package (empty string) */ QString _notInstalledText; std::set _emptyOpSet; /** @brief This maps the installed state to how it shall be diplayed. * * So _stateToText[Package::INSTALLED] returns "x" while _stateToText[Package::NOT_INSTALLED] returns an empty string */ map _stateToText; public: static const QString PLUGIN_NAME; /** */ PackageStatusPlugin(NApt::IPackageDB* pPackageDB); ~PackageStatusPlugin() ; /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ virtual uint searchPriority() const { return 2; } /** @brief This plugin offers no input widgets. */ virtual QWidget* inputWidget() const { return 0; }; /** @brief This plugin offers no input widgets. */ virtual QString inputWidgetTitle() const { return _emptyString; }; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return true; }; virtual const std::set& searchResult() const { return _emptyOpSet; }; virtual bool filterPackage(const string& package) const; /** Returns true if ALL is selected as filter. */ virtual bool isInactive() const; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 2; } virtual const QString shortInformationText(const string& package); /** The caption for the short information is I for installed */ virtual QString shortInformationCaption() const { return QString("I"); }; // documented in base class virtual int preferredColumnWidth() const { return 1; } //@} protected: /** @brief Returns the state of the handed package. * * Returns NApt::Package::NOT_INSTALLED if the package is not in the database. */ NApt::IPackage::InstalledState getState(const string& package) const; protected Q_SLOTS: /** Called whenever the user selects a new installed filter. * @param the item that was activated */ void onInstalledFilterChanged(int activated); }; } // namespace NPlugin #endif // __PACKAGESTATUSPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/plugins/aptplugin-test/0000755000000000000000000000000013507430555017611 5ustar packagesearch-2.7.11build1/src/plugins/aptplugin-test/aptfrontpackagedb-test.cpp0000644000000000000000000000261513507430555024755 0ustar #ifdef __UNIT_TEST_PP #include #include #include #include using namespace std; /// testing code for AptFrontPackageDB::searchString(text, searchPattern, caseSensitive, wholeWords) TEST(AptFrontPackageDB__searchString) { using namespace NApt; QString text; text = "apt-get"; CHECK( AptFrontPackageDB::searchString(text, "apt", false, false)); CHECK( AptFrontPackageDB::searchString(text, "apt", false, true)); CHECK( AptFrontPackageDB::searchString(text, "apt", true, false)); CHECK(!AptFrontPackageDB::searchString(text, "-get", true, true)); CHECK( AptFrontPackageDB::searchString(text, "-get", true, false)); CHECK( AptFrontPackageDB::searchString(text, "Apt", false, false)); CHECK(!AptFrontPackageDB::searchString(text, "Apt", true, false)); CHECK(!AptFrontPackageDB::searchString(text, "Apt", true, true)); text = "aptget-apt"; CHECK( AptFrontPackageDB::searchString(text, "apt", false, true)); CHECK( AptFrontPackageDB::searchString(text, "apt", true, false)); CHECK( AptFrontPackageDB::searchString(text, "apt", true, true)); CHECK(!AptFrontPackageDB::searchString(text, "get", false, true)); CHECK( AptFrontPackageDB::searchString(text, "get", true, false)); CHECK(!AptFrontPackageDB::searchString(text, "get", true, true)); text = "python-apt-doc"; CHECK(AptFrontPackageDB::searchString(text, "python", false, false)); } #endif packagesearch-2.7.11build1/src/plugins/aptplugin-test/aptplugin-test.pro0000644000000000000000000000106013507430555023310 0ustar TEMPLATE = app CONFIG += warn_on \ qt \ thread \ stl \ link_pkgconfig QT += xml TARGET = run-tests SOURCES += aptfrontpackagedb-test.cpp \ main-test.cpp INCLUDEPATH = . \ ../../ \ ../aptplugin debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } # use unit test ++ DEFINES += __UNIT_TEST_PP PKGCONFIG += unittest++ LIBS += -L../../ -L../ -lpackagesearch -laptplugin QMAKE_CXXFLAGS += -std=c++11 packagesearch-2.7.11build1/src/plugins/aptplugin-test/main-test.cpp0000644000000000000000000000014713507430555022220 0ustar #ifdef __UNIT_TEST_PP #include int main() { return UnitTest::RunAllTests(); } #endifpackagesearch-2.7.11build1/src/plugins/debtagsplugin/0000755000000000000000000000000013507430555017461 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin/.kdev4/0000755000000000000000000000000013507430555020554 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin/.kdev4/debtagsplugin.kdev40000644000000000000000000000041013507430555024336 0ustar [Buildset] BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x1a\x00d\x00e\x00b\x00t\x00a\x00g\x00s\x00p\x00l\x00u\x00g\x00i\x00n) [MakeBuilder] Number Of Jobs=2 [Project] VersionControlSupport=kdevsubversion packagesearch-2.7.11build1/src/plugins/debtagsplugin/.moc/0000755000000000000000000000000013507430555020315 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin/.obj/0000755000000000000000000000000013507430555020311 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin/.ui/0000755000000000000000000000000013507430555020154 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin/choosentagsdisplay.cpp0000644000000000000000000000066013507430555024072 0ustar // // C++ Implementation: choosentagsdisplay // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "choosentagsdisplay.h" ChoosenTagsDisplay::ChoosenTagsDisplay(QWidget *parent, const char *name) : QWidget(parent) { if (name) setObjectName(name); setupUi(this); } ChoosenTagsDisplay::~ChoosenTagsDisplay() { } packagesearch-2.7.11build1/src/plugins/debtagsplugin/choosentagsdisplay.h0000644000000000000000000000105013507430555023531 0ustar // // C++ Interface: choosentagsdisplay // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __CHOOSENTAGSDISPLAY_H_ #define __CHOOSENTAGSDISPLAY_H_ #include #include /** @author Benjamin Mesing */ class ChoosenTagsDisplay : public QWidget, public Ui::ChoosenTagsDisplay { Q_OBJECT public: ChoosenTagsDisplay(QWidget *parent = 0, const char *name = 0); ~ChoosenTagsDisplay(); }; #endif // packagesearch-2.7.11build1/src/plugins/debtagsplugin/choosentagsdisplay.ui0000644000000000000000000000261613507430555023730 0ustar ChoosenTagsDisplay 0 0 398 377 Form2 2 0 0 0 0 Show the packages with all of the tags Exclude packages with any of the tags qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagshelper.cpp0000644000000000000000000000451713507430555023005 0ustar // // C++ Implementation: debtagshelper // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "debtagshelper.h" #include #include #include #include namespace NUtil { std::set tagsForPackage(const string& package, const Xapian::Database& xapian) { std::set result; std::pair document = documentForPackage(package, xapian); if (!document.first) { return result; } Xapian::Document& doc = document.second; for (Xapian::TermIterator it = doc.termlist_begin(); it != doc.termlist_end(); ++it) { // if the term is a tag if ((*it).find("XT")==0) { result.insert((*it).erase(0,2)); } } return result; } /** @brief A Xapian ExpandDecider which accepts only tags. */ class AcceptTags : public Xapian::ExpandDecider { virtual bool operator()(const std::string& term) const { return (term[0] == 'X') && (term[1] == 'T'); } }; std::set companionTags(const std::set& tags, const Xapian::Database& xapian) { using namespace Xapian; std::set result; if (tags.empty()) { // Dismiss all tags which have no accociated document (i.e. package) for (TermIterator it = xapian.allterms_begin("XT"); it != xapian.allterms_end("XT"); ++it) { if (xapian.term_exists(*it)) result.insert((*it).substr(2, string::npos)); } cout << result.size() << endl; return result; } set terms; for (set::const_iterator it = tags.begin(); it != tags.end(); ++it) { terms.insert(string("XT")+*it); } Xapian::Query query(Xapian::Query::OP_AND, terms.begin(), terms.end()); Xapian::Enquire enq(xapian); enq.set_query(query); AcceptTags decider; // get all results Xapian::MSet mset = enq.get_mset(0, xapian.get_doccount()); Xapian::RSet allDocuments; for (Xapian::MSetIterator it = mset.begin(); it != mset.end(); ++it) allDocuments.add_document(*it); // assuming a maximum of 1000000 tags in the vocabulary Xapian::ESet companions = enq.get_eset(1000000, allDocuments, &decider); cout << companions.size() << endl; for (ESetIterator it = companions.begin(); it != companions.end(); ++it) result.insert((*it).substr(2, string::npos)); return result; } } // namespace NUtil packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagshelper.h0000644000000000000000000000227713507430555022453 0ustar // // C++ Interface: debtagshelper // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NUTIL_DEBTAGSHELPER_H_2005_09_24 #define __NUTIL_DEBTAGSHELPER_H_2005_09_24 #include #include #include using namespace std; namespace Xapian { class Database; } namespace NUtil { /** Returns the names of all tags of the given package. * * @param package the name of the package * @param xapian the xapian database to use (this is the apt-xapian database) * @returns the tag names or an empty set if no such package was found. */ set tagsForPackage(const string& package, const Xapian::Database& xapian); /** @brief Calculates the tags that produces a non-empty search result when used for * searching together with tags. * @param tags the tags to be used * @param xapian the xapian database to be used as source, it is assumed to be a * Debian-Package database, with tags having the prefix XT */ set companionTags(const set& tags, const Xapian::Database& xapian); } #endif // __NUTIL_DEBTAGSHELPER_H_2005_09_24 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugin.cpp0000644000000000000000000001227213507430555023021 0ustar #include #include #include #include #include #include #include #include #include #include //#include //#include #include "debtagsplugin.h" #include #include // NPlugin #include #include // NUtil #include "debtagshelper.h" #include "selectioninputanddisplay.h" #include "choosentagsdisplay.h" // NTagModel #include "vocabularymodel.h" typedef std::string Package; typedef std::string Tag; using namespace std; namespace NPlugin { const QString DebtagsPlugin::PLUGIN_NAME = "DebtagsPlugin"; ///////////////////////////////////////////////////// // Constructors/ Destructors ///////////////////////////////////////////////////// DebtagsPlugin::DebtagsPlugin(const DebtagsPluginContainer& container) : _container(container) { _pProvider = 0; _pTagSelection = 0; _pChooserWidget = 0; _isInactive = true; } DebtagsPlugin::~DebtagsPlugin() { delete _pChooserWidget; delete _pTagSelection; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void DebtagsPlugin::init(IProvider* pProvider) { _pProvider = pProvider; // this will be garbage collected if the parent is deleted _pTagSelection = new NWidgets::SelectionInputAndDisplay(&_container, vocabularyModel(), this); // currently disabled as the exclude tag option is not too useful and wastes some space // assume that the vocabulary is not accessible if one of the pointers is not set // bool debtagsEnabled = (_container.collection() != 0); connect(vocabularyModel(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(onTagSelectionChanged())); connect(vocabularyModel(), SIGNAL(modelReset()), SLOT(onTagSelectionChanged())); } QString DebtagsPlugin::title() const { return QString("Debtags Plugin"); } QString DebtagsPlugin::briefDescription() const { return QString("Offers information and search using the debtags system"); } QString DebtagsPlugin::description() const { return QString("This plugin shows the tags for a program in the detailed view.\n" "It also offers searching by tags that can be selected from a list."); } ///////////////////////////////////////////////////// // Search Plugin Interface ///////////////////////////////////////////////////// QWidget* DebtagsPlugin::shortInputAndFeedbackWidget() const { return _pTagSelection->tagDisplayWidget(); } QWidget* DebtagsPlugin::inputWidget() const { return _pTagSelection->tagSelectorWidget(); } const set& DebtagsPlugin::searchResult() const { return _searchResult; }; void DebtagsPlugin::clearSearch() { vocabularyModel()->setAllUnselected(); } ///////////////////////////////////////////////////// // Information Plugin Interface ///////////////////////////////////////////////////// QString DebtagsPlugin::informationText(const string& package) { { // add the tags of the package to the description set tagset = NUtil::tagsForPackage(package, _pProvider->xapian()); if (tagset.empty()) return _emptyString; QString detailsString = "Tags: "; for (set::iterator it = tagset.begin(); ; ) { detailsString += toQString( *it ); if ( ++it == tagset.end() ) { detailsString.append("\n"); break; } detailsString += ", "; } return detailsString+"
"; } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void DebtagsPlugin::showExcludeWidgets(bool ) { // TODO reimplement /* _pExcludeSelection->setVisible(display); _pChooserWidget->_pExcludeInputLabel->setVisible(display);*/ } void DebtagsPlugin::evaluateSearch() { _pProvider->reportBusy(this, tr("Performing tag search on package database")); // statusBar()->message(tr("Searching Package Database for tags")); _searchResult.clear(); set includeTags = vocabularyModel()->selectedTags(); if (includeTags.empty()) // if nothing is selected, do not show anything { _isInactive = true; } else { _isInactive = false; Xapian::Enquire enq(_pProvider->xapian()); set terms; for (set::const_iterator it = includeTags.begin(); it != includeTags.end(); ++it) { terms.insert(string("XT")+*it); } Xapian::Query query(Xapian::Query::OP_AND, terms.begin(), terms.end()); enq.set_query(query); Xapian::MSet match = enq.get_mset(0, 500000); for (Xapian::MSet::const_iterator it = match.begin(); it != match.end(); ++it) _searchResult.insert( it.get_document().get_data()); } _pProvider->reportReady(this); emit searchChanged(this); } void DebtagsPlugin::setWidgetsEnabled(bool enabled) { _pTagSelection->setEnabled(enabled); } void DebtagsPlugin::onTagSelectionChanged() { evaluateSearch(); if ( vocabularyModel()->selectedTags().size() == 0 ) _pTagSelection->setSelectedTagDisplayShown(false); else _pTagSelection->setSelectedTagDisplayShown(true); } NTagModel::VocabularyModel* DebtagsPlugin::vocabularyModel() { return _container.vocabularyModel(); } } // namespace NPlugin #undef emit packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugin.h0000644000000000000000000001150113507430555022460 0ustar #ifndef __DEBTAGSPLUGIN_H_2004_06_21 #define __DEBTAGSPLUGIN_H_2004_06_21 #include #include #include #include #include #include #include "tagchooserwidget.h" class QAbstractItemView; class QPoint; namespace NWidgets { class SelectionInputAndDisplay; } namespace NTagModel { class VocabularyModel; } using namespace std; namespace NPlugin { /** This plugin offers search by tags * * @author Benjamin Mesing */ class DebtagsPlugin : public SearchPlugin, public InformationPlugin { Q_OBJECT TagChooserWidget* _pChooserWidget; NWidgets::SelectionInputAndDisplay* _pTagSelection; /** @brief This holds a link to the manager which manages the plugin. * * Acquaintance relation */ IProvider* _pProvider; /** This manages the include widgets (but not the labels belonging to them. */ // NWidgets::SelectionInputAndDisplay* _pIncludeSelection; /** The container which holds this plugin. */ const DebtagsPluginContainer& _container; /** Holds if the search is currently inactive. */ bool _isInactive; /** This holds the search result for the current search */ std::set _searchResult; public: static const QString PLUGIN_NAME; /** Create this plugin as plugin in container. * * @param container the container which contains this plugin. */ DebtagsPlugin(const DebtagsPluginContainer& container);; virtual ~DebtagsPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ /** @brief Initializes the plugin. * * It does not load the debtags vocabulary if _pColl or _pPackageCollection are 0.*/ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; //@} ///@todo try to remove malformed descriptions /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ virtual uint searchPriority() const { return 5; }; /** @brief Returns a widget where you can select the debtags you want to in- and exclude. */ virtual QWidget* inputWidget() const; /** @brief Returns "Debtags". */ virtual QString inputWidgetTitle() const { return "Debtags"; }; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return false; }; virtual const std::set& searchResult() const; /** This plugin does not use the filter technique. */ virtual bool filterPackage(const string&) const { return true; }; virtual bool isInactive() const { return _isInactive; }; //@} /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 5; }; /** This plugin does not offer a separate information widget. */ virtual QWidget* informationWidget() const { return 0; }; /** This plugin does not offer a separate information widget. */ virtual QString informationWidgetTitle() const { return _emptyString; }; /** This plugin does not offer a separate information widget. */ virtual void updateInformationWidget(const string&) {}; /** This plugin does not offer a separate information widget. */ virtual void clearInformationWidget() {}; /** This plugin offers an information text. */ virtual bool offersInformationText() const { return true; }; /** Returns a string which lists the tags for the requested package. */ virtual QString informationText (const string& package); //@} protected Q_SLOTS: /** @brief This shows or hides the exclude widgets. * * @param display decides if to show (true) or hide (false) the elements. */ void showExcludeWidgets(bool display); /** This evaluates the current search */ void evaluateSearch(); /** @brief This enables/ disables the visible widgets. */ void setWidgetsEnabled(bool enabled); /** @brief Called whenever the selection of tags was changed. * * If no tags are selected any more, the widget displaying the selected * tags will be hidden. */ void onTagSelectionChanged(); /** @brief This shows or hides the exclude display elements. * * @param display decides if to show (true) or hide (false) the elements. */ // void showExcludeDisplay(bool display); /** @brief This shows or hides the exclude input elements. * * @param display decides if to show (true) or hide (false) the elements. */ // void showExcludeInput(bool display); protected: /** @brief Returns a pointer to the VocabularyModel instance used. */ NTagModel::VocabularyModel* vocabularyModel(); }; } // namespace NPlugin #endif // __DEBTAGSPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugin.kdev40000644000000000000000000000007313507430555023250 0ustar [Project] Manager=KDevCustomMakeManager Name=debtagsplugin packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugin.kdevelop0000644000000000000000000000543513507430555024053 0ustar Benjamin Mesing bensmail@gmx.net $VERSION$ KDevTrollProject C++ Qt false false *.o,*.lo,CVS false bash bash_bugs clanlib w3c-dom-level2-html fortran_bugs_gcc gnome1 gnustep gtk gtk_bugs haskell haskell_bugs_ghc java_bugs_gcc java_bugs_sun kde2book opengl pascal_bugs_fp php php_bugs perl perl_bugs python python_bugs qt-kdev3 ruby ruby_bugs sdl stl w3c-svg sw w3c-uaag10 wxwidgets_bugs KDE Libraries (Doxygen) executable true true true false true true true 250 400 250 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugin.pro0000644000000000000000000000506713507430555023043 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./debtagsplugin # Target is a library: # debug mode only FORMS += debtagssettingswidget.ui \ choosentagsdisplay.ui \ relatedfeedbackwidget.ui \ relatedinput.ui \ tagchooserwidget.ui HEADERS += debtagsplugin.h \ debtagsplugincontainer.h \ relatedplugin.h \ selectioninputanddisplay.h \ debtagspluginfactory.h \ debtagssettingswidget.h \ relatedfeedbackwidget.h \ relatedinput.h \ tagchooserwidget.h \ choosentagsdisplay.h \ debtagshelper.h \ vocabularymodel.h \ selectedtagsview.h \ unselectedtagsview.h \ vocabularymodelrole.h \ filterselectedproxymodel.h \ filterhiddenproxymodel.h \ taglistproxymodel.h \ emptytagfilter.h \ treefiltermodel.h SOURCES += debtagsplugin.cpp \ debtagsplugincontainer.cpp \ relatedplugin.cpp \ selectioninputanddisplay.cpp \ debtagspluginfactory.cpp \ debtagssettingswidget.cpp \ relatedfeedbackwidget.cpp \ relatedinput.cpp \ tagchooserwidget.cpp \ choosentagsdisplay.cpp \ vocabularymodel.cpp \ selectedtagsview.cpp \ unselectedtagsview.cpp \ filterselectedproxymodel.cpp \ filterhiddenproxymodel.cpp \ emptytagfilter.cpp \ debtagshelper.cpp TRANSLATIONS = ../../../translations/debtagsplugin_de.ts \ ../../../translations/debtagsplugin_es.ts TEMPLATE = lib CONFIG += warn_on \ qt \ thread \ stl \ plugin \ link_pkgconfig OBJECTS_DIR = .obj UI_DIR = .ui MOC_DIR = .moc DESTDIR = ../ VERSION = 0.0.1 INCLUDEPATH += . \ ../../ # QMAKE_CXXFLAGS += --include ../../workarounds.h PKGCONFIG += libept # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) QT += xml widgets debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } # QMAKE_CXX = g++-4.6 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugincontainer.cpp0000644000000000000000000001345313507430555024726 0ustar #include #include #include #include #include #include // for getuid and geteuid #include // #include "debtagsplugincontainer.h" #include #undef slots #include // NUtil #include "helpers.h" // NApplication #include "applicationfactory.h" #include "runcommand.h" // NPlugin #include #include #include #include "debtagsplugin.h" #include "relatedplugin.h" #include "debtagspluginfactory.h" // NTagModel #include "vocabularymodel.h" #include #include "debtagssettingswidget.h" extern "C" { NPlugin::PluginContainer* new_debtagsplugin() { return new NPlugin::DebtagsPluginContainer; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("debtagsplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } /** Initialize the plugin. */ __attribute__ ((constructor)) void init() { } // __attribute__ ((destructor)) void fini() // { // /* code here is executed just before dlclose() unloads the module */ // } namespace NPlugin { DebtagsPluginContainer::DebtagsPluginContainer() { // this assumes, that only one instance of the DebtagsPluginContainer is created // (no two versions of libapt-front may be opened at any time) // This is ok for our purpose - though usually there should be a singleton ensuring // this constraint... DebtagsPluginFactory::getInstance()->setContainer(this); _pCommand = 0; _pRelatedPlugin = 0; _pDebtagsPlugin = 0; _pSettingsWidget = 0; _pVocabularyModel = 0; addPlugin("DebtagsPlugin"); addPlugin("RelatedPlugin"); _debtagsEnabled=false; } DebtagsPluginContainer::~DebtagsPluginContainer() { unloadAllPlugins(); delete _pCommand; } ///////////////////////////////////////////////////// // PluginContainer Interface ///////////////////////////////////////////////////// bool DebtagsPluginContainer::init(IProvider* pProvider) { BasePluginContainer::init(pProvider, DebtagsPluginFactory::getInstance()); NUtil::IProgressObserver* pProgressObserver = provider()->progressObserver(); if (pProgressObserver) pProgressObserver->setText("Loading Debtags Plugin"); if (!_vocabulary.hasData()) { setDebtagsEnabled(false); // disable the debtags system provider()->reportError( tr("No vocabulary available" ), tr( "

The vocabulary is not available. This should not happen. Please reinstall " "debtags or check your /var/lib/debtags/vocabulary file manually.

" "The debtags plugin will be disabled for now, you can re-enable it via the Packagesearch menu -> Control Plugins." "

") /* "

" "The original error message reported by debtags was:
" "" ) + toQString(e.desc()) + "" "

"*/ ); return false; } setDebtagsEnabled(true); _pVocabularyModel = new NTagModel::VocabularyModel(this); // use dynamic cast here because of the virtual base class // (static_cast is not allowed there) _pRelatedPlugin = dynamic_cast(requestPlugin("RelatedPlugin")); _pDebtagsPlugin = dynamic_cast(requestPlugin("DebtagsPlugin")); // inform the plugins about the new collections /* if (_pDebtagsPlugin) _pDebtagsPlugin->debtagsDataChanged(); if (_pRelatedPlugin) _pRelatedPlugin->debtagsDataChanged(); if (pProgressObserver) pProgressObserver->setProgress(100);*/ return true; } vector< pair > DebtagsPluginContainer::actions() { vector< pair > result; return result; } QWidget* DebtagsPluginContainer::getSettingsWidget(QWidget* pParent) { _pSettingsWidget = new DebtagsSettingsWidget(_pVocabularyModel, pParent, "DebtagsSettingsWidget"); return _pSettingsWidget; } void DebtagsPluginContainer::applySettings() { // nothing to be done here, settings are applied automatically } ///////////////////////////////////////////////////// // BasePluginContainer Interface ///////////////////////////////////////////////////// QDomElement DebtagsPluginContainer::loadContainerSettings(const QDomElement source) { if (source.tagName() != "ContainerSettings") return source; float settingsVersion; NXml::getAttribute(source, settingsVersion, "settingsVersion", 0.0f); QDomNodeList hiddenFacets = source.elementsByTagName("HiddenFacet"); for (int i=0; i < hiddenFacets.count(); ++i) { string hiddenFacet = toString( hiddenFacets.item(i).toElement().text() ); _pVocabularyModel->setFacetHidden(true, hiddenFacet); } return NXml::getNextElement(source); } void DebtagsPluginContainer::saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const { qDebug("saveContainerSettings called"); typedef std::string Facet; QDomElement containerElement = outData.addElement(parent, "ContainerSettings"); outData.addAttribute(containerElement, 0.1f, "settingsVersion"); set hiddenFacets = _pVocabularyModel->hiddenFacets(); for (set::const_iterator it = hiddenFacets.begin(); it != hiddenFacets.end(); ++it) { QDomElement hiddenFacetElement = outData.addElement(containerElement, "HiddenFacet"); outData.addText(hiddenFacetElement, *it); } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// const Xapian::Database& DebtagsPluginContainer::xapian() const { return provider()->xapian(); } void DebtagsPluginContainer::setDebtagsEnabled(bool enabled) { _debtagsEnabled = enabled; } const std::set DebtagsPluginContainer::facets() const { const Vocabulary& tags = provider()->vocabulary(); return tags.facets(); } } // namespace NPlugin #undef emit /* #include #include #include */ packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagsplugincontainer.h0000644000000000000000000000717013507430555024372 0ustar #ifndef __DEBTAGSPLUGINCONTAINER_H_2004_06_23 #define __DEBTAGSPLUGINCONTAINER_H_2004_06_23 #include #include #include #include //#include #include using namespace std; namespace Xapian { class Database; } namespace NApplication { class RunCommand; } namespace NTagModel { class VocabularyModel; } class DebtagsSettingsWidget; namespace NPlugin { class DebtagsPlugin; class RelatedPlugin; /** @brief This class provides plugins using the debtags system. * * It manages the shared data and offers the possibility to update the debtags database. * * @author Benjamin Mesing */ class DebtagsPluginContainer : public QObject, public BasePluginContainer { Q_OBJECT typedef std::string Facet; typedef ept::debtags::Vocabulary Vocabulary; Vocabulary _vocabulary; NTagModel::VocabularyModel* _pVocabularyModel; /** @brief This holds if the debtags operations are currently enabled. * * This will be set to false if the reading of the tag database failed. */ bool _debtagsEnabled; /** Holds the debtags plugin created. */ DebtagsPlugin* _pDebtagsPlugin; /** Holds the related plugin created. */ RelatedPlugin* _pRelatedPlugin; /** This pointer is used to run the debtags update command. */ NApplication::RunCommand* _pCommand; /** @brief This holds a pointer to the settings widget currently active. * * This pointer must not be deleted and should only be used in applySettings(). */ DebtagsSettingsWidget* _pSettingsWidget; public: /** Empty Constructor */ DebtagsPluginContainer(); ~DebtagsPluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ virtual bool init(IProvider* pProvider); /** @returns "debtagsplugin" */ virtual string name() const { return "debtagsplugin"; }; virtual QString title() const { return tr("Debtags Plugins"); }; /** @brief This returns a list with one entry which is the "Debtags Update" entry * * The QString specifies the menu the action should be added to, the action is * a QAction which is connected to the operation to perform.\n * The default implementation returns an empty vector. */ vector< pair > actions(); virtual QWidget* getSettingsWidget(QWidget* pParent); virtual void applySettings(); //@} /** @name BasePluginContainer Overloads * * These functions implement saving and loading of the container settings * as described in BasePluginContainer. */ //@{ virtual QDomElement loadContainerSettings(const QDomElement source); virtual void saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const; //@} /** @brief Returns the #_debtagsEnabled property. */ bool debtagsEnabled() { return _debtagsEnabled; }; /** @brief Returns the facets from the vocabulary. */ const std::set facets() const; /** @brief Returns a pointer to the model used to store the information about the vocabulary * * This information includes selected tags, hidden facets and possibly more. */ NTagModel::VocabularyModel* vocabularyModel() const { return _pVocabularyModel; }; /** The xapian database. */ const Xapian::Database& xapian() const; const Vocabulary& vocabulary() const { return _vocabulary; } protected: /** @brief This sets the debtags operations to be enabled/ disabled * * If set to false all widgets will be disabled, else they will be enabled. * @see #_debtagsEnabled */ void setDebtagsEnabled(bool enabled); }; } // namespace NPlugin #endif // __DEBTAGSPLUGINCONTAINER_H_2004_06_23 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagspluginfactory.cpp0000644000000000000000000000154213507430555024407 0ustar // // C++ Implementation: debtagspluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "debtagspluginfactory.h" #include "debtagsplugin.h" #include "relatedplugin.h" namespace NPlugin { DebtagsPluginFactory* DebtagsPluginFactory::_pInstance = 0; DebtagsPluginFactory::DebtagsPluginFactory() { } DebtagsPluginFactory::~DebtagsPluginFactory() { } Plugin* DebtagsPluginFactory::createPlugin(const string& name) const { if (name=="DebtagsPlugin") { return new DebtagsPlugin(*_pContainer); } if (name=="RelatedPlugin") { return new RelatedPlugin(*_pContainer); } return 0; } DebtagsPluginFactory* DebtagsPluginFactory::getInstance() { if (_pInstance == 0) _pInstance = new DebtagsPluginFactory; return _pInstance; } }; packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagspluginfactory.h0000644000000000000000000000217513507430555024057 0ustar // // C++ Interface: debtagspluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGINDEBTAGSPLUGINFACTORY_H_ #define __NPLUGINDEBTAGSPLUGINFACTORY_H_ #include namespace NPlugin { class DebtagsPluginContainer; /** @brief This creates the debtags plugins. * * * @author Benjamin Mesing */ class DebtagsPluginFactory : public IPluginFactory { DebtagsPluginContainer* _pContainer; DebtagsPluginFactory(); static DebtagsPluginFactory* _pInstance; public: ~DebtagsPluginFactory(); void setContainer(DebtagsPluginContainer* pContainer) { _pContainer = pContainer; }; /** @name IPluginFactory interface */ //@{ /** @brief This creates a plugin for the given name. * * Accepted names are: * \li "DebtagsPlugin" * \li "RelatedPlugin" * * @pre setContainer() must have been called or 0 will be returned. */ virtual Plugin* createPlugin(const string& name) const; //@} static DebtagsPluginFactory* getInstance(); }; }; #endif // __NPLUGINDEBTAGSPLUGINFACTORY_H_ packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagssettingswidget.cpp0000644000000000000000000000373013507430555024566 0ustar // // C++ Implementation: debtagssettingswidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "debtagssettingswidget.h" #include /* #include #include #include */ // NTagModel #include "vocabularymodel.h" #include "vocabularymodelrole.h" #include "filterhiddenproxymodel.h" #include #include "exception.h" DebtagsSettingsWidget::DebtagsSettingsWidget(NTagModel::VocabularyModel* pModel, QWidget *parent, const char *name) : QWidget(parent), Ui::DebtagsSettingsWidget() { using namespace wibble::operators; typedef NTagModel::FilterHiddenProxyModel FilterHiddenProxyModel; if (name) setObjectName(name); setupUi(this); _pModel = pModel; // will be garbage collected _pShownModel = new FilterHiddenProxyModel(false, this); _pHiddenModel = new FilterHiddenProxyModel(true, this); _pShownModel->setSourceModel(_pModel); _pHiddenModel->setSourceModel(_pModel); _pShownModel->setDynamicSortFilter(true); _pHiddenModel->setDynamicSortFilter(true); _pShownFacetsList->setModel(_pShownModel); _pHiddenFacetsList->setModel(_pHiddenModel); } DebtagsSettingsWidget::~DebtagsSettingsWidget() { } void DebtagsSettingsWidget::on__pAddButton_clicked() { QModelIndexList selected = _pShownFacetsList->selectionModel()->selectedIndexes(); QModelIndex proxyIndex; foreach(proxyIndex, selected) { QModelIndex index = _pShownModel->mapToSource(proxyIndex); _pModel->setData(index, true, NTagModel::HiddenRole); } } void DebtagsSettingsWidget::on__pRemoveButton_clicked() { QModelIndexList selected = _pHiddenFacetsList->selectionModel()->selectedIndexes(); QModelIndex proxyIndex; foreach(proxyIndex, selected) { QModelIndex index = _pHiddenModel->mapToSource(proxyIndex); _pModel->setData(index, false, NTagModel::HiddenRole); } } packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagssettingswidget.h0000644000000000000000000000303613507430555024232 0ustar // // C++ Interface: debtagssettingswidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __DEBTAGSSETTINGSWIDGET_H_2005_08_28 #define __DEBTAGSSETTINGSWIDGET_H_2005_08_28 #include #include #include using namespace std; namespace NTagModel { class VocabularyModel; class FilterHiddenProxyModel; } /** @brief Widget used to let the user select facets to be hidden and shown. * * @author Benjamin Mesing */ class DebtagsSettingsWidget : public QWidget, public Ui::DebtagsSettingsWidget { Q_OBJECT typedef NTagModel::FilterHiddenProxyModel FilterHiddenProxyModel; NTagModel::VocabularyModel* _pModel; FilterHiddenProxyModel* _pShownModel; FilterHiddenProxyModel* _pHiddenModel; public: /** * @param hiddenFacets the facets which are selected to be hidden */ DebtagsSettingsWidget(NTagModel::VocabularyModel* pModel, QWidget *parent = 0, const char *name = 0); ~DebtagsSettingsWidget(); protected Q_SLOTS: /** @brief The button to add facets to the hidden facets was clicked. */ void on__pAddButton_clicked(); /** @brief The button to remove facets from the hidden facets was clicked. */ void on__pRemoveButton_clicked(); signals: /** @brief Emitted whenever the user hid a facet. */ void facetHidden(const string& facet); /** @brief Emitted whenever the user showed a facet. */ void facetShown(const string& facet); }; #endif // __DEBTAGSSETTINGSWIDGET_H_2005_08_28 packagesearch-2.7.11build1/src/plugins/debtagsplugin/debtagssettingswidget.ui0000644000000000000000000000537013507430555024423 0ustar DebtagsSettingsWidget 0 0 480 298 Form2 10 6 0 6 0 6 Facets Shown QAbstractItemView::ExtendedSelection 0 6 >> << 0 6 Facets Hidden QAbstractItemView::ExtendedSelection qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/debtagsplugin/emptytagfilter.cpp0000644000000000000000000000545713507430555023240 0ustar // // C++ Implementation: emptytagfilter // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "emptytagfilter.h" #include #include #include // NTagModel #include "vocabularymodel.h" #include "vocabularymodelrole.h" // NPlugin #include "debtagsplugincontainer.h" #include "debtagshelper.h" namespace NTagModel { EmptyTagFilter::EmptyTagFilter(const VocabularyModel* pModel, const Xapian::Database& xapian, QObject* pParent) : QSortFilterProxyModel(pParent), _xapian(xapian) { _tagSelectionHasChanged = false; _pVocabularyModel = pModel; connect(_pVocabularyModel, SIGNAL(selectionChanged()), SLOT(tagSelectionChanged())); } EmptyTagFilter::~EmptyTagFilter() { } bool EmptyTagFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { QModelIndex current = sourceModel()->index(sourceRow, 0, sourceParent); // facets are always accepted if (sourceModel()->data(current, TypeRole).toInt() == FacetTypeItem) { return true; } // Also apply filtering if no tags are selected, because there are tags in the vocab // which are not used //if (_pVocabularyModel->selectedTags().empty()) // return true; // static set companionTags; // if (_tagSelectionHasChanged) { // companionTags = ; // _tagSelectionHasChanged = false; // } // if (companionTags.find(tag) == companionTags.end()) // qDebug("Tag " + toQString(tag.fullname()) + " is hidden as non-companion"); // else // qDebug("Tag " + toQString(tag.fullname()) + " is shown as companion"); // return companionTags.find(tag) != companionTags.end(); Xapian::Enquire enq(_xapian); set includeTags = _pVocabularyModel->selectedTags(); Tag tag = sourceModel()->data(current, TagRole).value().tag; includeTags.insert(tag); set terms; for (set::const_iterator it = includeTags.begin(); it != includeTags.end(); ++it) { terms.insert(string("XT") + *it); } Xapian::Query query(Xapian::Query::OP_AND, terms.begin(), terms.end()); enq.set_query(query); Xapian::MSet match = enq.get_mset(0, 1); return (match.size() != 0); } void EmptyTagFilter::tagSelectionChanged() { _tagSelectionHasChanged = true; // it is not sufficient to call invalidateFilter() here (QT 4.5) this seems to be a QT bug // calling only invalidateFilter() does lead to hidden facets not being displayed as expected /* Bug description: [LB] select tag biology:CLUSTAL/ALN, type XML into tag-filter, remove tag XML -> XML facets are no longer shown Gives different result with biology:EMBOSSS Same goes for: workswith::XML && use::Data Visualisation -> Filter: "compiler" -> remove use::Data vis (compiler should now show devel::compiler but does not) */ invalidate(); } } // NTagModel packagesearch-2.7.11build1/src/plugins/debtagsplugin/emptytagfilter.h0000644000000000000000000000321513507430555022673 0ustar // // C++ Interface: emptytagfilter // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_EMPTYTAGFILTER_H_2007_04_06 #define __NTAGMODEL_EMPTYTAGFILTER_H_2007_04_06 #include #include using namespace std; namespace NPlugin { class DebtagsPluginContainer; } namespace Xapian { class Database; } namespace NTagModel { class VocabularyModel; /** Filters out all tags, that would lead to an empty search result. * * To filter out the tags, the set of currently selected tags (_selectedTags) is considered * and only tags which are assigned to at least one of packages selected by that tag set are shown. * * @author Benjamin Mesing */ class EmptyTagFilter : public QSortFilterProxyModel { Q_OBJECT typedef std::string Tag; /** The xapian database. */ const Xapian::Database& _xapian; /** The model holding the information about the selected tags. * * This information is required, to be able to access the selected tags. * The model is also used to access the Debtags object. */ const VocabularyModel* _pVocabularyModel; /** @brief This indicates if the tag selection has changed since the last calculation of the companion tags. */ mutable bool _tagSelectionHasChanged; public: EmptyTagFilter(const VocabularyModel* pModel, const Xapian::Database& xapian, QObject* pParent = 0); virtual ~EmptyTagFilter(); virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const; public Q_SLOTS: void tagSelectionChanged(); }; } #endif packagesearch-2.7.11build1/src/plugins/debtagsplugin/filterhiddenproxymodel.cpp0000644000000000000000000000157313507430555024757 0ustar // // C++ Implementation: filterhiddenproxymodel // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "filterhiddenproxymodel.h" // NTagModel #include "vocabularymodelrole.h" namespace NTagModel { FilterHiddenProxyModel::FilterHiddenProxyModel(bool displayHidden, QObject * pParent) : QSortFilterProxyModel(pParent) { _displayHidden = displayHidden; } FilterHiddenProxyModel::~FilterHiddenProxyModel() { } bool FilterHiddenProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); if (sourceModel()->data(index, TypeRole).toInt() == TagTypeItem) return true; bool isHidden = sourceModel()->data(index, HiddenRole).toBool(); return isHidden == _displayHidden; } } packagesearch-2.7.11build1/src/plugins/debtagsplugin/filterhiddenproxymodel.h0000644000000000000000000000216413507430555024421 0ustar // // C++ Interface: filterhiddenproxymodel // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_FILTERHIDDENPROXYMODEL_H_2007_03_30 #define __NTAGMODEL_FILTERHIDDENPROXYMODEL_H_2007_03_30 #include namespace NTagModel { /** * Filters model depending on wether HiddenRole is set. @author Benjamin Mesing */ class FilterHiddenProxyModel : public QSortFilterProxyModel { Q_OBJECT /** @brief Controls whether to display only hidden items or only unhidden items. * * If true only hidden items will be displayed, else only unhidden. */ bool _displayHidden; public: /** Creates an instance. * * @param displayHidden used to set _displayHidden */ FilterHiddenProxyModel(bool displayHidden, QObject * pParent = 0); ~FilterHiddenProxyModel(); /** @brief Sets _displayHidden. */ void setDisplayHidden(bool displayHidden) { _displayHidden = displayHidden; } bool filterAcceptsRow ( int sourceRow, const QModelIndex & sourceParent ) const; }; } #endif packagesearch-2.7.11build1/src/plugins/debtagsplugin/filterselectedproxymodel.cpp0000644000000000000000000000166013507430555025311 0ustar // // C++ Implementation: filterselectedproxymodel // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "filterselectedproxymodel.h" #include // NTagModel #include "vocabularymodelrole.h" namespace NTagModel { FilterSelectedProxyModel::FilterSelectedProxyModel(bool includeSelected, QObject * pParent) : QSortFilterProxyModel(pParent) { _includeSelected = includeSelected; } FilterSelectedProxyModel::~FilterSelectedProxyModel() { } bool FilterSelectedProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); if (sourceModel()->data(index, TypeRole).toInt() == FacetTypeItem) { return true; } bool isSelected = sourceModel()->data(index, SelectedRole).toBool(); return isSelected == _includeSelected; } } packagesearch-2.7.11build1/src/plugins/debtagsplugin/filterselectedproxymodel.h0000644000000000000000000000273013507430555024755 0ustar // // C++ Interface: filterselectedproxymodel // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_FILTERSELECTEDPROXYMODEL_H_2007_03_28 #define __NTAGMODEL_FILTERSELECTEDPROXYMODEL_H_2007_03_28 #include namespace NTagModel { class VocabularyModel; /** @brief Proxy model that filters items according to whether the items are selected or not. * * _includeSelected controls which items to be displayed. * * To determine if an item is selected, the data for the SelectedRole is queried * (which should return a boolean). Selection as meant here has nothing to do with * traditional selection (e.g. by clicking on items). * * @author Benjamin Mesing */ class FilterSelectedProxyModel : public QSortFilterProxyModel { Q_OBJECT /** @brief Controls which items to be displayed, if true only selected items will be * diplayed, else only unselected items. */ bool _includeSelected; public: /** Creates an instance. * * @param includeSelected used to set _includeSelected */ FilterSelectedProxyModel(bool includeSelected, QObject * pParent = 0); ~FilterSelectedProxyModel(); /** @brief Sets _includeSelected. */ void setIncludeSelected(bool includeSelected) { _includeSelected = includeSelected; } bool filterAcceptsRow ( int sourceRow, const QModelIndex & sourceParent ) const; }; } #endif packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedfeedbackwidget.cpp0000644000000000000000000000123113507430555024453 0ustar // // C++ Implementation: relatedfeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "relatedfeedbackwidget.h" RelatedFeedbackWidget::RelatedFeedbackWidget(QWidget *parent, const char *name) : QWidget(parent), Ui::RelatedFeedbackWidget() { if (name) setObjectName(name); setupUi(this); } RelatedFeedbackWidget::~RelatedFeedbackWidget() { } void RelatedFeedbackWidget::setClearButton( QPushButton * pButton, int index ) { delete(_pClearButton); _pClearButton = pButton; _pFeedbackLayout->insertWidget(index, _pClearButton); } packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedfeedbackwidget.h0000644000000000000000000000127413507430555024127 0ustar // // C++ Interface: relatedfeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RELATEDFEEDBACKWIDGET_H_2005_08_28 #define __RELATEDFEEDBACKWIDGET_H_2005_08_28 #include #include class QPushButton; /** @author Benjamin Mesing */ class RelatedFeedbackWidget : public QWidget, public Ui::RelatedFeedbackWidget { Q_OBJECT public: RelatedFeedbackWidget(QWidget *parent = 0, const char *name = 0); ~RelatedFeedbackWidget(); void setClearButton(QPushButton* pButton, int index ); }; #endif // __RELATEDFEEDBACKWIDGET_H_2005_08_28 packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedfeedbackwidget.ui0000644000000000000000000000335613507430555024320 0ustar RelatedFeedbackWidget 0 0 311 61 Form2 2 0 Search packages similar to 2 0 displays the package to search related packages for This displays the package for which you want to search related packages for. Enter the package under the "Related" section. true Clear qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedinput.cpp0000644000000000000000000000061413507430555022666 0ustar // // C++ Implementation: relatedinput // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "relatedinput.h" RelatedInput::RelatedInput(QWidget *parent, const char *name) : QWidget(parent) { if (name) setObjectName(name); setupUi(this); } RelatedInput::~RelatedInput() { } packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedinput.h0000644000000000000000000000100613507430555022327 0ustar // // C++ Interface: relatedinput // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RELATEDINPUT_H_2005_08_28 #define __RELATEDINPUT_H_2005_08_28 #include #include /** @author Benjamin Mesing */ class RelatedInput : public QWidget, public Ui::RelatedInput { Q_OBJECT public: RelatedInput(QWidget *parent = 0, const char *name = 0); ~RelatedInput(); }; #endif // packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedinput.ui0000644000000000000000000000635013507430555022524 0ustar RelatedInput 0 0 240 153 Form1 6 5 Similar to package true true 6 0 Result packages Number of result packages Defines the number of the most similar packages which will be displayed. 10000 10 20 6 0 Qt::Horizontal QSizePolicy::Expanding 71 20 Clear realated search Clear Qt::Vertical QSizePolicy::Expanding 20 16 qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedplugin.cpp0000644000000000000000000001320713507430555023027 0ustar #include #include #include #include #include #include #include #include #include #undef slots #include #include // NUtil #include // NPlugin #include // NPlugin #include "relatedplugin.h" #include "relatedinput.h" #include "relatedfeedbackwidget.h" // NUtil #include "debtagshelper.h" namespace NPlugin { const QString RelatedPlugin::PLUGIN_NAME = "RelatedPlugin"; RelatedPlugin::RelatedPlugin(const DebtagsPluginContainer& container) : _container(container) { _pMainWindow = 0; _pProvider = 0; _pRelatedInput = 0; _pRelatedFeedbackWidget = 0; _isInactive = true; } RelatedPlugin::~RelatedPlugin() { delete _pRelatedInput; delete _pRelatedFeedbackWidget; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// QString RelatedPlugin::title() const { return tr("Similar Plugin"); } QString RelatedPlugin::briefDescription() const { return tr("Plugin for searching packages similar to another package."); } QString RelatedPlugin::description() const { return tr("Plugin for searching packages similar to another package."); } void RelatedPlugin::init(IProvider* pProvider) { _pProvider = pProvider; _pMainWindow = pProvider->mainWindow(); _pRelatedInput = new RelatedInput(_pMainWindow, "RelatedInput"); const set& packages = pProvider->packages(); for (set::const_iterator it = packages.begin(); it != packages.end(); ++it) _pRelatedInput->_pPackageInput->addItem(toQString(*it)); _pRelatedInput->_pPackageInput->setMinimumWidth(100); _pRelatedInput->_pPackageInput->setEditText(""); connect(_pRelatedInput->_pPackageInput, SIGNAL(activated(const QString&)), SLOT(evaluateSearch())); connect(_pRelatedInput->_pClearButton, SIGNAL(clicked()), SLOT(onClearSearch())); _pRelatedFeedbackWidget = new RelatedFeedbackWidget(_pMainWindow, "RelatedFeedbackWidget"); _pRelatedFeedbackWidget->setClearButton( pProvider->createClearButton(_pRelatedFeedbackWidget, "AptClearButton"), 0); connect(_pRelatedFeedbackWidget->_pClearButton, SIGNAL(clicked()), SLOT(onClearSearch())); _pRelatedFeedbackWidget->setVisible(false); connect( _pRelatedInput->_pResultNumber, SIGNAL(valueChanged(int)), SLOT(evaluateSearch()) ); connect( _pRelatedInput->_pPackageInput, SIGNAL(editTextChanged(const QString&)), SLOT(onInputTextChanged(const QString&)) ); } ///////////////////////////////////////////////////// // SearchPlugin Interface ///////////////////////////////////////////////////// QString RelatedPlugin::inputWidgetTitle() const { return tr("Similar"); } QWidget* RelatedPlugin::inputWidget() const { return _pRelatedInput; } QWidget* RelatedPlugin::shortInputAndFeedbackWidget() const { return _pRelatedFeedbackWidget; } void RelatedPlugin::clearSearch() { _pRelatedInput->_pPackageInput->setEditText(""); } const std::set& RelatedPlugin::searchResult() const { return _searchResult; } ///////////////////////////////////////////////////// // ScorePlugin Interface ///////////////////////////////////////////////////// bool RelatedPlugin::offersScore() const { return !isInactive(); } void RelatedPlugin::ScoreCalculator::calculateScore(const set& packages) { for (set::const_iterator it = packages.begin(); it != packages.end(); ++it) { map::const_iterator jt = _scores.find(*it); // should not happen if (jt == _scores.end()) setScore(*it, 0); setScore(*it, jt->second); } } map RelatedPlugin::getScore(const set& packages) const { _calculator.calculateScore(packages); return _calculator.getScore(); } ///////////////////////////////////////////////////// // helper functions ///////////////////////////////////////////////////// void RelatedPlugin::onInputTextChanged(const QString& text) { if (text == "") evaluateSearch(); } void RelatedPlugin::evaluateSearch() { _pProvider->reportBusy(this, tr("Searching for similar packages")); _searchResult.clear(); _calculator._scores.clear(); _pRelatedFeedbackWidget->_pSimilarSearchTextView->setText( _pRelatedInput->_pPackageInput->currentText() ); string package = toString(_pRelatedInput->_pPackageInput->currentText()); _isInactive = package.empty(); // if no input was given the search is inactive if ( !_isInactive ) { int num = _pRelatedInput->_pResultNumber->value(); std::pair document = documentForPackage(package, _pProvider->xapian()); if (!document.first) { qWarning() << QString("Empty result set for search XP") << toQString(package); return; } Xapian::Document& packageDocument = document.second; // search all documents containing any of the search terms taken from the original // package Xapian::Query query(Xapian::Query::OP_OR, packageDocument.termlist_begin(), packageDocument.termlist_end()); Xapian::Enquire enq(_pProvider->xapian()); enq.set_query(query); // get the best matches Xapian::MSet matches = enq.get_mset(0, num); for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i) { string package = i.get_document().get_data(); _searchResult.insert(package); _calculator._scores[package] = i.get_percent() / 100.0f; } } // show the feedback widget only if a search was entered _pRelatedFeedbackWidget->setVisible(!_isInactive); _pProvider->reportReady(this); emit searchChanged(this); } void RelatedPlugin::setWidgetsEnabled(bool enabled) { if (_pRelatedInput) _pRelatedInput->setEnabled(enabled); } } // namespace NPlugin #undef emit packagesearch-2.7.11build1/src/plugins/debtagsplugin/relatedplugin.h0000644000000000000000000001167613507430555022504 0ustar #ifndef __RELATEDPLUGIN_H_2004_06_23 #define __RELATEDPLUGIN_H_2004_06_23 #include // NPlugin #include #include #include #include class QMainWindow; class RelatedInput; class RelatedFeedbackWidget; namespace NPlugin { /** @brief A plugin offering a search for packages similar to another one and * providing a scoring based on the degree of similarity. * * The plugin offers to search packages similar to another package. The latter * can be selected in a combobox. Additionally the degree of the maximum distance * to the package can be choosen. The distance is calculated by * \f$|(A \cup B) \setminus (A \cap B)|\f$ * * The scores for the packages are calculated in the getScores() function. */ class RelatedPlugin : public SearchPlugin, public ScorePlugin { Q_OBJECT /** Class used to calculate the scores for related plugins. */ class ScoreCalculator : public ScoreCalculationStrategyBase { public: /** @brief Holds the scores for the packages in the search result. */ map _scores; /** @brief Calculates the scores for the handed set of packages. * * Old calculations will be cleared. */ virtual void calculateScore(const set& packages); }; typedef std::string Tag; public: static const QString PLUGIN_NAME; RelatedPlugin(const DebtagsPluginContainer& container); ~RelatedPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; //@} /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ virtual uint searchPriority() const { return 10; } /** @brief Returns a widget where you can select the debtags you want to in- and exclude. */ virtual QWidget* inputWidget() const; /** @brief Returns "Debtags". */ virtual QString inputWidgetTitle() const; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return false; }; virtual const std::set& searchResult() const; /** @brief Unused, because this plugin does not use the filter technique. */ virtual bool filterPackage(const string&) const { return true; }; virtual bool isInactive() const { return _isInactive; }; //@} /** @name ScorePlugin interface * * Implementation of the ScorePlugin interface */ //@{ /** @brief Returns the score for the handed packages for the currently active search. * * The score for a package is calculated based on the distance of the tag sets of the * package to the "base" package. The higher the distance, the lower * the scores. */ virtual map getScore(const set& packages) const; /** @brief Returns true if a valid package was selected. * * It returns false if either no or an unkown package was selected. */ virtual bool offersScore() const; //@} protected Q_SLOTS: /** @brief Called whenever the user requests to clear the search. */ void onClearSearch() { clearSearch(); }; /** @brief This is called everytime the search changes. * * It might emit the searchChanged() signal. */ void evaluateSearch(); /** @brief This is called whenever the text of the widget where to insert the * package to be matched changes. * * Is only needed because the QComboBox::setCurrentText("") function does not * trigger a activated() signal. */ void onInputTextChanged(const QString& text); /** This enables/ disables the visible widgets. */ void setWidgetsEnabled(bool enabled); private: /** Used to calculate the scores fo the plugin. */ mutable ScoreCalculator _calculator; /** The container which holds this plugin. */ const DebtagsPluginContainer& _container; /** @brief Holds the result of the search currently active. */ std::set _searchResult; /** @brief Holds a pointer to the Plugin Manager which manages this plugin. */ IProvider* _pProvider; /** @brief Holds a pointer to the main window this plugin belongs to. */ QMainWindow* _pMainWindow; /** @brief Holds a pointer to the widget used for inputting the related search. */ RelatedInput* _pRelatedInput; /** @brief Holds a pointer to the widget used for displaying the currenly active search. * * This widget will be hidden if no search was active i.e. if #_isInactive is true. */ RelatedFeedbackWidget* _pRelatedFeedbackWidget; /** This holds if the search is currently inactive. */ bool _isInactive; /** This is the delay time in ms the delay timer waits for another input. */ uint _delayTime; }; } // namespace NPlugin #endif // __RELATEDPLUGIN_H_2004_06_23 packagesearch-2.7.11build1/src/plugins/debtagsplugin/selectedtagsview.cpp0000644000000000000000000000462413507430555023535 0ustar // // C++ Implementation: selectedtagsview // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "selectedtagsview.h" #include #include #include #include #include #include #include // NTagModel #include "taglistproxymodel.h" #include "vocabularymodel.h" #include "treefiltermodel.h" using namespace std; namespace NTagModel { SelectedTagsView::SelectedTagsView(QWidget * parent) : QListView(parent), _selectedProxyModel(true, this) { // _displayedTagsNum = 0; connect(this, SIGNAL(doubleClicked(const QModelIndex&)), SLOT(onItemDoubleClicked(const QModelIndex&))); // garbage collected _pTagListProxyModel = new TagListProxyModel(this); QListView::setModel(&_selectedProxyModel); setToolTip(tr("deselect a tag by double-clicking")); setWhatsThis(tr("This list displays the tags currently searched for. " "To remove a tag double-click it.")); } SelectedTagsView::~SelectedTagsView() { } void SelectedTagsView::setModel(QAbstractItemModel* pModel) { assert(dynamic_cast(pModel) != 0); _pModel = dynamic_cast(pModel); _pTagListProxyModel->setSourceModel(pModel); // we cannot set _pTagListProxyModel as source of _selectedProxyModel earlier, // because its source needs to be initialised before (with the vocabulary Model) _selectedProxyModel.setSourceModel(_pTagListProxyModel); //_selectedProxyModel.setSourceModel(pModel); _selectedProxyModel.setDynamicSortFilter(true); } void SelectedTagsView::onItemDoubleClicked(const QModelIndex& index ) { model()->setData(index, false, SelectedRole); } void SelectedTagsView::contextMenuEvent(QContextMenuEvent* pEvent) { QMenu menu(this); QModelIndex index = indexAt(pEvent->pos()); QAction* pClear = menu.addAction(tr("Clear")); QAction* pRemove = 0; // if the context menu was requested for a tag if ( index.isValid() ) { pRemove = menu.addAction(tr("Remove")); // not yet // QAction* pSelectAsUnwanted = menu.addAction("Select as unwanted"); } QAction* pAction = menu.exec(pEvent->globalPos()); if (pAction) { if (pAction == pRemove) // the index is definitely valid here model()->setData(index, false, SelectedRole); else if (pAction == pClear) { vocabularyModel()->setAllUnselected(); } } } } packagesearch-2.7.11build1/src/plugins/debtagsplugin/selectedtagsview.h0000644000000000000000000000266413507430555023204 0ustar // // C++ Interface: selectedtagsview // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_SELECTEDTAGSVIEW_2007_03_25 #define __NTAGMODEL_SELECTEDTAGSVIEW_2007_03_25 #include // NTagModel #include "filterselectedproxymodel.h" class QAbstractProxyModel; class QContextMenuEvent; class TreeFilterModel; namespace NTagModel { class VocabularyModel; class TagListProxyModel; /** Shows the selected tags in a simple list * * Expects a VocabularyModel as source model. * @author Benjamin Mesing */ class SelectedTagsView : public QListView { Q_OBJECT /** @brief The number of tags currently displayed. */ // int _displayedTagsNum; NTagModel::FilterSelectedProxyModel _selectedProxyModel; TagListProxyModel* _pTagListProxyModel; VocabularyModel* _pModel; TreeFilterModel* _pTreeFilterModel; public: SelectedTagsView(QWidget * parent = 0); ~SelectedTagsView(); /** @brief Sets the vocabulary mode to be displayed. * * @param pModel must be a VocabularyModel. */ virtual void setModel(QAbstractItemModel* pModel); protected Q_SLOTS: virtual void onItemDoubleClicked(const QModelIndex& index); virtual void contextMenuEvent(QContextMenuEvent* pEvent); protected: VocabularyModel* vocabularyModel() { return _pModel; }; }; } #endif // __NTAGMODEL_SELECTEDTAGSVIEW_2007_03_25 packagesearch-2.7.11build1/src/plugins/debtagsplugin/selectioninputanddisplay.cpp0000644000000000000000000000414413507430555025306 0ustar // // C++ Implementation: selectioninputanddisplay // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "selectioninputanddisplay.h" #include #include #include #include // NTagModel #include "vocabularymodel.h" #include "vocabularymodelrole.h" #include "unselectedtagsview.h" #include "selectedtagsview.h" #include "emptytagfilter.h" #include "helpers.h" using namespace wibble::operators; namespace NWidgets { typedef std::string Facet; typedef std::string Tag; SelectionInputAndDisplay::SelectionInputAndDisplay(const NPlugin::DebtagsPluginContainer* pContainer, NTagModel::VocabularyModel* pModel, QObject* pParent) : QObject(pParent), _pModel(pModel) { _pTagSelectorWidget = new QWidget(); QLayout* pLayout = new QVBoxLayout(_pTagSelectorWidget); QLineEdit* pFilterInput = new QLineEdit(_pTagSelectorWidget); pFilterInput->setToolTip(tr("filter string to filter tags")); pFilterInput->setWhatsThis(tr("Filters the tag names by the string in realtime.")); // will be garbage collected once DebtagsPlugin is destroyed _pTagSelector = new NTagModel::UnselectedTagsView(pContainer, _pTagSelectorWidget); _pTagSelector->setModel(_pModel); _pTagSelector->show(); pLayout->addWidget(pFilterInput); pLayout->addWidget(_pTagSelector); connect(pFilterInput, SIGNAL(textChanged(const QString&)), _pTagSelector, SLOT(setFilterFixedString(const QString&))); _pSelectedTagDisplay = new NTagModel::SelectedTagsView(); _pSelectedTagDisplay->setModel(_pModel); } SelectionInputAndDisplay::~SelectionInputAndDisplay() { delete _pSelectedTagDisplay; delete _pTagSelector; delete _pTagSelectorWidget; } void SelectionInputAndDisplay::setSelectedTagDisplayShown(bool shown) { _pSelectedTagDisplay->setVisible(shown); } void SelectionInputAndDisplay::setEnabled(bool enabled) { _pTagSelector->setEnabled(enabled); _pSelectedTagDisplay->setEnabled(enabled); } } // namespace NWidgets #undef emit //#include packagesearch-2.7.11build1/src/plugins/debtagsplugin/selectioninputanddisplay.h0000644000000000000000000000463413507430555024757 0ustar // // C++ Interface: selectioninputanddisplay // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __SELECTIONINPUTANDDISPLAY_H_2004_06_28 #define __SELECTIONINPUTANDDISPLAY_H_2004_06_28 #include #include class QAbstractItemView; class QLabel; class QWidget; class QModelIndex; class TagItem; namespace NTagModel { class VocabularyModel; class UnselectedTagsView; } namespace NPlugin { class DebtagsPluginContainer; } using namespace std; namespace NWidgets { /** @brief This class manages a widget to selected tags and one to display * the selected tags * @author Benjamin Mesing * */ class SelectionInputAndDisplay : public QObject { Q_OBJECT /** Widget to display the selected tags. * * @see _pTagSelector */ QAbstractItemView* _pSelectedTagDisplay; /** Widget to selected the tags to search. * * @see _pSelectedTagDisplay */ NTagModel::UnselectedTagsView* _pTagSelector; /** Contains all widgets used for selecting tags. * * This currently includes an AbstractItemView for displaying the tags and a * LineEdit for typing a filter. */ QWidget* _pTagSelectorWidget; /** Holds the model for the debtags vocabulary. */ NTagModel::VocabularyModel* _pModel; typedef std::string Facet; typedef std::string Tag; /** @brief The label shown above #_pTagView. */ QLabel* _pViewLabel; public: /** By default, the selectedTagDisplay will be hidden. * @param pParent the parent of this class */ SelectionInputAndDisplay(const NPlugin::DebtagsPluginContainer* pContainer, NTagModel::VocabularyModel* pModel, QObject* pParent); ~SelectionInputAndDisplay(); QWidget* tagSelectorWidget() const { return _pTagSelectorWidget; }; QAbstractItemView* tagDisplayWidget() const { return _pSelectedTagDisplay; }; public Q_SLOTS: /** @brief Shows or hides the widget displaying the selected tags. * * By default it is shown. */ void setSelectedTagDisplayShown(bool shown); /** @brief Enables/disables all widgets managed by this class. */ void setEnabled(bool enabled); signals: /** @brief The signal will be emitted, whenever the set of selected tags is changed. * * @param tags the tags that were selected by the user. */ void tagItemsSelected(std::set tags); }; } // namespace NWidgets #endif // __SELECTIONINPUTANDDISPLAY_H_2004_06_28 packagesearch-2.7.11build1/src/plugins/debtagsplugin/tagchooserwidget.cpp0000644000000000000000000000064413507430555023533 0ustar // // C++ Implementation: tagchooserwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "tagchooserwidget.h" TagChooserWidget::TagChooserWidget(QWidget *parent, const char *name) : QWidget(parent) { if (name) setObjectName(name); setupUi(this); } TagChooserWidget::~TagChooserWidget() { } packagesearch-2.7.11build1/src/plugins/debtagsplugin/tagchooserwidget.h0000644000000000000000000000103013507430555023166 0ustar // // C++ Interface: tagchooserwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __TAGCHOOSERWIDGET_H_ #define __TAGCHOOSERWIDGET_H_ #include #include /** @author Benjamin Mesing */ class TagChooserWidget : public QWidget, public Ui::TagChooserWidget { Q_OBJECT public: TagChooserWidget(QWidget *parent = 0, const char *name = 0); ~TagChooserWidget(); }; #endif // packagesearch-2.7.11build1/src/plugins/debtagsplugin/tagchooserwidget.ui0000644000000000000000000000303513507430555023363 0ustar TagChooserWidget 0 0 363 288 Form1 5 6 Show packages with these tags Check this to be able to exclude some tags Check this if you want to exclude some tags. If you check it, a list of tags will be shown. There you can select which to exclude. Exclude Tags but not these tags qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/debtagsplugin/taglistproxymodel.h0000644000000000000000000001157313507430555023433 0ustar // // C++ Interface: taglistproxymodel // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include #include // NTagModel #include "vocabularymodelrole.h" #include "vocabularymodel.h" #include using namespace std; namespace NTagModel { /** This proxy model limits the items to be viewed to the tags inside the facets. * * The tags are proxied to be in a simple list (i.e. no hierarchies will be considered). * * The proxy model expects a VocabularyModel as source model. */ class TagListProxyModel : public QAbstractProxyModel { Q_OBJECT typedef std::string Tag; typedef std::string Facet; /** Maps the row to the tag with the given name. */ map _rowToTag; /** Maps the tag name to the row for the tag. */ map _tagToRow; protected Q_SLOTS: /** Emits the dataChanged signal for the tags matching the given source indexes. */ virtual void onVocabularyModelChanged(const QModelIndex & sourceTl, const QModelIndex & sourceBr) { emit(dataChanged(mapFromSource(sourceTl), mapFromSource(sourceBr))); } public: TagListProxyModel(QObject * pParent) : QAbstractProxyModel(pParent) { } /** Determines the index by looking up the tag referred to by source index in _tagToRow. */ virtual QModelIndex mapFromSource(const QModelIndex& sourceIndex) const { ItemData* pData = (ItemData*) sourceIndex.internalPointer(); if (pData->isFacet()) { return QModelIndex(); } else { TagData* pTagData = pData->toTagData(); int row = _tagToRow.find(pTagData->tag())->second; return index(row, sourceIndex.column()); } } /** Determines the source index by querying VocabularyModel::indexForTag() for the tag * referred to by proxyIndex. */ virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const { std::map::const_iterator it = _rowToTag.find(proxyIndex.row()); if (it == _rowToTag.end()) return QModelIndex(); Tag tag = it->second; return vocabularyModel()->indexForTag(tag, proxyIndex.column()); } virtual QModelIndex index(int r, int c, const QModelIndex &ind=QModelIndex()) const { (void) ind; return createIndex(r,c); } /** Returns QModelIndex(). */ virtual QModelIndex parent(const QModelIndex&) const { return QModelIndex(); } /** Returns the number of tags in this model. */ virtual int rowCount(const QModelIndex& parent) const { if (!parent.isValid()) { return _tagToRow.size(); } else return 0; } /** Forwards retrieving the column count to the source model. */ virtual int columnCount(const QModelIndex &) const { return sourceModel()->columnCount(); } /** Forwards retrieving the data to the source model. */ virtual QVariant data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) return sourceModel()->data(mapToSource(index), FullDisplayRole); else return sourceModel()->data(mapToSource(index), role); // qDebug("[SelectedTagView] Requesting data for row: %d, col: %d", index.row(), index.column()); } virtual QVariant headerData(int, Qt::Orientation, int = Qt::DisplayRole ) { return QVariant(); } /** Sets the source model and initialises _tagToRow and _rowToTag. * * Emits modelReset(). */ virtual void setSourceModel(VocabularyModel* pModel) { beginResetModel(); QAbstractProxyModel::setSourceModel(pModel); QModelIndex parent; int row = 0; for(int i = 0; i < pModel->rowCount(parent); ++i) { QModelIndex facetIndex = pModel->index(i, 0, parent); for(int j = 0; j < pModel->rowCount(facetIndex); ++j) { QModelIndex index = pModel->index(j, 0, facetIndex); ItemData* pData = (ItemData*) index.internalPointer(); TagData* pTagData = pData->toTagData(); _tagToRow[pTagData->tag()] = row; _rowToTag[row] = pTagData->tag(); ++row; } } qDebug("[TagListProxyModel.setSourceModel()] Added %d tags", row); connect(pModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(onVocabularyModelChanged(const QModelIndex &, const QModelIndex &))); connect(pModel, &VocabularyModel::modelReset, &TagListProxyModel::modelReset); endResetModel(); } /** @pre dynamic_cast(pModel) != 0 */ virtual void setSourceModel(QAbstractItemModel* pModel) { assert(dynamic_cast(pModel)); setSourceModel(static_cast(pModel)); } /** Forwards setting the data to the source model. */ virtual bool setData(const QModelIndex& index, const QVariant & value, int role = Qt::EditRole) { return sourceModel()->setData(mapToSource(index), value, role); } /** Returns the source model casted to a VocabularyModel pointer. */ VocabularyModel* vocabularyModel() const { return dynamic_cast(sourceModel()); } }; } packagesearch-2.7.11build1/src/plugins/debtagsplugin/treefiltermodel.h0000644000000000000000000000200413507430555023014 0ustar // // // Author: Benjamin Mesing , (C) 2012 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __TREEFILTERMODEL_H_2012_05_13 #define __TREEFILTERMODEL_H_2012_05_13 #include /** @brief A filter which hides top level nodes which do not have any child nodes. * * All child nodes will be accepted. * * @author Benjamin Mesing */ class TreeFilterModel : public QSortFilterProxyModel { public: TreeFilterModel(QObject * pParent = 0) : QSortFilterProxyModel(pParent) {} virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { if (sourceParent.isValid()) return true; QModelIndex current = sourceModel()->index(sourceRow, 0, sourceParent); // qStrDebug("TreeSortFilter:item: " + data(current).toString()); if (sourceModel()->rowCount(current) > 0) { // qDebug("has children: %d ", sourceModel()->rowCount(current)); return true; } return false; } }; #endif // __TREEFILTERMODEL_H_2012_05_13packagesearch-2.7.11build1/src/plugins/debtagsplugin/unselectedtagsview.cpp0000644000000000000000000001063413507430555024076 0ustar // // C++ Implementation: unselectedtagsview // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #include "unselectedtagsview.h" #include #include #include #include #include // NTagModel #include "debtagsplugincontainer.h" #include "vocabularymodelrole.h" #include "emptytagfilter.h" #include "treefiltermodel.h" #include namespace NTagModel { /** @brief A filter which accepts all facets and tags only if they match the active filter. * * * @author Benjamin Mesing */ class TextFilter : public QSortFilterProxyModel { public: TextFilter(QObject * pParent = 0) : QSortFilterProxyModel(pParent) {} virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const { // if we have a facet (i.e. a root item) if (!sourceParent.isValid()) { return true; } return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); } }; UnselectedTagsView::UnselectedTagsView(const NPlugin::DebtagsPluginContainer* pContainer, QWidget * parent) : QTreeView(parent), _filterSelectedProxyModel(false, this), _hiddenFilterProxyModel(false, this) { connect(this, SIGNAL(doubleClicked(const QModelIndex&)), SLOT(onItemDoubleClicked(const QModelIndex&))); // build up ProxyModel/Filter chain -> see class documentation for the order of the chain _hiddenFilterProxyModel.setDynamicSortFilter(true); _pTagFilter = new EmptyTagFilter(pContainer->vocabularyModel(), pContainer->xapian(), this); _pTagFilter->setDynamicSortFilter(true); _filterSelectedProxyModel.setDynamicSortFilter(true); _pTextFilter = new TextFilter(this); _pTextFilter->setFilterKeyColumn(-1); _pTextFilter->setFilterCaseSensitivity(Qt::CaseInsensitive); _pTextFilter->setDynamicSortFilter(true); // TODO _ commented for debugging _filterChain.push_back(&_hiddenFilterProxyModel); _filterChain.push_back(_pTagFilter); _filterChain.push_back(&_filterSelectedProxyModel); _filterChain.push_back(_pTextFilter); QSortFilterProxyModel* pTreeFilter = new TreeFilterModel(this); pTreeFilter->setDynamicSortFilter(true); _filterChain.push_back(pTreeFilter); vector::iterator it = _filterChain.begin(); vector::iterator oldIt = _filterChain.begin(); ++it; for (; it != _filterChain.end(); ++it ) { (*it)->setSourceModel(*oldIt); oldIt = it; } setToolTip(tr("select a tag by double-clicking")); setWhatsThis(tr("This list shows the tags that can be searched for. " "The tags are organised in a tree beneath their facets (groups of tags). " "To search for packages with a tag, double-click the tag. Multiple tags can be selected like this. Facets cannot be selected.")); } UnselectedTagsView::~UnselectedTagsView() { } void UnselectedTagsView::setModel(QAbstractItemModel* pModel) { _pDataModel = pModel; _filterChain.front()->setSourceModel(pModel); QTreeView::setModel(_filterChain.back()); resizeColumnToContents(0); } void UnselectedTagsView::onItemDoubleClicked(const QModelIndex& index ) { //_pDataModel->setData(_pTextFilter->mapToSource(index), true, SelectedRole); model()->setData(index, true, SelectedRole); } void UnselectedTagsView::contextMenuEvent(QContextMenuEvent* pEvent) { QMenu menu(this); QModelIndex index = indexAt(pEvent->pos()); QAction* pSelectAsWanted = 0; // if the context menu was requested for a tag if ( index.isValid() && (model()->data(index, TypeRole).toInt() == TagTypeItem) ) { pSelectAsWanted = menu.addAction(tr("Add")); // not yet // QAction* pSelectAsUnwanted = menu.addAction("Select as unwanted"); } menu.addSeparator(); QAction* pCollapseAll = menu.addAction(tr("Collapse all")); QAction* pExpandAll = menu.addAction(tr("Expand all")); QAction* pAction = menu.exec(pEvent->globalPos()); if (pAction) { if (pAction == pCollapseAll) collapseAll(); else if (pAction == pExpandAll) expandAll(); else if (pAction == pSelectAsWanted) // the index is definitely valid here model()->setData(index, true, SelectedRole); } } void UnselectedTagsView::setFilterFixedString(const QString& string) { _pTextFilter->setFilterFixedString(string); // invalidate the TextFilter, so that the following filters are reevaluated. // This is required, because the TreeFilter changes depending on the tags in the filter _pTextFilter->invalidate(); } } packagesearch-2.7.11build1/src/plugins/debtagsplugin/unselectedtagsview.h0000644000000000000000000000467313507430555023551 0ustar // // C++ Interface: unselectedtagsview // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_UNSELECTEDTAGSVIEW_2007_03_25 #define __NTAGMODEL_UNSELECTEDTAGSVIEW_2007_03_25 #include using namespace std; #include // NTagModel #include "filterselectedproxymodel.h" #include "filterhiddenproxymodel.h" class QAbstractProxyModel; class QContextMenuEvent; namespace NPlugin { class DebtagsPluginContainer; } class TreeFilterModel; namespace NTagModel { class EmptyTagFilter; /** @brief This class can be used to display and modify VocabularyModels. * * It may only be initialised with VocabularyModels. * It allows to choose an item by double clicking on it. * * Model chain: _pTreeFilter -> TextFilter -> _filterSelectedProxyModel -> _pTagFilter -> _hiddenFilterProxyModel -> sourceModel * -> denotes the uses realtion */ class UnselectedTagsView : public QTreeView { Q_OBJECT FilterSelectedProxyModel _filterSelectedProxyModel; FilterHiddenProxyModel _hiddenFilterProxyModel; EmptyTagFilter* _pTagFilter; /** @brief Filters the facets according to whether a subtags is shown. */ TreeFilterModel* _pTreeFilter; /** Filters the tags according to a match-string. * * @see setFilterFixedString() */ QSortFilterProxyModel* _pTextFilter; /** This is the model holding the actual data. */ QAbstractItemModel* _pDataModel; public: UnselectedTagsView(const NPlugin::DebtagsPluginContainer* pContainer, QWidget * parent = 0); ~UnselectedTagsView(); virtual void setModel(QAbstractItemModel* pModel); /** @brief Returns the filter responsible for filtering out tags which should not be shown since * they would lead to an empty result set. */ EmptyTagFilter* emptyTagFilter() { return _pTagFilter; }; public Q_SLOTS: /** Allows to set a string for which the tags shall be filtered. * * Tags will be shown if they match the the given string (case insensitive). * Facets will be shown if they match the given string or any of the containing * tags matches the string. */ void setFilterFixedString(const QString& string); protected Q_SLOTS: virtual void onItemDoubleClicked(const QModelIndex& index); virtual void contextMenuEvent(QContextMenuEvent* event); private: /** Debug. */ vector _filterChain; }; } #endif // __NTAGMODEL_UNSELECTEDTAGSVIEW_2007_03_25 packagesearch-2.7.11build1/src/plugins/debtagsplugin/vocabularymodel.cpp0000644000000000000000000002635013507430555023363 0ustar // // C++ Implementation: vocabularymodel // // Description: // // // Author: Benjamin Mesing , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #include "vocabularymodel.h" #include using namespace wibble::operators; // NTagModel #include "vocabularymodelrole.h" #include #include typedef std::string Tag; typedef std::string Facet; TagWrapper::TagWrapper() {} TagWrapper::TagWrapper(Tag tag_) : tag(tag_) {} namespace NTagModel { VocabularyModel::VocabularyModel(const NPlugin::DebtagsPluginContainer* pContainer) { _pContainer = pContainer; const set facets = _pContainer->facets(); int i = 0; const ept::debtags::Vocabulary* dtvoc = &_pContainer->vocabulary(); for (set::const_iterator it = facets.begin(); it != facets.end(); ++it, ++i) { Facet facet = *it; const ept::debtags::voc::FacetData* fd = dtvoc->facetData(facet); if (!fd) continue; _facets.push_back(new FacetData(fd, i)); _facetToFacetData[facet] = _facets.size()-1; set tags = fd->tags(); vector tagData; int j = 0; for (set::const_iterator jt = tags.begin(); jt != tags.end(); ++jt, ++j) { const ept::debtags::voc::TagData* td = dtvoc->tagData(*jt); if (!td) continue; tagData.push_back( new TagData(td, i) ); _tagToTagData[td->name] = make_pair(i, j); } _tags[facet] = tagData; } //_companionTagsValid = false; } VocabularyModel::~VocabularyModel() { } void VocabularyModel::setFacetHidden(bool hidden, string facet) { // if the facet exists if (_facetToFacetData.find(facet) != _facetToFacetData.end()) { int intIndex = _facetToFacetData.find(facet)->second; QModelIndex modelIndex = this->index(intIndex, 0, QModelIndex()); setData(modelIndex, hidden, HiddenRole); } } int VocabularyModel::rowCount(const QModelIndex & parent) const { // if the number of facets was requested if (!parent.isValid()) { return _facets.size(); } else { // only the first column has any children if (parent.column() != 0) return 0; const ItemData* pData = (ItemData*) parent.internalPointer(); assert(pData != 0); // if the parent is a facet, the number of children is the number of tags in the facet if (pData->isFacet()) { const FacetData* pParentData = (FacetData*) pData; return pParentData->eptFacetData()->tags().size(); } else // parent is a tag - tags do not have children (since tag grouping is not supported) supported) return 0; } } QVariant VocabularyModel::data(const QModelIndex& index, int role) const { // qDebug("Requesting data for row: %d, col: %d", index.row(), index.column()); // sometime an item -1, -1 is requested if (index.row() < 0 || index.column() < 0) return QVariant(); switch (role) { case Qt::ToolTipRole: { const ItemData* pData = (ItemData*) index.internalPointer(); assert(pData != 0); return pData->description(); } case Qt::DisplayRole: { const ItemData* pData = (ItemData*) index.internalPointer(); assert(pData != 0); if (index.column() == 1) return pData->fullname(); return pData->name(); } case FullDisplayRole: { const ItemData* pData = (ItemData*) index.internalPointer(); assert(pData != 0); if (index.column() == 1) { // VocabularyModel::data() should not be called with FullDiplayRole and index.column(), // it should be used only by the list view assert(false); return ""; } return pData->fullDisplayText(); } case SelectedRole: { const ItemData* pData = (ItemData*) index.internalPointer(); if (!pData->isFacet()) { const TagData* pTagData = pData->toTagData(); return pTagData->selected; } else return false; } case HiddenRole: { const ItemData* pData = (ItemData*) index.internalPointer(); if (pData->isFacet()) return pData->toFacetData()->hidden; else return false; } case TypeRole: { const ItemData* pData = (ItemData*) index.internalPointer(); if (!pData->isFacet()) { return TagTypeItem; } else return FacetTypeItem; } case TagRole: { const ItemData* pData = (ItemData*) index.internalPointer(); assert(pData->toTagData()); Tag tag = pData->toTagData()->tag(); // dummy to pull in default constructor symbol // TagWrapper tw(); return QVariant::fromValue(TagWrapper(tag)); // return QVariant(); } } return QVariant(); } QVariant VocabularyModel::headerData( int section, Qt::Orientation, int role) const { if (role == Qt::DisplayRole) { if (section == 0) return "Name"; if (section == 1) return "ID"; } return QVariant(); } QModelIndex VocabularyModel::parent(const QModelIndex & index) const { if (!index.isValid()) return QModelIndex(); const ItemData* pData = (ItemData*) index.internalPointer(); assert(pData != 0); if (pData->isFacet()) { // qDebug("[parent()] Parent is facet: " + pData->fullname()); return QModelIndex(); // no parent for facets } else { const TagData* pTagData = static_cast(pData); FacetData* facetData = _facets.at(pTagData->facetIndex); // qDebug("[parent()] Getting parent for tag " + pTagData->fullname() + " with facet " + // facetData.fullname() + " at row %d", facetData.row); return createIndex(facetData->row, 0, const_cast(dynamic_cast(_facets[pTagData->facetIndex])) ); } } QModelIndex VocabularyModel::index (int row, int column, const QModelIndex & parent) const { // qDebug("[VocabularyModel::index()] requesting index row %i, col %i", row, column); // requesting index for a facet if (row < 0 || column < 0) return QModelIndex(); if (!parent.isValid()) { if (row >= (int) _facets.size() || column >= 2) { qWarning("[VocabularyModel::index()] Warning: row or column to large, row: %d, column, %d", row, column); return QModelIndex(); } const FacetData* pFd = _facets[row]; return createIndex(row, column, const_cast(dynamic_cast(pFd))); } const ItemData* pData = (ItemData*) parent.internalPointer(); if (!pData->isFacet()) return QModelIndex(); assert(dynamic_cast(pData) != 0); FacetData* pFacetData = (FacetData*) pData; const string facet = pFacetData->facet(); const vector& tagDataOfFacet = _tags.find(facet)->second; if (row >= (int) tagDataOfFacet.size() || column >= 2) { qDebug("[VocabularyModel::index()] Warning: row or column to large, row: %d, column, %d", row, column); qStrDebug("[VocabularyModel::index()] Facet: " + pFacetData->fullname()); return QModelIndex(); } const TagData* pTd = tagDataOfFacet[row]; return createIndex( row, column, (void*) pTd); } bool VocabularyModel::setData(const QModelIndex& index, const QVariant& value, int role) { switch(role) { case SelectedRole: { ItemData* pData = (ItemData*) index.internalPointer(); TagData* pTagData = pData->toTagData(); // setting selected for facets is not allowed/ignored if (!pTagData) return false; pTagData->selected = value.toBool(); qDebug("[VocabularyModel::setData()] size before insert/remove: %lu", _selectedTags.size()); // if the tag is selected if (value.toBool()) _selectedTags.insert(pTagData->tag()); else // the tag is unselected _selectedTags.erase(pTagData->tag()); qDebug("[VocabularyModel::setData()] size after insert/remove: %lu", _selectedTags.size()); //_companionTagsValid = false; // reset(); // emitAllDataChanged(); emit(selectionChanged()); emit(dataChanged(index, index)); return true; } case HiddenRole: { ItemData* pData = (ItemData*) index.internalPointer(); if (pData->isFacet()) { pData->toFacetData()->hidden = value.toBool(); emit(dataChanged(index, index)); return true; } else { qWarning("[VocabularyModel::setData()] trying to set hidden for a tag which is not supported"); } } default: return QAbstractItemModel::setData(index, value, role); } return false; } void VocabularyModel::setAllUnselected() { beginResetModel(); QModelIndex parent = QModelIndex(); for(int i = 0; i < rowCount(parent); ++i) { QModelIndex newParent = index(i, 0, parent); setAllUnselected(newParent); } //_companionTagsValid = false; endResetModel();} void VocabularyModel::setAllUnselected(QModelIndex index) { for(int i = 0; i < rowCount(index); ++i) { QModelIndex newParent = this->index(i, 0, index); setAllUnselected(newParent); } ItemData* pData = (ItemData*) index.internalPointer(); TagData* pTagData = pData->toTagData(); // if this is a tag if (pTagData) { pTagData->selected = false; _selectedTags.erase(pTagData->tag()); } //_companionTagsValid = false; } void VocabularyModel::emitAllDataChanged() { QModelIndex root = QModelIndex(); for(int i = 0; i < rowCount(root); ++i) { QModelIndex parent = index(i, 0, root); QModelIndex tl = index(0, 0, parent); QModelIndex br = index(rowCount(parent)-1, columnCount(parent)-1, parent); qStrDebug("Top Left Item: " + data(tl, Qt::DisplayRole).toString()); qStrDebug("Bottom Right Item: " + data(br, Qt::DisplayRole).toString()); emit(dataChanged(tl, br)); } QModelIndex parent = index(0, 0, root); QModelIndex br = index(rowCount(root)-1, columnCount(parent)-1, root); emit(dataChanged(parent, br)); } QModelIndex VocabularyModel::indexForTag(const Tag& tag, int column) const { map >::const_iterator it = _tagToTagData.find(tag); if (it == _tagToTagData.end()) return QModelIndex(); pair indexes = it->second; int facetIndex = indexes.first; const string facet = _facets[facetIndex]->facet(); int tagIndex = indexes.second; const TagData* pTd = _tags.find(facet)->second[tagIndex]; return createIndex( tagIndex, column, (void*) pTd); } Facet VocabularyModel::getFacet(int index) const { return getElement(_pContainer->facets(), index); } const set& VocabularyModel::selectedTags() const { return _selectedTags; } set VocabularyModel::hiddenFacets() const { set result; // iterate over all facets and collect the hidden ones QModelIndex parent = QModelIndex(); for(int i = 0; i < rowCount(parent); ++i) { QModelIndex index = this->index(i, 0, parent); NTagModel::FacetData* pFacet = (NTagModel::FacetData*) index.internalPointer(); if (pFacet->hidden) result.insert(pFacet->facet()); } return result; } set VocabularyModel::shownFacets() const { set result; // iterate over all facets and collect the shown ones QModelIndex parent = QModelIndex(); for(int i = 0; i < rowCount(parent); ++i) { QModelIndex index = this->index(i, 0, parent); NTagModel::FacetData* pFacet = (NTagModel::FacetData*) index.internalPointer(); if (!pFacet->hidden) result.insert(pFacet->facet()); } return result; } std::set VocabularyModel::collectSelectedChildItems(const QModelIndex& parent) const { std::set result; for(int i = 0; i < rowCount(parent); ++i) { QModelIndex index = this->index(i, 0, parent); // if the item is selected if (data(index, NTagModel::SelectedRole).toBool()) { NTagModel::TagData* pTagData = (NTagModel::TagData*) index.internalPointer(); result.insert(pTagData->tag()); } result |= collectSelectedChildItems(index); } return result; } } // NTagModel #undef emit //#include //#include packagesearch-2.7.11build1/src/plugins/debtagsplugin/vocabularymodel.h0000644000000000000000000001771713507430555023037 0ustar // // C++ Interface: vocabularymodel // // Description: // // // Author: Benjamin Mesing , (C) 2006 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTAGMODEL_VOCABULARYMODEL_H_2006_10_01 #define __NTAGMODEL_VOCABULARYMODEL_H_2006_10_01 #include #include #include #include #include namespace NTagModel { using namespace std; struct FacetData; struct TagData; /** @brief Base class for TagData and ItemData. * * Use by Vocabulary model to return the data. */ struct ItemData { virtual ~ItemData() {}; /** @brief Returns if the item is a facet. */ virtual bool isFacet() const = 0; /** @brief Returns the name of the item in user presentable form (i.e. "Text" instead of * "works-with-format:text"). */ virtual QString name() const = 0; /** @brief Returns the full user presentable text for the item (i.e. "Format: Text" instead of * "works-with-format::text"). */ virtual QString fullDisplayText() const = 0; /** @brief Returns the full technical name (e.g. "works-with-format" for a facet and * "works-with-format::text" for a tag). */ virtual QString fullname() const = 0; /** Returns the description of the item. */ virtual QString description() const = 0; virtual const FacetData* toFacetData() const = 0; virtual const TagData* toTagData() const = 0; virtual FacetData* toFacetData() = 0; virtual TagData* toTagData() = 0; }; class FacetData : public ItemData { typedef ept::debtags::voc::FacetData EptFacetData; const EptFacetData* _pEptFacetData; public: bool hidden; int row; FacetData(const EptFacetData* facet_, int row_) : _pEptFacetData(facet_), hidden(false), row(row_) { } const EptFacetData* eptFacetData() const { return _pEptFacetData; } string facet() const { return _pEptFacetData->name; } virtual bool isFacet() const { return true; } virtual QString name() const { return toQString(_pEptFacetData->shortDescription()); } virtual QString fullname() const { return toQString(_pEptFacetData->name); } virtual QString fullDisplayText() const { return name(); }; virtual QString description() const { return toQString(_pEptFacetData->shortDescription()); } virtual const FacetData* toFacetData() const { return this; }; virtual const TagData* toTagData() const { return 0; }; virtual FacetData* toFacetData() { return this; }; virtual TagData* toTagData() { return 0; }; }; struct TagData : public ItemData { typedef ept::debtags::voc::TagData EptTagData; const EptTagData* _eptTagData; public: int facetIndex; /** @brief Stores if the tag was selected to be searched for. * * This has nothing to do with user selection like it is happening * through the views. */ bool selected; TagData(const EptTagData* tag_, int facetIndex_) : _eptTagData(tag_), facetIndex(facetIndex_), selected(false) { } virtual bool isFacet() const { return false; } const string& tag() const { return _eptTagData->name; } virtual QString name() const { return toQString(_eptTagData->shortDescription()); } virtual QString fullname() const { return toQString(_eptTagData->name); } virtual QString fullDisplayText() const { QString tmp = toQString(ept::debtags::voc::getfacet(_eptTagData->name)); // FIXME: needs to access vocabulary for this: toQString(tag.facet().shortDescription()); tmp += QString(": "); tmp += name(); return tmp; }; virtual QString description() const { return toQString(_eptTagData->longDescription()); } virtual const FacetData* toFacetData() const { return 0; }; virtual const TagData* toTagData() const { return this; }; virtual FacetData* toFacetData() { return 0; }; virtual TagData* toTagData() { return this; }; }; /** * @author Benjamin Mesing */ class VocabularyModel : public QAbstractItemModel { Q_OBJECT typedef string Tag; typedef string Facet; /** @brief The object used to access the tag collection. * * If this is 0, the tag selection will not be accessible, and no companion tags * will be determined (i.e. if you select a tag, the selection will not be limited * according to this tag.) */ const NPlugin::DebtagsPluginContainer* _pContainer; vector _facets; /** Maps the facet to the list of tags belonging to it. */ map > _tags; /** Maps the tag to the pair (facetIndex, tagIndex) identifying the tag. */ map > _tagToTagData; /** Maps the facet names to the index identifying the facet. */ map _facetToFacetData; public: VocabularyModel() {}; VocabularyModel(const NPlugin::DebtagsPluginContainer* pContainer); ~VocabularyModel(); /** @brief Sets the hidden state of the facet with the given name. */ void setFacetHidden(bool hidden, string facet); /** @name AbstractItemModel interface * * Implementation of the AbstractItemModel interface */ //@{ virtual int rowCount(const QModelIndex & parent = QModelIndex() ) const; virtual int columnCount(const QModelIndex & = QModelIndex() ) const { return 2; }; virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QModelIndex parent(const QModelIndex & index ) const; virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex() ) const; //@} /** @brief Returns an index for the handed tag. * * @param tag the tag to get the index for * @param column the column for the row with the given tag * @returns an invalid index if no such tag/facet exists */ virtual QModelIndex indexForTag(const Tag& tag, int column) const; /** @brief Allows to set the data for the VocabularyModeRole::Selected and the * VocabularyModeRole::Hidden role. * * Setting data for any other role is passed up to QTreeView::setData(). * * @returns true if the data was set successfully, else false * @pre index.isValid() */ virtual bool setData(const QModelIndex& index, const QVariant& value, int role); /** @brief Sets VocabularyModeRole::Selected to false for all tags. */ virtual void setAllUnselected(); /** Gets the index'th facet in the current model. * * Precondition: 0 <= i < facetNum */ Facet getFacet(int index) const; /** @brief Returns the facets that are hidden. */ set hiddenFacets() const; /** @brief Returns the facets that are hidden. */ set shownFacets() const; /** Returns the tags selected for this model. */ const set& selectedTags() const; /** Gets the index'th object in the given set. * * Precondition: 0 <= i < collection.size() */ template const T& getElement(std::set collection, int index) const { typedef set set_type; int i = 0; typename set_type::const_iterator it = collection.begin(); while (i != index) { ++i; ++it; } return *it; } signals: void selectionChanged(); protected: /** @brief Helper method that sets all items beneath index and index itself as unselected. * * It will not emit any dataChanged signals. */ void setAllUnselected(QModelIndex index); /** Collects the tags from the model that are selected. * * @pre parent != QModelIndex() ( which means that the children of parent * must point be tags (i.e. no facets) */ std::set collectSelectedChildItems(const QModelIndex& parent) const; //private: public: /** Keeps track of the tags which are selected. */ std::set _selectedTags; // TODO: access for companion tags to be implemented (including caching) //mutable bool _companionTagsValid; // TODO: access for companion tags to be implemented (including caching) //mutable std::set _companionTagsChache; void emitAllDataChanged(); }; } struct TagWrapper { typedef std::string Tag; public: Tag tag; TagWrapper(); TagWrapper(Tag tag_); }; Q_DECLARE_METATYPE(TagWrapper) #endif // __NTAGMODEL_VOCABULARYMODEL_H_2006_10_01 packagesearch-2.7.11build1/src/plugins/debtagsplugin/vocabularymodelrole.h0000644000000000000000000000130113507430555023677 0ustar // // C++ Interface: vocabularymodelrole // // Description: // // // Author: Benjamin Mesing , (C) 2007 // // Copyright: See COPYING file that comes with this distribution // // namespace NTagModel { enum VocabularyModelRole { SelectedRole = Qt::UserRole, HiddenRole, /// role that decides wether the item is a facet or a tag TypeRole, // @pre TypeRole must be TagTypeItem // -> data() returns that Tag instance TagRole, /** Display role to be used, when tag names should be displayed along with the facet name. * * This is usually the case, when the tags are diplayed without a context. */ FullDisplayRole }; enum ItemType { FacetTypeItem, TagTypeItem }; } packagesearch-2.7.11build1/src/plugins/debtagsplugin-test/0000755000000000000000000000000013507430555020436 5ustar packagesearch-2.7.11build1/src/plugins/debtagsplugin-test/debtagshelper-test.cpp0000644000000000000000000000561413507430555024736 0ustar #ifdef __UNIT_TEST_PP #include #include #include #include #include #include //#include //#include #include using namespace std; /** @brief Checks if all tags ANDed together give a non-empty result set for * ANDed together with each companion. * * @param tags may be empty * @param companions may be empty */ void checkAllGiveNonEmpty(const set& tags, const set& companions, const Xapian::Database& xapian) { for (set::const_iterator it = companions.begin(); it != companions.end(); ++it) { set terms; for (set::const_iterator jt = tags.begin(); jt != tags.end(); ++jt) { terms.insert(string("XT")+(*jt)); } terms.insert(string("XT")+(*it)); Xapian::Query query(Xapian::Query::OP_AND, terms.begin(), terms.end()); Xapian::Enquire enq(xapian); enq.set_query(query); Xapian::MSet match = enq.get_mset(0, 1); CHECK(match.size() != 0); } } TEST(NUtil__companionTags) { using namespace NUtil; Xapian::Database xapian("/var/lib/apt-xapian-index/index"); set tags; set result = companionTags(tags, xapian); checkAllGiveNonEmpty(tags, result, xapian); // the number of tags which produce a result should be quite large CHECK(result.size() >= 70); // the tag implemented-in::c++ should definitely be in there CHECK(result.find("implemented-in::c++") != result.end()); tags.insert("implemented-in::c++"); result = companionTags(tags, xapian); checkAllGiveNonEmpty(tags, result, xapian); // there should be quite some tags in the companion set of implemented-in::c++ CHECK(result.size() >= 10); // the tag implemented-in::c++ itself should not be in there CHECK(result.find("implemented-in::c++") == result.end()); // the tag admin::package-management should not be in CHECK(result.find("admin::package-management") != result.end()); tags.insert("devel::compiler"); result = companionTags(tags, xapian); checkAllGiveNonEmpty(tags, result, xapian); CHECK(result.size() > 0); } /// testing code for NUtil::tagsForPackage() TEST(NUtil__tagsForPackage) { using namespace NUtil; Xapian::Database xapian("/var/lib/apt-xapian-index/index"); set result; result = tagsForPackage("", xapian); // empty package name CHECK(result.empty()); // invalid package name result = tagsForPackage("ewkhjgrkleghe", xapian); CHECK(result.empty()); // valid package name result = tagsForPackage("packagesearch", xapian); CHECK(result.size()>4); string searching = "use::searching"; bool foundSearching = false; string qt = "uitoolkit::qt"; bool foundQt = false; for (set::const_iterator it = result.begin(); it != result.end(); ++it) { if (*it == searching) foundSearching = true; if (*it == qt) foundQt = true; } CHECK(foundSearching); CHECK(foundQt); } #endif packagesearch-2.7.11build1/src/plugins/debtagsplugin-test/debtagsplugin-test.pro0000644000000000000000000000115513507430555024767 0ustar TEMPLATE = app CONFIG += warn_on \ qt \ thread \ stl \ link_pkgconfig QT += xml TARGET = run-tests SOURCES += debtagshelper-test.cpp \ main-test.cpp INCLUDEPATH = . \ ../../ \ ../debtagsplugin \ ../debtagsplugin/.ui \ ../debtagsplugin/.moc debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } # use unit test ++ DEFINES += __UNIT_TEST_PP PKGCONFIG += unittest++ libept LIBS += -L../../ -L../ -lpackagesearch -ldebtagsplugin QMAKE_CXXFLAGS += -std=c++11 packagesearch-2.7.11build1/src/plugins/debtagsplugin-test/main-test.cpp0000644000000000000000000000014713507430555023045 0ustar #ifdef __UNIT_TEST_PP #include int main() { return UnitTest::RunAllTests(); } #endifpackagesearch-2.7.11build1/src/plugins/debtagsplugin-test/run-tests.sh0000755000000000000000000000011013507430555022731 0ustar #!/bin/bash export LD_LIBRARY_PATH=$LD_LIBRARAY_PATH:../../ ./run-tests packagesearch-2.7.11build1/src/plugins/filenameplugin/0000755000000000000000000000000013507430555017630 5ustar packagesearch-2.7.11build1/src/plugins/filenameplugin/.moc/0000755000000000000000000000000013507430555020464 5ustar packagesearch-2.7.11build1/src/plugins/filenameplugin/.obj/0000755000000000000000000000000013507430555020460 5ustar packagesearch-2.7.11build1/src/plugins/filenameplugin/.ui/0000755000000000000000000000000013507430555020323 5ustar packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameactionplugin.cpp0000644000000000000000000000253213507430555024533 0ustar // // C++ Implementation: filenameactionplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "filenameactionplugin.h" #include namespace NPlugin { const QString FilenameActionPlugin::PLUGIN_NAME = "FilenameActionPlugin"; FilenameActionPlugin::FilenameActionPlugin() : _title("Filename-Action Plugin"), _briefDescription("Offers the menu and toolbar entries"), _description("This plugin offers the menu and toolbar entries for the Filename plugin. " "Currently this is only the debtags update entry.") { QAction* pQAptFileUpdateAction = new QAction(QObject::tr("Update File Database"), this); pQAptFileUpdateAction->setStatusTip(tr("Calls \"apt-file update\" updating the file database")); _pAptFileUpdateAction = new Action(pQAptFileUpdateAction, false, "System"); QAction* pQSeparatorAction = new QAction(this); pQSeparatorAction->setSeparator(true); _pSeparatorAction = new Action(pQSeparatorAction, false, "System"); } FilenameActionPlugin::~FilenameActionPlugin() { delete _pAptFileUpdateAction; delete _pSeparatorAction; } vector FilenameActionPlugin::actions() const { vector actions; actions.push_back(_pSeparatorAction); actions.push_back(_pAptFileUpdateAction); return actions; } } packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameactionplugin.h0000644000000000000000000000335713507430555024206 0ustar // // C++ Interface: filenameactionplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_FILENAMEACTIONPLUGIN_H_2005_09_01 #define __NPLUGIN_FILENAMEACTIONPLUGIN_H_2005_09_01 #include #include namespace NPlugin { /** @brief Offers the actions related to the filename plugin Currently the only action offered is used to perform apt-file update. * @author Benjamin Mesing */ class FilenameActionPlugin : public QObject, public ActionPlugin { const QString _title; const QString _briefDescription; const QString _description; /** @brief Action used to update the debtags database. */ Action* _pAptFileUpdateAction; Action* _pSeparatorAction; public: static const QString PLUGIN_NAME; FilenameActionPlugin(); ~FilenameActionPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider*) {}; /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @brief Returns the QAction object for the #_pAptFileUpdateAction. */ QAction* qAptFileUpdateAction() const { return _pAptFileUpdateAction->action(); } /** @name ActionPlugin Interface * * Implementation of the ActionPlugin Interface. */ //@{ virtual vector actions() const; //@} }; } #endif // __NPLUGIN_FILENAMEACTIONPLUGIN_H_2005_09_01 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamefeedbackwidget.cpp0000644000000000000000000000122113507430555024761 0ustar // // C++ Implementation: filenamefeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "filenamefeedbackwidget.h" FilenameFeedbackWidget::FilenameFeedbackWidget(QWidget *parent, const char *name) : QWidget(parent), Ui::FilenameFeedbackWidget() { setObjectName(name); setupUi(this); } FilenameFeedbackWidget::~FilenameFeedbackWidget() { } void FilenameFeedbackWidget::setClearButton(QPushButton* pButton, int index) { delete(_pClearButton); _pClearButton = pButton; _pInputLayout->insertWidget(index,_pClearButton); } packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamefeedbackwidget.h0000644000000000000000000000154013507430555024432 0ustar // // C++ Interface: filenamefeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __FILENAMEFEEDBACKWIDGET_H_2005_07_26 #define __FILENAMEFEEDBACKWIDGET_H_2005_07_26 #include #include /** @author Benjamin Mesing */ class FilenameFeedbackWidget : public QWidget, public Ui::FilenameFeedbackWidget { Q_OBJECT public: FilenameFeedbackWidget(QWidget *parent = 0, const char *name = 0); ~FilenameFeedbackWidget(); /** Sets the push button used in this dialog. * * @param index the position where the button is placed (0 is before the filename display, * 1 is behind it). */ void setClearButton(QPushButton* pButton, int index); }; #endif // __FILENAMEFEEDBACKWIDGET_H_2005_07_26 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamefeedbackwidget.ui0000644000000000000000000000274713507430555024632 0ustar FilenameFeedbackWidget 0 0 306 55 Form 2 0 Search for filename 2 0 Clear Shows the filename that was searched for true packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugin.cpp0000644000000000000000000002717313507430555023345 0ustar #include #include #include #include #include #include #include #include #include #include #include // NUtil #include #include #include "filenameplugin.h" #include "filenameview.h" #include "filenamesearchinput.h" #include "filenamefeedbackwidget.h" // NApplication #include using namespace std; namespace NPlugin { const QString FilenamePlugin::PLUGIN_NAME = "FilenamePlugin"; FilenamePlugin::FilenamePlugin() { _pProcess = 0; _pFilenameFeedbackWidget = 0; _pFileView = 0; _pProvider = 0; _pInputWidget = 0; _pDelayTimer = new QTimer(this); _pDelayTimer->setSingleShot(true); _delayTime=2000; connect(_pDelayTimer, SIGNAL(timeout()), SLOT(evaluateSearch())); } FilenamePlugin::~FilenamePlugin() { delete _pFileView; delete _pInputWidget; delete _pFilenameFeedbackWidget; delete _pDelayTimer; delete _pProcess; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// QString FilenamePlugin::title() const { return tr("Filename Plugin"); } QString FilenamePlugin::briefDescription() const { return tr("Plugin to search by files and diplay files in packages."); } QString FilenamePlugin::description() const { return tr("This plugin allows to search the packages for files, and to display the files included " "in the packages\n" "For information about not installed packages, it needs the apt-file tool."); } void FilenamePlugin::init(IProvider* pProvider) { _pProvider = pProvider; QMainWindow* pWindow = pProvider->mainWindow(); _pFileView = new FilenameView(pWindow, "FileView", pProvider); _pInputWidget = new FilenameSearchInput(pWindow); _pFilenameFeedbackWidget = new FilenameFeedbackWidget(pWindow, "filenameFeedbackWidget"); // replace the clear button QPushButton* pClearButton = pProvider->createClearButton(_pFilenameFeedbackWidget, "ClearButton"); _pFilenameFeedbackWidget->setClearButton(pClearButton, 0); connect(pClearButton, SIGNAL(clicked()), SLOT(onClearSearch())); connect( _pInputWidget->_pFilenamePatternInput, SIGNAL(textChanged(const QString&)), SLOT(onInputTextChanged(const QString&)) ); connect( _pInputWidget->_pFilenamePatternInput, SIGNAL(returnPressed()), SLOT(evaluateSearch()) ); connect( _pInputWidget->_pSearchInstalledOnlyCheck, SIGNAL(toggled(bool)), SLOT(evaluateSearch()) ); connect(_pFileView, SIGNAL(showRequested()), SLOT(onShowRequested())); } ///////////////////////////////////////////////////// // Information Plugin Interface ///////////////////////////////////////////////////// QWidget* FilenamePlugin::informationWidget() const { return _pFileView; } QString FilenamePlugin::informationWidgetTitle() const { return tr("Files"); } void FilenamePlugin::updateInformationWidget(const string& package) { if ( _currentPackage == toQString(package) ) return; _currentPackage = toQString(package); _pFileView->clear(); // prevent showing of information if we have only slow access to the file list (i.e. // apt-file if (isInstalled(package)) { onShowRequested(); _pFileView->setShowButtonEnabled(false); } else { if (aptFileAvailable()) { _pFileView->setErrorMessage ( tr("For packages not installed, the file list is not shown " "by default. This is because retreiving the file list will take some time.
" "Please click the "Show" button to show the filelist for the " "selected package.
") ); _pFileView->setShowButtonEnabled(true); } else { _pFileView->setErrorMessage( aptFileMissingErrorMsg(toQString(package)) ); _pFileView->setShowButtonEnabled(false); } } } void FilenamePlugin::clearInformationWidget() { _pFileView->clear(); } QString FilenamePlugin::informationText(const string&) { return _emptyString; } ///////////////////////////////////////////////////// // Search Plugin Interface ///////////////////////////////////////////////////// QWidget* FilenamePlugin::shortInputAndFeedbackWidget() const { return _pFilenameFeedbackWidget; } QWidget* FilenamePlugin::inputWidget() const { return _pInputWidget; } QString FilenamePlugin::inputWidgetTitle() const { return tr("Filenames"); }; void FilenamePlugin::clearSearch() { _pInputWidget->_pFilenamePatternInput->clear(); _pDelayTimer->stop(); evaluateSearch(); } bool FilenamePlugin::isInactive() const { return _pInputWidget->_pFilenamePatternInput->text().isEmpty(); } ///////////////////////////////////////////////////// // Information Helper Methods ///////////////////////////////////////////////////// QFileInfo FilenamePlugin::getFileListFileName(const string& packageName) { QFileInfo packageList("/var/lib/dpkg/info/" + toQString(packageName) + ".list"); if (packageList.isReadable()) return packageList; QDir pkgInfoDir("/var/lib/dpkg/info/"); QStringList filter; filter.append(toQString(packageName) + "*.list"); pkgInfoDir.setNameFilters(filter); QFileInfoList entries = pkgInfoDir.entryInfoList(); if (entries.isEmpty()) return QFileInfo(); return entries.first(); } bool FilenamePlugin::isInstalled(const string& packageName) { return getFileListFileName(packageName).isReadable(); // if the package is installed } QStringList FilenamePlugin::filesForPackage(const string& packageName) throw (NoInformationException) { QStringList files; // the files in the given package if (isInstalled(packageName)) // if the package is installed { QFileInfo fileInfo = getFileListFileName(packageName); string filename = toString(fileInfo.absoluteFilePath()); ifstream file(filename.c_str()); while (file) { string currentLine; file >> currentLine; if ( !currentLine.empty() ) files.push_back(toQString(currentLine)); } file.close(); } else { if (aptFileAvailable()) { if (!_processMutex.tryLock()) { qDebug("The mutex was locked\n"); return QStringList(); } _pProvider->reportBusy(this, tr("Querying database for file list")); _pProvider->setEnabled(false); _pProcess = new NApplication::RunCommandForOutput("apt-file"); connect(_pProcess, SIGNAL(processExited(RunCommandForOutput*)), SLOT(onFilelistProcessExited())); QStringList arguments; _pProcess->addArgument("list"); _pProcess->addArgument("--fixed-string"); _pProcess->addArgument(toQString(packageName)); _pProcess->start(); } else { throw NoInformationException( aptFileMissingErrorMsg(toQString(packageName)) ); } } return files; // return the list of files, or an empty list if a process was launched } bool FilenamePlugin::fixEntry(QString& entry, const QString& packageName) { if (!entry.startsWith(packageName+":")) return false; entry.remove(packageName+": "); return true; } void FilenamePlugin::onFilelistProcessExited() { qDebug("onFilelistProcessExited()"); QStringList output = _pProcess->getOutput(); for (QStringList::const_iterator it = output.begin(); it != output.end(); ++it) { QString line = *it; line.chop(1); // remove trailing \n if (fixEntry(line, _currentPackage)) _pFileView->addEntry(line); } if (!_pFileView->hasEntry()) { qDebug("No file information available"); _pFileView->setErrorMessage(tr("There is no file information for the current package available.")); } _pProvider->reportReady(this); _pProcess->deleteLater(); _pProcess = 0; _processMutex.unlock(); _pProvider->setEnabled(true); } void FilenamePlugin::onShowRequested() { _pFileView->clear(); try { QStringList files = filesForPackage(toString(_currentPackage)); NExtStd::for_each(files.begin(), files.end(), &FilenameView::addEntry, _pFileView); } catch (NoInformationException e) { _pFileView->setErrorMessage(e._errorMessage); } } ///////////////////////////////////////////////////// // Search Helper Methods ///////////////////////////////////////////////////// void FilenamePlugin::onInputTextChanged(const QString&) { _pProvider->mainWindow()->statusBar()->showMessage( tr("delayed evaluation - waiting for further input"), _delayTime ); _pDelayTimer->start(_delayTime); } void FilenamePlugin::evaluateSearch() { // stop the delay timer in case that this evaluateSearch() was triggered by // another event _pDelayTimer->stop(); // reportReady will be called on applications exit _searchResult.clear(); QString searchFilename = _pInputWidget->_pFilenamePatternInput->text(); if ( !searchFilename.isEmpty() ) // if the search is not empty { if (!aptFileAvailable() && !_pInputWidget->_pSearchInstalledOnlyCheck->isChecked()) { _pProvider->reportError( tr("Apt file search not availabe"), tr("You need the apt-file utility to search files " "in packages not installed.
" "To get apt-file fetch it via apt-get install apt-file and run " "apt-file update afterwards.") ); return; } if (!_processMutex.tryLock()) { qDebug("The mutex was locked\n"); return; } assert(_pProcess==0); _pProvider->reportBusy(this, tr("Performing search for filenames, this might take a while")); _pProvider->setEnabled(false); if (_pInputWidget->_pSearchInstalledOnlyCheck->isChecked()) { _pProcess = new NApplication::RunCommandForOutput("dpkg"); connect(_pProcess, SIGNAL(processExited(RunCommandForOutput*)), SLOT(onSearchProcessExited())); _pProcess->addArgument("-S"); _pProcess->addArgument("*"+searchFilename+"*"); _pProcess->start(); } else { _pProcess = new NApplication::RunCommandForOutput("apt-file"); connect(_pProcess, SIGNAL(processExited(RunCommandForOutput*)), SLOT(onSearchProcessExited())); _pProcess->addArgument("search"); _pProcess->addArgument("-l"); // list only package names _pProcess->addArgument(searchFilename); _pProcess->start(); } } else { // do not show the feedback widget if the search is empty _pFilenameFeedbackWidget->setVisible(false); emit searchChanged(this); } } void FilenamePlugin::onSearchProcessExited() { QStringList output = _pProcess->getOutput(); for (QStringList::const_iterator it = output.begin(); it != output.end(); ++it) { QString line = *it; line.chop(1); // remove trailing \n if (_pInputWidget->_pSearchInstalledOnlyCheck->isChecked()) { /// @todo intercept not found message here - not neccessary? /// @todo fix diversion bin entries line = line.left(line.indexOf(':')); // the packages are listed before the colon QStringList packages = line.split(", "); for(QStringList::iterator it = packages.begin(); it != packages.end(); ++it) _searchResult.insert( toString(*it) ); } // if it was an apt-file search else { _searchResult.insert( toString(line) ); } } _pProvider->reportReady(this); emit searchChanged(this); _pFilenameFeedbackWidget->setVisible(true); _pFilenameFeedbackWidget->_pFilenameDisplay->setText(_pInputWidget->_pFilenamePatternInput->text()); _pProcess->deleteLater(); _pProcess = 0; _processMutex.unlock(); _pProvider->setEnabled(true); } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// bool FilenamePlugin::aptFileAvailable() { QFileInfo aptFile("/usr/bin/apt-file"); return aptFile.isExecutable(); } QString FilenamePlugin::aptFileMissingErrorMsg(QString packageName) { return tr("

File list for ") + packageName + tr(" not available.

" "

For displaying the file list for not-installed packages, the \"apt-file\" " "package is required. Please install \"apt-file\" and " "retrieve the latest file database by running apt-file update.

"); } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugin.h0000644000000000000000000001450313507430555023003 0ustar #ifndef __FILENAMEPLUGIN_H_2004_06_21 #define __FILENAMEPLUGIN_H_2004_06_21 #include #include #include #include #include #include #include #include class FilenameView; class FilenameSearchInput; class FilenameFeedbackWidget; class QWidget; class QTimer; namespace NApplication { class RunCommandForOutput; } using namespace std; namespace NPlugin { // Class FilenamePlugin // // class FilenamePlugin : public SearchPlugin, public InformationPlugin { Q_OBJECT public: static const QString PLUGIN_NAME; FilenamePlugin(); virtual ~FilenamePlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual uint priority() const { return 7; }; virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } /** @returns "FilenamePlugin" */ virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; //@} /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 7; } /** @returns a widget which shows a description of this package. */ virtual QWidget* informationWidget() const; /** @returns "Description" */ virtual QString informationWidgetTitle() const; virtual void updateInformationWidget(const string& package); virtual void clearInformationWidget(); /** This plugin offers an information text. */ virtual bool offersInformationText() const { return false; }; virtual QString informationText(const string& package); //@} /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ virtual uint searchPriority() const { return 7; }; virtual QWidget* inputWidget() const; virtual QString inputWidgetTitle() const; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return false; }; virtual const std::set& searchResult() const { return _searchResult; }; virtual bool filterPackage(const string&) const { return true; }; virtual bool isInactive() const; //@} protected: /** This exception is thrown to indicate that no information about the * package could have be retrieved. */ class NoInformationException { public: /** This holds a message about what wen wrong. */ QString _errorMessage; NoInformationException(const QString& errorMessage) { _errorMessage = errorMessage; }; }; /** @brief This returns the files which belong to the given package. * * It might return an empty list, if the information can not * be retrieved immidiately.\n * @throws NoInformationException if no inforamtion about the package * can be retrieved. */ QStringList filesForPackage(const string& packageName) throw (NoInformationException); /** @brief File info for the file containing the list of installed files for the package. * * I first looks for the file in /var/lib/dpkg/info/packagename without * any arch extension, then for any file * with an arbitrary extension (returns the first match). * Returns an empty QFileInfo if the package is not installed (i.e. no list file is * available). */ QFileInfo getFileListFileName(const string& packageName); /** @brief Returns if the given package is installed. */ bool isInstalled(const string& packageName); /** This checks if the apt-file system is available. */ bool aptFileAvailable(); protected Q_SLOTS: /** @brief Slot that calls clearSearch() */ void onClearSearch() { clearSearch(); }; /** @brief Evaluates the currently entered search. */ void evaluateSearch(); private Q_SLOTS: /** This is called whenever the text of the widget where to insert the * search pattern changes. */ void onInputTextChanged(const QString&); /** Called when the search process has exited. */ void onSearchProcessExited(); /** Called when the search process has exited. */ void onFilelistProcessExited(); /** Called whenever the user clicked "show" in the view. */ void onShowRequested(); private: /** Locked if we currently evaluate a search. */ QMutex _processMutex; /** Process currently executed, make sure to get the _processMutex if you want to use it. * * 0 if no process is currently running. */ NApplication::RunCommandForOutput* _pProcess; /** @brief This checks if the given entry is for the handed package and * prepares the entry for output. * * It works on entries as returned by apt-file list packageName. * (which have the type: package: filename). * The entries which are for the given package will be changed to represent the * file location (i.e. the leading packageName: will be replaced by /). * @param entry the entry to be fixed (it will be changed by this function) * @param packageName the package to be matched against * @returns false if the entry is not for the current package (i.e. does not start with packageName:) * else true. */ bool fixEntry(QString& entry, const QString& packageName); /** Widget where the search might be enterd. */ FilenameSearchInput* _pInputWidget; /** The widget where the files will be shown in. */ FilenameView* _pFileView; /** The widget where the search selected is shown in. */ FilenameFeedbackWidget* _pFilenameFeedbackWidget; /** Holds a pointer to the pluginmanager which manages this pugin. */ IProvider* _pProvider; /** This holds the result of the currently active search. */ std::set _searchResult; /** This timer is used to delay the evaluation of the search a little to avoid unneccessary operations * e.g. on text input. */ QTimer* _pDelayTimer; /** This is the delay time in ms the delay timer waits for another input. */ uint _delayTime; /** The package where information for should be displayed. */ QString _currentPackage; /** @brief Returns an error message reporting, that apt-file is missing, and required for * retrieving file information for the given package. */ QString aptFileMissingErrorMsg(QString packageName); }; } // namespace NPlugin #endif // __FILENAMEPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugin.kdev40000644000000000000000000000007413507430555023567 0ustar [Project] Manager=KDevCustomMakeManager Name=filenameplugin packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugin.pro0000644000000000000000000000320313507430555023347 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./filenameplugin # Target is a library: HEADERS += filenameplugin.h \ filenameplugincontainer.h \ filenamepluginfactory.h \ filenameview.h \ filenamesearchinput.h \ filenamefeedbackwidget.h \ filenameactionplugin.h SOURCES += filenameplugin.cpp \ filenameplugincontainer.cpp \ filenamepluginfactory.cpp \ filenameview.cpp \ filenamesearchinput.cpp \ filenamefeedbackwidget.cpp \ filenameactionplugin.cpp TRANSLATIONS = ../../../translations/filenameplugin_de.ts \ ../../../translations/filenameplugin_es.ts INCLUDEPATH = . \ ../../ PKGCONFIG += libept # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) MOC_DIR = .moc UI_DIR = .ui OBJECTS_DIR = .obj DESTDIR = ../ CONFIG += warn_on \ qt \ thread \ plugin \ stl \ link_pkgconfig VERSION = 0.0.1 TEMPLATE = lib FORMS += filenamefeedbackwidget.ui filenamesearchinput.ui filenameview.ui QT += xml widgets debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugincontainer.cpp0000644000000000000000000000621713507430555025244 0ustar // // C++ Implementation: filenameplugincontainer // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "filenameplugincontainer.h" #include #include #include #include // NApplication #include #include // NPluign #include #include "filenameactionplugin.h" #include "filenameplugin.h" #include #include using namespace std; extern "C" { NPlugin::PluginContainer* new_filenameplugin() { return new NPlugin::FilenamePluginContainer;; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("filenameplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } namespace NPlugin { FilenamePluginContainer::FilenamePluginContainer() { addPlugin("FilenamePlugin"); addPlugin("FilenameActionPlugin"); _pCommand = 0; } FilenamePluginContainer::~FilenamePluginContainer() { unloadAllPlugins(); delete _pCommand; } ///////////////////////////////////////////////////// // Plugin Container Interface ///////////////////////////////////////////////////// bool FilenamePluginContainer::init(IProvider* pProvider) { BasePluginContainer::init(pProvider, FilenamePluginFactory::getInstance()); requestPlugin("FilenamePlugin"); _pFilenameActionPlugin = dynamic_cast(requestPlugin("FilenameActionPlugin")); connect( _pFilenameActionPlugin->qAptFileUpdateAction(), SIGNAL(triggered(bool)), SLOT(onAptFileUpdate()) ); return true; } QString FilenamePluginContainer::title() const { return QObject::tr("Filename Plugins"); } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void FilenamePluginContainer::onAptFileUpdate() { provider()->setEnabled(false); NApplication::ApplicationFactory* pFac = NApplication::ApplicationFactory::getInstance(); _pCommand = pFac->getRunCommand("AptFileUpdateProcess"); // get a suitable user interface for the update connect(_pCommand, SIGNAL(quit()), SLOT(onAptFileUpdateFinished()) ); _pCommand->addArgument("/usr/bin/apt-file"); _pCommand->addArgument("update"); try { if ( !_pCommand->startAsRoot() ) { provider()->reportError( tr("Command not executed"), tr("For an unknwon reason, the command could " "not be executed.") ); delete _pCommand; _pCommand = 0; provider()->setEnabled(true); } } catch (const NException::RuntimeException& e) { provider()->reportError(tr("Command not executed"), toQString(e.description())); delete _pCommand; _pCommand = 0; provider()->setEnabled(true); } } void FilenamePluginContainer::onAptFileUpdateFinished() { if (!_pCommand->processExitedSuccessful()) // if the command was aborted { provider()->reportWarning( tr("Update not successfully completed"), tr("The apt-file update was not completed successfully.
" "The database might be broken, rerun apt-file update to fix this.") ); } delete _pCommand; _pCommand = 0; provider()->setEnabled(true); } }; packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameplugincontainer.h0000644000000000000000000000313713507430555024707 0ustar // // C++ Interface: filenameplugincontainer // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __FILENAMEPLUGINCONTAINER_H_2004_07_17 #define __FILENAMEPLUGINCONTAINER_H_2004_07_17 #include #include #include "filenamepluginfactory.h" class QAction; namespace NApplication { class RunCommand; } namespace NPlugin { class FilenamePlugin; class FilenameActionPlugin; /** * @author Benjamin Mesing */ class FilenamePluginContainer : public QObject, public BasePluginContainer { Q_OBJECT public: FilenamePluginContainer(); virtual ~FilenamePluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ virtual bool init(IProvider* pProvider); /** This gets a plugin with the given name. * * Accepted names are: * \li "FilenamePlugin" * @see PluginContainer::requestPlugin() */ /** @returns "filenameplugin" */ virtual string name() const { return "filenameplugin"; }; virtual QString title() const; //@} protected slots: /** Launches the apt-file update command. * @pre _pCommand == 0 */ void onAptFileUpdate(); /** @brief This function will be called if the update finished. * @post _pCommand == 0 */ void onAptFileUpdateFinished(); private: /** This pointer is used to run the apt-file update command. */ NApplication::RunCommand* _pCommand; FilenameActionPlugin* _pFilenameActionPlugin; }; }; #endif // __FILENAMEPLUGINCONTAINER_H_2004_07_17 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamepluginfactory.cpp0000644000000000000000000000156613507430555024733 0ustar // // C++ Implementation: filenamepluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "filenamepluginfactory.h" #include "filenameactionplugin.h" #include "filenameplugin.h" namespace NPlugin { FilenamePluginFactory* FilenamePluginFactory::_pInstance = 0; FilenamePluginFactory::FilenamePluginFactory() { } FilenamePluginFactory::~FilenamePluginFactory() { } Plugin* FilenamePluginFactory::createPlugin(const string& name) const { if (name=="FilenamePlugin") { return new FilenamePlugin(); } if (name=="FilenameActionPlugin") { return new FilenameActionPlugin(); } else return 0; } FilenamePluginFactory* FilenamePluginFactory::getInstance() { if (_pInstance == 0) _pInstance = new FilenamePluginFactory; return _pInstance; } }; packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamepluginfactory.h0000644000000000000000000000145313507430555024373 0ustar // // C++ Interface: filenamepluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __FILENAMEPLUGINFACTORY_H_2004_09_10 #define __FILENAMEPLUGINFACTORY_H_2004_09_10 #include namespace NPlugin { /** * @author Benjamin Mesing */ class FilenamePluginFactory : public IPluginFactory { private: FilenamePluginFactory(); static FilenamePluginFactory* _pInstance; public: ~FilenamePluginFactory(); /** @name IPluginFactory interface */ //@{ virtual Plugin* createPlugin(const string& name) const; //@} /** @brief Returns the single instance of this class. */ static FilenamePluginFactory* getInstance(); }; }; #endif // __FILENAMEPLUGINFACTORY_H_2004_09_10 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamesearchinput.cpp0000644000000000000000000000063413507430555024365 0ustar // // C++ Implementation: filenamesearchinput // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "filenamesearchinput.h" FilenameSearchInput::FilenameSearchInput(QWidget *parent) : QWidget(parent), Ui::FilenameSearchInput() { setupUi(this); } FilenameSearchInput::~FilenameSearchInput() { } packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamesearchinput.h0000644000000000000000000000102213507430555024022 0ustar // // C++ Interface: filenamesearchinput // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __FILENAMESEARCHINPUT_H_ #define __FILENAMESEARCHINPUT_H_ #include #include "ui_filenamesearchinput.h" /** @author Benjamin Mesing */ class FilenameSearchInput : public QWidget, public Ui::FilenameSearchInput { Q_OBJECT public: FilenameSearchInput(QWidget *parent = 0); ~FilenameSearchInput(); }; #endif // packagesearch-2.7.11build1/src/plugins/filenameplugin/filenamesearchinput.ui0000644000000000000000000000340313507430555024215 0ustar FilenameSearchInput 0 0 247 218 Form1 6 5 Search packages with files containing Search packages containing a file whose filename matches the pattern Check this if you want to search only the installed packages (usually much faster) search installed packages only Qt::Vertical QSizePolicy::Expanding 20 101 qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameview.cpp0000644000000000000000000001527513507430555023021 0ustar // // C++ Implementation: filenameview // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "filenameview.h" #include #include #include #include #include #include #include #include QString FilenameView::_seeCommand("/usr/bin/see"); FilenameView::FilenameView(QWidget *parent, const char *name, NPlugin::IProvider* pProvider) : QWidget(parent), Ui::FilenameView() { setObjectName(name); _filterTextEmpty = true; _pProvider = pProvider; setupUi(this); _pErrorDisplay->setVisible(false); connect(_pShowButton, SIGNAL(clicked()), SIGNAL(showRequested())); connect( &_processContainer, SIGNAL(processExited(QProcess*)), this, SLOT(onProcessExited(QProcess*)) ); } FilenameView::~FilenameView() { } void FilenameView::viewFile(QString filename) { _pProvider->statusBar()->showMessage(tr("Trying to view ") + filename, 4000); QFileInfo seeInfo(_seeCommand ); if ( !seeInfo.isExecutable() ) { _pProvider->reportError( _seeCommand + tr(" not available"), tr("The ") + _seeCommand + tr(" command is not available.\n" "Please make sure that the mime-support package is installed " "and that you have permission to execute ") + _seeCommand + tr(".") ); return; } QProcess* pProcess = new QProcess(this); QStringList arguments; arguments.push_back(filename); _seeCommands[pProcess] = make_pair(filename, false); if (!_processContainer.start(pProcess, _seeCommand , arguments)) { _pProvider->reportError ( tr("Unable to launch ") + _seeCommand , tr("Launching ") + _seeCommand + " " + filename + tr(" failed due to an unknown reason.") ); } } void FilenameView::onProcessExited(QProcess* pProcess ) { static const QString TEXT_PLAIN_PREFIX("text/plain:"); qDebug("process exited"); // if the "see" did not exit normally try again specifying mimetime text/plain pair seeInformation = _seeCommands[pProcess]; QString filename = seeInformation.first; // Holds if viewing the file using mimetype text/plain was already tried bool wasTriedAsTextPlain = seeInformation.second; if (pProcess->exitCode() != 0) { qDebug("non-normal exit"); if (wasTriedAsTextPlain) { _seeCommands.erase(pProcess); pProcess->deleteLater(); _pProvider->reportError( tr("Error viewing file"), tr("Unable to view file ") + filename + tr("\nTried ") + _seeCommand + " " + filename + tr(" and\n") + _seeCommand + " " + TEXT_PLAIN_PREFIX + filename + "" ); // qDebug("Error launching see " + pItem->text(0)); } else { _seeCommands[pProcess] = make_pair(filename, true); _pProvider->statusBar()->showMessage(tr("Retrying to view ") + filename + tr(" with mimetype text/plain"), 4000); qDebug("%s", (QString("retrying process ") + filename).toLatin1().data()); QStringList arguments; arguments.push_back(TEXT_PLAIN_PREFIX+filename); _processContainer.start(pProcess, "see", arguments); } } else { qDebug("normal exit"); _pProvider->statusBar()->showMessage(tr("Finished viewing ") + filename, 4000); _seeCommands.erase(pProcess); pProcess->deleteLater(); } } void FilenameView::on__pFilenameView_itemDoubleClicked(QListWidgetItem* pItem) { if (pItem == 0) { qDebug("Didn't hit an item"); return; } QString filename = pItem->text(); if (!isFileViewable(filename)) { _pProvider->statusBar()->showMessage(tr("Can't view file ") + filename + tr(", it is not viewable"), 5000); return; } viewFile(pItem->text()); } void FilenameView::on__pFilterInput_textChanged( const QString & pattern ) { _filterTextEmpty = pattern.isEmpty(); updateView(); } void FilenameView::on__pFilenameView_customContextMenuRequested(const QPoint& pos) { QListWidgetItem* pItem = _pFilenameView->currentItem(); // if no item was selected return immidiately if (pItem == 0) return; QMenu menu(this); QString filename = pItem->text(); QAction* pCopyToClipboard = menu.addAction(tr("Copy to clipboard")); QAction* pCopyAllToClipboard = menu.addAction(tr("Copy all filenames to clipboard")); QAction* pViewFile = menu.addAction(tr("View file (depends on settings in /etc/mailcap)")); if (!isFileViewable(filename)) pViewFile->setEnabled(false); QAction* pResult = menu.exec(_pFilenameView->mapToGlobal(pos)); if (pResult == pCopyToClipboard) { QClipboard *pCb = QApplication::clipboard(); pCb->setText(filename, QClipboard::Clipboard); pCb->setText(filename, QClipboard::Selection); } else if (pResult == pCopyAllToClipboard) { QClipboard *pCb = QApplication::clipboard(); QString itemsString = getAllVisibleItems().join("\n"); pCb->setText(itemsString, QClipboard::Clipboard); pCb->setText(itemsString, QClipboard::Selection); } else if (pResult == pViewFile) { viewFile(filename); } } void FilenameView::clear() { _errorMessage = ""; _entries.clear(); _pFilenameView->clear(); } void FilenameView::setFilterText( const QString & pattern ) { _pFilterInput->setText(pattern); } void FilenameView::addEntry( const QString & entry ) { _entries.push_back(entry); insertItem(entry); } void FilenameView::updateView() { _pFilenameView->clear(); if (_errorMessage.isEmpty()) // if no error was indicated { _pFilenameView->setVisible(true); _pErrorDisplay->setVisible(false); for ( QStringList::iterator it = _entries.begin(); it != _entries.end(); ++it) { insertItem(*it); } } else { _pErrorDisplay->setHtml(_errorMessage); _pFilenameView->setVisible(false); _pErrorDisplay->setVisible(true); } } void FilenameView::setErrorMessage( const QString & errorMessage ) { /** The error message holds the error state. If it is empty no error has occured. */ _errorMessage = errorMessage; updateView(); } void FilenameView::insertItem( const QString & entry ) { if ( _filterTextEmpty || entry.contains(_pFilterInput->text()) ) { new QListWidgetItem(entry, _pFilenameView); } _pFilenameView->setVisible(true); _pErrorDisplay->setVisible(false); } QStringList FilenameView::getAllVisibleItems() { QStringList result; if (_errorMessage.isEmpty()) { for ( int i = 0; i < _pFilenameView->count(); ++i) { QListWidgetItem* pItem = _pFilenameView->item(i); if (!_pFilenameView->isItemHidden(pItem)) result.push_back(pItem->text()); } } return result; } /** @brief Returns if the file is viewable (i.e. no directory and readable). */ bool FilenameView::isFileViewable(QString filename) { QFileInfo fileinfo(filename); return fileinfo.isReadable() && !fileinfo.isDir(); } void FilenameView::setShowButtonEnabled(bool enabled) { _pShowButton->setEnabled(enabled); } packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameview.h0000644000000000000000000001037113507430555022456 0ustar // // C++ Interface: filenameview // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __FILENAMEVIEW_H_2005_08_26 #define __FILENAMEVIEW_H_2005_08_26 //Added by qt3to4: #include #include #include class QWidget; class QMouseEvent; namespace NPlugin { class IProvider; } /** @brief This subclasses the FilenameView to allow easy extension. * * It is used to display a set of files to the user, or alternatively an error message. * Use the addEntry() function to add a new file to the list of files * and the setErrorMessage() to set an error message. If an error message is displayed, * the entries will not be shown. * * Additionally a context menu can be shown which allows the user to copy the * file path or to view the file using the see command. For see * the function viewFile(QString) is called. * * The FilenameView is capable of filtering the items according to the input in a textbox * on top of the filelist. * * @author Benjamin Mesing */ class FilenameView : public QWidget, public Ui::FilenameView { Q_OBJECT static QString _seeCommand; NApplication::ProcessContainer _processContainer; NPlugin::IProvider* _pProvider; bool _filterTextEmpty; QString _errorMessage; QStringList _entries; /** @brief This map contains all the see commands currently running. * * It maps them to the file which they should display and if an attempt was already made, * to view the file as text/plain. */ map > _seeCommands; public: FilenameView(QWidget *parent, const char *name, NPlugin::IProvider* pProvider); ~FilenameView(); /** @brief Clears the content of the widget excluding the filter. * * The file list and the error message will be cleared. */ void clear(); /** @brief Sets the search pattern for the filter. * * The view will be updated accordingly. */ void setFilterText( const QString & pattern ); /** Adds an entry to the widget. */ void addEntry( const QString & entry ); /** @brief Returns if the filelist has at least one entry. */ bool hasEntry() { return !_entries.empty(); } /** Shows the entries which shall be shown according to the filter currently active. */ void updateView(); /** @brief Call this function if you want to indicate an error. * * The error message will be shown and not affected by the filter. * The error state will cleared at next call of the clear() function. */ void setErrorMessage( const QString & errorMessage ); /** @brief This adds an item to the filename view. * * The item is displayed only if it matches the active filter. */ void insertItem( const QString & entry ); /** Returns the text of all visible items in a string list. * * Each string will contain one line, the first item in the stringlist corresponds to the first in * the listview. * * If the error state is set, an emtpy list will be returned. */ QStringList getAllVisibleItems(); /** @brief Returns if the file is viewable (i.e. no directory and readable). */ bool isFileViewable(QString filename); /** @brief Views the file using the see command. * * Reports an error to the provider if the viewing fails. */ virtual void viewFile(QString filename); /** @brief Enables or disables the "Show" button. */ void setShowButtonEnabled(bool enabled); protected Q_SLOTS: /** @brief Called whenever one of the processes (executing see) exited. * * It tries to detect if the process exited successfully and if not it * tries to relaunch see handing the mime-type text/plain as fallback. * * If the process exited successfully or a try with text/plain was already * attempted, the process will be deleted. */ virtual void onProcessExited(QProcess* pProcess); void on__pFilenameView_itemDoubleClicked(QListWidgetItem* pItem); void on__pFilenameView_customContextMenuRequested(const QPoint & pos); /** @brief Filters the view by the given pattern. * * Called whenever the text in the filterinput changed. */ void on__pFilterInput_textChanged( const QString & pattern ); signals: void showRequested(); }; #endif // __FILENAMEVIEW_H_2005_08_26 packagesearch-2.7.11build1/src/plugins/filenameplugin/filenameview.ui0000644000000000000000000000455213507430555022650 0ustar FilenameView 0 0 338 197 Form1 1 3 2 0 Filter Filter files to be shown Show the filelist for the selected package Shows a list of the files which are included in the package. If the list is already shown it will be updated.<br> For installed packages the list is shown by default because it is quite fast. For not installed package it is only shown if this button is clicked as it takes a considerable amount of time. Show 2 0 Qt::CustomContextMenu qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/orphanplugin/0000755000000000000000000000000013507430555017337 5ustar packagesearch-2.7.11build1/src/plugins/orphanplugin/.moc/0000755000000000000000000000000013507430555020173 5ustar packagesearch-2.7.11build1/src/plugins/orphanplugin/.obj/0000755000000000000000000000000013507430555020167 5ustar packagesearch-2.7.11build1/src/plugins/orphanplugin/.ui/0000755000000000000000000000000013507430555020032 5ustar packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanfeedbackwidget.ui0000644000000000000000000000255513507430555024045 0ustar OrphanFeedbackWidget 0 0 388 36 Form1 0 2 Displays the deborphan commandline This displays the command line which is used to search for orphans. true Clears the orphan search Clear qPixmapFromMimeSource packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanfeedbackwidgetimpl.cpp0000644000000000000000000000115713507430555025071 0ustar // // C++ Implementation: orphanfeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "orphanfeedbackwidgetimpl.h" OrphanFeedbackWidget::OrphanFeedbackWidget(QWidget *parent) : QWidget(parent), Ui::OrphanFeedbackWidget() { setupUi(this); } OrphanFeedbackWidget::~OrphanFeedbackWidget() { } void OrphanFeedbackWidget::setClearButton( QPushButton * pButton, int index ) { delete(_pClearButton); _pClearButton = pButton; static_cast(layout())->insertWidget(index, pButton); } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanfeedbackwidgetimpl.h0000644000000000000000000000121413507430555024530 0ustar // // C++ Interface: orphanfeedbackwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __ORPHANFEEDBACKWIDGET_H_2005_08_24 #define __ORPHANFEEDBACKWIDGET_H_2005_08_24 #include #include /** @author Benjamin Mesing */ class OrphanFeedbackWidget : public QWidget, public Ui::OrphanFeedbackWidget { Q_OBJECT public: OrphanFeedbackWidget(QWidget *parent = 0); ~OrphanFeedbackWidget(); void setClearButton( QPushButton * pButton, int index ); }; #endif // __ORPHANFEEDBACKWIDGET_H_2005_08_24 packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugin.cpp0000644000000000000000000001064213507430555022554 0ustar // // C++ Implementation: orphanplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include // NPlugin #include // NApplication #include // NXml #include #include #include "orphanplugin.h" #include "orphansearchinputimpl.h" #include "orphanfeedbackwidgetimpl.h" namespace NPlugin { const QString OrphanPlugin::PLUGIN_NAME = "OrphanPlugin"; OrphanPlugin::OrphanPlugin() { _pOrphanFeedbackWidget = 0; _pProvider = 0; _pInputWidget = 0; } OrphanPlugin::~OrphanPlugin() { delete _pInputWidget; delete _pOrphanFeedbackWidget; } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// QString OrphanPlugin::title() const { return tr("Orphan Plugin"); } QString OrphanPlugin::briefDescription() const { return tr("Plugin to search for orphaned packages."); } QString OrphanPlugin::description() const { return tr("This plugin supports to search for packages which are orphaned.\n" "It uses deborphan to implement the search."); } void OrphanPlugin::init(IProvider* pProvider) { _pProvider = pProvider; QMainWindow* pWindow = pProvider->mainWindow(); _pInputWidget = new OrphanSearchInputImpl(pWindow); connect( _pInputWidget, SIGNAL(searchChanged()), SLOT(evaluateSearch()) ); _pOrphanFeedbackWidget = new OrphanFeedbackWidget(pWindow); _pOrphanFeedbackWidget->setClearButton( pProvider->createClearButton(_pOrphanFeedbackWidget, "ClearButton"), 0); connect( _pOrphanFeedbackWidget->_pClearButton, SIGNAL(clicked()), SLOT(onClearSearch()) ); } QDomElement OrphanPlugin::loadSettings(const QDomElement source) { if (source.tagName() != name()) return source; float settingsVersion; NXml::getAttribute(source, settingsVersion, "settingsVersion", 0.0); if (settingsVersion < 0.1) { qDebug("Settings version for OrphanPlugin to old"); return NXml::getNextElement(source); } // load the real data int searchOption; NXml::getAttribute(source, searchOption, "searchOption", 1); _pInputWidget->setSearchOption(OrphanSearchInputImpl::OrphanSearchOption(searchOption)); return NXml::getNextElement(source); } void OrphanPlugin::saveSettings(NXml::XmlData& outData, QDomElement parent) const { QDomElement orphanPluginElement = outData.addElement(parent, name()); outData.addAttribute(orphanPluginElement, 0.1f, "settingsVersion"); outData.addAttribute(orphanPluginElement, _pInputWidget->searchOption(), "searchOption"); } ///////////////////////////////////////////////////// // Search Plugin Interface ///////////////////////////////////////////////////// QWidget* OrphanPlugin::shortInputAndFeedbackWidget() const { return _pOrphanFeedbackWidget; } QWidget* OrphanPlugin::inputWidget() const { return _pInputWidget; } QString OrphanPlugin::inputWidgetTitle() const { return tr("Orphans"); }; void OrphanPlugin::clearSearch() { _pInputWidget->clearSearch(); // evaluateSearch(); } bool OrphanPlugin::isInactive() const { return !_pInputWidget->isActive(); } ///////////////////////////////////////////////////// // Search Helper Methods ///////////////////////////////////////////////////// void OrphanPlugin::evaluateSearch() { qDebug("evaluating orphan search"); _pProvider->reportBusy(this, tr("Searching orphans")); _searchResult.clear(); if ( !isInactive() ) // if the search is not empty { QString commandLine = _pInputWidget->getDeborphanCommandLine(); _pOrphanFeedbackWidget->_pTextDisplay->setText(commandLine); NApplication::RunCommandForOutput ro(commandLine); if (ro.run(commandLine, 0)) { QStringList lines = ro.getOutput(); // the output of deborphan is one package per line for (QStringList::const_iterator it = lines.begin(); it != lines.end(); ++it) { _searchResult.insert( extractPackageNameFromDeborphanLine(toString(*it)) ); } } else _pProvider->reportError(tr("Error running deborphan"), tr("An error occured running ")+ commandLine+""); } else _pOrphanFeedbackWidget->_pTextDisplay->clear(); _pOrphanFeedbackWidget->setVisible(!isInactive()); _pProvider->reportReady(this); emit searchChanged(this); } string OrphanPlugin::extractPackageNameFromDeborphanLine(const string& line ) { return line.substr(0, line.find(":")); } } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugin.h0000644000000000000000000000515513507430555022224 0ustar // // C++ Interface: orphanplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGINORPHANPLUGIN_H_2005_06_08 #define __NPLUGINORPHANPLUGIN_H_2005_06_08 #include #include class OrphanFeedbackWidget; namespace NPlugin { class OrphanSearchInputImpl; /** @author Benjamin Mesing */ class OrphanPlugin : public SearchPlugin { Q_OBJECT public: static const QString PLUGIN_NAME; OrphanPlugin(); virtual ~OrphanPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual uint priority() const { return 7; }; virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } /** @returns "OrphanPlugin" */ virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; virtual QDomElement loadSettings(const QDomElement source); virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const; //@} /** @name SearchPlugin interface * * Implementation of the SearchPlugin interface */ //@{ virtual uint searchPriority() const { return 9; }; virtual QWidget* inputWidget() const; virtual QString inputWidgetTitle() const; virtual QWidget* shortInputAndFeedbackWidget() const; virtual void clearSearch(); virtual bool usesFilterTechnique() const { return false; }; virtual const std::set& searchResult() const { return _searchResult; }; virtual bool filterPackage(const string&) const { return true; }; virtual bool isInactive() const; //@} protected Q_SLOTS: /** @brief Evaluates the currently entered search. */ void evaluateSearch(); /** @brief Slot that calls clearSearch() */ void onClearSearch() { clearSearch(); }; /** @brief Extracts the package name from the result line from deborphan. * * Currently this only strips the arch-part from the line, if available. */ static string extractPackageNameFromDeborphanLine(const string& line ); private: /** Widget where the search might be enterd. */ OrphanSearchInputImpl* _pInputWidget; /** The widget where the search selected is shown in. */ OrphanFeedbackWidget* _pOrphanFeedbackWidget; /** Holds a pointer to the pluginmanager which manages this pugin. */ IProvider* _pProvider; /** This holds the result of the currently active search. */ std::set _searchResult; }; } #endif // __NPLUGINORPHANPLUGIN_H_2005_06_08 packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugin.kdev40000644000000000000000000000007213507430555023003 0ustar [Project] Manager=KDevCustomMakeManager Name=orphanplugin packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugin.pro0000644000000000000000000000275313507430555022576 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./orphanplugin # Target is a library: FORMS += orphansearchinput.ui \ orphanfeedbackwidget.ui HEADERS += orphanplugincontainer.h \ orphanpluginfactory.h \ orphanplugin.h \ orphansearchinputimpl.h \ orphanfeedbackwidgetimpl.h SOURCES += orphanplugincontainer.cpp \ orphanpluginfactory.cpp \ orphanplugin.cpp \ orphansearchinputimpl.cpp \ orphanfeedbackwidgetimpl.cpp TRANSLATIONS = ../../../translations/orphanplugin_de.ts \ ../../../translations/orphanplugin_es.ts INCLUDEPATH = . \ ../../ PKGCONFIG += libept # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) MOC_DIR = .moc UI_DIR = .ui OBJECTS_DIR = .obj DESTDIR = ../ CONFIG += warn_on \ qt \ thread \ plugin \ stl \ link_pkgconfig VERSION = 0.0.1 TEMPLATE = lib QT += xml widgets debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugincontainer.cpp0000644000000000000000000000323413507430555024456 0ustar // // C++ Implementation: orphanplugincontainer // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include "orphanplugincontainer.h" #include "orphanpluginfactory.h" extern "C" { NPlugin::PluginContainer* new_orphanplugin() { return new NPlugin::OrphanPluginContainer;; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("orphanplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } namespace NPlugin { OrphanPluginContainer::OrphanPluginContainer() { addPlugin("OrphanPlugin"); } OrphanPluginContainer::~OrphanPluginContainer() { unloadAllPlugins(); } ///////////////////////////////////////////////////// // Plugin Container Interface ///////////////////////////////////////////////////// bool OrphanPluginContainer::init(IProvider* pProvider) { BasePluginContainer::init(pProvider, OrphanPluginFactory::getInstance()); requestPlugin("OrphanPlugin"); if (!QFile::exists("/usr/bin/deborphan")) { provider()->reportError( tr("deborphan not available"), tr("The deborphan application, needed by the orphan plugin, was not found. " "The orphan plugin was disabled. " "To use the orphan plugin install the deborphan package via
" "apt-get install deborphan
" "and reenable the plugin using Packagesearch -> Control Plugins afterwards." ) ); return false; } return true; } QString OrphanPluginContainer::title() const { return QObject::tr("Orphan Plugins"); } } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanplugincontainer.h0000644000000000000000000000225613507430555024126 0ustar // // C++ Interface: orphanplugincontainer // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_ORPHANPLUGINCONTAINER_H_2005_06_08 #define __NPLUGIN_ORPHANPLUGINCONTAINER_H_2005_06_08 #include #include namespace NPlugin { /** @author Benjamin Mesing */ class OrphanPluginContainer : public QObject, public BasePluginContainer { Q_OBJECT public: OrphanPluginContainer(); virtual ~OrphanPluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ virtual bool init(IProvider* pProvider); /** This gets a plugin with the given name. * * Accepted names are: * \li "FilenamePlugin" * @see PluginContainer::requestPlugin() */ /** @returns "filenameplugin" */ virtual string name() const { return "orphanplugin"; }; virtual QString title() const; /** This returns an empty list. */ vector< pair > actions() { return vector< pair >(); }; //@} }; } #endif // __NPLUGIN_ORPHANPLUGINCONTAINER_H_2005_06_08 packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanpluginfactory.cpp0000644000000000000000000000134713507430555024146 0ustar // // C++ Implementation: orphanpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "orphanpluginfactory.h" #include "orphanplugin.h" namespace NPlugin { OrphanPluginFactory* OrphanPluginFactory::_pInstance = 0; OrphanPluginFactory::OrphanPluginFactory() { } OrphanPluginFactory::~OrphanPluginFactory() { } Plugin* OrphanPluginFactory::createPlugin(const string& name) const { if (name=="OrphanPlugin") { return new OrphanPlugin(); } else return 0; } OrphanPluginFactory* OrphanPluginFactory::getInstance() { if (_pInstance == 0) _pInstance = new OrphanPluginFactory; return _pInstance; } } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphanpluginfactory.h0000644000000000000000000000150713507430555023611 0ustar // // C++ Interface: orphanpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_ORPHANPLUGINFACTORY_H_2005_06_08 #define __NPLUGIN_ORPHANPLUGINFACTORY_H_2005_06_08 #include namespace NPlugin { class OrphanPluginFactory; /** @author Benjamin Mesing */ class OrphanPluginFactory : public IPluginFactory { private: OrphanPluginFactory(); static OrphanPluginFactory* _pInstance; public: ~OrphanPluginFactory(); /** @name IPluginFactory interface */ //@{ virtual Plugin* createPlugin(const string& name) const; //@} /** @brief Returns the single instance of this class. */ static OrphanPluginFactory* getInstance(); }; } #endif // __NPLUGIN_ORPHANPLUGINFACTORY_H_2005_06_08 packagesearch-2.7.11build1/src/plugins/orphanplugin/orphansearchinput.ui0000644000000000000000000001206113507430555023433 0ustar OrphanSearchInput 0 0 275 249 Form1 6 6 Search for ophaned package <p>Enable this option to search for orphaned packages. Orphaned packages are packages which no other package depends on. By default only the <i>libs</i> and <i>oldlibs</i> sections are searched.</p> <p>This search uses the <tt>deborphan</tt> tool as backend so make sure it is installed.</p> Search orphaned false Options 6 6 Search in section lib and oldlib only Searches only the lib and oldlib section for orphans. Search lib and oldlib true Search in section lib, oldlib and libdevel Search in the section libdevel in addition to libs and oldlibs. Search lib, oldlib and libdevel Search all the packages, instead of only those in the libs section Search all sections Searches packages that are possibly useless <p>Search for packages where deborphan guesses them not to be of much use to you by examining the package's name and/or description. It will pretend the package is in the main/libs section, and report it as if it were a library. </p> <p>This method is in no way perfect or even reliable, so beware when using this! </p> Guess useless Searches packages with residual configuration <p>This option searches for uninstalled packages which still have configuration files on the system. </p> <p>It implies searching in all sections.</p> Search residual configuration Qt::Vertical 20 40 qPixmapFromMimeSource _pSearchOrphanedOption toggled(bool) _pOptionGroup setEnabled(bool) 79 24 208 116 packagesearch-2.7.11build1/src/plugins/orphanplugin/orphansearchinputimpl.cpp0000644000000000000000000000562213507430555024467 0ustar // // C++ Implementation: orphansearchinputimpl // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "orphansearchinputimpl.h" #include #include namespace NPlugin { OrphanSearchInputImpl::OrphanSearchInputImpl(QWidget* parent) : QWidget(parent) { setupUi(this); _pOptionButtonGroup = new QButtonGroup(this); _pOptionButtonGroup->addButton(_pDefaultOption); _pOptionButtonGroup->addButton(_pLibdevelOption); _pOptionButtonGroup->addButton(_pAllOption); _pOptionButtonGroup->addButton(_pGuessUselessOption); _pOptionButtonGroup->addButton(_pResidualConfigurationOption); connect(_pOptionButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(onSearchChanged())); } OrphanSearchInputImpl::~OrphanSearchInputImpl() { } void OrphanSearchInputImpl::onSearchChanged() { emit(searchChanged()); } QString OrphanSearchInputImpl::getDeborphanCommandLine() { QString commandLine = "deborphan"; // switch according to the buttonID set in the designer switch (searchOption()) { case DEFAULT: break; case LIBDEVEL: commandLine.append(" --libdevel"); break; case ALL: commandLine.append(" --all-packages --no-show-section"); break; case GUESS_USELESS: commandLine.append(" --guess-all"); break; case RESIDUAL_CONFIGURATION: commandLine.append(" --find-config"); break; } return commandLine; } void OrphanSearchInputImpl::clearSearch() { _pSearchOrphanedOption->setChecked(false); } bool OrphanSearchInputImpl::isActive() { return _pSearchOrphanedOption->isChecked(); } OrphanSearchInputImpl::OrphanSearchOption OrphanSearchInputImpl::searchOption() const { if (_pOptionButtonGroup->checkedButton() == _pDefaultOption) return DEFAULT; else if (_pOptionButtonGroup->checkedButton() == _pLibdevelOption) return LIBDEVEL; else if (_pOptionButtonGroup->checkedButton() == _pAllOption) return ALL; else if (_pOptionButtonGroup->checkedButton() == _pGuessUselessOption) return GUESS_USELESS; else if (_pOptionButtonGroup->checkedButton() == _pResidualConfigurationOption) return RESIDUAL_CONFIGURATION; qDebug("Warning: Unknown Orphan search option"); return DEFAULT; } void OrphanSearchInputImpl::setSearchOption(OrphanSearchOption searchOption) { QRadioButton* pCurrentButton = 0; switch (searchOption) { case DEFAULT: pCurrentButton = _pDefaultOption; break; case LIBDEVEL: pCurrentButton = _pLibdevelOption; break; case ALL: pCurrentButton = _pAllOption; break; case GUESS_USELESS: pCurrentButton = _pGuessUselessOption; break; case RESIDUAL_CONFIGURATION: pCurrentButton = _pResidualConfigurationOption; break; } pCurrentButton->setChecked(true); } void OrphanSearchInputImpl::on__pSearchOrphanedOption_toggled(bool checked) { _pOptionGroup->setEnabled(checked); emit(searchChanged()); } } packagesearch-2.7.11build1/src/plugins/orphanplugin/orphansearchinputimpl.h0000644000000000000000000000264513507430555024136 0ustar // // C++ Interface: orphansearchinputimpl // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_ORPHANSEARCHINPUTIMPL_H_2005_06_28 #define __NPLUGIN_ORPHANSEARCHINPUTIMPL_H_2005_06_28 #include #include "ui_orphansearchinput.h" class QButtonGroup; namespace NPlugin { /** @author Benjamin Mesing */ class OrphanSearchInputImpl : public QWidget, public Ui::OrphanSearchInput { Q_OBJECT QButtonGroup* _pOptionButtonGroup; public: // This enum corresponds to the values in the IDs of the radio buttons enum OrphanSearchOption { DEFAULT = 1, LIBDEVEL, ALL, GUESS_USELESS, RESIDUAL_CONFIGURATION }; OrphanSearchInputImpl(QWidget *parent = 0); ~OrphanSearchInputImpl(); virtual QString getDeborphanCommandLine(); virtual void clearSearch(); virtual bool isActive(); /** @brief Returns the current search option. * * Never returns a value not in OrphanSearchOption. */ virtual OrphanSearchOption searchOption() const; /** Sets the search option. */ virtual void setSearchOption(OrphanSearchOption searchOption); public Q_SLOTS: /** @brief Slot which emits the search changed signal. */ virtual void onSearchChanged(); void on__pSearchOrphanedOption_toggled(bool checked); signals: void searchChanged(); }; } #endif // __NPLUGIN_ORPHANSEARCHINPUTIMPL_H_2005_06_28 packagesearch-2.7.11build1/src/plugins/plugins-test.pro0000644000000000000000000000014213507430555020006 0ustar TEMPLATE = subdirs SUBDIRS += aptplugin-test debtagsplugin-test QMAKE_MAKEFILE = Makefile.test packagesearch-2.7.11build1/src/plugins/plugins.pro0000644000000000000000000000054713507430555017042 0ustar ###################################################################### # Automatically generated by qmake (1.06c) Wed Aug 11 16:37:48 2004 ###################################################################### TEMPLATE = subdirs SUBDIRS += aptplugin \ debtagsplugin \ filenameplugin \ orphanplugin \ # popconplugin \ screenshotplugin packagesearch-2.7.11build1/src/plugins/popconplugin/0000755000000000000000000000000013507430555017346 5ustar packagesearch-2.7.11build1/src/plugins/popconplugin/.kdev4/0000755000000000000000000000000013507430555020441 5ustar packagesearch-2.7.11build1/src/plugins/popconplugin/.kdev4/popconplugin.kdev40000644000000000000000000000034313507430555024115 0ustar [Buildset] BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x18\x00p\x00o\x00p\x00c\x00o\x00n\x00p\x00l\x00u\x00g\x00i\x00n) [Project] VersionControlSupport=kdevsubversion packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugin.cpp0000644000000000000000000000504613507430555022574 0ustar #include #include #include #include #include #include #include #include #include #include //#include //#include #include #include // NPlugin #include #include #include "popconplugin.h" using namespace std; namespace NPlugin { const QString PopconPlugin::PLUGIN_NAME = "PopconPlugin"; ///////////////////////////////////////////////////// // Constructors/ Destructors ///////////////////////////////////////////////////// PopconPlugin::PopconPlugin(const PopconPluginContainer& container) : _container(container) { _pProvider = 0; } PopconPlugin::~PopconPlugin() { } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void PopconPlugin::init(IProvider* pProvider) { _pProvider = pProvider; } QString PopconPlugin::title() const { return QString("Popcon Plugin"); } QString PopconPlugin::briefDescription() const { return QString("Makes popcon data available and uses it for score calucation"); } QString PopconPlugin::description() const { return QString("This plugin makes the popcon information available." "Popcon scores are used to calculate the scores for a package and " "displayed in the package details."); } ///////////////////////////////////////////////////// // Search Plugin Interface ///////////////////////////////////////////////////// map PopconPlugin::getScore(const set& packages) const { qDebug("PopconPlugin::getScore not implemented"); return map(); } bool PopconPlugin::offersScore() const { return false; } ///////////////////////////////////////////////////// // Information Plugin Interface ///////////////////////////////////////////////////// QString PopconPlugin::informationText(const string& package) { { // add the tags of the package to the description // float score = _container.popcon().scoreByName(package); QString detailsString = "Score: " ; // + QString::number(score); return detailsString+"
"; } } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// } // namespace NPlugin #undef emit /* #include #include #include #include */ packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugin.h0000644000000000000000000000742613507430555022245 0ustar #ifndef __POPCONPLUGIN_H_2010_02_28 #define __POPCONPLUGIN_H_2010_02_28 #include #include #include #include #include class QAbstractItemView; class QPoint; namespace NTagModel { class VocabularyModel; } using namespace std; namespace NPlugin { /** This plugin offers search by tags * * @author Benjamin Mesing */ class PopconPlugin : public ScorePlugin, public InformationPlugin { /** @brief This holds a link to the manager which manages the plugin. * * Acquaintance relation */ IProvider* _pProvider; /** The container which holds this plugin. */ const PopconPluginContainer& _container; public: static const QString PLUGIN_NAME; /** Create this plugin as plugin in container. * * @param container the container which contains this plugin. */ PopconPlugin(const PopconPluginContainer& container);; virtual ~PopconPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ /** @brief Initializes the plugin. */ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; //@} ///@todo try to remove malformed descriptions /** @name ScorePlugin interface * * Implementation of the SearchPlugin interface */ //@{ /** @brief Returns the score of the handed packages for the currently active search. * * The scores are in [0..1] where 0.0f means the lowest and 1.0f the highest score. * The scores are always calculated for a whole set of packages, because scores * may be relative to each other (i.e. there is no absolute criterion to score package * but we can say that package1 matches better than package2) * * @pre offersScore() == true * @post returnedValue.keys() == packages
* i.e. all the handed packages must be contained in the returned map * @returns a map mapping each package to its scores * @see offersScore() */ virtual map getScore(const set& packages) const ; /** @brief Returns if the plugin is currently offering scores. * * This could return false e.g. if scores are only calculated for an active search * (like e.g. a fulltext search), but no search is currently active. * @see getScore() */ virtual bool offersScore() const; //@} /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 5; }; /** This plugin does not offer a separate information widget. */ virtual QWidget* informationWidget() const { return 0; }; /** This plugin does not offer a separate information widget. */ virtual QString informationWidgetTitle() const { return _emptyString; }; /** This plugin does not offer a separate information widget. */ virtual void updateInformationWidget(const string&) {}; /** This plugin does not offer a separate information widget. */ virtual void clearInformationWidget() {}; /** This plugin offers an information text. */ virtual bool offersInformationText() const { return true; }; /** Returns a string which lists the tags for the requested package. */ virtual QString informationText (const string& package); //@} /** @brief This can be used to notify the plugin that the popcon data in the * plugin container (i.e. the tag collection and the vocabulary) has changed. * * It behaves sound if the values are not set in the container. */ void popconDataChanged(); }; } // namespace NPlugin #endif // __POPCONPLUGIN_H_2010_02_28 packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugin.kdev40000644000000000000000000000007213507430555023021 0ustar [Project] Manager=KDevCustomMakeManager Name=popconplugin packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugin.kdevelop0000644000000000000000000000543513507430555023625 0ustar Benjamin Mesing bensmail@gmx.net $VERSION$ KDevTrollProject C++ Qt false false *.o,*.lo,CVS false bash bash_bugs clanlib w3c-dom-level2-html fortran_bugs_gcc gnome1 gnustep gtk gtk_bugs haskell haskell_bugs_ghc java_bugs_gcc java_bugs_sun kde2book opengl pascal_bugs_fp php php_bugs perl perl_bugs python python_bugs qt-kdev3 ruby ruby_bugs sdl stl w3c-svg sw w3c-uaag10 wxwidgets_bugs KDE Libraries (Doxygen) executable true true true false true true true 250 400 250 packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugin.pro0000644000000000000000000000244413507430555022611 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./popconplugin # Target is a library: # debug mode only HEADERS += popconplugin.h \ popconplugincontainer.h \ popconpluginfactory.h SOURCES += popconplugin.cpp \ popconplugincontainer.cpp \ popconpluginfactory.cpp TRANSLATIONS = ../../../translations/popconplugin_de.ts \ ../../../translations/popconplugin_es.ts TEMPLATE = lib CONFIG += warn_on \ qt \ thread \ stl \ plugin \ link_pkgconfig OBJECTS_DIR = .obj UI_DIR = .ui MOC_DIR = .moc DESTDIR = ../ VERSION = 0.0.1 INCLUDEPATH += . \ ../../ PKGCONFIG += libept libtagcoll2 # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) QT += xml debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugincontainer.cpp0000644000000000000000000000537713507430555024506 0ustar #include #include #include #include #include #include // for getuid and geteuid #include // #include #include "popconplugincontainer.h" // NUtil #include "helpers.h" // NApplication #include "applicationfactory.h" #include "runcommand.h" // NPlugin #include #include #include #include "popconplugin.h" #include "popconpluginfactory.h" #include extern "C" { NPlugin::PluginContainer* new_popconplugin() { return new NPlugin::PopconPluginContainer; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("popconplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } /** Initialize the plugin. */ __attribute__ ((constructor)) void init() { } // __attribute__ ((destructor)) void fini() // { // /* code here is executed just before dlclose() unloads the module */ // } namespace NPlugin { PopconPluginContainer::PopconPluginContainer() { // this assumes, that only one instance of the PopconPluginContainer is created // (no two versions of libapt-front may be opened at any time) // This is ok for our purpose - though usually there should be a singleton ensuring // this constraint... PopconPluginFactory::getInstance()->setContainer(this); _pPopconPlugin = 0; addPlugin("PopconPlugin"); _popconEnabled=false; } PopconPluginContainer::~PopconPluginContainer() { unloadAllPlugins(); } ///////////////////////////////////////////////////// // PluginContainer Interface ///////////////////////////////////////////////////// bool PopconPluginContainer::init(IProvider* pProvider) { BasePluginContainer::init(pProvider, PopconPluginFactory::getInstance()); if (popconEnabled()) { // use dynamic cast here because of the virtual base class // (static_cast is not allowed there) _pPopconPlugin = dynamic_cast(requestPlugin("PopconPlugin")); } else { provider()->reportError( tr("Popcon data not available" ), tr( "

There is no popcon data available!

" "

" "The popcon plugin has been disabled." "

") ); return false; } return popconEnabled(); } ///////////////////////////////////////////////////// // BasePluginContainer Interface ///////////////////////////////////////////////////// vector< pair > PopconPluginContainer::actions() { vector< pair > result; return result; } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void PopconPluginContainer::setPopconEnabled(bool enabled) { _popconEnabled = enabled; } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/popconplugin/popconplugincontainer.h0000644000000000000000000000374113507430555024144 0ustar #ifndef __POPCONPLUGINCONTAINER_H_2010_02_28 #define __POPCONPLUGINCONTAINER_H_2010_02_28 #include #include #include //#include #include using namespace std; class PopconSettingsWidget; namespace NPlugin { class PopconPlugin; /** @brief This class provides plugins using the popcon system. * * It manages the shared data and offers the possibility to update the popcon database. * * @author Benjamin Mesing */ class PopconPluginContainer : public QObject, public BasePluginContainer { Q_OBJECT /** @brief This holds if the popcon operations are currently enabled. * * This will be set to false if the reading of the tag database failed. */ bool _popconEnabled; /** Holds the popcon plugin created. */ PopconPlugin* _pPopconPlugin; public: /** Empty Constructor */ PopconPluginContainer(); ~PopconPluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ virtual bool init(IProvider* pProvider); /** @returns "popconplugin" */ virtual string name() const { return "popconplugin"; }; virtual QString title() const { return tr("Popcon Plugins"); }; /** @brief This returns a list with one entry which is the "Popcon Update" entry * * The QString specifies the menu the action should be added to, the action is * a QAction which is connected to the operation to perform.\n * The default implementation returns an empty vector. */ vector< pair > actions(); //@} /** @brief Returns the #_popconEnabled property. */ bool popconEnabled() { return _popconEnabled; }; protected: /** @brief This sets the popcon operations to be enabled/ disabled * * If set to false all widgets will be disabled, else they will be enabled. * @see #_popconEnabled */ void setPopconEnabled(bool enabled); }; } // namespace NPlugin #endif // __POPCONPLUGINCONTAINER_H_2010_02_28 packagesearch-2.7.11build1/src/plugins/popconplugin/popconpluginfactory.cpp0000644000000000000000000000135413507430555024162 0ustar // // C++ Implementation: popconpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2010 // // Copyright: See COPYING file that comes with this distribution // // #include "popconpluginfactory.h" #include "popconplugin.h" namespace NPlugin { PopconPluginFactory* PopconPluginFactory::_pInstance = 0; PopconPluginFactory::PopconPluginFactory() { } PopconPluginFactory::~PopconPluginFactory() { } Plugin* PopconPluginFactory::createPlugin(const string& name) const { if (name=="PopconPlugin") { return new PopconPlugin(*_pContainer); } return 0; } PopconPluginFactory* PopconPluginFactory::getInstance() { if (_pInstance == 0) _pInstance = new PopconPluginFactory; return _pInstance; } }; packagesearch-2.7.11build1/src/plugins/popconplugin/popconpluginfactory.h0000644000000000000000000000215213507430555023624 0ustar // // C++ Interface: popconpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2010 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGINPOPCONPLUGINFACTORY_H_2010_02_28 #define __NPLUGINPOPCONPLUGINFACTORY_H_2010_02_28 #include namespace NPlugin { class PopconPluginContainer; /** @brief This creates the popcon plugins. * * * @author Benjamin Mesing */ class PopconPluginFactory : public IPluginFactory { PopconPluginContainer* _pContainer; PopconPluginFactory(); static PopconPluginFactory* _pInstance; public: ~PopconPluginFactory(); void setContainer(PopconPluginContainer* pContainer) { _pContainer = pContainer; }; /** @name IPluginFactory interface */ //@{ /** @brief This creates a plugin for the given name. * * Accepted names are: * \li "PopconPlugin" * * @pre setContainer() must have been called or 0 will be returned. */ virtual Plugin* createPlugin(const string& name) const; //@} static PopconPluginFactory* getInstance(); }; }; #endif // __NPLUGINPOPCONPLUGINFACTORY_H_ packagesearch-2.7.11build1/src/plugins/screenshotplugin/0000755000000000000000000000000013507430555020225 5ustar packagesearch-2.7.11build1/src/plugins/screenshotplugin/.kdev4/0000755000000000000000000000000013507430555021320 5ustar packagesearch-2.7.11build1/src/plugins/screenshotplugin/.kdev4/screenshotplugin.kdev40000644000000000000000000000036413507430555025656 0ustar [Buildset] BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00 \x00s\x00c\x00r\x00e\x00e\x00n\x00s\x00h\x00o\x00t\x00p\x00l\x00u\x00g\x00i\x00n) [Project] VersionControlSupport=kdevsubversion packagesearch-2.7.11build1/src/plugins/screenshotplugin/.moc/0000755000000000000000000000000013507430555021061 5ustar packagesearch-2.7.11build1/src/plugins/screenshotplugin/.obj/0000755000000000000000000000000013507430555021055 5ustar packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugin.cpp0000644000000000000000000001174113507430555024331 0ustar #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include #include #include // NPlugin #include #include #include "screenshotplugin.h" using namespace std; namespace NPlugin { const QString ScreenshotPlugin::PLUGIN_NAME = "ScreenshotPlugin"; ///////////////////////////////////////////////////// // Constructors/ Destructors ///////////////////////////////////////////////////// ScreenshotPlugin::ScreenshotPlugin(const ScreenshotPluginContainer& container) : _container(container) { _pProvider = 0; _pReply = 0; } ScreenshotPlugin::~ScreenshotPlugin() { } ///////////////////////////////////////////////////// // Plugin Interface ///////////////////////////////////////////////////// void ScreenshotPlugin::init(IProvider* pProvider) { _pProvider = pProvider; QMainWindow* pWindow = pProvider->mainWindow(); _pScrollArea = new QScrollArea(pWindow); _pScreenshotWidget = new QLabel("", pWindow); _pScrollArea->setWidget(_pScreenshotWidget); _pScrollArea->setWidgetResizable(true); //_pScrollArea->setVisible(false); } QString ScreenshotPlugin::title() const { return tr("Screenshot Plugin"); } QString ScreenshotPlugin::briefDescription() const { return tr("Displays screenshots of the packages to be installed"); } QString ScreenshotPlugin::description() const { return tr("This plugin displays screenshots of the packages to be installed. " "It fetches the screenshots from http://screenshots.debian.net so a working " "internet connection is required."); } ///////////////////////////////////////////////////// // Information Plugin Interface ///////////////////////////////////////////////////// QWidget* ScreenshotPlugin::informationWidget() const { return _pScrollArea; } void ScreenshotPlugin::updateInformationWidget(const string& package) { /* qDebug() << "Label size: " << _pScreenshotWidget->size(); qDebug() << "Scroll size: " << _pScrollArea->size();*/ if (_pReply) // if we have a download running, delete it { abortDownload(); } _pScreenshotWidget->setText(tr("Loading screenshot\nEstablishing connection, please wait...")); //_pReply = _nam.get(QNetworkRequest("myfile")); QUrl url(QString("http://screenshots.debian.net/screenshot/")+toQString(package)); _pReply = _pProvider->network()->get(QNetworkRequest(url)); connect(_pReply, SIGNAL(finished()), SLOT(httpFinished())); connect(_pReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(httpError(QNetworkReply::NetworkError))); connect(_pReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(httpDownloadProgress(qint64,qint64))); } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void ScreenshotPlugin::abortDownload() { if (_pReply) { _pReply->abort(); _pReply->deleteLater(); _pReply = 0; } } void ScreenshotPlugin::httpFinished() { // if an error other than ContentNotFound (which is expected if no screenshot is available) occured if (_pReply->error() != QNetworkReply::NoError && _pReply->error() != QNetworkReply::ContentNotFoundError) return; QImageReader reader(_pReply); QImage image = reader.read(); _pReply->deleteLater(); _pReply = 0; _pScreenshotWidget->setPixmap(QPixmap::fromImage(image)); } void ScreenshotPlugin::httpDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { // if an error occured or the download is finished if (_pReply->error() != QNetworkReply::NoError || _pReply->isFinished()) return; if (bytesTotal > 10*1024*1024) { abortDownload(); _pScreenshotWidget->setText(tr("The screenshot size exceeds 10 MB. " "Something seems to be wrong here!\n Aborting Download.")); return; } QString progress; progress.setNum((int) (((float) bytesReceived)/bytesTotal*100.0f) ) ; // ToDo insert linebreak instead of " - " here, but currently this leads to loads of QT warnings _pScreenshotWidget->setText(tr("Loading screenshot - Progress: ") + progress + "%"); } void ScreenshotPlugin::httpError(QNetworkReply::NetworkError e) { // this error is normally returned by if there was no screenshot available if (e==QNetworkReply::ContentNotFoundError) { _pScreenshotWidget->setText(tr("No screenshot available for ") + _pReply->url().toString()); return; } // if the error is OperationCanceled that is no error if (e==QNetworkReply::OperationCanceledError) return; qDebug() << "Network error\n" << _pReply->errorString(); // in all other cases abort the download _pScreenshotWidget->setText(tr("An error occured while trying to download the screenshot:\n") + _pReply->errorString()); abortDownload(); } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugin.h0000644000000000000000000000575213507430555024003 0ustar #ifndef __SCREENSHOTPLUGIN_H_2010_08_05 #define __SCREENSHOTPLUGIN_H_2010_08_05 #include #include #include #include #include #include #include using namespace std; class QLabel; class QScrollArea; namespace NPlugin { /** This plugin offers displaying of screenshots. * * @author Benjamin Mesing */ class ScreenshotPlugin : public QObject, public InformationPlugin { Q_OBJECT /** @brief This holds a link to the manager which manages the plugin. * * Acquaintance relation */ IProvider* _pProvider; /** The container which holds this plugin. */ const ScreenshotPluginContainer& _container; QLabel* _pScreenshotWidget; QScrollArea* _pScrollArea; /** @brief Holds the networt reply for the current screenshot-download or 0 if no download * is active. */ QNetworkReply *_pReply; public: static const QString PLUGIN_NAME; /** Create this plugin as plugin in container. * * @param container the container which contains this plugin. */ ScreenshotPlugin(const ScreenshotPluginContainer& container);; virtual ~ScreenshotPlugin(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ /** @brief Initializes the plugin. */ virtual void init(IProvider* pProvider); /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const; virtual QString briefDescription() const; virtual QString description() const; //@} //@{ /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 5; }; /** This plugin does not offer a separate information widget. */ virtual QWidget* informationWidget() const; /** This plugin does not offer a separate information widget. */ virtual QString informationWidgetTitle() const { return "Screenshot"; }; /** @brief Triggers downloading of a screenshot for the given package * * Displays screenshot as soon as it is available. */ virtual void updateInformationWidget(const string& package); /** This plugin does not offer a separate information widget. */ virtual void clearInformationWidget() {}; /** This plugin offers an information text. */ virtual bool offersInformationText() const { return false; }; /** Returns a string which lists the tags for the requested package. */ virtual QString informationText (const string& ) { return ""; }; //@} private Q_SLOTS: /** @brief Aborts the active download of the screenshot. * * Does nothing, if no download is running (i.e. _pReply == 0). */ void abortDownload(); void httpFinished(); void httpDownloadProgress(qint64 bytesReceived, qint64 bytesTotal ); void httpError(QNetworkReply::NetworkError); }; } // namespace NPlugin #endif // __SCREENSHOTPLUGIN_H_2010_08_05 packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugin.kdev40000644000000000000000000000007613507430555024563 0ustar [Project] Manager=KDevCustomMakeManager Name=screenshotplugin packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugin.pro0000644000000000000000000000251413507430555024345 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: ./screenshotplugin # Target is a library: # debug mode only HEADERS += screenshotplugin.h \ screenshotplugincontainer.h \ screenshotpluginfactory.h SOURCES += screenshotplugin.cpp \ screenshotplugincontainer.cpp \ screenshotpluginfactory.cpp TRANSLATIONS = ../../../translations/screenshotplugin_de.ts \ ../../../translations/screenshotplugin_es.ts TEMPLATE = lib CONFIG += warn_on \ qt \ thread \ stl \ plugin \ link_pkgconfig OBJECTS_DIR = .obj UI_DIR = .ui MOC_DIR = .moc DESTDIR = ../ VERSION = 0.0.1 INCLUDEPATH += . \ ../../ PKGCONFIG += libept # this is required to remove the --no-undefined flag, which causes a linker error QMAKE_LFLAGS -= -Wl,--no-undefined # yeah, go for C++11! QMAKE_CXXFLAGS += -std=c++11 # add standard Debian flags QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CPPFLAGS) QMAKE_CXXFLAGS_RELEASE += $$system(dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS += $$system(dpkg-buildflags --get LDFLAGS) QT += xml widgets network debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugincontainer.cpp0000644000000000000000000000410413507430555026227 0ustar #include #include #include #include #include "screenshotplugincontainer.h" // NUtil #include "helpers.h" // NApplication #include "applicationfactory.h" #include "runcommand.h" // NPlugin #include #include #include #include "screenshotplugin.h" #include "screenshotpluginfactory.h" #include extern "C" { NPlugin::PluginContainer* new_screenshotplugin() { return new NPlugin::ScreenshotPluginContainer; } NPlugin::PluginInformation get_pluginInformation() { return NPlugin::PluginInformation("screenshotplugin", toString(NPackageSearch::VERSION), "Benjamin Mesing"); } } /** Initialize the plugin. */ __attribute__ ((constructor)) void init() { } // __attribute__ ((destructor)) void fini() // { // /* code here is executed just before dlclose() unloads the module */ // } namespace NPlugin { ScreenshotPluginContainer::ScreenshotPluginContainer() { _pScreenshotPlugin = 0; addPlugin("ScreenshotPlugin"); _screenshotEnabled=true; } ScreenshotPluginContainer::~ScreenshotPluginContainer() { unloadAllPlugins(); } ///////////////////////////////////////////////////// // PluginContainer Interface ///////////////////////////////////////////////////// bool ScreenshotPluginContainer::init(IProvider* pProvider) { BasePluginContainer::init(pProvider, ScreenshotPluginFactory::getInstance()); if (screenshotEnabled()) { // use dynamic cast here because of the virtual base class // (static_cast is not allowed there) _pScreenshotPlugin = dynamic_cast(requestPlugin("ScreenshotPlugin")); } else { provider()->reportError( tr("Screenshots not supported" ), tr("Screenshots not supported") ); return false; } return screenshotEnabled(); } ///////////////////////////////////////////////////// // Helper Methods ///////////////////////////////////////////////////// void ScreenshotPluginContainer::setScreenshotEnabled(bool enabled) { _screenshotEnabled = enabled; } } // namespace NPlugin packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotplugincontainer.h0000644000000000000000000000314313507430555025676 0ustar #ifndef __SCREENSHOTPLUGINCONTAINER_H_2010_08_05 #define __SCREENSHOTPLUGINCONTAINER_H_2010_08_05 #include #include #include #include using namespace std; class ScreenshotSettingsWidget; namespace NPlugin { class ScreenshotPlugin; /** @brief This class provides plugins for displaying screenshots. * * @author Benjamin Mesing */ class ScreenshotPluginContainer : public QObject, public BasePluginContainer { Q_OBJECT /** @brief This holds if the screenshot operations are currently enabled. * * This will be set to false if the reading of the tag database failed. */ bool _screenshotEnabled; /** Holds the screenshot plugin created. */ ScreenshotPlugin* _pScreenshotPlugin; public: /** Empty Constructor */ ScreenshotPluginContainer(); ~ScreenshotPluginContainer(); /** @name PluginContainer Interface * * These functions implement the PluginContainer interface. */ //@{ virtual bool init(IProvider* pProvider); /** @returns "screenshotplugin" */ virtual string name() const { return "screenshotplugin"; }; virtual QString title() const { return tr("Screenshot Plugins"); }; //@} /** @brief Returns the #_screenshotEnabled property. */ bool screenshotEnabled() { return _screenshotEnabled; }; protected: /** @brief This sets the screenshot operations to be enabled/ disabled * * If set to false all widgets will be disabled, else they will be enabled. * @see #_screenshotEnabled */ void setScreenshotEnabled(bool enabled); }; } // namespace NPlugin #endif // __SCREENSHOTPLUGINCONTAINER_H_2010_08_05 packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotpluginfactory.cpp0000644000000000000000000000145013507430555025715 0ustar // // C++ Implementation: screenshotpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2010 // // Copyright: See COPYING file that comes with this distribution // // #include "screenshotpluginfactory.h" #include "screenshotplugin.h" namespace NPlugin { ScreenshotPluginFactory* ScreenshotPluginFactory::_pInstance = 0; ScreenshotPluginFactory::ScreenshotPluginFactory() { } ScreenshotPluginFactory::~ScreenshotPluginFactory() { } Plugin* ScreenshotPluginFactory::createPlugin(const string& name) const { if (name=="ScreenshotPlugin") { return new ScreenshotPlugin(*_pContainer); } return 0; } ScreenshotPluginFactory* ScreenshotPluginFactory::getInstance() { if (_pInstance == 0) _pInstance = new ScreenshotPluginFactory; return _pInstance; } }; packagesearch-2.7.11build1/src/plugins/screenshotplugin/screenshotpluginfactory.h0000644000000000000000000000224213507430555025362 0ustar // // C++ Interface: screenshotpluginfactory // // Description: // // // Author: Benjamin Mesing , (C) 2010 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGINSCREENSHOTPLUGINFACTORY_H_2010_08_05 #define __NPLUGINSCREENSHOTPLUGINFACTORY_H_2010_08_05 #include namespace NPlugin { class ScreenshotPluginContainer; /** @brief This creates the screenshot plugins. * * * @author Benjamin Mesing */ class ScreenshotPluginFactory : public IPluginFactory { ScreenshotPluginContainer* _pContainer; ScreenshotPluginFactory(); static ScreenshotPluginFactory* _pInstance; public: ~ScreenshotPluginFactory(); void setContainer(ScreenshotPluginContainer* pContainer) { _pContainer = pContainer; }; /** @name IPluginFactory interface */ //@{ /** @brief This creates a plugin for the given name. * * Accepted names are: * \li "ScreenshotPlugin" * * @pre setContainer() must have been called or 0 will be returned. */ virtual Plugin* createPlugin(const string& name) const; //@} static ScreenshotPluginFactory* getInstance(); }; }; #endif // __NPLUGINSCREENSHOTPLUGINFACTORY_H_ packagesearch-2.7.11build1/src/processcontainer.cpp0000644000000000000000000000234713507430555017243 0ustar // // C++ Implementation: processcontainer.cpp // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Tue Jun 14 2005 at 09:09:53 // #include "processcontainer.h" namespace NApplication { bool ProcessContainer::start(QProcess* pProcess, QString command, QStringList arguments) { _mutex.lock(); pProcess->start(command, arguments); bool started = pProcess->waitForStarted(); connect(pProcess, SIGNAL(finished(int)), this, SLOT(onProcessExited())); if (started) { _processes.insert(pProcess); } else { disconnect(pProcess, SIGNAL(finished(int)), this, SLOT(onProcessExited())); } _mutex.unlock(); return started; } void ProcessContainer::onProcessExited() { _mutex.lock(); // Each process not running should be a finished process. for (ProcessContainerType::iterator it = _processes.begin(); it != _processes.end(); ++it) { if ( (*it)->state() == QProcess::NotRunning ) { // call the erase first because emitting processExited might trigger a // re-add of the plugin _processes.erase(it); emit(processExited(*it)); _mutex.unlock(); return; } } _mutex.unlock(); } } // namespace NApplication packagesearch-2.7.11build1/src/processcontainer.h0000644000000000000000000000405713507430555016710 0ustar // // C++ Interface: processcontainer.h // // Author: Benjamin Mesing , (C) %year% // // Copyright: See COPYING file that comes with this distribution // // // This file was generated on Tue Jun 14 2005 at 09:09:53 // #ifndef __NAPPLICATION_PROCESSCONTAINER_H_2005_06_14 #define __NAPPLICATION_PROCESSCONTAINER_H_2005_06_14 #include using namespace std; #include #include namespace NApplication { /** * @brief This class can be used to keep track of different processes running. * * A new process is added with the launch command. As soon as the process terminates it will * be removed from the controlled processes and the processExited(QProcess*) signal will be emitted. */ class ProcessContainer : public QObject { Q_OBJECT typedef set ProcessContainerType; /** @brief The processes controlled by this Container. */ ProcessContainerType _processes; /** @brief Mutex enforce start() and onProcessExited() to be self and mutal exclusive. * * Note that the mutex is recursive. */ QMutex _mutex; public: ProcessContainer() : _mutex(QMutex::Recursive) {} /** * @brief Launches the handed process and adds it to the list of controlled processes. * * If the process could not be launched, it won't be added to the controlled processes. * The process will be removed from the controlled ones, as soon as it exits and the * processExited(QProcess*, int) signal will be emitted. * @returns if the process was launched successfully (timeout value 3000ms) */ bool start(QProcess* pProcess, QString command, QStringList arguments); protected Q_SLOTS: /** @brief Called on the exit of any of the given processes. * * It detemines the process that exited and emits the processExited(QProcess*) signal. */ void onProcessExited(); signals: /** * @brief Emitted whenever a process has exited. * * @param pProcess a pointer to the process that exited */ void processExited(QProcess* pProcess); }; } // namespace NApplication #endif // __NAPPLICATION_PROCESSCONTAINER_H_2005_06_14 packagesearch-2.7.11build1/src/progressdisplaydlg.cpp0000644000000000000000000000157213507430555017602 0ustar // // C++ Implementation: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #include "progressdisplaydlg.h" #include #include #include namespace NUtil { ProgressDisplayDlg::ProgressDisplayDlg(QWidget *parent, const char *name, bool modal) : QProgressDialog(parent), IProgressObserver() { setObjectName(name); setModal(modal); } ProgressDisplayDlg::~ProgressDisplayDlg() { } ///////////////////////////////////////////////////// // IProgressObserver Interface ///////////////////////////////////////////////////// void ProgressDisplayDlg::setAbsoluteProgress(int progress) { setValue(progress); qApp->processEvents(); } void ProgressDisplayDlg::setText(const QString& text) { setLabelText(text); qApp->processEvents(); } }; packagesearch-2.7.11build1/src/progressdisplaydlg.h0000644000000000000000000000164513507430555017250 0ustar // // C++ Interface: %{MODULE} // // Description: // // // Author: %{AUTHOR} <%{EMAIL}>, (C) %{YEAR} // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NUTILPROGRESSDISPLAYDLG_H_2005_03_20 #define __NUTILPROGRESSDISPLAYDLG_H_2005_03_20 #include #include "iprogressobserver.h" namespace NUtil { /** @author Benjamin Mesing */ class ProgressDisplayDlg : public QProgressDialog, public IProgressObserver { Q_OBJECT public: ProgressDisplayDlg(QWidget *parent = 0, const char *name = 0, bool modal = false); virtual ~ProgressDisplayDlg(); /** @name IProgressObserver interface * * These functions implement the IProgressObserver interface. */ //@{ // documented in base class virtual void setAbsoluteProgress(int progress); // documented in base class virtual void setText(const QString& text); //@} }; }; #endif // __NUTILPROGRESSDISPLAYDLG_H_2005_03_20 packagesearch-2.7.11build1/src/replace_in_files.pl0000755000000000000000000000107113507430555016772 0ustar #!/usr/bin/perl -w # this script replaces a regexp by a string sub replaceFunc; replaceFunc(); exit 0; sub replaceFunc { foreach $filename (@ARGV) { print "Processing file $filename\n"; open( FILE, $filename); @lines = ; close( FILE ); `cp $filename $filename.0~`; open(FILE, ">$filename"); # overwrite the exiting file foreach $line (@lines) { $line =~ s/Tagcoll::Tagcoll::/Tagcoll::/g; # $line =~ s/InputMerger/Tagcoll::InputMerger/g; print FILE $line; # print $line; } print "\n--------------\n\n"; } } packagesearch-2.7.11build1/src/runcommand.cpp0000644000000000000000000000076113507430555016023 0ustar // // C++ Implementation: runcommand // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "runcommand.h" namespace NApplication { GainRoot RunCommand::s_gainRoot = SU; RunCommand::RunCommand() { } RunCommand::~RunCommand() { } GainRoot RunCommand::gainRootCommand() { return s_gainRoot; } void RunCommand::setGainRootCommand(GainRoot gainRoot) { s_gainRoot = gainRoot; } }; packagesearch-2.7.11build1/src/runcommand.h0000644000000000000000000000717513507430555015476 0ustar // // C++ Interface: runcommand // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RUNCOMMAND_H_2004_05_12 #define __RUNCOMMAND_H_2004_05_12 #include // NException #include #include "gainroot.h" class QString; namespace NApplication { /** @brief Interface to execute a console application. * * After calling start the object will display the output of the started command to the user * in an independant window. After exiting the signal processExited() will be emitted.\n * The command executed will consist of the list of arguments, where the first * argument is the application itself. Arguments can be added via addArgument(). * @author Benjamin Mesing */ class RunCommand : public QObject { Q_OBJECT /** @brief Holds which tool to use for gaining root priviledges */ static GainRoot s_gainRoot; public: RunCommand(); virtual ~RunCommand(); /** @brief Adds a new argument to the command to be executed. * * The first argument is the command to be executed. */ virtual void addArgument(const QString& arg)=0; /** @brief Execute the command, returning immidiately. * * The application will be launched and processed in the background. The control is * returned immidiately. * @returns if the command could be executed * @throws NException::RuntimeError if the command could not be executed * for any reason */ virtual bool start()=0; /** @brief Execute the command asking for root rights, returning immidiately. * * The application will be launched and processed in the background. The control is * returned immon.hidiately. The user will have to authentificate, * if he is not root already. * @returns if the command could be launched * @throws NException::RuntimeError if the command could not be executed * for any reason */ virtual bool startAsRoot()=0; /** @returns true if the process exited successful, i.e. was not aborted and returned an * exit state of 0. */ virtual bool processExitedSuccessful() const=0; /** @brief Sets the title of the window displaying the command to be executed. * * By default the title is the command to be executed with all its arguments. */ virtual void setTitle(const QString& title)=0; // Docu Taken from QT /** Blocks until the process has finished and the finished() signal has been emitted, * or until msecs milliseconds have passed. * Returns true if the process finished; otherwise returns false (if the operation * timed out or if an error occurred). */ virtual bool waitForFinished(int msecs = 30000 ) = 0; /** @brief Returns true if the process has already finished, else false. */ virtual bool finished() = 0; /** @brief Sets the command to be used to become root. * * Default is su. */ static GainRoot gainRootCommand(); /** @brief Returns the command used to gain root rights. */ static void setGainRootCommand(GainRoot gainRoot); signals: /** @brief Emitted, when the command finished. */ void processExited(); /** This signal will be emitted, when RunCommand class is completly ready, this might happen long after * the processExited signal was emitted (e.g. if the window has to be closed manually).\n * The quit signal is quaranteed to be emitted after the processExited() signal. * @note this signal is delete safe, i.e. you might delete the object as a reaction to it as the * emitting function does not access its members after this. */ void quit(); private: RunCommand(RunCommand& rc); }; }; #endif // __RUNCOMMAND_H_2004_05_12 packagesearch-2.7.11build1/src/runcommandforoutput.cpp0000644000000000000000000000460613507430555020015 0ustar // // C++ Implementation: runcommandforoutput // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include // for usleep #include // for wait #include #include #include #include #include #include "runcommandforoutput.h" using namespace std; namespace NApplication { RunCommandForOutput::RunCommandForOutput(const QString& command) : _command(command) { _finished = false; _pProcess = new QProcess(this); connect(_pProcess, SIGNAL( readyReadStandardOutput()), SLOT(onReadyReadStdout())); connect(_pProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(onProcessExited())); } RunCommandForOutput::~RunCommandForOutput() { // qDebug("Destructing RunCommandForOutput"); delete _pProcess; } void RunCommandForOutput::start() { _pProcess->start(_command, _arguments); } void RunCommandForOutput::addArgument(const QString& arg) { _arguments.push_back(arg); } void RunCommandForOutput::onReadyReadStdout() { while ( _pProcess->canReadLine() ) { _output.push_back(_pProcess->readLine()); } } void RunCommandForOutput::onProcessExited() { while ( _pProcess->canReadLine() ) { _output.push_back(_pProcess->readLine()); } emit (processExited(this)); } bool RunCommandForOutput::normalExit() { return _pProcess->exitStatus() == QProcess::NormalExit; } // Thanks to // for the hint to use popen, it seems QT lacks some functionality here bool RunCommandForOutput::run(const QString& command, size_t maximumLineLength) { QString out; #ifdef __DEBUG QTime t; t.start(); #endif FILE* pipe = popen(command.toLatin1(), "r"); if (maximumLineLength==0) { char c; while( (c = getc(pipe)) != EOF ) { if (c=='\n') { _output.push_back(out); out.truncate(0); } else out += c; } } else { char* chars = new char[maximumLineLength]; // current maximum line while (fgets(chars, maximumLineLength, pipe) != 0) { _output.push_back(chars); _output.last().truncate(_output.last().length()-1); // remove the trailing newline } delete[] chars; } int exitStatus = pclose(pipe); #ifdef __DEBUG qDebug() << "Time elapsed for " << command << ": " << t.elapsed() << " ms"; #endif return exitStatus == 0; } }; packagesearch-2.7.11build1/src/runcommandforoutput.h0000644000000000000000000000535513507430555017464 0ustar // // C++ Interface: runcommandforoutput // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RUNCOMMANDFOROUTPUT_H_2004_07_18 #define __RUNCOMMANDFOROUTPUT_H_2004_07_18 #include #include class QProcess; namespace NApplication { /** @brief This class can be used to run a program where you are interested in its output. * * When the program has finished, a processExited(RunCommandForOutput*) signal will be * emitted. After this the output can be gotten via getOutput(); * * You can also use the run(const QString&, size_t) function which runs synchrone, i.e. * it will run the command and return after it is finished. * @warning every RunCommandForOutput command should used only ones! * @note this class relies on a working event queue, so make sure that * it will be evaluated or the program might never finish... * @author Benjamin Mesing */ class RunCommandForOutput : public QObject { Q_OBJECT QProcess* _pProcess; const QString _command; QStringList _arguments; /** Holds the output generated by the application. * * Each entry in the string list contains a single line. */ QStringList _output; bool _finished; public: /** @param command the command to be executed */ RunCommandForOutput(const QString& command); ~RunCommandForOutput(); void addArgument(const QString& arg); /** Starts the given command. */ void start(); /** @returns a list of all output lines created by the application. */ const QStringList getOutput() const { return _output; } /** @returns a list of all output lines created by the application, the lines are stripped * of the trailing \\n. */ QStringList getOutput() { return _output; }; bool normalExit(); /** @brief Starts the command and blocks until it terminates. * * The output can be fetched with the getOutput() function. This function ignores the command * handed on construction. * * @param command the command that should be executed * @param maximumLineLength hand the maximum length for single line, hand 0 if you * can't make any ensurance about the line length (this will be slower) * @returns if the program exited successfully */ bool run(const QString& command, size_t maximumLineLength=10000); signals: /** This is emitted when the process has finished*/ void processExited(RunCommandForOutput*); private Q_SLOTS: /** @brief Called whenever the process released something to stdout. * * This reads a line and attaches it to output. If a whole line can not * be read it does nothing. */ void onReadyReadStdout(); void onProcessExited(); }; }; #endif // __RUNCOMMANDFOROUTPUT_H_2004_07_18 packagesearch-2.7.11build1/src/runcommandinwindow.cpp0000644000000000000000000001066313507430555017604 0ustar // // C++ Implementation: runcommandinwindow // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifdef __USE_KDE_LIBS #include #include #include #include #include #include "runcommandinwindow.h" using namespace std; namespace NApplication { RunCommandInWindow::RunCommandInWindow(QObject* parent, const char* name) { // _lastLinePar = 0; _pOutput = 0; _pProcess = new QProcess(parent); if (name) _pProcess->setObjectName(name); _pProcess->setReadChannelMode(QProcess::MergedChannels); connect( _pProcess, SIGNAL(readyReadStandardOutput()), SLOT(onReadyReadStdout()) ); // forward signal to outer world connect(_pProcess, SIGNAL(finished(int)), SLOT(onProcessExited())); } RunCommandInWindow::~RunCommandInWindow() { delete _pProcess; delete _pOutput; // should not be neccessary } void RunCommandInWindow::addArgument(const QString& s) { if (_command.isEmpty()) _command = s; else _arguments.push_back(s); } bool RunCommandInWindow::start() { _pOutput = new RunCommandWidget(0, "CommandWindow"); _pOutput->resize(500,400); _pOutput->show(); connect(_pOutput->_pCloseButton, SIGNAL(clicked()), SLOT(onCommandWindowClosed())); connect(_pOutput->_pAbortButton, SIGNAL(clicked()), SLOT(onAbort())); _pProcess->start(_command, _arguments, QIODevice::ReadOnly); // TODO work correct here! return true; } bool RunCommandInWindow::processExitedSuccessful() const { return _pProcess->exitCode() == 0; } // 13 is CR, 10 is LF void RunCommandInWindow::onReadyReadStdout() { QString newString(_pProcess->readAllStandardOutput()); // qDebug("--- begin chunk ---"); // for (int i=0; iappend(" "); _lastLine = ""; } else firstLine = false; if (line.isEmpty()) continue; // find the last position of a carriage return (anything before this is // meaningless as there are no \n mark in) int crPos = line.findRev('\015'); if (crPos == -1) { line.prepend(_lastLine); } else { // take everything after the cr line = line.mid(crPos+1); } _lastLine = line; _pOutput->replaceLastLine(line); } } // void RunCommandInWindow::onReadyReadStderr(KProcess *proc, char *buffer, int buflen) // { // QString newString(buffer); // QStringList lines = QStringList::split(QRegExp("\r?\n\r?"), newString, true); // bool firstLine = true; // for (QStringList::const_iterator it = lines.begin(); it != lines.end(); ++it) // { // QString line = *it; // // only append if this is not the first entry in the splitting // if (!firstLine) // { // // WARNING: don't remove the space here, because QTextBrowser seems not to // // append a line if an empty String is handed! // _pOutput->append(" "); // _lastLine = ""; // } // else // firstLine = false; // if (line.isEmpty()) // continue; // // find the last position of a carriage return (anything before this is // // meaningless as there are no \n mark in) // int crPos = line.findRev('\015'); // if (crPos == -1) // { // line.prepend(_lastLine); // } // else // { // // take everything after the cr // line = line.mid(crPos+1); // } // _lastLine = line; // _pOutput->replaceLastLine(line); // } // } void RunCommandInWindow::onProcessExited() { _pOutput->_pCloseButton->setEnabled(true); _pOutput->_pAbortButton->setEnabled(false); emit processExited(); } void RunCommandInWindow::onCommandWindowClosed() { // deferred deleting as the sender of the close signal _pOutput->deleteLater(); _pOutput=0; emit quit(); } void RunCommandInWindow::onAbort() { if (_pProcess) _pProcess->terminate(); } } // namespace NApplication #endif // __USE_KDE_LIBS packagesearch-2.7.11build1/src/runcommandinwindow.h0000644000000000000000000000333113507430555017243 0ustar // // C++ Interface: runcommandinwindow // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifdef __USE_KDE_LIBS #ifndef __RUNCOMMANDINWINDOW_H_2004_05_07 #define __RUNCOMMANDINWINDOW_H_2004_05_07 #include #include #include #include "runcommand.h" #include "runcommandwidget.h" using namespace std; class QProcess; namespace NApplication { /** @brief This class encapsulates running an external program and displays its output in a textwindow. * * It is similar to a console except yet without input. * * @note This class assumes that only one \\r occurs per input flush. * * * @author Benjamin Mesing */ class RunCommandInWindow : public RunCommand { Q_OBJECT RunCommandWidget* _pOutput; /** The process that will be run. */ QProcess* _pProcess; /** Holds the content of the last line. */ QString _lastLine; QStringList _arguments; QString _command; /** Holds the paragraph number of the last line. */ // int _lastLinePar; private slots: void onProcessExited(); /** This function closes the widget and emits the quit() signal. */ virtual void onCommandWindowClosed(); protected slots: /** Handles new output on the command line. */ virtual void onReadyReadStdout(); /** This is called whenever the user choose to abort the command. */ void onAbort(); public: RunCommandInWindow(QObject* parent=0, const char* name=0); ~RunCommandInWindow(); virtual bool start(); virtual void addArgument(const QString& s); virtual bool processExitedSuccessful() const; }; } // namespace NApplication #endif // __RUNCOMMANDINWINDOW_H_2004_05_07 #endif // __USE_KDE_LIBS packagesearch-2.7.11build1/src/runcommandinxterm.cpp0000644000000000000000000000675513507430555017443 0ustar // // C++ Implementation: runcommandinxterm // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include // for getuid and geteuids #include // #include #include #include // NApplication #include "runcommandinxterm.h" #include "gainroot.h" // NException #include "exception.h" #include namespace NApplication { RunCommandInXterm::RunCommandInXterm() { _pProcess=0; } RunCommandInXterm::~RunCommandInXterm() { delete _pProcess; } void RunCommandInXterm::addArgument(const QString& arg) { _arguments.push_back(arg); } bool RunCommandInXterm::start(bool root) { _pProcess = new QProcess(0); QString argumentString = _arguments.join(" "); QString terminalEmulatorFullPath = "/usr/bin/uxterm"; QFileInfo terminalEmulator(terminalEmulatorFullPath); if (!terminalEmulator.isExecutable()) throw NException::RuntimeException(toString(terminalEmulatorFullPath) + string(" is not executable/available, " "probably there is no teminal emulator installed")); QFileInfo command(_arguments[0]); if (!command.isExecutable()) throw NException::RuntimeException(toString("Program " + command.absoluteFilePath() + " not executable/available")); QStringList arguments; arguments.push_back("-T"); if (_title.isNull()) arguments.push_back(argumentString); else arguments.push_back(_title); arguments.push_back("-e"); // execute using the shell arguments.push_back("/bin/sh"); arguments.push_back("-c"); QString fullArgumentString; fullArgumentString += "("; if (root) { fullArgumentString += "echo \"Please enter root password\" "; switch (gainRootCommand()) { case SU: fullArgumentString += "; " + GainRootPaths::su + " -c "; // for su the command to be executed must be ONE argument and since it // contains spaces it must be quoted fullArgumentString += "\"" + argumentString + "\""; break; // case SUDO: fullArgumentString += "; " + GainRootPaths::sudo + " "; // for sudo, everything following the sudo command is passed to // the target application, so there must be no quoting fullArgumentString += argumentString; break; } } else { fullArgumentString += argumentString; } fullArgumentString += "&& echo \"\nExecution completed successfully!\""; fullArgumentString += ")"; fullArgumentString += "|| ( echo \"\nExecution failed. \" ; read dummy ) "; arguments.push_back(fullArgumentString); // forward the signal connect(_pProcess, SIGNAL(finished(int)), this, SLOT(onProcessExited())); _pProcess->start(terminalEmulator.absoluteFilePath(), arguments); return true; } bool RunCommandInXterm::start() { return start(false); } bool RunCommandInXterm::startAsRoot() { if (geteuid() != 0) return start(true); else return start(false); } void RunCommandInXterm::onProcessExited() { _pProcess->deleteLater(); // delete during the next event loop _pProcess = 0; emit processExited(); emit quit(); } void RunCommandInXterm::setTitle(const QString& title) { _title = title; } bool RunCommandInXterm::waitForFinished(int msecs) { // if the process has finished if (_pProcess == 0) return true; // if the process is still running return _pProcess->waitForFinished(msecs); } bool RunCommandInXterm::finished() { // process is finished, if it is set back to 0 return _pProcess == 0; } }; packagesearch-2.7.11build1/src/runcommandinxterm.h0000644000000000000000000000336613507430555017103 0ustar // // C++ Interface: runcommandinxterm // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RUNCOMMANDINXTERM_H_2004_05_12 #define __RUNCOMMANDINXTERM_H_2004_05_12 #include #include #include "extalgorithm.h" #include "runcommand.h" using namespace std; class QProcess; namespace NApplication { /** This class runs a command in an XTerm. The XTerm is closes as soon as the started program is active. * @author Benjamin Mesing */ class RunCommandInXterm : public RunCommand { Q_OBJECT QStringList _arguments; /** @brief The process currently executed. 0 if no process is currently executed. */ QProcess* _pProcess; /** @brief The title of the window where the output is shown. */ QString _title; private slots: void onProcessExited(); protected: /** @brief This is a helper function implementing start() and startAsRoot() * * It does what is described in either start() or startAsRoot(). * @param root if true, the command will be started as root * @see start(), startAsRoot() */ bool start(bool root); public: RunCommandInXterm(); ~RunCommandInXterm(); virtual void addArgument(const QString& arg); virtual bool start(); virtual bool startAsRoot(); /** @brief This returns always true as I do not see a way to get hold of the exit status using an xterm. */ virtual bool processExitedSuccessful() const { return true; }; virtual void setTitle(const QString& title); /** @see RunCommand::waitForFinished() * @pre a process must be started */ virtual bool waitForFinished(int msecs = 30000 ); virtual bool finished(); }; }; // namespace NApplication #endif // __RUNCOMMANDINXTERM_H_2004_05_12 packagesearch-2.7.11build1/src/runcommandwidget.cpp0000644000000000000000000000176313507430555017232 0ustar // // C++ Implementation: runcommandwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "runcommandwidget.h" RunCommandWidget::RunCommandWidget(QWidget *parent, const char *name) : QDialog(parent) { if (name) setObjectName(name); setupUi(this); } RunCommandWidget::~RunCommandWidget() { } void RunCommandWidget::onClose() { close(); emit quit(); } void RunCommandWidget::replaceLastLine( const QString line ) { // change the last line QString text = _pConsoleOutput->text(); int lastLine = text.lastIndexOf("\n"); if (lastLine != -1) { text.truncate(lastLine+1); text.append(line); } else text = line; _pConsoleOutput->setText(text); /* _pOutput->_pConsoleOutput->removeParagraph(_pOutput->_pConsoleOutput->paragraphs()-1); _pOutput->_pConsoleOutput->append(line);*/ } void RunCommandWidget::append( const QString line ) { _pConsoleOutput->append(line); } packagesearch-2.7.11build1/src/runcommandwidget.h0000644000000000000000000000131313507430555016666 0ustar // // C++ Interface: runcommandwidget // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __RUNCOMMANDWIDGET_H_2005_08_28 #define __RUNCOMMANDWIDGET_H_2005_08_28 #include #include /** @author Benjamin Mesing */ class RunCommandWidget : public QDialog, public Ui::RunCommandWidget { Q_OBJECT public: RunCommandWidget(QWidget *parent = 0, const char *name = 0); ~RunCommandWidget(); void replaceLastLine( const QString line ); void append( const QString line ); public slots: void onClose(); signals: void quit(); }; #endif // __RUNCOMMANDWIDGET_H_2005_08_28 packagesearch-2.7.11build1/src/runcommandwidget.ui0000644000000000000000000000504713507430555017064 0ustar RunCommandWidget 0 0 600 526 RunCommandWidget 10 6 Courier 12 50 false false false false Qt::PlainText Q3TextEdit::NoWrap true 0 6 Abort Qt::Horizontal QSizePolicy::Expanding 330 20 false Close qPixmapFromMimeSource Q3TextEdit
q3textedit.h
0
packagesearch-2.7.11build1/src/scorecalculationstrategybase.cpp0000644000000000000000000000207313507430555021626 0ustar // // C++ Implementation: scorecalculationstrategybase // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include "scorecalculationstrategybase.h" #include namespace NPlugin { ScoreCalculationStrategyBase::ScoreCalculationStrategyBase() : NPlugin::IScoreCalculationStrategy() { } ScoreCalculationStrategyBase::~ScoreCalculationStrategyBase() { } ///////////////////////////////////////////////////// // IScoreCalculationStrategy Interface ///////////////////////////////////////////////////// float ScoreCalculationStrategyBase::getScore(const string& package) const { map::const_iterator it = _packagesToScore.find(package); if (it == _packagesToScore.end()) { qWarning("No scores for package %s", package.c_str()); return 1; } return it->second; } const map& ScoreCalculationStrategyBase::getScore() const { return _packagesToScore; } void ScoreCalculationStrategyBase::clear() { _packagesToScore.clear(); }; } packagesearch-2.7.11build1/src/scorecalculationstrategybase.h0000644000000000000000000000266513507430555021302 0ustar // // C++ Interface: scorecalculationstrategybase // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_SCORECALCULATIONSTRATEGYBASE_H_2005_07_30 #define __NPLUGIN_SCORECALCULATIONSTRATEGYBASE_H_2005_07_30 #include #include using namespace std; namespace NPlugin { /** @brief Provides a base implementation for a ScoreCalculationStrategy. * * In your strategies you only need to implement * IScoreCalculationStrategy::calculateScore(set<int>) when inheriting * this function. There you must call setScore(string, float) for each * of the packages handed. * * @author Benjamin Mesing */ class ScoreCalculationStrategyBase : public IScoreCalculationStrategy { map _packagesToScore; protected: /** @brief Sets the scores for the handed package. */ void setScore(const string package, float score) { _packagesToScore[package] = score; } public: ScoreCalculationStrategyBase(); virtual ~ScoreCalculationStrategyBase(); /** @name IScoreCalculationStrategy interface * * Implementation of the IScoreCalculationStrategy interface */ //@{ virtual float getScore(const string& package) const; virtual const map& getScore() const; virtual void clear(); //@} }; } #endif // __NPLUGIN_SCORECALCULATIONSTRATEGYBASE_H_2005_07_30 packagesearch-2.7.11build1/src/scoredisplayplugin.cpp0000644000000000000000000000772013507430555017602 0ustar // // C++ Implementation: scoredisplayplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include "scoredisplayplugin.h" // NPlugin #include #include #include namespace NPlugin { const QString ScoreDisplayPlugin::PLUGIN_NAME = "ScoreDisplayPlugin"; ScoreDisplayPlugin::ScoreDisplayPlugin() : ShortInformationPlugin(), _title(tr("Score Display Plugin")), _briefDescription(tr("Displays the package scores")), _description(tr("Displays the search scores of the packages returned by the current search.
\n" "The higher the scores, the better the packages matches to the search.")) { } ScoreDisplayPlugin::~ScoreDisplayPlugin() { } ///////////////////////////////////////////////////// // ShortInformationPlugin Interface ///////////////////////////////////////////////////// const QString ScoreDisplayPlugin::shortInformationText(const string& package) { QString scores; ScoreMap::const_iterator it = _packageToScore.find(package); if (it == _packageToScore.end()) throw PackageNotFoundException(package); scores.setNum(it->second, 'g', 3); return scores; } ///////////////////////////////////////////////////// // IPluginUser Interface ///////////////////////////////////////////////////// void ScoreDisplayPlugin::addPlugin(Plugin* pPlugin) { if (dynamic_cast(pPlugin) != 0) { // dynamic cast needed here because of virtual base class _scorePlugins.insert(dynamic_cast(pPlugin)); } } void ScoreDisplayPlugin::removePlugin(Plugin* pPlugin) { if (dynamic_cast(pPlugin) != 0) { // dynamic cast needed here because of virtual base class _scorePlugins.erase(dynamic_cast(pPlugin)); } } ///////////////////////////////////////////////////// // Other functions ///////////////////////////////////////////////////// void ScoreDisplayPlugin::updateScores(const set& packages) { qDebug("Updating scores"); _packageToScore.clear(); ScorePluginContainer activeScorePlugins; for (ScorePluginContainer::const_iterator it = _scorePlugins.begin(); it != _scorePlugins.end(); ++it) if ((*it)->offersScore()) activeScorePlugins.insert(*it); // if no plugins which offer scores are available simply add all package with a score of 1 if (activeScorePlugins.empty()) { for (std::set::iterator it = packages.begin(); it != packages.end(); ++it) _packageToScore.insert(make_pair(*it, 1.0)); } else { // maps the packages to the scores ScoreMap packageScores; // calculate scores for each plugin for (ScorePluginContainer::const_iterator it = activeScorePlugins.begin(); it != activeScorePlugins.end(); ++it) { try { ScoreMap scores = (*it)->getScore(packages); // if this is the first score plugin if (_packageToScore.empty()) swap(_packageToScore, scores); else { // multiply each score in the result scores with those in the packageScores for (ScoreMap::const_iterator jt = scores.begin(); jt != scores.end(); ++jt) { // must not happen, but somehow it does, so let's deal graciously with it if (_packageToScore.find(jt->first) == _packageToScore.end()) { qWarning() << "Found no score for package: %s" << jt->first.c_str(); // each package should return the same map for which score are calculated //assert( _packageToScore.find(jt->first) != _packageToScore.end() ); _packageToScore[jt->first] = jt->second * 0.5; } _packageToScore[jt->first] *= jt->second; } } } catch (std::exception& e) { qWarning() << "Plugin " << (*it)->name() << " failed to calculate scores\n" << "e.what(): " << e.what(); } catch (...) { qWarning() << "Plugin " << (*it)->name() << " failed to calculate scores (unknown exception thrown)"; } } } qDebug("Finished updating scores"); } } packagesearch-2.7.11build1/src/scoredisplayplugin.h0000644000000000000000000000562413507430555017250 0ustar // // C++ Interface: scoredisplayplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGIN_SCOREDISPLAYPLUGIN_H_2005_07_19 #define __NPLUGIN_SCOREDISPLAYPLUGIN_H_2005_07_19 #include #include #include #include // NPlugin #include #include #include #include using namespace std; namespace NPlugin { /** @brief This plugin is used to display the search scores packages in the search result. * * It holds a reference to the PackageSearchImpl and uses the * PackageSearchImpl#getScorePlugins() function. * Though this breaks the clean encapsulation a little, I preferred this to factoring out * this single method to a new interface. * @author Benjamin Mesing */ class ScoreDisplayPlugin : public QObject, public ShortInformationPlugin, public IPluginUser { const QString _title; const QString _briefDescription; const QString _description; typedef map ScoreMap; typedef set ScorePluginContainer; /** The score plugins used to calculate the scores. */ ScorePluginContainer _scorePlugins; /** @brief Maps the package to the scores. */ ScoreMap _packageToScore; public: ScoreDisplayPlugin(); ~ScoreDisplayPlugin(); const static QString PLUGIN_NAME; /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider*) {}; /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return PLUGIN_NAME; } virtual QString title() const { return _title; }; virtual QString briefDescription() const { return _briefDescription; }; virtual QString description() const { return _description; }; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return 0; } virtual const QString shortInformationText(const string& package); /** @brief Returns Score */ virtual QString shortInformationCaption() const { return tr("Score"); }; virtual int preferredColumnWidth() const { return 5; } //@} /** @brief Called whenever the scores of the package have changed. * * @param resultPackages the packages returned by the current search */ void updateScores(const set& resultPackages); /** @name IPluginUser interface */ //@{ /** @brief Tests if the handed plugin is a ScorePlugin and in case adds it to the #_scorePlugins. */ virtual void addPlugin(Plugin* pPlugin); /** @brief Removes the plugin from the #_scorePlugins. * * Does nothing if the plugin is not in. */ virtual void removePlugin(Plugin* pPlugin); }; } #endif // __NPLUGIN_SCOREDISPLAYPLUGIN_H_2005_07_19 packagesearch-2.7.11build1/src/scoreplugin.h0000644000000000000000000000337313507430555015661 0ustar // // C++ Interface: scoreplugin // // Description: // // // Author: Benjamin Mesing , (C) 2005 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NPLUGINSCOREPLUGIN_H_ #define __NPLUGINSCOREPLUGIN_H_ #include #include // NPlugin #include using namespace std; namespace NPlugin { /** @brief Plugin that offers scores for packages. * * The scores calculated can either depend on an active search (e.g. * scores depending on the fulltext search pattern), or can be * totally independent of such data (e.g. popcon scores). * * @author Benjamin Mesing */ class ScorePlugin : virtual public Plugin { public: virtual ~ScorePlugin() {}; /** @brief Returns the score of the handed packages for the currently active search. * * The scores are in [0..1] where 0.0f means the lowest and 1.0f the highest score. * The scores are always calculated for a whole set of packages, because scores * may be relative to each other (i.e. there is no absolute criterion to score package * but we can say that package1 matches better than package2) * * @pre offersScore() == true * @post returnedValue.keys() == packages
* i.e. all the handed packages must be contained in the returned map * @returns a map mapping each package to its scores * @see offersScore() */ virtual map getScore(const set& packages) const = 0; /** @brief Returns if the plugin is currently offering scores. * * This could return false e.g. if scores are only calculated for an active search * (like e.g. a fulltext search), but no search is currently active. * @see getScore() */ virtual bool offersScore() const = 0; }; } #endif // packagesearch-2.7.11build1/src/searchplugin.h0000644000000000000000000000750113507430555016010 0ustar #ifndef __SEARCHPLUGIN_H_2004_06_21 #define __SEARCHPLUGIN_H_2004_06_21 #include #include #include #include #include #include "plugin.h" class QWidget; using namespace std; namespace NPlugin { // Interface SearchPlugin // // /** * TODO: change signal "void searchChanged(NPlugin::SearchPlugin* pPlugin)" to * listener pattern based on function. This way, we can get rid of the QObject * stuff here (which severly breaks design). Instead plugins should themselves * derive from QOBject if desired. */ class SearchPlugin : public QObject, virtual public Plugin { Q_OBJECT public: /** @brief This returns the widget which is used for inputting the information. * * In opposite to shortInputAndFeedbackWidget() this can be used to show * larger widgets. They will be shown in a seperate section so they won't * push the user. * @returns the widget used, 0 if no such widget is offered by this plugin */ virtual QWidget* inputWidget() const = 0; /** @brief This returns the title used for the input widget. */ virtual QString inputWidgetTitle() const = 0; /** @brief Returns the widget to be shown in the easy accesible area of the SearchWindow. * Use this if your widget is really small (perhaps two lineedits) and you consider your * search to be important only. 0 if no such widget exists.
* It can also be the widget used to show the currently active. Such a feedback widget * should only be shown if there is an active search (i.e. isInactive()). You should * really offer such a feedback widget if you do also offer input widgets */ virtual QWidget* shortInputAndFeedbackWidget() const = 0; /** * @brief This clears the currently entered search. * * It sets all widgets to an empty search. The searchChanged signal will not be emitted. */ virtual void clearSearch() = 0; /** @brief @returns if this plugin uses filtering to create its results. * * This means that packges are queried via filterPackage() and processed accordingly. * This is in opposite to the searchResults() funtion. Only one of the techniques can be used. */ virtual bool usesFilterTechnique() const = 0; /** @brief @returns the set of packages which matched the search. * This function must not be used if usesFilterTechnology() returns true. * * @see usesFilterTechnology() */ virtual const std::set& searchResult() const = 0; /** * * @param package package to be checked */ virtual bool filterPackage(const string& package) const = 0; /** * @returns Returns the widget to be shown in the easy accesible area of the SearchWindow. * Use this if your widget is really small (perhaps two lineedits) and you consider * your search to be important only. 0 if no such widget exists.
* It can also be the widget used to show the currently active. Such a feedback widget * should only be shown if there is an active search (i.e. isInactive()). You should * really offer such a feedback widget if you do also offer input widgets * * */ virtual bool isInactive() const = 0; /** @brief Returns the priority of this search plugin. * * Lower values mean that the plugins output will be shown most visible (e.g. on top). */ virtual uint searchPriority() const = 0; signals: /** * The searchChanged signal is emitted whenever the results produced by this * search have changed. The SearchWindow will evaluate the search then. * @param pPlugin the plugin that emitted this signal * @warning always make sure to have a matching signature when matching - remember that * for QT the strings must match not the types (i.e. SLOT(searchChanged(SearchPlugin* pPlugin)) * won't work. */ void searchChanged(NPlugin::SearchPlugin* pPlugin); }; } // namespace NPlugin #endif // __SEARCHPLUGIN_H_2004_06_21 packagesearch-2.7.11build1/src/settingsdlg.cpp0000644000000000000000000000422713507430555016210 0ustar // // C++ Implementation: pluginsettingsdlg // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include #include #include #include #include #include "settingsdlg.h" #include "helpers.h" #include "plugincontainer.h" namespace NPackageSearch { SettingsDlg::SettingsDlg(const NUtil::NetworkSettings& network, QWidget *parent, const char *name) : QDialog(parent) { setObjectName(name); setupUi(this); _pProxyTypeGroup->setId(_pNoProxyButton, NUtil::NetworkSettings::NO_PROXY); _pProxyTypeGroup->setId(_pSystemProxyButton, NUtil::NetworkSettings::SYSTEM_PROXY); _pProxyTypeGroup->setId(_pCustomProxyButton, NUtil::NetworkSettings::CUSTOM_PROXY); switch (network.proxyType()) { case NUtil::NetworkSettings::NO_PROXY: _pNoProxyButton->setChecked(true); break; case NUtil::NetworkSettings::SYSTEM_PROXY: _pSystemProxyButton->setChecked(true); break; case NUtil::NetworkSettings::CUSTOM_PROXY: _pCustomProxyButton->setChecked(true); break; } _pProxyServerName->setText(toQString(network.host())); _pProxyServerPort->setValue(network.port() != -1 ? network.port() : 0); } SettingsDlg::~SettingsDlg() { } void SettingsDlg::addPlugin(NPlugin::PluginContainer* pPluginContainer) { QWidget* pSettingsWidget = pPluginContainer->getSettingsWidget(this); if (pSettingsWidget != 0) { _pSettingsTabWidget->addTab(pSettingsWidget, pPluginContainer->title()); } } void SettingsDlg::on__pProxyServerEnabledCheck_stateChanged(int state) { bool proxyInputEnabled = (state == Qt::Checked); _pProxyProtocolLabel->setEnabled(proxyInputEnabled); _pProxyServerName->setEnabled(proxyInputEnabled); _pProxyServerPort->setEnabled(proxyInputEnabled); } NUtil::NetworkSettings SettingsDlg::networkSettings() { QString serverName = _pProxyServerName->text(); return NUtil::NetworkSettings((NUtil::NetworkSettings::ProxyType) _pProxyTypeGroup->checkedId(), serverName.toStdString(), _pProxyServerPort->value()); } }; packagesearch-2.7.11build1/src/settingsdlg.h0000644000000000000000000000250113507430555015646 0ustar // // C++ Interface: pluginsettingsdlg // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __PLUGINSETTINGSDLG_H_2004_08_31 #define __PLUGINSETTINGSDLG_H_2004_08_31 #include #include #include #include "ui_settingsdlg.h" class QTabWidget; namespace NPlugin { class PluginContainer; } namespace NPackageSearch { /** @brief Class which controls different plugin containers. * * @todo Rename to "SettingsDlg" * @author Benjamin Mesing */ class SettingsDlg : public QDialog, public Ui::SettingsDlg { Q_OBJECT public: /** Initialises the dialog. * * Initially the settings from the proxy are applied. */ SettingsDlg(const NUtil::NetworkSettings& network, QWidget *parent = 0, const char *name = 0); ~SettingsDlg(); /** @brief Adds a plugin to show settings for. */ void addPlugin(NPlugin::PluginContainer* pPluginContainer); /** @brief Applies the proxy settings configured within this GUI to the QNetworkProxy configuration. * * Returns the proxy configured through this dialog. */ NUtil::NetworkSettings networkSettings(); public Q_SLOTS: void on__pProxyServerEnabledCheck_stateChanged(int state); }; }; #endif // __PLUGINSETTINGSDLG_H_2004_08_31 packagesearch-2.7.11build1/src/settingsdlg.ui0000644000000000000000000001633013507430555016041 0ustar SettingsDlg 0 0 394 330 Packagesearch Settings 3 3 0 Main Settings <!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:'Nimbus Sans L'; 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;">The program selected here will be used to execute commands as root when neccessary (e.g. when installing packages). <tt>su</tt> is the default and available on every Debian system.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><tt>sudo</tt> requires the package sudo to be installed. If configured properly, <tt>sudo</tt> might be more convenient, because you need to enter the password only once.</p></body></html> Program used to become root Use "su" to become root su Use "sudo" to become root sudo Network Settings No Proxy Server true _pProxyTypeGroup System Proxy Settings _pProxyTypeGroup Custom Proxy Settings _pProxyTypeGroup false http:// false Proxy server to be used false Proxy Server Port 65535 8080 Qt::Vertical 20 143 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() SettingsDlg accept() 248 254 157 274 buttonBox rejected() SettingsDlg reject() 316 260 286 274 packagesearch-2.7.11build1/src/shortinformationplugin.h0000644000000000000000000000435313507430555020152 0ustar // // C++ Interface: shortinformationplugin // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __SHORTINFORMATIONPLUGIN_H_2004_07_08 #define __SHORTINFORMATIONPLUGIN_H_2004_07_08 #include #include using namespace std; namespace NPlugin { /** @brief This offers short information about packages. * * The type of information offered is shortly described with the shortInformationCaption() * function.\n * Classes which implement this interface should take care, that the shortInformationText(const string&) * function should be as efficient as possible (e.g. using caching of information). * @author Benjamin Mesing */ class ShortInformationPlugin : virtual public Plugin { public: ShortInformationPlugin() {}; virtual ~ShortInformationPlugin() {}; /** * @returns a short information for the package. This will be shown in the listing * of the SearchWindows result view. * @param package the package to show information for */ virtual const QString shortInformationText(const string& package) = 0; /** * @returns the caption for the section off the short information */ virtual QString shortInformationCaption() const = 0; /** @brief Returns the priority of this short information plugin. * * Lower values mean that the plugins output will be shown most visible (e.g. on top). */ virtual uint shortInformationPriority() const = 0; /** @brief Returns the preferred width for the column displaying the short information. * * If nothing is specified -1 will be returned. * @returns the preferred width in number of characters */ virtual int preferredColumnWidth() const { return -1; }; }; /** @brief This function object can be used to compare the caption of ShortInformationPlugin * with QString objects. * * Returns true if they are equal. */ class ShortInformationCaptionEquals { const QString _caption; public: ShortInformationCaptionEquals(const QString caption) : _caption(caption) {} bool operator() (const ShortInformationPlugin* pPlugin) { return pPlugin->shortInformationCaption() == _caption; } }; }; #endif // __SHORTINFORMATIONPLUGIN_H_2004_07_08 packagesearch-2.7.11build1/src/singleton.cpp0000644000000000000000000000044013507430555015654 0ustar // // C++ Implementation: singleton // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include "singleton.h" template Singleton* Singleton::_pInstance = 0; packagesearch-2.7.11build1/src/singleton.h0000644000000000000000000000232113507430555015321 0ustar // // C++ Interface: singleton // // Description: // // // Author: Benjamin Mesing , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __SINGLETON_H_2004_07_03 #define __SINGLETON_H_2004_07_03 /** @brief This class implements the singleton pattern for classes. * * The class to be managed must be handled as template argument. It must offer a * default constructor which is used to create single instance. The Singleton * will be a child class of the managed class. * * @author Benjamin Mesing */ template class Singleton : public Base { static Singleton* _pInstance; public: /** This gets the instance managed by the singleton. */ static Singleton* instance() { if (_pInstance == 0) _pInstance = new Singleton; return _pInstance; } /** This can be used to get the instance managed by the singleton. It assumes the instance * to be allready created * @pre the instance must have been created (i.e. instance must have been called) */ static Singleton* uncheckedInstance() { assert (_pInstance != 0); return _pInstance; } protected: Singleton() {}; }; #endif // __SINGLETON_H_2004_07_03 packagesearch-2.7.11build1/src/src.kdev40000644000000000000000000000006113507430555014673 0ustar [Project] Manager=KDevCustomMakeManager Name=src packagesearch-2.7.11build1/src/xmldata.cpp0000644000000000000000000001755113507430555015317 0ustar // // C++ Implementation: xmldata // // Description: // // // Author: Benjamin Mesing,,, , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #include #include #include #include "xmldata.h" #include "helpers.h" using namespace std; namespace NXml { QDomElement getFirstChild(QDomNode node) { while (!node.isNull()) { if (!node.toElement().isNull()) // if the node is an element return node.toElement(); node = node.nextSibling(); } return node.toElement(); // returns the null element } QDomElement getFirstElement(QDomNode node) { while (!node.isNull()) { if (node.isElement()) // if the node is an element return node.toElement(); node = node.nextSibling(); } return node.toElement(); // returns the null element } QDomElement getNextElement(QDomNode node) { return getFirstElement(node.nextSibling()); } XmlData::XmlData() { } XmlData::XmlData(const QString& name) { _domDocument = QDomDocument(name); _domDocument.appendChild(_domDocument.createElement(name)); } XmlData::XmlData(QDomDocument document) { _domDocument = document; } XmlData::~XmlData() { } bool XmlData::loadFile(const QString& filename) { QFile file(filename); _domDocument = QDomDocument(); if (!_domDocument.setContent(&file, false)) // parse das XML Document { return false; } return true; } QDomElement XmlData::startDocument(const QString& name) { _domDocument = QDomDocument(name); QDomElement root = _domDocument.createElement(name); _domDocument.appendChild(root); return root; } void XmlData::xmlifyString(QString& string) { string.replace('&', "&"); string.replace('<', "<"); string.replace('>', ">"); string.replace('\'', "&apos"); string.replace('\"', """); } void XmlData::xmlifyStringList(QStringList& stringList) { QStringList::iterator end=stringList.end(); for (QStringList::iterator i=stringList.begin(); i!=end; ++i) xmlifyString( *i ); } QDomElement XmlData::addElement(QDomElement parent, const QString& tagName) { QDomElement element = _domDocument.createElement(tagName); parent.appendChild(element); return element; } QDomText XmlData::addText(QDomElement element, QString text) { xmlifyString(text); QDomText textNode = _domDocument.createTextNode(text); element.appendChild(textNode); return textNode; } QDomText XmlData::addText(QDomElement element, const string& text) { QString newText = toQString(text); xmlifyString(newText); QDomText textNode = _domDocument.createTextNode(newText); element.appendChild(textNode); return textNode; } void XmlData::addText(QDomElement element, QString tagName, QStringList text) { for (QStringList::iterator it = text.begin(); it != text.end(); ++it) { QDomElement subElement = addElement(element, tagName); addText(subElement, *it); } } QDomAttr XmlData::addAttribute(QDomElement node, const QString& value, const QString& name ) { QDomAttr attribute = _domDocument.createAttribute(name); QString copyValue(value); xmlifyString(copyValue); attribute.setValue(copyValue); node.setAttributeNode(attribute); return attribute; } QDomAttr XmlData::addAttribute(QDomElement node, const string& value, const QString& name) { return addAttribute(node, toQString(value), name); } QDomAttr XmlData::addAttribute(QDomElement node, uint value, const QString& name) { QString tmp; tmp.setNum(value); return addAttribute(node, tmp, name); } QDomAttr XmlData::addAttribute(QDomElement node, int value, const QString& name) { QString tmp; tmp.setNum(value); return addAttribute(node, tmp, name); } QDomAttr XmlData::addAttribute(QDomElement node, double value, const QString& name) { QString tmp; tmp.setNum(value); return addAttribute(node, tmp, name); } QDomAttr XmlData::addAttribute(QDomElement node, bool value, const QString& name) { return addAttribute(node, (value==false)? 0 : 1, name); } QDomElement XmlData::importNode(QDomElement src, QDomElement dst, bool deep) { QDomElement imported = _domDocument.importNode(src, deep).toElement(); dst.appendChild(imported); return imported; } bool XmlData::skipComments(QDomNode& node) { if (node.nodeType() != QDomNode::CommentNode ) return false; node = node.nextSibling(); while (node.nodeType() == QDomNode::CommentNode) // skip the comments node = node.nextSibling(); return true; } bool XmlData::writeFile(const QString& filename) const { ofstream out(filename.toLatin1(), ios::out); if (!out.good()) out.close(); if (!out.is_open()) { QString errorMsg(filename); errorMsg="Couldn't open file "+errorMsg; return false; } out << toString(_domDocument.toString()); out.close(); return true; } ///////////////////////////////////////////////////// // getAttribute functions ///////////////////////////////////////////////////// bool getAttribute(QDomElement element, QString& loadInto, const QString& name, QString def) { const QDomAttr attribute = element.attributeNode(name); if (attribute.isNull()) { loadInto=def; #ifdef DEBUG cout << "Attribute "< 255) success = false; loadInto = uchar(tmp); // 0 becomes false everything else true if (!success) loadInto = def; return success; } QStringList getTextList(QDomElement element) { QStringList result; QDomElement child = getFirstElement(element.firstChild()); while (!child.isNull()) { QDomText text = child.firstChild().toText(); // if the first child was a text node if (!text.isNull()) { result.push_back(text.nodeValue()); } child = getNextElement(child); } return result; } } // NXml packagesearch-2.7.11build1/src/xmldata.h0000644000000000000000000002404713507430555014762 0ustar // // C++ Interface: xmldata // // Description: // // // Author: Benjamin Mesing,,, , (C) 2004 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __XMLDATA_H_2004_01_22 #define __XMLDATA_H_2004_01_22 #include #include #include #include #include #include namespace NXml { using namespace std; /** @brief This class manages an QDomTree. * * @author Benjamin Mesing */ class XmlData { protected: /** hier wird das geladene XML Document gehalten, QDomDocument Objecte sind auch * auch nach dem Ladevorgang weiterhin mit der zugehrigen XMLDatei verknpft (siehe * DOM Documentation) */ QDomDocument _domDocument; public: /** Default constructor. Make sure to call either startDocument() or loadFile() before trying * to do anything with the class. */ XmlData(); /** @brief Create a document with the name "name" and a root tag with the same name. */ XmlData(const QString& name); /** Creates a XmlData instance for an existing document. */ XmlData(QDomDocument document); virtual ~XmlData(); /** Sets node to be the next sibling which is not a comment. If node is not a comment it * will not be changed. * @returns if the given node was a comment. */ static bool skipComments(QDomNode& node); /** Loads an XML file and fills the QDomTree with it. * @returns true on success, false on fail (file could not be read or was syntactically incorrect */ bool loadFile(const QString& filename); /** Starts a new DomTree. This will be a blank one, except for the root element * which does also have the handed name. If the DomTree was filled before it will be emptied. * @param name first element in the DomTree. */ QDomElement startDocument(const QString& name); /** @brief Returns a reference to the document used. */ const QDomDocument document() const { return _domDocument; } /** Writes the content of the QDomTree to a file. */ bool writeFile(const QString& filename) const; /** @brief Adds an element into the QDomTree. * * The element is filled with a text section containing the text from writeFrom. * @param parent node under which to add the new element * @param tagName name of the element (tagname) * @returns the Element created */ QDomElement addElement(QDomElement parent, const QString& tagName); /** @brief Adds the given text to the element. * * @returns the QDomText node created. */ QDomText addText(QDomElement element, QString text); /** @brief Adds the given QStringList as text nodes inside a number of nodes * of the name tagName beneath element. * * @param element the element where to add the new nodes * @param tagName the name of the nodes to be created * @param text the text to be added inside the created nodes * * Example:
* Consider the structure: * @verbatim * * * @endverbatim * inside XmlData data with a QElement myElements referring * to myElements in the XML structure. Now running * @code * QStringList elements; * elments.push_back("el1"); * elments.push_back("el2"); * data.addText(myElement, "element", elements); * @endcode * results in the structure: * @verbatim * * el1 * el2 * * @endverbatim */ void addText(QDomElement element, QString tagName, QStringList text); /** Adds the given text to the element. * * @returns the QDomText node created. */ QDomText addText(QDomElement element, const string& text); /** Adds an Attribute to the given Element. * @param node where to add the element. * @param value for the attribute * @param name of the attribute * @returns the attribute that was created */ QDomAttr addAttribute(QDomElement node, const QString& value, const QString& name); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function.\n * Adds a double attribute. */ QDomAttr addAttribute(QDomElement node, const string& value, const QString& name); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function.\n * Adds a double attribute. */ QDomAttr addAttribute(QDomElement node, double value, const QString& name); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Adds an uint attribute. */ QDomAttr addAttribute(QDomElement node, uint value, const QString& name); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Adds an int attribute. */ QDomAttr addAttribute(QDomElement node, int value, const QString& name); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Adds a bool attribute. It will be represented as either 0 or 1.*/ QDomAttr addAttribute(QDomElement node, bool value, const QString& name); /** @brief Imports a node from another document into this XML structure. * * Imports the node src from its document and inserts it as child of * dst. * @param src the node to be imported * @param dst the node where to add src * @param deep if the whole subtree beneath src should be imported * @returns the new node created */ QDomElement importNode(QDomElement src, QDomElement dst, bool deep); /** @returns the root element (QDomDocument::documentElement() in QT) */ QDomElement root() { return _domDocument.documentElement(); }; /** Macht einen String XML Konform, das heit ersetzt die nicht zulssigen Sonderzeichen * durch ihre XML Notation (z.B. > wird zu \>); */ static void xmlifyString(QString& string); /** Added for your convenience. * @see xmlifyString(), aber fr Stringlist */ static void xmlifyStringList(QStringList& stringList); }; /** @brief Find the first element which is sibling to the given node or the node itself. * * Starting with the given node this searches through * all sibling following siblings for the first node which is an element * skipping comments and everything else which is not a element. * @returns the first element, or null if there is no element or if node is null */ QDomElement getFirstElement(QDomNode node); /** @brief Find the next sibling of this node which is an element. * * This does the same as getFirstElement() but starts searching at * the next sibling instead of itself. * @returns the first element, */ QDomElement getNextElement(QDomNode node); /** @brief This loads an attribute from node into the loadInto value. * * This function fills loadInto with the value of the attribute "name" of the element * node. If the attrbute was not existent loadInto will be set to the default value.\n * If node is a comment the function will search for the next sibling which is not * a comment.\n * If the given node is not an element (or the one after the comment), false will be * returned. * @param element the node to be read. It should be either an element or a comment * @param loadInto the string that will be filled with the value. * @param name the name of the attribute. * @param def the default value, to be used if the loading failed * @pre node.toElement() != 0 * @returns if the attribute was specified and loaded correctly */ bool getAttribute(QDomElement element, QString& loadInto, const QString& name, QString def=""); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads a string attribute. */ bool getAttribute(QDomElement element, string& loadInto, const QString& name, string def=""); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads a double attribute. */ bool getAttribute(QDomElement element, double& loadInto, const QString& name, double def=0); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads a float attribute. */ bool getAttribute(QDomElement element, float& loadInto, const QString& name, float=0); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads an uint attribute. */ bool getAttribute(QDomElement element, uint& loadInto, const QString& name, uint=0); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads an int attribute. */ bool getAttribute(QDomElement element, int& loadInto, const QString& name, int=0); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads an uchar attribute. It must be saved as 0 or 1. */ bool getAttribute(QDomElement element, uchar& loadInto, const QString& name, uchar=0); /** This is an overloaded member function, provided for convenience. * It behaves essentially like the above function. \n * Loads an int attribute. */ bool getAttribute(QDomElement element, bool& loadInto, const QString& name, bool=false); /** @brief This reads a number of text nodes inside the nodes beneath element. * * @param element the element beneath were the nodes are located * @returns a list of all the texts found * * Example:
* Consider the structure: * @verbatim * * el1 * el2 * * @endverbatim * with a QElement myElements referring * to myElements in the XML structure. Now running * @code * QStringList strings = getTextList(myElements); * @endcode * results in strings containing el1 and el2. * @note that all nodes beneath element must have a text node as first child * @see XmlData::addText(QDomElement, QString, QStringList) */ QStringList getTextList(QDomElement element); } // namespace NXml #endif // __XMLDATA_H_2004_01_22 packagesearch-2.7.11build1/tags_branches0000644000000000000000000000173613507430555015116 0ustar Tag v0-0-2 release of version 0.0.2 Branch v0-1 We have a running version here. The PackageSearch Dialog is subclassed and the implications are currently commented out. The Dialog is quite slow as it still uses the TagFilter. Away from this it works fine. Description, apt-search, related-search is not yet implemented T beforePluginStructure T v0-3 release version 0.3 T v0-4 release version 0.4 after update to new libtagcoll (using Tag and Facet class) T v0-5 release version 0.5 using dynamic plugin structure T v1_0 release version 1.0 some ui improvements T before_stack_reduction (tagged only src/) before changing the infrastructure to use more heap memory instead of the stack T v1-1 release version 1.1 new apt plugin backend T v1-2 release version 1.2 T v1-3 release version 1.3 T libapt-front first conversion to libapt-front (only the debtags plugin uses its data) T v2-0-2 release version 2.0.2 debtags plugin is based on libapt-front now T v2-0-4 release version 2.0.4packagesearch-2.7.11build1/test-src/0000755000000000000000000000000013507430555014125 5ustar packagesearch-2.7.11build1/test-src/actionpluginmockup.cpp0000644000000000000000000000073513507430555020551 0ustar // // C++ Implementation: actionpluginmockup // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "actionpluginmockup.h" namespace NTest { ActionPluginMockup::ActionPluginMockup() : NPlugin::ActionPlugin() { } ActionPluginMockup::~ActionPluginMockup() { } vector ActionPluginMockup::actions() const { vector actions; return actions; } } packagesearch-2.7.11build1/test-src/actionpluginmockup.h0000644000000000000000000000244713507430555020220 0ustar // // C++ Interface: actionpluginmockup // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTEST_ACTIONPLUGINMOCKUP_H_2008_09_12 #define __NTEST_ACTIONPLUGINMOCKUP_H_2008_09_12 #include namespace NPlugin { class IProvider; } using namespace NPlugin; namespace NTest { /** @author Benjamin Mesing */ class ActionPluginMockup : public NPlugin::ActionPlugin { public: ActionPluginMockup(); ~ActionPluginMockup(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* /*pProvider*/) {}; /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return "ActionPluginMockup"; } virtual QString title() const { return "Action Plugin Mockup"; }; virtual QString briefDescription() const { return "Action Plugin Mockup for Testing"; }; virtual QString description() const { return "Action Plugin Mockup for Testing"; }; //@} /** @name ActionPlugin Interface * * Implementation of the ActionPlugin Interface. */ //@{ virtual vector actions() const; //@} }; } #endif packagesearch-2.7.11build1/test-src/applicationfactory-test.cpp0000644000000000000000000000221013507430555021474 0ustar // // C++ Implementation: applicationfactory-test // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifdef __UNIT_TEST_PP #include #include "applicationfactory.h" #include "runcommand.h" using namespace NApplication; SUITE(ApplicationFactory_Test) { // Equivalence classes: // GI1 getInstance() without it being called before // GI2 getInstance() after it was called before // SI1 setInstance() // GR getRunCommand TEST(getInstance) { // GI1 ApplicationFactory* pFac1 = ApplicationFactory::getInstance(); CHECK(pFac1 != 0); // GR pFac1->getRunCommand("test"); // everything should be fine here // GI2 ApplicationFactory* pFac2 = ApplicationFactory::getInstance(); CHECK_EQUAL(pFac1, pFac2); } // TEST(setInstance) // { // untested // } TEST(getRunCommand) { ApplicationFactory* pFac1 = ApplicationFactory::getInstance(); // GR RunCommand* pR = pFac1->getRunCommand("test"); // everything should be fine here CHECK(pR != 0); // cleanup delete pR; } } #endif // __UNIT_TEST_PP packagesearch-2.7.11build1/test-src/helpers-test.cpp0000644000000000000000000000337413507430555017257 0ustar /** Tests for functions in helpers.h */ #include #include using namespace std; #ifdef __QT_TEST #include class HelpersTest: public QObject { Q_OBJECT private slots: void testMakeLower() { string myString = "aBC"; string& result = makeLower(myString); QCOMPARE(myString, string("abc")); // result and myString should point to the same object QCOMPARE(&result, &myString); // test German umlauts myString = "ÜÖÄ"; string result1 = makeLower(myString); QCOMPARE(myString, string("ÜÖÄ")); } void testToLower() { string myString = "aBC"; string result = toLower(myString); QCOMPARE(result, string("abc")); // no side effects expected QCOMPARE(myString, string("aBC")); // result and myString should not point to the same object QVERIFY(&result != &myString); } }; QTEST_MAIN(HelpersTest) #include "helpers-test.moc" #endif // __QT_TEST #ifdef __UNIT_TEST_PP #include #include #include using namespace std; // std::string& makeLower(std::string& trans) TEST(makeLower) { string myString = "aBC"; string& result = makeLower(myString); CHECK_EQUAL(myString, string("abc")); // result and myString should point to the same object CHECK_EQUAL(&result, &myString); // test German umlauts // myString = "ÜÖÄ"; // string result1 = makeLower(myString); // QCOMPARE(myString, string("ÜÖÄ")); } // inline std::string toLower(const std::string& in) TEST(toLower) { string myString = "aBC"; string result = toLower(myString); CHECK_EQUAL(result, string("abc")); // no side effects expected CHECK_EQUAL(myString, string("aBC")); // result and myString should not point to the same object CHECK(&result != &myString); } #endif // __UNIT_TEST_PP packagesearch-2.7.11build1/test-src/history-test.cpp0000644000000000000000000000426613507430555017317 0ustar // // C++ Implementation: history-test // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifdef __UNIT_TEST_PP #include #include #include #include "history.h" using namespace std; SUITE(History) { // Equivalence classes // "History()" // Hi // "append(T)" // Ap1 empty, Ap2 not_empty // Ap3 current is invalid, Ap4 current is not the last element, Ap5 current is the last element // "empty()" // Em1 empty, Em2 not empty // "const T& current()" // Cu // "const T& back()" // Ba1 last element is current, Ba2 middle element is current // "const T& forward()" // Fo1 first element is current, Fo2 middle element is current // "const T& backPossible()" // Bp1 first element is current, Bp2 middle element is current, Bp3 last element is current // Bp4 empty // "const T& forwardPossible()" // Fp1 first element is current, Fp2 middle element is current, Fp3 last element is current // Fp4 empty // "clear()" // Cl1 empty, Cl2 not empty TEST(History_append) { // Hi NBrowser::History h; // Em1 CHECK(h.empty()); // Fp4 CHECK(!h.forwardPossible()); // Bp4 CHECK(!h.backPossible()); // Cl1 h.clear(); CHECK(h.empty()); // Ap1, Ap3 h.append("first"); // Em2 CHECK(!h.empty()); // Cu CHECK_EQUAL(h.current(), "first"); // Ap2, Ap5 h.append("second"); CHECK_EQUAL(h.current(), "second"); // Bp3 CHECK( h.backPossible()); // Fp3 CHECK(!h.forwardPossible()); // go back one entry // Ba1 CHECK_EQUAL(h.back(), "first"); // Bp1 CHECK(!h.backPossible()); // Fp1 CHECK(h.forwardPossible()); // Fo1 CHECK_EQUAL(h.forward(), "second"); h.append("third"); h.back(); // second is current // Bp2 CHECK(h.backPossible()); // Fp2 CHECK(h.forwardPossible()); // Ba2 CHECK_EQUAL(h.back(), "first"); h.forward(); // second // Fo2 CHECK_EQUAL(h.forward(), "third"); h.back(); // second // Ap4 h.append("fourth"); CHECK(!h.forwardPossible()); CHECK( h.backPossible()); CHECK_EQUAL(h.back(), "second"); // Cl2 h.clear(); CHECK(h.empty()); } } #endif // UNITTEST_PP packagesearch-2.7.11build1/test-src/informationpluginmockup.cpp0000644000000000000000000000100213507430555021605 0ustar // // C++ Implementation: informationpluginmockup // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include "informationpluginmockup.h" namespace NTest { InformationPluginMockup::InformationPluginMockup() : NPlugin::InformationPlugin(), NPlugin::ShortInformationPlugin(), _shortInformationPriority(0), _shortInformationCaption("Caption") { } InformationPluginMockup::~InformationPluginMockup() { } } packagesearch-2.7.11build1/test-src/informationpluginmockup.h0000644000000000000000000000602613507430555021265 0ustar // // C++ Interface: informationpluginmockup // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifndef __NTEST_INFORMATIONPLUGINMOCKUP_H_20080912 #define __NTEST_INFORMATIONPLUGINMOCKUP_H_20080912 #include #include #include #include namespace NPlugin { class IProvider; } namespace NTest { using namespace NPlugin; /** @author Benjamin Mesing */ class InformationPluginMockup : public QObject, public NPlugin::InformationPlugin, public NPlugin::ShortInformationPlugin { int _shortInformationPriority; QString _shortInformationCaption; public: InformationPluginMockup(); ~InformationPluginMockup(); /** @name Plugin Interface * * Implementation of the PluginInterface */ //@{ virtual void init(IProvider* /*pProvider*/) {}; /// @todo not yet implemented virtual void setEnabled(bool) {}; /// @todo not yet implemented virtual void setVisible(bool) {}; virtual QString name() const { return "InformationPluginMockup"; } /** @returns "PackageDescriptionPlugin" */ virtual QString title() const { return tr("InformationPluginMockup"); }; /// @todo to be implemented virtual QString briefDescription() const { return ""; }; /// @todo to be implemented virtual QString description() const { return ""; }; //@} /** @name InformationPlugin interface * * Implementation of the InformationPlugin interface */ //@{ virtual uint informationPriority() const { return 0; } /** @returns a widget which shows a description of this package. */ virtual QWidget* informationWidget() const { return 0; }; /** @returns "Description" */ virtual QString informationWidgetTitle() const { return "InformationPluginMockup"; }; virtual void updateInformationWidget(const string& /*package*/) {}; virtual void clearInformationWidget() {}; /** This plugin offers an information text. */ virtual bool offersInformationText() const { return false; }; virtual QString informationText (const string& package) { return toQString(package); }; //@} /** @name ShortInformationPlugin interface * * Implementation of the ShortInformationPlugin interface */ //@{ virtual uint shortInformationPriority() const { return _shortInformationPriority; }; /** This returns a short description about the package. * @param packageID a handle of the package to show information for */ virtual const QString shortInformationText(const string& package) { return toQString(package); }; /** The caption for the short information is Description. */ virtual QString shortInformationCaption() const { return _shortInformationCaption; }; // documented in base class virtual int preferredColumnWidth() const { return 10; } //@} void setShortInformationPriority(int priority) { _shortInformationPriority=priority; }; void setShortInformationCaption ( const QString& theValue ) { _shortInformationCaption = theValue; } }; } #endif packagesearch-2.7.11build1/test-src/main-test.cpp0000644000000000000000000000031513507430555016531 0ustar #ifdef __UNIT_TEST_PP #include #include int main(int argc, char* argv[]) { QApplication app(argc, argv); return UnitTest::RunAllTests(); // return app.exec(); } #endifpackagesearch-2.7.11build1/test-src/networksettings-test.cpp0000644000000000000000000000334713507430555021067 0ustar /** Tests for functions in networksettings.h */ #include #include #include using namespace std; #ifdef __UNIT_TEST_PP #include #include #include using namespace std; using namespace NUtil; void helper_setProxyEnv() { setenv("http_proxy", "http://localhost:8080", 1); } void helper_validateProxyEnv(const NetworkSettings& settings, NetworkSettings::ProxyType type, string host="", int port=-1, bool useProxy=false) { CHECK_EQUAL(host, settings.host()); CHECK_EQUAL(port, settings.port()); CHECK_EQUAL(type, settings.proxyType()); CHECK_EQUAL(useProxy, settings.useProxy()); } SUITE(NetworkSettings_Test) { TEST(ctorEmpty) { NetworkSettings settings; helper_validateProxyEnv(settings, NetworkSettings::NO_PROXY, "", -1); } TEST(ctor2) { NetworkSettings settings(NetworkSettings::NO_PROXY, "my_proxy", 80); helper_validateProxyEnv(settings, NetworkSettings::NO_PROXY, "my_proxy", 80, false); } TEST(ctor3) { NetworkSettings settings(NetworkSettings::CUSTOM_PROXY, "my_proxy", 80); helper_validateProxyEnv(settings, NetworkSettings::CUSTOM_PROXY, "my_proxy", 80, true); } TEST(ctor4) { helper_setProxyEnv(); // system proxy -> host and port NetworkSettings settings(NetworkSettings::SYSTEM_PROXY, "my_proxy", 0); helper_validateProxyEnv(settings, NetworkSettings::SYSTEM_PROXY, "localhost", 8080, true); } TEST(ctor5) { unsetenv("http_proxy"); // system proxy not set -> host and port should be stored as handed NetworkSettings settings(NetworkSettings::SYSTEM_PROXY, "my_proxy", 80); helper_validateProxyEnv(settings, NetworkSettings::SYSTEM_PROXY, "my_proxy", 80, false); } } // SUITE #endif // __UNIT_TEST_PP packagesearch-2.7.11build1/test-src/packagedisplaywidget-test.cpp0000644000000000000000000001132713507430555021777 0ustar // // C++ Implementation: packagedisplaywidget-test // // Description: // // // Author: Benjamin Mesing , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #ifdef __UNIT_TEST_PP #include #include #include #include "packagedisplaywidget.h" #include "informationpluginmockup.h" using namespace NPackageSearch; struct TheDialog { TheDialog() : argc(0), widget(*(new PackageDisplayWidget())) { } ~TheDialog() { /* some teardown */ } int argc; PackageDisplayWidget& widget; }; SUITE(PackageDisplayWidget_Test) { TEST_FIXTURE(TheDialog, ctor) { CHECK_EQUAL(0, widget.rowCount()); CHECK_EQUAL(0, widget.columnCount()); CHECK(widget.selectedPackage().isNull()); CHECK(!widget.scoreColumnVisible()); } // Equivalence classes SP-setPackages(): // SP1 empty package list (empty/uninitialised list before) // SP2 one package in list // SP3 multiple packages in list // SP4 empty package list (non-empty list before) // SP5 modifying package list after calling setPackages (should have no effect) TEST_FIXTURE(TheDialog, setPackages) { set packages; widget.setPackages(packages); CHECK_EQUAL((long) packages.size(), widget.rowCount()); // SP1 packages.insert("packagesearch"); widget.setPackages(packages); CHECK_EQUAL((long) packages.size(), widget.rowCount()); // SP2 packages.insert("apt"); packages.insert("libept"); widget.setPackages(packages); CHECK_EQUAL((long) packages.size(), widget.rowCount()); // SP3 long listSize = packages.size(); packages.clear(); CHECK_EQUAL(listSize, widget.rowCount()); // SP5 widget.setPackages(set()); CHECK_EQUAL(0, widget.rowCount()); // SP4 } // Equivalence classes AP-addPackages(): // xAP1 no short information plugin before // xAP2 one or more information plugin before // xAP3 short information plugin // AP4 no short information plugin // xAP5 plugin has valid shortInformationCaption // (untested) AP6 plugin has invalid shortInformationCaption // Not tested/specified: adding the same plugin twice or more // Column ordering // AP10 two plugins have the same priority // xAP11 added plugin has higher priority value than a plugin already added // xAP12 added plugin has lower priority value than a plugin already added // xAP13 added plugin has higher priority value than multiple plugins already added // xAP14 added plugin has lower priority value than multiple plugins already added // xAP15 plugin has highest priority value // xAP16 plugin has lowest priority value TEST_FIXTURE(TheDialog, addPlugin) { // DEBUG Begin // QMainWindow& wnd = *(new QMainWindow()); // wnd.setCentralWidget(&widget); // wnd.show(); // DEBUG End QHeaderView* pHeader = widget.horizontalHeader(); // default priority 0 NTest::InformationPluginMockup plugin1; plugin1.setShortInformationPriority(10); plugin1.setShortInformationCaption("Plugin1"); widget.addPlugin(&plugin1); // AP1, AP3, AP5 CHECK_EQUAL(1, widget.columnCount()); CHECK_EQUAL(plugin1.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(0))->text()); NTest::InformationPluginMockup plugin2; plugin2.setShortInformationPriority(5); plugin2.setShortInformationCaption("Plugin2"); widget.addPlugin(&plugin2); // AP2, AP12, AP16 CHECK_EQUAL(2, widget.columnCount()); CHECK_EQUAL(plugin2.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(0))->text()); CHECK_EQUAL(plugin1.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(1))->text()); NTest::InformationPluginMockup plugin3; plugin3.setShortInformationPriority(15); plugin3.setShortInformationCaption("Plugin3"); widget.addPlugin(&plugin3); // AP11, AP13, AP15 CHECK_EQUAL(plugin2.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(0))->text()); CHECK_EQUAL(plugin1.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(1))->text()); CHECK_EQUAL(plugin3.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(2))->text()); NTest::InformationPluginMockup plugin4; plugin4.setShortInformationPriority(3); plugin4.setShortInformationCaption("Plugin4"); widget.addPlugin(&plugin4); // AP14 CHECK_EQUAL(plugin4.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(0))->text()); CHECK_EQUAL(plugin2.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(1))->text()); CHECK_EQUAL(plugin1.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(2))->text()); CHECK_EQUAL(plugin3.shortInformationCaption(), widget.horizontalHeaderItem(pHeader->logicalIndex(3))->text()); } } #endif // __UNIT_TEST_PP packagesearch-2.7.11build1/test-src/packagesearch-test.pro0000644000000000000000000000164613507430555020414 0ustar # File generated by kdevelop's qmake manager. # ------------------------------------------- # Subdir relative project main directory: . # Target is an application: TEMPLATE = app CONFIG += warn_on \ qt \ thread \ stl \ link_pkgconfig \ qtestlib INCLUDEPATH += ./ ../src QT += xml network debug { message("generating debug version") OBJECTS_DIR = .obj_debug DEFINES += __DEBUG CONFIG -= release } else { message("generating release version") OBJECTS_DIR = .obj } SOURCES += helpers-test.cpp \ main-test.cpp \ history-test.cpp \ applicationfactory-test.cpp \ packagedisplaywidget-test.cpp \ actionpluginmockup.cpp \ informationpluginmockup.cpp \ networksettings-test.cpp TARGET = run-tests # use unit test ++ DEFINES += __UNIT_TEST_PP PKGCONFIG += unittest++ QMAKE_CXXFLAGS += -std=c++0x LIBS += -L../src \ -lpackagesearch HEADERS += actionpluginmockup.h \ informationpluginmockup.h packagesearch-2.7.11build1/test-src/run-tests.sh0000755000000000000000000000010513507430555016424 0ustar #!/bin/sh export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../src ./run-tests packagesearch-2.7.11build1/test-src/test-src.kdev40000644000000000000000000000006613507430555016632 0ustar [Project] Manager=KDevCustomMakeManager Name=test-src packagesearch-2.7.11build1/translations/0000755000000000000000000000000013507430555015102 5ustar packagesearch-2.7.11build1/translations/aptplugin_de.ts0000644000000000000000000006435713507430555020144 0ustar AptSearchPluginShortInputWidget Form1 Search for pattern Nach Zeichenkette suchen Search the package database for the given expression Durchsucht die Paketdatenbank nach dem angegebenen Ausdruck Clear Löschen Search case sensitive Groß-/Kleinschreibung beachten Case Sensitive Groß-/Kleinschreibung Search the package descriptions Paketbeschreibungen mit durchsuchen Search Descriptions Beschreibungen durchsuchen Search only full words matching the search patterns Nur ganze Wörter suchen die dem Suchausdruck entsprechen, keine Teilausdrücke When searching only full word matches of the pattern will be considered a match, i.e. if a part of a word matches the pattern it will not be considered a match. Every non-alphanumeric character is considerd to be a word boundary. Es wird nur nach ganzen Wörtern gesucht, die dem Suchausdruck entsprechen. Jedes nicht-alphanumerische Zeichen wird dabei als Wortgrenze betrachtet. Whole Words Only Ganze Wörter This searches the package names and descriptions for the given pattern. If you enter more than one word all words must be contained.<br> You can search for phrases by using double quotes around the phrase. To enter patterns or phrases which should not appear in the package precede them with a minus ('-'). Die Paketnamen und -beschreibungen werden nach der eingegebenen Zeichenkette durchsucht. Wird mehr als ein Wort angeben, so müssen alle Wörter gefunden werden.<br> Nach Wortgruppen kann gesucht werden, indem diese in Anführungsstriche gesetzt werden. Um eine unerwünschte Zeichenkette einzugeben kann ein Minuszeichen '-' vorangestellt werden. Check this if you want to search in the package descriptions. The search will search the package name, the long description and the short description.<br />If not checked only the package names will be searched. Wenn dieses Kästchen aktiviert ist, werden die Paketbeschreibungen mit durchsucht. Die Suche sucht dann in dem Namen, der ausführlichen und der Kurzbeschreibung. Ansonsten werden nur die Paketnamen durchsucht. AptSettingsWidget Form The selected tool will be used to install/remove the selected packages Das ausgewählte Programm wird zu Installation/Deinstallation von Paketen verwendet For package installation Debian Package Search relies on an external program. You can select wether to use apt or aptitude here. Zur Installation/Deinstallation von Paketen verwendet die Debian Paketsuche ein externes Programm. Hier kann eingestellt werden welches Programm verwendet werden soll. Package Administration Tool Programm zur Paketverwaltung apt-get aptitude InstalledFilterWidget Form1 Installed Filter Installationsstatus Search packages by installed state Pakete anhand ihres Installationsstatuses suchen Search packages by installed state. Pakete anhand ihres Installationsstatuses suchen. All Alle Installed Installiert Upgradable Aktualisierbar Not Installed Nicht Installiert NPlugin::AptActionPlugin Update Apt-Package Database Apt-Paketdatenbank aktualisieren Calls "apt-get update" updating the package database Ruft "apt-get update" bzw. "aptitude update" zum aktualisieren der Paketdatenbank auf Updates the package database Paketdatenbank aktualisieren Reloads the package database from disk (e.g. if apt-get update was performed externally). Aktualisiert die Paketinformationen von der Festplatte (z.B. wenn "aptitude update" extern aufgerufen wurde). Copy Command Line for Installing Package to Clipboard Kommandozeile zur Paketinstallation in Zwischenablage kopieren Creates a command line to install the selected package, and copies it to the clipboard Erzeugt Kommandozeile zur Installation des Paketes und kopiert diese in die Zwischenablage Install/Update Package Paket Installieren/Aktualisieren Installs/updates the package Installiert/aktualisiert das Paket Remove Package Paket entfernen Removes the package Entfernt das Paket Purge Package Paket restlos entfernen Removes package including configuration Entfernt Paket inklusive der Konfigurationsdateien Unable to launch command Konnte Programm nicht starten NPlugin::AptPluginContainer Command not executed Programm nicht ausgeführt For an unknwon reason, the command could not be executed. Aufgrund eines unbekannten Fehlers konnte das Programm nicht ausgeführt werden. NPlugin::AptSearchPlugin Apt-Search Plugin Plugin für Apt-Suche Performs a full text search Führt Volltextsuche aus This plugin can be used to search the packages for expressions. Dieser Plugin kann verwendet werden, um Pakete nach bestimmten Ausdrücken zu durchsuchen. Delayed evaluation - waiting for further input Verzögerte Auswertung - warte auf weitere Eingaben Performing full text search on package database Volltextsuche über Paketdatenbank wird ausgeführt NPlugin::AvailableVersionPlugin Available Version Plugin Plugin für Verfügbare Version Shows the version for the package available for download Zeigt Informationen über die verfügbare Version von Paketen an Available Version Verfügbare Version NPlugin::InstalledVersionPlugin Installed Version Plugin Plugin für Installierte Version Shows the version of the installed package in the package list Zeigt Informationen über die installierte Version von Paketen an Installed Version Installierte Version NPlugin::PackageDescriptionPlugin Description Beschreibung <h3>Package not found</h3><p>Could not find a valid description for the package <b> <h3>Paket nicht gefunden</h3><p>Für das Paket <b> </b> in the database.<br>This could mean either that you have selected a virtual package or that the package description was not found for an unknown reason. It is possible that your debtags and apt database are out of sync. Try running <tt>debtags update</tt> and <tt>apt-get update</tt> as root.</p> konnte keine gültige Beschreibung in der Datenbank gefunden werden. <br>Dies bedeutet entweder dass ein virtuelles Paket ausgewählt wurde oder dass die Paketbeschreibung aus einem anderen Grund nicht gefunden werden konnte. </p> PackageDescriptionPlugin Plugin für Paketbeschreibungen </b> in the database.<br>This could mean either that you have selected a virtual package or that the package description was not found for an unknown reason.</p> konnte keine gültige Beschreibung in der Datenbank gefunden werden. <br>Dies bedeutet entweder dass ein virtuelles Paket ausgewählt wurde oder dass die Paketbeschreibung aus einem anderen Grund nicht gefunden werden konnte. </p> <h3>Package not found</h3><p>Could not find a valid description for <b> <h3>Paket nicht gefunden</h3><p>Für das Paket <b> </b>.<br> konnte keine Beschreibung gefunden werden.<br> This could mean either that you have selected a virtual package or that the package description was not found for an unknown reason.</p> Dies bedeutet entweder dass ein virtuelles Paket ausgewählt wurde oder dass die Paketbeschreibung aus einem anderen Grund nicht gefunden werden konnte.</p> <b>Installed Version</b>: <b>Installierte Version</b>: <b>Available Version</b>: <b>Verfügbare Version</b>: <b>Available Version</b>: not available<br> <b>Verfügbare Version: </b> nicht verfügbar<br> <b>Essential</b>: <b>Essenziell</b>: <b>Priority</b>: <b>Priorität</b>: <b>Section</b>: <b>Sektion</b>: <b>Section</b>: not available<br> <b>Sektion</b>: nicht verfügbar<br> <b>Installed Size</b>: <b>Installierte Größe</b>: <b>Installed Size</b>: not available<br> <b>Installierte Größe</b>: nicht verfügbar<br> <b>Maintainer</b>: <b>Verwalter</b>: <b>Maintainer</b>: not available<br> <b>Verwalter</b>: nicht verfügbar<br> <b>Architecture</b>: <b>Architektur</b>: <b>Architecture</b>: not available<br> <b>Architektur</b>: nicht verfügbar<br> <b>Source</b>: <b>Quelle</b>: <b>Replaces</b>: <b>Ersetzt</b>: <b>Provides</b>: <b>Bietet an</b>: <b>Pre-Depends</b>: <b>Vorabhängigkeiten</b>: <b>Depends</b>: <b>Hängt ab</b>: <b>Recommends:</b> <b>Empfiehlt:</b> <b>Suggests:</b> <b>Schlägt vor:</b> <b>Conflicts</b>: <b>Konflikt mit</b>: <b>Filename</b>: <b>Dateiname</b>: <b>Filename</b>: not available<br> <b>Dateiname</b>: nicht verfügbar<br> <b>Size</b>: not available<br> <b>Größe</b>: nicht verfügbar<br> <b>MD5sum</b>: <b>MD5-Hash-Wert</b>: <b>MD5sum</b>: not available<br> <b>MD5-Hash-Wert</b>: nicht verfügbar<br> <b>Conffiles</b>: <b>Konfigurationsdateien</b>: <b>Homepage</b>: <a HREF=' <b>Size</b>: <b>Größe</b>: NPlugin::PackageStatusPlugin Package Status Plugin Plugin für Paketstatus QObject Reload Package Database Neuladen der Paketdatenbank packagesearch-2.7.11build1/translations/aptplugin_es.ts0000644000000000000000000006201113507430555020144 0ustar AptSearchPluginShortInputWidget Form1 Search for pattern Buscar paquetes Search the package database for the given expression Buscar en la base de datos el paquete indicado Clear Borrar Search case sensitive Groß-/Kleinschreibung beachten Case Sensitive Groß-/Kleinschreibung Search the package descriptions Buscar por descripción del paquete Search Descriptions Buscar también por descripción Search only full words matching the search patterns Nur ganze Wörter suchen die dem Suchausdruck entsprechen, keine Teilausdrücke When searching only full word matches of the pattern will be considered a match, i.e. if a part of a word matches the pattern it will not be considered a match. Every non-alphanumeric character is considerd to be a word boundary. Es wird nur nach ganzen Wörtern gesucht, die dem Suchausdruck entsprechen. Jedes nicht-alphanumerische Zeichen wird dabei als Wortgrenze betrachtet. Whole Words Only Ganze Wörter This searches the package names and descriptions for the given pattern. If you enter more than one word all words must be contained.<br> You can search for phrases by using double quotes around the phrase. To enter patterns or phrases which should not appear in the package precede them with a minus ('-'). Busca los nombres de los paquetes y las descripciones. Si introduce más de una palabra todas las palabras estarán contenidas en la búsqueda. <br> Puede buscar frases utilizando comillas dobles alrededor de la frase. Para buscar patrones o frases que no aparecan en el paquete debe estar precedido por un signo menos ('-'). Check this if you want to search in the package descriptions. The search will search the package name, the long description and the short description.<br />If not checked only the package names will be searched. Seleccione esta opción si desea buscar los paquetes por descripciones. La búsqueda se hará por el nombre del paquete, una descripción larga y una descripción corta. <br>Si no se marca, sólo el nombre del paquete será buscado. AptSettingsWidget Form The selected tool will be used to install/remove the selected packages La opción seleccionada se utilizará para instalar o eliminar los paquetes seleccionados For package installation Debian Package Search relies on an external program. You can select wether to use apt or aptitude here. Para la instalación o eliminación de paquetes se utiliza un programa externo. Puede seleccionar el tipo a usar apt-get o aptitude. Package Administration Tool Herramientas de administración de paquetes apt-get aptitude InstalledFilterWidget Form1 Installed Filter Filtro de búsqueda Search packages by installed state Busca paquetes según su estado Search packages by installed state. Busca paquetes según su estado. All Todos Installed instalados Upgradable Actualizables Not Installed No instalados NPlugin::AptActionPlugin Update Apt-Package Database Actualizar la Base de Datos Apt Calls "apt-get update" updating the package database Ruft "apt-get update" bzw. "aptitude update" zum aktualisieren der Paketdatenbank auf Updates the package database Actualizar la Base de Datos de los paquetes Reloads the package database from disk (e.g. if apt-get update was performed externally). Vuelve a cargar el paquete de la base de datos desde el disco (por ejemplo, si apt-get update se realizó externamente). Copy Command Line for Installing Package to Clipboard Copiar al portapapeles el comando Creates a command line to install the selected package, and copies it to the clipboard Copiarlo al portapapeles la línea de comandos para instalar el paquete seleccionado Install/Update Package Instalar o Actualizar el paquete Installs/updates the package Instalar o Actualizar los paquetes Remove Package Eliminar paquete Removes the package Eliminar los paquetes Purge Package Purgar paquete Removes package including configuration Eliminar paquetes incluyendo su configuración Unable to launch command No se puede iniciar los comandos NPlugin::AptPluginContainer Command not executed El comando no se ejecuta For an unknwon reason, the command could not be executed. Por a alguna razón desconocida, el programa no puede ser ejecutado. NPlugin::AptSearchPlugin Apt-Search Plugin Plugin para la búsqueda Apt Performs a full text search Realiza búsquedas de texto completo This plugin can be used to search the packages for expressions. Este plugin se puede utilizar para la búsqueda de paquetes con términos específicos. Delayed evaluation - waiting for further input Evaluación - a la espera de nuevas aportaciones Performing full text search on package database Realizar búsquedas de texto completo en la base de datos de los paquetes NPlugin::AvailableVersionPlugin Available Version Plugin Plugin versión disponible Shows the version for the package available for download Muestra la versión del paquete disponible para su descarga Available Version Disponible NPlugin::InstalledVersionPlugin Installed Version Plugin Plugin versión instalada Shows the version of the installed package in the package list Muestra información sobre la versión instalada de la lista de paquetes Installed Version Instalado NPlugin::PackageDescriptionPlugin Description Descripción <h3>Package not found</h3><p>Could not find a valid description for the package <b> <h3> Paquete no encontrado</h3><p>No se pudo encontrar una descripción válida para el paquete <b> </b> in the database.<br>This could mean either that you have selected a virtual package or that the package description was not found for an unknown reason. It is possible that your debtags and apt database are out of sync. Try running <tt>debtags update</tt> and <tt>apt-get update</tt> as root.</p> konnte keine gültige Beschreibung in der Datenbank gefunden werden. <br>Dies bedeutet entweder dass ein virtuelles Paket ausgewählt wurde oder dass die Paketbeschreibung aus einem anderen Grund nicht gefunden werden konnte. </p> PackageDescriptionPlugin Plugin para la descripción de los paquetes </b> in the database.<br>This could mean either that you have selected a virtual package or that the package description was not found for an unknown reason.</p> </b>. Esto significa que, o bien un paquete virtual se ha seleccionado o que la descripción del paquete por cualquier otra razón no pudo ser encontrada.</p> <b>Installed Version</b>: <b>Versión instalada</b>: <b>Available Version</b>: <b>Versión disponible</b>: <b>Available Version</b>: not available<br> <b>Versión disponible</b>no disponible<br> <b>Essential</b>: <b>Esencial</b>: <b>Priority</b>: <b>Prioritario</b>: <b>Section</b>: <b>Grupo</b>: <b>Section</b>: not available<br> <b>Grupo</b>: no disponibles<br> <b>Installed Size</b>: <b>Tamaño (KiB) una vez instalado</b>: <b>Installed Size</b>: not available<br> <b>Tamaño (KiB) instalado</b>: no disponible<br> <b>Maintainer</b>: <b>Mantenedor</b>: <b>Maintainer</b>: not available<br> <b>Mantenedor</b>: no disponible<br> <b>Architecture</b>: <b>Arquitectura</b>: <b>Architecture</b>: not available<br> <b>Arquitectura</b>: no disponible<br> <b>Source</b>: <b>Fuente</b>: <b>Replaces</b>: <b>Remplaza</b>: <b>Provides</b>: <b>Proporciona</b>: <b>Pre-Depends</b>: <b>Pre-Dependencias</b>: <b>Depends</b>: <b>Dependencias</b>: <b>Recommends:</b> <b>Recomendados:</b> <b>Suggests:</b> <b>Sugeridos:</b> <b>Conflicts</b>: <b>Conflictivos</b>: <b>Filename</b>: <b>Nombre de archivo</b>: <b>Filename</b>: not available<br> <b>Nombre de archivo</b>: no disponible<br> <b>Size</b>: not available<br> <b>Tamaño (bytes)</b>: no disponible<br> <b>MD5sum</b>: <b>Valor hash MD5</b>: <b>MD5sum</b>: not available<br> <b>Valor hash MD5</b>: no disponible<br> <b>Conffiles</b>: <b>Archivos de configuración</b>: <b>Size</b>: <b>Tamaño (bytes)</b>: NPlugin::PackageStatusPlugin Package Status Plugin Plugin para el estado del paquete QObject Reload Package Database Recargar la Base de Datos packagesearch-2.7.11build1/translations/debtagsplugin_de.ts0000644000000000000000000003654413507430555020766 0ustar ChoosenTagsDisplay Form2 Show the packages with all of the tags Exclude packages with any of the tags DebtagsSettingsWidget Form2 Facets Shown Angezeigte Facetten >> << Facets Hidden Ausgeblendete Facetten NPlugin::DebtagsPlugin Performing tag search on package database Führe Facettensuche aus NPlugin::DebtagsPluginContainer Tag Database Not Available Tag-Datenbank nicht verfügbar <p>The tag database is not available and the debtags plugin was disabled!</p><p>You must execute <tt><b>debtags update</b></tt> as root on the commandline to download the database. If debtags is not on your system you can install it via <tt><b>apt-get install debtags</b></tt><br>Afterwards you can enable the debtags plugin via the plugin menu -> Control Plugins.</p> <p>Die Tag-Datenbank is nicht verfügbar und der debtags plugin wurde deaktiviert. Sie müssen auf der Kommandozeile <tt><b>debtags update</b></tt> als root ausführen um die Datenbank herunterzuladen. Falls Debtags nicht auf Ihrem System installiert ist, können Sie es über <tt><b>aptitude install debtags</b></tt><br> herunterladen.<br> Anschließend können Sie den debtags-Plugin unter "Packagesearch" -> "Plugins verwalten" aktivieren.</p> Debtags Plugins <p>The tag database is not available and the debtags plugin was disabled!</p><p>You must execute <tt><b>debtags update</b></tt> as root on the commandline to download the database. If debtags is not on your system you can install it via <tt><b>apt-get install debtags</b></tt><br>Afterwards you can enable the debtags plugin via the Packagesearch menu -> Control Plugins.</p> <p>Die Tag-Datenbank is nicht verfügbar und der debtags plugin wurde deaktiviert. Sie müssen auf der Kommandozeile <tt><b>debtags update</b></tt> als root ausführen um die Datenbank herunterzuladen. Falls Debtags nicht auf Ihrem System installiert ist, können Sie es über <tt><b>aptitude install debtags</b></tt><br> herunterladen.<br>Anschließend können Sie den debtags-Plugin unter "Packagesearch" -> "Plugins verwalten" aktivieren.</p> No vocabulary available Vokabular-Datei fehlt <p>The vocabulary is not available. This should not happen. Please reinstall <tt>debtags</tt> or check your /var/lib/debtags/vocabulary file manually.</p>The debtags plugin will be disabled for now, you can re-enable it via the Packagesearch menu -> Control Plugins.</p> <p>Die Vokabular-Datei fehlt. Dies sollte nicht vorkommen. Bitte installieren Sie <tt>debtags</tt> erneut oder überprüfen Sie die Datei /var/lib/debtags/vocabulary von Hand.</p> <p>Der Debtags-Plugin wird deaktiviert. Er kann über das Packagesearch Menü unter "Plugins Verwalten" wieder aktiviert werden.</p> NPlugin::RelatedPlugin Similar Plugin Plugin für Ähnlichkeitssuche Plugin for searching packages similar to another package. Plugin zum Suchen von Paketen die ähnlich einem anderen sind. Similar Ähnlich Searching for similar packages Suche nach ähnlichen Paketen NTagModel::SelectedTagsView deselect a tag by double-clicking Tag durch Doppelklicken entfernen This list displays the tags currently searched for. To remove a tag double-click it. Listet die Tags auf, nach denen derzeit gesucht wird. Um einen Tag zu entfernen muss dieser doppelt angeklickt werden. Clear Löschen Remove Entfernen NTagModel::UnselectedTagsView select a tag by double-clicking Tag durch Doppelklicken auswählen This list shows the tags that can be searched for. The tags are organised in a tree beneath their facets (groups of tags). To search for packages with a tag, double-click the tag. Multiple tags can be selected like this. Facets cannot be selected. Diese Liste zeigt die Tags, nach denen gesucht werden kann. Die Tags sind in einem Baum innerhalb ihrer Facette (Kategorie) angeordnet. Um einen Tag für die Suche auszuwählen, kann dieser doppelt angeklickt werden. Mehrere Tags können auf diese Weise ausgewählt werden. Facetten können nicht ausgewählt werden. Add Hinzufügen Collapse all Alle zusammenklappen Expand all Alle aufklappen NWidgets::SelectionInputAndDisplay filter string to filter tags String um Tags zu filtern Filters the tag names by the string in realtime. Filtert die Tags entsprechend des eingegeben Strings. RelatedFeedbackWidget Form2 Search packages similar to Suche Pakete ähnlich zu displays the package to search related packages for Zeigt das Paket an, zu dem ähnliche Pakete gesucht werden This displays the package for which you want to search related packages for. Enter the package under the "Related" section. Hier wird das Paket angezeigt zu dem ähnliche Pakete gesucht werden. Das Paket kann in der Sektion "Ähnliche" ausgewählt werden. Clear Löschen RelatedInput Form1 Similar to package Ähnlich zu Paket Result packages Anzahl der Pakete Number of result packages Anzahl der Pakete die die Ähnlichkeitssuche zurückgeben soll Defines the number of the most similar packages which will be displayed. Anzahl der ähnlichsten Pakete die von der Suche zurückgegeben werden sollen. Maximum Distance: Maximale Distanz: Maximum number of tags the packages may differ Maximale Anzahl an Tags in sich Pakete unterscheiden dürfen This is the maximum number of tags in which the packages may differ from the given one. <br> Or more formal: <br> |(A union B) difference (A intersect B)| &lt;= MaxDistance Die Maximale Anzahl an Tags, in denen die Pakete von dem angegeben Paket abweichen dürfen.<br>Formal: <br>|(A vereinigt B) abzüglich (A geschnitten B)| &lt;= MaxAnzahl Clear realated search Ähnlichkeitssuche löschen Clear Löschen TagChooserWidget Form1 Show packages with these tags Pakete mit diesen Tags anzeigen Check this to be able to exclude some tags Check this if you want to exclude some tags. If you check it, a list of tags will be shown. There you can select which to exclude. Exclude Tags but not these tags packagesearch-2.7.11build1/translations/debtagsplugin_es.ts0000644000000000000000000003737713507430555021012 0ustar ChoosenTagsDisplay Form2 Show the packages with all of the tags Mostrar las etiquetas en los paquetes Exclude packages with any of the tags No mostrar las etiquetas en los paquetes DebtagsSettingsWidget Form2 Facets Shown Añadir a la interfaz >> << Facets Hidden Ocultar de la interfaz NPlugin::DebtagsPlugin Performing tag search on package database Búsqueda de etiquetas en la base de datos de los paquetes NPlugin::DebtagsPluginContainer Tag Database Not Available Tag-Datenbank nicht verfügbar <p>The tag database is not available and the debtags plugin was disabled!</p><p>You must execute <tt><b>debtags update</b></tt> as root on the commandline to download the database. If debtags is not on your system you can install it via <tt><b>apt-get install debtags</b></tt><br>Afterwards you can enable the debtags plugin via the plugin menu -> Control Plugins.</p> <p>Die Tag-Datenbank is nicht verfügbar und der debtags plugin wurde deaktiviert. Sie müssen auf der Kommandozeile <tt><b>debtags update</b></tt> als root ausführen um die Datenbank herunterzuladen. Falls Debtags nicht auf Ihrem System installiert ist, können Sie es über <tt><b>aptitude install debtags</b></tt><br> herunterladen.<br> Anschließend können Sie den debtags-Plugin unter "Packagesearch" -> "Plugins verwalten" aktivieren.</p> Debtags Plugins Plugin Etiquetas Deb <p>The tag database is not available and the debtags plugin was disabled!</p><p>You must execute <tt><b>debtags update</b></tt> as root on the commandline to download the database. If debtags is not on your system you can install it via <tt><b>apt-get install debtags</b></tt><br>Afterwards you can enable the debtags plugin via the Packagesearch menu -> Control Plugins.</p> <p>Die Tag-Datenbank is nicht verfügbar und der debtags plugin wurde deaktiviert. Sie müssen auf der Kommandozeile <tt><b>debtags update</b></tt> als root ausführen um die Datenbank herunterzuladen. Falls Debtags nicht auf Ihrem System installiert ist, können Sie es über <tt><b>aptitude install debtags</b></tt><br> herunterladen.<br>Anschließend können Sie den debtags-Plugin unter "Packagesearch" -> "Plugins verwalten" aktivieren.</p> No vocabulary available No disponible en el vocabulario <p>The vocabulary is not available. This should not happen. Please reinstall <tt>debtags</tt> or check your /var/lib/debtags/vocabulary file manually.</p>The debtags plugin will be disabled for now, you can re-enable it via the Packagesearch menu -> Control Plugins.</p> El vocabulario no está disponible. Esto no debería ocurrir. . Por favor, vuelva a instalar <tt>debtags</tt> o consulte manualmente el archivo: /var/lib/debtags/vocabulary </p> El plugin debtags será deshabilitado. Se puede volver a habilitar a través del menú Packagesearch -> Control de plugins </p> NPlugin::RelatedPlugin Similar Plugin Plugin de búsqueda por similitud Plugin for searching packages similar to another package. Plugin de búsqueda de paquetes que son similares entre si. Similar Similares Searching for similar packages Búsqueda de paquetes similares NTagModel::SelectedTagsView deselect a tag by double-clicking Para anular la selección de una etiqueta, haga doble clic This list displays the tags currently searched for. To remove a tag double-click it. Esta lista muestra las etiquetas en la búsqueda actual. Para eliminar una etiqueta , haga doble clic en ella. Clear Borrar Remove Eliminar NTagModel::UnselectedTagsView select a tag by double-clicking doble clic para seleccionar una etiqueta This list shows the tags that can be searched for. The tags are organised in a tree beneath their facets (groups of tags). To search for packages with a tag, double-click the tag. Multiple tags can be selected like this. Facets cannot be selected. Esta lista muestra las etiquetas que se pueden buscar. Las etiquetas se organizan en un árbol debajo de sus facetas (Categorías). Para buscar paquetes con una etiqueta determinada, haga doble clic en la etiqueta. Puede seleccionr varias etiquetas de esta manera. Las Categorías no se pueden seleccionar. Add Añadir Collapse all Ocultar todo Expand all Expandir todo NWidgets::SelectionInputAndDisplay filter string to filter tags cadena para filtrar las etiquetas Filters the tag names by the string in realtime. Filtra los nombres de las etiquetas por la cadena en tiempo real. RelatedFeedbackWidget Form2 Search packages similar to Búsqueda de los paquetes por similitud displays the package to search related packages for muestra el paquete en la búsqueda de paquetes relacionados This displays the package for which you want to search related packages for. Enter the package under the "Related" section. Aquí se muestra el paquete para el que desea buscar paquetes relacionados. Introduzca el paquete en la sección "relacionados". Clear Borrar RelatedInput Form1 Similar to package Paquetes similares Result packages Límite de resultados Number of result packages Número de paquetes adevolver del resultado en la búsqueda por similitud Defines the number of the most similar packages which will be displayed. Define el número total a mostrar de paquetes similares. Maximum Distance: Maximale Distanz: Maximum number of tags the packages may differ Maximale Anzahl an Tags in sich Pakete unterscheiden dürfen This is the maximum number of tags in which the packages may differ from the given one. <br> Or more formal: <br> |(A union B) difference (A intersect B)| &lt;= MaxDistance Die Maximale Anzahl an Tags, in denen die Pakete von dem angegeben Paket abweichen dürfen.<br>Formal: <br>|(A vereinigt B) abzüglich (A geschnitten B)| &lt;= MaxAnzahl Clear realated search Borrar la búsqueda por similitud Clear Borrar TagChooserWidget Form1 Show packages with these tags Ver paquetes con las siguientes etiquetas Check this to be able to exclude some tags Marca esta casilla para excluir algunas etiquetas Check this if you want to exclude some tags. If you check it, a list of tags will be shown. There you can select which to exclude. Seleccione esta opción si desea excluir algunas etiquetas. Si la selecciona, la lista de etiquetas será muestrada. Luego usted puede seleccionar cualas excluir. Exclude Tags Excluir Etiquetas but not these tags pero no estas etiquetas packagesearch-2.7.11build1/translations/filenameplugin_de.ts0000644000000000000000000003660013507430555021126 0ustar FilenameFeedbackWidget Search for filename Suche nach Dateinamen Clear Löschen Shows the filename that was searched for Der Dateiname nach dem gesucht wurde FilenameSearchInput Search packages with files containing Duchsuche Pakete nach Datei search installed packages only nur in installierten Paketen suchen Search packages containing a file whose filename matches the pattern Suche nach Pakete mit einer Datei deren Name die angegebene Zeichenkette enthält Check this if you want to search only the installed packages (usually much faster) Nur in installierten Paketen suchen (normalerweise deutlich schneller) FilenameView not available nicht verfügbar The <tt> Das Kommando <tt> </tt> command is not available. Please make sure that the <tt>mime-support</tt> package is installed and that you have permission to execute <tt> </tt> ist nicht verfügbar. Bitte stellen Sie sicher, dass das Paket <tt>mime-support</tt> installiert ist und dass Sie die Rechte haben <tt> Unable to launch Konnte folgendes Programm nicht ausführen: Launching <tt> Die Ausführung von <tt> </tt> failed due to an unknown reason. </tt> ist aus unbekanntem Grund fehlgeschlagen. Error viewing file Fehler beim Betrachten einer Datei Unable to view file Kann Datei nicht anzeigen: Tried <tt> Versucht mit <tt> </tt> and <tt> </tt> und <tt> Copy to clipboard In Zwischenablage kopieren Copy all filenames to clipboard Alle Dateinamen in Zwischenablage kopieren View file (depends on settings in /etc/mailcap) Datei ansehen (Abhängig von Einstellungen in /etc/mailcap) Show the filelist for the selected package Zeigt Dateiliste für ausgewähltes Paket an Shows a list of the files which are included in the package. If the list is already shown it will be updated.<br> For installed packages the list is shown by default because it is quite fast. For not installed package it is only shown if this button is clicked as it takes a considerable amount of time. Zeigt die Liste der Dateien in dem aktuellen Paket an. Wenn die Liste bereits angezeigt ist, so wird diese aktualisiert.<br> Für installierte Pakete wird die Dateiliste standardmäßig angezeigt da dies schnell ist. Für nicht-installierte Pakete wird diese nur angezeigt, wenn der Knopf angeklickt wird da diese eine zeitlang dauert. Show Anzeigen </tt>. </tt> auszuführen. Filter files to be shown Filter für angezeigte Dateien Trying to view Versuche Datei anzuzeigen: Retrying to view Versuche Datei with mimetype text/plain erneut mit dem MIME-Type text/plain anzuzeigen Finished viewing Ansehen von Datei beendet Can't view file Kann Datei nicht anzeigen , it is not viewable , die Datei ist nicht anzeigbar NPlugin::FilenameActionPlugin Calls "apt-file update" updating the file database Ruft "apt-file update" um die Dateidatenbank zu aktualisieren NPlugin::FilenamePlugin Filename Plugin Plugin für Dateinamen Plugin to search by files and diplay files in packages. Der Plugin erlaubt es nach Dateien zu suchen und Dateien in Paketen anzuzeigen. This plugin allows to search the packages for files, and to display the files included in the packages For information about not installed packages, it needs the <tt>apt-file</tt> tool. Der Plugin erlaubt es nach Dateien zu suchen und Dateien in Paketen anzuzeigen. Zum Anzeigen der Dateien in nicht installierten Pakete wird das Paket <tt>apt-file</tt> benötigt. Files Dateien There is no file information for the current package available. Es sind keine Informationen über die Dateien für das aktuelle Paket verfügbar. delayed evaluation - waiting for further input Verzögerte Auswertung - warte auf weitere Eingaben Apt file search not availabe Dateisucht nicht verfügbar You need the <tt>apt-file</tt> utility to search files in packages not installed.<br>To get apt-file fetch it via <tt>apt-get install apt-file</tt> and run <tt>apt-file update</tt> afterwards. Sie benötigen das Paket <tt>apt-file</tt> um in nicht installierten Paketen nach Dateien zu suchen oder die Dateien anzuzeigen.<br> Installieren Sie apt-file mittels <tt>apt-get install apt-file</tt>. Führen Sie anschließend <tt>apt-file update</tt> aus. Performing search for filenames, this might take a while Suche nach Dateinamen, dies kann einige Zeit in Anspruch nehmen Filenames Dateinamen Querying database for file list Abfragen der Dateidatenbank <font color=#606060><p>File list for <b> <font color=#606060><p>Die Dateiliste für Paket <b> </b> not available.</p><p>For displaying the file list for not-installed packages, the "apt-file" package is required. Please install "apt-file" and retrieve the latest file database by running <tt>apt-file update</tt>.</p></font> </b> ist nicht verfügbar.</p><p>Um die Dateien in nicht installierten Paketen anzuzeigen wird das Paket <tt>apt-file</tt> benötigt. Bitte installieren Sie apt-file und führen Sie anschließend <tt>apt-file update</tt> aus um die aktuellste Dateidatenbank herunterzuladen.</p></font> <font color=#606060>For packages <b>not installed</b>, the file list is not shown by default. This is because retreiving the file list will take some time.<br>Please click the <b>&quot;Show&quot;</b> button to show the filelist for the selected package.</font> <font color=#606060>Für <b>nicht installierte </b> Pakete wird die Dateiliste standardmäßig nicht angezeigt, da dies etwas Zeit in Anspruch nimmt.<br>Bitte klicken Sie den Knopf <b>&quot;Anzeigen&quot;</b> um die Dateiliste für das ausgewählte Paket anzuzeigen.</font> NPlugin::FilenamePluginContainer Command not executed Programm wurde nicht ausgeführt For an unknwon reason, the command could not be executed. Aus unbekanntem Grund wurde das Programm nicht ausgeführt. Update not successfully completed Update wurde nicht erfolgreich beendet The apt-file update was not completed successfully.<br>The database might be broken, rerun <tt>apt-file update</tt> to fix this. Das Update der Dateidatenbank wurde nicht erfolgreich beendet.<br>Die Datenbank könnte beschädigt sein. Bitte führen Sie <tt>apt-file update</tt> erneut aus um dies zu beheben. QObject Update File Database Dateidatenbank aktualiseren Filename Plugins Plugins für Dateinamen packagesearch-2.7.11build1/translations/filenameplugin_es.ts0000644000000000000000000003645513507430555021155 0ustar FilenameFeedbackWidget Search for filename Suche nach Dateinamen Clear Löschen Shows the filename that was searched for Der Dateiname nach dem gesucht wurde FilenameSearchInput Search packages with files containing Buscar paquetes con archivos que contiene search installed packages only buscar sólo paquetes instalados Search packages containing a file whose filename matches the pattern Suche nach Pakete mit einer Datei deren Name die angegebene Zeichenkette enthält Check this if you want to search only the installed packages (usually much faster) Nur in installierten Paketen suchen (normalerweise deutlich schneller) FilenameView not available no disponible The <tt> El Comando<tt> </tt> command is not available. Please make sure that the <tt>mime-support</tt> package is installed and that you have permission to execute <tt> </tt> no está disponible. Por favor, asegúrese de que el paquete <tt>mime-support</tt> esté instalado y que tiene permisos para ejecutarlo <tt> Unable to launch No se puede iniciar Launching <tt> La ejecución <tt> </tt> failed due to an unknown reason. </tt> falló debido a una error desconocido. Error viewing file Error al visualizar el archivo Unable to view file No se puede ver el archivo Tried <tt> Probando <tt> </tt> and <tt> </tt> con <tt> Copy to clipboard Copiar al portapapeles Copy all filenames to clipboard Copia todos los archivos al portapapeles View file (depends on settings in /etc/mailcap) Ver archivo (esto depende de suconfiguración en /etc/mailcap) Show the filelist for the selected package Zeigt Dateiliste für ausgewähltes Paket an Shows a list of the files which are included in the package. If the list is already shown it will be updated.<br> For installed packages the list is shown by default because it is quite fast. For not installed package it is only shown if this button is clicked as it takes a considerable amount of time. Zeigt die Liste der Dateien in dem aktuellen Paket an. Wenn die Liste bereits angezeigt ist, so wird diese aktualisiert.<br> Für installierte Pakete wird die Dateiliste standardmäßig angezeigt da dies schnell ist. Für nicht-installierte Pakete wird diese nur angezeigt, wenn der Knopf angeklickt wird da diese eine zeitlang dauert. Show Mostrar </tt>. </tt>. Filter files to be shown Filter für angezeigte Dateien Trying to view Tratando de ver Retrying to view Intentando de nuevo para ver with mimetype text/plain con mime type text/a simple vista Finished viewing Ver el final del archivo Can't view file No se puede ver el archivo , it is not viewable , este archivo no es visible NPlugin::FilenameActionPlugin Calls "apt-file update" updating the file database Llama a "apt-file update" para actualizar la base de datos NPlugin::FilenamePlugin Filename Plugin Plugin para nombres de archivos Plugin to search by files and diplay files in packages. Este plugin permite navegar por los paquetes y ver los archivos en los paquetes. This plugin allows to search the packages for files, and to display the files included in the packages For information about not installed packages, it needs the <tt>apt-file</tt> tool. El plugin permite navegar por los archivos y ver archivos en paquetes. Para ver los archivos en el paquete que no esté instalado es necesario el paquete<tt>apt-file</tt>. Files Archivos There is no file information for the current package available. No hay información de archivo para el paquete más reciente disponible. delayed evaluation - waiting for further input Evaluación de retardo - a la espera de nuevas aportaciones Apt file search not availabe Búsqueda de archivo Apt no disponible You need the <tt>apt-file</tt> utility to search files in packages not installed.<br>To get apt-file fetch it via <tt>apt-get install apt-file</tt> and run <tt>apt-file update</tt> afterwards. Usted necesita <tt>apt-file</tt> es una utilidad para buscar archivos en paquetes no instalados.<br>Para obtener apt-file realice <tt>apt-get install apt-file</tt> luego ejecute <tt>apt-file update</tt>. Performing search for filenames, this might take a while Buscar por nombre de archivo, esto puede tomar algún tiempo Filenames Nombre de archivo Querying database for file list Consultar la lista de archivos de la base de datos <font color=#606060><p>File list for <b> <font color=#606060><p>Lista de archivos <b> </b> not available.</p><p>For displaying the file list for not-installed packages, the "apt-file" package is required. Please install "apt-file" and retrieve the latest file database by running <tt>apt-file update</tt>.</p></font> </b> no está disponible. </p><p>Para mostrar la lista de archivos para los paquetes no-instalados, es necesario el paquete "apt-file". Por favor, instale "apt-file" y actualice la lista de la base de datos de archivos mediante la ejecución de<tt>apt-file update</tt>.</p></font> <font color=#606060>For packages <b>not installed</b>, the file list is not shown by default. This is because retreiving the file list will take some time.<br>Please click the <b>&quot;Show&quot;</b> button to show the filelist for the selected package.</font> <font color=#606060>Para los paquetes <b>no instalados</b>, la lista de archivos no se muestra por defecto. Recuperar la lista de archivos tomará algún tiempo.<br> Por favor, haga clic en el botón<b>&quot;Mostrar&quot;</b> para ver la lista de archivos del paquete seleccionado.</font> NPlugin::FilenamePluginContainer Command not executed Comando no ejecutado For an unknwon reason, the command could not be executed. Por razones desconocidas, el comando no puede ser ejecutado. Update not successfully completed Actualización fallida The apt-file update was not completed successfully.<br>The database might be broken, rerun <tt>apt-file update</tt> to fix this. La actualización apt-file no se completó correctamente. <br>Pueden existir paquetes rotos en la base de datos, <br>vuelva a ejecutar <tt>apt-file update</tt> para intentar solucionar este problema. QObject Update File Database Actualización de los archivos de la base de datos Filename Plugins Plugins para nombres de archivos packagesearch-2.7.11build1/translations/orphanplugin_de.ts0000644000000000000000000002612113507430555020632 0ustar NPlugin::OrphanPlugin Orphan Plugin Waisen Plugin Plugin to search for orphaned packages. Plugin um verwaiste Pakete zu suchen. This plugin supports to search for packages which are orphaned. It uses deborphan to implement the search Dieser Plugin ermöglicht die Suche nach verwaisten Paketen. Zur Realisierung der Suche wird deborphan verwendet. This plugin supports to search for packages which are orphaned. It uses deborphan to implement the search. Dieser Plugin ermöglicht die Suche nach verwaisten Paketen. Zur Realisierung der Suche wird deborphan verwendet. Searching orphans Suche nach verwaisten Paketen Error running deborphan Fehler beim Ausführen von deborphan An error occured running <tt> Ein Fehler trat auf, beim ausführen von <tt> Orphans Waisen NPlugin::OrphanPluginContainer deborphan not available deborphan ist nicht verfügbar The <tt>deborphan</tt> application, needed by the orphan plugin, was not found. The orphan plugin was disabled. To use the orphan plugin install the deborphan package via<br><tt>apt-get install deborphan</tt><br>and reenable the plugin using <i>Packagesearch -> Control Plugins</i> afterwards. Die Anwendung <tt>deborphan</tt> wird vom Waisen-Plugin benötigt aber wurde nicht gefunden. Der Waisen-Plugin wurde deaktiviert. Zum installieren von deborphan führen Sie bitte<br><tt>aptitude install deborphan</tt><br>aus und aktivieren Sie anschließend den Waisen-Plugin über <i>Packagesearch -> Plugins verwalten</i>. OrphanFeedbackWidget Form1 Displays the deborphan commandline Die deborpham Kommandozeile This displays the command line which is used to search for orphans. Dies zeigt die deborphan-Kommandozeile an, die für die Ermittlung der verwaisten Pakete verwendet wird. Clears the orphan search Löscht die Suche nach verwaisten Paketen Clear Löschen OrphanSearchInput Form1 Search for ophaned package Durchsucht nach verwaisten Paketen <p>Enable this option to search for orphaned packages. Orphaned packages are packages which no other package depends on. By default only the <i>libs</i> and <i>oldlibs</i> sections are searched.</p> <p>This search uses the <tt>deborphan</tt> tool as backend so make sure it is installed.</p> <p>Aktivieren Sie dieses Kästchen um nach verwaisten Paketen zu suchen. Verwaiste Pakete sind Pakete, von denen kein anderes Paket mehr abhängt. Standardmäßig werden nur die Sektionen <i>libs</i> und <i>oldlibs</i> durchsucht.</p><p>Die Suche verwendet <tt>deborphan</tt> als Backend, welches installiert sein sollte.</p> Search orphaned Verweiste Pakete suchen Options Optionen Search in section lib and oldlib only Suche nur in Sektionen lib und oldlib Searches only the lib and oldlib section for orphans. Sucht nur in den Sektionen lib und oldlib nach verwaisten Paketen. Search lib and oldlib Druchsuche lib und oldlib Search in section lib, oldlib and libdevel Suche nur in Sektionen lib, oldlib und libdevel Search in the section libdevel in addition to libs and oldlibs. Sucht nur in den Sektionen lib, oldlib und libdevel nach verwaisten Paketen. Search lib, oldlib and libdevel Durchsuche lib, oldlib und libdevel Search all the packages, instead of only those in the libs section Durchsucht alle Pakete anstatt nur in den libs Sektionen Search all sections Alle Sektionen durchsuchen Searches packages that are possibly useless Sucht nach wahrscheinlich unbenötigten Paketen <p>Search for packages where deborphan guesses them not to be of much use to you by examining the package's name and/or description. It will pretend the package is in the main/libs section, and report it as if it were a library. </p> <p>This method is in no way perfect or even reliable, so beware when using this! </p> Sucht nach Paketen für die vermutlich nicht mehr benötigt werden (basierend auf dem Paketnamen und/oder der Beschreibung). <p>Diese Methode ist nicht perfekt und nicht zuverlässig, daher seien Sie bitte vorsichtig bei deren Nutzung!</p> Guess useless Vermutlich unbenötigt Searches packages with residual configuration Sucht Pakete mit verbleibender Konfiguration Search residual configuration Suche Pakete mit verbleibender Konfiguration <p>This option searches for uninstalled packages which still have configuration files on the system. </p> <p>It implies searching in all sections.</p> <p>Mit dieser Option wird nach Paketen gesucht für die deinistalliert sind aber die noch Konfigurationsdateien auf der Festplatte haben.</p><p>Es wird in allen Sektionen gesucht.</p> QObject Orphan Plugins Waisen-Plugin packagesearch-2.7.11build1/translations/orphanplugin_es.ts0000644000000000000000000002534513507430555020660 0ustar NPlugin::OrphanPlugin Orphan Plugin Plugin huérfanos Plugin to search for orphaned packages. Plugin para búsqueda de paquetes huérfanos. This plugin supports to search for packages which are orphaned. It uses deborphan to implement the search Este plugin soporta la búsqueda de paquetes que han quedado huérfanos. Utiliza deborphan para implementar la búsqueda Searching orphans Búsqueda de huérfanos Error running deborphan Error al ejecutar deborphan An error occured running <tt> Se produjo un error en ejecución <tt> Orphans Huérfanos NPlugin::OrphanPluginContainer deborphan not available deborphan no disponible The <tt>deborphan</tt> application, needed by the orphan plugin, was not found. The orphan plugin was disabled. To use the orphan plugin install the deborphan package via<br><tt>apt-get install deborphan</tt><br>and reenable the plugin using <i>Packagesearch -> Control Plugins</i> afterwards. <tt>deborphan</tt> la aplicación, que necesita el plugin de paquetes huérfanos, no se ha encontrado. El plugin huérfano se ha desactivado. Para usar el complemento de paquetes huérfanos, debe instalar el paquete deborphan a través de <br><tt>apt-get install deborphan</tt><br>y luego volver a habilitar el plugin en <i>Packagesearch -> Control de Plugins</i>. OrphanFeedbackWidget Form1 Displays the deborphan commandline Muestra la línea de comandos deborphan This displays the command line which is used to search for orphans. Esto muestra la línea de comandos que se utiliza para buscar los paquetes huérfanos. Clears the orphan search Borra la búsqueda de paquetes huérfanos Clear Borrar OrphanSearchInput Form1 Search for ophaned package Búsquedas de paquetes huérfanos <p>Enable this option to search for orphaned packages. Orphaned packages are packages which no other package depends on. By default only the <i>libs</i> and <i>oldlibs</i> sections are searched.</p> <p>This search uses the <tt>deborphan</tt> tool as backend so make sure it is installed.</p> <p>Marque esta casilla para buscar paquetes huérfanos. Paquetes huérfanos son los paquetes que no dependen de ningún otro paquete. Por defecto, sólo se busca en las secciones <i>libs</i> y <i>oldlibs</i> </p> <p>La búsqueda utiliza la herramienta <tt>deborphan</tt> asegúrese de que está instalada.</p> Search orphaned Buscar huérfanos Options Opcciones Search in section lib and oldlib only Busca sólo en las secciones lib y oldlib Searches only the lib and oldlib section for orphans. Busca huérfanos sólo la sección lib y oldlib. Search lib and oldlib Buscar en lib y oldlib Search in section lib, oldlib and libdevel Busca en la sección lib, oldlib y libdevel Search in the section libdevel in addition to libs and oldlibs. Busca en la sección libdevel, además de libs y oldlibs. Search lib, oldlib and libdevel Buscar en lib, oldlib y libdevel Search all the packages, instead of only those in the libs section Buscar todos los paquetes, en lugar de sólo en la sección libs Search all sections Buscar en todas las secciones Searches packages that are possibly useless Busca paquetes que ya no son útiles <p>Search for packages where deborphan guesses them not to be of much use to you by examining the package's name and/or description. It will pretend the package is in the main/libs section, and report it as if it were a library. </p> <p>This method is in no way perfect or even reliable, so beware when using this! </p> <p>La búsqueda de paquetes que ya no son probablemente útiles (se basa en el nombre del paquete o en la descripción de éste). </p> <p>Este método no es perfecto ni fiable, así que por favor tenga cuidado cuando lo use. </p> Guess useless Buscar los supuestamente inútiles Searches packages with residual configuration Busca los paquetes por las configuraciones restantes Search residual configuration Buscar por la configuración restante <p>This option searches for uninstalled packages which still have configuration files on the system. </p> <p>It implies searching in all sections.</p> <p>Esta opción busca paquetes desinstalados que aún tienen los archivos de configuración en el sistema. </p> <p>Esto implica la búsqueda en todas las secciones.</p> QObject Orphan Plugins Plugin huérfanos packagesearch-2.7.11build1/translations/packagesearch_de.ts0000644000000000000000000007005113507430555020706 0ustar ColumnControlDlg Control Columns Spalten konfigurieren Shown Eingeblendet >> << Hidden Ausgeblendet &OK Alt+O &Cancel &Abbrechen Alt+C Alt+A MainProgram Usage: packagesearch [options] -h, --help prints this message -v, --version prints the version information If started without options the UI is launched Verwendung: packagesearch [Optionen] -h, --help gibt diesen Hilfetext aus -v, --version gibt die Version ausWird packagesearch ohne Option ausgeführt, dann wird die Nutzeroberfläche gestartet Unknown option Unbekannte Option Debian Package Search - Version Debian Paketsuche - Version NPackageSearch::PackageDisplayWidget Customize Columns Spalten anpassen Hide Column Spalte ausblenden Name Name Score Relevanz NPlugin::PackageNamePlugin Package Name Plugin Plugin für Paketnamen Displays the package names Zeigt die Namen der Pakete an Name Name NPlugin::PluginManager No translation for plugin found for current locale NPlugin::ScoreDisplayPlugin Score Display Plugin Score-Wert-Anzeige-Plugin Displays the package scores Zeigt den Scorewert für die Pakete an Displays the search scores of the packages returned by the current search.<br> The higher the scores, the better the packages matches to the search. Zeigt den Score-Wert für die Pakete aus der aktuellen Suche an. Ein höherer Score-Wert bedeutet eine bessere Übereinstimmung des Paketes mit der Suche. Score Relevanz PackageSearch Debian Package Search Debian Paketsuche <b>Search</b> <b>Suche</b> Clear Search Suche löschen Dummy <b>Result</b> Suchergebnis <font size="-1">No search active</font> <font size="-1">Keine Suche aktiv</font> Choose a package Paket auswählen <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Nimbus Sans L; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Here you can choose to display information about a package, from all packages available.</p></body></html> <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Nimbus Sans L; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Hier kann das Paket ausgewählt werden, für dass informaitonen angezeigt werden sollen.</p></body></html> Back Zurück Forward Vorwärts Details &Packagesearch &System &Help &Hilfe &View &Ansicht Pa&ckages Pa&kete &Contents... &Inhalt... Contents Inhalt &About &Über About Über Exit Beenden Control Plugins Plugins verwalten Control plugins Plugins verwalten Enable and disable plugins Aktivieren/deaktivieren von Plugins Preferences Einstellungen PackageSearchAboutDlg Debian Package Search Debian Paketsuche <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Nimbus Sans L'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Debian Package Search</span></p></body></html> Debian Paketsuche Author Autor <!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:'Sans Serif'; 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;"><span style=" font-family:'Nimbus Sans L'; font-weight:600;">Debian Package Search</span><span style=" font-family:'Nimbus Sans L';"><br />(c) 2004-2012, Benjamin Mesing<br />Email: </span><a href="mailto:bensmail@gmx.net"><span style=" font-family:'Nimbus Sans L'; text-decoration: underline; color:#0000ff;">bensmail@gmx.net</span></a></p></body></html> <!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:'Sans Serif'; 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;"><span style=" font-family:'Nimbus Sans L'; font-weight:600;">Debian Paketsuche</span><span style=" font-family:'Nimbus Sans L';"><br />(c) 2004-2012, Benjamin Mesing<br />Email: </span><a href="mailto:bensmail@gmx.net"><span style=" font-family:'Nimbus Sans L'; text-decoration: underline; color:#0000ff;">bensmail@gmx.net</span></a></p></body></html> <!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:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Enrico Zini</span> for the wonderful Debtags System and his tips regarding this application. Enrico does also sponsor the updates to the debian server.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Frannoe </span>for the Spanish translation and icon.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The <span style=" font-weight:600;">Bug reporters</span> who provided a lot of help tracking down the bugs: </p> <ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Thomas Kabelmann</li> <li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ross Boylan</li></ul></body></html> <p><b>Enrico Zini</b> für das durchdachte Debtags System und seine Hinweise zu dieser Anwendung.</p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Frannoe </span>for the Spanish translation and icon.</p> Die <b>Fehler-Melder</b> die viel Informationen geliefert haben um die Fehler zu beheben<ul><li>Thomas Kabelmann</li><li>Ross Boylan</li></ul> <!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:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <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; font-family:'Nimbus Sans L';"></p></body></html> Homepage: <a href=http://packagesearch.sourceforge.net>http://packagesearch.sourceforge.net</a> Thanks To Danksagung <p> <b>Enrico Zini</b> for the wonderful Debtags System and his tips regarding this application. Enrico does also sponsor the updates to the debian server.<br> </p> The <b>Bug reporters</b> who provided a lot of help tracking down the bugs: <ul> <li>Thomas Kabelmann</li> <li>Ross Boylan</li> </ul> <p><b>Enrico Zini</b> für das durchdachte Debtags System und seine Hinweise zu dieser Anwendung.</p>Die <b>Fehler-Melder</b> die viel Informationen geliefert haben um die Fehler zu beheben<ul><li>Thomas Kabelmann</li><li>Ross Boylan</li></ul> Licence Lizenz OK PackageSearchImpl Displays the packages matching the search entered above. Zeigt die Pakete an, die der oben angegebenen Suche entsprechen. Main Toolbar Haupt-Werkzeugleiste Error trying to open Xapian database Fehler beim öffnen der Xapian-Datenbank <p>An error occurred trying to open the xapian database at /var/lib/apt-xapian-index/index please make sure the file is readable and valid. You may try to run update-apt-xapian-index to fix this problem. The orginal error message was:<br>" Ein Fehler ist beim Öffnen der Xapian Datenbank unter /var/lib/apt-xapian-index/index aufgetreten. Stellen Sie sicher das die Datei lesbar und gültig ist. Sie könne versuchen update-apt-xapian-index auszuführen um das Problem zu beheben, Die ursprüngliche Fehlermeldung war:<br> Would you like to run update-apt-xapian-index now? Otherwise packagesearch will be terminated. Möchten sie update-apt-xapian-index jetzt ausführen? Andernfalls wird packagesearch beendet. Unable to write settings Konnte einstelungen nicht speichern Unable to write settings to Konnte Einstellungen nicht speichern in Details Evaluating searches Suche auswerten Package Search Help Page Debian Paketsuche - Hilfe PluginControl PluginControl Plugins verwalten Enabled Aktiviert Version Author Autor Location Pfad Close Schließen SettingsDlg Packagesearch Settings Einstellungen - Debian Paketsuche Main Settings Globale Einstellungen <!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:'Nimbus Sans L'; 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;">The program selected here will be used to execute commands as root when neccessary (e.g. when installing packages). <tt>su</tt> is the default and available on every Debian system.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><tt>sudo</tt> requires the package sudo to be installed. If configured properly, <tt>sudo</tt> might be more convenient, because you need to enter the password only once.</p></body></html> <!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" /></head><body> Das hier ausgewählt Programm wird für die Erlangung von Root-Rechten verwendet, wenn dies erforderlich ist (z. B. für die Installation von Paketen). <tt>su</tt> ist die Standardauswahl und ist auf jedem Debian-System verfügbar.</p> <p><tt>sudo</tt> erfordert die Installation des Paketes sudo. Wenn sudo entsprechend konfiguriert ist, ist es von der Verwendung bequemer, da das Passwort nicht so oft neu eingegeben werden muss.</p></body></html> Program used to become root Anwendung zum Erlangen von Root-Rechten Use "su" to become root "su" verwenden um Root zu werden su Use "sudo" to become root "sudo" verwenden um Root zu werden sudo Enable/Disable Proxy Server Ein-/Ausschlaten des Proxy Servers A proxy server might be used Ein Proxy-Server kann verwendet werden Proxy Server Proxy-Server http:// Proxy server to be used Server der als Proxy-Server verwendet werden soll Proxy Server Port Port des Proxy-Servers packagesearch-2.7.11build1/translations/packagesearch_es.ts0000644000000000000000000005576313507430555020742 0ustar ColumnControlDlg Control Columns Ajuste de Columnas Shown Mostrar >> << Hidden Ocultar &OK Alt+O &Cancel &Cancelar Alt+C Alt+A MainProgram Usage: packagesearch [options] -h, --help prints this message -v, --version prints the version information If started without options the UI is launched Uso: packagesearch [opciones] -h, --help imprime el mensage -v, --imprime la información de la versión Si se inicia sin opciones, la interfaz de usuario se pondrá en marcha Unknown option Opción desconocida Debian Package Search - Version Búsqueda de paquetes Debian - Versión NPackageSearch::PackageDisplayWidget Customize Columns Personalizar columnas Hide Column Ocultar columna NPlugin::PackageNamePlugin Package Name Plugin Nombre del plugin del paquete Displays the package names Muestra los nombres de los paquetes Name NPlugin::PluginManager No translation for plugin No hay traducción para el plugin found for current locale encontrada localización actual NPlugin::ScoreDisplayPlugin Score Display Plugin Plugin de Calificación Displays the package scores Muestra las calificaciones de los paquetes Displays the search scores of the packages returned by the current search.<br> The higher the scores, the better the packages matches to the search. Indica el valor de la puntuación de los paquetes en la búsqueda actual.<br> Cuanto mayor se la puntuación, mejor será el paquete buscado. Score PackageSearch Debian Package Search Búsqueda de paquetes Debian <b>Search</b> <b>Búsqueda</b> Clear Search Borrar búsqueda Dummy <b>Result</b> <b>Resultado de la búsqueda</b> <font size="-1">No search active</font> <font size="-1">no hay búsqueda activa</font> Choose a package Escoja un paquete <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Nimbus Sans L; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Here you can choose to display information about a package, from all packages available.</p></body></html> <html><head><meta name="qrichtext" content="1" /></head><body style=" white-space: pre-wrap; font-family:Nimbus Sans L; font-weight:400; font-style:normal; text-decoration:none;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Aquí puede elegir mostrar la información sobre un paquete en concreto, de todos los paquetes disponibles.</p></body></html> Back Atrás Forward Adelante Details Detalles &Packagesearch &System &Sistema &Help A&yuda &View &Ver Pa&ckages Pa&quetes &Contents... &Contenido... Contents Contenido &About &Acerca de About Acerca de Exit Salir Control Plugins Control de Plugins Control plugins Control de Plugins Enable and disable plugins Activar o desactivar plugins Preferences Preferencias PackageSearchAboutDlg Debian Package Search Búsqueda de paquetes Debian <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Nimbus Sans L'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:600;">Debian Package Search</span></p></body></html> Búsqueda de paquetes Debian Author Autor <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Nimbus Sans L'; 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;"><span style=" font-weight:600;">Debian Package Search</span><br />(c) 2004-2008, Benjamin Mesing<br />Email: <a href="mailto:bensmail@gmx.net"><span style=" text-decoration: underline; color:#0000ff;">bensmail@gmx.net</span></a></p></body></html> Homepage: <a href=http://packagesearch.sourceforge.net>http://packagesearch.sourceforge.net</a> Página Web: <a href=http://packagesearch.sourceforge.net>http://packagesearch.sourceforge.net</a> <br><br>Traducido al Español por: <b>Frannoe</b> (LMDE Cosillas)<br> <b> http://ubuntu-cosillas.blogspot.com</b> Thanks To Gracias a <p> <b>Enrico Zini</b> for the wonderful Debtags System and his tips regarding this application. Enrico does also sponsor the updates to the debian server.<br> </p> The <b>Bug reporters</b> who provided a lot of help tracking down the bugs: <ul> <li>Thomas Kabelmann</li> <li>Ross Boylan</li> </ul> Licence Licencia <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Nimbus Sans L'; font-size:10pt; font-weight:400; font-style:normal;"> <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;"></p></body></html> OK PackageSearchImpl Displays the packages matching the search entered above. Muestra los paquetes que coincidan con la búsqueda introducidos anteriormente. Main Toolbar Barra de herramientas principal Error trying to open Xapian database Error al intentar abrir la base de datos Xapian <p>An error occurred trying to open the xapian database at /var/lib/apt-xapian-index/index please make sure the file is readable and valid. You may try to run update-apt-xapian-index to fix this problem. The orginal error message was:<br>" <p>Se produjo un error al intentar abrir la base de datos xapian en /var/lib/apt-xapian-index/index por favor asegúrese de que el archivo es legible y válido. Usted puede tratar de ejecutar update-apt-xapian-index para intentar solucionar este problema. Mensaje de error original:<br>" Would you like to run update-apt-xapian-index now? Otherwise packagesearch will be terminated. ¿Quieres ejecutar update-apt-xapian-index ahora? De lo contrario Packagesearch se dará por terminado. ¿Quieres ejecutar update-apt-xapian-index ahora? De lo contrario Packagesearch se dará por terminado. Unable to write settings No se puede escribir en su configuración Unable to write settings to No se puede escribir en su configuración de Details Detalles Evaluating searches Evaluación de las búsquedas Package Search Help Page Página de ayuda PluginControl PluginControl Control de Plugin Enabled Habilitado Version Versión Author Autor Location Localización Close Cerrar SettingsDlg Packagesearch Settings Configuración de búsqueda de paquetes Debian Main Settings Ajustes globales <!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:'Nimbus Sans L'; 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;">The program selected here will be used to execute commands as root when neccessary (e.g. when installing packages). <tt>su</tt> is the default and available on every Debian system.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><tt>sudo</tt> requires the package sudo to be installed. If configured properly, <tt>sudo</tt> might be more convenient, because you need to enter the password only once.</p></body></html> <!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" /></head><body> El programa seleccionado se utiliza aquí para obtener privilegios de root, (por ejemplo, para la instalación de paquetes). <tt>su</tt> es la selección predeterminada y está disponible en cualquier sistema Debian.</p> <p><tt>sudo</tt> requiere de la instalación del paquete <tt>sudo</tt>. Si se configura sudo, es más conveniente para su uso, ya que la contraseña no se introduce con tanta frecuencia.</p></body></html> Program used to become root Comado deseado para convertirse en usuario Root Use "su" to become root Utilizar "su" para ser usuario Root su Use "sudo" to become root Utilizar "sudo" para ser usuario Root sudo packagesearch-2.7.11build1/translations/popconplugin_de.ts0000644000000000000000000000163113507430555020640 0ustar NPlugin::PopconPluginContainer Popcon data not available <p>There is no popcon data available!</p><p>The popcon plugin has been disabled.</p> Popcon Plugins packagesearch-2.7.11build1/translations/popconplugin_es.ts0000644000000000000000000000175113507430555020662 0ustar NPlugin::PopconPluginContainer Popcon data not available Datos Popcon no disponibles <p>There is no popcon data available!</p><p>The popcon plugin has been disabled.</p> <p>No hay datos disponibles popcon!</p><p>El plugin popcon ha sido desactivado.</p> Popcon Plugins packagesearch-2.7.11build1/translations/screenshotplugin_de.ts0000644000000000000000000000641213507430555021521 0ustar NPlugin::ScreenshotPlugin Screenshot Plugin Displays screenshots of the packages to be installed Zeigt Screenshots von dem zu installierenden Paket This plugin displays screenshots of the packages to be installed. It fetches the screenshots from http://screenshots.debian.net so a working internet connection is required. Dieser Plugin zeigt Screenshots für das zu installierende Paket an. Die Screenshots werden von http://screenshots.debian.net heruntergeladen, daher ist eine Internetverbindung erforderlich. Loading screenshot Establishing connection, please wait... Lade Screenshot Verbindung wird hergestellt, bitte warten Sie... The screenshot size exceeds 10 MB. Something seems to be wrong here! Aborting Download. Der Screenshot ist größer als 10MB irgendetwas scheint schiefgegangen zu sein! Download wird abgebrochen. Loading screenshot - Progress: Lade screenshot - Fortschritt: No screenshot available for Kein Screenshot für das Paket verfügbar An error occured while trying to download the screenshot: Ein Fehler ist beim herunterladen des Screenshots aufgetreten: NPlugin::ScreenshotPluginContainer Screenshots not supported Screenshots werden nicht unterstützt Screenshot Plugins packagesearch-2.7.11build1/translations/screenshotplugin_es.ts0000644000000000000000000000650413507430555021542 0ustar NPlugin::ScreenshotPlugin Screenshot Plugin Plugin para obtener capturas de pantalla Displays screenshots of the packages to be installed Muestra capturas de pantalla de los paquetes a instalar This plugin displays screenshots of the packages to be installed. It fetches the screenshots from http://screenshots.debian.net so a working internet connection is required. Este plugin muestra capturas (si las hay) de los paquetes a instalar. Estás imágenes se obtienen de http://screenshots.debian.net. Por lo tanto es necesaria conexión a Internet para acceder a éstas. Loading screenshot Establishing connection, please wait... Cargar imagen captura de pantalla Estableciendo la conexión, por favor espere... The screenshot size exceeds 10 MB. Something seems to be wrong here! Aborting Download. El tamaño de la imagen es superior a 10 MB. Algo parece estar mal aquí! Cancelando la descarga. Loading screenshot - Progress: Cargando imagen - Progreso: No screenshot available for Imagen no disponible An error occured while trying to download the screenshot: Ha ocurrido un error al intentar descargar la imagen: NPlugin::ScreenshotPluginContainer Screenshots not supported Capturador de pantalla no soportado Screenshot Plugins Plugin Capturador de pantalla