nemo-3.6.5/0000775000175000017500000000000013215733314011411 5ustar fabiofabionemo-3.6.5/COPYING0000664000175000017500000004311613215733314012451 0ustar fabiofabio GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. nemo-3.6.5/COPYING-DOCS0000664000175000017500000004330013215733314013172 0ustar fabiofabio GNU Free Documentation License Version 1.1, March 2000 Copyright (C) 2000 Free Software Foundation, Inc. 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five). C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled "History"; likewise combine any sections entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document 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. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation 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. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License". If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being LIST"; likewise for Back-Cover Texts. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. nemo-3.6.5/config.h.in0000664000175000017500000000733313215733314013442 0ustar fabiofabio/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Enable debug code */ #undef ENABLE_DEBUG /* define to enable the empty view that is used for performance measurement */ #undef ENABLE_EMPTY_VIEW /* always defined to indicate that i18n is enabled */ #undef ENABLE_NLS /* Define to enable Tracker support */ #undef ENABLE_TRACKER /* Defined if we meet the minimum version for g_content_type_get_generic_icon_name */ #undef GENERIC_ICON_API /* the gettext translation domain */ #undef GETTEXT_PACKAGE /* Define to 1 if you have the `bind_textdomain_codeset' function. */ #undef HAVE_BIND_TEXTDOMAIN_CODESET /* Define to 1 if you have the `dcgettext' function. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to enable xmp support */ #undef HAVE_EXEMPI /* Define to enable EXIF support */ #undef HAVE_EXIF /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `mallopt' function. */ #undef HAVE_MALLOPT /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if libselinux is available */ #undef HAVE_SELINUX /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_X11_XF86KEYSYM_H /* path for translations */ #undef LOCALEDIR /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Define to empty if `const' does not conform to ANSI C. */ #undef const nemo-3.6.5/debian/0000775000175000017500000000000013215733314012633 5ustar fabiofabionemo-3.6.5/test/0000775000175000017500000000000013215733314012370 5ustar fabiofabionemo-3.6.5/test/test-eel-editable-label.c0000664000175000017500000000260713215733314017107 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ #include #include #include static void quit (GtkWidget *widget, gpointer data) { gtk_main_quit (); } int main (int argc, char* argv[]) { GtkWidget *window; GtkWidget *label; GtkWidget *vbox; gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (quit), NULL); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); label = eel_editable_label_new ("Centered dsau dsfgsdfgoydsfiugy oiusdyfg iouysdf goiuys dfioguy siodufgy iusdyfgiu ydsf giusydf gouiysdfgoiuysdfg oiudyfsg Label"); gtk_widget_set_size_request (label, 200, -1); eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (label), TRUE); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4); label = eel_editable_label_new ("Left aligned label"); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4); label = eel_editable_label_new ("Right aligned label"); gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 4); gtk_window_set_default_size (GTK_WINDOW (window), 300, 300); gtk_widget_show_all (window); gtk_main (); return 0; } nemo-3.6.5/test/test.c0000664000175000017500000000406413215733314013517 0ustar fabiofabio#include "test.h" #include #include void test_init (int *argc, char ***argv) { gtk_init (argc, argv); eel_make_warnings_and_criticals_stop_in_debugger (); } int test_quit (int exit_code) { if (gtk_main_level () > 0) { gtk_main_quit (); } return exit_code; } void test_delete_event (GtkWidget *widget, GdkEvent *event, gpointer callback_data) { test_quit (0); } GtkWidget * test_window_new (const char *title, guint border_width) { GtkWidget *window; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); if (title != NULL) { gtk_window_set_title (GTK_WINDOW (window), title); } g_signal_connect (window, "delete_event", G_CALLBACK (test_delete_event), NULL); gtk_container_set_border_width (GTK_CONTAINER (window), border_width); return window; } GdkPixbuf * test_pixbuf_new_named (const char *name, float scale) { GdkPixbuf *pixbuf; char *path; g_return_val_if_fail (name != NULL, NULL); g_return_val_if_fail (scale >= 0.0, NULL); if (name[0] == '/') { path = g_strdup (name); } else { path = g_strdup_printf ("%s/%s", NEMO_DATADIR, name); } pixbuf = gdk_pixbuf_new_from_file (path, NULL); g_free (path); g_return_val_if_fail (pixbuf != NULL, NULL); if (scale != 1.0) { GdkPixbuf *scaled; float width = gdk_pixbuf_get_width (pixbuf) * scale; float height = gdk_pixbuf_get_width (pixbuf) * scale; scaled = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR); g_object_unref (pixbuf); g_return_val_if_fail (scaled != NULL, NULL); pixbuf = scaled; } return pixbuf; } GtkWidget * test_label_new (const char *text, gboolean with_background, int num_sizes_larger) { GtkWidget *label; if (text == NULL) { text = "Foo"; } label = gtk_label_new (text); return label; } void test_window_set_title_with_pid (GtkWindow *window, const char *title) { char *tmp; g_return_if_fail (GTK_IS_WINDOW (window)); tmp = g_strdup_printf ("%lu: %s", (gulong) getpid (), title); gtk_window_set_title (GTK_WINDOW (window), tmp); g_free (tmp); } nemo-3.6.5/test/test-nemo-directory-async.c0000664000175000017500000000406513215733314017571 0ustar fabiofabio#include #include #include #include #include void *client1, *client2; #if 0 static gboolean quit_cb (gpointer data) { gtk_main_quit (); return FALSE; } #endif static void files_added (NemoDirectory *directory, GList *added_files) { #if 0 GList *list; for (list = added_files; list != NULL; list = list->next) { NemoFile *file = list->data; g_print (" - %s\n", nemo_file_get_uri (file)); } #endif g_print ("files added: %d files\n", g_list_length (added_files)); } static void files_changed (NemoDirectory *directory, GList *changed_files) { #if 0 GList *list; for (list = changed_files; list != NULL; list = list->next) { NemoFile *file = list->data; g_print (" - %s\n", nemo_file_get_uri (file)); } #endif g_print ("files changed: %d\n", g_list_length (changed_files)); } static gboolean force_reload (NemoDirectory *directory) { g_print ("forcing reload!\n"); nemo_directory_force_reload (directory); return FALSE; } static void done_loading (NemoDirectory *directory) { static int i = 0; g_print ("done loading\n"); if (i == 0) { g_timeout_add (5000, (GSourceFunc)force_reload, directory); i++; } else { } } int main (int argc, char **argv) { NemoDirectory *directory; NemoQuery *query; client1 = g_new0 (int, 1); client2 = g_new0 (int, 1); gtk_init (&argc, &argv); query = nemo_query_new (); nemo_query_set_text (query, "richard hult"); directory = nemo_directory_get_by_uri ("x-nemo-search://0/"); nemo_search_directory_set_query (NEMO_SEARCH_DIRECTORY (directory), query); g_object_unref (query); g_signal_connect (directory, "files-added", G_CALLBACK (files_added), NULL); g_signal_connect (directory, "files-changed", G_CALLBACK (files_changed), NULL); g_signal_connect (directory, "done-loading", G_CALLBACK (done_loading), NULL); nemo_directory_file_monitor_add (directory, client1, TRUE, NEMO_FILE_ATTRIBUTE_INFO, NULL, NULL); gtk_main (); return 0; } nemo-3.6.5/test/test-nemo-search-engine.c0000664000175000017500000000222513215733314017156 0ustar fabiofabio#include #include static void hits_added_cb (NemoSearchEngine *engine, GSList *hits) { g_print ("hits added\n"); while (hits) { g_print (" - %s\n", (char *)hits->data); hits = hits->next; } } static void hits_subtracted_cb (NemoSearchEngine *engine, GSList *hits) { g_print ("hits subtracted\n"); while (hits) { g_print (" - %s\n", (char *)hits->data); hits = hits->next; } } static void finished_cb (NemoSearchEngine *engine) { g_print ("finished!\n"); // gtk_main_quit (); } int main (int argc, char* argv[]) { NemoSearchEngine *engine; NemoQuery *query; gtk_init (&argc, &argv); engine = nemo_search_engine_new (); g_signal_connect (engine, "hits-added", G_CALLBACK (hits_added_cb), NULL); g_signal_connect (engine, "hits-subtracted", G_CALLBACK (hits_subtracted_cb), NULL); g_signal_connect (engine, "finished", G_CALLBACK (finished_cb), NULL); query = nemo_query_new (); nemo_query_set_text (query, "richard hult"); nemo_search_engine_set_query (engine, query); g_object_unref (query); nemo_search_engine_start (engine); gtk_main (); return 0; } nemo-3.6.5/test/test-copy.c0000664000175000017500000000414413215733314014466 0ustar fabiofabio#include "test.h" #include #include #include static void copy_done (GHashTable *debuting_uris, gboolean success, gpointer data) { g_print ("Copy done\n"); } static void changed_cb (NemoProgressInfo *info, gpointer data) { g_print ("Changed: %s -- %s\n", nemo_progress_info_get_status (info), nemo_progress_info_get_details (info)); } static void progress_changed_cb (NemoProgressInfo *info, gpointer data) { g_print ("Progress changed: %f\n", nemo_progress_info_get_progress (info)); } static void finished_cb (NemoProgressInfo *info, gpointer data) { g_print ("Finished\n"); gtk_main_quit (); } int main (int argc, char* argv[]) { GtkWidget *window; GList *sources; GFile *dest; GFile *source; int i; GList *infos; NemoProgressInfoManager *manager; NemoProgressInfo *progress_info; test_init (&argc, &argv); if (argc < 3) { g_print ("Usage test-copy \n"); return 1; } sources = NULL; for (i = 1; i < argc - 1; i++) { source = g_file_new_for_commandline_arg (argv[i]); sources = g_list_prepend (sources, source); } sources = g_list_reverse (sources); dest = g_file_new_for_commandline_arg (argv[i]); window = test_window_new ("copy test", 5); gtk_widget_show (window); manager = nemo_progress_info_manager_new (); nemo_file_operations_copy (sources, NULL /* GArray *relative_item_points */, dest, GTK_WINDOW (window), copy_done, NULL); infos = nemo_progress_info_manager_get_all_infos (manager); if (infos == NULL) { g_object_unref (manager); return 0; } progress_info = NEMO_PROGRESS_INFO (infos->data); g_signal_connect (progress_info, "changed", (GCallback)changed_cb, NULL); g_signal_connect (progress_info, "progress-changed", (GCallback)progress_changed_cb, NULL); g_signal_connect (progress_info, "finished", (GCallback)finished_cb, NULL); gtk_main (); g_object_unref (manager); return 0; } nemo-3.6.5/test/Makefile.am0000664000175000017500000000121613215733314014424 0ustar fabiofabioNULL= AM_CPPFLAGS =\ -I$(top_srcdir) \ $(BASE_CFLAGS) \ $(COMMON_CFLAGS) \ $(NEMO_CFLAGS) \ $(WARN_CFLAGS) \ -DVERSION="\"$(VERSION)\"" \ -DNEMO_DATADIR=\""$(datadir)/nemo"\" \ $(NULL) LDADD =\ $(top_builddir)/libnemo-private/libnemo-private.la \ $(BASE_LIBS) \ $(COMMON_LIBS) \ $(NEMO_LIBS) \ $(NULL) noinst_PROGRAMS =\ test-nemo-search-engine \ test-nemo-directory-async \ test-nemo-copy \ test-eel-editable-label \ $(NULL) test_nemo_copy_SOURCES = test-copy.c test.c test_nemo_search_engine_SOURCES = test-nemo-search-engine.c test_nemo_directory_async_SOURCES = test-nemo-directory-async.c EXTRA_DIST = \ test.h \ $(NULL) nemo-3.6.5/test/test.h0000664000175000017500000000337113215733314013524 0ustar fabiofabio#ifndef TEST_H #define TEST_H #include #include #include #include #include void test_init (int *argc, char ***argv); int test_quit (int exit_code); void test_delete_event (GtkWidget *widget, GdkEvent *event, gpointer callback_data); GtkWidget *test_window_new (const char *title, guint border_width); void test_gtk_widget_set_background_image (GtkWidget *widget, const char *image_name); void test_gtk_widget_set_background_color (GtkWidget *widget, const char *color_spec); GdkPixbuf *test_pixbuf_new_named (const char *name, float scale); GtkWidget *test_label_new (const char *text, gboolean with_background, int num_sizes_larger); void test_pixbuf_draw_rectangle_tiled (GdkPixbuf *pixbuf, const char *tile_name, int x0, int y0, int x1, int y1, int opacity); void test_window_set_title_with_pid (GtkWindow *window, const char *title); #endif /* TEST_H */ nemo-3.6.5/files/0000775000175000017500000000000013215733314012513 5ustar fabiofabionemo-3.6.5/files/usr/0000775000175000017500000000000013215733314013324 5ustar fabiofabionemo-3.6.5/files/usr/share/0000775000175000017500000000000013215733314014426 5ustar fabiofabionemo-3.6.5/files/usr/share/nemo/0000775000175000017500000000000013215733314015364 5ustar fabiofabionemo-3.6.5/files/usr/share/nemo/script-info.md0000664000175000017500000000172413215733314020147 0ustar fabiofabio#### Scripts When executed from a local folder, scripts will be passed the selected file names. When executed from a remote folder (e.g. a folder showing web or ftp content), scripts will be passed no parameters. In all cases, the following environment variables will be set by Nemo, which the scripts may use: - NEMO_SCRIPT_SELECTED_FILE_PATHS: newline-delimited paths for selected files (only if local) - NEMO_SCRIPT_SELECTED_URIS: newline-delimited URIs for selected files - NEMO_SCRIPT_CURRENT_URI: URI for current location - NEMO_SCRIPT_WINDOW_GEOMETRY: position and size of current window - NEMO_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS: newline-delimited paths for selected files in the inactive pane of a split-view window (only if local) - NEMO_SCRIPT_NEXT_PANE_SELECTED_URIS: newline-delimited URIs for selected files in the inactive pane of a split-view window - NEMO_SCRIPT_NEXT_PANE_CURRENT_URI: URI for current location in the inactive pane of a split-view window nemo-3.6.5/files/usr/share/nemo/actions/0000775000175000017500000000000013215733314017024 5ustar fabiofabionemo-3.6.5/files/usr/share/nemo/actions/add-desklets.nemo_action0000664000175000017500000001012413215733314023603 0ustar fabiofabio[Nemo Action] Name=Add Desklets Comment=Add Cinamon desklets Exec=cinnamon-settings desklets Selection=None Extensions=any; Icon-Name=cs-desklets Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; Name[eu]=Gehitu desklet-ak Name[vi]=Thêm Tiểu trình màn hình Name[nl]=Minitoepassingen toevoegen Name[gd]=Cuir desktlets ris Name[bg]=ДобавÑне на деÑклети Name[fi]=Lisää työpöytäsovelmia Name[gl]=Engadir trebellos Name[lt]=PridÄ—ti ekrano programÄ—les Name[ga]=Cuir le Deiscíní Name[ca]=Afegeix miniaplicacions d'escriptori Name[en_GB]=Add Desklets Name[ko]=ë°ìФí¬ë¦¿ 추가 Name[hr]=Dodaj desklete Name[sl]=Dodaj aplete namizja Name[el]=ΠÏοσθήκη εφαÏμογών οθόνης Name[af]=Voeg Desklets By Name[pt_BR]=Adicionar desklets Name[nb]=Legg til skrivebordsprogrammer Name[es]=Añadir desklets Name[de]=Desklets hinzufügen Name[bn]=ডেসà§à¦•লেট যà§à¦•à§à¦¤ করà§à¦¨ Name[th]=เพิ่มเดสà¸à¹Œà¹€à¸¥à¹‡à¸• Name[cs]=PÅ™idat miniaplikace plochy Name[ro]=Adaugă deskleturi Name[it]=Aggiungi Desklet Name[tr]=Masaüstü Uygulamacıkları Ekle Name[zh_TW]=加入桌é¢å°ç¨‹å¼ Name[tg]=Илова кардани барномаҳои мизи корӣ Name[en_AU]=Add Desklets Name[da]=Tilføj skrivebordsprogrammer Name[am]=ዴስክሌትስ መጨመሪያ Name[sk]=PridaÅ¥ Desklet Name[fr_CA]=Ajouter des desklets Name[sr]=Додај Ñправице Name[zh_HK]=新增桌é¢å°å·¥å…· Name[ia]=Adder desklets Name[is]=Bæta við skjáborðsgræjum (desklets) Name[bs]=Dodaj Desklet-e Name[cy]=Ychwanegu Desgynau Name[ja]=デスクレットを追加 Name[sv]=Lägg till skrivbordsprogram Name[et]=Lisa Desklet Name[uk]=Додати деÑклети Name[hu]=Asztalkalmazások hozzáadása Name[ms]=Tambah Desklet Name[ur]=ڈیسک لیٹ شامل کریں Name[fr]=Ajouter des desklets Name[pl]=Dodaj desklety Name[jv]=Kabeh Desklet Name[pt]=Adicionar Mini-Aplicações Name[zh_CN]=添加桌é¢å°å·¥å…· Name[ru]=Добавить деÑклеты Name[id]=Tambah Desklet Name[be]=Дадаць дÑÑклеты Name[he]=Add Desklets Comment[eu]=Gehitu Cinnamon desklet-ak Comment[vi]=Thêm tiểu dụng màn hình Cinnamon Comment[nl]=Minitoepassingen toevoegen aan Cinnamon Comment[gd]=Cuir ris desklets Cinnamon Comment[bg]=Добави деÑклети на Cinnamon Comment[fi]=Lisää Cinnamon työpöytäsovelmia Comment[lt]=PridÄ—ti Cinnamon ekrano programÄ—les Comment[ca]=Afegeix miniaplicacions d'escriptori de Cinnamon Comment[en_GB]=Add Cinamon desklets Comment[ko]=시나몬 ë°ìФí¬ë¦¿ ë”하기 Comment[hr]=Dodaj Cinnamon desklete Comment[el]=ΠÏοσθήκη μικÏοεφαÏμογής στην επιφάνεια εÏγασίας Comment[pt_BR]=Adicionar desklets do Cinnamon Comment[es]=Añadir desklets de Cinnamon Comment[de]=Cinamon-Desklets hinzufügen Comment[th]=เพิ่มเดสà¸à¹Œà¹€à¸¥à¹‡à¸• Cinnamon Comment[cs]=PÅ™idat Cinnamon miniaplikace plochy Comment[ro]=Adaugă deskleturi Cinnamon Comment[it]=Aggiungi desklet di Cinnamon Comment[tr]=Cinnamon masaüstü uygulamacıkları ekle Comment[zh_TW]=加入 Cinamon 桌é¢å°ç¨‹å¼ Comment[da]=Tilføj Cinnamon-skrivebordsprogrammer Comment[am]=የ ሲናሞን ዴስክሌትስ መጨመሪያ Comment[sk]=PridaÅ¥ desklety prostredia Cinnamon Comment[fr_CA]=Ajouter des desklets Cinnamon Comment[sr]=Додајте Циметове Ñправице на радну површ Comment[zh_HK]=新增 Cinnamon 桌é¢å°å·¥å…· Comment[ia]=Adder le desklets de Cinamon Comment[is]=Bæta við Cinnamon skjáborðsgræjum (desklets) Comment[cy]=Ychwanegu desgledi Cinnamon Comment[ja]=Cinnamonデスクレットを追加 Comment[sv]=Lägg till Cinnamon skrivbordsprogram Comment[uk]=Додати деÑклети Cinnamon Comment[hu]=Cinnamon Asztalkalmazások hozzáadása Comment[ms]=Tambah desklet Cinamon Comment[ur]=سنامون ڈیسک لیٹ شامل کریں Comment[fr]=Ajouter des desklets Cinnamon Comment[pl]=Dodaj desklety Cinnamon Comment[pt]=Adicionar desklets Cinnamon Comment[zh_CN]=添加 Cinamon 桌é¢å°å·¥å…· Comment[ru]=Добавить деÑклеты Cinnamon nemo-3.6.5/files/usr/share/nemo/actions/91_delete-workspace.nemo_action0000664000175000017500000001057513215733314025020 0ustar fabiofabio[Nemo Action] Name=Remove workspace Comment=Remove the currently active workspace Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.RemoveCurrentWorkspace >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon;gsettings org.cinnamon number-workspaces i gt 1; Active=false Name[eu]=Kendu laneko area Name[vi]=Bá» vùng làm việc Name[nl]=Werkblad verwijderen Name[gd]=Thoir an rum-obrach air falbh Name[bg]=Премахване на работно мÑÑто Name[fi]=Poista työtila Name[gl]=Eliminar o espazo de traballo Name[lt]=Å alinti darbo sritį Name[ca]=Elimina espai de treball Name[en_GB]=Remove workspace Name[ko]=작업 공간 제거 Name[hr]=Ukloni radni prostor Name[el]=ΑπομακÏÏνση/ΑφαίÏεση του χώÏου εÏγασίας Name[pt_BR]=Remover espaço de trabalho Name[es]=Eliminar área de trabajo Name[de]=Arbeitsfläche entfernen Name[th]=ลบพื้นที่ทำงาน Name[cs]=Odstranit pracovní plochu Name[ro]=Elimină spaÅ£iu de lucru Name[it]=Rimuovi spazio di lavoro Name[tr]=Çalışma alanını sil Name[zh_TW]=ç§»é™¤å·¥ä½œå€ Name[da]=Fjern arbejdsomrÃ¥de Name[am]=የ ስራ ቦታ ማስወገጃ Name[sk]=OdstrániÄ› pracovnú plochu Name[fr_CA]=Supprimer l'espace de travail Name[sr]=Уклони радни проÑтор Name[ta]=பணிதளதà¯à®¤à¯ˆ நீகà¯à®•௠Name[zh_HK]=ç§»é™¤å·¥ä½œå€ Name[ia]=Remover le spatio de labor Name[is]=Fjarlægja vinnusvæði Name[cy]=Dileu gweithle Name[ja]=ワークスペースã®å‰Šé™¤ Name[sv]=Ta bort arbetsyta Name[et]=Kustuta tööala Name[uk]=Вилучити робочий проÑтір Name[hu]=Munkaterület eltávolítása Name[ms]=Hapus kawasan kerja Name[ur]=ورک سپیس Ûٹادیں Name[fr]=Supprimer l'espace de travail Name[pl]=UsuÅ„ przestrzeÅ„ roboczÄ… Name[pt]=Remover área de trabalho Name[zh_CN]=移除工作区 Name[ru]=Удалить рабочее меÑто Comment[eu]=Kendu uneko laneko area aktiboa Comment[vi]=Bá» vùng làm việc hiện hoạt Comment[nl]=Verwijder het thans actieve werkblad Comment[gd]=Thoir air falbh an rum-obrach a tha gnìomhach an-dràsta Comment[bg]=Премахване на актовното работно мÑÑто Comment[fi]=Poista nykyinen aktiivinen työtila Comment[gl]=Eliminar o espazo de traballo activo Comment[lt]=Å alinti esamÄ… aktyviÄ… darbo sritį Comment[ca]=Elimina l'espai de treball actiu Comment[en_GB]=Remove the currently active workspace Comment[ko]=현재 사용 ì¤‘ì¸ ìž‘ì—… ê³µê°„ì„ ì œê±°í•©ë‹ˆë‹¤ Comment[hr]=Ukloni trenutno aktivni radni prostor Comment[el]=ΑπομακÏÏνση/ΑφαίÏεση του Ï„Ïέχοντος ενεÏÎ³Î¿Ï Ï‡ÏŽÏου εÏγασίας Comment[pt_BR]=Remova o espaço de trabalho ativo no momento Comment[es]=Eliminar el área de trabajo activa Comment[de]=Die aktuell aktive Arbeitsfläche entfernen Comment[th]=ลบพื้นที่ทำงานที่ใช้งานอยู่ตอนนี้ Comment[cs]=Odstranit pracovní plochu, na které se nacházíte Comment[ro]=Elimină spaÅ£iul de lucru activ în acest moment Comment[it]=Rimuovi lo spazio di lavoro corrente Comment[tr]=Åžu an aktif olan çalışma alanını sil Comment[zh_TW]=移除目å‰ä½¿ç”¨ä¸­çš„å·¥ä½œå€ Comment[da]=Fjern det nuværende aktive arbejdsomrÃ¥de Comment[am]=የ አáˆáŠ‘áŠ• ንበየ ስራ ቦታ ማስወገጃ Comment[sk]=OdstrániÅ¥ momentálne aktívnu plochu Comment[fr_CA]=Supprimer l'espace de travail actif Comment[sr]=Уклоните тренутно активан радни проÑтор Comment[zh_HK]=移除目å‰ä½œç”¨ä¸­çš„å·¥ä½œå€ Comment[ia]=Remover le spatio de labor currentemente active Comment[is]=Fjarlægja vinnusvæðið sem er virkt núna Comment[cy]=Tynnu gweithle gweithredol cyfredol Comment[ja]=ç¾åœ¨ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ–ãªãƒ¯ãƒ¼ã‚¯ã‚¹ãƒšãƒ¼ã‚¹ã®å‰Šé™¤ Comment[sv]=Ta bort den nuvarande aktiva arbetsytan Comment[uk]=Вилучити поточний робочий проÑтір Comment[hu]=Aktív munkaterület eltávolítása Comment[ms]=Hapus kawasan kerja semasa Comment[ur]=Ù…ÙˆØ¬ÙˆØ¯Û Ø²ÛŒØ± عمل ورک سپیس Ú©Ùˆ Ûٹا دیں Comment[fr]=Supprimer l'espace de travail actif Comment[pl]=UsuÅ„ obecnie aktywnÄ… przestrzeÅ„ roboczÄ… Comment[pt]=Remover a área de trabalho activa no momento Comment[zh_CN]=ç§»é™¤å½“å‰æ´»è·ƒçš„工作区 Comment[ru]=Удалить текущее рабочее меÑто nemo-3.6.5/files/usr/share/nemo/actions/new-launcher.nemo_action0000664000175000017500000001302613215733314023633 0ustar fabiofabio[Nemo Action] Name=Create a new l_auncher here... Comment=Create a new launcher in this folder Exec=cinnamon-desktop-editor -mnemo-launcher -d"%P" Selection=None Stock-Id=gtk-add Extensions=any; Dependencies=cinnamon-desktop-editor; Conditions=desktop; Name[eu]=Sortu _abiarazle berri bat hemen... Name[vi]=Tạo trình _khởi chạy má»›i ở đây... Name[nl]=Maak hier een nieuwe starter... Name[gd]=Cruthaich lòinsear ùr an-seo... Name[bg]=Създаване на нов Ñ_тартер тук... Name[fi]=Luo uusi k_äynnistin... Name[gl]=Crear aquí un novo _iniciador Name[lt]=Sukurti Äia n_aujÄ… leistukÄ… Name[ca]=Crea aquí un l_lançador nou... Name[en_GB]=Create a new l_auncher here... Name[ko]=ì—¬ê¸°ì— ìƒˆ 런처 만들기(_A)... Name[hr]=Stvori novi p_okretaÄ ovdje... Name[sl]=Ustvari nov z_aganjalnik tukaj ... Name[el]=ΔημιουÏγία ενός νέου ε_κκινητή εδώ... Name[pt_BR]=Criar novo l_ançador aqui... Name[es]=Crear un l_anzador nuevo aquí... Name[de]=Neuen _Starter hier erstellen … Name[th]=_สร้างลอนเชอร์ใหม่ที่นี่... Name[cs]=VytvoÅ™it zde nový s_pouÅ¡těą Name[ro]=Creează un l_ansator nou aici... Name[it]=Crea un nuovo l_anciatore qui... Name[tr]=Burada yeni bir b_aÅŸlatıcı oluÅŸtur... Name[zh_TW]=在此建立新啟動器(_A)... Name[tg]=Эҷод кардани о_ғозкунандаи нав дар ин ҷо... Name[da]=Opret en ny _programstarter her ... Name[am]=አዲስ ማ_ስáŠáˆ» እዚህ መáጠሪያ... Name[sk]=VytvoriÅ¥ sem nový spúšťaÄ Name[fr_CA]=Créer un nouveau l_anceur Name[sr]=Овде направи нови _покретач... Name[zh_HK]=在此建立新啟動器(_A)... Name[ia]=Crear un nove l_anceator ci... Name[ast]=Crear un ll_anzador nuevu equí... Name[is]=Búa til nýjan _forritaræsi hér... Name[bs]=Napravi novi p_okretaÄ ovdje... Name[cy]=Creu C_ychwynnydd yma... Name[ja]=æ–°ã—ã„ランãƒãƒ£ã‚’ã“ã“ã«ä½œæˆ (_A) ... Name[sv]=Skapa en ny l_auncher här... Name[et]=Uue käivitaja _loomine... Name[uk]=Створити нового пуÑкача тут... Name[hu]=In_dító létrehozása… Name[ms]=Cipta pe_lancar baru disini... Name[ur]=ÛŒÛØ§Úº نیا لا_نچر بنائیں... Name[fr]=Créer un nouveau l_anceur Name[pl]=Utwórz nowy _aktywator tutaj... Name[pt]=Criar um novo L_ançador aqui... Name[zh_CN]=在此创建一个新的å¯åЍ噍... Name[ru]=Создать к_нопку запуÑка здеÑÑŒ... Name[id]=Buat sebuah pel_uncur disini... Name[be]=Стварыць новы Ñтартар тут... Name[he]=יצירת מ_שגר חדש ×›×ן.. Comment[eu]=Sortu abiarazle berri bat karpeta honetan Comment[vi]=Tạo trình khởi chạy má»›i trong thư mục này Comment[nl]=Maak een nieuwe starter in deze map Comment[gd]=Cruthaich lòinsear ùr anns a' phasgan seo Comment[bg]=Създаване на нов Ñтартер в тази папка Comment[fi]=Luo uusi käynnistin tähän kansioon Comment[gl]=Crear un novo iniciador neste cartafol Comment[lt]=Sukurti Å¡iame aplanke naujÄ… leistukÄ… Comment[ca]=Crear un nou llançador en aquesta carpeta Comment[en_GB]=Create a new launcher in this folder Comment[ko]=ì´ í´ë”ì— ìƒˆ 런처 만들기 Comment[hr]=Stvori novi pokretaÄ u ovoj mapi Comment[sl]=Ustvari nov zaganjalnik v tej mapi Comment[el]=ΔημιουÏγία ενός νέου εκκινητή σε αυτό το φάκελο Comment[pt_BR]=Criar um novo lançador nesta pasta Comment[es]=Crear un lanzador nuevo en esta carpeta Comment[de]=Einen neuen Starter in diesem Ordner erstellen Comment[th]=สร้างลอนเชอร์ใหม่ในโฟลเดอร์นี้ Comment[cs]=Vytvoří nový spouÅ¡tÄ›Ä v této složce Comment[ro]=Creează un lansator nou în acest dosar Comment[it]=Crea un nuovo lanciatore in questa cartella Comment[tr]=Bu dizin içinde yeni bir baÅŸlatıcı oluÅŸtur Comment[zh_TW]=在此資料夾建立新啟動器 Comment[tg]=Эҷод кардани оғозкунандаи нав дар ин ҷузвдон Comment[da]=Opret en ny programstarter i denne mappe Comment[am]=በዚህ áŽáˆá‹°áˆ­ á‹áˆµáŒ¥ ማስጀመሪያ መáጠሪያ Comment[sk]=VytvoriÅ¥ nový spúšťaÄ do tohto prieÄinka Comment[fr_CA]=Créer un nouveau lanceur dans ce dossier Comment[sr]=Ðаправи нови покретач у овој фаÑцикли Comment[zh_HK]=在此資料夾è£å»ºç«‹æ–°å•Ÿå‹•器 Comment[ia]=Crear un nove lanceator in ce plica Comment[ast]=Crea un llanzador nuevu nesta carpeta Comment[is]=Búa til nýjan forritaræsi í þessari möppu Comment[bs]=Napravi novi p_okretaÄ u ovom direktoriju Comment[cy]=Creu cychwynydd newydd yn y ffolder Comment[ja]=æ–°ã—ã„ランãƒãƒ£ã‚’ã“ã®ãƒ•ォルダã«ä½œæˆ Comment[sv]=Skapa en ny programstartare i denna mapp Comment[et]=Sellesse kausta uue käivitaja loomine Comment[uk]=Створити нового пуÑкача у цій теці Comment[hu]=Új indító létrehozása ebben a mappában Comment[ms]=Cipta pelancar baru dalam folder ini Comment[ur]=اس Ùولڈر میں نیا لانچر بنائیں Comment[fr]=Créer un nouveau lanceur dans ce dossier Comment[pl]=Utwórz nowy aktywator w tym katalogu Comment[pt]=Criar um novo Lançador neste directório Comment[zh_CN]=在此文件夹中创建一个新的å¯åЍ噍 Comment[ru]=Создать _кнопку запуÑка в текущей папке Comment[id]=Buat sebuah peluncur baru didalam folder ini Comment[be]=Стварыць новы Ñтартар у гÑтай папцы Comment[he]=יצירת משגר חדש בתיקייה זו nemo-3.6.5/files/usr/share/nemo/actions/send-by-mail.nemo_action0000664000175000017500000002020513215733314023521 0ustar fabiofabio[Nemo Action] Name=Send by Email Name[am]=በ ኢሜይሠመላኪያ Name[ar]=إرسال بالبريد الالكتروني Name[as]=ই-মেইলৰ দà§à¦¬à¦¾à§°à¦¾ পà§à¦°à§‡à§°à¦£ কৰক Name[ast]=Unviar per corréu Name[az]=Epoçtla göndÓ™r Name[be]=ДаÑлаць праз email Name[bg]=Изпращане по имейл Name[bn]=ইমেল দà§à¦¬à¦¾à¦°à¦¾ পাঠানো হয়েছে Name[bs]=PoÅ¡alji e-poÅ¡tom Name[ca]=Envia per correu electrònic Name[ca@valencia]=Enviar per correu Name[cs]=Odeslat e-mailem Name[cy]=Anfon drwy E-bost Name[da]=Send med e-mail Name[de]=Per E-Mail versenden Name[el]=Αποστολή με email Name[eo]=Elsendi per retpoÅto Name[es]=Enviar por correo Name[et]=Saada e-kirjaga Name[eu]=Bidali posta bidez Name[fa]=ارسال از طریق ایمیل Name[fi]=Lähetä sähköpostilla Name[fil]=Ipadala sa pamamagitan ng Email Name[fr]=Envoyer par email Name[fr_CA]=Envoyer par email Name[frp]=Mandar pèr mèssâjo Name[fy]=Ferstjoere oer Email Name[gd]=Cuir air a' phost-d Name[gl]=Enviar por correo-e Name[he]=שלח בדו×"ל Name[hr]=PoÅ¡alji e-poÅ¡tom Name[hu]=Küldés levélben Name[hy]=ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ էլ․ ÖƒÕ¸Õ½Õ¿Õ¸Õ¾ Name[ia]=Invia per e-posta Name[id]=Dikirim oleh Email Name[is]=Senda með tölvupósti Name[it]=Invia per Email Name[ja]=é›»å­ãƒ¡ãƒ¼ãƒ«ã§é€ä¿¡ Name[ka]=ელექტრáƒáƒœáƒ£áƒšáƒ˜ ფáƒáƒ¡áƒ¢áƒ˜áƒ— გáƒáƒ’ზáƒáƒ•ნრName[kab]=Azen s yimayl Name[kk]=Электронды пошта арқылы жіберу Name[ko]=ì´ë©”ì¼ë¡œ 보내기 Name[ksw]=sgur kaw ploe email Name[ku]=Bi Epeyamê bişîne Name[lb]=Per Email verschécken Name[lo]=ສົ່ງໂດàºàº­àºµà»€àº¡àº¥ Name[lt]=Siųsti el. paÅ¡tu Name[lv]=SÅ«tÄ«t pa e-pastu Name[mg]=Alefa imailaka Name[mn]=Е-майлÑÑÑ€ илгÑÑÑ… Name[mr]=ईमेल दà¥à¤µà¤¾à¤°à¥‡ पाठवा Name[ms]=Hantar melalui Emel Name[my]=အီးမေးလ်ဖြင့် ပေးပို့ပါ Name[nb]=Send med e-post Name[nds]=Sende per E-Mail Name[ne]=इमेल मारà¥à¤«à¤¤ पठाउनà¥à¤¹à¥‹à¤¸à¥ Name[nl]=Verzenden via e-mail Name[oc]=Mandar per corrièr electronic Name[om]=ergaa-e dhaan ergi Name[pa]=ਈਮੇਲ ਰਾਹੀਂ ਭੇਜੋ Name[pap]=Manda via Email Name[pl]=WyÅ›lij e-mailem Name[pt]=Enviar por correio eletrónico Name[pt_BR]=Enviar por e-mail Name[pt_PT]=Enviar por correio eletrónico Name[ro]=TrimiteÈ›i prin email Name[ru]=Отправить по Ñлектронной почте Name[sc]=Imbia cun s'Email Name[si]=විද්â€à¶ºà·”à¶­à·Š à¶­à·à¶´à·‘à¶½ මගින් යව෠ඇත Name[sk]=OdoslaÅ¥ cez Email Name[sl]=PoÅ¡lji po e-poÅ¡ti Name[sq]=Dërgo me Email Name[sr]=Пошаљи е-поштом Name[sr@latin]=Пошаљи е-поштом Name[sv]=Skicka via e-post Name[sw]=Tuma kwa Barua Pepe Name[ta]=மினà¯à®©à®žà¯à®šà®²à¯ மூலம௠அனà¯à®ªà¯à®ªà¯ Name[tg]=ФириÑтодан таваÑÑути почтаи Ñлектронӣ Name[th]=ส่งทางอีเมล์ Name[tl]=Ipadala sa pamamagitan ng Email Name[tr]=E-posta ile Gönder Name[tt]=Электрон почта аша җибәрү Name[uk]=ÐадіÑлати поштою Name[ur]=ای میل Ú©Û’ ذریعے بھیجئے Name[uz]=Электрон хат юбориш Name[vi]=Gá»­i bằng Äiện thư Name[zh_CN]=通过电å­é‚®ä»¶å‘é€ Name[zh_HK]=以電å­éƒµä»¶å‚³é€ Name[zh_TW]=以 email å‚³é€ Comment=Send as email attachment Comment[am]=እንደ ኢሜይሠማያያዣመላኪያ Comment[ar]=إرسال كمرÙÙ‚ للبريد الإلكتروني Comment[as]=ই-মেইলৰ সংযোজন ৰূপে পà§à¦°à§‡à§°à¦£ কৰক Comment[ast]=Unviar como axuntu de corréu Comment[be]=ДаÑлаць Ñк email-далучÑнне Comment[bg]=Изпращане като прикачен файл по имейл Comment[bn]=ইমেইল à¦à¦Ÿà¦¾à¦šà¦®à§‡à¦¨à§à¦Ÿ হিসেবে পাঠানো Comment[bs]=PoÅ¡alji kao prilog e-poÅ¡te Comment[ca]=Envia com a adjunt de correu electrònic Comment[ca@valencia]=Enviar com adjunt de correu Comment[cs]=Odeslat jako přílohu e-mailu Comment[cy]=Anfon fel atodiad e-bost Comment[da]=Send som vedhæftet fil i en e-mail Comment[de]=Als E-Mail-Anhang versenden Comment[el]=ΕπισÏναψη σε email και αποστολή Comment[eo]=Elsendi per retpoÅta afiÅo Comment[es]=Enviar como adjunto de correo Comment[et]=Saada e-kirja manusena Comment[eu]=Bidali posta-eranskin gisa Comment[fa]=ÙØ±Ø³ØªØ§Ø¯Ù† به عنوان پیوست ایمیل Comment[fi]=Lähetä sähköpostin liitteenä Comment[fil]=Ipadala bilang isang email attachment Comment[fr]=Envoyer en tant que pièce jointe Comment[fr_CA]=Envoyer en tant que pièce jointe Comment[frp]=Mandar como pièce juenta Comment[fy]=Ferstjoere taheakke oan in Email Comment[gd]=Cuir mar cheanglachan puist-d Comment[gl]=Enviar como anexo do correo Comment[he]=שלח כמצורף בדו×"ל Comment[hr]=PoÅ¡alji kao privitak e-poÅ¡te Comment[hu]=Küldés levélmellékletként Comment[hy]=ÕˆÖ‚Õ²Õ¡Ö€Õ¯Õ¥Õ¬ Ö†Õ¡ÕµÕ¬ էլ․ ÖƒÕ¸Õ½Õ¿Õ¸Õ¾ Comment[ia]=Invia per attachamento de e-posta Comment[id]=Kirim sebagai email attachment Comment[is]=Senda sem viðhengi í tölvupósti Comment[it]=Invia come allegato email Comment[ja]=é›»å­ãƒ¡ãƒ¼ãƒ«ã«æ·»ä»˜ã—ã¦é€ä¿¡ Comment[ka]=გáƒáƒ’ზáƒáƒ•ნრელექტრáƒáƒœáƒ£áƒšáƒ˜ ფáƒáƒ¡áƒ¢áƒ˜áƒ¡ მიმáƒáƒ’რებული ფáƒáƒ˜áƒšáƒ˜áƒ¡ სáƒáƒ®áƒ˜áƒ— Comment[kab]=Azen am umedday n yimayl Comment[kk]=Электрондық хатқа Ñалым ретінде жіберу Comment[ko]=ì´ë©”ì¼ì— 첨부해서 보내기 Comment[ksw]=sgur attachment kaw ploe email Comment[lb]=Als Email-Unhang verschécken Comment[lo]=ສົ່ງເປັນສິ່ງທີ່à»àº™àºšàº¡àº²àºàº±àºšàº­àºµà»€àº¡àº¥ Comment[lt]=IÅ¡siųsti kaip el. laiÅ¡ko priedÄ… Comment[lv]=SÅ«tÄ«t kÄ e-pasta pielikumu Comment[mg]=Alefa amin'ny mailaka Comment[mr]=ईमेल अटà¥à¤Ÿà¤šà¤‚मेनà¥à¤Ÿ मà¥à¤¹à¤£à¥‚न पाठवा Comment[ms]=Hantar sebagai lampiran emel Comment[my]=အီးမေးလ် ဖြင့် á€á€½á€²á€•ို့ပါ Comment[nb]=Send som e-postvedlegg Comment[nds]=Sende als E-Mail Anhang Comment[ne]=इमेल सङà¥à¤²à¤—à¥à¤¨à¤¤à¤¾à¤•ो रूपमा पठाउनà¥à¤¹à¥‹à¤¸à¥ Comment[nl]=Verzenden als e-mailbijlage Comment[oc]=Mandar en tant que pèça junta Comment[om]=Akka walqabsiisa ergaa-e dhaan ergi Comment[pa]=ਈਮੇਲ ਨਾਲ ਨੱਥੀ ਕਰਕੇ ਭੇਜੋ Comment[pap]=Manda manera un bijlage di email Comment[pl]=WyÅ›lij jako załącznik do e-maila Comment[pt]=Enviar como anexo eletrónico Comment[pt_BR]=Enviar como anexo de e-mail Comment[pt_PT]=Enviar como anexo eletrónico Comment[ro]=TrimiteÈ›i ca ataÈ™ament la email Comment[ru]=Отправить в качеÑтве Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ðº Ñлектронному пиÑьму Comment[sc]=Imbia che allongiadu de s'email Comment[sk]=OdoslaÅ¥ ako prílohu emailu Comment[sl]=PoÅ¡lji kot prilogo k e-poÅ¡ti Comment[sq]=Dërgoje si bashkangjitje në email Comment[sr]=Пошаљи као прилог е-поште Comment[sr@latin]=Пошаљи као прилог е-поште Comment[sv]=Skicka som epost-bilaga Comment[ta]=மினà¯à®©à®žà¯à®šà®²à¯ இணைபà¯à®ªà®¾à®• அனà¯à®ªà¯à®ªà¯ Comment[tg]=ФириÑтодан ҳамчун замимаи почтаи Ñлектронӣ Comment[th]=ส่งเป็นสิ่งที่à¹à¸™à¸šà¸¡à¸²à¸à¸±à¸šà¸­à¸µà¹€à¸¡à¸¥ Comment[tl]=Ipadala bilang isang email attachment Comment[tr]=E-posta eki olarak gönder Comment[tt]=Электрон хатта Ñалынма буларак җибәрү Comment[uk]=ÐадіÑлати Ñк Ð²ÐºÐ»Ð°Ð´ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти Comment[ur]=ای میل Ú©Û’ ساتھ جوڑ Ú©Û’ بھیجیں Comment[uz]=Электрон хатга илова Ñифатида юбориш Comment[vi]=Gá»­i dưới dạng đính kèm Ä‘iện thư Comment[zh_CN]=作为电å­é‚®ä»¶é™„ä»¶å‘é€ Comment[zh_HK]=以電å­éƒµä»¶é™„ä»¶å‚³é€ Comment[zh_TW]=以 email é™„åŠ æª”æ¡ˆå‚³é€ Quote=double Exec= Icon-Name=mail-attachment Selection=NotNone Extensions=nodirs; Dependencies=xdg-email Separator=/#/ nemo-3.6.5/files/usr/share/nemo/actions/sample.nemo_action0000664000175000017500000000771113215733314022530 0ustar fabiofabio[Nemo Action] ############################################# #### DEBUGGING: #### #### Run Nemo with the environment #### variable NEMO_ACTION_VERBOSE #### set to get useful log output #### for debugging your actions #### #### i.e. $ nemo --quit #### $ NEMO_ACTION_VERBOSE=1 nemo ############################################# # Whether this action is active. For troubleshooting. # Optional - if this field is omitted, the action will be active Active=false # Standard tokens that can be used in the Name, Comment (tooltip) and Exec fields: # # %U - insert URI list of selection # %F - insert path list of selection # %P - insert path of parent (current) directory # %f or %N (deprecated) - insert display name of first selected file # %p - insert display name of parent directory # %D - insert device path of file (i.e. /dev/sdb1) # The name to show in the menu, locale supported with standard desktop spec. # **** REQUIRED **** Name=Test Custom Action applied to %N # Tool tip, locale supported (Appears in the status bar) Comment=This is a test for Nemo actions. Action will be applied to %N # What to run. Enclose in < > to run an executable that resides in the actions folder. # **** REQUIRED **** #Exec=gedit %F Exec= # Icon name to use in the menu - must be a theme icon name Icon-Name=folder # Gtk Stock ID to use for the icon. Note if both Icon-name and Stock-Id are # defined, the Stock-Id takes precedence. #Stock-Id=gtk-cdrom # What type selection: [s]ingle, [m]ultiple, any, notnone, none (background click), or # a number representing how many files must be selected to display. # ****** REQUIRED ******* Selection=m # What extensions to display on - this is an array, end with a semicolon # Single entry options, ending in a semicolon: # "dir" for directory selection # "none" for no extension. # "nodirs" for any selection, but not including directories. # "any" for any file type, including directories. # Individual specific extensions can be a semicolon-terminated list # Extensions are NOT case sensitive. jpg will match JPG, jPg, jpg, etc.. # **** EITHER EXTENSIONS OR MIMETYPES IS REQUIRED ***** Extensions=any; # What mime-types to display on - this is an array, end with a semicolon # **** EITHER EXTENSIONS OR MIMETYPES IS REQUIRED ***** #Mimetypes=text/plain; # Separator to use (if any) - add a string to insert between path/url entries # in the exec line. Optional - if you leave this out, a space is inserted. # Note you can have trailing spaces here. #Separator=, # Quote type to use (if any) - enclose paths/urls with quotes. Optional - defaults # to no quotes. # Can be: single, double, backtick #Quote=double # Dependencies - program executables required for this action to work. Nemo will # Search in the path for these program(s) and not display the action if any are missing. # You can also supply an absolute path to a file (i.e. /usr/lib/gvfs/gvfsd-archive) to check # instead of or in addition to an executable in the path. # This is an array, separate entries with semi-colon, and terminate with a semicolon. #Dependencies=gedit; # Conditions - semicolon-separated array of special conditions: # "desktop" current (parent) folder is desktop # "removable" target (first selection) is removable # "gsettings " is true # "gsettings <[eq|ne|gt|lt]> " # "dbus " exists #Conditions=desktop; # Escape Spaces - set to true to escape spaces in filenames and uris ($U, $F, $P, $D) # # Sometimes this may be preferred to getting raw filenames that must be enclosed in # quotes. # # Optional - by default this is false EscapeSpaces=true # Run in terminal - set to true to execute the Exec line in a spawned terminal window. # # Generally if you use this you should not have Quotes defined, as that will be taken care # of during converting the expanded command string into an arg vector. # # Optional - by default this is false #Terminal=false nemo-3.6.5/files/usr/share/nemo/actions/send-by-mail.py0000775000175000017500000000055413215733314021666 0ustar fabiofabio#!/usr/bin/python3 -OOt import argparse from itertools import chain from subprocess import call parser = argparse.ArgumentParser() parser.add_argument('filelist', help='list of absolute paths separated by /#/') args = parser.parse_args() command = ['xdg-email'] + list(chain.from_iterable(('--attach', arg) for arg in args.filelist.split('/#/'))) call(command) nemo-3.6.5/files/usr/share/nemo/actions/92_show-expo.nemo_action0000664000175000017500000001406213215733314023507 0ustar fabiofabio[Nemo Action] Name=Manage workspaces (Expo) Comment=Open Expo to add, remove, or organize workspaces Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.ShowExpo >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon; Active=false Name[eu]=Kudeatu laneko areak (Expo) Name[vi]=Quản lý vùng làm việc (Expo) Name[nl]=Werkbladen beheren (Expo) Name[gd]=Rianaich rumannan-obrach (Expo) Name[bg]=Управление на работни меÑта (ЕкÑпо) Name[fi]=Hallitse työtiloja (Expo) Name[gl]=Administrar os espazos de traballo (Expo) Name[lt]=Tvarkyti darbo sritis (Expo) Name[ca]=Gestionar espais de treball (Expo) Name[en_GB]=Manage workspaces (Expo) Name[ko]=작업 공간 관리 (Expo) Name[hr]=Upravljanje radnim prostorima (Prikaz radnih prostora) Name[el]=ΔιαχείÏιση χώÏων εÏγασίας (Expo) Name[pt_BR]=Gerenciar espaços de trabalho (Expo) Name[es]=Gestionar áreas de trabajo (Expo) Name[de]=Arbeitsflächenübersicht Name[th]=จัดà¸à¸²à¸£à¸žà¸·à¹‰à¸™à¸—ี่ทำงาน (Expo) Name[cs]=Spravovat pracovní plochy (pÅ™ehled ploch) Name[ro]=Gestionează spaÈ›iile de lucru (Expo) Name[it]=Gestisci spazi di lavoro (Expo) Name[tr]=Çalışma alanlarını yönet (Sergi-Expo) Name[zh_TW]=工作å€ç®¡ç† (Expo) Name[da]=HÃ¥ndtér arbejdsomrÃ¥der (oversigt) Name[am]=የ ስራ ቦታ አስተዳዳሪ (Expo) Name[sk]=SpravovaÅ¥ plochy (Expo) Name[fr_CA]=Gérer les espaces de travail (Expo) Name[sr]=Управљај радним проÑторима (екÑпо) Name[ta]=பணிதளஙà¯à®•ளை நிரà¯à®µà®•ி Name[zh_HK]=管ç†å·¥ä½œå€ (Expo) Name[ia]=Administrar le spatios de labor (Expo) Name[is]=Sýsla með vinnusvæði (Expo) Name[cy]=Rheoli mannau gwaith (Expo) Name[ja]=ワークスペースã®ç®¡ç† (Expo) Name[sv]=Hantera arbetsytor (Expo) Name[et]=Halda tööalasid (Expo) Name[uk]=ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‡Ð¸Ð¼Ð¸ проÑторами (Expo) Name[hu]=Munkaterületek kezelése (Közszemle) Name[ms]=Mengurus kawasan kerja (Expo) Name[ur]=ورک سپیس کا انتظام کریں(ایکسپو) Name[fr]=Gérer les espaces de travail (Expo) Name[pl]=ZarzÄ…dzaj przestrzeniami roboczymi (Expo) Name[pt]=Gerir áreas de trabalho (Expo) Name[zh_CN]=管ç†å·¥ä½œåŒºï¼ˆå³Expo模å¼ï¼‰ Name[ru]=Менеджер рабочих меÑÑ‚ (Expo) Comment[eu]=Ireki Expo laneko areak gehitu, kendu edo antolatzeko Comment[vi]=Mở Expo để thêm, bá», quản lý vùng làm việc Comment[nl]=Open Expo om werkbladen toe te voegen, te verwijderen of te organiseren Comment[gd]=Fosgail Expo gus rumannan-obrach a chur ris, a thoirt air falbh no a rianachadh Comment[bg]=ОтварÑне на ЕкÑпо за добавÑне, премахване или организиране на работните меÑта Comment[fi]=Avaa Expo lisätäksesi, poistaaksesi tai järjestääksesi työtiloja Comment[gl]=Abrir Expo para engadir, retirar ou organizar espazos de traballo Comment[lt]=Atverti Expo, kad pridÄ—tumÄ—te, Å¡alintumÄ—te ar tvarkytumÄ—te darbo sritis Comment[ca]=Obre Expo per afegir, treure o organitzar espais de treball Comment[en_GB]=Open Expo to add, remove, or organise workspaces Comment[ko]=작업 ê³µê°„ì˜ ì¶”ê°€, 제거, ë˜ëŠ” êµ¬ì„±ì„ ìœ„í•´ Expo 열기 Comment[hr]=Otvorite prikaz radnih postora za dodavanje, uklanjanje ili organizaciju radnih prostora Comment[el]=Άνοιγμα Expo για Ï€Ïοσθήκη, κατάÏγηση ή οÏγάνωση των χώÏων εÏγασίας Comment[pt_BR]=Abrir Expo para adicionar, remover ou organizar espaços de trabalho Comment[es]=Abrir Expo para añadir, eliminar u organizar áreas de trabajo Comment[de]=Arbeitsflächenübersicht öffnen, um Arbeitsflächen hinzuzufügen, zu entfernen oder zu organisieren Comment[th]=เปิด Expo เพื่อเพิ่ม ลบ หรือจัดระเบียบพื้นที่ทำงาน Comment[cs]=Otevřít Expo k pÅ™idání, odstranÄ›ní nebo organizaci pracovních ploch Comment[ro]=Deschide Expo pentru a adăuga, a È™terge sau pentru a organiza spaÈ›iile de lucru Comment[it]=Apri Expo per aggiungere, togliere o organizzare gli spazi di lavoro Comment[tr]=Çalışma alanları eklemek, silmek ya da organize etmek için Sergi görünümünü aç Comment[zh_TW]=開啟工作å€ç®¡ç† (Expo) ä»¥åŠ å…¥ï¼Œç§»é™¤ï¼Œæˆ–çµ„ç¹”å·¥ä½œå€ Comment[da]=Ã…bn visning af arbejdsomrÃ¥der for at tilføje, fjerne eller organisere arbejdsomrÃ¥der Comment[am]=መክáˆá‰» ለ Expo ለ መጨመር: ለ ማስወገድ: ወይንሠየ ስራ ቦታዎች ለ ማደራጀት Comment[sk]=OtvoriÅ¥ Expo pre pridávanie, odstraňovanie a organizovanie pracovných plôch Comment[fr_CA]=Ouvrir Expo pour gérer les espaces de travail Comment[sr]=Отворите екÑпо да додате, уклоните или уредите радне проÑторе Comment[zh_HK]=開啟 Expo 以新增ã€ç§»é™¤æˆ–çµ„ç¹”å·¥ä½œå€ Comment[ia]=Aperir Expo pro adder, remover, o organisar le spatios de labor Comment[is]=Opna Expo til að bæta við, fjarlægja eða skipuleggja vinnusvæði Comment[cy]=Agor Expo i ychwanegu, dileu, neu drefnu'r gweithleoedd Comment[ja]=ワークスペースを管ç†ã™ã‚‹ãŸã‚ã« Expo ã‚’é–‹ã Comment[sv]=Öppna Expo för att lägga till, ta bort, eller ordna arbetsytor Comment[uk]=Відкрити Expo Ð´Ð»Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‡Ð¸Ð¼Ð¸ проÑторами Comment[hu]=Közszemle megnyitása a munkaterületek hozzáadásához, eltávolításához és kezeléséhez Comment[ms]=Buka Expo ke tambah, hapus, atau uruskan kawasan kerja Comment[ur]=ورک سپیسوں Ú©Ùˆ شامل، Ûٹانے یا منظم کرنے Ú©Û’ لیے ایکسپو کھولیں Comment[fr]=Ouvrir Expo pour gérer les espaces de travail Comment[pl]=Otwórz Expo, aby dodawać, usuwać i organizować przestrzenie robocze Comment[pt]=Abrir Expo para adicionar, remover ou organizar áreas de trabalho Comment[zh_CN]=打开 Expo 以添加,移除或整ç†å·¥ä½œåŒº Comment[ru]=Открыть Expo Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ, ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¸ организации рабочих меÑÑ‚ nemo-3.6.5/files/usr/share/nemo/actions/set-as-background.nemo_action0000664000175000017500000001375613215733314024566 0ustar fabiofabio[Nemo Action] Name=Set as Wallpaper... Comment=Set the selected image as your Cinnamon desktop wallpaper Exec=gsettings set org.cinnamon.desktop.background picture-uri "%U" Selection=s Mimetypes=image/*; Conditions=dbus org.Cinnamon; Name[eu]=Ezarri atzeko plano gisa... Name[vi]=Äặt làm Hình ná»n... Name[nl]=Gebruik als bureaubladachtergrond... Name[gd]=Suidhich mar phàipear-balla... Name[bg]=Задаване като тапет... Name[fi]=Aseta taustakuvaksi... Name[gl]=Estabelecer como fondo de pantalla Name[lt]=Nustatyti kaip darbastalio fonÄ… Name[ga]=Socraigh mar Cúlra na Deisce Name[sr@latin]=Postavi kao pozadinu... Name[ca]=Defineix com a fons de pantalla Name[ml]=പശàµà´šà´¾à´¤àµà´¤à´²à´šà´¿à´¤àµà´°à´®à´¾à´¯à´¿ സജàµà´œàµ€à´•à´°à´¿à´•àµà´•àµà´•... Name[en_GB]=Set as Wallpaper... Name[ko]=배경화면으로 설정하기... Name[hr]=Postavi kao pozadinu... Name[sl]=Nastavi kot sliko ozadja ... Name[el]=ΟÏισμός ως ΤαπετσαÏίας... Name[pt_BR]=Definir como papel de parede Name[nb]=Sett som bakgrunn... Name[es]=Establecer como fondo... Name[de]=Als Hintergrund festlegen … Name[th]=ตั้งเป็นภาพพื้นหลัง... Name[cs]=Nastavit jako pozadí plochy… Name[ro]=Setează ca imagine de fundal... Name[it]=Imposta come sfondo... Name[tr]=Duvarkağıdı olarak ayarla... Name[zh_TW]=設為桌布... Name[tg]=Танзим кардан ҳамчун таÑвири Ñкран... Name[da]=Anvend som baggrund ... Name[am]=እንደ áŒá‹µáŒá‹³ ወረቀት ማሰናጃ... Name[sk]=NastaviÅ¥ ako pozadie... Name[fr_CA]=Définir en tant que fond d'écran... Name[sr]=ПоÑтави као позадину... Name[zh_HK]=設為桌布... Name[ia]=Fixar como tapete de papiro... Name[ast]=Afitar como fondu pantalla... Name[is]=Gera að veggfóðri... Name[bs]=Postavi kao pozadinu... Name[cy]=Gosod fel Papur Wal... Name[ja]=å£ç´™ã«è¨­å®š... Name[sv]=Ange som skrivbordsbakgrund... Name[et]=Määra taustapildiks... Name[uk]=Ð’Ñтановити Ñк тло... Name[hu]=Beállítás háttérképként… Name[ms]=Tetapkan sebagai Kertas Dinding... Name[ur]=بطور وال پیپر سیٹ کریں... Name[fr]=Définir en tant que fond d'écran... Name[pl]=Ustaw jako tÅ‚o pulpitu... Name[pt]=Definir como fundo do Ambiente de Trabalho Name[zh_CN]=设置为å£çº¸... Name[ru]=Сделать фоном... Name[id]=Pasang sebagai Wallpaper... Name[be]=ÐŽÑталÑваць у ÑкаÑці фонавага малюнка... Name[he]=הגדרה כרקע... Comment[eu]=Ezarri hautatutako irudia zure Cinnamon mahaigaineko horma-paper bezala Comment[vi]=Äặt ảnh được chá»n làm màn hình ná»n Cinnamon Comment[nl]=Stel de geselecteerde afbeelding in als uw bureaubladachtergrond voor Cinnamon Comment[gd]=Suidhich an dealbh a thagh thu mar phàipear-balla an deasg Cinnamon Comment[bg]=Задай избраното изображение като тапет за Cinnamon Comment[fi]=Aseta valittu kuva Cinnamon työpöytäsi taustakuvaksi Comment[lt]=Nustatyti pasirinktÄ… paveikslÄ… kaip jÅ«sų Cinnamon darbalaukio fonÄ… Comment[ca]=Estableix la imatge seleccionada com a fons d'escriptori de Cinnamon Comment[en_GB]=Set the selected image as your Cinnamon desktop wallpaper Comment[ko]=ì„ íƒí•œ ì´ë¯¸ì§€ë¥¼ 시나몬 ë°ìФí¬í†±ì˜ 배경화면으로 사용하기 Comment[hr]=Postavi odabranu sliku kao pozadinu svoje Cinnamon radne povrÅ¡ine Comment[el]=ΟÏίστε την επιλεγμένη εικόνα ως ταπετσαÏία της επιφάνειας εÏγασίας σας Comment[pt_BR]=Escolher a imagem selecionada como seu papel de parede no desktop Cinnamon Comment[es]=Establecer la imagen seleccionada como fondo de escritorio de Cinnamon Comment[de]=Ausgewähltes Bild als Cinnamons Schreibtischhintergrund einstellen Comment[th]=ตั้งรูปที่เลือà¸à¹€à¸›à¹‡à¸™à¸ à¸²à¸žà¸žà¸·à¹‰à¸™à¸«à¸¥à¸±à¸‡à¹€à¸”สà¸à¹Œà¸—็อป Cinnamon ของคุณ Comment[cs]=Nastavit vybraný obrázek jako pozadí plochy v Cinnamonu Comment[ro]=Setează imaginea selectată ca imagine de fundal pentru desktopul Cinnamon Comment[it]=Imposta l'immagine selezionata come sfondo del tuo desktop Cinnamon Comment[tr]=Seçilen görüntüyü Cinnamon masaüstü duvarkağıdı olarak ayarla Comment[zh_TW]=將鏿“‡çš„å½±åƒè¨­ç‚ºæ‚¨ Cinnamon 桌é¢çš„æ¡Œå¸ƒ Comment[da]=Anvend det markerede billede som din Cinnamon-skrivebordsbaggrund Comment[am]=የ ተመረጠá‹áŠ• áˆáˆµáˆ በ እርስዎ የ ሲናሞን ዴስክቶᕠá‹áˆµáŒ¥ እንደ áŒá‹µáŒá‹³ ወረቀት መጠቀሚያ Comment[sk]=NastaviÅ¥ vybratý obrázok ako pozadie vaÅ¡ej pracovnej plochy prostredia Cinnamon Comment[fr_CA]=Utiliser l'image sélectionnée comme fond d'écran de Cinnamon Comment[sr]=ПоÑтавите изабрану Ñлику за позадину радне површи Comment[zh_HK]=將鏿“‡çš„å½±åƒè¨­ç‚ºä½ çš„ Cinnamon æ¡Œé¢æ¡Œå¸ƒ Comment[ia]=Configurar le imagine seligite imagine como tapete de papiro de tu scriptorio Cinnamon Comment[is]=Setja valda mynd sem bakgrunnsmynd skjáborðs Comment[cy]=Gosod y ddelwedd hon fel eich papur wall bwrdd gwaith Cinnamon Comment[ja]=é¸æŠžã—ãŸç”»åƒã‚’å£ç´™ã«è¨­å®š Comment[sv]=Ange den valda bilden som bakgrundsbild för skrivbordet i Cinnamon Comment[uk]=Ð’Ñтановити вибране Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð² ÑкоÑти шпалер Ñтільниці Cinnamon Comment[hu]=A kiválasztott kép beállítása Cinnamon asztal háttérképként Comment[ms]=Set imej dipilih sebagai wallpaper desktop Cinnamon Comment[ur]=منتخب Ú©Ø±Ø¯Û ØªØµÙˆÛŒØ± Ú©Ùˆ بطور وال پیپر متعین کریں Comment[fr]=Utiliser l'image sélectionnée comme fond d'écran de Cinnamon Comment[pl]=Ustaw wybrany obraz jako Twoje tÅ‚o pulpitu Cinnamon Comment[pt]=Definir a imagem seleccionada como o fundo da área de trabalho do Cinnamon Comment[zh_CN]=将选中的图片设为您的 Cinnamon 桌é¢å£çº¸ Comment[ru]=УÑтановить выбранное изображение фоном рабочего Ñтола Cinnamon nemo-3.6.5/files/usr/share/nemo/actions/90_new-workspace.nemo_action0000664000175000017500000001151213215733314024336 0ustar fabiofabio[Nemo Action] Name=Jump to new workspace Comment=Create a new workspace and activate it Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.JumpToNewWorkspace >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon; Active=false Name[eu]=Joan laneko area berrira Name[vi]=Chuyển qua vùng làm việc má»›i Name[nl]=Spring naar nieuw werkblad Name[gd]=Gearr leum tu rum-obrach ùr Name[bg]=Върви на ново работно мÑÑто Name[fi]=Siirry uuteen työtilaan Name[gl]=Cambiar a un espazo de traballo novo Name[lt]=Pereiti į naujÄ… darbo sritį Name[ca]=Vés a un espai de treball nou Name[en_GB]=Jump to new workspace Name[ko]=새 작업 공간으로 가기 Name[hr]=SkoÄi u novi radni prostor Name[el]=Μετάβαση σε νέο χώÏο εÏγασίας Name[pt_BR]=Ir para nova área de trabalho Name[es]=Ir a un nuevo espacio de trabajo Name[de]=Zu neuer Arbeitsfläche wechseln Name[th]=ข้ามไปพื้นที่ทำงานใหม่ Name[cs]=PÅ™ejít na novou pracovní plochu. Name[ro]=Sari la un spaÅ£iu de lucru nou Name[it]=Salta a nuovo spazio di lavoro Name[tr]=Yeni çalışma alanına git Name[zh_TW]=è·³è‡³æ–°å·¥ä½œå€ Name[da]=Hop til nyt arbejdsomrÃ¥de Name[am]=ወደ አዲስ የ ስራ ቦታ መá‹áˆˆá‹« Name[sk]=SkoÄiÅ¥ na novú plochu Name[fr_CA]=Aller vers un nouvel espace de travail Name[sr]=Пређи у нови радни проÑтор Name[ta]=பà¯à®¤à®¿à®¯ பணிதளதà¯à®¤à®¿à®±à¯à®•௠தாவ௠Name[zh_HK]=è·³è‡³æ–°å·¥ä½œå€ Name[ia]=Saltar a un nove spatio de labor Name[is]=Hoppa á nýtt vinnusvæði Name[cy]=Neidio i weithle newydd Name[sv]=Hoppa till ny arbetsyta Name[uk]=Перейти на новий робочий проÑтір Name[hu]=Ugrás az új munkaterületre Name[ms]=Lompat ke kawasan kerja baru Name[ur]=نئی ورک سپیس میں منتقل ÛÙˆÚº Name[fr]=Aller vers un nouvel espace de travail Name[pl]=Przejdź do nowej przestrzeni roboczej Name[pt]=Ir para nova área de trabalho Name[zh_CN]=跳到新的工作区 Name[ru]=Перейти на новое рабочее меÑто Comment[eu]=Laneko area berri bat sortu eta aktibatzen du Comment[vi]=Tạo và kích hoạt vùng làm việc má»›i Comment[nl]=Maak een nieuw werkblad en activeer het Comment[gd]=Cruthaich rum-obrach ùr is gnìomhaich e Comment[bg]=Създаване и активиране на ново работно мÑÑто Comment[fi]=Luo uusi työtila ja aktivoi se Comment[gl]=Crear un novo espazo de traballo e activalo Comment[lt]=Sukurti naujÄ… darbo sritį ir jÄ… aktyvuoti Comment[ca]=Crea un nou espai de treball i activa'l Comment[en_GB]=Create a new workspace and activate it Comment[ko]=새로운 작업 ê³µê°„ì„ ë§Œë“¤ê³  사용합니다 Comment[hr]=Stvori novi radni prostor i aktiviraj ga Comment[el]=ΔημιουÏγία νέου χώÏου εÏγασίας και ενεÏγοποίηση Comment[pt_BR]=Criar um novo espaço de trabalho e ativá-lo Comment[es]=Crear un área de trabajo nueva y activarla Comment[de]=Eine neue Arbeitsfläche erstellen und diese aktivieren Comment[th]=สร้างพื้นที่ทำงานใหม่à¹à¸¥à¸°à¹ƒà¸Šà¹‰à¸‡à¸²à¸™à¸žà¸·à¹‰à¸™à¸—ี่ทำงานนั้น Comment[cs]=VytvoÅ™it novou pracovní plochu a aktivovat ji Comment[ro]=Creează un spaÅ£iu de lucru nou ÅŸi activează-l Comment[it]=Crea un nuovo spazio di lavoro e attivalo Comment[tr]=Yeni bir çalışma alanı oluÅŸtur ve etkinleÅŸtir Comment[zh_TW]=建立新工作å€ä¸¦å•Ÿç”¨ Comment[da]=Opret et nyt arbejdsomrÃ¥de og aktivér det Comment[am]=አዲስ የ ስራ ቦታ መáጠሪያ እና ማስጀመሪያ Comment[sk]=VytvoriÅ¥ novú pracovnú plochu a aktivovaÅ¥ ju Comment[fr_CA]=Créer et activer un nouvel espace de travail Comment[sr]=Ðаправите нови радни проÑтор и активирајте га Comment[ta]=பà¯à®¤à®¿à®¯ பணிதà¯à®¤à®³à®¤à¯à®¤à¯ˆ உரà¯à®µà®¾à®•à¯à®•ி அதை உயிரà¯à®ªà¯à®ªà®¿ Comment[zh_HK]=建立新工作å€ä¸¦å°‡å…¶å•Ÿå‹• Comment[ia]=Crear un nove spatio de labor e activar lo Comment[is]=Búa til nýtt vinnusvæði og virkja það Comment[cy]=Creu gweithle newydd a'i roi ar waith Comment[sv]=Skapa en ny arbetsyta och aktivera den Comment[uk]=Створити й активувати новий робочий проÑтір Comment[hu]=Új munkaterület létrehozása és aktiválása Comment[ms]=Cipta kawasan kerja baru dan aktifkan ia. Comment[ur]=نیا مقام کار بنائیں اور اسے چالو کریں Comment[fr]=Créer et activer un nouvel espace de travail Comment[pl]=Utwórz nowÄ… przestrzeÅ„ roboczÄ… i aktywuj jÄ… Comment[pt]=Criar uma nova área de trabalho e activá-la Comment[zh_CN]=创建新的工作区并激活它 Comment[ru]=Создать рабочее меÑто и Ñделать активным nemo-3.6.5/files/usr/share/nemo/actions/desktop-settings.nemo_action0000664000175000017500000000771113215733314024556 0ustar fabiofabio[Nemo Action] Name=Desktop _Settings Comment=Change how your desktop works Exec=cinnamon-settings desktop Selection=None Icon-Name=cs-desktop Extensions=any; Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; Name[eu]=Mahaigainaren _ezarpenak Name[nl]=Instellingen van werkomgeving Name[gd]=_Roghainnean an deasg Name[bg]=_ÐаÑтройки на деÑктопа Name[fi]=_Työpöytäasetukset Name[lt]=Darbalaukio nu_statymai Name[ca]=Ajusts de l'e_scriptori Name[en_GB]=Desktop _Settings Name[ko]=바탕화면 설정(_S) Name[hr]=Postavke _radne povrÅ¡ine Name[el]=Ρυθμίσεις_Επιφάνειας_ΕÏγασίας Name[pt_BR]=Configurações da área de _trabalho Name[es]=_Configuración del escritorio Name[de]=_Schreibtischeinstellungen Name[th]=_ตั้งค่าเดสà¸à¹Œà¸—็อป Name[cs]=_Nastavení pracovní plochy Name[ro]=_Setări desktop Name[it]=Impo_stazioni del desktop Name[tr]=Masaüstü _Ayarları Name[zh_TW]=桌é¢è¨­å®š(_S) Name[da]=_Skrivebordsindstillinger Name[am]=ዴስክቶᕠ_ማሰናጃ Name[sk]=_Nastavenia pracovnej plochy Name[fr_CA]=_Paramètres de bureau Name[sr]=ПоÑтавке _радне површи Name[zh_HK]=桌é¢è¨­å®š(_S) Name[ia]=Configurationes (_Settings) del scriptorio Name[is]=_Skjáborðsstillingar Name[cy]=Gosodiadau _Bwrdd Gwaith Name[sv]=Skrivbords_inställningar Name[et]=Töölaua_Seaded Name[uk]=ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ _Ñтільниці Name[hu]=Asztal _beállítások Name[ms]=_Tetapan Desktop Name[ur]=ڈیسک ٹاپ Ú©ÛŒ _ترتیبات Name[fr]=_Paramètres de bureau Name[pl]=_Ustawienia pulpitu Name[pt]=Definiçõe_s do Ambiente de Trabalho Name[zh_CN]=桌é¢è®¾ç½®(_S) Name[ru]=ÐаÑтройка рабочего Ñтола Comment[eu]=Aldatu mahaigainaren funtzionatzeko modua Comment[nl]=Verander hoe uw werkomgeving werkt Comment[gd]=Atharraich an dòigh san obraich an deasg agad Comment[bg]=Промени работата на деÑктопа Comment[fi]=Muokkaa työpöydän toimintaa Comment[lt]=Pakeisti kaip veikia jÅ«sų darbalaukis Comment[ca]=Canvia el funcionament de l'escriptori Comment[en_GB]=Change how your desktop works Comment[ko]=바탕화면 활용 ë°©ë²•ì„ ë°”ê¿‰ë‹ˆë‹¤. Comment[hr]=Promijenite naÄin rada vaÅ¡e radne povrÅ¡ine Comment[el]=Αλλάξτε τον Ï„Ïόπο λειτουÏγίας της επιφάνειας εÏγασίας Comment[pt_BR]=Alterar como funciona a sua área de trabalho Comment[es]=Cambia el funcionamiento del escritorio Comment[de]=Die Arbeitsweise des Schreibtischs ändern Comment[th]=เปลี่ยนวิธีà¸à¸²à¸£à¸—ำงานของเดสà¸à¹Œà¸—็อปของคุณ Comment[cs]=Zmenit nastavení pracovní plochy Comment[ro]=Schimbă modul în care funcÈ›ionează desktop-ul Comment[it]=Cambia il funzionamento del desktop Comment[tr]=Masaüstünüzün nasıl olacağını belirler Comment[zh_TW]=變更您的桌é¢ä½œç”¨æ–¹å¼ Comment[da]=Ændr dit skrivebords virkemÃ¥de Comment[am]=የ እርስዎን ዴስክቶᕠአሰራር መቀየሪያ Comment[sk]=Zmení fungovanie vaÅ¡ej pracovnej plochy Comment[fr_CA]=Modifier le fonctionnement de votre bureau Comment[sr]=Измените начин рада ваше радне површи Comment[zh_HK]=變更你的桌é¢ä½œç”¨æ–¹å¼ Comment[ia]=Cambia como tu scriptotio functiona Comment[is]=Breyttu því hvernig skjáborðið virkar Comment[cy]=Newid sut mae eich bwrdd gwaith yn gweithio. Comment[sv]=Ändra hur ditt skrivbord fungerar Comment[uk]=Змінити Ñк Вашу Ñтільницю Comment[hu]=Asztal működésének megváltoztatása Comment[ms]=Ubah bagaimana dekstop anda berfungsi Comment[ur]=تبدیل کریں Ú©Û Ø¢Ù¾Ú©Ø§ ڈیسک ٹاپ کیسے کام کرتا ÛÛ’ Comment[fr]=Modifier le fonctionnement de votre bureau Comment[pl]=ZmieÅ„ sposób dziaÅ‚ania pulpitu Comment[pt]=Muda como o ambiente de trabalho funciona Comment[zh_CN]=æ”¹å˜æ¡Œé¢çš„å·¥ä½œæ–¹å¼ Comment[ru]=Изменить как ваш рабочий Ñтол nemo-3.6.5/files/usr/share/nemo/actions/myaction.py0000775000175000017500000000033213215733314021222 0ustar fabiofabio#! /usr/bin/python3 -OOt import sys command = sys.argv[0] print("Running " + command) print("With the following arguments:") for arg in sys.argv: if command == arg: continue else: print(arg) nemo-3.6.5/files/usr/share/nemo/actions/change-background.nemo_action0000664000175000017500000001250613215733314024607 0ustar fabiofabio[Nemo Action] Name=Change Desktop _Background Comment=Change the Cinnamon desktop background Exec=cinnamon-settings backgrounds Selection=None Icon-Name=cs-backgrounds Extensions=any; Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; Name[eu]=Aldatu _mahaigainaren atzeko planoa Name[vi]=Äổi Ảnh _ná»n Màn hình Name[nl]=Werk_bladachtergrond wijzigen Name[gd]=Atharraich _cùlaibh an desktop Name[bg]=ПромÑна на _фона Name[fi]=Muuta työpöydän _taustaa Name[gl]=Cambiar o _fondo do escritorio Name[nds]=Desktop_Hintergrund ändern Name[lt]=Keisti darbastalio _fonÄ… Name[ga]=Athraigh Cúlra_na Deisce Name[sr@latin]=Iz_meni pozadinu Name[ca]=Canvia el _fons de l'escriptori Name[ml]=ഡെസàµà´•àµà´Ÿàµ‹à´ªàµà´ªà´¿à´¨àµà´±àµ† _പശàµà´šà´¾à´¤àµà´¤à´²à´‚ മാറàµà´±àµà´• Name[en_GB]=Change Desktop _Background Name[ko]=바탕화면 ë°°ê²½ 바꾸기(_B) Name[hr]=Promijeni pozadinu _radne povrÅ¡ine Name[sl]=Spremeni _ozadje namizja Name[el]=Αλλαγή _εικόνας επιφάνειας εÏγασίας Name[af]=Verander Werkskerm Agtergrond Name[pt_BR]=Alterar plano de fundo Name[nb]=Endre skrivebords_bakgrunn Name[es]=Cambiar el _fondo del escritorio Name[de]=_Hintergrund des Schreibtisches ändern Name[bn]=ডেসà§à¦•টপের পটভূমি পরিবরà§à¦¤à¦¨ করà§à¦¨ (_B) Name[th]=_เปลี่ยนพื้นหลังของพื้นโต๊ะ Name[cs]=ZmÄ›nit _pozadí plochy Name[ro]=Schim_bă imaginea de fundal Name[it]=Ca_mbia sfondo desktop Name[tr]=Masaüstü _Arkaplanını DeÄŸiÅŸtir Name[zh_TW]=變更桌é¢èƒŒæ™¯(_B) Name[tg]=Тағйир додани паÑзаминаи _мизи корӣ Name[en_AU]=Change Desktop _Background Name[da]=Skift skrive_bordsbaggrund Name[am]=የዴስክቶᕠ_መደብ መቀየሪያ Name[sk]=ZmeniÅ¥ _pozadie plochy Name[fr_CA]=Modifier l'arrière-plan du _bureau Name[sr]=Из_мени позадину Name[ta]=(_B)பணிமேடை பினà¯à®©à®©à®¿à®¯à¯ˆ மாறà¯à®±à¯ Name[zh_HK]=變更桌é¢èƒŒæ™¯(_B) Name[ia]=Cambiar le fundo (_Background) del scriptorio Name[ast]=Camudar el fon_du d'escritoriu Name[is]=Breyta _bakgrunni skjáborðs Name[bs]=Promijeni _pozadinu desktopa Name[kk]=Ф_он Ñуретін ауыÑтыру Name[cy]=Newid Cefndir y _Bwrdd Gwaith Name[ja]=背景を変更 (_B) Name[sv]=Byt skrivbordsbak_grund Name[et]=Vaheta töölaua _taust Name[uk]=Змінити Ñ‚_ло Ñтільниці Name[hu]=Asztal _hátterének módosítása Name[ku]=Zemîna Sermaseyê Biguherîne Name[ms]=Tukar Latar _Belakang Desktop Name[ur]=ڈیسک ٹاپ کا _پس منظر بدلیں Name[fr]=Modifier l'arrière-plan du _bureau Name[pl]=ZmieÅ„ _tÅ‚o pulpitu Name[jv]=Ganti Gambar _Buri Desktop Name[pt]=Alterar _fundo da área de trabalho Name[oc]=Modificar lo _rèire plan del burèu Name[zh_CN]=更改桌é¢èƒŒæ™¯(_B) Name[sq]=Ndrysho _sfondin e desktopit Name[ru]=Изменить _фон рабочего Ñтола Name[id]=Ubah Latar _Belakang Desktop Name[be]=ЗмÑніць _фон працоўнага Ñтала Name[he]=שנה ×ת _רקע שולחן העבודה Comment[eu]=Aldatu Cinnamon mahaigainaren atzeko planoa Comment[vi]=Äổi ảnh ná»n Cinnamon Comment[nl]=Verander de bureaubladachtergrond van Cinnamon Comment[gd]=Atharraich cùlaibh an deasg Cinnamon Comment[bg]=Смени фона на Ñ€Ð°Ð±Ð¾Ñ‚Ð½Ð¸Ñ Ð¿Ð»Ð¾Ñ‚ Comment[fi]=Muuta Cinnamon työpöydän taustaa Comment[lt]=Keisti Cinnamon darbastalio fonÄ… Comment[ca]=Canvia el fons d'escriptori de Cinnamon Comment[en_GB]=Change the Cinnamon desktop background Comment[ko]=시나몬 ë°ìФí¬í†±ì˜ 배경화면 바꾸기 Comment[hr]=Promijeni pozadinu Cinnamon radne povrÅ¡ine Comment[el]=Αλλάξτε το φόντο της επιφάνειας εÏγασίας Comment[pt_BR]=Mude o plano de fundo do Cinnamon Comment[es]=Cambiar el fondo de escritorio de Cinnamon Comment[de]=Cinnamons Schreibtischhintergrund ändern Comment[th]=เปลี่ยนภาพพื้นหลังเดสà¸à¹Œà¸—็อป Cinnamon Comment[cs]=ZmÄ›nit pozadí plochy Cinnamonu Comment[ro]=Schimbă fundalul desktopului Cinnamon Comment[it]=Cambia lo sfondo del desktop Cinnamon Comment[tr]=Cinnamon masaüstü arkaplanını deÄŸiÅŸtir Comment[zh_TW]=變更 Cinnamon 桌é¢èƒŒæ™¯ Comment[da]=Skift Cinnamon-skrivebordsbaggrund Comment[am]=የ ሲናሞን ዴስክቶᕠመደብ መቀየሪያ Comment[sk]=ZmeniÅ¥ pozadie pracovnej plochy prostredia Cinnamon Comment[fr_CA]=Changer le fond d'écran de Cinnamon Comment[sr]=Измените позадину радне површи Comment[zh_HK]=變更 Cinnamon 桌é¢èƒŒæ™¯ Comment[ia]=Cambiar le fundo del scriptorio de Cinnamon Comment[is]=Breyta bakgrunni skjáborðsins Comment[cy]=Newid cefndir bwrdd gwaith Cinnamon Comment[ja]=å£ç´™ã‚’変更ã™ã‚‹ Comment[sv]=Byt bakgrundsbild pÃ¥ skrivbordet i Cinnamon Comment[uk]=Змінити тло Ñтільниці Cinnamon Comment[hu]=A Cinnamon asztal hátterének módosítása Comment[ms]=Tukar latar belakang desktop Cinnamon Comment[ur]=سنامون ڈیسک ٹاپ پس منظر تبدیل کریں Comment[fr]=Changer le fond d'écran de Cinnamon Comment[pl]=ZmieÅ„ tÅ‚o pulpitu Cinnamon Comment[pt]=Mudar o fundo da área de trabalho do Cinnamon Comment[zh_CN]=更改 Cinnamon 桌é¢èƒŒæ™¯ Comment[ru]=Сменить фон рабочего Ñтола Cinnamon nemo-3.6.5/files/usr/share/nemo/actions/mount-archive.nemo_action0000664000175000017500000001123413215733314024023 0ustar fabiofabio[Nemo Action] Name=Mount archive Comment=Mount %f to browse its contents Exec=/usr/lib/gvfs/gvfsd-archive file="%U" Selection=s Mimetypes=application/x-7z-compressed;application/x-cd-image;application/x-cpio;application/x-rar;application/x-rar-compressed;application/x-7z-compressed-tar;application/x-bzip-compressed-tar;application/x-compressed-tar;application/x-tar;application/zip; Stock-Id=gtk-directory Dependencies=/usr/lib/gvfs/gvfsd-archive; Selection=s Name[eu]=Muntatu fitxategia Name[vi]=Gắn kết bá»™ lưu trữ Name[nl]=Archiefbestand aankoppelen Name[gd]=Munntaich tasglann Name[bg]=Монтиране на архив Name[fi]=Liitä arkisto Name[gl]=Montar o ficheiro Name[lt]=Prijungti archyvÄ… Name[ga]=Feistigh an Cartlann Name[ca]=Munta l'arxiu Name[en_GB]=Mount archive Name[ko]=ë³´ê´€í•¨ì— ë§ˆìš´íŠ¸ 하기 Name[hr]=Montiraj arhivu Name[sl]=Priklopi arhiv Name[el]=ΑÏχείο Ï€ÏοσάÏτησης Name[pt_BR]=Montar arquivo Name[es]=Montar archivo Name[de]=Archive einhängen Name[th]=เมานท์à¹à¸Ÿà¹‰à¸¡à¸ˆà¸±à¸”เà¸à¹‡à¸š Name[cs]=PÅ™ipojit archiv Name[ro]=Montează arhiva Name[it]=Monta l'archivio Name[tr]=ArÅŸivi baÄŸla Name[zh_TW]=掛載壓縮檔 Name[da]=Montér arkiv Name[am]=ማህደር መጫኛ Name[sk]=PripojiÅ¥ archív Name[fr_CA]=Monter l'archive Name[sr]=Прикачи архиву Name[zh_HK]=掛載壓縮檔 Name[ia]=Montar le archivo Name[ast]=Montar archivu Name[is]=Tengja safnskrá Name[bs]=Montiraj arhivu Name[cy]=Arosod Archif Name[sv]=Montera arkiv Name[et]=Haagi arhiiv Name[uk]=Змонтувати архів Name[hu]=Archívum csatolása Name[ms]=Pautkan arkib Name[ur]=آرکائیوْ ماؤنٹ کریں Name[fr]=Monter l'archive Name[pl]=Zamontuj archiwum Name[pt]=Montar ficheiro Name[zh_CN]=挂载档案 Name[ru]=Подключить архив Name[id]=Pasang archive Name[be]=Падключыць архіў Name[he]=עגן ×רכיון Comment[eu]=Muntatu %f bere edukiak arakatzeko Comment[vi]=Gắn kết %f để duyệt xem ná»™i dung Comment[nl]=Koppel %f aan om zijn inhoud te verkennen Comment[gd]=Munntaich %f gus an susbaint aice a bhrabhsadh Comment[bg]=Монтиране на %f за преглед на Ñъдържанието Comment[fi]=Liitä %f selataksesi sen sisältöä Comment[gl]=Montar %f para examinar o seu contido Comment[lt]=Prijungti %f narÅ¡yti po jo turinį Comment[ga]=Feistigh %f chun féachaint ar inneachar Comment[ca]=Muntar %f per examinar-ne el contingut Comment[en_GB]=Mount %f to browse its contents Comment[ko]=ë‚´ìš©ì„ ë³´ê¸°ìœ„í•´ %f를 마운트 합니다 Comment[hr]=Montiraj %f za pregled sadržaja Comment[sl]=Priklopi %f za brskanje po vsebini Comment[el]=ΠÏοσαÏτήστε το %f για να πεÏιηγηθείτε στα πεÏιεχόμενά του Comment[pt_BR]=Montar %f para navegar em seu conteúdo Comment[es]=Montar %f para examinar su contenido Comment[de]=%f einhängen, um den Inhalt zu durchsuchen Comment[th]=เมานท์ %f เพื่อเรียà¸à¸”ูเนื้อหาของมัน Comment[cs]=PÅ™ipojit %f k prohlížení jeho obsahu Comment[ro]=Montează %f pentru a-i răsfoi conÈ›inutul Comment[it]=Montare %f per esplorarne i contenuti Comment[tr]=İçeriÄŸini açmak için %f öğesini baÄŸla Comment[zh_TW]=掛載 %f 以ç€è¦½å…¶å…§å®¹ Comment[da]=Montér %f for at gennemse indholdet Comment[am]=መጫኛ %f ይዞታዎችን ለ መቃኘት Comment[sk]=PripojiÅ¥ %f pre prehliadnutie jeho obsahu Comment[fr_CA]=Monter %f pour parcourir son contenu Comment[sr]=Прикачите „%f“ да биÑте видели Ñадржај Comment[zh_HK]=掛載 %f 以ç€è¦½å…¶å…§å®¹ Comment[ia]=Montar %f pro explorar su contento Comment[ast]=Montar %f pa restolar el so conteníu Comment[is]=Tengja %f til að skoða innihald hennar Comment[bs]=Montirajte %f da pregledate njen sadržaj Comment[cy]=Arosod %f i bori ei gynnwys Comment[sv]=Montera %f för att se dess innehÃ¥ll Comment[et]=%f haakimine sisu sirvimiseks Comment[uk]=Змонтувати %f щоб переглÑдати вміÑÑ‚ Comment[hu]=„%f†archívum csatolása a tartalom böngészéséhez Comment[ms]=Pautkan %f untuk layari kandungan Comment[ur]=â€%f کا مواد دیکھنے Ú©Û’ لیے اس Ú©Ùˆ ماؤنٹ کریں Comment[fr]=Monter %f pour parcourir son contenu Comment[pl]=Zamontuj %f, aby móc przeglÄ…dać jego zawartość Comment[pt]=Montar %f para navegar no seu conteúdo Comment[zh_CN]=挂载 %f 以æµè§ˆå…¶å†…容 Comment[ru]=Подключить %f Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñмотра Comment[id]=Pasang %f untuk menelusuri isinya Comment[be]=Падключыць %f, чтобы проÑмотреть его Ñодержимое Comment[he]=עגן ×ת %f לעיון בתוכנו nemo-3.6.5/files/usr/share/gtksourceview-2.0/0000775000175000017500000000000013215733314017624 5ustar fabiofabionemo-3.6.5/files/usr/share/gtksourceview-2.0/language-specs/0000775000175000017500000000000013215733314022522 5ustar fabiofabionemo-3.6.5/files/usr/share/gtksourceview-2.0/language-specs/nemo_action.lang0000664000175000017500000001014513215733314025661 0ustar fabiofabio application/nemo-action *.nemo_action # True True False True 0 True False 5 5 5 0 True True slide-left-right True False True False True False vertical True False 6 vertical 6 True False <b>Default View</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False View _new folders using: True default_view_combobox 0 False False 0 True False model1 0 False True 1 False True 0 True False 12 True False _Arrange items: True sort_order_combobox 0 False False 0 True False model2 0 False True 1 False True 1 Sort _folders before files True True False True 0 True False False 2 False True 1 False True 0 True False False True 1 True False 6 vertical 6 True False <b>Icon View Defaults</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False Default _zoom level: True icon_view_zoom_combobox 0 False False 0 True False model3 0 False True 1 False True 0 _Text beside icons True True False True 0 True False False 1 _Use compact layout True True False True 0 True False False 2 False True 1 False True 2 True False False True 3 True False 6 vertical 6 True False <b>Compact View Defaults</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False _Default zoom level: True compact_view_zoom_combobox 0 False False 0 True False model4 0 False True 1 False True 0 A_ll columns have the same width True True False True 0 True False False 1 False True 1 False True 4 True False False True 5 True False 6 vertical 6 True False <b>List View Defaults</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False D_efault zoom level: True list_view_zoom_combobox 0 False False 0 True False model5 0 False True 1 False True 0 False True 1 False True 6 True False False True 7 True False 6 vertical 6 True False <b>Tree View Defaults</b> True 0 False False 0 True False 40 True False vertical 6 Show _only folders True True False True 0 True False False 0 False True 1 False True 8 views Views True False True False True False vertical True False 6 vertical 6 True False <b>Behavior</b> True 0 False False 0 True False 40 True False vertical _Single click to open items True True False True 0 True True False False 0 _Double click to open items True True False True 0 True single_click_radiobutton False False 3 1 Click on a file's name twice to rename it True True False True 0 True False False 3 2 Open each _folder in its own window True True False True 0 True False False 3 3 Always start in dual-pane view True True False True 0 True False False 3 4 Ignore per-folder view preferences True True False True 0 True False False 3 5 Disable file operation queueing True True False True 0 True False False 3 6 Double-click on a blank area to go to the parent folder True True False True 0 True False False 3 7 False False 1 False True 0 True False False True 1 True False 6 vertical 6 True False <b>Executable Text Files</b> True 0 False False 0 True False 40 True False vertical 6 _Run executable text files when they are opened True True False True 0 True True False False 0 _View executable text files when they are opened True True False True 0 True scripts_execute_radiobutton False False 1 _Ask each time True True False True 0 True scripts_execute_radiobutton False False 2 False False 1 False True 2 True False False True 3 True False 6 vertical 6 True False <b>Trash</b> True 0 False False 0 True False 40 True False vertical 6 Ask before _emptying the Trash or deleting files True True False True 0 True False False 0 I_nclude a Delete command that bypasses Trash True True False True 0 True False False 1 Bypass the Trash when the Delete key is pressed True True False 0 True False False 2 False False 1 False True 4 True False False True 5 True False 6 vertical 6 True False <b>Media Handling</b> True 0 False False 0 True False 40 True False vertical 6 Automatically mount removeable media when inserted and on startup True True False True 0 True False False 0 Automatically open a folder for automounted media True True False True 0 True False False 1 Prompt or autorun/autostart programs when media are inserted True True False True 0 True False False 2 Automatically close the device's tab, pane, or window when a device is unmounted or ejected True True False True 0 True False False 3 False False 1 False True 6 True False False True 7 True False 6 vertical 6 True False <b>Bulk Rename</b> True 0 False False 0 True False 40 40 True False vertical True False 4 True False Command to invoke when renaming multiple items: 0 False True 0 True True True â— out False True 1 False True 0 False False 1 False True 8 behavior Behavior 1 True False True False True False vertical True False 6 vertical 6 True False <b>Icon Captions</b> True 0 False False 0 True False 40 True False vertical 6 True False Choose the order of information to appear beneath icon names. More information will appear when zooming in closer. True 0 False False 0 True False 40 True False False False 0 True False False False 1 False False 1 True False 40 True False True False False 0 True False False False 1 False False 2 True False 40 True False False False 0 True False False False 1 False False 3 False False 1 False True 2 True False False True 3 True False 6 vertical 6 True False <b>Date</b> True 0 False False 0 True False 40 True False 12 True False _Format: True date_format_combobox False False 0 True False False False 1 False False 1 False False 4 True False False True 5 True False 6 vertical 6 True False <b>Window and Tab Titles</b> True 0 False False 0 True False 40 True False vertical 6 Show the full p_ath in the title bar and tab bars True True False True 0 True False False 0 False False 1 False True 6 True False False True 7 True False 6 vertical 6 True False <b>File Size</b> True 0 False False 0 True False 40 True False 12 True False _Prefixes: True size_prefixes_combobox False False 0 True False model11 0 False False 1 False False 1 False False 8 True False False True 9 True False 6 vertical 6 True False <b>File Properties</b> True 0 False False 0 True False 40 True False vertical 6 Show advanced permissions in the file property dialog True True False True 0 True False False 0 False False 2 False False 10 True False False True 11 True False 6 vertical 6 True False <b>Move/Copy To Menu</b> True 0 False False 0 True False 40 True False vertical 6 List bookmarks in the menu True True False True 0 True False False 0 List devices and network locations in the menu True True False True 0 True False False 1 False False 1 False True 12 display Display 2 True False True False True False 12 vertical 18 True False vertical 6 True False <b>List Columns</b> True 0 False False 0 True False 12 True False vertical 6 True False Choose the order of information to appear in the list view. True 0 False False 0 True True 1 True True 0 list-columns List Columns 3 True False True False True False vertical True False 6 vertical 6 True False <b>Previewable Files</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False Show _thumbnails: True preview_image_combobox 0 False False 0 True False model7 0 False False 1 False False 0 True False 12 True False _Only for files smaller than: True preview_image_size_combobox 0 False False 0 True False model8 0 False True 1 False True 1 False True 1 False True 0 True False False True 1 True False 6 vertical 6 True False <b>Folders</b> True 0 False False 0 True False 40 True False vertical 6 True False 12 True False Count _number of items: True preview_folder_combobox 0 False False 0 True False model10 0 False True 1 False True 0 False True 1 False True 2 True False False True 3 True False 6 vertical 6 True False <b>Tooltips</b> True 0 False False 0 True False 40 True False vertical 3 Show tooltips in icon and compact views True True False True 0 True False False 3 0 Show tooltips in list views True True False True 0 True False False 3 1 Show tooltips on the desktop True True False True 0 True False False 3 2 True False <i>By default, a folder tooltip shows the item count, and files display their size. Select additional information to display in the tooltip:</i> True 0 False True 3 3 True False 40 True False vertical 6 Detailed file type True True False 0 True False False 0 Accessed date True True False True 0 True False False 3 Modified date True True False 0 True False False 3 File or folder location True True False True 0 True False False 4 False True 4 False False 1 False True 4 preview Preview 4 True False True False True False vertical True False 6 vertical 6 True False <b>Options</b> True 0 False False 0 True False 40 True False vertical 6 Show previous button True True False True 0 0.43999999761581421 True False False 0 Show next button True True False True 0 True False False 1 Show up button True True False True 0 True False False 2 Show refresh button True True False True 0 True False False 3 Show computer button True True False True 0 True False False 4 Show home button True True False True 0 True False False 5 Show location entry/breadcrumbs toggle button True True False True 0 True False False 6 Show open in terminal button True True False True 0 True False False 7 Show new folder button True True False True 0 True False False 8 Show search button True True False True 0 True False False 9 Show icon view button True True False True 0 True False False 10 Show list view button True True False True 0 True False False 11 Show compact view button True True False True 0 True False False 12 False True 1 False True 5 toolbar Toolbar 5 True True 1 closebutton1 Always Local Files Only Never nemo-3.6.5/src/nemo-trash-bar.h0000664000175000017500000000367113215733314015177 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2006 Paolo Borelli * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. * * Authors: Paolo Borelli * */ #ifndef __NEMO_TRASH_BAR_H #define __NEMO_TRASH_BAR_H #include "nemo-view.h" #include G_BEGIN_DECLS #define NEMO_TYPE_TRASH_BAR (nemo_trash_bar_get_type ()) #define NEMO_TRASH_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_TRASH_BAR, NemoTrashBar)) #define NEMO_TRASH_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_TRASH_BAR, NemoTrashBarClass)) #define NEMO_IS_TRASH_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_TRASH_BAR)) #define NEMO_IS_TRASH_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_TRASH_BAR)) #define NEMO_TRASH_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_TRASH_BAR, NemoTrashBarClass)) typedef struct NemoTrashBarPrivate NemoTrashBarPrivate; typedef struct { GtkInfoBar parent; NemoTrashBarPrivate *priv; } NemoTrashBar; typedef struct { GtkInfoBarClass parent_class; } NemoTrashBarClass; GType nemo_trash_bar_get_type (void) G_GNUC_CONST; GtkWidget *nemo_trash_bar_new (NemoView *view); G_END_DECLS #endif /* __GS_TRASH_BAR_H */ nemo-3.6.5/src/nemo-view.h0000664000175000017500000004357613215733314014276 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-view.h * * Copyright (C) 1999, 2000 Free Software Foundaton * Copyright (C) 2000, 2001 Eazel, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Ettore Perazzoli * Darin Adler * John Sullivan * Pavel Cisler */ #ifndef NEMO_VIEW_H #define NEMO_VIEW_H #include #include #include #include #include #include typedef struct NemoView NemoView; typedef struct NemoViewClass NemoViewClass; #include "nemo-window.h" #include "nemo-window-slot.h" #define NEMO_TYPE_VIEW nemo_view_get_type() #define NEMO_VIEW(obj)\ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_VIEW, NemoView)) #define NEMO_VIEW_CLASS(klass)\ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_VIEW, NemoViewClass)) #define NEMO_IS_VIEW(obj)\ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_VIEW)) #define NEMO_IS_VIEW_CLASS(klass)\ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_VIEW)) #define NEMO_VIEW_GET_CLASS(obj)\ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_VIEW, NemoViewClass)) typedef struct NemoViewDetails NemoViewDetails; struct NemoView { GtkScrolledWindow parent; NemoViewDetails *details; }; struct NemoViewClass { GtkScrolledWindowClass parent_class; /* The 'clear' signal is emitted to empty the view of its contents. * It must be replaced by each subclass. */ void (* clear) (NemoView *view); /* The 'begin_file_changes' signal is emitted before a set of files * are added to the view. It can be replaced by a subclass to do any * necessary preparation for a set of new files. The default * implementation does nothing. */ void (* begin_file_changes) (NemoView *view); /* The 'add_file' signal is emitted to add one file to the view. * It must be replaced by each subclass. */ void (* add_file) (NemoView *view, NemoFile *file, NemoDirectory *directory); void (* remove_file) (NemoView *view, NemoFile *file, NemoDirectory *directory); /* The 'file_changed' signal is emitted to signal a change in a file, * including the file being removed. * It must be replaced by each subclass. */ void (* file_changed) (NemoView *view, NemoFile *file, NemoDirectory *directory); /* The 'end_file_changes' signal is emitted after a set of files * are added to the view. It can be replaced by a subclass to do any * necessary cleanup (typically, cleanup for code in begin_file_changes). * The default implementation does nothing. */ void (* end_file_changes) (NemoView *view); /* The 'begin_loading' signal is emitted before any of the contents * of a directory are added to the view. It can be replaced by a * subclass to do any necessary preparation to start dealing with a * new directory. The default implementation does nothing. */ void (* begin_loading) (NemoView *view); /* The 'end_loading' signal is emitted after all of the contents * of a directory are added to the view. It can be replaced by a * subclass to do any necessary clean-up. The default implementation * does nothing. * * If all_files_seen is true, the handler may assume that * no load error ocurred, and all files of the underlying * directory were loaded. * * Otherwise, end_loading was emitted due to cancellation, * which usually means that not all files are available. */ void (* end_loading) (NemoView *view, gboolean all_files_seen); /* The 'load_error' signal is emitted when the directory model * reports an error in the process of monitoring the directory's * contents. The load error indicates that the process of * loading the contents has ended, but the directory is still * being monitored. The default implementation handles common * load failures like ACCESS_DENIED. */ void (* load_error) (NemoView *view, GError *error); /* Function pointers that don't have corresponding signals */ /* reset_to_defaults is a function pointer that subclasses must * override to set sort order, zoom level, etc to match default * values. */ void (* reset_to_defaults) (NemoView *view); /* get_backing uri is a function pointer for subclasses to * override. Subclasses may replace it with a function that * returns the URI for the location where to create new folders, * files, links and paste the clipboard to. */ char * (* get_backing_uri) (NemoView *view); /* get_selection is not a signal; it is just a function pointer for * subclasses to replace (override). Subclasses must replace it * with a function that returns a newly-allocated GList of * NemoFile pointers. */ GList * (* get_selection) (NemoView *view); /* get_selection_for_file_transfer is a function pointer for * subclasses to replace (override). Subclasses must replace it * with a function that returns a newly-allocated GList of * NemoFile pointers. The difference from get_selection is * that any files in the selection that also has a parent folder * in the selection is not included. */ GList * (* get_selection_for_file_transfer)(NemoView *view); /* select_all is a function pointer that subclasses must override to * select all of the items in the view */ void (* select_all) (NemoView *view); /* set_selection is a function pointer that subclasses must * override to select the specified items (and unselect all * others). The argument is a list of NemoFiles. */ void (* set_selection) (NemoView *view, GList *selection); /* invert_selection is a function pointer that subclasses must * override to invert selection. */ void (* invert_selection) (NemoView *view); /* Return an array of locations of selected icons in their view. */ GArray * (* get_selected_icon_locations) (NemoView *view); guint (* get_item_count) (NemoView *view); /* bump_zoom_level is a function pointer that subclasses must override * to change the zoom level of an object. */ void (* bump_zoom_level) (NemoView *view, int zoom_increment); /* zoom_to_level is a function pointer that subclasses must override * to set the zoom level of an object to the specified level. */ void (* zoom_to_level) (NemoView *view, NemoZoomLevel level); NemoZoomLevel (* get_zoom_level) (NemoView *view); /* restore_default_zoom_level is a function pointer that subclasses must override * to restore the zoom level of an object to a default setting. */ void (* restore_default_zoom_level) (NemoView *view); /* return the default zoom level for the current view */ NemoZoomLevel (* get_default_zoom_level) (NemoView *view); /* can_zoom_in is a function pointer that subclasses must override to * return whether the view is at maximum size (furthest-in zoom level) */ gboolean (* can_zoom_in) (NemoView *view); /* can_zoom_out is a function pointer that subclasses must override to * return whether the view is at minimum size (furthest-out zoom level) */ gboolean (* can_zoom_out) (NemoView *view); /* reveal_selection is a function pointer that subclasses may * override to make sure the selected items are sufficiently * apparent to the user (e.g., scrolled into view). By default, * this does nothing. */ void (* reveal_selection) (NemoView *view); /* merge_menus is a function pointer that subclasses can override to * add their own menu items to the window's menu bar. * If overridden, subclasses must call parent class's function. */ void (* merge_menus) (NemoView *view); void (* unmerge_menus) (NemoView *view); /* update_menus is a function pointer that subclasses can override to * update the sensitivity or wording of menu items in the menu bar. * It is called (at least) whenever the selection changes. If overridden, * subclasses must call parent class's function. */ void (* update_menus) (NemoView *view); /* sort_files is a function pointer that subclasses can override * to provide a sorting order to determine which files should be * presented when only a partial list is provided. */ int (* compare_files) (NemoView *view, NemoFile *a, NemoFile *b); /* using_manual_layout is a function pointer that subclasses may * override to control whether or not items can be freely positioned * on the user-visible area. * Note that this value is not guaranteed to be constant within the * view's lifecycle. */ gboolean (* using_manual_layout) (NemoView *view); /* is_read_only is a function pointer that subclasses may * override to control whether or not the user is allowed to * change the contents of the currently viewed directory. The * default implementation checks the permissions of the * directory. */ gboolean (* is_read_only) (NemoView *view); /* is_empty is a function pointer that subclasses must * override to report whether the view contains any items. */ gboolean (* is_empty) (NemoView *view); gboolean (* can_rename_file) (NemoView *view, NemoFile *file); /* select_all specifies whether the whole filename should be selected * or only its basename (i.e. everything except the extension) * */ void (* start_renaming_file) (NemoView *view, NemoFile *file, gboolean select_all); /* convert *point from widget's coordinate system to a coordinate * system used for specifying file operation positions, which is view-specific. * * This is used by the the icon view, which converts the screen position to a zoom * level-independent coordinate system. */ void (* widget_to_file_operation_position) (NemoView *view, GdkPoint *position); /* Preference change callbacks, overriden by icon and list views. * Icon and list views respond by synchronizing to the new preference * values and forcing an update if appropriate. */ void (* click_policy_changed) (NemoView *view); void (* click_to_rename_mode_changed) (NemoView *view); void (* sort_directories_first_changed) (NemoView *view); /* Get the id string for this view. Its a constant string, not memory managed */ const char * (* get_view_id) (NemoView *view); /* Return the uri of the first visible file */ char * (* get_first_visible_file) (NemoView *view); /* Scroll the view so that the file specified by the uri is at the top of the view */ void (* scroll_to_file) (NemoView *view, const char *uri); /* Signals used only for keybindings */ gboolean (* trash) (NemoView *view); gboolean (* delete) (NemoView *view); }; /* GObject support */ GType nemo_view_get_type (void); /* Functions callable from the user interface and elsewhere. */ NemoWindow *nemo_view_get_nemo_window (NemoView *view); NemoWindowSlot *nemo_view_get_nemo_window_slot (NemoView *view); char * nemo_view_get_uri (NemoView *view); void nemo_view_display_selection_info (NemoView *view); GdkAtom nemo_view_get_copied_files_atom (NemoView *view); gboolean nemo_view_get_active (NemoView *view); /* Wrappers for signal emitters. These are normally called * only by NemoView itself. They have corresponding signals * that observers might want to connect with. */ gboolean nemo_view_get_loading (NemoView *view); /* Hooks for subclasses to call. These are normally called only by * NemoView and its subclasses */ void nemo_view_activate_files (NemoView *view, GList *files, NemoWindowOpenFlags flags, gboolean confirm_multiple); void nemo_view_activate_file (NemoView *view, NemoFile *file, NemoWindowOpenFlags flags); void nemo_view_preview_files (NemoView *view, GList *files, GArray *locations); void nemo_view_start_batching_selection_changes (NemoView *view); void nemo_view_stop_batching_selection_changes (NemoView *view); void nemo_view_notify_selection_changed (NemoView *view); GtkUIManager * nemo_view_get_ui_manager (NemoView *view); NemoDirectory *nemo_view_get_model (NemoView *view); NemoFile *nemo_view_get_directory_as_file (NemoView *view); void nemo_view_pop_up_background_context_menu (NemoView *view, GdkEventButton *event); void nemo_view_pop_up_selection_context_menu (NemoView *view, GdkEventButton *event); gboolean nemo_view_should_show_file (NemoView *view, NemoFile *file); gboolean nemo_view_should_sort_directories_first (NemoView *view); void nemo_view_ignore_hidden_file_preferences (NemoView *view); void nemo_view_set_show_foreign (NemoView *view, gboolean show_foreign); gboolean nemo_view_handle_scroll_event (NemoView *view, GdkEventScroll *event); void nemo_view_freeze_updates (NemoView *view); void nemo_view_unfreeze_updates (NemoView *view); gboolean nemo_view_get_is_renaming (NemoView *view); void nemo_view_set_is_renaming (NemoView *view, gboolean renaming); void nemo_view_add_subdirectory (NemoView *view, NemoDirectory*directory); void nemo_view_remove_subdirectory (NemoView *view, NemoDirectory*directory); gboolean nemo_view_is_editable (NemoView *view); /* NemoView methods */ const char * nemo_view_get_view_id (NemoView *view); /* file operations */ char * nemo_view_get_backing_uri (NemoView *view); void nemo_view_move_copy_items (NemoView *view, const GList *item_uris, GArray *relative_item_points, const char *target_uri, int copy_action, int x, int y); void nemo_view_new_file_with_initial_contents (NemoView *view, const char *parent_uri, const char *filename, const char *initial_contents, int length, GdkPoint *pos); /* selection handling */ int nemo_view_get_selection_count (NemoView *view); GList * nemo_view_get_selection (NemoView *view); void nemo_view_set_selection (NemoView *view, GList *selection); void nemo_view_load_location (NemoView *view, GFile *location); void nemo_view_stop_loading (NemoView *view); char ** nemo_view_get_emblem_names_to_exclude (NemoView *view); char * nemo_view_get_first_visible_file (NemoView *view); void nemo_view_scroll_to_file (NemoView *view, const char *uri); char * nemo_view_get_title (NemoView *view); gboolean nemo_view_supports_zooming (NemoView *view); void nemo_view_bump_zoom_level (NemoView *view, int zoom_increment); void nemo_view_zoom_to_level (NemoView *view, NemoZoomLevel level); void nemo_view_restore_default_zoom_level (NemoView *view); gboolean nemo_view_can_zoom_in (NemoView *view); gboolean nemo_view_can_zoom_out (NemoView *view); NemoZoomLevel nemo_view_get_zoom_level (NemoView *view); void nemo_view_pop_up_location_context_menu (NemoView *view, GdkEventButton *event, const char *location); void nemo_view_grab_focus (NemoView *view); void nemo_view_update_menus (NemoView *view); void nemo_view_new_folder (NemoView *view); #endif /* NEMO_VIEW_H */ nemo-3.6.5/src/nemo-x-content-bar.c0000664000175000017500000002054013215733314015762 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2008 Red Hat, Inc. * Copyright (C) 2006 Paolo Borelli * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. * * Authors: David Zeuthen * Paolo Borelli * */ #include "config.h" #include #include #include #include "nemo-x-content-bar.h" #include #include #define NEMO_X_CONTENT_BAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NEMO_TYPE_X_CONTENT_BAR, NemoXContentBarPrivate)) struct NemoXContentBarPrivate { GtkWidget *label; GtkWidget *button; char *x_content_type; GMount *mount; }; enum { PROP_0, PROP_MOUNT, PROP_X_CONTENT_TYPE, }; enum { CONTENT_BAR_RESPONSE_APP = 1 }; G_DEFINE_TYPE (NemoXContentBar, nemo_x_content_bar, GTK_TYPE_INFO_BAR) static void content_bar_response_cb (GtkInfoBar *infobar, gint response_id, gpointer user_data) { GAppInfo *default_app; NemoXContentBar *bar; if (response_id != CONTENT_BAR_RESPONSE_APP) { return; } bar = user_data; if (bar->priv->x_content_type == NULL || bar->priv->mount == NULL) return; default_app = g_app_info_get_default_for_type (bar->priv->x_content_type, FALSE); if (default_app != NULL) { nemo_launch_application_for_mount (default_app, bar->priv->mount, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (bar)))); g_object_unref (default_app); } } static void nemo_x_content_bar_set_x_content_type (NemoXContentBar *bar, const char *x_content_type) { char *message; char *description; GAppInfo *default_app; g_free (bar->priv->x_content_type); bar->priv->x_content_type = g_strdup (x_content_type); description = g_content_type_get_description (x_content_type); /* Customize greeting for well-known x-content types */ if (strcmp (x_content_type, "x-content/audio-cdda") == 0) { message = g_strdup (_("These files are on an Audio CD.")); } else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) { message = g_strdup (_("These files are on an Audio DVD.")); } else if (strcmp (x_content_type, "x-content/video-dvd") == 0) { message = g_strdup (_("These files are on a Video DVD.")); } else if (strcmp (x_content_type, "x-content/video-vcd") == 0) { message = g_strdup (_("These files are on a Video CD.")); } else if (strcmp (x_content_type, "x-content/video-svcd") == 0) { message = g_strdup (_("These files are on a Super Video CD.")); } else if (strcmp (x_content_type, "x-content/image-photocd") == 0) { message = g_strdup (_("These files are on a Photo CD.")); } else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) { message = g_strdup (_("These files are on a Picture CD.")); } else if (strcmp (x_content_type, "x-content/image-dcf") == 0) { message = g_strdup (_("The media contains digital photos.")); } else if (strcmp (x_content_type, "x-content/audio-player") == 0) { message = g_strdup (_("These files are on a digital audio player.")); } else if (strcmp (x_content_type, "x-content/software") == 0) { message = g_strdup (_("The media contains software.")); } else { /* fallback to generic greeting */ message = g_strdup_printf (_("The media has been detected as \"%s\"."), description); } gtk_label_set_text (GTK_LABEL (bar->priv->label), message); gtk_widget_show (bar->priv->label); /* TODO: We really need a GtkBrowserBackButton-ish widget here.. until then, we only * show the default application. */ default_app = g_app_info_get_default_for_type (x_content_type, FALSE); if (default_app != NULL) { char *button_text; const char *name; GIcon *icon; GtkWidget *image; icon = g_app_info_get_icon (default_app); if (icon != NULL) { image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON); } else { image = NULL; } name = g_app_info_get_display_name (default_app); button_text = g_strdup_printf (_("Open %s"), name); gtk_button_set_image (GTK_BUTTON (bar->priv->button), image); gtk_button_set_label (GTK_BUTTON (bar->priv->button), button_text); gtk_widget_show (bar->priv->button); g_free (button_text); g_object_unref (default_app); } else { gtk_widget_hide (bar->priv->button); } g_free (message); g_free (description); } static void nemo_x_content_bar_set_mount (NemoXContentBar *bar, GMount *mount) { if (bar->priv->mount != NULL) { g_object_unref (bar->priv->mount); } bar->priv->mount = mount != NULL ? g_object_ref (mount) : NULL; } static void nemo_x_content_bar_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NemoXContentBar *bar; bar = NEMO_X_CONTENT_BAR (object); switch (prop_id) { case PROP_MOUNT: nemo_x_content_bar_set_mount (bar, G_MOUNT (g_value_get_object (value))); break; case PROP_X_CONTENT_TYPE: nemo_x_content_bar_set_x_content_type (bar, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_x_content_bar_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NemoXContentBar *bar = NEMO_X_CONTENT_BAR (object); switch (prop_id) { case PROP_MOUNT: g_value_set_object (value, bar->priv->mount); break; case PROP_X_CONTENT_TYPE: g_value_set_string (value, bar->priv->x_content_type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_x_content_bar_finalize (GObject *object) { NemoXContentBar *bar = NEMO_X_CONTENT_BAR (object); g_free (bar->priv->x_content_type); if (bar->priv->mount != NULL) g_object_unref (bar->priv->mount); G_OBJECT_CLASS (nemo_x_content_bar_parent_class)->finalize (object); } static void nemo_x_content_bar_class_init (NemoXContentBarClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->get_property = nemo_x_content_bar_get_property; object_class->set_property = nemo_x_content_bar_set_property; object_class->finalize = nemo_x_content_bar_finalize; g_type_class_add_private (klass, sizeof (NemoXContentBarPrivate)); g_object_class_install_property (object_class, PROP_MOUNT, g_param_spec_object ( "mount", "The GMount to run programs for", "The GMount to run programs for", G_TYPE_MOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_X_CONTENT_TYPE, g_param_spec_string ( "x-content-type", "The x-content type for the cluebar", "The x-content type for the cluebar", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } static void nemo_x_content_bar_init (NemoXContentBar *bar) { GtkWidget *content_area; bar->priv = NEMO_X_CONTENT_BAR_GET_PRIVATE (bar); content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (bar)); bar->priv->label = gtk_label_new (NULL); gtk_style_context_add_class (gtk_widget_get_style_context (bar->priv->label), "nemo-cluebar-label"); gtk_label_set_ellipsize (GTK_LABEL (bar->priv->label), PANGO_ELLIPSIZE_END); gtk_container_add (GTK_CONTAINER (content_area), bar->priv->label); bar->priv->button = gtk_info_bar_add_button (GTK_INFO_BAR (bar), "", CONTENT_BAR_RESPONSE_APP); g_signal_connect (bar, "response", G_CALLBACK (content_bar_response_cb), bar); } GtkWidget * nemo_x_content_bar_new (GMount *mount, const char *x_content_type) { return g_object_new (NEMO_TYPE_X_CONTENT_BAR, "mount", mount, "x-content-type", x_content_type, NULL); } nemo-3.6.5/src/nemo-statusbar-ui.xml0000664000175000017500000000041713215733314016303 0ustar fabiofabio nemo-3.6.5/src/nemo-floating-bar.c0000664000175000017500000002266213215733314015655 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Nemo - Floating status bar. * * Copyright (C) 2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Cosimo Cecchi * */ #include #include "nemo-floating-bar.h" struct _NemoFloatingBarDetails { gchar *label; GtkWidget *label_widget; GtkWidget *spinner; gboolean show_spinner; gboolean is_interactive; }; enum { PROP_LABEL = 1, PROP_SHOW_SPINNER, NUM_PROPERTIES }; enum { ACTION, NUM_SIGNALS }; static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; static guint signals[NUM_SIGNALS] = { 0, }; G_DEFINE_TYPE (NemoFloatingBar, nemo_floating_bar, GTK_TYPE_BOX); static void action_button_clicked_cb (GtkButton *button, NemoFloatingBar *self) { gint action_id; action_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "action-id")); g_signal_emit (self, signals[ACTION], 0, action_id); } static void nemo_floating_bar_finalize (GObject *obj) { NemoFloatingBar *self = NEMO_FLOATING_BAR (obj); g_free (self->priv->label); G_OBJECT_CLASS (nemo_floating_bar_parent_class)->finalize (obj); } static void nemo_floating_bar_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { NemoFloatingBar *self = NEMO_FLOATING_BAR (object); switch (property_id) { case PROP_LABEL: g_value_set_string (value, self->priv->label); break; case PROP_SHOW_SPINNER: g_value_set_boolean (value, self->priv->show_spinner); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_floating_bar_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { NemoFloatingBar *self = NEMO_FLOATING_BAR (object); switch (property_id) { case PROP_LABEL: nemo_floating_bar_set_label (self, g_value_get_string (value)); break; case PROP_SHOW_SPINNER: nemo_floating_bar_set_show_spinner (self, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void update_label (NemoFloatingBar *self) { gtk_label_set_text (GTK_LABEL (self->priv->label_widget), self->priv->label); } static gboolean overlay_enter_notify_cb (GtkWidget *parent, GdkEventCrossing *event, gpointer user_data) { GtkWidget *widget = user_data; if (event->window != gtk_widget_get_window (widget)) { return FALSE; } if (NEMO_FLOATING_BAR (widget)->priv->is_interactive) { return FALSE; } if (gtk_widget_get_halign (widget) == GTK_ALIGN_START) { gtk_widget_set_halign (widget, GTK_ALIGN_END); } else { gtk_widget_set_halign (widget, GTK_ALIGN_START); } gtk_widget_queue_resize (widget); return FALSE; } static void nemo_floating_bar_parent_set (GtkWidget *widget, GtkWidget *old_parent) { GtkWidget *parent; parent = gtk_widget_get_parent (widget); if (old_parent != NULL) { g_signal_handlers_disconnect_by_func (old_parent, overlay_enter_notify_cb, widget); } if (parent != NULL) { g_signal_connect (parent, "enter-notify-event", G_CALLBACK (overlay_enter_notify_cb), widget); } } static void nemo_floating_bar_show (GtkWidget *widget) { NemoFloatingBar *self = NEMO_FLOATING_BAR (widget); GTK_WIDGET_CLASS (nemo_floating_bar_parent_class)->show (widget); if (self->priv->show_spinner) { gtk_spinner_start (GTK_SPINNER (self->priv->spinner)); } } static void nemo_floating_bar_hide (GtkWidget *widget) { NemoFloatingBar *self = NEMO_FLOATING_BAR (widget); GTK_WIDGET_CLASS (nemo_floating_bar_parent_class)->hide (widget); gtk_spinner_stop (GTK_SPINNER (self->priv->spinner)); } static gboolean nemo_floating_bar_draw (GtkWidget *widget, cairo_t *cr) { GtkStyleContext *context; context = gtk_widget_get_style_context (widget); gtk_style_context_save (context); gtk_style_context_set_state (context, gtk_widget_get_state_flags (widget)); gtk_render_background (context, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); gtk_render_frame (context, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); gtk_style_context_restore (context); return GTK_WIDGET_CLASS (nemo_floating_bar_parent_class)->draw (widget, cr);; } static void nemo_floating_bar_constructed (GObject *obj) { NemoFloatingBar *self = NEMO_FLOATING_BAR (obj); GtkWidget *w, *box; G_OBJECT_CLASS (nemo_floating_bar_parent_class)->constructed (obj); box = GTK_WIDGET (obj); w = gtk_spinner_new (); gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0); gtk_widget_set_visible (w, self->priv->show_spinner); self->priv->spinner = w; gtk_widget_set_size_request (w, 16, 16); gtk_widget_set_margin_left (w, 8); w = gtk_label_new (NULL); gtk_label_set_ellipsize (GTK_LABEL (w), PANGO_ELLIPSIZE_END); gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0); g_object_set (w, "margin-top", 2, "margin-bottom", 2, "margin-left", 12, "margin-right", 12, NULL); self->priv->label_widget = w; gtk_widget_show (w); } static void nemo_floating_bar_init (NemoFloatingBar *self) { GtkStyleContext *context; self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_FLOATING_BAR, NemoFloatingBarDetails); context = gtk_widget_get_style_context (GTK_WIDGET (self)); gtk_style_context_add_class (context, "floating-bar"); } static void nemo_floating_bar_class_init (NemoFloatingBarClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass); oclass->constructed = nemo_floating_bar_constructed; oclass->set_property = nemo_floating_bar_set_property; oclass->get_property = nemo_floating_bar_get_property; oclass->finalize = nemo_floating_bar_finalize; wclass->draw = nemo_floating_bar_draw; wclass->show = nemo_floating_bar_show; wclass->hide = nemo_floating_bar_hide; wclass->parent_set = nemo_floating_bar_parent_set; properties[PROP_LABEL] = g_param_spec_string ("label", "Bar's label", "Label displayed by the bar", NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS); properties[PROP_SHOW_SPINNER] = g_param_spec_boolean ("show-spinner", "Show spinner", "Whether a spinner should be shown in the floating bar", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); signals[ACTION] = g_signal_new ("action", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); g_type_class_add_private (klass, sizeof (NemoFloatingBarDetails)); g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); } void nemo_floating_bar_set_label (NemoFloatingBar *self, const gchar *label) { if (g_strcmp0 (self->priv->label, label) != 0) { g_free (self->priv->label); self->priv->label = g_strdup (label); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LABEL]); update_label (self); } } void nemo_floating_bar_set_show_spinner (NemoFloatingBar *self, gboolean show_spinner) { if (self->priv->show_spinner != show_spinner) { self->priv->show_spinner = show_spinner; gtk_widget_set_visible (self->priv->spinner, show_spinner); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_SPINNER]); } } GtkWidget * nemo_floating_bar_new (const gchar *label, gboolean show_spinner) { return g_object_new (NEMO_TYPE_FLOATING_BAR, "label", label, "show-spinner", show_spinner, "orientation", GTK_ORIENTATION_HORIZONTAL, "spacing", 8, NULL); } void nemo_floating_bar_add_action (NemoFloatingBar *self, const gchar *stock_id, gint action_id) { GtkWidget *w, *button; w = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU); gtk_widget_show (w); button = gtk_button_new (); gtk_button_set_image (GTK_BUTTON (button), w); gtk_box_pack_end (GTK_BOX (self), button, FALSE, FALSE, 0); gtk_widget_show (button); g_object_set_data (G_OBJECT (button), "action-id", GINT_TO_POINTER (action_id)); g_signal_connect (button, "clicked", G_CALLBACK (action_button_clicked_cb), self); self->priv->is_interactive = TRUE; } void nemo_floating_bar_cleanup_actions (NemoFloatingBar *self) { GtkWidget *widget; GList *children, *l; gpointer data; children = gtk_container_get_children (GTK_CONTAINER (self)); l = children; while (l != NULL) { widget = l->data; data = g_object_get_data (G_OBJECT (widget), "action-id"); l = l->next; if (data != NULL) { /* destroy this */ gtk_widget_destroy (widget); } } g_list_free (children); self->priv->is_interactive = FALSE; } nemo-3.6.5/src/nemo-x-content-bar.h0000664000175000017500000000423013215733314015765 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2008 Red Hat, Inc. * Copyright (C) 2006 Paolo Borelli * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. * * Authors: David Zeuthen * Paolo Borelli * */ #ifndef __NEMO_X_CONTENT_BAR_H #define __NEMO_X_CONTENT_BAR_H #include #include G_BEGIN_DECLS #define NEMO_TYPE_X_CONTENT_BAR (nemo_x_content_bar_get_type ()) #define NEMO_X_CONTENT_BAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_X_CONTENT_BAR, NemoXContentBar)) #define NEMO_X_CONTENT_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_X_CONTENT_BAR, NemoXContentBarClass)) #define NEMO_IS_X_CONTENT_BAR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_X_CONTENT_BAR)) #define NEMO_IS_X_CONTENT_BAR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_X_CONTENT_BAR)) #define NEMO_X_CONTENT_BAR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_X_CONTENT_BAR, NemoXContentBarClass)) typedef struct NemoXContentBarPrivate NemoXContentBarPrivate; typedef struct { GtkInfoBar parent; NemoXContentBarPrivate *priv; } NemoXContentBar; typedef struct { GtkInfoBarClass parent_class; } NemoXContentBarClass; GType nemo_x_content_bar_get_type (void) G_GNUC_CONST; GtkWidget *nemo_x_content_bar_new (GMount *mount, const char *x_content_type); G_END_DECLS #endif /* __NEMO_X_CONTENT_BAR_H */ nemo-3.6.5/.github/0000775000175000017500000000000013215733314012751 5ustar fabiofabionemo-3.6.5/.github/ISSUE_TEMPLATE.md0000664000175000017500000000043413215733314015457 0ustar fabiofabio ``` * Nemo version (nemo --version) * Is issue with desktop or windowed nemo? * Distribution - (Mint 17.2, Arch, Fedora 25, etc...) * Graphics hardware *and* driver used * 32 or 64 bit ``` **Issue** **Steps to reproduce** **Expected behaviour** **Other information** nemo-3.6.5/icons/0000775000175000017500000000000013215733314012524 5ustar fabiofabionemo-3.6.5/icons/thumbnail_frame.png0000664000175000017500000000427013215733314016372 0ustar fabiofabio‰PNG  IHDRôxÔúsRGB®ÎérIDATxÚíÛ½jG€áw%}Ф²{ßÿ½8EŒ„SÈÑÏl AQŠãoçy`ø,©9 ûÎÊ.àÌöyþõM༮çù‡+{€S»™ŸGõûü|pnoççsõT=T÷Îíý¼õ?V_ª»ê“€s{WŸ«ßÊ¿€³»™oþª~­¶êVÀ¹]Ϩú¥úXýì¿À¹íóÖ¿Uoúúö°V ìÕ&`Ñ @€ @€` @€ @€ @€ @€ @€ @€ ücžCÀZÿ½Ú,Z€ @€ @ ¬ @€ @€¬dÌsXëâ¿W›€EK€ @€ @€€ @€ @°°1Ï!`­‹ÿ^m-@€ @€ V€ @€ @ÀÂÆ<‡€µ.þ{µ X´@€ @€ @X@€ @€  óÖºøïÕ&`Ñ @€ @€` @€ @€,lÌsXëâ¿W›€EK€ @€ @€€ @€ @°°1Ï!`­‹ÿ^m-@€ @€ V€ @€ @ÀÂÆ<‡€µ.þ{µ X´@€ @€ @X@€ @€  óÖºøïÕ&`Ñ @€ @€` @€ @€,lÌsXëâ¿W›€EK€ @€ @€€ @€ @°°1Ï!`­‹ÿ^m-@€ @€ V€ @€ @ÀÂÆ<‡€µ.þ{µ X´@€ @€ @X@€ @€ð_®^„ÀuuS½­ÞWïæ××Bί՘Ÿßþ \ž——øñíù~õâ÷óaÿ\=VÕ—ùóÍþàâ=VOÕxýài>ôÿ¬nçƒÿM~ð=pßf2“™Ìd¦ËŸé±úT}®î_ÀCuW}˜_œà À÷sü€û6“™Ìd&3]þLóáÿ¡º{÷³ªþ¨~š#üÅ1“™Ìd&3]öL£¯oùïªÛ¿']Šç¼w`ôIEND®B`‚nemo-3.6.5/icons/knob.png0000664000175000017500000000031613215733314014163 0ustar fabiofabio‰PNG  IHDR PXê•IDATÓuÏ1 Â@пìÿ!Hk›«x /#žÁ£¤M¡í6bH,[[¬ ‰8L1ðf>L8/ø_p=ŸÆ¼î`ÉSž+Œyn€ Ó¢MY¥¨l»)Ñ–m~ÂÐj§ïmÙ¢);ÚL¦~X6­h±Í[6[§D+¦o^òTŠw=ó½ëÈsꎻ~ðBÄÁ&AÐIEND®B`‚nemo-3.6.5/icons/Makefile.am0000664000175000017500000000013713215733314014561 0ustar fabiofabioNULL= noinst_DATA =\ knob.png \ thumbnail_frame.png \ $(NULL) EXTRA_DIST = $(noinst_DATA) nemo-3.6.5/Makefile.shared0000664000175000017500000000000713215733314014313 0ustar fabiofabioNULL = nemo-3.6.5/makepot0000775000175000017500000000044313215733314013000 0ustar fabiofabio#!/bin/bash data/extract_action_strings data xgettext --from-code=UTF-8 --keyword=_ --keyword=N_ --output=nemo.pot src/*.c libnemo-extension/*.c libnemo-private/*.c eel/*.c data/action_i18n_strings.py generate_additional_file xgettext --join-existing -L Glade src/*.glade --output=nemo.pot nemo-3.6.5/libnemo-private/0000775000175000017500000000000013215733314014506 5ustar fabiofabionemo-3.6.5/libnemo-private/nemo-search-directory.h0000664000175000017500000000554213215733314021070 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-search-directory.h: Subclass of NemoDirectory to implement a virtual directory consisting of the search directory and the search icons Copyright (C) 2005 Novell, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_SEARCH_DIRECTORY_H #define NEMO_SEARCH_DIRECTORY_H #include #include #define NEMO_TYPE_SEARCH_DIRECTORY nemo_search_directory_get_type() #define NEMO_SEARCH_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEARCH_DIRECTORY, NemoSearchDirectory)) #define NEMO_SEARCH_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEARCH_DIRECTORY, NemoSearchDirectoryClass)) #define NEMO_IS_SEARCH_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEARCH_DIRECTORY)) #define NEMO_IS_SEARCH_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEARCH_DIRECTORY)) #define NEMO_SEARCH_DIRECTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEARCH_DIRECTORY, NemoSearchDirectoryClass)) typedef struct NemoSearchDirectoryDetails NemoSearchDirectoryDetails; typedef struct { NemoDirectory parent_slot; NemoSearchDirectoryDetails *details; } NemoSearchDirectory; typedef struct { NemoDirectoryClass parent_slot; } NemoSearchDirectoryClass; GType nemo_search_directory_get_type (void); char *nemo_search_directory_generate_new_uri (void); NemoSearchDirectory *nemo_search_directory_new_from_saved_search (const char *uri); gboolean nemo_search_directory_is_saved_search (NemoSearchDirectory *search); gboolean nemo_search_directory_is_modified (NemoSearchDirectory *search); void nemo_search_directory_save_search (NemoSearchDirectory *search); void nemo_search_directory_save_to_file (NemoSearchDirectory *search, const char *save_file_uri); NemoQuery *nemo_search_directory_get_query (NemoSearchDirectory *search); void nemo_search_directory_set_query (NemoSearchDirectory *search, NemoQuery *query); #endif /* NEMO_SEARCH_DIRECTORY_H */ nemo-3.6.5/libnemo-private/nemo-icon-private.h0000664000175000017500000004723513215733314020226 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* gnome-icon-container-private.h Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Ettore Perazzoli */ #ifndef NEMO_ICON_CONTAINER_PRIVATE_H #define NEMO_ICON_CONTAINER_PRIVATE_H #include #include #include #include #include /* Private NemoIconContainer members. */ typedef struct { double start_x, start_y; EelCanvasItem *selection_rectangle; EelDRect prev_rect; guint timer_id; guint prev_x, prev_y; int last_adj_x; int last_adj_y; gboolean active; } NemoIconRubberbandInfo; typedef enum { DRAG_STATE_INITIAL, DRAG_STATE_MOVE_OR_COPY, DRAG_STATE_STRETCH } DragState; typedef struct { /* Pointer position in canvas coordinates. */ int pointer_x, pointer_y; /* Icon top, left, and size in canvas coordinates. */ int icon_x, icon_y; guint icon_size; } StretchState; typedef enum { AXIS_NONE, AXIS_HORIZONTAL, AXIS_VERTICAL } Axis; enum { LABEL_COLOR, LABEL_COLOR_HIGHLIGHT, LABEL_COLOR_ACTIVE, LABEL_COLOR_PRELIGHT, LABEL_INFO_COLOR, LABEL_INFO_COLOR_HIGHLIGHT, LABEL_INFO_COLOR_ACTIVE, LAST_LABEL_COLOR }; typedef struct { gint icon_pad_left; gint icon_pad_right; gint icon_pad_top; gint icon_pad_bottom; gint container_pad_left; gint container_pad_right; gint container_pad_top; gint container_pad_bottom; gint standard_icon_grid_width; gint text_beside_icon_grid_width; gint desktop_pad_horizontal; gint desktop_pad_vertical; gint snap_size_x; gint snap_size_y; gint max_text_width_standard; gint max_text_width_tighter; gint max_text_width_beside; gint max_text_width_beside_top_to_bottom; gint icon_vertical_adjust; } NemoViewLayoutConstants; typedef struct { NemoIconContainer *container; GtkBorder *borders; int **icon_grid; int *grid_memory; int num_rows; int num_columns; int icon_size; int real_snap_x; int real_snap_y; gboolean horizontal; } NemoCenteredPlacementGrid; typedef struct { NemoIconContainer *container; int **icon_grid; int *grid_memory; int num_rows; int num_columns; gboolean tight; } NemoPlacementGrid; struct NemoIconContainerDetails { /* List of icons. */ GList *icons; GList *new_icons; GHashTable *icon_set; /* Current icon for keyboard navigation. */ NemoIcon *keyboard_focus; NemoIcon *keyboard_rubberband_start; /* Rubberbanding status. */ NemoIconRubberbandInfo rubberband_info; NemoViewLayoutConstants *view_constants; /* Last highlighted drop target. */ NemoIcon *drop_target; /* Current icon with stretch handles, so we have only one. */ NemoIcon *stretch_icon; double stretch_initial_x, stretch_initial_y; /* The position we are scaling to on stretch */ double world_x; double world_y; guint stretch_initial_size; /* Timeout used to make a selected icon fully visible after a short * period of time. (The timeout is needed to make sure * double-clicking still works.) */ guint keyboard_icon_reveal_timer_id; NemoIcon *keyboard_icon_to_reveal; /* If a request is made to reveal an unpositioned icon we remember * it and reveal it once it gets positioned (in relayout). */ NemoIcon *pending_icon_to_reveal; /* If a request is made to rename an unpositioned icon we remember * it and start renaming it once it gets positioned (in relayout). */ NemoIcon *pending_icon_to_rename; /* Remembered information about the start of the current event. */ guint32 button_down_time; /* Drag state. Valid only if drag_button is non-zero. */ guint drag_button; NemoIcon *drag_icon; int drag_x, drag_y; DragState drag_state; gboolean drag_started; StretchState stretch_start; gboolean drag_allow_moves; gboolean icon_selected_on_button_down; guint double_click_button[2]; gboolean skip_rename_on_release; NemoIcon *double_click_icon[2]; /* Both clicks in a double click need to be on the same icon */ NemoIcon *range_selection_base_icon; /* DnD info. */ NemoIconDndInfo *dnd_info; /* Renaming Details */ GtkWidget *rename_widget; /* Editable text item */ char *original_text; /* Copy of editable text for later compare */ char *font; /* specific fonts used to draw labels */ gboolean renaming; /* Idle ID. */ guint idle_id; /* Idle handler for stretch code */ guint stretch_idle_id; /* Align idle id */ guint align_idle_id; /* Used to coalesce selection changed signals in some cases */ guint selection_changed_id; /* zoom level */ int zoom_level; /* font sizes used to draw labels */ int font_size_table[NEMO_ZOOM_LEVEL_LARGEST + 1]; /* State used so arrow keys don't wander if icons aren't lined up. */ int arrow_key_start_x; int arrow_key_start_y; GtkDirectionType arrow_key_direction; /* Mode settings. */ gboolean single_click_mode; gboolean auto_layout; gboolean stored_auto_layout; gboolean tighter_layout; gboolean click_to_rename; /* Whether for the vertical layout, all columns are supposed to * have the same width. */ gboolean all_columns_same_width; /* Layout mode */ NemoIconLayoutMode layout_mode; /* Label position */ NemoIconLabelPosition label_position; /* Forced icon size, iff greater than 0 */ int forced_icon_size; /* Should the container keep icons aligned to a grid */ gboolean keep_aligned; /* Set to TRUE after first allocation has been done */ gboolean has_been_allocated; int size_allocation_count; guint size_allocation_count_id; /* Is the container fixed or resizable */ gboolean is_fixed_size; /* Is the container for a desktop window */ gboolean is_desktop; /* Used by desktop grid container only */ gboolean horizontal; gboolean show_desktop_tooltips; gboolean show_icon_view_tooltips; /* Ignore the visible area the next time the scroll region is recomputed */ gboolean reset_scroll_region_trigger; gint tooltip_flags; /* Really a NemoFileTooltipFlags */ /* margins to follow, used for the desktop panel avoidance */ int left_margin; int right_margin; int top_margin; int bottom_margin; /* Whether we should use drop shadows for the icon labels or not */ gboolean use_drop_shadows; gboolean drop_shadows_requested; /* interactive search */ gboolean imcontext_changed; /* a11y items used by canvas items */ guint a11y_item_action_idle_handler; time_t layout_timestamp; GtkWidget *search_window; GtkWidget *search_entry; NemoCenteredPlacementGrid *dnd_grid; GQueue* a11y_item_action_queue; int selected_iter; guint search_entry_changed_id; guint typeselect_flush_timeout; gint current_dnd_x; gint current_dnd_y; gboolean insert_dnd_mode; eel_boolean_bit is_loading : 1; eel_boolean_bit needs_resort : 1; eel_boolean_bit store_layout_timestamps : 1; eel_boolean_bit store_layout_timestamps_when_finishing_new_icons : 1; }; typedef struct { double width; double height; double x_offset; double y_offset; } NemoCanvasRects; #define GET_VIEW_CONSTANT(c,name) (NEMO_ICON_CONTAINER (c)->details->view_constants->name) #define SNAP_HORIZONTAL(func,x) ((func ((double)((x) - GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) / GET_VIEW_CONSTANT (container, snap_size_x)) * GET_VIEW_CONSTANT (container, snap_size_x)) + GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) #define SNAP_VERTICAL(func, y) ((func ((double)((y) - GET_VIEW_CONSTANT (container, desktop_pad_vertical)) / GET_VIEW_CONSTANT (container, snap_size_y)) * GET_VIEW_CONSTANT (container, snap_size_y)) + GET_VIEW_CONSTANT (container, desktop_pad_vertical)) #define SNAP_NEAREST_HORIZONTAL(x) SNAP_HORIZONTAL (floor, x + .5) #define SNAP_NEAREST_VERTICAL(y) SNAP_VERTICAL (floor, y + .5) #define SNAP_CEIL_HORIZONTAL(x) SNAP_HORIZONTAL (ceil, x) #define SNAP_CEIL_VERTICAL(y) SNAP_VERTICAL (ceil, y) /* Private functions shared by mutiple files. */ NemoIcon *nemo_icon_container_get_icon_by_uri (NemoIconContainer *container, const char *uri); void nemo_icon_container_select_list_unselect_others (NemoIconContainer *container, GList *icons); char * nemo_icon_container_get_icon_uri (NemoIconContainer *container, NemoIcon *icon); char * nemo_icon_container_get_icon_drop_target_uri (NemoIconContainer *container, NemoIcon *icon); void nemo_icon_container_update_icon (NemoIconContainer *container, NemoIcon *icon); gboolean nemo_icon_container_scroll (NemoIconContainer *container, int delta_x, int delta_y); void nemo_icon_container_update_scroll_region (NemoIconContainer *container); gint nemo_icon_container_get_canvas_height (NemoIconContainer *container, GtkAllocation allocation); gint nemo_icon_container_get_canvas_width (NemoIconContainer *container, GtkAllocation allocation); double nemo_icon_container_get_mirror_x_position (NemoIconContainer *container, NemoIcon *icon, double x); void nemo_icon_container_set_rtl_positions (NemoIconContainer *container); void nemo_icon_container_end_renaming_mode (NemoIconContainer *container, gboolean commit); NemoIcon *nemo_icon_container_get_icon_being_renamed (NemoIconContainer *container); void nemo_icon_container_icon_set_position (NemoIconContainer *container, NemoIcon *icon, gdouble x, gdouble y); void nemo_icon_container_icon_get_bounding_box (NemoIconContainer *container, NemoIcon *icon, int *x1_return, int *y1_return, int *x2_return, int *y2_return, NemoIconCanvasItemBoundsUsage usage); void nemo_icon_container_move_icon (NemoIconContainer *container, NemoIcon *icon, int x, int y, double scale, gboolean raise, gboolean snap, gboolean update_position); void nemo_icon_container_icon_raise (NemoIconContainer *container, NemoIcon *icon); void nemo_icon_container_finish_adding_icon (NemoIconContainer *container, NemoIcon *icon); gboolean nemo_icon_container_icon_is_positioned (const NemoIcon *icon); void nemo_icon_container_sort_icons (NemoIconContainer *container, GList **icons); void nemo_icon_container_resort (NemoIconContainer *container); void nemo_icon_container_get_all_icon_bounds (NemoIconContainer *container, double *x1, double *y1, double *x2, double *y2, NemoIconCanvasItemBoundsUsage usage); void nemo_icon_container_store_layout_timestamps_now (NemoIconContainer *container); void nemo_icon_container_redo_layout (NemoIconContainer *container); void nemo_icon_container_start_monitor_top_left (NemoIconContainer *container, NemoIconData *data, gconstpointer client, gboolean large_text); void nemo_icon_container_stop_monitor_top_left (NemoIconContainer *container, NemoIconData *data, gconstpointer client); NemoIconInfo *nemo_icon_container_get_icon_images (NemoIconContainer *container, NemoIconData *data, int size, char **embedded_text, gboolean for_drag_accept, gboolean need_large_embeddded_text, gboolean *embedded_text_needs_loading, gboolean *has_open_window); void nemo_icon_container_get_icon_text (NemoIconContainer *container, NemoIconData *data, char **editable_text, char **additional_text, gboolean include_invisible); /* nemo-centered-placement-grid api * * used by nemo-icon-view-grid-container.c, nemo-icon-dnd.h */ NemoCenteredPlacementGrid *nemo_centered_placement_grid_new (NemoIconContainer *container, gboolean horizontal); void nemo_centered_placement_grid_free (NemoCenteredPlacementGrid *grid); void nemo_centered_placement_grid_nominal_to_icon_position (NemoCenteredPlacementGrid *grid, NemoIcon *icon, gint x_nominal, gint y_nominal, gint *x_adjusted, gint *y_adjusted); void nemo_centered_placement_grid_icon_position_to_nominal (NemoCenteredPlacementGrid *grid, NemoIcon *icon, gint x_adjusted, gint y_adjusted, gint *x_nominal, gint *y_nominal); void nemo_centered_placement_grid_mark_icon (NemoCenteredPlacementGrid *grid, NemoIcon *icon); void nemo_centered_placement_grid_unmark_icon (NemoCenteredPlacementGrid *grid, NemoIcon *icon); void nemo_centered_placement_grid_mark_position (NemoCenteredPlacementGrid *grid, gint x, gint y); void nemo_centered_placement_grid_unmark_position (NemoCenteredPlacementGrid *grid, gint x, gint y); void nemo_centered_placement_grid_pre_populate (NemoCenteredPlacementGrid *grid, GList *icons, gboolean ignore_lazy); void nemo_centered_placement_grid_get_next_position_rect (NemoCenteredPlacementGrid *grid, GdkRectangle *in_rect, GdkRectangle *out_rect, gboolean *is_free); void nemo_centered_placement_grid_get_current_position_rect (NemoCenteredPlacementGrid *grid, gint x, gint y, GdkRectangle *rect, gboolean *is_free); NemoIcon * nemo_centered_placement_grid_get_icon_at_position (NemoCenteredPlacementGrid *grid, gint x, gint y); GList * nemo_centered_placement_grid_clear_grid_for_selection (NemoCenteredPlacementGrid *grid, gint start_x, gint start_y, GList *drag_sel_list); /* nemo-placement-grid api * * used by nemo-icon-view-container.c */ NemoPlacementGrid *nemo_placement_grid_new (NemoIconContainer *container, gboolean tight); void nemo_placement_grid_free (NemoPlacementGrid *grid); gboolean nemo_placement_grid_position_is_free (NemoPlacementGrid *grid, EelIRect pos); void nemo_placement_grid_mark (NemoPlacementGrid *grid, EelIRect pos); void nemo_placement_grid_canvas_position_to_grid_position (NemoPlacementGrid *grid, EelIRect canvas_position, EelIRect *grid_position); void nemo_placement_grid_mark_icon (NemoPlacementGrid *grid, NemoIcon *icon); #endif /* NEMO_ICON_CONTAINER_PRIVATE_H */ nemo-3.6.5/libnemo-private/nemo-module.c0000664000175000017500000001304213215733314017073 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * nemo-module.h - Interface to nemo extensions * * Copyright (C) 2003 Novell, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * * Author: Dave Camp * */ #include #include "nemo-module.h" #include #include static GList *module_objects = NULL; G_DEFINE_TYPE (NemoModule, nemo_module, G_TYPE_TYPE_MODULE); static gboolean nemo_module_load (GTypeModule *gmodule) { NemoModule *module; module = NEMO_MODULE (gmodule); module->library = g_module_open (module->path, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); if (!module->library) { g_warning ("%s", g_module_error ()); return FALSE; } if (!g_module_symbol (module->library, "nemo_module_initialize", (gpointer *)&module->initialize) || !g_module_symbol (module->library, "nemo_module_shutdown", (gpointer *)&module->shutdown) || !g_module_symbol (module->library, "nemo_module_list_types", (gpointer *)&module->list_types)) { g_warning ("%s", g_module_error ()); g_module_close (module->library); return FALSE; } module->initialize (gmodule); return TRUE; } static void nemo_module_unload (GTypeModule *gmodule) { NemoModule *module; module = NEMO_MODULE (gmodule); module->shutdown (); g_module_close (module->library); module->initialize = NULL; module->shutdown = NULL; module->list_types = NULL; } static void nemo_module_finalize (GObject *object) { NemoModule *module; module = NEMO_MODULE (object); g_free (module->path); G_OBJECT_CLASS (nemo_module_parent_class)->finalize (object); } static void nemo_module_init (NemoModule *module) { } static void nemo_module_class_init (NemoModuleClass *class) { G_OBJECT_CLASS (class)->finalize = nemo_module_finalize; G_TYPE_MODULE_CLASS (class)->load = nemo_module_load; G_TYPE_MODULE_CLASS (class)->unload = nemo_module_unload; } static void module_object_weak_notify (gpointer user_data, GObject *object) { module_objects = g_list_remove (module_objects, object); } static gboolean module_is_selected (GType type) { gchar **disabled_list = g_settings_get_strv (nemo_plugin_preferences, NEMO_PLUGIN_PREFERENCES_DISABLED_EXTENSIONS); gboolean ret = TRUE; gint i = 0; for (i = 0; i < g_strv_length (disabled_list); i++) { if (g_strcmp0 (disabled_list[i], g_type_name (type)) == 0) ret = FALSE; } g_strfreev (disabled_list); return ret; } static void add_module_objects (NemoModule *module) { const GType *types; int num_types; int i; module->list_types (&types, &num_types); for (i = 0; i < num_types; i++) { if (types[i] == 0) { /* Work around broken extensions */ break; } if (module_is_selected (types[i])) { nemo_module_add_type (types[i]); } } } static void nemo_module_load_file (const char *filename) { NemoModule *module = NULL; module = g_object_new (NEMO_TYPE_MODULE, NULL); module->path = g_strdup (filename); if (g_type_module_use (G_TYPE_MODULE (module))) { add_module_objects (module); g_type_module_unuse (G_TYPE_MODULE (module)); } else { g_object_unref (module); } } static void load_module_dir (const char *dirname) { GDir *dir; dir = g_dir_open (dirname, 0, NULL); if (dir) { const char *name; while ((name = g_dir_read_name (dir))) { if (g_str_has_suffix (name, "." G_MODULE_SUFFIX)) { char *filename; filename = g_build_filename (dirname, name, NULL); nemo_module_load_file (filename); g_free (filename); } } g_dir_close (dir); } } static void free_module_objects (void) { GList *l, *next; for (l = module_objects; l != NULL; l = next) { next = l->next; g_object_unref (l->data); } g_list_free (module_objects); } void nemo_module_setup (void) { static gboolean initialized = FALSE; if (!initialized) { initialized = TRUE; load_module_dir (NEMO_EXTENSIONDIR); eel_debug_call_at_shutdown (free_module_objects); } } GList * nemo_module_get_extensions_for_type (GType type) { GList *l; GList *ret = NULL; for (l = module_objects; l != NULL; l = l->next) { if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (l->data), type)) { g_object_ref (l->data); ret = g_list_prepend (ret, l->data); } } return ret; } void nemo_module_extension_list_free (GList *extensions) { GList *l, *next; for (l = extensions; l != NULL; l = next) { next = l->next; g_object_unref (l->data); } g_list_free (extensions); } void nemo_module_add_type (GType type) { GObject *object; object = g_object_new (type, NULL); g_object_weak_ref (object, (GWeakNotify)module_object_weak_notify, NULL); module_objects = g_list_prepend (module_objects, object); } nemo-3.6.5/libnemo-private/nemo-query.c0000664000175000017500000001774113215733314016765 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Novell, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Anders Carlsson * */ #include #include #include "nemo-query.h" #include #include #include struct NemoQueryDetails { char *text; char *location_uri; GList *mime_types; }; static void nemo_query_class_init (NemoQueryClass *class); static void nemo_query_init (NemoQuery *query); G_DEFINE_TYPE (NemoQuery, nemo_query, G_TYPE_OBJECT); static void finalize (GObject *object) { NemoQuery *query; query = NEMO_QUERY (object); g_free (query->details->text); g_free (query->details->location_uri); G_OBJECT_CLASS (nemo_query_parent_class)->finalize (object); } static void nemo_query_class_init (NemoQueryClass *class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = finalize; g_type_class_add_private (class, sizeof (NemoQueryDetails)); } static void nemo_query_init (NemoQuery *query) { query->details = G_TYPE_INSTANCE_GET_PRIVATE (query, NEMO_TYPE_QUERY, NemoQueryDetails); } NemoQuery * nemo_query_new (void) { return g_object_new (NEMO_TYPE_QUERY, NULL); } char * nemo_query_get_text (NemoQuery *query) { return g_strdup (query->details->text); } void nemo_query_set_text (NemoQuery *query, const char *text) { g_free (query->details->text); query->details->text = g_strstrip (g_strdup (text)); } char * nemo_query_get_location (NemoQuery *query) { return g_strdup (query->details->location_uri); } void nemo_query_set_location (NemoQuery *query, const char *uri) { g_free (query->details->location_uri); query->details->location_uri = g_strdup (uri); } GList * nemo_query_get_mime_types (NemoQuery *query) { return eel_g_str_list_copy (query->details->mime_types); } void nemo_query_set_mime_types (NemoQuery *query, GList *mime_types) { g_list_free_full (query->details->mime_types, g_free); query->details->mime_types = eel_g_str_list_copy (mime_types); } void nemo_query_add_mime_type (NemoQuery *query, const char *mime_type) { query->details->mime_types = g_list_append (query->details->mime_types, g_strdup (mime_type)); } char * nemo_query_to_readable_string (NemoQuery *query) { if (!query || !query->details->text || query->details->text[0] == '\0') { return g_strdup (_("Search")); } return g_strdup_printf (_("Search for \"%s\""), query->details->text); } static char * encode_home_uri (const char *uri) { char *home_uri; const char *encoded_uri; home_uri = nemo_get_home_directory_uri (); if (g_str_has_prefix (uri, home_uri)) { encoded_uri = uri + strlen (home_uri); if (*encoded_uri == '/') { encoded_uri++; } } else { encoded_uri = uri; } g_free (home_uri); return g_markup_escape_text (encoded_uri, -1); } static char * decode_home_uri (const char *uri) { char *home_uri; char *decoded_uri; if (g_str_has_prefix (uri, "file:")) { decoded_uri = g_strdup (uri); } else { home_uri = nemo_get_home_directory_uri (); decoded_uri = g_strconcat (home_uri, "/", uri, NULL); g_free (home_uri); } return decoded_uri; } typedef struct { NemoQuery *query; gboolean in_text; gboolean in_location; gboolean in_mimetypes; gboolean in_mimetype; gboolean error; } ParserInfo; static void start_element_cb (GMarkupParseContext *ctx, const char *element_name, const char **attribute_names, const char **attribute_values, gpointer user_data, GError **err) { ParserInfo *info; info = (ParserInfo *) user_data; if (strcmp (element_name, "text") == 0) info->in_text = TRUE; else if (strcmp (element_name, "location") == 0) info->in_location = TRUE; else if (strcmp (element_name, "mimetypes") == 0) info->in_mimetypes = TRUE; else if (strcmp (element_name, "mimetype") == 0) info->in_mimetype = TRUE; } static void end_element_cb (GMarkupParseContext *ctx, const char *element_name, gpointer user_data, GError **err) { ParserInfo *info; info = (ParserInfo *) user_data; if (strcmp (element_name, "text") == 0) info->in_text = FALSE; else if (strcmp (element_name, "location") == 0) info->in_location = FALSE; else if (strcmp (element_name, "mimetypes") == 0) info->in_mimetypes = FALSE; else if (strcmp (element_name, "mimetype") == 0) info->in_mimetype = FALSE; } static void text_cb (GMarkupParseContext *ctx, const char *text, gsize text_len, gpointer user_data, GError **err) { ParserInfo *info; char *t, *uri; info = (ParserInfo *) user_data; t = g_strndup (text, text_len); if (info->in_text) { nemo_query_set_text (info->query, t); } else if (info->in_location) { uri = decode_home_uri (t); nemo_query_set_location (info->query, uri); g_free (uri); } else if (info->in_mimetypes && info->in_mimetype) { nemo_query_add_mime_type (info->query, t); } g_free (t); } static void error_cb (GMarkupParseContext *ctx, GError *err, gpointer user_data) { ParserInfo *info; info = (ParserInfo *) user_data; info->error = TRUE; } static GMarkupParser parser = { start_element_cb, end_element_cb, text_cb, NULL, error_cb }; static NemoQuery * nemo_query_parse_xml (char *xml, gsize xml_len) { ParserInfo info = { NULL }; GMarkupParseContext *ctx; if (xml_len == -1) { xml_len = strlen (xml); } info.query = nemo_query_new (); info.in_text = FALSE; info.error = FALSE; ctx = g_markup_parse_context_new (&parser, 0, &info, NULL); g_markup_parse_context_parse (ctx, xml, xml_len, NULL); g_markup_parse_context_free (ctx); if (info.error) { g_object_unref (info.query); return NULL; } return info.query; } NemoQuery * nemo_query_load (char *file) { NemoQuery *query; char *xml; gsize xml_len; if (!g_file_test (file, G_FILE_TEST_EXISTS)) { return NULL; } g_file_get_contents (file, &xml, &xml_len, NULL); if (xml_len == 0) { return NULL; } query = nemo_query_parse_xml (xml, xml_len); g_free (xml); return query; } static char * nemo_query_to_xml (NemoQuery *query) { GString *xml; char *text; char *uri; char *mimetype; GList *l; xml = g_string_new (""); g_string_append (xml, "\n" "\n"); text = g_markup_escape_text (query->details->text, -1); g_string_append_printf (xml, " %s\n", text); g_free (text); if (query->details->location_uri) { uri = encode_home_uri (query->details->location_uri); g_string_append_printf (xml, " %s\n", uri); g_free (uri); } if (query->details->mime_types) { g_string_append (xml, " \n"); for (l = query->details->mime_types; l != NULL; l = l->next) { mimetype = g_markup_escape_text (l->data, -1); g_string_append_printf (xml, " %s\n", mimetype); g_free (mimetype); } g_string_append (xml, " \n"); } g_string_append (xml, "\n"); return g_string_free (xml, FALSE); } gboolean nemo_query_save (NemoQuery *query, char *file) { char *xml; GError *err = NULL; gboolean res; res = TRUE; xml = nemo_query_to_xml (query); g_file_set_contents (file, xml, strlen (xml), &err); g_free (xml); if (err != NULL) { res = FALSE; g_error_free (err); } return res; } nemo-3.6.5/libnemo-private/nemo-lib-self-check-functions.h0000664000175000017500000000360113215733314022371 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-lib-self-check-functions.h: Wrapper and prototypes for all self-check functions in libnemo. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include void nemo_run_lib_self_checks (void); /* Putting the prototypes for these self-check functions in each header file for the files they are defined in would make compiling the self-check framework take way too long (since one file would have to include everything). So we put the list of functions here instead. Instead of just putting prototypes here, we put this macro that can be used to do operations on the whole list of functions. */ #define NEMO_LIB_FOR_EACH_SELF_CHECK_FUNCTION(macro) \ macro (nemo_self_check_file_utilities) \ macro (nemo_self_check_file_operations) \ macro (nemo_self_check_directory) \ macro (nemo_self_check_file) \ macro (nemo_self_check_icon_container) \ /* Add new self-check functions to the list above this line. */ /* Generate prototypes for all the functions. */ NEMO_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_SELF_CHECK_FUNCTION_PROTOTYPE) nemo-3.6.5/libnemo-private/nemo-widget-menu-item.h0000664000175000017500000000530313215733314020775 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #ifndef __NEMO_WIDGET_MENU_ITEM_H__ #define __NEMO_WIDGET_MENU_ITEM_H__ #include G_BEGIN_DECLS #define NEMO_TYPE_WIDGET_MENU_ITEM (nemo_widget_menu_item_get_type ()) #define NEMO_WIDGET_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_WIDGET_MENU_ITEM, NemoWidgetMenuItem)) #define NEMO_WIDGET_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_WIDGET_MENU_ITEM, NemoWidgetMenuItemClass)) #define NEMO_IS_WIDGET_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_WIDGET_MENU_ITEM)) #define NEMO_IS_WIDGET_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_WIDGET_MENU_ITEM)) #define NEMO_WIDGET_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_WIDGET_MENU_ITEM, NemoWidgetMenuItemClass)) typedef struct _NemoWidgetMenuItem NemoWidgetMenuItem; typedef struct _NemoWidgetMenuItemClass NemoWidgetMenuItemClass; struct _NemoWidgetMenuItem { GtkMenuItem menu_item; GtkWidget *child_widget; gint action_slot; /* GtkActivatable */ GtkAction *related_action; gboolean use_action_appearance; }; /** * NemoWidgetMenuItemClass: * @parent_class: The parent class. */ struct _NemoWidgetMenuItemClass { GtkMenuItemClass parent_class; }; GType nemo_widget_menu_item_get_type (void) G_GNUC_CONST; GtkWidget* nemo_widget_menu_item_new (GtkWidget *widget); void nemo_widget_menu_item_set_child_widget (NemoWidgetMenuItem *widget_menu_item, GtkWidget *widget); GtkWidget* nemo_widget_menu_item_get_child_widget (NemoWidgetMenuItem *widget_menu_item); G_END_DECLS #endif /* __NEMO_WIDGET_MENU_ITEM_H__ */ nemo-3.6.5/libnemo-private/nemo-clipboard-monitor.h0000664000175000017500000000610613215733314021242 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-clipboard-monitor.h: lets you notice clipboard changes. Copyright (C) 2004 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_CLIPBOARD_MONITOR_H #define NEMO_CLIPBOARD_MONITOR_H #include #define NEMO_TYPE_CLIPBOARD_MONITOR nemo_clipboard_monitor_get_type() #define NEMO_CLIPBOARD_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_CLIPBOARD_MONITOR, NemoClipboardMonitor)) #define NEMO_CLIPBOARD_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_CLIPBOARD_MONITOR, NemoClipboardMonitorClass)) #define NEMO_IS_CLIPBOARD_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_CLIPBOARD_MONITOR)) #define NEMO_IS_CLIPBOARD_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_CLIPBOARD_MONITOR)) #define NEMO_CLIPBOARD_MONITOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_CLIPBOARD_MONITOR, NemoClipboardMonitorClass)) typedef struct NemoClipboardMonitorDetails NemoClipboardMonitorDetails; typedef struct NemoClipboardInfo NemoClipboardInfo; typedef struct { GObject parent_slot; NemoClipboardMonitorDetails *details; } NemoClipboardMonitor; typedef struct { GObjectClass parent_slot; void (* clipboard_changed) (NemoClipboardMonitor *monitor); void (* clipboard_info) (NemoClipboardMonitor *monitor, NemoClipboardInfo *info); } NemoClipboardMonitorClass; struct NemoClipboardInfo { GList *files; gboolean cut; }; GType nemo_clipboard_monitor_get_type (void); NemoClipboardMonitor * nemo_clipboard_monitor_get (void); void nemo_clipboard_monitor_set_clipboard_info (NemoClipboardMonitor *monitor, NemoClipboardInfo *info); NemoClipboardInfo * nemo_clipboard_monitor_get_clipboard_info (NemoClipboardMonitor *monitor); void nemo_clipboard_monitor_emit_changed (void); void nemo_clear_clipboard_callback (GtkClipboard *clipboard, gpointer user_data); void nemo_get_clipboard_callback (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data); #endif /* NEMO_CLIPBOARD_MONITOR_H */ nemo-3.6.5/libnemo-private/nemo-undo-transaction.c0000664000175000017500000001764113215733314021107 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoUndoTransaction - An object for an undoable transaction. * Used internally by undo machinery. * Not public. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include #include #include #include "nemo-undo-private.h" #include #define NEMO_UNDO_TRANSACTION_LIST_DATA "Nemo undo transaction list" /* undo atoms */ static void undo_atom_list_free (GList *list); static void undo_atom_list_undo_and_free (GList *list); G_DEFINE_TYPE (NemoUndoTransaction, nemo_undo_transaction, G_TYPE_OBJECT); NemoUndoTransaction * nemo_undo_transaction_new (const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint) { NemoUndoTransaction *transaction; transaction = NEMO_UNDO_TRANSACTION (g_object_new (nemo_undo_transaction_get_type (), NULL)); transaction->operation_name = g_strdup (operation_name); transaction->undo_menu_item_label = g_strdup (undo_menu_item_label); transaction->undo_menu_item_hint = g_strdup (undo_menu_item_hint); transaction->redo_menu_item_label = g_strdup (redo_menu_item_label); transaction->redo_menu_item_hint = g_strdup (redo_menu_item_hint); return transaction; } static void nemo_undo_transaction_init (NemoUndoTransaction *transaction) { } static void remove_transaction_from_object (gpointer list_data, gpointer callback_data) { NemoUndoAtom *atom; NemoUndoTransaction *transaction; GList *list; g_assert (list_data != NULL); atom = list_data; transaction = NEMO_UNDO_TRANSACTION (callback_data); /* Remove the transaction from the list on the atom. */ list = g_object_get_data (atom->target, NEMO_UNDO_TRANSACTION_LIST_DATA); if (list != NULL) { list = g_list_remove (list, transaction); g_object_set_data (atom->target, NEMO_UNDO_TRANSACTION_LIST_DATA, list); } } static void remove_transaction_from_atom_targets (NemoUndoTransaction *transaction) { g_list_foreach (transaction->atom_list, remove_transaction_from_object, transaction); } static void nemo_undo_transaction_finalize (GObject *object) { NemoUndoTransaction *transaction; transaction = NEMO_UNDO_TRANSACTION (object); remove_transaction_from_atom_targets (transaction); undo_atom_list_free (transaction->atom_list); g_free (transaction->operation_name); g_free (transaction->undo_menu_item_label); g_free (transaction->undo_menu_item_hint); g_free (transaction->redo_menu_item_label); g_free (transaction->redo_menu_item_hint); if (transaction->owner != NULL) { g_object_unref (transaction->owner); } G_OBJECT_CLASS (nemo_undo_transaction_parent_class)->finalize (object); } void nemo_undo_transaction_add_atom (NemoUndoTransaction *transaction, const NemoUndoAtom *atom) { GList *list; g_return_if_fail (NEMO_IS_UNDO_TRANSACTION (transaction)); g_return_if_fail (atom != NULL); g_return_if_fail (G_IS_OBJECT (atom->target)); /* Add the atom to the atom list in the transaction. */ transaction->atom_list = g_list_append (transaction->atom_list, g_memdup (atom, sizeof (*atom))); /* Add the transaction to the list on the atoms target object. */ list = g_object_get_data (atom->target, NEMO_UNDO_TRANSACTION_LIST_DATA); if (g_list_find (list, transaction) != NULL) { return; } /* If it's not already on that atom, this object is new. */ list = g_list_prepend (list, transaction); g_object_set_data (atom->target, NEMO_UNDO_TRANSACTION_LIST_DATA, list); /* Connect a signal handler to the atom so it will unregister * itself when it's destroyed. */ g_signal_connect (atom->target, "destroy", G_CALLBACK (nemo_undo_transaction_unregister_object), NULL); } void nemo_undo_transaction_undo (NemoUndoTransaction *transaction) { g_return_if_fail (NEMO_IS_UNDO_TRANSACTION (transaction)); remove_transaction_from_atom_targets (transaction); undo_atom_list_undo_and_free (transaction->atom_list); transaction->atom_list = NULL; } void nemo_undo_transaction_add_to_undo_manager (NemoUndoTransaction *transaction, NemoUndoManager *manager) { g_return_if_fail (NEMO_IS_UNDO_TRANSACTION (transaction)); g_return_if_fail (transaction->owner == NULL); if (manager != NULL) { nemo_undo_manager_append (manager, transaction); transaction->owner = g_object_ref (manager); } } static void remove_atoms (NemoUndoTransaction *transaction, GObject *object) { GList *p, *next; NemoUndoAtom *atom; g_assert (NEMO_IS_UNDO_TRANSACTION (transaction)); g_assert (G_IS_OBJECT (object)); /* Destroy any atoms for this object. */ for (p = transaction->atom_list; p != NULL; p = next) { atom = p->data; next = p->next; if (atom->target == object) { transaction->atom_list = g_list_remove_link (transaction->atom_list, p); undo_atom_list_free (p); } } /* If all the atoms are gone, forget this transaction. * This may end up freeing the transaction. */ if (transaction->atom_list == NULL) { nemo_undo_manager_forget ( transaction->owner, transaction); } } static void remove_atoms_cover (gpointer list_data, gpointer callback_data) { if (NEMO_IS_UNDO_TRANSACTION (list_data)) { remove_atoms (NEMO_UNDO_TRANSACTION (list_data), G_OBJECT (callback_data)); } } void nemo_undo_transaction_unregister_object (GObject *object) { GList *list; g_return_if_fail (G_IS_OBJECT (object)); /* Remove atoms from each transaction on the list. */ list = g_object_get_data (object, NEMO_UNDO_TRANSACTION_LIST_DATA); if (list != NULL) { g_list_foreach (list, remove_atoms_cover, object); g_list_free (list); g_object_set_data (object, NEMO_UNDO_TRANSACTION_LIST_DATA, NULL); } } static void undo_atom_free (NemoUndoAtom *atom) { /* Call the destroy-notify function if it's present. */ if (atom->callback_data_destroy_notify != NULL) { (* atom->callback_data_destroy_notify) (atom->callback_data); } /* Free the atom storage. */ g_free (atom); } static void undo_atom_undo_and_free (NemoUndoAtom *atom) { /* Call the function that does the actual undo. */ (* atom->callback) (atom->target, atom->callback_data); /* Get rid of the atom now that it's spent. */ undo_atom_free (atom); } static void undo_atom_free_cover (gpointer atom, gpointer callback_data) { g_assert (atom != NULL); g_assert (callback_data == NULL); undo_atom_free (atom); } static void undo_atom_undo_and_free_cover (gpointer atom, gpointer callback_data) { g_assert (atom != NULL); g_assert (callback_data == NULL); undo_atom_undo_and_free (atom); } static void undo_atom_list_free (GList *list) { g_list_foreach (list, undo_atom_free_cover, NULL); g_list_free (list); } static void undo_atom_list_undo_and_free (GList *list) { g_list_foreach (list, undo_atom_undo_and_free_cover, NULL); g_list_free (list); } static void nemo_undo_transaction_class_init (NemoUndoTransactionClass *klass) { G_OBJECT_CLASS (klass)->finalize = nemo_undo_transaction_finalize; } nemo-3.6.5/libnemo-private/nemo-vfs-file.c0000664000175000017500000004310613215733314017325 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-vfs-file.c: Subclass of NemoFile to help implement the virtual trash directory. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-vfs-file.h" #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-file-private.h" #include G_DEFINE_TYPE (NemoVFSFile, nemo_vfs_file, NEMO_TYPE_FILE); static void vfs_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes) { nemo_directory_monitor_add_internal (file->details->directory, file, client, TRUE, attributes, NULL, NULL); } static void vfs_file_monitor_remove (NemoFile *file, gconstpointer client) { nemo_directory_monitor_remove_internal (file->details->directory, file, client); } static void vfs_file_call_when_ready (NemoFile *file, NemoFileAttributes file_attributes, NemoFileCallback callback, gpointer callback_data) { nemo_directory_call_when_ready_internal (file->details->directory, file, file_attributes, FALSE, NULL, callback, callback_data); } static void vfs_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data) { nemo_directory_cancel_callback_internal (file->details->directory, file, NULL, callback, callback_data); } static gboolean vfs_file_check_if_ready (NemoFile *file, NemoFileAttributes file_attributes) { return nemo_directory_check_if_ready_internal (file->details->directory, file, file_attributes); } static void set_metadata_get_info_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFile *file; GFileInfo *new_info; GError *error; file = callback_data; error = NULL; new_info = g_file_query_info_finish (G_FILE (source_object), res, &error); if (new_info != NULL) { if (nemo_file_update_info (file, new_info)) { nemo_file_changed (file); } g_object_unref (new_info); } nemo_file_unref (file); if (error) { g_error_free (error); } } static void set_metadata_callback (GObject *source_object, GAsyncResult *result, gpointer callback_data) { NemoFile *file; GError *error; gboolean res; file = callback_data; error = NULL; res = g_file_set_attributes_finish (G_FILE (source_object), result, NULL, &error); if (res) { g_file_query_info_async (G_FILE (source_object), NEMO_FILE_DEFAULT_ATTRIBUTES, 0, G_PRIORITY_DEFAULT, NULL, set_metadata_get_info_callback, file); } else { nemo_file_unref (file); g_error_free (error); } } static void vfs_file_set_metadata (NemoFile *file, const char *key, const char *value) { GFileInfo *info; GFile *location; char *gio_key; info = g_file_info_new (); gio_key = g_strconcat ("metadata::", key, NULL); if (value != NULL) { g_file_info_set_attribute_string (info, gio_key, value); } else { /* Unset the key */ g_file_info_set_attribute (info, gio_key, G_FILE_ATTRIBUTE_TYPE_INVALID, NULL); } g_free (gio_key); location = nemo_file_get_location (file); g_file_set_attributes_async (location, info, 0, G_PRIORITY_DEFAULT, NULL, set_metadata_callback, nemo_file_ref (file)); g_object_unref (location); g_object_unref (info); } static void vfs_file_set_metadata_as_list (NemoFile *file, const char *key, char **value) { GFile *location; GFileInfo *info; char *gio_key; info = g_file_info_new (); gio_key = g_strconcat ("metadata::", key, NULL); g_file_info_set_attribute_stringv (info, gio_key, value); g_free (gio_key); location = nemo_file_get_location (file); g_file_set_attributes_async (location, info, 0, G_PRIORITY_DEFAULT, NULL, set_metadata_callback, nemo_file_ref (file)); g_object_unref (info); g_object_unref (location); } static gboolean vfs_file_get_item_count (NemoFile *file, guint *count, gboolean *count_unreadable) { if (count_unreadable != NULL) { *count_unreadable = file->details->directory_count_failed; } if (!file->details->got_directory_count) { if (count != NULL) { *count = 0; } return FALSE; } if (count != NULL) { *count = file->details->directory_count; } return TRUE; } static NemoRequestStatus vfs_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size) { GFileType type; if (directory_count != NULL) { *directory_count = 0; } if (file_count != NULL) { *file_count = 0; } if (unreadable_directory_count != NULL) { *unreadable_directory_count = 0; } if (total_size != NULL) { *total_size = 0; } if (hidden_count != NULL) { *hidden_count = 0; } if (!nemo_file_is_directory (file)) { return NEMO_REQUEST_DONE; } if (file->details->deep_counts_status != NEMO_REQUEST_NOT_STARTED) { if (directory_count != NULL) { *directory_count = file->details->deep_directory_count; } if (file_count != NULL) { *file_count = file->details->deep_file_count; } if (unreadable_directory_count != NULL) { *unreadable_directory_count = file->details->deep_unreadable_count; } if (total_size != NULL) { *total_size = file->details->deep_size; } if (hidden_count != NULL) { *hidden_count = file->details->deep_hidden_count; } return file->details->deep_counts_status; } /* For directories, or before we know the type, we haven't started. */ type = nemo_file_get_file_type (file); if (type == G_FILE_TYPE_UNKNOWN || type == G_FILE_TYPE_DIRECTORY) { return NEMO_REQUEST_NOT_STARTED; } /* For other types, we are done, and the zeros are permanent. */ return NEMO_REQUEST_DONE; } static gboolean vfs_file_get_date (NemoFile *file, NemoDateType date_type, time_t *date) { switch (date_type) { case NEMO_DATE_TYPE_CHANGED: /* Before we have info on a file, the date is unknown. */ if (file->details->ctime == 0) { return FALSE; } if (date != NULL) { *date = file->details->ctime; } return TRUE; case NEMO_DATE_TYPE_ACCESSED: /* Before we have info on a file, the date is unknown. */ if (file->details->atime == 0) { return FALSE; } if (date != NULL) { *date = file->details->atime; } return TRUE; case NEMO_DATE_TYPE_MODIFIED: /* Before we have info on a file, the date is unknown. */ if (file->details->mtime == 0) { return FALSE; } if (date != NULL) { *date = file->details->mtime; } return TRUE; case NEMO_DATE_TYPE_TRASHED: /* Before we have info on a file, the date is unknown. */ if (file->details->trash_time == 0) { return FALSE; } if (date != NULL) { *date = file->details->trash_time; } return TRUE; case NEMO_DATE_TYPE_PERMISSIONS_CHANGED: /* Before we have info on a file, the date is unknown. */ if (file->details->mtime == 0 || file->details->ctime == 0) { return FALSE; } /* mtime is when the contents changed; ctime is when the * contents or the permissions (inc. owner/group) changed. * So we can only know when the permissions changed if mtime * and ctime are different. */ if (file->details->mtime == file->details->ctime) { return FALSE; } if (date != NULL) { *date = file->details->ctime; } return TRUE; } return FALSE; } static char * vfs_file_get_where_string (NemoFile *file) { GFile *activation_location; NemoFile *location; char *where_string; if (!nemo_file_is_in_recent (file)) { location = nemo_file_ref (file); } else { activation_location = nemo_file_get_activation_location (file); location = nemo_file_get (activation_location); g_object_unref (activation_location); } where_string = nemo_file_get_parent_uri_for_display (location); nemo_file_unref (location); return where_string; } static void vfs_file_mount_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; GFile *mounted_on; GError *error; op = callback_data; error = NULL; mounted_on = g_file_mount_mountable_finish (G_FILE (source_object), res, &error); nemo_file_operation_complete (op, mounted_on, error); if (mounted_on) { g_object_unref (mounted_on); } if (error) { g_error_free (error); } } static void vfs_file_mount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GError *error; GFile *location; if (file->details->type != G_FILE_TYPE_MOUNTABLE) { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be mounted")); callback (file, NULL, error, callback_data); g_error_free (error); } return; } op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } location = nemo_file_get_location (file); g_file_mount_mountable (location, 0, mount_op, op->cancellable, vfs_file_mount_callback, op); g_object_unref (location); } static void vfs_file_unmount_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean unmounted; GError *error; op = callback_data; error = NULL; unmounted = g_file_unmount_mountable_with_operation_finish (G_FILE (source_object), res, &error); if (!unmounted && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, G_FILE (source_object), error); if (error) { g_error_free (error); } } static void vfs_file_unmount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GFile *location; op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } location = nemo_file_get_location (file); g_file_unmount_mountable_with_operation (location, G_MOUNT_UNMOUNT_NONE, mount_op, op->cancellable, vfs_file_unmount_callback, op); g_object_unref (location); } static void vfs_file_eject_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean ejected; GError *error; op = callback_data; error = NULL; ejected = g_file_eject_mountable_with_operation_finish (G_FILE (source_object), res, &error); if (!ejected && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, G_FILE (source_object), error); if (error) { g_error_free (error); } } static void vfs_file_eject (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GFile *location; op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } location = nemo_file_get_location (file); g_file_eject_mountable_with_operation (location, G_MOUNT_UNMOUNT_NONE, mount_op, op->cancellable, vfs_file_eject_callback, op); g_object_unref (location); } static void vfs_file_start_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean started; GError *error; op = callback_data; error = NULL; started = g_file_start_mountable_finish (G_FILE (source_object), res, &error); if (!started && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, G_FILE (source_object), error); if (error) { g_error_free (error); } } static void vfs_file_start (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GError *error; GFile *location; if (file->details->type != G_FILE_TYPE_MOUNTABLE) { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be started")); callback (file, NULL, error, callback_data); g_error_free (error); } return; } op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } location = nemo_file_get_location (file); g_file_start_mountable (location, 0, mount_op, op->cancellable, vfs_file_start_callback, op); g_object_unref (location); } static void vfs_file_stop_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean stopped; GError *error; op = callback_data; error = NULL; stopped = g_file_stop_mountable_finish (G_FILE (source_object), res, &error); if (!stopped && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, G_FILE (source_object), error); if (error) { g_error_free (error); } } static void vfs_file_stop (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GFile *location; op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } location = nemo_file_get_location (file); g_file_stop_mountable (location, G_MOUNT_UNMOUNT_NONE, mount_op, op->cancellable, vfs_file_stop_callback, op); g_object_unref (location); } static void vfs_file_poll_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean stopped; GError *error; op = callback_data; error = NULL; stopped = g_file_poll_mountable_finish (G_FILE (source_object), res, &error); if (!stopped && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, G_FILE (source_object), error); if (error) { g_error_free (error); } } static void vfs_file_poll_for_media (NemoFile *file) { NemoFileOperation *op; GFile *location; op = nemo_file_operation_new (file, NULL, NULL); location = nemo_file_get_location (file); g_file_poll_mountable (location, op->cancellable, vfs_file_poll_callback, op); g_object_unref (location); } static void nemo_vfs_file_init (NemoVFSFile *file) { } static void nemo_vfs_file_class_init (NemoVFSFileClass *klass) { NemoFileClass *file_class = NEMO_FILE_CLASS (klass); file_class->monitor_add = vfs_file_monitor_add; file_class->monitor_remove = vfs_file_monitor_remove; file_class->call_when_ready = vfs_file_call_when_ready; file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready; file_class->check_if_ready = vfs_file_check_if_ready; file_class->get_item_count = vfs_file_get_item_count; file_class->get_deep_counts = vfs_file_get_deep_counts; file_class->get_date = vfs_file_get_date; file_class->get_where_string = vfs_file_get_where_string; file_class->set_metadata = vfs_file_set_metadata; file_class->set_metadata_as_list = vfs_file_set_metadata_as_list; file_class->mount = vfs_file_mount; file_class->unmount = vfs_file_unmount; file_class->eject = vfs_file_eject; file_class->start = vfs_file_start; file_class->stop = vfs_file_stop; file_class->poll_for_media = vfs_file_poll_for_media; } nemo-3.6.5/libnemo-private/nemo-job-queue.c0000664000175000017500000001517413215733314017512 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-job-queue.c - file operation queue This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include #include "nemo-job-queue.h" #include "nemo-global-preferences.h" struct _NemoJobQueuePriv { GList *queued_jobs; GList *running_jobs; gulong pref_changed_id; gboolean skip_queue; }; enum { NEW_JOB, LAST_SIGNAL }; typedef struct { GIOSchedulerJobFunc job_func; gpointer user_data; NemoProgressInfo *info; GCancellable *cancellable; } Job; static NemoJobQueue *singleton = NULL; static guint signals[LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE (NemoJobQueue, nemo_job_queue, G_TYPE_OBJECT); static void nemo_job_queue_finalize (GObject *obj) { NemoJobQueue *self = NEMO_JOB_QUEUE (obj); if (self->priv->queued_jobs != NULL) { g_list_free_full (self->priv->queued_jobs, g_object_unref); } if (self->priv->pref_changed_id != 0) { g_signal_handler_disconnect (nemo_preferences, self->priv->pref_changed_id); self->priv->pref_changed_id = 0; } G_OBJECT_CLASS (nemo_job_queue_parent_class)->finalize (obj); } static GObject * nemo_job_queue_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *retval; if (singleton != NULL) { return g_object_ref (singleton); } retval = G_OBJECT_CLASS (nemo_job_queue_parent_class)->constructor (type, n_props, props); singleton = NEMO_JOB_QUEUE (retval); g_object_add_weak_pointer (retval, (gpointer) &singleton); return retval; } static void pref_changed_cb (NemoJobQueue *self) { self->priv->skip_queue = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_NEVER_QUEUE_FILE_OPS); } static void nemo_job_queue_init (NemoJobQueue *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_JOB_QUEUE, NemoJobQueuePriv); self->priv->queued_jobs = NULL; self->priv->running_jobs = NULL; self->priv->pref_changed_id = g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_NEVER_QUEUE_FILE_OPS, G_CALLBACK (pref_changed_cb), self); pref_changed_cb (self); } static void nemo_job_queue_class_init (NemoJobQueueClass *klass) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (klass); oclass->constructor = nemo_job_queue_constructor; oclass->finalize = nemo_job_queue_finalize; signals[NEW_JOB] = g_signal_new ("new-job", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 0, NULL); g_type_class_add_private (klass, sizeof (NemoJobQueuePriv)); } static gint compare_info_func (gconstpointer a, gconstpointer b) { Job *job = (Job*) a; return (job->info == b) ? 0 : 1; } static gint compare_job_data_func (gconstpointer a, gconstpointer b) { Job *job = (Job*) a; return (job->job_func == b) ? 0 : 1; } static void job_finished_cb (NemoJobQueue *self, NemoProgressInfo *info) { GList *ptr; ptr = g_list_find_custom (self->priv->running_jobs, info, (GCompareFunc) compare_info_func); if (!ptr) ptr = g_list_find_custom (self->priv->queued_jobs, info, (GCompareFunc) compare_info_func); Job *job = ptr->data; self->priv->running_jobs = g_list_remove (self->priv->running_jobs, job); self->priv->queued_jobs = g_list_remove (self->priv->queued_jobs, job); g_slice_free (Job, job); nemo_job_queue_start_next_job (self); } static void start_job (NemoJobQueue *self, Job *job); NemoJobQueue * nemo_job_queue_get (void) { return g_object_new (NEMO_TYPE_JOB_QUEUE, NULL); } void nemo_job_queue_add_new_job (NemoJobQueue *self, GIOSchedulerJobFunc job_func, gpointer user_data, GCancellable *cancellable, NemoProgressInfo *info, gboolean start_immediately) { if (g_list_find_custom (self->priv->queued_jobs, user_data, (GCompareFunc) compare_job_data_func) != NULL) { g_warning ("Adding the same file job object to the job queue"); return; } Job *new_job = g_slice_new0 (Job); new_job->job_func = job_func; new_job->user_data = user_data; new_job->cancellable = cancellable; new_job->info = info; self->priv->queued_jobs = g_list_append (self->priv->queued_jobs, new_job); nemo_progress_info_queue (info); g_signal_connect_swapped (info, "finished", G_CALLBACK (job_finished_cb), self); if (self->priv->skip_queue || start_immediately) start_job (self, new_job); else nemo_job_queue_start_next_job (self); g_signal_emit (self, signals[NEW_JOB], 0, NULL); } static void start_job (NemoJobQueue *self, Job *job) { self->priv->queued_jobs = g_list_remove (self->priv->queued_jobs, job); g_io_scheduler_push_job (job->job_func, job->user_data, NULL, // destroy notify 0, job->cancellable); self->priv->running_jobs = g_list_append (self->priv->running_jobs, job); } void nemo_job_queue_start_next_job (NemoJobQueue *self) { if (g_list_length (self->priv->running_jobs) == 0 && g_list_length (self->priv->queued_jobs) > 0) start_job (self, self->priv->queued_jobs->data); } void nemo_job_queue_start_job_by_info (NemoJobQueue *self, NemoProgressInfo *info) { GList *target = g_list_find_custom (self->priv->queued_jobs, info, (GCompareFunc) compare_info_func); if (target) start_job (self, target->data); } GList * nemo_job_queue_get_all_jobs (NemoJobQueue *self) { return self->priv->queued_jobs; } nemo-3.6.5/libnemo-private/nemo-directory.c0000664000175000017500000013500513215733314017616 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-directory.c: Nemo directory model. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-directory-private.h" #include "nemo-directory-notify.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include "nemo-search-directory.h" #include "nemo-global-preferences.h" #include "nemo-lib-self-check-functions.h" #include "nemo-metadata.h" #include "nemo-desktop-directory.h" #include "nemo-vfs-directory.h" #include #include #include enum { FILES_ADDED, FILES_CHANGED, DONE_LOADING, LOAD_ERROR, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static GHashTable *directories; static void nemo_directory_finalize (GObject *object); static NemoDirectory *nemo_directory_new (GFile *location); static GList * real_get_file_list (NemoDirectory *directory); static gboolean real_is_editable (NemoDirectory *directory); static void set_directory_location (NemoDirectory *directory, GFile *location); G_DEFINE_TYPE (NemoDirectory, nemo_directory, G_TYPE_OBJECT); static void nemo_directory_class_init (NemoDirectoryClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = nemo_directory_finalize; signals[FILES_ADDED] = g_signal_new ("files_added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoDirectoryClass, files_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[FILES_CHANGED] = g_signal_new ("files_changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoDirectoryClass, files_changed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[DONE_LOADING] = g_signal_new ("done_loading", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoDirectoryClass, done_loading), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[LOAD_ERROR] = g_signal_new ("load_error", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoDirectoryClass, load_error), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); klass->get_file_list = real_get_file_list; klass->is_editable = real_is_editable; g_type_class_add_private (klass, sizeof (NemoDirectoryDetails)); } static void nemo_directory_init (NemoDirectory *directory) { directory->details = G_TYPE_INSTANCE_GET_PRIVATE ((directory), NEMO_TYPE_DIRECTORY, NemoDirectoryDetails); directory->details->file_hash = g_hash_table_new (g_str_hash, g_str_equal); directory->details->high_priority_queue = nemo_file_queue_new (); directory->details->low_priority_queue = nemo_file_queue_new (); directory->details->extension_queue = nemo_file_queue_new (); } NemoDirectory * nemo_directory_ref (NemoDirectory *directory) { if (directory == NULL) { return directory; } g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); g_object_ref (directory); return directory; } void nemo_directory_unref (NemoDirectory *directory) { if (directory == NULL) { return; } g_return_if_fail (NEMO_IS_DIRECTORY (directory)); g_object_unref (directory); } static void nemo_directory_finalize (GObject *object) { NemoDirectory *directory; directory = NEMO_DIRECTORY (object); g_hash_table_remove (directories, directory->details->location); nemo_directory_cancel (directory); g_assert (directory->details->count_in_progress == NULL); if (directory->details->monitor_list != NULL) { g_warning ("destroying a NemoDirectory while it's being monitored"); g_list_free_full (directory->details->monitor_list, g_free); } if (directory->details->monitor != NULL) { nemo_monitor_cancel (directory->details->monitor); } if (directory->details->dequeue_pending_idle_id != 0) { g_source_remove (directory->details->dequeue_pending_idle_id); } if (directory->details->call_ready_idle_id != 0) { g_source_remove (directory->details->call_ready_idle_id); } if (directory->details->location) { g_object_unref (directory->details->location); } g_assert (directory->details->file_list == NULL); g_hash_table_destroy (directory->details->file_hash); if (directory->details->hidden_file_hash) { g_hash_table_destroy (directory->details->hidden_file_hash); } nemo_file_queue_destroy (directory->details->high_priority_queue); nemo_file_queue_destroy (directory->details->low_priority_queue); nemo_file_queue_destroy (directory->details->extension_queue); g_assert (directory->details->directory_load_in_progress == NULL); g_assert (directory->details->count_in_progress == NULL); g_assert (directory->details->dequeue_pending_idle_id == 0); g_list_free_full (directory->details->pending_file_info, g_object_unref); G_OBJECT_CLASS (nemo_directory_parent_class)->finalize (object); } static void invalidate_one_count (gpointer key, gpointer value, gpointer user_data) { NemoDirectory *directory; g_assert (key != NULL); g_assert (NEMO_IS_DIRECTORY (value)); g_assert (user_data == NULL); directory = NEMO_DIRECTORY (value); nemo_directory_invalidate_count_and_mime_list (directory); } static void filtering_changed_callback (gpointer callback_data) { g_assert (callback_data == NULL); /* Preference about which items to show has changed, so we * can't trust any of our precomputed directory counts. */ g_hash_table_foreach (directories, invalidate_one_count, NULL); } void emit_change_signals_for_all_files (NemoDirectory *directory) { GList *files; files = g_list_copy (directory->details->file_list); if (directory->details->as_file != NULL) { files = g_list_prepend (files, directory->details->as_file); } nemo_file_list_ref (files); nemo_directory_emit_change_signals (directory, files); nemo_file_list_free (files); } static void collect_all_directories (gpointer key, gpointer value, gpointer callback_data) { NemoDirectory *directory; GList **dirs; directory = NEMO_DIRECTORY (value); dirs = callback_data; *dirs = g_list_prepend (*dirs, nemo_directory_ref (directory)); } void emit_change_signals_for_all_files_in_all_directories (void) { GList *dirs, *l; NemoDirectory *directory; dirs = NULL; g_hash_table_foreach (directories, collect_all_directories, &dirs); for (l = dirs; l != NULL; l = l->next) { directory = NEMO_DIRECTORY (l->data); emit_change_signals_for_all_files (directory); nemo_directory_unref (directory); } g_list_free (dirs); } static void async_state_changed_one (gpointer key, gpointer value, gpointer user_data) { NemoDirectory *directory; g_assert (key != NULL); g_assert (NEMO_IS_DIRECTORY (value)); g_assert (user_data == NULL); directory = NEMO_DIRECTORY (value); nemo_directory_async_state_changed (directory); emit_change_signals_for_all_files (directory); } static void async_data_preference_changed_callback (gpointer callback_data) { g_assert (callback_data == NULL); /* Preference involving fetched async data has changed, so * we have to kick off refetching all async data, and tell * each file that it (might have) changed. */ g_hash_table_foreach (directories, async_state_changed_one, NULL); } static void add_preferences_callbacks (void) { nemo_global_preferences_init (); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_SHOW_HIDDEN_FILES, G_CALLBACK(filtering_changed_callback), NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS, G_CALLBACK (async_data_preference_changed_callback), NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_DATE_FORMAT, G_CALLBACK(async_data_preference_changed_callback), NULL); } /** * nemo_directory_get_by_uri: * @uri: URI of directory to get. * * Get a directory given a uri. * Creates the appropriate subclass given the uri mappings. * Returns a referenced object, not a floating one. Unref when finished. * If two windows are viewing the same uri, the directory object is shared. */ NemoDirectory * nemo_directory_get_internal (GFile *location, gboolean create) { NemoDirectory *directory; /* Create the hash table first time through. */ if (directories == NULL) { directories = g_hash_table_new (g_file_hash, (GCompareFunc) g_file_equal); add_preferences_callbacks (); } /* If the object is already in the hash table, look it up. */ directory = g_hash_table_lookup (directories, location); if (directory != NULL) { nemo_directory_ref (directory); } else if (create) { /* Create a new directory object instead. */ directory = nemo_directory_new (location); if (directory == NULL) { return NULL; } /* Put it in the hash table. */ g_hash_table_insert (directories, directory->details->location, directory); } return directory; } NemoDirectory * nemo_directory_get (GFile *location) { if (location == NULL) { return NULL; } return nemo_directory_get_internal (location, TRUE); } NemoDirectory * nemo_directory_get_existing (GFile *location) { if (location == NULL) { return NULL; } return nemo_directory_get_internal (location, FALSE); } NemoDirectory * nemo_directory_get_by_uri (const char *uri) { NemoDirectory *directory; GFile *location; if (uri == NULL) { return NULL; } location = g_file_new_for_uri (uri); directory = nemo_directory_get_internal (location, TRUE); g_object_unref (location); return directory; } NemoDirectory * nemo_directory_get_for_file (NemoFile *file) { char *uri; NemoDirectory *directory; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); uri = nemo_file_get_uri (file); directory = nemo_directory_get_by_uri (uri); g_free (uri); return directory; } /* Returns a reffed NemoFile object for this directory. */ NemoFile * nemo_directory_get_corresponding_file (NemoDirectory *directory) { NemoFile *file; char *uri; file = nemo_directory_get_existing_corresponding_file (directory); if (file == NULL) { uri = nemo_directory_get_uri (directory); file = nemo_file_get_by_uri (uri); g_free (uri); } return file; } /* Returns a reffed NemoFile object for this directory, but only if the * NemoFile object has already been created. */ NemoFile * nemo_directory_get_existing_corresponding_file (NemoDirectory *directory) { NemoFile *file; char *uri; file = directory->details->as_file; if (file != NULL) { nemo_file_ref (file); return file; } uri = nemo_directory_get_uri (directory); file = nemo_file_get_existing_by_uri (uri); g_free (uri); return file; } /* nemo_directory_get_name_for_self_as_new_file: * * Get a name to display for the file representing this * directory. This is called only when there's no VFS * directory for this NemoDirectory. */ char * nemo_directory_get_name_for_self_as_new_file (NemoDirectory *directory) { char *directory_uri; char *name, *colon; directory_uri = nemo_directory_get_uri (directory); colon = strchr (directory_uri, ':'); if (colon == NULL || colon == directory_uri) { name = g_strdup (directory_uri); } else { name = g_strndup (directory_uri, colon - directory_uri); } g_free (directory_uri); return name; } char * nemo_directory_get_uri (NemoDirectory *directory) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); return g_file_get_uri (directory->details->location); } GFile * nemo_directory_get_location (NemoDirectory *directory) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); return g_object_ref (directory->details->location); } static NemoDirectory * nemo_directory_new (GFile *location) { NemoDirectory *directory; char *uri; uri = g_file_get_uri (location); if (eel_uri_is_desktop (uri)) { directory = NEMO_DIRECTORY (g_object_new (NEMO_TYPE_DESKTOP_DIRECTORY, NULL)); } else if (eel_uri_is_search (uri)) { directory = NEMO_DIRECTORY (g_object_new (NEMO_TYPE_SEARCH_DIRECTORY, NULL)); } else if (g_str_has_suffix (uri, NEMO_SAVED_SEARCH_EXTENSION)) { directory = NEMO_DIRECTORY (nemo_search_directory_new_from_saved_search (uri)); } else { directory = NEMO_DIRECTORY (g_object_new (NEMO_TYPE_VFS_DIRECTORY, NULL)); } set_directory_location (directory, location); g_free (uri); return directory; } gboolean nemo_directory_is_local (NemoDirectory *directory) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), FALSE); if (directory->details->location == NULL) { return TRUE; } return nemo_directory_is_in_trash (directory) || g_file_is_native (directory->details->location); } gboolean nemo_directory_is_in_trash (NemoDirectory *directory) { g_assert (NEMO_IS_DIRECTORY (directory)); if (directory->details->location == NULL) { return FALSE; } return g_file_has_uri_scheme (directory->details->location, "trash"); } gboolean nemo_directory_is_in_recent (NemoDirectory *directory) { g_assert (NEMO_IS_DIRECTORY (directory)); if (directory->details->location == NULL) { return FALSE; } return g_file_has_uri_scheme (directory->details->location, "recent"); } gboolean nemo_directory_are_all_files_seen (NemoDirectory *directory) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), FALSE); return NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->are_all_files_seen (directory); } static void add_to_hash_table (NemoDirectory *directory, NemoFile *file, GList *node) { const char *name; name = eel_ref_str_peek (file->details->name); g_assert (node != NULL); g_assert (g_hash_table_lookup (directory->details->file_hash, name) == NULL); g_hash_table_insert (directory->details->file_hash, (char *) name, node); } static GList * extract_from_hash_table (NemoDirectory *directory, NemoFile *file) { const char *name; GList *node; name = eel_ref_str_peek (file->details->name); if (name == NULL) { return NULL; } /* Find the list node in the hash table. */ node = g_hash_table_lookup (directory->details->file_hash, name); g_hash_table_remove (directory->details->file_hash, name); return node; } void nemo_directory_add_file (NemoDirectory *directory, NemoFile *file) { GList *node; gboolean add_to_work_queue; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (NEMO_IS_FILE (file)); g_assert (file->details->name != NULL); /* Add to list. */ node = g_list_prepend (directory->details->file_list, file); directory->details->file_list = node; /* Add to hash table. */ add_to_hash_table (directory, file, node); directory->details->confirmed_file_count++; add_to_work_queue = FALSE; if (nemo_directory_is_file_list_monitored (directory)) { /* Ref if we are monitoring, since monitoring owns the file list. */ nemo_file_ref (file); add_to_work_queue = TRUE; } else if (nemo_directory_has_active_request_for_file (directory, file)) { /* We're waiting for the file in a call_when_ready. Make sure we add the file to the work queue so that said waiter won't wait forever for e.g. all files in the directory to be done */ add_to_work_queue = TRUE; } if (add_to_work_queue) { nemo_directory_add_file_to_work_queue (directory, file); } } void nemo_directory_remove_file (NemoDirectory *directory, NemoFile *file) { GList *node; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (NEMO_IS_FILE (file)); g_assert (file->details->name != NULL); /* Find the list node in the hash table. */ node = extract_from_hash_table (directory, file); g_assert (node != NULL); g_assert (node->data == file); /* Remove the item from the list. */ directory->details->file_list = g_list_remove_link (directory->details->file_list, node); g_list_free_1 (node); nemo_directory_remove_file_from_work_queue (directory, file); if (!file->details->unconfirmed) { directory->details->confirmed_file_count--; } /* Unref if we are monitoring. */ if (nemo_directory_is_file_list_monitored (directory)) { nemo_file_unref (file); } } GList * nemo_directory_begin_file_name_change (NemoDirectory *directory, NemoFile *file) { /* Find the list node in the hash table. */ return extract_from_hash_table (directory, file); } void nemo_directory_end_file_name_change (NemoDirectory *directory, NemoFile *file, GList *node) { /* Add the list node to the hash table. */ if (node != NULL) { add_to_hash_table (directory, file, node); } } NemoFile * nemo_directory_find_file_by_name (NemoDirectory *directory, const char *name) { GList *node; g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); g_return_val_if_fail (name != NULL, NULL); node = g_hash_table_lookup (directory->details->file_hash, name); return node == NULL ? NULL : NEMO_FILE (node->data); } /* "." for the directory-as-file, otherwise the filename */ NemoFile * nemo_directory_find_file_by_internal_filename (NemoDirectory *directory, const char *internal_filename) { NemoFile *result; if (g_strcmp0 (internal_filename, ".") == 0) { result = nemo_directory_get_existing_corresponding_file (directory); if (result != NULL) { nemo_file_unref (result); } } else { result = nemo_directory_find_file_by_name (directory, internal_filename); } return result; } void nemo_directory_emit_files_added (NemoDirectory *directory, GList *added_files) { if (added_files != NULL) { g_signal_emit (directory, signals[FILES_ADDED], 0, added_files); } } void nemo_directory_emit_files_changed (NemoDirectory *directory, GList *changed_files) { if (changed_files != NULL) { g_signal_emit (directory, signals[FILES_CHANGED], 0, changed_files); } } void nemo_directory_emit_change_signals (NemoDirectory *directory, GList *changed_files) { GList *p; for (p = changed_files; p != NULL; p = p->next) { nemo_file_emit_changed (p->data); } nemo_directory_emit_files_changed (directory, changed_files); } void nemo_directory_emit_done_loading (NemoDirectory *directory) { g_signal_emit (directory, signals[DONE_LOADING], 0); } void nemo_directory_emit_load_error (NemoDirectory *directory, GError *error) { g_signal_emit (directory, signals[LOAD_ERROR], 0, error); } /* Return a directory object for this one's parent. */ static NemoDirectory * get_parent_directory (GFile *location) { NemoDirectory *directory; GFile *parent; parent = g_file_get_parent (location); if (parent) { directory = nemo_directory_get_internal (parent, TRUE); g_object_unref (parent); return directory; } return NULL; } /* If a directory object exists for this one's parent, then * return it, otherwise return NULL. */ static NemoDirectory * get_parent_directory_if_exists (GFile *location) { NemoDirectory *directory; GFile *parent; parent = g_file_get_parent (location); if (parent) { directory = nemo_directory_get_internal (parent, FALSE); g_object_unref (parent); return directory; } return NULL; } static void hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) { GList *list; list = g_hash_table_lookup (table, key); list = g_list_prepend (list, data); g_hash_table_insert (table, (gpointer) key, list); } static void call_files_added_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (NEMO_IS_DIRECTORY (key)); g_assert (value != NULL); g_assert (user_data == NULL); g_signal_emit (key, signals[FILES_ADDED], 0, value); g_list_free (value); } static void call_files_changed_common (NemoDirectory *directory, GList *file_list) { GList *node; NemoFile *file; for (node = file_list; node != NULL; node = node->next) { file = node->data; if (file->details->directory == directory) { nemo_directory_add_file_to_work_queue (directory, file); } } nemo_directory_async_state_changed (directory); nemo_directory_emit_change_signals (directory, file_list); } static void call_files_changed_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (value != NULL); g_assert (user_data == NULL); call_files_changed_common (NEMO_DIRECTORY (key), value); g_list_free (value); } static void call_files_changed_unref_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (value != NULL); g_assert (user_data == NULL); call_files_changed_common (NEMO_DIRECTORY (key), value); nemo_file_list_free (value); } static void call_get_file_info_free_list (gpointer key, gpointer value, gpointer user_data) { NemoDirectory *directory; GList *files; g_assert (NEMO_IS_DIRECTORY (key)); g_assert (value != NULL); g_assert (user_data == NULL); directory = key; files = value; nemo_directory_get_info_for_new_files (directory, files); g_list_foreach (files, (GFunc) g_object_unref, NULL); g_list_free (files); } static void invalidate_count_and_unref (gpointer key, gpointer value, gpointer user_data) { g_assert (NEMO_IS_DIRECTORY (key)); g_assert (value == key); g_assert (user_data == NULL); nemo_directory_invalidate_count_and_mime_list (key); nemo_directory_unref (key); } static void collect_parent_directories (GHashTable *hash_table, NemoDirectory *directory) { g_assert (hash_table != NULL); g_assert (NEMO_IS_DIRECTORY (directory)); if (g_hash_table_lookup (hash_table, directory) == NULL) { nemo_directory_ref (directory); g_hash_table_insert (hash_table, directory, directory); } } void nemo_directory_notify_files_added (GList *files) { GHashTable *added_lists; GList *p; NemoDirectory *directory; GHashTable *parent_directories; NemoFile *file; GFile *location, *parent; /* Make a list of added files in each directory. */ added_lists = g_hash_table_new (NULL, NULL); /* Make a list of parent directories that will need their counts updated. */ parent_directories = g_hash_table_new (NULL, NULL); for (p = files; p != NULL; p = p->next) { location = p->data; /* See if the directory is already known. */ directory = get_parent_directory_if_exists (location); if (directory == NULL) { /* In case the directory is not being * monitored, but the corresponding file is, * we must invalidate it's item count. */ file = NULL; parent = g_file_get_parent (location); if (parent) { file = nemo_file_get_existing (parent); g_object_unref (parent); } if (file != NULL) { nemo_file_invalidate_count_and_mime_list (file); nemo_file_unref (file); } continue; } collect_parent_directories (parent_directories, directory); /* If no one is monitoring files in the directory, nothing to do. */ if (!nemo_directory_is_file_list_monitored (directory)) { nemo_directory_unref (directory); continue; } file = nemo_file_get_existing (location); /* We check is_added here, because the file could have been added * to the directory by a nemo_file_get() but not gotten * files_added emitted */ if (file && file->details->is_added) { /* A file already exists, it was probably renamed. * If it was renamed this could be ignored, but * queue a change just in case */ nemo_file_changed (file); nemo_file_unref (file); } else { hash_table_list_prepend (added_lists, directory, g_object_ref (location)); } nemo_directory_unref (directory); } /* Now get file info for the new files. This creates NemoFile * objects for the new files, and sends out a files_added signal. */ g_hash_table_foreach (added_lists, call_get_file_info_free_list, NULL); g_hash_table_destroy (added_lists); /* Invalidate count for each parent directory. */ g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); g_hash_table_destroy (parent_directories); } static void g_file_pair_free (GFilePair *pair) { g_object_unref (pair->to); g_object_unref (pair->from); g_free (pair); } static GList * uri_pairs_to_file_pairs (GList *uri_pairs) { GList *l, *file_pair_list; GFilePair *file_pair; URIPair *uri_pair; file_pair_list = NULL; for (l = uri_pairs; l != NULL; l = l->next) { uri_pair = l->data; file_pair = g_new (GFilePair, 1); file_pair->from = g_file_new_for_uri (uri_pair->from_uri); file_pair->to = g_file_new_for_uri (uri_pair->to_uri); file_pair_list = g_list_prepend (file_pair_list, file_pair); } return g_list_reverse (file_pair_list); } void nemo_directory_notify_files_added_by_uri (GList *uris) { GList *files; files = nemo_file_list_from_uris (uris); nemo_directory_notify_files_added (files); g_list_free_full (files, g_object_unref); } void nemo_directory_notify_files_changed (GList *files) { GHashTable *changed_lists; GList *node; GFile *location; NemoFile *file; /* Make a list of changed files in each directory. */ changed_lists = g_hash_table_new (NULL, NULL); /* Go through all the notifications. */ for (node = files; node != NULL; node = node->next) { location = node->data; /* Find the file. */ file = nemo_file_get_existing (location); if (file != NULL) { /* Tell it to re-get info now, and later emit * a changed signal. */ file->details->file_info_is_up_to_date = FALSE; file->details->link_info_is_up_to_date = FALSE; nemo_file_invalidate_extension_info_internal (file); hash_table_list_prepend (changed_lists, file->details->directory, file); } } /* Now send out the changed signals. */ g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL); g_hash_table_destroy (changed_lists); } void nemo_directory_notify_files_changed_by_uri (GList *uris) { GList *files; files = nemo_file_list_from_uris (uris); nemo_directory_notify_files_changed (files); g_list_free_full (files, g_object_unref); } void nemo_directory_notify_files_removed (GList *files) { GHashTable *changed_lists; GList *p; NemoDirectory *directory; GHashTable *parent_directories; NemoFile *file; GFile *location; /* Make a list of changed files in each directory. */ changed_lists = g_hash_table_new (NULL, NULL); /* Make a list of parent directories that will need their counts updated. */ parent_directories = g_hash_table_new (NULL, NULL); /* Go through all the notifications. */ for (p = files; p != NULL; p = p->next) { location = p->data; /* Update file count for parent directory if anyone might care. */ directory = get_parent_directory_if_exists (location); if (directory != NULL) { collect_parent_directories (parent_directories, directory); nemo_directory_unref (directory); } /* Find the file. */ file = nemo_file_get_existing (location); if (file != NULL && !nemo_file_rename_in_progress (file)) { /* Mark it gone and prepare to send the changed signal. */ nemo_file_mark_gone (file); hash_table_list_prepend (changed_lists, file->details->directory, nemo_file_ref (file)); } nemo_file_unref (file); } /* Now send out the changed signals. */ g_hash_table_foreach (changed_lists, call_files_changed_unref_free_list, NULL); g_hash_table_destroy (changed_lists); /* Invalidate count for each parent directory. */ g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); g_hash_table_destroy (parent_directories); } void nemo_directory_notify_files_removed_by_uri (GList *uris) { GList *files; files = nemo_file_list_from_uris (uris); nemo_directory_notify_files_changed (files); g_list_free_full (files, g_object_unref); } static void set_directory_location (NemoDirectory *directory, GFile *location) { if (directory->details->location) { g_object_unref (directory->details->location); } directory->details->location = g_object_ref (location); } static void change_directory_location (NemoDirectory *directory, GFile *new_location) { /* I believe it's impossible for a self-owned file/directory * to be moved. But if that did somehow happen, this function * wouldn't do enough to handle it. */ g_assert (directory->details->as_file == NULL); g_hash_table_remove (directories, directory->details->location); set_directory_location (directory, new_location); g_hash_table_insert (directories, directory->details->location, directory); } typedef struct { GFile *container; GList *directories; } CollectData; static void collect_directories_by_container (gpointer key, gpointer value, gpointer callback_data) { NemoDirectory *directory; CollectData *collect_data; GFile *location; location = (GFile *) key; directory = NEMO_DIRECTORY (value); collect_data = (CollectData *) callback_data; if (g_file_has_prefix (location, collect_data->container) || g_file_equal (collect_data->container, location)) { nemo_directory_ref (directory); collect_data->directories = g_list_prepend (collect_data->directories, directory); } } static GList * nemo_directory_moved_internal (GFile *old_location, GFile *new_location) { CollectData collection; NemoDirectory *directory; GList *node, *affected_files; GFile *new_directory_location; char *relative_path; collection.container = old_location; collection.directories = NULL; g_hash_table_foreach (directories, collect_directories_by_container, &collection); affected_files = NULL; for (node = collection.directories; node != NULL; node = node->next) { directory = NEMO_DIRECTORY (node->data); new_directory_location = NULL; if (g_file_equal (directory->details->location, old_location)) { new_directory_location = g_object_ref (new_location); } else { relative_path = g_file_get_relative_path (old_location, directory->details->location); if (relative_path != NULL) { new_directory_location = g_file_resolve_relative_path (new_location, relative_path); g_free (relative_path); } } if (new_directory_location) { change_directory_location (directory, new_directory_location); g_object_unref (new_directory_location); /* Collect affected files. */ if (directory->details->as_file != NULL) { affected_files = g_list_prepend (affected_files, nemo_file_ref (directory->details->as_file)); } affected_files = g_list_concat (affected_files, nemo_file_list_copy (directory->details->file_list)); } nemo_directory_unref (directory); } g_list_free (collection.directories); return affected_files; } void nemo_directory_moved (const char *old_uri, const char *new_uri) { GList *list, *node; GHashTable *hash; NemoFile *file; GFile *old_location; GFile *new_location; hash = g_hash_table_new (NULL, NULL); old_location = g_file_new_for_uri (old_uri); new_location = g_file_new_for_uri (new_uri); list = nemo_directory_moved_internal (old_location, new_location); for (node = list; node != NULL; node = node->next) { file = NEMO_FILE (node->data); hash_table_list_prepend (hash, file->details->directory, nemo_file_ref (file)); } nemo_file_list_free (list); g_object_unref (old_location); g_object_unref (new_location); g_hash_table_foreach (hash, call_files_changed_unref_free_list, NULL); g_hash_table_destroy (hash); } void nemo_directory_notify_files_moved (GList *file_pairs) { GList *p, *affected_files, *node; GFilePair *pair; NemoFile *file; NemoDirectory *old_directory, *new_directory; GHashTable *parent_directories; GList *new_files_list, *unref_list; GHashTable *added_lists, *changed_lists; char *name; NemoFileAttributes cancel_attributes; GFile *to_location, *from_location; /* Make a list of added and changed files in each directory. */ new_files_list = NULL; added_lists = g_hash_table_new (NULL, NULL); changed_lists = g_hash_table_new (NULL, NULL); unref_list = NULL; /* Make a list of parent directories that will need their counts updated. */ parent_directories = g_hash_table_new (NULL, NULL); cancel_attributes = nemo_file_get_all_attributes (); for (p = file_pairs; p != NULL; p = p->next) { pair = p->data; from_location = pair->from; to_location = pair->to; /* Handle overwriting a file. */ file = nemo_file_get_existing (to_location); if (file != NULL) { /* Mark it gone and prepare to send the changed signal. */ nemo_file_mark_gone (file); new_directory = file->details->directory; hash_table_list_prepend (changed_lists, new_directory, file); collect_parent_directories (parent_directories, new_directory); } /* Update any directory objects that are affected. */ affected_files = nemo_directory_moved_internal (from_location, to_location); for (node = affected_files; node != NULL; node = node->next) { file = NEMO_FILE (node->data); hash_table_list_prepend (changed_lists, file->details->directory, file); } unref_list = g_list_concat (unref_list, affected_files); /* Move an existing file. */ file = nemo_file_get_existing (from_location); if (file == NULL) { /* Handle this as if it was a new file. */ new_files_list = g_list_prepend (new_files_list, to_location); } else { /* Handle notification in the old directory. */ old_directory = file->details->directory; collect_parent_directories (parent_directories, old_directory); /* Cancel loading of attributes in the old directory */ nemo_directory_cancel_loading_file_attributes (old_directory, file, cancel_attributes); /* Locate the new directory. */ new_directory = get_parent_directory (to_location); collect_parent_directories (parent_directories, new_directory); /* We can unref now -- new_directory is in the * parent directories list so it will be * around until the end of this function * anyway. */ nemo_directory_unref (new_directory); /* Update the file's name and directory. */ name = g_file_get_basename (to_location); nemo_file_update_name_and_directory (file, name, new_directory); g_free (name); /* Update file attributes */ nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_INFO); hash_table_list_prepend (changed_lists, old_directory, file); if (old_directory != new_directory) { hash_table_list_prepend (added_lists, new_directory, file); } /* Unref each file once to balance out nemo_file_get_by_uri. */ unref_list = g_list_prepend (unref_list, file); } } /* Now send out the changed and added signals for existing file objects. */ g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); g_hash_table_foreach (added_lists, call_files_added_free_list, NULL); g_hash_table_destroy (added_lists); /* Let the file objects go. */ nemo_file_list_free (unref_list); /* Invalidate count for each parent directory. */ g_hash_table_foreach (parent_directories, invalidate_count_and_unref, NULL); g_hash_table_destroy (parent_directories); /* Separate handling for brand new file objects. */ nemo_directory_notify_files_added (new_files_list); g_list_free (new_files_list); } void nemo_directory_notify_files_moved_by_uri (GList *uri_pairs) { GList *file_pairs; file_pairs = uri_pairs_to_file_pairs (uri_pairs); nemo_directory_notify_files_moved (file_pairs); g_list_foreach (file_pairs, (GFunc)g_file_pair_free, NULL); g_list_free (file_pairs); } void nemo_directory_schedule_position_set (GList *position_setting_list) { GList *p; const NemoFileChangesQueuePosition *item; NemoFile *file; time_t now; time (&now); for (p = position_setting_list; p != NULL; p = p->next) { item = (NemoFileChangesQueuePosition *) p->data; file = nemo_file_get (item->location); if (item->set) { nemo_file_set_position (file, item->point.x, item->point.y); } else { nemo_file_set_position (file, -1, -1); } if (item->set) { nemo_file_set_monitor_number (file, item->monitor); } else { nemo_file_set_monitor_number (file, -1); } nemo_file_set_time_metadata (file, NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP, UNDEFINED_TIME); nemo_file_unref (file); } } gboolean nemo_directory_contains_file (NemoDirectory *directory, NemoFile *file) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), FALSE); g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); if (nemo_file_is_gone (file)) { return FALSE; } return NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->contains_file (directory, file); } char * nemo_directory_get_file_uri (NemoDirectory *directory, const char *file_name) { GFile *child; char *result; g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); g_return_val_if_fail (file_name != NULL, NULL); result = NULL; child = g_file_get_child (directory->details->location, file_name); result = g_file_get_uri (child); g_object_unref (child); return result; } void nemo_directory_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_all_files, NemoDirectoryCallback callback, gpointer callback_data) { g_return_if_fail (NEMO_IS_DIRECTORY (directory)); g_return_if_fail (callback != NULL); NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->call_when_ready (directory, file_attributes, wait_for_all_files, callback, callback_data); } void nemo_directory_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data) { g_return_if_fail (NEMO_IS_DIRECTORY (directory)); g_return_if_fail (callback != NULL); NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->cancel_callback (directory, callback, callback_data); } void nemo_directory_file_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { g_return_if_fail (NEMO_IS_DIRECTORY (directory)); g_return_if_fail (client != NULL); NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->file_monitor_add (directory, client, monitor_hidden_files, file_attributes, callback, callback_data); } void nemo_directory_file_monitor_remove (NemoDirectory *directory, gconstpointer client) { g_return_if_fail (NEMO_IS_DIRECTORY (directory)); g_return_if_fail (client != NULL); NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->file_monitor_remove (directory, client); } void nemo_directory_force_reload (NemoDirectory *directory) { g_return_if_fail (NEMO_IS_DIRECTORY (directory)); NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->force_reload (directory); } gboolean nemo_directory_is_not_empty (NemoDirectory *directory) { g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), FALSE); return NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->is_not_empty (directory); } static gboolean is_tentative (gpointer data, gpointer callback_data) { NemoFile *file; g_assert (callback_data == NULL); file = NEMO_FILE (data); /* Avoid returning files with !is_added, because these * will later be sent with the files_added signal, and a * user doing get_file_list + files_added monitoring will * then see the file twice */ return !file->details->got_file_info || !file->details->is_added; } GList * nemo_directory_get_file_list (NemoDirectory *directory) { return NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->get_file_list (directory); } static GList * real_get_file_list (NemoDirectory *directory) { GList *tentative_files, *non_tentative_files; tentative_files = eel_g_list_partition (g_list_copy (directory->details->file_list), is_tentative, NULL, &non_tentative_files); g_list_free (tentative_files); nemo_file_list_ref (non_tentative_files); return non_tentative_files; } static gboolean real_is_editable (NemoDirectory *directory) { return TRUE; } gboolean nemo_directory_is_editable (NemoDirectory *directory) { return NEMO_DIRECTORY_CLASS (G_OBJECT_GET_CLASS (directory))->is_editable (directory); } GList * nemo_directory_match_pattern (NemoDirectory *directory, const char *pattern) { GList *files, *l, *ret; GPatternSpec *spec; ret = NULL; spec = g_pattern_spec_new (pattern); files = nemo_directory_get_file_list (directory); for (l = files; l; l = l->next) { NemoFile *file; char *name; file = NEMO_FILE (l->data); name = nemo_file_get_display_name (file); if (g_pattern_match_string (spec, name)) { ret = g_list_prepend(ret, nemo_file_ref (file)); } g_free (name); } g_pattern_spec_free (spec); nemo_file_list_free (files); return ret; } /** * nemo_directory_list_ref * * Ref all the directories in a list. * @list: GList of directories. **/ GList * nemo_directory_list_ref (GList *list) { g_list_foreach (list, (GFunc) nemo_directory_ref, NULL); return list; } /** * nemo_directory_list_unref * * Unref all the directories in a list. * @list: GList of directories. **/ void nemo_directory_list_unref (GList *list) { g_list_foreach (list, (GFunc) nemo_directory_unref, NULL); } /** * nemo_directory_list_free * * Free a list of directories after unrefing them. * @list: GList of directories. **/ void nemo_directory_list_free (GList *list) { nemo_directory_list_unref (list); g_list_free (list); } /** * nemo_directory_list_copy * * Copy the list of directories, making a new ref of each, * @list: GList of directories. **/ GList * nemo_directory_list_copy (GList *list) { return g_list_copy (nemo_directory_list_ref (list)); } static int compare_by_uri (NemoDirectory *a, NemoDirectory *b) { char *uri_a, *uri_b; int res; uri_a = g_file_get_uri (a->details->location); uri_b = g_file_get_uri (b->details->location); res = strcmp (uri_a, uri_b); g_free (uri_a); g_free (uri_b); return res; } static int compare_by_uri_cover (gconstpointer a, gconstpointer b) { return compare_by_uri (NEMO_DIRECTORY (a), NEMO_DIRECTORY (b)); } /** * nemo_directory_list_sort_by_uri * * Sort the list of directories by directory uri. * @list: GList of directories. **/ GList * nemo_directory_list_sort_by_uri (GList *list) { return g_list_sort (list, compare_by_uri_cover); } gboolean nemo_directory_is_desktop_directory (NemoDirectory *directory) { if (directory->details->location == NULL) { return FALSE; } return nemo_is_desktop_directory (directory->details->location); } #if !defined (NEMO_OMIT_SELF_CHECK) #include #include "nemo-file-attributes.h" static int data_dummy; static gboolean got_files_flag; static void got_files_callback (NemoDirectory *directory, GList *files, gpointer callback_data) { g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (g_list_length (files) > 10); g_assert (callback_data == &data_dummy); got_files_flag = TRUE; } /* Return the number of extant NemoDirectories */ int nemo_directory_number_outstanding (void) { return directories ? g_hash_table_size (directories) : 0; } void nemo_self_check_directory (void) { NemoDirectory *directory; NemoFile *file; directory = nemo_directory_get_by_uri ("file:///etc"); file = nemo_file_get_by_uri ("file:///etc/passwd"); EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1); nemo_directory_file_monitor_add (directory, &data_dummy, TRUE, 0, NULL, NULL); /* FIXME: these need to be updated to the new metadata infrastructure * as make check doesn't pass. nemo_file_set_metadata (file, "test", "default", "value"); EEL_CHECK_STRING_RESULT (nemo_file_get_metadata (file, "test", "default"), "value"); nemo_file_set_boolean_metadata (file, "test_boolean", TRUE, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_get_boolean_metadata (file, "test_boolean", TRUE), TRUE); nemo_file_set_boolean_metadata (file, "test_boolean", TRUE, FALSE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_get_boolean_metadata (file, "test_boolean", TRUE), FALSE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_get_boolean_metadata (NULL, "test_boolean", TRUE), TRUE); nemo_file_set_integer_metadata (file, "test_integer", 0, 17); EEL_CHECK_INTEGER_RESULT (nemo_file_get_integer_metadata (file, "test_integer", 0), 17); nemo_file_set_integer_metadata (file, "test_integer", 0, -1); EEL_CHECK_INTEGER_RESULT (nemo_file_get_integer_metadata (file, "test_integer", 0), -1); nemo_file_set_integer_metadata (file, "test_integer", 42, 42); EEL_CHECK_INTEGER_RESULT (nemo_file_get_integer_metadata (file, "test_integer", 42), 42); EEL_CHECK_INTEGER_RESULT (nemo_file_get_integer_metadata (NULL, "test_integer", 42), 42); EEL_CHECK_INTEGER_RESULT (nemo_file_get_integer_metadata (file, "nonexistent_key", 42), 42); */ EEL_CHECK_BOOLEAN_RESULT (nemo_directory_get_by_uri ("file:///etc") == directory, TRUE); nemo_directory_unref (directory); EEL_CHECK_BOOLEAN_RESULT (nemo_directory_get_by_uri ("file:///etc/") == directory, TRUE); nemo_directory_unref (directory); EEL_CHECK_BOOLEAN_RESULT (nemo_directory_get_by_uri ("file:///etc////") == directory, TRUE); nemo_directory_unref (directory); nemo_file_unref (file); nemo_directory_file_monitor_remove (directory, &data_dummy); nemo_directory_unref (directory); while (g_hash_table_size (directories) != 0) { gtk_main_iteration (); } EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0); directory = nemo_directory_get_by_uri ("file:///etc"); got_files_flag = FALSE; nemo_directory_call_when_ready (directory, NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_DEEP_COUNTS, TRUE, got_files_callback, &data_dummy); while (!got_files_flag) { gtk_main_iteration (); } EEL_CHECK_BOOLEAN_RESULT (directory->details->file_list == NULL, TRUE); EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 1); file = nemo_file_get_by_uri ("file:///etc/passwd"); /* EEL_CHECK_STRING_RESULT (nemo_file_get_metadata (file, "test", "default"), "value"); */ nemo_file_unref (file); nemo_directory_unref (directory); EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories), 0); } #endif /* !NEMO_OMIT_SELF_CHECK */ nemo-3.6.5/libnemo-private/nemo-global-preferences.c0000664000175000017500000001446013215733314021352 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-global-preferences.c - Nemo specific preference keys and functions. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ramiro Estrugo */ #include #include "nemo-global-preferences.h" #include "nemo-file-utilities.h" #include "nemo-file.h" #include #include #include #include #include #include static gboolean ignore_view_metadata = FALSE; /* * Public functions */ char * nemo_global_preferences_get_default_folder_viewer_preference_as_iid (void) { int preference_value; const char *viewer_iid; preference_value = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_DEFAULT_FOLDER_VIEWER); if (preference_value == NEMO_DEFAULT_FOLDER_VIEWER_LIST_VIEW) { viewer_iid = NEMO_LIST_VIEW_IID; } else if (preference_value == NEMO_DEFAULT_FOLDER_VIEWER_COMPACT_VIEW) { viewer_iid = NEMO_COMPACT_VIEW_IID; } else { viewer_iid = NEMO_ICON_VIEW_IID; } return g_strdup (viewer_iid); } char * nemo_global_preferences_get_desktop_iid (void) { gboolean use_grid; const char *viewer_iid; use_grid = g_settings_get_boolean (nemo_desktop_preferences, NEMO_PREFERENCES_USE_DESKTOP_GRID); if (use_grid) { viewer_iid = NEMO_DESKTOP_ICON_GRID_VIEW_IID; } else { viewer_iid = NEMO_DESKTOP_ICON_VIEW_IID; } return g_strdup (viewer_iid); } gboolean nemo_global_preferences_get_ignore_view_metadata (void) { return ignore_view_metadata; } gint nemo_global_preferences_get_tooltip_flags (void) { NemoFileTooltipFlags flags = NEMO_FILE_TOOLTIP_FLAGS_NONE; if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIP_FILE_TYPE)) flags |= NEMO_FILE_TOOLTIP_FLAGS_FILE_TYPE; if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIP_MOD_DATE)) flags |= NEMO_FILE_TOOLTIP_FLAGS_MOD_DATE; if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIP_ACCESS_DATE)) flags |= NEMO_FILE_TOOLTIP_FLAGS_ACCESS_DATE; if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIP_FULL_PATH)) flags |= NEMO_FILE_TOOLTIP_FLAGS_PATH; return flags; } gboolean nemo_global_preferences_should_load_plugin (const gchar *name, const gchar *key) { gchar **disabled_list = g_settings_get_strv (nemo_plugin_preferences, key); gboolean ret = TRUE; gint i = 0; for (i = 0; i < g_strv_length (disabled_list); i++) { if (g_strcmp0 (disabled_list[i], name) == 0) ret = FALSE; } g_strfreev (disabled_list); return ret; } static void ignore_view_metadata_cb (GSettings *settings, gchar *key, gpointer user_data) { ignore_view_metadata = g_settings_get_boolean (settings, key); } static void cache_fileroller_mimetypes (void) { if (nemo_is_file_roller_installed ()) { GAppInfo *app_info; gchar ***results; gchar **result; gint i; results = g_desktop_app_info_search ("file-roller"); if (results != NULL && results[0] != NULL) { const gchar *best; best = results[0][0]; app_info = G_APP_INFO (g_desktop_app_info_new (best)); if (app_info == NULL) { g_warning ("Unable to retrieve list of file-roller mimetypes"); file_roller_mimetypes = NULL; return; } file_roller_mimetypes = g_strdupv ((gchar **) g_app_info_get_supported_types (app_info)); g_object_unref (app_info); } i = 0; result = results[i]; while (result != NULL) { g_strfreev (result); result = results[++i]; } g_free (results); } else { file_roller_mimetypes = NULL; } } void nemo_global_preferences_init (void) { static gboolean initialized = FALSE; if (initialized) { return; } initialized = TRUE; nemo_preferences = g_settings_new("org.nemo.preferences"); nemo_window_state = g_settings_new("org.nemo.window-state"); nemo_icon_view_preferences = g_settings_new("org.nemo.icon-view"); nemo_list_view_preferences = g_settings_new("org.nemo.list-view"); nemo_compact_view_preferences = g_settings_new("org.nemo.compact-view"); nemo_desktop_preferences = g_settings_new("org.nemo.desktop"); nemo_tree_sidebar_preferences = g_settings_new("org.nemo.sidebar-panels.tree"); nemo_plugin_preferences = g_settings_new("org.nemo.plugins"); gnome_lockdown_preferences = g_settings_new("org.cinnamon.desktop.lockdown"); gnome_background_preferences = g_settings_new("org.cinnamon.desktop.background"); gnome_media_handling_preferences = g_settings_new("org.cinnamon.desktop.media-handling"); gnome_terminal_preferences = g_settings_new("org.cinnamon.desktop.default-applications.terminal"); cinnamon_privacy_preferences = g_settings_new("org.cinnamon.desktop.privacy"); cinnamon_interface_preferences = g_settings_new ("org.cinnamon.desktop.interface"); ignore_view_metadata = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_IGNORE_VIEW_METADATA); g_signal_connect (nemo_preferences, "changed::" NEMO_PREFERENCES_IGNORE_VIEW_METADATA, G_CALLBACK (ignore_view_metadata_cb), NULL); cache_fileroller_mimetypes (); } void nemo_global_preferences_finalize (void) { g_strfreev (file_roller_mimetypes); } nemo-3.6.5/libnemo-private/nemo-vfs-directory.h0000664000175000017500000000375313215733314020423 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-vfs-directory.h: Subclass of NemoDirectory to implement the the case of a VFS directory. Copyright (C) 1999, 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_VFS_DIRECTORY_H #define NEMO_VFS_DIRECTORY_H #include #define NEMO_TYPE_VFS_DIRECTORY nemo_vfs_directory_get_type() #define NEMO_VFS_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_VFS_DIRECTORY, NemoVFSDirectory)) #define NEMO_VFS_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_VFS_DIRECTORY, NemoVFSDirectoryClass)) #define NEMO_IS_VFS_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_VFS_DIRECTORY)) #define NEMO_IS_VFS_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_VFS_DIRECTORY)) #define NEMO_VFS_DIRECTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_VFS_DIRECTORY, NemoVFSDirectoryClass)) typedef struct NemoVFSDirectoryDetails NemoVFSDirectoryDetails; typedef struct { NemoDirectory parent_slot; } NemoVFSDirectory; typedef struct { NemoDirectoryClass parent_slot; } NemoVFSDirectoryClass; GType nemo_vfs_directory_get_type (void); #endif /* NEMO_VFS_DIRECTORY_H */ nemo-3.6.5/libnemo-private/nemo-dbus-manager.c0000664000175000017500000001335613215733314020163 0ustar fabiofabio/* * nemo-dbus-manager: nemo DBus interface * * Copyright (C) 2010, Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * * Author: Cosimo Cecchi * */ #include #include "nemo-dbus-manager.h" #include "nemo-generated.h" #include "nemo-file-operations.h" #define DEBUG_FLAG NEMO_DEBUG_DBUS #include "nemo-debug.h" #include struct _NemoDBusManager { GObject parent; GDBusObjectManagerServer *object_manager; NemoDBusFileOperations *file_operations; }; struct _NemoDBusManagerClass { GObjectClass parent_class; }; G_DEFINE_TYPE (NemoDBusManager, nemo_dbus_manager, G_TYPE_OBJECT); static void nemo_dbus_manager_dispose (GObject *object) { NemoDBusManager *self = (NemoDBusManager *) object; if (self->file_operations) { g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (self->file_operations)); g_object_unref (self->file_operations); self->file_operations = NULL; } if (self->object_manager) { g_object_unref (self->object_manager); self->object_manager = NULL; } G_OBJECT_CLASS (nemo_dbus_manager_parent_class)->dispose (object); } static gboolean handle_copy_file (NemoDBusFileOperations *object, GDBusMethodInvocation *invocation, const gchar *source_uri, const gchar *source_display_name, const gchar *dest_dir_uri, const gchar *dest_name) { GFile *source_file, *target_dir; const gchar *target_name = NULL, *source_name = NULL; source_file = g_file_new_for_uri (source_uri); target_dir = g_file_new_for_uri (dest_dir_uri); if (dest_name != NULL && dest_name[0] != '\0') target_name = dest_name; if (source_display_name != NULL && source_display_name[0] != '\0') source_name = source_display_name; nemo_file_operations_copy_file (source_file, target_dir, source_name, target_name, NULL, NULL, NULL); g_object_unref (source_file); g_object_unref (target_dir); nemo_dbus_file_operations_complete_copy_file (object, invocation); return TRUE; /* invocation was handled */ } static gboolean handle_copy_uris (NemoDBusFileOperations *object, GDBusMethodInvocation *invocation, const gchar **sources, const gchar *destination) { GList *source_files = NULL; GFile *dest_dir; gint idx; dest_dir = g_file_new_for_uri (destination); for (idx = 0; sources[idx] != NULL; idx++) source_files = g_list_prepend (source_files, g_file_new_for_uri (sources[idx])); nemo_file_operations_copy (source_files, NULL, dest_dir, NULL, NULL, NULL); g_list_free_full (source_files, g_object_unref); g_object_unref (dest_dir); nemo_dbus_file_operations_complete_copy_uris (object, invocation); return TRUE; /* invocation was handled */ } static gboolean handle_move_uris (NemoDBusFileOperations *object, GDBusMethodInvocation *invocation, const gchar **sources, const gchar *destination) { GList *source_files = NULL; GFile *dest_dir; gint idx; dest_dir = g_file_new_for_uri (destination); for (idx = 0; sources[idx] != NULL; idx++) source_files = g_list_prepend (source_files, g_file_new_for_uri (sources[idx])); nemo_file_operations_move (source_files, NULL, dest_dir, NULL, NULL, NULL); g_list_free_full (source_files, g_object_unref); g_object_unref (dest_dir); nemo_dbus_file_operations_complete_move_uris (object, invocation); return TRUE; /* invocation was handled */ } static gboolean handle_empty_trash (NemoDBusFileOperations *object, GDBusMethodInvocation *invocation) { nemo_file_operations_empty_trash (NULL); nemo_dbus_file_operations_complete_empty_trash (object, invocation); return TRUE; /* invocation was handled */ } static void nemo_dbus_manager_init (NemoDBusManager *self) { GDBusConnection *connection; connection = g_application_get_dbus_connection (g_application_get_default ()); self->object_manager = g_dbus_object_manager_server_new ("/org/Nemo"); self->file_operations = nemo_dbus_file_operations_skeleton_new (); g_signal_connect (self->file_operations, "handle-copy-uris", G_CALLBACK (handle_copy_uris), self); g_signal_connect (self->file_operations, "handle-copy-file", G_CALLBACK (handle_copy_file), self); g_signal_connect (self->file_operations, "handle-move-uris", G_CALLBACK (handle_move_uris), self); g_signal_connect (self->file_operations, "handle-empty-trash", G_CALLBACK (handle_empty_trash), self); g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->file_operations), connection, "/org/Nemo", NULL); g_dbus_object_manager_server_set_connection (self->object_manager, connection); } static void nemo_dbus_manager_class_init (NemoDBusManagerClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); oclass->dispose = nemo_dbus_manager_dispose; } NemoDBusManager * nemo_dbus_manager_new (void) { return g_object_new (nemo_dbus_manager_get_type (), NULL); } nemo-3.6.5/libnemo-private/nemo-clipboard.c0000664000175000017500000004263713215733314017561 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-clipboard.c * * Nemo Clipboard support. For now, routines to support component cut * and paste. * * Copyright (C) 1999, 2000 Free Software Foundaton * Copyright (C) 2000, 2001 Eazel, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Rebecca Schulman , * Darin Adler */ #include #include "nemo-clipboard.h" #include "nemo-file-utilities.h" #include #include #include typedef struct _TargetCallbackData TargetCallbackData; typedef void (* SelectAllCallback) (gpointer target); typedef void (* ConnectCallbacksFunc) (GObject *object, TargetCallbackData *target_data); static void selection_changed_callback (GtkWidget *widget, gpointer callback_data); static void owner_change_callback (GtkClipboard *clipboard, GdkEventOwnerChange *event, gpointer callback_data); struct _TargetCallbackData { GtkUIManager *ui_manager; GtkActionGroup *action_group; gboolean shares_selection_changes; SelectAllCallback select_all_callback; ConnectCallbacksFunc connect_callbacks; ConnectCallbacksFunc disconnect_callbacks; }; static void cut_callback (gpointer target) { g_assert (target != NULL); g_signal_emit_by_name (target, "cut-clipboard"); } static void copy_callback (gpointer target) { g_assert (target != NULL); g_signal_emit_by_name (target, "copy-clipboard"); } static void paste_callback (gpointer target) { g_assert (target != NULL); g_signal_emit_by_name (target, "paste-clipboard"); } static void editable_select_all_callback (gpointer target) { GtkEditable *editable; editable = GTK_EDITABLE (target); g_assert (editable != NULL); gtk_editable_set_position (editable, -1); gtk_editable_select_region (editable, 0, -1); } static void text_view_select_all_callback (gpointer target) { g_assert (GTK_IS_TEXT_VIEW (target)); g_signal_emit_by_name (target, "select-all", TRUE); } static void action_cut_callback (GtkAction *action, gpointer callback_data) { cut_callback (callback_data); } static void action_copy_callback (GtkAction *action, gpointer callback_data) { copy_callback (callback_data); } static void action_paste_callback (GtkAction *action, gpointer callback_data) { paste_callback (callback_data); } static void action_select_all_callback (GtkAction *action, gpointer callback_data) { TargetCallbackData *target_data; g_assert (callback_data != NULL); target_data = g_object_get_data (callback_data, "Nemo:clipboard_target_data"); g_assert (target_data != NULL); target_data->select_all_callback (callback_data); } static void received_clipboard_contents (GtkClipboard *clipboard, GtkSelectionData *selection_data, gpointer data) { GtkActionGroup *action_group; GtkAction *action; action_group = data; action = gtk_action_group_get_action (action_group, "Paste"); if (action != NULL) { gtk_action_set_sensitive (action, gtk_selection_data_targets_include_text (selection_data)); } g_object_unref (action_group); } static void set_paste_sensitive_if_clipboard_contains_data (GtkActionGroup *action_group) { GtkAction *action; if (gdk_display_supports_selection_notification (gdk_display_get_default ())) { gtk_clipboard_request_contents (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), gdk_atom_intern ("TARGETS", FALSE), received_clipboard_contents, g_object_ref (action_group)); } else { /* If selection notification isn't supported, always activate Paste */ action = gtk_action_group_get_action (action_group, "Paste"); gtk_action_set_sensitive (action, TRUE); } } static void set_clipboard_menu_items_sensitive (GtkActionGroup *action_group) { GtkAction *action; action = gtk_action_group_get_action (action_group, "Cut"); gtk_action_set_sensitive (action, TRUE); action = gtk_action_group_get_action (action_group, "Copy"); gtk_action_set_sensitive (action, TRUE); } static void set_clipboard_menu_items_insensitive (GtkActionGroup *action_group) { GtkAction *action; action = gtk_action_group_get_action (action_group, "Cut"); gtk_action_set_sensitive (action, FALSE); action = gtk_action_group_get_action (action_group, "Copy"); gtk_action_set_sensitive (action, FALSE); } static gboolean clipboard_items_are_merged_in (GtkWidget *widget) { return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "Nemo:clipboard_menu_items_merged")); } static void set_clipboard_items_are_merged_in (GObject *widget_as_object, gboolean merged_in) { g_object_set_data (widget_as_object, "Nemo:clipboard_menu_items_merged", GINT_TO_POINTER (merged_in)); } static void editable_connect_callbacks (GObject *object, TargetCallbackData *target_data) { g_signal_connect_after (object, "selection_changed", G_CALLBACK (selection_changed_callback), target_data); selection_changed_callback (GTK_WIDGET (object), target_data); } static void editable_disconnect_callbacks (GObject *object, TargetCallbackData *target_data) { g_signal_handlers_disconnect_matched (object, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, G_CALLBACK (selection_changed_callback), target_data); } static void text_buffer_update_sensitivity (GtkTextBuffer *buffer, TargetCallbackData *target_data) { g_assert (GTK_IS_TEXT_BUFFER (buffer)); g_assert (target_data != NULL); if (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL)) { set_clipboard_menu_items_sensitive (target_data->action_group); } else { set_clipboard_menu_items_insensitive (target_data->action_group); } } static void text_buffer_delete_range (GtkTextBuffer *buffer, GtkTextIter *iter1, GtkTextIter *iter2, TargetCallbackData *target_data) { text_buffer_update_sensitivity (buffer, target_data); } static void text_buffer_mark_set (GtkTextBuffer *buffer, GtkTextIter *iter, GtkTextMark *mark, TargetCallbackData *target_data) { /* anonymous marks with NULL names refer to cursor moves */ if (gtk_text_mark_get_name (mark) != NULL) { text_buffer_update_sensitivity (buffer, target_data); } } static void text_view_connect_callbacks (GObject *object, TargetCallbackData *target_data) { GtkTextBuffer *buffer; buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (object)); g_assert (buffer); g_signal_connect_after (buffer, "mark-set", G_CALLBACK (text_buffer_mark_set), target_data); g_signal_connect_after (buffer, "delete-range", G_CALLBACK (text_buffer_delete_range), target_data); text_buffer_update_sensitivity (buffer, target_data); } static void text_view_disconnect_callbacks (GObject *object, TargetCallbackData *target_data) { GtkTextBuffer *buffer; buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (object)); g_assert (buffer); g_signal_handlers_disconnect_matched (buffer, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, target_data); } static void merge_in_clipboard_menu_items (GObject *widget_as_object, TargetCallbackData *target_data) { gboolean add_selection_callback; g_assert (target_data != NULL); add_selection_callback = target_data->shares_selection_changes; gtk_ui_manager_insert_action_group (target_data->ui_manager, target_data->action_group, 0); set_paste_sensitive_if_clipboard_contains_data (target_data->action_group); g_signal_connect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), "owner_change", G_CALLBACK (owner_change_callback), target_data); if (add_selection_callback) { target_data->connect_callbacks (widget_as_object, target_data); } else { /* If we don't use sensitivity, everything should be on */ set_clipboard_menu_items_sensitive (target_data->action_group); } set_clipboard_items_are_merged_in (widget_as_object, TRUE); } static void merge_out_clipboard_menu_items (GObject *widget_as_object, TargetCallbackData *target_data) { gboolean selection_callback_was_added; g_assert (target_data != NULL); gtk_ui_manager_remove_action_group (target_data->ui_manager, target_data->action_group); g_signal_handlers_disconnect_matched (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, G_CALLBACK (owner_change_callback), target_data); selection_callback_was_added = target_data->shares_selection_changes; if (selection_callback_was_added) { target_data->disconnect_callbacks (widget_as_object, target_data); } set_clipboard_items_are_merged_in (widget_as_object, FALSE); } static gboolean focus_changed_callback (GtkWidget *widget, GdkEventAny *event, gpointer callback_data) { /* Connect the component to the container if the widget has focus. */ if (gtk_widget_has_focus (widget)) { if (!clipboard_items_are_merged_in (widget)) { merge_in_clipboard_menu_items (G_OBJECT (widget), callback_data); } } else { if (clipboard_items_are_merged_in (widget)) { merge_out_clipboard_menu_items (G_OBJECT (widget), callback_data); } } return FALSE; } static void selection_changed_callback (GtkWidget *widget, gpointer callback_data) { TargetCallbackData *target_data; GtkEditable *editable; int start, end; target_data = (TargetCallbackData *) callback_data; g_assert (target_data != NULL); editable = GTK_EDITABLE (widget); g_assert (editable != NULL); if (gtk_editable_get_selection_bounds (editable, &start, &end) && start != end) { set_clipboard_menu_items_sensitive (target_data->action_group); } else { set_clipboard_menu_items_insensitive (target_data->action_group); } } static void owner_change_callback (GtkClipboard *clipboard, GdkEventOwnerChange *event, gpointer callback_data) { TargetCallbackData *target_data; g_assert (callback_data != NULL); target_data = callback_data; set_paste_sensitive_if_clipboard_contains_data (target_data->action_group); } static void target_destroy_callback (GtkWidget *object, gpointer callback_data) { g_assert (callback_data != NULL); if (clipboard_items_are_merged_in (object)) { merge_out_clipboard_menu_items (G_OBJECT (object), callback_data); } } static void target_data_free (TargetCallbackData *target_data) { g_object_unref (target_data->action_group); g_free (target_data); } static const GtkActionEntry clipboard_entries[] = { /* name, stock id */ { "Cut", GTK_STOCK_CUT, /* label, accelerator */ NULL, NULL, /* tooltip */ N_("Cut the selected text to the clipboard"), G_CALLBACK (action_cut_callback) }, /* name, stock id */ { "Copy", GTK_STOCK_COPY, /* label, accelerator */ NULL, NULL, /* tooltip */ N_("Copy the selected text to the clipboard"), G_CALLBACK (action_copy_callback) }, /* name, stock id */ { "Paste", GTK_STOCK_PASTE, /* label, accelerator */ NULL, NULL, /* tooltip */ N_("Paste the text stored on the clipboard"), G_CALLBACK (action_paste_callback) }, /* name, stock id */ { "Select All", NULL, /* label, accelerator */ N_("Select _All"), "A", /* tooltip */ N_("Select all the text in a text field"), G_CALLBACK (action_select_all_callback) }, }; static TargetCallbackData * initialize_clipboard_component_with_callback_data (GtkEditable *target, GtkUIManager *ui_manager, gboolean shares_selection_changes, SelectAllCallback select_all_callback, ConnectCallbacksFunc connect_callbacks, ConnectCallbacksFunc disconnect_callbacks) { GtkActionGroup *action_group; TargetCallbackData *target_data; action_group = gtk_action_group_new ("ClipboardActions"); gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); gtk_action_group_add_actions (action_group, clipboard_entries, G_N_ELEMENTS (clipboard_entries), target); /* Do the actual connection of the UI to the container at * focus time, and disconnect at both focus and destroy * time. */ target_data = g_new (TargetCallbackData, 1); target_data->ui_manager = ui_manager; target_data->action_group = action_group; target_data->shares_selection_changes = shares_selection_changes; target_data->select_all_callback = select_all_callback; target_data->connect_callbacks = connect_callbacks; target_data->disconnect_callbacks = disconnect_callbacks; return target_data; } static void nemo_clipboard_real_set_up (gpointer target, GtkUIManager *ui_manager, gboolean shares_selection_changes, SelectAllCallback select_all_callback, ConnectCallbacksFunc connect_callbacks, ConnectCallbacksFunc disconnect_callbacks) { TargetCallbackData *target_data; if (g_object_get_data (G_OBJECT (target), "Nemo:clipboard_target_data") != NULL) { return; } target_data = initialize_clipboard_component_with_callback_data (target, ui_manager, shares_selection_changes, select_all_callback, connect_callbacks, disconnect_callbacks); g_signal_connect (target, "focus_in_event", G_CALLBACK (focus_changed_callback), target_data); g_signal_connect (target, "focus_out_event", G_CALLBACK (focus_changed_callback), target_data); g_signal_connect (target, "destroy", G_CALLBACK (target_destroy_callback), target_data); g_object_set_data_full (G_OBJECT (target), "Nemo:clipboard_target_data", target_data, (GDestroyNotify) target_data_free); /* Call the focus changed callback once to merge if the window is * already in focus. */ focus_changed_callback (GTK_WIDGET (target), NULL, target_data); } void nemo_clipboard_set_up_editable (GtkEditable *target, GtkUIManager *ui_manager, gboolean shares_selection_changes) { g_return_if_fail (GTK_IS_EDITABLE (target)); g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); nemo_clipboard_real_set_up (target, ui_manager, shares_selection_changes, editable_select_all_callback, editable_connect_callbacks, editable_disconnect_callbacks); } void nemo_clipboard_set_up_text_view (GtkTextView *target, GtkUIManager *ui_manager) { g_return_if_fail (GTK_IS_TEXT_VIEW (target)); g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); nemo_clipboard_real_set_up (target, ui_manager, TRUE, text_view_select_all_callback, text_view_connect_callbacks, text_view_disconnect_callbacks); } static GList * convert_lines_to_str_list (char **lines, gboolean *cut) { int i; GList *result; if (cut) { *cut = FALSE; } if (lines[0] == NULL) { return NULL; } if (strcmp (lines[0], "cut") == 0) { if (cut) { *cut = TRUE; } } else if (strcmp (lines[0], "copy") != 0) { return NULL; } result = NULL; for (i = 1; lines[i] != NULL; i++) { result = g_list_prepend (result, g_strdup (lines[i])); } return g_list_reverse (result); } GList* nemo_clipboard_get_uri_list_from_selection_data (GtkSelectionData *selection_data, gboolean *cut, GdkAtom copied_files_atom) { GList *items; char **lines; if (gtk_selection_data_get_data_type (selection_data) != copied_files_atom || gtk_selection_data_get_length (selection_data) <= 0) { items = NULL; } else { gchar *data; /* Not sure why it's legal to assume there's an extra byte * past the end of the selection data that it's safe to write * to. But gtk_editable_selection_received does this, so I * think it is OK. */ data = (gchar *) gtk_selection_data_get_data (selection_data); data[gtk_selection_data_get_length (selection_data)] = '\0'; lines = g_strsplit (data, "\n", 0); items = convert_lines_to_str_list (lines, cut); g_strfreev (lines); } return items; } GtkClipboard * nemo_clipboard_get (GtkWidget *widget) { return gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (widget)), GDK_SELECTION_CLIPBOARD); } void nemo_clipboard_clear_if_colliding_uris (GtkWidget *widget, const GList *item_uris, GdkAtom copied_files_atom) { GtkSelectionData *data; GList *clipboard_item_uris, *l; gboolean collision; collision = FALSE; data = gtk_clipboard_wait_for_contents (nemo_clipboard_get (widget), copied_files_atom); if (data == NULL) { return; } clipboard_item_uris = nemo_clipboard_get_uri_list_from_selection_data (data, NULL, copied_files_atom); for (l = (GList *) item_uris; l; l = l->next) { if (g_list_find_custom ((GList *) item_uris, l->data, (GCompareFunc) g_strcmp0)) { collision = TRUE; break; } } if (collision) { gtk_clipboard_clear (nemo_clipboard_get (widget)); } if (clipboard_item_uris) { g_list_free_full (clipboard_item_uris, g_free); } } nemo-3.6.5/libnemo-private/nemo-mime-application-chooser.c0000664000175000017500000006241713215733314022510 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * nemo-mime-application-chooser.c: an mime-application chooser * * Copyright (C) 2004 Novell, Inc. * Copyright (C) 2007, 2010 Red Hat, Inc. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but APPLICATIONOUT ANY WARRANTY; applicationout even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along application the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Dave Camp * Alexander Larsson * Cosimo Cecchi */ #include #include "nemo-mime-application-chooser.h" #include "nemo-file.h" #include "nemo-signaller.h" #include #include #include #include #include #include #include struct _NemoMimeApplicationChooserDetails { GList *files; char *uri; char *content_type; GtkWidget *label; GtkWidget *entry; GtkWidget *set_as_default_button; GtkWidget *open_with_widget; GtkWidget *add_button; GtkWidget *custom_picker; GtkWidget *file_button; GAppInfo *custom_info; GtkWidget *custom_entry; GtkWidget *dialog_ok; }; enum { PROP_CONTENT_TYPE = 1, PROP_URI, PROP_FILES, PROP_DIALOG_OK, NUM_PROPERTIES }; #define DEFAULT_APPS "Default Applications" #define ADDED_ASS "Added Associations" static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; G_DEFINE_TYPE (NemoMimeApplicationChooser, nemo_mime_application_chooser, GTK_TYPE_BOX); static void add_clicked_cb (GtkButton *button, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; GAppInfo *info; if (!chooser->details->custom_info) { info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget)); g_app_info_set_as_last_used_for_type (info, chooser->details->content_type, NULL); } else { info = chooser->details->custom_info; g_app_info_set_as_last_used_for_type (info, chooser->details->content_type, NULL); } if (info == NULL) return; gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget)); gtk_entry_set_text (GTK_ENTRY (chooser->details->custom_entry), ""); gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser->details->file_button), ""); g_signal_emit_by_name (nemo_signaller_get_current (), "mime_data_changed"); } static void remove_clicked_cb (GtkMenuItem *item, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; GError *error; GAppInfo *info; info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget)); if (info) { error = NULL; if (!g_app_info_remove_supports_type (info, chooser->details->content_type, &error)) { eel_show_error_dialog (_("Could not forget association"), error->message, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (chooser)))); g_error_free (error); } gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget)); g_object_unref (info); } g_signal_emit_by_name (nemo_signaller_get_current (), "mime_data_changed"); } static void populate_popup_cb (GtkAppChooserWidget *widget, GtkMenu *menu, GAppInfo *app, gpointer user_data) { GtkWidget *item; NemoMimeApplicationChooser *chooser = user_data; if (g_app_info_can_remove_supports_type (app)) { item = gtk_menu_item_new_with_label (_("Forget association")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); g_signal_connect (item, "activate", G_CALLBACK (remove_clicked_cb), chooser); } } static void reset_clicked_cb (GtkButton *button, gpointer user_data) { NemoMimeApplicationChooser *chooser; chooser = NEMO_MIME_APPLICATION_CHOOSER (user_data); g_app_info_reset_type_associations (chooser->details->content_type); gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget)); gtk_entry_set_text (GTK_ENTRY (chooser->details->custom_entry), ""); gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser->details->file_button), ""); g_signal_emit_by_name (nemo_signaller_get_current (), "mime_data_changed"); } static void set_as_default_clicked_cb (GtkButton *button, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; GAppInfo *info; if (!chooser->details->custom_info) { info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget)); g_app_info_set_as_default_for_type (info, chooser->details->content_type, NULL); } else { info = chooser->details->custom_info; g_app_info_set_as_default_for_type (info, chooser->details->content_type, NULL); } gtk_app_chooser_refresh (GTK_APP_CHOOSER (chooser->details->open_with_widget)); gtk_entry_set_text (GTK_ENTRY (chooser->details->custom_entry), ""); gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser->details->file_button), ""); g_signal_emit_by_name (nemo_signaller_get_current (), "mime_data_changed"); } static gint app_compare (gconstpointer a, gconstpointer b) { return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b)); } static gboolean app_info_can_add (GAppInfo *info, const gchar *content_type) { GList *recommended, *fallback; gboolean retval = FALSE; recommended = g_app_info_get_recommended_for_type (content_type); fallback = g_app_info_get_fallback_for_type (content_type); if (g_list_find_custom (recommended, info, app_compare)) { goto out; } if (g_list_find_custom (fallback, info, app_compare)) { goto out; } retval = TRUE; out: g_list_free_full (recommended, g_object_unref); g_list_free_full (fallback, g_object_unref); return retval; } static void application_selected_cb (GtkAppChooserWidget *widget, GAppInfo *info, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; GAppInfo *default_app; gtk_entry_set_text (GTK_ENTRY (chooser->details->custom_entry), ""); default_app = g_app_info_get_default_for_type (chooser->details->content_type, FALSE); gtk_widget_set_sensitive (chooser->details->set_as_default_button, !g_app_info_equal (info, default_app)); gtk_widget_set_sensitive (chooser->details->add_button, app_info_can_add (info, chooser->details->content_type)); gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser->details->file_button), ""); if (chooser->details->dialog_ok) gtk_widget_set_sensitive (chooser->details->dialog_ok, TRUE); g_object_unref (default_app); } static void application_activated_cb (GtkAppChooserWidget *widget, GAppInfo *info, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; if (chooser->details->dialog_ok) { gtk_window_activate_default (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (widget)))); } } static gboolean validate_entry (GtkEntry *entry, const gchar *str) { gint argcp = 0; gchar **argvp = NULL; gboolean ret = FALSE; if (g_shell_parse_argv (str, &argcp, &argvp, NULL)) { if (argcp > 0) { gchar *path_exec = g_find_program_in_path (argvp[0]); if (path_exec) { ret = TRUE; } else { if (!g_file_test (str, G_FILE_TEST_IS_DIR) && g_file_test (str, G_FILE_TEST_IS_EXECUTABLE)) { ret = TRUE; } } g_free (path_exec); } g_strfreev (argvp); } if (ret) { gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, "ok"); gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, _("Valid executable.")); } else { gtk_entry_set_icon_from_icon_name (entry, GTK_ENTRY_ICON_SECONDARY, "stop"); gtk_entry_set_icon_tooltip_text (entry, GTK_ENTRY_ICON_SECONDARY, _("Not a valid executable. Spaces in the file path must be escaped with backslash (\\).")); } return ret; } static gchar * get_nice_name (const gchar *entry) { gchar *exec_path; gchar *ret = NULL; gint argcp = 0; gchar **argvp = NULL; if (g_shell_parse_argv (entry, &argcp, &argvp, NULL)) { if (argcp > 0) { exec_path = argvp[0]; GFile *file = g_file_new_for_path (exec_path); ret = g_file_get_basename (file); g_object_unref (file); } g_strfreev (argvp); } return ret; } static void custom_entry_changed_cb (GtkEditable *entry, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; const gchar *entry_text = gtk_entry_get_text (GTK_ENTRY (entry)); gboolean empty = g_strcmp0 (entry_text, "") == 0; if (!empty && validate_entry (GTK_ENTRY (entry), entry_text)) { GAppInfo *default_app; gchar *cl = g_strdup_printf ("%s", entry_text); GAppInfo *info = g_app_info_create_from_commandline (cl, get_nice_name (cl), G_APP_INFO_CREATE_NONE, NULL); default_app = g_app_info_get_default_for_type (chooser->details->content_type, FALSE); gtk_widget_set_sensitive (chooser->details->set_as_default_button, !g_app_info_equal (info, default_app)); gtk_widget_set_sensitive (chooser->details->add_button, app_info_can_add (info, chooser->details->content_type)); g_object_unref (default_app); if (chooser->details->custom_info != NULL) { g_object_unref (chooser->details->custom_info); chooser->details->custom_info = NULL; } chooser->details->custom_info = info; if (chooser->details->dialog_ok) gtk_widget_set_sensitive (chooser->details->dialog_ok, TRUE); } else { if (chooser->details->custom_info != NULL) { g_object_unref (chooser->details->custom_info); chooser->details->custom_info = NULL; } if (empty) { gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL); gtk_entry_set_icon_tooltip_text (GTK_ENTRY (entry), GTK_ENTRY_ICON_SECONDARY, NULL); } gtk_widget_set_sensitive (chooser->details->set_as_default_button, FALSE); gtk_widget_set_sensitive (chooser->details->add_button, FALSE); if (chooser->details->dialog_ok) gtk_widget_set_sensitive (chooser->details->dialog_ok, FALSE); } } static void custom_app_set_cb (GtkFileChooserButton *button, gpointer user_data) { NemoMimeApplicationChooser *chooser = user_data; gchar *unescaped = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (button)); gchar *escaped = eel_str_escape_spaces (unescaped); gtk_entry_set_text (GTK_ENTRY (chooser->details->custom_entry), escaped); gtk_widget_grab_focus (chooser->details->custom_entry); gtk_editable_set_position (GTK_EDITABLE (chooser->details->custom_entry), -1); g_free (unescaped); g_free (escaped); } static char * get_extension (const char *basename) { char *p; p = strrchr (basename, '.'); if (p && *(p + 1) != '\0') { return g_strdup (p + 1); } else { return NULL; } } static gchar * get_extension_from_file (NemoFile *nfile) { char *name; char *extension; name = nemo_file_get_name (nfile); extension = get_extension (name); g_free (name); return extension; } static void nemo_mime_application_chooser_apply_labels (NemoMimeApplicationChooser *chooser) { gchar *label, *extension = NULL, *description = NULL; if (chooser->details->files != NULL) { /* here we assume all files are of the same content type */ if (g_content_type_is_unknown (chooser->details->content_type)) { extension = get_extension_from_file (NEMO_FILE (chooser->details->files->data)); /* the %s here is a file extension */ description = g_strdup_printf (_("%s document"), extension); } else { description = g_content_type_get_description (chooser->details->content_type); } label = g_strdup_printf (_("Open all files of type \"%s\" with"), description); } else { GFile *file; gchar *basename, *emname; file = g_file_new_for_uri (chooser->details->uri); basename = g_file_get_basename (file); if (g_content_type_is_unknown (chooser->details->content_type)) { extension = get_extension (basename); /* the %s here is a file extension */ description = g_strdup_printf (_("%s document"), extension); } else { description = g_content_type_get_description (chooser->details->content_type); } /* first %s is filename, second %s is mime-type description */ emname = g_strdup_printf ("%s", basename); label = g_strdup_printf (_("Select an application in the list to open %s and other files of type \"%s\""), emname, description); g_free (emname); g_free (basename); g_object_unref (file); } gtk_label_set_markup (GTK_LABEL (chooser->details->label), label); g_free (label); g_free (extension); g_free (description); } static gboolean exec_filter_func (const GtkFileFilterInfo *info, gpointer data) { if (info->contains & GTK_FILE_FILTER_FILENAME) { if (g_file_test (info->filename, G_FILE_TEST_IS_EXECUTABLE)) return TRUE; } return FALSE; } static void nemo_mime_application_chooser_build_ui (NemoMimeApplicationChooser *chooser) { GtkWidget *box, *button, *w; GAppInfo *info; gtk_container_set_border_width (GTK_CONTAINER (chooser), 8); gtk_box_set_spacing (GTK_BOX (chooser), 0); gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE); chooser->details->label = gtk_label_new (""); gtk_misc_set_alignment (GTK_MISC (chooser->details->label), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (chooser->details->label), TRUE); gtk_label_set_line_wrap_mode (GTK_LABEL (chooser->details->label), PANGO_WRAP_WORD_CHAR); gtk_box_pack_start (GTK_BOX (chooser), chooser->details->label, FALSE, FALSE, 0); gtk_widget_show (chooser->details->label); chooser->details->open_with_widget = gtk_app_chooser_widget_new (chooser->details->content_type); gtk_app_chooser_widget_set_show_default (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget), TRUE); gtk_app_chooser_widget_set_show_fallback (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget), TRUE); gtk_box_pack_start (GTK_BOX (chooser), chooser->details->open_with_widget, TRUE, TRUE, 6); gtk_widget_show (chooser->details->open_with_widget); g_signal_connect (chooser->details->open_with_widget, "application-selected", G_CALLBACK (application_selected_cb), chooser); g_signal_connect (chooser->details->open_with_widget, "populate-popup", G_CALLBACK (populate_popup_cb), chooser); g_signal_connect (chooser->details->open_with_widget, "application-activated", G_CALLBACK (application_activated_cb), chooser); gtk_app_chooser_widget_set_show_other (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget), TRUE); gtk_app_chooser_widget_set_show_recommended (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget), TRUE); GtkWidget *custom_label = gtk_label_new (_("You can also type or select a custom executable file to use to open this file type. " "You can use this command just once, or set it as default for all files of this type.")); gtk_misc_set_alignment (GTK_MISC (custom_label), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (custom_label), TRUE); gtk_label_set_line_wrap_mode (GTK_LABEL (custom_label), PANGO_WRAP_WORD_CHAR); gtk_box_pack_start (GTK_BOX (chooser), custom_label, FALSE, FALSE, 0); gtk_widget_show (GTK_WIDGET (custom_label)); GtkWidget *custom_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (chooser), custom_box, TRUE, TRUE, 0); GtkWidget *entry = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (custom_box), entry, TRUE, TRUE, 0); gtk_entry_set_placeholder_text (GTK_ENTRY (entry), _("Enter a custom command...")); gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); g_signal_connect (entry, "changed", G_CALLBACK (custom_entry_changed_cb), chooser); chooser->details->custom_entry = entry; button = gtk_file_chooser_button_new (_("Custom application"), GTK_FILE_CHOOSER_ACTION_OPEN); /* FIXME: I shouldn't do this, but this is the simplest way for 2.6 at this point to remove the useless (and misleading) label and image in the file picker button - when a program is selected, it dumps the path into the custom entry box, we don't need to show anything in the button. These names are valid in GTK 3.10, .12, .14, .16 and master. This should be replaced by a simple icon-only button that creates a GtkFileChooserDialog when clicked. A lot more changes involved there, postpone for 2.8 */ w = GTK_WIDGET (gtk_widget_get_template_child (button, GTK_TYPE_FILE_CHOOSER_BUTTON, "label")); gtk_widget_hide (w); w = GTK_WIDGET (gtk_widget_get_template_child (button, GTK_TYPE_FILE_CHOOSER_BUTTON, "image")); gtk_widget_hide (w); g_signal_connect (button, "file-set", G_CALLBACK (custom_app_set_cb), chooser); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (custom_box), button, FALSE, FALSE, 6); chooser->details->file_button = button; gtk_widget_show_all (custom_box); chooser->details->custom_picker = button; box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); gtk_box_set_spacing (GTK_BOX (box), 6); gtk_button_box_set_layout (GTK_BUTTON_BOX (box), GTK_BUTTONBOX_CENTER); gtk_box_pack_start (GTK_BOX (chooser), box, FALSE, FALSE, 6); gtk_widget_show (box); GtkFileFilter *filter = gtk_file_filter_new (); gtk_file_filter_add_custom (filter, GTK_FILE_FILTER_FILENAME, (GtkFileFilterFunc) exec_filter_func, NULL, NULL); gtk_file_filter_set_name (filter, _("Executables")); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (button), filter); button = gtk_button_new_with_label (_("Add to list")); g_signal_connect (button, "clicked", G_CALLBACK (add_clicked_cb), chooser); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); chooser->details->add_button = button; button = gtk_button_new_with_label (_("Set as default")); g_signal_connect (button, "clicked", G_CALLBACK (set_as_default_clicked_cb), chooser); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); chooser->details->set_as_default_button = button; button = gtk_button_new_with_label (_("Reset to system defaults")); g_signal_connect (button, "clicked", G_CALLBACK (reset_clicked_cb), chooser); gtk_widget_show (button); gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0); /* initialize sensitivity */ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget)); if (info != NULL) { application_selected_cb (GTK_APP_CHOOSER_WIDGET (chooser->details->open_with_widget), info, chooser); g_object_unref (info); } gtk_widget_grab_focus (chooser->details->custom_entry); } static void nemo_mime_application_chooser_init (NemoMimeApplicationChooser *chooser) { chooser->details = G_TYPE_INSTANCE_GET_PRIVATE (chooser, NEMO_TYPE_MIME_APPLICATION_CHOOSER, NemoMimeApplicationChooserDetails); gtk_orientable_set_orientation (GTK_ORIENTABLE (chooser), GTK_ORIENTATION_VERTICAL); chooser->details->custom_info = NULL; } static void nemo_mime_application_chooser_constructed (GObject *object) { NemoMimeApplicationChooser *chooser = NEMO_MIME_APPLICATION_CHOOSER (object); if (G_OBJECT_CLASS (nemo_mime_application_chooser_parent_class)->constructed != NULL) G_OBJECT_CLASS (nemo_mime_application_chooser_parent_class)->constructed (object); nemo_mime_application_chooser_build_ui (chooser); nemo_mime_application_chooser_apply_labels (chooser); } static void nemo_mime_application_chooser_finalize (GObject *object) { NemoMimeApplicationChooser *chooser; chooser = NEMO_MIME_APPLICATION_CHOOSER (object); g_free (chooser->details->uri); g_free (chooser->details->content_type); if (chooser->details->custom_info != NULL) g_object_unref (chooser->details->custom_info); G_OBJECT_CLASS (nemo_mime_application_chooser_parent_class)->finalize (object); } static void nemo_mime_application_chooser_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { NemoMimeApplicationChooser *chooser = NEMO_MIME_APPLICATION_CHOOSER (object); switch (property_id) { case PROP_CONTENT_TYPE: g_value_set_string (value, chooser->details->content_type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_mime_application_chooser_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { NemoMimeApplicationChooser *chooser = NEMO_MIME_APPLICATION_CHOOSER (object); switch (property_id) { case PROP_CONTENT_TYPE: chooser->details->content_type = g_value_dup_string (value); break; case PROP_FILES: chooser->details->files = g_value_get_pointer (value); break; case PROP_URI: chooser->details->uri = g_value_dup_string (value); break; case PROP_DIALOG_OK: chooser->details->dialog_ok = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_mime_application_chooser_class_init (NemoMimeApplicationChooserClass *class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->set_property = nemo_mime_application_chooser_set_property; gobject_class->get_property = nemo_mime_application_chooser_get_property; gobject_class->finalize = nemo_mime_application_chooser_finalize; gobject_class->constructed = nemo_mime_application_chooser_constructed; properties[PROP_CONTENT_TYPE] = g_param_spec_string ("content-type", "Content type", "Content type for this widget", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); properties[PROP_URI] = g_param_spec_string ("uri", "URI", "URI for this widget", NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); properties[PROP_FILES] = g_param_spec_pointer ("files", "Files", "Files for this widget", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); properties[PROP_DIALOG_OK] = g_param_spec_object ("ok-button", "Dialog OK button", "Dialog OK button", GTK_TYPE_WIDGET, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties); g_type_class_add_private (class, sizeof (NemoMimeApplicationChooserDetails)); } GtkWidget * nemo_mime_application_chooser_new (const char *uri, GList *files, const char *mime_type, GtkWidget *ok_button) { GtkWidget *chooser; chooser = g_object_new (NEMO_TYPE_MIME_APPLICATION_CHOOSER, "uri", uri, "files", files, "content-type", mime_type, "ok-button", ok_button, NULL); return chooser; } GAppInfo * nemo_mime_application_chooser_get_info (NemoMimeApplicationChooser *chooser) { if (chooser->details->custom_info == NULL) return gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (chooser->details->open_with_widget)); else return chooser->details->custom_info; } const gchar * nemo_mime_application_chooser_get_uri (NemoMimeApplicationChooser *chooser) { return chooser->details->uri; } nemo-3.6.5/libnemo-private/nemo-file-undo-manager.c0000664000175000017500000001613113215733314021102 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-undo-manager.c - Manages the undo/redo stack * * Copyright (C) 2007-2011 Amos Brocco * Copyright (C) 2010, 2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Amos Brocco * Cosimo Cecchi * */ #include #include "nemo-file-undo-manager.h" #include "nemo-file-operations.h" #include "nemo-file.h" #include "nemo-trash-monitor.h" #include #define DEBUG_FLAG NEMO_DEBUG_UNDO #include "nemo-debug.h" enum { SIGNAL_UNDO_CHANGED, NUM_SIGNALS, }; static guint signals[NUM_SIGNALS] = { 0, }; G_DEFINE_TYPE (NemoFileUndoManager, nemo_file_undo_manager, G_TYPE_OBJECT) struct _NemoFileUndoManagerPrivate { NemoFileUndoInfo *info; NemoFileUndoManagerState state; NemoFileUndoManagerState last_state; guint undo_redo_flag : 1; gulong trash_signal_id; }; static NemoFileUndoManager *undo_singleton = NULL; static NemoFileUndoManager * get_singleton (void) { if (undo_singleton == NULL) { undo_singleton = g_object_new (NEMO_TYPE_FILE_UNDO_MANAGER, NULL); g_object_add_weak_pointer (G_OBJECT (undo_singleton), (gpointer) &undo_singleton); } return undo_singleton; } static void file_undo_manager_clear (NemoFileUndoManager *self) { g_clear_object (&self->priv->info); self->priv->state = NEMO_FILE_UNDO_MANAGER_STATE_NONE; } static void trash_state_changed_cb (NemoTrashMonitor *monitor, gboolean is_empty, gpointer user_data) { NemoFileUndoManager *self = user_data; if (!is_empty) { return; } if (self->priv->state == NEMO_FILE_UNDO_MANAGER_STATE_NONE) { return; } if (NEMO_IS_FILE_UNDO_INFO_TRASH (self->priv->info)) { file_undo_manager_clear (self); g_signal_emit (self, signals[SIGNAL_UNDO_CHANGED], 0); } } static void nemo_file_undo_manager_init (NemoFileUndoManager * self) { NemoFileUndoManagerPrivate *priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_FILE_UNDO_MANAGER, NemoFileUndoManagerPrivate); priv->trash_signal_id = g_signal_connect (nemo_trash_monitor_get (), "trash-state-changed", G_CALLBACK (trash_state_changed_cb), self); } static void nemo_file_undo_manager_finalize (GObject * object) { NemoFileUndoManager *self = NEMO_FILE_UNDO_MANAGER (object); NemoFileUndoManagerPrivate *priv = self->priv; if (priv->trash_signal_id != 0) { g_signal_handler_disconnect (nemo_trash_monitor_get (), priv->trash_signal_id); priv->trash_signal_id = 0; } file_undo_manager_clear (self); G_OBJECT_CLASS (nemo_file_undo_manager_parent_class)->finalize (object); } static void nemo_file_undo_manager_class_init (NemoFileUndoManagerClass *klass) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (klass); oclass->finalize = nemo_file_undo_manager_finalize; signals[SIGNAL_UNDO_CHANGED] = g_signal_new ("undo-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_class_add_private (klass, sizeof (NemoFileUndoManagerPrivate)); } static void undo_info_apply_ready (GObject *source, GAsyncResult *res, gpointer user_data) { NemoFileUndoManager *self = user_data; NemoFileUndoInfo *info = NEMO_FILE_UNDO_INFO (source); gboolean success, user_cancel; success = nemo_file_undo_info_apply_finish (info, res, &user_cancel, NULL); /* just return in case we got another another operation set */ if ((self->priv->info != NULL) && (self->priv->info != info)) { return; } if (success) { if (self->priv->last_state == NEMO_FILE_UNDO_MANAGER_STATE_UNDO) { self->priv->state = NEMO_FILE_UNDO_MANAGER_STATE_REDO; } else if (self->priv->last_state == NEMO_FILE_UNDO_MANAGER_STATE_REDO) { self->priv->state = NEMO_FILE_UNDO_MANAGER_STATE_UNDO; } self->priv->info = g_object_ref (info); } else if (user_cancel) { self->priv->state = self->priv->last_state; self->priv->info = g_object_ref (info); } else { file_undo_manager_clear (self); } g_signal_emit (self, signals[SIGNAL_UNDO_CHANGED], 0); } static void do_undo_redo (NemoFileUndoManager *self, GtkWindow *parent_window) { gboolean undo = self->priv->state == NEMO_FILE_UNDO_MANAGER_STATE_UNDO; self->priv->last_state = self->priv->state; nemo_file_undo_manager_push_flag (); nemo_file_undo_info_apply_async (self->priv->info, undo, parent_window, undo_info_apply_ready, self); /* clear actions while undoing */ file_undo_manager_clear (self); g_signal_emit (self, signals[SIGNAL_UNDO_CHANGED], 0); } void nemo_file_undo_manager_redo (GtkWindow *parent_window) { NemoFileUndoManager *self = get_singleton (); if (self->priv->state != NEMO_FILE_UNDO_MANAGER_STATE_REDO) { g_warning ("Called redo, but state is %s!", self->priv->state == 0 ? "none" : "undo"); return; } do_undo_redo (self, parent_window); } void nemo_file_undo_manager_undo (GtkWindow *parent_window) { NemoFileUndoManager *self = get_singleton (); if (self->priv->state != NEMO_FILE_UNDO_MANAGER_STATE_UNDO) { g_warning ("Called undo, but state is %s!", self->priv->state == 0 ? "none" : "redo"); return; } do_undo_redo (self, parent_window); } void nemo_file_undo_manager_set_action (NemoFileUndoInfo *info) { NemoFileUndoManager *self = get_singleton (); DEBUG ("Setting undo information %p", info); file_undo_manager_clear (self); if (info != NULL) { self->priv->info = g_object_ref (info); self->priv->state = NEMO_FILE_UNDO_MANAGER_STATE_UNDO; self->priv->last_state = NEMO_FILE_UNDO_MANAGER_STATE_NONE; } g_signal_emit (self, signals[SIGNAL_UNDO_CHANGED], 0); } NemoFileUndoInfo * nemo_file_undo_manager_get_action (void) { NemoFileUndoManager *self = get_singleton (); return self->priv->info; } NemoFileUndoManagerState nemo_file_undo_manager_get_state (void) { NemoFileUndoManager *self = get_singleton (); return self->priv->state; } void nemo_file_undo_manager_push_flag () { NemoFileUndoManager *self = get_singleton (); NemoFileUndoManagerPrivate *priv = self->priv; priv->undo_redo_flag = TRUE; } gboolean nemo_file_undo_manager_pop_flag () { NemoFileUndoManager *self = get_singleton (); NemoFileUndoManagerPrivate *priv = self->priv; gboolean retval = FALSE; if (priv->undo_redo_flag) { retval = TRUE; } priv->undo_redo_flag = FALSE; return retval; } NemoFileUndoManager * nemo_file_undo_manager_get () { return get_singleton (); } nemo-3.6.5/libnemo-private/nemo-column-chooser.c0000664000175000017500000004114513215733314020550 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-column-chooser.h - A column chooser widget Copyright (C) 2004 Novell, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the column COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Dave Camp */ #include #include "nemo-column-chooser.h" #include #include #include #include "nemo-column-utilities.h" struct _NemoColumnChooserDetails { GtkTreeView *view; GtkListStore *store; GtkWidget *move_up_button; GtkWidget *move_down_button; GtkWidget *use_default_button; NemoFile *file; }; enum { COLUMN_VISIBLE, COLUMN_LABEL, COLUMN_NAME, COLUMN_TOGGLE_SENSITIVE, NUM_COLUMNS }; enum { PROP_FILE = 1, NUM_PROPERTIES }; enum { CHANGED, USE_DEFAULT, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE(NemoColumnChooser, nemo_column_chooser, GTK_TYPE_BOX); static void nemo_column_chooser_constructed (GObject *object); static void nemo_column_chooser_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { NemoColumnChooser *chooser; chooser = NEMO_COLUMN_CHOOSER (object); switch (param_id) { case PROP_FILE: chooser->details->file = g_value_get_object (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void nemo_column_chooser_class_init (NemoColumnChooserClass *chooser_class) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (chooser_class); oclass->set_property = nemo_column_chooser_set_property; oclass->constructed = nemo_column_chooser_constructed; signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (chooser_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoColumnChooserClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[USE_DEFAULT] = g_signal_new ("use_default", G_TYPE_FROM_CLASS (chooser_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoColumnChooserClass, use_default), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_object_class_install_property (oclass, PROP_FILE, g_param_spec_object ("file", "File", "The file this column chooser is for", NEMO_TYPE_FILE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE)); g_type_class_add_private (chooser_class, sizeof (NemoColumnChooserDetails)); } static void update_buttons (NemoColumnChooser *chooser) { GtkTreeSelection *selection; GtkTreeIter iter; selection = gtk_tree_view_get_selection (chooser->details->view); if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { gboolean visible; gboolean top; gboolean bottom; GtkTreePath *first; GtkTreePath *path; gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store), &iter, COLUMN_VISIBLE, &visible, -1); path = gtk_tree_model_get_path (GTK_TREE_MODEL (chooser->details->store), &iter); first = gtk_tree_path_new_first (); top = (gtk_tree_path_compare (path, first) == 0); gtk_tree_path_free (path); gtk_tree_path_free (first); bottom = !gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &iter); gtk_widget_set_sensitive (chooser->details->move_up_button, !top); gtk_widget_set_sensitive (chooser->details->move_down_button, !bottom); } else { gtk_widget_set_sensitive (chooser->details->move_up_button, FALSE); gtk_widget_set_sensitive (chooser->details->move_down_button, FALSE); } } static void list_changed (NemoColumnChooser *chooser) { update_buttons (chooser); g_signal_emit (chooser, signals[CHANGED], 0); } static void visible_toggled_callback (GtkCellRendererToggle *cell, char *path_string, gpointer user_data) { NemoColumnChooser *chooser; GtkTreePath *path; GtkTreeIter iter; gboolean visible; chooser = NEMO_COLUMN_CHOOSER (user_data); path = gtk_tree_path_new_from_string (path_string); gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store), &iter, path); gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store), &iter, COLUMN_VISIBLE, &visible, -1); gtk_list_store_set (chooser->details->store, &iter, COLUMN_VISIBLE, !visible, -1); gtk_tree_path_free (path); list_changed (chooser); } static void selection_changed_callback (GtkTreeSelection *selection, gpointer user_data) { update_buttons (NEMO_COLUMN_CHOOSER (user_data)); } static void row_deleted_callback (GtkTreeModel *model, GtkTreePath *path, gpointer user_data) { list_changed (NEMO_COLUMN_CHOOSER (user_data)); } static void add_tree_view (NemoColumnChooser *chooser) { GtkWidget *scrolled; GtkWidget *view; GtkListStore *store; GtkCellRenderer *cell; GtkTreeSelection *selection; view = gtk_tree_view_new (); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN); gtk_tree_view_set_model (GTK_TREE_VIEW (view), GTK_TREE_MODEL (store)); g_object_unref (store); gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); g_signal_connect (selection, "changed", G_CALLBACK (selection_changed_callback), chooser); cell = gtk_cell_renderer_toggle_new (); g_signal_connect (G_OBJECT (cell), "toggled", G_CALLBACK (visible_toggled_callback), chooser); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), -1, NULL, cell, "active", COLUMN_VISIBLE, "sensitive", COLUMN_TOGGLE_SENSITIVE, NULL); cell = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (view), -1, NULL, cell, "text", COLUMN_LABEL, NULL); chooser->details->view = GTK_TREE_VIEW (view); chooser->details->store = store; gtk_widget_show (view); scrolled = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_IN); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_widget_show (GTK_WIDGET (scrolled)); gtk_container_add (GTK_CONTAINER (scrolled), view); gtk_box_pack_start (GTK_BOX (chooser), scrolled, TRUE, TRUE, 0); } static void move_up_clicked_callback (GtkWidget *button, gpointer user_data) { NemoColumnChooser *chooser; GtkTreeIter iter; GtkTreeSelection *selection; chooser = NEMO_COLUMN_CHOOSER (user_data); selection = gtk_tree_view_get_selection (chooser->details->view); if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { GtkTreePath *path; GtkTreeIter prev; path = gtk_tree_model_get_path (GTK_TREE_MODEL (chooser->details->store), &iter); gtk_tree_path_prev (path); if (gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store), &prev, path)) { gtk_list_store_move_before (chooser->details->store, &iter, &prev); } gtk_tree_path_free (path); } list_changed (chooser); } static void move_down_clicked_callback (GtkWidget *button, gpointer user_data) { NemoColumnChooser *chooser; GtkTreeIter iter; GtkTreeSelection *selection; chooser = NEMO_COLUMN_CHOOSER (user_data); selection = gtk_tree_view_get_selection (chooser->details->view); if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { GtkTreeIter next; next = iter; if (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &next)) { gtk_list_store_move_after (chooser->details->store, &iter, &next); } } list_changed (chooser); } static void use_default_clicked_callback (GtkWidget *button, gpointer user_data) { g_signal_emit (NEMO_COLUMN_CHOOSER (user_data), signals[USE_DEFAULT], 0); } static GtkWidget * button_new_with_mnemonic (const gchar *stockid, const gchar *str) { GtkWidget *image; GtkWidget *button; button = gtk_button_new_with_mnemonic (str); image = gtk_image_new_from_stock (stockid, GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); return button; } static void add_buttons (NemoColumnChooser *chooser) { GtkWidget *box; GtkWidget *separator; box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); gtk_widget_show (box); chooser->details->move_up_button = button_new_with_mnemonic (GTK_STOCK_GO_UP, _("Move _Up")); g_signal_connect (chooser->details->move_up_button, "clicked", G_CALLBACK (move_up_clicked_callback), chooser); gtk_widget_show_all (chooser->details->move_up_button); gtk_widget_set_sensitive (chooser->details->move_up_button, FALSE); gtk_box_pack_start (GTK_BOX (box), chooser->details->move_up_button, FALSE, FALSE, 0); chooser->details->move_down_button = button_new_with_mnemonic (GTK_STOCK_GO_DOWN, _("Move Dow_n")); g_signal_connect (chooser->details->move_down_button, "clicked", G_CALLBACK (move_down_clicked_callback), chooser); gtk_widget_show_all (chooser->details->move_down_button); gtk_widget_set_sensitive (chooser->details->move_down_button, FALSE); gtk_box_pack_start (GTK_BOX (box), chooser->details->move_down_button, FALSE, FALSE, 0); separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL); gtk_widget_show (separator); gtk_box_pack_start (GTK_BOX (box), separator, FALSE, FALSE, 0); chooser->details->use_default_button = gtk_button_new_with_mnemonic (_("Use De_fault")); g_signal_connect (chooser->details->use_default_button, "clicked", G_CALLBACK (use_default_clicked_callback), chooser); gtk_widget_show (chooser->details->use_default_button); gtk_box_pack_start (GTK_BOX (box), chooser->details->use_default_button, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (chooser), box, FALSE, FALSE, 0); } static void populate_tree (NemoColumnChooser *chooser) { GList *columns; GList *l; columns = nemo_get_columns_for_file (chooser->details->file); for (l = columns; l != NULL; l = l->next) { GtkTreeIter iter; NemoColumn *column; char *name; char *label; column = NEMO_COLUMN (l->data); g_object_get (G_OBJECT (column), "name", &name, "label", &label, NULL); gtk_list_store_append (chooser->details->store, &iter); gtk_list_store_set (chooser->details->store, &iter, COLUMN_VISIBLE, FALSE, COLUMN_LABEL, label, COLUMN_NAME, name, COLUMN_TOGGLE_SENSITIVE, g_strcmp0 (name, "name") != 0, -1); g_free (name); g_free (label); } nemo_column_list_free (columns); } static void nemo_column_chooser_constructed (GObject *object) { NemoColumnChooser *chooser; chooser = NEMO_COLUMN_CHOOSER (object); populate_tree (chooser); g_signal_connect (chooser->details->store, "row_deleted", G_CALLBACK (row_deleted_callback), chooser); } static void nemo_column_chooser_init (NemoColumnChooser *chooser) { chooser->details = G_TYPE_INSTANCE_GET_PRIVATE ((chooser), NEMO_TYPE_COLUMN_CHOOSER, NemoColumnChooserDetails); g_object_set (G_OBJECT (chooser), "homogeneous", FALSE, "spacing", 8, "orientation", GTK_ORIENTATION_HORIZONTAL, NULL); add_tree_view (chooser); add_buttons (chooser); } static void set_visible_columns (NemoColumnChooser *chooser, char **visible_columns) { GHashTable *visible_columns_hash; GtkTreeIter iter; int i; visible_columns_hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; visible_columns[i] != NULL; ++i) { g_hash_table_insert (visible_columns_hash, visible_columns[i], visible_columns[i]); } if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store), &iter)) { do { char *name; gboolean visible; gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store), &iter, COLUMN_NAME, &name, -1); visible = (g_hash_table_lookup (visible_columns_hash, name) != NULL); gtk_list_store_set (chooser->details->store, &iter, COLUMN_VISIBLE, visible, -1); g_free (name); } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &iter)); } g_hash_table_destroy (visible_columns_hash); } static char ** get_column_names (NemoColumnChooser *chooser, gboolean only_visible) { GPtrArray *ret; GtkTreeIter iter; ret = g_ptr_array_new (); if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store), &iter)) { do { char *name; gboolean visible; gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store), &iter, COLUMN_VISIBLE, &visible, COLUMN_NAME, &name, -1); if (!only_visible || visible) { /* give ownership to the array */ g_ptr_array_add (ret, name); } } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), &iter)); } g_ptr_array_add (ret, NULL); return (char **) g_ptr_array_free (ret, FALSE); } static gboolean get_column_iter (NemoColumnChooser *chooser, NemoColumn *column, GtkTreeIter *iter) { char *column_name; g_object_get (NEMO_COLUMN (column), "name", &column_name, NULL); if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (chooser->details->store), iter)) { do { char *name; gtk_tree_model_get (GTK_TREE_MODEL (chooser->details->store), iter, COLUMN_NAME, &name, -1); if (!strcmp (name, column_name)) { g_free (column_name); g_free (name); return TRUE; } g_free (name); } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (chooser->details->store), iter)); } g_free (column_name); return FALSE; } static void set_column_order (NemoColumnChooser *chooser, char **column_order) { GList *columns; GList *l; GtkTreePath *path; columns = nemo_get_columns_for_file (chooser->details->file); columns = nemo_sort_columns (columns, column_order); g_signal_handlers_block_by_func (chooser->details->store, G_CALLBACK (row_deleted_callback), chooser); path = gtk_tree_path_new_first (); for (l = columns; l != NULL; l = l->next) { GtkTreeIter iter; if (get_column_iter (chooser, NEMO_COLUMN (l->data), &iter)) { GtkTreeIter before; if (path) { gtk_tree_model_get_iter (GTK_TREE_MODEL (chooser->details->store), &before, path); gtk_list_store_move_after (chooser->details->store, &iter, &before); gtk_tree_path_next (path); } else { gtk_list_store_move_after (chooser->details->store, &iter, NULL); } } } gtk_tree_path_free (path); g_signal_handlers_unblock_by_func (chooser->details->store, G_CALLBACK (row_deleted_callback), chooser); nemo_column_list_free (columns); } void nemo_column_chooser_set_settings (NemoColumnChooser *chooser, char **visible_columns, char **column_order) { g_return_if_fail (NEMO_IS_COLUMN_CHOOSER (chooser)); g_return_if_fail (visible_columns != NULL); g_return_if_fail (column_order != NULL); set_visible_columns (chooser, visible_columns); set_column_order (chooser, column_order); list_changed (chooser); } void nemo_column_chooser_get_settings (NemoColumnChooser *chooser, char ***visible_columns, char ***column_order) { g_return_if_fail (NEMO_IS_COLUMN_CHOOSER (chooser)); g_return_if_fail (visible_columns != NULL); g_return_if_fail (column_order != NULL); *visible_columns = get_column_names (chooser, TRUE); *column_order = get_column_names (chooser, FALSE); } GtkWidget * nemo_column_chooser_new (NemoFile *file) { return g_object_new (NEMO_TYPE_COLUMN_CHOOSER, "file", file, NULL); } nemo-3.6.5/libnemo-private/nemo-context-menu-menu-item.c0000664000175000017500000003722713215733314022145 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include #include "nemo-global-preferences.h" #include "nemo-context-menu-menu-item.h" #include "nemo-widget-action.h" #include static GtkActivatableIface *parent_activatable_iface; static void nemo_context_menu_menu_item_dispose (GObject *object); static gboolean nemo_context_menu_menu_item_enter (GtkWidget *widget, GdkEventCrossing *event); static gboolean nemo_context_menu_menu_item_leave (GtkWidget *widget, GdkEventCrossing *event); static gboolean nemo_context_menu_menu_item_motion (GtkWidget *widget, GdkEventMotion *event); static gboolean nemo_context_menu_menu_item_button_press (GtkWidget *widget, GdkEventButton *event); static gboolean nemo_context_menu_menu_item_button_release (GtkWidget *widget, GdkEventButton *event); static void nemo_context_menu_menu_item_set_label (GtkMenuItem *menu_item, const gchar *label); static void nemo_context_menu_menu_item_activatable_interface_init (GtkActivatableIface *iface); G_DEFINE_TYPE_WITH_CODE (NemoContextMenuMenuItem, nemo_context_menu_menu_item, GTK_TYPE_IMAGE_MENU_ITEM, G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, nemo_context_menu_menu_item_activatable_interface_init)); static void set_action_image_temporary_visibility (NemoContextMenuMenuItem *item, gboolean visible) { GtkWidget *image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (item)); if (!visible) { gtk_widget_set_visible (image, FALSE); } else { if (gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item))) { gtk_widget_set_visible (image, TRUE); } } } static void update_toggle_state (NemoContextMenuMenuItem *item, gboolean from_event, gboolean on_item) { gboolean complex_mode = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS); /* const */ gchar *tip_text = complex_mode ? _("Show fewer actions") : _("Show more actions"); gchar *markup = g_strdup_printf ("%s", tip_text); gtk_label_set_markup (GTK_LABEL (item->toggle_label_widget), markup); g_free (markup); if (item->on_toggle) { set_action_image_temporary_visibility (item, FALSE); gtk_stack_set_visible_child_name (GTK_STACK (item->stack), "toggle"); } else { set_action_image_temporary_visibility (item, TRUE); gtk_stack_set_visible_child_name (GTK_STACK (item->stack), "action"); } GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (item)); if (on_item) { gtk_image_set_from_icon_name (GTK_IMAGE (item->toggle_widget), complex_mode ? "collapse-menu-hover-symbolic" : "expand-menu-hover-symbolic", GTK_ICON_SIZE_MENU); } else { gtk_image_set_from_icon_name (GTK_IMAGE (item->toggle_widget), complex_mode ? "collapse-menu-symbolic" : "expand-menu-symbolic", GTK_ICON_SIZE_MENU); } GtkStateFlags default_item_state = from_event ? GTK_STATE_FLAG_PRELIGHT : gtk_style_context_get_state (context); gtk_style_context_set_state (context, item->on_toggle ? GTK_STATE_FLAG_NORMAL : default_item_state); gtk_widget_queue_draw (GTK_WIDGET (item)); } static void update_toggle_appearance_from_event (GtkWidget *widget, gint x, gint y, gboolean on_item) { NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget); GtkAllocation alloc; gtk_widget_get_allocation (item->toggle_widget, &alloc); item->on_toggle = ((x >= alloc.x) && (x <= alloc.x + alloc.width) && (y >= alloc.y) && (y <= alloc.y + alloc.height)); update_toggle_state (item, TRUE, on_item); } static void nemo_context_menu_menu_item_class_init (NemoContextMenuMenuItemClass *klass) { GObjectClass *gobject_class = (GObjectClass*) klass; GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass; GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gobject_class->dispose = nemo_context_menu_menu_item_dispose; menu_item_class->set_label = nemo_context_menu_menu_item_set_label; widget_class->enter_notify_event = nemo_context_menu_menu_item_enter; widget_class->leave_notify_event = nemo_context_menu_menu_item_leave; widget_class->motion_notify_event = nemo_context_menu_menu_item_motion; widget_class->button_press_event = nemo_context_menu_menu_item_button_press; widget_class->button_release_event = nemo_context_menu_menu_item_button_release; } static void nemo_context_menu_menu_item_init (NemoContextMenuMenuItem *item) { item->on_toggle = FALSE; GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); GtkWidget *stack = gtk_stack_new (); item->stack = stack; GtkWidget *label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.98, 0.5); gtk_stack_add_named (GTK_STACK (stack), label, "toggle"); item->toggle_label_widget = label; label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_stack_add_named (GTK_STACK (stack), label, "action"); item->label_widget = label; gtk_box_pack_start (GTK_BOX (box), stack, TRUE, TRUE, 0); GtkWidget *toggle = gtk_image_new (); gtk_box_pack_end (GTK_BOX (box), toggle, FALSE, FALSE, 0); item->toggle_widget = toggle; gtk_widget_show_all (box); gtk_container_add (GTK_CONTAINER (item), box); update_toggle_state (item, FALSE, FALSE); item->settings_monitor_id = g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS, G_CALLBACK (update_toggle_state), item); } static void nemo_context_menu_menu_item_dispose (GObject *object) { NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (object); if (item->settings_monitor_id > 0) { g_signal_handler_disconnect (nemo_preferences, item->settings_monitor_id); item->settings_monitor_id = 0; } G_OBJECT_CLASS (nemo_context_menu_menu_item_parent_class)->dispose (object); } static gboolean nemo_context_menu_menu_item_enter (GtkWidget *widget, GdkEventCrossing *event) { g_return_val_if_fail (event != NULL, FALSE); update_toggle_appearance_from_event (widget, event->x, event->y, TRUE); return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event); } static gboolean nemo_context_menu_menu_item_leave (GtkWidget *widget, GdkEventCrossing *event) { g_return_val_if_fail (event != NULL, FALSE); update_toggle_appearance_from_event (widget, event->x, event->y, FALSE); return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event); } static gboolean nemo_context_menu_menu_item_motion (GtkWidget *widget, GdkEventMotion *event) { g_return_val_if_fail (event != NULL, FALSE); update_toggle_appearance_from_event (widget, event->x, event->y, TRUE); return gtk_widget_event (gtk_widget_get_parent (widget), (GdkEvent *) event); } static gboolean nemo_context_menu_menu_item_button_press (GtkWidget *widget, GdkEventButton *event) { NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget); if (event->button != GDK_BUTTON_PRIMARY) return GDK_EVENT_PROPAGATE; update_toggle_appearance_from_event (widget, event->x, event->y, TRUE); if (item->on_toggle) { g_settings_set_boolean (nemo_preferences, NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS, !g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS)); return GDK_EVENT_STOP; } return GDK_EVENT_PROPAGATE; } static gboolean nemo_context_menu_menu_item_button_release (GtkWidget *widget, GdkEventButton *event) { NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (widget); if (event->button != GDK_BUTTON_PRIMARY && event->button != GDK_BUTTON_SECONDARY) return GDK_EVENT_PROPAGATE; update_toggle_appearance_from_event (widget, event->x, event->y, TRUE); if (item->on_toggle) { return GDK_EVENT_STOP; } return GDK_EVENT_PROPAGATE; } static void nemo_context_menu_menu_item_set_label (GtkMenuItem *menu_item, const gchar *label) { NemoContextMenuMenuItem *item = NEMO_CONTEXT_MENU_MENU_ITEM (menu_item); if (item->label != label) { g_free (item->label); item->label = g_strdup (label); gtk_label_set_text_with_mnemonic (GTK_LABEL (item->label_widget), label); g_object_notify (G_OBJECT (menu_item), "label"); } } static gboolean activatable_update_stock_id (GtkImageMenuItem *image_menu_item, GtkAction *action) { GtkWidget *image; const gchar *stock_id = gtk_action_get_stock_id (action); image = gtk_image_menu_item_get_image (image_menu_item); if (GTK_IS_IMAGE (image) && stock_id && gtk_icon_factory_lookup_default (stock_id)) { gtk_image_set_from_stock (GTK_IMAGE (image), stock_id, GTK_ICON_SIZE_MENU); return TRUE; } return FALSE; } static gboolean activatable_update_gicon (GtkImageMenuItem *image_menu_item, GtkAction *action) { GtkWidget *image; GIcon *icon = gtk_action_get_gicon (action); const gchar *stock_id; gboolean ret = FALSE; stock_id = gtk_action_get_stock_id (action); image = gtk_image_menu_item_get_image (image_menu_item); if (icon && GTK_IS_IMAGE (image) && !(stock_id && gtk_icon_factory_lookup_default (stock_id))) { gtk_image_set_from_gicon (GTK_IMAGE (image), icon, GTK_ICON_SIZE_MENU); ret = TRUE; } return ret; } static void activatable_update_icon_name (GtkImageMenuItem *image_menu_item, GtkAction *action) { GtkWidget *image; const gchar *icon_name = gtk_action_get_icon_name (action); image = gtk_image_menu_item_get_image (image_menu_item); if (GTK_IS_IMAGE (image) && (gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_EMPTY || gtk_image_get_storage_type (GTK_IMAGE (image)) == GTK_IMAGE_ICON_NAME)) { gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, GTK_ICON_SIZE_MENU); } } static void activatable_update_label (GtkMenuItem *menu_item, GtkAction *action) { const gchar *label; label = gtk_action_get_label (action); nemo_context_menu_menu_item_set_label (menu_item, label); } static void nemo_context_menu_menu_item_update (GtkActivatable *activatable, GtkAction *action, const gchar *property_name) { if (!gtk_activatable_get_use_action_appearance (activatable)) return; if (strcmp (property_name, "label") == 0) activatable_update_label (GTK_MENU_ITEM (activatable), action); else if (strcmp (property_name, "stock-id") == 0) activatable_update_stock_id (GTK_IMAGE_MENU_ITEM (activatable), action); else if (strcmp (property_name, "gicon") == 0) activatable_update_gicon (GTK_IMAGE_MENU_ITEM (activatable), action); else if (strcmp (property_name, "icon-name") == 0) activatable_update_icon_name (GTK_IMAGE_MENU_ITEM (activatable), action); } static void menu_item_sync_action_properties (NemoContextMenuMenuItem *menu_item, GtkAction *action) { GtkImageMenuItem *image_menu_item; GtkActivatable *activatable; GtkWidget *image; gboolean use_appearance; image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item); activatable = GTK_ACTIVATABLE (image_menu_item); if (!action) return; use_appearance = gtk_activatable_get_use_action_appearance (activatable); if (!use_appearance) return; image = gtk_image_menu_item_get_image (image_menu_item); if (image && !GTK_IS_IMAGE (image)) { gtk_image_menu_item_set_image (image_menu_item, NULL); image = NULL; } if (!image) { image = gtk_image_new (); gtk_widget_show (image); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (activatable), image); } if (!activatable_update_stock_id (image_menu_item, action) && !activatable_update_gicon (image_menu_item, action)) activatable_update_icon_name (image_menu_item, action); gtk_image_menu_item_set_always_show_image (image_menu_item, gtk_action_get_always_show_image (action)); activatable_update_label (GTK_MENU_ITEM (menu_item), action); } static void nemo_context_menu_menu_item_sync_action_properties (GtkActivatable *activatable, GtkAction *action) { NemoContextMenuMenuItem *context_menu_menu_item; context_menu_menu_item = NEMO_CONTEXT_MENU_MENU_ITEM (activatable); if (!action) return; if (!gtk_activatable_get_use_action_appearance (activatable)) return; menu_item_sync_action_properties (context_menu_menu_item, action); gtk_widget_show (GTK_WIDGET (context_menu_menu_item)); } static void nemo_context_menu_menu_item_activatable_interface_init (GtkActivatableIface *iface) { parent_activatable_iface = g_type_interface_peek_parent (iface); iface->update = nemo_context_menu_menu_item_update; iface->sync_action_properties = nemo_context_menu_menu_item_sync_action_properties; } /** * nemo_context_menu_menu_item_new: * @widget: The custom widget to use * * Creates a new #NemoContextMenuMenuItem. * * Returns: a new #NemoContextMenuMenuItem. */ GtkWidget * nemo_context_menu_menu_item_new (GtkWidget *widget) { return g_object_new (NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NULL); } nemo-3.6.5/libnemo-private/nemo-file-conflict-dialog.h0000664000175000017500000000536713215733314021601 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-conflict-dialog: dialog that handles file conflicts during transfer operations. Copyright (C) 2008, Cosimo Cecchi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Cosimo Cecchi */ #ifndef NEMO_FILE_CONFLICT_DIALOG_H #define NEMO_FILE_CONFLICT_DIALOG_H #include #include #include #define NEMO_TYPE_FILE_CONFLICT_DIALOG \ (nemo_file_conflict_dialog_get_type ()) #define NEMO_FILE_CONFLICT_DIALOG(o) \ (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_CONFLICT_DIALOG,\ NemoFileConflictDialog)) #define NEMO_FILE_CONFLICT_DIALOG_CLASS(k) \ (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_CONFLICT_DIALOG,\ NemoFileConflictDialogClass)) #define NEMO_IS_FILE_CONFLICT_DIALOG(o) \ (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_CONFLICT_DIALOG)) #define NEMO_IS_FILE_CONFLICT_DIALOG_CLASS(k) \ (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_CONFLICT_DIALOG)) #define NEMO_FILE_CONFLICT_DIALOG_GET_CLASS(o) \ (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_CONFLICT_DIALOG,\ NemoFileConflictDialogClass)) typedef struct _NemoFileConflictDialog NemoFileConflictDialog; typedef struct _NemoFileConflictDialogClass NemoFileConflictDialogClass; typedef struct _NemoFileConflictDialogDetails NemoFileConflictDialogDetails; struct _NemoFileConflictDialog { GtkDialog parent; NemoFileConflictDialogDetails *details; }; struct _NemoFileConflictDialogClass { GtkDialogClass parent_class; }; enum { CONFLICT_RESPONSE_SKIP = 1, CONFLICT_RESPONSE_REPLACE = 2, CONFLICT_RESPONSE_RENAME = 3, }; GType nemo_file_conflict_dialog_get_type (void) G_GNUC_CONST; GtkWidget* nemo_file_conflict_dialog_new (GtkWindow *parent, GFile *source, GFile *destination, GFile *dest_dir); char* nemo_file_conflict_dialog_get_new_name (NemoFileConflictDialog *dialog); gboolean nemo_file_conflict_dialog_get_apply_to_all (NemoFileConflictDialog *dialog); #endif /* NEMO_FILE_CONFLICT_DIALOG_H */ nemo-3.6.5/libnemo-private/nemo-widget-action.h0000664000175000017500000000553613215733314020362 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_WIDGET_ACTION_H #define NEMO_WIDGET_ACTION_H #include #include #define NEMO_TYPE_WIDGET_ACTION nemo_widget_action_get_type() #define NEMO_WIDGET_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_WIDGET_ACTION, NemoWidgetAction)) #define NEMO_WIDGET_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_WIDGET_ACTION, NemoWidgetActionClass)) #define NEMO_IS_WIDGET_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_WIDGET_ACTION)) #define NEMO_IS_WIDGET_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_WIDGET_ACTION)) #define NEMO_WIDGET_ACTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_WIDGET_ACTION, NemoWidgetActionClass)) typedef struct _NemoWidgetAction NemoWidgetAction; typedef struct _NemoWidgetActionClass NemoWidgetActionClass; struct _NemoWidgetAction { GtkAction parent; GtkWidget *widget_a; GtkWidget *widget_b; gboolean a_used; gboolean b_used; gboolean is_menu_toggle; }; struct _NemoWidgetActionClass { GtkActionClass parent_class; }; enum { ACTION_SLOT_A = 0, ACTION_SLOT_B }; GType nemo_widget_action_get_type (void); GtkAction *nemo_widget_action_new (const gchar *name, GtkWidget *widget_a, GtkWidget *widget_b); GtkAction *nemo_widget_action_new_for_menu_toggle (const gchar *name, const gchar *label, const gchar *tooltip); void nemo_widget_action_activate (NemoWidgetAction *action); GtkWidget * nemo_widget_action_get_widget_a (NemoWidgetAction *action); void nemo_widget_action_set_widget_a (NemoWidgetAction *action, GtkWidget *widget); GtkWidget * nemo_widget_action_get_widget_b (NemoWidgetAction *action); void nemo_widget_action_set_widget_b (NemoWidgetAction *action, GtkWidget *widget); #endif /* NEMO_WIDGET_ACTION_H */ nemo-3.6.5/libnemo-private/nemo-entry.c0000664000175000017500000002511313215733314016751 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoEntry: one-line text editing widget. This consists of bug fixes * and other improvements to GtkEntry, and all the changes could be rolled * into GtkEntry some day. * * Copyright (C) 2000 Eazel, Inc. * * Author: John Sullivan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include "nemo-entry.h" #include #include "nemo-global-preferences.h" #include "nemo-undo-signal-handlers.h" #include #include #include struct NemoEntryDetails { gboolean user_edit; gboolean special_tab_handling; guint select_idle_id; }; enum { USER_CHANGED, SELECTION_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void nemo_entry_editable_init (GtkEditableInterface *iface); G_DEFINE_TYPE_WITH_CODE (NemoEntry, nemo_entry, GTK_TYPE_ENTRY, G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, nemo_entry_editable_init)); static GtkEditableInterface *parent_editable_interface = NULL; static void nemo_entry_init (NemoEntry *entry) { entry->details = g_new0 (NemoEntryDetails, 1); entry->details->user_edit = TRUE; nemo_undo_set_up_nemo_entry_for_undo (entry); } GtkWidget * nemo_entry_new (void) { return gtk_widget_new (NEMO_TYPE_ENTRY, NULL); } GtkWidget * nemo_entry_new_with_max_length (guint16 max) { GtkWidget *widget; widget = gtk_widget_new (NEMO_TYPE_ENTRY, NULL); gtk_entry_set_max_length (GTK_ENTRY (widget), max); return widget; } static void nemo_entry_finalize (GObject *object) { NemoEntry *entry; entry = NEMO_ENTRY (object); if (entry->details->select_idle_id != 0) { g_source_remove (entry->details->select_idle_id); } g_free (entry->details); G_OBJECT_CLASS (nemo_entry_parent_class)->finalize (object); } static gboolean nemo_entry_key_press (GtkWidget *widget, GdkEventKey *event) { NemoEntry *entry; GtkEditable *editable; int position; gboolean old_has, new_has; gboolean result; entry = NEMO_ENTRY (widget); editable = GTK_EDITABLE (widget); if (!gtk_editable_get_editable (editable)) { return FALSE; } switch (event->keyval) { case GDK_KEY_Tab: /* The location bar entry wants TAB to work kind of * like it does in the shell for command completion, * so if we get a tab and there's a selection, we * should position the insertion point at the end of * the selection. */ if (entry->details->special_tab_handling && gtk_editable_get_selection_bounds (editable, NULL, NULL)) { position = strlen (gtk_entry_get_text (GTK_ENTRY (editable))); gtk_editable_select_region (editable, position, position); return TRUE; } break; default: break; } old_has = gtk_editable_get_selection_bounds (editable, NULL, NULL); result = GTK_WIDGET_CLASS (nemo_entry_parent_class)->key_press_event (widget, event); /* Pressing a key usually changes the selection if there is a selection. * If there is not selection, we can save work by not emitting a signal. */ if (result) { new_has = gtk_editable_get_selection_bounds (editable, NULL, NULL); if (old_has || new_has) { g_signal_emit (widget, signals[SELECTION_CHANGED], 0); } } return result; } static gboolean nemo_entry_motion_notify (GtkWidget *widget, GdkEventMotion *event) { int result; gboolean old_had, new_had; int old_start, old_end, new_start, new_end; GtkEditable *editable; editable = GTK_EDITABLE (widget); old_had = gtk_editable_get_selection_bounds (editable, &old_start, &old_end); result = GTK_WIDGET_CLASS (nemo_entry_parent_class)->motion_notify_event (widget, event); /* Send a signal if dragging the mouse caused the selection to change. */ if (result) { new_had = gtk_editable_get_selection_bounds (editable, &new_start, &new_end); if (old_had != new_had || (old_had && (old_start != new_start || old_end != new_end))) { g_signal_emit (widget, signals[SELECTION_CHANGED], 0); } } return result; } /** * nemo_entry_select_all * * Select all text, leaving the text cursor position at the end. * * @entry: A NemoEntry **/ void nemo_entry_select_all (NemoEntry *entry) { g_return_if_fail (NEMO_IS_ENTRY (entry)); gtk_editable_set_position (GTK_EDITABLE (entry), -1); gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1); } static gboolean select_all_at_idle (gpointer callback_data) { NemoEntry *entry; entry = NEMO_ENTRY (callback_data); nemo_entry_select_all (entry); entry->details->select_idle_id = 0; return FALSE; } /** * nemo_entry_select_all_at_idle * * Select all text at the next idle, not immediately. * This is useful when reacting to a key press, because * changing the selection and the text cursor position doesn't * work in a key_press signal handler. * * @entry: A NemoEntry **/ void nemo_entry_select_all_at_idle (NemoEntry *entry) { g_return_if_fail (NEMO_IS_ENTRY (entry)); /* If the text cursor position changes in this routine * then gtk_entry_key_press will unselect (and we want * to move the text cursor position to the end). */ if (entry->details->select_idle_id == 0) { entry->details->select_idle_id = g_idle_add (select_all_at_idle, entry); } } /** * nemo_entry_set_text * * This function wraps gtk_entry_set_text. It sets undo_registered * to TRUE and preserves the old value for a later restore. This is * done so the programmatic changes to the entry do not register * with the undo manager. * * @entry: A NemoEntry * @test: The text to set **/ void nemo_entry_set_text (NemoEntry *entry, const gchar *text) { g_return_if_fail (NEMO_IS_ENTRY (entry)); entry->details->user_edit = FALSE; gtk_entry_set_text (GTK_ENTRY (entry), text); entry->details->user_edit = TRUE; g_signal_emit (entry, signals[SELECTION_CHANGED], 0); } static void nemo_entry_set_selection_bounds (GtkEditable *editable, int start_pos, int end_pos) { parent_editable_interface->set_selection_bounds (editable, start_pos, end_pos); g_signal_emit (editable, signals[SELECTION_CHANGED], 0); } static gboolean nemo_entry_button_press (GtkWidget *widget, GdkEventButton *event) { gboolean result; result = GTK_WIDGET_CLASS (nemo_entry_parent_class)->button_press_event (widget, event); if (result) { g_signal_emit (widget, signals[SELECTION_CHANGED], 0); } return result; } static gboolean nemo_entry_button_release (GtkWidget *widget, GdkEventButton *event) { gboolean result; result = GTK_WIDGET_CLASS (nemo_entry_parent_class)->button_release_event (widget, event); if (result) { g_signal_emit (widget, signals[SELECTION_CHANGED], 0); } return result; } static void nemo_entry_insert_text (GtkEditable *editable, const gchar *text, int length, int *position) { NemoEntry *entry; entry = NEMO_ENTRY(editable); /* Fire off user changed signals */ if (entry->details->user_edit) { g_signal_emit (editable, signals[USER_CHANGED], 0); } parent_editable_interface->insert_text (editable, text, length, position); g_signal_emit (editable, signals[SELECTION_CHANGED], 0); } static void nemo_entry_delete_text (GtkEditable *editable, int start_pos, int end_pos) { NemoEntry *entry; entry = NEMO_ENTRY (editable); /* Fire off user changed signals */ if (entry->details->user_edit) { g_signal_emit (editable, signals[USER_CHANGED], 0); } parent_editable_interface->delete_text (editable, start_pos, end_pos); g_signal_emit (editable, signals[SELECTION_CHANGED], 0); } /* Overridden to work around GTK bug. The selection_clear_event is queued * when the selection changes. Changing the selection to NULL and then * back to the original selection owner still sends the event, so the * selection owner then gets the selection ripped away from it. We ran into * this with type-completion behavior in NemoLocationBar (see bug 5313). * There's a FIXME comment that seems to be about this same issue in * gtk+/gtkselection.c, gtk_selection_clear. */ static gboolean nemo_entry_selection_clear (GtkWidget *widget, GdkEventSelection *event) { g_assert (NEMO_IS_ENTRY (widget)); if (gdk_selection_owner_get (event->selection) == gtk_widget_get_window (widget)) { return FALSE; } return GTK_WIDGET_CLASS (nemo_entry_parent_class)->selection_clear_event (widget, event); } static void nemo_entry_editable_init (GtkEditableInterface *iface) { parent_editable_interface = g_type_interface_peek_parent (iface); iface->insert_text = nemo_entry_insert_text; iface->delete_text = nemo_entry_delete_text; iface->set_selection_bounds = nemo_entry_set_selection_bounds; /* Otherwise we might need some memcpy loving */ g_assert (iface->do_insert_text != NULL); g_assert (iface->get_position != NULL); g_assert (iface->get_chars != NULL); } static void nemo_entry_class_init (NemoEntryClass *class) { GtkWidgetClass *widget_class; GObjectClass *gobject_class; widget_class = GTK_WIDGET_CLASS (class); gobject_class = G_OBJECT_CLASS (class); widget_class->button_press_event = nemo_entry_button_press; widget_class->button_release_event = nemo_entry_button_release; widget_class->key_press_event = nemo_entry_key_press; widget_class->motion_notify_event = nemo_entry_motion_notify; widget_class->selection_clear_event = nemo_entry_selection_clear; gobject_class->finalize = nemo_entry_finalize; /* Set up signals */ signals[USER_CHANGED] = g_signal_new ("user_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoEntryClass, user_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoEntryClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } void nemo_entry_set_special_tab_handling (NemoEntry *entry, gboolean special_tab_handling) { g_return_if_fail (NEMO_IS_ENTRY (entry)); entry->details->special_tab_handling = special_tab_handling; } nemo-3.6.5/libnemo-private/nemo-icon-names.h0000664000175000017500000000240613215733314017646 0ustar fabiofabio#ifndef NEMO_ICON_NAMES_H #define NEMO_ICON_NAMES_H /* Icons for places */ #define NEMO_ICON_COMPUTER "computer" #define NEMO_ICON_DESKTOP "user-desktop" #define NEMO_ICON_FILESYSTEM "drive-harddisk" #define NEMO_ICON_FOLDER "folder" #define NEMO_ICON_FOLDER_REMOTE "folder-remote" #define NEMO_ICON_HOME "user-home" #define NEMO_ICON_NETWORK "network-workgroup" #define NEMO_ICON_NETWORK_SERVER "network-server" #define NEMO_ICON_SEARCH "system-search" #define NEMO_ICON_TRASH "user-trash" #define NEMO_ICON_TRASH_FULL "user-trash-full" #define NEMO_ICON_DELETE "edit-delete" #define NEMO_ICON_FOLDER_DESKTOP "user-desktop" #define NEMO_ICON_FOLDER_DOCUMENTS "folder-documents" #define NEMO_ICON_FOLDER_DOWNLOAD "folder-download" #define NEMO_ICON_FOLDER_MUSIC "folder-music" #define NEMO_ICON_FOLDER_PICTURES "folder-pictures" #define NEMO_ICON_FOLDER_PUBLIC_SHARE "folder-publicshare" #define NEMO_ICON_FOLDER_TEMPLATES "folder-templates" #define NEMO_ICON_FOLDER_VIDEOS "folder-videos" #define NEMO_ICON_FOLDER_SAVED_SEARCH "folder-saved-search" /* Other icons */ #define NEMO_ICON_TEMPLATE "text-x-generic-template" /* Icons not provided by fd.o naming spec or nemo itself */ #define NEMO_ICON_BURN "nemo-cd-burner" #endif /* NEMO_ICON_NAMES_H */ nemo-3.6.5/libnemo-private/nemo-search-directory-file.c0000664000175000017500000001475013215733314022001 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-search-directory-file.c: Subclass of NemoFile to help implement the searches Copyright (C) 2005 Novell, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Anders Carlsson */ #include #include "nemo-search-directory-file.h" #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include #include "nemo-search-directory.h" #include #include #include struct NemoSearchDirectoryFileDetails { NemoSearchDirectory *search_directory; }; G_DEFINE_TYPE(NemoSearchDirectoryFile, nemo_search_directory_file, NEMO_TYPE_FILE); static void search_directory_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes) { /* No need for monitoring, we always emit changed when files are added/removed, and no other metadata changes */ /* Update display name, in case this didn't happen yet */ nemo_search_directory_file_update_display_name (NEMO_SEARCH_DIRECTORY_FILE (file)); } static void search_directory_file_monitor_remove (NemoFile *file, gconstpointer client) { /* Do nothing here, we don't have any monitors */ } static void search_directory_file_call_when_ready (NemoFile *file, NemoFileAttributes file_attributes, NemoFileCallback callback, gpointer callback_data) { /* Update display name, in case this didn't happen yet */ nemo_search_directory_file_update_display_name (NEMO_SEARCH_DIRECTORY_FILE (file)); /* All data for directory-as-file is always uptodate */ (* callback) (file, callback_data); } static void search_directory_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data) { /* Do nothing here, we don't have any pending calls */ } static gboolean search_directory_file_check_if_ready (NemoFile *file, NemoFileAttributes attributes) { return TRUE; } static gboolean search_directory_file_get_item_count (NemoFile *file, guint *count, gboolean *count_unreadable) { GList *file_list; if (count) { file_list = nemo_directory_get_file_list (file->details->directory); *count = g_list_length (file_list); nemo_file_list_free (file_list); } return TRUE; } static NemoRequestStatus search_directory_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size) { NemoFile *dir_file; GList *file_list, *l; guint dirs, files; GFileType type; file_list = nemo_directory_get_file_list (file->details->directory); dirs = files = 0; for (l = file_list; l != NULL; l = l->next) { dir_file = NEMO_FILE (l->data); type = nemo_file_get_file_type (dir_file); if (type == G_FILE_TYPE_DIRECTORY) { dirs++; } else { files++; } } if (directory_count != NULL) { *directory_count = dirs; } if (file_count != NULL) { *file_count = files; } if (unreadable_directory_count != NULL) { *unreadable_directory_count = 0; } if (total_size != NULL) { /* FIXME: Maybe we want to calculate this? */ *total_size = 0; } if (hidden_count != NULL) { *hidden_count = 0; } nemo_file_list_free (file_list); return NEMO_REQUEST_DONE; } static char * search_directory_file_get_where_string (NemoFile *file) { return g_strdup (_("Search")); } void nemo_search_directory_file_update_display_name (NemoSearchDirectoryFile *search_file) { NemoFile *file; NemoSearchDirectory *search_dir; NemoQuery *query; char *display_name; gboolean changed; display_name = NULL; file = NEMO_FILE (search_file); if (file->details->directory) { search_dir = NEMO_SEARCH_DIRECTORY (file->details->directory); query = nemo_search_directory_get_query (search_dir); if (query != NULL) { display_name = nemo_query_to_readable_string (query); g_object_unref (query); } } if (display_name == NULL) { display_name = g_strdup (_("Search")); } changed = nemo_file_set_display_name (file, display_name, NULL, TRUE); if (changed) { nemo_file_emit_changed (file); } g_free (display_name); } static void nemo_search_directory_file_init (NemoSearchDirectoryFile *search_file) { NemoFile *file; file = NEMO_FILE (search_file); file->details->got_file_info = TRUE; file->details->mime_type = eel_ref_str_get_unique ("x-directory/normal"); file->details->type = G_FILE_TYPE_DIRECTORY; file->details->size = 0; file->details->file_info_is_up_to_date = TRUE; file->details->custom_icon = NULL; file->details->activation_uri = NULL; file->details->got_link_info = TRUE; file->details->link_info_is_up_to_date = TRUE; file->details->directory_count = 0; file->details->got_directory_count = TRUE; file->details->directory_count_is_up_to_date = TRUE; nemo_file_set_display_name (file, _("Search"), NULL, TRUE); } static void nemo_search_directory_file_class_init (NemoSearchDirectoryFileClass *klass) { NemoFileClass *file_class; file_class = NEMO_FILE_CLASS (klass); file_class->default_file_type = G_FILE_TYPE_DIRECTORY; file_class->monitor_add = search_directory_file_monitor_add; file_class->monitor_remove = search_directory_file_monitor_remove; file_class->call_when_ready = search_directory_file_call_when_ready; file_class->cancel_call_when_ready = search_directory_file_cancel_call_when_ready; file_class->check_if_ready = search_directory_file_check_if_ready; file_class->get_item_count = search_directory_file_get_item_count; file_class->get_deep_counts = search_directory_file_get_deep_counts; file_class->get_where_string = search_directory_file_get_where_string; } nemo-3.6.5/libnemo-private/nemo-clipboard-monitor.c0000664000175000017500000002040013215733314021226 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-clipboard-monitor.c: catch clipboard changes. Copyright (C) 2004 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-clipboard-monitor.h" #include "nemo-file.h" #include #include /* X11 has a weakness when it comes to clipboard handling, * there is no way to get told when the owner of the clipboard * changes. This is often needed, for instance to set the * sensitivity of the paste menu item. We work around this * internally in an app by telling the clipboard monitor when * we changed the clipboard. Unfortunately this doesn't give * us perfect results, we still don't catch changes made by * other clients * * This is fixed with the XFIXES extensions, which recent versions * of Gtk+ supports as the owner_change signal on GtkClipboard. We * use this now, but keep the old code since not all X servers support * XFIXES. */ enum { CLIPBOARD_CHANGED, CLIPBOARD_INFO, LAST_SIGNAL }; struct NemoClipboardMonitorDetails { NemoClipboardInfo *info; }; static guint signals[LAST_SIGNAL] = { 0 }; static GdkAtom copied_files_atom; G_DEFINE_TYPE (NemoClipboardMonitor, nemo_clipboard_monitor, G_TYPE_OBJECT); static NemoClipboardMonitor *clipboard_monitor = NULL; static void destroy_clipboard_monitor (void) { if (clipboard_monitor != NULL) { g_object_unref (clipboard_monitor); } } NemoClipboardMonitor * nemo_clipboard_monitor_get (void) { GtkClipboard *clipboard; if (clipboard_monitor == NULL) { clipboard_monitor = NEMO_CLIPBOARD_MONITOR (g_object_new (NEMO_TYPE_CLIPBOARD_MONITOR, NULL)); eel_debug_call_at_shutdown (destroy_clipboard_monitor); clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); g_signal_connect (clipboard, "owner_change", G_CALLBACK (nemo_clipboard_monitor_emit_changed), NULL); } return clipboard_monitor; } void nemo_clipboard_monitor_emit_changed (void) { NemoClipboardMonitor *monitor; monitor = nemo_clipboard_monitor_get (); g_signal_emit (monitor, signals[CLIPBOARD_CHANGED], 0); } static NemoClipboardInfo * nemo_clipboard_info_new (GList *files, gboolean cut) { NemoClipboardInfo *info; info = g_slice_new0 (NemoClipboardInfo); info->files = nemo_file_list_copy (files); info->cut = cut; return info; } static NemoClipboardInfo * nemo_clipboard_info_copy (NemoClipboardInfo *info) { NemoClipboardInfo *new_info; new_info = NULL; if (info != NULL) { new_info = nemo_clipboard_info_new (info->files, info->cut); } return new_info; } static void nemo_clipboard_info_free (NemoClipboardInfo *info) { nemo_file_list_free (info->files); g_slice_free (NemoClipboardInfo, info); } static void nemo_clipboard_monitor_init (NemoClipboardMonitor *monitor) { monitor->details = G_TYPE_INSTANCE_GET_PRIVATE (monitor, NEMO_TYPE_CLIPBOARD_MONITOR, NemoClipboardMonitorDetails); } static void clipboard_monitor_finalize (GObject *object) { NemoClipboardMonitor *monitor; monitor = NEMO_CLIPBOARD_MONITOR (object); if (monitor->details->info != NULL) { nemo_clipboard_info_free (monitor->details->info); monitor->details->info = NULL; } G_OBJECT_CLASS (nemo_clipboard_monitor_parent_class)->finalize (object); } static void nemo_clipboard_monitor_class_init (NemoClipboardMonitorClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = clipboard_monitor_finalize; copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE); signals[CLIPBOARD_CHANGED] = g_signal_new ("clipboard_changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoClipboardMonitorClass, clipboard_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[CLIPBOARD_INFO] = g_signal_new ("clipboard_info", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoClipboardMonitorClass, clipboard_info), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); g_type_class_add_private (klass, sizeof (NemoClipboardMonitorDetails)); } void nemo_clipboard_monitor_set_clipboard_info (NemoClipboardMonitor *monitor, NemoClipboardInfo *info) { if (monitor->details->info != NULL) { nemo_clipboard_info_free (monitor->details->info); monitor->details->info = NULL; } monitor->details->info = nemo_clipboard_info_copy (info); g_signal_emit (monitor, signals[CLIPBOARD_INFO], 0, monitor->details->info); nemo_clipboard_monitor_emit_changed (); } NemoClipboardInfo * nemo_clipboard_monitor_get_clipboard_info (NemoClipboardMonitor *monitor) { return monitor->details->info; } void nemo_clear_clipboard_callback (GtkClipboard *clipboard, gpointer user_data) { nemo_clipboard_monitor_set_clipboard_info (nemo_clipboard_monitor_get (), NULL); } static char * convert_file_list_to_string (NemoClipboardInfo *info, gboolean format_for_text, gsize *len) { GString *uris; char *uri, *tmp; GFile *f; guint i; GList *l; if (format_for_text) { uris = g_string_new (NULL); } else { uris = g_string_new (info->cut ? "cut" : "copy"); } for (i = 0, l = info->files; l != NULL; l = l->next, i++) { uri = nemo_file_get_uri (l->data); if (format_for_text) { f = g_file_new_for_uri (uri); tmp = g_file_get_parse_name (f); g_object_unref (f); if (tmp != NULL) { g_string_append (uris, tmp); g_free (tmp); } else { g_string_append (uris, uri); } /* skip newline for last element */ if (i + 1 < g_list_length (info->files)) { g_string_append_c (uris, '\n'); } } else { g_string_append_c (uris, '\n'); g_string_append (uris, uri); } g_free (uri); } *len = uris->len; return g_string_free (uris, FALSE); } void nemo_get_clipboard_callback (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data) { char **uris; GList *l; int i; NemoClipboardInfo *clipboard_info; GdkAtom target; clipboard_info = nemo_clipboard_monitor_get_clipboard_info (nemo_clipboard_monitor_get ()); target = gtk_selection_data_get_target (selection_data); if (gtk_targets_include_uri (&target, 1)) { uris = g_malloc ((g_list_length (clipboard_info->files) + 1) * sizeof (char *)); i = 0; for (l = clipboard_info->files; l != NULL; l = l->next) { uris[i] = nemo_file_get_uri (l->data); i++; } uris[i] = NULL; gtk_selection_data_set_uris (selection_data, uris); g_strfreev (uris); } else if (gtk_targets_include_text (&target, 1)) { char *str; gsize len; str = convert_file_list_to_string (clipboard_info, TRUE, &len); gtk_selection_data_set_text (selection_data, str, len); g_free (str); } else if (target == copied_files_atom) { char *str; gsize len; str = convert_file_list_to_string (clipboard_info, FALSE, &len); gtk_selection_data_set (selection_data, copied_files_atom, 8, (guchar *) str, len); g_free (str); } } nemo-3.6.5/libnemo-private/nemo-desktop-utils.c0000664000175000017500000001075713215733314020427 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * */ #include "nemo-desktop-utils.h" static GdkScreen *default_screen = NULL; static void ensure_screen (void) { if (!default_screen) default_screen = gdk_screen_get_default (); } #if GTK_CHECK_VERSION (3, 22, 0) static GdkDisplay *default_display = NULL; static void ensure_display (void) { if (!default_display) default_display = gdk_display_get_default (); } #endif void nemo_desktop_utils_get_monitor_work_rect (gint num, GdkRectangle *rect) { #if GTK_CHECK_VERSION (3, 22, 0) ensure_display (); g_return_if_fail (num >= 0 && num < gdk_display_get_n_monitors (default_display)); GdkMonitor *monitor = gdk_display_get_monitor (default_display, num); gdk_monitor_get_workarea (monitor, rect); #else ensure_screen (); g_return_if_fail (num >= 0 && num < gdk_screen_get_n_monitors (default_screen)); gdk_screen_get_monitor_workarea (default_screen, num, rect); #endif } void nemo_desktop_utils_get_monitor_geometry (gint num, GdkRectangle *rect) { #if GTK_CHECK_VERSION (3, 22, 0) ensure_display (); g_return_if_fail (num >= 0 && num < gdk_display_get_n_monitors (default_display)); GdkMonitor *monitor = gdk_display_get_monitor (default_display, num); gdk_monitor_get_geometry (monitor, rect); #else ensure_screen (); g_return_if_fail (num >= 0 && num < gdk_screen_get_n_monitors (default_screen)); gdk_screen_get_monitor_geometry (default_screen, num, rect); #endif } gint nemo_desktop_utils_get_primary_monitor (void) { #if GTK_CHECK_VERSION (3, 22, 0) gint n_mon, i; ensure_display (); n_mon = gdk_display_get_n_monitors (default_display); for (i = 0; i < n_mon; i ++) { GdkMonitor *monitor = gdk_display_get_monitor (default_display, i); if (gdk_monitor_is_primary (monitor)) { return i; } } return 0; #else ensure_screen (); return gdk_screen_get_primary_monitor (default_screen); #endif } gint nemo_desktop_utils_get_monitor_for_widget (GtkWidget *widget) { GdkWindow *window; GtkWidget *toplevel; gint monitor; g_return_val_if_fail (GTK_IS_WIDGET (widget), 0); toplevel = gtk_widget_get_toplevel (widget); if (toplevel != NULL && g_object_get_data (G_OBJECT (toplevel), "is_desktop_window")) { monitor = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (toplevel), "monitor_number")); return monitor; } ensure_screen (); window = gtk_widget_get_window (widget); if (window == NULL) { return 0; } monitor = gdk_screen_get_monitor_at_window (default_screen, window); return monitor; } gint nemo_desktop_utils_get_num_monitors (void) { ensure_screen (); return gdk_screen_get_n_monitors (default_screen); } gboolean nemo_desktop_utils_get_monitor_cloned (gint monitor, gint x_primary) { GdkRectangle rect_primary; GdkRectangle rect_test; gint n_monitors; ensure_screen (); n_monitors = gdk_screen_get_n_monitors (default_screen); g_return_val_if_fail (monitor >= 0 && monitor < n_monitors, FALSE); g_return_val_if_fail (x_primary >= 0 && x_primary < n_monitors, FALSE); gdk_screen_get_monitor_geometry(default_screen, x_primary, &rect_primary); gdk_screen_get_monitor_geometry(default_screen, monitor, &rect_test); if (rect_primary.x == rect_test.x && rect_primary.y == rect_test.y) { return TRUE; } return FALSE; } gint nemo_desktop_utils_get_scale_factor (void) { guint scale; GValue value = G_VALUE_INIT; ensure_screen (); g_value_init (&value, G_TYPE_UINT); if (gdk_screen_get_setting (default_screen, "gdk-window-scaling-factor", &value)) { scale = g_value_get_uint (&value); } else { scale = 1; } return (gint) scale; } nemo-3.6.5/libnemo-private/nemo-desktop-link.c0000664000175000017500000002163513215733314020221 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-link.c: Class that handles the links on the desktop Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-desktop-link.h" #include "nemo-desktop-link-monitor.h" #include "nemo-desktop-icon-file.h" #include "nemo-directory-private.h" #include "nemo-desktop-directory.h" #include "nemo-icon-names.h" #include #include #include #include #include #include struct NemoDesktopLinkDetails { NemoDesktopLinkType type; char *filename; char *display_name; GFile *activation_location; GIcon *icon; NemoDesktopIconFile *icon_file; GObject *signal_handler_obj; gulong signal_handler; /* Just for mount icons: */ GMount *mount; }; G_DEFINE_TYPE(NemoDesktopLink, nemo_desktop_link, G_TYPE_OBJECT) static void create_icon_file (NemoDesktopLink *link) { link->details->icon_file = nemo_desktop_icon_file_new (link); } static void nemo_desktop_link_changed (NemoDesktopLink *link) { if (link->details->icon_file != NULL) { nemo_desktop_icon_file_update (link->details->icon_file); } } static void mount_changed_callback (GMount *mount, NemoDesktopLink *link) { g_free (link->details->display_name); if (link->details->activation_location) { g_object_unref (link->details->activation_location); } if (link->details->icon) { g_object_unref (link->details->icon); } link->details->display_name = g_mount_get_name (mount); link->details->activation_location = g_mount_get_default_location (mount); link->details->icon = g_mount_get_icon (mount); nemo_desktop_link_changed (link); } static void trash_state_changed_callback (NemoTrashMonitor *trash_monitor, gboolean state, gpointer callback_data) { NemoDesktopLink *link; link = NEMO_DESKTOP_LINK (callback_data); g_assert (link->details->type == NEMO_DESKTOP_LINK_TRASH); if (link->details->icon) { g_object_unref (link->details->icon); } link->details->icon = nemo_trash_monitor_get_icon (); nemo_desktop_link_changed (link); } NemoDesktopLink * nemo_desktop_link_new (NemoDesktopLinkType type) { NemoDesktopLink *link; link = NEMO_DESKTOP_LINK (g_object_new (NEMO_TYPE_DESKTOP_LINK, NULL)); link->details->type = type; switch (type) { case NEMO_DESKTOP_LINK_HOME: link->details->filename = g_strdup ("home"); link->details->display_name = g_strdup (_("Home")); link->details->activation_location = g_file_new_for_path (g_get_home_dir ()); link->details->icon = g_themed_icon_new (NEMO_ICON_HOME); break; case NEMO_DESKTOP_LINK_COMPUTER: link->details->filename = g_strdup ("computer"); link->details->display_name = g_strdup (_("Computer")); link->details->activation_location = g_file_new_for_uri ("computer:///"); /* TODO: This might need a different icon: */ link->details->icon = g_themed_icon_new (NEMO_ICON_COMPUTER); break; case NEMO_DESKTOP_LINK_TRASH: link->details->filename = g_strdup ("trash"); link->details->display_name = g_strdup (_("Trash")); link->details->activation_location = g_file_new_for_uri (EEL_TRASH_URI); link->details->icon = nemo_trash_monitor_get_icon (); link->details->signal_handler_obj = G_OBJECT (nemo_trash_monitor_get ()); link->details->signal_handler = g_signal_connect_object (nemo_trash_monitor_get (), "trash_state_changed", G_CALLBACK (trash_state_changed_callback), link, 0); break; case NEMO_DESKTOP_LINK_NETWORK: link->details->filename = g_strdup ("network"); link->details->display_name = g_strdup (_("Network")); link->details->activation_location = g_file_new_for_uri ("network:///"); link->details->icon = g_themed_icon_new (NEMO_ICON_NETWORK); break; default: case NEMO_DESKTOP_LINK_MOUNT: g_assert_not_reached(); } create_icon_file (link); return link; } NemoDesktopLink * nemo_desktop_link_new_from_mount (GMount *mount) { NemoDesktopLink *link; GVolume *volume; char *name, *filename; link = NEMO_DESKTOP_LINK (g_object_new (NEMO_TYPE_DESKTOP_LINK, NULL)); link->details->type = NEMO_DESKTOP_LINK_MOUNT; link->details->mount = g_object_ref (mount); /* We try to use the drive name to get somewhat stable filenames for metadata */ volume = g_mount_get_volume (mount); if (volume != NULL) { name = g_volume_get_name (volume); g_object_unref (volume); } else { name = g_mount_get_name (mount); } /* Replace slashes in name */ filename = g_strconcat (g_strdelimit (name, "/", '-'), ".volume", NULL); link->details->filename = nemo_desktop_link_monitor_make_filename_unique (nemo_desktop_link_monitor_get (), filename); g_free (filename); g_free (name); link->details->display_name = g_mount_get_name (mount); link->details->activation_location = g_mount_get_default_location (mount); link->details->icon = g_mount_get_icon (mount); link->details->signal_handler_obj = G_OBJECT (mount); link->details->signal_handler = g_signal_connect (mount, "changed", G_CALLBACK (mount_changed_callback), link); create_icon_file (link); return link; } GMount * nemo_desktop_link_get_mount (NemoDesktopLink *link) { if (link->details->mount) { return g_object_ref (link->details->mount); } return NULL; } NemoDesktopLinkType nemo_desktop_link_get_link_type (NemoDesktopLink *link) { return link->details->type; } NemoFile * nemo_desktop_link_get_file (NemoDesktopLink *link) { return NEMO_FILE (link->details->icon_file); } char * nemo_desktop_link_get_file_name (NemoDesktopLink *link) { return g_strdup (link->details->filename); } char * nemo_desktop_link_get_display_name (NemoDesktopLink *link) { return g_strdup (link->details->display_name); } GIcon * nemo_desktop_link_get_icon (NemoDesktopLink *link) { if (link->details->icon != NULL) { return g_object_ref (link->details->icon); } return NULL; } GFile * nemo_desktop_link_get_activation_location (NemoDesktopLink *link) { if (link->details->activation_location) { return g_object_ref (link->details->activation_location); } return NULL; } char * nemo_desktop_link_get_activation_uri (NemoDesktopLink *link) { if (link->details->activation_location) { return g_file_get_uri (link->details->activation_location); } return NULL; } gboolean nemo_desktop_link_get_date (NemoDesktopLink *link, NemoDateType date_type, time_t *date) { return FALSE; } gboolean nemo_desktop_link_can_rename (NemoDesktopLink *link) { return !(link->details->type == NEMO_DESKTOP_LINK_HOME || link->details->type == NEMO_DESKTOP_LINK_TRASH || link->details->type == NEMO_DESKTOP_LINK_NETWORK || link->details->type == NEMO_DESKTOP_LINK_COMPUTER); } gboolean nemo_desktop_link_rename (NemoDesktopLink *link, const char *name) { /* Do we want volume renaming? */ return TRUE; } static void nemo_desktop_link_init (NemoDesktopLink *link) { link->details = G_TYPE_INSTANCE_GET_PRIVATE (link, NEMO_TYPE_DESKTOP_LINK, NemoDesktopLinkDetails); } static void desktop_link_finalize (GObject *object) { NemoDesktopLink *link; link = NEMO_DESKTOP_LINK (object); if (link->details->signal_handler != 0) { g_signal_handler_disconnect (link->details->signal_handler_obj, link->details->signal_handler); } if (link->details->icon_file != NULL) { nemo_desktop_icon_file_remove (link->details->icon_file); nemo_file_unref (NEMO_FILE (link->details->icon_file)); link->details->icon_file = NULL; } if (link->details->type == NEMO_DESKTOP_LINK_MOUNT) { g_object_unref (link->details->mount); } g_free (link->details->filename); g_free (link->details->display_name); if (link->details->activation_location) { g_object_unref (link->details->activation_location); } if (link->details->icon) { g_object_unref (link->details->icon); } G_OBJECT_CLASS (nemo_desktop_link_parent_class)->finalize (object); } static void nemo_desktop_link_class_init (NemoDesktopLinkClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = desktop_link_finalize; g_type_class_add_private (object_class, sizeof(NemoDesktopLinkDetails)); } nemo-3.6.5/libnemo-private/nemo-undo-signal-handlers.h0000664000175000017500000000255013215733314021633 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Signal handlers to enable undo in Gtk Widgets. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_UNDO_SIGNAL_HANDLERS_H #define NEMO_UNDO_SIGNAL_HANDLERS_H #include void nemo_undo_set_up_nemo_entry_for_undo (NemoEntry *entry); void nemo_undo_tear_down_nemo_entry_for_undo (NemoEntry *entry); void nemo_undo_set_up_editable_for_undo (GtkEditable *editable); void nemo_undo_tear_down_editable_for_undo (GtkEditable *editable); #endif /* NEMO_UNDO_SIGNAL_HANDLERS_H */ nemo-3.6.5/libnemo-private/nemo-file-dnd.c0000664000175000017500000000662613215733314017302 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-drag.c - Drag & drop handling code that operated on NemoFile objects. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Pavel Cisler , */ #include #include "nemo-file-dnd.h" #include "nemo-desktop-icon-file.h" #include "nemo-dnd.h" #include "nemo-directory.h" #include "nemo-file-utilities.h" #include static gboolean nemo_drag_can_accept_files (NemoFile *drop_target_item) { NemoDirectory *directory; if (nemo_file_is_directory (drop_target_item)) { gboolean res; /* target is a directory, accept if editable */ directory = nemo_directory_get_for_file (drop_target_item); res = nemo_directory_is_editable (directory); nemo_directory_unref (directory); return res; } if (NEMO_IS_DESKTOP_ICON_FILE (drop_target_item)) { return TRUE; } /* Launchers are an acceptable drop target */ if (nemo_file_is_launcher (drop_target_item)) { return TRUE; } if (nemo_is_file_roller_installed () && nemo_file_is_archive (drop_target_item)) { return TRUE; } return FALSE; } gboolean nemo_drag_can_accept_item (NemoFile *drop_target_item, const char *item_uri) { if (nemo_file_matches_uri (drop_target_item, item_uri)) { /* can't accept itself */ return FALSE; } return nemo_drag_can_accept_files (drop_target_item); } gboolean nemo_drag_can_accept_items (NemoFile *drop_target_item, const GList *items) { int max; if (drop_target_item == NULL) return FALSE; g_assert (NEMO_IS_FILE (drop_target_item)); /* Iterate through selection checking if item will get accepted by the * drop target. If more than 100 items selected, return an over-optimisic * result */ for (max = 100; items != NULL && max >= 0; items = items->next, max--) { if (!nemo_drag_can_accept_item (drop_target_item, ((NemoDragSelectionItem *)items->data)->uri)) { return FALSE; } } return TRUE; } gboolean nemo_drag_can_accept_info (NemoFile *drop_target_item, NemoIconDndTargetType drag_type, const GList *items) { switch (drag_type) { case NEMO_ICON_DND_GNOME_ICON_LIST: return nemo_drag_can_accept_items (drop_target_item, items); case NEMO_ICON_DND_URI_LIST: case NEMO_ICON_DND_NETSCAPE_URL: case NEMO_ICON_DND_TEXT: return nemo_drag_can_accept_files (drop_target_item); case NEMO_ICON_DND_XDNDDIRECTSAVE: case NEMO_ICON_DND_RAW: return nemo_drag_can_accept_files (drop_target_item); /* Check if we can accept files at this location */ case NEMO_ICON_DND_ROOTWINDOW_DROP: return FALSE; default: g_assert_not_reached (); return FALSE; } } nemo-3.6.5/libnemo-private/nemo-undo-manager.h0000664000175000017500000000547113215733314020177 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoUndoManager - Manages undo and redo transactions. * This is the public interface used by the application. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_UNDO_MANAGER_H #define NEMO_UNDO_MANAGER_H #include #define NEMO_TYPE_UNDO_MANAGER nemo_undo_manager_get_type() #define NEMO_UNDO_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_UNDO_MANAGER, NemoUndoManager)) #define NEMO_UNDO_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_UNDO_MANAGER, NemoUndoManagerClass)) #define NEMO_IS_UNDO_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_UNDO_MANAGER)) #define NEMO_IS_UNDO_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_UNDO_MANAGER)) #define NEMO_UNDO_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_UNDO_MANAGER, NemoUndoManagerClass)) typedef struct NemoUndoManagerDetails NemoUndoManagerDetails; typedef struct { GObject parent; NemoUndoManagerDetails *details; } NemoUndoManager; typedef struct { GObjectClass parent_slot; void (* changed) (GObject *object, gpointer data); } NemoUndoManagerClass; GType nemo_undo_manager_get_type (void); NemoUndoManager *nemo_undo_manager_new (void); /* Undo operations. */ void nemo_undo_manager_undo (NemoUndoManager *undo_manager); /* Attach the undo manager to a Gtk object so that object and the widgets inside it can participate in undo. */ void nemo_undo_manager_attach (NemoUndoManager *manager, GObject *object); void nemo_undo_manager_append (NemoUndoManager *manager, NemoUndoTransaction *transaction); void nemo_undo_manager_forget (NemoUndoManager *manager, NemoUndoTransaction *transaction); #endif /* NEMO_UNDO_MANAGER_H */ nemo-3.6.5/libnemo-private/nemo-context-menu-menu-item.h0000664000175000017500000000521413215733314022141 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #ifndef __NEMO_CONTEXT_MENU_MENU_ITEM_H__ #define __NEMO_CONTEXT_MENU_MENU_ITEM_H__ #include G_BEGIN_DECLS #define NEMO_TYPE_CONTEXT_MENU_MENU_ITEM (nemo_context_menu_menu_item_get_type ()) #define NEMO_CONTEXT_MENU_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItem)) #define NEMO_CONTEXT_MENU_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItemClass)) #define NEMO_IS_CONTEXT_MENU_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM)) #define NEMO_IS_CONTEXT_MENU_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM)) #define NEMO_CONTEXT_MENU_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NemoContextMenuMenuItemClass)) typedef struct _NemoContextMenuMenuItem NemoContextMenuMenuItem; typedef struct _NemoContextMenuMenuItemClass NemoContextMenuMenuItemClass; struct _NemoContextMenuMenuItem { GtkImageMenuItem menu_item; gchar *label; GtkWidget *stack; GtkWidget *label_widget; GtkWidget *toggle_label_widget; GtkWidget *toggle_widget; gulong settings_monitor_id; gboolean on_toggle; }; /** * NemoContextMenuMenuItemClass: * @parent_class: The parent class. */ struct _NemoContextMenuMenuItemClass { GtkImageMenuItemClass parent_class; }; GType nemo_context_menu_menu_item_get_type (void) G_GNUC_CONST; GtkWidget *nemo_context_menu_menu_item_new (GtkWidget *widget); G_END_DECLS #endif /* __NEMO_CONTEXT_MENU_MENU_ITEM_H__ */ nemo-3.6.5/libnemo-private/nemo-saved-search-file.h0000664000175000017500000000404713215733314021102 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-saved-search-file.h: Subclass of NemoVFSFile to implement the the case of a Saved Search file. Copyright (C) 2005 Red Hat, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_SAVED_SEARCH_FILE_H #define NEMO_SAVED_SEARCH_FILE_H #include #define NEMO_TYPE_SAVED_SEARCH_FILE nemo_saved_search_file_get_type() #define NEMO_SAVED_SEARCH_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SAVED_SEARCH_FILE, NemoSavedSearchFile)) #define NEMO_SAVED_SEARCH_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SAVED_SEARCH_FILE, NemoSavedSearchFileClass)) #define NEMO_IS_SAVED_SEARCH_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SAVED_SEARCH_FILE)) #define NEMO_IS_SAVED_SEARCH_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SAVED_SEARCH_FILE)) #define NEMO_SAVED_SEARCH_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SAVED_SEARCH_FILE, NemoSavedSearchFileClass)) typedef struct NemoSavedSearchFileDetails NemoSavedSearchFileDetails; typedef struct { NemoFile parent_slot; } NemoSavedSearchFile; typedef struct { NemoFileClass parent_slot; } NemoSavedSearchFileClass; GType nemo_saved_search_file_get_type (void); #endif /* NEMO_SAVED_SEARCH_FILE_H */ nemo-3.6.5/libnemo-private/nemo-module.h0000664000175000017500000000451113215733314017101 0ustar fabiofabio/* * nemo-module.h - Interface to nemo extensions * * Copyright (C) 2003 Novell, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * * Author: Dave Camp * */ #ifndef NEMO_MODULE_H #define NEMO_MODULE_H #include #include G_BEGIN_DECLS #define NEMO_TYPE_MODULE (nemo_module_get_type ()) #define NEMO_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_MODULE, NemoModule)) #define NEMO_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_MODULE, NemoModule)) #define NEMO_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_MODULE)) #define NEMO_IS_MODULE_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_MODULE)) typedef struct _NemoModule NemoModule; typedef struct _NemoModuleClass NemoModuleClass; struct _NemoModule { GTypeModule parent; GModule *library; char *path; void (*initialize) (GTypeModule *module); void (*shutdown) (void); void (*list_types) (const GType **types, int *num_types); void (*get_modules_name_and_desc) (gchar ***strings); }; struct _NemoModuleClass { GTypeModuleClass parent; }; GType nemo_module_get_type (void); void nemo_module_setup (void); void nemo_module_refresh (void); GList *nemo_module_get_extensions_for_type (GType type); void nemo_module_extension_list_free (GList *list); /* Add a type to the module interface - allows nemo to add its own modules * without putting them in separate shared libraries */ void nemo_module_add_type (GType type); G_END_DECLS #endif nemo-3.6.5/libnemo-private/nemo-undo-transaction.h0000664000175000017500000000630313215733314021105 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoUndoTransaction - An object for an undoable transaction. * Used internally by undo machinery. * Not public. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_UNDO_TRANSACTION_H #define NEMO_UNDO_TRANSACTION_H #include #define NEMO_TYPE_UNDO_TRANSACTION nemo_undo_transaction_get_type() #define NEMO_UNDO_TRANSACTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_UNDO_TRANSACTION, NemoUndoTransaction)) #define NEMO_UNDO_TRANSACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_UNDO_TRANSACTION, NemoUndoTransactionClass)) #define NEMO_IS_UNDO_TRANSACTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_UNDO_TRANSACTION)) #define NEMO_IS_UNDO_TRANSACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_UNDO_TRANSACTION)) #define NEMO_UNDO_TRANSACTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_UNDO_TRANSACTION, NemoUndoTransactionClass)) /* The typedef for NemoUndoTransaction is in nemo-undo.h to avoid circular deps */ typedef struct _NemoUndoTransactionClass NemoUndoTransactionClass; struct _NemoUndoTransaction { GObject parent_slot; char *operation_name; char *undo_menu_item_label; char *undo_menu_item_hint; char *redo_menu_item_label; char *redo_menu_item_hint; GList *atom_list; NemoUndoManager *owner; }; struct _NemoUndoTransactionClass { GObjectClass parent_slot; }; GType nemo_undo_transaction_get_type (void); NemoUndoTransaction *nemo_undo_transaction_new (const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint); void nemo_undo_transaction_add_atom (NemoUndoTransaction *transaction, const NemoUndoAtom *atom); void nemo_undo_transaction_add_to_undo_manager (NemoUndoTransaction *transaction, NemoUndoManager *manager); void nemo_undo_transaction_unregister_object (GObject *atom_target); void nemo_undo_transaction_undo (NemoUndoTransaction *transaction); #endif /* NEMO_UNDO_TRANSACTION_H */ nemo-3.6.5/libnemo-private/nemo-desktop-link-monitor.c0000664000175000017500000003406413215733314021706 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-link-monitor.c: singleton that manages the links Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-desktop-link-monitor.h" #include "nemo-desktop-metadata.h" #include "nemo-desktop-link.h" #include "nemo-desktop-icon-file.h" #include "nemo-directory.h" #include "nemo-desktop-directory.h" #include "nemo-global-preferences.h" #include #include #include #include #include #include #include #include struct NemoDesktopLinkMonitorDetails { GVolumeMonitor *volume_monitor; NemoDirectory *desktop_dir; NemoDesktopLink *home_link; NemoDesktopLink *computer_link; NemoDesktopLink *trash_link; NemoDesktopLink *network_link; GList *mount_links; }; G_DEFINE_TYPE (NemoDesktopLinkMonitor, nemo_desktop_link_monitor, G_TYPE_OBJECT); static NemoDesktopLinkMonitor *the_link_monitor = NULL; static void destroy_desktop_link_monitor (void) { if (the_link_monitor != NULL) { g_object_unref (the_link_monitor); } } NemoDesktopLinkMonitor * nemo_desktop_link_monitor_get (void) { if (the_link_monitor == NULL) { g_object_new (NEMO_TYPE_DESKTOP_LINK_MONITOR, NULL); eel_debug_call_at_shutdown (destroy_desktop_link_monitor); } return the_link_monitor; } static void volume_delete_dialog (GtkWidget *parent_view, NemoDesktopLink *link) { GMount *mount; char *dialog_str; char *display_name; mount = nemo_desktop_link_get_mount (link); if (mount != NULL) { display_name = nemo_desktop_link_get_display_name (link); dialog_str = g_strdup_printf (_("You cannot move the volume \"%s\" to the trash."), display_name); g_free (display_name); if (g_mount_can_eject (mount)) { eel_run_simple_dialog (parent_view, FALSE, GTK_MESSAGE_ERROR, dialog_str, _("If you want to eject the volume, please use \"Eject\" in the " "popup menu of the volume."), GTK_STOCK_OK, NULL); } else { eel_run_simple_dialog (parent_view, FALSE, GTK_MESSAGE_ERROR, dialog_str, _("If you want to unmount the volume, please use \"Unmount Volume\" in the " "popup menu of the volume."), GTK_STOCK_OK, NULL); } g_object_unref (mount); g_free (dialog_str); } } void nemo_desktop_link_monitor_delete_link (NemoDesktopLinkMonitor *monitor, NemoDesktopLink *link, GtkWidget *parent_view) { switch (nemo_desktop_link_get_link_type (link)) { case NEMO_DESKTOP_LINK_HOME: case NEMO_DESKTOP_LINK_COMPUTER: case NEMO_DESKTOP_LINK_TRASH: case NEMO_DESKTOP_LINK_NETWORK: /* just ignore. We don't allow you to delete these */ break; default: volume_delete_dialog (parent_view, link); break; } } static gboolean volume_file_name_used (NemoDesktopLinkMonitor *monitor, const char *name) { GList *l; char *other_name; gboolean same; for (l = monitor->details->mount_links; l != NULL; l = l->next) { other_name = nemo_desktop_link_get_file_name (l->data); same = strcmp (name, other_name) == 0; g_free (other_name); if (same) { return TRUE; } } return FALSE; } char * nemo_desktop_link_monitor_make_filename_unique (NemoDesktopLinkMonitor *monitor, const char *filename) { char *unique_name; int i; i = 2; unique_name = g_strdup (filename); while (volume_file_name_used (monitor, unique_name)) { g_free (unique_name); unique_name = g_strdup_printf ("%s.%d", filename, i++); } return unique_name; } static gboolean has_mount (NemoDesktopLinkMonitor *monitor, GMount *mount) { gboolean ret; GMount *other_mount; GList *l; ret = FALSE; for (l = monitor->details->mount_links; l != NULL; l = l->next) { other_mount = nemo_desktop_link_get_mount (l->data); if (mount == other_mount) { g_object_unref (other_mount); ret = TRUE; break; } g_object_unref (other_mount); } return ret; } static void create_mount_link (NemoDesktopLinkMonitor *monitor, GMount *mount) { NemoDesktopLink *link; if (has_mount (monitor, mount)) return; if ((!g_mount_is_shadowed (mount)) && g_settings_get_boolean (nemo_desktop_preferences, NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) { link = nemo_desktop_link_new_from_mount (mount); monitor->details->mount_links = g_list_prepend (monitor->details->mount_links, link); } } static void remove_mount_link (NemoDesktopLinkMonitor *monitor, GMount *mount) { GList *l; NemoDesktopLink *link; GMount *other_mount; link = NULL; for (l = monitor->details->mount_links; l != NULL; l = l->next) { other_mount = nemo_desktop_link_get_mount (l->data); if (mount == other_mount) { g_object_unref (other_mount); link = l->data; break; } g_object_unref (other_mount); } if (link) { monitor->details->mount_links = g_list_remove (monitor->details->mount_links, link); g_object_unref (link); } } static void mount_added_callback (GVolumeMonitor *volume_monitor, GMount *mount, NemoDesktopLinkMonitor *monitor) { create_mount_link (monitor, mount); } static void mount_removed_callback (GVolumeMonitor *volume_monitor, GMount *mount, NemoDesktopLinkMonitor *monitor) { remove_mount_link (monitor, mount); } static void mount_changed_callback (GVolumeMonitor *volume_monitor, GMount *mount, NemoDesktopLinkMonitor *monitor) { /* TODO: update the mount with other details */ /* remove a mount if it goes into the shadows */ if (g_mount_is_shadowed (mount) && has_mount (monitor, mount)) { remove_mount_link (monitor, mount); }} static void update_link_visibility (NemoDesktopLinkMonitor *monitor, NemoDesktopLink **link_ref, NemoDesktopLinkType link_type, const char *preference_key) { if (g_settings_get_boolean (nemo_desktop_preferences, preference_key)) { if (*link_ref == NULL) { *link_ref = nemo_desktop_link_new (link_type); } } else { if (*link_ref != NULL) { /* If this were a real file, removing (deleting or moving) it would * also remove its metadata, though for a different reason, and * unmanaged by us. We have to simulate that when removing a fake * 'desktop' file, so if it gets added again later, it behaves like a * 'new' file. */ nemo_desktop_clear_metadata (nemo_desktop_link_get_file (*link_ref)); g_object_unref (*link_ref); *link_ref = NULL; } } } static void desktop_home_visible_changed (gpointer callback_data) { NemoDesktopLinkMonitor *monitor; monitor = NEMO_DESKTOP_LINK_MONITOR (callback_data); update_link_visibility (NEMO_DESKTOP_LINK_MONITOR (monitor), &monitor->details->home_link, NEMO_DESKTOP_LINK_HOME, NEMO_PREFERENCES_DESKTOP_HOME_VISIBLE); } static void desktop_computer_visible_changed (gpointer callback_data) { NemoDesktopLinkMonitor *monitor; monitor = NEMO_DESKTOP_LINK_MONITOR (callback_data); update_link_visibility (NEMO_DESKTOP_LINK_MONITOR (callback_data), &monitor->details->computer_link, NEMO_DESKTOP_LINK_COMPUTER, NEMO_PREFERENCES_DESKTOP_COMPUTER_VISIBLE); } static void desktop_trash_visible_changed (gpointer callback_data) { NemoDesktopLinkMonitor *monitor; monitor = NEMO_DESKTOP_LINK_MONITOR (callback_data); update_link_visibility (NEMO_DESKTOP_LINK_MONITOR (callback_data), &monitor->details->trash_link, NEMO_DESKTOP_LINK_TRASH, NEMO_PREFERENCES_DESKTOP_TRASH_VISIBLE); } static void desktop_network_visible_changed (gpointer callback_data) { NemoDesktopLinkMonitor *monitor; monitor = NEMO_DESKTOP_LINK_MONITOR (callback_data); update_link_visibility (NEMO_DESKTOP_LINK_MONITOR (callback_data), &monitor->details->network_link, NEMO_DESKTOP_LINK_NETWORK, NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE); } static void desktop_volumes_visible_changed (gpointer callback_data) { NemoDesktopLinkMonitor *monitor; GList *l, *mounts; monitor = NEMO_DESKTOP_LINK_MONITOR (callback_data); if (g_settings_get_boolean (nemo_desktop_preferences, NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE)) { if (monitor->details->mount_links == NULL) { mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor); for (l = mounts; l != NULL; l = l->next) { create_mount_link (monitor, l->data); g_object_unref (l->data); } g_list_free (mounts); } } else { g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL); g_list_free (monitor->details->mount_links); monitor->details->mount_links = NULL; } } static void create_link_and_add_preference (NemoDesktopLink **link_ref, NemoDesktopLinkType link_type, const char *preference_key, GCallback callback, gpointer callback_data) { char *detailed_signal; if (g_settings_get_boolean (nemo_desktop_preferences, preference_key)) { *link_ref = nemo_desktop_link_new (link_type); } detailed_signal = g_strconcat ("changed::", preference_key, NULL); g_signal_connect_swapped (nemo_desktop_preferences, detailed_signal, callback, callback_data); g_free (detailed_signal); } static void nemo_desktop_link_monitor_init (NemoDesktopLinkMonitor *monitor) { GList *l, *mounts; GMount *mount; monitor->details = G_TYPE_INSTANCE_GET_PRIVATE (monitor, NEMO_TYPE_DESKTOP_LINK_MONITOR, NemoDesktopLinkMonitorDetails); the_link_monitor = monitor; monitor->details->volume_monitor = g_volume_monitor_get (); /* We keep around a ref to the desktop dir */ monitor->details->desktop_dir = nemo_directory_get_by_uri (EEL_DESKTOP_URI); /* Default links */ create_link_and_add_preference (&monitor->details->home_link, NEMO_DESKTOP_LINK_HOME, NEMO_PREFERENCES_DESKTOP_HOME_VISIBLE, G_CALLBACK (desktop_home_visible_changed), monitor); create_link_and_add_preference (&monitor->details->computer_link, NEMO_DESKTOP_LINK_COMPUTER, NEMO_PREFERENCES_DESKTOP_COMPUTER_VISIBLE, G_CALLBACK (desktop_computer_visible_changed), monitor); create_link_and_add_preference (&monitor->details->trash_link, NEMO_DESKTOP_LINK_TRASH, NEMO_PREFERENCES_DESKTOP_TRASH_VISIBLE, G_CALLBACK (desktop_trash_visible_changed), monitor); create_link_and_add_preference (&monitor->details->network_link, NEMO_DESKTOP_LINK_NETWORK, NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE, G_CALLBACK (desktop_network_visible_changed), monitor); /* Mount links */ mounts = g_volume_monitor_get_mounts (monitor->details->volume_monitor); for (l = mounts; l != NULL; l = l->next) { mount = l->data; create_mount_link (monitor, mount); g_object_unref (mount); } g_list_free (mounts); g_signal_connect_swapped (nemo_desktop_preferences, "changed::" NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE, G_CALLBACK (desktop_volumes_visible_changed), monitor); g_signal_connect_object (monitor->details->volume_monitor, "mount_added", G_CALLBACK (mount_added_callback), monitor, 0); g_signal_connect_object (monitor->details->volume_monitor, "mount_removed", G_CALLBACK (mount_removed_callback), monitor, 0); g_signal_connect_object (monitor->details->volume_monitor, "mount_changed", G_CALLBACK (mount_changed_callback), monitor, 0); } static void remove_link_and_preference (NemoDesktopLink **link_ref, const char *preference_key, GCallback callback, gpointer callback_data) { if (*link_ref != NULL) { g_object_unref (*link_ref); *link_ref = NULL; } g_signal_handlers_disconnect_by_func (nemo_desktop_preferences, callback, callback_data); } static void desktop_link_monitor_finalize (GObject *object) { NemoDesktopLinkMonitor *monitor; monitor = NEMO_DESKTOP_LINK_MONITOR (object); g_object_unref (monitor->details->volume_monitor); /* Default links */ remove_link_and_preference (&monitor->details->home_link, NEMO_PREFERENCES_DESKTOP_HOME_VISIBLE, G_CALLBACK (desktop_home_visible_changed), monitor); remove_link_and_preference (&monitor->details->computer_link, NEMO_PREFERENCES_DESKTOP_COMPUTER_VISIBLE, G_CALLBACK (desktop_computer_visible_changed), monitor); remove_link_and_preference (&monitor->details->trash_link, NEMO_PREFERENCES_DESKTOP_TRASH_VISIBLE, G_CALLBACK (desktop_trash_visible_changed), monitor); remove_link_and_preference (&monitor->details->network_link, NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE, G_CALLBACK (desktop_network_visible_changed), monitor); /* Mounts */ g_list_foreach (monitor->details->mount_links, (GFunc)g_object_unref, NULL); g_list_free (monitor->details->mount_links); monitor->details->mount_links = NULL; nemo_directory_unref (monitor->details->desktop_dir); monitor->details->desktop_dir = NULL; g_signal_handlers_disconnect_by_func (nemo_desktop_preferences, desktop_volumes_visible_changed, monitor); G_OBJECT_CLASS (nemo_desktop_link_monitor_parent_class)->finalize (object); } static void nemo_desktop_link_monitor_class_init (NemoDesktopLinkMonitorClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = desktop_link_monitor_finalize; g_type_class_add_private (klass, sizeof (NemoDesktopLinkMonitorDetails)); } nemo-3.6.5/libnemo-private/nemo-progress-info-manager.c0000664000175000017500000000736613215733314022027 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 2011 Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Cosimo Cecchi */ #include #include "nemo-progress-info-manager.h" struct _NemoProgressInfoManagerPriv { GList *progress_infos; }; enum { NEW_PROGRESS_INFO, LAST_SIGNAL }; static NemoProgressInfoManager *singleton = NULL; static guint signals[LAST_SIGNAL] = { 0, }; G_DEFINE_TYPE (NemoProgressInfoManager, nemo_progress_info_manager, G_TYPE_OBJECT); static void nemo_progress_info_manager_finalize (GObject *obj) { NemoProgressInfoManager *self = NEMO_PROGRESS_INFO_MANAGER (obj); if (self->priv->progress_infos != NULL) { g_list_free_full (self->priv->progress_infos, g_object_unref); } G_OBJECT_CLASS (nemo_progress_info_manager_parent_class)->finalize (obj); } static GObject * nemo_progress_info_manager_constructor (GType type, guint n_props, GObjectConstructParam *props) { GObject *retval; if (singleton != NULL) { return g_object_ref (singleton); } retval = G_OBJECT_CLASS (nemo_progress_info_manager_parent_class)->constructor (type, n_props, props); singleton = NEMO_PROGRESS_INFO_MANAGER (retval); g_object_add_weak_pointer (retval, (gpointer) &singleton); return retval; } static void nemo_progress_info_manager_init (NemoProgressInfoManager *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_PROGRESS_INFO_MANAGER, NemoProgressInfoManagerPriv); } static void nemo_progress_info_manager_class_init (NemoProgressInfoManagerClass *klass) { GObjectClass *oclass; oclass = G_OBJECT_CLASS (klass); oclass->constructor = nemo_progress_info_manager_constructor; oclass->finalize = nemo_progress_info_manager_finalize; signals[NEW_PROGRESS_INFO] = g_signal_new ("new-progress-info", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, NEMO_TYPE_PROGRESS_INFO); g_type_class_add_private (klass, sizeof (NemoProgressInfoManagerPriv)); } static void progress_info_finished_cb (NemoProgressInfo *info, NemoProgressInfoManager *self) { self->priv->progress_infos = g_list_remove (self->priv->progress_infos, info); } NemoProgressInfoManager * nemo_progress_info_manager_new (void) { return g_object_new (NEMO_TYPE_PROGRESS_INFO_MANAGER, NULL); } void nemo_progress_info_manager_add_new_info (NemoProgressInfoManager *self, NemoProgressInfo *info) { if (g_list_find (self->priv->progress_infos, info) != NULL) { g_warning ("Adding two times the same progress info object to the manager"); return; } self->priv->progress_infos = g_list_prepend (self->priv->progress_infos, g_object_ref (info)); g_signal_connect (info, "finished", G_CALLBACK (progress_info_finished_cb), self); g_signal_emit (self, signals[NEW_PROGRESS_INFO], 0, info); } GList * nemo_progress_info_manager_get_all_infos (NemoProgressInfoManager *self) { return self->priv->progress_infos; } nemo-3.6.5/libnemo-private/nemo-thumbnails.c0000664000175000017500000004630013215733314017757 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-thumbnails.h: Thumbnail code for icon factory. Copyright (C) 2000, 2001 Eazel, Inc. Copyright (C) 2002, 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Andy Hertzfeld */ #include #include "nemo-thumbnails.h" #define GNOME_DESKTOP_USE_UNSTABLE_API #include "nemo-directory-notify.h" #include "nemo-global-preferences.h" #include "nemo-file-utilities.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "nemo-file-private.h" /* turn this on to see messages about thumbnail creation */ #if 0 #define DEBUG_THUMBNAILS #endif /* Should never be a reasonable actual mtime */ #define INVALID_MTIME 0 /* Cool-off period between last file modification time and thumbnail creation */ #define THUMBNAIL_CREATION_DELAY_SECS 3 #define NEMO_THUMBNAIL_FRAME_LEFT 3 #define NEMO_THUMBNAIL_FRAME_TOP 3 #define NEMO_THUMBNAIL_FRAME_RIGHT 3 #define NEMO_THUMBNAIL_FRAME_BOTTOM 3 static gpointer thumbnail_thread_start (gpointer data); /* structure used for making thumbnails, associating a uri with where the thumbnail is to be stored */ typedef struct { char *image_uri; char *mime_type; time_t original_file_mtime; gint throttle_count; } NemoThumbnailInfo; /* * Thumbnail thread state. */ /* The id of the idle handler used to start the thumbnail thread, or 0 if no idle handler is currently registered. */ static guint thumbnail_thread_starter_id = 0; /* Our mutex used when accessing data shared between the main thread and the thumbnail thread, i.e. the thumbnail_thread_is_running flag and the thumbnails_to_make list. */ static pthread_mutex_t thumbnails_mutex = PTHREAD_MUTEX_INITIALIZER; /* A flag to indicate whether a thumbnail thread is running, so we don't start more than one. Lock thumbnails_mutex when accessing this. */ static volatile gboolean thumbnail_thread_is_running = FALSE; /* The list of NemoThumbnailInfo structs containing information about the thumbnails we are making. Lock thumbnails_mutex when accessing this. */ static volatile GQueue thumbnails_to_make = G_QUEUE_INIT; /* Quickly check if uri is in thumbnails_to_make list */ static GHashTable *thumbnails_to_make_hash = NULL; /* The currently thumbnailed icon. it also exists in the thumbnails_to_make list * to avoid adding it again. Lock thumbnails_mutex when accessing this. */ static NemoThumbnailInfo *currently_thumbnailing = NULL; static GnomeDesktopThumbnailFactory *thumbnail_factory = NULL; static gboolean get_file_mtime (const char *file_uri, time_t* mtime) { GFile *file; GFileInfo *info; gboolean ret; ret = FALSE; *mtime = INVALID_MTIME; file = g_file_new_for_uri (file_uri); info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL); if (info) { if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_TIME_MODIFIED)) { *mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); ret = TRUE; } g_object_unref (info); } g_object_unref (file); return ret; } static void free_thumbnail_info (NemoThumbnailInfo *info) { g_free (info->image_uri); g_free (info->mime_type); g_free (info); } static GnomeDesktopThumbnailFactory * get_thumbnail_factory (void) { if (thumbnail_factory == NULL) { thumbnail_factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL); } return thumbnail_factory; } /* This function is added as a very low priority idle function to start the thread to create any needed thumbnails. It is added with a very low priority so that it doesn't delay showing the directory in the icon/list views. We want to show the files in the directory as quickly as possible. */ static gboolean thumbnail_thread_starter_cb (gpointer data) { pthread_attr_t thread_attributes; pthread_t thumbnail_thread; /* Don't do this in thread, since g_object_ref is not threadsafe */ if (thumbnail_factory == NULL) { thumbnail_factory = get_thumbnail_factory (); } /* We create the thread in the detached state, as we don't need/want to join with it at any point. */ pthread_attr_init (&thread_attributes); pthread_attr_setdetachstate (&thread_attributes, PTHREAD_CREATE_DETACHED); #ifdef DEBUG_THUMBNAILS g_message ("(Main Thread) Creating thumbnails thread\n"); #endif /* We set a flag to indicate the thread is running, so we don't create a new one. We don't need to lock a mutex here, as the thumbnail thread isn't running yet. And we know we won't create the thread twice, as we also check thumbnail_thread_starter_id before scheduling this idle function. */ thumbnail_thread_is_running = TRUE; pthread_create (&thumbnail_thread, &thread_attributes, thumbnail_thread_start, NULL); thumbnail_thread_starter_id = 0; return FALSE; } static GdkPixbuf * nemo_get_thumbnail_frame (void) { static GdkPixbuf *thumbnail_frame = NULL; if (thumbnail_frame == NULL) { GInputStream *stream = g_resources_open_stream ("/org/nemo/icons/thumbnail_frame.png", 0, NULL); if (stream != NULL) { thumbnail_frame = gdk_pixbuf_new_from_stream (stream, NULL, NULL); g_object_unref (stream); } } return thumbnail_frame; } void nemo_thumbnail_frame_image (GdkPixbuf **pixbuf) { GdkPixbuf *pixbuf_with_frame, *frame; int left_offset, top_offset, right_offset, bottom_offset; /* The pixbuf isn't already framed (i.e., it was not made by * an old Nemo), so we must embed it in a frame. */ frame = nemo_get_thumbnail_frame (); if (frame == NULL) { return; } left_offset = NEMO_THUMBNAIL_FRAME_LEFT; top_offset = NEMO_THUMBNAIL_FRAME_TOP; right_offset = NEMO_THUMBNAIL_FRAME_RIGHT; bottom_offset = NEMO_THUMBNAIL_FRAME_BOTTOM; pixbuf_with_frame = eel_embed_image_in_frame (*pixbuf, frame, left_offset, top_offset, right_offset, bottom_offset); g_object_unref (*pixbuf); *pixbuf = pixbuf_with_frame; } void nemo_thumbnail_pad_top_and_bottom (GdkPixbuf **pixbuf, gint extra_height) { GdkPixbuf *pixbuf_with_padding; GdkRectangle rect; GdkRGBA transparent = { 0, 0, 0, 0.0 }; cairo_surface_t *surface; cairo_t *cr; gint width, height; width = gdk_pixbuf_get_width (*pixbuf); height = gdk_pixbuf_get_height (*pixbuf); surface = gdk_window_create_similar_image_surface (NULL, CAIRO_FORMAT_ARGB32, width, height + extra_height, 0); cr = cairo_create (surface); rect.x = 0; rect.y = 0; rect.width = width; rect.height = height + extra_height; gdk_cairo_rectangle (cr, &rect); gdk_cairo_set_source_rgba (cr, &transparent); cairo_fill (cr); gdk_cairo_set_source_pixbuf (cr, *pixbuf, 0, extra_height / 2); cairo_paint (cr); pixbuf_with_padding = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height + extra_height); g_object_unref (*pixbuf); cairo_surface_destroy (surface); cairo_destroy (cr); *pixbuf = pixbuf_with_padding; } void nemo_thumbnail_remove_from_queue (const char *file_uri) { GList *node; #ifdef DEBUG_THUMBNAILS g_message ("(Remove from queue) Locking mutex\n"); #endif pthread_mutex_lock (&thumbnails_mutex); /********************************* * MUTEX LOCKED *********************************/ if (thumbnails_to_make_hash) { node = g_hash_table_lookup (thumbnails_to_make_hash, file_uri); if (node && node->data != currently_thumbnailing) { g_hash_table_remove (thumbnails_to_make_hash, file_uri); free_thumbnail_info (node->data); g_queue_delete_link ((GQueue *)&thumbnails_to_make, node); } } /********************************* * MUTEX UNLOCKED *********************************/ #ifdef DEBUG_THUMBNAILS g_message ("(Remove from queue) Unlocking mutex\n"); #endif pthread_mutex_unlock (&thumbnails_mutex); } void nemo_thumbnail_prioritize (const char *file_uri) { GList *node; #ifdef DEBUG_THUMBNAILS g_message ("(Prioritize) Locking mutex\n"); #endif pthread_mutex_lock (&thumbnails_mutex); /********************************* * MUTEX LOCKED *********************************/ if (thumbnails_to_make_hash) { node = g_hash_table_lookup (thumbnails_to_make_hash, file_uri); if (node && node->data != currently_thumbnailing) { g_queue_unlink ((GQueue *)&thumbnails_to_make, node); g_queue_push_head_link ((GQueue *)&thumbnails_to_make, node); } } /********************************* * MUTEX UNLOCKED *********************************/ #ifdef DEBUG_THUMBNAILS g_message ("(Prioritize) Unlocking mutex\n"); #endif pthread_mutex_unlock (&thumbnails_mutex); } /*************************************************************************** * Thumbnail Thread Functions. ***************************************************************************/ /* This is a one-shot idle callback called from the main loop to call notify_file_changed() for a thumbnail. It frees the uri afterwards. We do this in an idle callback as I don't think nemo_file_changed() is thread-safe. */ static gboolean thumbnail_thread_notify_file_changed (gpointer image_uri) { NemoFile *file; file = nemo_file_get_by_uri ((char *) image_uri); #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Notifying file changed file:%p uri: %s\n", file, (char*) image_uri); #endif if (file != NULL) { nemo_file_set_is_thumbnailing (file, FALSE); nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_THUMBNAIL | NEMO_FILE_ATTRIBUTE_INFO); nemo_file_unref (file); } g_free (image_uri); return FALSE; } static GHashTable * get_types_table (void) { static GHashTable *image_mime_types = NULL; GSList *format_list, *l; char **types; int i; if (image_mime_types == NULL) { image_mime_types = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); format_list = gdk_pixbuf_get_formats (); for (l = format_list; l; l = l->next) { types = gdk_pixbuf_format_get_mime_types (l->data); for (i = 0; types[i] != NULL; i++) { g_hash_table_insert (image_mime_types, types [i], GUINT_TO_POINTER (1)); } g_free (types); } g_slist_free (format_list); } return image_mime_types; } static gboolean pixbuf_can_load_type (const char *mime_type) { GHashTable *image_mime_types; image_mime_types = get_types_table (); if (g_hash_table_lookup (image_mime_types, mime_type)) { return TRUE; } return FALSE; } gboolean nemo_can_thumbnail_internally (NemoFile *file) { char *mime_type; gboolean res; mime_type = nemo_file_get_mime_type (file); res = pixbuf_can_load_type (mime_type); g_free (mime_type); return res; } gboolean nemo_thumbnail_is_mimetype_limited_by_size (const char *mime_type) { return pixbuf_can_load_type (mime_type); } gboolean nemo_can_thumbnail (NemoFile *file) { GnomeDesktopThumbnailFactory *factory; gboolean res; char *uri; time_t mtime; char *mime_type; uri = nemo_file_get_uri (file); mime_type = nemo_file_get_mime_type (file); mtime = nemo_file_get_mtime (file); factory = get_thumbnail_factory (); res = gnome_desktop_thumbnail_factory_can_thumbnail (factory, uri, mime_type, mtime); g_free (mime_type); g_free (uri); return res; } void nemo_create_thumbnail (NemoFile *file, gint throttle_count) { time_t file_mtime = 0; NemoThumbnailInfo *info; NemoThumbnailInfo *existing_info; GList *existing, *node; nemo_file_set_is_thumbnailing (file, TRUE); info = g_new0 (NemoThumbnailInfo, 1); info->image_uri = nemo_file_get_uri (file); info->mime_type = nemo_file_get_mime_type (file); info->throttle_count = MIN (10, throttle_count); /* Hopefully the NemoFile will already have the image file mtime, so we can just use that. Otherwise we have to get it ourselves. */ if (file->details->got_file_info && file->details->file_info_is_up_to_date && file->details->mtime != 0) { file_mtime = file->details->mtime; } else { get_file_mtime (info->image_uri, &file_mtime); } info->original_file_mtime = file_mtime; #ifdef DEBUG_THUMBNAILS g_message ("(Main Thread) Locking mutex\n"); #endif pthread_mutex_lock (&thumbnails_mutex); /********************************* * MUTEX LOCKED *********************************/ if (thumbnails_to_make_hash == NULL) { thumbnails_to_make_hash = g_hash_table_new (g_str_hash, g_str_equal); } /* Check if it is already in the list of thumbnails to make. */ existing = g_hash_table_lookup (thumbnails_to_make_hash, info->image_uri); if (existing == NULL) { /* Add the thumbnail to the list. */ #ifdef DEBUG_THUMBNAILS g_message ("(Main Thread) Adding thumbnail: %s\n", info->image_uri); #endif g_queue_push_tail ((GQueue *)&thumbnails_to_make, info); node = g_queue_peek_tail_link ((GQueue *)&thumbnails_to_make); g_hash_table_insert (thumbnails_to_make_hash, info->image_uri, node); /* If the thumbnail thread isn't running, and we haven't scheduled an idle function to start it up, do that now. We don't want to start it until all the other work is done, so the GUI will be updated as quickly as possible.*/ if (thumbnail_thread_is_running == FALSE && thumbnail_thread_starter_id == 0) { thumbnail_thread_starter_id = g_idle_add_full (G_PRIORITY_LOW, thumbnail_thread_starter_cb, NULL, NULL); } } else { #ifdef DEBUG_THUMBNAILS g_message ("(Main Thread) Updating non-current mtime: %s\n", info->image_uri); #endif /* The file in the queue might need a new original mtime */ existing_info = existing->data; existing_info->original_file_mtime = info->original_file_mtime; free_thumbnail_info (info); } /********************************* * MUTEX UNLOCKED *********************************/ #ifdef DEBUG_THUMBNAILS g_message ("(Main Thread) Unlocking mutex\n"); #endif pthread_mutex_unlock (&thumbnails_mutex); } /* thumbnail_thread is invoked as a separate thread to to make thumbnails. */ static gpointer thumbnail_thread_start (gpointer data) { NemoThumbnailInfo *info = NULL; GdkPixbuf *pixbuf; time_t current_orig_mtime = 0; time_t current_time; GList *node; /* We loop until there are no more thumbails to make, at which point we exit the thread. */ for (;;) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Locking mutex\n"); #endif pthread_mutex_lock (&thumbnails_mutex); /********************************* * MUTEX LOCKED *********************************/ /* Pop the last thumbnail we just made off the head of the list and free it. I did this here so we only have to lock the mutex once per thumbnail, rather than once before creating it and once after. Don't pop the thumbnail off the queue if the original file mtime of the request changed. Then we need to redo the thumbnail. */ if (currently_thumbnailing && currently_thumbnailing->original_file_mtime == current_orig_mtime) { g_assert (info == currently_thumbnailing); node = g_hash_table_lookup (thumbnails_to_make_hash, info->image_uri); g_assert (node != NULL); g_hash_table_remove (thumbnails_to_make_hash, info->image_uri); free_thumbnail_info (info); g_queue_delete_link ((GQueue *)&thumbnails_to_make, node); } currently_thumbnailing = NULL; /* If there are no more thumbnails to make, reset the thumbnail_thread_is_running flag, unlock the mutex, and exit the thread. */ if (g_queue_is_empty ((GQueue *)&thumbnails_to_make)) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Exiting\n"); #endif thumbnail_thread_is_running = FALSE; pthread_mutex_unlock (&thumbnails_mutex); pthread_exit (NULL); } /* Get the next one to make. We leave it on the list until it is created so the main thread doesn't add it again while we are creating it. */ info = g_queue_peek_head ((GQueue *)&thumbnails_to_make); currently_thumbnailing = info; current_orig_mtime = info->original_file_mtime; /********************************* * MUTEX UNLOCKED *********************************/ #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Unlocking mutex\n"); #endif pthread_mutex_unlock (&thumbnails_mutex); time (¤t_time); /* Don't try to create a thumbnail if the file was modified recently. This prevents constant re-thumbnailing of changing files. */ if (current_time < current_orig_mtime + (THUMBNAIL_CREATION_DELAY_SECS * info->throttle_count) && current_time >= current_orig_mtime) { #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Skipping for %d seconds: %s\n", THUMBNAIL_CREATION_DELAY_SECS * info->throttle_count, info->image_uri); #endif /* Reschedule thumbnailing via a change notification */ g_timeout_add_seconds (THUMBNAIL_CREATION_DELAY_SECS * info->throttle_count, thumbnail_thread_notify_file_changed, g_strdup (info->image_uri)); continue; } /* Create the thumbnail. */ #ifdef DEBUG_THUMBNAILS g_message ("(Thumbnail Thread) Creating thumbnail: %s\n", info->image_uri); #endif pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory, info->image_uri, info->mime_type); if (pixbuf) { gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory, pixbuf, info->image_uri, current_orig_mtime); g_object_unref (pixbuf); } else { gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory, info->image_uri, current_orig_mtime); } /* We need to call nemo_file_changed(), but I don't think that is thread safe. So add an idle handler and do it from the main loop. */ g_idle_add_full (G_PRIORITY_HIGH_IDLE, thumbnail_thread_notify_file_changed, g_strdup (info->image_uri), NULL); } } gboolean nemo_thumbnail_factory_check_status (void) { return gnome_desktop_thumbnail_cache_check_permissions (get_thumbnail_factory (), TRUE); } nemo-3.6.5/libnemo-private/nemo-search-engine-simple.c0000664000175000017500000002757213215733314021622 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Red Hat, Inc * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Alexander Larsson * */ #include #include "nemo-search-engine-simple.h" #include #include #include #define BATCH_SIZE 500 typedef struct { NemoSearchEngineSimple *engine; GCancellable *cancellable; GList *mime_types; char **words; gboolean *word_strstr; gboolean words_and; GList *found_list; GQueue *directories; /* GFiles */ GHashTable *visited; gint n_processed_files; GList *uri_hits; } SearchThreadData; struct NemoSearchEngineSimpleDetails { NemoQuery *query; SearchThreadData *active_search; gboolean query_finished; }; G_DEFINE_TYPE (NemoSearchEngineSimple, nemo_search_engine_simple, NEMO_TYPE_SEARCH_ENGINE); static void finalize (GObject *object) { NemoSearchEngineSimple *simple; simple = NEMO_SEARCH_ENGINE_SIMPLE (object); if (simple->details->query) { g_object_unref (simple->details->query); simple->details->query = NULL; } G_OBJECT_CLASS (nemo_search_engine_simple_parent_class)->finalize (object); } /** * function modified taken from glib2 / gstrfuncs.c */ static gchar** strsplit_esc_n (const gchar *string, const gchar delimiter, const gchar escape, gint max_tokens, gint *n_tokens) { GSList *string_list = NULL, *slist; gchar **str_array, *s; guint n = 0; const gchar *remainder; g_return_val_if_fail (string != NULL, NULL); g_return_val_if_fail (delimiter != NULL, NULL); if (max_tokens < 1) max_tokens = G_MAXINT; remainder = string; s = remainder; while (s && *s) { if (*s == delimiter) break; else if (*s == escape) { s++; if (*s == 0) break; } s++; } if (*s == 0) s = NULL; if (s) { while (--max_tokens && s) { gsize len; len = s - remainder; string_list = g_slist_prepend (string_list, g_strndup (remainder, len)); n++; remainder = s + 1; s = remainder; while (s && *s) { if (*s == delimiter) break; else if (*s == escape) { s++; if (*s == 0) break; } s++; } if (*s == 0) s = NULL; } } if (*string) { n++; string_list = g_slist_prepend (string_list, g_strdup (remainder)); } *n_tokens = n; str_array = g_new (gchar*, n + 1); str_array[n--] = NULL; for (slist = string_list; slist; slist = slist->next) str_array[n--] = slist->data; g_slist_free (string_list); return str_array; } static SearchThreadData * search_thread_data_new (NemoSearchEngineSimple *engine, NemoQuery *query) { SearchThreadData *data; char *text, *lower, *normalized, *uri; GFile *location; gint n, i; data = g_new0 (SearchThreadData, 1); data->engine = engine; data->directories = g_queue_new (); data->visited = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); uri = nemo_query_get_location (query); location = NULL; if (uri != NULL) { location = g_file_new_for_uri (uri); g_free (uri); } if (location == NULL) { location = g_file_new_for_path ("/"); } g_queue_push_tail (data->directories, location); text = nemo_query_get_text (query); normalized = g_utf8_normalize (text, -1, G_NORMALIZE_NFD); lower = g_utf8_strdown (normalized, -1); data->words = strsplit_esc_n (lower, ' ', '\\', -1, &n); g_free (text); g_free (lower); g_free (normalized); data->word_strstr = g_malloc(sizeof(gboolean)*n); data->words_and = TRUE; for (i = 0; data->words[i] != NULL; i++) { data->word_strstr[i]=TRUE; text = data->words[i]; while(*text!=0) { if(*text=='\\' || *text=='?' || *text=='*') { data->word_strstr[i]=FALSE; break; } text++; } if (!data->word_strstr[i]) data->words_and = FALSE; } data->mime_types = nemo_query_get_mime_types (query); data->cancellable = g_cancellable_new (); return data; } static void search_thread_data_free (SearchThreadData *data) { g_queue_foreach (data->directories, (GFunc)g_object_unref, NULL); g_queue_free (data->directories); g_hash_table_destroy (data->visited); g_object_unref (data->cancellable); g_strfreev (data->words); g_free (data->word_strstr); g_list_free_full (data->mime_types, g_free); g_list_free_full (data->uri_hits, g_free); g_free (data); } static gboolean search_thread_done_idle (gpointer user_data) { SearchThreadData *data; data = user_data; if (!g_cancellable_is_cancelled (data->cancellable)) { nemo_search_engine_finished (NEMO_SEARCH_ENGINE (data->engine)); data->engine->details->active_search = NULL; } search_thread_data_free (data); return FALSE; } typedef struct { GList *uris; SearchThreadData *thread_data; } SearchHits; static gboolean search_thread_add_hits_idle (gpointer user_data) { SearchHits *hits; hits = user_data; if (!g_cancellable_is_cancelled (hits->thread_data->cancellable)) { nemo_search_engine_hits_added (NEMO_SEARCH_ENGINE (hits->thread_data->engine), hits->uris); } g_list_free_full (hits->uris, g_free); g_free (hits); return FALSE; } static void send_batch (SearchThreadData *data) { SearchHits *hits; data->n_processed_files = 0; if (data->uri_hits) { hits = g_new (SearchHits, 1); hits->uris = data->uri_hits; hits->thread_data = data; g_idle_add (search_thread_add_hits_idle, hits); } data->uri_hits = NULL; } static gboolean strwildcardcmp(char *a, char *b) { if (*a == 0 && *b == 0) return TRUE; while(*a!=0 && *b!=0) { if(*a=='\\') { // escaped character a++; if (*a != *b) return FALSE; } else { if (*a=='*') { if(*(a+1)==0) return TRUE; if(*b==0) return FALSE; if (strwildcardcmp(a+1, b) || strwildcardcmp(a, b+1)) return TRUE; else return FALSE; } else if (*a!='?' && (*a != *b)) return FALSE; } a++; b++; } if ((*a == 0 && *b == 0) || (*a=='*' && *(a+1)==0)) return TRUE; return FALSE; } #define STD_ATTRIBUTES \ G_FILE_ATTRIBUTE_STANDARD_NAME "," \ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," \ G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN "," \ G_FILE_ATTRIBUTE_STANDARD_TYPE "," \ G_FILE_ATTRIBUTE_ID_FILE static void visit_directory (GFile *dir, SearchThreadData *data) { GFileEnumerator *enumerator; GFileInfo *info; GFile *child; const char *mime_type, *display_name; char *lower_name, *normalized; gboolean hit; int i; GList *l; const char *id; gboolean visited; enumerator = g_file_enumerate_children (dir, data->mime_types != NULL ? STD_ATTRIBUTES "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE : STD_ATTRIBUTES , 0, data->cancellable, NULL); if (enumerator == NULL) { return; } while ((info = g_file_enumerator_next_file (enumerator, data->cancellable, NULL)) != NULL) { if (g_file_info_get_is_hidden (info)) { goto next; } display_name = g_file_info_get_display_name (info); if (display_name == NULL) { goto next; } normalized = g_utf8_normalize (display_name, -1, G_NORMALIZE_NFD); lower_name = g_utf8_strdown (normalized, -1); g_free (normalized); hit = data->words_and; for (i = 0; data->words[i] != NULL; i++) { if (data->word_strstr[i]) { if ((strstr (lower_name, data->words[i]) != NULL)^data->words_and) { hit = !data->words_and; break; } } else if (strwildcardcmp (data->words[i], lower_name)^data->words_and) { hit = !data->words_and; break; } } g_free (lower_name); if (hit && data->mime_types) { mime_type = g_file_info_get_content_type (info); hit = FALSE; for (l = data->mime_types; mime_type != NULL && l != NULL; l = l->next) { if (g_content_type_equals (mime_type, l->data)) { hit = TRUE; break; } } } child = g_file_get_child (dir, g_file_info_get_name (info)); if (hit) { data->uri_hits = g_list_prepend (data->uri_hits, g_file_get_uri (child)); } data->n_processed_files++; if (data->n_processed_files > BATCH_SIZE) { send_batch (data); } if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE); visited = FALSE; if (id) { if (g_hash_table_lookup_extended (data->visited, id, NULL, NULL)) { visited = TRUE; } else { g_hash_table_insert (data->visited, g_strdup (id), NULL); } } if (!visited) { g_queue_push_tail (data->directories, g_object_ref (child)); } } g_object_unref (child); next: g_object_unref (info); } g_object_unref (enumerator); } static gpointer search_thread_func (gpointer user_data) { SearchThreadData *data; GFile *dir; GFileInfo *info; const char *id; data = user_data; /* Insert id for toplevel directory into visited */ dir = g_queue_peek_head (data->directories); info = g_file_query_info (dir, G_FILE_ATTRIBUTE_ID_FILE, 0, data->cancellable, NULL); if (info) { id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE); if (id) { g_hash_table_insert (data->visited, g_strdup (id), NULL); } g_object_unref (info); } while (!g_cancellable_is_cancelled (data->cancellable) && (dir = g_queue_pop_head (data->directories)) != NULL) { visit_directory (dir, data); g_object_unref (dir); } send_batch (data); g_idle_add (search_thread_done_idle, data); return NULL; } static void nemo_search_engine_simple_start (NemoSearchEngine *engine) { NemoSearchEngineSimple *simple; SearchThreadData *data; GThread *thread; simple = NEMO_SEARCH_ENGINE_SIMPLE (engine); if (simple->details->active_search != NULL) { return; } if (simple->details->query == NULL) { return; } data = search_thread_data_new (simple, simple->details->query); thread = g_thread_new ("nemo-search-simple", search_thread_func, data); simple->details->active_search = data; g_thread_unref (thread); } static void nemo_search_engine_simple_stop (NemoSearchEngine *engine) { NemoSearchEngineSimple *simple; simple = NEMO_SEARCH_ENGINE_SIMPLE (engine); if (simple->details->active_search != NULL) { g_cancellable_cancel (simple->details->active_search->cancellable); simple->details->active_search = NULL; } } static void nemo_search_engine_simple_set_query (NemoSearchEngine *engine, NemoQuery *query) { NemoSearchEngineSimple *simple; simple = NEMO_SEARCH_ENGINE_SIMPLE (engine); if (query) { g_object_ref (query); } if (simple->details->query) { g_object_unref (simple->details->query); } simple->details->query = query; } static void nemo_search_engine_simple_class_init (NemoSearchEngineSimpleClass *class) { GObjectClass *gobject_class; NemoSearchEngineClass *engine_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = finalize; engine_class = NEMO_SEARCH_ENGINE_CLASS (class); engine_class->set_query = nemo_search_engine_simple_set_query; engine_class->start = nemo_search_engine_simple_start; engine_class->stop = nemo_search_engine_simple_stop; g_type_class_add_private (class, sizeof (NemoSearchEngineSimpleDetails)); } static void nemo_search_engine_simple_init (NemoSearchEngineSimple *engine) { engine->details = G_TYPE_INSTANCE_GET_PRIVATE (engine, NEMO_TYPE_SEARCH_ENGINE_SIMPLE, NemoSearchEngineSimpleDetails); } NemoSearchEngine * nemo_search_engine_simple_new (void) { NemoSearchEngine *engine; engine = g_object_new (NEMO_TYPE_SEARCH_ENGINE_SIMPLE, NULL); return engine; } nemo-3.6.5/libnemo-private/nemo-cell-renderer-disk.h0000664000175000017500000000421213215733314021265 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 2007 Martin Wehner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Martin Wehner */ #ifndef NEMO_CELL_RENDERER_DISK_H #define NEMO_CELL_RENDERER_DISK_H #include #define NEMO_TYPE_CELL_RENDERER_DISK nemo_cell_renderer_disk_get_type() #define NEMO_CELL_RENDERER_DISK(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_CELL_RENDERER_DISK, NemoCellRendererDisk)) #define NEMO_CELL_RENDERER_DISK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_CELL_RENDERER_DISK, NemoCellRendererDiskClass)) #define NEMO_IS_CELL_RENDERER_DISK(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_CELL_RENDERER_DISK)) #define NEMO_IS_CELL_RENDERER_DISK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_CELL_RENDERER_DISK)) #define NEMO_CELL_RENDERER_DISK_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_CELL_RENDERER_DISK, NemoCellRendererDiskClass)) typedef struct _NemoCellRendererDisk NemoCellRendererDisk; typedef struct _NemoCellRendererDiskClass NemoCellRendererDiskClass; struct _NemoCellRendererDisk { GtkCellRendererText parent; guint disk_full_percent; gboolean show_disk_full_percent; }; struct _NemoCellRendererDiskClass { GtkCellRendererTextClass parent_class; }; GType nemo_cell_renderer_disk_get_type (void); GtkCellRenderer *nemo_cell_renderer_disk_new (void); #endif /* NEMO_CELL_RENDERER_DISK_H */ nemo-3.6.5/libnemo-private/nemo-monitor.h0000664000175000017500000000245313215733314017306 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-monitor.h: file and directory change monitoring for nemo Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Seth Nickell Darin Adler */ #ifndef NEMO_MONITOR_H #define NEMO_MONITOR_H #include #include typedef struct NemoMonitor NemoMonitor; gboolean nemo_monitor_active (void); NemoMonitor *nemo_monitor_directory (GFile *location); void nemo_monitor_cancel (NemoMonitor *monitor); #endif /* NEMO_MONITOR_H */ nemo-3.6.5/libnemo-private/nemo-desktop-directory-file.c0000664000175000017500000004352713215733314022211 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-directory-file.c: Subclass of NemoFile to help implement the virtual desktop. Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-desktop-directory-file.h" #include "nemo-desktop-metadata.h" #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include #include "nemo-desktop-directory.h" #include "nemo-metadata.h" #include #include #include struct NemoDesktopDirectoryFileDetails { NemoDesktopDirectory *desktop_directory; NemoFile *real_dir_file; GHashTable *callbacks; GHashTable *monitors; }; typedef struct { NemoDesktopDirectoryFile *desktop_file; NemoFileCallback callback; gpointer callback_data; NemoFileAttributes delegated_attributes; NemoFileAttributes non_delegated_attributes; GList *non_ready_files; gboolean initializing; } DesktopCallback; typedef struct { NemoDesktopDirectoryFile *desktop_file; NemoFileAttributes delegated_attributes; NemoFileAttributes non_delegated_attributes; } DesktopMonitor; G_DEFINE_TYPE (NemoDesktopDirectoryFile, nemo_desktop_directory_file, NEMO_TYPE_FILE); static gchar * get_indexed_key (NemoFile *file) { NemoDesktopDirectory *desktop_directory; gchar *indexed_key; desktop_directory = NEMO_DESKTOP_DIRECTORY_FILE (file)->details->desktop_directory; indexed_key = g_strdup_printf ("desktop-monitor-%d", NEMO_DESKTOP_DIRECTORY (desktop_directory)->display_number); return indexed_key; } static guint desktop_callback_hash (gconstpointer desktop_callback_as_pointer) { const DesktopCallback *desktop_callback; desktop_callback = desktop_callback_as_pointer; return GPOINTER_TO_UINT (desktop_callback->callback) ^ GPOINTER_TO_UINT (desktop_callback->callback_data); } static gboolean desktop_callback_equal (gconstpointer desktop_callback_as_pointer, gconstpointer desktop_callback_as_pointer_2) { const DesktopCallback *desktop_callback, *desktop_callback_2; desktop_callback = desktop_callback_as_pointer; desktop_callback_2 = desktop_callback_as_pointer_2; return desktop_callback->callback == desktop_callback_2->callback && desktop_callback->callback_data == desktop_callback_2->callback_data; } static void real_file_changed_callback (NemoFile *real_file, gpointer callback_data) { NemoDesktopDirectoryFile *desktop_file; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (callback_data); nemo_file_changed (NEMO_FILE (desktop_file)); } static NemoFileAttributes get_delegated_attributes_mask (void) { return NEMO_FILE_ATTRIBUTE_DEEP_COUNTS | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES; } static void partition_attributes (NemoFileAttributes attributes, NemoFileAttributes *delegated_attributes, NemoFileAttributes *non_delegated_attributes) { NemoFileAttributes mask; mask = get_delegated_attributes_mask (); *delegated_attributes = attributes & mask; *non_delegated_attributes = attributes & ~mask; } static void desktop_directory_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes) { NemoDesktopDirectoryFile *desktop_file; DesktopMonitor *monitor; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); /* Map the client to a unique value so this doesn't interfere * with direct monitoring of the file by the same client. */ monitor = g_hash_table_lookup (desktop_file->details->monitors, client); if (monitor != NULL) { g_assert (monitor->desktop_file == desktop_file); } else { monitor = g_new0 (DesktopMonitor, 1); monitor->desktop_file = desktop_file; g_hash_table_insert (desktop_file->details->monitors, (gpointer) client, monitor); } partition_attributes (attributes, &monitor->delegated_attributes, &monitor->non_delegated_attributes); /* Pawn off partioned attributes to real dir file */ nemo_file_monitor_add (desktop_file->details->real_dir_file, monitor, monitor->delegated_attributes); /* Do the rest ourself */ nemo_directory_monitor_add_internal (file->details->directory, file, client, TRUE, monitor->non_delegated_attributes, NULL, NULL); } static void desktop_directory_file_monitor_remove (NemoFile *file, gconstpointer client) { NemoDesktopDirectoryFile *desktop_file; DesktopMonitor *monitor; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); /* Map the client to the value used by the earlier add call. */ monitor = g_hash_table_lookup (desktop_file->details->monitors, client); if (monitor == NULL) { return; } /* Call through to the real file remove calls. */ g_hash_table_remove (desktop_file->details->monitors, client); /* Remove the locally handled parts */ nemo_directory_monitor_remove_internal (file->details->directory, file, client); } static void desktop_callback_destroy (DesktopCallback *desktop_callback) { g_assert (desktop_callback != NULL); g_assert (NEMO_IS_DESKTOP_DIRECTORY_FILE (desktop_callback->desktop_file)); nemo_file_unref (NEMO_FILE (desktop_callback->desktop_file)); g_list_free (desktop_callback->non_ready_files); g_free (desktop_callback); } static void desktop_callback_check_done (DesktopCallback *desktop_callback) { NemoFile *file; /* Check if we are ready. */ if (desktop_callback->initializing || desktop_callback->non_ready_files != NULL) { return; } /* Ensure our metadata is updated before calling back */ file = NEMO_FILE (desktop_callback->desktop_file); nemo_desktop_update_metadata_from_keyfile (file, get_indexed_key (file)); /* Remove from the hash table before sending it. */ g_hash_table_remove (desktop_callback->desktop_file->details->callbacks, desktop_callback); /* We are ready, so do the real callback. */ (* desktop_callback->callback) (NEMO_FILE (desktop_callback->desktop_file), desktop_callback->callback_data); /* And we are done. */ desktop_callback_destroy (desktop_callback); } static void desktop_callback_remove_file (DesktopCallback *desktop_callback, NemoFile *file) { desktop_callback->non_ready_files = g_list_remove (desktop_callback->non_ready_files, file); desktop_callback_check_done (desktop_callback); } static void ready_callback (NemoFile *file, gpointer callback_data) { DesktopCallback *desktop_callback; g_assert (NEMO_IS_FILE (file)); g_assert (callback_data != NULL); desktop_callback = callback_data; g_assert (g_list_find (desktop_callback->non_ready_files, file) != NULL); desktop_callback_remove_file (desktop_callback, file); } static void desktop_directory_file_call_when_ready (NemoFile *file, NemoFileAttributes attributes, NemoFileCallback callback, gpointer callback_data) { NemoDesktopDirectoryFile *desktop_file; DesktopCallback search_key, *desktop_callback; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); /* Check to be sure we aren't overwriting. */ search_key.callback = callback; search_key.callback_data = callback_data; if (g_hash_table_lookup (desktop_file->details->callbacks, &search_key) != NULL) { g_warning ("tried to add a new callback while an old one was pending"); return; } /* Create a desktop_callback record. */ desktop_callback = g_new0 (DesktopCallback, 1); nemo_file_ref (file); desktop_callback->desktop_file = desktop_file; desktop_callback->callback = callback; desktop_callback->callback_data = callback_data; desktop_callback->initializing = TRUE; partition_attributes (attributes, &desktop_callback->delegated_attributes, &desktop_callback->non_delegated_attributes); desktop_callback->non_ready_files = g_list_prepend (desktop_callback->non_ready_files, file); desktop_callback->non_ready_files = g_list_prepend (desktop_callback->non_ready_files, desktop_file->details->real_dir_file); /* Put it in the hash table. */ g_hash_table_insert (desktop_file->details->callbacks, desktop_callback, desktop_callback); /* Now connect to each file's call_when_ready. */ nemo_directory_call_when_ready_internal (file->details->directory, file, desktop_callback->non_delegated_attributes, FALSE, NULL, ready_callback, desktop_callback); nemo_file_call_when_ready (desktop_file->details->real_dir_file, desktop_callback->delegated_attributes, ready_callback, desktop_callback); desktop_callback->initializing = FALSE; /* Check if any files became read while we were connecting up * the call_when_ready callbacks (also handles the pathological * case where there are no files at all). */ desktop_callback_check_done (desktop_callback); } static void desktop_directory_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data) { NemoDesktopDirectoryFile *desktop_file; DesktopCallback search_key, *desktop_callback; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); /* Find the entry in the table. */ search_key.callback = callback; search_key.callback_data = callback_data; desktop_callback = g_hash_table_lookup (desktop_file->details->callbacks, &search_key); if (desktop_callback == NULL) { return; } /* Remove from the hash table before working with it. */ g_hash_table_remove (desktop_callback->desktop_file->details->callbacks, desktop_callback); /* Tell the real directory to cancel the call. */ nemo_directory_cancel_callback_internal (file->details->directory, file, NULL, ready_callback, desktop_callback); nemo_file_cancel_call_when_ready (desktop_file->details->real_dir_file, ready_callback, desktop_callback); desktop_callback_destroy (desktop_callback); } static gboolean real_check_if_ready (NemoFile *file, NemoFileAttributes attributes) { return nemo_directory_check_if_ready_internal (file->details->directory, file, attributes); } static gboolean desktop_directory_file_check_if_ready (NemoFile *file, NemoFileAttributes attributes) { NemoFileAttributes delegated_attributes, non_delegated_attributes; NemoDesktopDirectoryFile *desktop_file; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); partition_attributes (attributes, &delegated_attributes, &non_delegated_attributes); return real_check_if_ready (file, non_delegated_attributes) && nemo_file_check_if_ready (desktop_file->details->real_dir_file, delegated_attributes); } static gboolean desktop_directory_file_get_item_count (NemoFile *file, guint *count, gboolean *count_unreadable) { NemoDesktopDirectoryFile *desktop_file; gboolean got_count; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); got_count = nemo_file_get_directory_item_count (desktop_file->details->real_dir_file, count, count_unreadable); if (count) { *count += g_list_length (file->details->directory->details->file_list); } return got_count; } static NemoRequestStatus desktop_directory_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size) { NemoDesktopDirectoryFile *desktop_file; NemoRequestStatus status; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); status = nemo_file_get_deep_counts (desktop_file->details->real_dir_file, directory_count, file_count, unreadable_directory_count, hidden_count, total_size, TRUE); if (file_count) { *file_count += g_list_length (file->details->directory->details->file_list); } return status; } static gboolean desktop_directory_file_get_date (NemoFile *file, NemoDateType date_type, time_t *date) { NemoDesktopDirectoryFile *desktop_file; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (file); return nemo_file_get_date (desktop_file->details->real_dir_file, date_type, date); } static char * desktop_directory_file_get_where_string (NemoFile *file) { return g_strdup (_("on the desktop")); } static void monitor_destroy (gpointer data) { DesktopMonitor *monitor = data; nemo_file_monitor_remove (NEMO_FILE (monitor->desktop_file->details->real_dir_file), monitor); g_free (monitor); } static void nemo_desktop_directory_file_set_metadata (NemoFile *file, const char *key, const char *value) { gchar *name; name = get_indexed_key (file); nemo_desktop_set_metadata_string (file, name, key, value); g_free (name); } static void nemo_desktop_directory_file_set_metadata_as_list (NemoFile *file, const char *key, char **value) { gchar *name; name = get_indexed_key (file); nemo_desktop_set_metadata_stringv (file, name, key, (const gchar **) value); g_free (name); } static gchar * nemo_desktop_directory_file_get_metadata (NemoFile *file, const char *key) { gchar *name; gchar *string; name = get_indexed_key (file); string = nemo_desktop_get_metadata_string (file, name, key); g_free (name); return string; } static gchar ** nemo_desktop_directory_file_get_metadata_as_list (NemoFile *file, const char *key) { gchar *name; gchar **stringv; name = get_indexed_key (file); stringv = nemo_desktop_get_metadata_stringv (file, name, key); g_free (name); return stringv; } static void nemo_desktop_directory_file_init (NemoDesktopDirectoryFile *desktop_file) { NemoDesktopDirectory *desktop_directory; NemoDirectory *real_dir; NemoFile *real_dir_file; desktop_file->details = G_TYPE_INSTANCE_GET_PRIVATE (desktop_file, NEMO_TYPE_DESKTOP_DIRECTORY_FILE, NemoDesktopDirectoryFileDetails); desktop_directory = NEMO_DESKTOP_DIRECTORY (nemo_directory_get_by_uri (EEL_DESKTOP_URI)); desktop_file->details->desktop_directory = desktop_directory; desktop_file->details->callbacks = g_hash_table_new (desktop_callback_hash, desktop_callback_equal); desktop_file->details->monitors = g_hash_table_new_full (NULL, NULL, NULL, monitor_destroy); real_dir = nemo_desktop_directory_get_real_directory (desktop_directory); real_dir_file = nemo_directory_get_corresponding_file (real_dir); nemo_directory_unref (real_dir); desktop_file->details->real_dir_file = real_dir_file; g_signal_connect_object (real_dir_file, "changed", G_CALLBACK (real_file_changed_callback), desktop_file, 0); } static void desktop_callback_remove_file_cover (gpointer key, gpointer value, gpointer callback_data) { desktop_callback_remove_file (value, NEMO_FILE (callback_data)); } static void desktop_finalize (GObject *object) { NemoDesktopDirectoryFile *desktop_file; NemoDesktopDirectory *desktop_directory; desktop_file = NEMO_DESKTOP_DIRECTORY_FILE (object); desktop_directory = desktop_file->details->desktop_directory; /* Todo: ghash now safe? */ eel_g_hash_table_safe_for_each (desktop_file->details->callbacks, desktop_callback_remove_file_cover, desktop_file->details->real_dir_file); if (g_hash_table_size (desktop_file->details->callbacks) != 0) { g_warning ("call_when_ready still pending when desktop virtual file is destroyed"); } g_hash_table_destroy (desktop_file->details->callbacks); g_hash_table_destroy (desktop_file->details->monitors); nemo_file_unref (desktop_file->details->real_dir_file); nemo_directory_unref (NEMO_DIRECTORY (desktop_directory)); G_OBJECT_CLASS (nemo_desktop_directory_file_parent_class)->finalize (object); } static void nemo_desktop_directory_file_class_init (NemoDesktopDirectoryFileClass *klass) { GObjectClass *object_class; NemoFileClass *file_class; object_class = G_OBJECT_CLASS (klass); file_class = NEMO_FILE_CLASS (klass); object_class->finalize = desktop_finalize; file_class->default_file_type = G_FILE_TYPE_DIRECTORY; file_class->monitor_add = desktop_directory_file_monitor_add; file_class->monitor_remove = desktop_directory_file_monitor_remove; file_class->call_when_ready = desktop_directory_file_call_when_ready; file_class->cancel_call_when_ready = desktop_directory_file_cancel_call_when_ready; file_class->check_if_ready = desktop_directory_file_check_if_ready; file_class->get_item_count = desktop_directory_file_get_item_count; file_class->get_deep_counts = desktop_directory_file_get_deep_counts; file_class->get_date = desktop_directory_file_get_date; file_class->get_where_string = desktop_directory_file_get_where_string; file_class->set_metadata = nemo_desktop_directory_file_set_metadata; file_class->get_metadata = nemo_desktop_directory_file_get_metadata; file_class->set_metadata_as_list = nemo_desktop_directory_file_set_metadata_as_list; file_class->get_metadata_as_list = nemo_desktop_directory_file_get_metadata_as_list; g_type_class_add_private (klass, sizeof (NemoDesktopDirectoryFileDetails)); } nemo-3.6.5/libnemo-private/nemo-default-file-icon.h0000664000175000017500000000224213215733314021102 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Default file icon used by the icon factory. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_DEFAULT_FILE_ICON_H #define NEMO_DEFAULT_FILE_ICON_H extern const int nemo_default_file_icon_width; extern const int nemo_default_file_icon_height; extern const unsigned char nemo_default_file_icon[]; #endif /* NEMO_DEFAULT_FILE_ICON_H */ nemo-3.6.5/libnemo-private/nemo-recent.c0000664000175000017500000000421513215733314017070 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2002 James Willcox * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, * Boston, MA 02110-1335, USA. */ #include "nemo-recent.h" #include #define DEFAULT_APP_EXEC "gnome-open %u" static GtkRecentManager * nemo_recent_get_manager (void) { static GtkRecentManager *manager = NULL; if (manager == NULL) { manager = gtk_recent_manager_get_default (); } return manager; } void nemo_recent_add_file (NemoFile *file, GAppInfo *application) { GtkRecentData recent_data; char *uri; uri = nemo_file_get_activation_uri (file); if (uri == NULL) { uri = nemo_file_get_uri (file); } /* do not add trash:// etc */ if (eel_uri_is_trash (uri) || eel_uri_is_search (uri) || eel_uri_is_recent (uri) || eel_uri_is_desktop (uri)) { g_free (uri); return; } recent_data.display_name = NULL; recent_data.description = NULL; recent_data.mime_type = nemo_file_get_mime_type (file); recent_data.app_name = g_strdup (g_get_application_name ()); if (application != NULL) recent_data.app_exec = g_strdup (g_app_info_get_commandline (application)); else recent_data.app_exec = g_strdup (DEFAULT_APP_EXEC); recent_data.groups = NULL; recent_data.is_private = FALSE; gtk_recent_manager_add_full (nemo_recent_get_manager (), uri, &recent_data); g_free (recent_data.mime_type); g_free (recent_data.app_name); g_free (recent_data.app_exec); g_free (uri); } nemo-3.6.5/libnemo-private/nemo-query.h0000664000175000017500000000502313215733314016760 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Novell, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Anders Carlsson * */ #ifndef NEMO_QUERY_H #define NEMO_QUERY_H #include #define NEMO_TYPE_QUERY (nemo_query_get_type ()) #define NEMO_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_QUERY, NemoQuery)) #define NEMO_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_QUERY, NemoQueryClass)) #define NEMO_IS_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_QUERY)) #define NEMO_IS_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_QUERY)) #define NEMO_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_QUERY, NemoQueryClass)) typedef struct NemoQueryDetails NemoQueryDetails; typedef struct NemoQuery { GObject parent; NemoQueryDetails *details; } NemoQuery; typedef struct { GObjectClass parent_class; } NemoQueryClass; GType nemo_query_get_type (void); gboolean nemo_query_enabled (void); NemoQuery* nemo_query_new (void); char * nemo_query_get_text (NemoQuery *query); void nemo_query_set_text (NemoQuery *query, const char *text); char * nemo_query_get_location (NemoQuery *query); void nemo_query_set_location (NemoQuery *query, const char *uri); GList * nemo_query_get_mime_types (NemoQuery *query); void nemo_query_set_mime_types (NemoQuery *query, GList *mime_types); void nemo_query_add_mime_type (NemoQuery *query, const char *mime_type); char * nemo_query_to_readable_string (NemoQuery *query); NemoQuery *nemo_query_load (char *file); gboolean nemo_query_save (NemoQuery *query, char *file); #endif /* NEMO_QUERY_H */ nemo-3.6.5/libnemo-private/nemo-merged-directory.h0000664000175000017500000000536013215733314021064 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-merged-directory.h: Subclass of NemoDirectory to implement a virtual directory consisting of the merged contents of some real directories. Copyright (C) 1999, 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_MERGED_DIRECTORY_H #define NEMO_MERGED_DIRECTORY_H #include #define NEMO_TYPE_MERGED_DIRECTORY nemo_merged_directory_get_type() #define NEMO_MERGED_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_MERGED_DIRECTORY, NemoMergedDirectory)) #define NEMO_MERGED_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_MERGED_DIRECTORY, NemoMergedDirectoryClass)) #define NEMO_IS_MERGED_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_MERGED_DIRECTORY)) #define NEMO_IS_MERGED_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_MERGED_DIRECTORY)) #define NEMO_MERGED_DIRECTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_MERGED_DIRECTORY, NemoMergedDirectoryClass)) typedef struct NemoMergedDirectoryDetails NemoMergedDirectoryDetails; typedef struct { NemoDirectory parent_slot; NemoMergedDirectoryDetails *details; } NemoMergedDirectory; typedef struct { NemoDirectoryClass parent_slot; void (* add_real_directory) (NemoMergedDirectory *merged_directory, NemoDirectory *real_directory); void (* remove_real_directory) (NemoMergedDirectory *merged_directory, NemoDirectory *real_directory); } NemoMergedDirectoryClass; GType nemo_merged_directory_get_type (void); void nemo_merged_directory_add_real_directory (NemoMergedDirectory *merged_directory, NemoDirectory *real_directory); void nemo_merged_directory_remove_real_directory (NemoMergedDirectory *merged_directory, NemoDirectory *real_directory); GList * nemo_merged_directory_get_real_directories (NemoMergedDirectory *merged_directory); #endif /* NEMO_MERGED_DIRECTORY_H */ nemo-3.6.5/libnemo-private/nemo-action-manager.h0000664000175000017500000000442313215733314020503 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_ACTION_MANAGER_H #define NEMO_ACTION_MANAGER_H #include #include "nemo-file.h" #define NEMO_TYPE_ACTION_MANAGER nemo_action_manager_get_type() #define NEMO_ACTION_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ACTION_MANAGER, NemoActionManager)) #define NEMO_ACTION_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ACTION_MANAGER, NemoActionManagerClass)) #define NEMO_IS_ACTION_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ACTION_MANAGER)) #define NEMO_IS_ACTION_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ACTION_MANAGER)) #define NEMO_ACTION_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ACTION_MANAGER, NemoActionManagerClass)) typedef struct _NemoActionManager NemoActionManager; typedef struct _NemoActionManagerClass NemoActionManagerClass; struct _NemoActionManager { GObject parent; GList *actions; GList *actions_directory_list; gboolean action_list_dirty; }; struct _NemoActionManagerClass { GObjectClass parent_class; void (* changed) (NemoActionManager *action_manager); }; GType nemo_action_manager_get_type (void); NemoActionManager *nemo_action_manager_new (void); GList * nemo_action_manager_list_actions (NemoActionManager *action_manager); gchar * nemo_action_manager_get_user_directory_path (void); gchar * nemo_action_manager_get_sys_directory_path (void); #endif /* NEMO_ACTION_MANAGER_H */ nemo-3.6.5/libnemo-private/nemo-icon-canvas-item.c0000664000175000017500000025502313215733314020752 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* Nemo - Icon canvas item class for icon container. * * Copyright (C) 2000 Eazel, Inc * * Author: Andy Hertzfeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include #include "nemo-icon-canvas-item.h" #include #include "nemo-file-utilities.h" #include "nemo-global-preferences.h" #include "nemo-icon-private.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* gap between bottom of icon and start of text box */ #define LABEL_OFFSET 1 #define LABEL_LINE_SPACING 0 /* special text height handling * each item has three text height variables: * + text_height: actual height of the displayed (i.e. on-screen) PangoLayout. * + text_height_for_layout: height used in icon grid layout algorithms. * “sane amount†of text. * “sane amount“ as of * + hard-coded to three lines in text-below-icon mode. * + unlimited in text-besides-icon mode (see VOODOO-TODO) * * This layout height is used by grid layout algorithms, even * though the actually displayed and/or requested text size may be larger * and overlap adjacent icons, if an icon is selected. * * + text_height_for_entire_text: height needed to display the entire PangoLayout, * if it wasn't ellipsized. */ /* Private part of the NemoIconCanvasItem structure. */ struct NemoIconCanvasItemDetails { /* The image, text, font. */ double x, y; GdkPixbuf *pixbuf; cairo_surface_t *rendered_surface; char *editable_text; /* Text that can be modified by a renaming function */ char *additional_text; /* Text that cannot be modifed, such as file size, etc. */ GdkPoint *attach_points; int n_attach_points; /* Size of the text at current font. */ int text_dx; int text_width; /* actual size required for rendering the text to display */ int text_height; /* actual size that would be required for rendering the entire text if it wasn't ellipsized */ int text_height_for_entire_text; /* actual size needed for rendering a “sane amount†of text */ int text_height_for_layout; int editable_text_height; /* whether the entire text must always be visible. In that case, * text_height_for_layout will always be equal to text_height. * Used for the last line of a line-wise icon layout. */ guint entire_text : 1; /* Highlight state. */ guint is_highlighted_for_selection : 1; guint is_highlighted_as_keyboard_focus: 1; guint is_highlighted_for_drop : 1; guint is_highlighted_for_clipboard : 1; guint show_stretch_handles : 1; guint is_prelit : 1; guint rendered_is_highlighted_for_selection : 1; guint rendered_is_highlighted_for_drop : 1; guint rendered_is_highlighted_for_clipboard : 1; guint rendered_is_prelit : 1; guint rendered_is_focused : 1; guint is_renaming : 1; guint bounds_cached : 1; guint is_visible : 1; GdkRectangle embedded_text_rect; char *embedded_text; /* Cached PangoLayouts. Only used if the icon is visible */ PangoLayout *editable_text_layout; PangoLayout *additional_text_layout; PangoLayout *embedded_text_layout; /* Cached rectangle in canvas coordinates */ EelIRect canvas_rect; EelIRect text_rect; EelIRect bounds_cache; EelIRect bounds_cache_for_layout; EelIRect bounds_cache_for_entire_item; GdkWindow *cursor_window; /* Accessibility bits */ GailTextUtil *text_util; }; /* Object argument IDs. */ enum { PROP_0, PROP_EDITABLE_TEXT, PROP_ADDITIONAL_TEXT, PROP_HIGHLIGHTED_FOR_SELECTION, PROP_HIGHLIGHTED_AS_KEYBOARD_FOCUS, PROP_HIGHLIGHTED_FOR_DROP, PROP_HIGHLIGHTED_FOR_CLIPBOARD }; typedef enum { RIGHT_SIDE, BOTTOM_SIDE, LEFT_SIDE, TOP_SIDE } RectangleSide; static void nemo_icon_canvas_item_text_interface_init (EelAccessibleTextIface *iface); static GType nemo_icon_canvas_item_accessible_factory_get_type (void); G_DEFINE_TYPE_WITH_CODE (NemoIconCanvasItem, nemo_icon_canvas_item, EEL_TYPE_CANVAS_ITEM, G_IMPLEMENT_INTERFACE (EEL_TYPE_ACCESSIBLE_TEXT, nemo_icon_canvas_item_text_interface_init)); /* private */ static void draw_label_text (NemoIconCanvasItem *item, cairo_t *cr, EelIRect icon_rect); static void measure_label_text (NemoIconCanvasItem *item); static void draw_pixbuf (GdkPixbuf *pixbuf, cairo_t *cr, int x, int y); static PangoLayout *get_label_layout (PangoLayout **layout, NemoIconCanvasItem *item, const char *text); static gboolean hit_test_stretch_handle (NemoIconCanvasItem *item, EelIRect canvas_rect, GtkCornerType *corner); static void draw_embedded_text (NemoIconCanvasItem *icon_item, cairo_t *cr, int x, int y); static void nemo_icon_canvas_item_ensure_bounds_up_to_date (NemoIconCanvasItem *icon_item); /* Object initialization function for the icon item. */ static void nemo_icon_canvas_item_init (NemoIconCanvasItem *icon_item) { icon_item->details = G_TYPE_INSTANCE_GET_PRIVATE ((icon_item), NEMO_TYPE_ICON_CANVAS_ITEM, NemoIconCanvasItemDetails); nemo_icon_canvas_item_invalidate_label_size (icon_item); } static void nemo_icon_canvas_item_finalize (GObject *object) { NemoIconCanvasItemDetails *details; g_assert (NEMO_IS_ICON_CANVAS_ITEM (object)); details = NEMO_ICON_CANVAS_ITEM (object)->details; if (details->cursor_window != NULL) { gdk_window_set_cursor (details->cursor_window, NULL); g_object_unref (details->cursor_window); } if (details->pixbuf != NULL) { g_object_unref (details->pixbuf); } if (details->text_util != NULL) { g_object_unref (details->text_util); } g_free (details->editable_text); g_free (details->additional_text); g_free (details->attach_points); if (details->rendered_surface != NULL) { cairo_surface_destroy (details->rendered_surface); } if (details->editable_text_layout != NULL) { g_object_unref (details->editable_text_layout); } if (details->additional_text_layout != NULL) { g_object_unref (details->additional_text_layout); } if (details->embedded_text_layout != NULL) { g_object_unref (details->embedded_text_layout); } g_free (details->embedded_text); G_OBJECT_CLASS (nemo_icon_canvas_item_parent_class)->finalize (object); } /* Currently we require pixbufs in this format (for hit testing). * Perhaps gdk-pixbuf will be changed so it can do the hit testing * and we won't have this requirement any more. */ static gboolean pixbuf_is_acceptable (GdkPixbuf *pixbuf) { return gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB && ((!gdk_pixbuf_get_has_alpha (pixbuf) && gdk_pixbuf_get_n_channels (pixbuf) == 3) || (gdk_pixbuf_get_has_alpha (pixbuf) && gdk_pixbuf_get_n_channels (pixbuf) == 4)) && gdk_pixbuf_get_bits_per_sample (pixbuf) == 8; } static void nemo_icon_canvas_item_invalidate_bounds_cache (NemoIconCanvasItem *item) { item->details->bounds_cached = FALSE; } /* invalidate the text width and height cached in the item details. */ void nemo_icon_canvas_item_invalidate_label_size (NemoIconCanvasItem *item) { if (item->details->editable_text_layout != NULL) { pango_layout_context_changed (item->details->editable_text_layout); } if (item->details->additional_text_layout != NULL) { pango_layout_context_changed (item->details->additional_text_layout); } if (item->details->embedded_text_layout != NULL) { pango_layout_context_changed (item->details->embedded_text_layout); } nemo_icon_canvas_item_invalidate_bounds_cache (item); item->details->text_width = -1; item->details->text_height = -1; item->details->text_height_for_layout = -1; item->details->text_height_for_entire_text = -1; item->details->editable_text_height = -1; } /* Set property handler for the icon item. */ static void nemo_icon_canvas_item_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { NemoIconCanvasItem *item; NemoIconCanvasItemDetails *details; AtkObject *accessible; item = NEMO_ICON_CANVAS_ITEM (object); accessible = atk_gobject_accessible_for_object (G_OBJECT (item)); details = item->details; switch (property_id) { case PROP_EDITABLE_TEXT: if (g_strcmp0 (details->editable_text, g_value_get_string (value)) == 0) { return; } g_free (details->editable_text); details->editable_text = g_strdup (g_value_get_string (value)); if (details->text_util) { gail_text_util_text_setup (details->text_util, details->editable_text); g_object_notify (G_OBJECT(accessible), "accessible-name"); } nemo_icon_canvas_item_invalidate_label_size (item); if (details->editable_text_layout) { g_object_unref (details->editable_text_layout); details->editable_text_layout = NULL; } break; case PROP_ADDITIONAL_TEXT: if (g_strcmp0 (details->additional_text, g_value_get_string (value)) == 0) { return; } g_free (details->additional_text); details->additional_text = g_strdup (g_value_get_string (value)); nemo_icon_canvas_item_invalidate_label_size (item); if (details->additional_text_layout) { g_object_unref (details->additional_text_layout); details->additional_text_layout = NULL; } break; case PROP_HIGHLIGHTED_FOR_SELECTION: if (!details->is_highlighted_for_selection == !g_value_get_boolean (value)) { return; } details->is_highlighted_for_selection = g_value_get_boolean (value); nemo_icon_canvas_item_invalidate_label_size (item); atk_object_notify_state_change (accessible, ATK_STATE_SELECTED, details->is_highlighted_for_selection); break; case PROP_HIGHLIGHTED_AS_KEYBOARD_FOCUS: if (!details->is_highlighted_as_keyboard_focus == !g_value_get_boolean (value)) { return; } details->is_highlighted_as_keyboard_focus = g_value_get_boolean (value); if (details->is_highlighted_as_keyboard_focus) { atk_focus_tracker_notify (accessible); } break; case PROP_HIGHLIGHTED_FOR_DROP: if (!details->is_highlighted_for_drop == !g_value_get_boolean (value)) { return; } details->is_highlighted_for_drop = g_value_get_boolean (value); nemo_icon_canvas_item_invalidate_label_size (item); break; case PROP_HIGHLIGHTED_FOR_CLIPBOARD: if (!details->is_highlighted_for_clipboard == !g_value_get_boolean (value)) { return; } details->is_highlighted_for_clipboard = g_value_get_boolean (value); break; default: g_warning ("nemo_icons_view_item_item_set_arg on unknown argument"); return; } eel_canvas_item_request_update (EEL_CANVAS_ITEM (object)); } /* Get property handler for the icon item */ static void nemo_icon_canvas_item_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { NemoIconCanvasItemDetails *details; details = NEMO_ICON_CANVAS_ITEM (object)->details; switch (property_id) { case PROP_EDITABLE_TEXT: g_value_set_string (value, details->editable_text); break; case PROP_ADDITIONAL_TEXT: g_value_set_string (value, details->additional_text); break; case PROP_HIGHLIGHTED_FOR_SELECTION: g_value_set_boolean (value, details->is_highlighted_for_selection); break; case PROP_HIGHLIGHTED_AS_KEYBOARD_FOCUS: g_value_set_boolean (value, details->is_highlighted_as_keyboard_focus); break; case PROP_HIGHLIGHTED_FOR_DROP: g_value_set_boolean (value, details->is_highlighted_for_drop); break; case PROP_HIGHLIGHTED_FOR_CLIPBOARD: g_value_set_boolean (value, details->is_highlighted_for_clipboard); break; default: g_warning ("invalid property %d", property_id); break; } } static void get_scaled_icon_size (NemoIconCanvasItem *item, gint *width, gint *height) { EelCanvas *canvas; GdkPixbuf *pixbuf = NULL; gint scale; scale = 1.0; if (item != NULL) { canvas = EEL_CANVAS_ITEM (item)->canvas; scale = gtk_widget_get_scale_factor (GTK_WIDGET (canvas)); pixbuf = item->details->pixbuf; } if (width) *width = (pixbuf == NULL) ? 0 : (gdk_pixbuf_get_width (pixbuf) / scale); if (height) *height = (pixbuf == NULL) ? 0 : (gdk_pixbuf_get_height (pixbuf) / scale); } cairo_surface_t * nemo_icon_canvas_item_get_drag_surface (NemoIconCanvasItem *item) { cairo_surface_t *surface; EelCanvas *canvas; int width, height; int pix_width, pix_height; int item_offset_x, item_offset_y; EelIRect icon_rect; double item_x, item_y; cairo_t *cr; GtkStyleContext *context; cairo_surface_t *drag_surface; g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), NULL); canvas = EEL_CANVAS_ITEM (item)->canvas; context = gtk_widget_get_style_context (GTK_WIDGET (canvas)); gtk_style_context_save (context); gtk_style_context_add_class (context, "nemo-canvas-item"); /* Assume we're updated so canvas item data is right */ /* Calculate the offset from the top-left corner of the new image to the item position (where the pixmap is placed) */ eel_canvas_world_to_window (canvas, item->details->x, item->details->y, &item_x, &item_y); item_offset_x = item_x - EEL_CANVAS_ITEM (item)->x1; item_offset_y = item_y - EEL_CANVAS_ITEM (item)->y1; /* Calculate the width of the item */ width = EEL_CANVAS_ITEM (item)->x2 - EEL_CANVAS_ITEM (item)->x1; height = EEL_CANVAS_ITEM (item)->y2 - EEL_CANVAS_ITEM (item)->y1; surface = gdk_window_create_similar_surface (gtk_widget_get_window (GTK_WIDGET (canvas)), CAIRO_CONTENT_COLOR_ALPHA, width, height); cr = cairo_create (surface); drag_surface = gdk_cairo_surface_create_from_pixbuf (item->details->pixbuf, gtk_widget_get_scale_factor (GTK_WIDGET (canvas)), gtk_widget_get_window (GTK_WIDGET (canvas))); gtk_render_icon_surface (context, cr, drag_surface, item_offset_x, item_offset_y); cairo_surface_destroy (drag_surface); get_scaled_icon_size (item, &pix_width, &pix_height); icon_rect.x0 = item_offset_x; icon_rect.y0 = item_offset_y; icon_rect.x1 = item_offset_x + pix_width; icon_rect.y1 = item_offset_y + pix_height; draw_embedded_text (item, cr, item_offset_x, item_offset_y); draw_label_text (item, cr, icon_rect); cairo_destroy (cr); gtk_style_context_restore (context); return surface; } void nemo_icon_canvas_item_set_image (NemoIconCanvasItem *item, GdkPixbuf *image) { NemoIconCanvasItemDetails *details; g_return_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item)); g_return_if_fail (image == NULL || pixbuf_is_acceptable (image)); details = item->details; if (details->pixbuf == image) { return; } if (image != NULL) { g_object_ref (image); } if (details->pixbuf != NULL) { g_object_unref (details->pixbuf); } if (details->rendered_surface != NULL) { cairo_surface_destroy (details->rendered_surface); details->rendered_surface = NULL; } details->pixbuf = image; nemo_icon_canvas_item_invalidate_bounds_cache (item); eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } void nemo_icon_canvas_item_set_attach_points (NemoIconCanvasItem *item, GdkPoint *attach_points, int n_attach_points) { g_free (item->details->attach_points); item->details->attach_points = NULL; item->details->n_attach_points = 0; if (attach_points != NULL && n_attach_points != 0) { item->details->attach_points = g_memdup (attach_points, n_attach_points * sizeof (GdkPoint)); item->details->n_attach_points = n_attach_points; } nemo_icon_canvas_item_invalidate_bounds_cache (item); } void nemo_icon_canvas_item_set_embedded_text_rect (NemoIconCanvasItem *item, const GdkRectangle *text_rect) { item->details->embedded_text_rect = *text_rect; nemo_icon_canvas_item_invalidate_bounds_cache (item); eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } void nemo_icon_canvas_item_set_embedded_text (NemoIconCanvasItem *item, const char *text) { g_free (item->details->embedded_text); item->details->embedded_text = g_strdup (text); if (item->details->embedded_text_layout != NULL) { if (text != NULL) { pango_layout_set_text (item->details->embedded_text_layout, text, -1); } else { pango_layout_set_text (item->details->embedded_text_layout, "", -1); } } eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } /* Recomputes the bounding box of a icon canvas item. * This is a generic implementation that could be used for any canvas item * class, it has no assumptions about how the item is used. */ static void recompute_bounding_box (NemoIconCanvasItem *icon_item, double i2w_dx, double i2w_dy) { /* The bounds stored in the item is the same as what get_bounds * returns, except it's in canvas coordinates instead of the item's * parent's coordinates. */ EelCanvasItem *item; EelDRect bounds_rect; item = EEL_CANVAS_ITEM (icon_item); eel_canvas_item_get_bounds (item, &bounds_rect.x0, &bounds_rect.y0, &bounds_rect.x1, &bounds_rect.y1); bounds_rect.x0 += i2w_dx; bounds_rect.y0 += i2w_dy; bounds_rect.x1 += i2w_dx; bounds_rect.y1 += i2w_dy; eel_canvas_w2c_d (item->canvas, bounds_rect.x0, bounds_rect.y0, &item->x1, &item->y1); eel_canvas_w2c_d (item->canvas, bounds_rect.x1, bounds_rect.y1, &item->x2, &item->y2); } static EelIRect compute_text_rectangle (const NemoIconCanvasItem *item, EelIRect icon_rectangle, gboolean canvas_coords, NemoIconCanvasItemBoundsUsage usage) { EelIRect text_rectangle; double pixels_per_unit; double text_width, text_height, text_height_for_layout, text_height_for_entire_text, real_text_height, text_dx; pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit; if (canvas_coords) { text_width = item->details->text_width; text_height = item->details->text_height; text_height_for_layout = item->details->text_height_for_layout; text_height_for_entire_text = item->details->text_height_for_entire_text; text_dx = item->details->text_dx; } else { text_width = item->details->text_width / pixels_per_unit; text_height = item->details->text_height / pixels_per_unit; text_height_for_layout = item->details->text_height_for_layout / pixels_per_unit; text_height_for_entire_text = item->details->text_height_for_entire_text / pixels_per_unit; text_dx = item->details->text_dx / pixels_per_unit; } if (NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas)->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { if (!nemo_icon_container_is_layout_rtl (NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas))) { text_rectangle.x0 = icon_rectangle.x1; text_rectangle.x1 = text_rectangle.x0 + text_dx + text_width; } else { text_rectangle.x1 = icon_rectangle.x0; text_rectangle.x0 = text_rectangle.x1 - text_dx - text_width; } /* VOODOO-TODO */ #if 0 if (for_layout) { /* in this case, we should be more smart and calculate the size according to the maximum * number of lines fitting next to the icon. However, this requires a more complex layout logic. * It would mean that when measuring the label, the icon dimensions must be known already, * and we * 1. start with an unlimited layout * 2. measure how many lines of this layout fit next to the icon * 3. limit the number of lines to the given number of fitting lines */ real_text_height = VOODOO(); } else { #endif real_text_height = text_height_for_entire_text; #if 0 } #endif text_rectangle.y0 = (icon_rectangle.y0 + icon_rectangle.y1) / 2- (int) real_text_height / 2; text_rectangle.y1 = text_rectangle.y0 + real_text_height; } else { text_rectangle.x0 = (icon_rectangle.x0 + icon_rectangle.x1) / 2 - (int) text_width / 2; text_rectangle.y0 = icon_rectangle.y1; text_rectangle.x1 = text_rectangle.x0 + text_width; if (usage == BOUNDS_USAGE_FOR_LAYOUT) { real_text_height = text_height_for_layout; } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) { real_text_height = text_height_for_entire_text; } else if (usage == BOUNDS_USAGE_FOR_DISPLAY) { real_text_height = text_height; } else { g_assert_not_reached (); } text_rectangle.y1 = text_rectangle.y0 + real_text_height + LABEL_OFFSET / pixels_per_unit; } return text_rectangle; } static EelIRect get_current_canvas_bounds (EelCanvasItem *item) { EelIRect bounds; g_assert (EEL_IS_CANVAS_ITEM (item)); bounds.x0 = item->x1; bounds.y0 = item->y1; bounds.x1 = item->x2; bounds.y1 = item->y2; return bounds; } void nemo_icon_canvas_item_update_bounds (NemoIconCanvasItem *item, double i2w_dx, double i2w_dy) { EelIRect before, after; EelCanvasItem *canvas_item; canvas_item = EEL_CANVAS_ITEM (item); /* Compute new bounds. */ before = get_current_canvas_bounds (canvas_item); recompute_bounding_box (item, i2w_dx, i2w_dy); after = get_current_canvas_bounds (canvas_item); /* If the bounds didn't change, we are done. */ if (eel_irect_equal (before, after)) { return; } /* Update canvas and text rect cache */ nemo_icon_canvas_item_get_icon_canvas_rectangle (item, &item->details->canvas_rect); item->details->text_rect = compute_text_rectangle (item, item->details->canvas_rect, TRUE, BOUNDS_USAGE_FOR_DISPLAY); /* queue a redraw. */ eel_canvas_request_redraw (canvas_item->canvas, before.x0, before.y0, before.x1 + 5, before.y1 + 5); } /* Update handler for the icon canvas item. */ static void nemo_icon_canvas_item_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, gint flags) { nemo_icon_canvas_item_update_bounds (NEMO_ICON_CANVAS_ITEM (item), i2w_dx, i2w_dy); eel_canvas_item_request_redraw (EEL_CANVAS_ITEM (item)); EEL_CANVAS_ITEM_CLASS (nemo_icon_canvas_item_parent_class)->update (item, i2w_dx, i2w_dy, flags); } /* Rendering */ static gboolean in_single_click_mode (void) { int click_policy; click_policy = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_CLICK_POLICY); return click_policy == NEMO_CLICK_POLICY_SINGLE; } /* Keep these for a bit while we work on performance of draw_or_measure_label_text. */ /* #define PERFORMANCE_TEST_DRAW_DISABLE #define PERFORMANCE_TEST_MEASURE_DISABLE */ /* This gets the size of the layout from the position of the layout. * This means that if the layout is right aligned we get the full width * of the layout, not just the width of the text snippet on the right side */ static void layout_get_full_size (PangoLayout *layout, int *width, int *height, int *dx) { PangoRectangle logical_rect; int the_width, total_width; pango_layout_get_extents (layout, NULL, &logical_rect); the_width = (logical_rect.width + PANGO_SCALE / 2) / PANGO_SCALE; total_width = (logical_rect.x + logical_rect.width + PANGO_SCALE / 2) / PANGO_SCALE; if (width != NULL) { *width = the_width; } if (height != NULL) { *height = (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE; } if (dx != NULL) { *dx = total_width - the_width; } } static void layout_get_size_for_layout (PangoLayout *layout, int max_layout_line_count, int height_for_entire_text, int *height_for_layout) { PangoLayoutIter *iter; PangoRectangle logical_rect; int i; /* only use the first max_layout_line_count lines for the gridded auto layout */ if (pango_layout_get_line_count (layout) <= max_layout_line_count) { *height_for_layout = height_for_entire_text; } else { *height_for_layout = 0; iter = pango_layout_get_iter (layout); /* VOODOO-TODO, determine number of lines based on the icon size for text besides icon. * cf. compute_text_rectangle() */ for (i = 0; i < max_layout_line_count; i++) { pango_layout_iter_get_line_extents (iter, NULL, &logical_rect); *height_for_layout += (logical_rect.height + PANGO_SCALE / 2) / PANGO_SCALE; if (!pango_layout_iter_next_line (iter)) { break; } *height_for_layout += pango_layout_get_spacing (layout); } pango_layout_iter_free (iter); } } #define IS_COMPACT_VIEW(container) \ ((container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_L_R || \ container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_R_L) && \ container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) #define TEXT_BACK_PADDING_X 4 #define TEXT_BACK_PADDING_Y 1 static void prepare_pango_layout_width (NemoIconCanvasItem *item, PangoLayout *layout) { if (nemo_icon_canvas_item_get_max_text_width (item) < 0) { pango_layout_set_width (layout, -1); } else { pango_layout_set_width (layout, floor (nemo_icon_canvas_item_get_max_text_width (item)) * PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); } } static void prepare_pango_layout_for_measure_entire_text (NemoIconCanvasItem *item, PangoLayout *layout) { NemoIconContainer *container; prepare_pango_layout_width (item, layout); container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); if (IS_COMPACT_VIEW (container)) { pango_layout_set_height (layout, -1); } else { pango_layout_set_height (layout, G_MININT); } } static void prepare_pango_layout_for_draw (NemoIconCanvasItem *item, PangoLayout *layout) { NemoIconCanvasItemDetails *details; NemoIconContainer *container; gboolean needs_highlight; prepare_pango_layout_width (item, layout); container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); details = item->details; needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop; if (IS_COMPACT_VIEW (container)) { pango_layout_set_height (layout, -1); } else if (needs_highlight || details->is_prelit || details->is_highlighted_as_keyboard_focus || details->entire_text || container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { /* VOODOO-TODO, cf. compute_text_rectangle() */ pango_layout_set_height (layout, G_MININT); } else { /* TODO? we might save some resources, when the re-layout is not neccessary in case * the layout height already fits into max. layout lines. But pango should figure this * out itself (which it doesn't ATM). */ pango_layout_set_height (layout, nemo_icon_container_get_max_layout_lines_for_pango (container)); } } static void measure_label_text (NemoIconCanvasItem *item) { NemoIconCanvasItemDetails *details; NemoIconContainer *container; gint editable_height, editable_height_for_layout, editable_height_for_entire_text, editable_width, editable_dx; gint additional_height, additional_width, additional_dx; PangoLayout *editable_layout; PangoLayout *additional_layout; gboolean have_editable, have_additional; /* check to see if the cached values are still valid; if so, there's * no work necessary */ if (item->details->text_width >= 0 && item->details->text_height >= 0) { return; } details = item->details; have_editable = details->editable_text != NULL && details->editable_text[0] != '\0'; have_additional = details->additional_text != NULL && details->additional_text[0] != '\0'; /* No font or no text, then do no work. */ if (!have_editable && !have_additional) { details->text_height = 0; details->text_height_for_layout = 0; details->text_height_for_entire_text = 0; details->text_width = 0; return; } #ifdef PERFORMANCE_TEST_MEASURE_DISABLE /* fake out the width */ details->text_width = 80; details->text_height = 20; details->text_height_for_layout = 20; details->text_height_for_entire_text = 20; return; #endif editable_width = 0; editable_height = 0; editable_height_for_layout = 0; editable_height_for_entire_text = 0; editable_dx = 0; additional_width = 0; additional_height = 0; additional_dx = 0; container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); editable_layout = NULL; additional_layout = NULL; if (have_editable) { /* first, measure required text height: editable_height_for_entire_text * then, measure text height applicable for layout: editable_height_for_layout * next, measure actually displayed height: editable_height */ editable_layout = get_label_layout (&details->editable_text_layout, item, details->editable_text); prepare_pango_layout_for_measure_entire_text (item, editable_layout); layout_get_full_size (editable_layout, NULL, &editable_height_for_entire_text, NULL); layout_get_size_for_layout (editable_layout, nemo_icon_container_get_max_layout_lines (container), editable_height_for_entire_text, &editable_height_for_layout); prepare_pango_layout_for_draw (item, editable_layout); layout_get_full_size (editable_layout, &editable_width, &editable_height, &editable_dx); } if (have_additional) { additional_layout = get_label_layout (&details->additional_text_layout, item, details->additional_text); prepare_pango_layout_for_draw (item, additional_layout); layout_get_full_size (additional_layout, &additional_width, &additional_height, &additional_dx); } details->editable_text_height = editable_height; if (editable_width > additional_width) { details->text_width = editable_width; details->text_dx = editable_dx; } else { details->text_width = additional_width; details->text_dx = additional_dx; } if (have_additional) { details->text_height = editable_height + LABEL_LINE_SPACING + additional_height; details->text_height_for_layout = editable_height_for_layout + LABEL_LINE_SPACING + additional_height; details->text_height_for_entire_text = editable_height_for_entire_text + LABEL_LINE_SPACING + additional_height; } else { details->text_height = editable_height; details->text_height_for_layout = editable_height_for_layout; details->text_height_for_entire_text = editable_height_for_entire_text; } /* add some extra space for highlighting even when we don't highlight so things won't move */ /* extra slop for nicer highlighting */ details->text_height += TEXT_BACK_PADDING_Y*2; details->text_height_for_layout += TEXT_BACK_PADDING_Y*2; details->text_height_for_entire_text += TEXT_BACK_PADDING_Y*2; details->editable_text_height += TEXT_BACK_PADDING_Y*2; /* extra to make it look nicer */ details->text_width += TEXT_BACK_PADDING_X*2; if (editable_layout) { g_object_unref (editable_layout); } if (additional_layout) { g_object_unref (additional_layout); } } static void draw_label_text (NemoIconCanvasItem *item, cairo_t *cr, EelIRect icon_rect) { NemoIconCanvasItemDetails *details; NemoIconContainer *container; PangoLayout *editable_layout; PangoLayout *additional_layout; GtkStyleContext *context; GtkStateFlags state, base_state; gboolean have_editable, have_additional; gboolean needs_highlight, prelight_label, is_rtl_label_beside; EelIRect text_rect; int x; int max_text_width; gdouble frame_w, frame_h, frame_x, frame_y; gboolean draw_frame = TRUE; #ifdef PERFORMANCE_TEST_DRAW_DISABLE return; #endif details = item->details; measure_label_text (item); if (details->text_height == 0 || details->text_width == 0) { return; } container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); context = gtk_widget_get_style_context (GTK_WIDGET (container)); text_rect = compute_text_rectangle (item, icon_rect, TRUE, BOUNDS_USAGE_FOR_DISPLAY); needs_highlight = details->is_highlighted_for_selection || details->is_highlighted_for_drop; is_rtl_label_beside = nemo_icon_container_is_layout_rtl (container) && container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE; editable_layout = NULL; additional_layout = NULL; have_editable = details->editable_text != NULL && details->editable_text[0] != '\0'; have_additional = details->additional_text != NULL && details->additional_text[0] != '\0'; g_assert (have_editable || have_additional); max_text_width = floor (nemo_icon_canvas_item_get_max_text_width (item)); base_state = gtk_widget_get_state_flags (GTK_WIDGET (container)); base_state &= ~(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_PRELIGHT); state = base_state; gtk_widget_style_get (GTK_WIDGET (container), "activate_prelight_icon_label", &prelight_label, NULL); /* if the icon is highlighted, do some set-up */ if (needs_highlight && !details->is_renaming) { state |= GTK_STATE_FLAG_SELECTED; frame_x = is_rtl_label_beside ? text_rect.x0 + item->details->text_dx : text_rect.x0; frame_y = text_rect.y0; frame_w = is_rtl_label_beside ? text_rect.x1 - text_rect.x0 - item->details->text_dx : text_rect.x1 - text_rect.x0; frame_h = text_rect.y1 - text_rect.y0; } else if (!needs_highlight && have_editable && details->text_width > 0 && details->text_height > 0 && prelight_label && item->details->is_prelit) { state |= GTK_STATE_FLAG_PRELIGHT; frame_x = text_rect.x0; frame_y = text_rect.y0; frame_w = text_rect.x1 - text_rect.x0; frame_h = text_rect.y1 - text_rect.y0; } else { draw_frame = FALSE; } if (draw_frame) { gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_render_frame (context, cr, frame_x, frame_y, frame_w, frame_h); gtk_render_background (context, cr, frame_x, frame_y, frame_w, frame_h); gtk_style_context_restore (context); } if (container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { x = text_rect.x0 + 2; } else { x = text_rect.x0 + ((text_rect.x1 - text_rect.x0) - max_text_width) / 2; } if (have_editable && !details->is_renaming) { state = base_state; if (prelight_label && item->details->is_prelit) { state |= GTK_STATE_FLAG_PRELIGHT; } if (needs_highlight) { state |= GTK_STATE_FLAG_SELECTED; } editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text); prepare_pango_layout_for_draw (item, editable_layout); gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_render_layout (context, cr, x, text_rect.y0 + TEXT_BACK_PADDING_Y, editable_layout); gtk_style_context_restore (context); } if (have_additional && !details->is_renaming) { state = base_state; if (needs_highlight) { state |= GTK_STATE_FLAG_SELECTED; } additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); prepare_pango_layout_for_draw (item, additional_layout); gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_style_context_add_class (context, "dim-label"); gtk_render_layout (context, cr, x, text_rect.y0 + details->editable_text_height + LABEL_LINE_SPACING + TEXT_BACK_PADDING_Y, additional_layout); } if (item->details->is_highlighted_as_keyboard_focus) { if (needs_highlight) { state = GTK_STATE_FLAG_SELECTED; } gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_render_focus (context, cr, text_rect.x0, text_rect.y0, text_rect.x1 - text_rect.x0, text_rect.y1 - text_rect.y0); gtk_style_context_restore (context); } if (editable_layout != NULL) { g_object_unref (editable_layout); } if (additional_layout != NULL) { g_object_unref (additional_layout); } } void nemo_icon_canvas_item_set_is_visible (NemoIconCanvasItem *item, gboolean visible) { if (item->details->is_visible == visible) return; item->details->is_visible = visible; if (!visible) { nemo_icon_canvas_item_invalidate_label (item); } } void nemo_icon_canvas_item_invalidate_label (NemoIconCanvasItem *item) { nemo_icon_canvas_item_invalidate_label_size (item); if (item->details->editable_text_layout) { g_object_unref (item->details->editable_text_layout); item->details->editable_text_layout = NULL; } if (item->details->additional_text_layout) { g_object_unref (item->details->additional_text_layout); item->details->additional_text_layout = NULL; } if (item->details->embedded_text_layout) { g_object_unref (item->details->embedded_text_layout); item->details->embedded_text_layout = NULL; } } static GdkPixbuf * get_knob_pixbuf (void) { GdkPixbuf *knob_pixbuf; knob_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), "stock-nemo-knob", 8, 0, NULL); if (!knob_pixbuf) { GInputStream *stream = g_resources_open_stream ("/org/nemo/icons/knob.png", 0, NULL); if (stream != NULL) { knob_pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, NULL); g_object_unref (stream); } } return knob_pixbuf; } static void draw_stretch_handles (NemoIconCanvasItem *item, cairo_t *cr, const EelIRect *rect) { GtkWidget *widget; GdkPixbuf *knob_pixbuf; int knob_width, knob_height; double dash = { 2.0 }; GtkStyleContext *style; GdkRGBA color; if (!item->details->show_stretch_handles) { return; } widget = GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas); style = gtk_widget_get_style_context (widget); cairo_save (cr); knob_pixbuf = get_knob_pixbuf (); knob_width = gdk_pixbuf_get_width (knob_pixbuf); knob_height = gdk_pixbuf_get_height (knob_pixbuf); /* first draw the box */ gtk_style_context_get_color (style, GTK_STATE_FLAG_SELECTED, &color); gdk_cairo_set_source_rgba (cr, &color); cairo_set_dash (cr, &dash, 1, 0); cairo_set_line_width (cr, 1.0); cairo_rectangle (cr, rect->x0 + 0.5, rect->y0 + 0.5, rect->x1 - rect->x0 - 1, rect->y1 - rect->y0 - 1); cairo_stroke (cr); cairo_restore (cr); /* draw the stretch handles themselves */ draw_pixbuf (knob_pixbuf, cr, rect->x0, rect->y0); draw_pixbuf (knob_pixbuf, cr, rect->x0, rect->y1 - knob_height); draw_pixbuf (knob_pixbuf, cr, rect->x1 - knob_width, rect->y0); draw_pixbuf (knob_pixbuf, cr, rect->x1 - knob_width, rect->y1 - knob_height); g_object_unref (knob_pixbuf); } static void draw_pixbuf (GdkPixbuf *pixbuf, cairo_t *cr, int x, int y) { cairo_save (cr); gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y); cairo_paint (cr); cairo_restore (cr); } /* shared code to highlight or dim the passed-in pixbuf */ static cairo_surface_t * real_map_surface (NemoIconCanvasItem *icon_item) { EelCanvas *canvas; GdkPixbuf *temp_pixbuf, *old_pixbuf; GtkStyleContext *style; GdkRGBA color; cairo_surface_t *surface; temp_pixbuf = icon_item->details->pixbuf; canvas = EEL_CANVAS_ITEM(icon_item)->canvas; g_object_ref (temp_pixbuf); if (icon_item->details->is_prelit || icon_item->details->is_highlighted_for_clipboard) { old_pixbuf = temp_pixbuf; temp_pixbuf = eel_create_spotlight_pixbuf (temp_pixbuf); g_object_unref (old_pixbuf); } if (icon_item->details->is_highlighted_for_selection || icon_item->details->is_highlighted_for_drop) { style = gtk_widget_get_style_context (GTK_WIDGET (canvas)); if (gtk_widget_has_focus (GTK_WIDGET (canvas))) { gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED, &color); } else { gtk_style_context_get_background_color (style, GTK_STATE_FLAG_ACTIVE, &color); } old_pixbuf = temp_pixbuf; temp_pixbuf = eel_create_colorized_pixbuf (temp_pixbuf, &color); g_object_unref (old_pixbuf); } surface = gdk_cairo_surface_create_from_pixbuf (temp_pixbuf, gtk_widget_get_scale_factor (GTK_WIDGET (canvas)), gtk_widget_get_window (GTK_WIDGET (canvas))); g_object_unref (temp_pixbuf); return surface; } static cairo_surface_t * map_surface (NemoIconCanvasItem *icon_item) { if (!(icon_item->details->rendered_surface != NULL && icon_item->details->rendered_is_prelit == icon_item->details->is_prelit && icon_item->details->rendered_is_highlighted_for_selection == icon_item->details->is_highlighted_for_selection && icon_item->details->rendered_is_highlighted_for_drop == icon_item->details->is_highlighted_for_drop && icon_item->details->rendered_is_highlighted_for_clipboard == icon_item->details->is_highlighted_for_clipboard && (icon_item->details->is_highlighted_for_selection && icon_item->details->rendered_is_focused == gtk_widget_has_focus (GTK_WIDGET (EEL_CANVAS_ITEM (icon_item)->canvas))))) { if (icon_item->details->rendered_surface != NULL) { cairo_surface_destroy (icon_item->details->rendered_surface); } icon_item->details->rendered_surface = real_map_surface (icon_item); icon_item->details->rendered_is_prelit = icon_item->details->is_prelit; icon_item->details->rendered_is_highlighted_for_selection = icon_item->details->is_highlighted_for_selection; icon_item->details->rendered_is_highlighted_for_drop = icon_item->details->is_highlighted_for_drop; icon_item->details->rendered_is_highlighted_for_clipboard = icon_item->details->is_highlighted_for_clipboard; icon_item->details->rendered_is_focused = gtk_widget_has_focus (GTK_WIDGET (EEL_CANVAS_ITEM (icon_item)->canvas)); } cairo_surface_reference (icon_item->details->rendered_surface); return icon_item->details->rendered_surface; } static void draw_embedded_text (NemoIconCanvasItem *item, cairo_t *cr, int x, int y) { PangoLayout *layout; PangoContext *context; PangoFontDescription *desc; GtkWidget *widget; GtkStyleContext *style_context; guint scale; if (item->details->embedded_text == NULL || item->details->embedded_text_rect.width == 0 || item->details->embedded_text_rect.height == 0) { return; } widget = GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas); if (item->details->embedded_text_layout != NULL) { layout = g_object_ref (item->details->embedded_text_layout); } else { context = gtk_widget_get_pango_context (widget); layout = pango_layout_new (context); pango_layout_set_text (layout, item->details->embedded_text, -1); desc = pango_font_description_from_string ("monospace 6"); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); if (item->details->is_visible) { item->details->embedded_text_layout = g_object_ref (layout); } } style_context = gtk_widget_get_style_context (widget); gtk_style_context_save (style_context); gtk_style_context_add_class (style_context, "icon-embedded-text"); cairo_save (cr); scale = gtk_widget_get_scale_factor (widget); cairo_rectangle (cr, x + item->details->embedded_text_rect.x / scale, y + item->details->embedded_text_rect.y / scale, item->details->embedded_text_rect.width / scale, item->details->embedded_text_rect.height / scale); cairo_clip (cr); gtk_render_layout (style_context, cr, x + item->details->embedded_text_rect.x / scale, y + item->details->embedded_text_rect.y / scale, layout); gtk_style_context_restore (style_context); cairo_restore (cr); } /* Draw the icon item for non-anti-aliased mode. */ static void nemo_icon_canvas_item_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region) { NemoIconContainer *container; NemoIconCanvasItem *icon_item; NemoIconCanvasItemDetails *details; EelIRect icon_rect; cairo_surface_t *temp_surface; GtkStyleContext *context; container = NEMO_ICON_CONTAINER (item->canvas); icon_item = NEMO_ICON_CANVAS_ITEM (item); details = icon_item->details; /* Draw the pixbuf. */ if (details->pixbuf == NULL) { return; } context = gtk_widget_get_style_context (GTK_WIDGET (container)); gtk_style_context_save (context); gtk_style_context_add_class (context, "nemo-canvas-item"); icon_rect = icon_item->details->canvas_rect; temp_surface = map_surface (icon_item); gtk_render_icon_surface (context, cr, temp_surface, icon_rect.x0, icon_rect.y0); cairo_surface_destroy (temp_surface); draw_embedded_text (icon_item, cr, icon_rect.x0, icon_rect.y0); /* Draw stretching handles (if necessary). */ draw_stretch_handles (icon_item, cr, &icon_rect); /* Draw the label text. */ draw_label_text (icon_item, cr, icon_rect); gtk_style_context_restore (context); } #define ZERO_WIDTH_SPACE "\xE2\x80\x8B" static PangoLayout * create_label_layout (NemoIconCanvasItem *item, const char *text) { PangoLayout *layout; PangoContext *context; PangoFontDescription *desc; NemoIconContainer *container; EelCanvasItem *canvas_item; GString *str; char *zeroified_text; const char *p; canvas_item = EEL_CANVAS_ITEM (item); container = NEMO_ICON_CONTAINER (canvas_item->canvas); context = gtk_widget_get_pango_context (GTK_WIDGET (canvas_item->canvas)); layout = pango_layout_new (context); zeroified_text = NULL; if (text != NULL) { str = g_string_new (NULL); for (p = text; *p != '\0'; p++) { str = g_string_append_c (str, *p); if (*p == '_' || *p == '-' || (*p == '.' && !g_ascii_isdigit(*(p+1)))) { /* Ensure that we allow to break after '_' or '.' characters, * if they are not followed by a number */ str = g_string_append (str, ZERO_WIDTH_SPACE); } } zeroified_text = g_string_free (str, FALSE); } pango_layout_set_text (layout, zeroified_text, -1); pango_layout_set_auto_dir (layout, FALSE); if (container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { if (!nemo_icon_container_is_layout_rtl (container)) { pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT); } else { pango_layout_set_alignment (layout, PANGO_ALIGN_RIGHT); } } else { pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); } pango_layout_set_spacing (layout, LABEL_LINE_SPACING); pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR); /* Create a font description */ if (container->details->font && g_strcmp0 (container->details->font, "") != 0) { desc = pango_font_description_from_string (container->details->font); } else { desc = pango_font_description_copy (pango_context_get_font_description (context)); } if (pango_font_description_get_size (desc) > 0) { pango_font_description_set_size (desc, pango_font_description_get_size (desc) + container->details->font_size_table [container->details->zoom_level]); } pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); g_free (zeroified_text); return layout; } static PangoLayout * get_label_layout (PangoLayout **layout_cache, NemoIconCanvasItem *item, const char *text) { PangoLayout *layout; if (*layout_cache != NULL) { return g_object_ref (*layout_cache); } layout = create_label_layout (item, text); if (item->details->is_visible) { *layout_cache = g_object_ref (layout); } return layout; } /* handle events */ static int nemo_icon_canvas_item_event (EelCanvasItem *item, GdkEvent *event) { NemoIconCanvasItem *icon_item; GdkCursor *cursor; GdkWindow *cursor_window; icon_item = NEMO_ICON_CANVAS_ITEM (item); cursor_window = ((GdkEventAny *)event)->window; switch (event->type) { case GDK_ENTER_NOTIFY: gtk_widget_set_tooltip_text (GTK_WIDGET (item->canvas), icon_item->tooltip); if (!icon_item->details->is_prelit) { icon_item->details->is_prelit = TRUE; nemo_icon_canvas_item_invalidate_label_size (icon_item); eel_canvas_item_request_update (item); eel_canvas_item_send_behind (item, NEMO_ICON_CONTAINER (item->canvas)->details->rubberband_info.selection_rectangle); /* show a hand cursor */ if (in_single_click_mode ()) { cursor = gdk_cursor_new_for_display (gdk_display_get_default(), GDK_HAND2); gdk_window_set_cursor (cursor_window, cursor); g_object_unref (cursor); icon_item->details->cursor_window = g_object_ref (cursor_window); } } return TRUE; case GDK_LEAVE_NOTIFY: gtk_widget_set_tooltip_text (GTK_WIDGET (item->canvas), ""); if (icon_item->details->is_prelit || icon_item->details->is_highlighted_for_drop) { /* When leaving, turn of the prelight state and the * higlighted for drop. The latter gets turned on * by the drag&drop motion callback. */ icon_item->details->is_prelit = FALSE; icon_item->details->is_highlighted_for_drop = FALSE; nemo_icon_canvas_item_invalidate_label_size (icon_item); eel_canvas_item_request_update (item); /* show default cursor */ gdk_window_set_cursor (cursor_window, NULL); g_clear_object (&icon_item->details->cursor_window); } return TRUE; default: /* Don't eat up other events; icon container might use them. */ return FALSE; } } static gboolean hit_test (NemoIconCanvasItem *icon_item, EelIRect canvas_rect) { NemoIconCanvasItemDetails *details; details = icon_item->details; /* Quick check to see if the rect hits the icon or text at all. */ if (!eel_irect_hits_irect (icon_item->details->canvas_rect, canvas_rect) && (!eel_irect_hits_irect (details->text_rect, canvas_rect))) { return FALSE; } /* Check for hits in the stretch handles. */ if (hit_test_stretch_handle (icon_item, canvas_rect, NULL)) { return TRUE; } /* Check for hit in the icon. */ if (eel_irect_hits_irect (icon_item->details->canvas_rect, canvas_rect)) { return TRUE; } /* Check for hit in the text. */ if (eel_irect_hits_irect (details->text_rect, canvas_rect) && !icon_item->details->is_renaming) { return TRUE; } return FALSE; } /* Point handler for the icon canvas item. */ static double nemo_icon_canvas_item_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) { EelIRect canvas_rect; *actual_item = item; canvas_rect.x0 = cx; canvas_rect.y0 = cy; canvas_rect.x1 = cx + 1; canvas_rect.y1 = cy + 1; if (hit_test (NEMO_ICON_CANVAS_ITEM (item), canvas_rect)) { return 0.0; } else { /* This value means not hit. * It's kind of arbitrary. Can we do better? */ return item->canvas->pixels_per_unit * 2 + 10; } } static void nemo_icon_canvas_item_translate (EelCanvasItem *item, double dx, double dy) { NemoIconCanvasItem *icon_item; NemoIconCanvasItemDetails *details; icon_item = NEMO_ICON_CANVAS_ITEM (item); details = icon_item->details; details->x += dx; details->y += dy; } void nemo_icon_canvas_item_get_bounds_for_layout (NemoIconCanvasItem *icon_item, double *x1, double *y1, double *x2, double *y2) { NemoIconCanvasItemDetails *details; EelIRect *total_rect; details = icon_item->details; nemo_icon_canvas_item_ensure_bounds_up_to_date (icon_item); g_assert (details->bounds_cached); total_rect = &details->bounds_cache_for_layout; /* Return the result. */ if (x1 != NULL) { *x1 = (int)details->x + total_rect->x0; } if (y1 != NULL) { *y1 = (int)details->y + total_rect->y0; } if (x2 != NULL) { *x2 = (int)details->x + total_rect->x1 + 1; } if (y2 != NULL) { *y2 = (int)details->y + total_rect->y1 + 1; } } void nemo_icon_canvas_item_get_bounds_for_entire_item (NemoIconCanvasItem *icon_item, double *x1, double *y1, double *x2, double *y2) { NemoIconCanvasItemDetails *details; EelIRect *total_rect; details = icon_item->details; nemo_icon_canvas_item_ensure_bounds_up_to_date (icon_item); g_assert (details->bounds_cached); total_rect = &details->bounds_cache_for_entire_item; /* Return the result. */ if (x1 != NULL) { *x1 = (int)details->x + total_rect->x0; } if (y1 != NULL) { *y1 = (int)details->y + total_rect->y0; } if (x2 != NULL) { *x2 = (int)details->x + total_rect->x1 + 1; } if (y2 != NULL) { *y2 = (int)details->y + total_rect->y1 + 1; } } /* Bounds handler for the icon canvas item. */ static void nemo_icon_canvas_item_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { NemoIconCanvasItem *icon_item; NemoIconCanvasItemDetails *details; EelIRect *total_rect; icon_item = NEMO_ICON_CANVAS_ITEM (item); details = icon_item->details; g_assert (x1 != NULL); g_assert (y1 != NULL); g_assert (x2 != NULL); g_assert (y2 != NULL); nemo_icon_canvas_item_ensure_bounds_up_to_date (icon_item); g_assert (details->bounds_cached); total_rect = &details->bounds_cache; /* Return the result. */ *x1 = (int)details->x + total_rect->x0; *y1 = (int)details->y + total_rect->y0; *x2 = (int)details->x + total_rect->x1 + 1; *y2 = (int)details->y + total_rect->y1 + 1; } static void nemo_icon_canvas_item_ensure_bounds_up_to_date (NemoIconCanvasItem *icon_item) { NemoIconCanvasItemDetails *details; EelIRect icon_rect, icon_rect_raw; EelIRect text_rect, text_rect_for_layout, text_rect_for_entire_text; EelIRect total_rect, total_rect_for_layout, total_rect_for_entire_text; EelCanvasItem *item; double pixels_per_unit; gint width, height; details = icon_item->details; item = EEL_CANVAS_ITEM (icon_item); if (!details->bounds_cached) { measure_label_text (icon_item); pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit; /* Compute raw and scaled icon rectangle. */ icon_rect.x0 = 0; icon_rect.y0 = 0; icon_rect_raw.x0 = 0; icon_rect_raw.y0 = 0; get_scaled_icon_size (icon_item, &width, &height); icon_rect_raw.x1 = icon_rect_raw.x0 + width; icon_rect_raw.y1 = icon_rect_raw.y0 + height; icon_rect.x1 = icon_rect_raw.x1 / pixels_per_unit; icon_rect.y1 = icon_rect_raw.y1 / pixels_per_unit; /* Compute text rectangle. */ text_rect = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_DISPLAY); text_rect_for_layout = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_LAYOUT); text_rect_for_entire_text = compute_text_rectangle (icon_item, icon_rect, FALSE, BOUNDS_USAGE_FOR_ENTIRE_ITEM); /* Compute total rectangle */ eel_irect_union (&total_rect, &icon_rect, &text_rect); eel_irect_union (&total_rect_for_layout, &icon_rect, &text_rect_for_layout); eel_irect_union (&total_rect_for_entire_text, &icon_rect, &text_rect_for_entire_text); details->bounds_cache = total_rect; details->bounds_cache_for_layout = total_rect_for_layout; details->bounds_cache_for_entire_item = total_rect_for_entire_text; details->bounds_cached = TRUE; } } /* Get the rectangle of the icon only, in world coordinates. */ EelDRect nemo_icon_canvas_item_get_icon_rectangle (const NemoIconCanvasItem *item) { EelDRect rectangle; double pixels_per_unit; gint width, height; g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), eel_drect_empty); rectangle.x0 = item->details->x; rectangle.y0 = item->details->y; pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit; get_scaled_icon_size (NEMO_ICON_CANVAS_ITEM (item), &width, &height); rectangle.x1 = rectangle.x0 + width / pixels_per_unit; rectangle.y1 = rectangle.y0 + height / pixels_per_unit; eel_canvas_item_i2w (EEL_CANVAS_ITEM (item), &rectangle.x0, &rectangle.y0); eel_canvas_item_i2w (EEL_CANVAS_ITEM (item), &rectangle.x1, &rectangle.y1); return rectangle; } EelDRect nemo_icon_canvas_item_get_text_rectangle (NemoIconCanvasItem *item, gboolean for_layout) { /* FIXME */ EelIRect icon_rectangle; EelIRect text_rectangle; EelDRect ret; double pixels_per_unit; gint width, height; g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), eel_drect_empty); icon_rectangle.x0 = item->details->x; icon_rectangle.y0 = item->details->y; pixels_per_unit = EEL_CANVAS_ITEM (item)->canvas->pixels_per_unit; get_scaled_icon_size (item, &width, &height); icon_rectangle.x1 = icon_rectangle.x0 + width / pixels_per_unit; icon_rectangle.y1 = icon_rectangle.y0 + height / pixels_per_unit; measure_label_text (item); text_rectangle = compute_text_rectangle (item, icon_rectangle, FALSE, for_layout ? BOUNDS_USAGE_FOR_LAYOUT : BOUNDS_USAGE_FOR_DISPLAY); ret.x0 = text_rectangle.x0; ret.y0 = text_rectangle.y0; ret.x1 = text_rectangle.x1; ret.y1 = text_rectangle.y1; eel_canvas_item_i2w (EEL_CANVAS_ITEM (item), &ret.x0, &ret.y0); eel_canvas_item_i2w (EEL_CANVAS_ITEM (item), &ret.x1, &ret.y1); return ret; } /* Get the rectangle of the icon only, in canvas coordinates. */ void nemo_icon_canvas_item_get_icon_canvas_rectangle (NemoIconCanvasItem *item, EelIRect *rect) { gint width, height; g_assert (NEMO_IS_ICON_CANVAS_ITEM (item)); g_assert (rect != NULL); eel_canvas_w2c (EEL_CANVAS_ITEM (item)->canvas, item->details->x, item->details->y, &rect->x0, &rect->y0); get_scaled_icon_size (item, &width, &height); rect->x1 = rect->x0 + width; rect->y1 = rect->y0 + height; } void nemo_icon_canvas_item_set_show_stretch_handles (NemoIconCanvasItem *item, gboolean show_stretch_handles) { g_return_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item)); g_return_if_fail (show_stretch_handles == FALSE || show_stretch_handles == TRUE); if (!item->details->show_stretch_handles == !show_stretch_handles) { return; } item->details->show_stretch_handles = show_stretch_handles; eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } /* Check if one of the stretch handles was hit. */ static gboolean hit_test_stretch_handle (NemoIconCanvasItem *item, EelIRect probe_canvas_rect, GtkCornerType *corner) { EelIRect icon_rect; GdkPixbuf *knob_pixbuf; int knob_width, knob_height; int hit_corner; g_assert (NEMO_IS_ICON_CANVAS_ITEM (item)); /* Make sure there are handles to hit. */ if (!item->details->show_stretch_handles) { return FALSE; } /* Quick check to see if the rect hits the icon at all. */ icon_rect = item->details->canvas_rect; if (!eel_irect_hits_irect (probe_canvas_rect, icon_rect)) { return FALSE; } knob_pixbuf = get_knob_pixbuf (); knob_width = gdk_pixbuf_get_width (knob_pixbuf); knob_height = gdk_pixbuf_get_height (knob_pixbuf); g_object_unref (knob_pixbuf); /* Check for hits in the stretch handles. */ hit_corner = -1; if (probe_canvas_rect.x0 < icon_rect.x0 + knob_width) { if (probe_canvas_rect.y0 < icon_rect.y0 + knob_height) hit_corner = GTK_CORNER_TOP_LEFT; else if (probe_canvas_rect.y1 >= icon_rect.y1 - knob_height) hit_corner = GTK_CORNER_BOTTOM_LEFT; } else if (probe_canvas_rect.x1 >= icon_rect.x1 - knob_width) { if (probe_canvas_rect.y0 < icon_rect.y0 + knob_height) hit_corner = GTK_CORNER_TOP_RIGHT; else if (probe_canvas_rect.y1 >= icon_rect.y1 - knob_height) hit_corner = GTK_CORNER_BOTTOM_RIGHT; } if (corner) *corner = hit_corner; return hit_corner != -1; } gboolean nemo_icon_canvas_item_hit_test_stretch_handles (NemoIconCanvasItem *item, gdouble world_x, gdouble world_y, GtkCornerType *corner) { EelIRect canvas_rect; g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), FALSE); eel_canvas_w2c (EEL_CANVAS_ITEM (item)->canvas, world_x, world_y, &canvas_rect.x0, &canvas_rect.y0); canvas_rect.x1 = canvas_rect.x0 + 1; canvas_rect.y1 = canvas_rect.y0 + 1; return hit_test_stretch_handle (item, canvas_rect, corner); } /* nemo_icon_canvas_item_hit_test_rectangle * * Check and see if there is an intersection between the item and the * canvas rect. */ gboolean nemo_icon_canvas_item_hit_test_rectangle (NemoIconCanvasItem *item, EelIRect canvas_rect) { g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item), FALSE); return hit_test (item, canvas_rect); } const char * nemo_icon_canvas_item_get_editable_text (NemoIconCanvasItem *icon_item) { g_return_val_if_fail (NEMO_IS_ICON_CANVAS_ITEM (icon_item), NULL); return icon_item->details->editable_text; } void nemo_icon_canvas_item_set_renaming (NemoIconCanvasItem *item, gboolean state) { g_return_if_fail (NEMO_IS_ICON_CANVAS_ITEM (item)); g_return_if_fail (state == FALSE || state == TRUE); if (!item->details->is_renaming == !state) { return; } item->details->is_renaming = state; eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } double nemo_icon_canvas_item_get_max_text_width (NemoIconCanvasItem *item) { EelCanvasItem *canvas_item; NemoIconContainer *container; canvas_item = EEL_CANVAS_ITEM (item); container = NEMO_ICON_CONTAINER (canvas_item->canvas); if (nemo_icon_container_is_tighter_layout (container)) { return GET_VIEW_CONSTANT (container, max_text_width_tighter) * canvas_item->canvas->pixels_per_unit; } else { if (container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { if (container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_L_R || container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_R_L) { if (container->details->all_columns_same_width) { return GET_VIEW_CONSTANT (container, max_text_width_beside_top_to_bottom) * canvas_item->canvas->pixels_per_unit; } else { return -1; } } else { return GET_VIEW_CONSTANT (container, max_text_width_beside) * canvas_item->canvas->pixels_per_unit; } } else { return GET_VIEW_CONSTANT (container, max_text_width_standard) * canvas_item->canvas->pixels_per_unit; } } } void nemo_icon_canvas_item_set_entire_text (NemoIconCanvasItem *item, gboolean entire_text) { if (item->details->entire_text != entire_text) { item->details->entire_text = entire_text; nemo_icon_canvas_item_invalidate_label_size (item); eel_canvas_item_request_update (EEL_CANVAS_ITEM (item)); } } /* Class initialization function for the icon canvas item. */ static void nemo_icon_canvas_item_class_init (NemoIconCanvasItemClass *class) { GObjectClass *object_class; EelCanvasItemClass *item_class; object_class = G_OBJECT_CLASS (class); item_class = EEL_CANVAS_ITEM_CLASS (class); object_class->finalize = nemo_icon_canvas_item_finalize; object_class->set_property = nemo_icon_canvas_item_set_property; object_class->get_property = nemo_icon_canvas_item_get_property; g_object_class_install_property ( object_class, PROP_EDITABLE_TEXT, g_param_spec_string ("editable_text", "editable text", "the editable label", "", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_ADDITIONAL_TEXT, g_param_spec_string ("additional_text", "additional text", "some more text", "", G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_FOR_SELECTION, g_param_spec_boolean ("highlighted_for_selection", "highlighted for selection", "whether we are highlighted for a selection", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_AS_KEYBOARD_FOCUS, g_param_spec_boolean ("highlighted_as_keyboard_focus", "highlighted as keyboard focus", "whether we are highlighted to render keyboard focus", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_FOR_DROP, g_param_spec_boolean ("highlighted_for_drop", "highlighted for drop", "whether we are highlighted for a D&D drop", FALSE, G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_HIGHLIGHTED_FOR_CLIPBOARD, g_param_spec_boolean ("highlighted_for_clipboard", "highlighted for clipboard", "whether we are highlighted for a clipboard paste (after we have been cut)", FALSE, G_PARAM_READWRITE)); item_class->update = nemo_icon_canvas_item_update; item_class->draw = nemo_icon_canvas_item_draw; item_class->point = nemo_icon_canvas_item_point; item_class->translate = nemo_icon_canvas_item_translate; item_class->bounds = nemo_icon_canvas_item_bounds; item_class->event = nemo_icon_canvas_item_event; atk_registry_set_factory_type (atk_get_default_registry (), NEMO_TYPE_ICON_CANVAS_ITEM, nemo_icon_canvas_item_accessible_factory_get_type ()); g_type_class_add_private (class, sizeof (NemoIconCanvasItemDetails)); } static GailTextUtil * nemo_icon_canvas_item_get_text (GObject *text) { return NEMO_ICON_CANVAS_ITEM (text)->details->text_util; } static void nemo_icon_canvas_item_text_interface_init (EelAccessibleTextIface *iface) { iface->get_text = nemo_icon_canvas_item_get_text; } /* ============================= a11y interfaces =========================== */ static const char *nemo_icon_canvas_item_accessible_action_names[] = { "open", "menu", NULL }; static const char *nemo_icon_canvas_item_accessible_action_descriptions[] = { "Open item", "Popup context menu", NULL }; enum { ACTION_OPEN, ACTION_MENU, LAST_ACTION }; typedef struct { char *action_descriptions[LAST_ACTION]; char *image_description; char *description; } NemoIconCanvasItemAccessiblePrivate; typedef struct { NemoIconCanvasItem *item; gint action_number; } NemoIconCanvasItemAccessibleActionContext; static GType nemo_icon_canvas_item_accessible_get_type (void); #define GET_PRIV(o) \ G_TYPE_INSTANCE_GET_PRIVATE(o,\ nemo_icon_canvas_item_accessible_get_type (),\ NemoIconCanvasItemAccessiblePrivate); /* accessible AtkAction interface */ static gboolean nemo_icon_canvas_item_accessible_idle_do_action (gpointer data) { NemoIconCanvasItem *item; NemoIconCanvasItemAccessibleActionContext *ctx; NemoIcon *icon; NemoIconContainer *container; GList* selection; GList file_list; GdkEventButton button_event = { 0 }; gint action_number; container = NEMO_ICON_CONTAINER (data); container->details->a11y_item_action_idle_handler = 0; while (!g_queue_is_empty (container->details->a11y_item_action_queue)) { ctx = g_queue_pop_head (container->details->a11y_item_action_queue); action_number = ctx->action_number; item = ctx->item; g_free (ctx); icon = item->user_data; switch (action_number) { case ACTION_OPEN: file_list.data = icon->data; file_list.next = NULL; file_list.prev = NULL; g_signal_emit_by_name (container, "activate", &file_list); break; case ACTION_MENU: selection = nemo_icon_container_get_selection (container); if (selection == NULL || g_list_length (selection) != 1 || selection->data != icon->data) { g_list_free (selection); return FALSE; } g_list_free (selection); g_signal_emit_by_name (container, "context_click_selection", &button_event); break; default : g_assert_not_reached (); break; } } return FALSE; } static gboolean nemo_icon_canvas_item_accessible_do_action (AtkAction *accessible, int i) { NemoIconCanvasItem *item; NemoIconCanvasItemAccessibleActionContext *ctx; NemoIconContainer *container; g_assert (i < LAST_ACTION); item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { return FALSE; } container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); switch (i) { case ACTION_OPEN: case ACTION_MENU: if (container->details->a11y_item_action_queue == NULL) { container->details->a11y_item_action_queue = g_queue_new (); } ctx = g_new (NemoIconCanvasItemAccessibleActionContext, 1); ctx->action_number = i; ctx->item = item; g_queue_push_head (container->details->a11y_item_action_queue, ctx); if (container->details->a11y_item_action_idle_handler == 0) { container->details->a11y_item_action_idle_handler = g_idle_add (nemo_icon_canvas_item_accessible_idle_do_action, container); } break; default : g_warning ("Invalid action passed to NemoIconCanvasItemAccessible::do_action"); return FALSE; } return TRUE; } static int nemo_icon_canvas_item_accessible_get_n_actions (AtkAction *accessible) { return LAST_ACTION; } static const char * nemo_icon_canvas_item_accessible_action_get_description (AtkAction *accessible, int i) { NemoIconCanvasItemAccessiblePrivate *priv; g_assert (i < LAST_ACTION); priv = GET_PRIV (accessible); if (priv->action_descriptions[i]) { return priv->action_descriptions[i]; } else { return nemo_icon_canvas_item_accessible_action_descriptions[i]; } } static const char * nemo_icon_canvas_item_accessible_action_get_name (AtkAction *accessible, int i) { g_assert (i < LAST_ACTION); return nemo_icon_canvas_item_accessible_action_names[i]; } static const char * nemo_icon_canvas_item_accessible_action_get_keybinding (AtkAction *accessible, int i) { g_assert (i < LAST_ACTION); return NULL; } static gboolean nemo_icon_canvas_item_accessible_action_set_description (AtkAction *accessible, int i, const char *description) { NemoIconCanvasItemAccessiblePrivate *priv; g_assert (i < LAST_ACTION); priv = GET_PRIV (accessible); if (priv->action_descriptions[i]) { g_free (priv->action_descriptions[i]); } priv->action_descriptions[i] = g_strdup (description); return TRUE; } static void nemo_icon_canvas_item_accessible_action_interface_init (AtkActionIface *iface) { iface->do_action = nemo_icon_canvas_item_accessible_do_action; iface->get_n_actions = nemo_icon_canvas_item_accessible_get_n_actions; iface->get_description = nemo_icon_canvas_item_accessible_action_get_description; iface->get_keybinding = nemo_icon_canvas_item_accessible_action_get_keybinding; iface->get_name = nemo_icon_canvas_item_accessible_action_get_name; iface->set_description = nemo_icon_canvas_item_accessible_action_set_description; } static const gchar * nemo_icon_canvas_item_accessible_get_name (AtkObject *accessible) { NemoIconCanvasItem *item; if (accessible->name) { return accessible->name; } item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { return NULL; } return item->details->editable_text; } static const gchar* nemo_icon_canvas_item_accessible_get_description (AtkObject *accessible) { NemoIconCanvasItem *item; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { return NULL; } return item->details->additional_text; } static AtkObject * nemo_icon_canvas_item_accessible_get_parent (AtkObject *accessible) { NemoIconCanvasItem *item; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { return NULL; } return gtk_widget_get_accessible (GTK_WIDGET (EEL_CANVAS_ITEM (item)->canvas)); } static int nemo_icon_canvas_item_accessible_get_index_in_parent (AtkObject *accessible) { NemoIconCanvasItem *item; NemoIconContainer *container; GList *l; NemoIcon *icon; int i; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { return -1; } container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); l = container->details->icons; i = 0; while (l) { icon = l->data; if (icon->item == item) { return i; } i++; l = l->next; } return -1; } static const gchar * nemo_icon_canvas_item_accessible_get_image_description (AtkImage *image) { NemoIconCanvasItemAccessiblePrivate *priv; NemoIconCanvasItem *item; NemoIcon *icon; NemoIconContainer *container; char *description; priv = GET_PRIV (image); if (priv->image_description) { return priv->image_description; } else { item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (image))); if (item == NULL) { return NULL; } icon = item->user_data; container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); description = nemo_icon_container_get_icon_description (container, icon->data); g_free (priv->description); priv->description = description; return priv->description; } } static void nemo_icon_canvas_item_accessible_get_image_size (AtkImage *image, gint *width, gint *height) { NemoIconCanvasItem *item; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (image))); get_scaled_icon_size (item, width, height); } static void nemo_icon_canvas_item_accessible_get_image_position (AtkImage *image, gint *x, gint *y, AtkCoordType coord_type) { NemoIconCanvasItem *item; gint x_offset, y_offset, itmp; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (image))); if (!item) { return; } if (!item->details->canvas_rect.x0 && !item->details->canvas_rect.x1) { return; } else { x_offset = 0; y_offset = 0; if (item->details->text_width) { itmp = item->details->canvas_rect.x0 - item->details->text_rect.x0; if (itmp > x_offset) { x_offset = itmp; } itmp = item->details->canvas_rect.y0 - item->details->text_rect.y0; if (itmp > y_offset) { y_offset = itmp; } } } atk_component_get_position (ATK_COMPONENT (image), x, y, coord_type); *x += x_offset; *y += y_offset; } static gboolean nemo_icon_canvas_item_accessible_set_image_description (AtkImage *image, const gchar *description) { NemoIconCanvasItemAccessiblePrivate *priv; priv = GET_PRIV (image); g_free (priv->image_description); priv->image_description = g_strdup (description); return TRUE; } static void nemo_icon_canvas_item_accessible_image_interface_init (AtkImageIface *iface) { iface->get_image_description = nemo_icon_canvas_item_accessible_get_image_description; iface->set_image_description = nemo_icon_canvas_item_accessible_set_image_description; iface->get_image_size = nemo_icon_canvas_item_accessible_get_image_size; iface->get_image_position = nemo_icon_canvas_item_accessible_get_image_position; } /* accessible text interface */ static gint nemo_icon_canvas_item_accessible_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords) { gint real_x, real_y, real_width, real_height; NemoIconCanvasItem *item; gint editable_height; gint offset = 0; gint index; PangoLayout *layout, *editable_layout, *additional_layout; PangoRectangle rect0; char *icon_text; gboolean have_editable; gboolean have_additional; gint text_offset, height; atk_component_get_extents (ATK_COMPONENT (text), &real_x, &real_y, &real_width, &real_height, coords); x -= real_x; y -= real_y; item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); if (item->details->pixbuf) { get_scaled_icon_size (item, NULL, &height); y -= height; } have_editable = item->details->editable_text != NULL && item->details->editable_text[0] != '\0'; have_additional = item->details->additional_text != NULL &&item->details->additional_text[0] != '\0'; editable_layout = NULL; additional_layout = NULL; if (have_editable) { editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text); prepare_pango_layout_for_draw (item, editable_layout); pango_layout_get_pixel_size (editable_layout, NULL, &editable_height); if (y >= editable_height && have_additional) { prepare_pango_layout_for_draw (item, editable_layout); additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); layout = additional_layout; icon_text = item->details->additional_text; y -= editable_height + LABEL_LINE_SPACING; } else { layout = editable_layout; icon_text = item->details->editable_text; } } else if (have_additional) { additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); prepare_pango_layout_for_draw (item, additional_layout); layout = additional_layout; icon_text = item->details->additional_text; } else { return 0; } text_offset = 0; if (have_editable) { pango_layout_index_to_pos (editable_layout, 0, &rect0); text_offset = PANGO_PIXELS (rect0.x); } if (have_additional) { gint itmp; pango_layout_index_to_pos (additional_layout, 0, &rect0); itmp = PANGO_PIXELS (rect0.x); if (itmp < text_offset) { text_offset = itmp; } } pango_layout_index_to_pos (layout, 0, &rect0); x += text_offset; if (!pango_layout_xy_to_index (layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, NULL)) { if (x < 0 || y < 0) { index = 0; } else { index = -1; } } if (index == -1) { offset = g_utf8_strlen (icon_text, -1); } else { offset = g_utf8_pointer_to_offset (icon_text, icon_text + index); } if (layout == additional_layout) { offset += g_utf8_strlen (item->details->editable_text, -1); } if (editable_layout != NULL) { g_object_unref (editable_layout); } if (additional_layout != NULL) { g_object_unref (additional_layout); } return offset; } static void nemo_icon_canvas_item_accessible_get_character_extents (AtkText *text, gint offset, gint *x, gint *y, gint *width, gint *height, AtkCoordType coords) { gint pos_x, pos_y; gint len, byte_offset; gint editable_height; gchar *icon_text; NemoIconCanvasItem *item; PangoLayout *layout, *editable_layout, *additional_layout; PangoRectangle rect; PangoRectangle rect0; gboolean have_editable; gint text_offset, pix_height; atk_component_get_position (ATK_COMPONENT (text), &pos_x, &pos_y, coords); item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); if (item->details->pixbuf) { get_scaled_icon_size (item, NULL, &pix_height); pos_y += pix_height; } have_editable = item->details->editable_text != NULL && item->details->editable_text[0] != '\0'; if (have_editable) { len = g_utf8_strlen (item->details->editable_text, -1); } else { len = 0; } editable_layout = get_label_layout (&item->details->editable_text_layout, item, item->details->editable_text); additional_layout = get_label_layout (&item->details->additional_text_layout, item, item->details->additional_text); if (offset < len) { icon_text = item->details->editable_text; layout = editable_layout; } else { offset -= len; icon_text = item->details->additional_text; layout = additional_layout; pos_y += LABEL_LINE_SPACING; if (have_editable) { pango_layout_get_pixel_size (editable_layout, NULL, &editable_height); pos_y += editable_height; } } byte_offset = g_utf8_offset_to_pointer (icon_text, offset) - icon_text; pango_layout_index_to_pos (layout, byte_offset, &rect); text_offset = 0; if (have_editable) { pango_layout_index_to_pos (editable_layout, 0, &rect0); text_offset = PANGO_PIXELS (rect0.x); } if (item->details->additional_text != NULL && item->details->additional_text[0] != '\0') { gint itmp; pango_layout_index_to_pos (additional_layout, 0, &rect0); itmp = PANGO_PIXELS (rect0.x); if (itmp < text_offset) { text_offset = itmp; } } g_object_unref (editable_layout); g_object_unref (additional_layout); *x = pos_x + PANGO_PIXELS (rect.x) - text_offset; *y = pos_y + PANGO_PIXELS (rect.y); *width = PANGO_PIXELS (rect.width); *height = PANGO_PIXELS (rect.height); } static void nemo_icon_canvas_item_accessible_text_interface_init (AtkTextIface *iface) { iface->get_text = eel_accessibility_text_get_text; iface->get_character_at_offset = eel_accessibility_text_get_character_at_offset; iface->get_text_before_offset = eel_accessibility_text_get_text_before_offset; iface->get_text_at_offset = eel_accessibility_text_get_text_at_offset; iface->get_text_after_offset = eel_accessibility_text_get_text_after_offset; iface->get_character_count = eel_accessibility_text_get_character_count; iface->get_character_extents = nemo_icon_canvas_item_accessible_get_character_extents; iface->get_offset_at_point = nemo_icon_canvas_item_accessible_get_offset_at_point; } typedef struct { AtkGObjectAccessible parent; } NemoIconCanvasItemAccessible; typedef struct { AtkGObjectAccessibleClass parent_class; } NemoIconCanvasItemAccessibleClass; G_DEFINE_TYPE_WITH_CODE (NemoIconCanvasItemAccessible, nemo_icon_canvas_item_accessible, ATK_TYPE_GOBJECT_ACCESSIBLE, G_IMPLEMENT_INTERFACE (ATK_TYPE_IMAGE, nemo_icon_canvas_item_accessible_image_interface_init) G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, nemo_icon_canvas_item_accessible_text_interface_init) G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, nemo_icon_canvas_item_accessible_action_interface_init)); static AtkStateSet* nemo_icon_canvas_item_accessible_ref_state_set (AtkObject *accessible) { AtkStateSet *state_set; NemoIconCanvasItem *item; NemoIconContainer *container; NemoIcon *icon; GList *l; gboolean one_item_selected; state_set = ATK_OBJECT_CLASS (nemo_icon_canvas_item_accessible_parent_class)->ref_state_set (accessible); item = NEMO_ICON_CANVAS_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); if (!item) { atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT); return state_set; } container = NEMO_ICON_CONTAINER (EEL_CANVAS_ITEM (item)->canvas); if (item->details->is_highlighted_as_keyboard_focus) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); } else if (!container->details->keyboard_focus) { one_item_selected = FALSE; l = container->details->icons; while (l) { icon = l->data; if (icon->item == item) { if (icon->is_selected) { one_item_selected = TRUE; } else { break; } } else if (icon->is_selected) { one_item_selected = FALSE; break; } l = l->next; } if (one_item_selected) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); } } return state_set; } static void nemo_icon_canvas_item_accessible_finalize (GObject *object) { NemoIconCanvasItemAccessiblePrivate *priv; int i; priv = GET_PRIV (object); for (i = 0; i < LAST_ACTION; i++) { g_free (priv->action_descriptions[i]); } g_free (priv->image_description); g_free (priv->description); G_OBJECT_CLASS (nemo_icon_canvas_item_accessible_parent_class)->finalize (object); } static void nemo_icon_canvas_item_accessible_initialize (AtkObject *accessible, gpointer widget) { ATK_OBJECT_CLASS (nemo_icon_canvas_item_accessible_parent_class)->initialize (accessible, widget); atk_object_set_role (accessible, ATK_ROLE_ICON); } static void nemo_icon_canvas_item_accessible_class_init (NemoIconCanvasItemAccessibleClass *klass) { AtkObjectClass *aclass = ATK_OBJECT_CLASS (klass); GObjectClass *oclass = G_OBJECT_CLASS (klass); oclass->finalize = nemo_icon_canvas_item_accessible_finalize; aclass->initialize = nemo_icon_canvas_item_accessible_initialize; aclass->get_name = nemo_icon_canvas_item_accessible_get_name; aclass->get_description = nemo_icon_canvas_item_accessible_get_description; aclass->get_parent = nemo_icon_canvas_item_accessible_get_parent; aclass->get_index_in_parent = nemo_icon_canvas_item_accessible_get_index_in_parent; aclass->ref_state_set = nemo_icon_canvas_item_accessible_ref_state_set; g_type_class_add_private (klass, sizeof (NemoIconCanvasItemAccessiblePrivate)); } static void nemo_icon_canvas_item_accessible_init (NemoIconCanvasItemAccessible *self) { } /* dummy typedef */ typedef AtkObjectFactory NemoIconCanvasItemAccessibleFactory; typedef AtkObjectFactoryClass NemoIconCanvasItemAccessibleFactoryClass; G_DEFINE_TYPE (NemoIconCanvasItemAccessibleFactory, nemo_icon_canvas_item_accessible_factory, ATK_TYPE_OBJECT_FACTORY); static AtkObject * nemo_icon_canvas_item_accessible_factory_create_accessible (GObject *for_object) { AtkObject *accessible; NemoIconCanvasItem *item; GString *item_text; item = NEMO_ICON_CANVAS_ITEM (for_object); g_assert (item != NULL); item_text = g_string_new (NULL); if (item->details->editable_text) { g_string_append (item_text, item->details->editable_text); } if (item->details->additional_text) { g_string_append (item_text, item->details->additional_text); } item->details->text_util = gail_text_util_new (); gail_text_util_text_setup (item->details->text_util, item_text->str); g_string_free (item_text, TRUE); accessible = g_object_new (nemo_icon_canvas_item_accessible_get_type (), NULL); atk_object_initialize (accessible, for_object); return accessible; } static GType nemo_icon_canvas_item_accessible_factory_get_accessible_type (void) { return nemo_icon_canvas_item_accessible_get_type (); } static void nemo_icon_canvas_item_accessible_factory_init (NemoIconCanvasItemAccessibleFactory *self) { } static void nemo_icon_canvas_item_accessible_factory_class_init (NemoIconCanvasItemAccessibleFactoryClass *klass) { klass->create_accessible = nemo_icon_canvas_item_accessible_factory_create_accessible; klass->get_accessible_type = nemo_icon_canvas_item_accessible_factory_get_accessible_type; } void nemo_icon_canvas_item_set_tooltip_text (NemoIconCanvasItem *item, const gchar *text) { item->tooltip = g_strdup (text); } nemo-3.6.5/libnemo-private/nemo-icon-info.c0000664000175000017500000004421013215733314017470 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-icon-info.c * Copyright (C) 2007 Red Hat, Inc., Alexander Larsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include #include "nemo-icon-info.h" #include "nemo-icon-names.h" #include "nemo-default-file-icon.h" #include #include struct _NemoIconInfo { GObject parent; gboolean sole_owner; gint64 last_use_time; GdkPixbuf *pixbuf; gboolean got_embedded_rect; GdkRectangle embedded_rect; gint n_attach_points; GdkPoint *attach_points; char *display_name; char *icon_name; gint orig_scale; }; struct _NemoIconInfoClass { GObjectClass parent_class; }; static void schedule_reap_cache (void); G_DEFINE_TYPE (NemoIconInfo, nemo_icon_info, G_TYPE_OBJECT); static void nemo_icon_info_init (NemoIconInfo *icon) { icon->last_use_time = g_get_monotonic_time (); icon->sole_owner = TRUE; } gboolean nemo_icon_info_is_fallback (NemoIconInfo *icon) { return icon->pixbuf == NULL; } static void pixbuf_toggle_notify (gpointer info, GObject *object, gboolean is_last_ref) { NemoIconInfo *icon = info; if (is_last_ref) { icon->sole_owner = TRUE; g_object_remove_toggle_ref (object, pixbuf_toggle_notify, info); icon->last_use_time = g_get_monotonic_time (); schedule_reap_cache (); } } static void nemo_icon_info_finalize (GObject *object) { NemoIconInfo *icon; icon = NEMO_ICON_INFO (object); if (!icon->sole_owner && icon->pixbuf) { g_object_remove_toggle_ref (G_OBJECT (icon->pixbuf), pixbuf_toggle_notify, icon); } if (icon->pixbuf) { g_object_unref (icon->pixbuf); } g_free (icon->attach_points); g_free (icon->display_name); g_free (icon->icon_name); G_OBJECT_CLASS (nemo_icon_info_parent_class)->finalize (object); } static void nemo_icon_info_class_init (NemoIconInfoClass *icon_info_class) { GObjectClass *gobject_class; gobject_class = (GObjectClass *) icon_info_class; gobject_class->finalize = nemo_icon_info_finalize; } NemoIconInfo * nemo_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf, gint scale) { NemoIconInfo *icon; icon = g_object_new (NEMO_TYPE_ICON_INFO, NULL); if (pixbuf) { icon->pixbuf = g_object_ref (pixbuf); } icon->orig_scale = scale; return icon; } static NemoIconInfo * nemo_icon_info_new_for_icon_info (GtkIconInfo *icon_info, gint scale) { NemoIconInfo *icon; GdkPoint *points; gint n_points; const char *filename; char *basename, *p; icon = g_object_new (NEMO_TYPE_ICON_INFO, NULL); icon->pixbuf = gtk_icon_info_load_icon (icon_info, NULL); icon->got_embedded_rect = gtk_icon_info_get_embedded_rect (icon_info, &icon->embedded_rect); if (gtk_icon_info_get_attach_points (icon_info, &points, &n_points)) { icon->n_attach_points = n_points; icon->attach_points = points; } icon->display_name = g_strdup (gtk_icon_info_get_display_name (icon_info)); filename = gtk_icon_info_get_filename (icon_info); if (filename != NULL) { basename = g_path_get_basename (filename); p = strrchr (basename, '.'); if (p) { *p = 0; } icon->icon_name = basename; } icon->orig_scale = scale; return icon; } typedef struct { GIcon *icon; int size; } LoadableIconKey; typedef struct { char *filename; int size; } ThemedIconKey; static GHashTable *loadable_icon_cache = NULL; static GHashTable *themed_icon_cache = NULL; static guint reap_cache_timeout = 0; #define MICROSEC_PER_SEC ((guint64)1000000L) static guint time_now; static gboolean reap_old_icon (gpointer key, gpointer value, gpointer user_info) { NemoIconInfo *icon = value; gboolean *reapable_icons_left = user_info; if (icon->sole_owner) { if (time_now - icon->last_use_time > 30 * MICROSEC_PER_SEC) { /* This went unused 30 secs ago. reap */ return TRUE; } else { /* We can reap this soon */ *reapable_icons_left = TRUE; } } return FALSE; } static gboolean reap_cache (gpointer data) { gboolean reapable_icons_left; reapable_icons_left = TRUE; time_now = g_get_monotonic_time (); if (loadable_icon_cache) { g_hash_table_foreach_remove (loadable_icon_cache, reap_old_icon, &reapable_icons_left); } if (themed_icon_cache) { g_hash_table_foreach_remove (themed_icon_cache, reap_old_icon, &reapable_icons_left); } if (reapable_icons_left) { return TRUE; } else { reap_cache_timeout = 0; return FALSE; } } static void schedule_reap_cache (void) { if (reap_cache_timeout == 0) { reap_cache_timeout = g_timeout_add_seconds_full (0, 5, reap_cache, NULL, NULL); } } void nemo_icon_info_clear_caches (void) { if (loadable_icon_cache) { g_hash_table_remove_all (loadable_icon_cache); } if (themed_icon_cache) { g_hash_table_remove_all (themed_icon_cache); } } static guint loadable_icon_key_hash (LoadableIconKey *key) { return g_icon_hash (key->icon) ^ key->size; } static gboolean loadable_icon_key_equal (const LoadableIconKey *a, const LoadableIconKey *b) { return a->size == b->size && g_icon_equal (a->icon, b->icon); } static LoadableIconKey * loadable_icon_key_new (GIcon *icon, int size) { LoadableIconKey *key; key = g_slice_new (LoadableIconKey); key->icon = g_object_ref (icon); key->size = size; return key; } static void loadable_icon_key_free (LoadableIconKey *key) { g_object_unref (key->icon); g_slice_free (LoadableIconKey, key); } static guint themed_icon_key_hash (ThemedIconKey *key) { return g_str_hash (key->filename) ^ key->size; } static gboolean themed_icon_key_equal (const ThemedIconKey *a, const ThemedIconKey *b) { return a->size == b->size && g_str_equal (a->filename, b->filename); } static ThemedIconKey * themed_icon_key_new (const char *filename, int size) { ThemedIconKey *key; key = g_slice_new (ThemedIconKey); key->filename = g_strdup (filename); key->size = size; return key; } static void themed_icon_key_free (ThemedIconKey *key) { g_free (key->filename); g_slice_free (ThemedIconKey, key); } NemoIconInfo * nemo_icon_info_lookup (GIcon *icon, int size, int scale) { NemoIconInfo *icon_info; if (G_IS_LOADABLE_ICON (icon)) { GdkPixbuf *pixbuf; LoadableIconKey lookup_key; LoadableIconKey *key; GInputStream *stream; if (loadable_icon_cache == NULL) { loadable_icon_cache = g_hash_table_new_full ((GHashFunc)loadable_icon_key_hash, (GEqualFunc)loadable_icon_key_equal, (GDestroyNotify) loadable_icon_key_free, (GDestroyNotify) g_object_unref); } lookup_key.icon = icon; lookup_key.size = size; icon_info = g_hash_table_lookup (loadable_icon_cache, &lookup_key); if (icon_info) { return g_object_ref (icon_info); } pixbuf = NULL; stream = g_loadable_icon_load (G_LOADABLE_ICON (icon), size * scale, NULL, NULL, NULL); if (stream) { pixbuf = gdk_pixbuf_new_from_stream_at_scale (stream, size * scale, size * scale, TRUE, NULL, NULL); g_input_stream_close (stream, NULL, NULL); g_object_unref (stream); } icon_info = nemo_icon_info_new_for_pixbuf (pixbuf, scale); key = loadable_icon_key_new (icon, size); g_hash_table_insert (loadable_icon_cache, key, icon_info); g_clear_object (&pixbuf); return g_object_ref (icon_info); } else if (G_IS_THEMED_ICON (icon)) { const char * const *names; ThemedIconKey lookup_key; ThemedIconKey *key; GtkIconTheme *icon_theme; GtkIconInfo *gtkicon_info; const char *filename; if (themed_icon_cache == NULL) { themed_icon_cache = g_hash_table_new_full ((GHashFunc)themed_icon_key_hash, (GEqualFunc)themed_icon_key_equal, (GDestroyNotify) themed_icon_key_free, (GDestroyNotify) g_object_unref); } names = g_themed_icon_get_names (G_THEMED_ICON (icon)); icon_theme = gtk_icon_theme_get_default (); gtkicon_info = gtk_icon_theme_choose_icon_for_scale (icon_theme, (const char **)names, size, scale, 0); if (gtkicon_info == NULL) { return nemo_icon_info_new_for_pixbuf (NULL, scale); } filename = gtk_icon_info_get_filename (gtkicon_info); if (filename == NULL) { g_object_unref (gtkicon_info); return nemo_icon_info_new_for_pixbuf (NULL, scale); } lookup_key.filename = (char *)filename; lookup_key.size = size; icon_info = g_hash_table_lookup (themed_icon_cache, &lookup_key); if (icon_info) { g_object_unref (gtkicon_info); return g_object_ref (icon_info); } icon_info = nemo_icon_info_new_for_icon_info (gtkicon_info, scale); key = themed_icon_key_new (filename, size); g_hash_table_insert (themed_icon_cache, key, icon_info); g_object_unref (gtkicon_info); return g_object_ref (icon_info); } else { GdkPixbuf *pixbuf; GtkIconInfo *gtk_icon_info; gtk_icon_info = gtk_icon_theme_lookup_by_gicon_for_scale (gtk_icon_theme_get_default (), icon, size, scale, 0); if (gtk_icon_info != NULL) { pixbuf = gtk_icon_info_load_icon (gtk_icon_info, NULL); g_object_unref (gtk_icon_info); } else { pixbuf = NULL; } icon_info = nemo_icon_info_new_for_pixbuf (pixbuf, scale); g_clear_object (&pixbuf); return icon_info; } } NemoIconInfo * nemo_icon_info_lookup_from_name (const char *name, int size, int scale) { GIcon *icon; NemoIconInfo *info; icon = g_themed_icon_new (name); info = nemo_icon_info_lookup (icon, size, scale); g_object_unref (icon); return info; } NemoIconInfo * nemo_icon_info_lookup_from_path (const char *path, int size, int scale) { GFile *icon_file; GIcon *icon; NemoIconInfo *info; icon_file = g_file_new_for_path (path); icon = g_file_icon_new (icon_file); info = nemo_icon_info_lookup (icon, size, scale); g_object_unref (icon); g_object_unref (icon_file); return info; } GdkPixbuf * nemo_icon_info_get_pixbuf_nodefault (NemoIconInfo *icon) { GdkPixbuf *res; if (icon->pixbuf == NULL) { res = NULL; } else { res = g_object_ref (icon->pixbuf); if (icon->sole_owner) { icon->sole_owner = FALSE; g_object_add_toggle_ref (G_OBJECT (res), pixbuf_toggle_notify, icon); } } return res; } GdkPixbuf * nemo_icon_info_get_pixbuf (NemoIconInfo *icon) { GdkPixbuf *res; res = nemo_icon_info_get_pixbuf_nodefault (icon); if (res == NULL) { res = gdk_pixbuf_new_from_data (nemo_default_file_icon, GDK_COLORSPACE_RGB, TRUE, 8, nemo_default_file_icon_width, nemo_default_file_icon_height, nemo_default_file_icon_width * 4, /* stride */ NULL, /* don't destroy info */ NULL); } return res; } GdkPixbuf * nemo_icon_info_get_pixbuf_nodefault_at_size (NemoIconInfo *icon, gsize forced_size) { GdkPixbuf *pixbuf, *scaled_pixbuf; int w, h, s; double scale; pixbuf = nemo_icon_info_get_pixbuf_nodefault (icon); if (pixbuf == NULL) return NULL; w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale; h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale; s = MAX (w, h); if (s == forced_size) { return pixbuf; } scale = (double)forced_size / s; scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, MAX (w * scale, 1), MAX (h * scale, 1), GDK_INTERP_BILINEAR); g_object_unref (pixbuf); return scaled_pixbuf; } GdkPixbuf * nemo_icon_info_get_pixbuf_at_size (NemoIconInfo *icon, gsize forced_size) { GdkPixbuf *pixbuf, *scaled_pixbuf; int w, h, s; double scale; pixbuf = nemo_icon_info_get_pixbuf (icon); w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale; h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale; s = MAX (w, h); if (s == forced_size) { return pixbuf; } scale = (double)forced_size / s; scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, MAX (w * scale, 1), MAX (h * scale, 1), GDK_INTERP_BILINEAR); g_object_unref (pixbuf); return scaled_pixbuf; } GdkPixbuf * nemo_icon_info_get_desktop_pixbuf_at_size (NemoIconInfo *icon, gsize max_height, gsize max_width) { GdkPixbuf *pixbuf, *scaled_pixbuf; int w, h; double scale; pixbuf = nemo_icon_info_get_pixbuf (icon); w = gdk_pixbuf_get_width (pixbuf) / icon->orig_scale; h = gdk_pixbuf_get_height (pixbuf) / icon->orig_scale; if (w == max_width || h == max_height) { return pixbuf; } scale = (gdouble) max_height / h; if (w * scale > max_width) { scale = (gdouble) max_width / w; } scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf, MAX (w * scale, 1), MAX (h * scale, 1), GDK_INTERP_BILINEAR); g_object_unref (pixbuf); return scaled_pixbuf; } gboolean nemo_icon_info_get_embedded_rect (NemoIconInfo *icon, GdkRectangle *rectangle) { *rectangle = icon->embedded_rect; return icon->got_embedded_rect; } gboolean nemo_icon_info_get_attach_points (NemoIconInfo *icon, GdkPoint **points, gint *n_points) { *n_points = icon->n_attach_points; *points = icon->attach_points; return icon->n_attach_points != 0; } const char * nemo_icon_info_get_display_name (NemoIconInfo *icon) { return icon->display_name; } const char * nemo_icon_info_get_used_name (NemoIconInfo *icon) { return icon->icon_name; } /* Return nominal icon size for given zoom level. * @zoom_level: zoom level for which to find matching icon size. * * Return value: icon size between NEMO_ICON_SIZE_SMALLEST and * NEMO_ICON_SIZE_LARGEST, inclusive. */ guint nemo_get_icon_size_for_zoom_level (NemoZoomLevel zoom_level) { switch (zoom_level) { case NEMO_ZOOM_LEVEL_SMALLEST: return NEMO_ICON_SIZE_SMALLEST; case NEMO_ZOOM_LEVEL_SMALLER: return NEMO_ICON_SIZE_SMALLER; case NEMO_ZOOM_LEVEL_SMALL: return NEMO_ICON_SIZE_SMALL; case NEMO_ZOOM_LEVEL_STANDARD: return NEMO_ICON_SIZE_STANDARD; case NEMO_ZOOM_LEVEL_LARGE: return NEMO_ICON_SIZE_LARGE; case NEMO_ZOOM_LEVEL_LARGER: return NEMO_ICON_SIZE_LARGER; case NEMO_ZOOM_LEVEL_LARGEST: return NEMO_ICON_SIZE_LARGEST; default: g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD); } } guint nemo_get_desktop_icon_size_for_zoom_level (NemoZoomLevel zoom_level) { switch (zoom_level) { case NEMO_ZOOM_LEVEL_SMALL: return NEMO_DESKTOP_ICON_SIZE_SMALL; case NEMO_ZOOM_LEVEL_STANDARD: return NEMO_DESKTOP_ICON_SIZE_STANDARD; case NEMO_ZOOM_LEVEL_LARGE: return NEMO_DESKTOP_ICON_SIZE_LARGE; case NEMO_ZOOM_LEVEL_SMALLEST: case NEMO_ZOOM_LEVEL_SMALLER: case NEMO_ZOOM_LEVEL_LARGER: case NEMO_ZOOM_LEVEL_LARGEST: default: g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD); } } guint nemo_get_list_icon_size_for_zoom_level (NemoZoomLevel zoom_level) { switch (zoom_level) { case NEMO_ZOOM_LEVEL_SMALLEST: return NEMO_ICON_SIZE_SMALLEST; case NEMO_ZOOM_LEVEL_SMALLER: return NEMO_ICON_SIZE_SMALLEST; case NEMO_ZOOM_LEVEL_SMALL: return NEMO_ICON_SIZE_SMALLER; case NEMO_ZOOM_LEVEL_STANDARD: return NEMO_ICON_SIZE_SMALL; case NEMO_ZOOM_LEVEL_LARGE: return NEMO_ICON_SIZE_STANDARD; case NEMO_ZOOM_LEVEL_LARGER: return NEMO_ICON_SIZE_LARGE; case NEMO_ZOOM_LEVEL_LARGEST: return NEMO_ICON_SIZE_LARGER; default: g_return_val_if_reached (NEMO_ICON_SIZE_STANDARD); } } gint nemo_get_icon_size_for_stock_size (GtkIconSize size) { gint w, h; if (gtk_icon_size_lookup (size, &w, &h)) { return MAX (w, h); } return NEMO_ICON_SIZE_STANDARD; } guint nemo_icon_get_emblem_size_for_icon_size (guint size) { if (size >= 96) return 48; if (size >= 64) return 32; if (size >= 48) return 24; if (size >= 24) return 16; if (size >= 16) return 12; return 0; /* no emblems for smaller sizes */ } gboolean nemo_icon_theme_can_render (GThemedIcon *icon) { GtkIconTheme *icon_theme; const gchar * const *names; gint idx; names = g_themed_icon_get_names (icon); icon_theme = gtk_icon_theme_get_default (); for (idx = 0; names[idx] != NULL; idx++) { if (gtk_icon_theme_has_icon (icon_theme, names[idx])) { return TRUE; } } return FALSE; } GIcon * nemo_user_special_directory_get_gicon (GUserDirectory directory) { #define ICON_CASE(x) \ case G_USER_DIRECTORY_ ## x:\ return g_themed_icon_new (NEMO_ICON_FOLDER_ ## x); switch (directory) { ICON_CASE (DESKTOP); ICON_CASE (DOCUMENTS); ICON_CASE (DOWNLOAD); ICON_CASE (MUSIC); ICON_CASE (PICTURES); ICON_CASE (PUBLIC_SHARE); ICON_CASE (TEMPLATES); ICON_CASE (VIDEOS); default: return g_themed_icon_new ("folder"); } #undef ICON_CASE } nemo-3.6.5/libnemo-private/nemo-vfs-file.h0000664000175000017500000000353213215733314017331 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-vfs-file.h: Subclass of NemoFile to implement the the case of a VFS file. Copyright (C) 1999, 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_VFS_FILE_H #define NEMO_VFS_FILE_H #include #define NEMO_TYPE_VFS_FILE nemo_vfs_file_get_type() #define NEMO_VFS_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_VFS_FILE, NemoVFSFile)) #define NEMO_VFS_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_VFS_FILE, NemoVFSFileClass)) #define NEMO_IS_VFS_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_VFS_FILE)) #define NEMO_IS_VFS_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_VFS_FILE)) #define NEMO_VFS_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_VFS_FILE, NemoVFSFileClass)) typedef struct NemoVFSFileDetails NemoVFSFileDetails; typedef struct { NemoFile parent_slot; } NemoVFSFile; typedef struct { NemoFileClass parent_slot; } NemoVFSFileClass; GType nemo_vfs_file_get_type (void); #endif /* NEMO_VFS_FILE_H */ nemo-3.6.5/libnemo-private/nemo-search-directory-file.h0000664000175000017500000000443413215733314022004 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-search-directory-file.h: Subclass of NemoFile to implement the the case of the search directory Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_SEARCH_DIRECTORY_FILE_H #define NEMO_SEARCH_DIRECTORY_FILE_H #include #define NEMO_TYPE_SEARCH_DIRECTORY_FILE nemo_search_directory_file_get_type() #define NEMO_SEARCH_DIRECTORY_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEARCH_DIRECTORY_FILE, NemoSearchDirectoryFile)) #define NEMO_SEARCH_DIRECTORY_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEARCH_DIRECTORY_FILE, NemoSearchDirectoryFileClass)) #define NEMO_IS_SEARCH_DIRECTORY_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEARCH_DIRECTORY_FILE)) #define NEMO_IS_SEARCH_DIRECTORY_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEARCH_DIRECTORY_FILE)) #define NEMO_SEARCH_DIRECTORY_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEARCH_DIRECTORY_FILE, NemoSearchDirectoryFileClass)) typedef struct NemoSearchDirectoryFileDetails NemoSearchDirectoryFileDetails; typedef struct { NemoFile parent_slot; NemoSearchDirectoryFileDetails *details; } NemoSearchDirectoryFile; typedef struct { NemoFileClass parent_slot; } NemoSearchDirectoryFileClass; GType nemo_search_directory_file_get_type (void); void nemo_search_directory_file_update_display_name (NemoSearchDirectoryFile *search_file); #endif /* NEMO_SEARCH_DIRECTORY_FILE_H */ nemo-3.6.5/libnemo-private/nemo-separator-action.h0000664000175000017500000000373113215733314021072 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_SEPARATOR_ACTION_H #define NEMO_SEPARATOR_ACTION_H #include #define NEMO_TYPE_SEPARATOR_ACTION nemo_separator_action_get_type() #define NEMO_SEPARATOR_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEPARATOR_ACTION, NemoSeparatorAction)) #define NEMO_SEPARATOR_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEPARATOR_ACTION, NemoSeparatorActionClass)) #define NEMO_IS_SEPARATOR_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEPARATOR_ACTION)) #define NEMO_IS_SEPARATOR_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEPARATOR_ACTION)) #define NEMO_SEPARATOR_ACTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEPARATOR_ACTION, NemoSeparatorActionClass)) typedef struct _NemoSeparatorAction NemoSeparatorAction; typedef struct _NemoSeparatorActionClass NemoSeparatorActionClass; struct _NemoSeparatorAction { GtkAction parent; }; struct _NemoSeparatorActionClass { GtkActionClass parent_class; }; GType nemo_separator_action_get_type (void); GtkAction *nemo_separator_action_new (const gchar *name); #endif /* NEMO_SEPARATOR_ACTION_H */ nemo-3.6.5/libnemo-private/nemo-vfs-directory.c0000664000175000017500000001006213215733314020405 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-vfs-directory.c: Subclass of NemoDirectory to help implement the virtual trash directory. Copyright (C) 1999, 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-vfs-directory.h" #include "nemo-directory-private.h" #include "nemo-file-private.h" G_DEFINE_TYPE (NemoVFSDirectory, nemo_vfs_directory, NEMO_TYPE_DIRECTORY); static void nemo_vfs_directory_init (NemoVFSDirectory *directory) { } static gboolean vfs_contains_file (NemoDirectory *directory, NemoFile *file) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); g_assert (NEMO_IS_FILE (file)); return file->details->directory == directory; } static void vfs_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback callback, gpointer callback_data) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); nemo_directory_call_when_ready_internal (directory, NULL, file_attributes, wait_for_file_list, callback, NULL, callback_data); } static void vfs_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); nemo_directory_cancel_callback_internal (directory, NULL, callback, NULL, callback_data); } static void vfs_file_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); g_assert (client != NULL); nemo_directory_monitor_add_internal (directory, NULL, client, monitor_hidden_files, file_attributes, callback, callback_data); } static void vfs_file_monitor_remove (NemoDirectory *directory, gconstpointer client) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); g_assert (client != NULL); nemo_directory_monitor_remove_internal (directory, NULL, client); } static void vfs_force_reload (NemoDirectory *directory) { NemoFileAttributes all_attributes; g_assert (NEMO_IS_DIRECTORY (directory)); all_attributes = nemo_file_get_all_attributes (); nemo_directory_force_reload_internal (directory, all_attributes); } static gboolean vfs_are_all_files_seen (NemoDirectory *directory) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); return directory->details->directory_loaded; } static gboolean vfs_is_not_empty (NemoDirectory *directory) { g_assert (NEMO_IS_VFS_DIRECTORY (directory)); g_assert (nemo_directory_is_anyone_monitoring_file_list (directory)); return directory->details->file_list != NULL; } static void nemo_vfs_directory_class_init (NemoVFSDirectoryClass *klass) { NemoDirectoryClass *directory_class = NEMO_DIRECTORY_CLASS (klass); directory_class->contains_file = vfs_contains_file; directory_class->call_when_ready = vfs_call_when_ready; directory_class->cancel_callback = vfs_cancel_callback; directory_class->file_monitor_add = vfs_file_monitor_add; directory_class->file_monitor_remove = vfs_file_monitor_remove; directory_class->force_reload = vfs_force_reload; directory_class->are_all_files_seen = vfs_are_all_files_seen; directory_class->is_not_empty = vfs_is_not_empty; } nemo-3.6.5/libnemo-private/nemo-icon-container.h0000664000175000017500000004621413215733314020532 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* gnome-icon-container.h - Icon container widget. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ettore Perazzoli , Darin Adler */ #ifndef NEMO_ICON_CONTAINER_H #define NEMO_ICON_CONTAINER_H #include #include #include #define NEMO_TYPE_ICON_CONTAINER nemo_icon_container_get_type() #define NEMO_ICON_CONTAINER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ICON_CONTAINER, NemoIconContainer)) #define NEMO_ICON_CONTAINER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ICON_CONTAINER, NemoIconContainerClass)) #define NEMO_IS_ICON_CONTAINER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ICON_CONTAINER)) #define NEMO_IS_ICON_CONTAINER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ICON_CONTAINER)) #define NEMO_ICON_CONTAINER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ICON_CONTAINER, NemoIconContainerClass)) /* Initial unpositioned icon value */ #define ICON_UNPOSITIONED_VALUE -1 typedef struct { int x; int y; double scale; int monitor; } NemoIconPosition; typedef enum { NEMO_ICON_LAYOUT_L_R_T_B, NEMO_ICON_LAYOUT_R_L_T_B, NEMO_ICON_LAYOUT_T_B_L_R, NEMO_ICON_LAYOUT_T_B_R_L } NemoIconLayoutMode; typedef enum { NEMO_ICON_LABEL_POSITION_UNDER, NEMO_ICON_LABEL_POSITION_BESIDE } NemoIconLabelPosition; #define NEMO_ICON_CONTAINER_TYPESELECT_FLUSH_DELAY 1000000 typedef struct NemoIconContainerDetails NemoIconContainerDetails; typedef struct { EelCanvas canvas; NemoIconContainerDetails *details; } NemoIconContainer; typedef struct { EelCanvasClass parent_slot; gboolean is_grid_container; /* Operations on the container. */ int (* button_press) (NemoIconContainer *container, GdkEventButton *event); void (* context_click_background) (NemoIconContainer *container, GdkEventButton *event); void (* middle_click) (NemoIconContainer *container, GdkEventButton *event); /* Operations on icons. */ void (* activate) (NemoIconContainer *container, NemoIconData *data); void (* activate_alternate) (NemoIconContainer *container, NemoIconData *data); void (* activate_previewer) (NemoIconContainer *container, GList *files, GArray *locations); void (* context_click_selection) (NemoIconContainer *container, GdkEventButton *event); void (* move_copy_items) (NemoIconContainer *container, const GList *item_uris, GdkPoint *relative_item_points, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_netscape_url) (NemoIconContainer *container, const char *url, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_uri_list) (NemoIconContainer *container, const char *uri_list, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_text) (NemoIconContainer *container, const char *text, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_raw) (NemoIconContainer *container, char *raw_data, int length, const char *target_uri, const char *direct_save_uri, GdkDragAction action, int x, int y); /* Queries on the container for subclass/client. * These must be implemented. The default "do nothing" is not good enough. */ char * (* get_container_uri) (NemoIconContainer *container); /* Queries on icons for subclass/client. * These must be implemented. The default "do nothing" is not * good enough, these are _not_ signals. */ NemoIconInfo *(* get_icon_images) (NemoIconContainer *container, NemoIconData *data, int icon_size, char **embedded_text, gboolean for_drag_accept, gboolean need_large_embeddded_text, gboolean *embedded_text_needs_loading, gboolean *has_window_open); void (* get_icon_text) (NemoIconContainer *container, NemoIconData *data, char **editable_text, char **additional_text, gboolean include_invisible); void (* update_icon) (NemoIconContainer *container, NemoIcon *icon); char * (* get_icon_description) (NemoIconContainer *container, NemoIconData *data); int (* compare_icons) (NemoIconContainer *container, NemoIconData *icon_a, NemoIconData *icon_b); void (* freeze_updates) (NemoIconContainer *container); void (* unfreeze_updates) (NemoIconContainer *container); void (* start_monitor_top_left) (NemoIconContainer *container, NemoIconData *data, gconstpointer client, gboolean large_text); void (* stop_monitor_top_left) (NemoIconContainer *container, NemoIconData *data, gconstpointer client); void (* prioritize_thumbnailing) (NemoIconContainer *container, NemoIconData *data); gint (* get_max_layout_lines_for_pango) (NemoIconContainer *container); gint (* get_max_layout_lines) (NemoIconContainer *container); /* Queries on icons for subclass/client. * These must be implemented => These are signals ! * The default "do nothing" is not good enough. */ gboolean (* can_accept_item) (NemoIconContainer *container, NemoIconData *target, const char *item_uri); char * (* get_icon_uri) (NemoIconContainer *container, NemoIconData *data); char * (* get_icon_drop_target_uri) (NemoIconContainer *container, NemoIconData *data); /* If icon data is NULL, the layout timestamp of the container should be retrieved. * That is the time when the container displayed a fully loaded directory with * all icon positions assigned. * * If icon data is not NULL, the position timestamp of the icon should be retrieved. * That is the time when the file (i.e. icon data payload) was last displayed in a * fully loaded directory with all icon positions assigned. */ gboolean (* get_stored_layout_timestamp) (NemoIconContainer *container, NemoIconData *data, time_t *time); /* If icon data is NULL, the layout timestamp of the container should be stored. * If icon data is not NULL, the position timestamp of the container should be stored. */ gboolean (* store_layout_timestamp) (NemoIconContainer *container, NemoIconData *data, const time_t *time); void (*lay_down_icons) (NemoIconContainer *container, GList *icons, double start_y); void (*icon_set_position) (NemoIconContainer *container, NemoIcon *icon, double x, double y); void (*move_icon) (NemoIconContainer *container, NemoIcon *icon, int x, int y, double scale, gboolean raise, gboolean snap, gboolean update_position); void (*align_icons) (NemoIconContainer *container); void (*finish_adding_new_icons) (NemoIconContainer *container); void (*reload_icon_positions) (NemoIconContainer *container); void (*icon_get_bounding_box) (NemoIcon *icon, int *x1_return, int *y1_return, int *x2_return, int *y2_return, NemoIconCanvasItemBoundsUsage usage); void (*set_zoom_level) (NemoIconContainer *container, gint new_level); /* Notifications for the whole container. */ void (* band_select_started) (NemoIconContainer *container); void (* band_select_ended) (NemoIconContainer *container); void (* selection_changed) (NemoIconContainer *container); void (* layout_changed) (NemoIconContainer *container); /* Notifications for icons. */ void (* icon_position_changed) (NemoIconContainer *container, NemoIconData *data, const NemoIconPosition *position); void (* icon_rename_started) (NemoIconContainer *container, GtkWidget *renaming_widget); void (* icon_rename_ended) (NemoIconContainer *container, NemoIconData *data, const char *text); void (* icon_stretch_started) (NemoIconContainer *container, NemoIconData *data); void (* icon_stretch_ended) (NemoIconContainer *container, NemoIconData *data); int (* preview) (NemoIconContainer *container, NemoIconData *data, gboolean start_flag); void (* icon_added) (NemoIconContainer *container, NemoIconData *data); void (* icon_removed) (NemoIconContainer *container, NemoIconData *data); void (* cleared) (NemoIconContainer *container); gboolean (* start_interactive_search) (NemoIconContainer *container); } NemoIconContainerClass; /* GtkObject */ GType nemo_icon_container_get_type (void); GtkWidget * nemo_icon_container_new (void); /* adding, removing, and managing icons */ void nemo_icon_container_clear (NemoIconContainer *view); gboolean nemo_icon_container_icon_is_new_for_monitor (NemoIconContainer *container, NemoIcon *icon, gint current_monitor); gboolean nemo_icon_container_add (NemoIconContainer *view, NemoIconData *data); void nemo_icon_container_layout_now (NemoIconContainer *container); gboolean nemo_icon_container_remove (NemoIconContainer *view, NemoIconData *data); void nemo_icon_container_for_each (NemoIconContainer *view, NemoIconCallback callback, gpointer callback_data); void nemo_icon_container_request_update (NemoIconContainer *view, NemoIconData *data); void nemo_icon_container_invalidate_labels (NemoIconContainer *container); void nemo_icon_container_request_update_all (NemoIconContainer *container); void nemo_icon_container_reveal (NemoIconContainer *container, NemoIconData *data); gboolean nemo_icon_container_is_empty (NemoIconContainer *container); NemoIconData *nemo_icon_container_get_first_visible_icon (NemoIconContainer *container); void nemo_icon_container_scroll_to_icon (NemoIconContainer *container, NemoIconData *data); void nemo_icon_container_begin_loading (NemoIconContainer *container); void nemo_icon_container_end_loading (NemoIconContainer *container, gboolean all_icons_added); /* control the layout */ gboolean nemo_icon_container_is_auto_layout (NemoIconContainer *container); void nemo_icon_container_set_auto_layout (NemoIconContainer *container, gboolean auto_layout); gboolean nemo_icon_container_is_tighter_layout (NemoIconContainer *container); void nemo_icon_container_set_tighter_layout (NemoIconContainer *container, gboolean tighter_layout); gboolean nemo_icon_container_is_keep_aligned (NemoIconContainer *container); void nemo_icon_container_set_keep_aligned (NemoIconContainer *container, gboolean keep_aligned); void nemo_icon_container_set_layout_mode (NemoIconContainer *container, NemoIconLayoutMode mode); void nemo_icon_container_set_horizontal_layout (NemoIconContainer *container, gboolean horizontal); gboolean nemo_icon_container_get_horizontal_layout (NemoIconContainer *container); void nemo_icon_container_set_label_position (NemoIconContainer *container, NemoIconLabelPosition pos); void nemo_icon_container_sort (NemoIconContainer *container); void nemo_icon_container_freeze_icon_positions (NemoIconContainer *container); gint nemo_icon_container_get_max_layout_lines (NemoIconContainer *container); gint nemo_icon_container_get_max_layout_lines_for_pango (NemoIconContainer *container); void nemo_icon_container_set_highlighted_for_clipboard (NemoIconContainer *container, GList *clipboard_icon_data); /* operations on all icons */ void nemo_icon_container_unselect_all (NemoIconContainer *view); void nemo_icon_container_select_all (NemoIconContainer *view); /* operations on the selection */ GList * nemo_icon_container_get_selection (NemoIconContainer *view); void nemo_icon_container_invert_selection (NemoIconContainer *view); void nemo_icon_container_set_selection (NemoIconContainer *view, GList *selection); GArray * nemo_icon_container_get_selected_icon_locations (NemoIconContainer *view); gboolean nemo_icon_container_has_stretch_handles (NemoIconContainer *container); gboolean nemo_icon_container_is_stretched (NemoIconContainer *container); void nemo_icon_container_show_stretch_handles (NemoIconContainer *container); void nemo_icon_container_unstretch (NemoIconContainer *container); void nemo_icon_container_start_renaming_selected_item (NemoIconContainer *container, gboolean select_all); /* options */ NemoZoomLevel nemo_icon_container_get_zoom_level (NemoIconContainer *view); void nemo_icon_container_set_zoom_level (NemoIconContainer *view, int new_zoom_level); void nemo_icon_container_set_single_click_mode (NemoIconContainer *container, gboolean single_click_mode); void nemo_icon_container_set_click_to_rename_enabled (NemoIconContainer *container, gboolean enabled); void nemo_icon_container_enable_linger_selection (NemoIconContainer *view, gboolean enable); gboolean nemo_icon_container_get_is_fixed_size (NemoIconContainer *container); void nemo_icon_container_set_is_fixed_size (NemoIconContainer *container, gboolean is_fixed_size); gboolean nemo_icon_container_get_is_desktop (NemoIconContainer *container); void nemo_icon_container_set_is_desktop (NemoIconContainer *container, gboolean is_desktop); gboolean nemo_icon_container_get_show_desktop_tooltips (NemoIconContainer *container); void nemo_icon_container_set_show_desktop_tooltips (NemoIconContainer *container, gboolean show_tooltips); void nemo_icon_container_reset_scroll_region (NemoIconContainer *container); void nemo_icon_container_set_font (NemoIconContainer *container, const char *font); void nemo_icon_container_set_font_size_table (NemoIconContainer *container, const int font_size_table[NEMO_ZOOM_LEVEL_LARGEST + 1]); void nemo_icon_container_set_margins (NemoIconContainer *container, int left_margin, int right_margin, int top_margin, int bottom_margin); void nemo_icon_container_set_use_drop_shadows (NemoIconContainer *container, gboolean use_drop_shadows); char* nemo_icon_container_get_icon_description (NemoIconContainer *container, NemoIconData *data); gboolean nemo_icon_container_get_allow_moves (NemoIconContainer *container); void nemo_icon_container_set_allow_moves (NemoIconContainer *container, gboolean allow_moves); void nemo_icon_container_set_forced_icon_size (NemoIconContainer *container, int forced_icon_size); void nemo_icon_container_set_all_columns_same_width (NemoIconContainer *container, gboolean all_columns_same_width); gboolean nemo_icon_container_is_layout_rtl (NemoIconContainer *container); gboolean nemo_icon_container_is_layout_vertical (NemoIconContainer *container); gboolean nemo_icon_container_get_store_layout_timestamps (NemoIconContainer *container); void nemo_icon_container_set_store_layout_timestamps (NemoIconContainer *container, gboolean store_layout); void nemo_icon_container_widget_to_file_operation_position (NemoIconContainer *container, GdkPoint *position); void nemo_icon_container_setup_tooltip_preference_callback (NemoIconContainer *container); #endif /* NEMO_ICON_CONTAINER_H */ nemo-3.6.5/libnemo-private/nemo-undo-private.h0000664000175000017500000000246313215733314020235 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* xxx * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_UNDO_PRIVATE_H #define NEMO_UNDO_PRIVATE_H #include #include #include NemoUndoManager * nemo_undo_get_undo_manager (GObject *attached_object); void nemo_undo_attach_undo_manager (GObject *object, NemoUndoManager *manager); #endif /* NEMO_UNDO_PRIVATE_H */ nemo-3.6.5/libnemo-private/nemo-search-engine-tracker.h0000664000175000017500000000427613215733314021765 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Mr Jamie McCracken * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Jamie McCracken (jamiemcc@gnome.org) * */ #ifndef NEMO_SEARCH_ENGINE_TRACKER_H #define NEMO_SEARCH_ENGINE_TRACKER_H #include #define NEMO_TYPE_SEARCH_ENGINE_TRACKER (nemo_search_engine_tracker_get_type ()) #define NEMO_SEARCH_ENGINE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEARCH_ENGINE_TRACKER, NemoSearchEngineTracker)) #define NEMO_SEARCH_ENGINE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEARCH_ENGINE_TRACKER, NemoSearchEngineTrackerClass)) #define NEMO_IS_SEARCH_ENGINE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEARCH_ENGINE_TRACKER)) #define NEMO_IS_SEARCH_ENGINE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEARCH_ENGINE_TRACKER)) #define NEMO_SEARCH_ENGINE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEARCH_ENGINE_TRACKER, NemoSearchEngineTrackerClass)) typedef struct NemoSearchEngineTrackerDetails NemoSearchEngineTrackerDetails; typedef struct NemoSearchEngineTracker { NemoSearchEngine parent; NemoSearchEngineTrackerDetails *details; } NemoSearchEngineTracker; typedef struct { NemoSearchEngineClass parent_class; } NemoSearchEngineTrackerClass; GType nemo_search_engine_tracker_get_type (void); NemoSearchEngine* nemo_search_engine_tracker_new (void); #endif /* NEMO_SEARCH_ENGINE_TRACKER_H */ nemo-3.6.5/libnemo-private/nemo-progress-info.h0000664000175000017500000001016313215733314020411 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-progress-info.h: file operation progress info. Copyright (C) 2007 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_PROGRESS_INFO_H #define NEMO_PROGRESS_INFO_H #include #include #define NEMO_TYPE_PROGRESS_INFO (nemo_progress_info_get_type ()) #define NEMO_PROGRESS_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_PROGRESS_INFO, NemoProgressInfo)) #define NEMO_PROGRESS_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_PROGRESS_INFO, NemoProgressInfoClass)) #define NEMO_IS_PROGRESS_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_PROGRESS_INFO)) #define NEMO_IS_PROGRESS_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_PROGRESS_INFO)) #define NEMO_PROGRESS_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_PROGRESS_INFO, NemoProgressInfoClass)) typedef struct _NemoProgressInfo NemoProgressInfo; typedef struct _NemoProgressInfoClass NemoProgressInfoClass; GType nemo_progress_info_get_type (void) G_GNUC_CONST; /* Signals: "changed" - status or details changed "progress-changed" - the percentage progress changed (or we pulsed if in activity_mode "started" - emited on job start "finished" - emitted when job is done All signals are emitted from idles in main loop. All methods are threadsafe. */ NemoProgressInfo *nemo_progress_info_new (void); GList * nemo_get_all_progress_info (void); char * nemo_progress_info_get_status (NemoProgressInfo *info); char * nemo_progress_info_get_details (NemoProgressInfo *info); char * nemo_progress_info_get_initial_details (NemoProgressInfo *info); double nemo_progress_info_get_progress (NemoProgressInfo *info); GCancellable *nemo_progress_info_get_cancellable (NemoProgressInfo *info); void nemo_progress_info_cancel (NemoProgressInfo *info); gboolean nemo_progress_info_get_is_started (NemoProgressInfo *info); gboolean nemo_progress_info_get_is_finished (NemoProgressInfo *info); gboolean nemo_progress_info_get_is_paused (NemoProgressInfo *info); void nemo_progress_info_queue (NemoProgressInfo *info); void nemo_progress_info_start (NemoProgressInfo *info); void nemo_progress_info_finish (NemoProgressInfo *info); void nemo_progress_info_pause (NemoProgressInfo *info); void nemo_progress_info_resume (NemoProgressInfo *info); void nemo_progress_info_set_status (NemoProgressInfo *info, const char *status); void nemo_progress_info_take_status (NemoProgressInfo *info, char *status); void nemo_progress_info_set_details (NemoProgressInfo *info, const char *details); void nemo_progress_info_take_initial_details (NemoProgressInfo *info, char *initial_details); void nemo_progress_info_take_details (NemoProgressInfo *info, char *details); void nemo_progress_info_set_progress (NemoProgressInfo *info, double current, double total); void nemo_progress_info_pulse_progress (NemoProgressInfo *info); #endif /* NEMO_PROGRESS_INFO_H */ nemo-3.6.5/libnemo-private/nemo-desktop-link-monitor.h0000664000175000017500000000501013215733314021700 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-link-monitor.h: singleton that manages the desktop links Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_DESKTOP_LINK_MONITOR_H #define NEMO_DESKTOP_LINK_MONITOR_H #include #include #define NEMO_TYPE_DESKTOP_LINK_MONITOR nemo_desktop_link_monitor_get_type() #define NEMO_DESKTOP_LINK_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DESKTOP_LINK_MONITOR, NemoDesktopLinkMonitor)) #define NEMO_DESKTOP_LINK_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DESKTOP_LINK_MONITOR, NemoDesktopLinkMonitorClass)) #define NEMO_IS_DESKTOP_LINK_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DESKTOP_LINK_MONITOR)) #define NEMO_IS_DESKTOP_LINK_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DESKTOP_LINK_MONITOR)) #define NEMO_DESKTOP_LINK_MONITOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DESKTOP_LINK_MONITOR, NemoDesktopLinkMonitorClass)) typedef struct NemoDesktopLinkMonitorDetails NemoDesktopLinkMonitorDetails; typedef struct { GObject parent_slot; NemoDesktopLinkMonitorDetails *details; } NemoDesktopLinkMonitor; typedef struct { GObjectClass parent_slot; } NemoDesktopLinkMonitorClass; GType nemo_desktop_link_monitor_get_type (void); NemoDesktopLinkMonitor * nemo_desktop_link_monitor_get (void); void nemo_desktop_link_monitor_delete_link (NemoDesktopLinkMonitor *monitor, NemoDesktopLink *link, GtkWidget *parent_view); /* Used by nemo-desktop-link.c */ char * nemo_desktop_link_monitor_make_filename_unique (NemoDesktopLinkMonitor *monitor, const char *filename); #endif /* NEMO_DESKTOP_LINK_MONITOR_H */ nemo-3.6.5/libnemo-private/nemo-search-directory.c0000664000175000017500000005451313215733314021065 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Copyright (C) 2005 Novell, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Anders Carlsson */ #include #include "nemo-search-directory.h" #include "nemo-search-directory-file.h" #include "nemo-directory-private.h" #include "nemo-file.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include "nemo-search-engine.h" #include #include #include #include #include struct NemoSearchDirectoryDetails { NemoQuery *query; char *saved_search_uri; gboolean modified; NemoSearchEngine *engine; gboolean search_running; gboolean search_finished; GList *files; GHashTable *file_hash; GList *monitor_list; GList *callback_list; GList *pending_callback_list; }; typedef struct { gboolean monitor_hidden_files; NemoFileAttributes monitor_attributes; gconstpointer client; } SearchMonitor; typedef struct { NemoSearchDirectory *search_directory; NemoDirectoryCallback callback; gpointer callback_data; NemoFileAttributes wait_for_attributes; gboolean wait_for_file_list; GList *file_list; GHashTable *non_ready_hash; } SearchCallback; G_DEFINE_TYPE (NemoSearchDirectory, nemo_search_directory, NEMO_TYPE_DIRECTORY); static void search_engine_hits_added (NemoSearchEngine *engine, GList *hits, NemoSearchDirectory *search); static void search_engine_hits_subtracted (NemoSearchEngine *engine, GList *hits, NemoSearchDirectory *search); static void search_engine_finished (NemoSearchEngine *engine, NemoSearchDirectory *search); static void search_engine_error (NemoSearchEngine *engine, const char *error, NemoSearchDirectory *search); static void search_callback_file_ready_callback (NemoFile *file, gpointer data); static void file_changed (NemoFile *file, NemoSearchDirectory *search); static void ensure_search_engine (NemoSearchDirectory *search) { if (!search->details->engine) { search->details->engine = nemo_search_engine_new (); g_signal_connect (search->details->engine, "hits-added", G_CALLBACK (search_engine_hits_added), search); g_signal_connect (search->details->engine, "hits-subtracted", G_CALLBACK (search_engine_hits_subtracted), search); g_signal_connect (search->details->engine, "finished", G_CALLBACK (search_engine_finished), search); g_signal_connect (search->details->engine, "error", G_CALLBACK (search_engine_error), search); } } static void reset_file_list (NemoSearchDirectory *search) { GList *list, *monitor_list; NemoFile *file; SearchMonitor *monitor; /* Remove file connections */ for (list = search->details->files; list != NULL; list = list->next) { file = list->data; /* Disconnect change handler */ g_signal_handlers_disconnect_by_func (file, file_changed, search); /* Remove monitors */ for (monitor_list = search->details->monitor_list; monitor_list; monitor_list = monitor_list->next) { monitor = monitor_list->data; nemo_file_monitor_remove (file, monitor); } } nemo_file_list_free (search->details->files); search->details->files = NULL; } static void start_or_stop_search_engine (NemoSearchDirectory *search, gboolean adding) { if (adding && (search->details->monitor_list || search->details->pending_callback_list) && search->details->query && !search->details->search_running) { /* We need to start the search engine */ search->details->search_running = TRUE; search->details->search_finished = FALSE; ensure_search_engine (search); nemo_search_engine_set_query (search->details->engine, search->details->query); reset_file_list (search); nemo_search_engine_start (search->details->engine); } else if (!adding && (!search->details->monitor_list || !search->details->pending_callback_list) && search->details->engine && search->details->search_running) { search->details->search_running = FALSE; nemo_search_engine_stop (search->details->engine); reset_file_list (search); } } static void file_changed (NemoFile *file, NemoSearchDirectory *search) { GList list; list.data = file; list.next = NULL; nemo_directory_emit_files_changed (NEMO_DIRECTORY (search), &list); } static void search_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { GList *list; SearchMonitor *monitor; NemoSearchDirectory *search; NemoFile *file; search = NEMO_SEARCH_DIRECTORY (directory); monitor = g_new0 (SearchMonitor, 1); monitor->monitor_hidden_files = monitor_hidden_files; monitor->monitor_attributes = file_attributes; monitor->client = client; search->details->monitor_list = g_list_prepend (search->details->monitor_list, monitor); if (callback != NULL) { (* callback) (directory, search->details->files, callback_data); } for (list = search->details->files; list != NULL; list = list->next) { file = list->data; /* Add monitors */ nemo_file_monitor_add (file, monitor, file_attributes); } start_or_stop_search_engine (search, TRUE); } static void search_monitor_remove_file_monitors (SearchMonitor *monitor, NemoSearchDirectory *search) { GList *list; NemoFile *file; for (list = search->details->files; list != NULL; list = list->next) { file = list->data; nemo_file_monitor_remove (file, monitor); } } static void search_monitor_destroy (SearchMonitor *monitor, NemoSearchDirectory *search) { search_monitor_remove_file_monitors (monitor, search); g_free (monitor); } static void search_monitor_remove (NemoDirectory *directory, gconstpointer client) { NemoSearchDirectory *search; SearchMonitor *monitor; GList *list; search = NEMO_SEARCH_DIRECTORY (directory); for (list = search->details->monitor_list; list != NULL; list = list->next) { monitor = list->data; if (monitor->client == client) { search->details->monitor_list = g_list_delete_link (search->details->monitor_list, list); search_monitor_destroy (monitor, search); break; } } start_or_stop_search_engine (search, FALSE); } static void cancel_call_when_ready (gpointer key, gpointer value, gpointer user_data) { SearchCallback *search_callback; NemoFile *file; file = key; search_callback = user_data; nemo_file_cancel_call_when_ready (file, search_callback_file_ready_callback, search_callback); } static void search_callback_destroy (SearchCallback *search_callback) { if (search_callback->non_ready_hash) { g_hash_table_foreach (search_callback->non_ready_hash, cancel_call_when_ready, search_callback); g_hash_table_destroy (search_callback->non_ready_hash); } nemo_file_list_free (search_callback->file_list); g_free (search_callback); } static void search_callback_invoke_and_destroy (SearchCallback *search_callback) { search_callback->callback (NEMO_DIRECTORY (search_callback->search_directory), search_callback->file_list, search_callback->callback_data); search_callback->search_directory->details->callback_list = g_list_remove (search_callback->search_directory->details->callback_list, search_callback); search_callback_destroy (search_callback); } static void search_callback_file_ready_callback (NemoFile *file, gpointer data) { SearchCallback *search_callback = data; g_hash_table_remove (search_callback->non_ready_hash, file); if (g_hash_table_size (search_callback->non_ready_hash) == 0) { search_callback_invoke_and_destroy (search_callback); } } static void search_callback_add_file_callbacks (SearchCallback *callback) { GList *file_list_copy, *list; NemoFile *file; file_list_copy = g_list_copy (callback->file_list); for (list = file_list_copy; list != NULL; list = list->next) { file = list->data; nemo_file_call_when_ready (file, callback->wait_for_attributes, search_callback_file_ready_callback, callback); } g_list_free (file_list_copy); } static SearchCallback * search_callback_find (NemoSearchDirectory *search, NemoDirectoryCallback callback, gpointer callback_data) { SearchCallback *search_callback; GList *list; for (list = search->details->callback_list; list != NULL; list = list->next) { search_callback = list->data; if (search_callback->callback == callback && search_callback->callback_data == callback_data) { return search_callback; } } return NULL; } static SearchCallback * search_callback_find_pending (NemoSearchDirectory *search, NemoDirectoryCallback callback, gpointer callback_data) { SearchCallback *search_callback; GList *list; for (list = search->details->pending_callback_list; list != NULL; list = list->next) { search_callback = list->data; if (search_callback->callback == callback && search_callback->callback_data == callback_data) { return search_callback; } } return NULL; } static GHashTable * file_list_to_hash_table (GList *file_list) { GList *list; GHashTable *table; if (!file_list) return NULL; table = g_hash_table_new (NULL, NULL); for (list = file_list; list != NULL; list = list->next) { g_hash_table_insert (table, list->data, list->data); } return table; } static void search_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback callback, gpointer callback_data) { NemoSearchDirectory *search; SearchCallback *search_callback; search = NEMO_SEARCH_DIRECTORY (directory); search_callback = search_callback_find (search, callback, callback_data); if (search_callback == NULL) { search_callback = search_callback_find_pending (search, callback, callback_data); } if (search_callback) { g_warning ("tried to add a new callback while an old one was pending"); return; } search_callback = g_new0 (SearchCallback, 1); search_callback->search_directory = search; search_callback->callback = callback; search_callback->callback_data = callback_data; search_callback->wait_for_attributes = file_attributes; search_callback->wait_for_file_list = wait_for_file_list; if (wait_for_file_list && !search->details->search_finished) { /* Add it to the pending callback list, which will be * processed when the directory has finished loading */ search->details->pending_callback_list = g_list_prepend (search->details->pending_callback_list, search_callback); /* We might need to start the search engine */ start_or_stop_search_engine (search, TRUE); } else { search_callback->file_list = nemo_file_list_copy (search->details->files); search_callback->non_ready_hash = file_list_to_hash_table (search->details->files); if (!search_callback->non_ready_hash) { /* If there are no ready files, we invoke the callback with an empty list. */ search_callback_invoke_and_destroy (search_callback); } else { search->details->callback_list = g_list_prepend (search->details->callback_list, search_callback); search_callback_add_file_callbacks (search_callback); } } } static void search_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data) { NemoSearchDirectory *search; SearchCallback *search_callback; search = NEMO_SEARCH_DIRECTORY (directory); search_callback = search_callback_find (search, callback, callback_data); if (search_callback) { search->details->callback_list = g_list_remove (search->details->callback_list, search_callback); search_callback_destroy (search_callback); return; } /* Check for a pending callback */ search_callback = search_callback_find_pending (search, callback, callback_data); if (search_callback) { search->details->pending_callback_list = g_list_remove (search->details->pending_callback_list, search_callback); search_callback_destroy (search_callback); /* We might need to stop the search engine now */ start_or_stop_search_engine (search, FALSE); } } static void search_engine_hits_added (NemoSearchEngine *engine, GList *hits, NemoSearchDirectory *search) { GList *hit_list; GList *file_list; NemoFile *file; char *uri; SearchMonitor *monitor; GList *monitor_list; file_list = NULL; for (hit_list = hits; hit_list != NULL; hit_list = hit_list->next) { uri = hit_list->data; if (g_str_has_suffix (uri, NEMO_SAVED_SEARCH_EXTENSION)) { /* Never return saved searches themselves as hits */ continue; } file = nemo_file_get_by_uri (uri); for (monitor_list = search->details->monitor_list; monitor_list; monitor_list = monitor_list->next) { monitor = monitor_list->data; /* Add monitors */ nemo_file_monitor_add (file, monitor, monitor->monitor_attributes); } g_signal_connect (file, "changed", G_CALLBACK (file_changed), search), file_list = g_list_prepend (file_list, file); } search->details->files = g_list_concat (search->details->files, file_list); nemo_directory_emit_files_added (NEMO_DIRECTORY (search), file_list); file = nemo_directory_get_corresponding_file (NEMO_DIRECTORY (search)); nemo_file_emit_changed (file); nemo_file_unref (file); } static void search_engine_hits_subtracted (NemoSearchEngine *engine, GList *hits, NemoSearchDirectory *search) { GList *hit_list; GList *monitor_list; SearchMonitor *monitor; GList *file_list; char *uri; NemoFile *file; file_list = NULL; for (hit_list = hits; hit_list != NULL; hit_list = hit_list->next) { uri = hit_list->data; file = nemo_file_get_by_uri (uri); for (monitor_list = search->details->monitor_list; monitor_list; monitor_list = monitor_list->next) { monitor = monitor_list->data; /* Remove monitors */ nemo_file_monitor_remove (file, monitor); } g_signal_handlers_disconnect_by_func (file, file_changed, search); search->details->files = g_list_remove (search->details->files, file); file_list = g_list_prepend (file_list, file); } nemo_directory_emit_files_changed (NEMO_DIRECTORY (search), file_list); nemo_file_list_free (file_list); file = nemo_directory_get_corresponding_file (NEMO_DIRECTORY (search)); nemo_file_emit_changed (file); nemo_file_unref (file); } static void search_callback_add_pending_file_callbacks (SearchCallback *callback) { callback->file_list = nemo_file_list_copy (callback->search_directory->details->files); callback->non_ready_hash = file_list_to_hash_table (callback->search_directory->details->files); search_callback_add_file_callbacks (callback); } static void search_engine_error (NemoSearchEngine *engine, const char *error_message, NemoSearchDirectory *search) { GError *error; error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, error_message); nemo_directory_emit_load_error (NEMO_DIRECTORY (search), error); g_error_free (error); } static void search_engine_finished (NemoSearchEngine *engine, NemoSearchDirectory *search) { search->details->search_finished = TRUE; nemo_directory_emit_done_loading (NEMO_DIRECTORY (search)); /* Add all file callbacks */ g_list_foreach (search->details->pending_callback_list, (GFunc)search_callback_add_pending_file_callbacks, NULL); search->details->callback_list = g_list_concat (search->details->callback_list, search->details->pending_callback_list); g_list_free (search->details->pending_callback_list); search->details->pending_callback_list = NULL; } static void search_force_reload (NemoDirectory *directory) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (directory); if (!search->details->query) { return; } search->details->search_finished = FALSE; if (!search->details->engine) { return; } /* Remove file monitors */ reset_file_list (search); if (search->details->search_running) { nemo_search_engine_stop (search->details->engine); nemo_search_engine_set_query (search->details->engine, search->details->query); nemo_search_engine_start (search->details->engine); } } static gboolean search_are_all_files_seen (NemoDirectory *directory) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (directory); return (!search->details->query || search->details->search_finished); } static gboolean search_is_not_empty (NemoDirectory *directory) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (directory); return search->details->files != NULL; } static gboolean search_contains_file (NemoDirectory *directory, NemoFile *file) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (directory); /* FIXME: Maybe put the files in a hash */ return (g_list_find (search->details->files, file) != NULL); } static GList * search_get_file_list (NemoDirectory *directory) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (directory); return nemo_file_list_copy (search->details->files); } static gboolean search_is_editable (NemoDirectory *directory) { return FALSE; } static void search_dispose (GObject *object) { NemoSearchDirectory *search; GList *list; search = NEMO_SEARCH_DIRECTORY (object); /* Remove search monitors */ if (search->details->monitor_list) { for (list = search->details->monitor_list; list != NULL; list = list->next) { search_monitor_destroy ((SearchMonitor *)list->data, search); } g_list_free (search->details->monitor_list); search->details->monitor_list = NULL; } reset_file_list (search); if (search->details->callback_list) { /* Remove callbacks */ g_list_foreach (search->details->callback_list, (GFunc)search_callback_destroy, NULL); g_list_free (search->details->callback_list); search->details->callback_list = NULL; } if (search->details->pending_callback_list) { g_list_foreach (search->details->pending_callback_list, (GFunc)search_callback_destroy, NULL); g_list_free (search->details->pending_callback_list); search->details->pending_callback_list = NULL; } if (search->details->query) { g_object_unref (search->details->query); search->details->query = NULL; } if (search->details->engine) { if (search->details->search_running) { nemo_search_engine_stop (search->details->engine); } g_object_unref (search->details->engine); search->details->engine = NULL; } G_OBJECT_CLASS (nemo_search_directory_parent_class)->dispose (object); } static void search_finalize (GObject *object) { NemoSearchDirectory *search; search = NEMO_SEARCH_DIRECTORY (object); g_free (search->details->saved_search_uri); g_free (search->details); G_OBJECT_CLASS (nemo_search_directory_parent_class)->finalize (object); } static void nemo_search_directory_init (NemoSearchDirectory *search) { search->details = g_new0 (NemoSearchDirectoryDetails, 1); } static void nemo_search_directory_class_init (NemoSearchDirectoryClass *class) { NemoDirectoryClass *directory_class; G_OBJECT_CLASS (class)->dispose = search_dispose; G_OBJECT_CLASS (class)->finalize = search_finalize; directory_class = NEMO_DIRECTORY_CLASS (class); directory_class->are_all_files_seen = search_are_all_files_seen; directory_class->is_not_empty = search_is_not_empty; directory_class->contains_file = search_contains_file; directory_class->force_reload = search_force_reload; directory_class->call_when_ready = search_call_when_ready; directory_class->cancel_callback = search_cancel_callback; directory_class->file_monitor_add = search_monitor_add; directory_class->file_monitor_remove = search_monitor_remove; directory_class->get_file_list = search_get_file_list; directory_class->is_editable = search_is_editable; } char * nemo_search_directory_generate_new_uri (void) { static int counter = 0; char *uri; uri = g_strdup_printf (EEL_SEARCH_URI"//%d/", counter++); return uri; } void nemo_search_directory_set_query (NemoSearchDirectory *search, NemoQuery *query) { NemoDirectory *dir; NemoFile *as_file; if (search->details->query != query) { search->details->modified = TRUE; } if (query) { g_object_ref (query); } if (search->details->query) { g_object_unref (search->details->query); } search->details->query = query; dir = NEMO_DIRECTORY (search); as_file = dir->details->as_file; if (as_file != NULL) { nemo_search_directory_file_update_display_name (NEMO_SEARCH_DIRECTORY_FILE (as_file)); } } NemoQuery * nemo_search_directory_get_query (NemoSearchDirectory *search) { if (search->details->query != NULL) { return g_object_ref (search->details->query); } return NULL; } NemoSearchDirectory * nemo_search_directory_new_from_saved_search (const char *uri) { NemoSearchDirectory *search; NemoQuery *query; char *file; search = NEMO_SEARCH_DIRECTORY (g_object_new (NEMO_TYPE_SEARCH_DIRECTORY, NULL)); search->details->saved_search_uri = g_strdup (uri); file = g_filename_from_uri (uri, NULL, NULL); if (file != NULL) { query = nemo_query_load (file); if (query != NULL) { nemo_search_directory_set_query (search, query); g_object_unref (query); } g_free (file); } else { g_warning ("Non-local saved searches not supported"); } search->details->modified = FALSE; return search; } gboolean nemo_search_directory_is_saved_search (NemoSearchDirectory *search) { return search->details->saved_search_uri != NULL; } gboolean nemo_search_directory_is_modified (NemoSearchDirectory *search) { return search->details->modified; } void nemo_search_directory_save_to_file (NemoSearchDirectory *search, const char *save_file_uri) { char *file; file = g_filename_from_uri (save_file_uri, NULL, NULL); if (file == NULL) { return; } if (search->details->query != NULL) { nemo_query_save (search->details->query, file); } g_free (file); } void nemo_search_directory_save_search (NemoSearchDirectory *search) { if (search->details->saved_search_uri == NULL) { return; } nemo_search_directory_save_to_file (search, search->details->saved_search_uri); search->details->modified = FALSE; } nemo-3.6.5/libnemo-private/nemo-lib-self-check-functions.c0000664000175000017500000000231713215733314022367 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-lib-self-check-functions.c: Wrapper for all self check functions in Nemo proper. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #if ! defined (NEMO_OMIT_SELF_CHECK) #include "nemo-lib-self-check-functions.h" void nemo_run_lib_self_checks (void) { NEMO_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_CALL_SELF_CHECK_FUNCTION) } #endif /* ! NEMO_OMIT_SELF_CHECK */ nemo-3.6.5/libnemo-private/nemo-file-private.h0000664000175000017500000002506013215733314020205 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-file-private.h: Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_FILE_PRIVATE_H #define NEMO_FILE_PRIVATE_H #include #include #include #include #include #include #define NEMO_FILE_DEFAULT_ATTRIBUTES \ "standard::*,access::*,mountable::*,time::*,unix::*,owner::*,selinux::*,thumbnail::*,id::filesystem,trash::orig-path,trash::deletion-date,metadata::*" /* These are in the typical sort order. Known things come first, then * things where we can't know, finally things where we don't yet know. */ typedef enum { KNOWN, UNKNOWABLE, UNKNOWN } Knowledge; struct NemoFileDetails { NemoDirectory *directory; eel_ref_str name; /* File info: */ GFileType type; eel_ref_str display_name; char *display_name_collation_key; eel_ref_str edit_name; goffset size; /* -1 is unknown */ int sort_order; guint32 permissions; int uid; /* -1 is none */ int gid; /* -1 is none */ eel_ref_str owner; eel_ref_str owner_real; eel_ref_str group; time_t atime; /* 0 is unknown */ time_t mtime; /* 0 is unknown */ time_t ctime; /* 0 is unknown */ char *symlink_name; eel_ref_str mime_type; char *selinux_context; char *description; GError *get_info_error; guint directory_count; guint deep_directory_count; guint deep_file_count; guint deep_unreadable_count; guint deep_hidden_count; goffset deep_size; GIcon *icon; char *thumbnail_path; eel_boolean_bit thumbnail_access_problem : 1; GdkPixbuf *thumbnail; time_t thumbnail_mtime; gint thumbnail_throttle_count; time_t last_thumbnail_try_mtime; GdkPixbuf *scaled_thumbnail; double thumbnail_scale; GList *mime_list; /* If this is a directory, the list of MIME types in it. */ /* Info you might get from a link (.desktop, .directory or nemo link) */ GIcon *custom_icon; char *activation_uri; /* used during DND, for checking whether source and destination are on * the same file system. */ eel_ref_str filesystem_id; char *trash_orig_path; /* The following is for file operations in progress. Since * there are normally only a few of these, we can move them to * a separate hash table or something if required to keep the * file objects small. */ GList *operations_in_progress; /* NemoInfoProviders that need to be run for this file */ GList *pending_info_providers; /* Emblems provided by extensions */ GList *extension_emblems; GList *pending_extension_emblems; /* Attributes provided by extensions */ GHashTable *extension_attributes; GHashTable *pending_extension_attributes; GHashTable *metadata; /* Mount for mountpoint or the references GMount for a "mountable" */ GMount *mount; /* boolean fields: bitfield to save space, since there can be many NemoFile objects. */ eel_boolean_bit unconfirmed : 1; eel_boolean_bit is_gone : 1; /* Set when emitting files_added on the directory to make sure we add a file, and only once */ eel_boolean_bit is_added : 1; /* Set by the NemoDirectory while it's loading the file * list so the file knows not to do redundant I/O. */ eel_boolean_bit loading_directory : 1; eel_boolean_bit got_file_info : 1; eel_boolean_bit get_info_failed : 1; eel_boolean_bit file_info_is_up_to_date : 1; eel_boolean_bit got_directory_count : 1; eel_boolean_bit directory_count_failed : 1; eel_boolean_bit directory_count_is_up_to_date : 1; eel_boolean_bit deep_counts_status : 2; /* NemoRequestStatus */ /* no deep_counts_are_up_to_date field; since we expose intermediate values for this attribute, we do actually forget it rather than invalidating. */ eel_boolean_bit got_mime_list : 1; eel_boolean_bit mime_list_failed : 1; eel_boolean_bit mime_list_is_up_to_date : 1; eel_boolean_bit mount_is_up_to_date : 1; eel_boolean_bit got_link_info : 1; eel_boolean_bit link_info_is_up_to_date : 1; eel_boolean_bit got_custom_display_name : 1; eel_boolean_bit got_custom_activation_uri : 1; eel_boolean_bit thumbnail_is_up_to_date : 1; eel_boolean_bit thumbnail_wants_original : 1; eel_boolean_bit thumbnail_tried_original : 1; eel_boolean_bit thumbnailing_failed : 1; eel_boolean_bit is_thumbnailing : 1; eel_boolean_bit is_desktop_orphan : 1; /* TRUE if the file is open in a spatial window */ eel_boolean_bit has_open_window : 1; eel_boolean_bit is_launcher : 1; eel_boolean_bit is_trusted_link : 1; eel_boolean_bit is_foreign_link : 1; eel_boolean_bit is_symlink : 1; eel_boolean_bit is_mountpoint : 1; eel_boolean_bit is_hidden : 1; eel_boolean_bit has_permissions : 1; eel_boolean_bit can_read : 1; eel_boolean_bit can_write : 1; eel_boolean_bit can_execute : 1; eel_boolean_bit can_delete : 1; eel_boolean_bit can_trash : 1; eel_boolean_bit can_rename : 1; eel_boolean_bit can_mount : 1; eel_boolean_bit can_unmount : 1; eel_boolean_bit can_eject : 1; eel_boolean_bit can_start : 1; eel_boolean_bit can_start_degraded : 1; eel_boolean_bit can_stop : 1; eel_boolean_bit start_stop_type : 3; /* GDriveStartStopType */ eel_boolean_bit can_poll_for_media : 1; eel_boolean_bit is_media_check_automatic : 1; eel_boolean_bit filesystem_readonly : 1; eel_boolean_bit filesystem_use_preview : 2; /* GFilesystemPreviewType */ eel_boolean_bit filesystem_info_is_up_to_date : 1; time_t trash_time; /* 0 is unknown */ guint64 free_space; /* (guint)-1 for unknown */ time_t free_space_read; /* The time free_space was updated, or 0 for never */ gint desktop_monitor; gint cached_position_x; gint cached_position_y; }; typedef struct { NemoFile *file; GCancellable *cancellable; NemoFileOperationCallback callback; gpointer callback_data; gboolean is_rename; gpointer data; GDestroyNotify free_data; NemoFileUndoInfo *undo_info; } NemoFileOperation; NemoFile *nemo_file_new_from_info (NemoDirectory *directory, GFileInfo *info); void nemo_file_emit_changed (NemoFile *file); void nemo_file_mark_gone (NemoFile *file); void nemo_file_set_directory (NemoFile *file, NemoDirectory *directory); gboolean nemo_file_get_date (NemoFile *file, NemoDateType date_type, time_t *date); void nemo_file_updated_deep_count_in_progress (NemoFile *file); void nemo_file_clear_info (NemoFile *file); /* Compare file's state with a fresh file info struct, return FALSE if * no change, update file and return TRUE if the file info contains * new state. */ gboolean nemo_file_update_info (NemoFile *file, GFileInfo *info); gboolean nemo_file_update_name (NemoFile *file, const char *name); gboolean nemo_file_update_metadata_from_info (NemoFile *file, GFileInfo *info); gboolean nemo_file_update_name_and_directory (NemoFile *file, const char *name, NemoDirectory *directory); gboolean nemo_file_set_display_name (NemoFile *file, const char *display_name, const char *edit_name, gboolean custom); void nemo_file_set_mount (NemoFile *file, GMount *mount); /* Mark specified attributes for this file out of date without canceling current * I/O or kicking off new I/O. */ void nemo_file_invalidate_attributes_internal (NemoFile *file, NemoFileAttributes file_attributes); NemoFileAttributes nemo_file_get_all_attributes (void); gboolean nemo_file_is_self_owned (NemoFile *file); void nemo_file_invalidate_count_and_mime_list (NemoFile *file); gboolean nemo_file_rename_in_progress (NemoFile *file); void nemo_file_invalidate_extension_info_internal (NemoFile *file); void nemo_file_info_providers_done (NemoFile *file); /* Thumbnailing: */ void nemo_file_set_is_thumbnailing (NemoFile *file, gboolean is_thumbnailing); NemoFileOperation *nemo_file_operation_new (NemoFile *file, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_operation_free (NemoFileOperation *op); void nemo_file_operation_complete (NemoFileOperation *op, GFile *result_location, GError *error); void nemo_file_operation_cancel (NemoFileOperation *op); #endif nemo-3.6.5/libnemo-private/nemo-directory-private.h0000664000175000017500000002475713215733314021306 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-directory-private.h: Nemo directory model. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include #include #include #include #include #include #include typedef struct LinkInfoReadState LinkInfoReadState; typedef struct FileMonitors FileMonitors; typedef struct DirectoryLoadState DirectoryLoadState; typedef struct DirectoryCountState DirectoryCountState; typedef struct DeepCountState DeepCountState; typedef struct GetInfoState GetInfoState; typedef struct NewFilesState NewFilesState; typedef struct MimeListState MimeListState; typedef struct ThumbnailState ThumbnailState; typedef struct MountState MountState; typedef struct FilesystemInfoState FilesystemInfoState; typedef enum { REQUEST_LINK_INFO, REQUEST_DEEP_COUNT, REQUEST_DIRECTORY_COUNT, REQUEST_FILE_INFO, REQUEST_FILE_LIST, /* always FALSE if file != NULL */ REQUEST_MIME_LIST, REQUEST_EXTENSION_INFO, REQUEST_THUMBNAIL, REQUEST_MOUNT, REQUEST_FILESYSTEM_INFO, REQUEST_TYPE_LAST } RequestType; /* A request for information about one or more files. */ typedef guint32 Request; typedef gint32 RequestCounter[REQUEST_TYPE_LAST]; #define REQUEST_WANTS_TYPE(request, type) ((request) & (1<<(type))) #define REQUEST_SET_TYPE(request, type) (request) |= (1<<(type)) struct NemoDirectoryDetails { /* The location. */ GFile *location; /* The file objects. */ NemoFile *as_file; GList *file_list; GHashTable *file_hash; /* Queues of files needing some I/O done. */ NemoFileQueue *high_priority_queue; NemoFileQueue *low_priority_queue; NemoFileQueue *extension_queue; /* These lists are going to be pretty short. If we think they * are going to get big, we can use hash tables instead. */ GList *call_when_ready_list; RequestCounter call_when_ready_counters; GList *monitor_list; RequestCounter monitor_counters; guint call_ready_idle_id; NemoMonitor *monitor; gulong mime_db_monitor; gboolean in_async_service_loop; gboolean state_changed; gboolean file_list_monitored; gboolean directory_loaded; gboolean directory_loaded_sent_notification; DirectoryLoadState *directory_load_in_progress; GList *pending_file_info; /* list of GnomeVFSFileInfo's that are pending */ int confirmed_file_count; guint dequeue_pending_idle_id; GList *new_files_in_progress; /* list of NewFilesState * */ DirectoryCountState *count_in_progress; NemoFile *deep_count_file; DeepCountState *deep_count_in_progress; MimeListState *mime_list_in_progress; NemoFile *get_info_file; GetInfoState *get_info_in_progress; NemoFile *extension_info_file; NemoInfoProvider *extension_info_provider; NemoOperationHandle *extension_info_in_progress; guint extension_info_idle; ThumbnailState *thumbnail_state; MountState *mount_state; FilesystemInfoState *filesystem_info_state; LinkInfoReadState *link_info_read_state; GList *file_operations_in_progress; /* list of FileOperation * */ GHashTable *hidden_file_hash; }; NemoDirectory *nemo_directory_get_existing (GFile *location); /* async. interface */ void nemo_directory_async_state_changed (NemoDirectory *directory); void nemo_directory_call_when_ready_internal (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback directory_callback, NemoFileCallback file_callback, gpointer callback_data); gboolean nemo_directory_check_if_ready_internal (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes); void nemo_directory_cancel_callback_internal (NemoDirectory *directory, NemoFile *file, NemoDirectoryCallback directory_callback, NemoFileCallback file_callback, gpointer callback_data); void nemo_directory_monitor_add_internal (NemoDirectory *directory, NemoFile *file, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes attributes, NemoDirectoryCallback callback, gpointer callback_data); void nemo_directory_monitor_remove_internal (NemoDirectory *directory, NemoFile *file, gconstpointer client); void nemo_directory_get_info_for_new_files (NemoDirectory *directory, GList *vfs_uris); NemoFile * nemo_directory_get_existing_corresponding_file (NemoDirectory *directory); void nemo_directory_invalidate_count_and_mime_list (NemoDirectory *directory); gboolean nemo_directory_is_file_list_monitored (NemoDirectory *directory); gboolean nemo_directory_is_anyone_monitoring_file_list (NemoDirectory *directory); gboolean nemo_directory_has_active_request_for_file (NemoDirectory *directory, NemoFile *file); void nemo_directory_remove_file_monitor_link (NemoDirectory *directory, GList *link); void nemo_directory_schedule_dequeue_pending (NemoDirectory *directory); void nemo_directory_stop_monitoring_file_list (NemoDirectory *directory); void nemo_directory_cancel (NemoDirectory *directory); void nemo_async_destroying_file (NemoFile *file); void nemo_directory_force_reload_internal (NemoDirectory *directory, NemoFileAttributes file_attributes); void nemo_directory_cancel_loading_file_attributes (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes); /* Calls shared between directory, file, and async. code. */ void nemo_directory_emit_files_added (NemoDirectory *directory, GList *added_files); void nemo_directory_emit_files_changed (NemoDirectory *directory, GList *changed_files); void nemo_directory_emit_change_signals (NemoDirectory *directory, GList *changed_files); void emit_change_signals_for_all_files (NemoDirectory *directory); void emit_change_signals_for_all_files_in_all_directories (void); void nemo_directory_emit_done_loading (NemoDirectory *directory); void nemo_directory_emit_load_error (NemoDirectory *directory, GError *error); NemoDirectory *nemo_directory_get_internal (GFile *location, gboolean create); char * nemo_directory_get_name_for_self_as_new_file (NemoDirectory *directory); Request nemo_directory_set_up_request (NemoFileAttributes file_attributes); /* Interface to the file list. */ NemoFile * nemo_directory_find_file_by_name (NemoDirectory *directory, const char *filename); NemoFile * nemo_directory_find_file_by_internal_filename (NemoDirectory *directory, const char *internal_filename); void nemo_directory_remove_file (NemoDirectory *directory, NemoFile *file); FileMonitors * nemo_directory_remove_file_monitors (NemoDirectory *directory, NemoFile *file); void nemo_directory_add_file_monitors (NemoDirectory *directory, NemoFile *file, FileMonitors *monitors); void nemo_directory_add_file (NemoDirectory *directory, NemoFile *file); GList * nemo_directory_begin_file_name_change (NemoDirectory *directory, NemoFile *file); void nemo_directory_end_file_name_change (NemoDirectory *directory, NemoFile *file, GList *node); void nemo_directory_moved (const char *from_uri, const char *to_uri); /* Interface to the work queue. */ void nemo_directory_add_file_to_work_queue (NemoDirectory *directory, NemoFile *file); void nemo_directory_remove_file_from_work_queue (NemoDirectory *directory, NemoFile *file); /* KDE compatibility hacks */ void nemo_set_kde_trash_name (const char *trash_dir); /* debugging functions */ int nemo_directory_number_outstanding (void); nemo-3.6.5/libnemo-private/nemo-desktop-directory.c0000664000175000017500000003706113215733314021270 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-directory.c: Subclass of NemoDirectory to implement a virtual directory consisting of the desktop directory and the desktop icons Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-desktop-directory.h" #include "nemo-directory-private.h" #include "nemo-file.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include "nemo-global-preferences.h" #include struct NemoDesktopDirectoryDetails { NemoDirectory *real_directory; GHashTable *callbacks; GHashTable *monitors; }; typedef struct { NemoDesktopDirectory *desktop_dir; NemoDirectoryCallback callback; gpointer callback_data; NemoFileAttributes wait_for_attributes; gboolean wait_for_file_list; GList *non_ready_directories; GList *merged_file_list; } MergedCallback; typedef struct { NemoDesktopDirectory *desktop_dir; gboolean monitor_hidden_files; NemoFileAttributes monitor_attributes; } MergedMonitor; static void desktop_directory_changed_callback (gpointer data); G_DEFINE_TYPE (NemoDesktopDirectory, nemo_desktop_directory, NEMO_TYPE_DIRECTORY); static gboolean desktop_contains_file (NemoDirectory *directory, NemoFile *file) { NemoDesktopDirectory *desktop; desktop = NEMO_DESKTOP_DIRECTORY (directory); if (nemo_directory_contains_file (desktop->details->real_directory, file)) { return TRUE; } return file->details->directory == directory; } static guint merged_callback_hash (gconstpointer merged_callback_as_pointer) { const MergedCallback *merged_callback; merged_callback = merged_callback_as_pointer; return GPOINTER_TO_UINT (merged_callback->callback) ^ GPOINTER_TO_UINT (merged_callback->callback_data); } static gboolean merged_callback_equal (gconstpointer merged_callback_as_pointer, gconstpointer merged_callback_as_pointer_2) { const MergedCallback *merged_callback, *merged_callback_2; merged_callback = merged_callback_as_pointer; merged_callback_2 = merged_callback_as_pointer_2; return merged_callback->callback == merged_callback_2->callback && merged_callback->callback_data == merged_callback_2->callback_data; } static void merged_callback_destroy (MergedCallback *merged_callback) { g_assert (merged_callback != NULL); g_assert (NEMO_IS_DESKTOP_DIRECTORY (merged_callback->desktop_dir)); g_list_free (merged_callback->non_ready_directories); nemo_file_list_free (merged_callback->merged_file_list); g_free (merged_callback); } static void merged_callback_check_done (MergedCallback *merged_callback) { /* Check if we are ready. */ if (merged_callback->non_ready_directories != NULL) { return; } /* Remove from the hash table before sending it. */ g_hash_table_steal (merged_callback->desktop_dir->details->callbacks, merged_callback); /* We are ready, so do the real callback. */ (* merged_callback->callback) (NEMO_DIRECTORY (merged_callback->desktop_dir), merged_callback->merged_file_list, merged_callback->callback_data); /* And we are done. */ merged_callback_destroy (merged_callback); } static void merged_callback_remove_directory (MergedCallback *merged_callback, NemoDirectory *directory) { merged_callback->non_ready_directories = g_list_remove (merged_callback->non_ready_directories, directory); merged_callback_check_done (merged_callback); } static void directory_ready_callback (NemoDirectory *directory, GList *files, gpointer callback_data) { MergedCallback *merged_callback; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (callback_data != NULL); merged_callback = callback_data; g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL); /* Update based on this call. */ merged_callback->merged_file_list = g_list_concat (merged_callback->merged_file_list, nemo_file_list_copy (files)); /* Check if we are ready. */ merged_callback_remove_directory (merged_callback, directory); } static void desktop_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback callback, gpointer callback_data) { NemoDesktopDirectory *desktop; MergedCallback search_key, *merged_callback; desktop = NEMO_DESKTOP_DIRECTORY (directory); /* Check to be sure we aren't overwriting. */ search_key.callback = callback; search_key.callback_data = callback_data; if (g_hash_table_lookup (desktop->details->callbacks, &search_key) != NULL) { g_warning ("tried to add a new callback while an old one was pending"); return; } /* Create a merged_callback record. */ merged_callback = g_new0 (MergedCallback, 1); merged_callback->desktop_dir = desktop; merged_callback->callback = callback; merged_callback->callback_data = callback_data; merged_callback->wait_for_attributes = file_attributes; merged_callback->wait_for_file_list = wait_for_file_list; merged_callback->non_ready_directories = g_list_prepend (merged_callback->non_ready_directories, directory); merged_callback->non_ready_directories = g_list_prepend (merged_callback->non_ready_directories, desktop->details->real_directory); merged_callback->merged_file_list = g_list_concat (NULL, nemo_file_list_copy (directory->details->file_list)); /* Put it in the hash table. */ g_hash_table_insert (desktop->details->callbacks, merged_callback, merged_callback); /* Now tell all the directories about it. */ nemo_directory_call_when_ready (desktop->details->real_directory, merged_callback->wait_for_attributes, merged_callback->wait_for_file_list, directory_ready_callback, merged_callback); nemo_directory_call_when_ready_internal (directory, NULL, merged_callback->wait_for_attributes, merged_callback->wait_for_file_list, directory_ready_callback, NULL, merged_callback); } static void desktop_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data) { NemoDesktopDirectory *desktop; MergedCallback search_key, *merged_callback; GList *node; desktop = NEMO_DESKTOP_DIRECTORY (directory); /* Find the entry in the table. */ search_key.callback = callback; search_key.callback_data = callback_data; merged_callback = g_hash_table_lookup (desktop->details->callbacks, &search_key); if (merged_callback == NULL) { return; } /* Remove from the hash table before working with it. */ g_hash_table_steal (merged_callback->desktop_dir->details->callbacks, merged_callback); /* Tell all the directories to cancel the call. */ for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) { nemo_directory_cancel_callback (node->data, directory_ready_callback, merged_callback); } merged_callback_destroy (merged_callback); } static void merged_monitor_destroy (MergedMonitor *monitor) { NemoDesktopDirectory *desktop; desktop = monitor->desktop_dir; /* Call through to the real directory remove calls. */ nemo_directory_file_monitor_remove (desktop->details->real_directory, monitor); nemo_directory_monitor_remove_internal (NEMO_DIRECTORY (desktop), NULL, monitor); g_free (monitor); } static void build_merged_callback_list (NemoDirectory *directory, GList *file_list, gpointer callback_data) { GList **merged_list; merged_list = callback_data; *merged_list = g_list_concat (*merged_list, nemo_file_list_copy (file_list)); } static void desktop_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { NemoDesktopDirectory *desktop; MergedMonitor *monitor; GList *merged_callback_list; desktop = NEMO_DESKTOP_DIRECTORY (directory); /* Map the client to a unique value so this doesn't interfere * with direct monitoring of the directory by the same client. */ monitor = g_hash_table_lookup (desktop->details->monitors, client); if (monitor != NULL) { g_assert (monitor->desktop_dir == desktop); } else { monitor = g_new0 (MergedMonitor, 1); monitor->desktop_dir = desktop; g_hash_table_insert (desktop->details->monitors, (gpointer) client, monitor); } monitor->monitor_hidden_files = monitor_hidden_files; monitor->monitor_attributes = file_attributes; /* Call through to the real directory add calls. */ merged_callback_list = NULL; /* Call up to real dir */ nemo_directory_file_monitor_add (desktop->details->real_directory, monitor, monitor_hidden_files, file_attributes, build_merged_callback_list, &merged_callback_list); /* Handle the desktop part */ merged_callback_list = g_list_concat (merged_callback_list, nemo_file_list_copy (directory->details->file_list)); if (callback != NULL) { (* callback) (directory, merged_callback_list, callback_data); } nemo_file_list_free (merged_callback_list); } static void desktop_monitor_remove (NemoDirectory *directory, gconstpointer client) { NemoDesktopDirectory *desktop; MergedMonitor *monitor; desktop = NEMO_DESKTOP_DIRECTORY (directory); monitor = g_hash_table_lookup (desktop->details->monitors, client); if (monitor == NULL) { return; } g_hash_table_remove (desktop->details->monitors, client); } static void desktop_force_reload (NemoDirectory *directory) { NemoDesktopDirectory *desktop; desktop = NEMO_DESKTOP_DIRECTORY (directory); nemo_directory_force_reload (desktop->details->real_directory); /* We don't invalidate the files in desktop, since they are always up to date. (And we don't ever want to mark them invalid.) */ } static gboolean desktop_are_all_files_seen (NemoDirectory *directory) { NemoDesktopDirectory *desktop; desktop = NEMO_DESKTOP_DIRECTORY (directory); if (!nemo_directory_are_all_files_seen (desktop->details->real_directory)) { return FALSE; } return TRUE; } static gboolean desktop_is_not_empty (NemoDirectory *directory) { NemoDesktopDirectory *desktop; desktop = NEMO_DESKTOP_DIRECTORY (directory); if (nemo_directory_is_not_empty (desktop->details->real_directory)) { return TRUE; } return directory->details->file_list != NULL; } static GList * desktop_get_file_list (NemoDirectory *directory) { GList *real_dir_file_list, *desktop_dir_file_list = NULL; real_dir_file_list = nemo_directory_get_file_list (NEMO_DESKTOP_DIRECTORY (directory)->details->real_directory); desktop_dir_file_list = NEMO_DIRECTORY_CLASS (nemo_desktop_directory_parent_class)->get_file_list (directory); return g_list_concat (real_dir_file_list, desktop_dir_file_list); } NemoDirectory * nemo_desktop_directory_get_real_directory (NemoDesktopDirectory *desktop) { nemo_directory_ref (desktop->details->real_directory); return desktop->details->real_directory; } static void desktop_finalize (GObject *object) { NemoDesktopDirectory *desktop; desktop = NEMO_DESKTOP_DIRECTORY (object); nemo_directory_unref (desktop->details->real_directory); g_hash_table_destroy (desktop->details->callbacks); g_hash_table_destroy (desktop->details->monitors); g_free (desktop->details); g_signal_handlers_disconnect_by_func (nemo_preferences, desktop_directory_changed_callback, desktop); G_OBJECT_CLASS (nemo_desktop_directory_parent_class)->finalize (object); } static void done_loading_callback (NemoDirectory *real_directory, NemoDesktopDirectory *desktop) { nemo_directory_emit_done_loading (NEMO_DIRECTORY (desktop)); } static void forward_files_added_cover (NemoDirectory *real_directory, GList *files, gpointer callback_data) { nemo_directory_emit_files_added (NEMO_DIRECTORY (callback_data), files); } static void forward_files_changed_cover (NemoDirectory *real_directory, GList *files, gpointer callback_data) { nemo_directory_emit_files_changed (NEMO_DIRECTORY (callback_data), files); } static void update_desktop_directory (NemoDesktopDirectory *desktop) { char *desktop_path; char *desktop_uri; NemoDirectory *real_directory; real_directory = desktop->details->real_directory; if (real_directory != NULL) { g_hash_table_remove_all (desktop->details->callbacks); g_hash_table_remove_all (desktop->details->monitors); g_signal_handlers_disconnect_by_func (real_directory, done_loading_callback, desktop); g_signal_handlers_disconnect_by_func (real_directory, forward_files_added_cover, desktop); g_signal_handlers_disconnect_by_func (real_directory, forward_files_changed_cover, desktop); nemo_directory_unref (real_directory); } desktop_path = nemo_get_desktop_directory (); desktop_uri = g_filename_to_uri (desktop_path, NULL, NULL); real_directory = nemo_directory_get_by_uri (desktop_uri); g_free (desktop_uri); g_free (desktop_path); g_signal_connect_object (real_directory, "done_loading", G_CALLBACK (done_loading_callback), desktop, 0); g_signal_connect_object (real_directory, "files_added", G_CALLBACK (forward_files_added_cover), desktop, 0); g_signal_connect_object (real_directory, "files_changed", G_CALLBACK (forward_files_changed_cover), desktop, 0); desktop->details->real_directory = real_directory; } static void desktop_directory_changed_callback (gpointer data) { update_desktop_directory (NEMO_DESKTOP_DIRECTORY (data)); nemo_directory_force_reload (NEMO_DIRECTORY (data)); } static void nemo_desktop_directory_init (NemoDesktopDirectory *desktop) { desktop->details = g_new0 (NemoDesktopDirectoryDetails, 1); desktop->details->callbacks = g_hash_table_new_full (merged_callback_hash, merged_callback_equal, NULL, (GDestroyNotify)merged_callback_destroy); desktop->details->monitors = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)merged_monitor_destroy); desktop->display_number = -1; update_desktop_directory (NEMO_DESKTOP_DIRECTORY (desktop)); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR, G_CALLBACK(desktop_directory_changed_callback), desktop); } static void nemo_desktop_directory_class_init (NemoDesktopDirectoryClass *class) { NemoDirectoryClass *directory_class; directory_class = NEMO_DIRECTORY_CLASS (class); G_OBJECT_CLASS (class)->finalize = desktop_finalize; directory_class->contains_file = desktop_contains_file; directory_class->call_when_ready = desktop_call_when_ready; directory_class->cancel_callback = desktop_cancel_callback; directory_class->file_monitor_add = desktop_monitor_add; directory_class->file_monitor_remove = desktop_monitor_remove; directory_class->force_reload = desktop_force_reload; directory_class->are_all_files_seen = desktop_are_all_files_seen; directory_class->is_not_empty = desktop_is_not_empty; /* Override get_file_list so that we can return the list of files * in NemoDesktopDirectory->details->real_directory, * in addition to the list of standard desktop icons on the desktop. */ directory_class->get_file_list = desktop_get_file_list; } nemo-3.6.5/libnemo-private/nemo-file-undo-operations.h0000664000175000017500000003444113215733314021664 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-undo-operations.h - Manages undo/redo of file operations * * Copyright (C) 2007-2011 Amos Brocco * Copyright (C) 2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Amos Brocco * Cosimo Cecchi * */ #ifndef __NEMO_FILE_UNDO_OPERATIONS_H__ #define __NEMO_FILE_UNDO_OPERATIONS_H__ #include #include typedef enum { NEMO_FILE_UNDO_OP_COPY, NEMO_FILE_UNDO_OP_DUPLICATE, NEMO_FILE_UNDO_OP_MOVE, NEMO_FILE_UNDO_OP_RENAME, NEMO_FILE_UNDO_OP_CREATE_EMPTY_FILE, NEMO_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE, NEMO_FILE_UNDO_OP_CREATE_FOLDER, NEMO_FILE_UNDO_OP_MOVE_TO_TRASH, NEMO_FILE_UNDO_OP_RESTORE_FROM_TRASH, NEMO_FILE_UNDO_OP_CREATE_LINK, NEMO_FILE_UNDO_OP_RECURSIVE_SET_PERMISSIONS, NEMO_FILE_UNDO_OP_SET_PERMISSIONS, NEMO_FILE_UNDO_OP_CHANGE_GROUP, NEMO_FILE_UNDO_OP_CHANGE_OWNER, NEMO_FILE_UNDO_OP_NUM_TYPES, } NemoFileUndoOp; #define NEMO_TYPE_FILE_UNDO_INFO (nemo_file_undo_info_get_type ()) #define NEMO_FILE_UNDO_INFO(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO, NemoFileUndoInfo)) #define NEMO_FILE_UNDO_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO, NemoFileUndoInfoClass)) #define NEMO_IS_FILE_UNDO_INFO(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO)) #define NEMO_IS_FILE_UNDO_INFO_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO)) #define NEMO_FILE_UNDO_INFO_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO, NemoFileUndoInfoClass)) typedef struct _NemoFileUndoInfo NemoFileUndoInfo; typedef struct _NemoFileUndoInfoClass NemoFileUndoInfoClass; typedef struct _NemoFileUndoInfoDetails NemoFileUndoInfoDetails; struct _NemoFileUndoInfo { GObject parent; NemoFileUndoInfoDetails *priv; }; struct _NemoFileUndoInfoClass { GObjectClass parent_class; void (* undo_func) (NemoFileUndoInfo *self, GtkWindow *parent_window); void (* redo_func) (NemoFileUndoInfo *self, GtkWindow *parent_window); void (* strings_func) (NemoFileUndoInfo *self, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description); }; GType nemo_file_undo_info_get_type (void) G_GNUC_CONST; void nemo_file_undo_info_apply_async (NemoFileUndoInfo *self, gboolean undo, GtkWindow *parent_window, GAsyncReadyCallback callback, gpointer user_data); gboolean nemo_file_undo_info_apply_finish (NemoFileUndoInfo *self, GAsyncResult *res, gboolean *user_cancel, GError **error); void nemo_file_undo_info_get_strings (NemoFileUndoInfo *self, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description); /* copy/move/duplicate/link/restore from trash */ #define NEMO_TYPE_FILE_UNDO_INFO_EXT (nemo_file_undo_info_ext_get_type ()) #define NEMO_FILE_UNDO_INFO_EXT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_EXT, NemoFileUndoInfoExt)) #define NEMO_FILE_UNDO_INFO_EXT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_EXT, NemoFileUndoInfoExtClass)) #define NEMO_IS_FILE_UNDO_INFO_EXT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_EXT)) #define NEMO_IS_FILE_UNDO_INFO_EXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_EXT)) #define NEMO_FILE_UNDO_INFO_EXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_EXT, NemoFileUndoInfoExtClass)) typedef struct _NemoFileUndoInfoExt NemoFileUndoInfoExt; typedef struct _NemoFileUndoInfoExtClass NemoFileUndoInfoExtClass; typedef struct _NemoFileUndoInfoExtDetails NemoFileUndoInfoExtDetails; struct _NemoFileUndoInfoExt { NemoFileUndoInfo parent; NemoFileUndoInfoExtDetails *priv; }; struct _NemoFileUndoInfoExtClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_ext_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_ext_new (NemoFileUndoOp op_type, gint item_count, GFile *src_dir, GFile *target_dir); void nemo_file_undo_info_ext_add_origin_target_pair (NemoFileUndoInfoExt *self, GFile *origin, GFile *target); /* create new file/folder */ #define NEMO_TYPE_FILE_UNDO_INFO_CREATE (nemo_file_undo_info_create_get_type ()) #define NEMO_FILE_UNDO_INFO_CREATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_CREATE, NemoFileUndoInfoCreate)) #define NEMO_FILE_UNDO_INFO_CREATE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_CREATE, NemoFileUndoInfoCreateClass)) #define NEMO_IS_FILE_UNDO_INFO_CREATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_CREATE)) #define NEMO_IS_FILE_UNDO_INFO_CREATE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_CREATE)) #define NEMO_FILE_UNDO_INFO_CREATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_CREATE, NemoFileUndoInfoCreateClass)) typedef struct _NemoFileUndoInfoCreate NemoFileUndoInfoCreate; typedef struct _NemoFileUndoInfoCreateClass NemoFileUndoInfoCreateClass; typedef struct _NemoFileUndoInfoCreateDetails NemoFileUndoInfoCreateDetails; struct _NemoFileUndoInfoCreate { NemoFileUndoInfo parent; NemoFileUndoInfoCreateDetails *priv; }; struct _NemoFileUndoInfoCreateClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_create_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_create_new (NemoFileUndoOp op_type); void nemo_file_undo_info_create_set_data (NemoFileUndoInfoCreate *self, GFile *file, const char *template, gint length); /* rename */ #define NEMO_TYPE_FILE_UNDO_INFO_RENAME (nemo_file_undo_info_rename_get_type ()) #define NEMO_FILE_UNDO_INFO_RENAME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_RENAME, NemoFileUndoInfoRename)) #define NEMO_FILE_UNDO_INFO_RENAME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_RENAME, NemoFileUndoInfoRenameClass)) #define NEMO_IS_FILE_UNDO_INFO_RENAME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_RENAME)) #define NEMO_IS_FILE_UNDO_INFO_RENAME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_RENAME)) #define NEMO_FILE_UNDO_INFO_RENAME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_RENAME, NemoFileUndoInfoRenameClass)) typedef struct _NemoFileUndoInfoRename NemoFileUndoInfoRename; typedef struct _NemoFileUndoInfoRenameClass NemoFileUndoInfoRenameClass; typedef struct _NemoFileUndoInfoRenameDetails NemoFileUndoInfoRenameDetails; struct _NemoFileUndoInfoRename { NemoFileUndoInfo parent; NemoFileUndoInfoRenameDetails *priv; }; struct _NemoFileUndoInfoRenameClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_rename_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_rename_new (void); void nemo_file_undo_info_rename_set_data_pre (NemoFileUndoInfoRename *self, GFile *old_file, gchar *old_display_name, gchar *new_display_name); void nemo_file_undo_info_rename_set_data_post (NemoFileUndoInfoRename *self, GFile *new_file); /* trash */ #define NEMO_TYPE_FILE_UNDO_INFO_TRASH (nemo_file_undo_info_trash_get_type ()) #define NEMO_FILE_UNDO_INFO_TRASH(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_TRASH, NemoFileUndoInfoTrash)) #define NEMO_FILE_UNDO_INFO_TRASH_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_TRASH, NemoFileUndoInfoTrashClass)) #define NEMO_IS_FILE_UNDO_INFO_TRASH(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_TRASH)) #define NEMO_IS_FILE_UNDO_INFO_TRASH_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_TRASH)) #define NEMO_FILE_UNDO_INFO_TRASH_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_TRASH, NemoFileUndoInfoTrashClass)) typedef struct _NemoFileUndoInfoTrash NemoFileUndoInfoTrash; typedef struct _NemoFileUndoInfoTrashClass NemoFileUndoInfoTrashClass; typedef struct _NemoFileUndoInfoTrashDetails NemoFileUndoInfoTrashDetails; struct _NemoFileUndoInfoTrash { NemoFileUndoInfo parent; NemoFileUndoInfoTrashDetails *priv; }; struct _NemoFileUndoInfoTrashClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_trash_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_trash_new (gint item_count); void nemo_file_undo_info_trash_add_file (NemoFileUndoInfoTrash *self, GFile *file); /* recursive permissions */ #define NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS (nemo_file_undo_info_rec_permissions_get_type ()) #define NEMO_FILE_UNDO_INFO_REC_PERMISSIONS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS, NemoFileUndoInfoRecPermissions)) #define NEMO_FILE_UNDO_INFO_REC_PERMISSIONS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS, NemoFileUndoInfoRecPermissionsClass)) #define NEMO_IS_FILE_UNDO_INFO_REC_PERMISSIONS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS)) #define NEMO_IS_FILE_UNDO_INFO_REC_PERMISSIONS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS)) #define NEMO_FILE_UNDO_INFO_REC_PERMISSIONS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS, NemoFileUndoInfoRecPermissionsClass)) typedef struct _NemoFileUndoInfoRecPermissions NemoFileUndoInfoRecPermissions; typedef struct _NemoFileUndoInfoRecPermissionsClass NemoFileUndoInfoRecPermissionsClass; typedef struct _NemoFileUndoInfoRecPermissionsDetails NemoFileUndoInfoRecPermissionsDetails; struct _NemoFileUndoInfoRecPermissions { NemoFileUndoInfo parent; NemoFileUndoInfoRecPermissionsDetails *priv; }; struct _NemoFileUndoInfoRecPermissionsClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_rec_permissions_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_rec_permissions_new (GFile *dest, guint32 file_permissions, guint32 file_mask, guint32 dir_permissions, guint32 dir_mask); void nemo_file_undo_info_rec_permissions_add_file (NemoFileUndoInfoRecPermissions *self, GFile *file, guint32 permission); /* single file change permissions */ #define NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS (nemo_file_undo_info_permissions_get_type ()) #define NEMO_FILE_UNDO_INFO_PERMISSIONS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS, NemoFileUndoInfoPermissions)) #define NEMO_FILE_UNDO_INFO_PERMISSIONS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS, NemoFileUndoInfoPermissionsClass)) #define NEMO_IS_FILE_UNDO_INFO_PERMISSIONS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS)) #define NEMO_IS_FILE_UNDO_INFO_PERMISSIONS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS)) #define NEMO_FILE_UNDO_INFO_PERMISSIONS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS, NemoFileUndoInfoPermissionsClass)) typedef struct _NemoFileUndoInfoPermissions NemoFileUndoInfoPermissions; typedef struct _NemoFileUndoInfoPermissionsClass NemoFileUndoInfoPermissionsClass; typedef struct _NemoFileUndoInfoPermissionsDetails NemoFileUndoInfoPermissionsDetails; struct _NemoFileUndoInfoPermissions { NemoFileUndoInfo parent; NemoFileUndoInfoPermissionsDetails *priv; }; struct _NemoFileUndoInfoPermissionsClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_permissions_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_permissions_new (GFile *file, guint32 current_permissions, guint32 new_permissions); /* group and owner change */ #define NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP (nemo_file_undo_info_ownership_get_type ()) #define NEMO_FILE_UNDO_INFO_OWNERSHIP(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP, NemoFileUndoInfoOwnership)) #define NEMO_FILE_UNDO_INFO_OWNERSHIP_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP, NemoFileUndoInfoOwnershipClass)) #define NEMO_IS_FILE_UNDO_INFO_OWNERSHIP(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP)) #define NEMO_IS_FILE_UNDO_INFO_OWNERSHIP_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP)) #define NEMO_FILE_UNDO_INFO_OWNERSHIP_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP, NemoFileUndoInfoOwnershipClass)) typedef struct _NemoFileUndoInfoOwnership NemoFileUndoInfoOwnership; typedef struct _NemoFileUndoInfoOwnershipClass NemoFileUndoInfoOwnershipClass; typedef struct _NemoFileUndoInfoOwnershipDetails NemoFileUndoInfoOwnershipDetails; struct _NemoFileUndoInfoOwnership { NemoFileUndoInfo parent; NemoFileUndoInfoOwnershipDetails *priv; }; struct _NemoFileUndoInfoOwnershipClass { NemoFileUndoInfoClass parent_class; }; GType nemo_file_undo_info_ownership_get_type (void) G_GNUC_CONST; NemoFileUndoInfo *nemo_file_undo_info_ownership_new (NemoFileUndoOp op_type, GFile *file, const char *current_data, const char *new_data); #endif /* __NEMO_FILE_UNDO_OPERATIONS_H__ */ nemo-3.6.5/libnemo-private/nemo-trash-monitor.c0000664000175000017500000001450413215733314020420 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-trash-monitor.c: Nemo trash state watcher. Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Pavel Cisler */ #include #include "nemo-trash-monitor.h" #include "nemo-directory-notify.h" #include "nemo-directory.h" #include "nemo-file-attributes.h" #include "nemo-icon-names.h" #include #include #include struct NemoTrashMonitorDetails { gboolean empty; GIcon *icon; GFileMonitor *file_monitor; }; enum { TRASH_STATE_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static NemoTrashMonitor *nemo_trash_monitor = NULL; G_DEFINE_TYPE(NemoTrashMonitor, nemo_trash_monitor, G_TYPE_OBJECT) static void nemo_trash_monitor_finalize (GObject *object) { NemoTrashMonitor *trash_monitor; trash_monitor = NEMO_TRASH_MONITOR (object); if (trash_monitor->details->icon) { g_object_unref (trash_monitor->details->icon); } if (trash_monitor->details->file_monitor) { g_object_unref (trash_monitor->details->file_monitor); } G_OBJECT_CLASS (nemo_trash_monitor_parent_class)->finalize (object); } static void nemo_trash_monitor_class_init (NemoTrashMonitorClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->finalize = nemo_trash_monitor_finalize; signals[TRASH_STATE_CHANGED] = g_signal_new ("trash_state_changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTrashMonitorClass, trash_state_changed), NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); g_type_class_add_private (object_class, sizeof(NemoTrashMonitorDetails)); } static void update_icon (NemoTrashMonitor *trash_monitor) { g_clear_object (&trash_monitor->details->icon); if (trash_monitor->details->empty) { trash_monitor->details->icon = g_themed_icon_new (NEMO_ICON_TRASH); } else { trash_monitor->details->icon = g_themed_icon_new (NEMO_ICON_TRASH_FULL); } } static void update_empty_info (NemoTrashMonitor *trash_monitor, gboolean is_empty) { if (trash_monitor->details->empty == is_empty) { return; } trash_monitor->details->empty = is_empty; update_icon (trash_monitor); /* trash got empty or full, notify everyone who cares */ g_signal_emit (trash_monitor, signals[TRASH_STATE_CHANGED], 0, trash_monitor->details->empty); } /* Use G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT since we only want to know whether the * trash is empty or not, not access its children. This is available for the * trash backend since it uses a cache. In this way we prevent flooding the * trash backend with enumeration requests when trashing > 1000 files */ static void trash_query_info_cb (GObject *source, GAsyncResult *res, gpointer user_data) { NemoTrashMonitor *trash_monitor = user_data; GFileInfo *info; guint32 item_count; gboolean is_empty = TRUE; info = g_file_query_info_finish (G_FILE (source), res, NULL); if (info != NULL) { item_count = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT); is_empty = item_count == 0; g_object_unref (info); } update_empty_info (trash_monitor, is_empty); g_object_unref (trash_monitor); } static void schedule_update_info (NemoTrashMonitor *trash_monitor) { GFile *location; location = g_file_new_for_uri ("trash:///"); g_file_query_info_async (location, G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, NULL, trash_query_info_cb, g_object_ref (trash_monitor)); g_object_unref (location); } static void file_changed (GFileMonitor* monitor, GFile *child, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { NemoTrashMonitor *trash_monitor; trash_monitor = NEMO_TRASH_MONITOR (user_data); schedule_update_info (trash_monitor); } static void nemo_trash_monitor_init (NemoTrashMonitor *trash_monitor) { GFile *location; trash_monitor->details = G_TYPE_INSTANCE_GET_PRIVATE (trash_monitor, NEMO_TYPE_TRASH_MONITOR, NemoTrashMonitorDetails); trash_monitor->details->empty = TRUE; update_icon (trash_monitor); location = g_file_new_for_uri ("trash:///"); trash_monitor->details->file_monitor = g_file_monitor_file (location, 0, NULL, NULL); g_signal_connect (trash_monitor->details->file_monitor, "changed", (GCallback)file_changed, trash_monitor); g_object_unref (location); schedule_update_info (trash_monitor); } static void unref_trash_monitor (void) { g_object_unref (nemo_trash_monitor); } NemoTrashMonitor * nemo_trash_monitor_get (void) { if (nemo_trash_monitor == NULL) { /* not running yet, start it up */ nemo_trash_monitor = NEMO_TRASH_MONITOR (g_object_new (NEMO_TYPE_TRASH_MONITOR, NULL)); eel_debug_call_at_shutdown (unref_trash_monitor); } return nemo_trash_monitor; } gboolean nemo_trash_monitor_is_empty (void) { NemoTrashMonitor *monitor; monitor = nemo_trash_monitor_get (); return monitor->details->empty; } GIcon * nemo_trash_monitor_get_icon (void) { NemoTrashMonitor *monitor; monitor = nemo_trash_monitor_get (); if (monitor->details->icon) { return g_object_ref (monitor->details->icon); } return NULL; } void nemo_trash_monitor_add_new_trash_directories (void) { /* We trashed something... */ } nemo-3.6.5/libnemo-private/nemo-desktop-icon-file.c0000664000175000017500000002474013215733314021131 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-icon-file.c: Subclass of NemoFile to help implement the virtual desktop icons. Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-desktop-icon-file.h" #include "nemo-desktop-metadata.h" #include "nemo-desktop-directory-file.h" #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include "nemo-file-operations.h" #include #include "nemo-desktop-directory.h" #include #include #include struct NemoDesktopIconFileDetails { NemoDesktopLink *link; }; G_DEFINE_TYPE(NemoDesktopIconFile, nemo_desktop_icon_file, NEMO_TYPE_FILE) static void desktop_icon_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes) { nemo_directory_monitor_add_internal (file->details->directory, file, client, TRUE, attributes, NULL, NULL); } static void desktop_icon_file_monitor_remove (NemoFile *file, gconstpointer client) { nemo_directory_monitor_remove_internal (file->details->directory, file, client); } static void desktop_icon_file_call_when_ready (NemoFile *file, NemoFileAttributes attributes, NemoFileCallback callback, gpointer callback_data) { nemo_directory_call_when_ready_internal (file->details->directory, file, attributes, FALSE, NULL, callback, callback_data); } static void desktop_icon_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data) { nemo_directory_cancel_callback_internal (file->details->directory, file, NULL, callback, callback_data); } static gboolean desktop_icon_file_check_if_ready (NemoFile *file, NemoFileAttributes attributes) { return nemo_directory_check_if_ready_internal (file->details->directory, file, attributes); } static gboolean desktop_icon_file_get_item_count (NemoFile *file, guint *count, gboolean *count_unreadable) { if (count != NULL) { *count = 0; } if (count_unreadable != NULL) { *count_unreadable = FALSE; } return TRUE; } static NemoRequestStatus desktop_icon_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size) { if (directory_count != NULL) { *directory_count = 0; } if (file_count != NULL) { *file_count = 0; } if (unreadable_directory_count != NULL) { *unreadable_directory_count = 0; } if (total_size != NULL) { *total_size = 0; } if (hidden_count != NULL) { *hidden_count = 0; } return NEMO_REQUEST_DONE; } static gboolean desktop_icon_file_get_date (NemoFile *file, NemoDateType date_type, time_t *date) { NemoDesktopIconFile *desktop_file; desktop_file = NEMO_DESKTOP_ICON_FILE (file); return nemo_desktop_link_get_date (desktop_file->details->link, date_type, date); } static char * desktop_icon_file_get_where_string (NemoFile *file) { return g_strdup (_("on the desktop")); } static void nemo_desktop_icon_file_init (NemoDesktopIconFile *desktop_file) { desktop_file->details = G_TYPE_INSTANCE_GET_PRIVATE (desktop_file, NEMO_TYPE_DESKTOP_ICON_FILE, NemoDesktopIconFileDetails); } static void update_info_from_link (NemoDesktopIconFile *icon_file) { NemoFile *file; NemoDesktopLink *link; char *display_name; GMount *mount; file = NEMO_FILE (icon_file); link = icon_file->details->link; if (link == NULL) { return; } eel_ref_str_unref (file->details->mime_type); file->details->mime_type = eel_ref_str_get_unique ("application/x-nemo-link"); file->details->type = G_FILE_TYPE_SHORTCUT; file->details->size = 0; file->details->has_permissions = FALSE; file->details->can_read = TRUE; file->details->can_write = TRUE; file->details->can_mount = FALSE; file->details->can_unmount = FALSE; file->details->can_eject = FALSE; if (file->details->mount) { g_object_unref (file->details->mount); } mount = nemo_desktop_link_get_mount (link); file->details->mount = mount; if (mount) { file->details->can_unmount = g_mount_can_unmount (mount); file->details->can_eject = g_mount_can_eject (mount); } file->details->file_info_is_up_to_date = TRUE; display_name = nemo_desktop_link_get_display_name (link); nemo_file_set_display_name (file, display_name, NULL, TRUE); g_free (display_name); if (file->details->icon != NULL) { g_object_unref (file->details->icon); } file->details->icon = nemo_desktop_link_get_icon (link); g_free (file->details->activation_uri); file->details->activation_uri = nemo_desktop_link_get_activation_uri (link); file->details->got_link_info = TRUE; file->details->link_info_is_up_to_date = TRUE; file->details->directory_count = 0; file->details->got_directory_count = TRUE; file->details->directory_count_is_up_to_date = TRUE; } void nemo_desktop_icon_file_update (NemoDesktopIconFile *icon_file) { NemoFile *file; update_info_from_link (icon_file); file = NEMO_FILE (icon_file); nemo_file_changed (file); } void nemo_desktop_icon_file_remove (NemoDesktopIconFile *icon_file) { NemoFile *file; GList list; icon_file->details->link = NULL; file = NEMO_FILE (icon_file); /* ref here because we might be removing the last ref when we * mark the file gone below, but we need to keep a ref at * least long enough to send the change notification. */ nemo_file_ref (file); file->details->is_gone = TRUE; list.data = file; list.next = NULL; list.prev = NULL; nemo_directory_remove_file (file->details->directory, file); nemo_directory_emit_change_signals (file->details->directory, &list); nemo_file_unref (file); } NemoDesktopIconFile * nemo_desktop_icon_file_new (NemoDesktopLink *link) { NemoFile *file; NemoDirectory *directory; NemoDesktopIconFile *icon_file; GList list; char *name; directory = nemo_directory_get_by_uri (EEL_DESKTOP_URI); file = NEMO_FILE (g_object_new (NEMO_TYPE_DESKTOP_ICON_FILE, NULL)); #ifdef NEMO_FILE_DEBUG_REF printf("%10p ref'd\n", file); eazel_dump_stack_trace ("\t", 10); #endif file->details->directory = directory; icon_file = NEMO_DESKTOP_ICON_FILE (file); icon_file->details->link = link; name = nemo_desktop_link_get_file_name (link); file->details->name = eel_ref_str_new (name); g_free (name); update_info_from_link (icon_file); nemo_desktop_update_metadata_from_keyfile (file, file->details->name); nemo_directory_add_file (directory, file); list.data = file; list.next = NULL; list.prev = NULL; nemo_directory_emit_files_added (directory, &list); return icon_file; } /* Note: This can return NULL if the link was recently removed (i.e. unmounted) */ NemoDesktopLink * nemo_desktop_icon_file_get_link (NemoDesktopIconFile *icon_file) { if (icon_file->details->link) return g_object_ref (icon_file->details->link); else return NULL; } static void nemo_desktop_icon_file_unmount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoDesktopIconFile *desktop_file; GMount *mount; desktop_file = NEMO_DESKTOP_ICON_FILE (file); if (desktop_file) { mount = nemo_desktop_link_get_mount (desktop_file->details->link); if (mount != NULL) { nemo_file_operations_unmount_mount (NULL, mount, FALSE, TRUE); } } } static void nemo_desktop_icon_file_eject (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { NemoDesktopIconFile *desktop_file; GMount *mount; desktop_file = NEMO_DESKTOP_ICON_FILE (file); if (desktop_file) { mount = nemo_desktop_link_get_mount (desktop_file->details->link); if (mount != NULL) { nemo_file_operations_unmount_mount (NULL, mount, TRUE, TRUE); } } } static void nemo_desktop_icon_file_set_metadata (NemoFile *file, const char *key, const char *value) { nemo_desktop_set_metadata_string (file, file->details->name, key, value); } static void nemo_desktop_icon_file_set_metadata_as_list (NemoFile *file, const char *key, char **value) { nemo_desktop_set_metadata_stringv (file, file->details->name, key, (const gchar **) value); } static void nemo_desktop_icon_file_class_init (NemoDesktopIconFileClass *klass) { GObjectClass *object_class; NemoFileClass *file_class; object_class = G_OBJECT_CLASS (klass); file_class = NEMO_FILE_CLASS (klass); file_class->default_file_type = G_FILE_TYPE_DIRECTORY; file_class->monitor_add = desktop_icon_file_monitor_add; file_class->monitor_remove = desktop_icon_file_monitor_remove; file_class->call_when_ready = desktop_icon_file_call_when_ready; file_class->cancel_call_when_ready = desktop_icon_file_cancel_call_when_ready; file_class->check_if_ready = desktop_icon_file_check_if_ready; file_class->get_item_count = desktop_icon_file_get_item_count; file_class->get_deep_counts = desktop_icon_file_get_deep_counts; file_class->get_date = desktop_icon_file_get_date; file_class->get_where_string = desktop_icon_file_get_where_string; file_class->set_metadata = nemo_desktop_icon_file_set_metadata; file_class->set_metadata_as_list = nemo_desktop_icon_file_set_metadata_as_list; file_class->unmount = nemo_desktop_icon_file_unmount; file_class->eject = nemo_desktop_icon_file_eject; g_type_class_add_private (object_class, sizeof(NemoDesktopIconFileDetails)); } nemo-3.6.5/libnemo-private/nemo-file-queue.h0000664000175000017500000000367413215733314017666 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 2001 Maciej Stachowiak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Maciej Stachowiak */ #ifndef NEMO_FILE_QUEUE_H #define NEMO_FILE_QUEUE_H #include typedef struct NemoFileQueue NemoFileQueue; NemoFileQueue *nemo_file_queue_new (void); void nemo_file_queue_destroy (NemoFileQueue *queue); /* Add a file to the tail of the queue, unless it's already in the queue */ void nemo_file_queue_enqueue (NemoFileQueue *queue, NemoFile *file); /* Return the file at the head of the queue after removing it from the * queue. This is dangerous unless you have another ref to the file, * since it will unref it. */ NemoFile * nemo_file_queue_dequeue (NemoFileQueue *queue); /* Remove a file from an arbitrary point in the queue in constant time. */ void nemo_file_queue_remove (NemoFileQueue *queue, NemoFile *file); /* Get the file at the head of the queue without removing or unrefing it. */ NemoFile * nemo_file_queue_head (NemoFileQueue *queue); gboolean nemo_file_queue_is_empty (NemoFileQueue *queue); #endif /* NEMO_FILE_CHANGES_QUEUE_H */ nemo-3.6.5/libnemo-private/nemo-directory-async.c0000664000175000017500000034120413215733314020731 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-directory-async.c: Nemo directory model state machine. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include "nemo-signaller.h" #include "nemo-global-preferences.h" #include "nemo-link.h" #include #include #include #include #include /* turn this on to see messages about each load_directory call: */ #if 0 #define DEBUG_LOAD_DIRECTORY #endif /* turn this on to check if async. job calls are balanced */ #if 0 #define DEBUG_ASYNC_JOBS #endif /* turn this on to log things starting and stopping */ #if 0 #define DEBUG_START_STOP #endif #define DIRECTORY_LOAD_ITEMS_PER_CALLBACK 100 /* Keep async. jobs down to this number for all directories. */ #define MAX_ASYNC_JOBS 10 struct LinkInfoReadState { NemoDirectory *directory; GCancellable *cancellable; NemoFile *file; }; struct ThumbnailState { NemoDirectory *directory; GCancellable *cancellable; NemoFile *file; gboolean trying_original; gboolean tried_original; }; struct MountState { NemoDirectory *directory; GCancellable *cancellable; NemoFile *file; }; struct FilesystemInfoState { NemoDirectory *directory; GCancellable *cancellable; NemoFile *file; }; struct DirectoryLoadState { NemoDirectory *directory; GCancellable *cancellable; GFileEnumerator *enumerator; GHashTable *load_mime_list_hash; NemoFile *load_directory_file; int load_file_count; }; struct MimeListState { NemoDirectory *directory; NemoFile *mime_list_file; GCancellable *cancellable; GFileEnumerator *enumerator; GHashTable *mime_list_hash; }; struct GetInfoState { NemoDirectory *directory; GCancellable *cancellable; }; struct NewFilesState { NemoDirectory *directory; GCancellable *cancellable; int count; }; struct DirectoryCountState { NemoDirectory *directory; NemoFile *count_file; GCancellable *cancellable; GFileEnumerator *enumerator; int file_count; }; struct DeepCountState { NemoDirectory *directory; GCancellable *cancellable; GFileEnumerator *enumerator; GFile *deep_count_location; GList *deep_count_subdirectories; GArray *seen_deep_count_inodes; char *fs_id; }; typedef struct { NemoFile *file; /* Which file, NULL means all. */ union { NemoDirectoryCallback directory; NemoFileCallback file; } callback; gpointer callback_data; Request request; gboolean active; /* Set to FALSE when the callback is triggered and * scheduled to be called at idle, its still kept * in the list so we can kill it when the file * goes away. */ } ReadyCallback; typedef struct { NemoFile *file; /* Which file, NULL means all. */ gboolean monitor_hidden_files; /* defines whether "all" includes hidden files */ gconstpointer client; Request request; } Monitor; typedef struct { NemoDirectory *directory; NemoInfoProvider *provider; NemoOperationHandle *handle; NemoOperationResult result; } InfoProviderResponse; typedef gboolean (* RequestCheck) (Request); typedef gboolean (* FileCheck) (NemoFile *); /* Current number of async. jobs. */ static int async_job_count; static GHashTable *waiting_directories; #ifdef DEBUG_ASYNC_JOBS static GHashTable *async_jobs; #endif /* Hide kde trashcan directory */ static char *kde_trash_dir_name = NULL; /* Forward declarations for functions that need them. */ static void deep_count_load (DeepCountState *state, GFile *location); static gboolean request_is_satisfied (NemoDirectory *directory, NemoFile *file, Request request); static void cancel_loading_attributes (NemoDirectory *directory, NemoFileAttributes file_attributes); static void add_all_files_to_work_queue (NemoDirectory *directory); static void link_info_done (NemoDirectory *directory, NemoFile *file, const char *uri, const char *name, GIcon *icon, gboolean is_launcher, gboolean is_foreign); static void move_file_to_low_priority_queue (NemoDirectory *directory, NemoFile *file); static void move_file_to_extension_queue (NemoDirectory *directory, NemoFile *file); static void nemo_directory_invalidate_file_attributes (NemoDirectory *directory, NemoFileAttributes file_attributes); void nemo_set_kde_trash_name (const char *trash_dir) { g_free (kde_trash_dir_name); kde_trash_dir_name = g_strdup (trash_dir); } /* Some helpers for case-insensitive strings. * Move to nemo-glib-extensions? */ static gboolean istr_equal (gconstpointer v, gconstpointer v2) { return g_ascii_strcasecmp (v, v2) == 0; } static guint istr_hash (gconstpointer key) { const char *p; guint h; h = 0; for (p = key; *p != '\0'; p++) { h = (h << 5) - h + g_ascii_tolower (*p); } return h; } static GHashTable * istr_set_new (void) { return g_hash_table_new_full (istr_hash, istr_equal, g_free, NULL); } static void istr_set_insert (GHashTable *table, const char *istr) { char *key; key = g_strdup (istr); g_hash_table_replace (table, key, key); } static void add_istr_to_list (gpointer key, gpointer value, gpointer callback_data) { GList **list; list = callback_data; *list = g_list_prepend (*list, g_strdup (key)); } static GList * istr_set_get_as_list (GHashTable *table) { GList *list; list = NULL; g_hash_table_foreach (table, add_istr_to_list, &list); return list; } static void istr_set_destroy (GHashTable *table) { g_hash_table_destroy (table); } static void request_counter_add_request (RequestCounter counter, Request request) { guint i; for (i = 0; i < REQUEST_TYPE_LAST; i++) { if (REQUEST_WANTS_TYPE (request, i)) { counter[i]++; } } } static void request_counter_remove_request (RequestCounter counter, Request request) { guint i; for (i = 0; i < REQUEST_TYPE_LAST; i++) { if (REQUEST_WANTS_TYPE (request, i)) { counter[i]--; } } } #if 0 static void nemo_directory_verify_request_counts (NemoDirectory *directory) { GList *l; RequestCounter counters; int i; gboolean fail; fail = FALSE; for (i = 0; i < REQUEST_TYPE_LAST; i ++) { counters[i] = 0; } for (l = directory->details->monitor_list; l != NULL; l = l->next) { Monitor *monitor = l->data; request_counter_add_request (counters, monitor->request); } for (i = 0; i < REQUEST_TYPE_LAST; i ++) { if (counters[i] != directory->details->monitor_counters[i]) { g_warning ("monitor counter for %i is wrong, expecting %d but found %d", i, counters[i], directory->details->monitor_counters[i]); fail = TRUE; } } for (i = 0; i < REQUEST_TYPE_LAST; i ++) { counters[i] = 0; } for (l = directory->details->call_when_ready_list; l != NULL; l = l->next) { ReadyCallback *callback = l->data; request_counter_add_request (counters, callback->request); } for (i = 0; i < REQUEST_TYPE_LAST; i ++) { if (counters[i] != directory->details->call_when_ready_counters[i]) { g_warning ("call when ready counter for %i is wrong, expecting %d but found %d", i, counters[i], directory->details->call_when_ready_counters[i]); fail = TRUE; } } g_assert (!fail); } #endif /* Start a job. This is really just a way of limiting the number of * async. requests that we issue at any given time. Without this, the * number of requests is unbounded. */ static gboolean async_job_start (NemoDirectory *directory, const char *job) { #ifdef DEBUG_ASYNC_JOBS char *key; #endif #ifdef DEBUG_START_STOP g_message ("starting %s in %p", job, directory->details->location); #endif g_assert (async_job_count >= 0); g_assert (async_job_count <= MAX_ASYNC_JOBS); if (async_job_count >= MAX_ASYNC_JOBS) { if (waiting_directories == NULL) { waiting_directories = g_hash_table_new (NULL, NULL); } g_hash_table_insert (waiting_directories, directory, directory); return FALSE; } #ifdef DEBUG_ASYNC_JOBS { char *uri; if (async_jobs == NULL) { async_jobs = g_hash_table_new (g_str_hash, g_str_equal); } uri = nemo_directory_get_uri (directory); key = g_strconcat (uri, ": ", job, NULL); if (g_hash_table_lookup (async_jobs, key) != NULL) { g_warning ("same job twice: %s in %s", job, uri); } g_free (uri); g_hash_table_insert (async_jobs, key, directory); } #endif async_job_count += 1; return TRUE; } /* End a job. */ static void async_job_end (NemoDirectory *directory, const char *job) { #ifdef DEBUG_ASYNC_JOBS char *key; gpointer table_key, value; #endif #ifdef DEBUG_START_STOP g_message ("stopping %s in %p", job, directory->details->location); #endif g_assert (async_job_count > 0); #ifdef DEBUG_ASYNC_JOBS { char *uri; uri = nemo_directory_get_uri (directory); g_assert (async_jobs != NULL); key = g_strconcat (uri, ": ", job, NULL); if (!g_hash_table_lookup_extended (async_jobs, key, &table_key, &value)) { g_warning ("ending job we didn't start: %s in %s", job, uri); } else { g_hash_table_remove (async_jobs, key); g_free (table_key); } g_free (uri); g_free (key); } #endif async_job_count -= 1; } /* Helper to get one value from a hash table. */ static void get_one_value_callback (gpointer key, gpointer value, gpointer callback_data) { gpointer *returned_value; returned_value = callback_data; *returned_value = value; } /* return a single value from a hash table. */ static gpointer get_one_value (GHashTable *table) { gpointer value; value = NULL; if (table != NULL) { g_hash_table_foreach (table, get_one_value_callback, &value); } return value; } /* Wake up directories that are "blocked" as long as there are job * slots available. */ static void async_job_wake_up (void) { static gboolean already_waking_up = FALSE; gpointer value; g_assert (async_job_count >= 0); g_assert (async_job_count <= MAX_ASYNC_JOBS); if (already_waking_up) { return; } already_waking_up = TRUE; while (async_job_count < MAX_ASYNC_JOBS) { value = get_one_value (waiting_directories); if (value == NULL) { break; } g_hash_table_remove (waiting_directories, value); nemo_directory_async_state_changed (NEMO_DIRECTORY (value)); } already_waking_up = FALSE; } static void directory_count_cancel (NemoDirectory *directory) { if (directory->details->count_in_progress != NULL) { g_cancellable_cancel (directory->details->count_in_progress->cancellable); } } static void deep_count_cancel (NemoDirectory *directory) { if (directory->details->deep_count_in_progress != NULL) { g_assert (NEMO_IS_FILE (directory->details->deep_count_file)); g_cancellable_cancel (directory->details->deep_count_in_progress->cancellable); directory->details->deep_count_file->details->deep_counts_status = NEMO_REQUEST_NOT_STARTED; directory->details->deep_count_in_progress->directory = NULL; directory->details->deep_count_in_progress = NULL; directory->details->deep_count_file = NULL; async_job_end (directory, "deep count"); } } static void mime_list_cancel (NemoDirectory *directory) { if (directory->details->mime_list_in_progress != NULL) { g_cancellable_cancel (directory->details->mime_list_in_progress->cancellable); } } static void link_info_cancel (NemoDirectory *directory) { if (directory->details->link_info_read_state != NULL) { g_cancellable_cancel (directory->details->link_info_read_state->cancellable); directory->details->link_info_read_state->directory = NULL; directory->details->link_info_read_state = NULL; async_job_end (directory, "link info"); } } static void thumbnail_cancel (NemoDirectory *directory) { if (directory->details->thumbnail_state != NULL) { g_cancellable_cancel (directory->details->thumbnail_state->cancellable); directory->details->thumbnail_state->directory = NULL; directory->details->thumbnail_state = NULL; async_job_end (directory, "thumbnail"); } } static void mount_cancel (NemoDirectory *directory) { if (directory->details->mount_state != NULL) { g_cancellable_cancel (directory->details->mount_state->cancellable); directory->details->mount_state->directory = NULL; directory->details->mount_state = NULL; async_job_end (directory, "mount"); } } static void file_info_cancel (NemoDirectory *directory) { if (directory->details->get_info_in_progress != NULL) { g_cancellable_cancel (directory->details->get_info_in_progress->cancellable); directory->details->get_info_in_progress->directory = NULL; directory->details->get_info_in_progress = NULL; directory->details->get_info_file = NULL; async_job_end (directory, "file info"); } } static void new_files_cancel (NemoDirectory *directory) { GList *l; NewFilesState *state; if (directory->details->new_files_in_progress != NULL) { for (l = directory->details->new_files_in_progress; l != NULL; l = l->next) { state = l->data; g_cancellable_cancel (state->cancellable); state->directory = NULL; } g_list_free (directory->details->new_files_in_progress); directory->details->new_files_in_progress = NULL; } } static int monitor_key_compare (gconstpointer a, gconstpointer data) { const Monitor *monitor; const Monitor *compare_monitor; monitor = a; compare_monitor = data; if (monitor->client < compare_monitor->client) { return -1; } if (monitor->client > compare_monitor->client) { return +1; } if (monitor->file < compare_monitor->file) { return -1; } if (monitor->file > compare_monitor->file) { return +1; } return 0; } static GList * find_monitor (NemoDirectory *directory, NemoFile *file, gconstpointer client) { Monitor monitor; monitor.client = client; monitor.file = file; return g_list_find_custom (directory->details->monitor_list, &monitor, monitor_key_compare); } static void remove_monitor_link (NemoDirectory *directory, GList *link) { Monitor *monitor; if (link != NULL) { monitor = link->data; request_counter_remove_request (directory->details->monitor_counters, monitor->request); directory->details->monitor_list = g_list_remove_link (directory->details->monitor_list, link); g_free (monitor); g_list_free_1 (link); } } static void remove_monitor (NemoDirectory *directory, NemoFile *file, gconstpointer client) { remove_monitor_link (directory, find_monitor (directory, file, client)); } Request nemo_directory_set_up_request (NemoFileAttributes file_attributes) { Request request; request = 0; if ((file_attributes & NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT) != 0) { REQUEST_SET_TYPE (request, REQUEST_DIRECTORY_COUNT); } if ((file_attributes & NEMO_FILE_ATTRIBUTE_DEEP_COUNTS) != 0) { REQUEST_SET_TYPE (request, REQUEST_DEEP_COUNT); } if ((file_attributes & NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES) != 0) { REQUEST_SET_TYPE (request, REQUEST_MIME_LIST); } if ((file_attributes & NEMO_FILE_ATTRIBUTE_INFO) != 0) { REQUEST_SET_TYPE (request, REQUEST_FILE_INFO); } if (file_attributes & NEMO_FILE_ATTRIBUTE_LINK_INFO) { REQUEST_SET_TYPE (request, REQUEST_FILE_INFO); REQUEST_SET_TYPE (request, REQUEST_LINK_INFO); } if ((file_attributes & NEMO_FILE_ATTRIBUTE_EXTENSION_INFO) != 0) { REQUEST_SET_TYPE (request, REQUEST_EXTENSION_INFO); } if (file_attributes & NEMO_FILE_ATTRIBUTE_THUMBNAIL) { REQUEST_SET_TYPE (request, REQUEST_THUMBNAIL); REQUEST_SET_TYPE (request, REQUEST_FILE_INFO); } if (file_attributes & NEMO_FILE_ATTRIBUTE_MOUNT) { REQUEST_SET_TYPE (request, REQUEST_MOUNT); REQUEST_SET_TYPE (request, REQUEST_FILE_INFO); } if (file_attributes & NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO) { REQUEST_SET_TYPE (request, REQUEST_FILESYSTEM_INFO); } return request; } static void mime_db_changed_callback (GObject *ignore, NemoDirectory *dir) { NemoFileAttributes attrs; g_assert (dir != NULL); g_assert (dir->details != NULL); attrs = NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_LINK_INFO | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES; nemo_directory_force_reload_internal (dir, attrs); } void nemo_directory_monitor_add_internal (NemoDirectory *directory, NemoFile *file, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { Monitor *monitor; GList *file_list; g_assert (NEMO_IS_DIRECTORY (directory)); /* Replace any current monitor for this client/file pair. */ remove_monitor (directory, file, client); /* Add the new monitor. */ monitor = g_new (Monitor, 1); monitor->file = file; monitor->monitor_hidden_files = monitor_hidden_files; monitor->client = client; monitor->request = nemo_directory_set_up_request (file_attributes); if (file == NULL) { REQUEST_SET_TYPE (monitor->request, REQUEST_FILE_LIST); } directory->details->monitor_list = g_list_prepend (directory->details->monitor_list, monitor); request_counter_add_request (directory->details->monitor_counters, monitor->request); if (callback != NULL) { file_list = nemo_directory_get_file_list (directory); (* callback) (directory, file_list, callback_data); nemo_file_list_free (file_list); } /* Start the "real" monitoring (FAM or whatever). */ /* We always monitor the whole directory since in practice * nemo almost always shows the whole directory anyway, and * it allows us to avoid one file monitor per file in a directory. */ if (directory->details->monitor == NULL) { directory->details->monitor = nemo_monitor_directory (directory->details->location); } if (REQUEST_WANTS_TYPE (monitor->request, REQUEST_FILE_INFO) && directory->details->mime_db_monitor == 0) { directory->details->mime_db_monitor = g_signal_connect_object (nemo_signaller_get_current (), "mime_data_changed", G_CALLBACK (mime_db_changed_callback), directory, 0); } /* Put the monitor file or all the files on the work queue. */ if (file != NULL) { nemo_directory_add_file_to_work_queue (directory, file); } else { add_all_files_to_work_queue (directory); } /* Kick off I/O. */ nemo_directory_async_state_changed (directory); } static void set_file_unconfirmed (NemoFile *file, gboolean unconfirmed) { NemoDirectory *directory; g_assert (NEMO_IS_FILE (file)); g_assert (unconfirmed == FALSE || unconfirmed == TRUE); if (file->details->unconfirmed == unconfirmed) { return; } file->details->unconfirmed = unconfirmed; directory = file->details->directory; if (unconfirmed) { directory->details->confirmed_file_count--; } else { directory->details->confirmed_file_count++; } } static gboolean show_hidden_files = TRUE; static void show_hidden_files_changed_callback (gpointer callback_data) { show_hidden_files = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SHOW_HIDDEN_FILES); } static gboolean should_skip_file (NemoDirectory *directory, GFileInfo *info) { static gboolean show_hidden_files_changed_callback_installed = FALSE; /* Add the callback once for the life of our process */ if (!show_hidden_files_changed_callback_installed) { g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_SHOW_HIDDEN_FILES, G_CALLBACK(show_hidden_files_changed_callback), NULL); show_hidden_files_changed_callback_installed = TRUE; /* Peek for the first time */ show_hidden_files_changed_callback (NULL); } if (!show_hidden_files && (g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info) || (directory != NULL && directory->details->hidden_file_hash != NULL && g_hash_table_lookup (directory->details->hidden_file_hash, g_file_info_get_name (info)) != NULL))) { return TRUE; } return FALSE; } static gboolean dequeue_pending_idle_callback (gpointer callback_data) { NemoDirectory *directory; GList *pending_file_info; GList *node, *next; NemoFile *file; GList *changed_files, *added_files; GFileInfo *file_info; const char *mimetype, *name; DirectoryLoadState *dir_load_state; directory = NEMO_DIRECTORY (callback_data); nemo_directory_ref (directory); directory->details->dequeue_pending_idle_id = 0; /* Handle the files in the order we saw them. */ pending_file_info = g_list_reverse (directory->details->pending_file_info); directory->details->pending_file_info = NULL; /* If we are no longer monitoring, then throw away these. */ if (!nemo_directory_is_file_list_monitored (directory)) { nemo_directory_async_state_changed (directory); goto drain; } added_files = NULL; changed_files = NULL; dir_load_state = directory->details->directory_load_in_progress; /* Build a list of NemoFile objects. */ for (node = pending_file_info; node != NULL; node = node->next) { file_info = node->data; name = g_file_info_get_name (file_info); /* Update the file count. */ /* FIXME bugzilla.gnome.org 45063: This could count a * file twice if we get it from both load_directory * and from new_files_callback. Not too hard to fix by * moving this into the actual callback instead of * waiting for the idle function. */ if (dir_load_state && !should_skip_file (directory, file_info)) { dir_load_state->load_file_count += 1; /* Add the MIME type to the set. */ mimetype = g_file_info_get_content_type (file_info); if (mimetype != NULL) { istr_set_insert (dir_load_state->load_mime_list_hash, mimetype); } } /* check if the file already exists */ file = nemo_directory_find_file_by_name (directory, name); if (file != NULL) { /* file already exists in dir, check if we still need to * emit file_added or if it changed */ set_file_unconfirmed (file, FALSE); if (!file->details->is_added) { /* We consider this newly added even if its in the list. * This can happen if someone called nemo_file_get_by_uri() * on a file in the folder before the add signal was * emitted */ nemo_file_ref (file); file->details->is_added = TRUE; added_files = g_list_prepend (added_files, file); } else if (nemo_file_update_info (file, file_info)) { /* File changed, notify about the change. */ nemo_file_ref (file); changed_files = g_list_prepend (changed_files, file); } } else { /* new file, create a nemo file object and add it to the list */ file = nemo_file_new_from_info (directory, file_info); nemo_directory_add_file (directory, file); file->details->is_added = TRUE; added_files = g_list_prepend (added_files, file); } } /* If we are done loading, then we assume that any unconfirmed * files are gone. */ if (directory->details->directory_loaded) { for (node = directory->details->file_list; node != NULL; node = next) { file = NEMO_FILE (node->data); next = node->next; if (file->details->unconfirmed) { nemo_file_ref (file); changed_files = g_list_prepend (changed_files, file); nemo_file_mark_gone (file); } } } /* Send the changed and added signals. */ nemo_directory_emit_change_signals (directory, changed_files); nemo_file_list_free (changed_files); nemo_directory_emit_files_added (directory, added_files); nemo_file_list_free (added_files); if (directory->details->directory_loaded && !directory->details->directory_loaded_sent_notification) { /* Send the done_loading signal. */ nemo_directory_emit_done_loading (directory); if (dir_load_state) { file = dir_load_state->load_directory_file; file->details->directory_count = dir_load_state->load_file_count; file->details->directory_count_is_up_to_date = TRUE; file->details->got_directory_count = TRUE; file->details->got_mime_list = TRUE; file->details->mime_list_is_up_to_date = TRUE; g_list_free_full (file->details->mime_list, g_free); file->details->mime_list = istr_set_get_as_list (dir_load_state->load_mime_list_hash); nemo_file_changed (file); } nemo_directory_async_state_changed (directory); directory->details->directory_loaded_sent_notification = TRUE; } drain: g_list_free_full (pending_file_info, g_object_unref); /* Get the state machine running again. */ nemo_directory_async_state_changed (directory); nemo_directory_unref (directory); return FALSE; } void nemo_directory_schedule_dequeue_pending (NemoDirectory *directory) { if (directory->details->dequeue_pending_idle_id == 0) { directory->details->dequeue_pending_idle_id = g_idle_add (dequeue_pending_idle_callback, directory); } } static void directory_load_one (NemoDirectory *directory, GFileInfo *info) { if (info == NULL) { return; } if (g_file_info_get_name (info) == NULL) { char *uri; uri = nemo_directory_get_uri (directory); g_warning ("Got GFileInfo with NULL name in %s, ignoring. This shouldn't happen unless the gvfs backend is broken.\n", uri); g_free (uri); return; } /* Arrange for the "loading" part of the work. */ g_object_ref (info); directory->details->pending_file_info = g_list_prepend (directory->details->pending_file_info, info); nemo_directory_schedule_dequeue_pending (directory); } static void directory_load_cancel (NemoDirectory *directory) { NemoFile *file; DirectoryLoadState *state; state = directory->details->directory_load_in_progress; if (state != NULL) { file = state->load_directory_file; file->details->loading_directory = FALSE; if (file->details->directory != directory) { nemo_directory_async_state_changed (file->details->directory); } g_cancellable_cancel (state->cancellable); state->directory = NULL; directory->details->directory_load_in_progress = NULL; async_job_end (directory, "file list"); } } static void file_list_cancel (NemoDirectory *directory) { directory_load_cancel (directory); if (directory->details->dequeue_pending_idle_id != 0) { g_source_remove (directory->details->dequeue_pending_idle_id); directory->details->dequeue_pending_idle_id = 0; } if (directory->details->pending_file_info != NULL) { g_list_free_full (directory->details->pending_file_info, g_object_unref); directory->details->pending_file_info = NULL; } if (directory->details->hidden_file_hash) { g_hash_table_remove_all (directory->details->hidden_file_hash); } } static void directory_load_done (NemoDirectory *directory, GError *error) { GList *node; directory->details->directory_loaded = TRUE; directory->details->directory_loaded_sent_notification = FALSE; if (error != NULL) { /* The load did not complete successfully. This means * we don't know the status of the files in this directory. * We clear the unconfirmed bit on each file here so that * they won't be marked "gone" later -- we don't know enough * about them to know whether they are really gone. */ for (node = directory->details->file_list; node != NULL; node = node->next) { set_file_unconfirmed (NEMO_FILE (node->data), FALSE); } nemo_directory_emit_load_error (directory, error); } /* Call the idle function right away. */ if (directory->details->dequeue_pending_idle_id != 0) { g_source_remove (directory->details->dequeue_pending_idle_id); } dequeue_pending_idle_callback (directory); directory_load_cancel (directory); } void nemo_directory_monitor_remove_internal (NemoDirectory *directory, NemoFile *file, gconstpointer client) { g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (file == NULL || NEMO_IS_FILE (file)); g_assert (client != NULL); remove_monitor (directory, file, client); if (directory->details->monitor != NULL && directory->details->monitor_list == NULL) { nemo_monitor_cancel (directory->details->monitor); directory->details->monitor = NULL; } /* XXX - do we need to remove anything from the work queue? */ nemo_directory_async_state_changed (directory); } FileMonitors * nemo_directory_remove_file_monitors (NemoDirectory *directory, NemoFile *file) { GList *result, **list, *node, *next; Monitor *monitor; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); result = NULL; list = &directory->details->monitor_list; for (node = directory->details->monitor_list; node != NULL; node = next) { next = node->next; monitor = node->data; if (monitor->file == file) { *list = g_list_remove_link (*list, node); result = g_list_concat (node, result); request_counter_remove_request (directory->details->monitor_counters, monitor->request); } } /* XXX - do we need to remove anything from the work queue? */ nemo_directory_async_state_changed (directory); return (FileMonitors *) result; } void nemo_directory_add_file_monitors (NemoDirectory *directory, NemoFile *file, FileMonitors *monitors) { GList **list; GList *l; Monitor *monitor; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (monitors == NULL) { return; } for (l = (GList *)monitors; l != NULL; l = l->next) { monitor = l->data; request_counter_add_request (directory->details->monitor_counters, monitor->request); } list = &directory->details->monitor_list; *list = g_list_concat (*list, (GList *) monitors); nemo_directory_add_file_to_work_queue (directory, file); nemo_directory_async_state_changed (directory); } static int ready_callback_key_compare (gconstpointer a, gconstpointer b) { const ReadyCallback *callback_a, *callback_b; callback_a = a; callback_b = b; if (callback_a->file < callback_b->file) { return -1; } if (callback_a->file > callback_b->file) { return 1; } if (callback_a->file == NULL) { /* ANSI C doesn't allow ordered compares of function pointers, so we cast them to * normal pointers to make some overly pedantic compilers (*cough* HP-UX *cough*) * compile this. Of course, on any compiler where ordered function pointers actually * break this probably won't work, but at least it will compile on platforms where it * works, but stupid compilers won't let you use it. */ if ((void *)callback_a->callback.directory < (void *)callback_b->callback.directory) { return -1; } if ((void *)callback_a->callback.directory > (void *)callback_b->callback.directory) { return 1; } } else { if ((void *)callback_a->callback.file < (void *)callback_b->callback.file) { return -1; } if ((void *)callback_a->callback.file > (void *)callback_b->callback.file) { return 1; } } if (callback_a->callback_data < callback_b->callback_data) { return -1; } if (callback_a->callback_data > callback_b->callback_data) { return 1; } return 0; } static int ready_callback_key_compare_only_active (gconstpointer a, gconstpointer b) { const ReadyCallback *callback_a; callback_a = a; /* Non active callbacks never match */ if (!callback_a->active) { return -1; } return ready_callback_key_compare (a, b); } static void ready_callback_call (NemoDirectory *directory, const ReadyCallback *callback) { GList *file_list; /* Call the callback. */ if (callback->file != NULL) { if (callback->callback.file) { (* callback->callback.file) (callback->file, callback->callback_data); } } else if (callback->callback.directory != NULL) { if (directory == NULL || !REQUEST_WANTS_TYPE (callback->request, REQUEST_FILE_LIST)) { file_list = NULL; } else { file_list = nemo_directory_get_file_list (directory); } /* Pass back the file list if the user was waiting for it. */ (* callback->callback.directory) (directory, file_list, callback->callback_data); nemo_file_list_free (file_list); } } void nemo_directory_call_when_ready_internal (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback directory_callback, NemoFileCallback file_callback, gpointer callback_data) { ReadyCallback callback; g_assert (directory == NULL || NEMO_IS_DIRECTORY (directory)); g_assert (file == NULL || NEMO_IS_FILE (file)); g_assert (file != NULL || directory_callback != NULL); /* Construct a callback object. */ callback.active = TRUE; callback.file = file; if (file == NULL) { callback.callback.directory = directory_callback; } else { callback.callback.file = file_callback; } callback.callback_data = callback_data; callback.request = nemo_directory_set_up_request (file_attributes); if (wait_for_file_list) { REQUEST_SET_TYPE (callback.request, REQUEST_FILE_LIST); } /* Handle the NULL case. */ if (directory == NULL) { ready_callback_call (NULL, &callback); return; } /* Check if the callback is already there. */ if (g_list_find_custom (directory->details->call_when_ready_list, &callback, ready_callback_key_compare_only_active) != NULL) { if (file_callback != NULL && directory_callback != NULL) { g_warning ("tried to add a new callback while an old one was pending"); } /* NULL callback means, just read it. Conflicts are ok. */ return; } /* Add the new callback to the list. */ directory->details->call_when_ready_list = g_list_prepend (directory->details->call_when_ready_list, g_memdup (&callback, sizeof (callback))); request_counter_add_request (directory->details->call_when_ready_counters, callback.request); /* Put the callback file or all the files on the work queue. */ if (file != NULL) { nemo_directory_add_file_to_work_queue (directory, file); } else { add_all_files_to_work_queue (directory); } nemo_directory_async_state_changed (directory); } gboolean nemo_directory_check_if_ready_internal (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes) { Request request; g_assert (NEMO_IS_DIRECTORY (directory)); request = nemo_directory_set_up_request (file_attributes); return request_is_satisfied (directory, file, request); } static void remove_callback_link_keep_data (NemoDirectory *directory, GList *link) { ReadyCallback *callback; callback = link->data; directory->details->call_when_ready_list = g_list_remove_link (directory->details->call_when_ready_list, link); request_counter_remove_request (directory->details->call_when_ready_counters, callback->request); g_list_free_1 (link); } static void remove_callback_link (NemoDirectory *directory, GList *link) { ReadyCallback *callback; callback = link->data; remove_callback_link_keep_data (directory, link); g_free (callback); } void nemo_directory_cancel_callback_internal (NemoDirectory *directory, NemoFile *file, NemoDirectoryCallback directory_callback, NemoFileCallback file_callback, gpointer callback_data) { ReadyCallback callback; GList *node; if (directory == NULL) { return; } g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (file == NULL || NEMO_IS_FILE (file)); g_assert (file != NULL || directory_callback != NULL); g_assert (file == NULL || file_callback != NULL); /* Construct a callback object. */ callback.file = file; if (file == NULL) { callback.callback.directory = directory_callback; } else { callback.callback.file = file_callback; } callback.callback_data = callback_data; /* Remove all queued callback from the list (including non-active). */ do { node = g_list_find_custom (directory->details->call_when_ready_list, &callback, ready_callback_key_compare); if (node != NULL) { remove_callback_link (directory, node); nemo_directory_async_state_changed (directory); } } while (node != NULL); } static void new_files_state_unref (NewFilesState *state) { state->count--; if (state->count == 0) { if (state->directory) { state->directory->details->new_files_in_progress = g_list_remove (state->directory->details->new_files_in_progress, state); } g_object_unref (state->cancellable); g_free (state); } } static void new_files_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { NemoDirectory *directory; GFileInfo *info; NewFilesState *state; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ new_files_state_unref (state); return; } directory = nemo_directory_ref (state->directory); /* Queue up the new file. */ info = g_file_query_info_finish (G_FILE (source_object), res, NULL); if (info != NULL) { directory_load_one (directory, info); g_object_unref (info); } new_files_state_unref (state); nemo_directory_unref (directory); } void nemo_directory_get_info_for_new_files (NemoDirectory *directory, GList *location_list) { NewFilesState *state; GFile *location; GList *l; if (location_list == NULL) { return; } state = g_new (NewFilesState, 1); state->directory = directory; state->cancellable = g_cancellable_new (); state->count = 0; for (l = location_list; l != NULL; l = l->next) { location = l->data; state->count++; g_file_query_info_async (location, NEMO_FILE_DEFAULT_ATTRIBUTES, 0, G_PRIORITY_DEFAULT, state->cancellable, new_files_callback, state); } directory->details->new_files_in_progress = g_list_prepend (directory->details->new_files_in_progress, state); } void nemo_async_destroying_file (NemoFile *file) { NemoDirectory *directory; gboolean changed; GList *node, *next; ReadyCallback *callback; Monitor *monitor; directory = file->details->directory; changed = FALSE; /* Check for callbacks. */ for (node = directory->details->call_when_ready_list; node != NULL; node = next) { next = node->next; callback = node->data; if (callback->file == file) { /* Client should have cancelled callback. */ if (callback->active) { g_warning ("destroyed file has call_when_ready pending"); } remove_callback_link (directory, node); changed = TRUE; } } /* Check for monitors. */ for (node = directory->details->monitor_list; node != NULL; node = next) { next = node->next; monitor = node->data; if (monitor->file == file) { /* Client should have removed monitor earlier. */ g_warning ("destroyed file still being monitored"); remove_monitor_link (directory, node); changed = TRUE; } } /* Check if it's a file that's currently being worked on. * If so, make that NULL so it gets canceled right away. */ if (directory->details->count_in_progress != NULL && directory->details->count_in_progress->count_file == file) { directory->details->count_in_progress->count_file = NULL; changed = TRUE; } if (directory->details->deep_count_file == file) { directory->details->deep_count_file = NULL; changed = TRUE; } if (directory->details->mime_list_in_progress != NULL && directory->details->mime_list_in_progress->mime_list_file == file) { directory->details->mime_list_in_progress->mime_list_file = NULL; changed = TRUE; } if (directory->details->get_info_file == file) { directory->details->get_info_file = NULL; changed = TRUE; } if (directory->details->link_info_read_state != NULL && directory->details->link_info_read_state->file == file) { directory->details->link_info_read_state->file = NULL; changed = TRUE; } if (directory->details->extension_info_file == file) { directory->details->extension_info_file = NULL; changed = TRUE; } if (directory->details->thumbnail_state != NULL && directory->details->thumbnail_state->file == file) { directory->details->thumbnail_state->file = NULL; changed = TRUE; } if (directory->details->mount_state != NULL && directory->details->mount_state->file == file) { directory->details->mount_state->file = NULL; changed = TRUE; } if (directory->details->filesystem_info_state != NULL && directory->details->filesystem_info_state->file == file) { directory->details->filesystem_info_state->file = NULL; changed = TRUE; } /* Let the directory take care of the rest. */ if (changed) { nemo_directory_async_state_changed (directory); } } static gboolean lacks_directory_count (NemoFile *file) { return !file->details->directory_count_is_up_to_date && nemo_file_should_show_directory_item_count (file); } static gboolean should_get_directory_count_now (NemoFile *file) { return lacks_directory_count (file) && !file->details->loading_directory; } static gboolean lacks_info (NemoFile *file) { return !file->details->file_info_is_up_to_date && !file->details->is_gone; } static gboolean lacks_filesystem_info (NemoFile *file) { return !file->details->filesystem_info_is_up_to_date; } static gboolean lacks_deep_count (NemoFile *file) { return file->details->deep_counts_status != NEMO_REQUEST_DONE; } static gboolean lacks_mime_list (NemoFile *file) { return !file->details->mime_list_is_up_to_date; } static gboolean should_get_mime_list (NemoFile *file) { return lacks_mime_list (file) && !file->details->loading_directory; } static gboolean lacks_link_info (NemoFile *file) { if (file->details->file_info_is_up_to_date && !file->details->link_info_is_up_to_date) { if (nemo_file_is_nemo_link (file)) { return TRUE; } else { link_info_done (file->details->directory, file, NULL, NULL, NULL, FALSE, FALSE); return FALSE; } } else { return FALSE; } } static gboolean lacks_extension_info (NemoFile *file) { return file->details->pending_info_providers != NULL; } static gboolean lacks_thumbnail (NemoFile *file) { return nemo_file_should_show_thumbnail (file) && file->details->thumbnail_path != NULL && !file->details->thumbnail_is_up_to_date; } static gboolean lacks_mount (NemoFile *file) { return (!file->details->mount_is_up_to_date && ( /* Unix mountpoint, could be a GMount */ file->details->is_mountpoint || /* The toplevel directory of something */ (file->details->type == G_FILE_TYPE_DIRECTORY && nemo_file_is_self_owned (file)) || /* Mountable, could be a mountpoint */ (file->details->type == G_FILE_TYPE_MOUNTABLE) ) ); } static gboolean has_problem (NemoDirectory *directory, NemoFile *file, FileCheck problem) { GList *node; if (file != NULL) { return (* problem) (file); } for (node = directory->details->file_list; node != NULL; node = node->next) { if ((* problem) (node->data)) { return TRUE; } } return FALSE; } static gboolean request_is_satisfied (NemoDirectory *directory, NemoFile *file, Request request) { if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_LIST) && !(directory->details->directory_loaded && directory->details->directory_loaded_sent_notification)) { return FALSE; } if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)) { if (has_problem (directory, file, lacks_directory_count)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)) { if (has_problem (directory, file, lacks_info)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_FILESYSTEM_INFO)) { if (has_problem (directory, file, lacks_filesystem_info)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)) { if (has_problem (directory, file, lacks_deep_count)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)) { if (has_problem (directory, file, lacks_thumbnail)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) { if (has_problem (directory, file, lacks_mount)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)) { if (has_problem (directory, file, lacks_mime_list)) { return FALSE; } } if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)) { if (has_problem (directory, file, lacks_link_info)) { return FALSE; } } return TRUE; } static gboolean call_ready_callbacks_at_idle (gpointer callback_data) { NemoDirectory *directory; GList *node, *next; ReadyCallback *callback; directory = NEMO_DIRECTORY (callback_data); directory->details->call_ready_idle_id = 0; nemo_directory_ref (directory); callback = NULL; while (1) { /* Check if any callbacks are non-active and call them if they are. */ for (node = directory->details->call_when_ready_list; node != NULL; node = next) { next = node->next; callback = node->data; if (!callback->active) { /* Non-active, remove and call */ break; } } if (node == NULL) { break; } /* Callbacks are one-shots, so remove it now. */ remove_callback_link_keep_data (directory, node); /* Call the callback. */ ready_callback_call (directory, callback); g_free (callback); } nemo_directory_async_state_changed (directory); nemo_directory_unref (directory); return FALSE; } static void schedule_call_ready_callbacks (NemoDirectory *directory) { if (directory->details->call_ready_idle_id == 0) { directory->details->call_ready_idle_id = g_idle_add (call_ready_callbacks_at_idle, directory); } } /* Marks all callbacks that are ready as non-active and * calls them at idle time, unless they are removed * before then */ static gboolean call_ready_callbacks (NemoDirectory *directory) { gboolean found_any; GList *node, *next; ReadyCallback *callback; found_any = FALSE; /* Check if any callbacks are satisifed and mark them for call them if they are. */ for (node = directory->details->call_when_ready_list; node != NULL; node = next) { next = node->next; callback = node->data; if (callback->active && request_is_satisfied (directory, callback->file, callback->request)) { callback->active = FALSE; found_any = TRUE; } } if (found_any) { schedule_call_ready_callbacks (directory); } return found_any; } gboolean nemo_directory_has_active_request_for_file (NemoDirectory *directory, NemoFile *file) { GList *node; ReadyCallback *callback; Monitor *monitor; for (node = directory->details->call_when_ready_list; node != NULL; node = node->next) { callback = node->data; if (callback->file == file || callback->file == NULL) { return TRUE; } } for (node = directory->details->monitor_list; node != NULL; node = node->next) { monitor = node->data; if (monitor->file == file || monitor->file == NULL) { return TRUE; } } return FALSE; } /* This checks if there's a request for monitoring the file list. */ gboolean nemo_directory_is_anyone_monitoring_file_list (NemoDirectory *directory) { if (directory->details->call_when_ready_counters[REQUEST_FILE_LIST] > 0) { return TRUE; } if (directory->details->monitor_counters[REQUEST_FILE_LIST] > 0) { return TRUE; } return FALSE; } /* This checks if the file list being monitored. */ gboolean nemo_directory_is_file_list_monitored (NemoDirectory *directory) { return directory->details->file_list_monitored; } static void mark_all_files_unconfirmed (NemoDirectory *directory) { GList *node; NemoFile *file; for (node = directory->details->file_list; node != NULL; node = node->next) { file = node->data; set_file_unconfirmed (file, TRUE); } } static void read_dot_hidden_file (NemoDirectory *directory) { gsize file_size; char *file_contents; GFile *child; GFileInfo *info; GFileType type; int i; /* FIXME: We only support .hidden on file: uri's for the moment. * Need to figure out if we should do this async or sync to extend * it to all types of uris. */ if (directory->details->location == NULL || !g_file_is_native (directory->details->location)) { return; } child = g_file_get_child (directory->details->location, ".hidden"); type = G_FILE_TYPE_UNKNOWN; info = g_file_query_info (child, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL); if (info != NULL) { type = g_file_info_get_file_type (info); g_object_unref (info); } if (type != G_FILE_TYPE_REGULAR) { g_object_unref (child); return; } if (!g_file_load_contents (child, NULL, &file_contents, &file_size, NULL, NULL)) { g_object_unref (child); return; } g_object_unref (child); if (directory->details->hidden_file_hash == NULL) { directory->details->hidden_file_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } /* Now parse the data */ i = 0; while (i < file_size) { int start; start = i; while (i < file_size && file_contents[i] != '\n') { i++; } if (i > start) { char *hidden_filename; hidden_filename = g_strndup (file_contents + start, i - start); g_hash_table_insert (directory->details->hidden_file_hash, hidden_filename, hidden_filename); } i++; } g_free (file_contents); } static void directory_load_state_free (DirectoryLoadState *state) { if (state->enumerator) { if (!g_file_enumerator_is_closed (state->enumerator)) { g_file_enumerator_close_async (state->enumerator, 0, NULL, NULL, NULL); } g_object_unref (state->enumerator); } if (state->load_mime_list_hash != NULL) { istr_set_destroy (state->load_mime_list_hash); } nemo_file_unref (state->load_directory_file); g_object_unref (state->cancellable); g_free (state); } static void more_files_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DirectoryLoadState *state; NemoDirectory *directory; GError *error; GList *files, *l; GFileInfo *info; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ directory_load_state_free (state); return; } directory = nemo_directory_ref (state->directory); g_assert (directory->details->directory_load_in_progress != NULL); g_assert (directory->details->directory_load_in_progress == state); error = NULL; files = g_file_enumerator_next_files_finish (state->enumerator, res, &error); for (l = files; l != NULL; l = l->next) { info = l->data; directory_load_one (directory, info); g_object_unref (info); } if (files == NULL) { directory_load_done (directory, error); directory_load_state_free (state); } else { g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, more_files_callback, state); } nemo_directory_unref (directory); if (error) { g_error_free (error); } g_list_free (files); } static void enumerate_children_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DirectoryLoadState *state; GFileEnumerator *enumerator; GError *error; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ directory_load_state_free (state); return; } error = NULL; enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, &error); if (enumerator == NULL) { directory_load_done (state->directory, error); g_error_free (error); directory_load_state_free (state); return; } else { state->enumerator = enumerator; g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, more_files_callback, state); } } /* Start monitoring the file list if it isn't already. */ static void start_monitoring_file_list (NemoDirectory *directory) { DirectoryLoadState *state; if (!directory->details->file_list_monitored) { g_assert (!directory->details->directory_load_in_progress); directory->details->file_list_monitored = TRUE; nemo_file_list_ref (directory->details->file_list); } if (directory->details->directory_loaded || directory->details->directory_load_in_progress != NULL) { return; } if (!async_job_start (directory, "file list")) { return; } mark_all_files_unconfirmed (directory); state = g_new0 (DirectoryLoadState, 1); state->directory = directory; state->cancellable = g_cancellable_new (); state->load_mime_list_hash = istr_set_new (); state->load_file_count = 0; g_assert (directory->details->location != NULL); state->load_directory_file = nemo_directory_get_corresponding_file (directory); state->load_directory_file->details->loading_directory = TRUE; read_dot_hidden_file (directory); /* Hack to work around kde trash dir */ if (kde_trash_dir_name != NULL && nemo_directory_is_desktop_directory (directory)) { char *fn; if (directory->details->hidden_file_hash == NULL) { directory->details->hidden_file_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } fn = g_strdup (kde_trash_dir_name); g_hash_table_insert (directory->details->hidden_file_hash, fn, fn); } #ifdef DEBUG_LOAD_DIRECTORY g_message ("load_directory called to monitor file list of %p", directory->details->location); #endif directory->details->directory_load_in_progress = state; g_file_enumerate_children_async (directory->details->location, NEMO_FILE_DEFAULT_ATTRIBUTES, 0, /* flags */ G_PRIORITY_DEFAULT, /* prio */ state->cancellable, enumerate_children_callback, state); } /* Stop monitoring the file list if it is being monitored. */ void nemo_directory_stop_monitoring_file_list (NemoDirectory *directory) { if (!directory->details->file_list_monitored) { g_assert (directory->details->directory_load_in_progress == NULL); return; } directory->details->file_list_monitored = FALSE; file_list_cancel (directory); nemo_file_list_unref (directory->details->file_list); directory->details->directory_loaded = FALSE; } static void file_list_start_or_stop (NemoDirectory *directory) { if (nemo_directory_is_anyone_monitoring_file_list (directory)) { start_monitoring_file_list (directory); } else { nemo_directory_stop_monitoring_file_list (directory); } } void nemo_file_invalidate_count_and_mime_list (NemoFile *file) { NemoFileAttributes attributes; attributes = NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES; nemo_file_invalidate_attributes (file, attributes); } /* Reset count and mime list. Invalidating deep counts is handled by * itself elsewhere because it's a relatively heavyweight and * special-purpose operation (see bug 5863). Also, the shallow count * needs to be refreshed when filtering changes, but the deep count * deliberately does not take filtering into account. */ void nemo_directory_invalidate_count_and_mime_list (NemoDirectory *directory) { NemoFile *file; file = nemo_directory_get_existing_corresponding_file (directory); if (file != NULL) { nemo_file_invalidate_count_and_mime_list (file); } nemo_file_unref (file); } static void nemo_directory_invalidate_file_attributes (NemoDirectory *directory, NemoFileAttributes file_attributes) { GList *node; cancel_loading_attributes (directory, file_attributes); for (node = directory->details->file_list; node != NULL; node = node->next) { nemo_file_invalidate_attributes_internal (NEMO_FILE (node->data), file_attributes); } if (directory->details->as_file != NULL) { nemo_file_invalidate_attributes_internal (directory->details->as_file, file_attributes); } } void nemo_directory_force_reload_internal (NemoDirectory *directory, NemoFileAttributes file_attributes) { /* invalidate attributes that are getting reloaded for all files */ nemo_directory_invalidate_file_attributes (directory, file_attributes); /* Start a new directory load. */ file_list_cancel (directory); directory->details->directory_loaded = FALSE; /* Start a new directory count. */ nemo_directory_invalidate_count_and_mime_list (directory); add_all_files_to_work_queue (directory); nemo_directory_async_state_changed (directory); } static gboolean monitor_includes_file (const Monitor *monitor, NemoFile *file) { if (monitor->file == file) { return TRUE; } if (monitor->file != NULL) { return FALSE; } if (file == file->details->directory->details->as_file) { return FALSE; } return nemo_file_should_show (file, monitor->monitor_hidden_files, TRUE); } static gboolean is_needy (NemoFile *file, FileCheck check_missing, RequestType request_type_wanted) { NemoDirectory *directory; GList *node; ReadyCallback *callback; Monitor *monitor; if (!(* check_missing) (file)) { return FALSE; } directory = file->details->directory; if (directory->details->call_when_ready_counters[request_type_wanted] > 0) { for (node = directory->details->call_when_ready_list; node != NULL; node = node->next) { callback = node->data; if (callback->active && REQUEST_WANTS_TYPE (callback->request, request_type_wanted)) { if (callback->file == file) { return TRUE; } if (callback->file == NULL && file != directory->details->as_file) { return TRUE; } } } } if (directory->details->monitor_counters[request_type_wanted] > 0) { for (node = directory->details->monitor_list; node != NULL; node = node->next) { monitor = node->data; if (REQUEST_WANTS_TYPE (monitor->request, request_type_wanted)) { if (monitor_includes_file (monitor, file)) { return TRUE; } } } } return FALSE; } static void directory_count_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->count_in_progress != NULL) { file = directory->details->count_in_progress->count_file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, should_get_directory_count_now, REQUEST_DIRECTORY_COUNT)) { return; } } /* The count is not wanted, so stop it. */ directory_count_cancel (directory); } } static guint count_non_skipped_files (GList *list) { guint count; GList *node; GFileInfo *info; count = 0; for (node = list; node != NULL; node = node->next) { info = node->data; if (!should_skip_file (NULL, info)) { count += 1; } } return count; } static void count_children_done (NemoDirectory *directory, NemoFile *count_file, gboolean succeeded, int count) { g_assert (NEMO_IS_FILE (count_file)); count_file->details->directory_count_is_up_to_date = TRUE; /* Record either a failure or success. */ if (!succeeded) { count_file->details->directory_count_failed = TRUE; count_file->details->got_directory_count = FALSE; count_file->details->directory_count = 0; } else { count_file->details->directory_count_failed = FALSE; count_file->details->got_directory_count = TRUE; count_file->details->directory_count = count; } directory->details->count_in_progress = NULL; /* Send file-changed even if count failed, so interested parties can * distinguish between unknowable and not-yet-known cases. */ nemo_file_changed (count_file); /* Start up the next one. */ async_job_end (directory, "directory count"); nemo_directory_async_state_changed (directory); } static void directory_count_state_free (DirectoryCountState *state) { if (state->enumerator) { if (!g_file_enumerator_is_closed (state->enumerator)) { g_file_enumerator_close_async (state->enumerator, 0, NULL, NULL, NULL); } g_object_unref (state->enumerator); } g_object_unref (state->cancellable); nemo_directory_unref (state->directory); g_free (state); } static void count_more_files_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DirectoryCountState *state; NemoDirectory *directory; GError *error; GList *files; state = user_data; directory = state->directory; if (g_cancellable_is_cancelled (state->cancellable)) { /* Operation was cancelled. Bail out */ directory->details->count_in_progress = NULL; async_job_end (directory, "directory count"); nemo_directory_async_state_changed (directory); directory_count_state_free (state); return; } g_assert (directory->details->count_in_progress != NULL); g_assert (directory->details->count_in_progress == state); error = NULL; files = g_file_enumerator_next_files_finish (state->enumerator, res, &error); state->file_count += count_non_skipped_files (files); if (files == NULL) { count_children_done (directory, state->count_file, TRUE, state->file_count); directory_count_state_free (state); } else { g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, count_more_files_callback, state); } g_list_free_full (files, g_object_unref); if (error) { g_error_free (error); } } static void count_children_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DirectoryCountState *state; GFileEnumerator *enumerator; NemoDirectory *directory; GError *error; state = user_data; if (g_cancellable_is_cancelled (state->cancellable)) { /* Operation was cancelled. Bail out */ directory = state->directory; directory->details->count_in_progress = NULL; async_job_end (directory, "directory count"); nemo_directory_async_state_changed (directory); directory_count_state_free (state); return; } error = NULL; enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, &error); if (enumerator == NULL) { count_children_done (state->directory, state->count_file, FALSE, 0); g_error_free (error); directory_count_state_free (state); return; } else { state->enumerator = enumerator; g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, count_more_files_callback, state); } } static void directory_count_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { DirectoryCountState *state; GFile *location; if (directory->details->count_in_progress != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, should_get_directory_count_now, REQUEST_DIRECTORY_COUNT)) { return; } *doing_io = TRUE; if (!nemo_file_is_directory (file)) { file->details->directory_count_is_up_to_date = TRUE; file->details->directory_count_failed = FALSE; file->details->got_directory_count = FALSE; nemo_directory_async_state_changed (directory); return; } if (!async_job_start (directory, "directory count")) { return; } /* Start counting. */ state = g_new0 (DirectoryCountState, 1); state->count_file = file; state->directory = nemo_directory_ref (directory); state->cancellable = g_cancellable_new (); directory->details->count_in_progress = state; location = nemo_file_get_location (file); #ifdef DEBUG_LOAD_DIRECTORY { char *uri; uri = g_file_get_uri (location); g_message ("load_directory called to get shallow file count for %s", uri); g_free (uri); } #endif g_file_enumerate_children_async (location, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN "," G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, /* flags */ G_PRIORITY_DEFAULT, /* prio */ state->cancellable, count_children_callback, state); g_object_unref (location); } static inline gboolean seen_inode (DeepCountState *state, GFileInfo *info) { guint64 inode, inode2; guint i; inode = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE); if (inode != 0) { for (i = 0; i < state->seen_deep_count_inodes->len; i++) { inode2 = g_array_index (state->seen_deep_count_inodes, guint64, i); if (inode == inode2) { return TRUE; } } } return FALSE; } static inline void mark_inode_as_seen (DeepCountState *state, GFileInfo *info) { guint64 inode; inode = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE); if (inode != 0) { g_array_append_val (state->seen_deep_count_inodes, inode); } } static void deep_count_one (DeepCountState *state, GFileInfo *info) { NemoFile *file; GFile *subdir; gboolean is_seen_inode; const char *id; gboolean hidden; is_seen_inode = seen_inode (state, info); if (!is_seen_inode) { mark_inode_as_seen (state, info); } file = state->directory->details->deep_count_file; hidden = should_skip_file (NULL, info); if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { /* Count the directory. */ if (hidden) { file->details->deep_hidden_count += 1; } else { file->details->deep_directory_count += 1; } /* Record the fact that we have to descend into this directory. */ id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM); if (g_strcmp0 (id, state->fs_id) == 0) { /* only if it is on the same filesystem */ subdir = g_file_get_child (state->deep_count_location, g_file_info_get_name (info)); state->deep_count_subdirectories = g_list_prepend (state->deep_count_subdirectories, subdir); } } else { /* Even non-regular files count as files. */ if (hidden) { file->details->deep_hidden_count += 1; } else { file->details->deep_file_count += 1; } } /* Count the size, hidden or not */ if (!is_seen_inode && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE)) { file->details->deep_size += g_file_info_get_size (info); } } static void deep_count_state_free (DeepCountState *state) { if (state->enumerator) { if (!g_file_enumerator_is_closed (state->enumerator)) { g_file_enumerator_close_async (state->enumerator, 0, NULL, NULL, NULL); } g_object_unref (state->enumerator); } g_object_unref (state->cancellable); if (state->deep_count_location) { g_object_unref (state->deep_count_location); } g_list_free_full (state->deep_count_subdirectories, g_object_unref); g_array_free (state->seen_deep_count_inodes, TRUE); g_free (state->fs_id); g_free (state); } static void deep_count_next_dir (DeepCountState *state) { GFile *location; NemoFile *file; NemoDirectory *directory; gboolean done; directory = state->directory; g_object_unref (state->deep_count_location); state->deep_count_location = NULL; done = FALSE; file = directory->details->deep_count_file; if (state->deep_count_subdirectories != NULL) { /* Work on a new directory. */ location = state->deep_count_subdirectories->data; state->deep_count_subdirectories = g_list_remove (state->deep_count_subdirectories, location); deep_count_load (state, location); g_object_unref (location); } else { file->details->deep_counts_status = NEMO_REQUEST_DONE; directory->details->deep_count_file = NULL; directory->details->deep_count_in_progress = NULL; deep_count_state_free (state); done = TRUE; } nemo_file_updated_deep_count_in_progress (file); if (done) { nemo_file_changed (file); async_job_end (directory, "deep count"); nemo_directory_async_state_changed (directory); } } static void deep_count_more_files_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DeepCountState *state; NemoDirectory *directory; GList *files, *l; GFileInfo *info; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ deep_count_state_free (state); return; } directory = nemo_directory_ref (state->directory); g_assert (directory->details->deep_count_in_progress != NULL); g_assert (directory->details->deep_count_in_progress == state); files = g_file_enumerator_next_files_finish (state->enumerator, res, NULL); for (l = files; l != NULL; l = l->next) { info = l->data; deep_count_one (state, info); g_object_unref (info); } if (files == NULL) { g_file_enumerator_close_async (state->enumerator, 0, NULL, NULL, NULL); g_object_unref (state->enumerator); state->enumerator = NULL; deep_count_next_dir (state); } else { g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_LOW, state->cancellable, deep_count_more_files_callback, state); } g_list_free (files); nemo_directory_unref (directory); } static void deep_count_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { DeepCountState *state; GFileEnumerator *enumerator; NemoFile *file; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ deep_count_state_free (state); return; } file = state->directory->details->deep_count_file; enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, NULL); if (enumerator == NULL) { file->details->deep_unreadable_count += 1; deep_count_next_dir (state); } else { state->enumerator = enumerator; g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_LOW, state->cancellable, deep_count_more_files_callback, state); } } static void deep_count_load (DeepCountState *state, GFile *location) { state->deep_count_location = g_object_ref (location); #ifdef DEBUG_LOAD_DIRECTORY g_message ("load_directory called to get deep file count for %p", location); #endif g_file_enumerate_children_async (state->deep_count_location, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN "," G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP "," G_FILE_ATTRIBUTE_ID_FILESYSTEM "," G_FILE_ATTRIBUTE_UNIX_INODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, /* flags */ G_PRIORITY_LOW, /* prio */ state->cancellable, deep_count_callback, state); } static void deep_count_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->deep_count_in_progress != NULL) { file = directory->details->deep_count_file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_deep_count, REQUEST_DEEP_COUNT)) { return; } } /* The count is not wanted, so stop it. */ deep_count_cancel (directory); } } static void deep_count_got_info (GObject *source_object, GAsyncResult *res, gpointer user_data) { GFileInfo *info; const char *id; GFile *file = (GFile *)source_object; DeepCountState *state = (DeepCountState *)user_data; info = g_file_query_info_finish (file, res, NULL); if (info) { id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM); state->fs_id = g_strdup (id); g_object_unref (info); } deep_count_load (state, file); } static void deep_count_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; DeepCountState *state; if (directory->details->deep_count_in_progress != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_deep_count, REQUEST_DEEP_COUNT)) { return; } *doing_io = TRUE; if (!nemo_file_is_directory (file)) { file->details->deep_counts_status = NEMO_REQUEST_DONE; nemo_directory_async_state_changed (directory); return; } if (!async_job_start (directory, "deep count")) { return; } /* Start counting. */ file->details->deep_counts_status = NEMO_REQUEST_IN_PROGRESS; file->details->deep_directory_count = 0; file->details->deep_file_count = 0; file->details->deep_unreadable_count = 0; file->details->deep_hidden_count = 0; file->details->deep_size = 0; directory->details->deep_count_file = file; state = g_new0 (DeepCountState, 1); state->directory = directory; state->cancellable = g_cancellable_new (); state->seen_deep_count_inodes = g_array_new (FALSE, TRUE, sizeof (guint64)); directory->details->deep_count_in_progress = state; location = nemo_file_get_location (file); state->fs_id = NULL; g_file_query_info_async (location, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_PRIORITY_DEFAULT, NULL, deep_count_got_info, state); g_object_unref (location); } static void mime_list_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->mime_list_in_progress != NULL) { file = directory->details->mime_list_in_progress->mime_list_file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, should_get_mime_list, REQUEST_MIME_LIST)) { return; } } /* The count is not wanted, so stop it. */ mime_list_cancel (directory); } } static void mime_list_state_free (MimeListState *state) { if (state->enumerator) { if (!g_file_enumerator_is_closed (state->enumerator)) { g_file_enumerator_close_async (state->enumerator, 0, NULL, NULL, NULL); } g_object_unref (state->enumerator); } g_object_unref (state->cancellable); istr_set_destroy (state->mime_list_hash); nemo_directory_unref (state->directory); g_free (state); } static void mime_list_done (MimeListState *state, gboolean success) { NemoFile *file; NemoDirectory *directory; directory = state->directory; g_assert (directory != NULL); file = state->mime_list_file; file->details->mime_list_is_up_to_date = TRUE; g_list_free_full (file->details->mime_list, g_free); if (success) { file->details->mime_list_failed = TRUE; file->details->mime_list = NULL; } else { file->details->got_mime_list = TRUE; file->details->mime_list = istr_set_get_as_list (state->mime_list_hash); } directory->details->mime_list_in_progress = NULL; /* Send file-changed even if getting the item type list * failed, so interested parties can distinguish between * unknowable and not-yet-known cases. */ nemo_file_changed (file); /* Start up the next one. */ async_job_end (directory, "MIME list"); nemo_directory_async_state_changed (directory); } static void mime_list_one (MimeListState *state, GFileInfo *info) { const char *mime_type; if (should_skip_file (NULL, info)) { g_object_unref (info); return; } mime_type = g_file_info_get_content_type (info); if (mime_type != NULL) { istr_set_insert (state->mime_list_hash, mime_type); } } static void mime_list_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { MimeListState *state; NemoDirectory *directory; GError *error; GList *files, *l; GFileInfo *info; state = user_data; directory = state->directory; if (g_cancellable_is_cancelled (state->cancellable)) { /* Operation was cancelled. Bail out */ directory->details->mime_list_in_progress = NULL; async_job_end (directory, "MIME list"); nemo_directory_async_state_changed (directory); mime_list_state_free (state); return; } g_assert (directory->details->mime_list_in_progress != NULL); g_assert (directory->details->mime_list_in_progress == state); error = NULL; files = g_file_enumerator_next_files_finish (state->enumerator, res, &error); for (l = files; l != NULL; l = l->next) { info = l->data; mime_list_one (state, info); g_object_unref (info); } if (files == NULL) { mime_list_done (state, error != NULL); mime_list_state_free (state); } else { g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, mime_list_callback, state); } g_list_free (files); if (error) { g_error_free (error); } } static void list_mime_enum_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { MimeListState *state; GFileEnumerator *enumerator; NemoDirectory *directory; GError *error; state = user_data; if (g_cancellable_is_cancelled (state->cancellable)) { /* Operation was cancelled. Bail out */ directory = state->directory; directory->details->mime_list_in_progress = NULL; async_job_end (directory, "MIME list"); nemo_directory_async_state_changed (directory); mime_list_state_free (state); return; } error = NULL; enumerator = g_file_enumerate_children_finish (G_FILE (source_object), res, &error); if (enumerator == NULL) { mime_list_done (state, FALSE); g_error_free (error); mime_list_state_free (state); return; } else { state->enumerator = enumerator; g_file_enumerator_next_files_async (state->enumerator, DIRECTORY_LOAD_ITEMS_PER_CALLBACK, G_PRIORITY_DEFAULT, state->cancellable, mime_list_callback, state); } } static void mime_list_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { MimeListState *state; GFile *location; mime_list_stop (directory); if (directory->details->mime_list_in_progress != NULL) { *doing_io = TRUE; return; } /* Figure out which file to get a mime list for. */ if (!is_needy (file, should_get_mime_list, REQUEST_MIME_LIST)) { return; } *doing_io = TRUE; if (!nemo_file_is_directory (file)) { g_list_free (file->details->mime_list); file->details->mime_list_failed = FALSE; file->details->got_mime_list = FALSE; file->details->mime_list_is_up_to_date = TRUE; nemo_directory_async_state_changed (directory); return; } if (!async_job_start (directory, "MIME list")) { return; } state = g_new0 (MimeListState, 1); state->mime_list_file = file; state->directory = nemo_directory_ref (directory); state->cancellable = g_cancellable_new (); state->mime_list_hash = istr_set_new (); directory->details->mime_list_in_progress = state; location = nemo_file_get_location (file); #ifdef DEBUG_LOAD_DIRECTORY { char *uri; uri = g_file_get_uri (location); g_message ("load_directory called to get MIME list of %s", uri); g_free (uri); } #endif g_file_enumerate_children_async (location, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, /* flags */ G_PRIORITY_LOW, /* prio */ state->cancellable, list_mime_enum_callback, state); g_object_unref (location); } static void get_info_state_free (GetInfoState *state) { g_object_unref (state->cancellable); g_free (state); } static void query_info_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { NemoDirectory *directory; NemoFile *get_info_file; GFileInfo *info; GetInfoState *state; GError *error; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ get_info_state_free (state); return; } directory = nemo_directory_ref (state->directory); get_info_file = directory->details->get_info_file; g_assert (NEMO_IS_FILE (get_info_file)); directory->details->get_info_file = NULL; directory->details->get_info_in_progress = NULL; /* ref here because we might be removing the last ref when we * mark the file gone below, but we need to keep a ref at * least long enough to send the change notification. */ nemo_file_ref (get_info_file); error = NULL; info = g_file_query_info_finish (G_FILE (source_object), res, &error); if (info == NULL) { if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_FOUND) { /* mark file as gone */ nemo_file_mark_gone (get_info_file); } get_info_file->details->file_info_is_up_to_date = TRUE; nemo_file_clear_info (get_info_file); get_info_file->details->get_info_failed = TRUE; get_info_file->details->get_info_error = error; } else { nemo_file_update_info (get_info_file, info); g_object_unref (info); } nemo_file_changed (get_info_file); nemo_file_unref (get_info_file); async_job_end (directory, "file info"); nemo_directory_async_state_changed (directory); nemo_directory_unref (directory); get_info_state_free (state); } static void file_info_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->get_info_in_progress != NULL) { file = directory->details->get_info_file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_info, REQUEST_FILE_INFO)) { return; } } /* The info is not wanted, so stop it. */ file_info_cancel (directory); } } static void file_info_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; GetInfoState *state; file_info_stop (directory); if (directory->details->get_info_in_progress != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_info, REQUEST_FILE_INFO)) { return; } *doing_io = TRUE; if (!async_job_start (directory, "file info")) { return; } directory->details->get_info_file = file; file->details->get_info_failed = FALSE; if (file->details->get_info_error) { g_error_free (file->details->get_info_error); file->details->get_info_error = NULL; } state = g_new (GetInfoState, 1); state->directory = directory; state->cancellable = g_cancellable_new (); directory->details->get_info_in_progress = state; location = nemo_file_get_location (file); g_file_query_info_async (location, NEMO_FILE_DEFAULT_ATTRIBUTES, 0, G_PRIORITY_DEFAULT, state->cancellable, query_info_callback, state); g_object_unref (location); } static gboolean is_link_trusted (NemoFile *file, gboolean is_launcher) { GFile *location; gboolean res; if (!is_launcher) { return TRUE; } if (nemo_file_can_execute (file)) { return TRUE; } res = FALSE; if (nemo_file_is_local (file)) { location = nemo_file_get_location (file); res = nemo_is_in_system_dir (location); g_object_unref (location); } return res; } static void link_info_done (NemoDirectory *directory, NemoFile *file, const char *uri, const char *name, GIcon *icon, gboolean is_launcher, gboolean is_foreign) { gboolean is_trusted; file->details->link_info_is_up_to_date = TRUE; is_trusted = is_link_trusted (file, is_launcher); if (is_trusted) { nemo_file_set_display_name (file, name, name, TRUE); } else { nemo_file_set_display_name (file, NULL, NULL, TRUE); } file->details->got_link_info = TRUE; g_clear_object (&file->details->custom_icon); if (uri) { g_free (file->details->activation_uri); file->details->activation_uri = NULL; file->details->got_custom_activation_uri = TRUE; file->details->activation_uri = g_strdup (uri); } if (is_trusted && (icon != NULL)) { file->details->custom_icon = g_object_ref (icon); } file->details->is_launcher = is_launcher; file->details->is_foreign_link = is_foreign; file->details->is_trusted_link = is_trusted; nemo_directory_async_state_changed (directory); } static void link_info_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->link_info_read_state != NULL) { file = directory->details->link_info_read_state->file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_link_info, REQUEST_LINK_INFO)) { return; } } /* The link info is not wanted, so stop it. */ link_info_cancel (directory); } } static void link_info_got_data (NemoDirectory *directory, NemoFile *file, gboolean result, goffset bytes_read, char *file_contents) { char *link_uri, *uri, *name; GIcon *icon; gboolean is_launcher; gboolean is_foreign; nemo_directory_ref (directory); uri = NULL; name = NULL; icon = NULL; is_launcher = FALSE; is_foreign = FALSE; /* Handle the case where we read the Nemo link. */ if (result) { link_uri = nemo_file_get_uri (file); nemo_link_get_link_info_given_file_contents (file_contents, bytes_read, link_uri, &uri, &name, &icon, &is_launcher, &is_foreign); g_free (link_uri); } else { /* FIXME bugzilla.gnome.org 42433: We should report this error to the user. */ } nemo_file_ref (file); link_info_done (directory, file, uri, name, icon, is_launcher, is_foreign); nemo_file_changed (file); nemo_file_unref (file); g_free (uri); g_free (name); if (icon != NULL) { g_object_unref (icon); } nemo_directory_unref (directory); } static void link_info_read_state_free (LinkInfoReadState *state) { g_object_unref (state->cancellable); g_free (state); } static void link_info_nemo_link_read_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { LinkInfoReadState *state; gsize file_size; char *file_contents; gboolean result; NemoDirectory *directory; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ link_info_read_state_free (state); return; } directory = nemo_directory_ref (state->directory); result = g_file_load_contents_finish (G_FILE (source_object), res, &file_contents, &file_size, NULL, NULL); state->directory->details->link_info_read_state = NULL; async_job_end (state->directory, "link info"); link_info_got_data (state->directory, state->file, result, file_size, file_contents); if (result) { g_free (file_contents); } link_info_read_state_free (state); nemo_directory_unref (directory); } static void link_info_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; gboolean nemo_style_link; LinkInfoReadState *state; if (directory->details->link_info_read_state != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_link_info, REQUEST_LINK_INFO)) { return; } *doing_io = TRUE; /* Figure out if it is a link. */ nemo_style_link = nemo_file_is_nemo_link (file); location = nemo_file_get_location (file); /* If it's not a link we are done. If it is, we need to read it. */ if (!nemo_style_link) { link_info_done (directory, file, NULL, NULL, NULL, FALSE, FALSE); } else { if (!async_job_start (directory, "link info")) { g_object_unref (location); return; } state = g_new0 (LinkInfoReadState, 1); state->directory = directory; state->file = file; state->cancellable = g_cancellable_new (); directory->details->link_info_read_state = state; g_file_load_contents_async (location, state->cancellable, link_info_nemo_link_read_callback, state); } g_object_unref (location); } static void thumbnail_done (NemoDirectory *directory, NemoFile *file, GdkPixbuf *pixbuf, gboolean tried_original) { const char *thumb_mtime_str; time_t thumb_mtime = 0; file->details->thumbnail_is_up_to_date = TRUE; file->details->thumbnail_tried_original = tried_original; if (file->details->thumbnail) { g_object_unref (file->details->thumbnail); file->details->thumbnail = NULL; } if (file->details->scaled_thumbnail) { g_object_unref (file->details->scaled_thumbnail); file->details->scaled_thumbnail = NULL; } if (pixbuf) { if (tried_original) { thumb_mtime = file->details->mtime; } else { thumb_mtime_str = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::MTime"); if (thumb_mtime_str) { thumb_mtime = atol (thumb_mtime_str); } } if (thumb_mtime == 0 || thumb_mtime == file->details->mtime) { file->details->thumbnail = g_object_ref (pixbuf); file->details->thumbnail_mtime = thumb_mtime; file->details->thumbnail_throttle_count = 1; } else { g_free (file->details->thumbnail_path); file->details->thumbnail_path = NULL; } } nemo_directory_async_state_changed (directory); } static void thumbnail_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->thumbnail_state != NULL) { file = directory->details->thumbnail_state->file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_thumbnail, REQUEST_THUMBNAIL)) { return; } } /* The link info is not wanted, so stop it. */ thumbnail_cancel (directory); } } static void thumbnail_got_pixbuf (NemoDirectory *directory, NemoFile *file, GdkPixbuf *pixbuf, gboolean tried_original) { nemo_directory_ref (directory); nemo_file_ref (file); thumbnail_done (directory, file, pixbuf, tried_original); nemo_file_changed (file); nemo_file_unref (file); if (pixbuf) { g_object_unref (pixbuf); } nemo_directory_unref (directory); } static void thumbnail_state_free (ThumbnailState *state) { g_object_unref (state->cancellable); g_free (state); } extern int cached_thumbnail_size; /* scale very large images down to the max. size we need */ static void thumbnail_loader_size_prepared (GdkPixbufLoader *loader, int width, int height, gpointer user_data) { int max_thumbnail_size; double aspect_ratio; aspect_ratio = ((double) width) / height; /* cf. nemo_file_get_icon() */ max_thumbnail_size = NEMO_ICON_SIZE_LARGEST * cached_thumbnail_size / NEMO_ICON_SIZE_STANDARD; if (MAX (width, height) > max_thumbnail_size) { if (width > height) { width = max_thumbnail_size; height = width / aspect_ratio; } else { height = max_thumbnail_size; width = height * aspect_ratio; } gdk_pixbuf_loader_set_size (loader, width, height); } } static GdkPixbuf * get_pixbuf_for_content (goffset file_len, char *file_contents) { gboolean res; GdkPixbuf *pixbuf, *pixbuf2; GdkPixbufLoader *loader; gsize chunk_len; pixbuf = NULL; loader = gdk_pixbuf_loader_new (); g_signal_connect (loader, "size-prepared", G_CALLBACK (thumbnail_loader_size_prepared), NULL); /* For some reason we have to write in chunks, or gdk-pixbuf fails */ res = TRUE; while (res && file_len > 0) { chunk_len = file_len; res = gdk_pixbuf_loader_write (loader, (guchar *) file_contents, chunk_len, NULL); file_contents += chunk_len; file_len -= chunk_len; } if (res) { res = gdk_pixbuf_loader_close (loader, NULL); } if (res) { pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)); } g_object_unref (G_OBJECT (loader)); if (pixbuf) { pixbuf2 = gdk_pixbuf_apply_embedded_orientation (pixbuf); g_object_unref (pixbuf); pixbuf = pixbuf2; } return pixbuf; } static void thumbnail_read_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { ThumbnailState *state; gsize file_size; char *file_contents; gboolean result; NemoDirectory *directory; GdkPixbuf *pixbuf; GFile *location; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ thumbnail_state_free (state); return; } directory = nemo_directory_ref (state->directory); result = g_file_load_contents_finish (G_FILE (source_object), res, &file_contents, &file_size, NULL, NULL); pixbuf = NULL; if (result) { pixbuf = get_pixbuf_for_content (file_size, file_contents); g_free (file_contents); } if (pixbuf == NULL && state->trying_original) { state->trying_original = FALSE; location = g_file_new_for_path (state->file->details->thumbnail_path); g_file_load_contents_async (location, state->cancellable, thumbnail_read_callback, state); g_object_unref (location); } else { state->directory->details->thumbnail_state = NULL; async_job_end (state->directory, "thumbnail"); thumbnail_got_pixbuf (state->directory, state->file, pixbuf, state->tried_original); thumbnail_state_free (state); } nemo_directory_unref (directory); } static void thumbnail_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; ThumbnailState *state; if (directory->details->thumbnail_state != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_thumbnail, REQUEST_THUMBNAIL)) { return; } *doing_io = TRUE; if (!async_job_start (directory, "thumbnail")) { return; } state = g_new0 (ThumbnailState, 1); state->directory = directory; state->file = file; state->cancellable = g_cancellable_new (); if (file->details->thumbnail_wants_original) { state->tried_original = TRUE; state->trying_original = TRUE; location = nemo_file_get_location (file); } else { location = g_file_new_for_path (file->details->thumbnail_path); } directory->details->thumbnail_state = state; g_file_load_contents_async (location, state->cancellable, thumbnail_read_callback, state); g_object_unref (location); } static void mount_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->mount_state != NULL) { file = directory->details->mount_state->file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_mount, REQUEST_MOUNT)) { return; } } /* The link info is not wanted, so stop it. */ mount_cancel (directory); } } static void mount_state_free (MountState *state) { g_object_unref (state->cancellable); g_free (state); } static void got_mount (MountState *state, GMount *mount) { NemoDirectory *directory; NemoFile *file; directory = nemo_directory_ref (state->directory); state->directory->details->mount_state = NULL; async_job_end (state->directory, "mount"); file = nemo_file_ref (state->file); file->details->mount_is_up_to_date = TRUE; nemo_file_set_mount (file, mount); nemo_directory_async_state_changed (directory); nemo_file_changed (file); nemo_file_unref (file); nemo_directory_unref (directory); mount_state_free (state); } static void find_enclosing_mount_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { GMount *mount; MountState *state; GFile *location, *root; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ mount_state_free (state); return; } mount = g_file_find_enclosing_mount_finish (G_FILE (source_object), res, NULL); if (mount) { root = g_mount_get_root (mount); location = nemo_file_get_location (state->file); if (!g_file_equal (location, root)) { g_object_unref (mount); mount = NULL; } g_object_unref (root); g_object_unref (location); } got_mount (state, mount); if (mount) { g_object_unref (mount); } } static GMount * get_mount_at (GFile *target) { GVolumeMonitor *monitor; GFile *root; GList *mounts, *l; GMount *found; monitor = g_volume_monitor_get (); mounts = g_volume_monitor_get_mounts (monitor); found = NULL; for (l = mounts; l != NULL; l = l->next) { GMount *mount = G_MOUNT (l->data); if (g_mount_is_shadowed (mount)) continue; root = g_mount_get_root (mount); if (g_file_equal (target, root)) { found = g_object_ref (mount); break; } g_object_unref (root); } g_list_free_full (mounts, g_object_unref); g_object_unref (monitor); return found; } static void mount_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; MountState *state; if (directory->details->mount_state != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_mount, REQUEST_MOUNT)) { return; } *doing_io = TRUE; if (!async_job_start (directory, "mount")) { return; } state = g_new0 (MountState, 1); state->directory = directory; state->file = file; state->cancellable = g_cancellable_new (); location = nemo_file_get_location (file); directory->details->mount_state = state; if (file->details->type == G_FILE_TYPE_MOUNTABLE) { GFile *target; GMount *mount; mount = NULL; target = nemo_file_get_activation_location (file); if (target != NULL) { mount = get_mount_at (target); g_object_unref (target); } got_mount (state, mount); if (mount) { g_object_unref (mount); } } else { g_file_find_enclosing_mount_async (location, G_PRIORITY_DEFAULT, state->cancellable, find_enclosing_mount_callback, state); } g_object_unref (location); } static void filesystem_info_cancel (NemoDirectory *directory) { if (directory->details->filesystem_info_state != NULL) { g_cancellable_cancel (directory->details->filesystem_info_state->cancellable); directory->details->filesystem_info_state->directory = NULL; directory->details->filesystem_info_state = NULL; async_job_end (directory, "filesystem info"); } } static void filesystem_info_stop (NemoDirectory *directory) { NemoFile *file; if (directory->details->filesystem_info_state != NULL) { file = directory->details->filesystem_info_state->file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_filesystem_info, REQUEST_FILESYSTEM_INFO)) { return; } } /* The filesystem info is not wanted, so stop it. */ filesystem_info_cancel (directory); } } static void filesystem_info_state_free (FilesystemInfoState *state) { g_object_unref (state->cancellable); g_free (state); } static void got_filesystem_info (FilesystemInfoState *state, GFileInfo *info) { NemoDirectory *directory; NemoFile *file; /* careful here, info may be NULL */ directory = nemo_directory_ref (state->directory); state->directory->details->filesystem_info_state = NULL; async_job_end (state->directory, "filesystem info"); file = nemo_file_ref (state->file); file->details->filesystem_info_is_up_to_date = TRUE; if (info != NULL) { file->details->filesystem_use_preview = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW); file->details->filesystem_readonly = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY); } nemo_directory_async_state_changed (directory); nemo_file_changed (file); nemo_file_unref (file); nemo_directory_unref (directory); filesystem_info_state_free (state); } static void query_filesystem_info_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { GFileInfo *info; FilesystemInfoState *state; state = user_data; if (state->directory == NULL) { /* Operation was cancelled. Bail out */ filesystem_info_state_free (state); return; } info = g_file_query_filesystem_info_finish (G_FILE (source_object), res, NULL); got_filesystem_info (state, info); if (info != NULL) { g_object_unref (info); } } static void filesystem_info_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { GFile *location; FilesystemInfoState *state; if (directory->details->filesystem_info_state != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_filesystem_info, REQUEST_FILESYSTEM_INFO)) { return; } *doing_io = TRUE; if (!async_job_start (directory, "filesystem info")) { return; } state = g_new0 (FilesystemInfoState, 1); state->directory = directory; state->file = file; state->cancellable = g_cancellable_new (); location = nemo_file_get_location (file); directory->details->filesystem_info_state = state; g_file_query_filesystem_info_async (location, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY "," G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_PRIORITY_DEFAULT, state->cancellable, query_filesystem_info_callback, state); g_object_unref (location); } static void extension_info_cancel (NemoDirectory *directory) { if (directory->details->extension_info_in_progress != NULL) { if (directory->details->extension_info_idle) { g_source_remove (directory->details->extension_info_idle); } else { nemo_info_provider_cancel_update (directory->details->extension_info_provider, directory->details->extension_info_in_progress); } directory->details->extension_info_in_progress = NULL; directory->details->extension_info_file = NULL; directory->details->extension_info_provider = NULL; directory->details->extension_info_idle = 0; async_job_end (directory, "extension info"); } } static void extension_info_stop (NemoDirectory *directory) { if (directory->details->extension_info_in_progress != NULL) { NemoFile *file; file = directory->details->extension_info_file; if (file != NULL) { g_assert (NEMO_IS_FILE (file)); g_assert (file->details->directory == directory); if (is_needy (file, lacks_extension_info, REQUEST_EXTENSION_INFO)) { return; } } /* The info is not wanted, so stop it. */ extension_info_cancel (directory); nemo_directory_unref (directory); } } static void finish_info_provider (NemoDirectory *directory, NemoFile *file, NemoInfoProvider *provider) { file->details->pending_info_providers = g_list_remove (file->details->pending_info_providers, provider); g_object_unref (provider); if (file->details->pending_info_providers == NULL) { nemo_file_info_providers_done (file); } nemo_directory_unref (directory); nemo_directory_async_state_changed (directory); } static gboolean info_provider_idle_callback (gpointer user_data) { InfoProviderResponse *response; NemoDirectory *directory; response = user_data; directory = response->directory; if (response->handle != directory->details->extension_info_in_progress || response->provider != directory->details->extension_info_provider) { g_warning ("Unexpected plugin response. This probably indicates a bug in a Nemo extension: handle=%p", response->handle); } else { NemoFile *file; async_job_end (directory, "extension info"); file = directory->details->extension_info_file; directory->details->extension_info_file = NULL; directory->details->extension_info_provider = NULL; directory->details->extension_info_in_progress = NULL; directory->details->extension_info_idle = 0; finish_info_provider (directory, file, response->provider); } return FALSE; } static void info_provider_callback (NemoInfoProvider *provider, NemoOperationHandle *handle, NemoOperationResult result, gpointer user_data) { InfoProviderResponse *response; response = g_new0 (InfoProviderResponse, 1); response->provider = provider; response->handle = handle; response->result = result; response->directory = NEMO_DIRECTORY (user_data); response->directory->details->extension_info_idle = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, info_provider_idle_callback, response, g_free); } static void extension_info_start (NemoDirectory *directory, NemoFile *file, gboolean *doing_io) { NemoInfoProvider *provider; NemoOperationResult result; NemoOperationHandle *handle; GClosure *update_complete; if (directory->details->extension_info_in_progress != NULL) { *doing_io = TRUE; return; } if (!is_needy (file, lacks_extension_info, REQUEST_EXTENSION_INFO)) { return; } *doing_io = TRUE; if (!async_job_start (directory, "extension info")) { return; } provider = file->details->pending_info_providers->data; /* If the user navigates out of the current directory while this job is * running, cleanup will occur before a progress-type callback can complete, * potentially causing a segfault as directory->details->extension_info_could * be NULL during finish_info_provider. */ nemo_directory_ref (directory); update_complete = g_cclosure_new (G_CALLBACK (info_provider_callback), directory, NULL); g_closure_set_marshal (update_complete, g_cclosure_marshal_generic); result = nemo_info_provider_update_file_info (provider, NEMO_FILE_INFO (file), update_complete, &handle); g_closure_unref (update_complete); if (result == NEMO_OPERATION_COMPLETE || result == NEMO_OPERATION_FAILED) { finish_info_provider (directory, file, provider); async_job_end (directory, "extension info"); } else { directory->details->extension_info_in_progress = handle; directory->details->extension_info_provider = provider; directory->details->extension_info_file = file; } } static void start_or_stop_io (NemoDirectory *directory) { NemoFile *file; gboolean doing_io; /* Start or stop reading files. */ file_list_start_or_stop (directory); /* Stop any no longer wanted attribute fetches. */ file_info_stop (directory); directory_count_stop (directory); deep_count_stop (directory); mime_list_stop (directory); link_info_stop (directory); extension_info_stop (directory); mount_stop (directory); thumbnail_stop (directory); filesystem_info_stop (directory); doing_io = FALSE; /* Take files that are all done off the queue. */ while (!nemo_file_queue_is_empty (directory->details->high_priority_queue)) { file = nemo_file_queue_head (directory->details->high_priority_queue); /* Start getting attributes if possible */ file_info_start (directory, file, &doing_io); link_info_start (directory, file, &doing_io); if (doing_io) { return; } move_file_to_low_priority_queue (directory, file); } /* High priority queue must be empty */ while (!nemo_file_queue_is_empty (directory->details->low_priority_queue)) { file = nemo_file_queue_head (directory->details->low_priority_queue); /* Start getting attributes if possible */ mount_start (directory, file, &doing_io); directory_count_start (directory, file, &doing_io); deep_count_start (directory, file, &doing_io); mime_list_start (directory, file, &doing_io); thumbnail_start (directory, file, &doing_io); filesystem_info_start (directory, file, &doing_io); if (doing_io) { return; } move_file_to_extension_queue (directory, file); } /* Low priority queue must be empty */ while (!nemo_file_queue_is_empty (directory->details->extension_queue)) { file = nemo_file_queue_head (directory->details->extension_queue); /* Start getting attributes if possible */ extension_info_start (directory, file, &doing_io); if (doing_io) { return; } nemo_directory_remove_file_from_work_queue (directory, file); } } /* Call this when the monitor or call when ready list changes, * or when some I/O is completed. */ void nemo_directory_async_state_changed (NemoDirectory *directory) { /* Check if any callbacks are satisfied and call them if they * are. Do this last so that any changes done in start or stop * I/O functions immediately (not in callbacks) are taken into * consideration. If any callbacks are called, consider the * I/O state again so that we can release or cancel I/O that * is not longer needed once the callbacks are satisfied. */ if (directory->details->in_async_service_loop) { directory->details->state_changed = TRUE; return; } directory->details->in_async_service_loop = TRUE; nemo_directory_ref (directory); do { directory->details->state_changed = FALSE; start_or_stop_io (directory); if (call_ready_callbacks (directory)) { directory->details->state_changed = TRUE; } } while (directory->details->state_changed); directory->details->in_async_service_loop = FALSE; nemo_directory_unref (directory); /* Check if any directories should wake up. */ async_job_wake_up (); } void nemo_directory_cancel (NemoDirectory *directory) { /* Arbitrary order (kept alphabetical). */ deep_count_cancel (directory); directory_count_cancel (directory); file_info_cancel (directory); file_list_cancel (directory); link_info_cancel (directory); mime_list_cancel (directory); new_files_cancel (directory); extension_info_cancel (directory); thumbnail_cancel (directory); mount_cancel (directory); filesystem_info_cancel (directory); /* We aren't waiting for anything any more. */ if (waiting_directories != NULL) { g_hash_table_remove (waiting_directories, directory); } /* Check if any directories should wake up. */ async_job_wake_up (); } static void cancel_directory_count_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->count_in_progress != NULL && directory->details->count_in_progress->count_file == file) { directory_count_cancel (directory); } } static void cancel_deep_counts_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->deep_count_file == file) { deep_count_cancel (directory); } } static void cancel_mime_list_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->mime_list_in_progress != NULL && directory->details->mime_list_in_progress->mime_list_file == file) { mime_list_cancel (directory); } } static void cancel_file_info_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->get_info_file == file) { file_info_cancel (directory); } } static void cancel_thumbnail_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->thumbnail_state != NULL && directory->details->thumbnail_state->file == file) { thumbnail_cancel (directory); } } static void cancel_mount_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->mount_state != NULL && directory->details->mount_state->file == file) { mount_cancel (directory); } } static void cancel_filesystem_info_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->filesystem_info_state != NULL && directory->details->filesystem_info_state->file == file) { filesystem_info_cancel (directory); } } static void cancel_link_info_for_file (NemoDirectory *directory, NemoFile *file) { if (directory->details->link_info_read_state != NULL && directory->details->link_info_read_state->file == file) { link_info_cancel (directory); } } static void cancel_loading_attributes (NemoDirectory *directory, NemoFileAttributes file_attributes) { Request request; request = nemo_directory_set_up_request (file_attributes); if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)) { directory_count_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)) { deep_count_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)) { mime_list_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)) { file_info_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_FILESYSTEM_INFO)) { filesystem_info_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)) { link_info_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)) { extension_info_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)) { thumbnail_cancel (directory); } if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) { mount_cancel (directory); } nemo_directory_async_state_changed (directory); } void nemo_directory_cancel_loading_file_attributes (NemoDirectory *directory, NemoFile *file, NemoFileAttributes file_attributes) { Request request; nemo_directory_remove_file_from_work_queue (directory, file); request = nemo_directory_set_up_request (file_attributes); if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)) { cancel_directory_count_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)) { cancel_deep_counts_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)) { cancel_mime_list_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)) { cancel_file_info_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_FILESYSTEM_INFO)) { cancel_filesystem_info_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)) { cancel_link_info_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)) { cancel_thumbnail_for_file (directory, file); } if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) { cancel_mount_for_file (directory, file); } nemo_directory_async_state_changed (directory); } void nemo_directory_add_file_to_work_queue (NemoDirectory *directory, NemoFile *file) { g_return_if_fail (file->details->directory == directory); nemo_file_queue_enqueue (directory->details->high_priority_queue, file); } static void add_all_files_to_work_queue (NemoDirectory *directory) { GList *node; NemoFile *file; for (node = directory->details->file_list; node != NULL; node = node->next) { file = NEMO_FILE (node->data); nemo_directory_add_file_to_work_queue (directory, file); } } void nemo_directory_remove_file_from_work_queue (NemoDirectory *directory, NemoFile *file) { nemo_file_queue_remove (directory->details->high_priority_queue, file); nemo_file_queue_remove (directory->details->low_priority_queue, file); nemo_file_queue_remove (directory->details->extension_queue, file); } static void move_file_to_low_priority_queue (NemoDirectory *directory, NemoFile *file) { /* Must add before removing to avoid ref underflow */ nemo_file_queue_enqueue (directory->details->low_priority_queue, file); nemo_file_queue_remove (directory->details->high_priority_queue, file); } static void move_file_to_extension_queue (NemoDirectory *directory, NemoFile *file) { /* Must add before removing to avoid ref underflow */ nemo_file_queue_enqueue (directory->details->extension_queue, file); nemo_file_queue_remove (directory->details->low_priority_queue, file); } nemo-3.6.5/libnemo-private/nemo-icon-dnd.c0000664000175000017500000017453713215733314017322 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-icon-dnd.c - Drag & drop handling for the icon container widget. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ettore Perazzoli , Darin Adler , Andy Hertzfeld Pavel Cisler XDS support: Benedikt Meurer (adapted by Amos Brocco ) */ #include #include #include "nemo-icon-dnd.h" #include "nemo-file-dnd.h" #include "nemo-icon-private.h" #include "libnemo-private/nemo-icon.h" #include "nemo-link.h" #include "nemo-metadata.h" #include "nemo-selection-canvas-item.h" #include "nemo-desktop-utils.h" #include "nemo-global-preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEBUG_FLAG NEMO_DEBUG_ICON_CONTAINER #include "nemo-debug.h" static const GtkTargetEntry drag_types [] = { { NEMO_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NEMO_ICON_DND_GNOME_ICON_LIST }, { NEMO_ICON_DND_URI_LIST_TYPE, 0, NEMO_ICON_DND_URI_LIST }, }; static const GtkTargetEntry drop_types [] = { { NEMO_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NEMO_ICON_DND_GNOME_ICON_LIST }, /* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */ { NEMO_ICON_DND_NETSCAPE_URL_TYPE, 0, NEMO_ICON_DND_NETSCAPE_URL }, { NEMO_ICON_DND_URI_LIST_TYPE, 0, NEMO_ICON_DND_URI_LIST }, { NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NEMO_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */ { NEMO_ICON_DND_RAW_TYPE, 0, NEMO_ICON_DND_RAW }, /* Must be last: */ { NEMO_ICON_DND_ROOTWINDOW_DROP_TYPE, 0, NEMO_ICON_DND_ROOTWINDOW_DROP } }; static void stop_dnd_highlight (GtkWidget *widget); static void dnd_highlight_queue_redraw (GtkWidget *widget); static GtkTargetList *drop_types_list = NULL; static GtkTargetList *drop_types_list_root = NULL; static char * nemo_icon_container_find_drop_target (NemoIconContainer *container, GdkDragContext *context, int x, int y, gboolean *icon_hit, gboolean rewrite_desktop); static void initialize_dnd_grid (NemoIconContainer *container) { GList *selection, *p; if (container->details->dnd_grid != NULL) { nemo_centered_placement_grid_free (container->details->dnd_grid); } container->details->dnd_grid = nemo_centered_placement_grid_new (container, container->details->horizontal); nemo_centered_placement_grid_pre_populate (container->details->dnd_grid, container->details->icons, FALSE); selection = nemo_icon_container_get_selection (container); for (p = selection; p != NULL; p = p->next) { NemoFile *file; NemoIcon *icon; gchar *uri; file = p->data; uri = nemo_file_get_uri (file); icon = nemo_icon_container_get_icon_by_uri (container, uri); if (icon != NULL) { nemo_centered_placement_grid_unmark_icon (container->details->dnd_grid, icon); } g_free (uri); } if (!container->details->auto_layout && container->details->keep_aligned) { container->details->insert_dnd_mode = TRUE; } g_list_free (selection); gtk_widget_queue_draw (GTK_WIDGET (container)); } static void free_dnd_grid (NemoIconContainer *container) { g_clear_pointer (&container->details->dnd_grid, nemo_centered_placement_grid_free); container->details->insert_dnd_mode = FALSE; gtk_widget_queue_draw (GTK_WIDGET (container)); } static EelCanvasItem * create_selection_shadow (NemoIconContainer *container, GList *list) { EelCanvasGroup *group; EelCanvas *canvas; int max_x, max_y; int min_x, min_y; GList *p; GtkAllocation allocation; if (list == NULL) { return NULL; } /* if we're only dragging a single item, don't worry about the shadow */ if (list->next == NULL) { return NULL; } canvas = EEL_CANVAS (container); gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); /* Creating a big set of rectangles in the canvas can be expensive, so we try to be smart and only create the maximum number of rectangles that we will need, in the vertical/horizontal directions. */ max_x = allocation.width; min_x = -max_x; max_y = allocation.height; min_y = -max_y; /* Create a group, so that it's easier to move all the items around at once. */ group = EEL_CANVAS_GROUP (eel_canvas_item_new (EEL_CANVAS_GROUP (canvas->root), eel_canvas_group_get_type (), NULL)); for (p = list; p != NULL; p = p->next) { NemoDragSelectionItem *item; int x1, y1, x2, y2; GdkRGBA black = { 0, 0, 0, 1 }; item = p->data; if (!item->got_icon_position) { continue; } x1 = item->icon_x; y1 = item->icon_y; x2 = x1 + item->icon_width; y2 = y1 + item->icon_height; if (x2 >= min_x && x1 <= max_x && y2 >= min_y && y1 <= max_y) eel_canvas_item_new (group, NEMO_TYPE_SELECTION_CANVAS_ITEM, "x1", (double) x1, "y1", (double) y1, "x2", (double) x2, "y2", (double) y2, "outline-color-rgba", &black, "outline-stippling", TRUE, "width_pixels", 1, NULL); } return EEL_CANVAS_ITEM (group); } /* Set the affine instead of the x and y position. * Simple, and setting x and y was broken at one point. */ static void set_shadow_position (EelCanvasItem *shadow, double x, double y) { eel_canvas_item_set (shadow, "x", x, "y", y, NULL); } /* Source-side handling of the drag. */ /* iteration glue struct */ typedef struct { gpointer iterator_context; NemoDragEachSelectedItemDataGet iteratee; gpointer iteratee_data; } IconGetDataBinderContext; static void canvas_rect_world_to_widget (EelCanvas *canvas, EelDRect *world_rect, EelIRect *widget_rect) { EelDRect window_rect; GtkAdjustment *hadj, *vadj; hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)); eel_canvas_world_to_window (canvas, world_rect->x0, world_rect->y0, &window_rect.x0, &window_rect.y0); eel_canvas_world_to_window (canvas, world_rect->x1, world_rect->y1, &window_rect.x1, &window_rect.y1); widget_rect->x0 = (int) window_rect.x0 - gtk_adjustment_get_value (hadj); widget_rect->y0 = (int) window_rect.y0 - gtk_adjustment_get_value (vadj); widget_rect->x1 = (int) window_rect.x1 - gtk_adjustment_get_value (hadj); widget_rect->y1 = (int) window_rect.y1 - gtk_adjustment_get_value (vadj); } static void canvas_widget_to_world (EelCanvas *canvas, double widget_x, double widget_y, double *world_x, double *world_y) { eel_canvas_window_to_world (canvas, widget_x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))), widget_y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))), world_x, world_y); } static gboolean icon_get_data_binder (NemoIcon *icon, gpointer data) { IconGetDataBinderContext *context; EelDRect world_rect; EelIRect widget_rect; char *uri; NemoIconContainer *container; context = (IconGetDataBinderContext *)data; g_assert (NEMO_IS_ICON_CONTAINER (context->iterator_context)); container = NEMO_ICON_CONTAINER (context->iterator_context); world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item); canvas_rect_world_to_widget (EEL_CANVAS (container), &world_rect, &widget_rect); uri = nemo_icon_container_get_icon_uri (container, icon); if (uri == NULL) { g_warning ("no URI for one of the iterated icons"); return TRUE; } widget_rect = eel_irect_offset_by (widget_rect, - container->details->dnd_info->drag_info.start_x, - container->details->dnd_info->drag_info.start_y); widget_rect = eel_irect_scale_by (widget_rect, 1 / EEL_CANVAS (container)->pixels_per_unit); /* pass the uri, mouse-relative x/y and icon width/height */ context->iteratee (uri, (int) widget_rect.x0, (int) widget_rect.y0, widget_rect.x1 - widget_rect.x0, widget_rect.y1 - widget_rect.y0, context->iteratee_data); g_free (uri); return TRUE; } /* Iterate over each selected icon in a NemoIconContainer, * calling each_function on each. */ static void nemo_icon_container_each_selected_icon (NemoIconContainer *container, gboolean (*each_function) (NemoIcon *, gpointer), gpointer data) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (!icon->is_selected) { continue; } if (!each_function (icon, data)) { return; } } } /* Adaptor function used with nemo_icon_container_each_selected_icon * to help iterate over all selected items, passing uris, x, y, w and h * values to the iteratee */ static void each_icon_get_data_binder (NemoDragEachSelectedItemDataGet iteratee, gpointer iterator_context, gpointer data) { IconGetDataBinderContext context; NemoIconContainer *container; g_assert (NEMO_IS_ICON_CONTAINER (iterator_context)); container = NEMO_ICON_CONTAINER (iterator_context); context.iterator_context = iterator_context; context.iteratee = iteratee; context.iteratee_data = data; nemo_icon_container_each_selected_icon (container, icon_get_data_binder, &context); } /* Called when the data for drag&drop is needed */ static void drag_data_get_callback (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint32 time, gpointer data) { g_assert (widget != NULL); g_assert (NEMO_IS_ICON_CONTAINER (widget)); g_return_if_fail (context != NULL); /* Call common function from nemo-drag that set's up * the selection data in the right format. Pass it means to * iterate all the selected icons. */ nemo_drag_drag_data_get (widget, context, selection_data, info, time, widget, each_icon_get_data_binder); } /* Target-side handling of the drag. */ static void nemo_icon_container_position_shadow (NemoIconContainer *container, int x, int y) { EelCanvasItem *shadow; double world_x, world_y; shadow = container->details->dnd_info->shadow; if (shadow == NULL) { return; } canvas_widget_to_world (EEL_CANVAS (container), x, y, &world_x, &world_y); set_shadow_position (shadow, world_x, world_y); eel_canvas_item_show (shadow); } static void nemo_icon_container_dropped_icon_feedback (GtkWidget *widget, GtkSelectionData *data, int x, int y) { NemoIconContainer *container; NemoIconDndInfo *dnd_info; container = NEMO_ICON_CONTAINER (widget); dnd_info = container->details->dnd_info; /* Delete old selection list. */ nemo_drag_destroy_selection_list (dnd_info->drag_info.selection_list); dnd_info->drag_info.selection_list = NULL; /* Delete old shadow if any. */ if (dnd_info->shadow != NULL) { /* FIXME bugzilla.gnome.org 42484: * Is a destroy really sufficient here? Who does the unref? */ eel_canvas_item_destroy (dnd_info->shadow); } /* Build the selection list and the shadow. */ dnd_info->drag_info.selection_list = nemo_drag_build_selection_list (data); dnd_info->shadow = create_selection_shadow (container, dnd_info->drag_info.selection_list); nemo_icon_container_position_shadow (container, x, y); } static char * get_direct_save_filename (GdkDragContext *context) { guchar *prop_text; gint prop_len; if (!gdk_property_get (gdk_drag_context_get_source_window (context), gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE), gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL, &prop_len, &prop_text)) { return NULL; } /* Zero-terminate the string */ prop_text = g_realloc (prop_text, prop_len + 1); prop_text[prop_len] = '\0'; /* Verify that the file name provided by the source is valid */ if (*prop_text == '\0' || strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) != NULL) { DEBUG ("Invalid filename provided by XDS drag site"); g_free (prop_text); return NULL; } return (gchar *) prop_text; } static void set_direct_save_uri (GtkWidget *widget, GdkDragContext *context, NemoDragInfo *drag_info, int x, int y) { GFile *base, *child; char *filename, *drop_target; gchar *uri; drag_info->got_drop_data_type = TRUE; drag_info->data_type = NEMO_ICON_DND_XDNDDIRECTSAVE; uri = NULL; filename = get_direct_save_filename (context); drop_target = nemo_icon_container_find_drop_target (NEMO_ICON_CONTAINER (widget), context, x, y, NULL, TRUE); if (drop_target && eel_uri_is_trash (drop_target)) { g_free (drop_target); drop_target = NULL; /* Cannot save to trash ...*/ } if (filename != NULL && drop_target != NULL) { /* Resolve relative path */ base = g_file_new_for_uri (drop_target); child = g_file_get_child (base, filename); uri = g_file_get_uri (child); g_object_unref (base); g_object_unref (child); /* Change the uri property */ gdk_property_change (gdk_drag_context_get_source_window (context), gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE), gdk_atom_intern ("text/plain", FALSE), 8, GDK_PROP_MODE_REPLACE, (const guchar *) uri, strlen (uri)); drag_info->direct_save_uri = uri; } g_free (filename); g_free (drop_target); } /* FIXME bugzilla.gnome.org 47445: Needs to become a shared function */ static void get_data_on_first_target_we_support (GtkWidget *widget, GdkDragContext *context, guint32 time, int x, int y) { GtkTargetList *list; GdkAtom target; if (drop_types_list == NULL) { drop_types_list = gtk_target_list_new (drop_types, G_N_ELEMENTS (drop_types) - 1); gtk_target_list_add_text_targets (drop_types_list, NEMO_ICON_DND_TEXT); } if (drop_types_list_root == NULL) { drop_types_list_root = gtk_target_list_new (drop_types, G_N_ELEMENTS (drop_types)); gtk_target_list_add_text_targets (drop_types_list_root, NEMO_ICON_DND_TEXT); } if (nemo_icon_container_get_is_desktop (NEMO_ICON_CONTAINER (widget))) { list = drop_types_list_root; } else { list = drop_types_list; } target = gtk_drag_dest_find_target (widget, context, list); if (target != GDK_NONE) { guint info; NemoDragInfo *drag_info; gboolean found; drag_info = &(NEMO_ICON_CONTAINER (widget)->details->dnd_info->drag_info); found = gtk_target_list_find (list, target, &info); g_assert (found); /* Don't get_data for destructive ops */ if ((info == NEMO_ICON_DND_ROOTWINDOW_DROP || info == NEMO_ICON_DND_XDNDDIRECTSAVE) && !drag_info->drop_occured) { /* We can't call get_data here, because that would make the source execute the rootwin action or the direct save */ drag_info->got_drop_data_type = TRUE; drag_info->data_type = info; } else { if (info == NEMO_ICON_DND_XDNDDIRECTSAVE) { set_direct_save_uri (widget, context, drag_info, x, y); } gtk_drag_get_data (GTK_WIDGET (widget), context, target, time); } } } static void nemo_icon_container_ensure_drag_data (NemoIconContainer *container, GdkDragContext *context, guint32 time) { NemoIconDndInfo *dnd_info; dnd_info = container->details->dnd_info; if (!dnd_info->drag_info.got_drop_data_type) { get_data_on_first_target_we_support (GTK_WIDGET (container), context, time, 0, 0); } } static void drag_end_callback (GtkWidget *widget, GdkDragContext *context, gpointer data) { NemoIconContainer *container; NemoIconDndInfo *dnd_info; container = NEMO_ICON_CONTAINER (widget); free_dnd_grid (container); dnd_info = container->details->dnd_info; nemo_drag_destroy_selection_list (dnd_info->drag_info.selection_list); dnd_info->drag_info.selection_list = NULL; g_clear_pointer (&dnd_info->drag_info.source_fs, g_free); } static NemoIcon * nemo_icon_container_item_at (NemoIconContainer *container, int x, int y) { GList *p; int size; EelDRect point; EelIRect canvas_point; /* build the hit-test rectangle. Base the size on the scale factor to ensure that it is * non-empty even at the smallest scale factor */ size = MAX (1, 1 + (1 / EEL_CANVAS (container)->pixels_per_unit)); point.x0 = x; point.y0 = y; point.x1 = x + size; point.y1 = y + size; for (p = container->details->icons; p != NULL; p = p->next) { NemoIcon *icon; icon = p->data; eel_canvas_w2c (EEL_CANVAS (container), point.x0, point.y0, &canvas_point.x0, &canvas_point.y0); eel_canvas_w2c (EEL_CANVAS (container), point.x1, point.y1, &canvas_point.x1, &canvas_point.y1); if (nemo_icon_canvas_item_hit_test_rectangle (icon->item, canvas_point)) { return icon; } } return NULL; } static char * get_container_uri (NemoIconContainer *container) { char *uri; /* get the URI associated with the container */ uri = NULL; g_signal_emit_by_name (container, "get_container_uri", &uri); return uri; } static gboolean nemo_icon_container_selection_items_local (NemoIconContainer *container, GList *items) { char *container_uri_string; gboolean result; /* must have at least one item */ g_assert (items); /* get the URI associated with the container */ container_uri_string = get_container_uri (container); if (eel_uri_is_desktop (container_uri_string)) { result = nemo_drag_items_on_desktop (items); } else { result = nemo_drag_items_local (container_uri_string, items); } g_free (container_uri_string); return result; } /* handle dropped url */ static void receive_dropped_netscape_url (NemoIconContainer *container, const char *encoded_url, GdkDragContext *context, int x, int y) { char *drop_target; if (encoded_url == NULL) { return; } drop_target = nemo_icon_container_find_drop_target (container, context, x, y, NULL, TRUE); g_signal_emit_by_name (container, "handle_netscape_url", encoded_url, drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } /* handle dropped uri list */ static void receive_dropped_uri_list (NemoIconContainer *container, const char *uri_list, GdkDragContext *context, int x, int y) { char *drop_target; if (uri_list == NULL) { return; } drop_target = nemo_icon_container_find_drop_target (container, context, x, y, NULL, TRUE); g_signal_emit_by_name (container, "handle_uri_list", uri_list, drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } /* handle dropped text */ static void receive_dropped_text (NemoIconContainer *container, const char *text, GdkDragContext *context, int x, int y) { char *drop_target; if (text == NULL) { return; } drop_target = nemo_icon_container_find_drop_target (container, context, x, y, NULL, TRUE); g_signal_emit_by_name (container, "handle_text", text, drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } /* handle dropped raw data */ static void receive_dropped_raw (NemoIconContainer *container, const char *raw_data, int length, const char *direct_save_uri, GdkDragContext *context, int x, int y) { char *drop_target; if (raw_data == NULL) { return; } drop_target = nemo_icon_container_find_drop_target (container, context, x, y, NULL, TRUE); g_signal_emit_by_name (container, "handle_raw", raw_data, length, drop_target, direct_save_uri, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } static int auto_scroll_timeout_callback (gpointer data) { NemoIconContainer *container; GtkWidget *widget; float x_scroll_delta, y_scroll_delta; GdkRectangle exposed_area; GtkAllocation allocation; g_assert (NEMO_IS_ICON_CONTAINER (data)); widget = GTK_WIDGET (data); container = NEMO_ICON_CONTAINER (widget); if (container->details->dnd_info->drag_info.waiting_to_autoscroll && container->details->dnd_info->drag_info.start_auto_scroll_in > g_get_monotonic_time ()) { /* not yet */ return TRUE; } container->details->dnd_info->drag_info.waiting_to_autoscroll = FALSE; nemo_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta); if (x_scroll_delta == 0 && y_scroll_delta == 0) { /* no work */ return TRUE; } /* Clear the old dnd highlight frame */ dnd_highlight_queue_redraw (widget); if (!nemo_icon_container_scroll (container, (int)x_scroll_delta, (int)y_scroll_delta)) { /* the scroll value got pinned to a min or max adjustment value, * we ended up not scrolling */ return TRUE; } /* Make sure the dnd highlight frame is redrawn */ dnd_highlight_queue_redraw (widget); /* update cached drag start offsets */ container->details->dnd_info->drag_info.start_x -= x_scroll_delta; container->details->dnd_info->drag_info.start_y -= y_scroll_delta; /* Due to a glitch in GtkLayout, whe need to do an explicit draw of the exposed * area. * Calculate the size of the area we need to draw */ gtk_widget_get_allocation (widget, &allocation); exposed_area.x = allocation.x; exposed_area.y = allocation.y; exposed_area.width = allocation.width; exposed_area.height = allocation.height; if (x_scroll_delta > 0) { exposed_area.x = exposed_area.width - x_scroll_delta; } else if (x_scroll_delta < 0) { exposed_area.width = -x_scroll_delta; } if (y_scroll_delta > 0) { exposed_area.y = exposed_area.height - y_scroll_delta; } else if (y_scroll_delta < 0) { exposed_area.height = -y_scroll_delta; } /* offset it to 0, 0 */ exposed_area.x -= allocation.x; exposed_area.y -= allocation.y; gtk_widget_queue_draw_area (widget, exposed_area.x, exposed_area.y, exposed_area.width, exposed_area.height); return TRUE; } static void set_up_auto_scroll_if_needed (NemoIconContainer *container) { nemo_drag_autoscroll_start (&container->details->dnd_info->drag_info, GTK_WIDGET (container), auto_scroll_timeout_callback, container); } static void stop_auto_scroll (NemoIconContainer *container) { nemo_drag_autoscroll_stop (&container->details->dnd_info->drag_info); } static NemoIcon * get_icon_from_drag_info (NemoIconContainer *container, NemoDragSelectionItem *item, time_t now, gint monitor) { NemoIcon *icon; NemoFile *file; icon = nemo_icon_container_get_icon_by_uri (container, item->uri); if (icon == NULL) { /* probably dragged from another monitor or screen. Add it to * this screen */ file = nemo_file_get_by_uri (item->uri); nemo_file_set_time_metadata (file, NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP, now); nemo_file_set_is_desktop_orphan (file, FALSE); nemo_file_set_monitor_number (file, monitor); nemo_icon_container_add (container, NEMO_ICON_CONTAINER_ICON_DATA (file)); icon = nemo_icon_container_get_icon_by_uri (container, item->uri); } return icon; } static void handle_local_move (NemoIconContainer *container, double world_x, double world_y) { GList *moved_icons, *p; NemoDragSelectionItem *item; NemoIcon *icon; NemoFile *file = NULL; gint monitor; time_t now; if (container->details->auto_layout) { return; } monitor = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (container)); time (&now); /* Move and select the icons. */ moved_icons = NULL; for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { item = p->data; icon = nemo_icon_container_get_icon_by_uri (container, item->uri); icon = get_icon_from_drag_info (container, item, now, monitor); file = NEMO_FILE (icon->data); nemo_file_set_is_desktop_orphan (file, FALSE); if (item->got_icon_position) { nemo_icon_container_move_icon (container, icon, world_x + item->icon_x, world_y + item->icon_y, icon->scale, TRUE, TRUE, TRUE); } moved_icons = g_list_prepend (moved_icons, icon); } nemo_icon_container_select_list_unselect_others (container, moved_icons); /* Might have been moved in a way that requires adjusting scroll region. */ nemo_icon_container_update_scroll_region (container); g_list_free (moved_icons); } static void handle_local_grid_container_move (NemoIconContainer *container, double world_x, double world_y) { GList *moved_icons, *p; NemoDragSelectionItem *item; NemoIcon *icon; NemoFile *file; gint monitor; gint drop_x, drop_y; time_t now; if (container->details->auto_layout) { if (nemo_icon_container_get_is_desktop (container)) { item = container->details->dnd_info->drag_info.selection_list->data; if (nemo_icon_container_get_icon_by_uri (container, item->uri)) { return; } } else { return; } } drop_x = (gint)(world_x + 0.5); drop_y = (gint)(world_y + 0.5); monitor = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (container)); time (&now); /* Now move and select the icons of the original drag selection */ moved_icons = NULL; for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { item = p->data; icon = get_icon_from_drag_info (container, item, now, monitor); file = NEMO_FILE (icon->data); nemo_file_set_is_desktop_orphan (file, FALSE); nemo_icon_container_move_icon (container, icon, item->icon_x + drop_x, item->icon_y + drop_y, icon->scale, TRUE, TRUE, TRUE); moved_icons = g_list_prepend (moved_icons, icon); } nemo_icon_container_select_list_unselect_others (container, moved_icons); g_list_free (moved_icons); } static void handle_nonlocal_move (NemoIconContainer *container, GdkDragAction action, int x, int y, const char *target_uri, gboolean icon_hit) { GList *source_uris, *p; GArray *source_item_locations; gboolean free_target_uri, is_rtl; int index, item_x; GtkAllocation allocation; if (container->details->dnd_info->drag_info.selection_list == NULL) { return; } source_uris = NULL; for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { /* do a shallow copy of all the uri strings of the copied files */ source_uris = g_list_prepend (source_uris, ((NemoDragSelectionItem *)p->data)->uri); } source_uris = g_list_reverse (source_uris); is_rtl = nemo_icon_container_is_layout_rtl (container); source_item_locations = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); if (!icon_hit) { /* Drop onto a container. Pass along the item points to allow placing * the items in their same relative positions in the new container. */ source_item_locations = g_array_set_size (source_item_locations, g_list_length (container->details->dnd_info->drag_info.selection_list)); for (index = 0, p = container->details->dnd_info->drag_info.selection_list; p != NULL; index++, p = p->next) { item_x = ((NemoDragSelectionItem *)p->data)->icon_x; if (is_rtl) item_x = -item_x - ((NemoDragSelectionItem *)p->data)->icon_width; g_array_index (source_item_locations, GdkPoint, index).x = item_x; g_array_index (source_item_locations, GdkPoint, index).y = ((NemoDragSelectionItem *)p->data)->icon_y; } } free_target_uri = FALSE; /* Rewrite internal desktop URIs to the normal target uri */ if (eel_uri_is_desktop (target_uri)) { target_uri = nemo_get_desktop_directory_uri (); free_target_uri = TRUE; } if (is_rtl) { gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); x = nemo_icon_container_get_canvas_width (container, allocation) - x; } /* start the copy */ g_signal_emit_by_name (container, "move_copy_items", source_uris, source_item_locations, target_uri, action, x, y); if (free_target_uri) { g_free ((char *)target_uri); } g_list_free (source_uris); g_array_free (source_item_locations, TRUE); } static char * nemo_icon_container_find_drop_target (NemoIconContainer *container, GdkDragContext *context, int x, int y, gboolean *icon_hit, gboolean rewrite_desktop) { NemoIcon *drop_target_icon; double world_x, world_y; NemoFile *file; char *icon_uri; char *container_uri; if (icon_hit) { *icon_hit = FALSE; } if (!container->details->dnd_info->drag_info.got_drop_data_type) { return NULL; } canvas_widget_to_world (EEL_CANVAS (container), x, y, &world_x, &world_y); /* FIXME bugzilla.gnome.org 42485: * These "can_accept_items" tests need to be done by * the icon view, not here. This file is not supposed to know * that the target is a file. */ /* Find the item we hit with our drop, if any */ drop_target_icon = nemo_icon_container_item_at (container, world_x, world_y); if (drop_target_icon != NULL) { icon_uri = nemo_icon_container_get_icon_uri (container, drop_target_icon); if (icon_uri != NULL) { file = nemo_file_get_by_uri (icon_uri); if (!nemo_drag_can_accept_info (file, container->details->dnd_info->drag_info.data_type, container->details->dnd_info->drag_info.selection_list)) { /* the item we dropped our selection on cannot accept the items, * do the same thing as if we just dropped the items on the canvas */ drop_target_icon = NULL; } g_free (icon_uri); nemo_file_unref (file); } } if (drop_target_icon == NULL) { if (icon_hit) { *icon_hit = FALSE; } container_uri = get_container_uri (container); if (rewrite_desktop && container_uri != NULL && eel_uri_is_desktop (container_uri)) { g_free (container_uri); container_uri = nemo_get_desktop_directory_uri (); } return container_uri; } if (icon_hit) { *icon_hit = TRUE; } return nemo_icon_container_get_icon_drop_target_uri (container, drop_target_icon); } static void prep_selection (NemoIconContainer *container, double world_x, double world_y) { NemoCenteredPlacementGrid *grid; gint drop_x, drop_y; GList *p, *push_list; GdkRectangle drop_rect, iter_rect; NemoDragSelectionItem *item; NemoIcon *icon; NemoFile *file; gint monitor; time_t now; gboolean drop_position_free; gboolean iter_is_free; if (!NEMO_ICON_CONTAINER_GET_CLASS (container)->is_grid_container) { return; } drop_x = (gint)(world_x + 0.5); drop_y = (gint)(world_y + 0.5); monitor = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (container)); time (&now); /* For keep-aligned mode, we need to determine: * * - If our 'drop point' is in a grid position currently occupied by another icon * (one not in the selection list itself,) then we're in 'insert_dnd_mode' - which means, * we'll push existing icons in 'front' of our drop point (according to our grid * direction) to make room to place our selection list in order from that point. * * - If we're not in insert_dnd_mode, we check if the apparent drop positions of each * icon are empty - if they are, we just drop the icons where their DnD clone was * when we ended the drag. If they aren't empty, we apply our grid functions to * find an available spot for the ones that don't fit */ grid = container->details->dnd_grid; nemo_centered_placement_grid_get_current_position_rect (grid, drop_x, drop_y, &drop_rect, &drop_position_free); if (container->details->keep_aligned) { if (drop_position_free) { /* Not insert mode, but with keep_aligned active, try to drop icons in their * new relative spots, or, failing that, lay down the positions in some valid * position */ GList *unplaced_list, *placed_list; unplaced_list = placed_list = NULL; for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { item = p->data; /* Clear the grid of any items in the selection list as we go * this may be null if this is a non-local move, which is fine - the * icon won't be there anyhow. */ icon = nemo_icon_container_get_icon_by_uri (grid->container, item->uri); if (icon != NULL) { nemo_centered_placement_grid_unmark_icon (grid, icon); } if (item->got_icon_position) { nemo_centered_placement_grid_get_current_position_rect (grid, drop_x + item->icon_x + item->icon_width / 2, drop_y + item->icon_y + item->icon_height / 2, &iter_rect, &iter_is_free); if (!iter_is_free) { item->got_icon_position = FALSE; unplaced_list = g_list_prepend (unplaced_list, item); } else { nemo_centered_placement_grid_nominal_to_icon_position (grid, icon, /* may be null - it's ok */ iter_rect.x - drop_x, iter_rect.y - drop_y, &item->icon_x, &item->icon_y); nemo_centered_placement_grid_mark_position (grid, iter_rect.x, iter_rect.y); placed_list = g_list_prepend (placed_list, item); } } else { unplaced_list = g_list_prepend (unplaced_list, item); } } /* Start searching for free spots beyond our drop point * and reposition the unplaced icons by our rules */ iter_rect.x = drop_rect.x; iter_rect.y = drop_rect.y; unplaced_list = g_list_reverse (unplaced_list); for (p = unplaced_list; p != NULL; p = p->next) { item = p->data; icon = nemo_icon_container_get_icon_by_uri (container, item->uri); nemo_centered_placement_grid_get_next_position_rect (grid, &iter_rect, &iter_rect, &iter_is_free); if (iter_is_free) { item->icon_x = iter_rect.x; item->icon_y = iter_rect.y; } else { while (!iter_is_free) { nemo_centered_placement_grid_get_next_position_rect (grid, &iter_rect, &iter_rect, &iter_is_free); } item->icon_x = iter_rect.x; item->icon_y = iter_rect.y; } nemo_centered_placement_grid_nominal_to_icon_position (grid, icon, iter_rect.x - drop_x, iter_rect.y - drop_y, &item->icon_x, &item->icon_y); nemo_centered_placement_grid_mark_position (grid, iter_rect.x, iter_rect.y); } } else { /* If we're inserting items, we need to also shift icons over that are in our way. * To do this, let's append icons that are subsequent to the drop point until we've * got a contiguous space long enough to hold our original selection *plus* the icons * we've picked up to accomodate them */ push_list = NULL; push_list = nemo_centered_placement_grid_clear_grid_for_selection (grid, drop_x, drop_y, container->details->dnd_info->drag_info.selection_list); /* Move the extra icons that were needed to accomodate the selection, * but don't add them to moved_icons - we don't want them highlighted * when we're done * * The push list has already been adjusted for grid<->nominal, etc.. so * we just move them here. */ for (p = push_list; p != NULL; p = p->next) { item = p->data; /* This icon should exist always */ icon = get_icon_from_drag_info (container, item, now, monitor); if (icon != NULL) { file = NEMO_FILE (icon->data); nemo_file_set_is_desktop_orphan (file, FALSE); nemo_icon_container_move_icon (container, icon, item->icon_x + drop_x, item->icon_y + drop_y, icon->scale, TRUE, TRUE, TRUE); } } nemo_drag_destroy_selection_list (push_list); } } else { iter_rect.x = drop_rect.x; iter_rect.y = drop_rect.y; /* Just a normal move - no alignment - if we're provided a position, let it go wherever it wants. */ for (p = container->details->dnd_info->drag_info.selection_list; p != NULL; p = p->next) { item = p->data; icon = nemo_icon_container_get_icon_by_uri (container, item->uri); if (!item->got_icon_position) { /* If there's no position, place it by grid rules */ nemo_centered_placement_grid_get_next_position_rect (grid, &iter_rect, &iter_rect, &iter_is_free); if (iter_is_free) { item->icon_x = iter_rect.x; item->icon_y = iter_rect.y; } else { while (!iter_is_free) { nemo_centered_placement_grid_get_next_position_rect (grid, &iter_rect, &iter_rect, &iter_is_free); } item->icon_x = iter_rect.x; item->icon_y = iter_rect.y; } nemo_centered_placement_grid_nominal_to_icon_position (grid, icon, item->icon_x - drop_x, item->icon_y - drop_y, &item->icon_x, &item->icon_y); } } } } static void nemo_icon_container_receive_dropped_icons (NemoIconContainer *container, GdkDragContext *context, int x, int y) { char *drop_target; gboolean local_move_only; double world_x, world_y; gboolean icon_hit; GdkDragAction action, real_action; drop_target = NULL; if (container->details->dnd_info->drag_info.selection_list == NULL) { return; } real_action = gdk_drag_context_get_selected_action (context); if (real_action == GDK_ACTION_ASK) { /* FIXME bugzilla.gnome.org 42485: This belongs in FMDirectoryView, not here. */ /* Check for special case items in selection list */ if (nemo_drag_selection_includes_special_link (container->details->dnd_info->drag_info.selection_list)) { /* We only want to move the trash */ action = GDK_ACTION_MOVE; } else { action = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK; } real_action = nemo_drag_drop_action_ask (GTK_WIDGET (container), action); } if (real_action > 0) { eel_canvas_window_to_world (EEL_CANVAS (container), x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))), y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))), &world_x, &world_y); drop_target = nemo_icon_container_find_drop_target (container, context, x, y, &icon_hit, FALSE); local_move_only = FALSE; if (!icon_hit && real_action == GDK_ACTION_MOVE) { /* we can just move the icon positions if the move ended up in * the item's parent container */ local_move_only = nemo_icon_container_selection_items_local (container, container->details->dnd_info->drag_info.selection_list); } if (local_move_only) { prep_selection (container, world_x, world_y); if (NEMO_ICON_CONTAINER_GET_CLASS (container)->is_grid_container) { handle_local_grid_container_move (container, world_x, world_y); } else { handle_local_move (container, world_x, world_y); } } else { if (!icon_hit) { prep_selection (container, world_x, world_y); } handle_nonlocal_move (container, real_action, world_x, world_y, drop_target, icon_hit); } } g_free (drop_target); nemo_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list); g_clear_pointer (&container->details->dnd_info->drag_info.source_fs, g_free); container->details->dnd_info->drag_info.selection_list = NULL; free_dnd_grid (container); } static void nemo_icon_container_get_drop_action (NemoIconContainer *container, GdkDragContext *context, int x, int y, int *action) { char *drop_target; gboolean icon_hit; double world_x, world_y; icon_hit = FALSE; if (!container->details->dnd_info->drag_info.got_drop_data_type) { /* drag_data_received_callback didn't get called yet */ return; } /* find out if we're over an icon */ canvas_widget_to_world (EEL_CANVAS (container), x, y, &world_x, &world_y); *action = 0; /* case out on the type of object being dragged */ switch (container->details->dnd_info->drag_info.data_type) { case NEMO_ICON_DND_GNOME_ICON_LIST: if (container->details->dnd_info->drag_info.selection_list == NULL) { return; } drop_target = nemo_icon_container_find_drop_target (container, context, x, y, &icon_hit, FALSE); if (!drop_target) { return; } nemo_drag_default_drop_action_for_icons (context, drop_target, container->details->dnd_info->drag_info.selection_list, action, &container->details->dnd_info->drag_info.source_fs, &container->details->dnd_info->drag_info.can_delete_source); g_free (drop_target); break; case NEMO_ICON_DND_URI_LIST: drop_target = nemo_icon_container_find_drop_target (container, context, x, y, &icon_hit, FALSE); *action = nemo_drag_default_drop_action_for_uri_list (context, drop_target); g_free (drop_target); break; case NEMO_ICON_DND_NETSCAPE_URL: *action = nemo_drag_default_drop_action_for_netscape_url (context); break; case NEMO_ICON_DND_ROOTWINDOW_DROP: *action = gdk_drag_context_get_suggested_action (context); break; case NEMO_ICON_DND_TEXT: case NEMO_ICON_DND_XDNDDIRECTSAVE: case NEMO_ICON_DND_RAW: *action = GDK_ACTION_COPY; break; } } static void set_drop_target (NemoIconContainer *container, NemoIcon *icon) { NemoIcon *old_icon; /* Check if current drop target changed, update icon drop * higlight if needed. */ old_icon = container->details->drop_target; if (icon == old_icon) { return; } /* Remember the new drop target for the next round. */ container->details->drop_target = icon; nemo_icon_container_update_icon (container, old_icon); nemo_icon_container_update_icon (container, icon); if (icon != NULL) { nemo_icon_container_icon_raise (container, icon); } } static void nemo_icon_dnd_update_drop_target (NemoIconContainer *container, GdkDragContext *context, int x, int y) { NemoIcon *icon; NemoFile *file; double world_x, world_y; char *uri; g_assert (NEMO_IS_ICON_CONTAINER (container)); canvas_widget_to_world (EEL_CANVAS (container), x, y, &world_x, &world_y); /* Find the item we hit with our drop, if any. */ icon = nemo_icon_container_item_at (container, world_x, world_y); /* FIXME bugzilla.gnome.org 42485: * These "can_accept_items" tests need to be done by * the icon view, not here. This file is not supposed to know * that the target is a file. */ /* Find if target icon accepts our drop. */ if (icon != NULL) { uri = nemo_icon_container_get_icon_uri (container, icon); file = nemo_file_get_by_uri (uri); g_free (uri); if (!nemo_drag_can_accept_info (file, container->details->dnd_info->drag_info.data_type, container->details->dnd_info->drag_info.selection_list)) { icon = NULL; } nemo_file_unref (file); } set_drop_target (container, icon); } static void nemo_icon_container_free_drag_data (NemoIconContainer *container) { NemoIconDndInfo *dnd_info; dnd_info = container->details->dnd_info; dnd_info->drag_info.got_drop_data_type = FALSE; if (dnd_info->shadow != NULL) { eel_canvas_item_destroy (dnd_info->shadow); dnd_info->shadow = NULL; } if (dnd_info->drag_info.selection_data != NULL) { gtk_selection_data_free (dnd_info->drag_info.selection_data); dnd_info->drag_info.selection_data = NULL; } if (dnd_info->drag_info.direct_save_uri != NULL) { g_free (dnd_info->drag_info.direct_save_uri); dnd_info->drag_info.direct_save_uri = NULL; } } static void drag_leave_callback (GtkWidget *widget, GdkDragContext *context, guint32 time, gpointer data) { NemoIconDndInfo *dnd_info; dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info; if (dnd_info->shadow != NULL) eel_canvas_item_hide (dnd_info->shadow); stop_dnd_highlight (widget); set_drop_target (NEMO_ICON_CONTAINER (widget), NULL); stop_auto_scroll (NEMO_ICON_CONTAINER (widget)); nemo_icon_container_free_drag_data(NEMO_ICON_CONTAINER (widget)); } static void drag_begin_callback (GtkWidget *widget, GdkDragContext *context, gpointer data) { NemoIconContainer *container; cairo_surface_t *surface; double x1, y1, x2, y2, winx, winy; int x_offset, y_offset; int start_x, start_y; container = NEMO_ICON_CONTAINER (widget); start_x = container->details->dnd_info->drag_info.start_x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); start_y = container->details->dnd_info->drag_info.start_y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); /* create a pixmap and mask to drag with */ surface = nemo_icon_canvas_item_get_drag_surface (container->details->drag_icon->item); /* compute the image's offset */ eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (container->details->drag_icon->item), &x1, &y1, &x2, &y2); eel_canvas_world_to_window (EEL_CANVAS (container), x1, y1, &winx, &winy); x_offset = start_x - winx; y_offset = start_y - winy; cairo_surface_set_device_offset (surface, -x_offset, -y_offset); gtk_drag_set_icon_surface (context, surface); cairo_surface_destroy (surface); } void nemo_icon_dnd_begin_drag (NemoIconContainer *container, GdkDragAction actions, int button, GdkEventMotion *event, int start_x, int start_y) { NemoIconDndInfo *dnd_info; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (event != NULL); dnd_info = container->details->dnd_info; g_return_if_fail (dnd_info != NULL); /* Notice that the event is in bin_window coordinates, because of the way the canvas handles events. */ dnd_info->drag_info.start_x = start_x - gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); dnd_info->drag_info.start_y = start_y - gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); /* start the drag */ gtk_drag_begin (GTK_WIDGET (container), dnd_info->drag_info.target_list, actions, button, (GdkEvent *) event); } static gboolean drag_highlight_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data) { gint width, height; GdkWindow *window; GtkStyleContext *style; window = gtk_widget_get_window (widget); width = gdk_window_get_width (window); height = gdk_window_get_height (window); style = gtk_widget_get_style_context (widget); gtk_style_context_save (style); gtk_style_context_add_class (style, GTK_STYLE_CLASS_DND); gtk_style_context_set_state (style, GTK_STATE_FLAG_FOCUSED); gtk_render_frame (style, cr, 0, 0, width, height); gtk_style_context_restore (style); return FALSE; } /* Queue a redraw of the dnd highlight rect */ static void dnd_highlight_queue_redraw (GtkWidget *widget) { NemoIconDndInfo *dnd_info; int width, height; GtkAllocation allocation; dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info; if (!dnd_info->highlighted) { return; } gtk_widget_get_allocation (widget, &allocation); width = allocation.width; height = allocation.height; /* we don't know how wide the shadow is exactly, * so we expose a 10-pixel wide border */ gtk_widget_queue_draw_area (widget, 0, 0, width, 10); gtk_widget_queue_draw_area (widget, 0, 0, 10, height); gtk_widget_queue_draw_area (widget, 0, height - 10, width, 10); gtk_widget_queue_draw_area (widget, width - 10, 0, 10, height); } static void start_dnd_highlight (GtkWidget *widget) { NemoIconDndInfo *dnd_info; GtkWidget *toplevel; dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info; toplevel = gtk_widget_get_toplevel (widget); if (toplevel != NULL && g_object_get_data (G_OBJECT (toplevel), "is_desktop_window")) { return; } if (!dnd_info->highlighted) { dnd_info->highlighted = TRUE; g_signal_connect_after (widget, "draw", G_CALLBACK (drag_highlight_draw), NULL); dnd_highlight_queue_redraw (widget); } } static void stop_dnd_highlight (GtkWidget *widget) { NemoIconDndInfo *dnd_info; dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info; if (dnd_info->highlighted) { g_signal_handlers_disconnect_by_func (widget, drag_highlight_draw, NULL); dnd_highlight_queue_redraw (widget); dnd_info->highlighted = FALSE; } } static gboolean drag_motion_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, guint32 time) { NemoIconContainer *container; int action; container = NEMO_ICON_CONTAINER (widget); nemo_icon_container_ensure_drag_data (container, context, time); nemo_icon_container_position_shadow (container, x, y); if (container->details->dnd_grid == NULL) { initialize_dnd_grid (container); gtk_widget_queue_draw (widget); } container->details->current_dnd_x = x; container->details->current_dnd_y = y; nemo_icon_dnd_update_drop_target (container, context, x, y); set_up_auto_scroll_if_needed (container); /* Find out what the drop actions are based on our drag selection and * the drop target. */ action = 0; nemo_icon_container_get_drop_action (container, context, x, y, &action); if (action != 0) { start_dnd_highlight (widget); gtk_widget_queue_draw (widget); } gdk_drag_status (context, action, time); return TRUE; } static gboolean drag_drop_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, guint32 time, gpointer data) { NemoIconDndInfo *dnd_info; dnd_info = NEMO_ICON_CONTAINER (widget)->details->dnd_info; /* tell the drag_data_received callback that the drop occured and that it can actually process the actions. make sure it is going to be called at least once. */ dnd_info->drag_info.drop_occured = TRUE; get_data_on_first_target_we_support (widget, context, time, x, y); return TRUE; } void nemo_icon_dnd_end_drag (NemoIconContainer *container) { NemoIconDndInfo *dnd_info; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); dnd_info = container->details->dnd_info; g_return_if_fail (dnd_info != NULL); stop_auto_scroll (container); /* Do nothing. * Can that possibly be right? */ } /** this callback is called in 2 cases. It is called upon drag_motion events to get the actual data In that case, it just makes sure it gets the data. It is called upon drop_drop events to execute the actual actions on the received action. In that case, it actually first makes sure that we have got the data then processes it. */ static void drag_data_received_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, GtkSelectionData *data, guint info, guint32 time, gpointer user_data) { NemoDragInfo *drag_info; guchar *tmp; const guchar *tmp_raw; int length; gboolean success; drag_info = &(NEMO_ICON_CONTAINER (widget)->details->dnd_info->drag_info); drag_info->got_drop_data_type = TRUE; drag_info->data_type = info; switch (info) { case NEMO_ICON_DND_GNOME_ICON_LIST: nemo_icon_container_dropped_icon_feedback (widget, data, x, y); break; case NEMO_ICON_DND_URI_LIST: case NEMO_ICON_DND_TEXT: case NEMO_ICON_DND_XDNDDIRECTSAVE: case NEMO_ICON_DND_RAW: /* Save the data so we can do the actual work on drop. */ if (drag_info->selection_data != NULL) { gtk_selection_data_free (drag_info->selection_data); } drag_info->selection_data = gtk_selection_data_copy (data); break; /* Netscape keeps sending us the data, even though we accept the first drag */ case NEMO_ICON_DND_NETSCAPE_URL: if (drag_info->selection_data != NULL) { gtk_selection_data_free (drag_info->selection_data); drag_info->selection_data = gtk_selection_data_copy (data); } break; case NEMO_ICON_DND_ROOTWINDOW_DROP: /* Do nothing, this won't even happen, since we don't want to call get_data twice */ break; } /* this is the second use case of this callback. * we have to do the actual work for the drop. */ if (drag_info->drop_occured) { success = FALSE; switch (info) { case NEMO_ICON_DND_GNOME_ICON_LIST: nemo_icon_container_receive_dropped_icons (NEMO_ICON_CONTAINER (widget), context, x, y); break; case NEMO_ICON_DND_NETSCAPE_URL: receive_dropped_netscape_url (NEMO_ICON_CONTAINER (widget), (char *) gtk_selection_data_get_data (data), context, x, y); success = TRUE; free_dnd_grid (NEMO_ICON_CONTAINER (widget)); break; case NEMO_ICON_DND_URI_LIST: receive_dropped_uri_list (NEMO_ICON_CONTAINER (widget), (char *) gtk_selection_data_get_data (data), context, x, y); success = TRUE; free_dnd_grid (NEMO_ICON_CONTAINER (widget)); break; case NEMO_ICON_DND_TEXT: tmp = gtk_selection_data_get_text (data); receive_dropped_text (NEMO_ICON_CONTAINER (widget), (char *) tmp, context, x, y); success = TRUE; g_free (tmp); free_dnd_grid (NEMO_ICON_CONTAINER (widget)); break; case NEMO_ICON_DND_RAW: length = gtk_selection_data_get_length (data); tmp_raw = gtk_selection_data_get_data (data); receive_dropped_raw (NEMO_ICON_CONTAINER (widget), (const gchar *) tmp_raw, length, drag_info->direct_save_uri, context, x, y); success = TRUE; free_dnd_grid (NEMO_ICON_CONTAINER (widget)); break; case NEMO_ICON_DND_ROOTWINDOW_DROP: /* Do nothing, everything is done by the sender */ break; case NEMO_ICON_DND_XDNDDIRECTSAVE: { const guchar *selection_data; gint selection_length; gint selection_format; selection_data = gtk_selection_data_get_data (drag_info->selection_data); selection_length = gtk_selection_data_get_length (drag_info->selection_data); selection_format = gtk_selection_data_get_format (drag_info->selection_data); if (selection_format == 8 && selection_length == 1 && selection_data[0] == 'F') { gtk_drag_get_data (widget, context, gdk_atom_intern (NEMO_ICON_DND_RAW_TYPE, FALSE), time); return; } else if (selection_format == 8 && selection_length == 1 && selection_data[0] == 'F' && drag_info->direct_save_uri != NULL) { GdkPoint p; GFile *location; location = g_file_new_for_uri (drag_info->direct_save_uri); nemo_file_changes_queue_file_added (location); p.x = x; p.y = y; nemo_file_changes_queue_schedule_position_set ( location, p, nemo_desktop_utils_get_monitor_for_widget (widget)); g_object_unref (location); nemo_file_changes_consume_changes (TRUE); success = TRUE; } free_dnd_grid (NEMO_ICON_CONTAINER (widget)); break; } /* NEMO_ICON_DND_XDNDDIRECTSAVE */ } gtk_drag_finish (context, success, FALSE, time); nemo_icon_container_free_drag_data (NEMO_ICON_CONTAINER (widget)); set_drop_target (NEMO_ICON_CONTAINER (widget), NULL); /* reinitialise it for the next dnd */ drag_info->drop_occured = FALSE; } } void nemo_icon_dnd_init (NemoIconContainer *container) { GtkTargetList *targets; int n_elements; g_return_if_fail (container != NULL); g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->dnd_info = g_new0 (NemoIconDndInfo, 1); nemo_drag_init (&container->details->dnd_info->drag_info, drag_types, G_N_ELEMENTS (drag_types), TRUE); /* Set up the widget as a drag destination. * (But not a source, as drags starting from this widget will be * implemented by dealing with events manually.) */ n_elements = G_N_ELEMENTS (drop_types); if (!nemo_icon_container_get_is_desktop (container)) { /* Don't set up rootwindow drop */ n_elements -= 1; } gtk_drag_dest_set (GTK_WIDGET (container), 0, drop_types, n_elements, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); targets = gtk_drag_dest_get_target_list (GTK_WIDGET (container)); gtk_target_list_add_text_targets (targets, NEMO_ICON_DND_TEXT); /* Messages for outgoing drag. */ g_signal_connect (container, "drag_begin", G_CALLBACK (drag_begin_callback), NULL); g_signal_connect (container, "drag_data_get", G_CALLBACK (drag_data_get_callback), NULL); g_signal_connect (container, "drag_end", G_CALLBACK (drag_end_callback), NULL); /* Messages for incoming drag. */ g_signal_connect (container, "drag_data_received", G_CALLBACK (drag_data_received_callback), NULL); g_signal_connect (container, "drag_motion", G_CALLBACK (drag_motion_callback), NULL); g_signal_connect (container, "drag_drop", G_CALLBACK (drag_drop_callback), NULL); g_signal_connect (container, "drag_leave", G_CALLBACK (drag_leave_callback), NULL); } void nemo_icon_dnd_fini (NemoIconContainer *container) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); if (container->details->dnd_info != NULL) { stop_auto_scroll (container); nemo_drag_finalize (&container->details->dnd_info->drag_info); container->details->dnd_info = NULL; } } nemo-3.6.5/libnemo-private/nemo-directory-notify.h0000664000175000017500000000523113215733314021126 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-directory-notify.h: Nemo directory notify calls. Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include typedef struct { char *from_uri; char *to_uri; } URIPair; typedef struct { GFile *from; GFile *to; } GFilePair; typedef struct { GFile *location; gboolean set; GdkPoint point; int screen; int monitor; } NemoFileChangesQueuePosition; /* Almost-public change notification calls */ void nemo_directory_notify_files_added (GList *files); void nemo_directory_notify_files_moved (GList *file_pairs); void nemo_directory_notify_files_changed (GList *files); void nemo_directory_notify_files_removed (GList *files); void nemo_directory_schedule_metadata_copy (GList *file_pairs); void nemo_directory_schedule_metadata_move (GList *file_pairs); void nemo_directory_schedule_metadata_remove (GList *files); /* Deprecated URI versions: to be converted */ void nemo_directory_notify_files_added_by_uri (GList *uris); void nemo_directory_notify_files_changed_by_uri (GList *uris); void nemo_directory_notify_files_moved_by_uri (GList *uri_pairs); void nemo_directory_notify_files_removed_by_uri (GList *uris); void nemo_directory_schedule_metadata_copy_by_uri (GList *uri_pairs); void nemo_directory_schedule_metadata_move_by_uri (GList *uri_pairs); void nemo_directory_schedule_metadata_remove_by_uri (GList *uris); void nemo_directory_schedule_position_set (GList *position_setting_list); /* Change notification hack. * This is called when code modifies the file and it needs to trigger * a notification. Eventually this should become private, but for now * it needs to be used for code like the thumbnail generation. */ void nemo_file_changed (NemoFile *file); nemo-3.6.5/libnemo-private/nemo-places-tree-view.h0000664000175000017500000000372013215733314020771 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 2007 Martin Wehner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_PLACES_TREE_VIEW_H #define NEMO_PLACES_TREE_VIEW_H #include #define NEMO_TYPE_PLACES_TREE_VIEW nemo_places_tree_view_get_type() #define NEMO_PLACES_TREE_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_PLACES_TREE_VIEW, NemoPlacesTreeView)) #define NEMO_PLACES_TREE_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_PLACES_TREE_VIEW, NemoPlacesTreeViewClass)) #define NEMO_IS_PLACES_TREE_VIEW(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_PLACES_TREE_VIEW)) #define NEMO_IS_PLACES_TREE_VIEW_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_PLACES_TREE_VIEW)) #define NEMO_PLACES_TREE_VIEW_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_PLACES_TREE_VIEW, NemoPlacesTreeViewClass)) typedef struct _NemoPlacesTreeView NemoPlacesTreeView; typedef struct _NemoPlacesTreeViewClass NemoPlacesTreeViewClass; struct _NemoPlacesTreeView { GtkTreeView parent; }; struct _NemoPlacesTreeViewClass { GtkTreeViewClass parent_class; }; GType nemo_places_tree_view_get_type (void); GtkWidget *nemo_places_tree_view_new (void); #endif /* NEMO_PLACES_TREE_VIEW_H */ nemo-3.6.5/libnemo-private/nemo-entry.h0000664000175000017500000000477713215733314016773 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoEntry: one-line text editing widget. This consists of bug fixes * and other improvements to GtkEntry, and all the changes could be rolled * into GtkEntry some day. * * Copyright (C) 2000 Eazel, Inc. * * Author: John Sullivan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_ENTRY_H #define NEMO_ENTRY_H #include G_BEGIN_DECLS #define NEMO_TYPE_ENTRY nemo_entry_get_type() #define NEMO_ENTRY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ENTRY, NemoEntry)) #define NEMO_ENTRY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ENTRY, NemoEntryClass)) #define NEMO_IS_ENTRY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ENTRY)) #define NEMO_IS_ENTRY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ENTRY)) #define NEMO_ENTRY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ENTRY, NemoEntryClass)) typedef struct NemoEntryDetails NemoEntryDetails; typedef struct { GtkEntry parent; NemoEntryDetails *details; } NemoEntry; typedef struct { GtkEntryClass parent_class; void (*user_changed) (NemoEntry *entry); void (*selection_changed) (NemoEntry *entry); } NemoEntryClass; GType nemo_entry_get_type (void); GtkWidget *nemo_entry_new (void); GtkWidget *nemo_entry_new_with_max_length (guint16 max); void nemo_entry_set_text (NemoEntry *entry, const char *text); void nemo_entry_select_all (NemoEntry *entry); void nemo_entry_select_all_at_idle (NemoEntry *entry); void nemo_entry_set_special_tab_handling (NemoEntry *entry, gboolean special_tab_handling); G_END_DECLS #endif /* NEMO_ENTRY_H */ nemo-3.6.5/libnemo-private/nemo-desktop-metadata.c0000664000175000017500000001705513215733314021045 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 2011 Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Cosimo Cecchi */ #include #include "nemo-desktop-metadata.h" #include "nemo-directory-notify.h" #include "nemo-file-private.h" #include "nemo-file-utilities.h" #include #include #include #include static guint save_in_idle_source_id = 0; static gchar * get_keyfile_path (void) { gchar *xdg_dir, *retval; xdg_dir = nemo_get_user_directory (); retval = g_build_filename (xdg_dir, "desktop-metadata", NULL); g_free (xdg_dir); return retval; } static gboolean save_in_idle_cb (gpointer data) { GKeyFile *keyfile = data; gchar *contents, *filename; gsize length; GError *error = NULL; save_in_idle_source_id = 0; contents = g_key_file_to_data (keyfile, &length, NULL); filename = get_keyfile_path (); if (contents != NULL) { g_file_set_contents (filename, contents, length, &error); g_free (contents); } if (error != NULL) { g_warning ("Couldn't save the desktop metadata keyfile to disk: %s", error->message); g_error_free (error); } g_free (filename); return FALSE; } static void save_in_idle (GKeyFile *keyfile) { if (save_in_idle_source_id != 0) { g_source_remove (save_in_idle_source_id); } save_in_idle_source_id = g_idle_add (save_in_idle_cb, keyfile); } static GKeyFile * load_metadata_keyfile (void) { GKeyFile *retval; GError *error = NULL; gchar *filename; retval = g_key_file_new (); filename = get_keyfile_path (); g_key_file_load_from_file (retval, filename, G_KEY_FILE_NONE, &error); if (error != NULL) { if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { g_print ("Unable to open the desktop metadata keyfile: %s\n", error->message); } g_error_free (error); } g_free (filename); return retval; } static GKeyFile * get_keyfile (void) { static gboolean keyfile_loaded = FALSE; static GKeyFile *keyfile = NULL; if (!keyfile_loaded) { keyfile = load_metadata_keyfile (); keyfile_loaded = TRUE; } return keyfile; } void nemo_desktop_metadata_init (void) { GKeyFile *file; file = get_keyfile (); } void nemo_desktop_set_metadata_string (NemoFile *file, const gchar *name, const gchar *key, const gchar *string) { GKeyFile *keyfile; keyfile = get_keyfile (); g_key_file_set_string (keyfile, name, key, string); save_in_idle (keyfile); if (nemo_desktop_update_metadata_from_keyfile (file, name)) { nemo_file_changed (file); } } #define STRV_TERMINATOR "@x-nemo-desktop-metadata-term@" void nemo_desktop_set_metadata_stringv (NemoFile *file, const char *name, const char *key, const char * const *stringv) { GKeyFile *keyfile; guint length; gchar **actual_stringv = NULL; gboolean free_strv = FALSE; keyfile = get_keyfile (); /* if we would be setting a single-length strv, append a fake * terminator to the array, to be able to differentiate it later from * the single string case */ length = g_strv_length ((gchar **) stringv); if (length == 1) { actual_stringv = g_malloc0 (3 * sizeof (gchar *)); actual_stringv[0] = (gchar *) stringv[0]; actual_stringv[1] = STRV_TERMINATOR; actual_stringv[2] = NULL; length = 2; free_strv = TRUE; } else { actual_stringv = (gchar **) stringv; } g_key_file_set_string_list (keyfile, name, key, (const gchar **) actual_stringv, length); save_in_idle (keyfile); if (nemo_desktop_update_metadata_from_keyfile (file, name)) { nemo_file_changed (file); } if (free_strv) { g_free (actual_stringv); } } void nemo_desktop_clear_metadata (NemoFile *file) { GKeyFile *keyfile; keyfile = get_keyfile (); if (g_key_file_remove_group (keyfile, file->details->name, NULL)) { save_in_idle (keyfile); } } gchar * nemo_desktop_get_metadata_string (NemoFile *file, const gchar *name, const gchar *key) { GKeyFile *keyfile; gchar *string; keyfile = get_keyfile (); string = g_key_file_get_string (keyfile, name, key, NULL); return string; } gchar ** nemo_desktop_get_metadata_stringv (NemoFile *file, const char *name, const char *key) { GKeyFile *keyfile; guint length; gchar **stringv = NULL; keyfile = get_keyfile (); stringv = g_key_file_get_string_list (keyfile, name, key, &length, NULL); return stringv; } gboolean nemo_desktop_update_metadata_from_keyfile (NemoFile *file, const gchar *name) { gchar **keys, **values; const gchar *actual_values[2]; const gchar *key, *value; gchar *gio_key; gsize length, values_length; GKeyFile *keyfile; GFileInfo *info; gint idx; gboolean res; keyfile = get_keyfile (); keys = g_key_file_get_keys (keyfile, name, &length, NULL); if (keys == NULL) { return FALSE; } info = g_file_info_new (); for (idx = 0; idx < length; idx++) { key = keys[idx]; values = g_key_file_get_string_list (keyfile, name, key, &values_length, NULL); gio_key = g_strconcat ("metadata::", key, NULL); if (values_length < 1) { continue; } else if (values_length == 1) { g_file_info_set_attribute_string (info, gio_key, values[0]); } else if (values_length == 2) { /* deal with the fact that single-length strv are stored * with an additional terminator in the keyfile string, to differentiate * them from the regular string case. */ value = values[1]; if (g_strcmp0 (value, STRV_TERMINATOR) == 0) { /* if the 2nd value is the terminator, remove it */ actual_values[0] = values[0]; actual_values[1] = NULL; g_file_info_set_attribute_stringv (info, gio_key, (gchar **) actual_values); } else { /* otherwise, set it as a regular strv */ g_file_info_set_attribute_stringv (info, gio_key, values); } } else { g_file_info_set_attribute_stringv (info, gio_key, values); } g_free (gio_key); g_strfreev (values); } res = nemo_file_update_metadata_from_info (file, info); g_strfreev (keys); g_object_unref (info); return res; } nemo-3.6.5/libnemo-private/nemo-file-queue.c0000664000175000017500000000536713215733314017662 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 2001 Maciej Stachowiak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Maciej Stachowiak */ #include #include "nemo-file-queue.h" #include struct NemoFileQueue { GList *head; GList *tail; GHashTable *item_to_link_map; }; NemoFileQueue * nemo_file_queue_new (void) { NemoFileQueue *queue; queue = g_new0 (NemoFileQueue, 1); queue->item_to_link_map = g_hash_table_new (g_direct_hash, g_direct_equal); return queue; } void nemo_file_queue_destroy (NemoFileQueue *queue) { g_hash_table_destroy (queue->item_to_link_map); nemo_file_list_free (queue->head); g_free (queue); } void nemo_file_queue_enqueue (NemoFileQueue *queue, NemoFile *file) { if (g_hash_table_lookup (queue->item_to_link_map, file) != NULL) { /* It's already on the queue. */ return; } if (queue->tail == NULL) { queue->head = g_list_append (NULL, file); queue->tail = queue->head; } else { queue->tail = g_list_append (queue->tail, file); queue->tail = queue->tail->next; } nemo_file_ref (file); g_hash_table_insert (queue->item_to_link_map, file, queue->tail); } NemoFile * nemo_file_queue_dequeue (NemoFileQueue *queue) { NemoFile *file; file = nemo_file_queue_head (queue); nemo_file_queue_remove (queue, file); return file; } void nemo_file_queue_remove (NemoFileQueue *queue, NemoFile *file) { GList *link; link = g_hash_table_lookup (queue->item_to_link_map, file); if (link == NULL) { /* It's not on the queue */ return; } if (link == queue->tail) { /* Need to special-case removing the tail. */ queue->tail = queue->tail->prev; } queue->head = g_list_remove_link (queue->head, link); g_list_free (link); g_hash_table_remove (queue->item_to_link_map, file); nemo_file_unref (file); } NemoFile * nemo_file_queue_head (NemoFileQueue *queue) { if (queue->head == NULL) { return NULL; } return NEMO_FILE (queue->head->data); } gboolean nemo_file_queue_is_empty (NemoFileQueue *queue) { return (queue->head == NULL); } nemo-3.6.5/libnemo-private/nemo-undo.h0000664000175000017500000000561513215733314016567 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-undo.h - public interface for objects that implement * undoable actions -- works across components * * Copyright (C) 2000 Eazel, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Darin Adler */ #ifndef NEMO_UNDO_H #define NEMO_UNDO_H #include typedef struct _NemoUndoTransaction NemoUndoTransaction; /* The basic undoable operation. */ typedef void (* NemoUndoCallback) (GObject *target, gpointer callback_data); /* Recipe for undo of a bit of work on an object. * Create these atoms when you want to register more * than one as a single undoable operation. */ typedef struct { GObject *target; NemoUndoCallback callback; gpointer callback_data; GDestroyNotify callback_data_destroy_notify; } NemoUndoAtom; /* Registering something that can be undone. */ void nemo_undo_register (GObject *target, NemoUndoCallback callback, gpointer callback_data, GDestroyNotify callback_data_destroy_notify, const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint); void nemo_undo_register_full (GList *atoms, GObject *undo_manager_search_start_object, const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint); void nemo_undo_unregister (GObject *target); /* Performing an undo explicitly. Only for use by objects "out in the field". * The menu bar itself uses a richer API in the undo manager. */ void nemo_undo (GObject *undo_manager_search_start_object); /* Connecting an undo manager. */ void nemo_undo_share_undo_manager (GObject *destination_object, GObject *source_object); #endif /* NEMO_UNDO_H */ nemo-3.6.5/libnemo-private/nemo-file-utilities.c0000664000175000017500000010214613215733314020542 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-utilities.c - implementation of file manipulation routines. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan */ #include #include "nemo-file-utilities.h" #include "nemo-global-preferences.h" #include "nemo-lib-self-check-functions.h" #include "nemo-metadata.h" #include "nemo-file.h" #include "nemo-file-operations.h" #include "nemo-search-directory.h" #include "nemo-signaller.h" #include #include #include #include #include #include #include #include #include #include #define NEMO_USER_DIRECTORY_NAME "nemo" #define DESKTOP_DIRECTORY_NAME "Desktop" #define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop" static void update_xdg_dir_cache (void); static void schedule_user_dirs_changed (void); static void desktop_dir_changed (void); static GFile *nemo_find_file_insensitive_next (GFile *parent, const gchar *name); char * nemo_compute_title_for_location (GFile *location) { NemoFile *file; char *title; char *builder; /* TODO-gio: This doesn't really work all that great if the info about the file isn't known atm... */ if (nemo_is_home_directory (location)) { return g_strdup (_("Home")); } builder = NULL; if (location) { file = nemo_file_get (location); builder = nemo_file_get_description (file); if (builder == NULL) { builder = nemo_file_get_display_name (file); } nemo_file_unref (file); } if (builder == NULL) { builder = g_file_get_basename (location); } if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SHOW_FULL_PATH_TITLES)) { file = nemo_file_get (location); char *path = g_filename_from_uri (nemo_file_get_uri (file), NULL, NULL); if (path != NULL) { title = g_strdup_printf("%s - %s", builder, path); } else { title = g_strdup(builder); } nemo_file_unref (file); g_free (path); g_free (builder); } else { title = g_strdup(builder); g_free (builder); } return title; } /** * nemo_get_user_directory: * * Get the path for the directory containing nemo settings. * * Return value: the directory path. **/ char * nemo_get_user_directory (void) { char *user_directory = NULL; user_directory = g_build_filename (g_get_user_config_dir (), NEMO_USER_DIRECTORY_NAME, NULL); if (!g_file_test (user_directory, G_FILE_TEST_EXISTS)) { g_mkdir_with_parents (user_directory, DEFAULT_NEMO_DIRECTORY_MODE); /* FIXME bugzilla.gnome.org 41286: * How should we handle the case where this mkdir fails? * Note that nemo_application_startup will refuse to launch if this * directory doesn't get created, so that case is OK. But the directory * could be deleted after Nemo was launched, and perhaps * there is some bad side-effect of not handling that case. */ } return user_directory; } /** * nemo_get_accel_map_file: * * Get the path for the filename containing nemo accelerator map. * The filename need not exist. * * Return value: the filename path, or NULL if the home directory could not be found **/ char * nemo_get_accel_map_file (void) { const gchar *override; override = g_getenv ("GNOME22_USER_DIR"); if (override) { return g_build_filename (override, "accels/nemo", NULL); } else { return g_build_filename (g_get_home_dir (), ".gnome2/accels/nemo", NULL); } } /** * nemo_get_scripts_directory_path: * * Get the path for the directory containing nemo scripts. * * Return value: the directory path containing nemo scripts **/ char * nemo_get_scripts_directory_path (void) { return g_build_filename (g_get_user_data_dir (), "nemo", "scripts", NULL); } typedef struct { char *type; char *path; NemoFile *file; } XdgDirEntry; static XdgDirEntry * parse_xdg_dirs (const char *config_file) { GArray *array; char *config_file_free = NULL; XdgDirEntry dir; char *data; char **lines; char *p, *d; int i; char *type_start, *type_end; char *value, *unescaped; gboolean relative; array = g_array_new (TRUE, TRUE, sizeof (XdgDirEntry)); if (config_file == NULL) { config_file_free = g_build_filename (g_get_user_config_dir (), "user-dirs.dirs", NULL); config_file = (const char *)config_file_free; } if (g_file_get_contents (config_file, &data, NULL, NULL)) { lines = g_strsplit (data, "\n", 0); g_free (data); for (i = 0; lines[i] != NULL; i++) { p = lines[i]; while (g_ascii_isspace (*p)) p++; if (*p == '#') continue; value = strchr (p, '='); if (value == NULL) continue; *value++ = 0; g_strchug (g_strchomp (p)); if (!g_str_has_prefix (p, "XDG_")) continue; if (!g_str_has_suffix (p, "_DIR")) continue; type_start = p + 4; type_end = p + strlen (p) - 4; while (g_ascii_isspace (*value)) value++; if (*value != '"') continue; value++; relative = FALSE; if (g_str_has_prefix (value, "$HOME")) { relative = TRUE; value += 5; while (*value == '/') value++; } else if (*value != '/') continue; d = unescaped = g_malloc (strlen (value) + 1); while (*value && *value != '"') { if ((*value == '\\') && (*(value + 1) != 0)) value++; *d++ = *value++; } *d = 0; *type_end = 0; dir.type = g_strdup (type_start); if (relative) { dir.path = g_build_filename (g_get_home_dir (), unescaped, NULL); g_free (unescaped); } else dir.path = unescaped; g_array_append_val (array, dir); } g_strfreev (lines); } g_free (config_file_free); return (XdgDirEntry *)g_array_free (array, FALSE); } static XdgDirEntry *cached_xdg_dirs = NULL; static GFileMonitor *cached_xdg_dirs_monitor = NULL; static void xdg_dir_changed (NemoFile *file, XdgDirEntry *dir) { GFile *location, *dir_location; char *path; location = nemo_file_get_location (file); dir_location = g_file_new_for_path (dir->path); if (!g_file_equal (location, dir_location)) { path = g_file_get_path (location); if (path) { char *argv[5]; int i; g_free (dir->path); dir->path = path; i = 0; argv[i++] = "xdg-user-dirs-update"; argv[i++] = "--set"; argv[i++] = dir->type; argv[i++] = dir->path; argv[i++] = NULL; /* We do this sync, to avoid possible race-conditions if multiple dirs change at the same time. Its blocking the main thread, but these updates should be very rare and very fast. */ g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, NULL, NULL); g_reload_user_special_dirs_cache (); schedule_user_dirs_changed (); desktop_dir_changed (); /* Icon might have changed */ nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_INFO); } } g_object_unref (location); g_object_unref (dir_location); } static void xdg_dir_cache_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type) { if (event_type == G_FILE_MONITOR_EVENT_CHANGED || event_type == G_FILE_MONITOR_EVENT_CREATED) { update_xdg_dir_cache (); } } static int user_dirs_changed_tag = 0; static gboolean emit_user_dirs_changed_idle (gpointer data) { g_signal_emit_by_name (nemo_signaller_get_current (), "user_dirs_changed"); user_dirs_changed_tag = 0; return FALSE; } static void schedule_user_dirs_changed (void) { if (user_dirs_changed_tag == 0) { user_dirs_changed_tag = g_idle_add (emit_user_dirs_changed_idle, NULL); } } static void unschedule_user_dirs_changed (void) { if (user_dirs_changed_tag != 0) { g_source_remove (user_dirs_changed_tag); user_dirs_changed_tag = 0; } } static void free_xdg_dir_cache (void) { int i; if (cached_xdg_dirs != NULL) { for (i = 0; cached_xdg_dirs[i].type != NULL; i++) { if (cached_xdg_dirs[i].file != NULL) { nemo_file_monitor_remove (cached_xdg_dirs[i].file, &cached_xdg_dirs[i]); g_signal_handlers_disconnect_by_func (cached_xdg_dirs[i].file, G_CALLBACK (xdg_dir_changed), &cached_xdg_dirs[i]); nemo_file_unref (cached_xdg_dirs[i].file); } g_free (cached_xdg_dirs[i].type); g_free (cached_xdg_dirs[i].path); } g_free (cached_xdg_dirs); } } static void destroy_xdg_dir_cache (void) { free_xdg_dir_cache (); unschedule_user_dirs_changed (); desktop_dir_changed (); if (cached_xdg_dirs_monitor != NULL) { g_object_unref (cached_xdg_dirs_monitor); cached_xdg_dirs_monitor = NULL; } } static void update_xdg_dir_cache (void) { GFile *file; char *config_file, *uri; int i; free_xdg_dir_cache (); g_reload_user_special_dirs_cache (); schedule_user_dirs_changed (); desktop_dir_changed (); cached_xdg_dirs = parse_xdg_dirs (NULL); for (i = 0 ; cached_xdg_dirs[i].type != NULL; i++) { cached_xdg_dirs[i].file = NULL; if (strcmp (cached_xdg_dirs[i].path, g_get_home_dir ()) != 0) { uri = g_filename_to_uri (cached_xdg_dirs[i].path, NULL, NULL); cached_xdg_dirs[i].file = nemo_file_get_by_uri (uri); nemo_file_monitor_add (cached_xdg_dirs[i].file, &cached_xdg_dirs[i], NEMO_FILE_ATTRIBUTE_INFO); g_signal_connect (cached_xdg_dirs[i].file, "changed", G_CALLBACK (xdg_dir_changed), &cached_xdg_dirs[i]); g_free (uri); } } if (cached_xdg_dirs_monitor == NULL) { config_file = g_build_filename (g_get_user_config_dir (), "user-dirs.dirs", NULL); file = g_file_new_for_path (config_file); cached_xdg_dirs_monitor = g_file_monitor_file (file, 0, NULL, NULL); g_signal_connect (cached_xdg_dirs_monitor, "changed", G_CALLBACK (xdg_dir_cache_changed_cb), NULL); g_object_unref (file); g_free (config_file); eel_debug_call_at_shutdown (destroy_xdg_dir_cache); } } char * nemo_get_xdg_dir (const char *type) { int i; if (cached_xdg_dirs == NULL) { update_xdg_dir_cache (); } for (i = 0 ; cached_xdg_dirs != NULL && cached_xdg_dirs[i].type != NULL; i++) { if (strcmp (cached_xdg_dirs[i].type, type) == 0) { return g_strdup (cached_xdg_dirs[i].path); } } if (strcmp ("DESKTOP", type) == 0) { return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL); } if (strcmp ("TEMPLATES", type) == 0) { return g_build_filename (g_get_home_dir (), "Templates", NULL); } return g_strdup (g_get_home_dir ()); } static char * get_desktop_path (void) { if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR)) { return g_strdup (g_get_home_dir()); } else { return nemo_get_xdg_dir ("DESKTOP"); } } /** * nemo_get_desktop_directory: * * Get the path for the directory containing files on the desktop. * * Return value: the directory path. **/ char * nemo_get_desktop_directory (void) { char *desktop_directory; desktop_directory = get_desktop_path (); /* Don't try to create a home directory */ if (!g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR)) { if (!g_file_test (desktop_directory, G_FILE_TEST_EXISTS)) { g_mkdir (desktop_directory, DEFAULT_DESKTOP_DIRECTORY_MODE); /* FIXME bugzilla.gnome.org 41286: * How should we handle the case where this mkdir fails? * Note that nemo_application_startup will refuse to launch if this * directory doesn't get created, so that case is OK. But the directory * could be deleted after Nemo was launched, and perhaps * there is some bad side-effect of not handling that case. */ } } return desktop_directory; } GFile * nemo_get_desktop_location (void) { char *desktop_directory; GFile *res; desktop_directory = get_desktop_path (); res = g_file_new_for_path (desktop_directory); g_free (desktop_directory); return res; } /** * nemo_get_desktop_directory_uri: * * Get the uri for the directory containing files on the desktop. * * Return value: the directory path. **/ char * nemo_get_desktop_directory_uri (void) { char *desktop_path; char *desktop_uri; desktop_path = nemo_get_desktop_directory (); desktop_uri = g_filename_to_uri (desktop_path, NULL, NULL); g_free (desktop_path); return desktop_uri; } char * nemo_get_desktop_directory_uri_no_create (void) { char *desktop_path; char *desktop_uri; desktop_path = get_desktop_path (); desktop_uri = g_filename_to_uri (desktop_path, NULL, NULL); g_free (desktop_path); return desktop_uri; } char * nemo_get_home_directory_uri (void) { return g_filename_to_uri (g_get_home_dir (), NULL, NULL); } gboolean nemo_should_use_templates_directory (void) { char *dir; gboolean res; dir = nemo_get_xdg_dir ("TEMPLATES"); res = strcmp (dir, g_get_home_dir ()) != 0; g_free (dir); return res; } char * nemo_get_templates_directory (void) { return nemo_get_xdg_dir ("TEMPLATES"); } void nemo_create_templates_directory (void) { char *dir; dir = nemo_get_templates_directory (); if (!g_file_test (dir, G_FILE_TEST_EXISTS)) { g_mkdir (dir, DEFAULT_NEMO_DIRECTORY_MODE); } g_free (dir); } char * nemo_get_templates_directory_uri (void) { char *directory, *uri; directory = nemo_get_templates_directory (); uri = g_filename_to_uri (directory, NULL, NULL); g_free (directory); return uri; } char * nemo_get_searches_directory (void) { char *user_dir; char *searches_dir; user_dir = nemo_get_user_directory (); searches_dir = g_build_filename (user_dir, "searches", NULL); g_free (user_dir); if (!g_file_test (searches_dir, G_FILE_TEST_EXISTS)) g_mkdir (searches_dir, DEFAULT_NEMO_DIRECTORY_MODE); return searches_dir; } /* These need to be reset to NULL when desktop_is_home_dir changes */ static GFile *desktop_dir = NULL; static GFile *desktop_dir_dir = NULL; static char *desktop_dir_filename = NULL; static gboolean desktop_dir_changed_callback_installed = FALSE; static void desktop_dir_changed (void) { if (desktop_dir) { g_object_unref (desktop_dir); } if (desktop_dir_dir) { g_object_unref (desktop_dir_dir); } g_free (desktop_dir_filename); desktop_dir = NULL; desktop_dir_dir = NULL; desktop_dir_filename = NULL; } static void desktop_dir_changed_callback (gpointer callback_data) { desktop_dir_changed (); } static void update_desktop_dir (void) { char *path; char *dirname; path = get_desktop_path (); desktop_dir = g_file_new_for_path (path); dirname = g_path_get_dirname (path); desktop_dir_dir = g_file_new_for_path (dirname); g_free (dirname); desktop_dir_filename = g_path_get_basename (path); g_free (path); } gboolean nemo_is_home_directory_file (GFile *dir, const char *filename) { char *dirname; static GFile *home_dir_dir = NULL; static char *home_dir_filename = NULL; if (home_dir_dir == NULL) { dirname = g_path_get_dirname (g_get_home_dir ()); home_dir_dir = g_file_new_for_path (dirname); g_free (dirname); home_dir_filename = g_path_get_basename (g_get_home_dir ()); } return (g_file_equal (dir, home_dir_dir) && strcmp (filename, home_dir_filename) == 0); } gboolean nemo_is_home_directory (GFile *dir) { static GFile *home_dir = NULL; if (home_dir == NULL) { home_dir = g_file_new_for_path (g_get_home_dir ()); } return g_file_equal (dir, home_dir); } gboolean nemo_is_root_directory (GFile *dir) { static GFile *root_dir = NULL; if (root_dir == NULL) { root_dir = g_file_new_for_path ("/"); } return g_file_equal (dir, root_dir); } gboolean nemo_is_desktop_directory_file (GFile *dir, const char *file) { if (!desktop_dir_changed_callback_installed) { g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR, G_CALLBACK(desktop_dir_changed_callback), NULL); desktop_dir_changed_callback_installed = TRUE; } if (desktop_dir == NULL) { update_desktop_dir (); } return (g_file_equal (dir, desktop_dir_dir) && strcmp (file, desktop_dir_filename) == 0); } gboolean nemo_is_desktop_directory (GFile *dir) { if (!desktop_dir_changed_callback_installed) { g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR, G_CALLBACK(desktop_dir_changed_callback), NULL); desktop_dir_changed_callback_installed = TRUE; } if (desktop_dir == NULL) { update_desktop_dir (); } return g_file_equal (dir, desktop_dir); } /** * nemo_get_gmc_desktop_directory: * * Get the path for the directory containing the legacy gmc desktop. * * Return value: the directory path. **/ char * nemo_get_gmc_desktop_directory (void) { return g_build_filename (g_get_home_dir (), LEGACY_DESKTOP_DIRECTORY_NAME, NULL); } char * nemo_get_data_file_path (const char *partial_path) { char *path; char *user_directory; /* first try the user's home directory */ user_directory = nemo_get_user_directory (); path = g_build_filename (user_directory, partial_path, NULL); g_free (user_directory); if (g_file_test (path, G_FILE_TEST_EXISTS)) { return path; } g_free (path); /* next try the shared directory */ path = g_build_filename (NEMO_DATADIR, partial_path, NULL); if (g_file_test (path, G_FILE_TEST_EXISTS)) { return path; } g_free (path); return NULL; } char * nemo_ensure_unique_file_name (const char *directory_uri, const char *base_name, const char *extension) { GFileInfo *info; char *filename; GFile *dir, *child; int copy; char *res; dir = g_file_new_for_uri (directory_uri); info = g_file_query_info (dir, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL); if (info == NULL) { g_object_unref (dir); return NULL; } g_object_unref (info); filename = g_strdup_printf ("%s%s", base_name, extension); child = g_file_get_child (dir, filename); g_free (filename); copy = 1; while ((info = g_file_query_info (child, G_FILE_ATTRIBUTE_STANDARD_TYPE, 0, NULL, NULL)) != NULL) { g_object_unref (info); g_object_unref (child); filename = g_strdup_printf ("%s-%d%s", base_name, copy, extension); child = g_file_get_child (dir, filename); g_free (filename); copy++; } res = g_file_get_uri (child); g_object_unref (child); g_object_unref (dir); return res; } char * nemo_unique_temporary_file_name (void) { const char *prefix = "/tmp/nemo-temp-file"; char *file_name; int fd; file_name = g_strdup_printf ("%sXXXXXX", prefix); fd = g_mkstemp (file_name); if (fd == -1) { g_free (file_name); file_name = NULL; } else { close (fd); } return file_name; } GFile * nemo_find_existing_uri_in_hierarchy (GFile *location) { GFileInfo *info; GFile *tmp; g_assert (location != NULL); location = g_object_ref (location); while (location != NULL) { info = g_file_query_info (location, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL); g_object_unref (info); if (info != NULL) { return location; } tmp = location; location = g_file_get_parent (location); g_object_unref (tmp); } return location; } /** * nemo_find_file_insensitive * * Attempt to find a file case-insentively. If the path can be found, the * returned file maps directly to it. Otherwise, a file using the * originally-cased path is returned. This function performs might perform * I/O. * * Return value: a #GFile to a child specified by @name. **/ GFile * nemo_find_file_insensitive (GFile *parent, const gchar *name) { gchar **split_path; gchar *component; GFile *file, *next; gint i; split_path = g_strsplit (name, G_DIR_SEPARATOR_S, -1); file = g_object_ref (parent); for (i = 0; (component = split_path[i]) != NULL; i++) { if (!(next = nemo_find_file_insensitive_next (file, component))) { /* File does not exist */ g_object_unref (file); file = NULL; break; } g_object_unref (file); file = next; } g_strfreev (split_path); if (file) { return file; } return g_file_get_child (parent, name); } static GFile * nemo_find_file_insensitive_next (GFile *parent, const gchar *name) { GFileEnumerator *children; GFileInfo *info; gboolean use_utf8, found; char *filename, *case_folded_name, *utf8_collation_key, *ascii_collation_key, *child_key; GFile *file; const char *child_name, *compare_key; /* First check the given version */ file = g_file_get_child (parent, name); if (g_file_query_exists (file, NULL)) { return file; } g_object_unref (file); ascii_collation_key = g_ascii_strdown (name, -1); use_utf8 = g_utf8_validate (name, -1, NULL); utf8_collation_key = NULL; if (use_utf8) { case_folded_name = g_utf8_casefold (name, -1); utf8_collation_key = g_utf8_collate_key (case_folded_name, -1); g_free (case_folded_name); } /* Enumerate and compare insensitive */ filename = NULL; children = g_file_enumerate_children (parent, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL); if (children != NULL) { while ((info = g_file_enumerator_next_file (children, NULL, NULL))) { child_name = g_file_info_get_name (info); if (use_utf8 && g_utf8_validate (child_name, -1, NULL)) { gchar *case_folded; case_folded = g_utf8_casefold (child_name, -1); child_key = g_utf8_collate_key (case_folded, -1); g_free (case_folded); compare_key = utf8_collation_key; } else { child_key = g_ascii_strdown (child_name, -1); compare_key = ascii_collation_key; } found = strcmp (child_key, compare_key) == 0; g_free (child_key); if (found) { filename = g_strdup (child_name); break; } } g_file_enumerator_close (children, NULL, NULL); g_object_unref (children); } g_free (ascii_collation_key); g_free (utf8_collation_key); if (filename) { file = g_file_get_child (parent, filename); g_free (filename); return file; } return NULL; } static gboolean have_program_in_path (const char *name) { char *path; gboolean result; path = g_find_program_in_path (name); result = (path != NULL); g_free (path); return result; } gboolean nemo_is_file_roller_installed (void) { static int installed = - 1; if (installed < 0) { if (have_program_in_path ("file-roller")) { installed = 1; } else { installed = 0; } } return installed > 0 ? TRUE : FALSE; } #define GSM_NAME "org.gnome.SessionManager" #define GSM_PATH "/org/gnome/SessionManager" #define GSM_INTERFACE "org.gnome.SessionManager" /* The following values come from * http://www.gnome.org/~mccann/gnome-session/docs/gnome-session.html#org.gnome.SessionManager.Inhibit */ #define INHIBIT_LOGOUT (1U) #define INHIBIT_SUSPEND (4U) static GDBusConnection * get_dbus_connection (void) { static GDBusConnection *conn = NULL; if (conn == NULL) { GError *error = NULL; conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); if (conn == NULL) { g_warning ("Could not connect to session bus: %s", error->message); g_error_free (error); } } return conn; } /** * nemo_inhibit_power_manager: * @message: a human readable message for the reason why power management * is being suspended. * * Inhibits the power manager from logging out or suspending the machine * (e.g. whenever Nemo is doing file operations). * * Returns: an integer cookie, which must be passed to * nemo_uninhibit_power_manager() to resume * normal power management. */ int nemo_inhibit_power_manager (const char *message) { GDBusConnection *connection; GVariant *result; GError *error = NULL; guint cookie = 0; g_return_val_if_fail (message != NULL, -1); connection = get_dbus_connection (); if (connection == NULL) { return -1; } result = g_dbus_connection_call_sync (connection, GSM_NAME, GSM_PATH, GSM_INTERFACE, "Inhibit", g_variant_new ("(susu)", "Nemo", (guint) 0, message, (guint) (INHIBIT_LOGOUT | INHIBIT_SUSPEND)), G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error); if (error != NULL) { g_warning ("Could not inhibit power management: %s", error->message); g_error_free (error); return -1; } g_variant_get (result, "(u)", &cookie); g_variant_unref (result); return (int) cookie; } /** * nemo_uninhibit_power_manager: * @cookie: the cookie value returned by nemo_inhibit_power_manager() * * Uninhibits power management. This function must be called after the task * which inhibited power management has finished, or the system will not * return to normal power management. */ void nemo_uninhibit_power_manager (gint cookie) { GDBusConnection *connection; GVariant *result; GError *error = NULL; g_return_if_fail (cookie > 0); connection = get_dbus_connection (); if (connection == NULL) { return; } result = g_dbus_connection_call_sync (connection, GSM_NAME, GSM_PATH, GSM_INTERFACE, "Uninhibit", g_variant_new ("(u)", (guint) cookie), NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &error); if (result == NULL) { g_warning ("Could not uninhibit power management: %s", error->message); g_error_free (error); return; } g_variant_unref (result); } /* Returns TRUE if the file is in XDG_DATA_DIRS or in "~/.gnome2/". This is used for deciding if a desktop file is "trusted" based on the path */ gboolean nemo_is_in_system_dir (GFile *file) { const char * const * data_dirs; char *path, *gnome2; int i; gboolean res; if (!g_file_is_native (file)) { return FALSE; } path = g_file_get_path (file); res = FALSE; data_dirs = g_get_system_data_dirs (); for (i = 0; path != NULL && data_dirs[i] != NULL; i++) { if (g_str_has_prefix (path, data_dirs[i])) { res = TRUE; break; } } if (!res) { /* Panel desktop files are here, trust them */ gnome2 = g_build_filename (g_get_home_dir (), ".gnome2", NULL); if (g_str_has_prefix (path, gnome2)) { res = TRUE; } g_free (gnome2); } g_free (path); return res; } GHashTable * nemo_trashed_files_get_original_directories (GList *files, GList **unhandled_files) { GHashTable *directories; NemoFile *file, *original_file, *original_dir; GList *l, *m; directories = NULL; if (unhandled_files != NULL) { *unhandled_files = NULL; } for (l = files; l != NULL; l = l->next) { file = NEMO_FILE (l->data); original_file = nemo_file_get_trash_original_file (file); original_dir = NULL; if (original_file != NULL) { original_dir = nemo_file_get_parent (original_file); } if (original_dir != NULL) { if (directories == NULL) { directories = g_hash_table_new_full (g_direct_hash, g_direct_equal, (GDestroyNotify) nemo_file_unref, (GDestroyNotify) nemo_file_list_free); } nemo_file_ref (original_dir); m = g_hash_table_lookup (directories, original_dir); if (m != NULL) { g_hash_table_steal (directories, original_dir); nemo_file_unref (original_dir); } m = g_list_append (m, nemo_file_ref (file)); g_hash_table_insert (directories, original_dir, m); } else if (unhandled_files != NULL) { *unhandled_files = g_list_append (*unhandled_files, nemo_file_ref (file)); } if (original_file != NULL) { nemo_file_unref (original_file); } if (original_dir != NULL) { nemo_file_unref (original_dir); } } return directories; } static GList * locations_from_file_list (GList *file_list) { NemoFile *file; GList *l, *ret; ret = NULL; for (l = file_list; l != NULL; l = l->next) { file = NEMO_FILE (l->data); ret = g_list_prepend (ret, nemo_file_get_location (file)); } return g_list_reverse (ret); } typedef struct { GHashTable *original_dirs_hash; GtkWindow *parent_window; } RestoreFilesData; static void ensure_dirs_task_ready_cb (GObject *_source, GAsyncResult *res, gpointer user_data) { NemoFile *original_dir; GFile *original_dir_location; GList *original_dirs, *files, *locations, *l; RestoreFilesData *data = user_data; original_dirs = g_hash_table_get_keys (data->original_dirs_hash); for (l = original_dirs; l != NULL; l = l->next) { original_dir = NEMO_FILE (l->data); original_dir_location = nemo_file_get_location (original_dir); files = g_hash_table_lookup (data->original_dirs_hash, original_dir); locations = locations_from_file_list (files); nemo_file_operations_move (locations, NULL, original_dir_location, data->parent_window, NULL, NULL); g_list_free_full (locations, g_object_unref); g_object_unref (original_dir_location); } g_list_free (original_dirs); g_hash_table_unref (data->original_dirs_hash); g_slice_free (RestoreFilesData, data); } static void ensure_dirs_task_thread_func (GTask *task, gpointer source, gpointer task_data, GCancellable *cancellable) { RestoreFilesData *data = task_data; NemoFile *original_dir; GFile *original_dir_location; GList *original_dirs, *l; original_dirs = g_hash_table_get_keys (data->original_dirs_hash); for (l = original_dirs; l != NULL; l = l->next) { original_dir = NEMO_FILE (l->data); original_dir_location = nemo_file_get_location (original_dir); g_file_make_directory_with_parents (original_dir_location, cancellable, NULL); g_object_unref (original_dir_location); } g_task_return_pointer (task, NULL, NULL); } static void restore_files_ensure_parent_directories (GHashTable *original_dirs_hash, GtkWindow *parent_window) { RestoreFilesData *data; GTask *ensure_dirs_task; data = g_slice_new0 (RestoreFilesData); data->parent_window = parent_window; data->original_dirs_hash = g_hash_table_ref (original_dirs_hash); ensure_dirs_task = g_task_new (NULL, NULL, ensure_dirs_task_ready_cb, data); g_task_set_task_data (ensure_dirs_task, data, NULL); g_task_run_in_thread (ensure_dirs_task, ensure_dirs_task_thread_func); g_object_unref (ensure_dirs_task); } void nemo_restore_files_from_trash (GList *files, GtkWindow *parent_window) { NemoFile *file; GHashTable *original_dirs_hash; GList *unhandled_files, *l; char *message, *file_name; original_dirs_hash = nemo_trashed_files_get_original_directories (files, &unhandled_files); for (l = unhandled_files; l != NULL; l = l->next) { file = NEMO_FILE (l->data); file_name = nemo_file_get_display_name (file); message = g_strdup_printf (_("Could not determine original location of \"%s\" "), file_name); g_free (file_name); eel_show_warning_dialog (message, _("The item cannot be restored from trash"), parent_window); g_free (message); } if (original_dirs_hash != NULL) { restore_files_ensure_parent_directories (original_dirs_hash, parent_window); g_hash_table_unref (original_dirs_hash); } nemo_file_list_unref (unhandled_files); } typedef struct { NemoMountGetContent callback; gpointer user_data; } GetContentTypesData; static void get_types_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GetContentTypesData *data; char **types; data = user_data; types = g_mount_guess_content_type_finish (G_MOUNT (source_object), res, NULL); g_object_set_data_full (source_object, "nemo-content-type-cache", g_strdupv (types), (GDestroyNotify)g_strfreev); if (data->callback) { data->callback ((const char **) types, data->user_data); } g_strfreev (types); g_slice_free (GetContentTypesData, data); } void nemo_get_x_content_types_for_mount_async (GMount *mount, NemoMountGetContent callback, GCancellable *cancellable, gpointer user_data) { char **cached; GetContentTypesData *data; if (mount == NULL) { if (callback) { callback (NULL, user_data); } return; } cached = g_object_get_data (G_OBJECT (mount), "nemo-content-type-cache"); if (cached != NULL) { if (callback) { callback ((const char **) cached, user_data); } return; } data = g_slice_new0 (GetContentTypesData); data->callback = callback; data->user_data = user_data; g_mount_guess_content_type (mount, FALSE, cancellable, get_types_cb, data); } char ** nemo_get_cached_x_content_types_for_mount (GMount *mount) { char **cached; if (mount == NULL) { return NULL; } cached = g_object_get_data (G_OBJECT (mount), "nemo-content-type-cache"); if (cached != NULL) { return g_strdupv (cached); } return NULL; } #if !defined (NEMO_OMIT_SELF_CHECK) void nemo_self_check_file_utilities (void) { } #endif /* !NEMO_OMIT_SELF_CHECK */ nemo-3.6.5/libnemo-private/nemo-dnd.c0000664000175000017500000006541513215733314016366 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-dnd.c - Common Drag & drop handling code shared by the icon container and the list view. Copyright (C) 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Pavel Cisler , Ettore Perazzoli */ #include #include "nemo-dnd.h" #include "nemo-program-choosing.h" #include "nemo-link.h" #include #include #include #include #include #include #include #include #include /* a set of defines stolen from the eel-icon-dnd.c file. * These are in microseconds. */ #define AUTOSCROLL_TIMEOUT_INTERVAL 100 #define AUTOSCROLL_INITIAL_DELAY 100000 /* drag this close to the view edge to start auto scroll*/ #define AUTO_SCROLL_MARGIN 30 /* the smallest amount of auto scroll used when we just enter the autoscroll * margin */ #define MIN_AUTOSCROLL_DELTA 5 /* the largest amount of auto scroll used when we are right over the view * edge */ #define MAX_AUTOSCROLL_DELTA 50 void nemo_drag_init (NemoDragInfo *drag_info, const GtkTargetEntry *drag_types, int drag_type_count, gboolean add_text_targets) { drag_info->target_list = gtk_target_list_new (drag_types, drag_type_count); if (add_text_targets) { gtk_target_list_add_text_targets (drag_info->target_list, NEMO_ICON_DND_TEXT); } drag_info->drop_occured = FALSE; drag_info->need_to_destroy = FALSE; drag_info->source_fs = NULL; drag_info->can_delete_source = FALSE; } void nemo_drag_finalize (NemoDragInfo *drag_info) { gtk_target_list_unref (drag_info->target_list); nemo_drag_destroy_selection_list (drag_info->selection_list); g_free (drag_info->source_fs); drag_info->can_delete_source = FALSE; g_free (drag_info); } /* Functions to deal with NemoDragSelectionItems. */ NemoDragSelectionItem * nemo_drag_selection_item_new (void) { return g_new0 (NemoDragSelectionItem, 1); } static void drag_selection_item_destroy (NemoDragSelectionItem *item) { g_free (item->uri); g_free (item); } void nemo_drag_destroy_selection_list (GList *list) { GList *p; if (list == NULL) return; for (p = list; p != NULL; p = p->next) drag_selection_item_destroy (p->data); g_list_free (list); } char ** nemo_drag_uri_array_from_selection_list (const GList *selection_list) { GList *uri_list; char **uris; uri_list = nemo_drag_uri_list_from_selection_list (selection_list); uris = nemo_drag_uri_array_from_list (uri_list); g_list_free_full (uri_list, g_free); return uris; } GList * nemo_drag_uri_list_from_selection_list (const GList *selection_list) { NemoDragSelectionItem *selection_item; GList *uri_list; const GList *l; uri_list = NULL; for (l = selection_list; l != NULL; l = l->next) { selection_item = (NemoDragSelectionItem *) l->data; if (selection_item->uri != NULL) { uri_list = g_list_prepend (uri_list, g_strdup (selection_item->uri)); } } return g_list_reverse (uri_list); } char ** nemo_drag_uri_array_from_list (const GList *uri_list) { const GList *l; char **uris; int i; if (uri_list == NULL) { return NULL; } uris = g_new0 (char *, g_list_length ((GList *) uri_list)); for (i = 0, l = uri_list; l != NULL; l = l->next) { uris[i++] = g_strdup ((char *) l->data); } uris[i] = NULL; return uris; } GList * nemo_drag_uri_list_from_array (const char **uris) { GList *uri_list; int i; if (uris == NULL) { return NULL; } uri_list = NULL; for (i = 0; uris[i] != NULL; i++) { uri_list = g_list_prepend (uri_list, g_strdup (uris[i])); } return g_list_reverse (uri_list); } GList * nemo_drag_build_selection_list (GtkSelectionData *data) { GList *result; const guchar *p, *oldp; int size; result = NULL; oldp = gtk_selection_data_get_data (data); size = gtk_selection_data_get_length (data); while (size > 0) { NemoDragSelectionItem *item; guint len; /* The list is in the form: name\rx:y:width:height\r\n The geometry information after the first \r is optional. */ /* 1: Decode name. */ p = memchr (oldp, '\r', size); if (p == NULL) { break; } item = nemo_drag_selection_item_new (); len = p - oldp; item->uri = g_malloc (len + 1); memcpy (item->uri, oldp, len); item->uri[len] = 0; p++; if (*p == '\n' || *p == '\0') { result = g_list_prepend (result, item); if (p == 0) { g_warning ("Invalid x-special/gnome-icon-list data received: " "missing newline character."); break; } else { oldp = p + 1; continue; } } size -= p - oldp; oldp = p; /* 2: Decode geometry information. */ item->got_icon_position = sscanf ((const gchar *) p, "%d:%d:%d:%d%*s", &item->icon_x, &item->icon_y, &item->icon_width, &item->icon_height) == 4; if (!item->got_icon_position) { g_warning ("Invalid x-special/gnome-icon-list data received: " "invalid icon position specification."); } result = g_list_prepend (result, item); p = memchr (p, '\r', size); if (p == NULL || p[1] != '\n') { g_warning ("Invalid x-special/gnome-icon-list data received: " "missing newline character."); if (p == NULL) { break; } } else { p += 2; } size -= p - oldp; oldp = p; } return g_list_reverse (result); } static gboolean nemo_drag_file_local_internal (const char *target_uri_string, const char *first_source_uri) { /* check if the first item on the list has target_uri_string as a parent * FIXME: * we should really test each item but that would be slow for large selections * and currently dropped items can only be from the same container */ GFile *target, *item, *parent; gboolean result; result = FALSE; target = g_file_new_for_uri (target_uri_string); /* get the parent URI of the first item in the selection */ item = g_file_new_for_uri (first_source_uri); parent = g_file_get_parent (item); g_object_unref (item); if (parent != NULL) { result = g_file_equal (parent, target); g_object_unref (parent); } g_object_unref (target); return result; } gboolean nemo_drag_uris_local (const char *target_uri, const GList *source_uri_list) { /* must have at least one item */ g_assert (source_uri_list); return nemo_drag_file_local_internal (target_uri, source_uri_list->data); } gboolean nemo_drag_items_local (const char *target_uri_string, const GList *selection_list) { /* must have at least one item */ g_assert (selection_list); return nemo_drag_file_local_internal (target_uri_string, ((NemoDragSelectionItem *)selection_list->data)->uri); } gboolean nemo_drag_items_in_trash (const GList *selection_list) { /* check if the first item on the list is in trash. * FIXME: * we should really test each item but that would be slow for large selections * and currently dropped items can only be from the same container */ return eel_uri_is_trash (((NemoDragSelectionItem *)selection_list->data)->uri); } gboolean nemo_drag_items_on_desktop (const GList *selection_list) { char *uri; GFile *desktop, *item, *parent; gboolean result; /* check if the first item on the list is in trash. * FIXME: * we should really test each item but that would be slow for large selections * and currently dropped items can only be from the same container */ uri = ((NemoDragSelectionItem *)selection_list->data)->uri; if (eel_uri_is_desktop (uri)) { return TRUE; } desktop = nemo_get_desktop_location (); item = g_file_new_for_uri (uri); parent = g_file_get_parent (item); g_object_unref (item); result = FALSE; if (parent) { result = g_file_equal (desktop, parent); g_object_unref (parent); } g_object_unref (desktop); return result; } GdkDragAction nemo_drag_default_drop_action_for_netscape_url (GdkDragContext *context) { /* Mozilla defaults to copy, but unless thats the only allowed thing (enforced by ctrl) we want to LINK */ if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY && gdk_drag_context_get_actions (context) != GDK_ACTION_COPY) { return GDK_ACTION_LINK; } else if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE) { /* Don't support move */ return GDK_ACTION_COPY; } return gdk_drag_context_get_suggested_action (context); } static gboolean check_same_fs (NemoFile *target_file, NemoFile *source_file, const gchar *source_fs_for_desktop) { char *target_id, *source_id; gboolean result; result = FALSE; if (target_file != NULL && source_file != NULL) { source_id = nemo_file_get_filesystem_id (source_file); target_id = nemo_file_get_filesystem_id (target_file); if (source_id != NULL && target_id != NULL) { result = (strcmp (source_id, target_id) == 0); } g_free (source_id); g_free (target_id); } else if (target_file != NULL && source_fs_for_desktop != NULL) { target_id = nemo_file_get_filesystem_id (target_file); if (target_id != NULL) { result = (strcmp (source_fs_for_desktop, target_id) == 0); } g_free (target_id); } return result; } static gboolean source_is_deletable (GFile *file) { NemoFile *naut_file; gboolean ret; /* if there's no a cached NemoFile, it returns NULL */ naut_file = nemo_file_get_existing (file); if (naut_file == NULL) { return FALSE; } ret = nemo_file_can_delete (naut_file); nemo_file_unref (naut_file); return ret; } static gboolean uri_contains_desktop (const gchar *uri) { gchar *real_desktop_uri; if (eel_uri_is_desktop (uri)) { return TRUE; } real_desktop_uri = nemo_get_desktop_directory_uri (); if (g_str_has_prefix (uri, real_desktop_uri)) { g_free (real_desktop_uri); return TRUE; } return FALSE; } void nemo_drag_default_drop_action_for_icons (GdkDragContext *context, const char *target_uri_string, const GList *items, int *action, gchar **source_fs, gboolean *can_delete_source) { gboolean same_fs; gboolean target_is_source_parent; gboolean source_deletable; const char *dropped_uri; GFile *target, *dropped, *dropped_directory; GdkDragAction actions; NemoFile *dropped_file, *target_file; if (target_uri_string == NULL) { *action = 0; return; } actions = gdk_drag_context_get_actions (context) & (GDK_ACTION_MOVE | GDK_ACTION_COPY); if (actions == 0) { /* We can't use copy or move, just go with the suggested action. */ *action = gdk_drag_context_get_suggested_action (context); return; } if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_ASK) { /* Don't override ask */ *action = gdk_drag_context_get_suggested_action (context); return; } dropped_uri = ((NemoDragSelectionItem *)items->data)->uri; dropped_file = nemo_file_get_existing_by_uri (dropped_uri); /* To/from desktop preparation - since we are separate processes, we don't have the full filesystem * info on the source and destination - we only have the destination info. Creating a NemoFile for it * is an async operation, so here we'll grab the source filesystem type and store it for the duration of * the drag. We can use it to compare below with the destination type to ensure a proper move action - * (we default to copy when we can't confirm source and destination fs types are the same.) */ if (dropped_file == NULL && (uri_contains_desktop (target_uri_string) || uri_contains_desktop (dropped_uri))) { if (*source_fs == NULL) { GFile *source_file; source_file = g_file_new_for_uri (dropped_uri); if (g_file_is_native (source_file)) { GFileInfo *fs_info; GError *error = NULL; fs_info = g_file_query_info (source_file, G_FILE_ATTRIBUTE_ID_FILESYSTEM "," G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, G_FILE_QUERY_INFO_NONE, NULL, &error); if (error != NULL) { g_warning ("Cannot fetch filesystem type for drag involving the desktop: %s", error->message); g_clear_error (&error); } else { if (g_file_info_has_attribute (fs_info, G_FILE_ATTRIBUTE_ID_FILESYSTEM)) { *source_fs = g_strdup (g_file_info_get_attribute_string (fs_info, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); } else { *source_fs = NULL; } if (g_file_info_has_attribute (fs_info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE)) { *can_delete_source = g_file_info_get_attribute_boolean (fs_info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE); } else { *can_delete_source = FALSE; } } g_object_unref (fs_info); } g_object_unref (source_file); } } target_file = nemo_file_get_existing_by_uri (target_uri_string); /* * Check for trash URI. We do a find_directory for any Trash directory. * Passing 0 permissions as gnome-vfs would override the permissions * passed with 700 while creating .Trash directory */ if (eel_uri_is_trash (target_uri_string)) { /* Only move to Trash */ if (actions & GDK_ACTION_MOVE) { *action = GDK_ACTION_MOVE; } nemo_file_unref (dropped_file); nemo_file_unref (target_file); return; } else if (dropped_file != NULL && nemo_file_is_launcher (dropped_file)) { if (actions & GDK_ACTION_MOVE) { *action = GDK_ACTION_MOVE; } nemo_file_unref (dropped_file); nemo_file_unref (target_file); return; } else if (eel_uri_is_desktop (target_uri_string)) { target = nemo_get_desktop_location (); nemo_file_unref (target_file); target_file = nemo_file_get (target); if (eel_uri_is_desktop (dropped_uri)) { /* Only move to Desktop icons */ if (actions & GDK_ACTION_MOVE) { *action = GDK_ACTION_MOVE; } g_object_unref (target); nemo_file_unref (dropped_file); nemo_file_unref (target_file); return; } } else if (target_file != NULL && nemo_file_is_archive (target_file)) { *action = GDK_ACTION_COPY; nemo_file_unref (dropped_file); nemo_file_unref (target_file); return; } else { target = g_file_new_for_uri (target_uri_string); } same_fs = check_same_fs (target_file, dropped_file, *source_fs); nemo_file_unref (dropped_file); nemo_file_unref (target_file); /* Compare the first dropped uri with the target uri for same fs match. */ dropped = g_file_new_for_uri (dropped_uri); dropped_directory = g_file_get_parent (dropped); target_is_source_parent = FALSE; if (dropped_directory != NULL) { /* If the dropped file is already in the same directory but is in another filesystem we still want to move, not copy as this is then just a move of a mountpoint to another position in the dir */ target_is_source_parent = g_file_equal (dropped_directory, target); g_object_unref (dropped_directory); } source_deletable = source_is_deletable (dropped); if ((same_fs && (source_deletable || *can_delete_source)) || target_is_source_parent || g_file_has_uri_scheme (dropped, "trash")) { if (actions & GDK_ACTION_MOVE) { *action = GDK_ACTION_MOVE; } else { *action = gdk_drag_context_get_suggested_action (context); } } else { if (actions & GDK_ACTION_COPY) { *action = GDK_ACTION_COPY; } else { *action = gdk_drag_context_get_suggested_action (context); } } g_object_unref (target); g_object_unref (dropped); } GdkDragAction nemo_drag_default_drop_action_for_uri_list (GdkDragContext *context, const char *target_uri_string) { if (eel_uri_is_trash (target_uri_string) && (gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE)) { /* Only move to Trash */ return GDK_ACTION_MOVE; } else { return gdk_drag_context_get_suggested_action (context); } } /* Encode a "x-special/gnome-icon-list" selection. Along with the URIs of the dragged files, this encodes the location and size of each icon relative to the cursor. */ static void add_one_gnome_icon (const char *uri, int x, int y, int w, int h, gpointer data) { GString *result; result = (GString *) data; g_string_append_printf (result, "%s\r%d:%d:%hu:%hu\r\n", uri, x, y, w, h); } /* * Cf. #48423 */ #ifdef THIS_WAS_REALLY_BROKEN static gboolean is_path_that_gnome_uri_list_extract_filenames_can_parse (const char *path) { if (path == NULL || path [0] == '\0') { return FALSE; } /* It strips leading and trailing spaces. So it can't handle * file names with leading and trailing spaces. */ if (g_ascii_isspace (path [0])) { return FALSE; } if (g_ascii_isspace (path [strlen (path) - 1])) { return FALSE; } /* # works as a comment delimiter, and \r and \n are used to * separate the lines, so it can't handle file names with any * of these. */ if (strchr (path, '#') != NULL || strchr (path, '\r') != NULL || strchr (path, '\n') != NULL) { return FALSE; } return TRUE; } /* Encode a "text/plain" selection; this is a broken URL -- just * "file:" with a path after it (no escaping or anything). We are * trying to make the old gnome_uri_list_extract_filenames function * happy, so this is coded to its idiosyncrasises. */ static void add_one_compatible_uri (const char *uri, int x, int y, int w, int h, gpointer data) { GString *result; char *local_path; result = (GString *) data; /* For URLs that do not have a file: scheme, there's no harm * in passing the real URL. But for URLs that do have a file: * scheme, we have to send a URL that will work with the old * gnome-libs function or nothing will be able to understand * it. */ if (!g_str_has_prefix (uri, "file:")) { g_string_append (result, uri); g_string_append (result, "\r\n"); } else { local_path = g_filename_from_uri (uri, NULL, NULL); /* Check for characters that confuse the old * gnome_uri_list_extract_filenames implementation, and just leave * out any paths with those in them. */ if (is_path_that_gnome_uri_list_extract_filenames_can_parse (local_path)) { g_string_append (result, "file:"); g_string_append (result, local_path); g_string_append (result, "\r\n"); } g_free (local_path); } } #endif static void add_one_uri (const char *uri, int x, int y, int w, int h, gpointer data) { GString *result; result = (GString *) data; g_string_append (result, uri); g_string_append (result, "\r\n"); } /* Common function for drag_data_get_callback calls. * Returns FALSE if it doesn't handle drag data */ gboolean nemo_drag_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint32 time, gpointer container_context, NemoDragEachSelectedItemIterator each_selected_item_iterator) { GString *result; switch (info) { case NEMO_ICON_DND_GNOME_ICON_LIST: result = g_string_new (NULL); (* each_selected_item_iterator) (add_one_gnome_icon, container_context, result); break; case NEMO_ICON_DND_URI_LIST: case NEMO_ICON_DND_TEXT: result = g_string_new (NULL); (* each_selected_item_iterator) (add_one_uri, container_context, result); break; default: return FALSE; } gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *) result->str, result->len); g_string_free (result, TRUE); return TRUE; } typedef struct { GMainLoop *loop; GdkDragAction chosen; } DropActionMenuData; static void menu_deactivate_callback (GtkWidget *menu, gpointer data) { DropActionMenuData *damd; damd = data; if (g_main_loop_is_running (damd->loop)) g_main_loop_quit (damd->loop); } static void drop_action_activated_callback (GtkWidget *menu_item, gpointer data) { DropActionMenuData *damd; damd = data; damd->chosen = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "action")); if (g_main_loop_is_running (damd->loop)) g_main_loop_quit (damd->loop); } static void append_drop_action_menu_item (GtkWidget *menu, const char *text, GdkDragAction action, gboolean sensitive, DropActionMenuData *damd) { GtkWidget *menu_item; menu_item = gtk_menu_item_new_with_mnemonic (text); gtk_widget_set_sensitive (menu_item, sensitive); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); g_object_set_data (G_OBJECT (menu_item), "action", GINT_TO_POINTER (action)); g_signal_connect (menu_item, "activate", G_CALLBACK (drop_action_activated_callback), damd); gtk_widget_show (menu_item); } /* Pops up a menu of actions to perform on dropped files */ GdkDragAction nemo_drag_drop_action_ask (GtkWidget *widget, GdkDragAction actions) { GtkWidget *menu; GtkWidget *menu_item; DropActionMenuData damd; /* Create the menu and set the sensitivity of the items based on the * allowed actions. */ menu = gtk_menu_new (); gtk_menu_set_screen (GTK_MENU (menu), gtk_widget_get_screen (widget)); append_drop_action_menu_item (menu, _("_Move Here"), GDK_ACTION_MOVE, (actions & GDK_ACTION_MOVE) != 0, &damd); append_drop_action_menu_item (menu, _("_Copy Here"), GDK_ACTION_COPY, (actions & GDK_ACTION_COPY) != 0, &damd); append_drop_action_menu_item (menu, _("_Link Here"), GDK_ACTION_LINK, (actions & GDK_ACTION_LINK) != 0, &damd); eel_gtk_menu_append_separator (GTK_MENU (menu)); menu_item = gtk_menu_item_new_with_mnemonic (_("Cancel")); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); gtk_widget_show (menu_item); damd.chosen = 0; damd.loop = g_main_loop_new (NULL, FALSE); g_signal_connect (menu, "deactivate", G_CALLBACK (menu_deactivate_callback), &damd); gtk_grab_add (menu); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME); g_main_loop_run (damd.loop); gtk_grab_remove (menu); g_main_loop_unref (damd.loop); g_object_ref_sink (menu); g_object_unref (menu); return damd.chosen; } gboolean nemo_drag_autoscroll_in_scroll_region (GtkWidget *widget) { float x_scroll_delta, y_scroll_delta; nemo_drag_autoscroll_calculate_delta (widget, &x_scroll_delta, &y_scroll_delta); return x_scroll_delta != 0 || y_scroll_delta != 0; } void nemo_drag_autoscroll_calculate_delta (GtkWidget *widget, float *x_scroll_delta, float *y_scroll_delta) { GtkAllocation allocation; GdkDeviceManager *manager; GdkDevice *pointer; int x, y; g_assert (GTK_IS_WIDGET (widget)); manager = gdk_display_get_device_manager (gtk_widget_get_display (widget)); pointer = gdk_device_manager_get_client_pointer (manager); gdk_window_get_device_position (gtk_widget_get_window (widget), pointer, &x, &y, NULL); /* Find out if we are anywhere close to the tree view edges * to see if we need to autoscroll. */ *x_scroll_delta = 0; *y_scroll_delta = 0; if (x < AUTO_SCROLL_MARGIN) { *x_scroll_delta = (float)(x - AUTO_SCROLL_MARGIN); } gtk_widget_get_allocation (widget, &allocation); if (x > allocation.width - AUTO_SCROLL_MARGIN) { if (*x_scroll_delta != 0) { /* Already trying to scroll because of being too close to * the top edge -- must be the window is really short, * don't autoscroll. */ return; } *x_scroll_delta = (float)(x - (allocation.width - AUTO_SCROLL_MARGIN)); } if (y < AUTO_SCROLL_MARGIN) { *y_scroll_delta = (float)(y - AUTO_SCROLL_MARGIN); } if (y > allocation.height - AUTO_SCROLL_MARGIN) { if (*y_scroll_delta != 0) { /* Already trying to scroll because of being too close to * the top edge -- must be the window is really narrow, * don't autoscroll. */ return; } *y_scroll_delta = (float)(y - (allocation.height - AUTO_SCROLL_MARGIN)); } if (*x_scroll_delta == 0 && *y_scroll_delta == 0) { /* no work */ return; } /* Adjust the scroll delta to the proper acceleration values depending on how far * into the sroll margins we are. * FIXME bugzilla.eazel.com 2486: * we could use an exponential acceleration factor here for better feel */ if (*x_scroll_delta != 0) { *x_scroll_delta /= AUTO_SCROLL_MARGIN; *x_scroll_delta *= (MAX_AUTOSCROLL_DELTA - MIN_AUTOSCROLL_DELTA); *x_scroll_delta += MIN_AUTOSCROLL_DELTA; } if (*y_scroll_delta != 0) { *y_scroll_delta /= AUTO_SCROLL_MARGIN; *y_scroll_delta *= (MAX_AUTOSCROLL_DELTA - MIN_AUTOSCROLL_DELTA); *y_scroll_delta += MIN_AUTOSCROLL_DELTA; } } void nemo_drag_autoscroll_start (NemoDragInfo *drag_info, GtkWidget *widget, GSourceFunc callback, gpointer user_data) { if (nemo_drag_autoscroll_in_scroll_region (widget)) { if (drag_info->auto_scroll_timeout_id == 0) { drag_info->waiting_to_autoscroll = TRUE; drag_info->start_auto_scroll_in = g_get_monotonic_time () + AUTOSCROLL_INITIAL_DELAY; drag_info->auto_scroll_timeout_id = g_timeout_add (AUTOSCROLL_TIMEOUT_INTERVAL, callback, user_data); } } else { if (drag_info->auto_scroll_timeout_id != 0) { g_source_remove (drag_info->auto_scroll_timeout_id); drag_info->auto_scroll_timeout_id = 0; } } } void nemo_drag_autoscroll_stop (NemoDragInfo *drag_info) { if (drag_info->auto_scroll_timeout_id != 0) { g_source_remove (drag_info->auto_scroll_timeout_id); drag_info->auto_scroll_timeout_id = 0; } } gboolean nemo_drag_selection_includes_special_link (GList *selection_list) { GList *node; char *uri; for (node = selection_list; node != NULL; node = node->next) { uri = ((NemoDragSelectionItem *) node->data)->uri; if (eel_uri_is_desktop (uri)) { return TRUE; } } return FALSE; } nemo-3.6.5/libnemo-private/nemo-file-operations.c0000664000175000017500000053515013215733314020717 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-file-operations.c - Nemo file operations. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000, 2001 Eazel, Inc. Copyright (C) 2007 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Alexander Larsson Ettore Perazzoli Pavel Cisler */ #include #include #include #include #include #include #include #include #include #include #include "nemo-file-operations.h" #include "nemo-file-changes-queue.h" #include "nemo-lib-self-check-functions.h" #include "nemo-progress-info.h" #include #include #include #include #include #include #include #include #include #include #include "nemo-file-changes-queue.h" #include "nemo-file-private.h" #include "nemo-desktop-icon-file.h" #include "nemo-desktop-link-monitor.h" #include "nemo-global-preferences.h" #include "nemo-link.h" #include "nemo-desktop-utils.h" #include "nemo-trash-monitor.h" #include "nemo-file-utilities.h" #include "nemo-file-conflict-dialog.h" #include "nemo-file-undo-operations.h" #include "nemo-file-undo-manager.h" #include "nemo-job-queue.h" /* TODO: TESTING!!! */ typedef enum { OP_KIND_COPY, OP_KIND_MOVE, OP_KIND_DELETE, OP_KIND_TRASH, OP_KIND_EMPTY_TRASH, OP_KIND_DUPE, OP_KIND_PERMISSIONS, OP_KIND_LINK, OP_KIND_CREATE, OP_KIND_TRUST } OpKind; typedef struct { GIOSchedulerJob *io_job; GTimer *time; GtkWindow *parent_window; int monitor_num; int inhibit_cookie; NemoProgressInfo *progress; GCancellable *cancellable; GHashTable *skip_files; GHashTable *skip_readdir_error; NemoFileUndoInfo *undo_info; gboolean skip_all_error; gboolean skip_all_conflict; gboolean merge_all; gboolean replace_all; gboolean delete_all; } CommonJob; typedef struct { CommonJob common; gboolean is_move; GList *files; GFile *destination; GFile *desktop_location; GFile *fake_display_source; GdkPoint *icon_positions; int n_icon_positions; GHashTable *debuting_files; gchar *target_name; NemoCopyCallback done_callback; gpointer done_callback_data; } CopyMoveJob; typedef struct { CommonJob common; GList *files; gboolean try_trash; gboolean user_cancel; NemoDeleteCallback done_callback; gpointer done_callback_data; } DeleteJob; typedef struct { CommonJob common; GFile *dest_dir; char *filename; gboolean make_dir; GFile *src; char *src_data; int length; GdkPoint position; gboolean has_position; GFile *created_file; NemoCreateCallback done_callback; gpointer done_callback_data; } CreateJob; typedef struct { CommonJob common; GList *trash_dirs; gboolean should_confirm; NemoOpCallback done_callback; gpointer done_callback_data; } EmptyTrashJob; typedef struct { CommonJob common; GFile *file; gboolean interactive; NemoOpCallback done_callback; gpointer done_callback_data; } MarkTrustedJob; typedef struct { CommonJob common; GFile *file; NemoOpCallback done_callback; gpointer done_callback_data; guint32 file_permissions; guint32 file_mask; guint32 dir_permissions; guint32 dir_mask; } SetPermissionsJob; typedef struct { int num_files; goffset num_bytes; int num_files_since_progress; OpKind op; } SourceInfo; typedef struct { int num_files; goffset num_bytes; OpKind op; guint64 last_report_time; int last_reported_files_left; } TransferInfo; #define SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE 8 #define US_PER_MS 1000 #define PROGRESS_UPDATE_THRESHOLD 250 #define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50 #define IS_IO_ERROR(__error, KIND) (((__error)->domain == G_IO_ERROR && (__error)->code == G_IO_ERROR_ ## KIND)) #define SKIP _("_Skip") #define SKIP_ALL _("S_kip All") #define RETRY _("_Retry") #define DELETE_ALL _("Delete _All") #define REPLACE _("_Replace") #define REPLACE_ALL _("Replace _All") #define MERGE _("_Merge") #define MERGE_ALL _("Merge _All") #define COPY_FORCE _("Copy _Anyway") ; static void add_job_to_job_queue (GIOSchedulerJobFunc job_func, gpointer user_data, GCancellable *cancellable, NemoProgressInfo *info, OpKind kind); static void mark_desktop_file_trusted (CommonJob *common, GCancellable *cancellable, GFile *file, gboolean interactive); static gboolean is_all_button_text (const char *button_text) { g_assert (button_text != NULL); return !strcmp (button_text, SKIP_ALL) || !strcmp (button_text, REPLACE_ALL) || !strcmp (button_text, DELETE_ALL) || !strcmp (button_text, MERGE_ALL); } static void scan_sources (GList *files, SourceInfo *source_info, CommonJob *job, OpKind kind); static gboolean empty_trash_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data); static char * query_fs_type (GFile *file, GCancellable *cancellable); /* keep in time with format_time() * * This counts and outputs the number of “time units†* formatted and displayed by format_time(). * For instance, if format_time outputs “3 hours, 4 minutes†* it yields 7. */ static int seconds_count_format_time_units (int seconds) { int minutes; int hours; if (seconds < 0) { /* Just to make sure... */ seconds = 0; } if (seconds < 60) { /* seconds */ return seconds; } if (seconds < 60*60) { /* minutes */ minutes = seconds / 60; return minutes; } hours = seconds / (60*60); if (seconds < 60*60*4) { /* minutes + hours */ minutes = (seconds - hours * 60 * 60) / 60; return minutes + hours; } return hours; } static char * format_time (int seconds) { int minutes; int hours; char *res; if (seconds < 0) { /* Just to make sure... */ seconds = 0; } if (seconds < 60) { return g_strdup_printf (ngettext ("%'d second","%'d seconds", (int) seconds), (int) seconds); } if (seconds < 60*60) { minutes = seconds / 60; return g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes); } hours = seconds / (60*60); if (seconds < 60*60*4) { char *h, *m; minutes = (seconds - hours * 60 * 60) / 60; h = g_strdup_printf (ngettext ("%'d hour", "%'d hours", hours), hours); m = g_strdup_printf (ngettext ("%'d minute", "%'d minutes", minutes), minutes); res = g_strconcat (h, ", ", m, NULL); g_free (h); g_free (m); return res; } return g_strdup_printf (ngettext ("approximately %'d hour", "approximately %'d hours", hours), hours); } static char * shorten_utf8_string (const char *base, int reduce_by_num_bytes) { int len; char *ret; const char *p; len = strlen (base); len -= reduce_by_num_bytes; if (len <= 0) { return NULL; } ret = g_new (char, len + 1); p = base; while (len) { char *next; next = g_utf8_next_char (p); if (next - p > len || *next == '\0') { break; } len -= next - p; p = next; } if (p - base == 0) { g_free (ret); return NULL; } else { memcpy (ret, base, p - base); ret[p - base] = '\0'; return ret; } } /* Note that we have these two separate functions with separate format * strings for ease of localization. */ static char * get_link_name (const char *name, int count, int max_length) { const char *format; char *result; int unshortened_length; gboolean use_count; g_assert (name != NULL); if (count < 0) { g_warning ("bad count in get_link_name"); count = 0; } if (count <= 2) { /* Handle special cases for low numbers. * Perhaps for some locales we will need to add more. */ switch (count) { default: g_assert_not_reached (); /* fall through */ case 0: /* duplicate original file name */ format = "%s"; break; case 1: /* appended to new link file */ format = _("Link to %s"); break; case 2: /* appended to new link file */ format = _("Another link to %s"); break; } use_count = FALSE; } else { /* Handle special cases for the first few numbers of each ten. * For locales where getting this exactly right is difficult, * these can just be made all the same as the general case below. */ switch (count % 10) { case 1: /* Localizers: Feel free to leave out the "st" suffix * if there's no way to do that nicely for a * particular language. */ format = _("%'dst link to %s"); break; case 2: /* appended to new link file */ format = _("%'dnd link to %s"); break; case 3: /* appended to new link file */ format = _("%'drd link to %s"); break; default: /* appended to new link file */ format = _("%'dth link to %s"); break; } use_count = TRUE; } if (use_count) result = g_strdup_printf (format, count, name); else result = g_strdup_printf (format, name); if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) { char *new_name; new_name = shorten_utf8_string (name, unshortened_length - max_length); if (new_name) { g_free (result); if (use_count) result = g_strdup_printf (format, count, new_name); else result = g_strdup_printf (format, new_name); g_assert (strlen (result) <= max_length); g_free (new_name); } } return result; } /* Localizers: * Feel free to leave out the st, nd, rd and th suffix or * make some or all of them match. */ /* localizers: tag used to detect the first copy of a file */ static const char untranslated_copy_duplicate_tag[] = N_(" (copy)"); /* localizers: tag used to detect the second copy of a file */ static const char untranslated_another_copy_duplicate_tag[] = N_(" (another copy)"); /* localizers: tag used to detect the x11th copy of a file */ static const char untranslated_x11th_copy_duplicate_tag[] = N_("th copy)"); /* localizers: tag used to detect the x12th copy of a file */ static const char untranslated_x12th_copy_duplicate_tag[] = N_("th copy)"); /* localizers: tag used to detect the x13th copy of a file */ static const char untranslated_x13th_copy_duplicate_tag[] = N_("th copy)"); /* localizers: tag used to detect the x1st copy of a file */ static const char untranslated_st_copy_duplicate_tag[] = N_("st copy)"); /* localizers: tag used to detect the x2nd copy of a file */ static const char untranslated_nd_copy_duplicate_tag[] = N_("nd copy)"); /* localizers: tag used to detect the x3rd copy of a file */ static const char untranslated_rd_copy_duplicate_tag[] = N_("rd copy)"); /* localizers: tag used to detect the xxth copy of a file */ static const char untranslated_th_copy_duplicate_tag[] = N_("th copy)"); #define COPY_DUPLICATE_TAG _(untranslated_copy_duplicate_tag) #define ANOTHER_COPY_DUPLICATE_TAG _(untranslated_another_copy_duplicate_tag) #define X11TH_COPY_DUPLICATE_TAG _(untranslated_x11th_copy_duplicate_tag) #define X12TH_COPY_DUPLICATE_TAG _(untranslated_x12th_copy_duplicate_tag) #define X13TH_COPY_DUPLICATE_TAG _(untranslated_x13th_copy_duplicate_tag) #define ST_COPY_DUPLICATE_TAG _(untranslated_st_copy_duplicate_tag) #define ND_COPY_DUPLICATE_TAG _(untranslated_nd_copy_duplicate_tag) #define RD_COPY_DUPLICATE_TAG _(untranslated_rd_copy_duplicate_tag) #define TH_COPY_DUPLICATE_TAG _(untranslated_th_copy_duplicate_tag) /* localizers: appended to first file copy */ static const char untranslated_first_copy_duplicate_format[] = N_("%s (copy)%s"); /* localizers: appended to second file copy */ static const char untranslated_second_copy_duplicate_format[] = N_("%s (another copy)%s"); /* localizers: appended to x11th file copy */ static const char untranslated_x11th_copy_duplicate_format[] = N_("%s (%'dth copy)%s"); /* localizers: appended to x12th file copy */ static const char untranslated_x12th_copy_duplicate_format[] = N_("%s (%'dth copy)%s"); /* localizers: appended to x13th file copy */ static const char untranslated_x13th_copy_duplicate_format[] = N_("%s (%'dth copy)%s"); /* localizers: if in your language there's no difference between 1st, 2nd, 3rd and nth * plurals, you can leave the st, nd, rd suffixes out and just make all the translated * strings look like "%s (copy %'d)%s". */ /* localizers: appended to x1st file copy */ static const char untranslated_st_copy_duplicate_format[] = N_("%s (%'dst copy)%s"); /* localizers: appended to x2nd file copy */ static const char untranslated_nd_copy_duplicate_format[] = N_("%s (%'dnd copy)%s"); /* localizers: appended to x3rd file copy */ static const char untranslated_rd_copy_duplicate_format[] = N_("%s (%'drd copy)%s"); /* localizers: appended to xxth file copy */ static const char untranslated_th_copy_duplicate_format[] = N_("%s (%'dth copy)%s"); #define FIRST_COPY_DUPLICATE_FORMAT _(untranslated_first_copy_duplicate_format) #define SECOND_COPY_DUPLICATE_FORMAT _(untranslated_second_copy_duplicate_format) #define X11TH_COPY_DUPLICATE_FORMAT _(untranslated_x11th_copy_duplicate_format) #define X12TH_COPY_DUPLICATE_FORMAT _(untranslated_x12th_copy_duplicate_format) #define X13TH_COPY_DUPLICATE_FORMAT _(untranslated_x13th_copy_duplicate_format) #define ST_COPY_DUPLICATE_FORMAT _(untranslated_st_copy_duplicate_format) #define ND_COPY_DUPLICATE_FORMAT _(untranslated_nd_copy_duplicate_format) #define RD_COPY_DUPLICATE_FORMAT _(untranslated_rd_copy_duplicate_format) #define TH_COPY_DUPLICATE_FORMAT _(untranslated_th_copy_duplicate_format) static char * extract_string_until (const char *original, const char *until_substring) { char *result; g_assert ((int) strlen (original) >= until_substring - original); g_assert (until_substring - original >= 0); result = g_malloc (until_substring - original + 1); strncpy (result, original, until_substring - original); result[until_substring - original] = '\0'; return result; } /* Dismantle a file name, separating the base name, the file suffix and removing any * (xxxcopy), etc. string. Figure out the count that corresponds to the given * (xxxcopy) substring. */ static void parse_previous_duplicate_name (const char *name, char **name_base, const char **suffix, int *count) { const char *tag; g_assert (name[0] != '\0'); *suffix = eel_filename_get_extension_offset (name + 1); if (*suffix == NULL || (*suffix)[1] == '\0') { /* no suffix */ *suffix = ""; } tag = strstr (name, COPY_DUPLICATE_TAG); if (tag != NULL) { if (tag > *suffix) { /* handle case "foo. (copy)" */ *suffix = ""; } *name_base = extract_string_until (name, tag); *count = 1; return; } tag = strstr (name, ANOTHER_COPY_DUPLICATE_TAG); if (tag != NULL) { if (tag > *suffix) { /* handle case "foo. (another copy)" */ *suffix = ""; } *name_base = extract_string_until (name, tag); *count = 2; return; } /* Check to see if we got one of st, nd, rd, th. */ tag = strstr (name, X11TH_COPY_DUPLICATE_TAG); if (tag == NULL) { tag = strstr (name, X12TH_COPY_DUPLICATE_TAG); } if (tag == NULL) { tag = strstr (name, X13TH_COPY_DUPLICATE_TAG); } if (tag == NULL) { tag = strstr (name, ST_COPY_DUPLICATE_TAG); } if (tag == NULL) { tag = strstr (name, ND_COPY_DUPLICATE_TAG); } if (tag == NULL) { tag = strstr (name, RD_COPY_DUPLICATE_TAG); } if (tag == NULL) { tag = strstr (name, TH_COPY_DUPLICATE_TAG); } /* If we got one of st, nd, rd, th, fish out the duplicate number. */ if (tag != NULL) { /* localizers: opening parentheses to match the "th copy)" string */ tag = strstr (name, _(" (")); if (tag != NULL) { if (tag > *suffix) { /* handle case "foo. (22nd copy)" */ *suffix = ""; } *name_base = extract_string_until (name, tag); /* localizers: opening parentheses of the "th copy)" string */ if (sscanf (tag, _(" (%'d"), count) == 1) { if (*count < 1 || *count > 1000000) { /* keep the count within a reasonable range */ *count = 0; } return; } *count = 0; return; } } *count = 0; if (**suffix != '\0') { *name_base = extract_string_until (name, *suffix); } else { *name_base = g_strdup (name); } } static char * make_next_duplicate_name (const char *base, const char *suffix, int count, int max_length) { const char *format; char *result; int unshortened_length; gboolean use_count; if (count < 1) { g_warning ("bad count %d in get_duplicate_name", count); count = 1; } if (count <= 2) { /* Handle special cases for low numbers. * Perhaps for some locales we will need to add more. */ switch (count) { default: g_assert_not_reached (); /* fall through */ case 1: format = FIRST_COPY_DUPLICATE_FORMAT; break; case 2: format = SECOND_COPY_DUPLICATE_FORMAT; break; } use_count = FALSE; } else { /* Handle special cases for the first few numbers of each ten. * For locales where getting this exactly right is difficult, * these can just be made all the same as the general case below. */ /* Handle special cases for x11th - x20th. */ switch (count % 100) { case 11: format = X11TH_COPY_DUPLICATE_FORMAT; break; case 12: format = X12TH_COPY_DUPLICATE_FORMAT; break; case 13: format = X13TH_COPY_DUPLICATE_FORMAT; break; default: format = NULL; break; } if (format == NULL) { switch (count % 10) { case 1: format = ST_COPY_DUPLICATE_FORMAT; break; case 2: format = ND_COPY_DUPLICATE_FORMAT; break; case 3: format = RD_COPY_DUPLICATE_FORMAT; break; default: /* The general case. */ format = TH_COPY_DUPLICATE_FORMAT; break; } } use_count = TRUE; } if (use_count) result = g_strdup_printf (format, base, count, suffix); else result = g_strdup_printf (format, base, suffix); if (max_length > 0 && (unshortened_length = strlen (result)) > max_length) { char *new_base; new_base = shorten_utf8_string (base, unshortened_length - max_length); if (new_base) { g_free (result); if (use_count) result = g_strdup_printf (format, new_base, count, suffix); else result = g_strdup_printf (format, new_base, suffix); g_assert (strlen (result) <= max_length); g_free (new_base); } } return result; } static char * get_duplicate_name (const char *name, int count_increment, int max_length) { char *result; char *name_base; const char *suffix; int count; parse_previous_duplicate_name (name, &name_base, &suffix, &count); result = make_next_duplicate_name (name_base, suffix, count + count_increment, max_length); g_free (name_base); return result; } static gboolean has_invalid_xml_char (char *str) { gunichar c; while (*str != 0) { c = g_utf8_get_char (str); /* characters XML permits */ if (!(c == 0x9 || c == 0xA || c == 0xD || (c >= 0x20 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF))) { return TRUE; } str = g_utf8_next_char (str); } return FALSE; } static char * custom_full_name_to_string (char *format, va_list va) { GFile *file; file = va_arg (va, GFile *); return g_file_get_parse_name (file); } static void custom_full_name_skip (va_list *va) { (void) va_arg (*va, GFile *); } static char * custom_basename_to_string (char *format, va_list va) { GFile *file; GFileInfo *info; char *name, *basename, *tmp; file = va_arg (va, GFile *); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, g_cancellable_get_current (), NULL); name = NULL; if (info) { name = g_strdup (g_file_info_get_display_name (info)); g_object_unref (info); } if (name == NULL) { basename = g_file_get_basename (file); if (g_utf8_validate (basename, -1, NULL)) { name = basename; } else { name = g_uri_escape_string (basename, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); g_free (basename); } } /* Some chars can't be put in the markup we use for the dialogs... */ if (has_invalid_xml_char (name)) { tmp = name; name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); g_free (tmp); } /* Finally, if the string is too long, truncate it. */ if (name != NULL) { tmp = name; name = eel_str_middle_truncate (tmp, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH); g_free (tmp); } return name; } static void custom_basename_skip (va_list *va) { (void) va_arg (*va, GFile *); } static char * custom_size_to_string (char *format, va_list va) { goffset size; size = va_arg (va, goffset); int prefix; prefix = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES); return g_format_size_full (size, prefix); } static void custom_size_skip (va_list *va) { (void) va_arg (*va, goffset); } static char * custom_time_to_string (char *format, va_list va) { int secs; secs = va_arg (va, int); return format_time (secs); } static void custom_time_skip (va_list *va) { (void) va_arg (*va, int); } static char * custom_mount_to_string (char *format, va_list va) { GMount *mount; mount = va_arg (va, GMount *); return g_mount_get_name (mount); } static void custom_mount_skip (va_list *va) { (void) va_arg (*va, GMount *); } static EelPrintfHandler handlers[] = { { 'F', custom_full_name_to_string, custom_full_name_skip }, { 'B', custom_basename_to_string, custom_basename_skip }, { 'S', custom_size_to_string, custom_size_skip }, { 'T', custom_time_to_string, custom_time_skip }, { 'V', custom_mount_to_string, custom_mount_skip }, { 0 } }; static char * f (const char *format, ...) { va_list va; char *res; va_start (va, format); res = eel_strdup_vprintf_with_custom (handlers, format, va); va_end (va); return res; } static void get_best_name (GFile *file, gchar **name) { gchar *out; if (g_file_is_native (file)) { gchar *path = g_file_get_path (file); if (g_str_has_prefix (path, g_get_home_dir ())) { GString *str = g_string_new (path); str = g_string_erase (str, 0, strlen (g_get_home_dir ())); str = g_string_prepend (str, "~"); out = g_string_free (str, FALSE); } else { out = g_strdup (path); } g_free (path); } else { out = g_file_get_basename (file); } *name = out; } static void get_parent_name (GFile *file, gchar **name) { GFile *parent = g_file_get_parent (file); if (!parent) return; gchar *get = NULL; get_best_name (parent, &get); g_object_unref (parent); *name = get; } /* adapted from gio/glocalfile.c */ static gboolean _g_local_file_delete (GFile *file, GCancellable *cancellable, GError **error) { gchar *path; path = g_file_get_path (file); if (g_remove (path) == -1) { int errsv = errno; /* Posix allows EEXIST too, but the more sane error is G_IO_ERROR_NOT_FOUND, and it's what nautilus expects */ if (errsv == EEXIST) { errsv = ENOTEMPTY; } g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error removing file: %s"), g_strerror (errsv)); g_free (path); return FALSE; } g_free (path); return TRUE; } static gboolean file_delete_wrapper (GFile *file, GCancellable *cancellable, GError **error) { gboolean ret; ret = FALSE; if (g_file_is_native (file)) { ret = _g_local_file_delete (file, cancellable, error); } else { ret = g_file_delete (file, cancellable, error); } return ret; } static void generate_initial_job_details (NemoProgressInfo *info, OpKind kind, GList *files, GFile *destination) { gchar *s = NULL; gchar *dest_name = NULL; gchar *src_name = NULL; if (destination != NULL) get_best_name (destination, &dest_name); if (files != NULL) get_parent_name (files->data, &src_name); switch (kind) { case OP_KIND_COPY: g_return_if_fail (files != NULL); g_return_if_fail (destination != NULL); s = f (ngettext("Waiting to copy a file from '%1$s' to '%2$s'", "Waiting to copy files from '%1$s' to '%2$s'", g_list_length (files)), src_name, dest_name); break; case OP_KIND_MOVE: g_return_if_fail (files != NULL); g_return_if_fail (destination != NULL); s = f (ngettext("Waiting to move a file from '%1$s' to '%2$s'", "Waiting to move files from '%1$s' to '%2$s'", g_list_length (files)), src_name, dest_name); break; case OP_KIND_DELETE: g_return_if_fail (files != NULL); s = f (ngettext("Waiting to permanently delete a file from '%s'", "Waiting to permanently delete files from '%s'", g_list_length (files)), src_name); break; case OP_KIND_TRASH: g_return_if_fail (files != NULL); s = f (ngettext("Waiting to trash a file in '%s'", "Waiting to trash files in '%s'", g_list_length (files)), src_name); break; case OP_KIND_EMPTY_TRASH: s = f (_("Waiting to empty the trash")); break; case OP_KIND_DUPE: g_return_if_fail (files != NULL); g_return_if_fail (destination != NULL); s = f (ngettext("Waiting to duplicate a file in '%s'", "Waiting to duplicate files in '%s'", g_list_length (files)), dest_name); break; case OP_KIND_PERMISSIONS: g_return_if_fail (destination != NULL); s = f (_("Waiting to change permissions of files in '%s'"), dest_name); break; case OP_KIND_LINK: g_return_if_fail (files != NULL); g_return_if_fail (destination != NULL); s = f (ngettext("Waiting to link a file from '%1$s' to '%2$s'", "Waiting to link files from '%1$s' to '%2$s'", g_list_length (files)), src_name, dest_name); break; default: break; } g_free (dest_name); g_free (src_name); nemo_progress_info_take_initial_details (info, s); } #define op_job_new(__type, parent_window) ((__type *)(init_common (sizeof(__type), parent_window))) static gpointer init_common (gsize job_size, GtkWindow *parent_window) { CommonJob *common; common = g_malloc0 (job_size); if (parent_window) { common->parent_window = parent_window; g_object_add_weak_pointer (G_OBJECT (common->parent_window), (gpointer *) &common->parent_window); } common->progress = nemo_progress_info_new (); common->cancellable = nemo_progress_info_get_cancellable (common->progress); common->time = g_timer_new (); common->inhibit_cookie = -1; common->monitor_num = 0; if (parent_window) { common->monitor_num = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (parent_window)); } return common; } static void finalize_common (CommonJob *common) { nemo_progress_info_finish (common->progress); if (common->inhibit_cookie != -1) { nemo_uninhibit_power_manager (common->inhibit_cookie); } common->inhibit_cookie = -1; g_timer_destroy (common->time); if (common->parent_window) { g_object_remove_weak_pointer (G_OBJECT (common->parent_window), (gpointer *) &common->parent_window); } if (common->skip_files) { g_hash_table_destroy (common->skip_files); } if (common->skip_readdir_error) { g_hash_table_destroy (common->skip_readdir_error); } if (common->undo_info != NULL) { nemo_file_undo_manager_set_action (common->undo_info); g_object_unref (common->undo_info); } g_object_unref (common->progress); g_object_unref (common->cancellable); g_free (common); } static void skip_file (CommonJob *common, GFile *file) { if (common->skip_files == NULL) { common->skip_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); } g_hash_table_insert (common->skip_files, g_object_ref (file), file); } static void skip_readdir_error (CommonJob *common, GFile *dir) { if (common->skip_readdir_error == NULL) { common->skip_readdir_error = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); } g_hash_table_insert (common->skip_readdir_error, g_object_ref (dir), dir); } static gboolean should_skip_file (CommonJob *common, GFile *file) { if (common->skip_files != NULL) { return g_hash_table_lookup (common->skip_files, file) != NULL; } return FALSE; } static gboolean should_skip_readdir_error (CommonJob *common, GFile *dir) { if (common->skip_readdir_error != NULL) { return g_hash_table_lookup (common->skip_readdir_error, dir) != NULL; } return FALSE; } static gboolean can_delete_without_confirm (GFile *file) { if (g_file_has_uri_scheme (file, "burn") || g_file_has_uri_scheme (file, "recent") || g_file_has_uri_scheme (file, "x-nemo-desktop")) { return TRUE; } return FALSE; } static gboolean can_delete_files_without_confirm (GList *files) { g_assert (files != NULL); while (files != NULL) { if (!can_delete_without_confirm (files->data)) { return FALSE; } files = files->next; } return TRUE; } typedef struct { GtkWindow **parent_window; gboolean ignore_close_box; GtkMessageType message_type; const char *primary_text; const char *secondary_text; const char *details_text; const char **button_titles; gboolean show_all; int result; } RunSimpleDialogData; static gboolean do_run_simple_dialog (gpointer _data) { RunSimpleDialogData *data = _data; const char *button_title; GtkWidget *dialog; int result; int response_id; /* Create the dialog. */ dialog = gtk_message_dialog_new (*data->parent_window, 0, data->message_type, GTK_BUTTONS_NONE, NULL); g_object_set (dialog, "text", data->primary_text, "secondary-text", data->secondary_text, NULL); for (response_id = 0; data->button_titles[response_id] != NULL; response_id++) { button_title = data->button_titles[response_id]; if (!data->show_all && is_all_button_text (button_title)) { continue; } gtk_dialog_add_button (GTK_DIALOG (dialog), button_title, response_id); gtk_dialog_set_default_response (GTK_DIALOG (dialog), response_id); } if (data->details_text) { eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog), data->details_text); } /* Run it. */ result = gtk_dialog_run (GTK_DIALOG (dialog)); while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && data->ignore_close_box) { result = gtk_dialog_run (GTK_DIALOG (dialog)); } gtk_widget_destroy (dialog); data->result = result; return FALSE; } /* NOTE: This frees the primary / secondary strings, in order to avoid doing that everywhere. So, make sure they are strduped */ static int run_simple_dialog_va (CommonJob *job, gboolean ignore_close_box, GtkMessageType message_type, char *primary_text, char *secondary_text, const char *details_text, gboolean show_all, va_list varargs) { RunSimpleDialogData *data; int res; const char *button_title; GPtrArray *ptr_array; g_timer_stop (job->time); data = g_new0 (RunSimpleDialogData, 1); data->parent_window = &job->parent_window; data->ignore_close_box = ignore_close_box; data->message_type = message_type; data->primary_text = primary_text; data->secondary_text = secondary_text; data->details_text = details_text; data->show_all = show_all; ptr_array = g_ptr_array_new (); while ((button_title = va_arg (varargs, const char *)) != NULL) { g_ptr_array_add (ptr_array, (char *)button_title); } g_ptr_array_add (ptr_array, NULL); data->button_titles = (const char **)g_ptr_array_free (ptr_array, FALSE); nemo_progress_info_pause (job->progress); g_io_scheduler_job_send_to_mainloop (job->io_job, do_run_simple_dialog, data, NULL); nemo_progress_info_resume (job->progress); res = data->result; g_free (data->button_titles); g_free (data); g_timer_continue (job->time); g_free (primary_text); g_free (secondary_text); return res; } #if 0 /* Not used at the moment */ static int run_simple_dialog (CommonJob *job, gboolean ignore_close_box, GtkMessageType message_type, char *primary_text, char *secondary_text, const char *details_text, ...) { va_list varargs; int res; va_start (varargs, details_text); res = run_simple_dialog_va (job, ignore_close_box, message_type, primary_text, secondary_text, details_text, varargs); va_end (varargs); return res; } #endif static int run_error (CommonJob *job, char *primary_text, char *secondary_text, const char *details_text, gboolean show_all, ...) { va_list varargs; int res; va_start (varargs, show_all); res = run_simple_dialog_va (job, FALSE, GTK_MESSAGE_ERROR, primary_text, secondary_text, details_text, show_all, varargs); va_end (varargs); return res; } static int run_warning (CommonJob *job, char *primary_text, char *secondary_text, const char *details_text, gboolean show_all, ...) { va_list varargs; int res; va_start (varargs, show_all); res = run_simple_dialog_va (job, FALSE, GTK_MESSAGE_WARNING, primary_text, secondary_text, details_text, show_all, varargs); va_end (varargs); return res; } static int run_question (CommonJob *job, char *primary_text, char *secondary_text, const char *details_text, gboolean show_all, ...) { va_list varargs; int res; va_start (varargs, show_all); res = run_simple_dialog_va (job, FALSE, GTK_MESSAGE_QUESTION, primary_text, secondary_text, details_text, show_all, varargs); va_end (varargs); return res; } static void inhibit_power_manager (CommonJob *job, const char *message) { job->inhibit_cookie = nemo_inhibit_power_manager (message); } static void abort_job (CommonJob *job) { /* destroy the undo action data too */ g_clear_object (&job->undo_info); g_cancellable_cancel (job->cancellable); } static gboolean job_aborted (CommonJob *job) { return g_cancellable_is_cancelled (job->cancellable); } /* Since this happens on a thread we can't use the global prefs object */ static gboolean should_confirm_trash (void) { gboolean confirm_trash; confirm_trash = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CONFIRM_TRASH); return confirm_trash; } static gboolean confirm_delete_from_trash (CommonJob *job, GList *files) { char *prompt; int file_count; int response; /* Just Say Yes if the preference says not to confirm. */ if (!should_confirm_trash ()) { return TRUE; } file_count = g_list_length (files); g_assert (file_count > 0); if (file_count == 1) { prompt = f (_("Are you sure you want to permanently delete \"%B\" " "from the trash?"), files->data); } else { prompt = f (ngettext("Are you sure you want to permanently delete " "the %'d selected item from the trash?", "Are you sure you want to permanently delete " "the %'d selected items from the trash?", file_count), file_count); } response = run_warning (job, prompt, f (_("If you delete an item, it will be permanently lost.")), NULL, FALSE, GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL); return (response == 1); } static gboolean confirm_empty_trash (CommonJob *job) { char *prompt; int response; /* Just Say Yes if the preference says not to confirm. */ if (!should_confirm_trash ()) { return TRUE; } prompt = f (_("Empty all items from Trash?")); response = run_warning (job, prompt, f(_("All items in the Trash will be permanently deleted.")), NULL, FALSE, GTK_STOCK_CANCEL, _("Empty _Trash"), NULL); return (response == 1); } static gboolean confirm_delete_directly (CommonJob *job, GList *files) { char *prompt; int file_count; int response; /* Just Say Yes if the preference says not to confirm. */ if (!should_confirm_trash ()) { return TRUE; } file_count = g_list_length (files); g_assert (file_count > 0); if (can_delete_files_without_confirm (files)) { return TRUE; } if (file_count == 1) { prompt = f (_("Are you sure you want to permanently delete \"%B\"?"), files->data); } else { prompt = f (ngettext("Are you sure you want to permanently delete " "the %'d selected item?", "Are you sure you want to permanently delete " "the %'d selected items?", file_count), file_count); } response = run_warning (job, prompt, f (_("If you delete an item, it will be permanently lost.")), NULL, FALSE, GTK_STOCK_CANCEL, GTK_STOCK_DELETE, NULL); return response == 1; } static void report_delete_progress (CommonJob *job, SourceInfo *source_info, TransferInfo *transfer_info) { int files_left; double elapsed, transfer_rate; int remaining_time; gint64 now; char *files_left_s; now = g_get_monotonic_time (); if (transfer_info->last_report_time != 0 && ABS ((gint64)(transfer_info->last_report_time - now)) < PROGRESS_UPDATE_THRESHOLD * US_PER_MS) { return; } transfer_info->last_report_time = now; files_left = source_info->num_files - transfer_info->num_files; /* Races and whatnot could cause this to be negative... */ if (files_left < 0) { files_left = 1; } files_left_s = f (ngettext ("%'d file left to delete", "%'d files left to delete", files_left), files_left); nemo_progress_info_take_status (job->progress, f (_("Deleting files"))); elapsed = g_timer_elapsed (job->time, NULL); if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE) { nemo_progress_info_set_details (job->progress, files_left_s); } else { char *details, *time_left_s; transfer_rate = transfer_info->num_files / elapsed; remaining_time = files_left / transfer_rate; /* To translators: %T will expand to a time like "2 minutes". * The singular/plural form will be used depending on the remaining time (i.e. the %T argument). */ time_left_s = f (ngettext ("%T left", "%T left", seconds_count_format_time_units (remaining_time)), remaining_time); details = g_strconcat (files_left_s, "\xE2\x80\x94", time_left_s, NULL); nemo_progress_info_take_details (job->progress, details); g_free (time_left_s); } g_free (files_left_s); if (source_info->num_files != 0) { nemo_progress_info_set_progress (job->progress, transfer_info->num_files, source_info->num_files); } } static void delete_file (CommonJob *job, GFile *file, gboolean *skipped_file, SourceInfo *source_info, TransferInfo *transfer_info, gboolean toplevel); static void delete_dir (CommonJob *job, GFile *dir, gboolean *skipped_file, SourceInfo *source_info, TransferInfo *transfer_info, gboolean toplevel) { GFileInfo *info; GError *error; GFile *file; GFileEnumerator *enumerator; char *primary, *secondary, *details; int response; gboolean skip_error; gboolean local_skipped_file; local_skipped_file = FALSE; skip_error = should_skip_readdir_error (job, dir); retry: error = NULL; enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, &error); if (enumerator) { error = NULL; while (!job_aborted (job) && (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error)) != NULL) { file = g_file_get_child (dir, g_file_info_get_name (info)); delete_file (job, file, &local_skipped_file, source_info, transfer_info, FALSE); g_object_unref (file); g_object_unref (info); } g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); if (error && IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else if (error) { primary = f (_("Error while deleting.")); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("Files in the folder \"%B\" cannot be deleted because you do " "not have permissions to see them."), dir); } else { secondary = f (_("There was an error getting information about the files in the folder \"%B\"."), dir); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, _("_Skip files"), NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* Skip: Do Nothing */ local_skipped_file = TRUE; } else { g_assert_not_reached (); } } } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { primary = f (_("Error while deleting.")); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("The folder \"%B\" cannot be deleted because you do not have " "permissions to read it."), dir); } else { secondary = f (_("There was an error reading the folder \"%B\"."), dir); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, SKIP, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* Skip: Do Nothing */ local_skipped_file = TRUE; } else if (response == 2) { goto retry; } else { g_assert_not_reached (); } } if (!job_aborted (job) && /* Don't delete dir if there was a skipped file */ !local_skipped_file) { if (!file_delete_wrapper (dir, job->cancellable, &error)) { if (job->skip_all_error) { goto skip; } primary = f (_("Error while deleting.")); secondary = f (_("Could not remove the folder %B."), dir); details = error->message; response = run_warning (job, primary, secondary, details, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; local_skipped_file = TRUE; } else if (response == 2) { /* skip */ local_skipped_file = TRUE; } else { g_assert_not_reached (); } skip: g_error_free (error); } else { nemo_file_changes_queue_file_removed (dir); transfer_info->num_files ++; report_delete_progress (job, source_info, transfer_info); return; } } if (local_skipped_file) { *skipped_file = TRUE; } } static void delete_file (CommonJob *job, GFile *file, gboolean *skipped_file, SourceInfo *source_info, TransferInfo *transfer_info, gboolean toplevel) { GError *error; char *primary, *secondary, *details; int response; if (should_skip_file (job, file)) { *skipped_file = TRUE; return; } error = NULL; if (file_delete_wrapper (file, job->cancellable, &error)) { nemo_file_changes_queue_file_removed (file); transfer_info->num_files ++; report_delete_progress (job, source_info, transfer_info); return; } if (IS_IO_ERROR (error, NOT_EMPTY)) { g_error_free (error); delete_dir (job, file, skipped_file, source_info, transfer_info, toplevel); return; } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { if (job->skip_all_error) { goto skip; } primary = f (_("Error while deleting.")); secondary = f (_("There was an error deleting %B."), file); details = error->message; response = run_warning (job, primary, secondary, details, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } skip: g_error_free (error); } *skipped_file = TRUE; } static void delete_files (CommonJob *job, GList *files, int *files_skipped) { GList *l; GFile *file; SourceInfo source_info; TransferInfo transfer_info; gboolean skipped_file; if (job_aborted (job)) { return; } scan_sources (files, &source_info, job, OP_KIND_DELETE); if (job_aborted (job)) { return; } g_timer_start (job->time); memset (&transfer_info, 0, sizeof (transfer_info)); report_delete_progress (job, &source_info, &transfer_info); for (l = files; l != NULL && !job_aborted (job); l = l->next) { file = l->data; skipped_file = FALSE; delete_file (job, file, &skipped_file, &source_info, &transfer_info, TRUE); if (skipped_file) { (*files_skipped)++; } } } static void report_trash_progress (CommonJob *job, int files_trashed, int total_files) { int files_left; char *s; files_left = total_files - files_trashed; nemo_progress_info_take_status (job->progress, f (_("Moving files to trash"))); s = f (ngettext ("%'d file left to trash", "%'d files left to trash", files_left), files_left); nemo_progress_info_take_details (job->progress, s); if (total_files != 0) { nemo_progress_info_set_progress (job->progress, files_trashed, total_files); } } static void trash_files (CommonJob *job, GList *files, int *files_skipped) { GList *l; GFile *file; GList *to_delete; GError *error; int total_files, files_trashed; char *primary, *secondary, *details; int response; if (job_aborted (job)) { return; } total_files = g_list_length (files); files_trashed = 0; report_trash_progress (job, files_trashed, total_files); to_delete = NULL; for (l = files; l != NULL && !job_aborted (job); l = l->next) { file = l->data; error = NULL; if (!g_file_trash (file, job->cancellable, &error)) { if (job->skip_all_error) { (*files_skipped)++; goto skip; } if (job->delete_all) { to_delete = g_list_prepend (to_delete, file); goto skip; } primary = f (_("Cannot move file to trash, do you want to delete immediately?")); secondary = f (_("The file \"%B\" cannot be moved to the trash."), file); details = NULL; if (!IS_IO_ERROR (error, NOT_SUPPORTED)) { details = error->message; } response = run_question (job, primary, secondary, details, (total_files - files_trashed) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, DELETE_ALL, GTK_STOCK_DELETE, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { ((DeleteJob *) job)->user_cancel = TRUE; abort_job (job); } else if (response == 1) { /* skip all */ (*files_skipped)++; job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ (*files_skipped)++; } else if (response == 3) { /* delete all */ to_delete = g_list_prepend (to_delete, file); job->delete_all = TRUE; } else if (response == 4) { /* delete */ to_delete = g_list_prepend (to_delete, file); } skip: g_error_free (error); total_files--; } else { nemo_file_changes_queue_file_removed (file); if (job->undo_info != NULL) { nemo_file_undo_info_trash_add_file (NEMO_FILE_UNDO_INFO_TRASH (job->undo_info), file); } files_trashed++; report_trash_progress (job, files_trashed, total_files); } } if (to_delete) { to_delete = g_list_reverse (to_delete); delete_files (job, to_delete, files_skipped); g_list_free (to_delete); } } static gboolean delete_job_done (gpointer user_data) { DeleteJob *job; GHashTable *debuting_uris; job = user_data; g_list_free_full (job->files, g_object_unref); if (job->done_callback) { debuting_uris = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); job->done_callback (debuting_uris, job->user_cancel, job->done_callback_data); g_hash_table_unref (debuting_uris); } finalize_common ((CommonJob *)job); nemo_file_changes_consume_changes (TRUE); return FALSE; } static gboolean delete_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { DeleteJob *job = user_data; GList *to_trash_files; GList *to_delete_files; GList *l; GFile *file; gboolean confirmed; CommonJob *common; gboolean must_confirm_delete_in_trash; gboolean must_confirm_delete; int files_skipped; common = (CommonJob *)job; common->io_job = io_job; nemo_progress_info_start (common->progress); to_trash_files = NULL; to_delete_files = NULL; must_confirm_delete_in_trash = FALSE; must_confirm_delete = FALSE; files_skipped = 0; for (l = job->files; l != NULL; l = l->next) { file = l->data; if (job->try_trash && g_file_has_uri_scheme (file, "trash")) { must_confirm_delete_in_trash = TRUE; to_delete_files = g_list_prepend (to_delete_files, file); } else if (can_delete_without_confirm (file)) { to_delete_files = g_list_prepend (to_delete_files, file); } else { if (job->try_trash) { to_trash_files = g_list_prepend (to_trash_files, file); } else { must_confirm_delete = TRUE; to_delete_files = g_list_prepend (to_delete_files, file); } } } if (to_delete_files != NULL && !job_aborted (common)) { to_delete_files = g_list_reverse (to_delete_files); confirmed = TRUE; if (must_confirm_delete_in_trash) { confirmed = confirm_delete_from_trash (common, to_delete_files); } else if (must_confirm_delete) { confirmed = confirm_delete_directly (common, to_delete_files); } if (confirmed) { delete_files (common, to_delete_files, &files_skipped); } else { job->user_cancel = TRUE; } } if (to_trash_files != NULL) { to_trash_files = g_list_reverse (to_trash_files); trash_files (common, to_trash_files, &files_skipped); } g_list_free (to_trash_files); g_list_free (to_delete_files); if (files_skipped == g_list_length (job->files)) { /* User has skipped all files, report user cancel */ job->user_cancel = TRUE; } g_io_scheduler_job_send_to_mainloop_async (io_job, delete_job_done, job, NULL); return FALSE; } static void trash_or_delete_internal (GList *files, GtkWindow *parent_window, gboolean try_trash, NemoDeleteCallback done_callback, gpointer done_callback_data) { DeleteJob *job; /* TODO: special case desktop icon link files ... */ job = op_job_new (DeleteJob, parent_window); job->files = eel_g_object_list_copy (files); job->try_trash = try_trash; job->user_cancel = FALSE; job->done_callback = done_callback; job->done_callback_data = done_callback_data; if (try_trash) { inhibit_power_manager ((CommonJob *)job, _("Trashing Files")); } else { inhibit_power_manager ((CommonJob *)job, _("Deleting Files")); } if (try_trash && !nemo_file_undo_manager_pop_flag ()) { job->common.undo_info = nemo_file_undo_info_trash_new (g_list_length (files)); } generate_initial_job_details (job->common.progress, try_trash ? OP_KIND_TRASH : OP_KIND_DELETE, job->files, NULL); add_job_to_job_queue (delete_job, job, job->common.cancellable, job->common.progress, try_trash ? OP_KIND_TRASH : OP_KIND_DELETE); } void nemo_file_operations_trash_or_delete (GList *files, GtkWindow *parent_window, NemoDeleteCallback done_callback, gpointer done_callback_data) { g_return_if_fail (files != NULL); trash_or_delete_internal (files, parent_window, TRUE, done_callback, done_callback_data); } void nemo_file_operations_delete (GList *files, GtkWindow *parent_window, NemoDeleteCallback done_callback, gpointer done_callback_data) { trash_or_delete_internal (files, parent_window, FALSE, done_callback, done_callback_data); } typedef struct { gboolean eject; GMount *mount; GMountOperation *mount_operation; GtkWindow *parent_window; NemoUnmountCallback callback; gpointer callback_data; } UnmountData; static void unmount_data_free (UnmountData *data) { if (data->parent_window) { g_object_remove_weak_pointer (G_OBJECT (data->parent_window), (gpointer *) &data->parent_window); } g_clear_object (&data->mount_operation); g_object_unref (data->mount); g_free (data); } static void unmount_mount_callback (GObject *source_object, GAsyncResult *res, gpointer user_data) { UnmountData *data = user_data; GError *error; char *primary; gboolean unmounted; error = NULL; if (data->eject) { unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error); } else { unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object), res, &error); } if (! unmounted) { if (error->code != G_IO_ERROR_FAILED_HANDLED) { if (data->eject) { primary = f (_("Unable to eject %V"), source_object); } else { primary = f (_("Unable to unmount %V"), source_object); } eel_show_error_dialog (primary, error->message, data->parent_window); g_free (primary); } } if (data->callback) { data->callback (data->callback_data); } if (error != NULL) { g_error_free (error); } unmount_data_free (data); } static void do_unmount (UnmountData *data) { GMountOperation *mount_op; if (data->mount_operation) { mount_op = g_object_ref (data->mount_operation); } else { mount_op = gtk_mount_operation_new (data->parent_window); } if (data->eject) { g_mount_eject_with_operation (data->mount, 0, mount_op, NULL, unmount_mount_callback, data); } else { g_mount_unmount_with_operation (data->mount, 0, mount_op, NULL, unmount_mount_callback, data); } g_object_unref (mount_op); } static gboolean dir_has_files (GFile *dir) { GFileEnumerator *enumerator; gboolean res; GFileInfo *file_info; res = FALSE; enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, 0, NULL, NULL); if (enumerator) { file_info = g_file_enumerator_next_file (enumerator, NULL, NULL); if (file_info != NULL) { res = TRUE; g_object_unref (file_info); } g_file_enumerator_close (enumerator, NULL, NULL); g_object_unref (enumerator); } return res; } static GList * get_trash_dirs_for_mount (GMount *mount) { GFile *root; GFile *trash; char *relpath; GList *list; root = g_mount_get_root (mount); if (root == NULL) { return NULL; } list = NULL; if (g_file_is_native (root)) { relpath = g_strdup_printf (".Trash/%d", getuid ()); trash = g_file_resolve_relative_path (root, relpath); g_free (relpath); list = g_list_prepend (list, g_file_get_child (trash, "files")); list = g_list_prepend (list, g_file_get_child (trash, "info")); g_object_unref (trash); relpath = g_strdup_printf (".Trash-%d", getuid ()); trash = g_file_get_child (root, relpath); g_free (relpath); list = g_list_prepend (list, g_file_get_child (trash, "files")); list = g_list_prepend (list, g_file_get_child (trash, "info")); g_object_unref (trash); } g_object_unref (root); return list; } static gboolean has_trash_files (GMount *mount) { GList *dirs, *l; GFile *dir; gboolean res; dirs = get_trash_dirs_for_mount (mount); res = FALSE; for (l = dirs; l != NULL; l = l->next) { dir = l->data; if (dir_has_files (dir)) { res = TRUE; break; } } g_list_free_full (dirs, g_object_unref); return res; } static gint prompt_empty_trash (GtkWindow *parent_window) { gint result; GtkWidget *dialog; GdkScreen *screen; screen = NULL; if (parent_window != NULL) { screen = gtk_widget_get_screen (GTK_WIDGET (parent_window)); } /* Do we need to be modal ? */ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, _("Do you want to empty the trash before you unmount?")); gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), _("In order to regain the " "free space on this volume " "the trash must be emptied. " "All trashed items on the volume " "will be permanently lost.")); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Do _not Empty Trash"), GTK_RESPONSE_REJECT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("Empty _Trash"), GTK_RESPONSE_ACCEPT, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); gtk_window_set_title (GTK_WINDOW (dialog), ""); /* as per HIG */ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE); if (screen) { gtk_window_set_screen (GTK_WINDOW (dialog), screen); } atk_object_set_role (gtk_widget_get_accessible (dialog), ATK_ROLE_ALERT); gtk_window_set_wmclass (GTK_WINDOW (dialog), "empty_trash", "Nemo"); /* Make transient for the window group */ gtk_widget_realize (dialog); if (screen != NULL) { gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (dialog)), gdk_screen_get_root_window (screen)); } result = gtk_dialog_run (GTK_DIALOG (dialog)); gtk_widget_destroy (dialog); return result; } static void empty_trash_for_unmount_done (gboolean success, gpointer user_data) { UnmountData *data = user_data; do_unmount (data); } void nemo_file_operations_unmount_mount_full (GtkWindow *parent_window, GMount *mount, GMountOperation *mount_operation, gboolean eject, gboolean check_trash, NemoUnmountCallback callback, gpointer callback_data) { UnmountData *data; int response; data = g_new0 (UnmountData, 1); data->callback = callback; data->callback_data = callback_data; if (parent_window) { data->parent_window = parent_window; g_object_add_weak_pointer (G_OBJECT (data->parent_window), (gpointer *) &data->parent_window); } if (mount_operation) { data->mount_operation = g_object_ref (mount_operation); } data->eject = eject; data->mount = g_object_ref (mount); if (check_trash && has_trash_files (mount)) { response = prompt_empty_trash (parent_window); if (response == GTK_RESPONSE_ACCEPT) { EmptyTrashJob *job; job = op_job_new (EmptyTrashJob, parent_window); job->should_confirm = FALSE; job->trash_dirs = get_trash_dirs_for_mount (mount); job->done_callback = empty_trash_for_unmount_done; job->done_callback_data = data; generate_initial_job_details (job->common.progress, OP_KIND_EMPTY_TRASH, NULL, NULL); add_job_to_job_queue (empty_trash_job, job, job->common.cancellable, job->common.progress, OP_KIND_EMPTY_TRASH); return; } else if (response == GTK_RESPONSE_CANCEL) { if (callback) { callback (callback_data); } unmount_data_free (data); return; } } do_unmount (data); } void nemo_file_operations_unmount_mount (GtkWindow *parent_window, GMount *mount, gboolean eject, gboolean check_trash) { nemo_file_operations_unmount_mount_full (parent_window, mount, NULL, eject, check_trash, NULL, NULL); } static void mount_callback_data_notify (gpointer data, GObject *object) { GMountOperation *mount_op; mount_op = G_MOUNT_OPERATION (data); g_object_set_data (G_OBJECT (mount_op), "mount-callback", NULL); g_object_set_data (G_OBJECT (mount_op), "mount-callback-data", NULL); } static void volume_mount_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { NemoMountCallback mount_callback; GObject *mount_callback_data_object; GMountOperation *mount_op = user_data; GError *error; char *primary; char *name; gboolean success; success = TRUE; error = NULL; if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) { if (error->code != G_IO_ERROR_FAILED_HANDLED && error->code != G_IO_ERROR_ALREADY_MOUNTED) { name = g_volume_get_name (G_VOLUME (source_object)); primary = g_strdup_printf (_("Unable to mount %s"), name); g_free (name); success = FALSE; eel_show_error_dialog (primary, error->message, NULL); g_free (primary); } g_error_free (error); } mount_callback = (NemoMountCallback) g_object_get_data (G_OBJECT (mount_op), "mount-callback"); mount_callback_data_object = g_object_get_data (G_OBJECT (mount_op), "mount-callback-data"); if (mount_callback != NULL) { (* mount_callback) (G_VOLUME (source_object), success, mount_callback_data_object); if (mount_callback_data_object != NULL) { g_object_weak_unref (mount_callback_data_object, mount_callback_data_notify, mount_op); } } g_object_unref (mount_op); } void nemo_file_operations_mount_volume (GtkWindow *parent_window, GVolume *volume) { nemo_file_operations_mount_volume_full (parent_window, volume, NULL, NULL); } void nemo_file_operations_mount_volume_full (GtkWindow *parent_window, GVolume *volume, NemoMountCallback mount_callback, GObject *mount_callback_data_object) { GMountOperation *mount_op; mount_op = gtk_mount_operation_new (parent_window); g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION); g_object_set_data (G_OBJECT (mount_op), "mount-callback", mount_callback); if (mount_callback != NULL && mount_callback_data_object != NULL) { g_object_weak_ref (mount_callback_data_object, mount_callback_data_notify, mount_op); } g_object_set_data (G_OBJECT (mount_op), "mount-callback-data", mount_callback_data_object); g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op); } static void report_count_progress (CommonJob *job, SourceInfo *source_info) { char *s; switch (source_info->op) { default: case OP_KIND_COPY: s = f (ngettext("Preparing to copy %'d file (%S)", "Preparing to copy %'d files (%S)", source_info->num_files), source_info->num_files, source_info->num_bytes); break; case OP_KIND_MOVE: s = f (ngettext("Preparing to move %'d file (%S)", "Preparing to move %'d files (%S)", source_info->num_files), source_info->num_files, source_info->num_bytes); break; case OP_KIND_DELETE: s = f (ngettext("Preparing to delete %'d file (%S)", "Preparing to delete %'d files (%S)", source_info->num_files), source_info->num_files, source_info->num_bytes); break; case OP_KIND_TRASH: s = f (ngettext("Preparing to trash %'d file", "Preparing to trash %'d files", source_info->num_files), source_info->num_files); break; } nemo_progress_info_take_details (job->progress, s); nemo_progress_info_pulse_progress (job->progress); } static void count_file (GFileInfo *info, CommonJob *job, SourceInfo *source_info) { source_info->num_files += 1; source_info->num_bytes += g_file_info_get_size (info); if (source_info->num_files_since_progress++ > 100) { report_count_progress (job, source_info); source_info->num_files_since_progress = 0; } } static char * get_scan_primary (OpKind kind) { switch (kind) { default: case OP_KIND_COPY: return f (_("Error while copying.")); case OP_KIND_MOVE: return f (_("Error while moving.")); case OP_KIND_DELETE: return f (_("Error while deleting.")); case OP_KIND_TRASH: return f (_("Error while moving files to trash.")); } } static void scan_dir (GFile *dir, SourceInfo *source_info, CommonJob *job, GQueue *dirs) { GFileInfo *info; GError *error; GFile *subdir; GFileEnumerator *enumerator; char *primary, *secondary, *details; int response; SourceInfo saved_info; saved_info = *source_info; retry: error = NULL; enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME"," G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, &error); if (enumerator) { error = NULL; while ((info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL) { count_file (info, job, source_info); if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { subdir = g_file_get_child (dir, g_file_info_get_name (info)); /* Push to head, since we want depth-first */ g_queue_push_head (dirs, subdir); } g_object_unref (info); } g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); if (error && IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else if (error) { primary = get_scan_primary (source_info->op); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("Files in the folder \"%B\" cannot be handled because you do " "not have permissions to see them."), dir); } else { secondary = f (_("There was an error getting information about the files in the folder \"%B\"."), dir); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, RETRY, SKIP, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { *source_info = saved_info; goto retry; } else if (response == 2) { skip_readdir_error (job, dir); } else { g_assert_not_reached (); } } } else if (job->skip_all_error) { g_error_free (error); skip_file (job, dir); } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { primary = get_scan_primary (source_info->op); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("The folder \"%B\" cannot be handled because you do not have " "permissions to read it."), dir); } else { secondary = f (_("There was an error reading the folder \"%B\"."), dir); details = error->message; } /* set show_all to TRUE here, as we don't know how many * files we'll end up processing yet. */ response = run_warning (job, primary, secondary, details, TRUE, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1 || response == 2) { if (response == 1) { job->skip_all_error = TRUE; } skip_file (job, dir); } else if (response == 3) { goto retry; } else { g_assert_not_reached (); } } } static void scan_file (GFile *file, SourceInfo *source_info, CommonJob *job) { GFileInfo *info; GError *error; GQueue *dirs; GFile *dir; char *primary; char *secondary; char *details; int response; dirs = g_queue_new (); retry: error = NULL; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, &error); if (info) { count_file (info, job, source_info); /* trashing operation doesn't recurse */ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY && source_info->op != OP_KIND_TRASH) { g_queue_push_head (dirs, g_object_ref (file)); } g_object_unref (info); } else if (job->skip_all_error) { g_error_free (error); skip_file (job, file); } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { primary = get_scan_primary (source_info->op); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("The file \"%B\" cannot be handled because you do not have " "permissions to read it."), file); } else { secondary = f (_("There was an error getting information about \"%B\"."), file); details = error->message; } /* set show_all to TRUE here, as we don't know how many * files we'll end up processing yet. */ response = run_warning (job, primary, secondary, details, TRUE, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1 || response == 2) { if (response == 1) { job->skip_all_error = TRUE; } skip_file (job, file); } else if (response == 3) { goto retry; } else { g_assert_not_reached (); } } while (!job_aborted (job) && (dir = g_queue_pop_head (dirs)) != NULL) { scan_dir (dir, source_info, job, dirs); g_object_unref (dir); } /* Free all from queue if we exited early */ g_queue_foreach (dirs, (GFunc)g_object_unref, NULL); g_queue_free (dirs); } static void scan_sources (GList *files, SourceInfo *source_info, CommonJob *job, OpKind kind) { GList *l; GFile *file; memset (source_info, 0, sizeof (SourceInfo)); source_info->op = kind; report_count_progress (job, source_info); for (l = files; l != NULL && !job_aborted (job); l = l->next) { file = l->data; scan_file (file, source_info, job); } /* Make sure we report the final count */ report_count_progress (job, source_info); } static void verify_destination (CommonJob *job, GFile *dest, char **dest_fs_id, goffset required_size) { GFileInfo *info, *fsinfo; GError *error; guint64 free_size; guint64 size_difference; char *primary, *secondary, *details; int response; GFileType file_type; if (dest_fs_id) { *dest_fs_id = NULL; } retry: error = NULL; info = g_file_query_info (dest, G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_ID_FILESYSTEM, 0, job->cancellable, &error); if (info == NULL) { if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); return; } primary = f (_("Error while copying to \"%B\"."), dest); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("You do not have permissions to access the destination folder.")); } else { secondary = f (_("There was an error getting information about the destination.")); details = error->message; } response = run_error (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { goto retry; } else { g_assert_not_reached (); } return; } file_type = g_file_info_get_file_type (info); if (dest_fs_id) { *dest_fs_id = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); } g_object_unref (info); if (file_type != G_FILE_TYPE_DIRECTORY) { primary = f (_("Error while copying to \"%B\"."), dest); secondary = f (_("The destination is not a folder.")); response = run_error (job, primary, secondary, NULL, FALSE, GTK_STOCK_CANCEL, NULL); abort_job (job); return; } fsinfo = g_file_query_filesystem_info (dest, G_FILE_ATTRIBUTE_FILESYSTEM_FREE"," G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, job->cancellable, NULL); if (fsinfo == NULL) { /* All sorts of things can go wrong getting the fs info (like not supported) * only check these things if the fs returns them */ return; } if (required_size > 0 && g_file_info_has_attribute (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) { free_size = g_file_info_get_attribute_uint64 (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_FREE); if (free_size < required_size) { size_difference = required_size - free_size; primary = f (_("Error while copying to \"%B\"."), dest); secondary = f (_("There is not enough space on the destination. Try to remove files to make space.")); details = f (_("%S more space is required to copy to the destination."), size_difference); response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, COPY_FORCE, RETRY, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 2) { goto retry; } else if (response == 1) { /* We are forced to copy - just fall through ... */ } else { g_assert_not_reached (); } } } if (!job_aborted (job) && g_file_info_get_attribute_boolean (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY)) { primary = f (_("Error while copying to \"%B\"."), dest); secondary = f (_("The destination is read-only.")); response = run_error (job, primary, secondary, NULL, FALSE, GTK_STOCK_CANCEL, NULL); g_error_free (error); abort_job (job); } g_object_unref (fsinfo); } static void report_copy_progress (CopyMoveJob *copy_job, SourceInfo *source_info, TransferInfo *transfer_info) { int files_left; goffset total_size; double elapsed, transfer_rate; int remaining_time; guint64 now; CommonJob *job; gboolean is_move; job = (CommonJob *)copy_job; is_move = copy_job->is_move; now = g_get_monotonic_time (); if (transfer_info->last_report_time != 0 && ABS ((gint64)(transfer_info->last_report_time - now)) < PROGRESS_UPDATE_THRESHOLD * US_PER_MS) { return; } transfer_info->last_report_time = now; files_left = source_info->num_files - transfer_info->num_files; /* Races and whatnot could cause this to be negative... */ if (files_left < 0) { files_left = 1; } if (files_left != transfer_info->last_reported_files_left || transfer_info->last_reported_files_left == 0) { /* Avoid changing this unless files_left changed since last time */ transfer_info->last_reported_files_left = files_left; if (source_info->num_files == 1) { if (copy_job->destination != NULL) { nemo_progress_info_take_status (job->progress, f (is_move ? _("Moving \"%B\" to \"%B\""): _("Copying \"%B\" to \"%B\""), copy_job->fake_display_source != NULL ? copy_job->fake_display_source : (GFile *)copy_job->files->data, copy_job->destination)); } else { nemo_progress_info_take_status (job->progress, f (_("Duplicating \"%B\""), (GFile *)copy_job->files->data)); } } else if (copy_job->files != NULL && copy_job->files->next == NULL) { if (copy_job->destination != NULL) { nemo_progress_info_take_status (job->progress, f (is_move ? _("Moving file %'d of %'d (in \"%B\") to \"%B\"") : _("Copying file %'d of %'d (in \"%B\") to \"%B\""), transfer_info->num_files + 1, source_info->num_files, (GFile *)copy_job->files->data, copy_job->destination)); } else { nemo_progress_info_take_status (job->progress, f (_("Duplicating file %'d of %'d (in \"%B\")"), transfer_info->num_files + 1, source_info->num_files, (GFile *)copy_job->files->data)); } } else { if (copy_job->destination != NULL) { nemo_progress_info_take_status (job->progress, f (is_move ? _("Moving file %'d of %'d to \"%B\"") : _ ("Copying file %'d of %'d to \"%B\""), transfer_info->num_files + 1, source_info->num_files, copy_job->destination)); } else { nemo_progress_info_take_status (job->progress, f (_("Duplicating file %'d of %'d"), transfer_info->num_files + 1, source_info->num_files)); } } } total_size = MAX (source_info->num_bytes, transfer_info->num_bytes); elapsed = g_timer_elapsed (job->time, NULL); transfer_rate = 0; if (elapsed > 0) { transfer_rate = transfer_info->num_bytes / elapsed; } if (elapsed < SECONDS_NEEDED_FOR_RELIABLE_TRANSFER_RATE && transfer_rate > 0) { char *s; /* To translators: %S will expand to a size like "2 bytes" or "3 MB", so something like "4 kb of 4 MB" */ s = f (_("%S of %S"), transfer_info->num_bytes, total_size); nemo_progress_info_take_details (job->progress, s); } else { char *s; remaining_time = (total_size - transfer_info->num_bytes) / transfer_rate; /* To translators: %S will expand to a size like "2 bytes" or "3 MB", %T to a time duration like * "2 minutes". So the whole thing will be something like "2 kb of 4 MB -- 2 hours left (4kb/sec)" * * The singular/plural form will be used depending on the remaining time (i.e. the %T argument). */ s = f (ngettext ("%S of %S \xE2\x80\x94 %T left (%S/sec)", "%S of %S \xE2\x80\x94 %T left (%S/sec)", seconds_count_format_time_units (remaining_time)), transfer_info->num_bytes, total_size, remaining_time, (goffset)transfer_rate); nemo_progress_info_take_details (job->progress, s); } nemo_progress_info_set_progress (job->progress, transfer_info->num_bytes, total_size); } static int get_max_name_length (GFile *file_dir) { int max_length; char *dir; long max_path; long max_name; max_length = -1; if (!g_file_has_uri_scheme (file_dir, "file")) return max_length; dir = g_file_get_path (file_dir); if (!dir) return max_length; max_path = pathconf (dir, _PC_PATH_MAX); max_name = pathconf (dir, _PC_NAME_MAX); if (max_name == -1 && max_path == -1) { max_length = -1; } else if (max_name == -1 && max_path != -1) { max_length = max_path - (strlen (dir) + 1); } else if (max_name != -1 && max_path == -1) { max_length = max_name; } else { int leftover; leftover = max_path - (strlen (dir) + 1); max_length = MIN (leftover, max_name); } g_free (dir); return max_length; } #define FAT_FORBIDDEN_CHARACTERS "/:;*?\"<>" static gboolean str_replace (char *str, const char *chars_to_replace, char replacement) { gboolean success; int i; success = FALSE; for (i = 0; str[i] != '\0'; i++) { if (strchr (chars_to_replace, str[i])) { success = TRUE; str[i] = replacement; } } return success; } static gboolean make_file_name_valid_for_dest_fs (char *filename, const char *dest_fs_type) { if (dest_fs_type != NULL && filename != NULL) { if (!strcmp (dest_fs_type, "fat") || !strcmp (dest_fs_type, "vfat") || !strcmp (dest_fs_type, "msdos") || !strcmp (dest_fs_type, "msdosfs")) { gboolean ret; int i, old_len; ret = str_replace (filename, FAT_FORBIDDEN_CHARACTERS, '_'); old_len = strlen (filename); for (i = 0; i < old_len; i++) { if (filename[i] != ' ') { g_strchomp (filename); ret |= (old_len != strlen (filename)); break; } } return ret; } } return FALSE; } static GFile * get_unique_target_file (GFile *src, GFile *dest_dir, gboolean same_fs, const char *dest_fs_type, int count) { const char *editname, *end; char *basename, *new_name; GFileInfo *info; GFile *dest; int max_length; max_length = get_max_name_length (dest_dir); dest = NULL; info = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, 0, NULL, NULL); if (info != NULL) { editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME); if (editname != NULL) { new_name = get_duplicate_name (editname, count, max_length); make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL); g_free (new_name); } g_object_unref (info); } if (dest == NULL) { basename = g_file_get_basename (src); if (g_utf8_validate (basename, -1, NULL)) { new_name = get_duplicate_name (basename, count, max_length); make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL); g_free (new_name); } if (dest == NULL) { end = strrchr (basename, '.'); if (end != NULL) { count += atoi (end + 1); } new_name = g_strdup_printf ("%s.%d", basename, count); make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child (dest_dir, new_name); g_free (new_name); } g_free (basename); } return dest; } static GFile * get_target_file_for_link (GFile *src, GFile *dest_dir, const char *dest_fs_type, int count) { const char *editname; char *basename, *new_name; GFileInfo *info; GFile *dest; int max_length; max_length = get_max_name_length (dest_dir); dest = NULL; info = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME, 0, NULL, NULL); if (info != NULL) { editname = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME); if (editname != NULL) { new_name = get_link_name (editname, count, max_length); make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL); g_free (new_name); } g_object_unref (info); } if (dest == NULL) { basename = g_file_get_basename (src); make_file_name_valid_for_dest_fs (basename, dest_fs_type); if (g_utf8_validate (basename, -1, NULL)) { new_name = get_link_name (basename, count, max_length); make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, new_name, NULL); g_free (new_name); } if (dest == NULL) { if (count == 1) { new_name = g_strdup_printf ("%s.lnk", basename); } else { new_name = g_strdup_printf ("%s.lnk%d", basename, count); } make_file_name_valid_for_dest_fs (new_name, dest_fs_type); dest = g_file_get_child (dest_dir, new_name); g_free (new_name); } g_free (basename); } return dest; } static GFile * get_target_file_with_custom_name (GFile *src, GFile *dest_dir, const char *dest_fs_type, gboolean same_fs, const gchar *custom_name) { char *basename; GFile *dest; GFileInfo *info; char *copyname; dest = NULL; if (custom_name != NULL) { copyname = g_strdup (custom_name); make_file_name_valid_for_dest_fs (copyname, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL); g_free (copyname); } if (dest == NULL && !same_fs) { info = g_file_query_info (src, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME "," G_FILE_ATTRIBUTE_TRASH_ORIG_PATH, 0, NULL, NULL); if (info) { copyname = NULL; /* if file is being restored from trash make sure it uses its original name */ if (g_file_has_uri_scheme (src, "trash")) { copyname = g_strdup (g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH)); } if (copyname == NULL) { copyname = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME)); } if (copyname) { make_file_name_valid_for_dest_fs (copyname, dest_fs_type); dest = g_file_get_child_for_display_name (dest_dir, copyname, NULL); g_free (copyname); } g_object_unref (info); } } if (dest == NULL) { basename = g_file_get_basename (src); make_file_name_valid_for_dest_fs (basename, dest_fs_type); dest = g_file_get_child (dest_dir, basename); g_free (basename); } return dest; } static GFile * get_target_file (GFile *src, GFile *dest_dir, const char *dest_fs_type, gboolean same_fs) { return get_target_file_with_custom_name (src, dest_dir, dest_fs_type, same_fs, NULL); } static gboolean has_fs_id (GFile *file, const char *fs_id) { const char *id; GFileInfo *info; gboolean res; res = FALSE; info = g_file_query_info (file, G_FILE_ATTRIBUTE_ID_FILESYSTEM, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); if (info) { id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM); if (id && strcmp (id, fs_id) == 0) { res = TRUE; } g_object_unref (info); } return res; } static gboolean is_dir (GFile *file) { GFileInfo *info; gboolean res; res = FALSE; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); if (info) { res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY; g_object_unref (info); } return res; } static void copy_move_file (CopyMoveJob *job, GFile *src, GFile *dest_dir, gboolean same_fs, gboolean unique_names, char **dest_fs_type, SourceInfo *source_info, TransferInfo *transfer_info, GHashTable *debuting_files, GdkPoint *point, gboolean overwrite, gboolean *skipped_file, gboolean readonly_source_fs); typedef enum { CREATE_DEST_DIR_RETRY, CREATE_DEST_DIR_FAILED, CREATE_DEST_DIR_SUCCESS } CreateDestDirResult; static CreateDestDirResult create_dest_dir (CommonJob *job, GFile *src, GFile **dest, gboolean same_fs, char **dest_fs_type) { GError *error; GFile *new_dest, *dest_dir; char *primary, *secondary, *details; int response; gboolean handled_invalid_filename; handled_invalid_filename = *dest_fs_type != NULL; retry: /* First create the directory, then copy stuff to it before copying the attributes, because we need to be sure we can write to it */ error = NULL; if (!g_file_make_directory (*dest, job->cancellable, &error)) { if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); return CREATE_DEST_DIR_FAILED; } else if (IS_IO_ERROR (error, INVALID_FILENAME) && !handled_invalid_filename) { handled_invalid_filename = TRUE; g_assert (*dest_fs_type == NULL); dest_dir = g_file_get_parent (*dest); if (dest_dir != NULL) { *dest_fs_type = query_fs_type (dest_dir, job->cancellable); new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs); g_object_unref (dest_dir); if (!g_file_equal (*dest, new_dest)) { g_object_unref (*dest); *dest = new_dest; g_error_free (error); return CREATE_DEST_DIR_RETRY; } else { g_object_unref (new_dest); } } } primary = f (_("Error while copying.")); details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("The folder \"%B\" cannot be copied because you do not have " "permissions to create it in the destination."), src); } else { secondary = f (_("There was an error creating the folder \"%B\"."), src); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, SKIP, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* Skip: Do Nothing */ } else if (response == 2) { goto retry; } else { g_assert_not_reached (); } return CREATE_DEST_DIR_FAILED; } nemo_file_changes_queue_file_added (*dest); if (job->undo_info != NULL) { nemo_file_undo_info_ext_add_origin_target_pair (NEMO_FILE_UNDO_INFO_EXT (job->undo_info), src, *dest); } return CREATE_DEST_DIR_SUCCESS; } /* a return value of FALSE means retry, i.e. * the destination has changed and the source * is expected to re-try the preceeding * g_file_move() or g_file_copy() call with * the new destination. */ static gboolean copy_move_directory (CopyMoveJob *copy_job, GFile *src, GFile **dest, gboolean same_fs, gboolean create_dest, char **parent_dest_fs_type, SourceInfo *source_info, TransferInfo *transfer_info, GHashTable *debuting_files, gboolean *skipped_file, gboolean readonly_source_fs) { GFileInfo *info; GError *error; GFile *src_file; GFileEnumerator *enumerator; char *primary, *secondary, *details; char *dest_fs_type; int response; gboolean skip_error; gboolean local_skipped_file; CommonJob *job; GFileCopyFlags flags; job = (CommonJob *)copy_job; if (create_dest) { switch (create_dest_dir (job, src, dest, same_fs, parent_dest_fs_type)) { case CREATE_DEST_DIR_RETRY: /* next time copy_move_directory() is called, * create_dest will be FALSE if a directory already * exists under the new name (i.e. WOULD_RECURSE) */ return FALSE; case CREATE_DEST_DIR_FAILED: *skipped_file = TRUE; return TRUE; case CREATE_DEST_DIR_SUCCESS: default: break; } if (debuting_files) { g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (TRUE)); } } local_skipped_file = FALSE; dest_fs_type = NULL; skip_error = should_skip_readdir_error (job, src); retry: error = NULL; enumerator = g_file_enumerate_children (src, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, &error); if (enumerator) { error = NULL; while (!job_aborted (job) && (info = g_file_enumerator_next_file (enumerator, job->cancellable, skip_error?NULL:&error)) != NULL) { src_file = g_file_get_child (src, g_file_info_get_name (info)); copy_move_file (copy_job, src_file, *dest, same_fs, FALSE, &dest_fs_type, source_info, transfer_info, NULL, NULL, FALSE, &local_skipped_file, readonly_source_fs); g_object_unref (src_file); g_object_unref (info); } g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); if (error && IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else if (error) { if (copy_job->is_move) { primary = f (_("Error while moving.")); } else { primary = f (_("Error while copying.")); } details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("Files in the folder \"%B\" cannot be copied because you do " "not have permissions to see them."), src); } else { secondary = f (_("There was an error getting information about the files in the folder \"%B\"."), src); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, _("_Skip files"), NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* Skip: Do Nothing */ local_skipped_file = TRUE; } else { g_assert_not_reached (); } } /* Count the copied directory as a file */ transfer_info->num_files ++; report_copy_progress (copy_job, source_info, transfer_info); if (debuting_files) { g_hash_table_replace (debuting_files, g_object_ref (*dest), GINT_TO_POINTER (create_dest)); } } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { if (copy_job->is_move) { primary = f (_("Error while moving.")); } else { primary = f (_("Error while copying.")); } details = NULL; if (IS_IO_ERROR (error, PERMISSION_DENIED)) { secondary = f (_("The folder \"%B\" cannot be copied because you do not have " "permissions to read it."), src); } else { secondary = f (_("There was an error reading the folder \"%B\"."), src); details = error->message; } response = run_warning (job, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, SKIP, RETRY, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* Skip: Do Nothing */ local_skipped_file = TRUE; } else if (response == 2) { goto retry; } else { g_assert_not_reached (); } } if (create_dest) { flags = (readonly_source_fs) ? G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_TARGET_DEFAULT_PERMS : G_FILE_COPY_NOFOLLOW_SYMLINKS; /* Ignore errors here. Failure to copy metadata is not a hard error */ g_file_copy_attributes (src, *dest, flags, job->cancellable, NULL); } if (!job_aborted (job) && copy_job->is_move && /* Don't delete source if there was a skipped file */ !local_skipped_file) { if (!file_delete_wrapper (src, job->cancellable, &error)) { if (job->skip_all_error) { goto skip; } primary = f (_("Error while moving \"%B\"."), src); secondary = f (_("Could not remove the source folder.")); details = error->message; response = run_warning (job, primary, secondary, details, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; local_skipped_file = TRUE; } else if (response == 2) { /* skip */ local_skipped_file = TRUE; } else { g_assert_not_reached (); } skip: g_error_free (error); } } if (local_skipped_file) { *skipped_file = TRUE; } g_free (dest_fs_type); return TRUE; } static gboolean remove_target_recursively (CommonJob *job, GFile *src, GFile *toplevel_dest, GFile *file) { GFileEnumerator *enumerator; GError *error; GFile *child; gboolean stop; char *primary, *secondary, *details; int response; GFileInfo *info; stop = FALSE; error = NULL; enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, &error); if (enumerator) { error = NULL; while (!job_aborted (job) && (info = g_file_enumerator_next_file (enumerator, job->cancellable, &error)) != NULL) { child = g_file_get_child (file, g_file_info_get_name (info)); if (!remove_target_recursively (job, src, toplevel_dest, child)) { stop = TRUE; break; } g_object_unref (child); g_object_unref (info); } g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); } else if (IS_IO_ERROR (error, NOT_DIRECTORY)) { /* Not a dir, continue */ g_error_free (error); } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } else { if (job->skip_all_error) { goto skip1; } primary = f (_("Error while copying \"%B\"."), src); secondary = f (_("Could not remove files from the already existing folder %F."), file); details = error->message; /* set show_all to TRUE here, as we don't know how many * files we'll end up processing yet. */ response = run_warning (job, primary, secondary, details, TRUE, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } skip1: g_error_free (error); stop = TRUE; } if (stop) { return FALSE; } error = NULL; if (!file_delete_wrapper (file, job->cancellable, &error)) { if (job->skip_all_error || IS_IO_ERROR (error, CANCELLED)) { goto skip2; } primary = f (_("Error while copying \"%B\"."), src); secondary = f (_("Could not remove the already existing file %F."), file); details = error->message; /* set show_all to TRUE here, as we don't know how many * files we'll end up processing yet. */ response = run_warning (job, primary, secondary, details, TRUE, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } skip2: g_error_free (error); return FALSE; } nemo_file_changes_queue_file_removed (file); return TRUE; } typedef struct { CopyMoveJob *job; goffset last_size; SourceInfo *source_info; TransferInfo *transfer_info; } ProgressData; static void copy_file_progress_callback (goffset current_num_bytes, goffset total_num_bytes, gpointer user_data) { ProgressData *pdata; goffset new_size; pdata = user_data; new_size = current_num_bytes - pdata->last_size; if (new_size > 0) { pdata->transfer_info->num_bytes += new_size; pdata->last_size = current_num_bytes; report_copy_progress (pdata->job, pdata->source_info, pdata->transfer_info); } } static gboolean test_dir_is_parent (GFile *child, GFile *root) { GFile *f, *tmp; f = g_file_dup (child); while (f) { if (g_file_equal (f, root)) { g_object_unref (f); return TRUE; } tmp = f; f = g_file_get_parent (f); g_object_unref (tmp); } if (f) { g_object_unref (f); } return FALSE; } static char * query_fs_type (GFile *file, GCancellable *cancellable) { GFileInfo *fsinfo; char *ret; ret = NULL; fsinfo = g_file_query_filesystem_info (file, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, cancellable, NULL); if (fsinfo != NULL) { ret = g_strdup (g_file_info_get_attribute_string (fsinfo, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE)); g_object_unref (fsinfo); } if (ret == NULL) { /* ensure that we don't attempt to query * the FS type for each file in a given * directory, if it can't be queried. */ ret = g_strdup (""); } return ret; } static gboolean is_trusted_desktop_file (GFile *file, GCancellable *cancellable) { char *basename; gboolean res; GFileInfo *info; /* Don't trust non-local files */ if (!g_file_is_native (file)) { return FALSE; } basename = g_file_get_basename (file); if (!g_str_has_suffix (basename, ".desktop")) { g_free (basename); return FALSE; } g_free (basename); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, NULL); if (info == NULL) { return FALSE; } res = FALSE; /* Weird file => not trusted, Already executable => no need to mark trusted */ if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR && !g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE) && nemo_is_in_system_dir (file)) { res = TRUE; } g_object_unref (info); return res; } typedef struct { int id; char *new_name; gboolean apply_to_all; } ConflictResponseData; typedef struct { GFile *src; GFile *dest; GFile *dest_dir; GtkWindow *parent; ConflictResponseData *resp_data; } ConflictDialogData; static gboolean do_run_conflict_dialog (gpointer _data) { ConflictDialogData *data = _data; GtkWidget *dialog; int response; dialog = nemo_file_conflict_dialog_new (data->parent, data->src, data->dest, data->dest_dir); response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == CONFLICT_RESPONSE_RENAME) { data->resp_data->new_name = nemo_file_conflict_dialog_get_new_name (NEMO_FILE_CONFLICT_DIALOG (dialog)); } else if (response != GTK_RESPONSE_CANCEL || response != GTK_RESPONSE_NONE) { data->resp_data->apply_to_all = nemo_file_conflict_dialog_get_apply_to_all (NEMO_FILE_CONFLICT_DIALOG (dialog)); } data->resp_data->id = response; gtk_widget_destroy (dialog); return FALSE; } static ConflictResponseData * run_conflict_dialog (CommonJob *job, GFile *src, GFile *dest, GFile *dest_dir) { ConflictDialogData *data; ConflictResponseData *resp_data; g_timer_stop (job->time); data = g_slice_new0 (ConflictDialogData); data->parent = job->parent_window; data->src = src; data->dest = dest; data->dest_dir = dest_dir; resp_data = g_slice_new0 (ConflictResponseData); resp_data->new_name = NULL; data->resp_data = resp_data; nemo_progress_info_pause (job->progress); g_io_scheduler_job_send_to_mainloop (job->io_job, do_run_conflict_dialog, data, NULL); nemo_progress_info_resume (job->progress); g_slice_free (ConflictDialogData, data); g_timer_continue (job->time); return resp_data; } static void conflict_response_data_free (ConflictResponseData *data) { g_free (data->new_name); g_slice_free (ConflictResponseData, data); } static GFile * get_target_file_for_display_name (GFile *dir, const gchar *name) { GFile *dest; dest = NULL; dest = g_file_get_child_for_display_name (dir, name, NULL); if (dest == NULL) { dest = g_file_get_child (dir, name); } return dest; } /* Debuting files is non-NULL only for toplevel items */ static void copy_move_file (CopyMoveJob *copy_job, GFile *src, GFile *dest_dir, gboolean same_fs, gboolean unique_names, char **dest_fs_type, SourceInfo *source_info, TransferInfo *transfer_info, GHashTable *debuting_files, GdkPoint *position, gboolean overwrite, gboolean *skipped_file, gboolean readonly_source_fs) { GFile *dest, *new_dest; GError *error; GFileCopyFlags flags; char *primary, *secondary, *details; int response; ProgressData pdata; gboolean would_recurse, is_merge; CommonJob *job; gboolean res; int unique_name_nr; gboolean handled_invalid_filename; gboolean target_is_desktop, source_is_desktop; job = (CommonJob *)copy_job; if (should_skip_file (job, src)) { *skipped_file = TRUE; return; } target_is_desktop = (copy_job->desktop_location != NULL && g_file_equal (copy_job->desktop_location, dest_dir)); source_is_desktop = FALSE; if (src != NULL) { GFile *parent = g_file_get_parent (src); if (parent != NULL && g_file_equal (copy_job->desktop_location, parent)) { source_is_desktop = TRUE; g_object_unref (parent); } } unique_name_nr = 1; /* another file in the same directory might have handled the invalid * filename condition for us */ handled_invalid_filename = *dest_fs_type != NULL; if (unique_names) { dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++); } else if (copy_job->target_name != NULL) { dest = get_target_file_with_custom_name (src, dest_dir, *dest_fs_type, same_fs, copy_job->target_name); } else { dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs); } /* Don't allow recursive move/copy into itself. * (We would get a file system error if we proceeded but it is nicer to * detect and report it at this level) */ if (test_dir_is_parent (dest_dir, src)) { if (job->skip_all_error) { goto out; } /* the run_warning() frees all strings passed in automatically */ primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself.")) : g_strdup (_("You cannot copy a folder into itself.")); secondary = g_strdup (_("The destination folder is inside the source folder.")); response = run_warning (job, primary, secondary, NULL, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } goto out; } /* Don't allow copying over the source or one of the parents of the source. */ if (test_dir_is_parent (src, dest)) { if (job->skip_all_error) { goto out; } /* the run_warning() frees all strings passed in automatically */ primary = copy_job->is_move ? g_strdup (_("You cannot move a file over itself.")) : g_strdup (_("You cannot copy a file over itself.")); secondary = g_strdup (_("The source file would be overwritten by the destination.")); response = run_warning (job, primary, secondary, NULL, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } goto out; } retry: error = NULL; flags = G_FILE_COPY_NOFOLLOW_SYMLINKS; if (overwrite) { flags |= G_FILE_COPY_OVERWRITE; } if (readonly_source_fs) { flags |= G_FILE_COPY_TARGET_DEFAULT_PERMS; } pdata.job = copy_job; pdata.last_size = 0; pdata.source_info = source_info; pdata.transfer_info = transfer_info; if (copy_job->is_move) { res = g_file_move (src, dest, flags, job->cancellable, copy_file_progress_callback, &pdata, &error); } else { res = g_file_copy (src, dest, flags, job->cancellable, copy_file_progress_callback, &pdata, &error); } if (res) { transfer_info->num_files ++; report_copy_progress (copy_job, source_info, transfer_info); if (debuting_files) { if (target_is_desktop && position) { nemo_file_changes_queue_schedule_position_set (dest, *position, job->monitor_num); } else if (source_is_desktop && copy_job->is_move) { nemo_file_changes_queue_schedule_position_remove (dest); } g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)); } if (copy_job->is_move) { nemo_file_changes_queue_file_moved (src, dest); } else { nemo_file_changes_queue_file_added (dest); } /* If copying a trusted desktop file to the desktop, mark it as trusted. */ if (copy_job->desktop_location != NULL && g_file_equal (copy_job->desktop_location, dest_dir) && is_trusted_desktop_file (src, job->cancellable)) { mark_desktop_file_trusted (job, job->cancellable, dest, FALSE); } if (job->undo_info != NULL) { nemo_file_undo_info_ext_add_origin_target_pair (NEMO_FILE_UNDO_INFO_EXT (job->undo_info), src, dest); } g_object_unref (dest); return; } if (!handled_invalid_filename && IS_IO_ERROR (error, INVALID_FILENAME)) { handled_invalid_filename = TRUE; g_assert (*dest_fs_type == NULL); *dest_fs_type = query_fs_type (dest_dir, job->cancellable); if (unique_names) { new_dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr); } else { new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs); } if (!g_file_equal (dest, new_dest)) { g_object_unref (dest); dest = new_dest; g_error_free (error); goto retry; } else { g_object_unref (new_dest); } } /* Conflict */ if (!overwrite && IS_IO_ERROR (error, EXISTS)) { gboolean is_merge; ConflictResponseData *response; g_error_free (error); if (unique_names) { g_object_unref (dest); dest = get_unique_target_file (src, dest_dir, same_fs, *dest_fs_type, unique_name_nr++); goto retry; } is_merge = FALSE; if (is_dir (dest) && is_dir (src)) { is_merge = TRUE; } if ((is_merge && job->merge_all) || (!is_merge && job->replace_all)) { overwrite = TRUE; goto retry; } if (job->skip_all_conflict) { goto out; } response = run_conflict_dialog (job, src, dest, dest_dir); if (response->id == GTK_RESPONSE_CANCEL || response->id == GTK_RESPONSE_DELETE_EVENT) { conflict_response_data_free (response); abort_job (job); } else if (response->id == CONFLICT_RESPONSE_SKIP) { if (response->apply_to_all) { job->skip_all_conflict = TRUE; } conflict_response_data_free (response); } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */ if (response->apply_to_all) { if (is_merge) { job->merge_all = TRUE; } else { job->replace_all = TRUE; } } overwrite = TRUE; conflict_response_data_free (response); goto retry; } else if (response->id == CONFLICT_RESPONSE_RENAME) { g_object_unref (dest); dest = get_target_file_for_display_name (dest_dir, response->new_name); conflict_response_data_free (response); goto retry; } else { g_assert_not_reached (); } } else if (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)) { g_error_free (error); if (remove_target_recursively (job, src, dest, dest)) { goto retry; } } /* Needs to recurse */ else if (IS_IO_ERROR (error, WOULD_RECURSE) || IS_IO_ERROR (error, WOULD_MERGE)) { is_merge = error->code == G_IO_ERROR_WOULD_MERGE; would_recurse = error->code == G_IO_ERROR_WOULD_RECURSE; g_error_free (error); if (overwrite && would_recurse) { error = NULL; /* Copying a dir onto file, first remove the file */ if (!file_delete_wrapper (dest, job->cancellable, &error) && !IS_IO_ERROR (error, NOT_FOUND)) { if (job->skip_all_error) { g_error_free (error); goto out; } if (copy_job->is_move) { primary = f (_("Error while moving \"%B\"."), src); } else { primary = f (_("Error while copying \"%B\"."), src); } secondary = f (_("Could not remove the already existing file with the same name in %F."), dest_dir); details = error->message; /* setting TRUE on show_all here, as we could have * another error on the same file later. */ response = run_warning (job, primary, secondary, details, TRUE, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } goto out; } if (error) { g_error_free (error); error = NULL; } nemo_file_changes_queue_file_removed (dest); } if (is_merge) { /* On merge we now write in the target directory, which may not be in the same directory as the source, even if the parent is (if the merged directory is a mountpoint). This could cause problems as we then don't transcode filenames. We just set same_fs to FALSE which is safe but a bit slower. */ same_fs = FALSE; } if (!copy_move_directory (copy_job, src, &dest, same_fs, would_recurse, dest_fs_type, source_info, transfer_info, debuting_files, skipped_file, readonly_source_fs)) { /* destination changed, since it was an invalid file name */ g_assert (*dest_fs_type != NULL); handled_invalid_filename = TRUE; goto retry; } g_object_unref (dest); return; } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } /* Other error */ else { if (job->skip_all_error) { g_error_free (error); goto out; } primary = f (_("Error while copying \"%B\"."), src); secondary = f (_("There was an error copying the file into %F."), dest_dir); details = error->message; response = run_warning (job, primary, secondary, details, (source_info->num_files - transfer_info->num_files) > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } } out: *skipped_file = TRUE; /* Or aborted, but same-same */ g_object_unref (dest); } static void copy_files (CopyMoveJob *job, const char *dest_fs_id, SourceInfo *source_info, TransferInfo *transfer_info) { CommonJob *common; GList *l; GFile *src; gboolean same_fs; int i; GdkPoint *point; gboolean skipped_file; gboolean unique_names; GFile *dest; GFile *source_dir; char *dest_fs_type; GFileInfo *inf; gboolean readonly_source_fs; dest_fs_type = NULL; readonly_source_fs = FALSE; common = &job->common; report_copy_progress (job, source_info, transfer_info); /* Query the source dir, not the file because if its a symlink we'll follow it */ source_dir = g_file_get_parent ((GFile *) job->files->data); if (source_dir) { inf = g_file_query_filesystem_info (source_dir, "filesystem::readonly", NULL, NULL); if (inf != NULL) { readonly_source_fs = g_file_info_get_attribute_boolean (inf, "filesystem::readonly"); g_object_unref (inf); } g_object_unref (source_dir); } unique_names = (job->destination == NULL); i = 0; for (l = job->files; l != NULL && !job_aborted (common); l = l->next) { src = l->data; if (i < job->n_icon_positions) { point = &job->icon_positions[i]; } else { point = NULL; } same_fs = FALSE; if (dest_fs_id) { same_fs = has_fs_id (src, dest_fs_id); } if (job->destination) { dest = g_object_ref (job->destination); } else { dest = g_file_get_parent (src); } if (dest) { skipped_file = FALSE; copy_move_file (job, src, dest, same_fs, unique_names, &dest_fs_type, source_info, transfer_info, job->debuting_files, point, FALSE, &skipped_file, readonly_source_fs); g_object_unref (dest); } i++; } g_free (dest_fs_type); } static gboolean copy_job_done (gpointer user_data) { CopyMoveJob *job; job = user_data; if (job->done_callback) { job->done_callback (job->debuting_files, !job_aborted ((CommonJob *) job), job->done_callback_data); } g_list_free_full (job->files, g_object_unref); if (job->destination) { g_object_unref (job->destination); } if (job->desktop_location) { g_object_unref (job->desktop_location); } g_hash_table_unref (job->debuting_files); g_free (job->icon_positions); g_free (job->target_name); g_clear_object (&job->fake_display_source); finalize_common ((CommonJob *)job); nemo_file_changes_consume_changes (TRUE); return FALSE; } static gboolean copy_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { CopyMoveJob *job; CommonJob *common; SourceInfo source_info; TransferInfo transfer_info; char *dest_fs_id; GFile *dest; job = user_data; common = &job->common; common->io_job = io_job; dest_fs_id = NULL; nemo_progress_info_start (common->progress); scan_sources (job->files, &source_info, common, OP_KIND_COPY); if (job_aborted (common)) { goto aborted; } if (job->destination) { dest = g_object_ref (job->destination); } else { /* Duplication, no dest, * use source for free size, etc */ dest = g_file_get_parent (job->files->data); } verify_destination (&job->common, dest, &dest_fs_id, source_info.num_bytes); g_object_unref (dest); if (job_aborted (common)) { goto aborted; } g_timer_start (job->common.time); memset (&transfer_info, 0, sizeof (transfer_info)); copy_files (job, dest_fs_id, &source_info, &transfer_info); aborted: g_free (dest_fs_id); g_io_scheduler_job_send_to_mainloop_async (io_job, copy_job_done, job, NULL); return FALSE; } void nemo_file_operations_copy_file (GFile *source_file, GFile *target_dir, const gchar *source_display_name, const gchar *new_name, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data) { CopyMoveJob *job; job = op_job_new (CopyMoveJob, parent_window); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = g_list_append (NULL, g_object_ref (source_file)); job->destination = g_object_ref (target_dir); job->target_name = g_strdup (new_name); job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); if (source_display_name != NULL) { gchar *path; path = g_build_filename ("/", source_display_name, NULL); job->fake_display_source = g_file_new_for_path (path); g_free (path); } inhibit_power_manager ((CommonJob *)job, _("Copying Files")); generate_initial_job_details (job->common.progress, OP_KIND_COPY, job->files, job->destination); add_job_to_job_queue (copy_job, job, job->common.cancellable, job->common.progress, OP_KIND_COPY); } void nemo_file_operations_copy (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data) { CopyMoveJob *job; job = op_job_new (CopyMoveJob, parent_window); job->desktop_location = nemo_get_desktop_location (); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); job->destination = g_object_ref (target_dir); if (relative_item_points != NULL && relative_item_points->len > 0) { job->icon_positions = g_memdup (relative_item_points->data, sizeof (GdkPoint) * relative_item_points->len); job->n_icon_positions = relative_item_points->len; } job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); inhibit_power_manager ((CommonJob *)job, _("Copying Files")); if (!nemo_file_undo_manager_pop_flag ()) { GFile* src_dir; src_dir = g_file_get_parent (files->data); job->common.undo_info = nemo_file_undo_info_ext_new (NEMO_FILE_UNDO_OP_COPY, g_list_length (files), src_dir, target_dir); g_object_unref (src_dir); } generate_initial_job_details (job->common.progress, OP_KIND_COPY, job->files, job->destination); add_job_to_job_queue (copy_job, job, job->common.cancellable, job->common.progress, OP_KIND_COPY); } static void report_move_progress (CopyMoveJob *move_job, int total, int left) { CommonJob *job; job = (CommonJob *)move_job; nemo_progress_info_take_status (job->progress, f (_("Preparing to Move to \"%B\""), move_job->destination)); nemo_progress_info_take_details (job->progress, f (ngettext ("Preparing to move %'d file", "Preparing to move %'d files", left), left)); nemo_progress_info_pulse_progress (job->progress); } typedef struct { GFile *file; gboolean overwrite; gboolean has_position; GdkPoint position; } MoveFileCopyFallback; static MoveFileCopyFallback * move_copy_file_callback_new (GFile *file, gboolean overwrite, GdkPoint *position) { MoveFileCopyFallback *fallback; fallback = g_new (MoveFileCopyFallback, 1); fallback->file = file; fallback->overwrite = overwrite; if (position) { fallback->has_position = TRUE; fallback->position = *position; } else { fallback->has_position = FALSE; } return fallback; } static GList * get_files_from_fallbacks (GList *fallbacks) { MoveFileCopyFallback *fallback; GList *res, *l; res = NULL; for (l = fallbacks; l != NULL; l = l->next) { fallback = l->data; res = g_list_prepend (res, fallback->file); } return g_list_reverse (res); } static void move_file_prepare (CopyMoveJob *move_job, GFile *src, GFile *dest_dir, gboolean same_fs, char **dest_fs_type, GHashTable *debuting_files, GdkPoint *position, GList **fallback_files, int files_left) { GFile *dest, *new_dest; GError *error; CommonJob *job; gboolean overwrite; char *primary, *secondary, *details; int response; GFileCopyFlags flags; MoveFileCopyFallback *fallback; gboolean handled_invalid_filename; gboolean target_is_desktop, source_is_desktop; target_is_desktop = (move_job->desktop_location != NULL && g_file_equal (move_job->desktop_location, dest_dir)); source_is_desktop = FALSE; if (src != NULL) { GFile *parent = g_file_get_parent (src); if (parent != NULL && g_file_equal (move_job->desktop_location, parent)) { source_is_desktop = TRUE; g_object_unref (parent); } } overwrite = FALSE; handled_invalid_filename = *dest_fs_type != NULL; job = (CommonJob *)move_job; dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs); /* Don't allow recursive move/copy into itself. * (We would get a file system error if we proceeded but it is nicer to * detect and report it at this level) */ if (test_dir_is_parent (dest_dir, src)) { if (job->skip_all_error) { goto out; } /* the run_warning() frees all strings passed in automatically */ primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself.")) : g_strdup (_("You cannot copy a folder into itself.")); secondary = g_strdup (_("The destination folder is inside the source folder.")); response = run_warning (job, primary, secondary, NULL, files_left > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } goto out; } retry: flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE; if (overwrite) { flags |= G_FILE_COPY_OVERWRITE; } error = NULL; if (g_file_move (src, dest, flags, job->cancellable, NULL, NULL, &error)) { if (debuting_files) { g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)); } nemo_file_changes_queue_file_moved (src, dest); if (target_is_desktop && position) { nemo_file_changes_queue_schedule_position_set (dest, *position, job->monitor_num); } else if (source_is_desktop) { nemo_file_changes_queue_schedule_position_remove (dest); } if (job->undo_info != NULL) { nemo_file_undo_info_ext_add_origin_target_pair (NEMO_FILE_UNDO_INFO_EXT (job->undo_info), src, dest); } return; } if (IS_IO_ERROR (error, INVALID_FILENAME) && !handled_invalid_filename) { g_error_free (error); handled_invalid_filename = TRUE; g_assert (*dest_fs_type == NULL); *dest_fs_type = query_fs_type (dest_dir, job->cancellable); new_dest = get_target_file (src, dest_dir, *dest_fs_type, same_fs); if (!g_file_equal (dest, new_dest)) { g_object_unref (dest); dest = new_dest; goto retry; } else { g_object_unref (new_dest); } } /* Conflict */ else if (!overwrite && IS_IO_ERROR (error, EXISTS)) { gboolean is_merge; ConflictResponseData *response; g_error_free (error); is_merge = FALSE; if (is_dir (dest) && is_dir (src)) { is_merge = TRUE; } if ((is_merge && job->merge_all) || (!is_merge && job->replace_all)) { overwrite = TRUE; goto retry; } if (job->skip_all_conflict) { goto out; } response = run_conflict_dialog (job, src, dest, dest_dir); if (response->id == GTK_RESPONSE_CANCEL || response->id == GTK_RESPONSE_DELETE_EVENT) { conflict_response_data_free (response); abort_job (job); } else if (response->id == CONFLICT_RESPONSE_SKIP) { if (response->apply_to_all) { job->skip_all_conflict = TRUE; } conflict_response_data_free (response); } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */ if (response->apply_to_all) { if (is_merge) { job->merge_all = TRUE; } else { job->replace_all = TRUE; } } overwrite = TRUE; conflict_response_data_free (response); goto retry; } else if (response->id == CONFLICT_RESPONSE_RENAME) { g_object_unref (dest); dest = get_target_file_for_display_name (dest_dir, response->new_name); conflict_response_data_free (response); goto retry; } else { g_assert_not_reached (); } } else if (IS_IO_ERROR (error, WOULD_RECURSE) || IS_IO_ERROR (error, WOULD_MERGE) || IS_IO_ERROR (error, NOT_SUPPORTED) || (overwrite && IS_IO_ERROR (error, IS_DIRECTORY))) { g_error_free (error); fallback = move_copy_file_callback_new (src, overwrite, position); *fallback_files = g_list_prepend (*fallback_files, fallback); } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } /* Other error */ else { if (job->skip_all_error) { goto out; } primary = f (_("Error while moving \"%B\"."), src); secondary = f (_("There was an error moving the file into %F."), dest_dir); details = error->message; response = run_warning (job, primary, secondary, details, files_left > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (job); } else if (response == 1) { /* skip all */ job->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } } out: g_object_unref (dest); } static void move_files_prepare (CopyMoveJob *job, const char *dest_fs_id, char **dest_fs_type, GList **fallbacks) { CommonJob *common; GList *l; GFile *src; gboolean same_fs; int i; GdkPoint *point; int total, left; common = &job->common; total = left = g_list_length (job->files); report_move_progress (job, total, left); i = 0; for (l = job->files; l != NULL && !job_aborted (common); l = l->next) { src = l->data; if (i < job->n_icon_positions) { point = &job->icon_positions[i]; } else { point = NULL; } same_fs = FALSE; if (dest_fs_id) { same_fs = has_fs_id (src, dest_fs_id); } move_file_prepare (job, src, job->destination, same_fs, dest_fs_type, job->debuting_files, point, fallbacks, left); report_move_progress (job, total, --left); i++; } *fallbacks = g_list_reverse (*fallbacks); } static void move_files (CopyMoveJob *job, GList *fallbacks, const char *dest_fs_id, char **dest_fs_type, SourceInfo *source_info, TransferInfo *transfer_info) { CommonJob *common; GList *l; GFile *src; gboolean same_fs; int i; GdkPoint *point; gboolean skipped_file; MoveFileCopyFallback *fallback; common = &job->common; report_copy_progress (job, source_info, transfer_info); i = 0; for (l = fallbacks; l != NULL && !job_aborted (common); l = l->next) { fallback = l->data; src = fallback->file; if (fallback->has_position) { point = &fallback->position; } else { point = NULL; } same_fs = FALSE; if (dest_fs_id) { same_fs = has_fs_id (src, dest_fs_id); } /* Set overwrite to true, as the user has selected overwrite on all toplevel items */ skipped_file = FALSE; copy_move_file (job, src, job->destination, same_fs, FALSE, dest_fs_type, source_info, transfer_info, job->debuting_files, point, fallback->overwrite, &skipped_file, FALSE); i++; } } static gboolean move_job_done (gpointer user_data) { CopyMoveJob *job; job = user_data; if (job->done_callback) { job->done_callback (job->debuting_files, !job_aborted ((CommonJob *) job), job->done_callback_data); } g_list_free_full (job->files, g_object_unref); g_object_unref (job->destination); g_hash_table_unref (job->debuting_files); g_free (job->icon_positions); finalize_common ((CommonJob *)job); nemo_file_changes_consume_changes (TRUE); return FALSE; } static gboolean move_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { CopyMoveJob *job; CommonJob *common; GList *fallbacks; SourceInfo source_info; TransferInfo transfer_info; char *dest_fs_id; char *dest_fs_type; GList *fallback_files; job = user_data; common = &job->common; common->io_job = io_job; dest_fs_id = NULL; dest_fs_type = NULL; fallbacks = NULL; nemo_progress_info_start (common->progress); verify_destination (&job->common, job->destination, &dest_fs_id, -1); if (job_aborted (common)) { goto aborted; } /* This moves all files that we can do without copy + delete */ move_files_prepare (job, dest_fs_id, &dest_fs_type, &fallbacks); if (job_aborted (common)) { goto aborted; } /* The rest we need to do deep copy + delete behind on, so scan for size */ fallback_files = get_files_from_fallbacks (fallbacks); scan_sources (fallback_files, &source_info, common, OP_KIND_MOVE); g_list_free (fallback_files); if (job_aborted (common)) { goto aborted; } verify_destination (&job->common, job->destination, NULL, source_info.num_bytes); if (job_aborted (common)) { goto aborted; } memset (&transfer_info, 0, sizeof (transfer_info)); move_files (job, fallbacks, dest_fs_id, &dest_fs_type, &source_info, &transfer_info); aborted: g_list_free_full (fallbacks, g_free); g_free (dest_fs_id); g_free (dest_fs_type); g_io_scheduler_job_send_to_mainloop (io_job, move_job_done, job, NULL); return FALSE; } void nemo_file_operations_move (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data) { CopyMoveJob *job; job = op_job_new (CopyMoveJob, parent_window); job->is_move = TRUE; job->desktop_location = nemo_get_desktop_location (); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); job->destination = g_object_ref (target_dir); if (relative_item_points != NULL && relative_item_points->len > 0) { job->icon_positions = g_memdup (relative_item_points->data, sizeof (GdkPoint) * relative_item_points->len); job->n_icon_positions = relative_item_points->len; } job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); inhibit_power_manager ((CommonJob *)job, _("Moving Files")); if (!nemo_file_undo_manager_pop_flag ()) { GFile* src_dir; src_dir = g_file_get_parent (files->data); if (g_file_has_uri_scheme (g_list_first (files)->data, "trash")) { job->common.undo_info = nemo_file_undo_info_ext_new (NEMO_FILE_UNDO_OP_RESTORE_FROM_TRASH, g_list_length (files), src_dir, target_dir); } else { job->common.undo_info = nemo_file_undo_info_ext_new (NEMO_FILE_UNDO_OP_MOVE, g_list_length (files), src_dir, target_dir); } g_object_unref (src_dir); } generate_initial_job_details (job->common.progress, OP_KIND_MOVE, job->files, job->destination); add_job_to_job_queue (move_job, job, job->common.cancellable, job->common.progress, OP_KIND_MOVE); } static void report_link_progress (CopyMoveJob *link_job, int total, int left) { CommonJob *job; job = (CommonJob *)link_job; nemo_progress_info_take_status (job->progress, f (_("Creating links in \"%B\""), link_job->destination)); nemo_progress_info_take_details (job->progress, f (ngettext ("Making link to %'d file", "Making links to %'d files", left), left)); nemo_progress_info_set_progress (job->progress, left, total); } static char * get_abs_path_for_symlink (GFile *file) { GFile *root, *parent; char *relative, *abs; if (g_file_is_native (file)) { return g_file_get_path (file); } root = g_object_ref (file); while ((parent = g_file_get_parent (root)) != NULL) { g_object_unref (root); root = parent; } relative = g_file_get_relative_path (root, file); g_object_unref (root); abs = g_strconcat ("/", relative, NULL); g_free (relative); return abs; } static void link_file (CopyMoveJob *job, GFile *src, GFile *dest_dir, char **dest_fs_type, GHashTable *debuting_files, GdkPoint *position, int files_left) { GFile *src_dir, *dest, *new_dest; int count; char *path; gboolean not_local; GError *error; CommonJob *common; char *primary, *secondary, *details; int response; gboolean handled_invalid_filename; gboolean target_is_desktop; target_is_desktop = (job->desktop_location != NULL && g_file_equal (job->desktop_location, dest_dir)); common = (CommonJob *)job; count = 0; src_dir = g_file_get_parent (src); if (g_file_equal (src_dir, dest_dir)) { count = 1; } g_object_unref (src_dir); handled_invalid_filename = *dest_fs_type != NULL; dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count); retry: error = NULL; not_local = FALSE; path = get_abs_path_for_symlink (src); if (path == NULL) { not_local = TRUE; } else if (g_file_make_symbolic_link (dest, path, common->cancellable, &error)) { if (common->undo_info != NULL) { nemo_file_undo_info_ext_add_origin_target_pair (NEMO_FILE_UNDO_INFO_EXT (common->undo_info), src, dest); } g_free (path); if (debuting_files) { g_hash_table_replace (debuting_files, g_object_ref (dest), GINT_TO_POINTER (TRUE)); } nemo_file_changes_queue_file_added (dest); if (target_is_desktop && position) { nemo_file_changes_queue_schedule_position_set (dest, *position, common->monitor_num); } g_object_unref (dest); return; } g_free (path); if (error != NULL && IS_IO_ERROR (error, INVALID_FILENAME) && !handled_invalid_filename) { handled_invalid_filename = TRUE; g_assert (*dest_fs_type == NULL); *dest_fs_type = query_fs_type (dest_dir, common->cancellable); new_dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count); if (!g_file_equal (dest, new_dest)) { g_object_unref (dest); dest = new_dest; g_error_free (error); goto retry; } else { g_object_unref (new_dest); } } /* Conflict */ if (error != NULL && IS_IO_ERROR (error, EXISTS)) { g_object_unref (dest); dest = get_target_file_for_link (src, dest_dir, *dest_fs_type, count++); g_error_free (error); goto retry; } else if (error != NULL && IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } /* Other error */ else { if (common->skip_all_error) { goto out; } primary = f (_("Error while creating link to %B."), src); if (not_local) { secondary = f (_("Symbolic links only supported for local files")); details = NULL; } else if (error != NULL && IS_IO_ERROR (error, NOT_SUPPORTED)) { secondary = f (_("The target doesn't support symbolic links.")); details = NULL; } else { secondary = f (_("There was an error creating the symlink in %F."), dest_dir); details = error->message; } response = run_warning (common, primary, secondary, details, files_left > 1, GTK_STOCK_CANCEL, SKIP_ALL, SKIP, NULL); if (error) { g_error_free (error); } if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { /* skip all */ common->skip_all_error = TRUE; } else if (response == 2) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } } out: g_object_unref (dest); } static gboolean link_job_done (gpointer user_data) { CopyMoveJob *job; job = user_data; if (job->done_callback) { job->done_callback (job->debuting_files, !job_aborted ((CommonJob *) job), job->done_callback_data); } g_list_free_full (job->files, g_object_unref); g_object_unref (job->destination); g_hash_table_unref (job->debuting_files); g_free (job->icon_positions); finalize_common ((CommonJob *)job); nemo_file_changes_consume_changes (TRUE); return FALSE; } static gboolean link_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { CopyMoveJob *job; CommonJob *common; GFile *src; GdkPoint *point; char *dest_fs_type; int total, left; int i; GList *l; job = user_data; common = &job->common; common->io_job = io_job; dest_fs_type = NULL; nemo_progress_info_start (common->progress); verify_destination (&job->common, job->destination, NULL, -1); if (job_aborted (common)) { goto aborted; } total = left = g_list_length (job->files); report_link_progress (job, total, left); i = 0; for (l = job->files; l != NULL && !job_aborted (common); l = l->next) { src = l->data; if (i < job->n_icon_positions) { point = &job->icon_positions[i]; } else { point = NULL; } link_file (job, src, job->destination, &dest_fs_type, job->debuting_files, point, left); report_link_progress (job, total, --left); i++; } aborted: g_free (dest_fs_type); g_io_scheduler_job_send_to_mainloop (io_job, link_job_done, job, NULL); return FALSE; } void nemo_file_operations_link (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data) { CopyMoveJob *job; job = op_job_new (CopyMoveJob, parent_window); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); job->destination = g_object_ref (target_dir); if (relative_item_points != NULL && relative_item_points->len > 0) { job->icon_positions = g_memdup (relative_item_points->data, sizeof (GdkPoint) * relative_item_points->len); job->n_icon_positions = relative_item_points->len; } job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); if (!nemo_file_undo_manager_pop_flag ()) { GFile* src_dir; src_dir = g_file_get_parent (files->data); job->common.undo_info = nemo_file_undo_info_ext_new (NEMO_FILE_UNDO_OP_CREATE_LINK, g_list_length (files), src_dir, target_dir); g_object_unref (src_dir); } generate_initial_job_details (job->common.progress, OP_KIND_LINK, job->files, job->destination); add_job_to_job_queue (link_job, job, job->common.cancellable, job->common.progress, OP_KIND_LINK); } void nemo_file_operations_duplicate (GList *files, GArray *relative_item_points, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data) { CopyMoveJob *job; job = op_job_new (CopyMoveJob, parent_window); job->desktop_location = nemo_get_desktop_location (); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->files = eel_g_object_list_copy (files); job->destination = NULL; if (relative_item_points != NULL && relative_item_points->len > 0) { job->icon_positions = g_memdup (relative_item_points->data, sizeof (GdkPoint) * relative_item_points->len); job->n_icon_positions = relative_item_points->len; } job->debuting_files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, NULL); if (!nemo_file_undo_manager_pop_flag ()) { GFile* src_dir; src_dir = g_file_get_parent (files->data); job->common.undo_info = nemo_file_undo_info_ext_new (NEMO_FILE_UNDO_OP_DUPLICATE, g_list_length (files), src_dir, src_dir); g_object_unref (src_dir); } GFile *src_dir = g_file_get_parent (files->data); generate_initial_job_details (job->common.progress, OP_KIND_DUPE, job->files, src_dir); g_object_unref (src_dir); add_job_to_job_queue (copy_job, job, job->common.cancellable, job->common.progress, OP_KIND_DUPE); } static gboolean set_permissions_job_done (gpointer user_data) { SetPermissionsJob *job; job = user_data; g_object_unref (job->file); if (job->done_callback) { job->done_callback (!job_aborted ((CommonJob *) job), job->done_callback_data); } finalize_common ((CommonJob *)job); return FALSE; } static void set_permissions_file (SetPermissionsJob *job, GFile *file, GFileInfo *info) { CommonJob *common; GFileInfo *child_info; gboolean free_info; guint32 current; guint32 value; guint32 mask; GFileEnumerator *enumerator; GFile *child; common = (CommonJob *)job; nemo_progress_info_pulse_progress (common->progress); free_info = FALSE; if (info == NULL) { free_info = TRUE; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, common->cancellable, NULL); /* Ignore errors */ if (info == NULL) { return; } } if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { value = job->dir_permissions; mask = job->dir_mask; } else { value = job->file_permissions; mask = job->file_mask; } if (!job_aborted (common) && g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE)) { current = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); if (common->undo_info != NULL) { nemo_file_undo_info_rec_permissions_add_file (NEMO_FILE_UNDO_INFO_REC_PERMISSIONS (common->undo_info), file, current); } current = (current & ~mask) | value; g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, current, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, common->cancellable, NULL); } if (!job_aborted (common) && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME"," G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, common->cancellable, NULL); if (enumerator) { while (!job_aborted (common) && (child_info = g_file_enumerator_next_file (enumerator, common->cancellable, NULL)) != NULL) { child = g_file_get_child (file, g_file_info_get_name (child_info)); set_permissions_file (job, child, child_info); g_object_unref (child); g_object_unref (child_info); } g_file_enumerator_close (enumerator, common->cancellable, NULL); g_object_unref (enumerator); } } if (free_info) { g_object_unref (info); } } static gboolean set_permissions_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { SetPermissionsJob *job = user_data; CommonJob *common; common = (CommonJob *)job; common->io_job = io_job; nemo_progress_info_set_status (common->progress, _("Setting permissions")); nemo_progress_info_start (common->progress); set_permissions_file (job, job->file, NULL); g_io_scheduler_job_send_to_mainloop_async (io_job, set_permissions_job_done, job, NULL); return FALSE; } void nemo_file_set_permissions_recursive (const char *directory, guint32 file_permissions, guint32 file_mask, guint32 dir_permissions, guint32 dir_mask, NemoOpCallback callback, gpointer callback_data) { SetPermissionsJob *job; job = op_job_new (SetPermissionsJob, NULL); job->file = g_file_new_for_uri (directory); job->file_permissions = file_permissions; job->file_mask = file_mask; job->dir_permissions = dir_permissions; job->dir_mask = dir_mask; job->done_callback = callback; job->done_callback_data = callback_data; if (!nemo_file_undo_manager_pop_flag ()) { job->common.undo_info = nemo_file_undo_info_rec_permissions_new (job->file, file_permissions, file_mask, dir_permissions, dir_mask); } generate_initial_job_details (job->common.progress, OP_KIND_PERMISSIONS, NULL, job->file); add_job_to_job_queue (set_permissions_job, job, job->common.cancellable, job->common.progress, OP_KIND_PERMISSIONS); } static GList * location_list_from_uri_list (const GList *uris) { const GList *l; GList *files; GFile *f; files = NULL; for (l = uris; l != NULL; l = l->next) { f = g_file_new_for_uri (l->data); files = g_list_prepend (files, f); } return g_list_reverse (files); } typedef struct { NemoCopyCallback real_callback; gpointer real_data; } MoveTrashCBData; static void callback_for_move_to_trash (GHashTable *debuting_uris, gboolean user_cancelled, MoveTrashCBData *data) { if (data->real_callback) data->real_callback (debuting_uris, !user_cancelled, data->real_data); g_slice_free (MoveTrashCBData, data); } void nemo_file_operations_copy_move (const GList *item_uris, GArray *relative_item_points, const char *target_dir, GdkDragAction copy_action, GtkWidget *parent_view, NemoCopyCallback done_callback, gpointer done_callback_data) { GList *locations; GList *p; GFile *dest, *src_dir; GtkWindow *parent_window; gboolean target_is_mapping; gboolean have_nonmapping_source; dest = NULL; target_is_mapping = FALSE; have_nonmapping_source = FALSE; if (target_dir) { dest = g_file_new_for_uri (target_dir); if (g_file_has_uri_scheme (dest, "burn")) { target_is_mapping = TRUE; } } locations = location_list_from_uri_list (item_uris); for (p = locations; p != NULL; p = p->next) { if (!g_file_has_uri_scheme ((GFile* )p->data, "burn")) { have_nonmapping_source = TRUE; } } if (target_is_mapping && have_nonmapping_source && copy_action == GDK_ACTION_MOVE) { /* never move to "burn:///", but fall back to copy. * This is a workaround, because otherwise the source files would be removed. */ copy_action = GDK_ACTION_COPY; } parent_window = NULL; if (parent_view) { parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } if (copy_action == GDK_ACTION_COPY) { src_dir = g_file_get_parent (locations->data); if (target_dir == NULL || (src_dir != NULL && g_file_equal (src_dir, dest))) { nemo_file_operations_duplicate (locations, relative_item_points, parent_window, done_callback, done_callback_data); } else { nemo_file_operations_copy (locations, relative_item_points, dest, parent_window, done_callback, done_callback_data); } if (src_dir) { g_object_unref (src_dir); } } else if (copy_action == GDK_ACTION_MOVE) { if (g_file_has_uri_scheme (dest, "trash")) { MoveTrashCBData *cb_data; cb_data = g_slice_new0 (MoveTrashCBData); cb_data->real_callback = done_callback; cb_data->real_data = done_callback_data; nemo_file_operations_trash_or_delete (locations, parent_window, (NemoDeleteCallback) callback_for_move_to_trash, cb_data); } else { nemo_file_operations_move (locations, relative_item_points, dest, parent_window, done_callback, done_callback_data); } } else { nemo_file_operations_link (locations, relative_item_points, dest, parent_window, done_callback, done_callback_data); } g_list_free_full (locations, g_object_unref); if (dest) { g_object_unref (dest); } } static gboolean create_job_done (gpointer user_data) { CreateJob *job; job = user_data; if (job->done_callback) { job->done_callback (job->created_file, !job_aborted ((CommonJob *) job), job->done_callback_data); } g_object_unref (job->dest_dir); if (job->src) { g_object_unref (job->src); } g_free (job->src_data); g_free (job->filename); if (job->created_file) { g_object_unref (job->created_file); } finalize_common ((CommonJob *)job); nemo_file_changes_consume_changes (TRUE); return FALSE; } static gboolean create_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { CreateJob *job; CommonJob *common; int count; GFile *dest; char *basename; char *filename, *filename2, *new_filename; char *filename_base, *suffix; char *dest_fs_type; GError *error; gboolean res; gboolean filename_is_utf8; char *primary, *secondary, *details; int response; char *data; int length; GFileOutputStream *out; gboolean handled_invalid_filename; int max_length, offset; job = user_data; common = &job->common; common->io_job = io_job; nemo_progress_info_start (common->progress); handled_invalid_filename = FALSE; dest_fs_type = NULL; filename = NULL; dest = NULL; max_length = get_max_name_length (job->dest_dir); verify_destination (common, job->dest_dir, NULL, -1); if (job_aborted (common)) { goto aborted; } filename = g_strdup (job->filename); filename_is_utf8 = FALSE; if (filename) { filename_is_utf8 = g_utf8_validate (filename, -1, NULL); } if (filename == NULL) { if (job->make_dir) { /* localizers: the initial name of a new folder */ filename = g_strdup (_("Untitled Folder")); filename_is_utf8 = TRUE; /* Pass in utf8 */ } else { if (job->src != NULL) { basename = g_file_get_basename (job->src); /* localizers: the initial name of a new template document */ filename = g_strdup_printf ("%s", basename); g_free (basename); } if (filename == NULL) { /* localizers: the initial name of a new empty document */ filename = g_strdup (_("Untitled Document")); filename_is_utf8 = TRUE; /* Pass in utf8 */ } } } make_file_name_valid_for_dest_fs (filename, dest_fs_type); if (filename_is_utf8) { dest = g_file_get_child_for_display_name (job->dest_dir, filename, NULL); } if (dest == NULL) { dest = g_file_get_child (job->dest_dir, filename); } count = 1; retry: error = NULL; if (job->make_dir) { res = g_file_make_directory (dest, common->cancellable, &error); if (res && common->undo_info != NULL) { nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info), dest, NULL, 0); } } else { if (job->src) { res = g_file_copy (job->src, dest, G_FILE_COPY_NONE, common->cancellable, NULL, NULL, &error); if (res && common->undo_info != NULL) { gchar *uri; uri = g_file_get_uri (job->src); nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info), dest, uri, 0); g_free (uri); } } else { data = ""; length = 0; if (job->src_data) { data = job->src_data; length = job->length; } out = g_file_create (dest, G_FILE_CREATE_NONE, common->cancellable, &error); if (out) { res = g_output_stream_write_all (G_OUTPUT_STREAM (out), data, length, NULL, common->cancellable, &error); if (res) { res = g_output_stream_close (G_OUTPUT_STREAM (out), common->cancellable, &error); if (res && common->undo_info != NULL) { nemo_file_undo_info_create_set_data (NEMO_FILE_UNDO_INFO_CREATE (common->undo_info), dest, data, length); } } /* This will close if the write failed and we didn't close */ g_object_unref (out); } else { res = FALSE; } } } if (res) { job->created_file = g_object_ref (dest); nemo_file_changes_queue_file_added (dest); if (job->has_position) { nemo_file_changes_queue_schedule_position_set (dest, job->position, common->monitor_num); } } else { g_assert (error != NULL); if (IS_IO_ERROR (error, INVALID_FILENAME) && !handled_invalid_filename) { handled_invalid_filename = TRUE; g_assert (dest_fs_type == NULL); dest_fs_type = query_fs_type (job->dest_dir, common->cancellable); g_clear_object (&dest); if (count == 1) { new_filename = g_strdup (filename); } else { filename_base = eel_filename_strip_extension (filename); offset = strlen (filename_base); suffix = g_strdup (filename + offset); filename2 = g_strdup_printf ("%s %d%s", filename_base, count, suffix); new_filename = NULL; if (max_length > 0 && strlen (filename2) > max_length) { new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length); } if (new_filename == NULL) { new_filename = g_strdup (filename2); } g_free (filename2); g_free (suffix); } if (make_file_name_valid_for_dest_fs (new_filename, dest_fs_type)) { g_clear_object (&dest); if (filename_is_utf8) { dest = g_file_get_child_for_display_name (job->dest_dir, new_filename, NULL); } if (dest == NULL) { dest = g_file_get_child (job->dest_dir, new_filename); } g_free (new_filename); g_error_free (error); goto retry; } g_free (new_filename); } else if (IS_IO_ERROR (error, EXISTS)) { g_clear_object (&dest); dest = NULL; filename_base = eel_filename_strip_extension (filename); offset = strlen (filename_base); suffix = g_strdup (filename + offset); filename2 = g_strdup_printf ("%s %d%s", filename_base, ++count, suffix); if (max_length > 0 && strlen (filename2) > max_length) { new_filename = shorten_utf8_string (filename2, strlen (filename2) - max_length); if (new_filename != NULL) { g_free (filename2); filename2 = new_filename; } } make_file_name_valid_for_dest_fs (filename2, dest_fs_type); if (filename_is_utf8) { dest = g_file_get_child_for_display_name (job->dest_dir, filename2, NULL); } if (dest == NULL) { dest = g_file_get_child (job->dest_dir, filename2); } g_free (filename2); g_free (suffix); g_error_free (error); goto retry; } else if (IS_IO_ERROR (error, CANCELLED)) { g_error_free (error); } /* Other error */ else { if (job->make_dir) { primary = f (_("Error while creating directory %B."), dest); } else { primary = f (_("Error while creating file %B."), dest); } secondary = f (_("There was an error creating the directory in %F."), job->dest_dir); details = error->message; response = run_warning (common, primary, secondary, details, FALSE, GTK_STOCK_CANCEL, SKIP, NULL); g_error_free (error); if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { /* skip */ /* do nothing */ } else { g_assert_not_reached (); } } } aborted: g_clear_object (&dest); g_free (filename); g_free (dest_fs_type); g_io_scheduler_job_send_to_mainloop_async (io_job, create_job_done, job, NULL); return FALSE; } void nemo_file_operations_new_folder (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir, NemoCreateCallback done_callback, gpointer done_callback_data) { CreateJob *job; GtkWindow *parent_window; parent_window = NULL; if (parent_view) { parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } job = op_job_new (CreateJob, parent_window); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); job->make_dir = TRUE; if (target_point != NULL) { job->position = *target_point; job->has_position = TRUE; } if (!nemo_file_undo_manager_pop_flag ()) { job->common.undo_info = nemo_file_undo_info_create_new (NEMO_FILE_UNDO_OP_CREATE_FOLDER); } add_job_to_job_queue (create_job, job, job->common.cancellable, job->common.progress, OP_KIND_CREATE); } void nemo_file_operations_new_file_from_template (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir, const char *target_filename, const char *template_uri, NemoCreateCallback done_callback, gpointer done_callback_data) { CreateJob *job; GtkWindow *parent_window; parent_window = NULL; if (parent_view) { parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } job = op_job_new (CreateJob, parent_window); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); if (target_point != NULL) { job->position = *target_point; job->has_position = TRUE; } job->filename = g_strdup (target_filename); if (template_uri) { job->src = g_file_new_for_uri (template_uri); } if (!nemo_file_undo_manager_pop_flag ()) { job->common.undo_info = nemo_file_undo_info_create_new (NEMO_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE); } add_job_to_job_queue (create_job, job, job->common.cancellable, job->common.progress, OP_KIND_CREATE); } void nemo_file_operations_new_file (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir, const char *target_filename, const char *initial_contents, int length, NemoCreateCallback done_callback, gpointer done_callback_data) { CreateJob *job; GtkWindow *parent_window; parent_window = NULL; if (parent_view) { parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } job = op_job_new (CreateJob, parent_window); job->done_callback = done_callback; job->done_callback_data = done_callback_data; job->dest_dir = g_file_new_for_uri (parent_dir); if (target_point != NULL) { job->position = *target_point; job->has_position = TRUE; } job->src_data = g_memdup (initial_contents, length); job->length = length; job->filename = g_strdup (target_filename); if (!nemo_file_undo_manager_pop_flag ()) { job->common.undo_info = nemo_file_undo_info_create_new (NEMO_FILE_UNDO_OP_CREATE_EMPTY_FILE); } add_job_to_job_queue (create_job, job, job->common.cancellable, job->common.progress, OP_KIND_CREATE); } static void delete_trash_file (CommonJob *job, GFile *file, int *deletions_since_progress, gboolean del_file, gboolean del_children) { GFileInfo *info; GFile *child; GFileEnumerator *enumerator; if (job_aborted (job)) { return; } if (del_children) { enumerator = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, job->cancellable, NULL); if (enumerator) { while (!job_aborted (job) && (info = g_file_enumerator_next_file (enumerator, job->cancellable, NULL)) != NULL) { child = g_file_get_child (file, g_file_info_get_name (info)); delete_trash_file (job, child, deletions_since_progress, TRUE, g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY); g_object_unref (child); g_object_unref (info); } g_file_enumerator_close (enumerator, job->cancellable, NULL); g_object_unref (enumerator); } } if (!job_aborted (job) && del_file) { file_delete_wrapper (file, job->cancellable, NULL); if ((*deletions_since_progress)++ > 100) { nemo_progress_info_pulse_progress (job->progress); *deletions_since_progress = 0; } } } static gboolean empty_trash_job_done (gpointer user_data) { EmptyTrashJob *job; job = user_data; g_list_free_full (job->trash_dirs, g_object_unref); if (job->done_callback) { job->done_callback (!job_aborted ((CommonJob *) job), job->done_callback_data); } finalize_common ((CommonJob *)job); return FALSE; } static gboolean empty_trash_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { EmptyTrashJob *job = user_data; CommonJob *common; GList *l; gboolean confirmed; int deletions_since_progress = 0; common = (CommonJob *)job; common->io_job = io_job; nemo_progress_info_start (common->progress); if (job->should_confirm && !job_aborted (common)) { confirmed = confirm_empty_trash (common); } else { confirmed = TRUE; } if (confirmed) { nemo_progress_info_set_status (common->progress, _("Emptying Trash")); nemo_progress_info_set_details (common->progress, _("Emptying Trash")); for (l = job->trash_dirs; l != NULL && !job_aborted (common); l = l->next) { delete_trash_file (common, l->data, &deletions_since_progress, FALSE, TRUE); } } g_io_scheduler_job_send_to_mainloop_async (io_job, empty_trash_job_done, job, NULL); return FALSE; } void nemo_file_operations_empty_trash (GtkWidget *parent_view) { EmptyTrashJob *job; GtkWindow *parent_window; parent_window = NULL; if (parent_view) { parent_window = (GtkWindow *)gtk_widget_get_ancestor (parent_view, GTK_TYPE_WINDOW); } job = op_job_new (EmptyTrashJob, parent_window); job->trash_dirs = g_list_prepend (job->trash_dirs, g_file_new_for_uri ("trash:")); job->should_confirm = TRUE; inhibit_power_manager ((CommonJob *)job, _("Emptying Trash")); generate_initial_job_details (job->common.progress, OP_KIND_EMPTY_TRASH, NULL, NULL); add_job_to_job_queue (empty_trash_job, job, job->common.cancellable, job->common.progress, OP_KIND_EMPTY_TRASH); } static gboolean mark_trusted_job_done (gpointer user_data) { MarkTrustedJob *job = user_data; g_object_unref (job->file); if (job->done_callback) { job->done_callback (!job_aborted ((CommonJob *) job), job->done_callback_data); } finalize_common ((CommonJob *)job); return FALSE; } #define TRUSTED_SHEBANG "#!/usr/bin/env xdg-open\n" static void mark_desktop_file_trusted (CommonJob *common, GCancellable *cancellable, GFile *file, gboolean interactive) { char *contents, *new_contents; gsize length, new_length; GError *error; guint32 current_perms, new_perms; int response; GFileInfo *info; retry: error = NULL; if (!g_file_load_contents (file, cancellable, &contents, &length, NULL, &error)) { if (interactive) { response = run_error (common, g_strdup (_("Unable to mark launcher trusted (executable)")), error->message, NULL, FALSE, GTK_STOCK_CANCEL, RETRY, NULL); } else { response = 0; } if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { goto retry; } else { g_assert_not_reached (); } goto out; } if (!g_str_has_prefix (contents, "#!")) { new_length = length + strlen (TRUSTED_SHEBANG); new_contents = g_malloc (new_length); strcpy (new_contents, TRUSTED_SHEBANG); memcpy (new_contents + strlen (TRUSTED_SHEBANG), contents, length); if (!g_file_replace_contents (file, new_contents, new_length, NULL, FALSE, 0, NULL, cancellable, &error)) { g_free (contents); g_free (new_contents); if (interactive) { response = run_error (common, g_strdup (_("Unable to mark launcher trusted (executable)")), error->message, NULL, FALSE, GTK_STOCK_CANCEL, RETRY, NULL); } else { response = 0; } if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { goto retry; } else { g_assert_not_reached (); } goto out; } g_free (new_contents); } g_free (contents); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE"," G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, common->cancellable, &error); if (info == NULL) { if (interactive) { response = run_error (common, g_strdup (_("Unable to mark launcher trusted (executable)")), error->message, NULL, FALSE, GTK_STOCK_CANCEL, RETRY, NULL); } else { response = 0; } if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { goto retry; } else { g_assert_not_reached (); } goto out; } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE)) { current_perms = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); new_perms = current_perms | S_IXGRP | S_IXUSR | S_IXOTH; if ((current_perms != new_perms) && !g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_MODE, new_perms, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, common->cancellable, &error)) { g_object_unref (info); if (interactive) { response = run_error (common, g_strdup (_("Unable to mark launcher trusted (executable)")), error->message, NULL, FALSE, GTK_STOCK_CANCEL, RETRY, NULL); } else { response = 0; } if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { abort_job (common); } else if (response == 1) { goto retry; } else { g_assert_not_reached (); } goto out; } } g_object_unref (info); out: ; } static gboolean mark_trusted_job (GIOSchedulerJob *io_job, GCancellable *cancellable, gpointer user_data) { MarkTrustedJob *job = user_data; CommonJob *common; common = (CommonJob *)job; common->io_job = io_job; nemo_progress_info_start (common->progress); mark_desktop_file_trusted (common, cancellable, job->file, job->interactive); g_io_scheduler_job_send_to_mainloop_async (io_job, mark_trusted_job_done, job, NULL); return FALSE; } void nemo_file_mark_desktop_file_trusted (GFile *file, GtkWindow *parent_window, gboolean interactive, NemoOpCallback done_callback, gpointer done_callback_data) { MarkTrustedJob *job; job = op_job_new (MarkTrustedJob, parent_window); job->file = g_object_ref (file); job->interactive = interactive; job->done_callback = done_callback; job->done_callback_data = done_callback_data; add_job_to_job_queue (mark_trusted_job, job, job->common.cancellable, job->common.progress, OP_KIND_PERMISSIONS); } #if 0 #define DEBUG_FILE_OP_QUEUE #endif static gboolean job_is_local (GList *files, GFile *destination) { gboolean ret = FALSE; NemoFile *source = nemo_file_get_existing (G_FILE (files->data)); if (source == NULL) return FALSE; NemoFile *dest = destination != NULL ? nemo_file_get_existing (destination) : NULL; if (dest != NULL) { ret = nemo_file_is_local (source) && nemo_file_is_local (dest); } else { ret = nemo_file_is_local (source); } nemo_file_unref (source); nemo_file_unref (dest); #ifdef DEBUG_FILE_OP_QUEUE g_message ("File op job is local: %s\n", ret ? "TRUE" : "FALSE"); #endif return ret; } static gboolean job_is_same_fs (GList *files, GFile *destination) { gboolean ret = FALSE; NemoFile *source = nemo_file_get_existing (G_FILE (files->data)); if (source == NULL) return FALSE; NemoFile *dest = nemo_file_get_existing (destination); if (dest != NULL) { gchar *src_fs_id = nemo_file_get_filesystem_id (source); gchar *dst_fs_id = nemo_file_get_filesystem_id (dest); if (g_strcmp0 (src_fs_id, dst_fs_id) == 0) ret = TRUE; #ifdef DEBUG_FILE_OP_QUEUE g_message ("File op job is same filesystem (src: %s, dst: %s): %s\n", src_fs_id, dst_fs_id, ret ? "TRUE" : "FALSE"); #endif g_free (src_fs_id); g_free (dst_fs_id); } nemo_file_unref (source); nemo_file_unref (dest); return ret; } static gboolean job_has_no_folders (GList *files) { GList *l; gboolean ret = TRUE; for (l = files; l != NULL; l = l->next) { GFile *location = G_FILE (l->data); NemoFile *file = nemo_file_get_existing (location); if (file == NULL) { ret = FALSE; break; } if (nemo_file_is_directory (file)) { ret = FALSE; nemo_file_unref (file); break; } nemo_file_unref (file); } #ifdef DEBUG_FILE_OP_QUEUE g_message ("File op job has no folders: %s\n", ret ? "TRUE" : "FALSE"); #endif return ret; } static gboolean job_is_small (GList *files) { gboolean ret = FALSE; GList *l; goffset size = 0; for (l = files; l != NULL; l = l->next) { GFile *location = G_FILE (l->data); NemoFile *file = nemo_file_get_existing (location); if (file == NULL) { size = G_MAXOFFSET; break; } size = size + nemo_file_get_size (file); nemo_file_unref (file); } ret = size < 104857600; /* 100 mb */ #ifdef DEBUG_FILE_OP_QUEUE g_message ("File op job is small: %s\n", ret ? "TRUE" : "FALSE"); #endif return ret; } static gboolean should_start_immediately (OpKind kind, gpointer op_data) { gboolean ret = FALSE; switch (kind) { case OP_KIND_CREATE: case OP_KIND_TRUST: case OP_KIND_EMPTY_TRASH: case OP_KIND_PERMISSIONS: case OP_KIND_LINK: ret = TRUE; break; case OP_KIND_MOVE: ; CopyMoveJob *mjob = (CopyMoveJob *) op_data; ret = job_is_same_fs (mjob->files, mjob->destination) && job_is_local (mjob->files, mjob->destination); break; case OP_KIND_COPY: ; CopyMoveJob *cjob = (CopyMoveJob *) op_data; ret = job_is_same_fs (cjob->files, cjob->destination) && job_is_local (cjob->files, cjob->destination) && job_has_no_folders (cjob->files) && job_is_small (cjob->files); break; case OP_KIND_DUPE: ; CopyMoveJob *dupejob = (CopyMoveJob *) op_data; ret = job_is_local (dupejob->files, dupejob->destination) && job_has_no_folders (dupejob->files) && job_is_small (dupejob->files); break; case OP_KIND_DELETE: case OP_KIND_TRASH: ; DeleteJob *deljob = (DeleteJob *) op_data; ret = job_is_local (deljob->files, NULL) || (job_has_no_folders (deljob->files) && job_is_small (deljob->files)); break; default: ret = FALSE; break; } #ifdef DEBUG_FILE_OP_QUEUE g_message ("File op job STARTING IMMEDIATELY: %s\n", ret ? "TRUE" : "FALSE"); #endif return ret; } void add_job_to_job_queue (GIOSchedulerJobFunc job_func, gpointer user_data, GCancellable *cancellable, NemoProgressInfo *info, OpKind kind) { gboolean start_immediately; NemoJobQueue *job_queue = nemo_job_queue_get (); start_immediately = should_start_immediately (kind, user_data); nemo_job_queue_add_new_job (job_queue, job_func, user_data, cancellable, info, start_immediately); } #if !defined (NEMO_OMIT_SELF_CHECK) void nemo_self_check_file_operations (void) { setlocale (LC_MESSAGES, "C"); /* test the next duplicate name generator */ EEL_CHECK_STRING_RESULT (get_duplicate_name (" (copy)", 1, -1), " (another copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo", 1, -1), "foo (copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name (".bashrc", 1, -1), ".bashrc (copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name (".foo.txt", 1, -1), ".foo (copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo", 1, -1), "foo foo (copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo.txt", 1, -1), "foo (copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt", 1, -1), "foo foo (copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo.txt txt", 1, -1), "foo foo (copy).txt txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...txt", 1, -1), "foo.. (copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo...", 1, -1), "foo... (copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo. (copy)", 1, -1), "foo. (another copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy)", 1, -1), "foo (another copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (copy).txt", 1, -1), "foo (another copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy)", 1, -1), "foo (3rd copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (another copy).txt", 1, -1), "foo (3rd copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (another copy).txt", 1, -1), "foo foo (3rd copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy)", 1, -1), "foo (14th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (13th copy).txt", 1, -1), "foo (14th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy)", 1, -1), "foo (22nd copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (21st copy).txt", 1, -1), "foo (22nd copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy)", 1, -1), "foo (23rd copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (22nd copy).txt", 1, -1), "foo (23rd copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy)", 1, -1), "foo (24th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (23rd copy).txt", 1, -1), "foo (24th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy)", 1, -1), "foo (25th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (24th copy).txt", 1, -1), "foo (25th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy)", 1, -1), "foo foo (25th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (24th copy).txt", 1, -1), "foo foo (25th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo foo (100000000000000th copy).txt", 1, -1), "foo foo (copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy)", 1, -1), "foo (11th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (10th copy).txt", 1, -1), "foo (11th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy)", 1, -1), "foo (12th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (11th copy).txt", 1, -1), "foo (12th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy)", 1, -1), "foo (13th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (12th copy).txt", 1, -1), "foo (13th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy)", 1, -1), "foo (111th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (110th copy).txt", 1, -1), "foo (111th copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy)", 1, -1), "foo (123rd copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (122nd copy).txt", 1, -1), "foo (123rd copy).txt"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy)", 1, -1), "foo (124th copy)"); EEL_CHECK_STRING_RESULT (get_duplicate_name ("foo (123rd copy).txt", 1, -1), "foo (124th copy).txt"); setlocale (LC_MESSAGES, ""); } #endif nemo-3.6.5/libnemo-private/nemo-job-queue.h0000664000175000017500000000502613215733314017512 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-job-queue.h - file operation queue This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef __NEMO_JOB_QUEUE_H__ #define __NEMO_JOB_QUEUE_H__ #include #include #define NEMO_TYPE_JOB_QUEUE nemo_job_queue_get_type() #define NEMO_JOB_QUEUE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_JOB_QUEUE, NemoJobQueue)) #define NEMO_JOB_QUEUE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_JOB_QUEUE, NemoJobQueueClass)) #define NEMO_IS_JOB_QUEUE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_JOB_QUEUE)) #define NEMO_IS_JOB_QUEUE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_JOB_QUEUE)) #define NEMO_JOB_QUEUE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_JOB_QUEUE, NemoJobQueueClass)) typedef struct _NemoJobQueue NemoJobQueue; typedef struct _NemoJobQueueClass NemoJobQueueClass; typedef struct _NemoJobQueuePriv NemoJobQueuePriv; struct _NemoJobQueue { GObject parent; /* private */ NemoJobQueuePriv *priv; }; struct _NemoJobQueueClass { GObjectClass parent_class; }; GType nemo_job_queue_get_type (void); NemoJobQueue *nemo_job_queue_get (void); void nemo_job_queue_add_new_job (NemoJobQueue *self, GIOSchedulerJobFunc job_func, gpointer user_data, GCancellable *cancellable, NemoProgressInfo *info, gboolean start_immediately); void nemo_job_queue_start_next_job (NemoJobQueue *self); void nemo_job_queue_start_job_by_info (NemoJobQueue *self, NemoProgressInfo *info); GList *nemo_job_queue_get_all_jobs (NemoJobQueue *self); G_END_DECLS #endif /* __NEMO_JOB_QUEUE_H__ */ nemo-3.6.5/libnemo-private/nemo-undo-signal-handlers.c0000664000175000017500000001520713215733314021631 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Signal handlers to enable undo in Gtk Widgets. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include #include #include #include #include "nemo-undo-signal-handlers.h" typedef struct { char *undo_text; gint position; guint selection_start; guint selection_end; } EditableUndoData; typedef struct { gboolean undo_registered; } EditableUndoObjectData; static void restore_editable_from_undo_snapshot_callback (GObject *target, gpointer callback_data); static void editable_register_edit_undo (GtkEditable *editable); static void free_editable_object_data (gpointer data); /* nemo_undo_set_up_nemo_entry_for_undo * * Functions and callback methods to handle undo * in a NemoEntry */ static void nemo_entry_user_changed_callback (NemoEntry *entry) { /* Register undo transaction */ editable_register_edit_undo (GTK_EDITABLE (entry)); } void nemo_undo_set_up_nemo_entry_for_undo (NemoEntry *entry) { EditableUndoObjectData *data; if (!NEMO_IS_ENTRY (entry) ) { return; } data = g_new(EditableUndoObjectData, 1); data->undo_registered = FALSE; g_object_set_data_full (G_OBJECT (entry), "undo_registered", data, free_editable_object_data); /* Connect to entry signals */ g_signal_connect (entry, "user_changed", G_CALLBACK (nemo_entry_user_changed_callback), NULL); } void nemo_undo_tear_down_nemo_entry_for_undo (NemoEntry *entry) { if (!NEMO_IS_ENTRY (entry) ) { return; } /* Disconnect from entry signals */ g_signal_handlers_disconnect_by_func (entry, G_CALLBACK (nemo_entry_user_changed_callback), NULL); } /* nemo_undo_set_up_nemo_entry_for_undo * * Functions and callback methods to handle undo * in a NemoEntry */ static void free_editable_undo_data (gpointer data) { EditableUndoData *undo_data; undo_data = (EditableUndoData *) data; g_free (undo_data->undo_text); g_free (undo_data); } static void free_editable_object_data (gpointer data) { g_free (data); } static void editable_insert_text_callback (GtkEditable *editable) { /* Register undo transaction */ editable_register_edit_undo (editable); } static void editable_delete_text_callback (GtkEditable *editable) { /* Register undo transaction */ editable_register_edit_undo (editable); } static void editable_register_edit_undo (GtkEditable *editable) { EditableUndoData *undo_data; EditableUndoObjectData *undo_info; gpointer data; if (!GTK_IS_EDITABLE (editable) ) { return; } /* Check our undo registered flag */ data = g_object_get_data (G_OBJECT (editable), "undo_registered"); if (data == NULL) { g_warning ("Undo data is NULL"); return; } undo_info = (EditableUndoObjectData *)data; if (undo_info->undo_registered) { return; } undo_data = g_new0 (EditableUndoData, 1); undo_data->undo_text = gtk_editable_get_chars (editable, 0, -1); undo_data->position = gtk_editable_get_position (editable); gtk_editable_get_selection_bounds (editable, &undo_data->selection_start, &undo_data->selection_end); nemo_undo_register (G_OBJECT (editable), restore_editable_from_undo_snapshot_callback, undo_data, (GDestroyNotify) free_editable_undo_data, _("Edit"), _("Undo Edit"), _("Undo the edit"), _("Redo Edit"), _("Redo the edit")); undo_info->undo_registered = TRUE; } void nemo_undo_set_up_editable_for_undo (GtkEditable *editable) { EditableUndoObjectData *data; if (!GTK_IS_EDITABLE (editable) ) { return; } /* Connect to editable signals */ g_signal_connect (editable, "insert_text", G_CALLBACK (editable_insert_text_callback), NULL); g_signal_connect (editable, "delete_text", G_CALLBACK (editable_delete_text_callback), NULL); data = g_new (EditableUndoObjectData, 1); data->undo_registered = FALSE; g_object_set_data_full (G_OBJECT (editable), "undo_registered", data, free_editable_object_data); } void nemo_undo_tear_down_editable_for_undo (GtkEditable *editable) { if (!GTK_IS_EDITABLE (editable) ) { return; } /* Disconnect from entry signals */ g_signal_handlers_disconnect_by_func (editable, G_CALLBACK (editable_insert_text_callback), NULL); g_signal_handlers_disconnect_by_func (editable, G_CALLBACK (editable_delete_text_callback), NULL); } /* restore_editable_from_undo_snapshot_callback * * Restore edited text. */ static void restore_editable_from_undo_snapshot_callback (GObject *target, gpointer callback_data) { GtkEditable *editable; GtkWindow *window; EditableUndoData *undo_data; EditableUndoObjectData *data; gint position; editable = GTK_EDITABLE (target); undo_data = (EditableUndoData *) callback_data; /* Check our undo registered flag */ data = g_object_get_data (target, "undo_registered"); if (data == NULL) { g_warning ("Undo regisetred flag not found"); return; } /* Reset the registered flag so we get a new item for future editing. */ data->undo_registered = FALSE; /* Register a new undo transaction for redo. */ editable_register_edit_undo (editable); /* Restore the text. */ position = 0; gtk_editable_delete_text (editable, 0, -1); gtk_editable_insert_text (editable, undo_data->undo_text, strlen (undo_data->undo_text), &position); /* Set focus to widget */ window = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (target))); gtk_window_set_focus (window, GTK_WIDGET (editable)); /* We have to do this call, because the previous call selects all text */ gtk_editable_select_region (editable, 0, 0); /* Restore selection */ gtk_editable_select_region (editable, undo_data->selection_start, undo_data->selection_end); /* Set the i-beam to the saved position */ gtk_editable_set_position (editable, undo_data->position); /* Reset the registered flag so we get a new item for future editing. */ data->undo_registered = FALSE; } nemo-3.6.5/libnemo-private/nemo-desktop-directory-file.h0000664000175000017500000000433313215733314022206 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-directory-file.h: Subclass of NemoFile to implement the the case of the desktop directory Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_DESKTOP_DIRECTORY_FILE_H #define NEMO_DESKTOP_DIRECTORY_FILE_H #include #define NEMO_TYPE_DESKTOP_DIRECTORY_FILE nemo_desktop_directory_file_get_type() #define NEMO_DESKTOP_DIRECTORY_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DESKTOP_DIRECTORY_FILE, NemoDesktopDirectoryFile)) #define NEMO_DESKTOP_DIRECTORY_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DESKTOP_DIRECTORY_FILE, NemoDesktopDirectoryFileClass)) #define NEMO_IS_DESKTOP_DIRECTORY_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DESKTOP_DIRECTORY_FILE)) #define NEMO_IS_DESKTOP_DIRECTORY_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DESKTOP_DIRECTORY_FILE)) #define NEMO_DESKTOP_DIRECTORY_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DESKTOP_DIRECTORY_FILE, NemoDesktopDirectoryFileClass)) typedef struct NemoDesktopDirectoryFileDetails NemoDesktopDirectoryFileDetails; typedef struct { NemoFile parent_slot; NemoDesktopDirectoryFileDetails *details; } NemoDesktopDirectoryFile; typedef struct { NemoFileClass parent_slot; } NemoDesktopDirectoryFileClass; GType nemo_desktop_directory_file_get_type (void); #endif /* NEMO_DESKTOP_DIRECTORY_FILE_H */ nemo-3.6.5/libnemo-private/nemo-desktop-link.h0000664000175000017500000000673013215733314020225 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-link.h: Class that handles the links on the desktop Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_DESKTOP_LINK_H #define NEMO_DESKTOP_LINK_H #include #include #define NEMO_TYPE_DESKTOP_LINK nemo_desktop_link_get_type() #define NEMO_DESKTOP_LINK(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DESKTOP_LINK, NemoDesktopLink)) #define NEMO_DESKTOP_LINK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DESKTOP_LINK, NemoDesktopLinkClass)) #define NEMO_IS_DESKTOP_LINK(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DESKTOP_LINK)) #define NEMO_IS_DESKTOP_LINK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DESKTOP_LINK)) #define NEMO_DESKTOP_LINK_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DESKTOP_LINK, NemoDesktopLinkClass)) typedef struct NemoDesktopLinkDetails NemoDesktopLinkDetails; typedef struct { GObject parent_slot; NemoDesktopLinkDetails *details; } NemoDesktopLink; typedef struct { GObjectClass parent_slot; } NemoDesktopLinkClass; typedef enum { NEMO_DESKTOP_LINK_HOME, NEMO_DESKTOP_LINK_COMPUTER, NEMO_DESKTOP_LINK_TRASH, NEMO_DESKTOP_LINK_MOUNT, NEMO_DESKTOP_LINK_NETWORK } NemoDesktopLinkType; GType nemo_desktop_link_get_type (void); NemoDesktopLink * nemo_desktop_link_new (NemoDesktopLinkType type); NemoDesktopLink * nemo_desktop_link_new_from_mount (GMount *mount); NemoDesktopLinkType nemo_desktop_link_get_link_type (NemoDesktopLink *link); NemoFile * nemo_desktop_link_get_file (NemoDesktopLink *link); char * nemo_desktop_link_get_file_name (NemoDesktopLink *link); char * nemo_desktop_link_get_display_name (NemoDesktopLink *link); GIcon * nemo_desktop_link_get_icon (NemoDesktopLink *link); GFile * nemo_desktop_link_get_activation_location (NemoDesktopLink *link); char * nemo_desktop_link_get_activation_uri (NemoDesktopLink *link); gboolean nemo_desktop_link_get_date (NemoDesktopLink *link, NemoDateType date_type, time_t *date); GMount * nemo_desktop_link_get_mount (NemoDesktopLink *link); gboolean nemo_desktop_link_can_rename (NemoDesktopLink *link); gboolean nemo_desktop_link_rename (NemoDesktopLink *link, const char *name); #endif /* NEMO_DESKTOP_LINK_H */ nemo-3.6.5/libnemo-private/nemo-file-undo-operations.c0000664000175000017500000014044713215733314021663 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-undo-operations.c - Manages undo/redo of file operations * * Copyright (C) 2007-2011 Amos Brocco * Copyright (C) 2010, 2012 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Amos Brocco * Cosimo Cecchi * */ #include #include "nemo-file-undo-operations.h" #include #include #include "nemo-file-operations.h" #include "nemo-file.h" #include "nemo-file-undo-manager.h" /* Since we use g_get_current_time for setting "orig_trash_time" in the undo * info, there are situations where the difference between this value and the * real deletion time can differ enough to make the rounding a difference of 1 * second, failing the equality check. To make sure we avoid this, and to be * preventive, use 2 seconds epsilon. */ #define TRASH_TIME_EPSILON 2 #define HEAD(q) (g_queue_peek_head_link(q)) G_DEFINE_TYPE (NemoFileUndoInfo, nemo_file_undo_info, G_TYPE_OBJECT) enum { PROP_OP_TYPE = 1, PROP_ITEM_COUNT, N_PROPERTIES }; static GParamSpec *properties[N_PROPERTIES] = { NULL, }; struct _NemoFileUndoInfoDetails { NemoFileUndoOp op_type; guint count; /* Number of items */ GSimpleAsyncResult *apply_async_result; gchar *undo_label; gchar *redo_label; gchar *undo_description; gchar *redo_description; }; /* description helpers */ static void nemo_file_undo_info_init (NemoFileUndoInfo *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_FILE_UNDO_INFO, NemoFileUndoInfoDetails); self->priv->apply_async_result = NULL; } static void nemo_file_undo_info_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { NemoFileUndoInfo *self = NEMO_FILE_UNDO_INFO (object); switch (property_id) { case PROP_OP_TYPE: g_value_set_int (value, self->priv->op_type); break; case PROP_ITEM_COUNT: g_value_set_int (value, self->priv->count); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_file_undo_info_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { NemoFileUndoInfo *self = NEMO_FILE_UNDO_INFO (object); switch (property_id) { case PROP_OP_TYPE: self->priv->op_type = g_value_get_int (value); break; case PROP_ITEM_COUNT: self->priv->count = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_file_redo_info_warn_redo (NemoFileUndoInfo *self, GtkWindow *parent_window) { g_critical ("Object %p of type %s does not implement redo_func!!", self, G_OBJECT_TYPE_NAME (self)); } static void nemo_file_undo_info_warn_undo (NemoFileUndoInfo *self, GtkWindow *parent_window) { g_critical ("Object %p of type %s does not implement undo_func!!", self, G_OBJECT_TYPE_NAME (self)); } static void nemo_file_undo_info_strings_func (NemoFileUndoInfo *self, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { if (undo_label != NULL) { *undo_label = g_strdup (_("Undo")); } if (undo_description != NULL) { *undo_description = g_strdup (_("Undo last action")); } if (redo_label != NULL) { *redo_label = g_strdup (_("Redo")); } if (redo_description != NULL) { *redo_description = g_strdup (_("Redo last undone action")); } } static void nemo_file_undo_info_finalize (GObject *obj) { NemoFileUndoInfo *self = NEMO_FILE_UNDO_INFO (obj); g_clear_object (&self->priv->apply_async_result); G_OBJECT_CLASS (nemo_file_undo_info_parent_class)->finalize (obj); } static void nemo_file_undo_info_class_init (NemoFileUndoInfoClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); oclass->finalize = nemo_file_undo_info_finalize; oclass->get_property = nemo_file_undo_info_get_property; oclass->set_property = nemo_file_undo_info_set_property; klass->undo_func = nemo_file_undo_info_warn_undo; klass->redo_func = nemo_file_redo_info_warn_redo; klass->strings_func = nemo_file_undo_info_strings_func; properties[PROP_OP_TYPE] = g_param_spec_int ("op-type", "Undo info op type", "Type of undo operation", 0, NEMO_FILE_UNDO_OP_NUM_TYPES - 1, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); properties[PROP_ITEM_COUNT] = g_param_spec_int ("item-count", "Number of items", "Number of items", 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_type_class_add_private (klass, sizeof (NemoFileUndoInfoDetails)); g_object_class_install_properties (oclass, N_PROPERTIES, properties); } static NemoFileUndoOp nemo_file_undo_info_get_op_type (NemoFileUndoInfo *self) { return self->priv->op_type; } static gint nemo_file_undo_info_get_item_count (NemoFileUndoInfo *self) { return self->priv->count; } void nemo_file_undo_info_apply_async (NemoFileUndoInfo *self, gboolean undo, GtkWindow *parent_window, GAsyncReadyCallback callback, gpointer user_data) { g_assert (self->priv->apply_async_result == NULL); self->priv->apply_async_result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, nemo_file_undo_info_apply_async); if (undo) { NEMO_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->undo_func (self, parent_window); } else { NEMO_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->redo_func (self, parent_window); } } typedef struct { gboolean success; gboolean user_cancel; } FileUndoInfoOpRes; static void file_undo_info_op_res_free (gpointer data) { g_slice_free (FileUndoInfoOpRes, data); } gboolean nemo_file_undo_info_apply_finish (NemoFileUndoInfo *self, GAsyncResult *res, gboolean *user_cancel, GError **error) { FileUndoInfoOpRes *op_res; if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error)) { return FALSE; } op_res = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); *user_cancel = op_res->user_cancel; return op_res->success; } void nemo_file_undo_info_get_strings (NemoFileUndoInfo *self, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { return NEMO_FILE_UNDO_INFO_CLASS (G_OBJECT_GET_CLASS (self))->strings_func (self, undo_label, undo_description, redo_label, redo_description); } static void file_undo_info_complete_apply (NemoFileUndoInfo *self, gboolean success, gboolean user_cancel) { FileUndoInfoOpRes *op_res = g_slice_new0 (FileUndoInfoOpRes); op_res->user_cancel = user_cancel; op_res->success = success; g_simple_async_result_set_op_res_gpointer (self->priv->apply_async_result, op_res, file_undo_info_op_res_free); g_simple_async_result_complete_in_idle (self->priv->apply_async_result); g_clear_object (&self->priv->apply_async_result); } static void file_undo_info_transfer_callback (GHashTable * debuting_uris, gboolean success, gpointer user_data) { NemoFileUndoInfo *self = user_data; /* TODO: we need to forward the cancelled state from * the file operation to the file undo info object. */ file_undo_info_complete_apply (self, success, FALSE); } static void file_undo_info_operation_callback (NemoFile * file, GFile * result_location, GError * error, gpointer user_data) { NemoFileUndoInfo *self = user_data; file_undo_info_complete_apply (self, (error == NULL), g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)); } static void file_undo_info_delete_callback (GHashTable *debuting_uris, gboolean user_cancel, gpointer user_data) { NemoFileUndoInfo *self = user_data; file_undo_info_complete_apply (self, !user_cancel, user_cancel); } /* copy/move/duplicate/link/restore from trash */ G_DEFINE_TYPE (NemoFileUndoInfoExt, nemo_file_undo_info_ext, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoExtDetails { GFile *src_dir; GFile *dest_dir; GQueue *sources; /* Relative to src_dir */ GQueue *destinations; /* Relative to dest_dir */ }; static char * ext_get_first_target_short_name (NemoFileUndoInfoExt *self) { GFile *first_file; char *file_name = NULL; first_file = G_FILE (g_queue_peek_head (self->priv->destinations)); if (first_file != NULL) { file_name = g_file_get_basename (first_file); } return file_name; } static void ext_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoExt *self = NEMO_FILE_UNDO_INFO_EXT (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); gint count = nemo_file_undo_info_get_item_count (info); gchar *name = NULL, *source, *destination; source = g_file_get_path (self->priv->src_dir); destination = g_file_get_path (self->priv->dest_dir); if (count <= 1) { name = ext_get_first_target_short_name (self); } if (op_type == NEMO_FILE_UNDO_OP_MOVE) { if (count > 1) { *undo_description = g_strdup_printf (ngettext ("Move %d item back to '%s'", "Move %d items back to '%s'", count), count, source); *redo_description = g_strdup_printf (ngettext ("Move %d item to '%s'", "Move %d items to '%s'", count), count, destination); *undo_label = g_strdup_printf (ngettext ("_Undo Move %d item", "_Undo Move %d items", count), count); *redo_label = g_strdup_printf (ngettext ("_Redo Move %d item", "_Redo Move %d items", count), count); } else { *undo_description = g_strdup_printf (_("Move '%s' back to '%s'"), name, source); *redo_description = g_strdup_printf (_("Move '%s' to '%s'"), name, destination); *undo_label = g_strdup (_("_Undo Move")); *redo_label = g_strdup (_("_Redo Move")); } } else if (op_type == NEMO_FILE_UNDO_OP_RESTORE_FROM_TRASH) { *undo_label = g_strdup (_("_Undo Restore from Trash")); *redo_label = g_strdup (_("_Redo Restore from Trash")); if (count > 1) { *undo_description = g_strdup_printf (ngettext ("Move %d item back to trash", "Move %d items back to trash", count), count); *redo_description = g_strdup_printf (ngettext ("Restore %d item from trash", "Restore %d items from trash", count), count); } else { *undo_description = g_strdup_printf (_("Move '%s' back to trash"), name); *redo_description = g_strdup_printf (_("Restore '%s' from trash"), name); } } else if (op_type == NEMO_FILE_UNDO_OP_COPY) { if (count > 1) { *undo_description = g_strdup_printf (ngettext ("Delete %d copied item", "Delete %d copied items", count), count); *redo_description = g_strdup_printf (ngettext ("Copy %d item to '%s'", "Copy %d items to '%s'", count), count, destination); *undo_label = g_strdup_printf (ngettext ("_Undo Copy %d item", "_Undo Copy %d items", count), count); *redo_label = g_strdup_printf (ngettext ("_Redo Copy %d item", "_Redo Copy %d items", count), count); } else { *undo_description = g_strdup_printf (_("Delete '%s'"), name); *redo_description = g_strdup_printf (_("Copy '%s' to '%s'"), name, destination); *undo_label = g_strdup (_("_Undo Copy")); *redo_label = g_strdup (_("_Redo Copy")); } } else if (op_type == NEMO_FILE_UNDO_OP_DUPLICATE) { if (count > 1) { *undo_description = g_strdup_printf (ngettext ("Delete %d duplicated item", "Delete %d duplicated items", count), count); *redo_description = g_strdup_printf (ngettext ("Duplicate %d item in '%s'", "Duplicate %d items in '%s'", count), count, destination); *undo_label = g_strdup_printf (ngettext ("_Undo Duplicate %d item", "_Undo Duplicate %d items", count), count); *redo_label = g_strdup_printf (ngettext ("_Redo Duplicate %d item", "_Redo Duplicate %d items", count), count); } else { *undo_description = g_strdup_printf (_("Delete '%s'"), name); *redo_description = g_strdup_printf (_("Duplicate '%s' in '%s'"), name, destination); *undo_label = g_strdup (_("_Undo Duplicate")); *redo_label = g_strdup (_("_Redo Duplicate")); } } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_LINK) { if (count > 1) { *undo_description = g_strdup_printf (ngettext ("Delete links to %d item", "Delete links to %d items", count), count); *redo_description = g_strdup_printf (ngettext ("Create links to %d item", "Create links to %d items", count), count); } else { *undo_description = g_strdup_printf (_("Delete link to '%s'"), name); *redo_description = g_strdup_printf (_("Create link to '%s'"), name); *undo_label = g_strdup (_("_Undo Create Link")); *redo_label = g_strdup (_("_Redo Create Link")); } } else { g_assert_not_reached (); } g_free (name); g_free (source); g_free (destination); } static void ext_create_link_redo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_link (HEAD (self->priv->sources), NULL, self->priv->dest_dir, parent_window, file_undo_info_transfer_callback, self); } static void ext_duplicate_redo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_duplicate (HEAD (self->priv->sources), NULL, parent_window, file_undo_info_transfer_callback, self); } static void ext_copy_redo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_copy (HEAD (self->priv->sources), NULL, self->priv->dest_dir, parent_window, file_undo_info_transfer_callback, self); } static void ext_move_restore_redo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_move (HEAD (self->priv->sources), NULL, self->priv->dest_dir, parent_window, file_undo_info_transfer_callback, self); } static void ext_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoExt *self = NEMO_FILE_UNDO_INFO_EXT (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); if (op_type == NEMO_FILE_UNDO_OP_MOVE || op_type == NEMO_FILE_UNDO_OP_RESTORE_FROM_TRASH) { ext_move_restore_redo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_COPY) { ext_copy_redo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_DUPLICATE) { ext_duplicate_redo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_LINK) { ext_create_link_redo_func (self, parent_window); } else { g_assert_not_reached (); } } static void ext_restore_undo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_trash_or_delete (HEAD (self->priv->destinations), parent_window, file_undo_info_delete_callback, self); } static void ext_move_undo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { nemo_file_operations_move (HEAD (self->priv->destinations), NULL, self->priv->src_dir, parent_window, file_undo_info_transfer_callback, self); } static void ext_copy_duplicate_undo_func (NemoFileUndoInfoExt *self, GtkWindow *parent_window) { GList *files; files = g_list_copy (HEAD (self->priv->destinations)); files = g_list_reverse (files); /* Deleting must be done in reverse */ nemo_file_operations_delete (files, parent_window, file_undo_info_delete_callback, self); g_list_free (files); } static void ext_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoExt *self = NEMO_FILE_UNDO_INFO_EXT (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); if (op_type == NEMO_FILE_UNDO_OP_COPY || op_type == NEMO_FILE_UNDO_OP_DUPLICATE || op_type == NEMO_FILE_UNDO_OP_CREATE_LINK) { ext_copy_duplicate_undo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_MOVE) { ext_move_undo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_RESTORE_FROM_TRASH) { ext_restore_undo_func (self, parent_window); } else { g_assert_not_reached (); } } static void nemo_file_undo_info_ext_init (NemoFileUndoInfoExt *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_ext_get_type (), NemoFileUndoInfoExtDetails); } static void nemo_file_undo_info_ext_finalize (GObject *obj) { NemoFileUndoInfoExt *self = NEMO_FILE_UNDO_INFO_EXT (obj); if (self->priv->sources) { g_queue_free_full (self->priv->sources, g_object_unref); } if (self->priv->destinations) { g_queue_free_full (self->priv->destinations, g_object_unref); } g_clear_object (&self->priv->src_dir); g_clear_object (&self->priv->dest_dir); G_OBJECT_CLASS (nemo_file_undo_info_ext_parent_class)->finalize (obj); } static void nemo_file_undo_info_ext_class_init (NemoFileUndoInfoExtClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_ext_finalize; iclass->undo_func = ext_undo_func; iclass->redo_func = ext_redo_func; iclass->strings_func = ext_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoExtDetails)); } NemoFileUndoInfo * nemo_file_undo_info_ext_new (NemoFileUndoOp op_type, gint item_count, GFile *src_dir, GFile *target_dir) { NemoFileUndoInfoExt *retval; retval = g_object_new (NEMO_TYPE_FILE_UNDO_INFO_EXT, "op-type", op_type, "item-count", item_count, NULL); retval->priv->src_dir = g_object_ref (src_dir); retval->priv->dest_dir = g_object_ref (target_dir); retval->priv->destinations = g_queue_new (); retval->priv->sources = g_queue_new (); return NEMO_FILE_UNDO_INFO (retval); } void nemo_file_undo_info_ext_add_origin_target_pair (NemoFileUndoInfoExt *self, GFile *origin, GFile *target) { g_queue_push_tail (self->priv->sources, g_object_ref (origin)); g_queue_push_tail (self->priv->destinations, g_object_ref (target)); } /* create new file/folder */ G_DEFINE_TYPE (NemoFileUndoInfoCreate, nemo_file_undo_info_create, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoCreateDetails { char *template; GFile *target_file; gint length; }; static void create_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoCreate *self = NEMO_FILE_UNDO_INFO_CREATE (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); char *name; name = g_file_get_parse_name (self->priv->target_file); *undo_description = g_strdup_printf (_("Delete '%s'"), name); if (op_type == NEMO_FILE_UNDO_OP_CREATE_EMPTY_FILE) { *redo_description = g_strdup_printf (_("Create an empty file '%s'"), name); *undo_label = g_strdup (_("_Undo Create Empty File")); *redo_label = g_strdup (_("_Redo Create Empty File")); } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_FOLDER) { *redo_description = g_strdup_printf (_("Create a new folder '%s'"), name); *undo_label = g_strdup (_("_Undo Create Folder")); *redo_label = g_strdup (_("_Redo Create Folder")); } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE) { *redo_description = g_strdup_printf (_("Create new file '%s' from template "), name); *undo_label = g_strdup (_("_Undo Create from Template")); *redo_label = g_strdup (_("_Redo Create from Template")); } else { g_assert_not_reached (); } g_free (name); } static void create_callback (GFile * new_file, gboolean success, gpointer callback_data) { file_undo_info_transfer_callback (NULL, success, callback_data); } static void create_from_template_redo_func (NemoFileUndoInfoCreate *self, GtkWindow *parent_window) { GFile *parent; gchar *parent_uri, *new_name; parent = g_file_get_parent (self->priv->target_file); parent_uri = g_file_get_uri (parent); new_name = g_file_get_parse_name (self->priv->target_file); nemo_file_operations_new_file_from_template (NULL, NULL, parent_uri, new_name, self->priv->template, create_callback, self); g_free (parent_uri); g_free (new_name); g_object_unref (parent); } static void create_folder_redo_func (NemoFileUndoInfoCreate *self, GtkWindow *parent_window) { GFile *parent; gchar *parent_uri; parent = g_file_get_parent (self->priv->target_file); parent_uri = g_file_get_uri (parent); nemo_file_operations_new_folder (NULL, NULL, parent_uri, create_callback, self); g_free (parent_uri); g_object_unref (parent); } static void create_empty_redo_func (NemoFileUndoInfoCreate *self, GtkWindow *parent_window) { GFile *parent; gchar *parent_uri; gchar *new_name; parent = g_file_get_parent (self->priv->target_file); parent_uri = g_file_get_uri (parent); new_name = g_file_get_parse_name (self->priv->target_file); nemo_file_operations_new_file (NULL, NULL, parent_uri, new_name, self->priv->template, self->priv->length, create_callback, self); g_free (parent_uri); g_free (new_name); g_object_unref (parent); } static void create_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoCreate *self = NEMO_FILE_UNDO_INFO_CREATE (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); if (op_type == NEMO_FILE_UNDO_OP_CREATE_EMPTY_FILE) { create_empty_redo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_FOLDER) { create_folder_redo_func (self, parent_window); } else if (op_type == NEMO_FILE_UNDO_OP_CREATE_FILE_FROM_TEMPLATE) { create_from_template_redo_func (self, parent_window); } else { g_assert_not_reached (); } } static void create_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoCreate *self = NEMO_FILE_UNDO_INFO_CREATE (info); GList *files = NULL; files = g_list_append (files, g_object_ref (self->priv->target_file)); nemo_file_operations_delete (files, parent_window, file_undo_info_delete_callback, self); g_list_free_full (files, g_object_unref); } static void nemo_file_undo_info_create_init (NemoFileUndoInfoCreate *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_create_get_type (), NemoFileUndoInfoCreateDetails); } static void nemo_file_undo_info_create_finalize (GObject *obj) { NemoFileUndoInfoCreate *self = NEMO_FILE_UNDO_INFO_CREATE (obj); g_clear_object (&self->priv->target_file); g_free (self->priv->template); G_OBJECT_CLASS (nemo_file_undo_info_create_parent_class)->finalize (obj); } static void nemo_file_undo_info_create_class_init (NemoFileUndoInfoCreateClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_create_finalize; iclass->undo_func = create_undo_func; iclass->redo_func = create_redo_func; iclass->strings_func = create_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoCreateDetails)); } NemoFileUndoInfo * nemo_file_undo_info_create_new (NemoFileUndoOp op_type) { return g_object_new (NEMO_TYPE_FILE_UNDO_INFO_CREATE, "op-type", op_type, "item-count", 1, NULL); } void nemo_file_undo_info_create_set_data (NemoFileUndoInfoCreate *self, GFile *file, const char *template, gint length) { self->priv->target_file = g_object_ref (file); self->priv->template = g_strdup (template); self->priv->length = length; } /* rename */ G_DEFINE_TYPE (NemoFileUndoInfoRename, nemo_file_undo_info_rename, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoRenameDetails { GFile *old_file; GFile *new_file; gchar *old_display_name; gchar *new_display_name; }; static void rename_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (info); gchar *new_name, *old_name; new_name = g_file_get_parse_name (self->priv->new_file); old_name = g_file_get_parse_name (self->priv->old_file); *undo_description = g_strdup_printf (_("Rename '%s' as '%s'"), new_name, old_name); *redo_description = g_strdup_printf (_("Rename '%s' as '%s'"), old_name, new_name); *undo_label = g_strdup (_("_Undo Rename")); *redo_label = g_strdup (_("_Redo Rename")); g_free (old_name); g_free (new_name); } static void rename_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (info); NemoFile *file; file = nemo_file_get (self->priv->old_file); nemo_file_rename (file, self->priv->new_display_name, file_undo_info_operation_callback, self); nemo_file_unref (file); } static void rename_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (info); NemoFile *file; file = nemo_file_get (self->priv->new_file); nemo_file_rename (file, self->priv->old_display_name, file_undo_info_operation_callback, self); nemo_file_unref (file); } static void nemo_file_undo_info_rename_init (NemoFileUndoInfoRename *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_rename_get_type (), NemoFileUndoInfoRenameDetails); } static void nemo_file_undo_info_rename_finalize (GObject *obj) { NemoFileUndoInfoRename *self = NEMO_FILE_UNDO_INFO_RENAME (obj); g_clear_object (&self->priv->old_file); g_clear_object (&self->priv->new_file); g_free (self->priv->old_display_name); g_free (self->priv->new_display_name); G_OBJECT_CLASS (nemo_file_undo_info_rename_parent_class)->finalize (obj); } static void nemo_file_undo_info_rename_class_init (NemoFileUndoInfoRenameClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_rename_finalize; iclass->undo_func = rename_undo_func; iclass->redo_func = rename_redo_func; iclass->strings_func = rename_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoRenameDetails)); } NemoFileUndoInfo * nemo_file_undo_info_rename_new (void) { return g_object_new (NEMO_TYPE_FILE_UNDO_INFO_RENAME, "op-type", NEMO_FILE_UNDO_OP_RENAME, "item-count", 1, NULL); } void nemo_file_undo_info_rename_set_data_pre (NemoFileUndoInfoRename *self, GFile *old_file, gchar *old_display_name, gchar *new_display_name) { self->priv->old_file = g_object_ref (old_file); self->priv->old_display_name = g_strdup (old_display_name); self->priv->new_display_name = g_strdup (new_display_name); } void nemo_file_undo_info_rename_set_data_post (NemoFileUndoInfoRename *self, GFile *new_file) { self->priv->new_file = g_object_ref (new_file); } /* trash */ G_DEFINE_TYPE (NemoFileUndoInfoTrash, nemo_file_undo_info_trash, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoTrashDetails { GHashTable *trashed; }; static void trash_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (info); gint count = g_hash_table_size (self->priv->trashed); if (count != 1) { *undo_description = g_strdup_printf (ngettext ("Restore %d item from trash", "Restore %d items from trash", count), count); *redo_description = g_strdup_printf (ngettext ("Move %d item to trash", "Move %d items to trash", count), count); } else { GList *keys; char *name, *orig_path; GFile *file; keys = g_hash_table_get_keys (self->priv->trashed); file = keys->data; name = g_file_get_basename (file); orig_path = g_file_get_path (file); *undo_description = g_strdup_printf (_("Restore '%s' to '%s'"), name, orig_path); g_free (name); g_free (orig_path); g_list_free (keys); name = g_file_get_parse_name (file); *redo_description = g_strdup_printf (_("Move '%s' to trash"), name); g_free (name); *undo_label = g_strdup (_("_Undo Trash")); *redo_label = g_strdup (_("_Redo Trash")); } } static void trash_redo_func_callback (GHashTable *debuting_uris, gboolean user_cancel, gpointer user_data) { NemoFileUndoInfoTrash *self = user_data; GHashTable *new_trashed_files; GTimeVal current_time; gsize updated_trash_time; GFile *file; GList *keys, *l; if (!user_cancel) { new_trashed_files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL); keys = g_hash_table_get_keys (self->priv->trashed); g_get_current_time (¤t_time); updated_trash_time = current_time.tv_sec; for (l = keys; l != NULL; l = l->next) { file = l->data; g_hash_table_insert (new_trashed_files, g_object_ref (file), GSIZE_TO_POINTER (updated_trash_time)); } g_list_free (keys); g_hash_table_destroy (self->priv->trashed); self->priv->trashed = new_trashed_files; } file_undo_info_delete_callback (debuting_uris, user_cancel, user_data); } static void trash_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (info); if (g_hash_table_size (self->priv->trashed) > 0) { GList *locations; locations = g_hash_table_get_keys (self->priv->trashed); nemo_file_operations_trash_or_delete (locations, parent_window, trash_redo_func_callback, self); g_list_free (locations); } } static GHashTable * trash_retrieve_files_to_restore_finish (NemoFileUndoInfoTrash *self, GAsyncResult *res, GError **error) { GHashTable *retval = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)); if (retval == NULL) { g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); } return retval; } static void trash_retrieve_files_to_restore_thread (GSimpleAsyncResult *res, GObject *object, GCancellable *cancellable) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (object); GFileEnumerator *enumerator; GHashTable *to_restore; GFile *trash; GError *error = NULL; to_restore = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, g_object_unref); trash = g_file_new_for_uri ("trash:///"); enumerator = g_file_enumerate_children (trash, G_FILE_ATTRIBUTE_STANDARD_NAME"," G_FILE_ATTRIBUTE_TRASH_DELETION_DATE"," G_FILE_ATTRIBUTE_TRASH_ORIG_PATH, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); if (enumerator) { GFileInfo *info; gpointer lookupvalue; GFile *item; GTimeVal timeval; glong trash_time, orig_trash_time; const char *origpath; GFile *origfile; const char *time_string; while ((info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL) { /* Retrieve the original file uri */ origpath = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_TRASH_ORIG_PATH); origfile = g_file_new_for_path (origpath); lookupvalue = g_hash_table_lookup (self->priv->trashed, origfile); if (lookupvalue) { orig_trash_time = GPOINTER_TO_SIZE (lookupvalue); time_string = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_TRASH_DELETION_DATE); if (time_string != NULL) { g_time_val_from_iso8601 (time_string, &timeval); trash_time = timeval.tv_sec; } else { trash_time = 0; } if (ABS (orig_trash_time - trash_time) <= TRASH_TIME_EPSILON) { /* File in the trash */ item = g_file_get_child (trash, g_file_info_get_name (info)); g_hash_table_insert (to_restore, item, g_object_ref (origfile)); } } g_object_unref (origfile); } g_file_enumerator_close (enumerator, FALSE, NULL); g_object_unref (enumerator); } g_object_unref (trash); if (error != NULL) { g_simple_async_result_take_error (res, error); g_hash_table_destroy (to_restore); } else { g_simple_async_result_set_op_res_gpointer (res, to_restore, NULL); } } static void trash_retrieve_files_to_restore_async (NemoFileUndoInfoTrash *self, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *async_op; async_op = g_simple_async_result_new (G_OBJECT (self), callback, user_data, trash_retrieve_files_to_restore_async); g_simple_async_result_run_in_thread (async_op, trash_retrieve_files_to_restore_thread, G_PRIORITY_DEFAULT, NULL); g_object_unref (async_op); } static void trash_retrieve_files_ready (GObject *source, GAsyncResult *res, gpointer user_data) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (source); GHashTable *files_to_restore; GError *error = NULL; files_to_restore = trash_retrieve_files_to_restore_finish (self, res, &error); if (error == NULL && g_hash_table_size (files_to_restore) > 0) { GList *gfiles_in_trash, *l; GFile *item; GFile *dest; gfiles_in_trash = g_hash_table_get_keys (files_to_restore); for (l = gfiles_in_trash; l != NULL; l = l->next) { item = l->data; dest = g_hash_table_lookup (files_to_restore, item); g_file_move (item, dest, G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, NULL); } g_list_free (gfiles_in_trash); /* Here we must do what's necessary for the callback */ file_undo_info_transfer_callback (NULL, (error == NULL), self); } else { file_undo_info_transfer_callback (NULL, FALSE, self); } if (files_to_restore != NULL) { g_hash_table_destroy (files_to_restore); } g_clear_error (&error); } static void trash_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (info); /* Internally managed op, pop flag. */ nemo_file_undo_manager_pop_flag (); trash_retrieve_files_to_restore_async (self, trash_retrieve_files_ready, NULL); } static void nemo_file_undo_info_trash_init (NemoFileUndoInfoTrash *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_trash_get_type (), NemoFileUndoInfoTrashDetails); self->priv->trashed = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL); } static void nemo_file_undo_info_trash_finalize (GObject *obj) { NemoFileUndoInfoTrash *self = NEMO_FILE_UNDO_INFO_TRASH (obj); g_hash_table_destroy (self->priv->trashed); G_OBJECT_CLASS (nemo_file_undo_info_trash_parent_class)->finalize (obj); } static void nemo_file_undo_info_trash_class_init (NemoFileUndoInfoTrashClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_trash_finalize; iclass->undo_func = trash_undo_func; iclass->redo_func = trash_redo_func; iclass->strings_func = trash_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoTrashDetails)); } NemoFileUndoInfo * nemo_file_undo_info_trash_new (gint item_count) { return g_object_new (NEMO_TYPE_FILE_UNDO_INFO_TRASH, "op-type", NEMO_FILE_UNDO_OP_MOVE_TO_TRASH, "item-count", item_count, NULL); } void nemo_file_undo_info_trash_add_file (NemoFileUndoInfoTrash *self, GFile *file) { GTimeVal current_time; gsize orig_trash_time; g_get_current_time (¤t_time); orig_trash_time = current_time.tv_sec; g_hash_table_insert (self->priv->trashed, g_object_ref (file), GSIZE_TO_POINTER (orig_trash_time)); } /* recursive permissions */ G_DEFINE_TYPE (NemoFileUndoInfoRecPermissions, nemo_file_undo_info_rec_permissions, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoRecPermissionsDetails { GFile *dest_dir; GHashTable *original_permissions; guint32 dir_mask; guint32 dir_permissions; guint32 file_mask; guint32 file_permissions; }; static void rec_permissions_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoRecPermissions *self = NEMO_FILE_UNDO_INFO_REC_PERMISSIONS (info); char *name; name = g_file_get_path (self->priv->dest_dir); *undo_description = g_strdup_printf (_("Restore original permissions of items enclosed in '%s'"), name); *redo_description = g_strdup_printf (_("Set permissions of items enclosed in '%s'"), name); *undo_label = g_strdup (_("_Undo Change Permissions")); *redo_label = g_strdup (_("_Redo Change Permissions")); g_free (name); } static void rec_permissions_callback (gboolean success, gpointer callback_data) { file_undo_info_transfer_callback (NULL, success, callback_data); } static void rec_permissions_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoRecPermissions *self = NEMO_FILE_UNDO_INFO_REC_PERMISSIONS (info); gchar *parent_uri; parent_uri = g_file_get_uri (self->priv->dest_dir); nemo_file_set_permissions_recursive (parent_uri, self->priv->file_permissions, self->priv->file_mask, self->priv->dir_permissions, self->priv->dir_mask, rec_permissions_callback, self); g_free (parent_uri); } static void rec_permissions_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoRecPermissions *self = NEMO_FILE_UNDO_INFO_REC_PERMISSIONS (info); /* Internally managed op, pop flag. */ /* TODO: why? */ nemo_file_undo_manager_pop_flag (); if (g_hash_table_size (self->priv->original_permissions) > 0) { GList *gfiles_list; guint32 perm; GList *l; GFile *dest; char *item; gfiles_list = g_hash_table_get_keys (self->priv->original_permissions); for (l = gfiles_list; l != NULL; l = l->next) { item = l->data; perm = GPOINTER_TO_UINT (g_hash_table_lookup (self->priv->original_permissions, item)); dest = g_file_new_for_uri (item); g_file_set_attribute_uint32 (dest, G_FILE_ATTRIBUTE_UNIX_MODE, perm, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); g_object_unref (dest); } g_list_free (gfiles_list); /* Here we must do what's necessary for the callback */ file_undo_info_transfer_callback (NULL, TRUE, self); } } static void nemo_file_undo_info_rec_permissions_init (NemoFileUndoInfoRecPermissions *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_rec_permissions_get_type (), NemoFileUndoInfoRecPermissionsDetails); self->priv->original_permissions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); } static void nemo_file_undo_info_rec_permissions_finalize (GObject *obj) { NemoFileUndoInfoRecPermissions *self = NEMO_FILE_UNDO_INFO_REC_PERMISSIONS (obj); g_hash_table_destroy (self->priv->original_permissions); g_clear_object (&self->priv->dest_dir); G_OBJECT_CLASS (nemo_file_undo_info_rec_permissions_parent_class)->finalize (obj); } static void nemo_file_undo_info_rec_permissions_class_init (NemoFileUndoInfoRecPermissionsClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_rec_permissions_finalize; iclass->undo_func = rec_permissions_undo_func; iclass->redo_func = rec_permissions_redo_func; iclass->strings_func = rec_permissions_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoRecPermissionsDetails)); } NemoFileUndoInfo * nemo_file_undo_info_rec_permissions_new (GFile *dest, guint32 file_permissions, guint32 file_mask, guint32 dir_permissions, guint32 dir_mask) { NemoFileUndoInfoRecPermissions *retval; retval = g_object_new (NEMO_TYPE_FILE_UNDO_INFO_REC_PERMISSIONS, "op-type", NEMO_FILE_UNDO_OP_RECURSIVE_SET_PERMISSIONS, "item-count", 1, NULL); retval->priv->dest_dir = g_object_ref (dest); retval->priv->file_permissions = file_permissions; retval->priv->file_mask = file_mask; retval->priv->dir_permissions = dir_permissions; retval->priv->dir_mask = dir_mask; return NEMO_FILE_UNDO_INFO (retval); } void nemo_file_undo_info_rec_permissions_add_file (NemoFileUndoInfoRecPermissions *self, GFile *file, guint32 permission) { gchar *original_uri = g_file_get_uri (file); g_hash_table_insert (self->priv->original_permissions, original_uri, GUINT_TO_POINTER (permission)); } /* single file change permissions */ G_DEFINE_TYPE (NemoFileUndoInfoPermissions, nemo_file_undo_info_permissions, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoPermissionsDetails { GFile *target_file; guint32 current_permissions; guint32 new_permissions; }; static void permissions_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoPermissions *self = NEMO_FILE_UNDO_INFO_PERMISSIONS (info); gchar *name; name = g_file_get_parse_name (self->priv->target_file); *undo_description = g_strdup_printf (_("Restore original permissions of '%s'"), name); *redo_description = g_strdup_printf (_("Set permissions of '%s'"), name); *undo_label = g_strdup (_("_Undo Change Permissions")); *redo_label = g_strdup (_("_Redo Change Permissions")); g_free (name); } static void permissions_real_func (NemoFileUndoInfoPermissions *self, guint32 permissions) { NemoFile *file; file = nemo_file_get (self->priv->target_file); nemo_file_set_permissions (file, permissions, file_undo_info_operation_callback, self); nemo_file_unref (file); } static void permissions_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoPermissions *self = NEMO_FILE_UNDO_INFO_PERMISSIONS (info); permissions_real_func (self, self->priv->new_permissions); } static void permissions_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoPermissions *self = NEMO_FILE_UNDO_INFO_PERMISSIONS (info); permissions_real_func (self, self->priv->current_permissions); } static void nemo_file_undo_info_permissions_init (NemoFileUndoInfoPermissions *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_permissions_get_type (), NemoFileUndoInfoPermissionsDetails); } static void nemo_file_undo_info_permissions_finalize (GObject *obj) { NemoFileUndoInfoPermissions *self = NEMO_FILE_UNDO_INFO_PERMISSIONS (obj); g_clear_object (&self->priv->target_file); G_OBJECT_CLASS (nemo_file_undo_info_permissions_parent_class)->finalize (obj); } static void nemo_file_undo_info_permissions_class_init (NemoFileUndoInfoPermissionsClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_permissions_finalize; iclass->undo_func = permissions_undo_func; iclass->redo_func = permissions_redo_func; iclass->strings_func = permissions_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoPermissionsDetails)); } NemoFileUndoInfo * nemo_file_undo_info_permissions_new (GFile *file, guint32 current_permissions, guint32 new_permissions) { NemoFileUndoInfoPermissions *retval; retval = g_object_new (NEMO_TYPE_FILE_UNDO_INFO_PERMISSIONS, "op-type", NEMO_FILE_UNDO_OP_SET_PERMISSIONS, "item-count", 1, NULL); retval->priv->target_file = g_object_ref (file); retval->priv->current_permissions = current_permissions; retval->priv->new_permissions = new_permissions; return NEMO_FILE_UNDO_INFO (retval); } /* group and owner change */ G_DEFINE_TYPE (NemoFileUndoInfoOwnership, nemo_file_undo_info_ownership, NEMO_TYPE_FILE_UNDO_INFO) struct _NemoFileUndoInfoOwnershipDetails { GFile *target_file; char *original_ownership; char *new_ownership; }; static void ownership_strings_func (NemoFileUndoInfo *info, gchar **undo_label, gchar **undo_description, gchar **redo_label, gchar **redo_description) { NemoFileUndoInfoOwnership *self = NEMO_FILE_UNDO_INFO_OWNERSHIP (info); NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (info); gchar *name; name = g_file_get_parse_name (self->priv->target_file); if (op_type == NEMO_FILE_UNDO_OP_CHANGE_GROUP) { *undo_description = g_strdup_printf (_("Restore group of '%s' to '%s'"), name, self->priv->original_ownership); *redo_description = g_strdup_printf (_("Set group of '%s' to '%s'"), name, self->priv->new_ownership); *undo_label = g_strdup (_("_Undo Change Group")); *redo_label = g_strdup (_("_Redo Change Group")); } else if (op_type == NEMO_FILE_UNDO_OP_CHANGE_OWNER) { *undo_description = g_strdup_printf (_("Restore owner of '%s' to '%s'"), name, self->priv->original_ownership); *redo_description = g_strdup_printf (_("Set owner of '%s' to '%s'"), name, self->priv->new_ownership); *undo_label = g_strdup (_("_Undo Change Owner")); *redo_label = g_strdup (_("_Redo Change Owner")); } g_free (name); } static void ownership_real_func (NemoFileUndoInfoOwnership *self, const gchar *ownership) { NemoFileUndoOp op_type = nemo_file_undo_info_get_op_type (NEMO_FILE_UNDO_INFO (self)); NemoFile *file; file = nemo_file_get (self->priv->target_file); if (op_type == NEMO_FILE_UNDO_OP_CHANGE_OWNER) { nemo_file_set_owner (file, ownership, file_undo_info_operation_callback, self); } else if (op_type == NEMO_FILE_UNDO_OP_CHANGE_GROUP) { nemo_file_set_group (file, ownership, file_undo_info_operation_callback, self); } nemo_file_unref (file); } static void ownership_redo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoOwnership *self = NEMO_FILE_UNDO_INFO_OWNERSHIP (info); ownership_real_func (self, self->priv->new_ownership); } static void ownership_undo_func (NemoFileUndoInfo *info, GtkWindow *parent_window) { NemoFileUndoInfoOwnership *self = NEMO_FILE_UNDO_INFO_OWNERSHIP (info); ownership_real_func (self, self->priv->original_ownership); } static void nemo_file_undo_info_ownership_init (NemoFileUndoInfoOwnership *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, nemo_file_undo_info_ownership_get_type (), NemoFileUndoInfoOwnershipDetails); } static void nemo_file_undo_info_ownership_finalize (GObject *obj) { NemoFileUndoInfoOwnership *self = NEMO_FILE_UNDO_INFO_OWNERSHIP (obj); g_clear_object (&self->priv->target_file); g_free (self->priv->original_ownership); g_free (self->priv->new_ownership); G_OBJECT_CLASS (nemo_file_undo_info_ownership_parent_class)->finalize (obj); } static void nemo_file_undo_info_ownership_class_init (NemoFileUndoInfoOwnershipClass *klass) { GObjectClass *oclass = G_OBJECT_CLASS (klass); NemoFileUndoInfoClass *iclass = NEMO_FILE_UNDO_INFO_CLASS (klass); oclass->finalize = nemo_file_undo_info_ownership_finalize; iclass->undo_func = ownership_undo_func; iclass->redo_func = ownership_redo_func; iclass->strings_func = ownership_strings_func; g_type_class_add_private (klass, sizeof (NemoFileUndoInfoOwnershipDetails)); } NemoFileUndoInfo * nemo_file_undo_info_ownership_new (NemoFileUndoOp op_type, GFile *file, const char *current_data, const char *new_data) { NemoFileUndoInfoOwnership *retval; retval = g_object_new (NEMO_TYPE_FILE_UNDO_INFO_OWNERSHIP, "item-count", 1, "op-type", op_type, NULL); retval->priv->target_file = g_object_ref (file); retval->priv->original_ownership = g_strdup (current_data); retval->priv->new_ownership = g_strdup (new_data); return NEMO_FILE_UNDO_INFO (retval); } nemo-3.6.5/libnemo-private/nemo-widget-menu-item.c0000664000175000017500000004727413215733314021005 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "nemo-widget-menu-item.h" #include "nemo-widget-action.h" #include enum { PROP_0, PROP_CHILD_WIDGET, PROP_ACTION_SLOT, PROP_ACTIVATABLE_RELATED_ACTION, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, }; static GtkActivatableIface *parent_activatable_iface; static void nemo_widget_menu_item_dispose (GObject *object); static void nemo_widget_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void nemo_widget_menu_item_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void nemo_widget_menu_item_activatable_interface_init (GtkActivatableIface *iface); static void nemo_widget_menu_item_update (GtkActivatable *activatable, GtkAction *action, const gchar *property_name); static void nemo_widget_menu_item_sync_action_properties (GtkActivatable *activatable, GtkAction *action); static void nemo_widget_menu_item_set_related_action (NemoWidgetMenuItem *menu_item, GtkAction *action); static void nemo_widget_menu_item_set_use_action_appearance (NemoWidgetMenuItem *widget_menu_item, gboolean use_appearance); static gboolean activatable_update_child_widget (NemoWidgetMenuItem *widget_menu_item, GtkAction *action); static void nemo_widget_menu_item_realize (GtkWidget *widget); static void nemo_widget_menu_item_unrealize (GtkWidget *widget); static void nemo_widget_menu_item_map (GtkWidget *widget); static void nemo_widget_menu_item_unmap (GtkWidget *widget); static void nemo_widget_menu_item_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static void nemo_widget_menu_item_activate (GtkMenuItem *menu_item); G_DEFINE_TYPE_WITH_CODE (NemoWidgetMenuItem, nemo_widget_menu_item, GTK_TYPE_MENU_ITEM, G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, nemo_widget_menu_item_activatable_interface_init)); static void nemo_widget_menu_item_class_init (NemoWidgetMenuItemClass *klass) { GObjectClass *gobject_class = (GObjectClass*) klass; GtkWidgetClass *widget_class = (GtkWidgetClass*) klass; GtkMenuItemClass *menu_item_class = (GtkMenuItemClass*) klass; gobject_class->dispose = nemo_widget_menu_item_dispose; gobject_class->set_property = nemo_widget_menu_item_set_property; gobject_class->get_property = nemo_widget_menu_item_get_property; menu_item_class->activate = nemo_widget_menu_item_activate; widget_class->realize = nemo_widget_menu_item_realize; widget_class->unrealize = nemo_widget_menu_item_unrealize; widget_class->map = nemo_widget_menu_item_map; widget_class->unmap = nemo_widget_menu_item_unmap; widget_class->size_allocate = nemo_widget_menu_item_size_allocate; /** * NemoWidgetMenuItem:widget: * * Child widget to use in place of a label. * */ g_object_class_install_property (gobject_class, PROP_CHILD_WIDGET, g_param_spec_object ("child-widget", "Child widget", "Child widget to appear next to the menu text", GTK_TYPE_WIDGET, G_PARAM_READWRITE)); /** * NemoWidgetMenuItem:action-slot: * * The action widget slot the child-widget came from. * */ g_object_class_install_property (gobject_class, PROP_ACTION_SLOT, g_param_spec_int ("action-slot", "Action slot", "The action's widget slot child-widget came from", -1, 1, -1, G_PARAM_READWRITE) ); g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action"); g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance"); } static void nemo_widget_menu_item_init (NemoWidgetMenuItem *item) { item->child_widget = NULL; item->action_slot = -1; } static void nemo_widget_menu_item_dispose (GObject *object) { NemoWidgetMenuItem *widget_menu_item = NEMO_WIDGET_MENU_ITEM (object); if (widget_menu_item->related_action) { gtk_action_disconnect_accelerator (widget_menu_item->related_action); nemo_widget_menu_item_set_related_action (widget_menu_item, NULL); widget_menu_item->related_action = NULL; } G_OBJECT_CLASS (nemo_widget_menu_item_parent_class)->dispose (object); } static void nemo_widget_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NemoWidgetMenuItem *widget_menu_item = NEMO_WIDGET_MENU_ITEM (object); switch (prop_id) { case PROP_CHILD_WIDGET: nemo_widget_menu_item_set_child_widget (widget_menu_item, (GtkWidget *) g_value_get_object (value)); break; case PROP_ACTION_SLOT: widget_menu_item->action_slot = g_value_get_int (value); break; case PROP_ACTIVATABLE_RELATED_ACTION: nemo_widget_menu_item_set_related_action (widget_menu_item, g_value_get_object (value)); break; case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE: nemo_widget_menu_item_set_use_action_appearance (widget_menu_item, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_widget_menu_item_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NemoWidgetMenuItem *widget_menu_item = NEMO_WIDGET_MENU_ITEM (object); switch (prop_id) { case PROP_CHILD_WIDGET: g_value_set_object (value, nemo_widget_menu_item_get_child_widget (widget_menu_item)); break; case PROP_ACTION_SLOT: g_value_set_int (value, widget_menu_item->action_slot); break; case PROP_ACTIVATABLE_RELATED_ACTION: g_value_set_object (value, widget_menu_item->related_action); break; case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE: g_value_set_boolean (value, widget_menu_item->use_action_appearance); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_widget_menu_item_activatable_interface_init (GtkActivatableIface *iface) { parent_activatable_iface = g_type_interface_peek_parent (iface); iface->update = nemo_widget_menu_item_update; iface->sync_action_properties = nemo_widget_menu_item_sync_action_properties; } static gboolean activatable_update_child_widget (NemoWidgetMenuItem *widget_menu_item, GtkAction *action) { GtkWidget *widget, *action_widget; NemoWidgetAction *widget_action = NEMO_WIDGET_ACTION (action); widget = nemo_widget_menu_item_get_child_widget (widget_menu_item); if (widget_menu_item->action_slot == ACTION_SLOT_A) { action_widget = nemo_widget_action_get_widget_a (widget_action); } else if (widget_menu_item->action_slot == ACTION_SLOT_B) { action_widget = nemo_widget_action_get_widget_b (widget_action); } else return FALSE; if (widget && action_widget && (widget == action_widget)) { return FALSE; } if (action_widget) { nemo_widget_menu_item_set_child_widget (widget_menu_item, action_widget); return TRUE; } if (!action_widget) { nemo_widget_menu_item_set_child_widget (widget_menu_item, NULL); return TRUE; } return FALSE; } static void nemo_widget_menu_item_update (GtkActivatable *activatable, GtkAction *action, const gchar *property_name) { NemoWidgetMenuItem *widget_menu_item; widget_menu_item = NEMO_WIDGET_MENU_ITEM (activatable); if (!gtk_activatable_get_use_action_appearance (activatable)) return; if (strcmp (property_name, "widget-a") == 0) activatable_update_child_widget (widget_menu_item, action); else if (strcmp (property_name, "widget-b") == 0) activatable_update_child_widget (widget_menu_item, action); } static void nemo_widget_menu_item_sync_action_properties (GtkActivatable *activatable, GtkAction *action) { NemoWidgetMenuItem *widget_menu_item; GtkWidget *widget; widget_menu_item = NEMO_WIDGET_MENU_ITEM (activatable); // parent_activatable_iface->sync_action_properties (activatable, action); if (!action) return; if (!gtk_activatable_get_use_action_appearance (activatable)) return; widget = nemo_widget_menu_item_get_child_widget (widget_menu_item); if (widget && !GTK_IS_WIDGET (widget)) { nemo_widget_menu_item_set_child_widget (widget_menu_item, NULL); widget = NULL; } activatable_update_child_widget (widget_menu_item, action); gtk_widget_show (GTK_WIDGET (widget_menu_item)); } static void nemo_widget_menu_item_set_related_action (NemoWidgetMenuItem *widget_menu_item, GtkAction *action) { if (widget_menu_item->related_action == action) return; if (widget_menu_item->related_action) { gtk_action_disconnect_accelerator (widget_menu_item->related_action); } if (action) { const gchar *accel_path; accel_path = gtk_action_get_accel_path (action); if (accel_path) { gtk_action_connect_accelerator (action); gtk_menu_item_set_accel_path (GTK_MENU_ITEM (widget_menu_item), accel_path); } } gtk_activatable_do_set_related_action (GTK_ACTIVATABLE (widget_menu_item), action); nemo_widget_menu_item_sync_action_properties (GTK_ACTIVATABLE (widget_menu_item), action); widget_menu_item->related_action = action; } static void nemo_widget_menu_item_set_use_action_appearance (NemoWidgetMenuItem *widget_menu_item, gboolean use_appearance) { if (widget_menu_item->use_action_appearance != use_appearance) { widget_menu_item->use_action_appearance = use_appearance; gtk_activatable_sync_action_properties (GTK_ACTIVATABLE (widget_menu_item), widget_menu_item->related_action); } } static void nemo_widget_menu_item_activate (GtkMenuItem *menu_item) { } static void nemo_widget_menu_item_realize (GtkWidget *widget) { GTK_WIDGET_CLASS (g_type_class_peek_parent (nemo_widget_menu_item_parent_class))->realize (widget); } static void nemo_widget_menu_item_unrealize (GtkWidget *widget) { GTK_WIDGET_CLASS (g_type_class_peek_parent (nemo_widget_menu_item_parent_class))->unrealize (widget); } static void nemo_widget_menu_item_map (GtkWidget *widget) { GTK_WIDGET_CLASS (g_type_class_peek_parent (nemo_widget_menu_item_parent_class))->map (widget); } static void nemo_widget_menu_item_unmap (GtkWidget *widget) { GTK_WIDGET_CLASS (g_type_class_peek_parent (nemo_widget_menu_item_parent_class))->unmap (widget); } static void get_arrow_size (GtkWidget *widget, GtkWidget *child, gint *size, gint *spacing) { PangoContext *context; PangoFontMetrics *metrics; gfloat arrow_scaling; gint arrow_spacing; g_assert (size); gtk_widget_style_get (widget, "arrow-scaling", &arrow_scaling, "arrow-spacing", &arrow_spacing, NULL); if (spacing != NULL) *spacing = arrow_spacing; context = gtk_widget_get_pango_context (child); metrics = pango_context_get_metrics (context, pango_context_get_font_description (context), pango_context_get_language (context)); *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics))); pango_font_metrics_unref (metrics); *size = *size * arrow_scaling; } static gint get_toggle_size (GtkMenuItem *menu_item) { NemoWidgetMenuItem *widget_menu_item = NEMO_WIDGET_MENU_ITEM (menu_item); GtkPackDirection pack_dir; GtkWidget *parent; gint req = 0; GtkWidget *widget = GTK_WIDGET (menu_item); parent = gtk_widget_get_parent (widget); if (GTK_IS_MENU_BAR (parent)) pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); else pack_dir = GTK_PACK_DIRECTION_LTR; if (widget_menu_item->child_widget && gtk_widget_get_visible (widget_menu_item->child_widget)) { gint icon_size; guint toggle_spacing; gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, NULL); gtk_widget_style_get (GTK_WIDGET (menu_item), "toggle-spacing", &toggle_spacing, NULL); if (pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) { if (icon_size > 0) req = icon_size + toggle_spacing; } else { if (icon_size > 0) req = icon_size + toggle_spacing; } } return req; } static void nemo_widget_menu_item_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkBin *bin; GtkAllocation child_allocation; GtkTextDirection direction; GtkPackDirection child_pack_dir; GtkWidget *child; GtkWidget *parent; g_return_if_fail (GTK_IS_MENU_ITEM (widget)); g_return_if_fail (allocation != NULL); bin = GTK_BIN (widget); direction = gtk_widget_get_direction (widget); parent = gtk_widget_get_parent (widget); if (GTK_IS_MENU_BAR (parent)) { child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (parent)); } else { child_pack_dir = GTK_PACK_DIRECTION_LTR; } gtk_widget_set_allocation (widget, allocation); child = gtk_bin_get_child (bin); if (child) { GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; guint border_width; gint toggle_size; context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); gtk_style_context_get_padding (context, state, &padding); border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); child_allocation.x = border_width + padding.left; child_allocation.y = border_width + padding.top; child_allocation.width = allocation->width - (border_width * 2) - padding.left - padding.right; child_allocation.height = allocation->height - (border_width * 2) - padding.top - padding.bottom; toggle_size = get_toggle_size (GTK_MENU_ITEM (widget)); if (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL) { if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_RTL)) child_allocation.x += toggle_size; child_allocation.width -= toggle_size; } else { if ((direction == GTK_TEXT_DIR_LTR) == (child_pack_dir != GTK_PACK_DIRECTION_BTT)) child_allocation.y += toggle_size; child_allocation.height -= toggle_size; } child_allocation.x += allocation->x; child_allocation.y += allocation->y; if ((gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)) && !GTK_IS_MENU_BAR (parent)) || gtk_menu_item_get_reserve_indicator (GTK_MENU_ITEM (widget))) { gint arrow_spacing, arrow_size; get_arrow_size (widget, child, &arrow_size, &arrow_spacing); if (direction == GTK_TEXT_DIR_RTL) child_allocation.x += arrow_size + arrow_spacing; child_allocation.width -= arrow_size + arrow_spacing; } if (child_allocation.width < 1) child_allocation.width = 1; gtk_widget_size_allocate (child, &child_allocation); } if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget))) gtk_menu_reposition (GTK_MENU (gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)))); } /** * nemo_widget_menu_item_new: * @widget: The custom widget to use * * Creates a new #NemoWidgetMenuItem. * * Returns: a new #NemoWidgetMenuItem. */ GtkWidget * nemo_widget_menu_item_new (GtkWidget *widget) { return g_object_new (NEMO_TYPE_WIDGET_MENU_ITEM, "widget", widget, NULL); } /** * nemo_widget_menu_item_set_child_widget: * @widget_menu_item: a #GtkNemoWidgetMenuItem. * @widget: (allow-none): a widget to set as the child widget for the menu item. * * Sets the child-widget of @widget_menu_item to the given widget. * */ void nemo_widget_menu_item_set_child_widget (NemoWidgetMenuItem *widget_menu_item, GtkWidget *widget) { g_return_if_fail (NEMO_IS_WIDGET_MENU_ITEM (widget_menu_item)); GtkWidget *old_w; old_w = gtk_bin_get_child (GTK_BIN (widget_menu_item)); if (widget == widget_menu_item->child_widget && widget == old_w) return; if (old_w) gtk_container_remove (GTK_CONTAINER (widget_menu_item), old_w); widget_menu_item->child_widget = widget; if (widget == NULL) return; if (!gtk_widget_get_parent (widget)) gtk_container_add (GTK_CONTAINER (widget_menu_item), widget); g_object_set (widget, "visible", TRUE, NULL); g_object_notify (G_OBJECT (widget_menu_item), "child-widget"); } /** * nemo_widget_menu_item_get_child_widget: * @widget_menu_item: a #NemoWidgetMenuItem * * Gets the widget that is currently set as the child-widget of @widget_menu_item. * See nemo_widget_menu_item_set_child_widget(). * * Returns: (transfer none): the widget set as child-widget of @widget_menu_item * * Deprecated: 3.10 **/ GtkWidget* nemo_widget_menu_item_get_child_widget (NemoWidgetMenuItem *widget_menu_item) { g_return_val_if_fail (NEMO_IS_WIDGET_MENU_ITEM (widget_menu_item), NULL); return widget_menu_item->child_widget; } nemo-3.6.5/libnemo-private/nemo-search-engine-tracker.c0000664000175000017500000002332413215733314021753 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Mr Jamie McCracken * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Jamie McCracken * */ #include #include "nemo-search-engine-tracker.h" #include #include #include #include /* If defined, we use fts:match, this has to be enabled in Tracker to * work which it usually is. The alternative is to undefine it and * use filename matching instead. This doesn't use the content of the * file however. */ #undef FTS_MATCHING struct NemoSearchEngineTrackerDetails { TrackerSparqlConnection *connection; NemoQuery *query; gboolean query_pending; GCancellable *cancellable; }; G_DEFINE_TYPE (NemoSearchEngineTracker, nemo_search_engine_tracker, NEMO_TYPE_SEARCH_ENGINE); static void finalize (GObject *object) { NemoSearchEngineTracker *tracker; tracker = NEMO_SEARCH_ENGINE_TRACKER (object); g_clear_object (&tracker->details->query); g_clear_object (&tracker->details->cancellable); g_clear_object (&tracker->details->connection); G_OBJECT_CLASS (nemo_search_engine_tracker_parent_class)->finalize (object); } /* stolen from tracker sources, tracker.c */ static void sparql_append_string_literal (GString *sparql, const gchar *str) { char *s; s = tracker_sparql_escape_string (str); g_string_append_c (sparql, '"'); g_string_append (sparql, s); g_string_append_c (sparql, '"'); g_free (s); } static void cursor_callback (GObject *object, GAsyncResult *result, gpointer user_data); static void cursor_next (NemoSearchEngineTracker *tracker, TrackerSparqlCursor *cursor) { tracker_sparql_cursor_next_async (cursor, tracker->details->cancellable, cursor_callback, tracker); } static void cursor_callback (GObject *object, GAsyncResult *result, gpointer user_data) { NemoSearchEngineTracker *tracker; GError *error = NULL; TrackerSparqlCursor *cursor; GList *hits; gboolean success; tracker = NEMO_SEARCH_ENGINE_TRACKER (user_data); cursor = TRACKER_SPARQL_CURSOR (object); success = tracker_sparql_cursor_next_finish (cursor, result, &error); if (error) { tracker->details->query_pending = FALSE; nemo_search_engine_error (NEMO_SEARCH_ENGINE (tracker), error->message); g_error_free (error); g_object_unref (cursor); return; } if (!success) { tracker->details->query_pending = FALSE; nemo_search_engine_finished (NEMO_SEARCH_ENGINE (tracker)); g_object_unref (cursor); return; } /* We iterate result by result, not n at a time. */ hits = g_list_append (NULL, (gchar*) tracker_sparql_cursor_get_string (cursor, 0, NULL)); nemo_search_engine_hits_added (NEMO_SEARCH_ENGINE (tracker), hits); g_list_free (hits); /* Get next */ cursor_next (tracker, cursor); } static void query_callback (GObject *object, GAsyncResult *result, gpointer user_data) { NemoSearchEngineTracker *tracker; TrackerSparqlConnection *connection; TrackerSparqlCursor *cursor; GError *error = NULL; tracker = NEMO_SEARCH_ENGINE_TRACKER (user_data); connection = TRACKER_SPARQL_CONNECTION (object); cursor = tracker_sparql_connection_query_finish (connection, result, &error); if (error) { tracker->details->query_pending = FALSE; nemo_search_engine_error (NEMO_SEARCH_ENGINE (tracker), error->message); g_error_free (error); return; } if (!cursor) { tracker->details->query_pending = FALSE; nemo_search_engine_finished (NEMO_SEARCH_ENGINE (tracker)); return; } cursor_next (tracker, cursor); } static void nemo_search_engine_tracker_start (NemoSearchEngine *engine) { NemoSearchEngineTracker *tracker; gchar *search_text, *location_uri; GString *sparql; GList *mimetypes, *l; gint mime_count; tracker = NEMO_SEARCH_ENGINE_TRACKER (engine); if (tracker->details->query_pending) { return; } if (tracker->details->query == NULL) { return; } g_cancellable_reset (tracker->details->cancellable); search_text = nemo_query_get_text (tracker->details->query); location_uri = nemo_query_get_location (tracker->details->query); mimetypes = nemo_query_get_mime_types (tracker->details->query); mime_count = g_list_length (mimetypes); #ifdef FTS_MATCHING /* Using FTS: */ sparql = g_string_new ("SELECT nie:url(?urn) " "WHERE {" " ?urn a nfo:FileDataObject ;" " tracker:available true ; "); if (mime_count > 0) { g_string_append (sparql, "nie:mimeType ?mime ;"); } g_string_append (sparql, " fts:match "); sparql_append_string_literal (sparql, search_text); if (location_uri || mime_count > 0) { g_string_append (sparql, " . FILTER ("); if (location_uri) { g_string_append (sparql, " fn:starts-with(nie:url(?urn),"); sparql_append_string_literal (sparql, location_uri); g_string_append (sparql, ")"); } if (mime_count > 0) { if (location_uri) { g_string_append (sparql, " && "); } g_string_append (sparql, "("); for (l = mimetypes; l != NULL; l = l->next) { if (l != mimetypes) { g_string_append (sparql, " || "); } g_string_append (sparql, "?mime = "); sparql_append_string_literal (sparql, l->data); } g_string_append (sparql, ")"); } g_string_append (sparql, ")"); } g_string_append (sparql, " } ORDER BY DESC(fts:rank(?urn)) ASC(nie:url(?urn))"); #else /* FTS_MATCHING */ /* Using filename matching: */ sparql = g_string_new ("SELECT nie:url(?urn) " "WHERE {" " ?urn a nfo:FileDataObject ;"); if (mime_count > 0) { g_string_append (sparql, "nie:mimeType ?mime ;"); } g_string_append (sparql, " tracker:available true ." " FILTER (fn:contains(nfo:fileName(?urn),"); sparql_append_string_literal (sparql, search_text); g_string_append (sparql, ")"); if (location_uri) { g_string_append (sparql, " && fn:starts-with(nie:url(?urn),"); sparql_append_string_literal (sparql, location_uri); g_string_append (sparql, ")"); } if (mime_count > 0) { g_string_append (sparql, " && "); g_string_append (sparql, "("); for (l = mimetypes; l != NULL; l = l->next) { if (l != mimetypes) { g_string_append (sparql, " || "); } g_string_append (sparql, "?mime = "); sparql_append_string_literal (sparql, l->data); } g_string_append (sparql, ")"); } g_string_append (sparql, ")"); g_string_append (sparql, "} ORDER BY DESC(nie:url(?urn)) DESC(nfo:fileName(?urn))"); #endif /* FTS_MATCHING */ tracker_sparql_connection_query_async (tracker->details->connection, sparql->str, tracker->details->cancellable, query_callback, tracker); g_string_free (sparql, TRUE); tracker->details->query_pending = TRUE; g_free (search_text); g_free (location_uri); if (mimetypes != NULL) { g_list_free_full (mimetypes, g_free); } } static void nemo_search_engine_tracker_stop (NemoSearchEngine *engine) { NemoSearchEngineTracker *tracker; tracker = NEMO_SEARCH_ENGINE_TRACKER (engine); if (tracker->details->query && tracker->details->query_pending) { g_cancellable_cancel (tracker->details->cancellable); tracker->details->query_pending = FALSE; } } static void nemo_search_engine_tracker_set_query (NemoSearchEngine *engine, NemoQuery *query) { NemoSearchEngineTracker *tracker; tracker = NEMO_SEARCH_ENGINE_TRACKER (engine); if (query) { g_object_ref (query); } if (tracker->details->query) { g_object_unref (tracker->details->query); } tracker->details->query = query; } static void nemo_search_engine_tracker_class_init (NemoSearchEngineTrackerClass *class) { GObjectClass *gobject_class; NemoSearchEngineClass *engine_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->finalize = finalize; engine_class = NEMO_SEARCH_ENGINE_CLASS (class); engine_class->set_query = nemo_search_engine_tracker_set_query; engine_class->start = nemo_search_engine_tracker_start; engine_class->stop = nemo_search_engine_tracker_stop; g_type_class_add_private (class, sizeof (NemoSearchEngineTrackerDetails)); } static void nemo_search_engine_tracker_init (NemoSearchEngineTracker *engine) { engine->details = G_TYPE_INSTANCE_GET_PRIVATE (engine, NEMO_TYPE_SEARCH_ENGINE_TRACKER, NemoSearchEngineTrackerDetails); } NemoSearchEngine * nemo_search_engine_tracker_new (void) { NemoSearchEngineTracker *engine; TrackerSparqlConnection *connection; GError *error = NULL; connection = tracker_sparql_connection_get (NULL, &error); if (error) { g_warning ("Could not establish a connection to Tracker: %s", error->message); g_error_free (error); return NULL; } engine = g_object_new (NEMO_TYPE_SEARCH_ENGINE_TRACKER, NULL); engine->details->connection = connection; engine->details->cancellable = g_cancellable_new (); return NEMO_SEARCH_ENGINE (engine); } nemo-3.6.5/libnemo-private/nemo-debug.h0000664000175000017500000000521713215733314016706 0ustar fabiofabio/* * nemo-debug: debug loggers for nemo * * Copyright (C) 2007 Collabora Ltd. * Copyright (C) 2007 Nokia Corporation * Copyright (C) 2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Based on Empathy's empathy-debug. */ #ifndef __NEMO_DEBUG_H__ #define __NEMO_DEBUG_H__ #include #include G_BEGIN_DECLS #ifdef ENABLE_DEBUG typedef enum { NEMO_DEBUG_APPLICATION = 1 << 1, NEMO_DEBUG_BOOKMARKS = 1 << 2, NEMO_DEBUG_DBUS = 1 << 3, NEMO_DEBUG_DIRECTORY_VIEW = 1 << 4, NEMO_DEBUG_FILE = 1 << 5, NEMO_DEBUG_ICON_CONTAINER = 1 << 6, NEMO_DEBUG_ICON_VIEW = 1 << 7, NEMO_DEBUG_LIST_VIEW = 1 << 8, NEMO_DEBUG_MIME = 1 << 9, NEMO_DEBUG_PLACES = 1 << 10, NEMO_DEBUG_PREVIEWER = 1 << 11, NEMO_DEBUG_SMCLIENT = 1 << 12, NEMO_DEBUG_WINDOW = 1 << 13, NEMO_DEBUG_UNDO = 1 << 14, NEMO_DEBUG_ACTIONS = 1 << 15, NEMO_DEBUG_DESKTOP = 1 << 16 } DebugFlags; void nemo_debug_set_flags (DebugFlags flags); gboolean nemo_debug_flag_is_set (DebugFlags flag); void nemo_debug_valist (DebugFlags flag, const gchar *format, va_list args); void nemo_debug (DebugFlags flag, const gchar *format, ...) G_GNUC_PRINTF (2, 3); void nemo_debug_files (DebugFlags flag, GList *files, const gchar *format, ...) G_GNUC_PRINTF (3, 4); #ifdef DEBUG_FLAG #define DEBUG(format, ...) \ nemo_debug (DEBUG_FLAG, "%s: %s: " format, G_STRFUNC, G_STRLOC, \ ##__VA_ARGS__) #define DEBUG_FILES(files, format, ...) \ nemo_debug_files (DEBUG_FLAG, files, "%s:" format, G_STRFUNC, \ ##__VA_ARGS__) #define DEBUGGING nemo_debug_flag_is_set(DEBUG_FLAG) #endif /* DEBUG_FLAG */ #else /* ENABLE_DEBUG */ #ifdef DEBUG_FLAG #define DEBUG(format, ...) \ G_STMT_START { } G_STMT_END #define DEBUG_FILES(files, format, ...) \ G_STMT_START { } G_STMT_END #define DEBUGGING 0 #endif /* DEBUG_FLAG */ #endif /* ENABLE_DEBUG */ G_END_DECLS #endif /* __NEMO_DEBUG_H__ */ nemo-3.6.5/libnemo-private/nemo-file-changes-queue.c0000664000175000017500000002352513215733314021264 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Pavel Cisler */ #include #include "nemo-file-changes-queue.h" #include "nemo-directory-notify.h" typedef enum { CHANGE_FILE_INITIAL, CHANGE_FILE_ADDED, CHANGE_FILE_CHANGED, CHANGE_FILE_REMOVED, CHANGE_FILE_MOVED, CHANGE_POSITION_SET, CHANGE_POSITION_REMOVE } NemoFileChangeKind; typedef struct { NemoFileChangeKind kind; GFile *from; GFile *to; GdkPoint point; int monitor; } NemoFileChange; typedef struct { GList *head; GList *tail; GMutex mutex; } NemoFileChangesQueue; static NemoFileChangesQueue * nemo_file_changes_queue_new (void) { NemoFileChangesQueue *result; result = g_new0 (NemoFileChangesQueue, 1); g_mutex_init (&result->mutex); return result; } static NemoFileChangesQueue * nemo_file_changes_queue_get (void) { static NemoFileChangesQueue *file_changes_queue; if (file_changes_queue == NULL) { file_changes_queue = nemo_file_changes_queue_new (); } return file_changes_queue; } static void nemo_file_changes_queue_add_common (NemoFileChangesQueue *queue, NemoFileChange *new_item) { /* enqueue the new queue item while locking down the list */ g_mutex_lock (&queue->mutex); queue->head = g_list_prepend (queue->head, new_item); if (queue->tail == NULL) queue->tail = queue->head; g_mutex_unlock (&queue->mutex); } void nemo_file_changes_queue_file_added (GFile *location) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get(); new_item = g_new0 (NemoFileChange, 1); new_item->kind = CHANGE_FILE_ADDED; new_item->from = g_object_ref (location); nemo_file_changes_queue_add_common (queue, new_item); } void nemo_file_changes_queue_file_changed (GFile *location) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get(); new_item = g_new0 (NemoFileChange, 1); new_item->kind = CHANGE_FILE_CHANGED; new_item->from = g_object_ref (location); nemo_file_changes_queue_add_common (queue, new_item); } void nemo_file_changes_queue_file_removed (GFile *location) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get(); new_item = g_new0 (NemoFileChange, 1); new_item->kind = CHANGE_FILE_REMOVED; new_item->from = g_object_ref (location); nemo_file_changes_queue_add_common (queue, new_item); } void nemo_file_changes_queue_file_moved (GFile *from, GFile *to) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get (); new_item = g_new (NemoFileChange, 1); new_item->kind = CHANGE_FILE_MOVED; new_item->from = g_object_ref (from); new_item->to = g_object_ref (to); nemo_file_changes_queue_add_common (queue, new_item); } void nemo_file_changes_queue_schedule_position_set (GFile *location, GdkPoint point, int monitor) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get (); new_item = g_new (NemoFileChange, 1); new_item->kind = CHANGE_POSITION_SET; new_item->from = g_object_ref (location); new_item->point = point; new_item->monitor = monitor; nemo_file_changes_queue_add_common (queue, new_item); } void nemo_file_changes_queue_schedule_position_remove (GFile *location) { NemoFileChange *new_item; NemoFileChangesQueue *queue; queue = nemo_file_changes_queue_get (); new_item = g_new (NemoFileChange, 1); new_item->kind = CHANGE_POSITION_REMOVE; new_item->from = g_object_ref (location); nemo_file_changes_queue_add_common (queue, new_item); } static NemoFileChange * nemo_file_changes_queue_get_change (NemoFileChangesQueue *queue) { GList *new_tail; NemoFileChange *result; g_assert (queue != NULL); /* dequeue the tail item while locking down the list */ g_mutex_lock (&queue->mutex); if (queue->tail == NULL) { result = NULL; } else { new_tail = queue->tail->prev; result = queue->tail->data; queue->head = g_list_remove_link (queue->head, queue->tail); g_list_free_1 (queue->tail); queue->tail = new_tail; } g_mutex_unlock (&queue->mutex); return result; } enum { CONSUME_CHANGES_MAX_CHUNK = 20 }; static void pairs_list_free (GList *pairs) { GList *p; GFilePair *pair; /* deep delete the list of pairs */ for (p = pairs; p != NULL; p = p->next) { /* delete the strings in each pair */ pair = p->data; g_object_unref (pair->from); g_object_unref (pair->to); } /* delete the list and the now empty pair structs */ g_list_free_full (pairs, g_free); } static void position_set_list_free (GList *list) { GList *p; NemoFileChangesQueuePosition *item; for (p = list; p != NULL; p = p->next) { item = p->data; g_object_unref (item->location); } /* delete the list and the now empty structs */ g_list_free_full (list, g_free); } /* go through changes in the change queue, send ones with the same kind * in a list to the different nemo_directory_notify calls */ void nemo_file_changes_consume_changes (gboolean consume_all) { NemoFileChange *change; GList *additions, *changes, *deletions, *moves; GList *position_set_requests; GFilePair *pair; NemoFileChangesQueuePosition *position_set; guint chunk_count; NemoFileChangesQueue *queue; gboolean flush_needed; additions = NULL; changes = NULL; deletions = NULL; moves = NULL; position_set_requests = NULL; queue = nemo_file_changes_queue_get(); /* Consume changes from the queue, stuffing them into one of three lists, * keep doing it while the changes are of the same kind, then send them off. * This is to ensure that the changes get sent off in the same order that they * arrived. */ for (chunk_count = 0; ; chunk_count++) { change = nemo_file_changes_queue_get_change (queue); /* figure out if we need to flush the pending changes that we collected sofar */ if (change == NULL) { flush_needed = TRUE; /* no changes left, flush everything */ } else { flush_needed = additions != NULL && change->kind != CHANGE_FILE_ADDED && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE; flush_needed |= changes != NULL && change->kind != CHANGE_FILE_CHANGED; flush_needed |= moves != NULL && change->kind != CHANGE_FILE_MOVED && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE; flush_needed |= deletions != NULL && change->kind != CHANGE_FILE_REMOVED; flush_needed |= position_set_requests != NULL && change->kind != CHANGE_POSITION_SET && change->kind != CHANGE_POSITION_REMOVE && change->kind != CHANGE_FILE_ADDED && change->kind != CHANGE_FILE_MOVED; flush_needed |= !consume_all && chunk_count >= CONSUME_CHANGES_MAX_CHUNK; /* we have reached the chunk maximum */ } if (flush_needed) { /* Send changes we collected off. * At one time we may only have one of the lists * contain changes. */ if (deletions != NULL) { deletions = g_list_reverse (deletions); nemo_directory_notify_files_removed (deletions); g_list_free_full (deletions, g_object_unref); deletions = NULL; } if (moves != NULL) { moves = g_list_reverse (moves); nemo_directory_notify_files_moved (moves); pairs_list_free (moves); moves = NULL; } if (additions != NULL) { additions = g_list_reverse (additions); nemo_directory_notify_files_added (additions); g_list_free_full (additions, g_object_unref); additions = NULL; } if (changes != NULL) { changes = g_list_reverse (changes); nemo_directory_notify_files_changed (changes); g_list_free_full (changes, g_object_unref); changes = NULL; } if (position_set_requests != NULL) { position_set_requests = g_list_reverse (position_set_requests); nemo_directory_schedule_position_set (position_set_requests); position_set_list_free (position_set_requests); position_set_requests = NULL; } } if (change == NULL) { /* we are done */ return; } /* add the new change to the list */ switch (change->kind) { case CHANGE_FILE_ADDED: additions = g_list_prepend (additions, change->from); break; case CHANGE_FILE_CHANGED: changes = g_list_prepend (changes, change->from); break; case CHANGE_FILE_REMOVED: deletions = g_list_prepend (deletions, change->from); break; case CHANGE_FILE_MOVED: pair = g_new (GFilePair, 1); pair->from = change->from; pair->to = change->to; moves = g_list_prepend (moves, pair); break; case CHANGE_POSITION_SET: position_set = g_new (NemoFileChangesQueuePosition, 1); position_set->location = change->from; position_set->set = TRUE; position_set->point = change->point; position_set->monitor = change->monitor; position_set_requests = g_list_prepend (position_set_requests, position_set); break; case CHANGE_POSITION_REMOVE: position_set = g_new (NemoFileChangesQueuePosition, 1); position_set->location = change->from; position_set->set = FALSE; position_set_requests = g_list_prepend (position_set_requests, position_set); break; default: g_assert_not_reached (); break; } g_free (change); } } nemo-3.6.5/libnemo-private/nemo-recent.h0000664000175000017500000000033613215733314017075 0ustar fabiofabio #ifndef __NEMO_RECENT_H__ #define __NEMO_RECENT_H__ #include #include #include void nemo_recent_add_file (NemoFile *file, GAppInfo *application); #endif nemo-3.6.5/libnemo-private/nemo-link.h0000664000175000017500000000415413215733314016554 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-link.h: . Copyright (C) 2001 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Jonathan Blandford */ #ifndef NEMO_LINK_H #define NEMO_LINK_H #include gboolean nemo_link_local_create (const char *directory_uri, const char *base_name, const char *display_name, const char *image, const char *target_uri, const GdkPoint *point, int monitor, gboolean unique_filename); gboolean nemo_link_local_set_text (const char *uri, const char *text); gboolean nemo_link_local_set_icon (const char *uri, const char *icon); char * nemo_link_local_get_text (const char *uri); char * nemo_link_local_get_link_uri (const char *uri); void nemo_link_get_link_info_given_file_contents (const char *file_contents, int link_file_size, const char *file_uri, char **uri, char **name, GIcon **icon, gboolean *is_launcher, gboolean *is_foreign); #endif /* NEMO_LINK_H */ nemo-3.6.5/libnemo-private/nemo-desktop-icon-file.h0000664000175000017500000000474213215733314021136 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-file.h: Subclass of NemoFile to implement the the case of a desktop icon file Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_DESKTOP_ICON_FILE_H #define NEMO_DESKTOP_ICON_FILE_H #include #include #define NEMO_TYPE_DESKTOP_ICON_FILE nemo_desktop_icon_file_get_type() #define NEMO_DESKTOP_ICON_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DESKTOP_ICON_FILE, NemoDesktopIconFile)) #define NEMO_DESKTOP_ICON_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DESKTOP_ICON_FILE, NemoDesktopIconFileClass)) #define NEMO_IS_DESKTOP_ICON_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DESKTOP_ICON_FILE)) #define NEMO_IS_DESKTOP_ICON_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DESKTOP_ICON_FILE)) #define NEMO_DESKTOP_ICON_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DESKTOP_ICON_FILE, NemoDesktopIconFileClass)) typedef struct NemoDesktopIconFileDetails NemoDesktopIconFileDetails; typedef struct { NemoFile parent_slot; NemoDesktopIconFileDetails *details; } NemoDesktopIconFile; typedef struct { NemoFileClass parent_slot; } NemoDesktopIconFileClass; GType nemo_desktop_icon_file_get_type (void); NemoDesktopIconFile *nemo_desktop_icon_file_new (NemoDesktopLink *link); void nemo_desktop_icon_file_update (NemoDesktopIconFile *icon_file); void nemo_desktop_icon_file_remove (NemoDesktopIconFile *icon_file); NemoDesktopLink *nemo_desktop_icon_file_get_link (NemoDesktopIconFile *icon_file); #endif /* NEMO_DESKTOP_ICON_FILE_H */ nemo-3.6.5/libnemo-private/nemo-desktop-utils.h0000664000175000017500000000254513215733314020430 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * */ #ifndef NEMO_DESKTOP_UTILS_H #define NEMO_DESKTOP_UTILS_H #include #include G_BEGIN_DECLS void nemo_desktop_utils_get_monitor_work_rect (gint num, GdkRectangle *rect); void nemo_desktop_utils_get_monitor_geometry (gint num, GdkRectangle *rect); gint nemo_desktop_utils_get_primary_monitor (void); gint nemo_desktop_utils_get_monitor_for_widget (GtkWidget *widget); gint nemo_desktop_utils_get_num_monitors (void); gboolean nemo_desktop_utils_get_monitor_cloned (gint monitor, gint x_primary); gint nemo_desktop_utils_get_scale_factor (void); G_END_DECLS #endif nemo-3.6.5/libnemo-private/nemo-directory.h0000664000175000017500000002515313215733314017625 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-directory.h: Nemo directory model. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_DIRECTORY_H #define NEMO_DIRECTORY_H #include #include #include /* NemoDirectory is a class that manages the model for a directory, real or virtual, for Nemo, mainly the file-manager component. The directory is responsible for managing both real data and cached metadata. On top of the file system independence provided by gio, the directory object also provides: 1) A synchronization framework, which notifies via signals as the set of known files changes. 2) An abstract interface for getting attributes and performing operations on files. */ #define NEMO_TYPE_DIRECTORY nemo_directory_get_type() #define NEMO_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DIRECTORY, NemoDirectory)) #define NEMO_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DIRECTORY, NemoDirectoryClass)) #define NEMO_IS_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DIRECTORY)) #define NEMO_IS_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DIRECTORY)) #define NEMO_DIRECTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DIRECTORY, NemoDirectoryClass)) /* NemoFile is defined both here and in nemo-file.h. */ #ifndef NEMO_FILE_DEFINED #define NEMO_FILE_DEFINED typedef struct NemoFile NemoFile; #endif typedef struct NemoDirectoryDetails NemoDirectoryDetails; typedef struct { GObject object; NemoDirectoryDetails *details; } NemoDirectory; typedef void (*NemoDirectoryCallback) (NemoDirectory *directory, GList *files, gpointer callback_data); typedef struct { GObjectClass parent_class; /*** Notification signals for clients to connect to. ***/ /* The files_added signal is emitted as the directory model * discovers new files. */ void (* files_added) (NemoDirectory *directory, GList *added_files); /* The files_changed signal is emitted as changes occur to * existing files that are noticed by the synchronization framework, * including when an old file has been deleted. When an old file * has been deleted, this is the last chance to forget about these * file objects, which are about to be unref'd. Use a call to * nemo_file_is_gone () to test for this case. */ void (* files_changed) (NemoDirectory *directory, GList *changed_files); /* The done_loading signal is emitted when a directory load * request completes. This is needed because, at least in the * case where the directory is empty, the caller will receive * no kind of notification at all when a directory load * initiated by `nemo_directory_file_monitor_add' completes. */ void (* done_loading) (NemoDirectory *directory); void (* load_error) (NemoDirectory *directory, GError *error); /*** Virtual functions for subclasses to override. ***/ gboolean (* contains_file) (NemoDirectory *directory, NemoFile *file); void (* call_when_ready) (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback callback, gpointer callback_data); void (* cancel_callback) (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data); void (* file_monitor_add) (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes monitor_attributes, NemoDirectoryCallback initial_files_callback, gpointer callback_data); void (* file_monitor_remove) (NemoDirectory *directory, gconstpointer client); void (* force_reload) (NemoDirectory *directory); gboolean (* are_all_files_seen) (NemoDirectory *directory); gboolean (* is_not_empty) (NemoDirectory *directory); /* get_file_list is a function pointer that subclasses may override to * customize collecting the list of files in a directory. * For example, the NemoDesktopDirectory overrides this so that it can * merge together the list of files in the $HOME/Desktop directory with * the list of standard icons (Computer, Home, Trash) on the desktop. */ GList * (* get_file_list) (NemoDirectory *directory); /* Should return FALSE if the directory is read-only and doesn't * allow setting of metadata. * An example of this is the search directory. */ gboolean (* is_editable) (NemoDirectory *directory); } NemoDirectoryClass; /* Basic GObject requirements. */ GType nemo_directory_get_type (void); /* Get a directory given a uri. * Creates the appropriate subclass given the uri mappings. * Returns a referenced object, not a floating one. Unref when finished. * If two windows are viewing the same uri, the directory object is shared. */ NemoDirectory *nemo_directory_get (GFile *location); NemoDirectory *nemo_directory_get_by_uri (const char *uri); NemoDirectory *nemo_directory_get_for_file (NemoFile *file); /* Covers for g_object_ref and g_object_unref that provide two conveniences: * 1) Using these is type safe. * 2) You are allowed to call these with NULL, */ NemoDirectory *nemo_directory_ref (NemoDirectory *directory); void nemo_directory_unref (NemoDirectory *directory); /* Access to a URI. */ char * nemo_directory_get_uri (NemoDirectory *directory); GFile * nemo_directory_get_location (NemoDirectory *directory); /* Is this file still alive and in this directory? */ gboolean nemo_directory_contains_file (NemoDirectory *directory, NemoFile *file); /* Get the uri of the file in the directory, NULL if not found */ char * nemo_directory_get_file_uri (NemoDirectory *directory, const char *file_name); /* Get (and ref) a NemoFile object for this directory. */ NemoFile * nemo_directory_get_corresponding_file (NemoDirectory *directory); /* Waiting for data that's read asynchronously. * The file attribute and metadata keys are for files in the directory. */ void nemo_directory_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_all_files, NemoDirectoryCallback callback, gpointer callback_data); void nemo_directory_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data); /* Monitor the files in a directory. */ void nemo_directory_file_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes attributes, NemoDirectoryCallback initial_files_callback, gpointer callback_data); void nemo_directory_file_monitor_remove (NemoDirectory *directory, gconstpointer client); void nemo_directory_force_reload (NemoDirectory *directory); /* Get a list of all files currently known in the directory. */ GList * nemo_directory_get_file_list (NemoDirectory *directory); GList * nemo_directory_match_pattern (NemoDirectory *directory, const char *glob); /* Return true if the directory has information about all the files. * This will be false until the directory has been read at least once. */ gboolean nemo_directory_are_all_files_seen (NemoDirectory *directory); /* Return true if the directory is local. */ gboolean nemo_directory_is_local (NemoDirectory *directory); gboolean nemo_directory_is_in_trash (NemoDirectory *directory); gboolean nemo_directory_is_in_recent (NemoDirectory *directory); /* Return false if directory contains anything besides a Nemo metafile. * Only valid if directory is monitored. Used by the Trash monitor. */ gboolean nemo_directory_is_not_empty (NemoDirectory *directory); /* Convenience functions for dealing with a list of NemoDirectory objects that each have a ref. * These are just convenient names for functions that work on lists of GtkObject *. */ GList * nemo_directory_list_ref (GList *directory_list); void nemo_directory_list_unref (GList *directory_list); void nemo_directory_list_free (GList *directory_list); GList * nemo_directory_list_copy (GList *directory_list); GList * nemo_directory_list_sort_by_uri (GList *directory_list); /* Fast way to check if a directory is the desktop directory */ gboolean nemo_directory_is_desktop_directory (NemoDirectory *directory); gboolean nemo_directory_is_editable (NemoDirectory *directory); #endif /* NEMO_DIRECTORY_H */ nemo-3.6.5/libnemo-private/nemo-undo.c0000664000175000017500000001333113215733314016554 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-undo.c - public interface for objects that implement * undoable actions -- works across components * * Copyright (C) 2000 Eazel, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Darin Adler */ #include #include "nemo-undo.h" #include "nemo-undo-private.h" #include "nemo-undo-transaction.h" #include #define NEMO_UNDO_MANAGER_DATA "Nemo undo manager" /* Register a simple undo action by calling nemo_undo_register_full. */ void nemo_undo_register (GObject *target, NemoUndoCallback callback, gpointer callback_data, GDestroyNotify callback_data_destroy_notify, const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint) { NemoUndoAtom atom; GList single_atom_list; g_return_if_fail (G_IS_OBJECT (target)); g_return_if_fail (callback != NULL); /* Make an atom. */ atom.target = target; atom.callback = callback; atom.callback_data = callback_data; atom.callback_data_destroy_notify = callback_data_destroy_notify; /* Make a single-atom list. */ single_atom_list.data = &atom; single_atom_list.next = NULL; single_atom_list.prev = NULL; /* Call the full version of the registration function, * using the undo target as the place to search for the * undo manager. */ nemo_undo_register_full (&single_atom_list, target, operation_name, undo_menu_item_label, undo_menu_item_hint, redo_menu_item_label, redo_menu_item_hint); } /* Register an undo action. */ void nemo_undo_register_full (GList *atoms, GObject *undo_manager_search_start_object, const char *operation_name, const char *undo_menu_item_label, const char *undo_menu_item_hint, const char *redo_menu_item_label, const char *redo_menu_item_hint) { NemoUndoTransaction *transaction; GList *p; g_return_if_fail (atoms != NULL); g_return_if_fail (G_IS_OBJECT (undo_manager_search_start_object)); /* Create an undo transaction */ transaction = nemo_undo_transaction_new (operation_name, undo_menu_item_label, undo_menu_item_hint, redo_menu_item_label, redo_menu_item_hint); for (p = atoms; p != NULL; p = p->next) { nemo_undo_transaction_add_atom (transaction, p->data); } nemo_undo_transaction_add_to_undo_manager (transaction, nemo_undo_get_undo_manager (undo_manager_search_start_object)); /* Now we are done with the transaction. * If the undo manager is holding it, then this will not destroy it. */ g_object_unref (transaction); } /* Cover for forgetting about all undo relating to a particular target. */ void nemo_undo_unregister (GObject *target) { /* Perhaps this should also unregister all children if called on a * GtkContainer? That might be handy. */ nemo_undo_transaction_unregister_object (target); } void nemo_undo (GObject *undo_manager_search_start_object) { NemoUndoManager *manager; g_return_if_fail (G_IS_OBJECT (undo_manager_search_start_object)); manager = nemo_undo_get_undo_manager (undo_manager_search_start_object); if (manager != NULL) { nemo_undo_manager_undo (manager); } } NemoUndoManager * nemo_undo_get_undo_manager (GObject *start_object) { NemoUndoManager *manager; GtkWidget *parent; GtkWindow *transient_parent; if (start_object == NULL) { return NULL; } g_return_val_if_fail (G_IS_OBJECT (start_object), NULL); /* Check for an undo manager right here. */ manager = g_object_get_data (start_object, NEMO_UNDO_MANAGER_DATA); if (manager != NULL) { return manager; } /* Check for undo manager up the parent chain. */ if (GTK_IS_WIDGET (start_object)) { parent = gtk_widget_get_parent (GTK_WIDGET (start_object)); if (parent != NULL) { manager = nemo_undo_get_undo_manager (G_OBJECT (parent)); if (manager != NULL) { return manager; } } /* Check for undo manager in our window's parent. */ if (GTK_IS_WINDOW (start_object)) { transient_parent = gtk_window_get_transient_for (GTK_WINDOW (start_object)); if (transient_parent != NULL) { manager = nemo_undo_get_undo_manager (G_OBJECT (transient_parent)); if (manager != NULL) { return manager; } } } } /* Found nothing. I can live with that. */ return NULL; } void nemo_undo_attach_undo_manager (GObject *object, NemoUndoManager *manager) { g_return_if_fail (G_IS_OBJECT (object)); if (manager == NULL) { g_object_set_data (object, NEMO_UNDO_MANAGER_DATA, NULL); } else { g_object_ref (manager); g_object_set_data_full (object, NEMO_UNDO_MANAGER_DATA, manager, g_object_unref); } } /* Copy a reference to the undo manager fromone object to another. */ void nemo_undo_share_undo_manager (GObject *destination_object, GObject *source_object) { NemoUndoManager *manager; manager = nemo_undo_get_undo_manager (source_object); nemo_undo_attach_undo_manager (destination_object, manager); } nemo-3.6.5/libnemo-private/nemo-saved-search-file.c0000664000175000017500000000263513215733314021076 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-saved-search-file.h: Subclass of NemoVFSFile to implement the the case of a Saved Search file. Copyright (C) 2005 Red Hat, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include "nemo-saved-search-file.h" #include "nemo-file-private.h" G_DEFINE_TYPE(NemoSavedSearchFile, nemo_saved_search_file, NEMO_TYPE_VFS_FILE) static void nemo_saved_search_file_init (NemoSavedSearchFile *search_file) { } static void nemo_saved_search_file_class_init (NemoSavedSearchFileClass * klass) { NemoFileClass *file_class; file_class = NEMO_FILE_CLASS (klass); file_class->default_file_type = G_FILE_TYPE_DIRECTORY; } nemo-3.6.5/libnemo-private/nemo-metadata.c0000664000175000017500000000536213215733314017374 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-*/ /* nemo-metadata.c - metadata utils * * Copyright (C) 2009 Red Hatl, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include "nemo-metadata.h" #include static char *used_metadata_names[] = { NEMO_METADATA_KEY_DEFAULT_VIEW, NEMO_METADATA_KEY_LOCATION_BACKGROUND_COLOR, NEMO_METADATA_KEY_LOCATION_BACKGROUND_IMAGE, NEMO_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL, NEMO_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT, NEMO_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT, NEMO_METADATA_KEY_ICON_VIEW_SORT_BY, NEMO_METADATA_KEY_ICON_VIEW_SORT_REVERSED, NEMO_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED, NEMO_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP, NEMO_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL, NEMO_METADATA_KEY_LIST_VIEW_SORT_COLUMN, NEMO_METADATA_KEY_LIST_VIEW_SORT_REVERSED, NEMO_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NEMO_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NEMO_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL, NEMO_METADATA_KEY_WINDOW_GEOMETRY, NEMO_METADATA_KEY_WINDOW_SCROLL_POSITION, NEMO_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES, NEMO_METADATA_KEY_WINDOW_MAXIMIZED, NEMO_METADATA_KEY_WINDOW_STICKY, NEMO_METADATA_KEY_WINDOW_KEEP_ABOVE, NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR, NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE, NEMO_METADATA_KEY_SIDEBAR_BUTTONS, NEMO_METADATA_KEY_ANNOTATION, NEMO_METADATA_KEY_ICON_POSITION, NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP, NEMO_METADATA_KEY_ICON_SCALE, NEMO_METADATA_KEY_CUSTOM_ICON, NEMO_METADATA_KEY_CUSTOM_ICON_NAME, NEMO_METADATA_KEY_EMBLEMS, NEMO_METADATA_KEY_MONITOR, NEMO_METADATA_KEY_DESKTOP_GRID_HORIZONTAL, NULL }; guint nemo_metadata_get_id (const char *metadata) { static GHashTable *hash; int i; if (hash == NULL) { hash = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; used_metadata_names[i] != NULL; i++) g_hash_table_insert (hash, used_metadata_names[i], GINT_TO_POINTER (i + 1)); } return GPOINTER_TO_INT (g_hash_table_lookup (hash, metadata)); } nemo-3.6.5/libnemo-private/org.nemo.gschema.xml.in0000664000175000017500000010542413215733314020775 0ustar fabiofabio 'after-current-tab' <_summary>Where to position newly open tabs in browser windows. <_description>If set to "after-current-tab", then new tabs are inserted after the current tab. If set to "end", then new tabs are appended to the end of the tab list. true <_summary>Enables the classic Nemo behavior, where all windows are browsers <_description>If set to true, then all Nemo windows will be browser windows. This is how Nemo used to behave before version 2.6, and some people prefer this behavior. false <_summary>Enables renaming of icons by two times clicking with pause between clicks <_description>If set to true, then icons in all Nemo windows will be able to get renamed quickly. Users should click two times on icons with a pause time more than double-click time of their system. false <_summary>Show the location entry by default <_description>If set to true, then Nemo browser windows will show a textual input entry for the location toolbar. true Show Previous button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show Next button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show Up button in nemo toolbar If set to true, then Nemo browser windows will show the button. false Show refresh button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show toggle button location entry/pathbar If set to true, then Nemo browser windows will show the button. false Show Home button in nemo toolbar If set to true, then Nemo browser windows will show the button. false Show Computer button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show Search button in nemo toolbar If set to true, then Nemo browser windows will show the button. false Show new folder button in nemo toolbar If set to true, then Nemo browser windows will show the button. false Show open in terminal in the nemo toolbar If set to true, then Nemo browser windows will show the button. true Show Icon View button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show List View button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show Compact View button in nemo toolbar If set to true, then Nemo browser windows will show the button. true Show a warning when Nemo is running as root If set to true, Nemo shows a warning in the infobar when it is running as root. true <_summary>Whether to ask for confirmation when deleting files, or emptying Trash <_description>If set to true, then Nemo will ask for confirmation when you attempt to delete files, or empty the Trash. true <_summary>Whether to enable immediate deletion <_description>If set to true, then Nemo will have a feature allowing you to delete a file immediately and in-place, instead of moving it to the trash. This feature can be dangerous, so use caution. false <_summary>Whether to swap the hotkeys for Trash and Delete <_description>If set to true, the Delete key will permanently delete a file, and the Shift-Delete key will only trash a file. 'local-only' <_summary>When to show number of items in a folder <_description>Speed tradeoff for when to show the number of items in a folder. If set to "always" then always show item counts, even if the folder is on a remote server. If set to "local-only" then only show counts for local file systems. If set to "never" then never bother to compute item counts. 'double' <_summary>Type of click used to launch/open files <_description>Possible values are "single" to launch files on a single click, or "double" to launch them on a double click. 'ask' <_summary>What to do with executable text files when activated <_description>What to do with executable text files when they are activated (single or double clicked). Possible values are "launch" to launch them as programs, "ask" to ask what to do via a dialog, and "display" to display them as text files. true <_summary>Use extra mouse button events in Nemo' browser window <_description>For users with mice that have "Forward" and "Back" buttons, this key will determine if any action is taken inside of Nemo when either is pressed. 9 <_summary>Mouse button to activate the "Forward" command in browser window <_description>For users with mice that have buttons for "Forward" and "Back", this key will set which button activates the "Forward" command in a browser window. Possible values range between 6 and 14. 8 <_summary>Mouse button to activate the "Back" command in browser window <_description>For users with mice that have buttons for "Forward" and "Back", this key will set which button activates the "Back" command in a browser window. Possible values range between 6 and 14. 'local-only' <_summary>When to show thumbnails of image files <_description>Speed tradeoff for when to show an image file as a thumbnail. If set to "always" then always thumbnail, even if the folder is on a remote server. If set to "local-only" then only show thumbnails for local file systems. If set to "never" then never bother to thumbnail images, just use a generic icon. 1048576 <_summary>Maximum image size for thumbnailing <_description>Images over this size (in bytes) won't be thumbnailed. The purpose of this setting is to avoid thumbnailing large images that may take a long time to load or use lots of memory. false <_summary>Show advanced permissions in the file property dialog <_description>If set to true, then Nemo lets you edit and display file permissions in a more unix-like way, accessing some more esoteric options. true <_summary>Show folders first in windows <_description>If set to true, then Nemo shows folders prior to showing files in the icon and list views. 'name' <_summary>Default sort order <_description>The default sort-order for items in the icon view. Possible values are "name", "size", "type" and "mtime". false <_summary>Reverse sort order in new windows <_description>If true, files in new windows will be sorted in reverse order. ie, if sorted by name, then instead of sorting the files from "a" to "z", they will be sorted from "z" to "a"; if sorted by size, instead of being incrementally they will be sorted decrementally. false <_summary>Nemo uses the users home folder as the desktop <_description>If set to true, then Nemo will use the user's home folder as the desktop. If it is false, then it will use ~/Desktop as the desktop. 'icon-view' <_summary>Default folder viewer <_description>When a folder is visited this viewer is used unless you have selected another view for that particular folder. Possible values are "list-view", "icon-view" and "compact-view". 'locale' <_summary>Date Format <_description>The format of file dates. Possible values are "locale", "iso", and "informal". false <_summary>Whether to show hidden files <_description>If set to true, then hidden files are shown by default in the file manager. Hidden files are either dotfiles, listed in the folder's .hidden file or backup files ending with a tilde (~). false <_summary>Whether to show the full path of the current view in the title bar and tab bars <_description>If set to true, will show the normal title of a window or tab, followed by the full path to that location in parentheses. [] <_summary>Bulk rename utility <_description>If set, Nemo will append URIs of selected files and treat the result as a command line for bulk renaming. Bulk rename applications can register themselves in this key by setting the key to a space-separated string of their executable name and any command line options. If the executable name is not set to a full path, it will be searched for in the search path. 'base-10' <_summary>Prefixes used for file sizes <_description>Determines whether Nemo uses base-10, base-10 long, base-2 or base-2 long file size prefixes false <_summary>Whether to close a view of a removeable device instead of navigating Home <_description>If set to true, a view open for a removeable device will be closed instead of sent Home if the device is ejected false <_summary>Whether to default to showing dual-pane view when a new window is opened <_description>If set to true, new Nemo windows will default to showing two panes false <_summary>Whether to ignore folder metadata for view zoom levels and layouts <_description>If set to true, views will not change according to their metadata, but stay consistent for the life of that window true <_summary>Whether to list bookmarks in the Move To/Copy To menus <_description>If set to true, bookmarks will be listed in the MoveTo/CopyTo menus true <_summary>Whether to list places in the Move To/Copy To menus <_description>If set to true, places will be listed in the MoveTo/CopyTo menus false <_summary>Whether to show all available actions in context menus <_description>If set to true, all actions are visible. Otherwise nemo shows a simplified version of what is present in the menubar. false <_summary>Show tooltips for desktop items <_description>If true, tooltips will be displayed for desktop items. false <_summary>Show tooltips when hovering on items in an icon or compact view <_description>If true, tooltips will be displayed for icon and compact view items false <_summary>Show tooltips when hovering on items in a list view <_description>If true, tooltips will be displayed for list view items false <_summary>Show detailed file type in tooltip <_description>If true, tooltips will show a detailed file type. false <_summary>Show file modified date in tooltip <_description>If true, tooltips will show their modified date. false <_summary>Show file accessed date in tooltip <_description>If true, tooltips will show their accessed date. false <_summary>Show full path in tooltip <_description>If true, tooltips will show the file's full path. false <_summary>Don't show the explainer message when turning off the main menu <_description>If true, you will no longer recieve a popup explaining how to reactivate the main menu once you've hidden it 2 <_summary>Last server connect method used false <_summary>If true, all file operations will start immediately false <_summary>If true, double click left on blank area will go to parent folder [ 'none', 'size', 'date_modified' ] <_summary>List of possible captions on icons <_description>A list of captions below an icon in the icon view and the desktop. The actual number of captions shown depends on the zoom level. Some possible values are: "size", "type", "date_modified", "date_changed", "date_accessed", "owner", "group", "permissions", "octal_permissions" and "mime_type". false <_summary>Use tighter layout in new windows <_description>If true, icons will be laid out tighter by default in new windows. false <_summary>Put labels beside icons <_description>If true, labels will be placed beside icons rather than underneath them. 'standard' <_summary>Default icon zoom level <_description>Default zoom level used by the icon view. 64 <_summary>Default Thumbnail Icon Size <_description>The default size of an icon for a thumbnail in the icon view. [ '3' ] <_summary>Text Ellipsis Limit <_description>A string specifying how parts of overlong file names should be replaced by ellipses, depending on the zoom level. Each of the list entries is of the form "Zoom Level:Integer". For each specified zoom level, if the given integer is larger than 0, the file name will not exceed the given number of lines. If the integer is 0 or smaller, no limit is imposed on the specified zoom level. A default entry of the form "Integer" without any specified zoom level is also allowed. It defines the maximum number of lines for all other zoom levels. Examples: 0 - always display overlong file names; 3 - shorten file names if they exceed three lines; smallest:5,smaller:4,0 - shorten file names if they exceed five lines for zoom level "smallest". Shorten file names if they exceed four lines for zoom level "smaller". Do not shorten file names for other zoom levels. Available zoom levels: smallest (33%), smaller (50%), small (66%), standard (100%), large (150%), larger (200%), largest (400%) 'standard' <_summary>Default compact view zoom level <_description>Default zoom level used by the compact view. false <_summary>All columns have same width <_description>If this preference is set, all columns in the compact view have the same width. Otherwise, the width of each column is determined seperately. 'smaller' <_summary>Default list zoom level <_description>Default zoom level used by the list view. [ 'name', 'size', 'type', 'date_modified' ] <_summary>Default list of columns visible in the list view <_description>Default list of columns visible in the list view. [ 'name', 'size', 'type', 'date_modified' ] <_summary>Default column order in the list view <_description>Default column order in the list view. [ 'name', 'size', 'type', 'where' ] <_summary>Default list of columns visible in the search view. <_description>Default list of columns visible in the search view. true <_summary>Only show folders in the tree side pane <_description>If set to true, Nemo will only show folders in the tree side pane. Otherwise it will show both folders and files. 'Noto Sans 10' <_summary>Desktop font <_description>The font _description used for the icons on the desktop. "true::false" <_summary>Desktop layout <_description>Format bool:bool, show desktop folder on primary monitor:show desktop on remaining monitors true <_summary>Whether to show icons from inactive monitors on another monitor true <_summary>Deprecated: Allow Nemo to manage the desktop <_description>Deprecated: If this is set to true, Nemo will autostart and manage the desktop true <_summary>Which desktop view type to use <_description>If true, the new desktop grid view will be used by nemo-desktop, otherwise the legacy view will be used. 1.0 <_summary>Vertical desktop grid adjustment <_description>Overrides the standard vertical spacing for the desktop grid, in situation where default spacing is not ideal due to label customizations. This is a value from 0.5 to 1.5, with 1.0 being no adjustment, and 0.5 being half the default spacing. 1.0 <_summary>Horizontal desktop grid adjustment <_description>Overrides the standard horizontal spacing for the desktop grid, in situation where default spacing is not ideal due to label customizations. This is a value from 0.5 to 1.5, with 1.0 being no adjustment, and 0.5 being half the default spacing. false <_summary>Home icon visible on desktop <_description>If this is set to true, an icon linking to the home folder will be put on the desktop. false <_summary>Computer icon visible on desktop <_description>If this is set to true, an icon linking to the computer location will be put on the desktop. false <_summary>Trash icon visible on desktop <_description>If this is set to true, an icon linking to the trash will be put on the desktop. false <_summary>Show mounted volumes on the desktop <_description>If this is set to true, icons linking to mounted volumes will be put on the desktop. false <_summary>Network Servers icon visible on the desktop <_description>If this is set to true, an icon linking to the Network Servers view will be put on the desktop. 2 <_summary>Text Ellipsis Limit <_description>An integer specifying how parts of overlong file names should be replaced by ellipses on the desktop. If the number is larger than 0, the file name will not exceed the given number of lines. If the number is 0 or smaller, no limit is imposed on the number of displayed lines. ['conky'] <_summary>List of desktop-handling to ignore when determining whether or not to manager the desktop. <_description>Nemo checks for _NET_WM_WINDOW_TYPE_DESKTOP-type windows, and skips managing the desktop if any others are detected. Add potential names to this list to ignore when performing this check. This means that you want nemo to create its own desktop window(s) even though something else already seems to. The check is based on a program's WM_CLASS. true <_summary>Fade the background on change <_description>If set to true, then Nemo will use a fade effect to change the desktop background. '' <_summary>The geometry string for a navigation window. <_description>A string containing the saved geometry and coordinates string for navigation windows. false <_summary>Whether the navigation window should be maximized. <_description>Whether the navigation window should be maximized by default. 148 <_summary>Width of the side pane <_description>The default width of the side pane in new windows. -1 <_summary>Index of the bookmark list to jump to the dedicated sidebar bookmark section <_description>This is an internal setting for the sidebar that tracks the index in the bookmark list that separates bookmarks in the Computer section from bookmarks in the Bookmark section. true <_summary>Show toolbar in new windows <_description>If set to true, newly opened windows will have toolbars visible. true <_summary>Show location bar in new windows <_description>If set to true, newly opened windows will have the location bar visible. true <_summary>Show status bar in new windows <_description>If set to true, newly opened windows will have the status bar visible. true <_summary>Show side pane in new windows <_description>If set to true, newly opened windows will have the side pane visible. true <_summary>Show menu bar in new windows <_description>If set to true, newly opened windows will have the menu bar visible. true <_summary>Expand My Computer section in places sidebar <_description>View state storage for My Computer in places sidebar true <_summary>Expand Bookmark section in places sidebar <_description>View state storage for Bookmarks in places sidebar true <_summary>Expand Devices section in places sidebar <_description>View state storage for My Computer in places sidebar true <_summary>Expand Network section in places sidebar <_description>View state storage for My Computer in places sidebar 'places' <_summary>Side pane view <_description>The side pane view to show in newly opened windows. [] <_summary>List of extensions -not- to load. <_description>List of extension names you do -not- want to load. This maintains the behavior of an installed extension being enabled by default. [] <_summary>List of NemoActions -not- to load. <_description>List of action files you do -not- want loaded. This maintains the behavior of an installed action being enabled by default. [] <_summary>List of scripts -not- to load. <_description>List of script files you do -not- want loaded. This maintains the behavior of an installed script being enabled by default. nemo-3.6.5/libnemo-private/nemo-trash-monitor.h0000664000175000017500000000457713215733314020436 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-trash-monitor.h: Nemo trash state watcher. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Pavel Cisler */ #ifndef NEMO_TRASH_MONITOR_H #define NEMO_TRASH_MONITOR_H #include #include typedef struct NemoTrashMonitor NemoTrashMonitor; typedef struct NemoTrashMonitorClass NemoTrashMonitorClass; typedef struct NemoTrashMonitorDetails NemoTrashMonitorDetails; #define NEMO_TYPE_TRASH_MONITOR nemo_trash_monitor_get_type() #define NEMO_TRASH_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_TRASH_MONITOR, NemoTrashMonitor)) #define NEMO_TRASH_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_TRASH_MONITOR, NemoTrashMonitorClass)) #define NEMO_IS_TRASH_MONITOR(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_TRASH_MONITOR)) #define NEMO_IS_TRASH_MONITOR_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_TRASH_MONITOR)) #define NEMO_TRASH_MONITOR_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_TRASH_MONITOR, NemoTrashMonitorClass)) struct NemoTrashMonitor { GObject object; NemoTrashMonitorDetails *details; }; struct NemoTrashMonitorClass { GObjectClass parent_class; void (* trash_state_changed) (NemoTrashMonitor *trash_monitor, gboolean new_state); }; GType nemo_trash_monitor_get_type (void); NemoTrashMonitor *nemo_trash_monitor_get (void); gboolean nemo_trash_monitor_is_empty (void); GIcon *nemo_trash_monitor_get_icon (void); void nemo_trash_monitor_add_new_trash_directories (void); #endif nemo-3.6.5/libnemo-private/nemo-column-chooser.h0000664000175000017500000000511513215733314020552 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-column-choose.h - A column chooser widget Copyright (C) 2004 Novell, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the column COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Dave Camp */ #ifndef NEMO_COLUMN_CHOOSER_H #define NEMO_COLUMN_CHOOSER_H #include #include #define NEMO_TYPE_COLUMN_CHOOSER nemo_column_chooser_get_type() #define NEMO_COLUMN_CHOOSER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_COLUMN_CHOOSER, NemoColumnChooser)) #define NEMO_COLUMN_CHOOSER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_COLUMN_CHOOSER, NemoColumnChooserClass)) #define NEMO_IS_COLUMN_CHOOSER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_COLUMN_CHOOSER)) #define NEMO_IS_COLUMN_CHOOSER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_COLUMN_CHOOSER)) #define NEMO_COLUMN_CHOOSER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_COLUMN_CHOOSER, NemoColumnChooserClass)) typedef struct _NemoColumnChooserDetails NemoColumnChooserDetails; typedef struct { GtkBox parent; NemoColumnChooserDetails *details; } NemoColumnChooser; typedef struct { GtkBoxClass parent_slot; void (*changed) (NemoColumnChooser *chooser); void (*use_default) (NemoColumnChooser *chooser); } NemoColumnChooserClass; GType nemo_column_chooser_get_type (void); GtkWidget *nemo_column_chooser_new (NemoFile *file); void nemo_column_chooser_set_settings (NemoColumnChooser *chooser, char **visible_columns, char **column_order); void nemo_column_chooser_get_settings (NemoColumnChooser *chooser, char ***visible_columns, char ***column_order); #endif /* NEMO_COLUMN_CHOOSER_H */ nemo-3.6.5/libnemo-private/nemo-ui-utilities.c0000664000175000017500000000730013215733314020234 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-ui-utilities.c - helper functions for GtkUIManager stuff Copyright (C) 2004 Red Hat, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Alexander Larsson */ #include #include "nemo-ui-utilities.h" #include "nemo-icon-info.h" #include #include #include void nemo_ui_unmerge_ui (GtkUIManager *ui_manager, guint *merge_id, GtkActionGroup **action_group) { if (*merge_id != 0) { gtk_ui_manager_remove_ui (ui_manager, *merge_id); *merge_id = 0; } if (*action_group != NULL) { gtk_ui_manager_remove_action_group (ui_manager, *action_group); *action_group = NULL; } } void nemo_ui_prepare_merge_ui (GtkUIManager *ui_manager, const char *name, guint *merge_id, GtkActionGroup **action_group) { *merge_id = gtk_ui_manager_new_merge_id (ui_manager); *action_group = gtk_action_group_new (name); gtk_action_group_set_translation_domain (*action_group, GETTEXT_PACKAGE); gtk_ui_manager_insert_action_group (ui_manager, *action_group, 0); g_object_unref (*action_group); /* owned by ui manager */ } static void extension_action_callback (GtkAction *action, gpointer callback_data) { nemo_menu_item_activate (NEMO_MENU_ITEM (callback_data)); } GtkAction * nemo_action_from_menu_item (NemoMenuItem *item, GtkWidget *parent_widget) { char *name, *label, *tip, *icon_name; gboolean sensitive, priority; GtkAction *action; GdkPixbuf *pixbuf; g_object_get (G_OBJECT (item), "name", &name, "label", &label, "tip", &tip, "icon", &icon_name, "sensitive", &sensitive, "priority", &priority, NULL); action = gtk_action_new (name, label, tip, NULL); if (icon_name != NULL) { pixbuf = nemo_ui_get_menu_icon (icon_name, parent_widget); if (pixbuf != NULL) { gtk_action_set_gicon (action, G_ICON (pixbuf)); g_object_unref (pixbuf); } } gtk_action_set_sensitive (action, sensitive); g_object_set (action, "is-important", priority, NULL); g_signal_connect_data (action, "activate", G_CALLBACK (extension_action_callback), g_object_ref (item), (GClosureNotify)g_object_unref, 0); g_free (name); g_free (label); g_free (tip); g_free (icon_name); return action; } GdkPixbuf * nemo_ui_get_menu_icon (const char *icon_name, GtkWidget *parent_widget) { NemoIconInfo *info; GdkPixbuf *pixbuf; int size; int scale; size = nemo_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU); scale = gtk_widget_get_scale_factor (parent_widget); if (g_path_is_absolute (icon_name)) { info = nemo_icon_info_lookup_from_path (icon_name, size, scale); } else { info = nemo_icon_info_lookup_from_name (icon_name, size, scale); } pixbuf = nemo_icon_info_get_pixbuf_nodefault_at_size (info, size); g_object_unref (info); return pixbuf; } nemo-3.6.5/libnemo-private/nemo-program-choosing.c0000664000175000017500000002564413215733314021077 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-program-choosing.c - functions for selecting and activating programs for opening/viewing particular files. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: John Sullivan */ #include #include "nemo-program-choosing.h" #include "nemo-global-preferences.h" #include "nemo-icon-info.h" #include "nemo-recent.h" #include "nemo-desktop-icon-file.h" #include #include #include #include #include #include #include #include #include void nemo_launch_application_for_mount (GAppInfo *app_info, GMount *mount, GtkWindow *parent_window) { GFile *root; NemoFile *file; GList *files; root = g_mount_get_root (mount); file = nemo_file_get (root); g_object_unref (root); files = g_list_append (NULL, file); nemo_launch_application (app_info, files, parent_window); g_list_free_full (files, (GDestroyNotify) nemo_file_unref); } /** * nemo_launch_application: * * Fork off a process to launch an application with a given file as a * parameter. Provide a parent window for error dialogs. * * @application: The application to be launched. * @uris: The files whose locations should be passed as a parameter to the application. * @parent_window: A window to use as the parent for any error dialogs. */ void nemo_launch_application (GAppInfo *application, GList *files, GtkWindow *parent_window) { GList *uris, *l; uris = NULL; for (l = files; l != NULL; l = l->next) { uris = g_list_prepend (uris, nemo_file_get_activation_uri (l->data)); } uris = g_list_reverse (uris); nemo_launch_application_by_uri (application, uris, parent_window); g_list_free_full (uris, g_free); } void nemo_launch_application_by_uri (GAppInfo *application, GList *uris, GtkWindow *parent_window) { char *uri; GList *locations, *l; GFile *location; NemoFile *file; gboolean result; GError *error; GdkDisplay *display; GdkAppLaunchContext *launch_context; NemoIconInfo *icon; int count, total; g_assert (uris != NULL); /* count the number of uris with local paths */ count = 0; total = g_list_length (uris); locations = NULL; for (l = uris; l != NULL; l = l->next) { uri = l->data; location = g_file_new_for_uri (uri); if (g_file_is_native (location)) { count++; } locations = g_list_prepend (locations, location); } locations = g_list_reverse (locations); if (parent_window != NULL) { display = gtk_widget_get_display (GTK_WIDGET (parent_window)); } else { display = gdk_display_get_default (); } launch_context = gdk_display_get_app_launch_context (display); if (parent_window != NULL) { gdk_app_launch_context_set_screen (launch_context, gtk_window_get_screen (parent_window)); } file = nemo_file_get_by_uri (uris->data); icon = nemo_file_get_icon (file, 48, 0, gtk_widget_get_scale_factor (GTK_WIDGET (parent_window)), 0); nemo_file_unref (file); if (icon) { gdk_app_launch_context_set_icon_name (launch_context, nemo_icon_info_get_used_name (icon)); g_object_unref (icon); } error = NULL; if (count == total) { /* All files are local, so we can use g_app_info_launch () with * the file list we constructed before. */ result = g_app_info_launch (application, locations, G_APP_LAUNCH_CONTEXT (launch_context), &error); } else { /* Some files are non local, better use g_app_info_launch_uris (). */ result = g_app_info_launch_uris (application, uris, G_APP_LAUNCH_CONTEXT (launch_context), &error); } g_object_unref (launch_context); if (result) { for (l = uris; l != NULL; l = l->next) { file = nemo_file_get_by_uri (l->data); nemo_recent_add_file (file, application); nemo_file_unref (file); } } g_list_free_full (locations, g_object_unref); } static void launch_application_from_command_internal (const gchar *full_command, GdkScreen *screen, gboolean use_terminal) { GAppInfo *app; GdkAppLaunchContext *ctx; GdkDisplay *display; if (use_terminal) { eel_gnome_open_terminal_on_screen (full_command, screen); } else { app = g_app_info_create_from_commandline (full_command, NULL, 0, NULL); if (app != NULL) { display = gdk_screen_get_display (screen); ctx = gdk_display_get_app_launch_context (display); gdk_app_launch_context_set_screen (ctx, screen); g_app_info_launch (app, NULL, G_APP_LAUNCH_CONTEXT (ctx), NULL); g_object_unref (app); g_object_unref (ctx); } } } /** * nemo_launch_application_from_command: * * Fork off a process to launch an application with a given uri as * a parameter. * * @command_string: The application to be launched, with any desired * command-line options. * @...: Passed as parameters to the application after quoting each of them. */ void nemo_launch_application_from_command (GdkScreen *screen, const char *command_string, gboolean use_terminal, ...) { char *full_command, *tmp; char *quoted_parameter; char *parameter; va_list ap; full_command = g_strdup (command_string); va_start (ap, use_terminal); while ((parameter = va_arg (ap, char *)) != NULL) { quoted_parameter = g_shell_quote (parameter); tmp = g_strconcat (full_command, " ", quoted_parameter, NULL); g_free (quoted_parameter); g_free (full_command); full_command = tmp; } va_end (ap); launch_application_from_command_internal (full_command, screen, use_terminal); g_free (full_command); } /** * nemo_launch_application_from_command: * * Fork off a process to launch an application with a given uri as * a parameter. * * @command_string: The application to be launched, with any desired * command-line options. * @parameters: Passed as parameters to the application after quoting each of them. */ void nemo_launch_application_from_command_array (GdkScreen *screen, const char *command_string, gboolean use_terminal, const char * const * parameters) { char *full_command, *tmp; char *quoted_parameter; const char * const *p; full_command = g_strdup (command_string); if (parameters != NULL) { for (p = parameters; *p != NULL; p++) { quoted_parameter = g_shell_quote (*p); tmp = g_strconcat (full_command, " ", quoted_parameter, NULL); g_free (quoted_parameter); g_free (full_command); full_command = tmp; } } launch_application_from_command_internal (full_command, screen, use_terminal); g_free (full_command); } void nemo_launch_desktop_file (GdkScreen *screen, const char *desktop_file_uri, const GList *parameter_uris, GtkWindow *parent_window) { GError *error; char *message, *desktop_file_path; const GList *p; GList *files; int total, count; GFile *file, *desktop_file; GDesktopAppInfo *app_info; GdkAppLaunchContext *context; /* Don't allow command execution from remote locations * to partially mitigate the security * risk of executing arbitrary commands. */ desktop_file = g_file_new_for_uri (desktop_file_uri); desktop_file_path = g_file_get_path (desktop_file); if (!g_file_is_native (desktop_file)) { g_free (desktop_file_path); g_object_unref (desktop_file); eel_show_error_dialog (_("Sorry, but you cannot execute commands from " "a remote site."), _("This is disabled due to security considerations."), parent_window); return; } g_object_unref (desktop_file); app_info = g_desktop_app_info_new_from_filename (desktop_file_path); g_free (desktop_file_path); if (app_info == NULL) { eel_show_error_dialog (_("There was an error launching the application."), NULL, parent_window); return; } /* count the number of uris with local paths */ count = 0; total = g_list_length ((GList *) parameter_uris); files = NULL; for (p = parameter_uris; p != NULL; p = p->next) { file = g_file_new_for_uri ((const char *) p->data); if (g_file_is_native (file)) { count++; } files = g_list_prepend (files, file); } /* check if this app only supports local files */ if (g_app_info_supports_files (G_APP_INFO (app_info)) && !g_app_info_supports_uris (G_APP_INFO (app_info)) && parameter_uris != NULL) { if (count == 0) { /* all files are non-local */ eel_show_error_dialog (_("This drop target only supports local files."), _("To open non-local files copy them to a local folder and then" " drop them again."), parent_window); g_list_free_full (files, g_object_unref); g_object_unref (app_info); return; } else if (count != total) { /* some files are non-local */ eel_show_warning_dialog (_("This drop target only supports local files."), _("To open non-local files copy them to a local folder and then" " drop them again. The local files you dropped have already been opened."), parent_window); } } error = NULL; context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (parent_window))); /* TODO: Ideally we should accept a timestamp here instead of using GDK_CURRENT_TIME */ gdk_app_launch_context_set_timestamp (context, GDK_CURRENT_TIME); gdk_app_launch_context_set_screen (context, gtk_window_get_screen (parent_window)); if (count == total) { /* All files are local, so we can use g_app_info_launch () with * the file list we constructed before. */ g_app_info_launch (G_APP_INFO (app_info), files, G_APP_LAUNCH_CONTEXT (context), &error); } else { /* Some files are non local, better use g_app_info_launch_uris (). */ g_app_info_launch_uris (G_APP_INFO (app_info), (GList *) parameter_uris, G_APP_LAUNCH_CONTEXT (context), &error); } if (error != NULL) { message = g_strconcat (_("Details: "), error->message, NULL); eel_show_error_dialog (_("There was an error launching the application."), message, parent_window); g_error_free (error); g_free (message); } g_list_free_full (files, g_object_unref); g_object_unref (context); g_object_unref (app_info); } nemo-3.6.5/libnemo-private/nemo-signaller.c0000664000175000017500000000547113215733314017575 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 1999, 2000 Eazel, Inc. * * Nemo is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA * * Author: John Sullivan */ /* nemo-signaller.h: Class to manage nemo-wide signals that don't * correspond to any particular object. */ #include #include "nemo-signaller.h" #include typedef GObject NemoSignaller; typedef GObjectClass NemoSignallerClass; enum { HISTORY_LIST_CHANGED, POPUP_MENU_CHANGED, USER_DIRS_CHANGED, MIME_DATA_CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static GType nemo_signaller_get_type (void); G_DEFINE_TYPE (NemoSignaller, nemo_signaller, G_TYPE_OBJECT); GObject * nemo_signaller_get_current (void) { static GObject *global_signaller = NULL; if (global_signaller == NULL) { global_signaller = g_object_new (nemo_signaller_get_type (), NULL); } return global_signaller; } static void nemo_signaller_init (NemoSignaller *signaller) { } static void nemo_signaller_class_init (NemoSignallerClass *class) { signals[HISTORY_LIST_CHANGED] = g_signal_new ("history_list_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[POPUP_MENU_CHANGED] = g_signal_new ("popup_menu_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[USER_DIRS_CHANGED] = g_signal_new ("user_dirs_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[MIME_DATA_CHANGED] = g_signal_new ("mime_data_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } nemo-3.6.5/libnemo-private/nemo-clipboard.h0000664000175000017500000000440513215733314017555 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* fm-directory-view.h * * Copyright (C) 1999, 2000 Free Software Foundaton * Copyright (C) 2000 Eazel, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Rebecca Schulman */ #ifndef NEMO_CLIPBOARD_H #define NEMO_CLIPBOARD_H #include /* This makes this editable or text view put clipboard commands into * the passed UI manager when the editable/text view is in focus. * Callers in Nemo normally get the UI manager from * nemo_window_get_ui_manager. */ /* The shares selection changes argument should be set to true if the * widget uses the signal "selection_changed" to tell others about * text selection changes. The NemoEntry widget * is currently the only editable in nemo that shares selection * changes. */ void nemo_clipboard_set_up_editable (GtkEditable *target, GtkUIManager *ui_manager, gboolean shares_selection_changes); void nemo_clipboard_set_up_text_view (GtkTextView *target, GtkUIManager *ui_manager); void nemo_clipboard_clear_if_colliding_uris (GtkWidget *widget, const GList *item_uris, GdkAtom copied_files_atom); GtkClipboard* nemo_clipboard_get (GtkWidget *widget); GList* nemo_clipboard_get_uri_list_from_selection_data (GtkSelectionData *selection_data, gboolean *cut, GdkAtom copied_files_atom); #endif /* NEMO_CLIPBOARD_H */ nemo-3.6.5/libnemo-private/nemo-separator-action.c0000664000175000017500000000462113215733314021064 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-separator-action.h" G_DEFINE_TYPE (NemoSeparatorAction, nemo_separator_action, GTK_TYPE_ACTION); static void nemo_separator_action_init (NemoSeparatorAction *action); static void nemo_separator_action_class_init (NemoSeparatorActionClass *klass); static GtkWidget *create_menu_item (GtkAction *action); static GtkWidget *create_tool_item (GtkAction *action); static gpointer parent_class; static void nemo_separator_action_init (NemoSeparatorAction *action) { } static void nemo_separator_action_class_init (NemoSeparatorActionClass *klass) { GtkActionClass *action_class = GTK_ACTION_CLASS (klass); parent_class = g_type_class_peek_parent (klass); action_class->create_menu_item = create_menu_item; action_class->create_tool_item = create_tool_item; action_class->menu_item_type = GTK_TYPE_SEPARATOR_MENU_ITEM; action_class->toolbar_item_type = GTK_TYPE_SEPARATOR_TOOL_ITEM; } GtkAction * nemo_separator_action_new (const gchar *name) { return g_object_new (NEMO_TYPE_SEPARATOR_ACTION, "name", name, NULL); } static GtkWidget * create_menu_item (GtkAction *action) { GType menu_item_type; GtkWidget *ret; menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type; ret = g_object_new (menu_item_type, NULL); gtk_activatable_set_use_action_appearance (GTK_ACTIVATABLE (ret), FALSE); return ret; } static GtkWidget * create_tool_item (GtkAction *action) { g_warning ("NemoSeparatorAction: Toolbar items unsupported at this time."); return NULL; } nemo-3.6.5/libnemo-private/nemo-column-utilities.h0000664000175000017500000000301613215733314021121 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-column-utilities.h - Utilities related to column specifications Copyright (C) 2004 Novell, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the column COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Dave Camp */ #ifndef NEMO_COLUMN_UTILITIES_H #define NEMO_COLUMN_UTILITIES_H #include #include GList *nemo_get_all_columns (void); GList *nemo_get_common_columns (void); GList *nemo_get_columns_for_file (NemoFile *file); GList *nemo_column_list_copy (GList *columns); void nemo_column_list_free (GList *columns); GList *nemo_sort_columns (GList *columns, char **column_order); #endif /* NEMO_COLUMN_UTILITIES_H */ nemo-3.6.5/libnemo-private/nemo-dnd.h0000664000175000017500000001507213215733314016365 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-dnd.h - Common Drag & drop handling code shared by the icon container and the list view. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Pavel Cisler , Ettore Perazzoli */ #ifndef NEMO_DND_H #define NEMO_DND_H #include /* Drag & Drop target names. */ #define NEMO_ICON_DND_GNOME_ICON_LIST_TYPE "x-special/gnome-icon-list" #define NEMO_ICON_DND_URI_LIST_TYPE "text/uri-list" #define NEMO_ICON_DND_NETSCAPE_URL_TYPE "_NETSCAPE_URL" #define NEMO_ICON_DND_BGIMAGE_TYPE "property/bgimage" #define NEMO_ICON_DND_ROOTWINDOW_DROP_TYPE "application/x-rootwindow-drop" #define NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE "XdndDirectSave0" /* XDS Protocol Type */ #define NEMO_ICON_DND_RAW_TYPE "application/octet-stream" /* Item of the drag selection list */ typedef struct { char *uri; gboolean got_icon_position; int icon_x, icon_y; int icon_width, icon_height; } NemoDragSelectionItem; /* Standard Drag & Drop types. */ typedef enum { NEMO_ICON_DND_GNOME_ICON_LIST, NEMO_ICON_DND_URI_LIST, NEMO_ICON_DND_NETSCAPE_URL, NEMO_ICON_DND_TEXT, NEMO_ICON_DND_XDNDDIRECTSAVE, NEMO_ICON_DND_RAW, NEMO_ICON_DND_ROOTWINDOW_DROP } NemoIconDndTargetType; typedef enum { NEMO_DND_ACTION_FIRST = GDK_ACTION_ASK << 1, NEMO_DND_ACTION_SET_AS_BACKGROUND = NEMO_DND_ACTION_FIRST << 0, NEMO_DND_ACTION_SET_AS_FOLDER_BACKGROUND = NEMO_DND_ACTION_FIRST << 1, NEMO_DND_ACTION_SET_AS_GLOBAL_BACKGROUND = NEMO_DND_ACTION_FIRST << 2 } NemoDndAction; /* drag&drop-related information. */ typedef struct { GtkTargetList *target_list; gchar *source_fs; gboolean can_delete_source; /* Stuff saved at "receive data" time needed later in the drag. */ gboolean got_drop_data_type; NemoIconDndTargetType data_type; GtkSelectionData *selection_data; char *direct_save_uri; /* Start of the drag, in window coordinates. */ int start_x, start_y; /* List of NemoDragSelectionItems, representing items being dragged, or NULL * if data about them has not been received from the source yet. */ GList *selection_list; /* has the drop occured ? */ gboolean drop_occured; /* whether or not need to clean up the previous dnd data */ gboolean need_to_destroy; /* autoscrolling during dragging */ int auto_scroll_timeout_id; gboolean waiting_to_autoscroll; gint64 start_auto_scroll_in; } NemoDragInfo; typedef void (* NemoDragEachSelectedItemDataGet) (const char *url, int x, int y, int w, int h, gpointer data); typedef void (* NemoDragEachSelectedItemIterator) (NemoDragEachSelectedItemDataGet iteratee, gpointer iterator_context, gpointer data); void nemo_drag_init (NemoDragInfo *drag_info, const GtkTargetEntry *drag_types, int drag_type_count, gboolean add_text_targets); void nemo_drag_finalize (NemoDragInfo *drag_info); NemoDragSelectionItem *nemo_drag_selection_item_new (void); void nemo_drag_destroy_selection_list (GList *selection_list); GList *nemo_drag_build_selection_list (GtkSelectionData *data); char ** nemo_drag_uri_array_from_selection_list (const GList *selection_list); GList * nemo_drag_uri_list_from_selection_list (const GList *selection_list); char ** nemo_drag_uri_array_from_list (const GList *uri_list); GList * nemo_drag_uri_list_from_array (const char **uris); gboolean nemo_drag_items_local (const char *target_uri, const GList *selection_list); gboolean nemo_drag_uris_local (const char *target_uri, const GList *source_uri_list); gboolean nemo_drag_items_in_trash (const GList *selection_list); gboolean nemo_drag_items_on_desktop (const GList *selection_list); void nemo_drag_default_drop_action_for_icons (GdkDragContext *context, const char *target_uri_string, const GList *items, int *action, gchar **source_fs, gboolean *can_delete_source); GdkDragAction nemo_drag_default_drop_action_for_netscape_url (GdkDragContext *context); GdkDragAction nemo_drag_default_drop_action_for_uri_list (GdkDragContext *context, const char *target_uri_string); gboolean nemo_drag_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint32 time, gpointer container_context, NemoDragEachSelectedItemIterator each_selected_item_iterator); int nemo_drag_modifier_based_action (int default_action, int non_default_action); GdkDragAction nemo_drag_drop_action_ask (GtkWidget *widget, GdkDragAction possible_actions); gboolean nemo_drag_autoscroll_in_scroll_region (GtkWidget *widget); void nemo_drag_autoscroll_calculate_delta (GtkWidget *widget, float *x_scroll_delta, float *y_scroll_delta); void nemo_drag_autoscroll_start (NemoDragInfo *drag_info, GtkWidget *widget, GSourceFunc callback, gpointer user_data); void nemo_drag_autoscroll_stop (NemoDragInfo *drag_info); gboolean nemo_drag_selection_includes_special_link (GList *selection_list); #endif nemo-3.6.5/libnemo-private/nemo-program-choosing.h0000664000175000017500000000531513215733314021075 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-program-choosing.h - functions for selecting and activating programs for opening/viewing particular files. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: John Sullivan */ #ifndef NEMO_PROGRAM_CHOOSING_H #define NEMO_PROGRAM_CHOOSING_H #include #include #include typedef void (*NemoApplicationChoiceCallback) (GAppInfo *application, gpointer callback_data); void nemo_launch_application (GAppInfo *application, GList *files, GtkWindow *parent_window); void nemo_launch_application_by_uri (GAppInfo *application, GList *uris, GtkWindow *parent_window); void nemo_launch_application_for_mount (GAppInfo *app_info, GMount *mount, GtkWindow *parent_window); void nemo_launch_application_from_command (GdkScreen *screen, const char *command_string, gboolean use_terminal, ...) G_GNUC_NULL_TERMINATED; void nemo_launch_application_from_command_array (GdkScreen *screen, const char *command_string, gboolean use_terminal, const char * const * parameters); void nemo_launch_desktop_file (GdkScreen *screen, const char *desktop_file_uri, const GList *parameter_uris, GtkWindow *parent_window); #endif /* NEMO_PROGRAM_CHOOSING_H */ nemo-3.6.5/libnemo-private/nemo-search-engine.h0000664000175000017500000000600613215733314020325 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Novell, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Anders Carlsson * */ #ifndef NEMO_SEARCH_ENGINE_H #define NEMO_SEARCH_ENGINE_H #include #include #define NEMO_TYPE_SEARCH_ENGINE (nemo_search_engine_get_type ()) #define NEMO_SEARCH_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEARCH_ENGINE, NemoSearchEngine)) #define NEMO_SEARCH_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEARCH_ENGINE, NemoSearchEngineClass)) #define NEMO_IS_SEARCH_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEARCH_ENGINE)) #define NEMO_IS_SEARCH_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEARCH_ENGINE)) #define NEMO_SEARCH_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEARCH_ENGINE, NemoSearchEngineClass)) typedef struct NemoSearchEngineDetails NemoSearchEngineDetails; typedef struct NemoSearchEngine { GObject parent; NemoSearchEngineDetails *details; } NemoSearchEngine; typedef struct { GObjectClass parent_class; /* VTable */ void (*set_query) (NemoSearchEngine *engine, NemoQuery *query); void (*start) (NemoSearchEngine *engine); void (*stop) (NemoSearchEngine *engine); /* Signals */ void (*hits_added) (NemoSearchEngine *engine, GList *hits); void (*hits_subtracted) (NemoSearchEngine *engine, GList *hits); void (*finished) (NemoSearchEngine *engine); void (*error) (NemoSearchEngine *engine, const char *error_message); } NemoSearchEngineClass; GType nemo_search_engine_get_type (void); gboolean nemo_search_engine_enabled (void); NemoSearchEngine* nemo_search_engine_new (void); void nemo_search_engine_set_query (NemoSearchEngine *engine, NemoQuery *query); void nemo_search_engine_start (NemoSearchEngine *engine); void nemo_search_engine_stop (NemoSearchEngine *engine); void nemo_search_engine_hits_added (NemoSearchEngine *engine, GList *hits); void nemo_search_engine_hits_subtracted (NemoSearchEngine *engine, GList *hits); void nemo_search_engine_finished (NemoSearchEngine *engine); void nemo_search_engine_error (NemoSearchEngine *engine, const char *error_message); #endif /* NEMO_SEARCH_ENGINE_H */ nemo-3.6.5/libnemo-private/nemo-progress-info-manager.h0000664000175000017500000000511413215733314022021 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 2011 Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Cosimo Cecchi */ #ifndef __NEMO_PROGRESS_INFO_MANAGER_H__ #define __NEMO_PROGRESS_INFO_MANAGER_H__ #include #include #define NEMO_TYPE_PROGRESS_INFO_MANAGER nemo_progress_info_manager_get_type() #define NEMO_PROGRESS_INFO_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_PROGRESS_INFO_MANAGER, NemoProgressInfoManager)) #define NEMO_PROGRESS_INFO_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_PROGRESS_INFO_MANAGER, NemoProgressInfoManagerClass)) #define NEMO_IS_PROGRESS_INFO_MANAGER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_PROGRESS_INFO_MANAGER)) #define NEMO_IS_PROGRESS_INFO_MANAGER_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_PROGRESS_INFO_MANAGER)) #define NEMO_PROGRESS_INFO_MANAGER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_PROGRESS_INFO_MANAGER, NemoProgressInfoManagerClass)) typedef struct _NemoProgressInfoManager NemoProgressInfoManager; typedef struct _NemoProgressInfoManagerClass NemoProgressInfoManagerClass; typedef struct _NemoProgressInfoManagerPriv NemoProgressInfoManagerPriv; struct _NemoProgressInfoManager { GObject parent; /* private */ NemoProgressInfoManagerPriv *priv; }; struct _NemoProgressInfoManagerClass { GObjectClass parent_class; }; GType nemo_progress_info_manager_get_type (void); NemoProgressInfoManager* nemo_progress_info_manager_new (void); void nemo_progress_info_manager_add_new_info (NemoProgressInfoManager *self, NemoProgressInfo *info); GList *nemo_progress_info_manager_get_all_infos (NemoProgressInfoManager *self); G_END_DECLS #endif /* __NEMO_PROGRESS_INFO_MANAGER_H__ */ nemo-3.6.5/libnemo-private/nemo-tree-view-drag-dest.c0000664000175000017500000007025113215733314021372 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* * Nemo * * Copyright (C) 2002 Sun Microsystems, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Dave Camp * XDS support: Benedikt Meurer (adapted by Amos Brocco ) */ /* nemo-tree-view-drag-dest.c: Handles drag and drop for treeviews which * contain a hierarchy of files */ #include #include "nemo-tree-view-drag-dest.h" #include "nemo-file-dnd.h" #include "nemo-file-changes-queue.h" #include "nemo-icon-dnd.h" #include "nemo-link.h" #include #include #include #define DEBUG_FLAG NEMO_DEBUG_LIST_VIEW #include "nemo-debug.h" #define AUTO_SCROLL_MARGIN 20 #define HOVER_EXPAND_TIMEOUT 1 struct _NemoTreeViewDragDestDetails { GtkTreeView *tree_view; gboolean drop_occurred; gboolean have_drag_data; guint drag_type; GtkSelectionData *drag_data; GList *drag_list; guint highlight_id; guint scroll_id; guint expand_id; gchar *desktop_dnd_source_fs; gboolean desktop_dnd_can_delete_source; char *direct_save_uri; }; enum { GET_ROOT_URI, GET_FILE_FOR_PATH, MOVE_COPY_ITEMS, HANDLE_NETSCAPE_URL, HANDLE_URI_LIST, HANDLE_TEXT, HANDLE_RAW, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (NemoTreeViewDragDest, nemo_tree_view_drag_dest, G_TYPE_OBJECT); static const GtkTargetEntry drag_types [] = { { NEMO_ICON_DND_GNOME_ICON_LIST_TYPE, 0, NEMO_ICON_DND_GNOME_ICON_LIST }, /* prefer "_NETSCAPE_URL" over "text/uri-list" to satisfy web browsers. */ { NEMO_ICON_DND_NETSCAPE_URL_TYPE, 0, NEMO_ICON_DND_NETSCAPE_URL }, { NEMO_ICON_DND_URI_LIST_TYPE, 0, NEMO_ICON_DND_URI_LIST }, { NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, 0, NEMO_ICON_DND_XDNDDIRECTSAVE }, /* XDS Protocol Type */ { NEMO_ICON_DND_RAW_TYPE, 0, NEMO_ICON_DND_RAW } }; static void gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view) { GdkRectangle visible_rect; GtkAdjustment *vadjustment; GdkDeviceManager *manager; GdkDevice *pointer; GdkWindow *window; int y; int offset; float value; window = gtk_tree_view_get_bin_window (tree_view); vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (tree_view)); manager = gdk_display_get_device_manager (gtk_widget_get_display (GTK_WIDGET (tree_view))); pointer = gdk_device_manager_get_client_pointer (manager); gdk_window_get_device_position (window, pointer, NULL, &y, NULL); y += gtk_adjustment_get_value (vadjustment); gtk_tree_view_get_visible_rect (tree_view, &visible_rect); offset = y - (visible_rect.y + 2 * AUTO_SCROLL_MARGIN); if (offset > 0) { offset = y - (visible_rect.y + visible_rect.height - 2 * AUTO_SCROLL_MARGIN); if (offset < 0) { return; } } value = CLAMP (gtk_adjustment_get_value (vadjustment) + offset, 0.0, gtk_adjustment_get_upper (vadjustment) - gtk_adjustment_get_page_size (vadjustment)); gtk_adjustment_set_value (vadjustment, value); } static int scroll_timeout (gpointer data) { GtkTreeView *tree_view = GTK_TREE_VIEW (data); gtk_tree_view_vertical_autoscroll (tree_view); return TRUE; } static void remove_scroll_timeout (NemoTreeViewDragDest *dest) { if (dest->details->scroll_id) { g_source_remove (dest->details->scroll_id); dest->details->scroll_id = 0; } } static int expand_timeout (gpointer data) { GtkTreeView *tree_view; GtkTreePath *drop_path; tree_view = GTK_TREE_VIEW (data); gtk_tree_view_get_drag_dest_row (tree_view, &drop_path, NULL); if (drop_path) { gtk_tree_view_expand_row (tree_view, drop_path, FALSE); gtk_tree_path_free (drop_path); } return FALSE; } static void remove_expand_timeout (NemoTreeViewDragDest *dest) { if (dest->details->expand_id) { g_source_remove (dest->details->expand_id); dest->details->expand_id = 0; } } static gboolean highlight_draw (GtkWidget *widget, cairo_t *cr, gpointer data) { GdkWindow *bin_window; int width; int height; GtkStyleContext *style; /* FIXMEchpe: is bin window right here??? */ bin_window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget)); width = gdk_window_get_width (bin_window); height = gdk_window_get_height (bin_window); style = gtk_widget_get_style_context (widget); gtk_style_context_save (style); gtk_style_context_add_class (style, "treeview-drop-indicator"); gtk_render_focus (style, cr, 0, 0, width, height); gtk_style_context_restore (style); return FALSE; } static void set_widget_highlight (NemoTreeViewDragDest *dest, gboolean highlight) { if (!highlight && dest->details->highlight_id) { g_signal_handler_disconnect (dest->details->tree_view, dest->details->highlight_id); dest->details->highlight_id = 0; gtk_widget_queue_draw (GTK_WIDGET (dest->details->tree_view)); } if (highlight && !dest->details->highlight_id) { dest->details->highlight_id = g_signal_connect_object (dest->details->tree_view, "draw", G_CALLBACK (highlight_draw), dest, 0); gtk_widget_queue_draw (GTK_WIDGET (dest->details->tree_view)); } } static void set_drag_dest_row (NemoTreeViewDragDest *dest, GtkTreePath *path) { if (path) { set_widget_highlight (dest, FALSE); gtk_tree_view_set_drag_dest_row (dest->details->tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); } else { set_widget_highlight (dest, TRUE); gtk_tree_view_set_drag_dest_row (dest->details->tree_view, NULL, 0); } } static void clear_drag_dest_row (NemoTreeViewDragDest *dest) { gtk_tree_view_set_drag_dest_row (dest->details->tree_view, NULL, 0); set_widget_highlight (dest, FALSE); } static gboolean get_drag_data (NemoTreeViewDragDest *dest, GdkDragContext *context, guint32 time) { GdkAtom target; target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view), context, NULL); if (target == GDK_NONE) { return FALSE; } if (target == gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE) && !dest->details->drop_occurred) { dest->details->drag_type = NEMO_ICON_DND_XDNDDIRECTSAVE; dest->details->have_drag_data = TRUE; return TRUE; } gtk_drag_get_data (GTK_WIDGET (dest->details->tree_view), context, target, time); return TRUE; } static void free_drag_data (NemoTreeViewDragDest *dest) { dest->details->have_drag_data = FALSE; if (dest->details->drag_data) { gtk_selection_data_free (dest->details->drag_data); dest->details->drag_data = NULL; } if (dest->details->drag_list) { nemo_drag_destroy_selection_list (dest->details->drag_list); dest->details->drag_list = NULL; } g_clear_pointer (&dest->details->direct_save_uri, g_free); g_clear_pointer (&dest->details->desktop_dnd_source_fs, g_free); dest->details->desktop_dnd_can_delete_source = FALSE; } static char * get_root_uri (NemoTreeViewDragDest *dest) { char *uri; g_signal_emit (dest, signals[GET_ROOT_URI], 0, &uri); return uri; } static NemoFile * file_for_path (NemoTreeViewDragDest *dest, GtkTreePath *path) { NemoFile *file; char *uri; if (path) { g_signal_emit (dest, signals[GET_FILE_FOR_PATH], 0, path, &file); } else { uri = get_root_uri (dest); file = NULL; if (uri != NULL) { file = nemo_file_get_by_uri (uri); } g_free (uri); } return file; } static GtkTreePath * get_drop_path (NemoTreeViewDragDest *dest, GtkTreePath *path) { NemoFile *file; GtkTreePath *ret; if (!path || !dest->details->have_drag_data) { return NULL; } ret = gtk_tree_path_copy (path); file = file_for_path (dest, ret); /* Go up the tree until we find a file that can accept a drop */ while (file == NULL /* dummy row */ || !nemo_drag_can_accept_info (file, dest->details->drag_type, dest->details->drag_list)) { if (gtk_tree_path_get_depth (ret) == 1) { gtk_tree_path_free (ret); ret = NULL; break; } else { gtk_tree_path_up (ret); nemo_file_unref (file); file = file_for_path (dest, ret); } } nemo_file_unref (file); return ret; } static char * get_drop_target_uri_for_path (NemoTreeViewDragDest *dest, GtkTreePath *path) { NemoFile *file; char *target; file = file_for_path (dest, path); if (file == NULL) { return NULL; } target = nemo_file_get_drop_target_uri (file); nemo_file_unref (file); return target; } static guint get_drop_action (NemoTreeViewDragDest *dest, GdkDragContext *context, GtkTreePath *path) { char *drop_target; int action; if (!dest->details->have_drag_data || (dest->details->drag_type == NEMO_ICON_DND_GNOME_ICON_LIST && dest->details->drag_list == NULL)) { return 0; } switch (dest->details->drag_type) { case NEMO_ICON_DND_GNOME_ICON_LIST : drop_target = get_drop_target_uri_for_path (dest, path); if (!drop_target) { return 0; } nemo_drag_default_drop_action_for_icons (context, drop_target, dest->details->drag_list, &action, &dest->details->desktop_dnd_source_fs, &dest->details->desktop_dnd_can_delete_source); g_free (drop_target); return action; case NEMO_ICON_DND_NETSCAPE_URL: drop_target = get_drop_target_uri_for_path (dest, path); if (drop_target == NULL) { return 0; } action = nemo_drag_default_drop_action_for_netscape_url (context); g_free (drop_target); return action; case NEMO_ICON_DND_URI_LIST : drop_target = get_drop_target_uri_for_path (dest, path); if (drop_target == NULL) { return 0; } g_free (drop_target); return gdk_drag_context_get_suggested_action (context); case NEMO_ICON_DND_TEXT: case NEMO_ICON_DND_RAW: case NEMO_ICON_DND_XDNDDIRECTSAVE: return GDK_ACTION_COPY; } return 0; } static gboolean drag_motion_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, guint32 time, gpointer data) { NemoTreeViewDragDest *dest; GtkTreePath *path; GtkTreePath *drop_path, *old_drop_path; GtkTreeModel *model; GtkTreeIter drop_iter; GtkTreeViewDropPosition pos; GdkWindow *bin_window; guint action; gboolean res = TRUE; dest = NEMO_TREE_VIEW_DRAG_DEST (data); gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), x, y, &path, &pos); if (!dest->details->have_drag_data) { res = get_drag_data (dest, context, time); } if (!res) { return FALSE; } drop_path = get_drop_path (dest, path); action = 0; bin_window = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget)); if (bin_window != NULL) { int bin_x, bin_y; gdk_window_get_position (bin_window, &bin_x, &bin_y); if (bin_y <= y) { /* ignore drags on the header */ action = get_drop_action (dest, context, drop_path); } } gtk_tree_view_get_drag_dest_row (GTK_TREE_VIEW (widget), &old_drop_path, NULL); if (action) { set_drag_dest_row (dest, drop_path); model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); if (drop_path == NULL || (old_drop_path != NULL && gtk_tree_path_compare (old_drop_path, drop_path) != 0)) { remove_expand_timeout (dest); } if (dest->details->expand_id == 0 && drop_path != NULL) { gtk_tree_model_get_iter (model, &drop_iter, drop_path); if (gtk_tree_model_iter_has_child (model, &drop_iter)) { dest->details->expand_id = g_timeout_add_seconds (HOVER_EXPAND_TIMEOUT, expand_timeout, dest->details->tree_view); } } } else { clear_drag_dest_row (dest); remove_expand_timeout (dest); } if (path) { gtk_tree_path_free (path); } if (drop_path) { gtk_tree_path_free (drop_path); } if (old_drop_path) { gtk_tree_path_free (old_drop_path); } if (dest->details->scroll_id == 0) { dest->details->scroll_id = g_timeout_add (150, scroll_timeout, dest->details->tree_view); } gdk_drag_status (context, action, time); return TRUE; } static void drag_leave_callback (GtkWidget *widget, GdkDragContext *context, guint32 time, gpointer data) { NemoTreeViewDragDest *dest; dest = NEMO_TREE_VIEW_DRAG_DEST (data); clear_drag_dest_row (dest); free_drag_data (dest); remove_scroll_timeout (dest); remove_expand_timeout (dest); } static char * get_drop_target_uri_at_pos (NemoTreeViewDragDest *dest, int x, int y) { char *drop_target; GtkTreePath *path; GtkTreePath *drop_path; GtkTreeViewDropPosition pos; gtk_tree_view_get_dest_row_at_pos (dest->details->tree_view, x, y, &path, &pos); drop_path = get_drop_path (dest, path); drop_target = get_drop_target_uri_for_path (dest, drop_path); if (path != NULL) { gtk_tree_path_free (path); } if (drop_path != NULL) { gtk_tree_path_free (drop_path); } return drop_target; } static void receive_uris (NemoTreeViewDragDest *dest, GdkDragContext *context, GList *source_uris, int x, int y) { char *drop_target; GdkDragAction action, real_action; drop_target = get_drop_target_uri_at_pos (dest, x, y); g_assert (drop_target != NULL); real_action = gdk_drag_context_get_selected_action (context); if (real_action == GDK_ACTION_ASK) { if (nemo_drag_selection_includes_special_link (dest->details->drag_list)) { /* We only want to move the trash */ action = GDK_ACTION_MOVE; } else { action = GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK; } real_action = nemo_drag_drop_action_ask (GTK_WIDGET (dest->details->tree_view), action); } if (real_action > 0) { if (!nemo_drag_uris_local (drop_target, source_uris) || real_action != GDK_ACTION_MOVE) { g_signal_emit (dest, signals[MOVE_COPY_ITEMS], 0, source_uris, drop_target, real_action, x, y); } } g_free (drop_target); } static void receive_dropped_icons (NemoTreeViewDragDest *dest, GdkDragContext *context, int x, int y) { GList *source_uris; GList *l; /* FIXME: ignore local only moves */ if (!dest->details->drag_list) { return; } source_uris = NULL; for (l = dest->details->drag_list; l != NULL; l = l->next) { source_uris = g_list_prepend (source_uris, ((NemoDragSelectionItem *)l->data)->uri); } source_uris = g_list_reverse (source_uris); receive_uris (dest, context, source_uris, x, y); g_list_free (source_uris); } static void receive_dropped_uri_list (NemoTreeViewDragDest *dest, GdkDragContext *context, int x, int y) { char *drop_target; if (!dest->details->drag_data) { return; } drop_target = get_drop_target_uri_at_pos (dest, x, y); g_assert (drop_target != NULL); g_signal_emit (dest, signals[HANDLE_URI_LIST], 0, (char*) gtk_selection_data_get_data (dest->details->drag_data), drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } static void receive_dropped_text (NemoTreeViewDragDest *dest, GdkDragContext *context, int x, int y) { char *drop_target; guchar *text; if (!dest->details->drag_data) { return; } drop_target = get_drop_target_uri_at_pos (dest, x, y); g_assert (drop_target != NULL); text = gtk_selection_data_get_text (dest->details->drag_data); g_signal_emit (dest, signals[HANDLE_TEXT], 0, (char *) text, drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (text); g_free (drop_target); } static void receive_dropped_raw (NemoTreeViewDragDest *dest, const char *raw_data, int length, GdkDragContext *context, int x, int y) { char *drop_target; if (!dest->details->drag_data) { return; } drop_target = get_drop_target_uri_at_pos (dest, x, y); g_assert (drop_target != NULL); g_signal_emit (dest, signals[HANDLE_RAW], 0, raw_data, length, drop_target, dest->details->direct_save_uri, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } static void receive_dropped_netscape_url (NemoTreeViewDragDest *dest, GdkDragContext *context, int x, int y) { char *drop_target; if (!dest->details->drag_data) { return; } drop_target = get_drop_target_uri_at_pos (dest, x, y); g_assert (drop_target != NULL); g_signal_emit (dest, signals[HANDLE_NETSCAPE_URL], 0, (char*) gtk_selection_data_get_data (dest->details->drag_data), drop_target, gdk_drag_context_get_selected_action (context), x, y); g_free (drop_target); } static gboolean receive_xds (NemoTreeViewDragDest *dest, GtkWidget *widget, guint32 time, GdkDragContext *context, int x, int y) { GFile *location; const guchar *selection_data; gint selection_format; gint selection_length; selection_data = gtk_selection_data_get_data (dest->details->drag_data); selection_format = gtk_selection_data_get_format (dest->details->drag_data); selection_length = gtk_selection_data_get_length (dest->details->drag_data); if (selection_format == 8 && selection_length == 1 && selection_data[0] == 'F') { gtk_drag_get_data (widget, context, gdk_atom_intern (NEMO_ICON_DND_RAW_TYPE, FALSE), time); return FALSE; } else if (selection_format == 8 && selection_length == 1 && selection_data[0] == 'S') { g_assert (dest->details->direct_save_uri != NULL); location = g_file_new_for_uri (dest->details->direct_save_uri); nemo_file_changes_queue_file_added (location); nemo_file_changes_consume_changes (TRUE); g_object_unref (location); } return TRUE; } static gboolean drag_data_received_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, GtkSelectionData *selection_data, guint info, guint32 time, gpointer data) { NemoTreeViewDragDest *dest; const gchar *tmp; int length; gboolean success, finished; dest = NEMO_TREE_VIEW_DRAG_DEST (data); if (!dest->details->have_drag_data) { dest->details->have_drag_data = TRUE; dest->details->drag_type = info; dest->details->drag_data = gtk_selection_data_copy (selection_data); if (info == NEMO_ICON_DND_GNOME_ICON_LIST) { dest->details->drag_list = nemo_drag_build_selection_list (selection_data); } } if (dest->details->drop_occurred) { success = FALSE; finished = TRUE; switch (info) { case NEMO_ICON_DND_GNOME_ICON_LIST : receive_dropped_icons (dest, context, x, y); success = TRUE; break; case NEMO_ICON_DND_NETSCAPE_URL : receive_dropped_netscape_url (dest, context, x, y); success = TRUE; break; case NEMO_ICON_DND_URI_LIST : receive_dropped_uri_list (dest, context, x, y); success = TRUE; break; case NEMO_ICON_DND_TEXT: receive_dropped_text (dest, context, x, y); success = TRUE; break; case NEMO_ICON_DND_RAW: length = gtk_selection_data_get_length (selection_data); tmp = (const gchar *) gtk_selection_data_get_data (selection_data); receive_dropped_raw (dest, tmp, length, context, x, y); success = TRUE; break; case NEMO_ICON_DND_XDNDDIRECTSAVE: finished = receive_xds (dest, widget, time, context, x, y); success = TRUE; break; } if (finished) { dest->details->drop_occurred = FALSE; free_drag_data (dest); gtk_drag_finish (context, success, FALSE, time); } } /* appease GtkTreeView by preventing its drag_data_receive * from being called */ g_signal_stop_emission_by_name (dest->details->tree_view, "drag_data_received"); return TRUE; } static char * get_direct_save_filename (GdkDragContext *context) { guchar *prop_text; gint prop_len; if (!gdk_property_get (gdk_drag_context_get_source_window (context), gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE), gdk_atom_intern ("text/plain", FALSE), 0, 1024, FALSE, NULL, NULL, &prop_len, &prop_text)) { return NULL; } /* Zero-terminate the string */ prop_text = g_realloc (prop_text, prop_len + 1); prop_text[prop_len] = '\0'; /* Verify that the file name provided by the source is valid */ if (*prop_text == '\0' || strchr ((const gchar *) prop_text, G_DIR_SEPARATOR) != NULL) { DEBUG ("Invalid filename provided by XDS drag site"); g_free (prop_text); return NULL; } return (gchar *) prop_text; } static gboolean set_direct_save_uri (NemoTreeViewDragDest *dest, GdkDragContext *context, int x, int y) { GFile *base, *child; char *drop_uri; char *filename, *uri; g_assert (dest->details->direct_save_uri == NULL); uri = NULL; drop_uri = get_drop_target_uri_at_pos (dest, x, y); if (drop_uri != NULL) { filename = get_direct_save_filename (context); if (filename != NULL) { /* Resolve relative path */ base = g_file_new_for_uri (drop_uri); child = g_file_get_child (base, filename); uri = g_file_get_uri (child); g_object_unref (base); g_object_unref (child); /* Change the property */ gdk_property_change (gdk_drag_context_get_source_window (context), gdk_atom_intern (NEMO_ICON_DND_XDNDDIRECTSAVE_TYPE, FALSE), gdk_atom_intern ("text/plain", FALSE), 8, GDK_PROP_MODE_REPLACE, (const guchar *) uri, strlen (uri)); dest->details->direct_save_uri = uri; } else { DEBUG ("Invalid filename provided by XDS drag site"); } } else { DEBUG ("Could not retrieve XDS drop destination"); } return uri != NULL; } static gboolean drag_drop_callback (GtkWidget *widget, GdkDragContext *context, int x, int y, guint32 time, gpointer data) { NemoTreeViewDragDest *dest; guint info; GdkAtom target; dest = NEMO_TREE_VIEW_DRAG_DEST (data); target = gtk_drag_dest_find_target (GTK_WIDGET (dest->details->tree_view), context, NULL); if (target == GDK_NONE) { return FALSE; } info = dest->details->drag_type; if (info == NEMO_ICON_DND_XDNDDIRECTSAVE) { /* We need to set this or get_drop_path will fail, and it was unset by drag_leave_callback */ dest->details->have_drag_data = TRUE; if (!set_direct_save_uri (dest, context, x, y)) { return FALSE; } dest->details->have_drag_data = FALSE; } dest->details->drop_occurred = TRUE; get_drag_data (dest, context, time); remove_scroll_timeout (dest); remove_expand_timeout (dest); clear_drag_dest_row (dest); return TRUE; } static void tree_view_weak_notify (gpointer user_data, GObject *object) { NemoTreeViewDragDest *dest; dest = NEMO_TREE_VIEW_DRAG_DEST (user_data); remove_scroll_timeout (dest); remove_expand_timeout (dest); dest->details->tree_view = NULL; } static void nemo_tree_view_drag_dest_dispose (GObject *object) { NemoTreeViewDragDest *dest; dest = NEMO_TREE_VIEW_DRAG_DEST (object); if (dest->details->tree_view) { g_object_weak_unref (G_OBJECT (dest->details->tree_view), tree_view_weak_notify, dest); } remove_scroll_timeout (dest); remove_expand_timeout (dest); G_OBJECT_CLASS (nemo_tree_view_drag_dest_parent_class)->dispose (object); } static void nemo_tree_view_drag_dest_finalize (GObject *object) { NemoTreeViewDragDest *dest; dest = NEMO_TREE_VIEW_DRAG_DEST (object); free_drag_data (dest); G_OBJECT_CLASS (nemo_tree_view_drag_dest_parent_class)->finalize (object); } static void nemo_tree_view_drag_dest_init (NemoTreeViewDragDest *dest) { dest->details = G_TYPE_INSTANCE_GET_PRIVATE (dest, NEMO_TYPE_TREE_VIEW_DRAG_DEST, NemoTreeViewDragDestDetails); } static void nemo_tree_view_drag_dest_class_init (NemoTreeViewDragDestClass *class) { GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (class); gobject_class->dispose = nemo_tree_view_drag_dest_dispose; gobject_class->finalize = nemo_tree_view_drag_dest_finalize; g_type_class_add_private (class, sizeof (NemoTreeViewDragDestDetails)); signals[GET_ROOT_URI] = g_signal_new ("get_root_uri", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, get_root_uri), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_STRING, 0); signals[GET_FILE_FOR_PATH] = g_signal_new ("get_file_for_path", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, get_file_for_path), NULL, NULL, g_cclosure_marshal_generic, NEMO_TYPE_FILE, 1, GTK_TYPE_TREE_PATH); signals[MOVE_COPY_ITEMS] = g_signal_new ("move_copy_items", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, move_copy_items), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_NETSCAPE_URL] = g_signal_new ("handle_netscape_url", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, handle_netscape_url), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_URI_LIST] = g_signal_new ("handle_uri_list", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, handle_uri_list), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_TEXT] = g_signal_new ("handle_text", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, handle_text), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_RAW] = g_signal_new ("handle_raw", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoTreeViewDragDestClass, handle_raw), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 7, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); } NemoTreeViewDragDest * nemo_tree_view_drag_dest_new (GtkTreeView *tree_view) { NemoTreeViewDragDest *dest; GtkTargetList *targets; dest = g_object_new (NEMO_TYPE_TREE_VIEW_DRAG_DEST, NULL); dest->details->tree_view = tree_view; dest->details->desktop_dnd_source_fs = NULL; dest->details->desktop_dnd_can_delete_source = FALSE; g_object_weak_ref (G_OBJECT (dest->details->tree_view), tree_view_weak_notify, dest); gtk_drag_dest_set (GTK_WIDGET (tree_view), 0, drag_types, G_N_ELEMENTS (drag_types), GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK); targets = gtk_drag_dest_get_target_list (GTK_WIDGET (tree_view)); gtk_target_list_add_text_targets (targets, NEMO_ICON_DND_TEXT); g_signal_connect_object (tree_view, "drag_motion", G_CALLBACK (drag_motion_callback), dest, 0); g_signal_connect_object (tree_view, "drag_leave", G_CALLBACK (drag_leave_callback), dest, 0); g_signal_connect_object (tree_view, "drag_drop", G_CALLBACK (drag_drop_callback), dest, 0); g_signal_connect_object (tree_view, "drag_data_received", G_CALLBACK (drag_data_received_callback), dest, 0); return dest; } nemo-3.6.5/libnemo-private/nemo-link.c0000664000175000017500000003340513215733314016550 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-link.c: .desktop link files. Copyright (C) 2001 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the historicalied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Jonathan Blandford Alexander Larsson */ #include #include "nemo-link.h" #include "nemo-directory-notify.h" #include "nemo-directory.h" #include "nemo-file-utilities.h" #include "nemo-file.h" #include "nemo-program-choosing.h" #include "nemo-icon-names.h" #include #include #include #include #include #define MAIN_GROUP "Desktop Entry" #define NEMO_LINK_GENERIC_TAG "Link" #define NEMO_LINK_TRASH_TAG "X-nemo-trash" #define NEMO_LINK_MOUNT_TAG "FSDevice" #define NEMO_LINK_HOME_TAG "X-nemo-home" static gboolean is_link_mime_type (const char *mime_type) { if (mime_type != NULL && g_ascii_strcasecmp (mime_type, "application/x-desktop") == 0) { return TRUE; } return FALSE; } static gboolean is_local_file_a_link (const char *uri) { gboolean link; GFile *file; GFileInfo *info; GError *error; error = NULL; link = FALSE; file = g_file_new_for_uri (uri); info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, 0, NULL, &error); if (info) { link = is_link_mime_type (g_file_info_get_content_type (info)); g_object_unref (info); } else { g_warning ("Error getting info: %s\n", error->message); g_error_free (error); } g_object_unref (file); return link; } static gboolean _g_key_file_load_from_gfile (GKeyFile *key_file, GFile *file, GKeyFileFlags flags, GError **error) { char *data; gsize len; gboolean res; if (!g_file_load_contents (file, NULL, &data, &len, NULL, error)) { return FALSE; } res = g_key_file_load_from_data (key_file, data, len, flags, error); g_free (data); return res; } static gboolean _g_key_file_save_to_gfile (GKeyFile *key_file, GFile *file, GError **error) { char *data; gsize len; data = g_key_file_to_data (key_file, &len, error); if (data == NULL) { return FALSE; } if (!g_file_replace_contents (file, data, len, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, error)) { g_free (data); return FALSE; } g_free (data); return TRUE; } static GKeyFile * _g_key_file_new_from_uri (const char *uri, GKeyFileFlags flags, GError **error) { GKeyFile *key_file; GFile *file; file = g_file_new_for_uri (uri); key_file = g_key_file_new (); if (!_g_key_file_load_from_gfile (key_file, file, flags, error)) { g_key_file_free (key_file); key_file = NULL; } g_object_unref (file); return key_file; } static char * slurp_key_string (const char *uri, const char *keyname, gboolean localize) { GKeyFile *key_file; char *result; key_file = _g_key_file_new_from_uri (uri, G_KEY_FILE_NONE, NULL); if (key_file == NULL) { return NULL; } if (localize) { result = g_key_file_get_locale_string (key_file, MAIN_GROUP, keyname, NULL, NULL); } else { result = g_key_file_get_string (key_file, MAIN_GROUP, keyname, NULL); } g_key_file_free (key_file); return result; } gboolean nemo_link_local_create (const char *directory_uri, const char *base_name, const char *display_name, const char *image, const char *target_uri, const GdkPoint *point, int monitor, gboolean unique_filename) { char *real_directory_uri; char *uri, *contents; GFile *file; GList dummy_list; NemoFileChangesQueuePosition item; g_return_val_if_fail (directory_uri != NULL, FALSE); g_return_val_if_fail (base_name != NULL, FALSE); g_return_val_if_fail (display_name != NULL, FALSE); g_return_val_if_fail (target_uri != NULL, FALSE); if (eel_uri_is_trash (directory_uri) || eel_uri_is_search (directory_uri)) { return FALSE; } if (eel_uri_is_desktop (directory_uri)) { real_directory_uri = nemo_get_desktop_directory_uri (); } else { real_directory_uri = g_strdup (directory_uri); } if (unique_filename) { uri = nemo_ensure_unique_file_name (real_directory_uri, base_name, ".desktop"); if (uri == NULL) { g_free (real_directory_uri); return FALSE; } file = g_file_new_for_uri (uri); g_free (uri); } else { char *link_name; GFile *dir; link_name = g_strdup_printf ("%s.desktop", base_name); /* replace '/' with '-', just in case */ g_strdelimit (link_name, "/", '-'); dir = g_file_new_for_uri (directory_uri); file = g_file_get_child (dir, link_name); g_free (link_name); g_object_unref (dir); } g_free (real_directory_uri); contents = g_strdup_printf ("[Desktop Entry]\n" "Encoding=UTF-8\n" "Name=%s\n" "Type=Link\n" "URL=%s\n" "%s%s\n", display_name, target_uri, image != NULL ? "Icon=" : "", image != NULL ? image : ""); if (!g_file_replace_contents (file, contents, strlen (contents), NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, NULL)) { g_free (contents); g_object_unref (file); return FALSE; } g_free (contents); dummy_list.data = file; dummy_list.next = NULL; dummy_list.prev = NULL; nemo_directory_notify_files_added (&dummy_list); if (point != NULL) { item.location = file; item.set = TRUE; item.monitor = monitor; item.point.x = point->x; item.point.y = point->y; item.screen = 0; dummy_list.data = &item; dummy_list.next = NULL; dummy_list.prev = NULL; nemo_directory_schedule_position_set (&dummy_list); } g_object_unref (file); return TRUE; } static const char * get_language (void) { const char * const *langs_pointer; int i; langs_pointer = g_get_language_names (); for (i = 0; langs_pointer[i] != NULL; i++) { /* find first without encoding */ if (strchr (langs_pointer[i], '.') == NULL) { return langs_pointer[i]; } } return NULL; } static gboolean nemo_link_local_set_key (const char *uri, const char *key, const char *value, gboolean localize) { gboolean success; GKeyFile *key_file; GFile *file; file = g_file_new_for_uri (uri); key_file = g_key_file_new (); if (!_g_key_file_load_from_gfile (key_file, file, G_KEY_FILE_KEEP_COMMENTS, NULL)) { g_key_file_free (key_file); g_object_unref (file); return FALSE; } if (localize) { g_key_file_set_locale_string (key_file, MAIN_GROUP, key, get_language (), value); } else { g_key_file_set_string (key_file, MAIN_GROUP, key, value); } success = _g_key_file_save_to_gfile (key_file, file, NULL); g_key_file_free (key_file); g_object_unref (file); return success; } gboolean nemo_link_local_set_text (const char *uri, const char *text) { return nemo_link_local_set_key (uri, "Name", text, TRUE); } gboolean nemo_link_local_set_icon (const char *uri, const char *icon) { return nemo_link_local_set_key (uri, "Icon", icon, FALSE); } char * nemo_link_local_get_text (const char *path) { return slurp_key_string (path, "Name", TRUE); } static char * nemo_link_get_link_uri_from_desktop (GKeyFile *key_file, const char *desktop_file_uri) { GFile *file, *parent; char *type; char *retval; char *scheme; retval = NULL; type = g_key_file_get_string (key_file, MAIN_GROUP, "Type", NULL); if (type == NULL) { return NULL; } if (strcmp (type, "URL") == 0) { /* Some old broken desktop files use this nonstandard feature, we need handle it though */ retval = g_key_file_get_string (key_file, MAIN_GROUP, "Exec", NULL); } else if ((strcmp (type, NEMO_LINK_GENERIC_TAG) == 0) || (strcmp (type, NEMO_LINK_MOUNT_TAG) == 0) || (strcmp (type, NEMO_LINK_TRASH_TAG) == 0) || (strcmp (type, NEMO_LINK_HOME_TAG) == 0)) { retval = g_key_file_get_string (key_file, MAIN_GROUP, "URL", NULL); } g_free (type); if (retval != NULL && desktop_file_uri != NULL) { /* Handle local file names. * Ideally, we'd be able to use * g_file_parse_name(), but it does not know how to resolve * relative file names, since the base directory is unknown. */ scheme = g_uri_parse_scheme (retval); if (scheme == NULL) { file = g_file_new_for_uri (desktop_file_uri); parent = g_file_get_parent (file); g_object_unref (file); if (parent != NULL) { file = g_file_resolve_relative_path (parent, retval); g_free (retval); retval = g_file_get_uri (file); g_object_unref (file); g_object_unref (parent); } } g_free (scheme); } return retval; } static char * nemo_link_get_link_name_from_desktop (GKeyFile *key_file) { return g_key_file_get_locale_string (key_file, MAIN_GROUP, "Name", NULL, NULL); } static GIcon * nemo_link_get_link_icon_from_desktop (GKeyFile *key_file) { char *icon_str, *p, *type = NULL; GFile *file; GIcon *icon; /* Look at the Icon: key */ icon_str = g_key_file_get_string (key_file, MAIN_GROUP, "Icon", NULL); /* if it's an absolute path, return a GFileIcon for that path */ if (icon_str != NULL && g_path_is_absolute (icon_str)) { file = g_file_new_for_path (icon_str); icon = g_file_icon_new (file); g_object_unref (file); goto out; } type = g_key_file_get_string (key_file, MAIN_GROUP, "Type", NULL); if (icon_str == NULL) { if (g_strcmp0 (type, "Application") == 0) { icon_str = g_strdup ("application-x-executable"); } else if (g_strcmp0 (type, "FSDevice") == 0) { icon_str = g_strdup ("drive-harddisk"); } else if (g_strcmp0 (type, "Directory") == 0) { icon_str = g_strdup (NEMO_ICON_FOLDER); } else if (g_strcmp0 (type, "Service") == 0 || g_strcmp0 (type, "ServiceType") == 0) { icon_str = g_strdup ("folder-remote"); } else { icon_str = g_strdup ("text-x-preview"); } } else { /* Strip out any extension on non-filename icons. Old desktop files may have this */ p = strchr (icon_str, '.'); /* Only strip known icon extensions */ if ((p != NULL) && ((g_ascii_strcasecmp (p, ".png") == 0) || (g_ascii_strcasecmp (p, ".svn") == 0) || (g_ascii_strcasecmp (p, ".jpg") == 0) || (g_ascii_strcasecmp (p, ".xpm") == 0) || (g_ascii_strcasecmp (p, ".bmp") == 0) || (g_ascii_strcasecmp (p, ".jpeg") == 0))) { *p = 0; } } icon = g_themed_icon_new (icon_str); /* apply a link emblem if it's a link */ if (g_strcmp0 (type, "Link") == 0) { GIcon *emblemed, *emblem_icon; GEmblem *emblem; emblem_icon = g_themed_icon_new ("emblem-symbolic-link"); emblem = g_emblem_new (emblem_icon); emblemed = g_emblemed_icon_new (icon, emblem); g_object_unref (icon); g_object_unref (emblem_icon); g_object_unref (emblem); icon = emblemed; } out: g_free (icon_str); g_free (type); return icon; } char * nemo_link_local_get_link_uri (const char *uri) { GKeyFile *key_file; char *retval; if (!is_local_file_a_link (uri)) { return NULL; } key_file = _g_key_file_new_from_uri (uri, G_KEY_FILE_NONE, NULL); if (key_file == NULL) { return NULL; } retval = nemo_link_get_link_uri_from_desktop (key_file, uri); g_key_file_free (key_file); return retval; } static gboolean string_array_contains (char **array, const char *str) { char **p; if (!array) return FALSE; for (p = array; *p; p++) if (g_ascii_strcasecmp (*p, str) == 0) { return TRUE; } return FALSE; } static const gchar * get_session (void) { const gchar * session; session = g_getenv ("XDG_CURRENT_DESKTOP"); if (session == NULL || session[0] == 0) { /* historic behavior */ session = "GNOME"; } return session; } void nemo_link_get_link_info_given_file_contents (const char *file_contents, int link_file_size, const char *file_uri, char **uri, char **name, GIcon **icon, gboolean *is_launcher, gboolean *is_foreign) { GKeyFile *key_file; char *type; char **only_show_in; char **not_show_in; const gchar *session; session = get_session (); key_file = g_key_file_new (); if (!g_key_file_load_from_data (key_file, file_contents, link_file_size, G_KEY_FILE_NONE, NULL)) { g_key_file_free (key_file); return; } *uri = nemo_link_get_link_uri_from_desktop (key_file, file_uri); *name = nemo_link_get_link_name_from_desktop (key_file); *icon = nemo_link_get_link_icon_from_desktop (key_file); *is_launcher = FALSE; type = g_key_file_get_string (key_file, MAIN_GROUP, "Type", NULL); if (g_strcmp0 (type, "Application") == 0 && g_key_file_has_key (key_file, MAIN_GROUP, "Exec", NULL)) { *is_launcher = TRUE; } g_free (type); *is_foreign = FALSE; only_show_in = g_key_file_get_string_list (key_file, MAIN_GROUP, "OnlyShowIn", NULL, NULL); if (session && only_show_in && !(string_array_contains (only_show_in, session) || string_array_contains (only_show_in, "GNOME"))) { *is_foreign = TRUE; } g_strfreev (only_show_in); not_show_in = g_key_file_get_string_list (key_file, MAIN_GROUP, "NotShowIn", NULL, NULL); if (session && not_show_in && string_array_contains (not_show_in, session)) { *is_foreign = TRUE; } g_strfreev (not_show_in); g_key_file_free (key_file); } nemo-3.6.5/libnemo-private/nemo-thumbnails.h0000664000175000017500000000375213215733314017770 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-thumbnails.h: Thumbnail code for icon factory. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Andy Hertzfeld */ #ifndef NEMO_THUMBNAILS_H #define NEMO_THUMBNAILS_H #include #include /* Cool-off period between last file modification time and thumbnail creation */ #define THUMBNAIL_CREATION_DELAY_SECS 3 /* Returns NULL if there's no thumbnail yet. */ void nemo_create_thumbnail (NemoFile *file, gint throttle_count); gboolean nemo_can_thumbnail (NemoFile *file); gboolean nemo_can_thumbnail_internally (NemoFile *file); gboolean nemo_thumbnail_is_mimetype_limited_by_size (const char *mime_type); void nemo_thumbnail_frame_image (GdkPixbuf **pixbuf); void nemo_thumbnail_pad_top_and_bottom (GdkPixbuf **pixbuf, gint extra_height); /* Queue handling: */ void nemo_thumbnail_remove_from_queue (const char *file_uri); void nemo_thumbnail_prioritize (const char *file_uri); gboolean nemo_thumbnail_factory_check_status (void); #endif /* NEMO_THUMBNAILS_H */ nemo-3.6.5/libnemo-private/nemo-debug.c0000664000175000017500000000761613215733314016706 0ustar fabiofabio/* * nemo-debug: debug loggers for nemo * * Copyright (C) 2007 Collabora Ltd. * Copyright (C) 2007 Nokia Corporation * Copyright (C) 2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Based on Empathy's empathy-debug. */ #include #include #include "nemo-debug.h" #include "nemo-file.h" #ifdef ENABLE_DEBUG static DebugFlags flags = 0; static gboolean initialized = FALSE; static GDebugKey keys[] = { { "Application", NEMO_DEBUG_APPLICATION }, { "Bookmarks", NEMO_DEBUG_BOOKMARKS }, { "DBus", NEMO_DEBUG_DBUS }, { "DirectoryView", NEMO_DEBUG_DIRECTORY_VIEW }, { "File", NEMO_DEBUG_FILE }, { "IconContainer", NEMO_DEBUG_ICON_CONTAINER }, { "IconView", NEMO_DEBUG_ICON_VIEW }, { "ListView", NEMO_DEBUG_LIST_VIEW }, { "Mime", NEMO_DEBUG_MIME }, { "Places", NEMO_DEBUG_PLACES }, { "Previewer", NEMO_DEBUG_PREVIEWER }, { "Smclient", NEMO_DEBUG_SMCLIENT }, { "Window", NEMO_DEBUG_WINDOW }, { "Undo", NEMO_DEBUG_UNDO }, { "Actions", NEMO_DEBUG_ACTIONS }, { "Desktop", NEMO_DEBUG_DESKTOP }, { 0, } }; static void nemo_debug_set_flags_from_env () { guint nkeys; const gchar *flags_string; for (nkeys = 0; keys[nkeys].value; nkeys++); flags_string = g_getenv ("NEMO_DEBUG"); if (flags_string) nemo_debug_set_flags (g_parse_debug_string (flags_string, keys, nkeys)); initialized = TRUE; } void nemo_debug_set_flags (DebugFlags new_flags) { flags |= new_flags; initialized = TRUE; } gboolean nemo_debug_flag_is_set (DebugFlags flag) { return flag & flags; } void nemo_debug (DebugFlags flag, const gchar *format, ...) { va_list args; va_start (args, format); nemo_debug_valist (flag, format, args); va_end (args); } void nemo_debug_valist (DebugFlags flag, const gchar *format, va_list args) { if (G_UNLIKELY(!initialized)) nemo_debug_set_flags_from_env (); if (flag & flags) g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args); } static void nemo_debug_files_valist (DebugFlags flag, GList *files, const gchar *format, va_list args) { NemoFile *file; GList *l; gchar *uri, *msg; if (G_UNLIKELY (!initialized)) nemo_debug_set_flags_from_env (); if (!(flag & flags)) return; msg = g_strdup_vprintf (format, args); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s:", msg); for (l = files; l != NULL; l = l->next) { file = l->data; uri = nemo_file_get_uri (file); if (nemo_file_is_gone (file)) { gchar *new_uri; /* Hack: this will create an invalid URI, but it's for * display purposes only. */ new_uri = g_strconcat (uri ? uri : "", " (gone)", NULL); g_free (uri); uri = new_uri; } g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, " %s", uri); g_free (uri); } g_free (msg); } void nemo_debug_files (DebugFlags flag, GList *files, const gchar *format, ...) { va_list args; va_start (args, format); nemo_debug_files_valist (flag, files, format, args); va_end (args); } #endif /* ENABLE_DEBUG */ nemo-3.6.5/libnemo-private/nemo-bookmark.h0000664000175000017500000001156313215733314017426 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-bookmark.h - implementation of individual bookmarks. * * Copyright (C) 1999, 2000 Eazel, Inc. * Copyright (C) 2011, Red Hat, Inc. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: John Sullivan * Cosimo Cecchi */ #ifndef NEMO_BOOKMARK_H #define NEMO_BOOKMARK_H #include #include typedef struct NemoBookmark NemoBookmark; #define NEMO_TYPE_BOOKMARK nemo_bookmark_get_type() #define NEMO_BOOKMARK(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_BOOKMARK, NemoBookmark)) #define NEMO_BOOKMARK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_BOOKMARK, NemoBookmarkClass)) #define NEMO_IS_BOOKMARK(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_BOOKMARK)) #define NEMO_IS_BOOKMARK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_BOOKMARK)) #define NEMO_BOOKMARK_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_BOOKMARK, NemoBookmarkClass)) typedef struct NemoBookmarkDetails NemoBookmarkDetails; struct NemoBookmark { GObject object; NemoBookmarkDetails *details; }; typedef struct { gchar *bookmark_name; gchar *icon_name; gchar *icon_uri; gchar **emblems; } NemoBookmarkMetadata; struct NemoBookmarkClass { GObjectClass parent_class; /* Signals that clients can connect to. */ /* The contents-changed signal is emitted when the bookmark's contents * (custom name or URI) changed. */ void (* contents_changed) (NemoBookmark *bookmark); gboolean (* location_mounted) (GFile *location); }; typedef struct NemoBookmarkClass NemoBookmarkClass; GType nemo_bookmark_get_type (void); NemoBookmark * nemo_bookmark_new (GFile *location, const char *custom_name, GIcon *icon, NemoBookmarkMetadata *md); NemoBookmark * nemo_bookmark_copy (NemoBookmark *bookmark); const char * nemo_bookmark_get_name (NemoBookmark *bookmark); GFile * nemo_bookmark_get_location (NemoBookmark *bookmark); char * nemo_bookmark_get_uri (NemoBookmark *bookmark); GIcon * nemo_bookmark_get_icon (NemoBookmark *bookmark); gboolean nemo_bookmark_get_has_custom_name (NemoBookmark *bookmark); void nemo_bookmark_set_custom_name (NemoBookmark *bookmark, const char *new_name); gboolean nemo_bookmark_uri_get_exists (NemoBookmark *bookmark); int nemo_bookmark_compare_with (gconstpointer a, gconstpointer b); int nemo_bookmark_compare_uris (gconstpointer a, gconstpointer b); void nemo_bookmark_set_scroll_pos (NemoBookmark *bookmark, const char *uri); char * nemo_bookmark_get_scroll_pos (NemoBookmark *bookmark); /* Helper functions for displaying bookmarks */ GtkWidget * nemo_bookmark_menu_item_new (NemoBookmark *bookmark); void nemo_bookmark_connect (NemoBookmark *bookmark); /* Bookmark metadata struct functions */ NemoBookmarkMetadata *nemo_bookmark_get_updated_metadata (NemoBookmark *bookmark); NemoBookmarkMetadata *nemo_bookmark_get_current_metadata (NemoBookmark *bookmark); gboolean nemo_bookmark_metadata_compare (NemoBookmarkMetadata *d1, NemoBookmarkMetadata *d2); NemoBookmarkMetadata *nemo_bookmark_metadata_new (void); NemoBookmarkMetadata *nemo_bookmark_metadata_copy (NemoBookmarkMetadata *meta); void nemo_bookmark_metadata_free (NemoBookmarkMetadata *metadata); #endif /* NEMO_BOOKMARK_H */ nemo-3.6.5/libnemo-private/nemo-monitor.c0000664000175000017500000001153713215733314017304 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-monitor.c: file and directory change monitoring for nemo Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Seth Nickell Darin Adler Alex Graveley */ #include #include "nemo-monitor.h" #include "nemo-file-changes-queue.h" #include "nemo-file-utilities.h" #include struct NemoMonitor { GFileMonitor *monitor; GVolumeMonitor *volume_monitor; GFile *location; }; gboolean nemo_monitor_active (void) { static gboolean tried_monitor = FALSE; static gboolean monitor_success; GFileMonitor *dir_monitor; GFile *file; if (tried_monitor == FALSE) { file = g_file_new_for_path (g_get_home_dir ()); dir_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); g_object_unref (file); monitor_success = (dir_monitor != NULL); if (dir_monitor) { g_object_unref (dir_monitor); } tried_monitor = TRUE; } return monitor_success; } static gboolean call_consume_changes_idle_id = 0; static gboolean call_consume_changes_idle_cb (gpointer not_used) { nemo_file_changes_consume_changes (TRUE); call_consume_changes_idle_id = 0; return FALSE; } static void schedule_call_consume_changes (void) { if (call_consume_changes_idle_id == 0) { call_consume_changes_idle_id = g_idle_add (call_consume_changes_idle_cb, NULL); } } static void mount_removed (GVolumeMonitor *volume_monitor, GMount *mount, gpointer user_data) { NemoMonitor *monitor = user_data; GFile *mount_location; mount_location = g_mount_get_root (mount); if (g_file_has_prefix (monitor->location, mount_location)) { nemo_file_changes_queue_file_removed (monitor->location); schedule_call_consume_changes (); } g_object_unref (mount_location); } static void dir_changed (GFileMonitor* monitor, GFile *child, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { char *uri, *to_uri; uri = g_file_get_uri (child); to_uri = NULL; if (other_file) { to_uri = g_file_get_uri (other_file); } switch (event_type) { default: case G_FILE_MONITOR_EVENT_CHANGED: /* ignore */ break; case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: nemo_file_changes_queue_file_changed (child); break; case G_FILE_MONITOR_EVENT_DELETED: nemo_file_changes_queue_file_removed (child); break; case G_FILE_MONITOR_EVENT_CREATED: nemo_file_changes_queue_file_added (child); break; case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: /* TODO: Do something */ break; case G_FILE_MONITOR_EVENT_UNMOUNTED: /* TODO: Do something */ break; } g_free (uri); g_free (to_uri); schedule_call_consume_changes (); } NemoMonitor * nemo_monitor_directory (GFile *location) { GFileMonitor *dir_monitor; NemoMonitor *ret; ret = g_new0 (NemoMonitor, 1); dir_monitor = g_file_monitor_directory (location, G_FILE_MONITOR_WATCH_MOUNTS, NULL, NULL); if (dir_monitor != NULL) { ret->monitor = dir_monitor; } else if (!g_file_is_native (location)) { ret->location = g_object_ref (location); ret->volume_monitor = g_volume_monitor_get (); } if (ret->monitor != NULL) { g_signal_connect (ret->monitor, "changed", G_CALLBACK (dir_changed), ret); } if (ret->volume_monitor != NULL) { g_signal_connect (ret->volume_monitor, "mount-removed", G_CALLBACK (mount_removed), ret); } /* We return a monitor even on failure, so we can avoid later trying again */ return ret; } void nemo_monitor_cancel (NemoMonitor *monitor) { if (monitor->monitor != NULL) { g_signal_handlers_disconnect_by_func (monitor->monitor, dir_changed, monitor); g_file_monitor_cancel (monitor->monitor); g_object_unref (monitor->monitor); } if (monitor->volume_monitor != NULL) { g_signal_handlers_disconnect_by_func (monitor->volume_monitor, mount_removed, monitor); g_object_unref (monitor->volume_monitor); } g_clear_object (&monitor->location); g_free (monitor); } nemo-3.6.5/libnemo-private/README0000664000175000017500000000067713215733314015400 0ustar fabiofabioREADME for nemo/libnemo-private This library, libnemo-private, is totally private to nemo. If you are writing a nemo component, you should not use this library or link with it. The code in here is internal to nemo and not available for public consumption. If you think that there is something interesting in this library that you would like to use in a third party component, please send mail to the nemo mailing list at: nemo-list@gnome.org nemo-3.6.5/libnemo-private/nemo-icon-dnd.h0000664000175000017500000000376213215733314017316 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-icon-dnd.h - Drag & drop handling for the icon container widget. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ettore Perazzoli , Darin Adler , Andy Hertzfeld */ #ifndef NEMO_ICON_DND_H #define NEMO_ICON_DND_H #include #include /* DnD-related information. */ typedef struct { /* inherited drag info context */ NemoDragInfo drag_info; gboolean highlighted; /* Shadow for the icons being dragged. */ EelCanvasItem *shadow; } NemoIconDndInfo; void nemo_icon_dnd_init (NemoIconContainer *container); void nemo_icon_dnd_fini (NemoIconContainer *container); void nemo_icon_dnd_begin_drag (NemoIconContainer *container, GdkDragAction actions, gint button, GdkEventMotion *event, int start_x, int start_y); void nemo_icon_dnd_end_drag (NemoIconContainer *container); #endif /* NEMO_ICON_DND_H */ nemo-3.6.5/libnemo-private/nemo-tree-view-drag-dest.h0000664000175000017500000000634113215733314021376 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 2002 Sun Microsystems, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Dave Camp */ /* nemo-tree-view-drag-dest.h: Handles drag and drop for treeviews which * contain a hierarchy of files */ #ifndef NEMO_TREE_VIEW_DRAG_DEST_H #define NEMO_TREE_VIEW_DRAG_DEST_H #include #include "nemo-file.h" G_BEGIN_DECLS #define NEMO_TYPE_TREE_VIEW_DRAG_DEST (nemo_tree_view_drag_dest_get_type ()) #define NEMO_TREE_VIEW_DRAG_DEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_TREE_VIEW_DRAG_DEST, NemoTreeViewDragDest)) #define NEMO_TREE_VIEW_DRAG_DEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_TREE_VIEW_DRAG_DEST, NemoTreeViewDragDestClass)) #define NEMO_IS_TREE_VIEW_DRAG_DEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_TREE_VIEW_DRAG_DEST)) #define NEMO_IS_TREE_VIEW_DRAG_DEST_CLASS(klass) (G_TYPE_CLASS_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_TREE_VIEW_DRAG_DEST)) typedef struct _NemoTreeViewDragDest NemoTreeViewDragDest; typedef struct _NemoTreeViewDragDestClass NemoTreeViewDragDestClass; typedef struct _NemoTreeViewDragDestDetails NemoTreeViewDragDestDetails; struct _NemoTreeViewDragDest { GObject parent; NemoTreeViewDragDestDetails *details; }; struct _NemoTreeViewDragDestClass { GObjectClass parent; char *(*get_root_uri) (NemoTreeViewDragDest *dest); NemoFile *(*get_file_for_path) (NemoTreeViewDragDest *dest, GtkTreePath *path); void (*move_copy_items) (NemoTreeViewDragDest *dest, const GList *item_uris, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_netscape_url) (NemoTreeViewDragDest *dest, const char *url, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_uri_list) (NemoTreeViewDragDest *dest, const char *uri_list, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_text) (NemoTreeViewDragDest *dest, const char *text, const char *target_uri, GdkDragAction action, int x, int y); void (* handle_raw) (NemoTreeViewDragDest *dest, char *raw_data, int length, const char *target_uri, const char *direct_save_uri, GdkDragAction action, int x, int y); }; GType nemo_tree_view_drag_dest_get_type (void); NemoTreeViewDragDest *nemo_tree_view_drag_dest_new (GtkTreeView *tree_view); G_END_DECLS #endif nemo-3.6.5/libnemo-private/nemo-search-engine-simple.h0000664000175000017500000000425713215733314021622 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Red Hat, Inc * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Alexander Larsson * */ #ifndef NEMO_SEARCH_ENGINE_SIMPLE_H #define NEMO_SEARCH_ENGINE_SIMPLE_H #include #define NEMO_TYPE_SEARCH_ENGINE_SIMPLE (nemo_search_engine_simple_get_type ()) #define NEMO_SEARCH_ENGINE_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SEARCH_ENGINE_SIMPLE, NemoSearchEngineSimple)) #define NEMO_SEARCH_ENGINE_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SEARCH_ENGINE_SIMPLE, NemoSearchEngineSimpleClass)) #define NEMO_IS_SEARCH_ENGINE_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SEARCH_ENGINE_SIMPLE)) #define NEMO_IS_SEARCH_ENGINE_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SEARCH_ENGINE_SIMPLE)) #define NEMO_SEARCH_ENGINE_SIMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SEARCH_ENGINE_SIMPLE, NemoSearchEngineSimpleClass)) typedef struct NemoSearchEngineSimpleDetails NemoSearchEngineSimpleDetails; typedef struct NemoSearchEngineSimple { NemoSearchEngine parent; NemoSearchEngineSimpleDetails *details; } NemoSearchEngineSimple; typedef struct { NemoSearchEngineClass parent_class; } NemoSearchEngineSimpleClass; GType nemo_search_engine_simple_get_type (void); NemoSearchEngine* nemo_search_engine_simple_new (void); #endif /* NEMO_SEARCH_ENGINE_SIMPLE_H */ nemo-3.6.5/libnemo-private/nemo-file.h0000664000175000017500000010427613215733314016544 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-file.h: Nemo file model. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_FILE_H #define NEMO_FILE_H #include #include #include #include /* NemoFile is an object used to represent a single element of a * NemoDirectory. It's lightweight and relies on NemoDirectory * to do most of the work. */ /* NemoFile is defined both here and in nemo-directory.h. */ #ifndef NEMO_FILE_DEFINED #define NEMO_FILE_DEFINED typedef struct NemoFile NemoFile; #endif #define NEMO_TYPE_FILE nemo_file_get_type() #define NEMO_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_FILE, NemoFile)) #define NEMO_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_FILE, NemoFileClass)) #define NEMO_IS_FILE(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_FILE)) #define NEMO_IS_FILE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_FILE)) #define NEMO_FILE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_FILE, NemoFileClass)) typedef enum { NEMO_FILE_SORT_NONE, NEMO_FILE_SORT_BY_DISPLAY_NAME, NEMO_FILE_SORT_BY_SIZE, NEMO_FILE_SORT_BY_TYPE, NEMO_FILE_SORT_BY_DETAILED_TYPE, NEMO_FILE_SORT_BY_MTIME, NEMO_FILE_SORT_BY_ATIME, NEMO_FILE_SORT_BY_TRASHED_TIME } NemoFileSortType; typedef enum { NEMO_REQUEST_NOT_STARTED, NEMO_REQUEST_IN_PROGRESS, NEMO_REQUEST_DONE } NemoRequestStatus; typedef enum { NEMO_FILE_ICON_FLAGS_NONE = 0, NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS = (1<<0), NEMO_FILE_ICON_FLAGS_IGNORE_VISITING = (1<<1), NEMO_FILE_ICON_FLAGS_EMBEDDING_TEXT = (1<<2), NEMO_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT = (1<<3), NEMO_FILE_ICON_FLAGS_FOR_OPEN_FOLDER = (1<<4), /* whether the thumbnail size must match the display icon size */ NEMO_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE = (1<<5), /* uses the icon of the mount if present */ NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON = (1<<6), /* render the mount icon as an emblem over the regular one */ NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM = (1<<7), NEMO_FILE_ICON_FLAGS_PIN_HEIGHT_FOR_DESKTOP = (1<<8) } NemoFileIconFlags; typedef enum { NEMO_DATE_TYPE_MODIFIED, NEMO_DATE_TYPE_CHANGED, NEMO_DATE_TYPE_ACCESSED, NEMO_DATE_TYPE_PERMISSIONS_CHANGED, NEMO_DATE_TYPE_TRASHED } NemoDateType; typedef enum { NEMO_FILE_TOOLTIP_FLAGS_NONE = 0, NEMO_FILE_TOOLTIP_FLAGS_FILE_TYPE = (1<<0), NEMO_FILE_TOOLTIP_FLAGS_MOD_DATE = (1<<1), NEMO_FILE_TOOLTIP_FLAGS_ACCESS_DATE = (1<<2), NEMO_FILE_TOOLTIP_FLAGS_PATH = (1<<3) } NemoFileTooltipFlags; /* Emblems sometimes displayed for NemoFiles. Do not localize. */ #define NEMO_FILE_EMBLEM_NAME_SYMBOLIC_LINK "symbolic-link" #define NEMO_FILE_EMBLEM_NAME_CANT_READ "noread" #define NEMO_FILE_EMBLEM_NAME_CANT_WRITE "nowrite" #define NEMO_FILE_EMBLEM_NAME_TRASH "trash" #define NEMO_FILE_EMBLEM_NAME_NOTE "note" typedef void (*NemoFileCallback) (NemoFile *file, gpointer callback_data); typedef void (*NemoFileListCallback) (GList *file_list, gpointer callback_data); typedef void (*NemoFileOperationCallback) (NemoFile *file, GFile *result_location, GError *error, gpointer callback_data); typedef int (*NemoWidthMeasureCallback) (const char *string, void *context); typedef char * (*NemoTruncateCallback) (const char *string, int width, void *context); #define NEMO_FILE_ATTRIBUTES_FOR_ICON (NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_LINK_INFO | NEMO_FILE_ATTRIBUTE_THUMBNAIL) typedef void NemoFileListHandle; /* GObject requirements. */ GType nemo_file_get_type (void); /* Getting at a single file. */ NemoFile * nemo_file_get (GFile *location); NemoFile * nemo_file_get_by_uri (const char *uri); /* Get a file only if the nemo version already exists */ NemoFile * nemo_file_get_existing (GFile *location); NemoFile * nemo_file_get_existing_by_uri (const char *uri); /* Covers for g_object_ref and g_object_unref that provide two conveniences: * 1) Using these is type safe. * 2) You are allowed to call these with NULL, */ NemoFile * nemo_file_ref (NemoFile *file); void nemo_file_unref (NemoFile *file); /* Monitor the file. */ void nemo_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes); void nemo_file_monitor_remove (NemoFile *file, gconstpointer client); /* Waiting for data that's read asynchronously. * This interface currently works only for metadata, but could be expanded * to other attributes as well. */ void nemo_file_call_when_ready (NemoFile *file, NemoFileAttributes attributes, NemoFileCallback callback, gpointer callback_data); void nemo_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data); gboolean nemo_file_check_if_ready (NemoFile *file, NemoFileAttributes attributes); void nemo_file_invalidate_attributes (NemoFile *file, NemoFileAttributes attributes); void nemo_file_invalidate_all_attributes (NemoFile *file); void nemo_file_increment_thumbnail_try_count (NemoFile *file); /* Basic attributes for file objects. */ gboolean nemo_file_contains_text (NemoFile *file); char * nemo_file_get_display_name (NemoFile *file); char * nemo_file_get_edit_name (NemoFile *file); char * nemo_file_get_name (NemoFile *file); const char * nemo_file_peek_name (NemoFile *file); GFile * nemo_file_get_location (NemoFile *file); char * nemo_file_get_description (NemoFile *file); char * nemo_file_get_uri (NemoFile *file); char * nemo_file_get_path (NemoFile *file); char * nemo_file_get_uri_scheme (NemoFile *file); NemoFile * nemo_file_get_parent (NemoFile *file); GFile * nemo_file_get_parent_location (NemoFile *file); char * nemo_file_get_parent_uri (NemoFile *file); char * nemo_file_get_parent_uri_for_display (NemoFile *file); gboolean nemo_file_can_get_size (NemoFile *file); goffset nemo_file_get_size (NemoFile *file); time_t nemo_file_get_mtime (NemoFile *file); time_t nemo_file_get_ctime (NemoFile *file); GFileType nemo_file_get_file_type (NemoFile *file); char * nemo_file_get_mime_type (NemoFile *file); gboolean nemo_file_is_mime_type (NemoFile *file, const char *mime_type); gboolean nemo_file_is_launchable (NemoFile *file); gboolean nemo_file_is_symbolic_link (NemoFile *file); gboolean nemo_file_is_mountpoint (NemoFile *file); GMount * nemo_file_get_mount (NemoFile *file); char * nemo_file_get_volume_free_space (NemoFile *file); char * nemo_file_get_volume_name (NemoFile *file); char * nemo_file_get_symbolic_link_target_path (NemoFile *file); char * nemo_file_get_symbolic_link_target_uri (NemoFile *file); gboolean nemo_file_is_broken_symbolic_link (NemoFile *file); gboolean nemo_file_is_nemo_link (NemoFile *file); gboolean nemo_file_is_executable (NemoFile *file); gboolean nemo_file_is_directory (NemoFile *file); gboolean nemo_file_is_user_special_directory (NemoFile *file, GUserDirectory special_directory); gboolean nemo_file_is_archive (NemoFile *file); gboolean nemo_file_is_in_trash (NemoFile *file); gboolean nemo_file_is_in_recent (NemoFile *file); gboolean nemo_file_is_in_desktop (NemoFile *file); gboolean nemo_file_is_home (NemoFile *file); gboolean nemo_file_is_desktop_directory (NemoFile *file); GError * nemo_file_get_file_info_error (NemoFile *file); gboolean nemo_file_get_directory_item_count (NemoFile *file, guint *count, gboolean *count_unreadable); void nemo_file_recompute_deep_counts (NemoFile *file); NemoRequestStatus nemo_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size, gboolean force); gboolean nemo_file_should_show_thumbnail (NemoFile *file); gboolean nemo_file_should_show_directory_item_count (NemoFile *file); gboolean nemo_file_should_show_type (NemoFile *file); GList * nemo_file_get_keywords (NemoFile *file); GList * nemo_file_get_emblem_icons (NemoFile *file, char **exclude); gboolean nemo_file_get_directory_item_mime_types (NemoFile *file, GList **mime_list); void nemo_file_set_attributes (NemoFile *file, GFileInfo *attributes, NemoFileOperationCallback callback, gpointer callback_data); GFilesystemPreviewType nemo_file_get_filesystem_use_preview (NemoFile *file); char * nemo_file_get_filesystem_id (NemoFile *file); NemoFile * nemo_file_get_trash_original_file (NemoFile *file); /* Permissions. */ gboolean nemo_file_can_get_permissions (NemoFile *file); gboolean nemo_file_can_set_permissions (NemoFile *file); guint nemo_file_get_permissions (NemoFile *file); gboolean nemo_file_can_get_owner (NemoFile *file); gboolean nemo_file_can_set_owner (NemoFile *file); gboolean nemo_file_can_get_group (NemoFile *file); gboolean nemo_file_can_set_group (NemoFile *file); char * nemo_file_get_owner_name (NemoFile *file); char * nemo_file_get_group_name (NemoFile *file); GList * nemo_get_user_names (void); GList * nemo_get_all_group_names (void); GList * nemo_file_get_settable_group_names (NemoFile *file); gboolean nemo_file_can_get_selinux_context (NemoFile *file); char * nemo_file_get_selinux_context (NemoFile *file); /* "Capabilities". */ gboolean nemo_file_can_read (NemoFile *file); gboolean nemo_file_can_write (NemoFile *file); gboolean nemo_file_can_execute (NemoFile *file); gboolean nemo_file_can_rename (NemoFile *file); gboolean nemo_file_can_delete (NemoFile *file); gboolean nemo_file_can_trash (NemoFile *file); gboolean nemo_file_can_mount (NemoFile *file); gboolean nemo_file_can_unmount (NemoFile *file); gboolean nemo_file_can_eject (NemoFile *file); gboolean nemo_file_can_start (NemoFile *file); gboolean nemo_file_can_start_degraded (NemoFile *file); gboolean nemo_file_can_stop (NemoFile *file); GDriveStartStopType nemo_file_get_start_stop_type (NemoFile *file); gboolean nemo_file_can_poll_for_media (NemoFile *file); gboolean nemo_file_is_media_check_automatic (NemoFile *file); void nemo_file_mount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_unmount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_eject (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_start (NemoFile *file, GMountOperation *start_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_stop (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_poll_for_media (NemoFile *file); /* Basic operations for file objects. */ void nemo_file_set_owner (NemoFile *file, const char *user_name_or_id, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_set_group (NemoFile *file, const char *group_name_or_id, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_set_permissions (NemoFile *file, guint32 permissions, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_rename (NemoFile *file, const char *new_name, NemoFileOperationCallback callback, gpointer callback_data); void nemo_file_cancel (NemoFile *file, NemoFileOperationCallback callback, gpointer callback_data); /* Return true if this file has already been deleted. * This object will be unref'd after sending the files_removed signal, * but it could hang around longer if someone ref'd it. */ gboolean nemo_file_is_gone (NemoFile *file); /* Return true if this file is not confirmed to have ever really * existed. This is true when the NemoFile object has been created, but no I/O * has yet confirmed the existence of a file by that name. */ gboolean nemo_file_is_not_yet_confirmed (NemoFile *file); /* Simple getting and setting top-level metadata. */ char * nemo_file_get_metadata (NemoFile *file, const char *key, const char *default_metadata); GList * nemo_file_get_metadata_list (NemoFile *file, const char *key); void nemo_file_set_metadata (NemoFile *file, const char *key, const char *default_metadata, const char *metadata); void nemo_file_set_metadata_list (NemoFile *file, const char *key, GList *list); /* Covers for common data types. */ gboolean nemo_file_get_boolean_metadata (NemoFile *file, const char *key, gboolean default_metadata); void nemo_file_set_boolean_metadata (NemoFile *file, const char *key, gboolean default_metadata, gboolean metadata); int nemo_file_get_integer_metadata (NemoFile *file, const char *key, int default_metadata); void nemo_file_set_integer_metadata (NemoFile *file, const char *key, int default_metadata, int metadata); #define UNDEFINED_TIME ((time_t) (-1)) time_t nemo_file_get_time_metadata (NemoFile *file, const char *key); void nemo_file_set_time_metadata (NemoFile *file, const char *key, time_t time); /* Attributes for file objects as user-displayable strings. */ char * nemo_file_get_string_attribute (NemoFile *file, const char *attribute_name); char * nemo_file_get_string_attribute_q (NemoFile *file, GQuark attribute_q); char * nemo_file_get_string_attribute_with_default (NemoFile *file, const char *attribute_name); char * nemo_file_get_string_attribute_with_default_q (NemoFile *file, GQuark attribute_q); /* Matching with another URI. */ gboolean nemo_file_matches_uri (NemoFile *file, const char *uri); /* Is the file local? */ gboolean nemo_file_is_local (NemoFile *file); /* Comparing two file objects for sorting */ NemoFileSortType nemo_file_get_default_sort_type (NemoFile *file, gboolean *reversed); const gchar * nemo_file_get_default_sort_attribute (NemoFile *file, gboolean *reversed); int nemo_file_compare_for_sort (NemoFile *file_1, NemoFile *file_2, NemoFileSortType sort_type, gboolean directories_first, gboolean reversed); int nemo_file_compare_for_sort_by_attribute (NemoFile *file_1, NemoFile *file_2, const char *attribute, gboolean directories_first, gboolean reversed); int nemo_file_compare_for_sort_by_attribute_q (NemoFile *file_1, NemoFile *file_2, GQuark attribute, gboolean directories_first, gboolean reversed); gboolean nemo_file_is_date_sort_attribute_q (GQuark attribute); int nemo_file_compare_display_name (NemoFile *file_1, const char *pattern); int nemo_file_compare_location (NemoFile *file_1, NemoFile *file_2); /* filtering functions for use by various directory views */ gboolean nemo_file_is_hidden_file (NemoFile *file); gboolean nemo_file_should_show (NemoFile *file, gboolean show_hidden, gboolean show_foreign); GList *nemo_file_list_filter_hidden (GList *files, gboolean show_hidden); /* Get the URI that's used when activating the file. * Getting this can require reading the contents of the file. */ gboolean nemo_file_is_launcher (NemoFile *file); gboolean nemo_file_is_foreign_link (NemoFile *file); gboolean nemo_file_is_trusted_link (NemoFile *file); gboolean nemo_file_has_activation_uri (NemoFile *file); char * nemo_file_get_activation_uri (NemoFile *file); GFile * nemo_file_get_activation_location (NemoFile *file); char * nemo_file_get_drop_target_uri (NemoFile *file); GIcon * nemo_file_get_gicon (NemoFile *file, NemoFileIconFlags flags); GIcon * nemo_file_get_emblemed_icon (NemoFile *file, NemoFileIconFlags flags); NemoIconInfo * nemo_file_get_icon (NemoFile *file, int size, int max_width, int scale, NemoFileIconFlags flags); GdkPixbuf * nemo_file_get_icon_pixbuf (NemoFile *file, int size, gboolean force_size, int scale, NemoFileIconFlags flags); gboolean nemo_file_has_open_window (NemoFile *file); void nemo_file_set_has_open_window (NemoFile *file, gboolean has_open_window); /* Thumbnailing handling */ gboolean nemo_file_is_thumbnailing (NemoFile *file); /* Convenience functions for dealing with a list of NemoFile objects that each have a ref. * These are just convenient names for functions that work on lists of GtkObject *. */ GList * nemo_file_list_ref (GList *file_list); void nemo_file_list_unref (GList *file_list); void nemo_file_list_free (GList *file_list); GList * nemo_file_list_copy (GList *file_list); GList * nemo_file_list_from_uris (GList *uri_list); GList * nemo_file_list_sort_by_display_name (GList *file_list); void nemo_file_list_call_when_ready (GList *file_list, NemoFileAttributes attributes, NemoFileListHandle **handle, NemoFileListCallback callback, gpointer callback_data); void nemo_file_list_cancel_call_when_ready (NemoFileListHandle *handle); char * nemo_file_get_owner_as_string (NemoFile *file, gboolean include_real_name); char * nemo_file_get_type_as_string (NemoFile *file); char * nemo_file_get_detailed_type_as_string (NemoFile *file); gchar * nemo_file_construct_tooltip (NemoFile *file, NemoFileTooltipFlags flags); gboolean nemo_file_has_thumbnail_access_problem (NemoFile *file); gint nemo_file_get_monitor_number (NemoFile *file); void nemo_file_set_monitor_number (NemoFile *file, gint monitor); void nemo_file_get_position (NemoFile *file, GdkPoint *point); void nemo_file_set_position (NemoFile *file, gint x, gint y); gboolean nemo_file_get_is_desktop_orphan (NemoFile *file); void nemo_file_set_is_desktop_orphan (NemoFile *file, gboolean is_desktop_orphan); /* Debugging */ void nemo_file_dump (NemoFile *file); typedef struct NemoFileDetails NemoFileDetails; struct NemoFile { GObject parent_slot; NemoFileDetails *details; }; typedef struct { GObjectClass parent_slot; /* Subclasses can set this to something other than G_FILE_TYPE_UNKNOWN and it will be used as the default file type. This is useful when creating a "virtual" NemoFile subclass that you can't actually get real information about. For exaple NemoDesktopDirectoryFile. */ GFileType default_file_type; /* Called when the file notices any change. */ void (* changed) (NemoFile *file); /* Called periodically while directory deep count is being computed. */ void (* updated_deep_count_in_progress) (NemoFile *file); /* Virtual functions (mainly used for trash directory). */ void (* monitor_add) (NemoFile *file, gconstpointer client, NemoFileAttributes attributes); void (* monitor_remove) (NemoFile *file, gconstpointer client); void (* call_when_ready) (NemoFile *file, NemoFileAttributes attributes, NemoFileCallback callback, gpointer callback_data); void (* cancel_call_when_ready) (NemoFile *file, NemoFileCallback callback, gpointer callback_data); gboolean (* check_if_ready) (NemoFile *file, NemoFileAttributes attributes); gboolean (* get_item_count) (NemoFile *file, guint *count, gboolean *count_unreadable); NemoRequestStatus (* get_deep_counts) (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size); gboolean (* get_date) (NemoFile *file, NemoDateType type, time_t *date); char * (* get_where_string) (NemoFile *file); void (* set_metadata) (NemoFile *file, const char *key, const char *value); void (* set_metadata_as_list) (NemoFile *file, const char *key, char **value); gchar * (* get_metadata) (NemoFile *file, const char *key); gchar ** (* get_metadata_as_list) (NemoFile *file, const char *key); void (* mount) (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void (* unmount) (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void (* eject) (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void (* start) (NemoFile *file, GMountOperation *start_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void (* stop) (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data); void (* poll_for_media) (NemoFile *file); } NemoFileClass; #endif /* NEMO_FILE_H */ nemo-3.6.5/libnemo-private/nemo-search-engine.c0000664000175000017500000001066113215733314020322 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2005 Novell, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Anders Carlsson * */ #include #include "nemo-search-engine.h" #include "nemo-search-engine-simple.h" #ifdef ENABLE_TRACKER #include "nemo-search-engine-tracker.h" #endif enum { HITS_ADDED, HITS_SUBTRACTED, FINISHED, ERROR, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_ABSTRACT_TYPE (NemoSearchEngine, nemo_search_engine, G_TYPE_OBJECT); static void nemo_search_engine_class_init (NemoSearchEngineClass *class) { signals[HITS_ADDED] = g_signal_new ("hits-added", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoSearchEngineClass, hits_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[HITS_SUBTRACTED] = g_signal_new ("hits-subtracted", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoSearchEngineClass, hits_subtracted), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoSearchEngineClass, finished), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[ERROR] = g_signal_new ("error", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoSearchEngineClass, error), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } static void nemo_search_engine_init (NemoSearchEngine *engine) { } NemoSearchEngine * nemo_search_engine_new (void) { NemoSearchEngine *engine; #ifdef ENABLE_TRACKER engine = nemo_search_engine_tracker_new (); if (engine) { return engine; } #endif engine = nemo_search_engine_simple_new (); return engine; } void nemo_search_engine_set_query (NemoSearchEngine *engine, NemoQuery *query) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_return_if_fail (NEMO_SEARCH_ENGINE_GET_CLASS (engine)->set_query != NULL); NEMO_SEARCH_ENGINE_GET_CLASS (engine)->set_query (engine, query); } void nemo_search_engine_start (NemoSearchEngine *engine) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_return_if_fail (NEMO_SEARCH_ENGINE_GET_CLASS (engine)->start != NULL); NEMO_SEARCH_ENGINE_GET_CLASS (engine)->start (engine); } void nemo_search_engine_stop (NemoSearchEngine *engine) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_return_if_fail (NEMO_SEARCH_ENGINE_GET_CLASS (engine)->stop != NULL); NEMO_SEARCH_ENGINE_GET_CLASS (engine)->stop (engine); } void nemo_search_engine_hits_added (NemoSearchEngine *engine, GList *hits) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_signal_emit (engine, signals[HITS_ADDED], 0, hits); } void nemo_search_engine_hits_subtracted (NemoSearchEngine *engine, GList *hits) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_signal_emit (engine, signals[HITS_SUBTRACTED], 0, hits); } void nemo_search_engine_finished (NemoSearchEngine *engine) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_signal_emit (engine, signals[FINISHED], 0); } void nemo_search_engine_error (NemoSearchEngine *engine, const char *error_message) { g_return_if_fail (NEMO_IS_SEARCH_ENGINE (engine)); g_signal_emit (engine, signals[ERROR], 0, error_message); } nemo-3.6.5/libnemo-private/nemo-icon-container.c0000664000175000017500000066020513215733314020527 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-icon-container.c - Icon container widget. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000, 2001 Eazel, Inc. Copyright (C) 2002, 2003 Red Hat, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ettore Perazzoli , Darin Adler */ #include #include #include "nemo-icon-container.h" #include "nemo-file.h" #include "nemo-desktop-icon-file.h" #include "nemo-global-preferences.h" #include "nemo-icon-private.h" #include "nemo-lib-self-check-functions.h" #include "nemo-selection-canvas-item.h" #include "nemo-desktop-utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #define DEBUG_FLAG NEMO_DEBUG_ICON_CONTAINER #include "nemo-debug.h" #define TAB_NAVIGATION_DISABLED /* Interval for updating the rubberband selection, in milliseconds. */ #define RUBBERBAND_TIMEOUT_INTERVAL 10 #define RUBBERBAND_SCROLL_THRESHOLD 5 /* Timeout for making the icon currently selected for keyboard operation visible. * If this is 0, you can get into trouble with extra scrolling after holding * down the arrow key for awhile when there are many items. */ #define KEYBOARD_ICON_REVEAL_TIMEOUT 10 /* Maximum amount of milliseconds the mouse button is allowed to stay down * and still be considered a click. */ #define MAX_CLICK_TIME 1500 /* Button assignments. */ #define DRAG_BUTTON 1 #define RUBBERBAND_BUTTON 1 #define MIDDLE_BUTTON 2 #define CONTEXTUAL_MENU_BUTTON 3 #define DRAG_MENU_BUTTON 2 /* Copied from NemoIconContainer */ #define NEMO_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT 5 /* Copied from NemoFile */ #define UNDEFINED_TIME ((time_t) (-1)) enum { ACTION_ACTIVATE, ACTION_MENU, LAST_ACTION }; typedef struct { GList *selection; char *action_descriptions[LAST_ACTION]; } NemoIconContainerAccessiblePrivate; static GType nemo_icon_container_accessible_get_type (void); static void preview_selected_items (NemoIconContainer *container); static void activate_selected_items (NemoIconContainer *container); static void activate_selected_items_alternate (NemoIconContainer *container, NemoIcon *icon); static void compute_stretch (StretchState *start, StretchState *current); static NemoIcon *get_first_selected_icon (NemoIconContainer *container); static NemoIcon *get_nth_selected_icon (NemoIconContainer *container, int index); static gboolean has_multiple_selection (NemoIconContainer *container); static gboolean all_selected (NemoIconContainer *container); static gboolean has_selection (NemoIconContainer *container); static void icon_destroy (NemoIconContainer *container, NemoIcon *icon); static gboolean is_renaming (NemoIconContainer *container); static gboolean is_renaming_pending (NemoIconContainer *container); static void process_pending_icon_to_rename (NemoIconContainer *container); static void handle_hadjustment_changed (GtkAdjustment *adjustment, NemoIconContainer *container); static void handle_vadjustment_changed (GtkAdjustment *adjustment, NemoIconContainer *container); static GList * nemo_icon_container_get_selected_icons (NemoIconContainer *container); static void nemo_icon_container_update_visible_icons (NemoIconContainer *container); static void reveal_icon (NemoIconContainer *container, NemoIcon *icon); static void text_ellipsis_limit_changed_container_callback (gpointer callback_data); static int compare_icons_horizontal (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b); static int compare_icons_vertical (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b); static void remove_search_entry_timeout (NemoIconContainer *container); static gboolean handle_icon_slow_two_click (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event); static void schedule_align_icons (NemoIconContainer *container); static gpointer accessible_parent_class; static GQuark accessible_private_data_quark = 0; static const char *nemo_icon_container_accessible_action_names[] = { "activate", "menu", NULL }; static const char *nemo_icon_container_accessible_action_descriptions[] = { "Activate selected items", "Popup context menu", NULL }; G_DEFINE_TYPE (NemoIconContainer, nemo_icon_container, EEL_TYPE_CANVAS); /* The NemoIconContainer signals. */ enum { ACTIVATE, ACTIVATE_ALTERNATE, ACTIVATE_PREVIEWER, BAND_SELECT_STARTED, BAND_SELECT_ENDED, BUTTON_PRESS, CAN_ACCEPT_ITEM, CONTEXT_CLICK_BACKGROUND, CONTEXT_CLICK_SELECTION, MIDDLE_CLICK, GET_CONTAINER_URI, GET_ICON_URI, GET_ICON_DROP_TARGET_URI, ICON_POSITION_CHANGED, GET_STORED_LAYOUT_TIMESTAMP, STORE_LAYOUT_TIMESTAMP, ICON_RENAME_STARTED, ICON_RENAME_ENDED, ICON_STRETCH_STARTED, ICON_STRETCH_ENDED, LAYOUT_CHANGED, MOVE_COPY_ITEMS, HANDLE_NETSCAPE_URL, HANDLE_URI_LIST, HANDLE_TEXT, HANDLE_RAW, SELECTION_CHANGED, ICON_ADDED, ICON_REMOVED, CLEARED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void tooltip_prefs_changed_callback (NemoIconContainer *container) { container->details->show_desktop_tooltips = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIPS_DESKTOP); container->details->show_icon_view_tooltips = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIPS_ICON_VIEW); container->details->tooltip_flags = nemo_global_preferences_get_tooltip_flags (); nemo_icon_container_request_update_all (container); } /* Functions dealing with NemoIcons. */ static gboolean clicked_on_text (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { if (icon == NULL) return FALSE; double eventX, eventY; EelDRect icon_rect; icon_rect = nemo_icon_canvas_item_get_text_rectangle (icon->item, TRUE); eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &eventX, &eventY); gboolean ret = (eventX > icon_rect.x0) && (eventX < icon_rect.x1) && (eventY > icon_rect.y0) && (eventY < icon_rect.y1); return ret; } static gboolean clicked_on_icon (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { if (icon == NULL) return FALSE; double eventX, eventY; EelDRect icon_rect; icon_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item); eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &eventX, &eventY); gboolean ret = (eventX > icon_rect.x0) && (eventX < icon_rect.x1) && (eventY > icon_rect.y0) && (eventY < icon_rect.y1); return ret; } static void icon_free (NemoIcon *icon) { /* Destroy this canvas item; the parent will unref it. */ eel_canvas_item_destroy (EEL_CANVAS_ITEM (icon->item)); g_free (icon); } gboolean nemo_icon_container_icon_is_positioned (const NemoIcon *icon) { return icon->x != ICON_UNPOSITIONED_VALUE && icon->y != ICON_UNPOSITIONED_VALUE; } static void icon_get_size (NemoIconContainer *container, NemoIcon *icon, guint *size) { if (size != NULL) { *size = MAX (nemo_get_icon_size_for_zoom_level (container->details->zoom_level) * icon->scale, NEMO_ICON_SIZE_SMALLEST); } } /* The icon_set_size function is used by the stretching user * interface, which currently stretches in a way that keeps the aspect * ratio. Later we might have a stretching interface that stretches Y * separate from X and we will change this around. */ static void icon_set_size (NemoIconContainer *container, NemoIcon *icon, guint icon_size, gboolean snap, gboolean update_position) { guint old_size; double scale; icon_get_size (container, icon, &old_size); if (icon_size == old_size) { return; } scale = (double) icon_size / nemo_get_icon_size_for_zoom_level (container->details->zoom_level); nemo_icon_container_move_icon (container, icon, icon->x, icon->y, scale, FALSE, snap, update_position); } static void emit_stretch_started (NemoIconContainer *container, NemoIcon *icon) { g_signal_emit (container, signals[ICON_STRETCH_STARTED], 0, icon->data); } static void emit_stretch_ended (NemoIconContainer *container, NemoIcon *icon) { g_signal_emit (container, signals[ICON_STRETCH_ENDED], 0, icon->data); } static void icon_toggle_selected (NemoIconContainer *container, NemoIcon *icon) { nemo_icon_container_end_renaming_mode (container, TRUE); icon->is_selected = !icon->is_selected; eel_canvas_item_set (EEL_CANVAS_ITEM (icon->item), "highlighted_for_selection", (gboolean) icon->is_selected, NULL); /* If the icon is deselected, then get rid of the stretch handles. * No harm in doing the same if the item is newly selected. */ if (icon == container->details->stretch_icon) { container->details->stretch_icon = NULL; nemo_icon_canvas_item_set_show_stretch_handles (icon->item, FALSE); /* snap the icon if necessary */ if (container->details->keep_aligned) { nemo_icon_container_move_icon (container, icon, icon->x, icon->y, icon->scale, FALSE, TRUE, TRUE); } emit_stretch_ended (container, icon); } /* Raise each newly-selected icon to the front as it is selected. */ if (icon->is_selected) { nemo_icon_container_icon_raise (container, icon); } } /* Select an icon. Return TRUE if selection has changed. */ static gboolean icon_set_selected (NemoIconContainer *container, NemoIcon *icon, gboolean select) { g_assert (select == FALSE || select == TRUE); g_assert (icon->is_selected == FALSE || icon->is_selected == TRUE); if (select == icon->is_selected) { return FALSE; } icon_toggle_selected (container, icon); g_assert (select == icon->is_selected); return TRUE; } /* Utility functions for NemoIconContainer. */ gboolean nemo_icon_container_scroll (NemoIconContainer *container, int delta_x, int delta_y) { GtkAdjustment *hadj, *vadj; int old_h_value, old_v_value; hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)); /* Store the old ajustment values so we can tell if we * ended up actually scrolling. We may not have in a case * where the resulting value got pinned to the adjustment * min or max. */ old_h_value = gtk_adjustment_get_value (hadj); old_v_value = gtk_adjustment_get_value (vadj); gtk_adjustment_set_value (hadj, gtk_adjustment_get_value (hadj) + delta_x); gtk_adjustment_set_value (vadj, gtk_adjustment_get_value (vadj) + delta_y); /* return TRUE if we did scroll */ return gtk_adjustment_get_value (hadj) != old_h_value || gtk_adjustment_get_value (vadj) != old_v_value; } static void pending_icon_to_reveal_destroy_callback (NemoIconCanvasItem *item, NemoIconContainer *container) { g_assert (NEMO_IS_ICON_CONTAINER (container)); g_assert (container->details->pending_icon_to_reveal != NULL); g_assert (container->details->pending_icon_to_reveal->item == item); container->details->pending_icon_to_reveal = NULL; } static NemoIcon* get_pending_icon_to_reveal (NemoIconContainer *container) { return container->details->pending_icon_to_reveal; } static void set_pending_icon_to_reveal (NemoIconContainer *container, NemoIcon *icon) { NemoIcon *old_icon; old_icon = container->details->pending_icon_to_reveal; if (icon == old_icon) { return; } if (old_icon != NULL) { g_signal_handlers_disconnect_by_func (old_icon->item, G_CALLBACK (pending_icon_to_reveal_destroy_callback), container); } if (icon != NULL) { g_signal_connect (icon->item, "destroy", G_CALLBACK (pending_icon_to_reveal_destroy_callback), container); } container->details->pending_icon_to_reveal = icon; } static void item_get_canvas_bounds (NemoIconContainer *container, EelCanvasItem *item, EelIRect *bounds, gboolean safety_pad) { EelDRect world_rect; eel_canvas_item_get_bounds (item, &world_rect.x0, &world_rect.y0, &world_rect.x1, &world_rect.y1); eel_canvas_item_i2w (item->parent, &world_rect.x0, &world_rect.y0); eel_canvas_item_i2w (item->parent, &world_rect.x1, &world_rect.y1); if (safety_pad) { world_rect.x0 -= GET_VIEW_CONSTANT (container, icon_pad_left) + GET_VIEW_CONSTANT (container, icon_pad_right); world_rect.x1 += GET_VIEW_CONSTANT (container, icon_pad_left) + GET_VIEW_CONSTANT (container, icon_pad_right); world_rect.y0 -= GET_VIEW_CONSTANT (container, icon_pad_top) + GET_VIEW_CONSTANT (container, icon_pad_bottom); world_rect.y1 += GET_VIEW_CONSTANT (container, icon_pad_top) + GET_VIEW_CONSTANT (container, icon_pad_bottom); } eel_canvas_w2c (item->canvas, world_rect.x0, world_rect.y0, &bounds->x0, &bounds->y0); eel_canvas_w2c (item->canvas, world_rect.x1, world_rect.y1, &bounds->x1, &bounds->y1); } static void icon_get_row_and_column_bounds (NemoIconContainer *container, NemoIcon *icon, EelIRect *bounds, gboolean safety_pad) { GList *p; NemoIcon *one_icon; EelIRect one_bounds; item_get_canvas_bounds (container, EEL_CANVAS_ITEM (icon->item), bounds, safety_pad); for (p = container->details->icons; p != NULL; p = p->next) { one_icon = p->data; if (icon == one_icon) { continue; } if (compare_icons_horizontal (container, icon, one_icon) == 0) { item_get_canvas_bounds (container, EEL_CANVAS_ITEM (one_icon->item), &one_bounds, safety_pad); bounds->x0 = MIN (bounds->x0, one_bounds.x0); bounds->x1 = MAX (bounds->x1, one_bounds.x1); } if (compare_icons_vertical (container, icon, one_icon) == 0) { item_get_canvas_bounds (container, EEL_CANVAS_ITEM (one_icon->item), &one_bounds, safety_pad); bounds->y0 = MIN (bounds->y0, one_bounds.y0); bounds->y1 = MAX (bounds->y1, one_bounds.y1); } } } static void reveal_icon (NemoIconContainer *container, NemoIcon *icon) { GtkAllocation allocation; GtkAdjustment *hadj, *vadj; EelIRect bounds; if (!nemo_icon_container_icon_is_positioned (icon)) { set_pending_icon_to_reveal (container, icon); return; } set_pending_icon_to_reveal (container, NULL); gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)); if (nemo_icon_container_is_auto_layout (container)) { /* ensure that we reveal the entire row/column */ icon_get_row_and_column_bounds (container, icon, &bounds, TRUE); } else { item_get_canvas_bounds (container, EEL_CANVAS_ITEM (icon->item), &bounds, TRUE); } if (bounds.y0 < gtk_adjustment_get_value (vadj)) { gtk_adjustment_set_value (vadj, bounds.y0); } else if (bounds.y1 > gtk_adjustment_get_value (vadj) + allocation.height) { gtk_adjustment_set_value (vadj, bounds.y1 - allocation.height); } if (bounds.x0 < gtk_adjustment_get_value (hadj)) { gtk_adjustment_set_value (hadj, bounds.x0); } else if (bounds.x1 > gtk_adjustment_get_value (hadj) + allocation.width) { if (bounds.x1 - allocation.width > bounds.x0) { gtk_adjustment_set_value (hadj, bounds.x0); } else { gtk_adjustment_set_value (hadj, bounds.x1 - allocation.width); } } } static void process_pending_icon_to_reveal (NemoIconContainer *container) { NemoIcon *pending_icon_to_reveal; pending_icon_to_reveal = get_pending_icon_to_reveal (container); if (pending_icon_to_reveal != NULL) { reveal_icon (container, pending_icon_to_reveal); } } static gboolean keyboard_icon_reveal_timeout_callback (gpointer data) { NemoIconContainer *container; NemoIcon *icon; container = NEMO_ICON_CONTAINER (data); icon = container->details->keyboard_icon_to_reveal; g_assert (icon != NULL); /* Only reveal the icon if it's still the keyboard focus or if * it's still selected. Someone originally thought we should * cancel this reveal if the user manages to sneak a direct * scroll in before the timeout fires, but we later realized * this wouldn't actually be an improvement * (see bugzilla.gnome.org 40612). */ if (icon == container->details->keyboard_focus || icon->is_selected) { reveal_icon (container, icon); } container->details->keyboard_icon_reveal_timer_id = 0; return FALSE; } static void unschedule_keyboard_icon_reveal (NemoIconContainer *container) { NemoIconContainerDetails *details; details = container->details; if (details->keyboard_icon_reveal_timer_id != 0) { g_source_remove (details->keyboard_icon_reveal_timer_id); } } static void schedule_keyboard_icon_reveal (NemoIconContainer *container, NemoIcon *icon) { NemoIconContainerDetails *details; details = container->details; unschedule_keyboard_icon_reveal (container); details->keyboard_icon_to_reveal = icon; details->keyboard_icon_reveal_timer_id = g_timeout_add (KEYBOARD_ICON_REVEAL_TIMEOUT, keyboard_icon_reveal_timeout_callback, container); } static void clear_keyboard_focus (NemoIconContainer *container) { if (container->details->keyboard_focus != NULL) { eel_canvas_item_set (EEL_CANVAS_ITEM (container->details->keyboard_focus->item), "highlighted_as_keyboard_focus", 0, NULL); } container->details->keyboard_focus = NULL; } inline static void emit_atk_focus_tracker_notify (NemoIcon *icon) { AtkObject *atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)); atk_focus_tracker_notify (atk_object); } /* Set @icon as the icon currently selected for keyboard operations. */ static void set_keyboard_focus (NemoIconContainer *container, NemoIcon *icon) { g_assert (icon != NULL); if (icon == container->details->keyboard_focus) { return; } clear_keyboard_focus (container); container->details->keyboard_focus = icon; eel_canvas_item_set (EEL_CANVAS_ITEM (container->details->keyboard_focus->item), "highlighted_as_keyboard_focus", 1, NULL); emit_atk_focus_tracker_notify (icon); } static void set_keyboard_rubberband_start (NemoIconContainer *container, NemoIcon *icon) { container->details->keyboard_rubberband_start = icon; } static void clear_keyboard_rubberband_start (NemoIconContainer *container) { container->details->keyboard_rubberband_start = NULL; } /* carbon-copy of eel_canvas_group_bounds(), but * for NemoIconContainerItems it returns the * bounds for the “entire itemâ€. */ static void get_icon_bounds_for_canvas_bounds (EelCanvasGroup *group, double *x1, double *y1, double *x2, double *y2, NemoIconCanvasItemBoundsUsage usage) { EelCanvasItem *child; GList *list; double tx1, ty1, tx2, ty2; double minx, miny, maxx, maxy; int set; /* Get the bounds of the first visible item */ child = NULL; /* Unnecessary but eliminates a warning. */ set = FALSE; for (list = group->item_list; list; list = list->next) { child = list->data; if (!NEMO_IS_ICON_CANVAS_ITEM (child)) { continue; } if (child->flags & EEL_CANVAS_ITEM_VISIBLE) { set = TRUE; if (!NEMO_IS_ICON_CANVAS_ITEM (child) || usage == BOUNDS_USAGE_FOR_DISPLAY) { eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy); } else if (usage == BOUNDS_USAGE_FOR_LAYOUT) { nemo_icon_canvas_item_get_bounds_for_layout (NEMO_ICON_CANVAS_ITEM (child), &minx, &miny, &maxx, &maxy); } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) { nemo_icon_canvas_item_get_bounds_for_entire_item (NEMO_ICON_CANVAS_ITEM (child), &minx, &miny, &maxx, &maxy); } else { g_assert_not_reached (); } break; } } /* If there were no visible items, return an empty bounding box */ if (!set) { *x1 = *y1 = *x2 = *y2 = 0.0; return; } /* Now we can grow the bounds using the rest of the items */ list = list->next; for (; list; list = list->next) { child = list->data; if (!NEMO_IS_ICON_CANVAS_ITEM (child)) { continue; } if (!(child->flags & EEL_CANVAS_ITEM_VISIBLE)) continue; if (!NEMO_IS_ICON_CANVAS_ITEM (child) || usage == BOUNDS_USAGE_FOR_DISPLAY) { eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2); } else if (usage == BOUNDS_USAGE_FOR_LAYOUT) { nemo_icon_canvas_item_get_bounds_for_layout (NEMO_ICON_CANVAS_ITEM (child), &tx1, &ty1, &tx2, &ty2); } else if (usage == BOUNDS_USAGE_FOR_ENTIRE_ITEM) { nemo_icon_canvas_item_get_bounds_for_entire_item (NEMO_ICON_CANVAS_ITEM (child), &tx1, &ty1, &tx2, &ty2); } else { g_assert_not_reached (); } if (tx1 < minx) minx = tx1; if (ty1 < miny) miny = ty1; if (tx2 > maxx) maxx = tx2; if (ty2 > maxy) maxy = ty2; } /* Make the bounds be relative to our parent's coordinate system */ if (EEL_CANVAS_ITEM (group)->parent) { minx += group->xpos; miny += group->ypos; maxx += group->xpos; maxy += group->ypos; } if (x1 != NULL) { *x1 = minx; } if (y1 != NULL) { *y1 = miny; } if (x2 != NULL) { *x2 = maxx; } if (y2 != NULL) { *y2 = maxy; } } void nemo_icon_container_get_all_icon_bounds (NemoIconContainer *container, double *x1, double *y1, double *x2, double *y2, NemoIconCanvasItemBoundsUsage usage) { /* FIXME bugzilla.gnome.org 42477: Do we have to do something about the rubberband * here? Any other non-icon items? */ get_icon_bounds_for_canvas_bounds (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root), x1, y1, x2, y2, usage); } /* Don't preserve visible white space the next time the scroll region * is recomputed when the container is not empty. */ void nemo_icon_container_reset_scroll_region (NemoIconContainer *container) { container->details->reset_scroll_region_trigger = TRUE; } /* Set a new scroll region without eliminating any of the currently-visible area. */ static void canvas_set_scroll_region_include_visible_area (EelCanvas *canvas, double x1, double y1, double x2, double y2) { double old_x1, old_y1, old_x2, old_y2; double old_scroll_x, old_scroll_y; double height, width; GtkAllocation allocation; eel_canvas_get_scroll_region (canvas, &old_x1, &old_y1, &old_x2, &old_y2); gtk_widget_get_allocation (GTK_WIDGET (canvas), &allocation); width = (allocation.width) / canvas->pixels_per_unit; height = (allocation.height) / canvas->pixels_per_unit; old_scroll_x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))); old_scroll_y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))); x1 = MIN (x1, old_x1 + old_scroll_x); y1 = MIN (y1, old_y1 + old_scroll_y); x2 = MAX (x2, old_x1 + old_scroll_x + width); y2 = MAX (y2, old_y1 + old_scroll_y + height); eel_canvas_set_scroll_region (canvas, x1, y1, x2, y2); } void nemo_icon_container_update_scroll_region (NemoIconContainer *container) { double x1, y1, x2, y2; double pixels_per_unit; GtkAdjustment *hadj, *vadj; float step_increment; gboolean reset_scroll_region; GtkAllocation allocation; pixels_per_unit = EEL_CANVAS (container)->pixels_per_unit; if (nemo_icon_container_get_is_fixed_size (container)) { /* Set the scroll region to the size of the container allocation */ gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); eel_canvas_set_scroll_region (EEL_CANVAS (container), (double) - container->details->left_margin / pixels_per_unit, (double) - container->details->top_margin / pixels_per_unit, ((double) (allocation.width - 1) - container->details->left_margin - container->details->right_margin) / pixels_per_unit, ((double) (allocation.height - 1) - container->details->top_margin - container->details->bottom_margin) / pixels_per_unit); return; } reset_scroll_region = container->details->reset_scroll_region_trigger || nemo_icon_container_is_empty (container) || nemo_icon_container_is_auto_layout (container); /* The trigger is only cleared when container is non-empty, so * callers can reliably reset the scroll region when an item * is added even if extraneous relayouts are called when the * window is still empty. */ if (!nemo_icon_container_is_empty (container)) { container->details->reset_scroll_region_trigger = FALSE; } nemo_icon_container_get_all_icon_bounds (container, &x1, &y1, &x2, &y2, BOUNDS_USAGE_FOR_ENTIRE_ITEM); /* Add border at the "end"of the layout (i.e. after the icons), to * ensure we get some space when scrolled to the end. * For horizontal layouts, we add a bottom border. * Vertical layout is used by the compact view so the end * depends on the RTL setting. */ if (nemo_icon_container_is_layout_vertical (container)) { if (nemo_icon_container_is_layout_rtl (container)) { x1 -= GET_VIEW_CONSTANT (container, icon_pad_left) + GET_VIEW_CONSTANT (container, container_pad_left); } else { x2 += GET_VIEW_CONSTANT (container, icon_pad_right) + GET_VIEW_CONSTANT (container, container_pad_right); } } else { y2 += GET_VIEW_CONSTANT (container, icon_pad_bottom) + GET_VIEW_CONSTANT (container, container_pad_bottom); } /* Auto-layout assumes a 0, 0 scroll origin and at least allocation->width. * Then we lay out to the right or to the left, so * x can be < 0 and > allocation */ if (nemo_icon_container_is_auto_layout (container)) { gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); x1 = MIN (x1, 0); x2 = MAX (x2, allocation.width / pixels_per_unit); y1 = 0; } else { /* Otherwise we add the padding that is at the start of the layout */ if (nemo_icon_container_is_layout_rtl (container)) { x2 += GET_VIEW_CONSTANT (container, icon_pad_right) + GET_VIEW_CONSTANT (container, container_pad_right); } else { x1 -= GET_VIEW_CONSTANT (container, icon_pad_left) + GET_VIEW_CONSTANT (container, container_pad_left); } y1 -= GET_VIEW_CONSTANT (container, icon_pad_top) + GET_VIEW_CONSTANT (container, container_pad_top); } x2 -= 1; x2 = MAX(x1, x2); y2 -= 1; y2 = MAX(y1, y2); if (reset_scroll_region) { eel_canvas_set_scroll_region (EEL_CANVAS (container), x1, y1, x2, y2); } else { canvas_set_scroll_region_include_visible_area (EEL_CANVAS (container), x1, y1, x2, y2); } hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)); /* Scroll by 1/4 icon each time you click. */ step_increment = nemo_get_icon_size_for_zoom_level (container->details->zoom_level) / 4; if (gtk_adjustment_get_step_increment (hadj) != step_increment) { gtk_adjustment_set_step_increment (hadj, step_increment); } if (gtk_adjustment_get_step_increment (vadj) != step_increment) { gtk_adjustment_set_step_increment (vadj, step_increment); } } static int compare_icons (gconstpointer a, gconstpointer b, gpointer icon_container) { NemoIconContainerClass *klass; const NemoIcon *icon_a, *icon_b; icon_a = a; icon_b = b; klass = NEMO_ICON_CONTAINER_GET_CLASS (icon_container); return klass->compare_icons (icon_container, icon_a->data, icon_b->data); } static void align_icons (NemoIconContainer *container) { NEMO_ICON_CONTAINER_GET_CLASS (container)->align_icons (container); } static void redo_layout_internal (NemoIconContainer *container) { if (NEMO_ICON_CONTAINER_GET_CLASS (container)->finish_adding_new_icons != NULL) { NEMO_ICON_CONTAINER_GET_CLASS (container)->finish_adding_new_icons (container); } /* Don't do any re-laying-out during stretching. Later we * might add smart logic that does this and leaves room for * the stretched icon, but if we do it we want it to be fast * and only re-lay-out when it's really needed. */ if (container->details->auto_layout && container->details->drag_state != DRAG_STATE_STRETCH) { if (container->details->needs_resort) { nemo_icon_container_resort (container); container->details->needs_resort = FALSE; } NEMO_ICON_CONTAINER_GET_CLASS (container)->lay_down_icons (container, container->details->icons, 0); } if (nemo_icon_container_is_layout_rtl (container)) { nemo_icon_container_set_rtl_positions (container); } nemo_icon_container_update_scroll_region (container); process_pending_icon_to_reveal (container); process_pending_icon_to_rename (container); nemo_icon_container_update_visible_icons (container); } static gboolean redo_layout_callback (gpointer callback_data) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (callback_data); redo_layout_internal (container); container->details->idle_id = 0; return FALSE; } static void unschedule_redo_layout (NemoIconContainer *container) { if (container->details->idle_id != 0) { g_source_remove (container->details->idle_id); container->details->idle_id = 0; } } static void schedule_redo_layout (NemoIconContainer *container) { if (container->details->idle_id == 0 && container->details->has_been_allocated) { container->details->idle_id = g_idle_add (redo_layout_callback, container); } } void nemo_icon_container_redo_layout (NemoIconContainer *container) { unschedule_redo_layout (container); redo_layout_internal (container); } static void reload_icon_positions (NemoIconContainer *container) { NEMO_ICON_CONTAINER_GET_CLASS (container)->reload_icon_positions (container); } /* Container-level icon handling functions. */ static gboolean button_event_modifies_selection (GdkEventButton *event) { return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0; } /* invalidate the cached label sizes for all the icons */ static void invalidate_label_sizes (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; nemo_icon_canvas_item_invalidate_label_size (icon->item); } } static void update_icons (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; nemo_icon_container_update_icon (container, icon); } } static gboolean select_range (NemoIconContainer *container, NemoIcon *icon1, NemoIcon *icon2, gboolean unselect_outside_range) { gboolean selection_changed; GList *p; NemoIcon *icon; NemoIcon *unmatched_icon; gboolean select; selection_changed = FALSE; unmatched_icon = NULL; select = FALSE; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (unmatched_icon == NULL) { if (icon == icon1) { unmatched_icon = icon2; select = TRUE; } else if (icon == icon2) { unmatched_icon = icon1; select = TRUE; } } if (select || unselect_outside_range) { selection_changed |= icon_set_selected (container, icon, select); } if (unmatched_icon != NULL && icon == unmatched_icon) { select = FALSE; } } if (selection_changed && icon2 != NULL) { emit_atk_focus_tracker_notify (icon2); } return selection_changed; } static gboolean select_one_unselect_others (NemoIconContainer *container, NemoIcon *icon_to_select) { gboolean selection_changed; GList *p; NemoIcon *icon; selection_changed = FALSE; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; selection_changed |= icon_set_selected (container, icon, icon == icon_to_select); } if (selection_changed && icon_to_select != NULL) { emit_atk_focus_tracker_notify (icon_to_select); reveal_icon (container, icon_to_select); } return selection_changed; } static gboolean unselect_all (NemoIconContainer *container) { return select_one_unselect_others (container, NULL); } /* Implementation of rubberband selection. */ static void rubberband_select (NemoIconContainer *container, const EelDRect *previous_rect, const EelDRect *current_rect) { GList *p; gboolean selection_changed, is_in, canvas_rect_calculated; NemoIcon *icon; EelIRect canvas_rect; EelCanvas *canvas; selection_changed = FALSE; canvas_rect_calculated = FALSE; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (!canvas_rect_calculated) { /* Only do this calculation once, since all the canvas items * we are interating are in the same coordinate space */ canvas = EEL_CANVAS_ITEM (icon->item)->canvas; eel_canvas_w2c (canvas, current_rect->x0, current_rect->y0, &canvas_rect.x0, &canvas_rect.y0); eel_canvas_w2c (canvas, current_rect->x1, current_rect->y1, &canvas_rect.x1, &canvas_rect.y1); canvas_rect_calculated = TRUE; } is_in = nemo_icon_canvas_item_hit_test_rectangle (icon->item, canvas_rect); selection_changed |= icon_set_selected (container, icon, is_in ^ icon->was_selected_before_rubberband); } if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } static int rubberband_timeout_callback (gpointer data) { NemoIconContainer *container; GtkWidget *widget; NemoIconRubberbandInfo *band_info; int x, y; double x1, y1, x2, y2; double world_x, world_y; int x_scroll, y_scroll; int adj_x, adj_y; gboolean adj_changed; GtkAllocation allocation; EelDRect selection_rect; widget = GTK_WIDGET (data); container = NEMO_ICON_CONTAINER (data); band_info = &container->details->rubberband_info; g_assert (band_info->timer_id != 0); adj_changed = FALSE; gtk_widget_get_allocation (widget, &allocation); adj_x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); if (adj_x != band_info->last_adj_x) { band_info->last_adj_x = adj_x; adj_changed = TRUE; } adj_y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); if (adj_y != band_info->last_adj_y) { band_info->last_adj_y = adj_y; adj_changed = TRUE; } gdk_window_get_device_position (gtk_widget_get_window (widget), gdk_device_manager_get_client_pointer ( gdk_display_get_device_manager ( gtk_widget_get_display (widget))), &x, &y, NULL); if (x < RUBBERBAND_SCROLL_THRESHOLD) { x_scroll = x - RUBBERBAND_SCROLL_THRESHOLD; x = 0; } else if (x >= allocation.width - RUBBERBAND_SCROLL_THRESHOLD) { x_scroll = x - allocation.width + RUBBERBAND_SCROLL_THRESHOLD + 1; x = allocation.width - 1; } else { x_scroll = 0; } if (y < RUBBERBAND_SCROLL_THRESHOLD) { y_scroll = y - RUBBERBAND_SCROLL_THRESHOLD; y = 0; } else if (y >= allocation.height - RUBBERBAND_SCROLL_THRESHOLD) { y_scroll = y - allocation.height + RUBBERBAND_SCROLL_THRESHOLD + 1; y = allocation.height - 1; } else { y_scroll = 0; } if (y_scroll == 0 && x_scroll == 0 && (int) band_info->prev_x == x && (int) band_info->prev_y == y && !adj_changed) { return TRUE; } nemo_icon_container_scroll (container, x_scroll, y_scroll); /* Remember to convert from widget to scrolled window coords */ eel_canvas_window_to_world (EEL_CANVAS (container), x + gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))), y + gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))), &world_x, &world_y); if (world_x < band_info->start_x) { x1 = world_x; x2 = band_info->start_x; } else { x1 = band_info->start_x; x2 = world_x; } if (world_y < band_info->start_y) { y1 = world_y; y2 = band_info->start_y; } else { y1 = band_info->start_y; y2 = world_y; } /* Don't let the area of the selection rectangle be empty. * Aside from the fact that it would be funny when the rectangle disappears, * this also works around a crash in libart that happens sometimes when a * zero height rectangle is passed. */ x2 = MAX (x1 + 1, x2); y2 = MAX (y1 + 1, y2); eel_canvas_item_set (band_info->selection_rectangle, "x1", x1, "y1", y1, "x2", x2, "y2", y2, NULL); selection_rect.x0 = x1; selection_rect.y0 = y1; selection_rect.x1 = x2; selection_rect.y1 = y2; rubberband_select (container, &band_info->prev_rect, &selection_rect); band_info->prev_x = x; band_info->prev_y = y; band_info->prev_rect = selection_rect; return TRUE; } static void start_rubberbanding (NemoIconContainer *container, GdkEventButton *event) { AtkObject *accessible; NemoIconContainerDetails *details; NemoIconRubberbandInfo *band_info; GdkRGBA bg_color, border_color; GList *p; NemoIcon *icon; GtkStyleContext *context; details = container->details; band_info = &details->rubberband_info; g_signal_emit (container, signals[BAND_SELECT_STARTED], 0); for (p = details->icons; p != NULL; p = p->next) { icon = p->data; icon->was_selected_before_rubberband = icon->is_selected; } eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &band_info->start_x, &band_info->start_y); context = gtk_widget_get_style_context (GTK_WIDGET (container)); gtk_style_context_save (context); gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg_color); gtk_style_context_get_border_color (context, GTK_STATE_FLAG_NORMAL, &border_color); gtk_style_context_restore (context); band_info->selection_rectangle = eel_canvas_item_new (eel_canvas_root (EEL_CANVAS (container)), NEMO_TYPE_SELECTION_CANVAS_ITEM, "x1", band_info->start_x, "y1", band_info->start_y, "x2", band_info->start_x, "y2", band_info->start_y, "fill_color_rgba", &bg_color, "outline_color_rgba", &border_color, "width_pixels", 1, NULL); accessible = atk_gobject_accessible_for_object (G_OBJECT (band_info->selection_rectangle)); atk_object_set_name (accessible, "selection"); atk_object_set_description (accessible, _("The selection rectangle")); band_info->prev_x = event->x - gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); band_info->prev_y = event->y - gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); band_info->active = TRUE; if (band_info->timer_id == 0) { band_info->timer_id = g_timeout_add (RUBBERBAND_TIMEOUT_INTERVAL, rubberband_timeout_callback, container); } eel_canvas_item_grab (band_info->selection_rectangle, (GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK), NULL, event->time); } static void stop_rubberbanding (NemoIconContainer *container, guint32 time) { NemoIconRubberbandInfo *band_info; GList *icons; gboolean enable_animation; band_info = &container->details->rubberband_info; g_assert (band_info->timer_id != 0); g_source_remove (band_info->timer_id); band_info->timer_id = 0; band_info->active = FALSE; g_object_get (gtk_settings_get_default (), "gtk-enable-animations", &enable_animation, NULL); /* Destroy this canvas item; the parent will unref it. */ eel_canvas_item_ungrab (band_info->selection_rectangle, time); eel_canvas_item_lower_to_bottom (band_info->selection_rectangle); if (enable_animation) { nemo_selection_canvas_item_fade_out (NEMO_SELECTION_CANVAS_ITEM (band_info->selection_rectangle), 150); } else { eel_canvas_item_destroy (band_info->selection_rectangle); } band_info->selection_rectangle = NULL; /* if only one item has been selected, use it as range * selection base (cf. handle_icon_button_press) */ icons = nemo_icon_container_get_selected_icons (container); if (g_list_length (icons) == 1) { container->details->range_selection_base_icon = icons->data; } g_list_free (icons); g_signal_emit (container, signals[BAND_SELECT_ENDED], 0); } /* Keyboard navigation. */ typedef gboolean (* IsBetterIconFunction) (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data); static NemoIcon * find_best_icon (NemoIconContainer *container, NemoIcon *start_icon, IsBetterIconFunction function, void *data) { GList *p; NemoIcon *best, *candidate; best = NULL; for (p = container->details->icons; p != NULL; p = p->next) { candidate = p->data; if (candidate != start_icon) { if ((* function) (container, start_icon, best, candidate, data)) { best = candidate; } } } return best; } static NemoIcon * find_best_selected_icon (NemoIconContainer *container, NemoIcon *start_icon, IsBetterIconFunction function, void *data) { GList *p; NemoIcon *best, *candidate; best = NULL; for (p = container->details->icons; p != NULL; p = p->next) { candidate = p->data; if (candidate != start_icon && candidate->is_selected) { if ((* function) (container, start_icon, best, candidate, data)) { best = candidate; } } } return best; } static int compare_icons_by_uri (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b) { char *uri_a, *uri_b; int result; g_assert (NEMO_IS_ICON_CONTAINER (container)); g_assert (icon_a != NULL); g_assert (icon_b != NULL); g_assert (icon_a != icon_b); uri_a = nemo_icon_container_get_icon_uri (container, icon_a); uri_b = nemo_icon_container_get_icon_uri (container, icon_b); result = strcmp (uri_a, uri_b); g_assert (result != 0); g_free (uri_a); g_free (uri_b); return result; } static int get_cmp_point_x (NemoIconContainer *container, EelDRect icon_rect) { if (container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) { return icon_rect.x0; } else { return icon_rect.x1; } } else { return (icon_rect.x0 + icon_rect.x1) / 2; } } static int get_cmp_point_y (NemoIconContainer *container, EelDRect icon_rect) { if (container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { return (icon_rect.y0 + icon_rect.y1)/2; } else { return icon_rect.y1; } } static int compare_icons_horizontal (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b) { EelDRect world_rect; int ax, bx; world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_a->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &ax, NULL); world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_b->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &bx, NULL); if (ax < bx) { return -1; } if (ax > bx) { return +1; } return 0; } static int compare_icons_vertical (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b) { EelDRect world_rect; int ay, by; world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_a->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), NULL, &ay); world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_b->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), NULL, &by); if (ay < by) { return -1; } if (ay > by) { return +1; } return 0; } static int compare_icons_horizontal_first (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b) { EelDRect world_rect; int ax, ay, bx, by; world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_a->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &ax, &ay); world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_b->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &bx, &by); if (ax < bx) { return -1; } if (ax > bx) { return +1; } if (ay < by) { return -1; } if (ay > by) { return +1; } return compare_icons_by_uri (container, icon_a, icon_b); } static int compare_icons_vertical_first (NemoIconContainer *container, NemoIcon *icon_a, NemoIcon *icon_b) { EelDRect world_rect; int ax, ay, bx, by; world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_a->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &ax, &ay); world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon_b->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &bx, &by); if (ay < by) { return -1; } if (ay > by) { return +1; } if (ax < bx) { return -1; } if (ax > bx) { return +1; } return compare_icons_by_uri (container, icon_a, icon_b); } static gboolean leftmost_in_top_row (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { if (best_so_far == NULL) { return TRUE; } return compare_icons_vertical_first (container, best_so_far, candidate) > 0; } static gboolean rightmost_in_top_row (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { if (best_so_far == NULL) { return TRUE; } return compare_icons_vertical (container, best_so_far, candidate) > 0; return compare_icons_horizontal (container, best_so_far, candidate) < 0; } static gboolean rightmost_in_bottom_row (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { if (best_so_far == NULL) { return TRUE; } return compare_icons_vertical_first (container, best_so_far, candidate) < 0; } static int compare_with_start_row (NemoIconContainer *container, NemoIcon *icon) { EelCanvasItem *item; item = EEL_CANVAS_ITEM (icon->item); if (container->details->arrow_key_start_y < item->y1) { return -1; } if (container->details->arrow_key_start_y > item->y2) { return +1; } return 0; } static int compare_with_start_column (NemoIconContainer *container, NemoIcon *icon) { EelCanvasItem *item; item = EEL_CANVAS_ITEM (icon->item); if (container->details->arrow_key_start_x < item->x1) { return -1; } if (container->details->arrow_key_start_x > item->x2) { return +1; } return 0; } static gboolean same_row_right_side_leftmost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* Candidates not on the start row do not qualify. */ if (compare_with_start_row (container, candidate) != 0) { return FALSE; } /* Candidates that are farther right lose out. */ if (best_so_far != NULL) { if (compare_icons_horizontal_first (container, best_so_far, candidate) < 0) { return FALSE; } } /* Candidate to the left of the start do not qualify. */ if (compare_icons_horizontal_first (container, candidate, start_icon) <= 0) { return FALSE; } return TRUE; } static gboolean same_row_left_side_rightmost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* Candidates not on the start row do not qualify. */ if (compare_with_start_row (container, candidate) != 0) { return FALSE; } /* Candidates that are farther left lose out. */ if (best_so_far != NULL) { if (compare_icons_horizontal_first (container, best_so_far, candidate) > 0) { return FALSE; } } /* Candidate to the right of the start do not qualify. */ if (compare_icons_horizontal_first (container, candidate, start_icon) >= 0) { return FALSE; } return TRUE; } static gboolean next_row_leftmost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not below the current row */ if (compare_with_start_row (container, candidate) >= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_vertical_first (container, best_so_far, candidate) > 0) { /* candidate is above best choice, but below the current row */ return TRUE; } if (compare_icons_horizontal_first (container, best_so_far, candidate) > 0) { return TRUE; } } return best_so_far == NULL; } static gboolean next_row_rightmost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not below the current row */ if (compare_with_start_row (container, candidate) >= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_vertical_first (container, best_so_far, candidate) > 0) { /* candidate is above best choice, but below the current row */ return TRUE; } if (compare_icons_horizontal_first (container, best_so_far, candidate) < 0) { return TRUE; } } return best_so_far == NULL; } static gboolean next_column_bottommost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not on the right of the current column */ if (compare_with_start_column (container, candidate) >= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_horizontal_first (container, best_so_far, candidate) > 0) { /* candidate is above best choice, but below the current row */ return TRUE; } if (compare_icons_vertical_first (container, best_so_far, candidate) < 0) { return TRUE; } } return best_so_far == NULL; } static gboolean previous_row_rightmost (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not above the current row */ if (compare_with_start_row (container, candidate) <= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_vertical_first (container, best_so_far, candidate) < 0) { /* candidate is below the best choice, but above the current row */ return TRUE; } if (compare_icons_horizontal_first (container, best_so_far, candidate) < 0) { return TRUE; } } return best_so_far == NULL; } static gboolean same_column_above_lowest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* Candidates not on the start column do not qualify. */ if (compare_with_start_column (container, candidate) != 0) { return FALSE; } /* Candidates that are higher lose out. */ if (best_so_far != NULL) { if (compare_icons_vertical_first (container, best_so_far, candidate) > 0) { return FALSE; } } /* Candidates below the start do not qualify. */ if (compare_icons_vertical_first (container, candidate, start_icon) >= 0) { return FALSE; } return TRUE; } static gboolean same_column_below_highest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* Candidates not on the start column do not qualify. */ if (compare_with_start_column (container, candidate) != 0) { return FALSE; } /* Candidates that are lower lose out. */ if (best_so_far != NULL) { if (compare_icons_vertical_first (container, best_so_far, candidate) < 0) { return FALSE; } } /* Candidates above the start do not qualify. */ if (compare_icons_vertical_first (container, candidate, start_icon) <= 0) { return FALSE; } return TRUE; } static gboolean previous_column_highest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not before the current column */ if (compare_with_start_column (container, candidate) <= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_horizontal (container, best_so_far, candidate) < 0) { /* candidate is right of the best choice, but left of the current column */ return TRUE; } if (compare_icons_vertical (container, best_so_far, candidate) > 0) { return TRUE; } } return best_so_far == NULL; } static gboolean next_column_highest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not after the current column */ if (compare_with_start_column (container, candidate) >= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_horizontal_first (container, best_so_far, candidate) > 0) { /* candidate is left of the best choice, but right of the current column */ return TRUE; } if (compare_icons_vertical_first (container, best_so_far, candidate) > 0) { return TRUE; } } return best_so_far == NULL; } static gboolean previous_column_lowest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { /* sort out icons that are not before the current column */ if (compare_with_start_column (container, candidate) <= 0) { return FALSE; } if (best_so_far != NULL) { if (compare_icons_horizontal_first (container, best_so_far, candidate) < 0) { /* candidate is right of the best choice, but left of the current column */ return TRUE; } if (compare_icons_vertical_first (container, best_so_far, candidate) < 0) { return TRUE; } } return best_so_far == NULL; } static gboolean last_column_lowest (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { if (best_so_far == NULL) { return TRUE; } return compare_icons_horizontal_first (container, best_so_far, candidate) < 0; } static gboolean closest_in_90_degrees (NemoIconContainer *container, NemoIcon *start_icon, NemoIcon *best_so_far, NemoIcon *candidate, void *data) { EelDRect world_rect; int x, y; int dx, dy; int dist; int *best_dist; world_rect = nemo_icon_canvas_item_get_icon_rectangle (candidate->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &x, &y); dx = x - container->details->arrow_key_start_x; dy = y - container->details->arrow_key_start_y; switch (container->details->arrow_key_direction) { case GTK_DIR_UP: if (dy > 0 || ABS(dx) > ABS(dy)) { return FALSE; } break; case GTK_DIR_DOWN: if (dy < 0 || ABS(dx) > ABS(dy)) { return FALSE; } break; case GTK_DIR_LEFT: if (dx > 0 || ABS(dy) > ABS(dx)) { return FALSE; } break; case GTK_DIR_RIGHT: if (dx < 0 || ABS(dy) > ABS(dx)) { return FALSE; } break; default: g_assert_not_reached(); } dist = dx*dx + dy*dy; best_dist = data; if (best_so_far == NULL) { *best_dist = dist; return TRUE; } if (dist < *best_dist) { *best_dist = dist; return TRUE; } return FALSE; } static EelDRect get_rubberband (NemoIcon *icon1, NemoIcon *icon2) { EelDRect rect1; EelDRect rect2; EelDRect ret; eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon1->item), &rect1.x0, &rect1.y0, &rect1.x1, &rect1.y1); eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon2->item), &rect2.x0, &rect2.y0, &rect2.x1, &rect2.y1); eel_drect_union (&ret, &rect1, &rect2); return ret; } static void keyboard_move_to (NemoIconContainer *container, NemoIcon *icon, NemoIcon *from, GdkEventKey *event) { if (icon == NULL) { return; } if (event != NULL && (event->state & GDK_CONTROL_MASK) != 0 && (event->state & GDK_SHIFT_MASK) == 0) { /* Move the keyboard focus. Use Control modifier * rather than Alt to avoid Sawfish conflict. */ set_keyboard_focus (container, icon); container->details->keyboard_rubberband_start = NULL; } else if (event != NULL && ((event->state & GDK_CONTROL_MASK) != 0 || !container->details->auto_layout) && (event->state & GDK_SHIFT_MASK) != 0) { /* Do rubberband selection */ EelDRect rect; if (from && !container->details->keyboard_rubberband_start) { set_keyboard_rubberband_start (container, from); } set_keyboard_focus (container, icon); if (icon && container->details->keyboard_rubberband_start) { rect = get_rubberband (container->details->keyboard_rubberband_start, icon); rubberband_select (container, NULL, &rect); } } else if (event != NULL && (event->state & GDK_CONTROL_MASK) == 0 && (event->state & GDK_SHIFT_MASK) != 0) { /* Select range */ NemoIcon *start_icon; start_icon = container->details->range_selection_base_icon; if (start_icon == NULL || !start_icon->is_selected) { start_icon = icon; container->details->range_selection_base_icon = icon; } set_keyboard_focus (container, icon); if (select_range (container, start_icon, icon, TRUE)) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } else { /* Select icons and get rid of the special keyboard focus. */ clear_keyboard_focus (container); clear_keyboard_rubberband_start (container); container->details->range_selection_base_icon = icon; if (select_one_unselect_others (container, icon)) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } schedule_keyboard_icon_reveal (container, icon); } static void keyboard_home (NemoIconContainer *container, GdkEventKey *event) { NemoIcon *from; NemoIcon *to; /* Home selects the first icon. * Control-Home sets the keyboard focus to the first icon. */ from = find_best_selected_icon (container, NULL, rightmost_in_bottom_row, NULL); to = find_best_icon (container, NULL, leftmost_in_top_row, NULL); keyboard_move_to (container, to, from, event); } static void keyboard_end (NemoIconContainer *container, GdkEventKey *event) { NemoIcon *to; NemoIcon *from; /* End selects the last icon. * Control-End sets the keyboard focus to the last icon. */ from = find_best_selected_icon (container, NULL, leftmost_in_top_row, NULL); to = find_best_icon (container, NULL, nemo_icon_container_is_layout_vertical (container) ? last_column_lowest : rightmost_in_bottom_row, NULL); keyboard_move_to (container, to, from, event); } static void record_arrow_key_start (NemoIconContainer *container, NemoIcon *icon, GtkDirectionType direction) { EelDRect world_rect; world_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item); eel_canvas_w2c (EEL_CANVAS (container), get_cmp_point_x (container, world_rect), get_cmp_point_y (container, world_rect), &container->details->arrow_key_start_x, &container->details->arrow_key_start_y); container->details->arrow_key_direction = direction; } static void keyboard_arrow_key (NemoIconContainer *container, GdkEventKey *event, GtkDirectionType direction, IsBetterIconFunction better_start, IsBetterIconFunction empty_start, IsBetterIconFunction better_destination, IsBetterIconFunction better_destination_fallback, IsBetterIconFunction better_destination_fallback_fallback, IsBetterIconFunction better_destination_manual) { NemoIcon *from; NemoIcon *to; int data; /* Chose the icon to start with. * If we have a keyboard focus, start with it. * Otherwise, use the single selected icon. * If there's multiple selection, use the icon farthest toward the end. */ from = container->details->keyboard_focus; if (from == NULL) { if (has_multiple_selection (container)) { if (all_selected (container)) { from = find_best_selected_icon (container, NULL, empty_start, NULL); } else { from = find_best_selected_icon (container, NULL, better_start, NULL); } } else { from = get_first_selected_icon (container); } } /* If there's no icon, select the icon farthest toward the end. * If there is an icon, select the next icon based on the arrow direction. */ if (from == NULL) { to = from = find_best_icon (container, NULL, empty_start, NULL); } else { record_arrow_key_start (container, from, direction); to = find_best_icon (container, from, container->details->auto_layout ? better_destination : better_destination_manual, &data); /* Wrap around to next/previous row/column */ if (to == NULL && better_destination_fallback != NULL) { to = find_best_icon (container, from, better_destination_fallback, &data); } /* With a layout like * 1 2 3 * 4 * (horizontal layout) * * or * * 1 4 * 2 * 3 * (vertical layout) * * * pressing down for any of 1,2,3 (horizontal layout) * * pressing right for any of 1,2,3 (vertical layout) * * Should select 4. */ if (to == NULL && container->details->auto_layout && better_destination_fallback_fallback != NULL) { to = find_best_icon (container, from, better_destination_fallback_fallback, &data); } if (to == NULL) { to = from; } } keyboard_move_to (container, to, from, event); } static gboolean is_rectangle_selection_event (GdkEventKey *event) { return (event->state & GDK_CONTROL_MASK) != 0 && (event->state & GDK_SHIFT_MASK) != 0; } static void keyboard_right (NemoIconContainer *container, GdkEventKey *event) { IsBetterIconFunction fallback; IsBetterIconFunction next_column_fallback; fallback = NULL; if (container->details->auto_layout && !nemo_icon_container_is_layout_vertical (container) && !is_rectangle_selection_event (event)) { fallback = next_row_leftmost; } next_column_fallback = NULL; if (nemo_icon_container_is_layout_vertical (container) && gtk_widget_get_direction (GTK_WIDGET (container)) != GTK_TEXT_DIR_RTL) { next_column_fallback = next_column_bottommost; } /* Right selects the next icon in the same row. * Control-Right sets the keyboard focus to the next icon in the same row. */ keyboard_arrow_key (container, event, GTK_DIR_RIGHT, rightmost_in_bottom_row, nemo_icon_container_is_layout_rtl (container) ? rightmost_in_top_row : leftmost_in_top_row, same_row_right_side_leftmost, fallback, next_column_fallback, closest_in_90_degrees); } static void keyboard_left (NemoIconContainer *container, GdkEventKey *event) { IsBetterIconFunction fallback; IsBetterIconFunction previous_column_fallback; fallback = NULL; if (container->details->auto_layout && !nemo_icon_container_is_layout_vertical (container) && !is_rectangle_selection_event (event)) { fallback = previous_row_rightmost; } previous_column_fallback = NULL; if (nemo_icon_container_is_layout_vertical (container) && gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) { previous_column_fallback = previous_column_lowest; } /* Left selects the next icon in the same row. * Control-Left sets the keyboard focus to the next icon in the same row. */ keyboard_arrow_key (container, event, GTK_DIR_LEFT, rightmost_in_bottom_row, nemo_icon_container_is_layout_rtl (container) ? rightmost_in_top_row : leftmost_in_top_row, same_row_left_side_rightmost, fallback, previous_column_fallback, closest_in_90_degrees); } static void keyboard_down (NemoIconContainer *container, GdkEventKey *event) { IsBetterIconFunction fallback; IsBetterIconFunction next_row_fallback; fallback = NULL; if (container->details->auto_layout && nemo_icon_container_is_layout_vertical (container) && !is_rectangle_selection_event (event)) { if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) { fallback = previous_column_highest; } else { fallback = next_column_highest; } } next_row_fallback = NULL; if (!nemo_icon_container_is_layout_vertical (container)) { if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) { next_row_fallback = next_row_leftmost; } else { next_row_fallback = next_row_rightmost; } } /* Down selects the next icon in the same column. * Control-Down sets the keyboard focus to the next icon in the same column. */ keyboard_arrow_key (container, event, GTK_DIR_DOWN, rightmost_in_bottom_row, nemo_icon_container_is_layout_rtl (container) ? rightmost_in_top_row : leftmost_in_top_row, same_column_below_highest, fallback, next_row_fallback, closest_in_90_degrees); } static void keyboard_up (NemoIconContainer *container, GdkEventKey *event) { IsBetterIconFunction fallback; fallback = NULL; if (container->details->auto_layout && nemo_icon_container_is_layout_vertical (container) && !is_rectangle_selection_event (event)) { if (gtk_widget_get_direction (GTK_WIDGET (container)) == GTK_TEXT_DIR_RTL) { fallback = next_column_bottommost; } else { fallback = previous_column_lowest; } } /* Up selects the next icon in the same column. * Control-Up sets the keyboard focus to the next icon in the same column. */ keyboard_arrow_key (container, event, GTK_DIR_UP, rightmost_in_bottom_row, nemo_icon_container_is_layout_rtl (container) ? rightmost_in_top_row : leftmost_in_top_row, same_column_above_lowest, fallback, NULL, closest_in_90_degrees); } static void keyboard_space (NemoIconContainer *container, GdkEventKey *event) { NemoIcon *icon; if (!has_selection (container) && container->details->keyboard_focus != NULL) { keyboard_move_to (container, container->details->keyboard_focus, NULL, NULL); } else if ((event->state & GDK_CONTROL_MASK) != 0 && (event->state & GDK_SHIFT_MASK) == 0) { /* Control-space toggles the selection state of the current icon. */ if (container->details->keyboard_focus != NULL) { icon_toggle_selected (container, container->details->keyboard_focus); g_signal_emit (container, signals[SELECTION_CHANGED], 0); if (container->details->keyboard_focus->is_selected) { container->details->range_selection_base_icon = container->details->keyboard_focus; } } else { icon = find_best_selected_icon (container, NULL, leftmost_in_top_row, NULL); if (icon == NULL) { icon = find_best_icon (container, NULL, leftmost_in_top_row, NULL); } if (icon != NULL) { set_keyboard_focus (container, icon); } } } else if ((event->state & GDK_SHIFT_MASK) != 0) { activate_selected_items_alternate (container, NULL); } else { preview_selected_items (container); } } /* look for the first icon that matches the longest part of a given * search pattern */ typedef struct { gunichar *name; int last_match_length; } BestNameMatch; #ifndef TAB_NAVIGATION_DISABLED static void select_previous_or_next_icon (NemoIconContainer *container, gboolean next, GdkEventKey *event) { NemoIcon *icon; const GList *item; item = NULL; /* Chose the icon to start with. * If we have a keyboard focus, start with it. * Otherwise, use the single selected icon. */ icon = container->details->keyboard_focus; if (icon == NULL) { icon = get_first_selected_icon (container); } if (icon != NULL) { /* must have at least @icon in the list */ g_assert (container->details->icons != NULL); item = g_list_find (container->details->icons, icon); g_assert (item != NULL); item = next ? item->next : item->prev; if (item == NULL) { item = next ? g_list_first (container->details->icons) : g_list_last (container->details->icons); } } else if (container->details->icons != NULL) { /* no selection yet, pick the first or last item to select */ item = next ? g_list_first (container->details->icons) : g_list_last (container->details->icons); } icon = (item != NULL) ? item->data : NULL; if (icon != NULL) { keyboard_move_to (container, icon, NULL, event); } } #endif static void destroy (GtkWidget *object) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (object); nemo_icon_container_clear (container); if (container->details->rubberband_info.timer_id != 0) { g_source_remove (container->details->rubberband_info.timer_id); container->details->rubberband_info.timer_id = 0; } if (container->details->idle_id != 0) { g_source_remove (container->details->idle_id); container->details->idle_id = 0; } if (container->details->stretch_idle_id != 0) { g_source_remove (container->details->stretch_idle_id); container->details->stretch_idle_id = 0; } if (container->details->align_idle_id != 0) { g_source_remove (container->details->align_idle_id); container->details->align_idle_id = 0; } if (container->details->selection_changed_id != 0) { g_source_remove (container->details->selection_changed_id); container->details->selection_changed_id = 0; } if (container->details->size_allocation_count_id != 0) { g_source_remove (container->details->size_allocation_count_id); container->details->size_allocation_count_id = 0; } /* destroy interactive search dialog */ if (container->details->search_window) { gtk_widget_destroy (container->details->search_window); container->details->search_window = NULL; container->details->search_entry = NULL; } remove_search_entry_timeout (container); GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->destroy (object); } static void finalize (GObject *object) { NemoIconContainerDetails *details; details = NEMO_ICON_CONTAINER (object)->details; g_signal_handlers_disconnect_by_func (nemo_icon_view_preferences, text_ellipsis_limit_changed_container_callback, object); g_signal_handlers_disconnect_by_func (nemo_desktop_preferences, text_ellipsis_limit_changed_container_callback, object); g_signal_handlers_disconnect_by_func (nemo_preferences, tooltip_prefs_changed_callback, object); g_hash_table_destroy (details->icon_set); details->icon_set = NULL; g_free (details->font); if (details->a11y_item_action_queue != NULL) { while (!g_queue_is_empty (details->a11y_item_action_queue)) { g_free (g_queue_pop_head (details->a11y_item_action_queue)); } g_queue_free (details->a11y_item_action_queue); } if (details->a11y_item_action_idle_handler != 0) { g_source_remove (details->a11y_item_action_idle_handler); } g_slice_free (NemoViewLayoutConstants, details->view_constants); g_free (details); G_OBJECT_CLASS (nemo_icon_container_parent_class)->finalize (object); } /* GtkWidget methods. */ static gboolean clear_size_allocation_count (gpointer data) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (data); container->details->size_allocation_count_id = 0; container->details->size_allocation_count = 0; return FALSE; } static void size_allocate (GtkWidget *widget, GtkAllocation *allocation) { NemoIconContainer *container; gboolean need_layout_redone; GtkAllocation wid_allocation; container = NEMO_ICON_CONTAINER (widget); need_layout_redone = !container->details->has_been_allocated; gtk_widget_get_allocation (widget, &wid_allocation); if (allocation->width != wid_allocation.width) { need_layout_redone = TRUE; } if (allocation->height != wid_allocation.height) { need_layout_redone = TRUE; } /* Under some conditions we can end up in a loop when size allocating. * This happens when the icons don't fit without a scrollbar, but fits * when a scrollbar is added (bug #129963 for details). * We keep track of this looping by increasing a counter in size_allocate * and clearing it in a high-prio idle (the only way to detect the loop is * done). * When we've done at more than two iterations (with/without scrollbar) * we terminate this looping by not redoing the layout when the width * is wider than the current one (i.e when removing the scrollbar). */ if (container->details->size_allocation_count_id == 0) { container->details->size_allocation_count_id = g_idle_add_full (G_PRIORITY_HIGH, clear_size_allocation_count, container, NULL); } container->details->size_allocation_count++; if (container->details->size_allocation_count > 2 && allocation->width >= wid_allocation.width) { need_layout_redone = FALSE; } GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->size_allocate (widget, allocation); container->details->has_been_allocated = TRUE; if (need_layout_redone) { nemo_icon_container_redo_layout (container); } } static GtkSizeRequestMode get_request_mode (GtkWidget *widget) { /* Don't trade size at all, since we get whatever we get anyway. */ return GTK_SIZE_REQUEST_CONSTANT_SIZE; } /* We need to implement these since the GtkScrolledWindow uses them to guess whether to show scrollbars or not, and if we don't report anything it'll tend to get it wrong causing double calls to size_allocate (at different sizes) during its size allocation. */ static void get_prefered_width (GtkWidget *widget, gint *minimum_size, gint *natural_size) { EelCanvasGroup *root; double x1, x2; int cx1, cx2; int width; root = eel_canvas_root (EEL_CANVAS (widget)); eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (root), &x1, NULL, &x2, NULL); eel_canvas_w2c (EEL_CANVAS (widget), x1, 0, &cx1, NULL); eel_canvas_w2c (EEL_CANVAS (widget), x2, 0, &cx2, NULL); width = cx2 - cx1; if (natural_size) { *natural_size = width; } if (minimum_size) { *minimum_size = width; } } static void get_prefered_height (GtkWidget *widget, gint *minimum_size, gint *natural_size) { EelCanvasGroup *root; double y1, y2; int cy1, cy2; int height; root = eel_canvas_root (EEL_CANVAS (widget)); eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (root), NULL, &y1, NULL, &y2); eel_canvas_w2c (EEL_CANVAS (widget), 0, y1, NULL, &cy1); eel_canvas_w2c (EEL_CANVAS (widget), 0, y2, NULL, &cy2); height = cy2 - cy1; if (natural_size) { *natural_size = height; } if (minimum_size) { *minimum_size = height; } } static void realize (GtkWidget *widget) { GtkAdjustment *vadj, *hadj; NemoIconContainer *container; GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->realize (widget); container = NEMO_ICON_CONTAINER (widget); /* Set up DnD. */ nemo_icon_dnd_init (container); hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (widget)); g_signal_connect (hadj, "value_changed", G_CALLBACK (handle_hadjustment_changed), widget); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (widget)); g_signal_connect (vadj, "value_changed", G_CALLBACK (handle_vadjustment_changed), widget); } static void unrealize (GtkWidget *widget) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (widget); nemo_icon_dnd_fini (container); remove_search_entry_timeout (container); GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->unrealize (widget); } static void style_updated (GtkWidget *widget) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (widget); container->details->use_drop_shadows = container->details->drop_shadows_requested; /* Don't chain up to parent, if this is a desktop container, * because that resets the background of the window. */ if (!nemo_icon_container_get_is_desktop (container)) { GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->style_updated (widget); } if (gtk_widget_get_realized (widget)) { nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); } } static gboolean button_press_event (GtkWidget *widget, GdkEventButton *event) { NemoIconContainer *container; gboolean selection_changed; gboolean return_value; gboolean clicked_on_item; container = NEMO_ICON_CONTAINER (widget); container->details->button_down_time = event->time; /* Forget about the old keyboard selection now that we've started mousing. */ clear_keyboard_focus (container); clear_keyboard_rubberband_start (container); if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { /* We use our own double-click detection. */ return TRUE; } /* Invoke the canvas event handler and see if an item picks up the event. */ clicked_on_item = GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->button_press_event (widget, event); /* Move focus to icon container, unless we're still renaming (to avoid exiting * renaming mode) */ if (!gtk_widget_has_focus (widget) && !(is_renaming (container) || is_renaming_pending (container))) { gtk_widget_grab_focus (widget); } if (clicked_on_item) { NemoIcon *icon; // current icon which was clicked on /* when icon is in renaming mode and user clicks on the image part of icon renaming should get closed */ icon = get_first_selected_icon (container); // this function gets the clicked icon if (clicked_on_icon (container, icon, event) && icon == nemo_icon_container_get_icon_being_renamed (container)) { nemo_icon_container_end_renaming_mode (container, TRUE); } return TRUE; } if (event->button == DRAG_BUTTON && event->type == GDK_BUTTON_PRESS) { /* Clear the last click icon for double click */ container->details->double_click_icon[1] = container->details->double_click_icon[0]; container->details->double_click_icon[0] = NULL; } /* Button 1 does rubber banding. */ if (event->button == RUBBERBAND_BUTTON) { if (! button_event_modifies_selection (event)) { selection_changed = unselect_all (container); if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } start_rubberbanding (container, event); return TRUE; } /* Prevent multi-button weirdness such as bug 6181 */ if (container->details->rubberband_info.active) { return TRUE; } /* Button 2 may be passed to the window manager. */ if (event->button == MIDDLE_BUTTON) { selection_changed = unselect_all (container); if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } g_signal_emit (widget, signals[MIDDLE_CLICK], 0, event); return TRUE; } /* Button 3 does a contextual menu. */ if (event->button == CONTEXTUAL_MENU_BUTTON) { nemo_icon_container_end_renaming_mode (container, TRUE); selection_changed = unselect_all (container); if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } g_signal_emit (widget, signals[CONTEXT_CLICK_BACKGROUND], 0, event); return TRUE; } /* Otherwise, we emit a button_press message. */ g_signal_emit (widget, signals[BUTTON_PRESS], 0, event, &return_value); return return_value; } static void nemo_icon_container_did_not_drag (NemoIconContainer *container, GdkEventButton *event) { NemoIconContainerDetails *details; gboolean selection_changed; static gint64 last_click_time = 0; static gint click_count = 0; gint double_click_time; gint64 current_time; details = container->details; if (details->icon_selected_on_button_down && ((event->state & GDK_CONTROL_MASK) != 0 || (event->state & GDK_SHIFT_MASK) == 0)) { if (button_event_modifies_selection (event)) { details->range_selection_base_icon = NULL; icon_toggle_selected (container, details->drag_icon); g_signal_emit (container, signals[SELECTION_CHANGED], 0); } else { details->range_selection_base_icon = details->drag_icon; selection_changed = select_one_unselect_others (container, details->drag_icon); if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } } if (details->drag_icon != NULL && (details->single_click_mode || event->button == MIDDLE_BUTTON)) { /* Determine click count */ g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container))), "gtk-double-click-time", &double_click_time, NULL); current_time = g_get_monotonic_time (); if (current_time - last_click_time < double_click_time * 1000) { click_count++; } else { click_count = 0; } /* Stash time for next compare */ last_click_time = current_time; /* If single-click mode, activate the selected icons, unless modifying * the selection or pressing for a very long time, or double clicking. */ if (click_count == 0 && event->time - details->button_down_time < MAX_CLICK_TIME && ! button_event_modifies_selection (event)) { /* It's a tricky UI issue whether this should activate * just the clicked item (as if it were a link), or all * the selected items (as if you were issuing an "activate * selection" command). For now, we're trying the activate * entire selection version to see how it feels. Note that * NemoList goes the other way because its "links" seem * much more link-like. */ if (event->button == MIDDLE_BUTTON) { activate_selected_items_alternate (container, NULL); } else { activate_selected_items (container); } } } if (details->drag_icon != NULL && handle_icon_slow_two_click (container, details->drag_icon, event)) { if (!details->skip_rename_on_release) nemo_icon_container_start_renaming_selected_item (container, FALSE); } } static gboolean clicked_within_double_click_interval (NemoIconContainer *container) { static gint64 last_click_time = 0; static gint click_count = 0; gint64 current_time; gint interval; /* fetch system double-click time */ g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container))), "gtk-double-click-time", &interval, NULL); current_time = g_get_monotonic_time (); if (current_time - last_click_time < interval * 1000) { click_count++; } else { click_count = 0; } /* Stash time for next compare */ last_click_time = current_time; /* Only allow double click */ if (click_count == 1) { click_count = 0; return TRUE; } else { return FALSE; } } static gboolean clicked_within_slow_click_interval_on_text (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { static gint64 last_slow_click_time = 0; static gint slow_click_count = 0; gint64 current_time; gint interval; gint double_click_interval; /* fetch system double-click time */ g_object_get (G_OBJECT (gtk_widget_get_settings (GTK_WIDGET (container))), "gtk-double-click-time", &double_click_interval, NULL); /* slow click interval is always 2 seconds longer than the system * double-click interval. */ interval = double_click_interval + 2000; current_time = g_get_monotonic_time (); if (current_time - last_slow_click_time < interval * 1000) { slow_click_count = 1; } else { slow_click_count = 0; } /* Stash time for next compare */ last_slow_click_time = current_time; /* Only allow second click on text to trigger this */ if (slow_click_count == 1 && icon == get_first_selected_icon (container) && clicked_on_text (container, icon, event)) { slow_click_count = 0; return TRUE; } else { return FALSE; } } static void clear_drag_state (NemoIconContainer *container) { container->details->drag_icon = NULL; container->details->drag_state = DRAG_STATE_INITIAL; } static gboolean start_stretching (NemoIconContainer *container) { NemoIconContainerDetails *details; NemoIcon *icon; GtkWidget *toplevel; GtkCornerType corner; GdkCursor *cursor; details = container->details; icon = details->stretch_icon; /* Check if we hit the stretch handles. */ if (!nemo_icon_canvas_item_hit_test_stretch_handles (icon->item, details->drag_x, details->drag_y, &corner)) { return FALSE; } switch (corner) { case GTK_CORNER_TOP_LEFT: cursor = gdk_cursor_new (GDK_TOP_LEFT_CORNER); break; case GTK_CORNER_BOTTOM_LEFT: cursor = gdk_cursor_new (GDK_BOTTOM_LEFT_CORNER); break; case GTK_CORNER_TOP_RIGHT: cursor = gdk_cursor_new (GDK_TOP_RIGHT_CORNER); break; case GTK_CORNER_BOTTOM_RIGHT: cursor = gdk_cursor_new (GDK_BOTTOM_RIGHT_CORNER); break; default: cursor = NULL; break; } /* Set up the dragging. */ details->drag_state = DRAG_STATE_STRETCH; eel_canvas_w2c (EEL_CANVAS (container), details->drag_x, details->drag_y, &details->stretch_start.pointer_x, &details->stretch_start.pointer_y); eel_canvas_w2c (EEL_CANVAS (container), icon->x, icon->y, &details->stretch_start.icon_x, &details->stretch_start.icon_y); icon_get_size (container, icon, &details->stretch_start.icon_size); eel_canvas_item_grab (EEL_CANVAS_ITEM (icon->item), (GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK), cursor, GDK_CURRENT_TIME); if (cursor) g_object_unref (cursor); /* Ensure the window itself is focused.. */ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (container)); if (toplevel != NULL && gtk_widget_get_realized (toplevel)) { gdk_window_focus (gtk_widget_get_window (toplevel), GDK_CURRENT_TIME); } return TRUE; } static gboolean update_stretch_at_idle (NemoIconContainer *container) { NemoIconContainerDetails *details; NemoIcon *icon; double world_x, world_y; StretchState stretch_state; details = container->details; icon = details->stretch_icon; if (icon == NULL) { container->details->stretch_idle_id = 0; return FALSE; } eel_canvas_w2c (EEL_CANVAS (container), details->world_x, details->world_y, &stretch_state.pointer_x, &stretch_state.pointer_y); compute_stretch (&details->stretch_start, &stretch_state); eel_canvas_c2w (EEL_CANVAS (container), stretch_state.icon_x, stretch_state.icon_y, &world_x, &world_y); nemo_icon_container_icon_set_position (container, icon, world_x, world_y); icon_set_size (container, icon, stretch_state.icon_size, FALSE, FALSE); container->details->stretch_idle_id = 0; return FALSE; } static void continue_stretching (NemoIconContainer *container, double world_x, double world_y) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->world_x = world_x; container->details->world_y = world_y; if (container->details->stretch_idle_id == 0) { container->details->stretch_idle_id = g_idle_add ((GSourceFunc) update_stretch_at_idle, container); } } static gboolean keyboard_stretching (NemoIconContainer *container, GdkEventKey *event) { NemoIcon *icon; guint size; icon = container->details->stretch_icon; if (icon == NULL || !icon->is_selected) { return FALSE; } icon_get_size (container, icon, &size); switch (event->keyval) { case GDK_KEY_equal: case GDK_KEY_plus: case GDK_KEY_KP_Add: icon_set_size (container, icon, size + 5, FALSE, FALSE); break; case GDK_KEY_minus: case GDK_KEY_KP_Subtract: icon_set_size (container, icon, size - 5, FALSE, FALSE); break; case GDK_KEY_0: case GDK_KEY_KP_0: nemo_icon_container_move_icon (container, icon, icon->x, icon->y, 1.0, FALSE, TRUE, TRUE); break; } return TRUE; } static void ungrab_stretch_icon (NemoIconContainer *container) { eel_canvas_item_ungrab (EEL_CANVAS_ITEM (container->details->stretch_icon->item), GDK_CURRENT_TIME); } static void end_stretching (NemoIconContainer *container, double world_x, double world_y) { NemoIconPosition position; NemoIcon *icon; continue_stretching (container, world_x, world_y); ungrab_stretch_icon (container); /* now that we're done stretching, update the icon's position */ icon = container->details->drag_icon; if (nemo_icon_container_is_layout_rtl (container)) { position.x = icon->saved_ltr_x = nemo_icon_container_get_mirror_x_position (container, icon, icon->x); } else { position.x = icon->x; } position.y = icon->y; position.scale = icon->scale; g_signal_emit (container, signals[ICON_POSITION_CHANGED], 0, icon->data, &position); clear_drag_state (container); nemo_icon_container_redo_layout (container); } static gboolean undo_stretching (NemoIconContainer *container) { NemoIcon *stretched_icon; stretched_icon = container->details->stretch_icon; if (stretched_icon == NULL) { return FALSE; } if (container->details->drag_state == DRAG_STATE_STRETCH) { ungrab_stretch_icon (container); clear_drag_state (container); } nemo_icon_canvas_item_set_show_stretch_handles (stretched_icon->item, FALSE); nemo_icon_container_icon_set_position (container, stretched_icon, container->details->stretch_initial_x, container->details->stretch_initial_y); icon_set_size (container, stretched_icon, container->details->stretch_initial_size, TRUE, TRUE); container->details->stretch_icon = NULL; emit_stretch_ended (container, stretched_icon); nemo_icon_container_redo_layout (container); return TRUE; } static gboolean button_release_event (GtkWidget *widget, GdkEventButton *event) { NemoIconContainer *container; NemoIconContainerDetails *details; double world_x, world_y; container = NEMO_ICON_CONTAINER (widget); details = container->details; if (event->button == RUBBERBAND_BUTTON && details->rubberband_info.active) { stop_rubberbanding (container, event->time); return TRUE; } if (event->button == details->drag_button) { details->drag_button = 0; switch (details->drag_state) { case DRAG_STATE_MOVE_OR_COPY: if (!details->drag_started) { nemo_icon_container_did_not_drag (container, event); } else { nemo_icon_dnd_end_drag (container); DEBUG ("Ending drag from icon container"); } break; case DRAG_STATE_STRETCH: eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &world_x, &world_y); end_stretching (container, world_x, world_y); break; default: break; } clear_drag_state (container); return TRUE; } return GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->button_release_event (widget, event); } static int motion_notify_event (GtkWidget *widget, GdkEventMotion *event) { NemoIconContainer *container; NemoIconContainerDetails *details; double world_x, world_y; int canvas_x, canvas_y; GdkDragAction actions; container = NEMO_ICON_CONTAINER (widget); details = container->details; if (details->drag_button != 0) { switch (details->drag_state) { case DRAG_STATE_MOVE_OR_COPY: if (details->drag_started) { break; } eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &world_x, &world_y); if (gtk_drag_check_threshold (widget, details->drag_x, details->drag_y, world_x, world_y)) { details->drag_started = TRUE; details->drag_state = DRAG_STATE_MOVE_OR_COPY; nemo_icon_container_end_renaming_mode (container, TRUE); eel_canvas_w2c (EEL_CANVAS (container), details->drag_x, details->drag_y, &canvas_x, &canvas_y); actions = GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_ASK; if (container->details->drag_allow_moves) { actions |= GDK_ACTION_MOVE; } nemo_icon_dnd_begin_drag (container, actions, details->drag_button, event, canvas_x, canvas_y); DEBUG ("Beginning drag from icon container"); } break; case DRAG_STATE_STRETCH: eel_canvas_window_to_world (EEL_CANVAS (container), event->x, event->y, &world_x, &world_y); continue_stretching (container, world_x, world_y); break; default: break; } } return GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->motion_notify_event (widget, event); } static void nemo_icon_container_search_position_func (NemoIconContainer *container, GtkWidget *search_dialog) { gint x, y; gint cont_x, cont_y; gint cont_width, cont_height; GdkWindow *cont_window; GtkRequisition requisition; gint monitor_num; GdkRectangle monitor; cont_window = gtk_widget_get_window (GTK_WIDGET (container)); monitor_num = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (container)); /* FIXME?? _NET_WORKAREA hint only provides accurate workarea geometry for the * primary monitor. Non-primary will return the full monitor geometry instead. */ nemo_desktop_utils_get_monitor_work_rect (monitor_num, &monitor); gtk_widget_realize (search_dialog); gdk_window_get_origin (cont_window, &cont_x, &cont_y); cont_width = gdk_window_get_width (cont_window); cont_height = gdk_window_get_height (cont_window); gtk_widget_get_preferred_size (search_dialog, &requisition, NULL); if (nemo_icon_container_get_is_desktop (container)) { x = cont_x + cont_width - requisition.width; y = cont_y + cont_height - requisition.height; } else { if (cont_x + cont_width > monitor.x + monitor.width) { x = monitor.x + monitor.width - requisition.width; } else if (cont_x + cont_width - requisition.width < 0) { x = 0; } else { x = cont_x + cont_width - requisition.width; } if (cont_y + cont_height + requisition.height > monitor.y + monitor.height) { y = monitor.y + monitor.height - requisition.height; } else if (cont_y + cont_height < 0) { y = 0; } else { y = cont_y + cont_height; } } gdk_window_move (gtk_widget_get_window (search_dialog), x, y); } /* Cut and paste from gtkwindow.c */ static void send_focus_change (GtkWidget *widget, gboolean in) { GdkEvent *fevent; fevent = gdk_event_new (GDK_FOCUS_CHANGE); g_object_ref (widget); ((GdkEventFocus *) fevent)->in = in; gtk_widget_send_focus_change (widget, fevent); fevent->focus_change.type = GDK_FOCUS_CHANGE; fevent->focus_change.window = g_object_ref (gtk_widget_get_window (widget)); fevent->focus_change.in = in; gtk_widget_event (widget, fevent); g_object_notify (G_OBJECT (widget), "has-focus"); g_object_unref (widget); gdk_event_free (fevent); } static void nemo_icon_container_search_dialog_hide (GtkWidget *search_dialog, NemoIconContainer *container) { if (container->details->search_entry_changed_id) { g_signal_handler_disconnect (container->details->search_entry, container->details->search_entry_changed_id); container->details->search_entry_changed_id = 0; } remove_search_entry_timeout (container); /* send focus-in event */ send_focus_change (GTK_WIDGET (container->details->search_entry), FALSE); gtk_widget_hide (search_dialog); gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), ""); } static gboolean nemo_icon_container_search_entry_flush_timeout (gpointer data) { NemoIconContainer *container = data; container->details->typeselect_flush_timeout = 0; nemo_icon_container_search_dialog_hide (container->details->search_window, container); return FALSE; } static void add_search_entry_timeout (NemoIconContainer *container) { container->details->typeselect_flush_timeout = g_timeout_add_seconds (NEMO_ICON_CONTAINER_SEARCH_DIALOG_TIMEOUT, nemo_icon_container_search_entry_flush_timeout, container); } static void remove_search_entry_timeout (NemoIconContainer *container) { if (container->details->typeselect_flush_timeout) { g_source_remove (container->details->typeselect_flush_timeout); container->details->typeselect_flush_timeout = 0; } } static void reset_search_entry_timeout (NemoIconContainer *container) { remove_search_entry_timeout (container); add_search_entry_timeout (container); } /* Because we're visible but offscreen, we just set a flag in the preedit * callback. */ static void nemo_icon_container_search_preedit_changed (GtkEntry *entry, gchar *preedit, NemoIconContainer *container) { container->details->imcontext_changed = 1; reset_search_entry_timeout (container); } static void nemo_icon_container_search_activate (GtkEntry *entry, NemoIconContainer *container) { nemo_icon_container_search_dialog_hide (container->details->search_window, container); activate_selected_items (container); } static gboolean nemo_icon_container_search_delete_event (GtkWidget *widget, GdkEventAny *event, NemoIconContainer *container) { nemo_icon_container_search_dialog_hide (widget, container); return TRUE; } static gboolean nemo_icon_container_search_button_press_event (GtkWidget *widget, GdkEventButton *event, NemoIconContainer *container) { nemo_icon_container_search_dialog_hide (widget, container); if (event->window == gtk_layout_get_bin_window (GTK_LAYOUT (container))) { button_press_event (GTK_WIDGET (container), event); } return TRUE; } static gboolean nemo_icon_container_search_entry_button_press_event (GtkWidget *widget, GdkEventButton *event, NemoIconContainer *container) { reset_search_entry_timeout (container); return FALSE; } static void nemo_icon_container_search_populate_popup (GtkEntry *entry, GtkMenu *menu, NemoIconContainer *container) { remove_search_entry_timeout (container); g_signal_connect_swapped (menu, "hide", G_CALLBACK (add_search_entry_timeout), container); } void nemo_icon_container_get_icon_text (NemoIconContainer *container, NemoIconData *data, char **editable_text, char **additional_text, gboolean include_invisible) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->get_icon_text != NULL); klass->get_icon_text (container, data, editable_text, additional_text, include_invisible); } static gboolean nemo_icon_container_search_iter (NemoIconContainer *container, const char *key, gint n) { GList *p; NemoIcon *icon; char *name; int count; char *normalized_key, *case_normalized_key; char *normalized_name, *case_normalized_name; g_assert (key != NULL); g_assert (n >= 1); normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL); if (!normalized_key) { return FALSE; } case_normalized_key = g_utf8_casefold (normalized_key, -1); g_free (normalized_key); if (!case_normalized_key) { return FALSE; } icon = NULL; name = NULL; count = 0; for (p = container->details->icons; p != NULL && count != n; p = p->next) { icon = p->data; nemo_icon_container_get_icon_text (container, icon->data, &name, NULL, TRUE); /* This can happen if a key event is handled really early while * loading the icon container, before the items have all been * updated once. */ if (!name) { continue; } normalized_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL); if (!normalized_name) { continue; } case_normalized_name = g_utf8_casefold (normalized_name, -1); g_free (normalized_name); if (!case_normalized_name) { continue; } if (strncmp (case_normalized_key, case_normalized_name, strlen (case_normalized_key)) == 0) { count++; } g_free (case_normalized_name); g_free (name); name = NULL; } g_free (case_normalized_key); if (count == n) { if (select_one_unselect_others (container, icon)) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } schedule_keyboard_icon_reveal (container, icon); return TRUE; } return FALSE; } static void nemo_icon_container_search_move (GtkWidget *window, NemoIconContainer *container, gboolean up) { gboolean ret; gint len; const gchar *text; text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)); g_assert (text != NULL); if (container->details->selected_iter == 0) { return; } if (up && container->details->selected_iter == 1) { return; } len = strlen (text); if (len < 1) { return; } /* search */ unselect_all (container); ret = nemo_icon_container_search_iter (container, text, up?((container->details->selected_iter) - 1):((container->details->selected_iter + 1))); if (ret) { /* found */ container->details->selected_iter += up?(-1):(1); } else { /* return to old iter */ nemo_icon_container_search_iter (container, text, container->details->selected_iter); } } static gboolean nemo_icon_container_search_scroll_event (GtkWidget *widget, GdkEventScroll *event, NemoIconContainer *container) { gboolean retval = FALSE; if (event->direction == GDK_SCROLL_UP) { nemo_icon_container_search_move (widget, container, TRUE); retval = TRUE; } else if (event->direction == GDK_SCROLL_DOWN) { nemo_icon_container_search_move (widget, container, FALSE); retval = TRUE; } reset_search_entry_timeout (container); return retval; } static gboolean nemo_icon_container_search_key_press_event (GtkWidget *widget, GdkEventKey *event, NemoIconContainer *container) { gboolean retval = FALSE; g_assert (GTK_IS_WIDGET (widget)); g_assert (NEMO_IS_ICON_CONTAINER (container)); /* close window and cancel the search */ if (event->keyval == GDK_KEY_Escape || event->keyval == GDK_KEY_Tab) { nemo_icon_container_search_dialog_hide (widget, container); return TRUE; } /* close window and activate alternate */ if (event->keyval == GDK_KEY_Return && event->state & GDK_SHIFT_MASK) { nemo_icon_container_search_dialog_hide (widget, container); activate_selected_items_alternate (container, NULL); return TRUE; } /* select previous matching iter */ if (event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) { nemo_icon_container_search_move (widget, container, TRUE); retval = TRUE; } if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) { nemo_icon_container_search_move (widget, container, TRUE); retval = TRUE; } /* select next matching iter */ if (event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down) { nemo_icon_container_search_move (widget, container, FALSE); retval = TRUE; } if (((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) == GDK_CONTROL_MASK) && (event->keyval == GDK_KEY_g || event->keyval == GDK_KEY_G)) { nemo_icon_container_search_move (widget, container, FALSE); retval = TRUE; } reset_search_entry_timeout (container); return retval; } static void nemo_icon_container_search_init (GtkWidget *entry, NemoIconContainer *container) { gint ret; gint len; const gchar *text; g_assert (GTK_IS_ENTRY (entry)); g_assert (NEMO_IS_ICON_CONTAINER (container)); text = gtk_entry_get_text (GTK_ENTRY (entry)); len = strlen (text); /* search */ unselect_all (container); reset_search_entry_timeout (container); if (len < 1) { return; } ret = nemo_icon_container_search_iter (container, text, 1); if (ret) { container->details->selected_iter = 1; } } static void nemo_icon_container_ensure_interactive_directory (NemoIconContainer *container) { GtkWidget *frame, *vbox; if (container->details->search_window != NULL) { return; } container->details->search_window = gtk_window_new (GTK_WINDOW_POPUP); gtk_window_set_modal (GTK_WINDOW (container->details->search_window), TRUE); gtk_window_set_type_hint (GTK_WINDOW (container->details->search_window), GDK_WINDOW_TYPE_HINT_COMBO); g_signal_connect (container->details->search_window, "delete_event", G_CALLBACK (nemo_icon_container_search_delete_event), container); g_signal_connect (container->details->search_window, "key_press_event", G_CALLBACK (nemo_icon_container_search_key_press_event), container); g_signal_connect (container->details->search_window, "button_press_event", G_CALLBACK (nemo_icon_container_search_button_press_event), container); g_signal_connect (container->details->search_window, "scroll_event", G_CALLBACK (nemo_icon_container_search_scroll_event), container); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); gtk_widget_show (frame); gtk_container_add (GTK_CONTAINER (container->details->search_window), frame); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_widget_show (vbox); gtk_container_add (GTK_CONTAINER (frame), vbox); gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); /* add entry */ container->details->search_entry = gtk_entry_new (); gtk_widget_show (container->details->search_entry); g_signal_connect (container->details->search_entry, "populate-popup", G_CALLBACK (nemo_icon_container_search_populate_popup), container); g_signal_connect (container->details->search_entry, "activate", G_CALLBACK (nemo_icon_container_search_activate), container); g_signal_connect (container->details->search_entry, "preedit-changed", G_CALLBACK (nemo_icon_container_search_preedit_changed), container); g_signal_connect (container->details->search_entry, "button-press-event", G_CALLBACK (nemo_icon_container_search_entry_button_press_event), container); gtk_container_add (GTK_CONTAINER (vbox), container->details->search_entry); gtk_widget_realize (container->details->search_entry); } /* Pops up the interactive search entry. If keybinding is TRUE then the user * started this by typing the start_interactive_search keybinding. Otherwise, it came from */ static gboolean nemo_icon_container_start_interactive_search (NemoIconContainer *container) { /* We only start interactive search if we have focus. If one of our * children have focus, we don't want to start the search. */ GtkWidgetClass *entry_parent_class; if (container->details->search_window != NULL && gtk_widget_get_visible (container->details->search_window)) { return TRUE; } if (!gtk_widget_has_focus (GTK_WIDGET (container))) { return FALSE; } nemo_icon_container_ensure_interactive_directory (container); /* done, show it */ nemo_icon_container_search_position_func (container, container->details->search_window); gtk_widget_show (container->details->search_window); if (container->details->search_entry_changed_id == 0) { container->details->search_entry_changed_id = g_signal_connect (container->details->search_entry, "changed", G_CALLBACK (nemo_icon_container_search_init), container); } /* Grab focus will select all the text. We don't want that to happen, so we * call the parent instance and bypass the selection change. This is probably * really non-kosher. */ entry_parent_class = g_type_class_peek_parent (GTK_ENTRY_GET_CLASS (container->details->search_entry)); (entry_parent_class->grab_focus) (container->details->search_entry); /* send focus-in event */ send_focus_change (container->details->search_entry, TRUE); /* search first matching iter */ nemo_icon_container_search_init (container->details->search_entry, container); return TRUE; } static gboolean handle_popups (NemoIconContainer *container, GdkEventKey *event, const char *signal) { GdkEventButton button_event = { 0 }; /* ensure we clear the drag state before showing the menu */ clear_drag_state (container); g_signal_emit_by_name (container, signal, &button_event); return TRUE; } static int key_press_event (GtkWidget *widget, GdkEventKey *event) { NemoIconContainer *container; gboolean handled; container = NEMO_ICON_CONTAINER (widget); handled = FALSE; if (is_renaming (container) || is_renaming_pending (container)) { switch (event->keyval) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: nemo_icon_container_end_renaming_mode (container, TRUE); handled = TRUE; break; case GDK_KEY_Escape: nemo_icon_container_end_renaming_mode (container, FALSE); handled = TRUE; break; default: break; } } else if (container->details->search_window != NULL && gtk_widget_get_visible (container->details->search_window)) { /* Workaround for BGO #662591, where container is still focused * although we're in search mode. Forward events to * search_entry, where they belong. */ GdkEvent *new_event = gdk_event_copy ((GdkEvent *) event); GdkWindow *window = ((GdkEventKey *) new_event)->window; ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry); handled = gtk_widget_event (container->details->search_window, new_event); ((GdkEventKey *) new_event)->window = window; gdk_event_free(new_event); } else { switch (event->keyval) { case GDK_KEY_Home: case GDK_KEY_KP_Home: keyboard_home (container, event); handled = TRUE; break; case GDK_KEY_End: case GDK_KEY_KP_End: keyboard_end (container, event); handled = TRUE; break; case GDK_KEY_Left: case GDK_KEY_KP_Left: /* Don't eat Alt-Left, as that is used for history browsing */ if ((event->state & GDK_MOD1_MASK) == 0) { keyboard_left (container, event); handled = TRUE; } break; case GDK_KEY_Up: case GDK_KEY_KP_Up: /* Don't eat Alt-Up, as that is used for alt-shift-Up */ if ((event->state & GDK_MOD1_MASK) == 0) { keyboard_up (container, event); handled = TRUE; } break; case GDK_KEY_Right: case GDK_KEY_KP_Right: /* Don't eat Alt-Right, as that is used for history browsing */ if ((event->state & GDK_MOD1_MASK) == 0) { keyboard_right (container, event); handled = TRUE; } break; case GDK_KEY_Down: case GDK_KEY_KP_Down: /* Don't eat Alt-Down, as that is used for Open */ if ((event->state & GDK_MOD1_MASK) == 0) { keyboard_down (container, event); handled = TRUE; } break; case GDK_KEY_space: keyboard_space (container, event); handled = TRUE; break; #ifndef TAB_NAVIGATION_DISABLED case GDK_KEY_Tab: case GDK_KEY_ISO_Left_Tab: select_previous_or_next_icon (container, (event->state & GDK_SHIFT_MASK) == 0, event); handled = TRUE; break; #endif case GDK_KEY_Return: case GDK_KEY_KP_Enter: if ((event->state & GDK_SHIFT_MASK) != 0) { activate_selected_items_alternate (container, NULL); } else { activate_selected_items (container); } handled = TRUE; break; case GDK_KEY_Escape: handled = undo_stretching (container); break; case GDK_KEY_plus: case GDK_KEY_minus: case GDK_KEY_equal: case GDK_KEY_KP_Add: case GDK_KEY_KP_Subtract: case GDK_KEY_0: case GDK_KEY_KP_0: if (event->state & GDK_CONTROL_MASK) { handled = keyboard_stretching (container, event); } break; case GDK_KEY_F10: /* handle Ctrl+F10 because we want to display the * background popup even if something is selected. * The other cases are handled by popup_menu(). */ if (event->state & GDK_CONTROL_MASK) { handled = handle_popups (container, event, "context_click_background"); } break; case GDK_KEY_v: /* Eat Control + v to not enable type ahead */ if ((event->state & GDK_CONTROL_MASK) != 0) { handled = TRUE; } break; default: break; } } if (!handled) { handled = GTK_WIDGET_CLASS (nemo_icon_container_parent_class)->key_press_event (widget, event); } /* We pass the event to the search_entry. If its text changes, then we * start the typeahead find capabilities. * Copied from NemoIconContainer */ if (!handled && event->keyval != GDK_KEY_asciitilde && event->keyval != GDK_KEY_KP_Divide && event->keyval != GDK_KEY_slash /* don't steal slash key events, used for "go to" */ && event->keyval != GDK_KEY_BackSpace && event->keyval != GDK_KEY_Delete) { GdkEvent *new_event; GdkWindow *window; char *old_text; const char *new_text; gboolean retval; gboolean text_modified; gulong popup_menu_id; nemo_icon_container_ensure_interactive_directory (container); /* Make a copy of the current text */ old_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (container->details->search_entry))); new_event = gdk_event_copy ((GdkEvent *) event); window = ((GdkEventKey *) new_event)->window; ((GdkEventKey *) new_event)->window = gtk_widget_get_window (container->details->search_entry); gtk_widget_realize (container->details->search_window); popup_menu_id = g_signal_connect (container->details->search_entry, "popup_menu", G_CALLBACK (gtk_true), NULL); gtk_widget_show (container->details->search_window); /* Send the event to the window. If the preedit_changed signal is emitted * during this event, we will set priv->imcontext_changed */ container->details->imcontext_changed = FALSE; retval = gtk_widget_event (container->details->search_entry, new_event); gtk_widget_hide (container->details->search_window); g_signal_handler_disconnect (container->details->search_entry, popup_menu_id); /* We check to make sure that the entry tried to handle the text, and that * the text has changed. */ new_text = gtk_entry_get_text (GTK_ENTRY (container->details->search_entry)); text_modified = strcmp (old_text, new_text) != 0; g_free (old_text); if (container->details->imcontext_changed || /* we're in a preedit */ (retval && text_modified)) { /* ...or the text was modified */ if (nemo_icon_container_start_interactive_search (container)) { gtk_widget_grab_focus (GTK_WIDGET (container)); return TRUE; } else { gtk_entry_set_text (GTK_ENTRY (container->details->search_entry), ""); return FALSE; } } ((GdkEventKey *) new_event)->window = window; gdk_event_free (new_event); } return handled; } static gboolean popup_menu (GtkWidget *widget) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (widget); if (has_selection (container)) { handle_popups (container, NULL, "context_click_selection"); } else { handle_popups (container, NULL, "context_click_background"); } return TRUE; } static void draw_canvas_background (EelCanvas *canvas, cairo_t *cr) { /* Don't chain up to the parent to avoid clearing and redrawing. * This is overridden by nemo-icon-view-grid-container. */ return; } static AtkObject * get_accessible (GtkWidget *widget) { AtkObject *accessible; if ((accessible = eel_accessibility_get_atk_object (widget))) { return accessible; } accessible = g_object_new (nemo_icon_container_accessible_get_type (), NULL); return eel_accessibility_set_atk_object_return (widget, accessible); } static void grab_notify_cb (GtkWidget *widget, gboolean was_grabbed) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (widget); if (container->details->rubberband_info.active && !was_grabbed) { /* we got a (un)grab-notify during rubberband. * This happens when a new modal dialog shows * up (e.g. authentication or an error). Stop * the rubberbanding so that we can handle the * dialog. */ stop_rubberbanding (container, GDK_CURRENT_TIME); } } static void text_ellipsis_limit_changed_container_callback (gpointer callback_data) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (callback_data); invalidate_label_sizes (container); schedule_redo_layout (container); } static void real_lay_down_icons (NemoIconContainer *container, GList *icons, double start_y) { g_assert_not_reached (); } static void real_icon_set_position (NemoIconContainer *container, NemoIcon *icon, double x, double y) { g_assert_not_reached (); } static void real_move_icon (NemoIconContainer *container, NemoIcon *icon, int x, int y, double scale, gboolean raise, gboolean snap, gboolean update_position) { g_assert_not_reached (); } static void real_update_icon (NemoIconContainer *container, NemoIcon *icon) { g_assert_not_reached (); } static void real_align_icons (NemoIconContainer *container) { g_assert_not_reached (); } static void real_icon_get_bounding_box (NemoIcon *icon, int *x1_return, int *y1_return, int *x2_return, int *y2_return, NemoIconCanvasItemBoundsUsage usage) { g_assert_not_reached (); } static void real_set_zoom_level (NemoIconContainer *container, gint new_level) { g_assert_not_reached (); } /* Initialization. */ static void nemo_icon_container_class_init (NemoIconContainerClass *class) { GtkWidgetClass *widget_class; EelCanvasClass *canvas_class; G_OBJECT_CLASS (class)->finalize = finalize; class->lay_down_icons = real_lay_down_icons; class->icon_set_position = real_icon_set_position; class->move_icon = real_move_icon; class->update_icon = real_update_icon; class->align_icons = real_align_icons; class->finish_adding_new_icons = NULL; class->icon_get_bounding_box = real_icon_get_bounding_box; class->set_zoom_level = real_set_zoom_level; class->is_grid_container = FALSE; /* Signals. */ signals[SELECTION_CHANGED] = g_signal_new ("selection_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[BUTTON_PRESS] = g_signal_new ("button_press", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, button_press), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT); signals[ACTIVATE] = g_signal_new ("activate", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, activate), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ACTIVATE_ALTERNATE] = g_signal_new ("activate_alternate", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, activate_alternate), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ACTIVATE_PREVIEWER] = g_signal_new ("activate_previewer", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, activate_previewer), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[CONTEXT_CLICK_SELECTION] = g_signal_new ("context_click_selection", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, context_click_selection), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[CONTEXT_CLICK_BACKGROUND] = g_signal_new ("context_click_background", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, context_click_background), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[MIDDLE_CLICK] = g_signal_new ("middle_click", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, middle_click), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ICON_POSITION_CHANGED] = g_signal_new ("icon_position_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_position_changed), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[ICON_STRETCH_STARTED] = g_signal_new ("icon_stretch_started", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_stretch_started), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ICON_STRETCH_ENDED] = g_signal_new ("icon_stretch_ended", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_stretch_ended), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ICON_RENAME_STARTED] = g_signal_new ("icon_rename_started", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_rename_started), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ICON_RENAME_ENDED] = g_signal_new ("icon_rename_ended", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_rename_ended), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING); signals[GET_ICON_URI] = g_signal_new ("get_icon_uri", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, get_icon_uri), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_STRING, 1, G_TYPE_POINTER); signals[GET_ICON_DROP_TARGET_URI] = g_signal_new ("get_icon_drop_target_uri", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, get_icon_drop_target_uri), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_STRING, 1, G_TYPE_POINTER); signals[MOVE_COPY_ITEMS] = g_signal_new ("move_copy_items", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, move_copy_items), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_NETSCAPE_URL] = g_signal_new ("handle_netscape_url", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, handle_netscape_url), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_URI_LIST] = g_signal_new ("handle_uri_list", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, handle_uri_list), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_TEXT] = g_signal_new ("handle_text", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, handle_text), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 5, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[HANDLE_RAW] = g_signal_new ("handle_raw", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, handle_raw), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 7, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_DRAG_ACTION, G_TYPE_INT, G_TYPE_INT); signals[GET_CONTAINER_URI] = g_signal_new ("get_container_uri", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, get_container_uri), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_STRING, 0); signals[CAN_ACCEPT_ITEM] = g_signal_new ("can_accept_item", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, can_accept_item), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_INT, 2, G_TYPE_POINTER, G_TYPE_STRING); signals[GET_STORED_LAYOUT_TIMESTAMP] = g_signal_new ("get_stored_layout_timestamp", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, get_stored_layout_timestamp), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[STORE_LAYOUT_TIMESTAMP] = g_signal_new ("store_layout_timestamp", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, store_layout_timestamp), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 2, G_TYPE_POINTER, G_TYPE_POINTER); signals[LAYOUT_CHANGED] = g_signal_new ("layout_changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, layout_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[BAND_SELECT_STARTED] = g_signal_new ("band_select_started", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, band_select_started), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[BAND_SELECT_ENDED] = g_signal_new ("band_select_ended", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, band_select_ended), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[ICON_ADDED] = g_signal_new ("icon_added", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_added), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[ICON_REMOVED] = g_signal_new ("icon_removed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, icon_removed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[CLEARED] = g_signal_new ("cleared", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoIconContainerClass, cleared), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /* GtkWidget class. */ widget_class = GTK_WIDGET_CLASS (class); widget_class->destroy = destroy; widget_class->size_allocate = size_allocate; widget_class->get_request_mode = get_request_mode; widget_class->get_preferred_width = get_prefered_width; widget_class->get_preferred_height = get_prefered_height; widget_class->realize = realize; widget_class->unrealize = unrealize; widget_class->button_press_event = button_press_event; widget_class->button_release_event = button_release_event; widget_class->motion_notify_event = motion_notify_event; widget_class->key_press_event = key_press_event; widget_class->popup_menu = popup_menu; widget_class->get_accessible = get_accessible; widget_class->style_updated = style_updated; widget_class->grab_notify = grab_notify_cb; canvas_class = EEL_CANVAS_CLASS (class); canvas_class->draw_background = draw_canvas_background; gtk_widget_class_install_style_property (widget_class, g_param_spec_boolean ("activate_prelight_icon_label", "Activate Prelight Icon Label", "Whether icon labels should make use of its prelight color in prelight state", FALSE, G_PARAM_READABLE)); } static void update_selected (NemoIconContainer *container) { GList *node; NemoIcon *icon; for (node = container->details->icons; node != NULL; node = node->next) { icon = node->data; if (icon->is_selected) { eel_canvas_item_request_update (EEL_CANVAS_ITEM (icon->item)); } } } static gboolean handle_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) { update_selected (NEMO_ICON_CONTAINER (widget)); return FALSE; } static gboolean handle_focus_out_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) { /* End renaming and commit change. */ nemo_icon_container_end_renaming_mode (NEMO_ICON_CONTAINER (widget), TRUE); update_selected (NEMO_ICON_CONTAINER (widget)); return FALSE; } static void nemo_icon_container_init (NemoIconContainer *container) { NemoIconContainerDetails *details; details = g_new0 (NemoIconContainerDetails, 1); details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal); details->layout_timestamp = UNDEFINED_TIME; details->zoom_level = NEMO_ZOOM_LEVEL_STANDARD; details->font_size_table[NEMO_ZOOM_LEVEL_SMALLEST] = -2 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_SMALLER] = -2 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_SMALL] = -0 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_STANDARD] = 0 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_LARGE] = 0 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_LARGER] = 0 * PANGO_SCALE; details->font_size_table[NEMO_ZOOM_LEVEL_LARGEST] = 0 * PANGO_SCALE; details->view_constants = g_slice_new0 (NemoViewLayoutConstants); container->details = details; g_signal_connect (container, "focus-in-event", G_CALLBACK (handle_focus_in_event), NULL); g_signal_connect (container, "focus-out-event", G_CALLBACK (handle_focus_out_event), NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIPS_DESKTOP, G_CALLBACK (tooltip_prefs_changed_callback), container); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIPS_ICON_VIEW, G_CALLBACK (tooltip_prefs_changed_callback), container); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIP_FILE_TYPE, G_CALLBACK (tooltip_prefs_changed_callback), container); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIP_MOD_DATE, G_CALLBACK (tooltip_prefs_changed_callback), container); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIP_ACCESS_DATE, G_CALLBACK (tooltip_prefs_changed_callback), container); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_TOOLTIP_FULL_PATH, G_CALLBACK (tooltip_prefs_changed_callback), container); container->details->show_desktop_tooltips = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIPS_DESKTOP); container->details->show_icon_view_tooltips = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_TOOLTIPS_ICON_VIEW); container->details->tooltip_flags = nemo_global_preferences_get_tooltip_flags (); details->skip_rename_on_release = FALSE; details->dnd_grid = NULL; } typedef struct { NemoIconContainer *container; GdkEventButton *event; } ContextMenuParameters; static gboolean handle_icon_double_click (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { NemoIconContainerDetails *details; if (event->button != DRAG_BUTTON) { return FALSE; } details = container->details; if (!details->single_click_mode && clicked_within_double_click_interval (container) && details->double_click_icon[0] == details->double_click_icon[1] && details->double_click_button[0] == details->double_click_button[1]) { if (!button_event_modifies_selection (event)) { activate_selected_items (container); return TRUE; } else if ((event->state & GDK_CONTROL_MASK) == 0 && (event->state & GDK_SHIFT_MASK) != 0) { activate_selected_items_alternate (container, icon); return TRUE; } } return FALSE; } static gboolean handle_icon_slow_two_click (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { NemoIconContainerDetails *details; NemoFile *file = NEMO_FILE (icon->data); if (!nemo_file_can_rename (file)) return FALSE; if (event->button != DRAG_BUTTON) { return FALSE; } details = container->details; if (!details->click_to_rename) return FALSE; GList *selection = nemo_icon_container_get_selection (container); gint selected_count = g_list_length (selection); g_list_free (selection); if (selected_count != 1) return FALSE; if (!details->single_click_mode && clicked_within_slow_click_interval_on_text (container, icon, event) && details->double_click_icon[0] == details->double_click_icon[1] && details->double_click_button[0] == details->double_click_button[1]) { if (!button_event_modifies_selection (event)) { return TRUE; } } return FALSE; } /* NemoIcon event handling. */ /* Conceptually, pressing button 1 together with CTRL or SHIFT toggles * selection of a single icon without affecting the other icons; * without CTRL or SHIFT, it selects a single icon and un-selects all * the other icons. But in this latter case, the de-selection should * only happen when the button is released if the icon is already * selected, because the user might select multiple icons and drag all * of them by doing a simple click-drag. */ static gboolean handle_icon_button_press (NemoIconContainer *container, NemoIcon *icon, GdkEventButton *event) { NemoIconContainerDetails *details; details = container->details; details->skip_rename_on_release = FALSE; if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { return TRUE; } if (event->button != DRAG_BUTTON && event->button != CONTEXTUAL_MENU_BUTTON && event->button != DRAG_MENU_BUTTON) { return TRUE; } if ((event->button == DRAG_BUTTON) && event->type == GDK_BUTTON_PRESS) { /* The next double click has to be on this icon */ details->double_click_icon[1] = details->double_click_icon[0]; details->double_click_icon[0] = icon; details->double_click_button[1] = details->double_click_button[0]; details->double_click_button[0] = event->button; } if (handle_icon_double_click (container, icon, event)) { /* Double clicking does not trigger a D&D action. */ details->drag_button = 0; details->drag_icon = NULL; return TRUE; } if (event->button == DRAG_BUTTON || event->button == DRAG_MENU_BUTTON) { details->drag_button = event->button; details->drag_icon = icon; details->drag_x = event->x; details->drag_y = event->y; details->drag_state = DRAG_STATE_MOVE_OR_COPY; details->drag_started = FALSE; /* Check to see if this is a click on the stretch handles. * If so, it won't modify the selection. */ if (icon == container->details->stretch_icon) { if (start_stretching (container)) { return TRUE; } } } /* Modify the selection as appropriate. Selection is modified * the same way for contextual menu as it would be without. */ details->icon_selected_on_button_down = icon->is_selected; GList *sel = nemo_icon_container_get_selected_icons (container); details->skip_rename_on_release = g_list_length (sel) > 1; g_list_free (sel); if ((event->button == DRAG_BUTTON || event->button == MIDDLE_BUTTON) && (event->state & GDK_SHIFT_MASK) != 0) { NemoIcon *start_icon; start_icon = details->range_selection_base_icon; if (start_icon == NULL || !start_icon->is_selected) { start_icon = icon; details->range_selection_base_icon = icon; } if (select_range (container, start_icon, icon, (event->state & GDK_CONTROL_MASK) == 0)) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } else if (!details->icon_selected_on_button_down) { details->range_selection_base_icon = icon; if (button_event_modifies_selection (event)) { icon_toggle_selected (container, icon); g_signal_emit (container, signals[SELECTION_CHANGED], 0); } else { select_one_unselect_others (container, icon); g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } if (event->button == CONTEXTUAL_MENU_BUTTON) { clear_drag_state (container); g_signal_emit (container, signals[CONTEXT_CLICK_SELECTION], 0, event); } return TRUE; } static int item_event_callback (EelCanvasItem *item, GdkEvent *event, gpointer data) { NemoIconContainer *container; NemoIcon *icon; container = NEMO_ICON_CONTAINER (data); icon = NEMO_ICON_CANVAS_ITEM (item)->user_data; g_assert (icon != NULL); switch (event->type) { case GDK_BUTTON_PRESS: if (handle_icon_button_press (container, icon, &event->button)) { /* Stop the event from being passed along further. Returning * TRUE ain't enough. */ return TRUE; } return FALSE; default: return FALSE; } } GtkWidget * nemo_icon_container_new (void) { return gtk_widget_new (NEMO_TYPE_ICON_CONTAINER, NULL); } /* Clear all of the icons in the container. */ void nemo_icon_container_clear (NemoIconContainer *container) { NemoIconContainerDetails *details; NemoIcon *icon; GList *p; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); details = container->details; details->layout_timestamp = UNDEFINED_TIME; details->store_layout_timestamps_when_finishing_new_icons = FALSE; if (details->icons == NULL) { return; } nemo_icon_container_end_renaming_mode (container, TRUE); clear_keyboard_focus (container); clear_keyboard_rubberband_start (container); unschedule_keyboard_icon_reveal (container); set_pending_icon_to_reveal (container, NULL); details->stretch_icon = NULL; details->drop_target = NULL; for (p = details->icons; p != NULL; p = p->next) { icon = p->data; if (icon->is_monitored) { nemo_icon_container_stop_monitor_top_left (container, icon->data, icon); } icon_free (p->data); } g_list_free (details->icons); details->icons = NULL; g_list_free (details->new_icons); details->new_icons = NULL; g_hash_table_destroy (details->icon_set); details->icon_set = g_hash_table_new (g_direct_hash, g_direct_equal); nemo_icon_container_update_scroll_region (container); } gboolean nemo_icon_container_is_empty (NemoIconContainer *container) { return container->details->icons == NULL; } NemoIconData * nemo_icon_container_get_first_visible_icon (NemoIconContainer *container) { GList *l; NemoIcon *icon, *best_icon; double x, y; double x1, y1, x2, y2; double *pos, best_pos; double hadj_v, vadj_v, h_page_size; gboolean better_icon; gboolean compare_lt; hadj_v = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); vadj_v = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container))); h_page_size = gtk_adjustment_get_page_size (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container))); if (nemo_icon_container_is_layout_rtl (container)) { x = hadj_v + h_page_size - GET_VIEW_CONSTANT (container, icon_pad_left) - 1; y = vadj_v; } else { x = hadj_v; y = vadj_v; } eel_canvas_c2w (EEL_CANVAS (container), x, y, &x, &y); l = container->details->icons; best_icon = NULL; best_pos = 0; while (l != NULL) { icon = l->data; if (nemo_icon_container_icon_is_positioned (icon)) { eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item), &x1, &y1, &x2, &y2); compare_lt = FALSE; if (nemo_icon_container_is_layout_vertical (container)) { pos = &x1; if (nemo_icon_container_is_layout_rtl (container)) { compare_lt = TRUE; better_icon = x1 < x + GET_VIEW_CONSTANT (container, icon_pad_left); } else { better_icon = x2 > x + GET_VIEW_CONSTANT (container, icon_pad_left); } } else { pos = &y1; better_icon = y2 > y + GET_VIEW_CONSTANT (container, icon_pad_top); } if (better_icon) { if (best_icon == NULL) { better_icon = TRUE; } else if (compare_lt) { better_icon = best_pos < *pos; } else { better_icon = best_pos > *pos; } if (better_icon) { best_icon = icon; best_pos = *pos; } } } l = l->next; } return best_icon ? best_icon->data : NULL; } /* puts the icon at the top of the screen */ void nemo_icon_container_scroll_to_icon (NemoIconContainer *container, NemoIconData *data) { GList *l; NemoIcon *icon; GtkAdjustment *hadj, *vadj; EelIRect bounds; GtkAllocation allocation; hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)); gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); /* We need to force a relayout now if there are updates queued * since we need the final positions */ nemo_icon_container_layout_now (container); l = container->details->icons; while (l != NULL) { icon = l->data; if (icon->data == data && nemo_icon_container_icon_is_positioned (icon)) { if (nemo_icon_container_is_auto_layout (container)) { /* ensure that we reveal the entire row/column */ icon_get_row_and_column_bounds (container, icon, &bounds, TRUE); } else { item_get_canvas_bounds (container, EEL_CANVAS_ITEM (icon->item), &bounds, TRUE); } if (nemo_icon_container_is_layout_vertical (container)) { if (nemo_icon_container_is_layout_rtl (container)) { gtk_adjustment_set_value (hadj, bounds.x1 - allocation.width); } else { gtk_adjustment_set_value (hadj, bounds.x0); } } else { gtk_adjustment_set_value (vadj, bounds.y0); } } l = l->next; } } /* Call a function for all the icons. */ typedef struct { NemoIconCallback callback; gpointer callback_data; } CallbackAndData; static void call_icon_callback (gpointer data, gpointer callback_data) { NemoIcon *icon; CallbackAndData *callback_and_data; icon = data; callback_and_data = callback_data; (* callback_and_data->callback) (icon->data, callback_and_data->callback_data); } void nemo_icon_container_for_each (NemoIconContainer *container, NemoIconCallback callback, gpointer callback_data) { CallbackAndData callback_and_data; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); callback_and_data.callback = callback; callback_and_data.callback_data = callback_data; g_list_foreach (container->details->icons, call_icon_callback, &callback_and_data); } static int selection_changed_at_idle_callback (gpointer data) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (data); g_signal_emit (container, signals[SELECTION_CHANGED], 0); container->details->selection_changed_id = 0; return FALSE; } /* utility routine to remove a single icon from the container */ static void icon_destroy (NemoIconContainer *container, NemoIcon *icon) { NemoIconContainerDetails *details; gboolean was_selected; NemoIcon *icon_to_focus; GList *item; details = container->details; item = g_list_find (details->icons, icon); item = item->next ? item->next : item->prev; icon_to_focus = (item != NULL) ? item->data : NULL; details->icons = g_list_remove (details->icons, icon); details->new_icons = g_list_remove (details->new_icons, icon); g_hash_table_remove (details->icon_set, icon->data); was_selected = icon->is_selected; if (details->keyboard_focus == icon || details->keyboard_focus == NULL) { if (icon_to_focus != NULL) { set_keyboard_focus (container, icon_to_focus); } else { clear_keyboard_focus (container); } } if (details->keyboard_rubberband_start == icon) { clear_keyboard_rubberband_start (container); } if (details->keyboard_icon_to_reveal == icon) { unschedule_keyboard_icon_reveal (container); } if (details->drag_icon == icon) { clear_drag_state (container); } if (details->drop_target == icon) { details->drop_target = NULL; } if (details->range_selection_base_icon == icon) { details->range_selection_base_icon = NULL; } if (details->pending_icon_to_reveal == icon) { set_pending_icon_to_reveal (container, NULL); } if (details->stretch_icon == icon) { details->stretch_icon = NULL; } if (icon->is_monitored) { nemo_icon_container_stop_monitor_top_left (container, icon->data, icon); } icon_free (icon); if (was_selected) { /* Coalesce multiple removals causing multiple selection_changed events */ details->selection_changed_id = g_idle_add (selection_changed_at_idle_callback, container); } } /* activate any selected items in the container */ static void activate_selected_items (NemoIconContainer *container) { GList *selection; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); selection = nemo_icon_container_get_selection (container); if (selection != NULL) { g_signal_emit (container, signals[ACTIVATE], 0, selection); } g_list_free (selection); } static void preview_selected_items (NemoIconContainer *container) { GList *selection; GArray *locations; gint idx; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); selection = nemo_icon_container_get_selection (container); locations = nemo_icon_container_get_selected_icon_locations (container); for (idx = 0; idx < locations->len; idx++) { GdkPoint *point = &(g_array_index (locations, GdkPoint, idx)); gint scroll_x, scroll_y; eel_canvas_get_scroll_offsets (EEL_CANVAS (container), &scroll_x, &scroll_y); point->x -= scroll_x; point->y -= scroll_y; } if (selection != NULL) { g_signal_emit (container, signals[ACTIVATE_PREVIEWER], 0, selection, locations); } g_list_free (selection); } static void activate_selected_items_alternate (NemoIconContainer *container, NemoIcon *icon) { GList *selection; g_assert (NEMO_IS_ICON_CONTAINER (container)); if (icon != NULL) { selection = g_list_prepend (NULL, icon->data); } else { selection = nemo_icon_container_get_selection (container); } if (selection != NULL) { g_signal_emit (container, signals[ACTIVATE_ALTERNATE], 0, selection); } g_list_free (selection); } NemoIconInfo * nemo_icon_container_get_icon_images (NemoIconContainer *container, NemoIconData *data, int size, char **embedded_text, gboolean for_drag_accept, gboolean need_large_embeddded_text, gboolean *embedded_text_needs_loading, gboolean *has_open_window) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->get_icon_images != NULL); return klass->get_icon_images (container, data, size, embedded_text, for_drag_accept, need_large_embeddded_text, embedded_text_needs_loading, has_open_window); } static void nemo_icon_container_freeze_updates (NemoIconContainer *container) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->freeze_updates != NULL); klass->freeze_updates (container); } static void nemo_icon_container_unfreeze_updates (NemoIconContainer *container) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->unfreeze_updates != NULL); klass->unfreeze_updates (container); } void nemo_icon_container_start_monitor_top_left (NemoIconContainer *container, NemoIconData *data, gconstpointer client, gboolean large_text) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->start_monitor_top_left != NULL); klass->start_monitor_top_left (container, data, client, large_text); } void nemo_icon_container_stop_monitor_top_left (NemoIconContainer *container, NemoIconData *data, gconstpointer client) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_return_if_fail (klass->stop_monitor_top_left != NULL); klass->stop_monitor_top_left (container, data, client); } static void nemo_icon_container_prioritize_thumbnailing (NemoIconContainer *container, NemoIcon *icon) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->prioritize_thumbnailing != NULL); klass->prioritize_thumbnailing (container, icon->data); } static void nemo_icon_container_update_visible_icons (NemoIconContainer *container) { GtkAdjustment *vadj, *hadj; double min_y, max_y; double min_x, max_x; double x0, y0, x1, y1; GList *node; NemoIcon *icon; gboolean visible; GtkAllocation allocation; hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (container)); vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (container)); gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); min_x = gtk_adjustment_get_value (hadj); max_x = min_x + allocation.width; min_y = gtk_adjustment_get_value (vadj); max_y = min_y + allocation.height; eel_canvas_c2w (EEL_CANVAS (container), min_x, min_y, &min_x, &min_y); eel_canvas_c2w (EEL_CANVAS (container), max_x, max_y, &max_x, &max_y); /* Do the iteration in reverse to get the render-order from top to * bottom for the prioritized thumbnails. */ for (node = g_list_last (container->details->icons); node != NULL; node = node->prev) { icon = node->data; if (nemo_icon_container_icon_is_positioned (icon)) { eel_canvas_item_get_bounds (EEL_CANVAS_ITEM (icon->item), &x0, &y0, &x1, &y1); eel_canvas_item_i2w (EEL_CANVAS_ITEM (icon->item)->parent, &x0, &y0); eel_canvas_item_i2w (EEL_CANVAS_ITEM (icon->item)->parent, &x1, &y1); if (nemo_icon_container_is_layout_vertical (container)) { visible = x1 >= min_x && x0 <= max_x; } else { visible = y1 >= min_y && y0 <= max_y; } if (visible) { nemo_icon_canvas_item_set_is_visible (icon->item, TRUE); nemo_icon_container_prioritize_thumbnailing (container, icon); } else { nemo_icon_canvas_item_set_is_visible (icon->item, FALSE); } } } } static void handle_vadjustment_changed (GtkAdjustment *adjustment, NemoIconContainer *container) { if (!nemo_icon_container_is_layout_vertical (container)) { nemo_icon_container_update_visible_icons (container); } } static void handle_hadjustment_changed (GtkAdjustment *adjustment, NemoIconContainer *container) { if (nemo_icon_container_is_layout_vertical (container)) { nemo_icon_container_update_visible_icons (container); } } static gboolean is_old_or_unknown_icon_data (NemoIconContainer *container, NemoIconData *data) { time_t timestamp; gboolean success; gboolean is_transient; /* Undefined at startup */ if (container->details->layout_timestamp == UNDEFINED_TIME) { return FALSE; } is_transient = NEMO_IS_DESKTOP_ICON_FILE (data); g_signal_emit (container, signals[GET_STORED_LAYOUT_TIMESTAMP], 0, data, ×tamp, &success); return (!success || is_transient || timestamp < container->details->layout_timestamp); } gboolean nemo_icon_container_icon_is_new_for_monitor (NemoIconContainer *container, NemoIcon *icon, gint current_monitor) { if (container->details->auto_layout || !container->details->is_desktop) { return FALSE; } return nemo_file_get_monitor_number (NEMO_FILE (icon->data)) != current_monitor; } /** * nemo_icon_container_add: * @container: A NemoIconContainer * @data: Icon data. * * Add icon to represent @data to container. * Returns FALSE if there was already such an icon. **/ gboolean nemo_icon_container_add (NemoIconContainer *container, NemoIconData *data) { NemoIconContainerDetails *details; NemoIcon *icon; EelCanvasItem *band, *item; g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); g_return_val_if_fail (data != NULL, FALSE); details = container->details; if (g_hash_table_lookup (details->icon_set, data) != NULL) { return FALSE; } /* Create the new icon, including the canvas item. */ icon = g_new0 (NemoIcon, 1); icon->data = data; icon->x = ICON_UNPOSITIONED_VALUE; icon->y = ICON_UNPOSITIONED_VALUE; /* Whether the saved icon position should only be used * if the previous icon position is free. If the position * is occupied, another position near the last one will */ icon->has_lazy_position = is_old_or_unknown_icon_data (container, data); icon->scale = 1.0; icon->item = NEMO_ICON_CANVAS_ITEM (eel_canvas_item_new (EEL_CANVAS_GROUP (EEL_CANVAS (container)->root), nemo_icon_canvas_item_get_type (), "visible", FALSE, NULL)); icon->item->user_data = icon; /* Make sure the icon is under the selection_rectangle */ item = EEL_CANVAS_ITEM (icon->item); band = NEMO_ICON_CONTAINER (item->canvas)->details->rubberband_info.selection_rectangle; if (band) { eel_canvas_item_send_behind (item, band); } /* Put it on both lists. */ details->icons = g_list_prepend (details->icons, icon); details->new_icons = g_list_prepend (details->new_icons, icon); g_hash_table_insert (details->icon_set, data, icon); details->needs_resort = TRUE; /* Run an idle function to add the icons. */ schedule_redo_layout (container); return TRUE; } void nemo_icon_container_layout_now (NemoIconContainer *container) { if (container->details->idle_id != 0) { unschedule_redo_layout (container); redo_layout_internal (container); } /* Also need to make sure we're properly resized, for instance * newly added files may trigger a change in the size allocation and * thus toggle scrollbars on */ gtk_container_check_resize (GTK_CONTAINER (gtk_widget_get_parent (GTK_WIDGET (container)))); } /** * nemo_icon_container_remove: * @container: A NemoIconContainer. * @data: Icon data. * * Remove the icon with this data. **/ gboolean nemo_icon_container_remove (NemoIconContainer *container, NemoIconData *data) { NemoIcon *icon; g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); g_return_val_if_fail (data != NULL, FALSE); nemo_icon_container_end_renaming_mode (container, FALSE); icon = g_hash_table_lookup (container->details->icon_set, data); if (icon == NULL) { return FALSE; } gtk_widget_set_tooltip_text (GTK_WIDGET (EEL_CANVAS_ITEM (icon->item)->canvas), ""); icon_destroy (container, icon); schedule_redo_layout (container); g_signal_emit (container, signals[ICON_REMOVED], 0, icon); return TRUE; } /** * nemo_icon_container_request_update: * @container: A NemoIconContainer. * @data: Icon data. * * Update the icon with this data. **/ void nemo_icon_container_request_update (NemoIconContainer *container, NemoIconData *data) { NemoIcon *icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (data != NULL); icon = g_hash_table_lookup (container->details->icon_set, data); if (icon != NULL) { nemo_icon_container_update_icon (container, icon); container->details->needs_resort = TRUE; schedule_redo_layout (container); } } /* invalidate the entire labels (i.e. their attributes) for all the icons */ void nemo_icon_container_invalidate_labels (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; nemo_icon_canvas_item_invalidate_label (icon->item); } } /* zooming */ NemoZoomLevel nemo_icon_container_get_zoom_level (NemoIconContainer *container) { return container->details->zoom_level; } void nemo_icon_container_set_zoom_level (NemoIconContainer *container, gint new_level) { NEMO_ICON_CONTAINER_GET_CLASS (container)->set_zoom_level (container, new_level); nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); } /** * nemo_icon_container_request_update_all: * For each icon, synchronizes the displayed information (image, text) with the * information from the model. * * @container: An icon container. **/ void nemo_icon_container_request_update_all (NemoIconContainer *container) { GList *node; NemoIcon *icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); for (node = container->details->icons; node != NULL; node = node->next) { icon = node->data; nemo_icon_container_update_icon (container, icon); } container->details->needs_resort = TRUE; nemo_icon_container_redo_layout (container); gtk_widget_queue_draw (GTK_WIDGET (container)); } /** * nemo_icon_container_reveal: * Change scroll position as necessary to reveal the specified item. */ void nemo_icon_container_reveal (NemoIconContainer *container, NemoIconData *data) { NemoIcon *icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (data != NULL); icon = g_hash_table_lookup (container->details->icon_set, data); if (icon != NULL) { reveal_icon (container, icon); } } /** * nemo_icon_container_get_selection: * @container: An icon container. * * Get a list of the icons currently selected in @container. * * Return value: A GList of the programmer-specified data associated to each * selected icon, or NULL if no icon is selected. The caller is expected to * free the list when it is not needed anymore. **/ GList * nemo_icon_container_get_selection (NemoIconContainer *container) { GList *list, *p; g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), NULL); list = NULL; for (p = container->details->icons; p != NULL; p = p->next) { NemoIcon *icon; icon = p->data; if (icon->is_selected) { list = g_list_prepend (list, icon->data); } } return g_list_reverse (list); } static GList * nemo_icon_container_get_selected_icons (NemoIconContainer *container) { GList *list, *p; g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), NULL); list = NULL; for (p = container->details->icons; p != NULL; p = p->next) { NemoIcon *icon; icon = p->data; if (icon->is_selected) { list = g_list_prepend (list, icon); } } return g_list_reverse (list); } /** * nemo_icon_container_invert_selection: * @container: An icon container. * * Inverts the selection in @container. * **/ void nemo_icon_container_invert_selection (NemoIconContainer *container) { GList *p; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); for (p = container->details->icons; p != NULL; p = p->next) { NemoIcon *icon; icon = p->data; icon_toggle_selected (container, icon); } g_signal_emit (container, signals[SELECTION_CHANGED], 0); } /* Returns an array of GdkPoints of locations of the icons. */ static GArray * nemo_icon_container_get_icon_locations (NemoIconContainer *container, GList *icons) { GArray *result; GList *node; int index; result = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); result = g_array_set_size (result, g_list_length (icons)); for (index = 0, node = icons; node != NULL; index++, node = node->next) { g_array_index (result, GdkPoint, index).x = ((NemoIcon *)node->data)->x; g_array_index (result, GdkPoint, index).y = ((NemoIcon *)node->data)->y; } return result; } /** * nemo_icon_container_get_selected_icon_locations: * @container: An icon container widget. * * Returns an array of GdkPoints of locations of the selected icons. **/ GArray * nemo_icon_container_get_selected_icon_locations (NemoIconContainer *container) { GArray *result; GList *icons; g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), NULL); icons = nemo_icon_container_get_selected_icons (container); result = nemo_icon_container_get_icon_locations (container, icons); g_list_free (icons); return result; } /** * nemo_icon_container_select_all: * @container: An icon container widget. * * Select all the icons in @container at once. **/ void nemo_icon_container_select_all (NemoIconContainer *container) { gboolean selection_changed; GList *p; NemoIcon *icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); selection_changed = FALSE; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; selection_changed |= icon_set_selected (container, icon, TRUE); } if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } /** * nemo_icon_container_set_selection: * @container: An icon container widget. * @selection: A list of NemoIconData *. * * Set the selection to exactly the icons in @container which have * programmer data matching one of the items in @selection. **/ void nemo_icon_container_set_selection (NemoIconContainer *container, GList *selection) { gboolean selection_changed; GHashTable *hash; GList *p; gboolean res; NemoIcon *icon, *selected_icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); selection_changed = FALSE; selected_icon = NULL; hash = g_hash_table_new (NULL, NULL); for (p = selection; p != NULL; p = p->next) { g_hash_table_insert (hash, p->data, p->data); } for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; res = icon_set_selected (container, icon, g_hash_table_lookup (hash, icon->data) != NULL); selection_changed |= res; if (res) { selected_icon = icon; } } g_hash_table_destroy (hash); if (selection_changed) { /* if only one item has been selected, use it as range * selection base (cf. handle_icon_button_press) */ if (g_list_length (selection) == 1) { container->details->range_selection_base_icon = selected_icon; } g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } /** * nemo_icon_container_select_list_unselect_others. * @container: An icon container widget. * @selection: A list of NemoIcon *. * * Set the selection to exactly the icons in @selection. **/ void nemo_icon_container_select_list_unselect_others (NemoIconContainer *container, GList *selection) { gboolean selection_changed; GHashTable *hash; GList *p; NemoIcon *icon; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); selection_changed = FALSE; hash = g_hash_table_new (NULL, NULL); for (p = selection; p != NULL; p = p->next) { g_hash_table_insert (hash, p->data, p->data); } for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; selection_changed |= icon_set_selected (container, icon, g_hash_table_lookup (hash, icon) != NULL); } g_hash_table_destroy (hash); if (selection_changed) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } /** * nemo_icon_container_unselect_all: * @container: An icon container widget. * * Deselect all the icons in @container. **/ void nemo_icon_container_unselect_all (NemoIconContainer *container) { if (unselect_all (container)) { g_signal_emit (container, signals[SELECTION_CHANGED], 0); } } /** * nemo_icon_container_get_icon_by_uri: * @container: An icon container widget. * @uri: The uri of an icon to find. * * Locate an icon, given the URI. The URI must match exactly. * Later we may have to have some way of figuring out if the * URI specifies the same object that does not require an exact match. **/ NemoIcon * nemo_icon_container_get_icon_by_uri (NemoIconContainer *container, const char *uri) { NemoIconContainerDetails *details; GList *p; /* Eventually, we must avoid searching the entire icon list, but it's OK for now. A hash table mapping uri to icon is one possibility. */ details = container->details; for (p = details->icons; p != NULL; p = p->next) { NemoIcon *icon; char *icon_uri; gboolean is_match; icon = p->data; icon_uri = nemo_icon_container_get_icon_uri (container, icon); is_match = strcmp (uri, icon_uri) == 0; g_free (icon_uri); if (is_match) { return icon; } } return NULL; } static NemoIcon * get_nth_selected_icon (NemoIconContainer *container, int index) { GList *p; NemoIcon *icon; int selection_count; g_assert (index > 0); /* Find the nth selected icon. */ selection_count = 0; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (icon->is_selected) { if (++selection_count == index) { return icon; } } } return NULL; } static NemoIcon * get_first_selected_icon (NemoIconContainer *container) { return get_nth_selected_icon (container, 1); } static gboolean has_multiple_selection (NemoIconContainer *container) { return get_nth_selected_icon (container, 2) != NULL; } static gboolean all_selected (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (!icon->is_selected) { return FALSE; } } return TRUE; } static gboolean has_selection (NemoIconContainer *container) { return get_nth_selected_icon (container, 1) != NULL; } /** * nemo_icon_container_show_stretch_handles: * @container: An icon container widget. * * Makes stretch handles visible on the first selected icon. **/ void nemo_icon_container_show_stretch_handles (NemoIconContainer *container) { NemoIconContainerDetails *details; NemoIcon *icon; guint initial_size; icon = get_first_selected_icon (container); if (icon == NULL) { return; } /* Check if it already has stretch handles. */ details = container->details; if (details->stretch_icon == icon) { return; } /* Get rid of the existing stretch handles and put them on the new icon. */ if (details->stretch_icon != NULL) { nemo_icon_canvas_item_set_show_stretch_handles (details->stretch_icon->item, FALSE); ungrab_stretch_icon (container); emit_stretch_ended (container, details->stretch_icon); } nemo_icon_canvas_item_set_show_stretch_handles (icon->item, TRUE); details->stretch_icon = icon; icon_get_size (container, icon, &initial_size); /* only need to keep size in one dimension, since they are constrained to be the same */ container->details->stretch_initial_x = icon->x; container->details->stretch_initial_y = icon->y; container->details->stretch_initial_size = initial_size; emit_stretch_started (container, icon); } /** * nemo_icon_container_has_stretch_handles * @container: An icon container widget. * * Returns true if the first selected item has stretch handles. **/ gboolean nemo_icon_container_has_stretch_handles (NemoIconContainer *container) { NemoIcon *icon; icon = get_first_selected_icon (container); if (icon == NULL) { return FALSE; } return icon == container->details->stretch_icon; } /** * nemo_icon_container_is_stretched * @container: An icon container widget. * * Returns true if the any selected item is stretched to a size other than 1.0. **/ gboolean nemo_icon_container_is_stretched (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (icon->is_selected && icon->scale != 1.0) { return TRUE; } } return FALSE; } /** * nemo_icon_container_unstretch * @container: An icon container widget. * * Gets rid of any icon stretching. **/ void nemo_icon_container_unstretch (NemoIconContainer *container) { GList *p; NemoIcon *icon; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; if (icon->is_selected) { nemo_icon_container_move_icon (container, icon, icon->x, icon->y, 1.0, FALSE, TRUE, TRUE); } } } static void compute_stretch (StretchState *start, StretchState *current) { gboolean right, bottom; int x_stretch, y_stretch; /* FIXME bugzilla.gnome.org 45390: This doesn't correspond to * the way the handles are drawn. */ /* Figure out which handle we are dragging. */ right = start->pointer_x > start->icon_x + (int) start->icon_size / 2; bottom = start->pointer_y > start->icon_y + (int) start->icon_size / 2; /* Figure out how big we should stretch. */ x_stretch = start->pointer_x - current->pointer_x; y_stretch = start->pointer_y - current->pointer_y; if (right) { x_stretch = - x_stretch; } if (bottom) { y_stretch = - y_stretch; } current->icon_size = MAX ((int) start->icon_size + MIN (x_stretch, y_stretch), (int) NEMO_ICON_SIZE_SMALLEST); /* Figure out where the corner of the icon should be. */ current->icon_x = start->icon_x; if (!right) { current->icon_x += start->icon_size - current->icon_size; } current->icon_y = start->icon_y; if (!bottom) { current->icon_y += start->icon_size - current->icon_size; } } char * nemo_icon_container_get_icon_uri (NemoIconContainer *container, NemoIcon *icon) { char *uri; uri = NULL; g_signal_emit (container, signals[GET_ICON_URI], 0, icon->data, &uri); return uri; } char * nemo_icon_container_get_icon_drop_target_uri (NemoIconContainer *container, NemoIcon *icon) { char *uri; uri = NULL; g_signal_emit (container, signals[GET_ICON_DROP_TARGET_URI], 0, icon->data, &uri); return uri; } /* Call to reset the scroll region only if the container is not empty, * to avoid having the flag linger until the next file is added. */ static void reset_scroll_region_if_not_empty (NemoIconContainer *container) { if (!nemo_icon_container_is_empty (container)) { nemo_icon_container_reset_scroll_region (container); } } /* Switch from automatic layout to manual or vice versa. * If we switch to manual layout, we restore the icon positions from the * last manual layout. */ void nemo_icon_container_set_auto_layout (NemoIconContainer *container, gboolean auto_layout) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (auto_layout == FALSE || auto_layout == TRUE); if (container->details->auto_layout == auto_layout) { return; } reset_scroll_region_if_not_empty (container); container->details->stored_auto_layout = auto_layout; container->details->auto_layout = auto_layout; if (!auto_layout) { reload_icon_positions (container); nemo_icon_container_freeze_icon_positions (container); } container->details->needs_resort = TRUE; nemo_icon_container_redo_layout (container); g_signal_emit (container, signals[LAYOUT_CHANGED], 0); } void nemo_icon_container_set_horizontal_layout (NemoIconContainer *container, gboolean horizontal) { GtkTextDirection dir; NemoIconLayoutMode layout_mode; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (horizontal == FALSE || horizontal == TRUE); if (container->details->horizontal == horizontal) { return; } container->details->horizontal = horizontal; dir = gtk_widget_get_direction (GTK_WIDGET (container)); if (dir == GTK_TEXT_DIR_LTR) { layout_mode = horizontal ? NEMO_ICON_LAYOUT_L_R_T_B : NEMO_ICON_LAYOUT_T_B_L_R; } else { layout_mode = horizontal ? NEMO_ICON_LAYOUT_R_L_T_B : NEMO_ICON_LAYOUT_T_B_R_L; } container->details->layout_mode = layout_mode; } gboolean nemo_icon_container_get_horizontal_layout (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->horizontal; } /* Toggle the tighter layout boolean. */ void nemo_icon_container_set_tighter_layout (NemoIconContainer *container, gboolean tighter_layout) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (tighter_layout == FALSE || tighter_layout == TRUE); if (container->details->tighter_layout == tighter_layout) { return; } container->details->tighter_layout = tighter_layout; if (container->details->auto_layout) { invalidate_label_sizes (container); nemo_icon_container_redo_layout (container); g_signal_emit (container, signals[LAYOUT_CHANGED], 0); } else { /* in manual layout, label sizes still change, even though * the icons don't move. */ invalidate_label_sizes (container); nemo_icon_container_request_update_all (container); } } gboolean nemo_icon_container_is_keep_aligned (NemoIconContainer *container) { return container->details->keep_aligned; } static gboolean align_icons_callback (gpointer callback_data) { NemoIconContainer *container; container = NEMO_ICON_CONTAINER (callback_data); align_icons (container); container->details->align_idle_id = 0; return FALSE; } static void unschedule_align_icons (NemoIconContainer *container) { if (container->details->align_idle_id != 0) { g_source_remove (container->details->align_idle_id); container->details->align_idle_id = 0; } } static void schedule_align_icons (NemoIconContainer *container) { if (container->details->align_idle_id == 0 && container->details->has_been_allocated) { container->details->align_idle_id = g_idle_add (align_icons_callback, container); } } void nemo_icon_container_set_keep_aligned (NemoIconContainer *container, gboolean keep_aligned) { if (container->details->keep_aligned != keep_aligned) { container->details->keep_aligned = keep_aligned; if (keep_aligned && !container->details->auto_layout) { schedule_align_icons (container); } else { unschedule_align_icons (container); } } } void nemo_icon_container_set_layout_mode (NemoIconContainer *container, NemoIconLayoutMode mode) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->layout_mode = mode; nemo_icon_container_invalidate_labels (container); container->details->needs_resort = TRUE; nemo_icon_container_redo_layout (container); g_signal_emit (container, signals[LAYOUT_CHANGED], 0); } void nemo_icon_container_set_label_position (NemoIconContainer *container, NemoIconLabelPosition position) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); if (container->details->label_position != position) { container->details->label_position = position; nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); schedule_redo_layout (container); } } /* Switch from automatic to manual layout, freezing all the icons in their * current positions instead of restoring icon positions from the last manual * layout as set_auto_layout does. */ void nemo_icon_container_freeze_icon_positions (NemoIconContainer *container) { gboolean changed; GList *p; NemoIcon *icon; NemoIconPosition position; changed = container->details->auto_layout; container->details->auto_layout = FALSE; for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; position.x = icon->saved_ltr_x; position.y = icon->y; position.scale = icon->scale; position.monitor = nemo_desktop_utils_get_monitor_for_widget (GTK_WIDGET (container)); g_signal_emit (container, signals[ICON_POSITION_CHANGED], 0, icon->data, &position); } if (changed) { g_signal_emit (container, signals[LAYOUT_CHANGED], 0); } } /* Re-sort, switching to automatic layout if it was in manual layout. */ void nemo_icon_container_sort (NemoIconContainer *container) { gboolean changed; container->details->stored_auto_layout = container->details->auto_layout; changed = !container->details->auto_layout; container->details->auto_layout = TRUE; reset_scroll_region_if_not_empty (container); container->details->needs_resort = TRUE; nemo_icon_container_redo_layout (container); if (changed) { g_signal_emit (container, signals[LAYOUT_CHANGED], 0); } } gboolean nemo_icon_container_is_auto_layout (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->auto_layout; } gboolean nemo_icon_container_is_tighter_layout (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->tighter_layout; } static void pending_icon_to_rename_destroy_callback (NemoIconCanvasItem *item, NemoIconContainer *container) { g_assert (container->details->pending_icon_to_rename != NULL); g_assert (container->details->pending_icon_to_rename->item == item); container->details->pending_icon_to_rename = NULL; } static NemoIcon* get_pending_icon_to_rename (NemoIconContainer *container) { return container->details->pending_icon_to_rename; } static void set_pending_icon_to_rename (NemoIconContainer *container, NemoIcon *icon) { NemoIcon *old_icon; old_icon = container->details->pending_icon_to_rename; if (icon == old_icon) { return; } if (old_icon != NULL) { g_signal_handlers_disconnect_by_func (old_icon->item, G_CALLBACK (pending_icon_to_rename_destroy_callback), container); } if (icon != NULL) { g_signal_connect (icon->item, "destroy", G_CALLBACK (pending_icon_to_rename_destroy_callback), container); } container->details->pending_icon_to_rename = icon; } static void process_pending_icon_to_rename (NemoIconContainer *container) { NemoIcon *pending_icon_to_rename; pending_icon_to_rename = get_pending_icon_to_rename (container); if (pending_icon_to_rename != NULL) { if (pending_icon_to_rename->is_selected && !has_multiple_selection (container)) { nemo_icon_container_start_renaming_selected_item (container, FALSE); } else { set_pending_icon_to_rename (container, NULL); } } } static gboolean is_renaming_pending (NemoIconContainer *container) { return get_pending_icon_to_rename (container) != NULL; } static gboolean is_renaming (NemoIconContainer *container) { return container->details->renaming; } /** * nemo_icon_container_start_renaming_selected_item * @container: An icon container widget. * @select_all: Whether the whole file should initially be selected, or * only its basename (i.e. everything except its extension). * * Displays the edit name widget on the first selected icon **/ void nemo_icon_container_start_renaming_selected_item (NemoIconContainer *container, gboolean select_all) { NemoIconContainerDetails *details; NemoIcon *icon; EelDRect icon_rect; EelDRect text_rect; PangoContext *context; PangoFontDescription *desc; const char *editable_text; int x, y, width; int start_offset, end_offset; /* Check if it already in renaming mode, if so - select all */ details = container->details; if (details->renaming) { eel_editable_label_select_region (EEL_EDITABLE_LABEL (details->rename_widget), 0, -1); return; } /* Find selected icon */ icon = get_first_selected_icon (container); if (icon == NULL) { return; } g_assert (!has_multiple_selection (container)); if (!nemo_icon_container_icon_is_positioned (icon)) { set_pending_icon_to_rename (container, icon); return; } set_pending_icon_to_rename (container, NULL); /* Make a copy of the original editable text for a later compare */ editable_text = nemo_icon_canvas_item_get_editable_text (icon->item); /* This could conceivably be NULL if a rename was triggered really early. */ if (editable_text == NULL) { return; } details->original_text = g_strdup (editable_text); /* Freeze updates so files added while renaming don't cause rename to loose focus, bug #318373 */ nemo_icon_container_freeze_updates (container); /* Create text renaming widget, if it hasn't been created already. * We deal with the broken icon text item widget by keeping it around * so its contents can still be cut and pasted as part of the clipboard */ if (details->rename_widget == NULL) { details->rename_widget = eel_editable_label_new ("Test text"); eel_editable_label_set_line_wrap (EEL_EDITABLE_LABEL (details->rename_widget), TRUE); eel_editable_label_set_line_wrap_mode (EEL_EDITABLE_LABEL (details->rename_widget), PANGO_WRAP_WORD_CHAR); eel_editable_label_set_draw_outline (EEL_EDITABLE_LABEL (details->rename_widget), TRUE); if (details->label_position != NEMO_ICON_LABEL_POSITION_BESIDE) { eel_editable_label_set_justify (EEL_EDITABLE_LABEL (details->rename_widget), GTK_JUSTIFY_CENTER); } gtk_misc_set_padding (GTK_MISC (details->rename_widget), 1, 1); gtk_layout_put (GTK_LAYOUT (container), details->rename_widget, 0, 0); } /* Set the right font */ if (details->font && g_strcmp0 (details->font, "") != 0) { desc = pango_font_description_from_string (details->font); } else { context = gtk_widget_get_pango_context (GTK_WIDGET (container)); desc = pango_font_description_copy (pango_context_get_font_description (context)); } if (pango_font_description_get_size (desc) > 0) { pango_font_description_set_size (desc, pango_font_description_get_size (desc) + container->details->font_size_table [container->details->zoom_level]); } eel_editable_label_set_font_description (EEL_EDITABLE_LABEL (details->rename_widget), desc); pango_font_description_free (desc); icon_rect = nemo_icon_canvas_item_get_icon_rectangle (icon->item); text_rect = nemo_icon_canvas_item_get_text_rectangle (icon->item, TRUE); if (nemo_icon_container_is_layout_vertical (container) && container->details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { /* for one-line editables, the width changes dynamically */ width = -1; } else { width = nemo_icon_canvas_item_get_max_text_width (icon->item); } if (details->label_position == NEMO_ICON_LABEL_POSITION_BESIDE) { eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)->canvas, text_rect.x0, text_rect.y0, &x, &y); } else { eel_canvas_w2c (EEL_CANVAS_ITEM (icon->item)->canvas, (icon_rect.x0 + icon_rect.x1) / 2, icon_rect.y1, &x, &y); x = x - width / 2 - 1; } gtk_layout_move (GTK_LAYOUT (container), details->rename_widget, x, y); gtk_widget_set_size_request (details->rename_widget, width, -1); eel_editable_label_set_text (EEL_EDITABLE_LABEL (details->rename_widget), editable_text); if (select_all) { start_offset = 0; end_offset = -1; } else { /* if it is a directory it should select all of the text regardless of select_all option */ if (nemo_file_is_directory (NEMO_FILE (icon->data))) { start_offset = 0; end_offset = -1; } else { eel_filename_get_rename_region (editable_text, &start_offset, &end_offset); } } gtk_widget_show (details->rename_widget); gtk_widget_grab_focus (details->rename_widget); eel_editable_label_select_region (EEL_EDITABLE_LABEL (details->rename_widget), start_offset, end_offset); g_signal_emit (container, signals[ICON_RENAME_STARTED], 0, GTK_EDITABLE (details->rename_widget)); nemo_icon_container_update_icon (container, icon); /* We are in renaming mode */ details->renaming = TRUE; nemo_icon_canvas_item_set_renaming (icon->item, TRUE); } NemoIcon * nemo_icon_container_get_icon_being_renamed (NemoIconContainer *container) { NemoIcon *rename_icon; if (!is_renaming (container)) { return NULL; } g_assert (!has_multiple_selection (container)); rename_icon = get_first_selected_icon (container); g_assert (rename_icon != NULL); return rename_icon; } void nemo_icon_container_end_renaming_mode (NemoIconContainer *container, gboolean commit) { NemoIcon *icon; const char *changed_text = NULL; set_pending_icon_to_rename (container, NULL); icon = nemo_icon_container_get_icon_being_renamed (container); if (icon == NULL) { return; } /* We are not in renaming mode */ container->details->renaming = FALSE; nemo_icon_canvas_item_set_renaming (icon->item, FALSE); nemo_icon_container_unfreeze_updates (container); if (commit) { set_pending_icon_to_reveal (container, icon); } gtk_widget_grab_focus (GTK_WIDGET (container)); if (commit) { /* Verify that text has been modified before signalling change. */ changed_text = eel_editable_label_get_text (EEL_EDITABLE_LABEL (container->details->rename_widget)); if (strcmp (container->details->original_text, changed_text) == 0) { changed_text = NULL; } } g_signal_emit (container, signals[ICON_RENAME_ENDED], 0, icon->data, changed_text); gtk_widget_hide (container->details->rename_widget); g_free (container->details->original_text); } void nemo_icon_container_set_single_click_mode (NemoIconContainer *container, gboolean single_click_mode) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->single_click_mode = single_click_mode; } void nemo_icon_container_set_click_to_rename_enabled (NemoIconContainer *container, gboolean enabled) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->click_to_rename = enabled; } /* Return if the icon container is a fixed size */ gboolean nemo_icon_container_get_is_fixed_size (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->is_fixed_size; } /* Set the icon container to be a fixed size */ void nemo_icon_container_set_is_fixed_size (NemoIconContainer *container, gboolean is_fixed_size) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->is_fixed_size = is_fixed_size; } gboolean nemo_icon_container_get_is_desktop (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->is_desktop; } void nemo_icon_container_set_is_desktop (NemoIconContainer *container, gboolean is_desktop) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->is_desktop = is_desktop; g_signal_handlers_disconnect_by_func (nemo_icon_view_preferences, text_ellipsis_limit_changed_container_callback, container); g_signal_handlers_disconnect_by_func (nemo_desktop_preferences, text_ellipsis_limit_changed_container_callback, container); if (is_desktop) { GtkStyleContext *context; context = gtk_widget_get_style_context (GTK_WIDGET (container)); gtk_style_context_add_class (context, "nemo-desktop"); g_signal_connect_swapped (nemo_desktop_preferences, "changed::" NEMO_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT, G_CALLBACK (text_ellipsis_limit_changed_container_callback), container); } else { g_signal_connect_swapped (nemo_icon_view_preferences, "changed::" NEMO_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT, G_CALLBACK (text_ellipsis_limit_changed_container_callback), container); } } void nemo_icon_container_set_margins (NemoIconContainer *container, int left_margin, int right_margin, int top_margin, int bottom_margin) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->left_margin = left_margin; container->details->right_margin = right_margin; container->details->top_margin = top_margin; container->details->bottom_margin = bottom_margin; /* redo layout of icons as the margins have changed */ schedule_redo_layout (container); } void nemo_icon_container_set_use_drop_shadows (NemoIconContainer *container, gboolean use_drop_shadows) { if (container->details->drop_shadows_requested == use_drop_shadows) { return; } container->details->drop_shadows_requested = use_drop_shadows; container->details->use_drop_shadows = use_drop_shadows; gtk_widget_queue_draw (GTK_WIDGET (container)); } /* handle theme changes */ void nemo_icon_container_set_font (NemoIconContainer *container, const char *font) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); if (g_strcmp0 (container->details->font, font) == 0) { return; } g_free (container->details->font); container->details->font = g_strdup (font); nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); gtk_widget_queue_draw (GTK_WIDGET (container)); } void nemo_icon_container_set_font_size_table (NemoIconContainer *container, const int font_size_table[NEMO_ZOOM_LEVEL_LARGEST + 1]) { int old_font_size; int i; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); g_return_if_fail (font_size_table != NULL); old_font_size = container->details->font_size_table[container->details->zoom_level]; for (i = 0; i <= NEMO_ZOOM_LEVEL_LARGEST; i++) { if (container->details->font_size_table[i] != font_size_table[i]) { container->details->font_size_table[i] = font_size_table[i]; } } if (old_font_size != container->details->font_size_table[container->details->zoom_level]) { nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); } } /** * nemo_icon_container_get_icon_description * @container: An icon container widget. * @data: Icon data * * Gets the description for the icon. This function may return NULL. **/ char* nemo_icon_container_get_icon_description (NemoIconContainer *container, NemoIconData *data) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); if (klass->get_icon_description) { return klass->get_icon_description (container, data); } else { return NULL; } } gboolean nemo_icon_container_get_allow_moves (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return container->details->drag_allow_moves; } void nemo_icon_container_set_allow_moves (NemoIconContainer *container, gboolean allow_moves) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); container->details->drag_allow_moves = allow_moves; } void nemo_icon_container_set_forced_icon_size (NemoIconContainer *container, int forced_icon_size) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); if (forced_icon_size != container->details->forced_icon_size) { container->details->forced_icon_size = forced_icon_size; invalidate_label_sizes (container); update_icons (container); nemo_icon_container_request_update_all (container); } } void nemo_icon_container_set_all_columns_same_width (NemoIconContainer *container, gboolean all_columns_same_width) { g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); if (all_columns_same_width != container->details->all_columns_same_width) { container->details->all_columns_same_width = all_columns_same_width; nemo_icon_container_invalidate_labels (container); nemo_icon_container_request_update_all (container); } } /** * nemo_icon_container_set_highlighted_for_clipboard * @container: An icon container widget. * @data: Icon Data associated with all icons that should be highlighted. * Others will be unhighlighted. **/ void nemo_icon_container_set_highlighted_for_clipboard (NemoIconContainer *container, GList *clipboard_icon_data) { GList *l; NemoIcon *icon; gboolean highlighted_for_clipboard; g_return_if_fail (NEMO_IS_ICON_CONTAINER (container)); for (l = container->details->icons; l != NULL; l = l->next) { icon = l->data; highlighted_for_clipboard = (g_list_find (clipboard_icon_data, icon->data) != NULL); eel_canvas_item_set (EEL_CANVAS_ITEM (icon->item), "highlighted-for-clipboard", highlighted_for_clipboard, NULL); } } /* NemoIconContainerAccessible */ static NemoIconContainerAccessiblePrivate * accessible_get_priv (AtkObject *accessible) { NemoIconContainerAccessiblePrivate *priv; priv = g_object_get_qdata (G_OBJECT (accessible), accessible_private_data_quark); return priv; } /* AtkAction interface */ static gboolean nemo_icon_container_accessible_do_action (AtkAction *accessible, int i) { GtkWidget *widget; NemoIconContainer *container; GList *selection; g_return_val_if_fail (i < LAST_ACTION, FALSE); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); switch (i) { case ACTION_ACTIVATE : selection = nemo_icon_container_get_selection (container); if (selection) { g_signal_emit_by_name (container, "activate", selection); g_list_free (selection); } break; case ACTION_MENU : handle_popups (container, NULL,"context_click_background"); break; default : g_warning ("Invalid action passed to NemoIconContainerAccessible::do_action"); return FALSE; } return TRUE; } static int nemo_icon_container_accessible_get_n_actions (AtkAction *accessible) { return LAST_ACTION; } static const char * nemo_icon_container_accessible_action_get_description (AtkAction *accessible, int i) { NemoIconContainerAccessiblePrivate *priv; g_assert (i < LAST_ACTION); priv = accessible_get_priv (ATK_OBJECT (accessible)); if (priv->action_descriptions[i]) { return priv->action_descriptions[i]; } else { return nemo_icon_container_accessible_action_descriptions[i]; } } static const char * nemo_icon_container_accessible_action_get_name (AtkAction *accessible, int i) { g_assert (i < LAST_ACTION); return nemo_icon_container_accessible_action_names[i]; } static const char * nemo_icon_container_accessible_action_get_keybinding (AtkAction *accessible, int i) { g_assert (i < LAST_ACTION); return NULL; } static gboolean nemo_icon_container_accessible_action_set_description (AtkAction *accessible, int i, const char *description) { NemoIconContainerAccessiblePrivate *priv; g_assert (i < LAST_ACTION); priv = accessible_get_priv (ATK_OBJECT (accessible)); if (priv->action_descriptions[i]) { g_free (priv->action_descriptions[i]); } priv->action_descriptions[i] = g_strdup (description); return FALSE; } static void nemo_icon_container_accessible_action_interface_init (AtkActionIface *iface) { iface->do_action = nemo_icon_container_accessible_do_action; iface->get_n_actions = nemo_icon_container_accessible_get_n_actions; iface->get_description = nemo_icon_container_accessible_action_get_description; iface->get_name = nemo_icon_container_accessible_action_get_name; iface->get_keybinding = nemo_icon_container_accessible_action_get_keybinding; iface->set_description = nemo_icon_container_accessible_action_set_description; } /* AtkSelection interface */ static void nemo_icon_container_accessible_update_selection (AtkObject *accessible) { NemoIconContainer *container; NemoIconContainerAccessiblePrivate *priv; GList *l; NemoIcon *icon; container = NEMO_ICON_CONTAINER (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible))); priv = accessible_get_priv (accessible); if (priv->selection) { g_list_free (priv->selection); priv->selection = NULL; } for (l = container->details->icons; l != NULL; l = l->next) { icon = l->data; if (icon->is_selected) { priv->selection = g_list_prepend (priv->selection, icon); } } priv->selection = g_list_reverse (priv->selection); } static void nemo_icon_container_accessible_selection_changed_cb (NemoIconContainer *container, gpointer data) { g_signal_emit_by_name (data, "selection_changed"); } static void nemo_icon_container_accessible_icon_added_cb (NemoIconContainer *container, NemoIconData *icon_data, gpointer data) { NemoIcon *icon; AtkObject *atk_parent; AtkObject *atk_child; int index; icon = g_hash_table_lookup (container->details->icon_set, icon_data); if (icon) { atk_parent = ATK_OBJECT (data); atk_child = atk_gobject_accessible_for_object (G_OBJECT (icon->item)); index = g_list_index (container->details->icons, icon); g_signal_emit_by_name (atk_parent, "children_changed::add", index, atk_child, NULL); } } static void nemo_icon_container_accessible_icon_removed_cb (NemoIconContainer *container, NemoIconData *icon_data, gpointer data) { NemoIcon *icon; AtkObject *atk_parent; AtkObject *atk_child; int index; icon = g_hash_table_lookup (container->details->icon_set, icon_data); if (icon) { atk_parent = ATK_OBJECT (data); atk_child = atk_gobject_accessible_for_object (G_OBJECT (icon->item)); index = g_list_index (container->details->icons, icon); g_signal_emit_by_name (atk_parent, "children_changed::remove", index, atk_child, NULL); } } static void nemo_icon_container_accessible_cleared_cb (NemoIconContainer *container, gpointer data) { g_signal_emit_by_name (data, "children_changed", 0, NULL, NULL); } static gboolean nemo_icon_container_accessible_add_selection (AtkSelection *accessible, int i) { GtkWidget *widget; NemoIconContainer *container; GList *selection; NemoIcon *icon; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); icon = g_list_nth_data (container->details->icons, i); if (icon) { selection = nemo_icon_container_get_selection (container); selection = g_list_prepend (selection, icon->data); nemo_icon_container_set_selection (container, selection); g_list_free (selection); return TRUE; } return FALSE; } static gboolean nemo_icon_container_accessible_clear_selection (AtkSelection *accessible) { GtkWidget *widget; NemoIconContainer *container; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); nemo_icon_container_unselect_all (container); return TRUE; } static AtkObject * nemo_icon_container_accessible_ref_selection (AtkSelection *accessible, int i) { AtkObject *atk_object; NemoIconContainerAccessiblePrivate *priv; NemoIcon *icon; nemo_icon_container_accessible_update_selection (ATK_OBJECT (accessible)); priv = accessible_get_priv (ATK_OBJECT (accessible)); icon = g_list_nth_data (priv->selection, i); if (icon) { atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)); if (atk_object) { g_object_ref (atk_object); } return atk_object; } else { return NULL; } } static int nemo_icon_container_accessible_get_selection_count (AtkSelection *accessible) { int count; NemoIconContainerAccessiblePrivate *priv; nemo_icon_container_accessible_update_selection (ATK_OBJECT (accessible)); priv = accessible_get_priv (ATK_OBJECT (accessible)); count = g_list_length (priv->selection); return count; } static gboolean nemo_icon_container_accessible_is_child_selected (AtkSelection *accessible, int i) { NemoIconContainer *container; NemoIcon *icon; GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); icon = g_list_nth_data (container->details->icons, i); return icon ? icon->is_selected : FALSE; } static gboolean nemo_icon_container_accessible_remove_selection (AtkSelection *accessible, int i) { NemoIconContainer *container; NemoIconContainerAccessiblePrivate *priv; GList *selection; NemoIcon *icon; GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } nemo_icon_container_accessible_update_selection (ATK_OBJECT (accessible)); priv = accessible_get_priv (ATK_OBJECT (accessible)); container = NEMO_ICON_CONTAINER (widget); icon = g_list_nth_data (priv->selection, i); if (icon) { selection = nemo_icon_container_get_selection (container); selection = g_list_remove (selection, icon->data); nemo_icon_container_set_selection (container, selection); g_list_free (selection); return TRUE; } return FALSE; } static gboolean nemo_icon_container_accessible_select_all_selection (AtkSelection *accessible) { NemoIconContainer *container; GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); nemo_icon_container_select_all (container); return TRUE; } void nemo_icon_container_widget_to_file_operation_position (NemoIconContainer *container, GdkPoint *position) { double x, y; g_return_if_fail (position != NULL); x = position->x; y = position->y; eel_canvas_window_to_world (EEL_CANVAS (container), x, y, &x, &y); position->x = (int) x; position->y = (int) y; /* ensure that we end up in the middle of the icon */ position->x -= nemo_get_icon_size_for_zoom_level (container->details->zoom_level) / 2; position->y -= nemo_get_icon_size_for_zoom_level (container->details->zoom_level) / 2; } static void nemo_icon_container_accessible_selection_interface_init (AtkSelectionIface *iface) { iface->add_selection = nemo_icon_container_accessible_add_selection; iface->clear_selection = nemo_icon_container_accessible_clear_selection; iface->ref_selection = nemo_icon_container_accessible_ref_selection; iface->get_selection_count = nemo_icon_container_accessible_get_selection_count; iface->is_child_selected = nemo_icon_container_accessible_is_child_selected; iface->remove_selection = nemo_icon_container_accessible_remove_selection; iface->select_all_selection = nemo_icon_container_accessible_select_all_selection; } static gint nemo_icon_container_accessible_get_n_children (AtkObject *accessible) { NemoIconContainer *container; GtkWidget *widget; gint i; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return FALSE; } container = NEMO_ICON_CONTAINER (widget); i = g_hash_table_size (container->details->icon_set); if (container->details->rename_widget) { i++; } return i; } static AtkObject* nemo_icon_container_accessible_ref_child (AtkObject *accessible, int i) { AtkObject *atk_object; NemoIconContainer *container; NemoIcon *icon; GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) { return NULL; } container = NEMO_ICON_CONTAINER (widget); icon = g_list_nth_data (container->details->icons, i); if (icon) { atk_object = atk_gobject_accessible_for_object (G_OBJECT (icon->item)); g_object_ref (atk_object); return atk_object; } else { if (i == g_list_length (container->details->icons)) { if (container->details->rename_widget) { atk_object = gtk_widget_get_accessible (container->details->rename_widget); g_object_ref (atk_object); return atk_object; } } return NULL; } } static void nemo_icon_container_accessible_initialize (AtkObject *accessible, gpointer data) { NemoIconContainer *container; NemoIconContainerAccessiblePrivate *priv; if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize) { ATK_OBJECT_CLASS (accessible_parent_class)->initialize (accessible, data); } priv = g_new0 (NemoIconContainerAccessiblePrivate, 1); g_object_set_qdata (G_OBJECT (accessible), accessible_private_data_quark, priv); if (GTK_IS_ACCESSIBLE (accessible)) { nemo_icon_container_accessible_update_selection (ATK_OBJECT (accessible)); container = NEMO_ICON_CONTAINER (gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible))); g_signal_connect (G_OBJECT (container), "selection_changed", G_CALLBACK (nemo_icon_container_accessible_selection_changed_cb), accessible); g_signal_connect (G_OBJECT (container), "icon_added", G_CALLBACK (nemo_icon_container_accessible_icon_added_cb), accessible); g_signal_connect (G_OBJECT (container), "icon_removed", G_CALLBACK (nemo_icon_container_accessible_icon_removed_cb), accessible); g_signal_connect (G_OBJECT (container), "cleared", G_CALLBACK (nemo_icon_container_accessible_cleared_cb), accessible); } } static void nemo_icon_container_accessible_finalize (GObject *object) { NemoIconContainerAccessiblePrivate *priv; int i; priv = accessible_get_priv (ATK_OBJECT (object)); if (priv->selection) { g_list_free (priv->selection); } for (i = 0; i < LAST_ACTION; i++) { if (priv->action_descriptions[i]) { g_free (priv->action_descriptions[i]); } } g_free (priv); G_OBJECT_CLASS (accessible_parent_class)->finalize (object); } static void nemo_icon_container_accessible_class_init (AtkObjectClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); accessible_parent_class = g_type_class_peek_parent (klass); gobject_class->finalize = nemo_icon_container_accessible_finalize; klass->get_n_children = nemo_icon_container_accessible_get_n_children; klass->ref_child = nemo_icon_container_accessible_ref_child; klass->initialize = nemo_icon_container_accessible_initialize; accessible_private_data_quark = g_quark_from_static_string ("icon-container-accessible-private-data"); } static GType nemo_icon_container_accessible_get_type (void) { static GType type = 0; if (!type) { static GInterfaceInfo atk_action_info = { (GInterfaceInitFunc) nemo_icon_container_accessible_action_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; static GInterfaceInfo atk_selection_info = { (GInterfaceInitFunc) nemo_icon_container_accessible_selection_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; type = eel_accessibility_create_derived_type ("NemoIconContainerAccessible", EEL_TYPE_CANVAS, nemo_icon_container_accessible_class_init); g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); g_type_add_interface_static (type, ATK_TYPE_SELECTION, &atk_selection_info); } return type; } #if ! defined (NEMO_OMIT_SELF_CHECK) static char * check_compute_stretch (int icon_x, int icon_y, int icon_size, int start_pointer_x, int start_pointer_y, int end_pointer_x, int end_pointer_y) { StretchState start, current; start.icon_x = icon_x; start.icon_y = icon_y; start.icon_size = icon_size; start.pointer_x = start_pointer_x; start.pointer_y = start_pointer_y; current.pointer_x = end_pointer_x; current.pointer_y = end_pointer_y; compute_stretch (&start, ¤t); return g_strdup_printf ("%d,%d:%d", current.icon_x, current.icon_y, current.icon_size); } void nemo_self_check_icon_container (void) { EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 0, 0, 0, 0), "0,0:16"); EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 16, 16, 17, 17), "0,0:17"); EEL_CHECK_STRING_RESULT (check_compute_stretch (0, 0, 16, 16, 16, 17, 16), "0,0:16"); EEL_CHECK_STRING_RESULT (check_compute_stretch (100, 100, 64, 105, 105, 40, 40), "35,35:129"); } gboolean nemo_icon_container_is_layout_rtl (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), 0); return gtk_widget_get_direction (GTK_WIDGET(container)) == GTK_TEXT_DIR_RTL; } gboolean nemo_icon_container_is_layout_vertical (NemoIconContainer *container) { g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), FALSE); return (container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_L_R || container->details->layout_mode == NEMO_ICON_LAYOUT_T_B_R_L); } gint nemo_icon_container_get_max_layout_lines_for_pango (NemoIconContainer *container) { return NEMO_ICON_CONTAINER_GET_CLASS (container)->get_max_layout_lines_for_pango (container); } gint nemo_icon_container_get_max_layout_lines (NemoIconContainer *container) { return NEMO_ICON_CONTAINER_GET_CLASS (container)->get_max_layout_lines (container); } void nemo_icon_container_begin_loading (NemoIconContainer *container) { gboolean dummy; if (nemo_icon_container_get_store_layout_timestamps (container)) { container->details->layout_timestamp = UNDEFINED_TIME; g_signal_emit (container, signals[GET_STORED_LAYOUT_TIMESTAMP], 0, NULL, &container->details->layout_timestamp, &dummy); } } void nemo_icon_container_store_layout_timestamps_now (NemoIconContainer *container) { NemoIcon *icon; GList *p; gboolean dummy; container->details->layout_timestamp = time (NULL); g_signal_emit (container, signals[STORE_LAYOUT_TIMESTAMP], 0, NULL, &container->details->layout_timestamp, &dummy); for (p = container->details->icons; p != NULL; p = p->next) { icon = p->data; g_signal_emit (container, signals[STORE_LAYOUT_TIMESTAMP], 0, icon->data, &container->details->layout_timestamp, &dummy); } } void nemo_icon_container_end_loading (NemoIconContainer *container, gboolean all_icons_added) { if (all_icons_added && nemo_icon_container_get_store_layout_timestamps (container)) { if (container->details->new_icons == NULL) { nemo_icon_container_store_layout_timestamps_now (container); } else { container->details->store_layout_timestamps_when_finishing_new_icons = TRUE; } } } gboolean nemo_icon_container_get_store_layout_timestamps (NemoIconContainer *container) { return container->details->store_layout_timestamps; } void nemo_icon_container_set_store_layout_timestamps (NemoIconContainer *container, gboolean store_layout_timestamps) { container->details->store_layout_timestamps = store_layout_timestamps; } gint nemo_icon_container_get_canvas_height (NemoIconContainer *container, GtkAllocation allocation) { return (allocation.height - container->details->top_margin - container->details->bottom_margin) / EEL_CANVAS (container)->pixels_per_unit; } gint nemo_icon_container_get_canvas_width (NemoIconContainer *container, GtkAllocation allocation) { return (allocation.width - container->details->left_margin - container->details->right_margin) / EEL_CANVAS (container)->pixels_per_unit; } double nemo_icon_container_get_mirror_x_position (NemoIconContainer *container, NemoIcon *icon, double x) { EelDRect icon_bounds; GtkAllocation allocation; gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); icon_bounds = nemo_icon_canvas_item_get_icon_rectangle (icon->item); return nemo_icon_container_get_canvas_width (container, allocation) - x - (icon_bounds.x1 - icon_bounds.x0); } void nemo_icon_container_set_rtl_positions (NemoIconContainer *container) { GList *l; NemoIcon *icon; double x; if (!container->details->icons) { return; } for (l = container->details->icons; l != NULL; l = l->next) { icon = l->data; x = nemo_icon_container_get_mirror_x_position (container, icon, icon->saved_ltr_x); nemo_icon_container_icon_set_position (container, icon, x, icon->y); } } void nemo_icon_container_sort_icons (NemoIconContainer *container, GList **icons) { NemoIconContainerClass *klass; klass = NEMO_ICON_CONTAINER_GET_CLASS (container); g_assert (klass->compare_icons != NULL); *icons = g_list_sort_with_data (*icons, compare_icons, container); } void nemo_icon_container_resort (NemoIconContainer *container) { nemo_icon_container_sort_icons (container, &container->details->icons); } void nemo_icon_container_icon_raise (NemoIconContainer *container, NemoIcon *icon) { EelCanvasItem *item, *band; item = EEL_CANVAS_ITEM (icon->item); band = container->details->rubberband_info.selection_rectangle; eel_canvas_item_send_behind (item, band); } void nemo_icon_container_finish_adding_icon (NemoIconContainer *container, NemoIcon *icon) { eel_canvas_item_show (EEL_CANVAS_ITEM (icon->item)); g_signal_connect_object (icon->item, "event", G_CALLBACK (item_event_callback), container, 0); g_signal_emit (container, signals[ICON_ADDED], 0, icon->data); } void nemo_icon_container_move_icon (NemoIconContainer *container, NemoIcon *icon, int x, int y, double scale, gboolean raise, gboolean snap, gboolean update_position) { NEMO_ICON_CONTAINER_GET_CLASS (container)->move_icon (container, icon, x, y, scale, raise, snap, update_position); } void nemo_icon_container_icon_set_position (NemoIconContainer *container, NemoIcon *icon, gdouble x, gdouble y) { NEMO_ICON_CONTAINER_GET_CLASS (container)->icon_set_position (container, icon, x, y); } void nemo_icon_container_icon_get_bounding_box (NemoIconContainer *container, NemoIcon *icon, int *x1_return, int *y1_return, int *x2_return, int *y2_return, NemoIconCanvasItemBoundsUsage usage) { NEMO_ICON_CONTAINER_GET_CLASS (container)->icon_get_bounding_box (icon, x1_return, y1_return, x2_return, y2_return, usage); } void nemo_icon_container_update_icon (NemoIconContainer *container, NemoIcon *icon) { NEMO_ICON_CONTAINER_GET_CLASS (container)->update_icon (container, icon); } #endif /* ! NEMO_OMIT_SELF_CHECK */ nemo-3.6.5/libnemo-private/nemo-file-conflict-dialog.c0000664000175000017500000004566513215733314021601 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-file-conflict-dialog: dialog that handles file conflicts during transfer operations. Copyright (C) 2008-2010 Cosimo Cecchi This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Cosimo Cecchi */ #include #include "nemo-file-conflict-dialog.h" #include #include #include #include #include #include #include "nemo-file.h" #include "nemo-icon-info.h" struct _NemoFileConflictDialogDetails { /* conflicting objects */ NemoFile *source; NemoFile *destination; NemoFile *dest_dir; gchar *conflict_name; NemoFileListHandle *handle; gulong src_handler_id; gulong dest_handler_id; /* UI objects */ GtkWidget *titles_vbox; GtkWidget *first_hbox; GtkWidget *second_hbox; GtkWidget *expander; GtkWidget *entry; GtkWidget *checkbox; GtkWidget *rename_button; GtkWidget *replace_button; GtkWidget *dest_image; GtkWidget *src_image; }; G_DEFINE_TYPE (NemoFileConflictDialog, nemo_file_conflict_dialog, GTK_TYPE_DIALOG); #define NEMO_FILE_CONFLICT_DIALOG_GET_PRIVATE(object) \ (G_TYPE_INSTANCE_GET_PRIVATE ((object), NEMO_TYPE_FILE_CONFLICT_DIALOG, \ NemoFileConflictDialogDetails)) static void file_icons_changed (NemoFile *file, NemoFileConflictDialog *fcd) { GdkPixbuf *pixbuf; pixbuf = nemo_file_get_icon_pixbuf (fcd->details->destination, NEMO_ICON_SIZE_LARGE, TRUE, gtk_widget_get_scale_factor (fcd->details->dest_image), NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS); gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->dest_image), pixbuf); g_object_unref (pixbuf); pixbuf = nemo_file_get_icon_pixbuf (fcd->details->source, NEMO_ICON_SIZE_LARGE, TRUE, gtk_widget_get_scale_factor (fcd->details->src_image), NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS); gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->src_image), pixbuf); g_object_unref (pixbuf); } static void file_list_ready_cb (GList *files, gpointer user_data) { NemoFileConflictDialog *fcd = user_data; NemoFile *src, *dest, *dest_dir; time_t src_mtime, dest_mtime; gboolean source_is_dir, dest_is_dir, should_show_type; NemoFileConflictDialogDetails *details; char *primary_text, *message, *secondary_text; const gchar *message_extra; char *dest_name, *dest_dir_name, *edit_name; char *label_text; char *size, *date, *type = NULL; GdkPixbuf *pixbuf; GtkWidget *label; GString *str; PangoAttrList *attr_list; details = fcd->details; details->handle = NULL; dest_dir = g_list_nth_data (files, 0); dest = g_list_nth_data (files, 1); src = g_list_nth_data (files, 2); src_mtime = nemo_file_get_mtime (src); dest_mtime = nemo_file_get_mtime (dest); dest_name = nemo_file_get_display_name (dest); dest_dir_name = nemo_file_get_display_name (dest_dir); source_is_dir = nemo_file_is_directory (src); dest_is_dir = nemo_file_is_directory (dest); type = nemo_file_get_mime_type (dest); should_show_type = !nemo_file_is_mime_type (src, type); g_clear_pointer (&type, g_free); /* Set up the right labels */ if (dest_is_dir) { if (source_is_dir) { primary_text = g_strdup_printf (_("Merge folder \"%s\"?"), dest_name); message_extra = _("Merging will ask for confirmation before replacing any files in " "the folder that conflict with the files being copied."); if (src_mtime > dest_mtime) { message = g_strdup_printf ( _("An older folder with the same name already exists in \"%s\"."), dest_dir_name); } else if (src_mtime < dest_mtime) { message = g_strdup_printf ( _("A newer folder with the same name already exists in \"%s\"."), dest_dir_name); } else { message = g_strdup_printf ( _("Another folder with the same name already exists in \"%s\"."), dest_dir_name); } } else { message_extra = _("Replacing it will remove all files in the folder."); primary_text = g_strdup_printf (_("Replace folder \"%s\"?"), dest_name); message = g_strdup_printf (_("A folder with the same name already exists in \"%s\"."), dest_dir_name); } } else { primary_text = g_strdup_printf (_("Replace file \"%s\"?"), dest_name); message_extra = _("Replacing it will overwrite its content."); if (src_mtime > dest_mtime) { message = g_strdup_printf ( _("An older file with the same name already exists in \"%s\"."), dest_dir_name); } else if (src_mtime < dest_mtime) { message = g_strdup_printf ( _("A newer file with the same name already exists in \"%s\"."), dest_dir_name); } else { message = g_strdup_printf ( _("Another file with the same name already exists in \"%s\"."), dest_dir_name); } } secondary_text = g_strdup_printf ("%s\n%s", message, message_extra); g_clear_pointer (&message, g_free); label = gtk_label_new (primary_text); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (details->titles_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); attr_list = pango_attr_list_new (); pango_attr_list_insert (attr_list, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); pango_attr_list_insert (attr_list, pango_attr_scale_new (PANGO_SCALE_LARGE)); g_object_set (label, "attributes", attr_list, NULL); pango_attr_list_unref (attr_list); label = gtk_label_new (secondary_text); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_box_pack_start (GTK_BOX (details->titles_vbox), label, FALSE, FALSE, 0); gtk_widget_show (label); g_free (primary_text); g_free (secondary_text); /* Set up file icons */ pixbuf = nemo_file_get_icon_pixbuf (dest, NEMO_ICON_SIZE_LARGE, TRUE, gtk_widget_get_scale_factor (fcd->details->titles_vbox), NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS); details->dest_image = gtk_image_new_from_pixbuf (pixbuf); gtk_box_pack_start (GTK_BOX (details->first_hbox), details->dest_image, FALSE, FALSE, 0); gtk_widget_show (details->dest_image); g_object_unref (pixbuf); pixbuf = nemo_file_get_icon_pixbuf (src, NEMO_ICON_SIZE_LARGE, TRUE, gtk_widget_get_scale_factor (fcd->details->titles_vbox), NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS); details->src_image = gtk_image_new_from_pixbuf (pixbuf); gtk_box_pack_start (GTK_BOX (details->second_hbox), details->src_image, FALSE, FALSE, 0); gtk_widget_show (details->src_image); g_object_unref (pixbuf); /* Set up labels */ label = gtk_label_new (NULL); date = nemo_file_get_string_attribute (dest, "date_modified"); size = nemo_file_get_string_attribute (dest, "size"); if (should_show_type) { type = nemo_file_get_string_attribute (dest, "type"); } str = g_string_new (NULL); g_string_append_printf (str, "%s\n", _("Original file")); g_string_append_printf (str, "%s %s\n", _("Size:"), size); if (should_show_type) { g_string_append_printf (str, "%s %s\n", _("Type:"), type); } g_string_append_printf (str, "%s %s", _("Last modified:"), date); label_text = str->str; gtk_label_set_markup (GTK_LABEL (label), label_text); gtk_box_pack_start (GTK_BOX (details->first_hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); g_clear_pointer (&size, g_free); g_clear_pointer (&type, g_free); g_clear_pointer (&date, g_free); g_string_erase (str, 0, -1); /* Second label */ label = gtk_label_new (NULL); date = nemo_file_get_string_attribute (src, "date_modified"); size = nemo_file_get_string_attribute (src, "size"); if (should_show_type) { type = nemo_file_get_string_attribute (src, "type"); } g_string_append_printf (str, "%s\n", _("Replace with")); g_string_append_printf (str, "%s %s\n", _("Size:"), size); if (should_show_type) { g_string_append_printf (str, "%s %s\n", _("Type:"), type); } g_string_append_printf (str, "%s %s", _("Last modified:"), date); label_text = g_string_free (str, FALSE); gtk_label_set_markup (GTK_LABEL (label), label_text); gtk_box_pack_start (GTK_BOX (details->second_hbox), label, FALSE, FALSE, 0); gtk_widget_show (label); g_clear_pointer (&size, g_free); g_clear_pointer (&type, g_free); g_clear_pointer (&date, g_free); g_clear_pointer (&label_text, g_free); /* Populate the entry */ edit_name = nemo_file_get_edit_name (dest); details->conflict_name = edit_name; gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name); if (source_is_dir && dest_is_dir) { gtk_button_set_label (GTK_BUTTON (details->replace_button), _("Merge")); } nemo_file_monitor_add (src, fcd, NEMO_FILE_ATTRIBUTES_FOR_ICON); nemo_file_monitor_add (dest, fcd, NEMO_FILE_ATTRIBUTES_FOR_ICON); details->src_handler_id = g_signal_connect (src, "changed", G_CALLBACK (file_icons_changed), fcd); details->dest_handler_id = g_signal_connect (dest, "changed", G_CALLBACK (file_icons_changed), fcd); } static void build_dialog_appearance (NemoFileConflictDialog *fcd) { GList *files = NULL; NemoFileConflictDialogDetails *details = fcd->details; files = g_list_prepend (files, details->source); files = g_list_prepend (files, details->destination); files = g_list_prepend (files, details->dest_dir); nemo_file_list_call_when_ready (files, NEMO_FILE_ATTRIBUTES_FOR_ICON, &details->handle, file_list_ready_cb, fcd); g_list_free (files); } static void set_source_and_destination (GtkWidget *w, GFile *source, GFile *destination, GFile *dest_dir) { NemoFileConflictDialog *dialog; NemoFileConflictDialogDetails *details; dialog = NEMO_FILE_CONFLICT_DIALOG (w); details = dialog->details; details->source = nemo_file_get (source); details->destination = nemo_file_get (destination); details->dest_dir = nemo_file_get (dest_dir); build_dialog_appearance (dialog); } static void entry_text_changed_cb (GtkEditable *entry, NemoFileConflictDialog *dialog) { NemoFileConflictDialogDetails *details; details = dialog->details; /* The rename button is visible only if there's text * in the entry. */ if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), "") != 0 && g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), details->conflict_name) != 0) { gtk_widget_hide (details->replace_button); gtk_widget_show (details->rename_button); gtk_widget_set_sensitive (details->checkbox, FALSE); gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_RENAME); } else { gtk_widget_hide (details->rename_button); gtk_widget_show (details->replace_button); gtk_widget_set_sensitive (details->checkbox, TRUE); gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_REPLACE); } } static void expander_activated_cb (GtkExpander *w, NemoFileConflictDialog *dialog) { NemoFileConflictDialogDetails *details; int start_pos, end_pos; details = dialog->details; if (!gtk_expander_get_expanded (w)) { if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)), details->conflict_name) == 0) { gtk_widget_grab_focus (details->entry); eel_filename_get_rename_region (details->conflict_name, &start_pos, &end_pos); gtk_editable_select_region (GTK_EDITABLE (details->entry), start_pos, end_pos); } } } static void checkbox_toggled_cb (GtkToggleButton *t, NemoFileConflictDialog *dialog) { NemoFileConflictDialogDetails *details; details = dialog->details; gtk_widget_set_sensitive (details->expander, !gtk_toggle_button_get_active (t)); gtk_widget_set_sensitive (details->rename_button, !gtk_toggle_button_get_active (t)); if (!gtk_toggle_button_get_active (t) && g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)), "") != 0 && g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)), details->conflict_name) != 0) { gtk_widget_hide (details->replace_button); gtk_widget_show (details->rename_button); } else { gtk_widget_hide (details->rename_button); gtk_widget_show (details->replace_button); } } static void reset_button_clicked_cb (GtkButton *w, NemoFileConflictDialog *dialog) { NemoFileConflictDialogDetails *details; int start_pos, end_pos; details = dialog->details; gtk_entry_set_text (GTK_ENTRY (details->entry), details->conflict_name); gtk_widget_grab_focus (details->entry); eel_filename_get_rename_region (details->conflict_name, &start_pos, &end_pos); gtk_editable_select_region (GTK_EDITABLE (details->entry), start_pos, end_pos); } static void nemo_file_conflict_dialog_init (NemoFileConflictDialog *fcd) { GtkWidget *hbox, *vbox, *vbox2, *alignment; GtkWidget *widget, *dialog_area; NemoFileConflictDialogDetails *details; GtkDialog *dialog; details = fcd->details = NEMO_FILE_CONFLICT_DIALOG_GET_PRIVATE (fcd); dialog = GTK_DIALOG (fcd); /* Setup the main hbox */ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); dialog_area = gtk_dialog_get_content_area (dialog); gtk_box_pack_start (GTK_BOX (dialog_area), hbox, FALSE, FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); /* Setup the dialog image */ widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); gtk_misc_set_alignment (GTK_MISC (widget), 0.5, 0.0); /* Setup the vbox containing the dialog body */ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); /* Setup the vbox for the dialog labels */ widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); details->titles_vbox = widget; /* Setup the hboxes to pack file infos into */ alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0); g_object_set (alignment, "left-padding", 12, NULL); vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_add (GTK_CONTAINER (alignment), vbox2); gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); details->first_hbox = hbox; hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); details->second_hbox = hbox; /* Setup the expander for the rename action */ details->expander = gtk_expander_new_with_mnemonic (_("_Select a new name for the destination")); gtk_box_pack_start (GTK_BOX (vbox2), details->expander, FALSE, FALSE, 0); g_signal_connect (details->expander, "activate", G_CALLBACK (expander_activated_cb), dialog); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_container_add (GTK_CONTAINER (details->expander), hbox); widget = gtk_entry_new (); gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6); details->entry = widget; g_signal_connect (widget, "changed", G_CALLBACK (entry_text_changed_cb), dialog); widget = gtk_button_new_with_label (_("Reset")); gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_stock (GTK_STOCK_UNDO, GTK_ICON_SIZE_MENU)); gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6); g_signal_connect (widget, "clicked", G_CALLBACK (reset_button_clicked_cb), dialog); gtk_widget_show_all (alignment); /* Setup the checkbox to apply the action to all files */ widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files")); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); details->checkbox = widget; g_signal_connect (widget, "toggled", G_CALLBACK (checkbox_toggled_cb), dialog); /* Add buttons */ gtk_dialog_add_buttons (dialog, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, _("_Skip"), CONFLICT_RESPONSE_SKIP, NULL); details->rename_button = gtk_dialog_add_button (dialog, _("Re_name"), CONFLICT_RESPONSE_RENAME); gtk_widget_hide (details->rename_button); details->replace_button = gtk_dialog_add_button (dialog, _("Replace"), CONFLICT_RESPONSE_REPLACE); gtk_widget_grab_focus (details->replace_button); /* Setup HIG properties */ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (dialog)), 14); gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); gtk_widget_show_all (dialog_area); } static void do_finalize (GObject *self) { NemoFileConflictDialogDetails *details = NEMO_FILE_CONFLICT_DIALOG (self)->details; g_free (details->conflict_name); if (details->handle != NULL) { nemo_file_list_cancel_call_when_ready (details->handle); } if (details->src_handler_id) { g_signal_handler_disconnect (details->source, details->src_handler_id); nemo_file_monitor_remove (details->source, self); } if (details->dest_handler_id) { g_signal_handler_disconnect (details->destination, details->dest_handler_id); nemo_file_monitor_remove (details->destination, self); } nemo_file_unref (details->source); nemo_file_unref (details->destination); nemo_file_unref (details->dest_dir); G_OBJECT_CLASS (nemo_file_conflict_dialog_parent_class)->finalize (self); } static void nemo_file_conflict_dialog_class_init (NemoFileConflictDialogClass *klass) { G_OBJECT_CLASS (klass)->finalize = do_finalize; g_type_class_add_private (klass, sizeof (NemoFileConflictDialogDetails)); } char * nemo_file_conflict_dialog_get_new_name (NemoFileConflictDialog *dialog) { return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->details->entry))); } gboolean nemo_file_conflict_dialog_get_apply_to_all (NemoFileConflictDialog *dialog) { return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->details->checkbox)); } GtkWidget * nemo_file_conflict_dialog_new (GtkWindow *parent, GFile *source, GFile *destination, GFile *dest_dir) { GtkWidget *dialog; dialog = GTK_WIDGET (g_object_new (NEMO_TYPE_FILE_CONFLICT_DIALOG, "title", _("File conflict"), NULL)); set_source_and_destination (dialog, source, destination, dest_dir); gtk_window_set_transient_for (GTK_WINDOW (dialog), parent); return dialog; } nemo-3.6.5/libnemo-private/nemo-selection-canvas-item.c0000664000175000017500000004051613215733314022006 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Nemo - Canvas item for floating selection. * * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation * Copyright (C) 2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Federico Mena * Cosimo Cecchi */ #include #include "nemo-selection-canvas-item.h" #include enum { PROP_X1 = 1, PROP_Y1, PROP_X2, PROP_Y2, PROP_FILL_COLOR_RGBA, PROP_OUTLINE_COLOR_RGBA, PROP_OUTLINE_STIPPLING, PROP_WIDTH_PIXELS, NUM_PROPERTIES }; static GParamSpec *properties[NUM_PROPERTIES] = { NULL }; typedef struct { /*< public >*/ int x0, y0, x1, y1; } Rect; struct _NemoSelectionCanvasItemDetails { Rect last_update_rect; Rect last_outline_update_rect; int last_outline_update_width; double x1, y1, x2, y2; /* Corners of item */ double width; /* Outline width */ GdkRGBA fill_color; GdkRGBA outline_color; gboolean outline_stippling; /* Configuration flags */ unsigned int fill_set : 1; /* Is fill color set? */ unsigned int outline_set : 1; /* Is outline color set? */ double fade_out_fill_alpha; double fade_out_outline_alpha; double fade_out_fill_delta; double fade_out_outline_delta; guint fade_out_handler_id; }; G_DEFINE_TYPE (NemoSelectionCanvasItem, nemo_selection_canvas_item, EEL_TYPE_CANVAS_ITEM); #define DASH_ON 0.8 #define DASH_OFF 1.7 static void nemo_selection_canvas_item_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region) { NemoSelectionCanvasItem *self; double x1, y1, x2, y2; int cx1, cy1, cx2, cy2; double i2w_dx, i2w_dy; self = NEMO_SELECTION_CANVAS_ITEM (item); /* Get canvas pixel coordinates */ i2w_dx = 0.0; i2w_dy = 0.0; eel_canvas_item_i2w (item, &i2w_dx, &i2w_dy); x1 = self->priv->x1 + i2w_dx; y1 = self->priv->y1 + i2w_dy; x2 = self->priv->x2 + i2w_dx; y2 = self->priv->y2 + i2w_dy; eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); if (cx2 <= cx1 || cy2 <= cy1 ) { return; } cairo_save (cr); if (self->priv->fill_set) { GdkRGBA actual_fill; actual_fill = self->priv->fill_color; if (self->priv->fade_out_handler_id != 0) { actual_fill.alpha = self->priv->fade_out_fill_alpha; } gdk_cairo_set_source_rgba (cr, &actual_fill); cairo_rectangle (cr, cx1, cy1, cx2 - cx1 + 1, cy2 - cy1 + 1); cairo_fill (cr); } if (self->priv->outline_set) { GdkRGBA actual_outline; actual_outline = self->priv->outline_color; if (self->priv->fade_out_handler_id != 0) { actual_outline.alpha = self->priv->fade_out_outline_alpha; } gdk_cairo_set_source_rgba (cr, &actual_outline); cairo_set_line_width (cr, (int) self->priv->width); if (self->priv->outline_stippling) { double dash[2] = { DASH_ON, DASH_OFF }; cairo_set_dash (cr, dash, G_N_ELEMENTS (dash), 0); } cairo_rectangle (cr, cx1 + 0.5, cy1 + 0.5, cx2 - cx1, cy2 - cy1); cairo_stroke (cr); } cairo_restore (cr); } static double nemo_selection_canvas_item_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) { NemoSelectionCanvasItem *self; double x1, y1, x2, y2; double hwidth; double dx, dy; double tmp; self = NEMO_SELECTION_CANVAS_ITEM (item); *actual_item = item; /* Find the bounds for the rectangle plus its outline width */ x1 = self->priv->x1; y1 = self->priv->y1; x2 = self->priv->x2; y2 = self->priv->y2; if (self->priv->outline_set) { hwidth = (self->priv->width / item->canvas->pixels_per_unit) / 2.0; x1 -= hwidth; y1 -= hwidth; x2 += hwidth; y2 += hwidth; } else hwidth = 0.0; /* Is point inside rectangle (which can be hollow if it has no fill set)? */ if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { if (self->priv->fill_set || !self->priv->outline_set) return 0.0; dx = x - x1; tmp = x2 - x; if (tmp < dx) dx = tmp; dy = y - y1; tmp = y2 - y; if (tmp < dy) dy = tmp; if (dy < dx) dx = dy; dx -= 2.0 * hwidth; if (dx < 0.0) return 0.0; else return dx; } /* Point is outside rectangle */ if (x < x1) dx = x1 - x; else if (x > x2) dx = x - x2; else dx = 0.0; if (y < y1) dy = y1 - y; else if (y > y2) dy = y - y2; else dy = 0.0; return sqrt (dx * dx + dy * dy); } static void request_redraw_borders (EelCanvas *canvas, Rect *update_rect, int width) { eel_canvas_request_redraw (canvas, update_rect->x0, update_rect->y0, update_rect->x1, update_rect->y0 + width); eel_canvas_request_redraw (canvas, update_rect->x0, update_rect->y1-width, update_rect->x1, update_rect->y1); eel_canvas_request_redraw (canvas, update_rect->x0, update_rect->y0, update_rect->x0+width, update_rect->y1); eel_canvas_request_redraw (canvas, update_rect->x1-width, update_rect->y0, update_rect->x1, update_rect->y1); } static Rect make_rect (int x0, int y0, int x1, int y1); static int rect_empty (const Rect *src) { return (src->x1 <= src->x0 || src->y1 <= src->y0); } static gboolean rects_intersect (Rect r1, Rect r2) { if (r1.x0 >= r2.x1) { return FALSE; } if (r2.x0 >= r1.x1) { return FALSE; } if (r1.y0 >= r2.y1) { return FALSE; } if (r2.y0 >= r1.y1) { return FALSE; } return TRUE; } static void diff_rects_guts (Rect ra, Rect rb, int *count, Rect result[4]) { if (ra.x0 < rb.x0) { result[(*count)++] = make_rect (ra.x0, ra.y0, rb.x0, ra.y1); } if (ra.y0 < rb.y0) { result[(*count)++] = make_rect (ra.x0, ra.y0, ra.x1, rb.y0); } if (ra.x1 < rb.x1) { result[(*count)++] = make_rect (ra.x1, rb.y0, rb.x1, rb.y1); } if (ra.y1 < rb.y1) { result[(*count)++] = make_rect (rb.x0, ra.y1, rb.x1, rb.y1); } } static void diff_rects (Rect r1, Rect r2, int *count, Rect result[4]) { g_assert (count != NULL); g_assert (result != NULL); *count = 0; if (rects_intersect (r1, r2)) { diff_rects_guts (r1, r2, count, result); diff_rects_guts (r2, r1, count, result); } else { if (!rect_empty (&r1)) { result[(*count)++] = r1; } if (!rect_empty (&r2)) { result[(*count)++] = r2; } } } static Rect make_rect (int x0, int y0, int x1, int y1) { Rect r; r.x0 = x0; r.y0 = y0; r.x1 = x1; r.y1 = y1; return r; } static void nemo_selection_canvas_item_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, gint flags) { NemoSelectionCanvasItem *self; NemoSelectionCanvasItemDetails *priv; double x1, y1, x2, y2; int cx1, cy1, cx2, cy2; int repaint_rects_count, i; int width_pixels; int width_lt, width_rb; Rect update_rect, repaint_rects[4]; if (EEL_CANVAS_ITEM_CLASS (nemo_selection_canvas_item_parent_class)->update) (* EEL_CANVAS_ITEM_CLASS (nemo_selection_canvas_item_parent_class)->update) (item, i2w_dx, i2w_dy, flags); self = NEMO_SELECTION_CANVAS_ITEM (item); priv = self->priv; x1 = priv->x1 + i2w_dx; y1 = priv->y1 + i2w_dy; x2 = priv->x2 + i2w_dx; y2 = priv->y2 + i2w_dy; eel_canvas_w2c (item->canvas, x1, y1, &cx1, &cy1); eel_canvas_w2c (item->canvas, x2, y2, &cx2, &cy2); update_rect = make_rect (cx1, cy1, cx2+1, cy2+1); diff_rects (update_rect, priv->last_update_rect, &repaint_rects_count, repaint_rects); for (i = 0; i < repaint_rects_count; i++) { eel_canvas_request_redraw (item->canvas, repaint_rects[i].x0, repaint_rects[i].y0, repaint_rects[i].x1, repaint_rects[i].y1); } priv->last_update_rect = update_rect; if (priv->outline_set) { /* Outline and bounding box */ width_pixels = (int) priv->width; width_lt = width_pixels / 2; width_rb = (width_pixels + 1) / 2; cx1 -= width_lt; cy1 -= width_lt; cx2 += width_rb; cy2 += width_rb; update_rect = make_rect (cx1, cy1, cx2, cy2); request_redraw_borders (item->canvas, &update_rect, (width_lt + width_rb)); request_redraw_borders (item->canvas, &priv->last_outline_update_rect, priv->last_outline_update_width); priv->last_outline_update_rect = update_rect; priv->last_outline_update_width = width_lt + width_rb; item->x1 = cx1; item->y1 = cy1; item->x2 = cx2+1; item->y2 = cy2+1; } else { item->x1 = cx1; item->y1 = cy1; item->x2 = cx2+1; item->y2 = cy2+1; } } static void nemo_selection_canvas_item_translate (EelCanvasItem *item, double dx, double dy) { NemoSelectionCanvasItem *self; self = NEMO_SELECTION_CANVAS_ITEM (item); self->priv->x1 += dx; self->priv->y1 += dy; self->priv->x2 += dx; self->priv->y2 += dy; } static void nemo_selection_canvas_item_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { NemoSelectionCanvasItem *self; double hwidth; self = NEMO_SELECTION_CANVAS_ITEM (item); hwidth = (self->priv->width / item->canvas->pixels_per_unit) / 2.0; *x1 = self->priv->x1 - hwidth; *y1 = self->priv->y1 - hwidth; *x2 = self->priv->x2 + hwidth; *y2 = self->priv->y2 + hwidth; } #define FADE_OUT_STEPS 5 #define FADE_OUT_SPEED 30 static gboolean fade_and_request_redraw (gpointer user_data) { NemoSelectionCanvasItem *self = user_data; if (self->priv->fade_out_fill_alpha <= 0 || self->priv->fade_out_outline_alpha <= 0) { self->priv->fade_out_handler_id = 0; eel_canvas_item_destroy (EEL_CANVAS_ITEM (self)); return FALSE; } self->priv->fade_out_fill_alpha -= self->priv->fade_out_fill_delta; self->priv->fade_out_outline_alpha -= self->priv->fade_out_outline_delta; eel_canvas_item_request_redraw (EEL_CANVAS_ITEM (self)); return TRUE; } void nemo_selection_canvas_item_fade_out (NemoSelectionCanvasItem *self, guint transition_time) { self->priv->fade_out_fill_alpha = self->priv->fill_color.alpha; self->priv->fade_out_outline_alpha = self->priv->outline_color.alpha; self->priv->fade_out_fill_delta = self->priv->fade_out_fill_alpha / FADE_OUT_STEPS; self->priv->fade_out_outline_delta = self->priv->fade_out_outline_alpha / FADE_OUT_STEPS; self->priv->fade_out_handler_id = g_timeout_add ((guint) (transition_time / FADE_OUT_STEPS), fade_and_request_redraw, self); } static void nemo_selection_canvas_item_dispose (GObject *obj) { NemoSelectionCanvasItem *self = NEMO_SELECTION_CANVAS_ITEM (obj); if (self->priv->fade_out_handler_id != 0) { g_source_remove (self->priv->fade_out_handler_id); self->priv->fade_out_handler_id = 0; } G_OBJECT_CLASS (nemo_selection_canvas_item_parent_class)->dispose (obj); } static void do_set_fill (NemoSelectionCanvasItem *self, gboolean fill_set) { if (self->priv->fill_set != fill_set) { self->priv->fill_set = fill_set; eel_canvas_item_request_update (EEL_CANVAS_ITEM (self)); } } static void do_set_outline (NemoSelectionCanvasItem *self, gboolean outline_set) { if (self->priv->outline_set != outline_set) { self->priv->outline_set = outline_set; eel_canvas_item_request_update (EEL_CANVAS_ITEM (self)); } } static void nemo_selection_canvas_item_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { EelCanvasItem *item; NemoSelectionCanvasItem *self; self = NEMO_SELECTION_CANVAS_ITEM (object); item = EEL_CANVAS_ITEM (object); switch (param_id) { case PROP_X1: self->priv->x1 = g_value_get_double (value); eel_canvas_item_request_update (item); break; case PROP_Y1: self->priv->y1 = g_value_get_double (value); eel_canvas_item_request_update (item); break; case PROP_X2: self->priv->x2 = g_value_get_double (value); eel_canvas_item_request_update (item); break; case PROP_Y2: self->priv->y2 = g_value_get_double (value); eel_canvas_item_request_update (item); break; case PROP_FILL_COLOR_RGBA: { GdkRGBA *color; color = g_value_get_boxed (value); do_set_fill (self, color != NULL); if (color != NULL) { self->priv->fill_color = *color; } eel_canvas_item_request_redraw (item); break; } case PROP_OUTLINE_COLOR_RGBA: { GdkRGBA *color; color = g_value_get_boxed (value); do_set_outline (self, color != NULL); if (color != NULL) { self->priv->outline_color = *color; } eel_canvas_item_request_redraw (item); break; } case PROP_OUTLINE_STIPPLING: self->priv->outline_stippling = g_value_get_boolean (value); eel_canvas_item_request_redraw (item); break; case PROP_WIDTH_PIXELS: self->priv->width = g_value_get_uint (value); eel_canvas_item_request_update (item); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void nemo_selection_canvas_item_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { NemoSelectionCanvasItem *self; self = NEMO_SELECTION_CANVAS_ITEM (object); switch (param_id) { case PROP_X1: g_value_set_double (value, self->priv->x1); break; case PROP_Y1: g_value_set_double (value, self->priv->y1); break; case PROP_X2: g_value_set_double (value, self->priv->x2); break; case PROP_Y2: g_value_set_double (value, self->priv->y2); break; case PROP_FILL_COLOR_RGBA: g_value_set_boxed (value, &self->priv->fill_color); break; case PROP_OUTLINE_COLOR_RGBA: g_value_set_boxed (value, &self->priv->outline_color); break; case PROP_OUTLINE_STIPPLING: g_value_set_boolean (value, self->priv->outline_stippling); break; case PROP_WIDTH_PIXELS: g_value_set_uint (value, self->priv->width); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void nemo_selection_canvas_item_class_init (NemoSelectionCanvasItemClass *klass) { EelCanvasItemClass *item_class; GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); item_class = EEL_CANVAS_ITEM_CLASS (klass); gobject_class->set_property = nemo_selection_canvas_item_set_property; gobject_class->get_property = nemo_selection_canvas_item_get_property; gobject_class->dispose = nemo_selection_canvas_item_dispose; item_class->draw = nemo_selection_canvas_item_draw; item_class->point = nemo_selection_canvas_item_point; item_class->update = nemo_selection_canvas_item_update; item_class->bounds = nemo_selection_canvas_item_bounds; item_class->translate = nemo_selection_canvas_item_translate; properties[PROP_X1] = g_param_spec_double ("x1", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE); properties[PROP_Y1] = g_param_spec_double ("y1", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE); properties[PROP_X2] = g_param_spec_double ("x2", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE); properties[PROP_Y2] = g_param_spec_double ("y2", NULL, NULL, -G_MAXDOUBLE, G_MAXDOUBLE, 0, G_PARAM_READWRITE); properties[PROP_FILL_COLOR_RGBA] = g_param_spec_boxed ("fill-color-rgba", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE); properties[PROP_OUTLINE_COLOR_RGBA] = g_param_spec_boxed ("outline-color-rgba", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE); properties[PROP_OUTLINE_STIPPLING] = g_param_spec_boolean ("outline-stippling", NULL, NULL, FALSE, G_PARAM_READWRITE); properties[PROP_WIDTH_PIXELS] = g_param_spec_uint ("width-pixels", NULL, NULL, 0, G_MAXUINT, 0, G_PARAM_READWRITE); g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties); g_type_class_add_private (klass, sizeof (NemoSelectionCanvasItemDetails)); } static void nemo_selection_canvas_item_init (NemoSelectionCanvasItem *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NEMO_TYPE_SELECTION_CANVAS_ITEM, NemoSelectionCanvasItemDetails); } nemo-3.6.5/libnemo-private/nemo-icon-canvas-item.h0000664000175000017500000001316013215733314020751 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Nemo - Icon canvas item class for icon container. * * Copyright (C) 2000 Eazel, Inc. * * Author: Andy Hertzfeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef NEMO_ICON_CANVAS_ITEM_H #define NEMO_ICON_CANVAS_ITEM_H #include #include G_BEGIN_DECLS #define NEMO_TYPE_ICON_CANVAS_ITEM nemo_icon_canvas_item_get_type() #define NEMO_ICON_CANVAS_ITEM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ICON_CANVAS_ITEM, NemoIconCanvasItem)) #define NEMO_ICON_CANVAS_ITEM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ICON_CANVAS_ITEM, NemoIconCanvasItemClass)) #define NEMO_IS_ICON_CANVAS_ITEM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ICON_CANVAS_ITEM)) #define NEMO_IS_ICON_CANVAS_ITEM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ICON_CANVAS_ITEM)) #define NEMO_ICON_CANVAS_ITEM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ICON_CANVAS_ITEM, NemoIconCanvasItemClass)) typedef struct NemoIconCanvasItem NemoIconCanvasItem; typedef struct NemoIconCanvasItemClass NemoIconCanvasItemClass; typedef struct NemoIconCanvasItemDetails NemoIconCanvasItemDetails; struct NemoIconCanvasItem { EelCanvasItem item; NemoIconCanvasItemDetails *details; gpointer user_data; gchar *tooltip; }; struct NemoIconCanvasItemClass { EelCanvasItemClass parent_class; }; /* not namespaced due to their length */ typedef enum { BOUNDS_USAGE_FOR_LAYOUT, BOUNDS_USAGE_FOR_ENTIRE_ITEM, BOUNDS_USAGE_FOR_DISPLAY } NemoIconCanvasItemBoundsUsage; /* GObject */ GType nemo_icon_canvas_item_get_type (void); /* attributes */ void nemo_icon_canvas_item_set_image (NemoIconCanvasItem *item, GdkPixbuf *image); cairo_surface_t* nemo_icon_canvas_item_get_drag_surface (NemoIconCanvasItem *item); void nemo_icon_canvas_item_set_emblems (NemoIconCanvasItem *item, GList *emblem_pixbufs); void nemo_icon_canvas_item_set_show_stretch_handles (NemoIconCanvasItem *item, gboolean show_stretch_handles); void nemo_icon_canvas_item_set_attach_points (NemoIconCanvasItem *item, GdkPoint *attach_points, int n_attach_points); void nemo_icon_canvas_item_set_embedded_text_rect (NemoIconCanvasItem *item, const GdkRectangle *text_rect); void nemo_icon_canvas_item_set_embedded_text (NemoIconCanvasItem *item, const char *text); double nemo_icon_canvas_item_get_max_text_width (NemoIconCanvasItem *item); const char *nemo_icon_canvas_item_get_editable_text (NemoIconCanvasItem *icon_item); void nemo_icon_canvas_item_set_renaming (NemoIconCanvasItem *icon_item, gboolean state); /* geometry and hit testing */ gboolean nemo_icon_canvas_item_hit_test_rectangle (NemoIconCanvasItem *item, EelIRect canvas_rect); gboolean nemo_icon_canvas_item_hit_test_stretch_handles (NemoIconCanvasItem *item, gdouble world_x, gdouble world_y, GtkCornerType *corner); void nemo_icon_canvas_item_invalidate_label (NemoIconCanvasItem *item); void nemo_icon_canvas_item_invalidate_label_size (NemoIconCanvasItem *item); EelDRect nemo_icon_canvas_item_get_icon_rectangle (const NemoIconCanvasItem *item); EelDRect nemo_icon_canvas_item_get_text_rectangle (NemoIconCanvasItem *item, gboolean for_layout); void nemo_icon_canvas_item_get_icon_canvas_rectangle (NemoIconCanvasItem *item, EelIRect *rect); void nemo_icon_canvas_item_get_bounds_for_layout (NemoIconCanvasItem *item, double *x1, double *y1, double *x2, double *y2); void nemo_icon_canvas_item_get_bounds_for_entire_item (NemoIconCanvasItem *item, double *x1, double *y1, double *x2, double *y2); void nemo_icon_canvas_item_update_bounds (NemoIconCanvasItem *item, double i2w_dx, double i2w_dy); void nemo_icon_canvas_item_set_is_visible (NemoIconCanvasItem *item, gboolean visible); /* whether the entire label text must be visible at all times */ void nemo_icon_canvas_item_set_entire_text (NemoIconCanvasItem *icon_item, gboolean entire_text); void nemo_icon_canvas_item_set_tooltip_text (NemoIconCanvasItem *item, const gchar *text); G_END_DECLS #endif /* NEMO_ICON_CANVAS_ITEM_H */ nemo-3.6.5/libnemo-private/Makefile.am0000664000175000017500000001337313215733314016551 0ustar fabiofabioinclude $(top_srcdir)/Makefile.shared noinst_LTLIBRARIES=libnemo-private.la AM_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_builddir) \ -I$(top_srcdir)/cut-n-paste-code \ $(BASE_CFLAGS) \ $(COMMON_CFLAGS) \ $(NEMO_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ $(TRACKER_CFLAGS) \ -DDATADIR=\""$(datadir)"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DNEMO_DATADIR=\""$(datadir)/nemo"\" \ -DNEMO_EXTENSIONDIR=\""$(libdir)/nemo/extensions-3.0"\" \ $(NULL) dbus_built_sources = nemo-generated.c nemo-generated.h $(dbus_built_sources) : Makefile.am $(top_srcdir)/data/dbus-interfaces.xml gdbus-codegen \ --interface-prefix org.Nemo. \ --c-namespace NemoDBus \ --c-generate-object-manager \ --generate-c-code nemo-generated \ $(top_srcdir)/data/dbus-interfaces.xml \ $(NULL) BUILT_SOURCES = \ $(dbus_built_sources) \ $(NULL) if ENABLE_TRACKER nemo_tracker_engine_sources = \ nemo-search-engine-tracker.c \ nemo-search-engine-tracker.h endif dependency_static_libs = \ $(top_builddir)/cut-n-paste-code/libegg/libegg.la \ $(NULL) libnemo_private_la_LDFLAGS = \ $(WARN_LDFLAGS) \ -no-undefined \ $(NULL) libnemo_private_la_LIBADD = \ $(dependency_static_libs) \ $(SELINUX_LIBS) \ $(TRACKER_LIBS) \ $(top_builddir)/eel/libeel-2.la \ $(top_builddir)/libnemo-extension/libnemo-extension.la \ $(BASE_LIBS) \ $(COMMON_LIBS) \ $(NEMO_LIBS) \ -lm \ $(NULL) libnemo_private_la_SOURCES = \ nemo-action.c \ nemo-action.h \ nemo-action-manager.c \ nemo-action-manager.h \ nemo-bookmark.c \ nemo-bookmark.h \ nemo-cell-renderer-disk.c \ nemo-cell-renderer-disk.h \ nemo-centered-placement-grid.c \ nemo-clipboard-monitor.c \ nemo-clipboard-monitor.h \ nemo-clipboard.c \ nemo-clipboard.h \ nemo-column-chooser.c \ nemo-column-chooser.h \ nemo-column-utilities.c \ nemo-column-utilities.h \ nemo-context-menu-menu-item.c \ nemo-context-menu-menu-item.h \ nemo-dbus-manager.c \ nemo-dbus-manager.h \ nemo-debug.c \ nemo-debug.h \ nemo-default-file-icon.c \ nemo-default-file-icon.h \ nemo-desktop-directory-file.c \ nemo-desktop-directory-file.h \ nemo-desktop-directory.c \ nemo-desktop-directory.h \ nemo-desktop-icon-file.c \ nemo-desktop-icon-file.h \ nemo-desktop-link-monitor.c \ nemo-desktop-link-monitor.h \ nemo-desktop-link.c \ nemo-desktop-link.h \ nemo-desktop-metadata.c \ nemo-desktop-metadata.h \ nemo-desktop-utils.c \ nemo-desktop-utils.h \ nemo-directory-async.c \ nemo-directory-notify.h \ nemo-directory-private.h \ nemo-directory.c \ nemo-directory.h \ nemo-dnd.c \ nemo-dnd.h \ nemo-entry.c \ nemo-entry.h \ nemo-file-attributes.h \ nemo-file-changes-queue.c \ nemo-file-changes-queue.h \ nemo-file-conflict-dialog.c \ nemo-file-conflict-dialog.h \ nemo-file-dnd.c \ nemo-file-dnd.h \ nemo-file-operations.c \ nemo-file-operations.h \ nemo-file-private.h \ nemo-file-queue.c \ nemo-file-queue.h \ nemo-file-utilities.c \ nemo-file-utilities.h \ nemo-file.c \ nemo-file.h \ nemo-generated.c \ nemo-generated.h \ nemo-global-preferences.c \ nemo-global-preferences.h \ nemo-icon.h \ nemo-icon-canvas-item.c \ nemo-icon-canvas-item.h \ nemo-icon-container.c \ nemo-icon-container.h \ nemo-icon-dnd.c \ nemo-icon-dnd.h \ nemo-icon-private.h \ nemo-icon-info.c \ nemo-icon-info.h \ nemo-icon-names.h \ nemo-job-queue.c \ nemo-job-queue.h \ nemo-lib-self-check-functions.c \ nemo-lib-self-check-functions.h \ nemo-link.c \ nemo-link.h \ nemo-merged-directory.c \ nemo-merged-directory.h \ nemo-metadata.h \ nemo-metadata.c \ nemo-mime-application-chooser.c \ nemo-mime-application-chooser.h \ nemo-module.c \ nemo-module.h \ nemo-monitor.c \ nemo-monitor.h \ nemo-placement-grid.c \ nemo-places-tree-view.c \ nemo-places-tree-view.h \ nemo-progress-info.c \ nemo-progress-info.h \ nemo-progress-info-manager.c \ nemo-progress-info-manager.h \ nemo-program-choosing.c \ nemo-program-choosing.h \ nemo-recent.c \ nemo-recent.h \ nemo-saved-search-file.c \ nemo-saved-search-file.h \ nemo-search-directory.c \ nemo-search-directory.h \ nemo-search-directory-file.c \ nemo-search-directory-file.h \ nemo-search-engine.c \ nemo-search-engine.h \ nemo-search-engine-simple.c \ nemo-search-engine-simple.h \ nemo-selection-canvas-item.c \ nemo-selection-canvas-item.h \ nemo-signaller.h \ nemo-signaller.c \ nemo-query.c \ nemo-query.h \ nemo-separator-action.c \ nemo-separator-action.h \ nemo-thumbnails.c \ nemo-thumbnails.h \ nemo-trash-monitor.c \ nemo-trash-monitor.h \ nemo-tree-view-drag-dest.c \ nemo-tree-view-drag-dest.h \ nemo-ui-utilities.c \ nemo-ui-utilities.h \ nemo-undo-manager.c \ nemo-undo-manager.h \ nemo-undo-private.h \ nemo-undo-signal-handlers.c \ nemo-undo-signal-handlers.h \ nemo-undo-transaction.c \ nemo-undo-transaction.h \ nemo-undo.c \ nemo-undo.h \ nemo-vfs-directory.c \ nemo-vfs-directory.h \ nemo-vfs-file.c \ nemo-vfs-file.h \ nemo-widget-action.c \ nemo-widget-action.h \ nemo-widget-menu-item.c \ nemo-widget-menu-item.h \ nemo-file-undo-operations.c \ nemo-file-undo-operations.h \ nemo-file-undo-manager.c \ nemo-file-undo-manager.h \ $(nemo_tracker_engine_sources) \ $(NULL) nodist_libnemo_private_la_SOURCES =\ $(BUILT_SOURCES) \ $(NULL) $(lib_LTLIBRARIES): $(dependency_static_libs) gsettingsschema_in_files = org.nemo.gschema.xml.in gsettings_SCHEMAS = $(gsettingsschema_in_files:.xml.in=.xml) .PRECIOUS: $(gsettings_SCHEMAS) @INTLTOOL_XML_NOMERGE_RULE@ @GSETTINGS_RULES@ EXTRA_DIST = \ $(gsettingsschema_in_files) \ $(TRACKER_SOURCES) \ $(NULL) CLEANFILES = \ $(BUILT_SOURCES) \ $(gsettings_SCHEMAS) \ $(NULL) dist-hook: cd $(distdir); rm -f $(CLEANFILES) nemo-3.6.5/libnemo-private/nemo-file-utilities.h0000664000175000017500000001055513215733314020551 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-utilities.h - interface for file manipulation routines. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan */ #ifndef NEMO_FILE_UTILITIES_H #define NEMO_FILE_UTILITIES_H #include #include #define NEMO_SAVED_SEARCH_EXTENSION ".savedSearch" #define NEMO_SAVED_SEARCH_MIMETYPE "application/x-gnome-saved-search" #define DEFAULT_NEMO_DIRECTORY_MODE (0755) #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755) /* These functions all return something something that needs to be * freed with g_free, is not NULL, and is guaranteed to exist. */ char * nemo_get_xdg_dir (const char *type); char * nemo_get_user_directory (void); char * nemo_get_desktop_directory (void); GFile * nemo_get_desktop_location (void); char * nemo_get_desktop_directory_uri (void); char * nemo_get_home_directory_uri (void); gboolean nemo_is_desktop_directory_file (GFile *dir, const char *filename); gboolean nemo_is_root_directory (GFile *dir); gboolean nemo_is_desktop_directory (GFile *dir); gboolean nemo_is_home_directory (GFile *dir); gboolean nemo_is_home_directory_file (GFile *dir, const char *filename); gboolean nemo_is_in_system_dir (GFile *location); char * nemo_get_gmc_desktop_directory (void); gboolean nemo_should_use_templates_directory (void); char * nemo_get_templates_directory (void); char * nemo_get_templates_directory_uri (void); void nemo_create_templates_directory (void); char * nemo_get_searches_directory (void); char * nemo_compute_title_for_location (GFile *file); /* This function returns something that needs to be freed with g_free, * is not NULL, but is not garaunteed to exist */ char * nemo_get_desktop_directory_uri_no_create (void); /* Locate a file in either the uers directory or the datadir. */ char * nemo_get_data_file_path (const char *partial_path); gboolean nemo_is_file_roller_installed (void); /* Inhibit/Uninhibit GNOME Power Manager */ int nemo_inhibit_power_manager (const char *message) G_GNUC_WARN_UNUSED_RESULT; void nemo_uninhibit_power_manager (int cookie); /* Return an allocated file name that is guranteed to be unique, but * tries to make the name readable to users. * This isn't race-free, so don't use for security-related things */ char * nemo_ensure_unique_file_name (const char *directory_uri, const char *base_name, const char *extension); char * nemo_unique_temporary_file_name (void); GFile * nemo_find_existing_uri_in_hierarchy (GFile *location); GFile * nemo_find_file_insensitive (GFile *parent, const gchar *name); char * nemo_get_accel_map_file (void); char * nemo_get_scripts_directory_path (void); GHashTable * nemo_trashed_files_get_original_directories (GList *files, GList **unhandled_files); void nemo_restore_files_from_trash (GList *files, GtkWindow *parent_window); typedef void (*NemoMountGetContent) (const char **content, gpointer user_data); char ** nemo_get_cached_x_content_types_for_mount (GMount *mount); void nemo_get_x_content_types_for_mount_async (GMount *mount, NemoMountGetContent callback, GCancellable *cancellable, gpointer user_data); #endif /* NEMO_FILE_UTILITIES_H */ nemo-3.6.5/libnemo-private/nemo-placement-grid.c0000664000175000017500000001373613215733314020513 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Ettore Perazzoli */ #include "math.h" #include #include "nemo-icon-private.h" NemoPlacementGrid * nemo_placement_grid_new (NemoIconContainer *container, gboolean tight) { NemoPlacementGrid *grid; int width, height; int num_columns; int num_rows; int i; GtkAllocation allocation; /* Get container dimensions */ gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); width = nemo_icon_container_get_canvas_width (container, allocation); height = nemo_icon_container_get_canvas_height (container, allocation); num_columns = width / GET_VIEW_CONSTANT (container, snap_size_x); num_rows = height / GET_VIEW_CONSTANT (container, snap_size_y); if (num_columns == 0 || num_rows == 0) { return NULL; } grid = g_new0 (NemoPlacementGrid, 1); grid->container = container; grid->tight = tight; grid->num_columns = num_columns; grid->num_rows = num_rows; grid->grid_memory = g_new0 (int, (num_rows * num_columns)); grid->icon_grid = g_new0 (int *, num_columns); for (i = 0; i < num_columns; i++) { grid->icon_grid[i] = grid->grid_memory + (i * num_rows); } return grid; } void nemo_placement_grid_free (NemoPlacementGrid *grid) { g_free (grid->icon_grid); g_free (grid->grid_memory); g_free (grid); } gboolean nemo_placement_grid_position_is_free (NemoPlacementGrid *grid, EelIRect pos) { int x, y; g_assert (pos.x0 >= 0 && pos.x0 < grid->num_columns); g_assert (pos.y0 >= 0 && pos.y0 < grid->num_rows); g_assert (pos.x1 >= 0 && pos.x1 < grid->num_columns); g_assert (pos.y1 >= 0 && pos.y1 < grid->num_rows); for (x = pos.x0; x <= pos.x1; x++) { for (y = pos.y0; y <= pos.y1; y++) { if (grid->icon_grid[x][y] != 0) { return FALSE; } } } return TRUE; } void nemo_placement_grid_mark (NemoPlacementGrid *grid, EelIRect pos) { int x, y; g_assert (pos.x0 >= 0 && pos.x0 < grid->num_columns); g_assert (pos.y0 >= 0 && pos.y0 < grid->num_rows); g_assert (pos.x1 >= 0 && pos.x1 < grid->num_columns); g_assert (pos.y1 >= 0 && pos.y1 < grid->num_rows); for (x = pos.x0; x <= pos.x1; x++) { for (y = pos.y0; y <= pos.y1; y++) { grid->icon_grid[x][y] = 1; } } } void nemo_placement_grid_canvas_position_to_grid_position (NemoPlacementGrid *grid, EelIRect canvas_position, EelIRect *grid_position) { /* The first causes minimal moving around during a snap, but * can end up with partially overlapping icons. The second one won't * allow any overlapping, but can cause more movement to happen * during a snap. */ NemoIconContainer *container = grid->container; if (grid->tight) { grid_position->x0 = ceil ((double)(canvas_position.x0 - GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) / GET_VIEW_CONSTANT (container, snap_size_x)); grid_position->y0 = ceil ((double)(canvas_position.y0 - GET_VIEW_CONSTANT (container, desktop_pad_vertical)) / GET_VIEW_CONSTANT (container, snap_size_y)); grid_position->x1 = floor ((double)(canvas_position.x1 - GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) / GET_VIEW_CONSTANT (container, snap_size_x)); grid_position->y1 = floor ((double)(canvas_position.y1 - GET_VIEW_CONSTANT (container, desktop_pad_vertical)) / GET_VIEW_CONSTANT (container, snap_size_y)); } else { grid_position->x0 = floor ((double)(canvas_position.x0 - GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) / GET_VIEW_CONSTANT (container, snap_size_x)); grid_position->y0 = floor ((double)(canvas_position.y0 - GET_VIEW_CONSTANT (container, desktop_pad_vertical)) / GET_VIEW_CONSTANT (container, snap_size_y)); grid_position->x1 = floor ((double)(canvas_position.x1 - GET_VIEW_CONSTANT (container, desktop_pad_horizontal)) / GET_VIEW_CONSTANT (container, snap_size_x)); grid_position->y1 = floor ((double)(canvas_position.y1 - GET_VIEW_CONSTANT (container, desktop_pad_vertical)) / GET_VIEW_CONSTANT (container, snap_size_y)); } grid_position->x0 = CLAMP (grid_position->x0, 0, grid->num_columns - 1); grid_position->y0 = CLAMP (grid_position->y0, 0, grid->num_rows - 1); grid_position->x1 = CLAMP (grid_position->x1, grid_position->x0, grid->num_columns - 1); grid_position->y1 = CLAMP (grid_position->y1, grid_position->y0, grid->num_rows - 1); } void nemo_placement_grid_mark_icon (NemoPlacementGrid *grid, NemoIcon *icon) { EelIRect icon_pos; EelIRect grid_pos; nemo_icon_container_icon_get_bounding_box (grid->container, icon, &icon_pos.x0, &icon_pos.y0, &icon_pos.x1, &icon_pos.y1, BOUNDS_USAGE_FOR_LAYOUT); nemo_placement_grid_canvas_position_to_grid_position (grid, icon_pos, &grid_pos); nemo_placement_grid_mark (grid, grid_pos); } nemo-3.6.5/libnemo-private/nemo-selection-canvas-item.h0000664000175000017500000000512213215733314022005 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Nemo - Canvas item for floating selection. * * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation * Copyright (C) 2011 Red Hat Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Federico Mena * Cosimo Cecchi */ #ifndef __NEMO_SELECTION_CANVAS_ITEM_H__ #define __NEMO_SELECTION_CANVAS_ITEM_H__ #include G_BEGIN_DECLS #define NEMO_TYPE_SELECTION_CANVAS_ITEM nemo_selection_canvas_item_get_type() #define NEMO_SELECTION_CANVAS_ITEM(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_SELECTION_CANVAS_ITEM, NemoSelectionCanvasItem)) #define NEMO_SELECTION_CANVAS_ITEM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_SELECTION_CANVAS_ITEM, NemoSelectionCanvasItemClass)) #define NEMO_IS_SELECTION_CANVAS_ITEM(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_SELECTION_CANVAS_ITEM)) #define NEMO_IS_SELECTION_CANVAS_ITEM_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_SELECTION_CANVAS_ITEM)) #define NEMO_SELECTION_CANVAS_ITEM_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_SELECTION_CANVAS_ITEM, NemoSelectionCanvasItemClass)) typedef struct _NemoSelectionCanvasItem NemoSelectionCanvasItem; typedef struct _NemoSelectionCanvasItemClass NemoSelectionCanvasItemClass; typedef struct _NemoSelectionCanvasItemDetails NemoSelectionCanvasItemDetails; struct _NemoSelectionCanvasItem { EelCanvasItem item; NemoSelectionCanvasItemDetails *priv; gpointer user_data; }; struct _NemoSelectionCanvasItemClass { EelCanvasItemClass parent_class; }; /* GObject */ GType nemo_selection_canvas_item_get_type (void); void nemo_selection_canvas_item_fade_out (NemoSelectionCanvasItem *self, guint transition_time); G_END_DECLS #endif /* __NEMO_SELECTION_CANVAS_ITEM_H__ */ nemo-3.6.5/libnemo-private/nemo-desktop-metadata.h0000664000175000017500000000421113215733314021040 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 2011 Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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; see the file COPYING. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: Cosimo Cecchi */ #ifndef __NEMO_DESKTOP_METADATA_H__ #define __NEMO_DESKTOP_METADATA_H__ #include #include void nemo_desktop_metadata_init (void); void nemo_desktop_set_metadata_string (NemoFile *file, const gchar *name, const gchar *key, const gchar *string); void nemo_desktop_set_metadata_stringv (NemoFile *file, const char *name, const char *key, const char * const *stringv); void nemo_desktop_clear_metadata (NemoFile *file); gchar *nemo_desktop_get_metadata_string (NemoFile *file, const gchar *name, const gchar *key); gchar **nemo_desktop_get_metadata_stringv (NemoFile *file, const char *name, const char *key); gboolean nemo_desktop_update_metadata_from_keyfile (NemoFile *file, const gchar *name); #endif /* __NEMO_DESKTOP_METADATA_H__ */ nemo-3.6.5/libnemo-private/nemo-column-utilities.c0000664000175000017500000002122613215733314021117 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-column-utilities.h - Utilities related to column specifications Copyright (C) 2004 Novell, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the column COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Dave Camp */ #include #include "nemo-column-utilities.h" #include #include #include #include #include static GList * get_builtin_columns (void) { GList *columns; columns = g_list_append (NULL, g_object_new (NEMO_TYPE_COLUMN, "name", "name", "attribute", "name", "label", _("Name"), "description", _("The name and icon of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "size", "attribute", "size", "label", _("Size"), "description", _("The size of the file."), "xalign", 1.0, NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "type", "attribute", "type", "label", _("Type"), "description", _("The general type of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "detailed_type", "attribute", "detailed_type", "label", _("Detailed Type"), "description", _("The specific type of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "date_modified", "attribute", "date_modified", "label", _("Date Modified"), "description", _("The date the file was modified."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "date_accessed", "attribute", "date_accessed", "label", _("Date Accessed"), "description", _("The date the file was accessed."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "owner", "attribute", "owner", "label", _("Owner"), "description", _("The owner of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "group", "attribute", "group", "label", _("Group"), "description", _("The group of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "permissions", "attribute", "permissions", "label", _("Permissions"), "description", _("The permissions of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "octal_permissions", "attribute", "octal_permissions", "label", _("Octal Permissions"), "description", _("The permissions of the file, in octal notation."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "mime_type", "attribute", "mime_type", "label", _("MIME Type"), "description", _("The mime type of the file."), NULL)); #ifdef HAVE_SELINUX columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "selinux_context", "attribute", "selinux_context", "label", _("SELinux Context"), "description", _("The SELinux security context of the file."), NULL)); #endif columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "where", "attribute", "where", "label", _("Location"), "description", _("The location of the file."), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "date_modified_with_time", "attribute", "date_modified_with_time", "label", _("Modified - Time"), "description", _("The date the file was modified."), "xalign", 1.0, NULL)); return columns; } static GList * get_extension_columns (void) { GList *columns; GList *providers; GList *l; providers = nemo_module_get_extensions_for_type (NEMO_TYPE_COLUMN_PROVIDER); columns = NULL; for (l = providers; l != NULL; l = l->next) { NemoColumnProvider *provider; GList *provider_columns; provider = NEMO_COLUMN_PROVIDER (l->data); provider_columns = nemo_column_provider_get_columns (provider); columns = g_list_concat (columns, provider_columns); } nemo_module_extension_list_free (providers); return columns; } static GList * get_trash_columns (void) { static GList *columns = NULL; if (columns == NULL) { columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "trashed_on", "attribute", "trashed_on", "label", _("Trashed On"), "description", _("Date when file was moved to the Trash"), NULL)); columns = g_list_append (columns, g_object_new (NEMO_TYPE_COLUMN, "name", "trash_orig_path", "attribute", "trash_orig_path", "label", _("Original Location"), "description", _("Original location of file before moved to the Trash"), NULL)); } return nemo_column_list_copy (columns); } GList * nemo_get_common_columns (void) { static GList *columns = NULL; if (!columns) { columns = g_list_concat (get_builtin_columns (), get_extension_columns ()); } return nemo_column_list_copy (columns); } GList * nemo_get_all_columns (void) { GList *columns = NULL; columns = g_list_concat (nemo_get_common_columns (), get_trash_columns ()); return columns; } GList * nemo_get_columns_for_file (NemoFile *file) { GList *columns; columns = nemo_get_common_columns (); if (file != NULL && nemo_file_is_in_trash (file)) { columns = g_list_concat (columns, get_trash_columns ()); } return columns; } GList * nemo_column_list_copy (GList *columns) { GList *ret; GList *l; ret = g_list_copy (columns); for (l = ret; l != NULL; l = l->next) { g_object_ref (l->data); } return ret; } void nemo_column_list_free (GList *columns) { GList *l; for (l = columns; l != NULL; l = l->next) { g_object_unref (l->data); } g_list_free (columns); } static int strv_index (char **strv, const char *str) { int i; for (i = 0; strv[i] != NULL; ++i) { if (strcmp (strv[i], str) == 0) return i; } return -1; } static int column_compare (NemoColumn *a, NemoColumn *b, char **column_order) { int index_a; int index_b; char *name; g_object_get (G_OBJECT (a), "name", &name, NULL); index_a = strv_index (column_order, name); g_free (name); g_object_get (G_OBJECT (b), "name", &name, NULL); index_b = strv_index (column_order, name); g_free (name); if (index_a == index_b) { int ret; char *label_a; char *label_b; g_object_get (G_OBJECT (a), "label", &label_a, NULL); g_object_get (G_OBJECT (b), "label", &label_b, NULL); ret = strcmp (label_a, label_b); g_free (label_a); g_free (label_b); return ret; } else if (index_a == -1) { return 1; } else if (index_b == -1) { return -1; } else { return index_a - index_b; } } GList * nemo_sort_columns (GList *columns, char **column_order) { if (!column_order) { return NULL; } return g_list_sort_with_data (columns, (GCompareDataFunc)column_compare, column_order); } nemo-3.6.5/libnemo-private/nemo-widget-action.c0000664000175000017500000002174313215733314020353 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-widget-action.h" #include "nemo-widget-menu-item.h" #include "nemo-context-menu-menu-item.h" G_DEFINE_TYPE (NemoWidgetAction, nemo_widget_action, GTK_TYPE_ACTION); static void nemo_widget_action_init (NemoWidgetAction *action); static void nemo_widget_action_class_init (NemoWidgetActionClass *klass); static void nemo_widget_action_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void nemo_widget_action_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void nemo_widget_action_constructed (GObject *object); static void nemo_widget_action_finalize (GObject *gobject); static void nemo_widget_action_dispose (GObject *gobject); static GtkWidget *create_menu_item (GtkAction *action); static GtkWidget *create_tool_item (GtkAction *action); static gpointer parent_class; enum { PROP_0, PROP_WIDGET_A, PROP_WIDGET_B }; static void nemo_widget_action_init (NemoWidgetAction *action) { action->widget_a = NULL; action->widget_b = NULL; action->a_used = FALSE; action->b_used = FALSE; action->is_menu_toggle = FALSE; } static void nemo_widget_action_class_init (NemoWidgetActionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); GtkActionClass *action_class = GTK_ACTION_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = nemo_widget_action_finalize; object_class->dispose = nemo_widget_action_dispose; object_class->set_property = nemo_widget_action_set_property; object_class->get_property = nemo_widget_action_get_property; object_class->constructed = nemo_widget_action_constructed; action_class->create_menu_item = create_menu_item; action_class->create_tool_item = create_tool_item; action_class->menu_item_type = NEMO_TYPE_WIDGET_MENU_ITEM; action_class->toolbar_item_type = G_TYPE_NONE; g_object_class_install_property (object_class, PROP_WIDGET_A, g_param_spec_object ("widget-a", "The widget A for this action", "The widget to use for this action", GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) ); g_object_class_install_property (object_class, PROP_WIDGET_B, g_param_spec_object ("widget-b", "The widget B for this action", "The widget to use for this action", GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) ); } void nemo_widget_action_constructed (GObject *object) { G_OBJECT_CLASS (parent_class)->constructed (object); } GtkAction * nemo_widget_action_new (const gchar *name, GtkWidget *widget_a, GtkWidget *widget_b) { return g_object_new (NEMO_TYPE_WIDGET_ACTION, "name", name, "widget-a", widget_a, "widget-b", widget_b, NULL); } GtkAction * nemo_widget_action_new_for_menu_toggle (const gchar *name, const gchar *label, const gchar *tooltip) { GtkAction *ret = g_object_new (NEMO_TYPE_WIDGET_ACTION, "name", name, "label", label, "tooltip", tooltip, NULL); NEMO_WIDGET_ACTION (ret)->is_menu_toggle = TRUE; return ret; } static void nemo_widget_action_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void nemo_widget_action_dispose (GObject *object) { NemoWidgetAction *action = NEMO_WIDGET_ACTION (object); if (action->widget_a) { g_object_unref (action->widget_a); nemo_widget_action_set_widget_a (action, NULL); } if (action->widget_b) { g_object_unref (action->widget_b); nemo_widget_action_set_widget_b (action, NULL); } G_OBJECT_CLASS (parent_class)->dispose (object); } static void nemo_widget_action_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NemoWidgetAction *action; action = NEMO_WIDGET_ACTION (object); switch (prop_id) { case PROP_WIDGET_A: nemo_widget_action_set_widget_a (action, g_value_get_object (value)); break; case PROP_WIDGET_B: action->widget_b = g_value_get_object (value); g_object_ref_sink (action->widget_b); g_object_notify (G_OBJECT (action), "widget-b"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_widget_action_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NemoWidgetAction *action; action = NEMO_WIDGET_ACTION (object); switch (prop_id) { case PROP_WIDGET_A: g_value_set_object (value, action->widget_a); break; case PROP_WIDGET_B: g_value_set_object (value, action->widget_b); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static GtkWidget * create_menu_item (GtkAction *action) { NemoWidgetAction *widget_action; GType menu_item_type; GtkWidget *w; GtkWidget *ret = NULL; gint slot = -1; widget_action = NEMO_WIDGET_ACTION (action); menu_item_type = GTK_ACTION_GET_CLASS (action)->menu_item_type; if (widget_action->is_menu_toggle) { ret = g_object_new (NEMO_TYPE_CONTEXT_MENU_MENU_ITEM, NULL); } else { if (!widget_action->a_used) { w = widget_action->widget_a; widget_action->a_used = TRUE; slot = ACTION_SLOT_A; } else if (!widget_action->b_used) { w = widget_action->widget_b; widget_action->b_used = TRUE; slot = ACTION_SLOT_B; } if (slot != -1) ret = g_object_new (menu_item_type, "child-widget", w, "action-slot", slot, NULL); } if (ret) gtk_activatable_set_related_action (GTK_ACTIVATABLE (ret), action); return ret; } static GtkWidget * create_tool_item (GtkAction *action) { g_warning ("NemoWidgetAction: Toolbar items unsupported at this time."); return NULL; } void nemo_widget_action_activate (NemoWidgetAction *action) { } GtkWidget * nemo_widget_action_get_widget_a (NemoWidgetAction *action) { if (action->widget_a) return action->widget_a; else return NULL; } void nemo_widget_action_set_widget_a (NemoWidgetAction *action, GtkWidget *widget) { action->widget_a = widget; if (widget) g_object_ref_sink (action->widget_a); g_object_notify (G_OBJECT (action), "widget-a"); } GtkWidget * nemo_widget_action_get_widget_b (NemoWidgetAction *action) { if (action->widget_b) return action->widget_b; else return NULL; } void nemo_widget_action_set_widget_b (NemoWidgetAction *action, GtkWidget *widget) { action->widget_b = widget; if (widget) g_object_ref_sink (action->widget_b); g_object_notify (G_OBJECT (action), "widget-b"); } nemo-3.6.5/libnemo-private/nemo-progress-info.c0000664000175000017500000003104513215733314020406 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-progress-info.h: file operation progress info. Copyright (C) 2007 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #include #include #include #include #include #include "nemo-progress-info.h" #include "nemo-progress-info-manager.h" #include "nemo-icon-info.h" enum { CHANGED, QUEUED, PROGRESS_CHANGED, STARTED, FINISHED, LAST_SIGNAL }; #define SIGNAL_DELAY_MSEC 100 static guint signals[LAST_SIGNAL] = { 0 }; struct _NemoProgressInfo { GObject parent_instance; GCancellable *cancellable; char *status; char *details; char *initial_details; double progress; gboolean activity_mode; gboolean started; gboolean finished; gboolean paused; gboolean queued; GSource *idle_source; gboolean source_is_now; gboolean start_at_idle; gboolean finish_at_idle; gboolean changed_at_idle; gboolean progress_at_idle; gboolean queue_at_idle; }; struct _NemoProgressInfoClass { GObjectClass parent_class; }; G_LOCK_DEFINE_STATIC(progress_info); G_DEFINE_TYPE (NemoProgressInfo, nemo_progress_info, G_TYPE_OBJECT) static void nemo_progress_info_finalize (GObject *object) { NemoProgressInfo *info; info = NEMO_PROGRESS_INFO (object); g_free (info->status); g_free (info->details); g_free (info->initial_details); g_object_unref (info->cancellable); if (G_OBJECT_CLASS (nemo_progress_info_parent_class)->finalize) { (*G_OBJECT_CLASS (nemo_progress_info_parent_class)->finalize) (object); } } static void nemo_progress_info_dispose (GObject *object) { NemoProgressInfo *info; info = NEMO_PROGRESS_INFO (object); G_LOCK (progress_info); /* Destroy source in dispose, because the callback could come here before the destroy, which should ressurect the object for a while */ if (info->idle_source) { g_source_destroy (info->idle_source); g_source_unref (info->idle_source); info->idle_source = NULL; } G_UNLOCK (progress_info); } static void nemo_progress_info_class_init (NemoProgressInfoClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = nemo_progress_info_finalize; gobject_class->dispose = nemo_progress_info_dispose; signals[CHANGED] = g_signal_new ("changed", NEMO_TYPE_PROGRESS_INFO, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[QUEUED] = g_signal_new ("queued", NEMO_TYPE_PROGRESS_INFO, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[PROGRESS_CHANGED] = g_signal_new ("progress-changed", NEMO_TYPE_PROGRESS_INFO, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[STARTED] = g_signal_new ("started", NEMO_TYPE_PROGRESS_INFO, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[FINISHED] = g_signal_new ("finished", NEMO_TYPE_PROGRESS_INFO, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void nemo_progress_info_init (NemoProgressInfo *info) { NemoProgressInfoManager *manager; info->cancellable = g_cancellable_new (); manager = nemo_progress_info_manager_new (); nemo_progress_info_manager_add_new_info (manager, info); g_object_unref (manager); } NemoProgressInfo * nemo_progress_info_new (void) { NemoProgressInfo *info; info = g_object_new (NEMO_TYPE_PROGRESS_INFO, NULL); return info; } char * nemo_progress_info_get_status (NemoProgressInfo *info) { char *res; G_LOCK (progress_info); if (info->status) { res = g_strdup (info->status); } else { res = g_strdup (_("Preparing")); } G_UNLOCK (progress_info); return res; } char * nemo_progress_info_get_details (NemoProgressInfo *info) { char *res; G_LOCK (progress_info); if (info->details) { res = g_strdup (info->details); } else { res = g_strdup (_("Preparing")); } G_UNLOCK (progress_info); return res; } char * nemo_progress_info_get_initial_details (NemoProgressInfo *info) { char *res; G_LOCK (progress_info); if (info->initial_details) { res = g_strdup (info->initial_details); } else { res = g_strdup (_("Preparing")); } G_UNLOCK (progress_info); return res; } double nemo_progress_info_get_progress (NemoProgressInfo *info) { double res; G_LOCK (progress_info); if (info->activity_mode) { res = -1.0; } else { res = info->progress; } G_UNLOCK (progress_info); return res; } void nemo_progress_info_cancel (NemoProgressInfo *info) { G_LOCK (progress_info); g_cancellable_cancel (info->cancellable); G_UNLOCK (progress_info); } GCancellable * nemo_progress_info_get_cancellable (NemoProgressInfo *info) { GCancellable *c; G_LOCK (progress_info); c = g_object_ref (info->cancellable); G_UNLOCK (progress_info); return c; } gboolean nemo_progress_info_get_is_started (NemoProgressInfo *info) { gboolean res; G_LOCK (progress_info); res = info->started; G_UNLOCK (progress_info); return res; } gboolean nemo_progress_info_get_is_finished (NemoProgressInfo *info) { gboolean res; G_LOCK (progress_info); res = info->finished; G_UNLOCK (progress_info); return res; } gboolean nemo_progress_info_get_is_paused (NemoProgressInfo *info) { gboolean res; G_LOCK (progress_info); res = info->paused; G_UNLOCK (progress_info); return res; } static gboolean idle_callback (gpointer data) { NemoProgressInfo *info = data; gboolean start_at_idle; gboolean finish_at_idle; gboolean changed_at_idle; gboolean progress_at_idle; gboolean queue_at_idle; GSource *source; source = g_main_current_source (); G_LOCK (progress_info); /* Protect agains races where the source has been destroyed on another thread while it was being dispatched. Similar to what gdk_threads_add_idle does. */ if (g_source_is_destroyed (source)) { G_UNLOCK (progress_info); return FALSE; } /* We hadn't destroyed the source, so take a ref. * This might ressurect the object from dispose, but * that should be ok. */ g_object_ref (info); g_assert (source == info->idle_source); g_source_unref (source); info->idle_source = NULL; start_at_idle = info->start_at_idle; finish_at_idle = info->finish_at_idle; changed_at_idle = info->changed_at_idle; progress_at_idle = info->progress_at_idle; queue_at_idle = info->queue_at_idle; info->start_at_idle = FALSE; info->finish_at_idle = FALSE; info->changed_at_idle = FALSE; info->progress_at_idle = FALSE; info->queue_at_idle = FALSE; G_UNLOCK (progress_info); if (start_at_idle) { g_signal_emit (info, signals[STARTED], 0); } if (changed_at_idle) { g_signal_emit (info, signals[CHANGED], 0); } if (progress_at_idle) { g_signal_emit (info, signals[PROGRESS_CHANGED], 0); } if (finish_at_idle) { g_signal_emit (info, signals[FINISHED], 0); } if (queue_at_idle) { g_signal_emit (info, signals[QUEUED], 0); } g_object_unref (info); return FALSE; } /* Called with lock held */ static void queue_idle (NemoProgressInfo *info, gboolean now) { if (info->idle_source == NULL || (now && !info->source_is_now)) { if (info->idle_source) { g_source_destroy (info->idle_source); g_source_unref (info->idle_source); info->idle_source = NULL; } info->source_is_now = now; if (now) { info->idle_source = g_idle_source_new (); } else { info->idle_source = g_timeout_source_new (SIGNAL_DELAY_MSEC); } g_source_set_callback (info->idle_source, idle_callback, info, NULL); g_source_attach (info->idle_source, NULL); } } void nemo_progress_info_queue (NemoProgressInfo *info) { G_LOCK (progress_info); if (!info->queued) { info->queued = TRUE; info->queue_at_idle = TRUE; queue_idle (info, TRUE); } G_UNLOCK (progress_info); } void nemo_progress_info_pause (NemoProgressInfo *info) { G_LOCK (progress_info); if (!info->paused) { info->paused = TRUE; } G_UNLOCK (progress_info); } void nemo_progress_info_resume (NemoProgressInfo *info) { G_LOCK (progress_info); if (info->paused) { info->paused = FALSE; } G_UNLOCK (progress_info); } void nemo_progress_info_start (NemoProgressInfo *info) { G_LOCK (progress_info); if (!info->started) { info->started = TRUE; info->start_at_idle = TRUE; queue_idle (info, TRUE); } G_UNLOCK (progress_info); } void nemo_progress_info_finish (NemoProgressInfo *info) { G_LOCK (progress_info); if (!info->finished) { info->finished = TRUE; info->finish_at_idle = TRUE; queue_idle (info, TRUE); } G_UNLOCK (progress_info); } void nemo_progress_info_take_status (NemoProgressInfo *info, char *status) { G_LOCK (progress_info); if (g_strcmp0 (info->status, status) != 0) { g_free (info->status); info->status = status; info->changed_at_idle = TRUE; queue_idle (info, FALSE); } else { g_free (status); } G_UNLOCK (progress_info); } void nemo_progress_info_set_status (NemoProgressInfo *info, const char *status) { G_LOCK (progress_info); if (g_strcmp0 (info->status, status) != 0) { g_free (info->status); info->status = g_strdup (status); info->changed_at_idle = TRUE; queue_idle (info, FALSE); } G_UNLOCK (progress_info); } void nemo_progress_info_take_details (NemoProgressInfo *info, char *details) { G_LOCK (progress_info); if (g_strcmp0 (info->details, details) != 0) { g_free (info->details); info->details = details; info->changed_at_idle = TRUE; queue_idle (info, FALSE); } else { g_free (details); } G_UNLOCK (progress_info); } void nemo_progress_info_set_details (NemoProgressInfo *info, const char *details) { G_LOCK (progress_info); if (g_strcmp0 (info->details, details) != 0) { g_free (info->details); info->details = g_strdup (details); info->changed_at_idle = TRUE; queue_idle (info, FALSE); } G_UNLOCK (progress_info); } void nemo_progress_info_take_initial_details (NemoProgressInfo *info, char *initial_details) { G_LOCK (progress_info); if (g_strcmp0 (info->initial_details, initial_details) != 0) { g_free (info->initial_details); info->initial_details = initial_details; info->changed_at_idle = TRUE; queue_idle (info, FALSE); } else { g_free (initial_details); } G_UNLOCK (progress_info); } void nemo_progress_info_pulse_progress (NemoProgressInfo *info) { G_LOCK (progress_info); info->activity_mode = TRUE; info->progress = 0.0; info->progress_at_idle = TRUE; queue_idle (info, FALSE); G_UNLOCK (progress_info); } void nemo_progress_info_set_progress (NemoProgressInfo *info, double current, double total) { double current_percent; if (total <= 0) { current_percent = 1.0; } else { current_percent = current / total; if (current_percent < 0) { current_percent = 0; } if (current_percent > 1.0) { current_percent = 1.0; } } G_LOCK (progress_info); if (info->activity_mode || /* emit on switch from activity mode */ fabs (current_percent - info->progress) > 0.005 /* Emit on change of 0.5 percent */ ) { info->activity_mode = FALSE; info->progress = current_percent; info->progress_at_idle = TRUE; queue_idle (info, FALSE); } G_UNLOCK (progress_info); } nemo-3.6.5/libnemo-private/nemo-action-manager.c0000664000175000017500000002577513215733314020513 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-action-manager.h" #include "nemo-directory.h" #include "nemo-action.h" #include #include "nemo-file-utilities.h" G_DEFINE_TYPE (NemoActionManager, nemo_action_manager, G_TYPE_OBJECT); static void set_up_actions (NemoActionManager *action_manager); static void nemo_action_manager_init (NemoActionManager *action_manager); static void nemo_action_manager_class_init (NemoActionManagerClass *klass); static void nemo_action_manager_constructed (GObject *object); static void nemo_action_manager_dispose (GObject *gobject); static void nemo_action_manager_finalize (GObject *gobject); static gpointer parent_class; enum { PROP_0, PROP_CONDITIONS }; enum { CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static void actions_added_or_changed (NemoDirectory *directory, GList *files, gpointer callback_data) { NemoActionManager *action_manager; action_manager = NEMO_ACTION_MANAGER (callback_data); action_manager->action_list_dirty = TRUE; set_up_actions (action_manager); } static void plugin_prefs_changed (GSettings *settings, gchar *key, gpointer user_data) { actions_added_or_changed (NULL, NULL, user_data); } static void add_directory_to_directory_list (NemoActionManager *action_manager, NemoDirectory *directory, GList **directory_list, GCallback changed_callback) { NemoFileAttributes attributes; if (g_list_find (*directory_list, directory) == NULL) { nemo_directory_ref (directory); attributes = NEMO_FILE_ATTRIBUTES_FOR_ICON | NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT; nemo_directory_file_monitor_add (directory, directory_list, FALSE, attributes, (NemoDirectoryCallback)changed_callback, action_manager); g_signal_connect_object (directory, "files_added", G_CALLBACK (changed_callback), action_manager, 0); g_signal_connect_object (directory, "files_changed", G_CALLBACK (changed_callback), action_manager, 0); *directory_list = g_list_append (*directory_list, directory); } } static void remove_directory_from_directory_list (NemoActionManager *action_manager, NemoDirectory *directory, GList **directory_list, GCallback changed_callback) { *directory_list = g_list_remove (*directory_list, directory); g_signal_handlers_disconnect_by_func (directory, G_CALLBACK (changed_callback), action_manager); nemo_directory_file_monitor_remove (directory, directory_list); nemo_directory_unref (directory); } static void add_directory_to_actions_directory_list (NemoActionManager *action_manager, NemoDirectory *directory) { add_directory_to_directory_list (action_manager, directory, &action_manager->actions_directory_list, G_CALLBACK (actions_added_or_changed)); } static void remove_directory_from_actions_directory_list (NemoActionManager *action_manager, NemoDirectory *directory) { remove_directory_from_directory_list (action_manager, directory, &action_manager->actions_directory_list, G_CALLBACK (actions_added_or_changed)); } static void set_up_actions_directories (NemoActionManager *action_manager) { gchar *sys_path = nemo_action_manager_get_sys_directory_path (); gchar *sys_uri = g_filename_to_uri (sys_path, NULL, NULL); gchar *user_path = g_build_filename (g_get_user_data_dir (), "nemo", "actions", NULL); if (!g_file_test (user_path, G_FILE_TEST_EXISTS)) { g_mkdir_with_parents (user_path, DEFAULT_NEMO_DIRECTORY_MODE); } gchar *user_uri = g_filename_to_uri (user_path, NULL, NULL); if (action_manager->actions_directory_list != NULL) { nemo_directory_list_free (action_manager->actions_directory_list); } NemoDirectory *dir; dir = nemo_directory_get_by_uri (user_uri); add_directory_to_actions_directory_list (action_manager, dir); nemo_directory_unref (dir); dir = nemo_directory_get_by_uri (sys_uri); add_directory_to_actions_directory_list (action_manager, dir); nemo_directory_unref (dir); g_free (sys_path); g_free (sys_uri); g_free (user_path); g_free (user_uri); } static char * escape_action_name (const char *action_name, const char *prefix) { GString *s; if (action_name == NULL) { return NULL; } s = g_string_new (prefix); while (*action_name != 0) { switch (*action_name) { case '\\': g_string_append (s, "\\\\"); break; case '/': g_string_append (s, "\\s"); break; case '&': g_string_append (s, "\\a"); break; case '"': g_string_append (s, "\\q"); break; default: g_string_append_c (s, *action_name); } action_name ++; } return g_string_free (s, FALSE); } static void add_action_to_action_list (NemoActionManager *action_manager, NemoFile *file) { gchar *uri; gchar *action_name; NemoAction *action; uri = nemo_file_get_uri (file); action_name = escape_action_name (uri, "action_"); gchar *path = g_filename_from_uri (uri, NULL, NULL); action = nemo_action_new (action_name, path); g_free (path); if (action == NULL) { g_free (uri); g_free (action_name); return; } action_manager->actions = g_list_append (action_manager->actions, action); } static void void_action_list (NemoActionManager *action_manager) { GList *tmp = action_manager->actions; action_manager->actions = NULL; g_list_free_full (tmp, g_object_unref); } static void set_up_actions (NemoActionManager *action_manager) { GList *dir, *file_list, *node; NemoFile *file; NemoDirectory *directory; if (g_list_length (action_manager->actions) > 0) void_action_list (action_manager); for (dir = action_manager->actions_directory_list; dir != NULL; dir = dir->next) { directory = dir->data; file_list = nemo_directory_get_file_list (directory); for (node = file_list; node != NULL; node = node->next) { file = node->data; if (!g_str_has_suffix (nemo_file_peek_name (file), ".nemo_action") || !nemo_global_preferences_should_load_plugin (nemo_file_peek_name (file), NEMO_PLUGIN_PREFERENCES_DISABLED_ACTIONS)) continue; add_action_to_action_list (action_manager, file); } nemo_file_list_free (file_list); } action_manager->action_list_dirty = FALSE; g_signal_emit (action_manager, signals[CHANGED], 0); } static void nemo_action_manager_init (NemoActionManager *action_manager) { action_manager->actions = NULL; action_manager->actions_directory_list = NULL; action_manager->action_list_dirty = TRUE; } static void nemo_action_manager_class_init (NemoActionManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = nemo_action_manager_finalize; object_class->dispose = nemo_action_manager_dispose; object_class->constructed = nemo_action_manager_constructed; signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoActionManagerClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } void nemo_action_manager_constructed (GObject *object) { G_OBJECT_CLASS (parent_class)->constructed (object); NemoActionManager *action_manager = NEMO_ACTION_MANAGER (object); set_up_actions_directories (action_manager); set_up_actions (action_manager); g_signal_connect (nemo_plugin_preferences, "changed::" NEMO_PLUGIN_PREFERENCES_DISABLED_ACTIONS, G_CALLBACK (plugin_prefs_changed), action_manager); } NemoActionManager * nemo_action_manager_new (void) { return g_object_new (NEMO_TYPE_ACTION_MANAGER, NULL); } static void nemo_action_manager_dispose (GObject *object) { NemoActionManager *action_manager = NEMO_ACTION_MANAGER (object); if (action_manager->actions_directory_list != NULL) { GList *node, *copy; copy = nemo_directory_list_copy (action_manager->actions_directory_list); for (node = copy; node != NULL; node = node->next) { remove_directory_from_actions_directory_list (action_manager, node->data); } g_list_free (action_manager->actions_directory_list); action_manager->actions_directory_list = NULL; nemo_directory_list_free (copy); } g_signal_handlers_disconnect_by_func (nemo_plugin_preferences, G_CALLBACK (plugin_prefs_changed), action_manager); G_OBJECT_CLASS (parent_class)->dispose (object); } static void nemo_action_manager_finalize (GObject *object) { NemoActionManager *action_manager = NEMO_ACTION_MANAGER (object); g_list_free_full (action_manager->actions, g_object_unref); G_OBJECT_CLASS (parent_class)->finalize (object); } GList * nemo_action_manager_list_actions (NemoActionManager *action_manager) { return action_manager->action_list_dirty ? NULL : action_manager->actions; } gchar * nemo_action_manager_get_user_directory_path (void) { return g_build_filename (g_get_user_data_dir (), "nemo", "actions", NULL); } gchar * nemo_action_manager_get_sys_directory_path (void) { return g_build_filename (NEMO_DATADIR, "actions", NULL); } nemo-3.6.5/libnemo-private/nemo-places-tree-view.c0000664000175000017500000001065713215733314020773 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-places-tree-view.h" G_DEFINE_TYPE (NemoPlacesTreeView, nemo_places_tree_view, GTK_TYPE_TREE_VIEW); static void nemo_places_tree_view_init (NemoPlacesTreeView *tree_view); static void nemo_places_tree_view_class_init (NemoPlacesTreeViewClass *klass); static void nemo_places_tree_view_finalize (GObject *gobject); static gpointer parent_class; static void nemo_places_tree_view_init (NemoPlacesTreeView *tree_view) { gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (tree_view)), "places-treeview"); } static void nemo_places_tree_view_class_init (NemoPlacesTreeViewClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = nemo_places_tree_view_finalize; gtk_widget_class_install_style_property (widget_class, g_param_spec_boxed ("disk-full-bg-color", "Unselected disk indicator background color", "Unselected disk indicator background color", GDK_TYPE_COLOR, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_boxed ("disk-full-fg-color", "Unselected disk indicator foreground color", "Unselected disk indicator foreground color", GDK_TYPE_COLOR, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("disk-full-bar-width", "Disk indicator bar width", "Disk indicator bar width", 0, G_MAXINT, 2, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("disk-full-bar-radius", "Disk indicator bar radius (usually half the width)", "Disk indicator bar radius (usually half the width)", 0, G_MAXINT, 1, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("disk-full-bottom-padding", "Extra padding under the disk indicator", "Extra padding under the disk indicator", 0, G_MAXINT, 1, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("disk-full-max-length", "Maximum length of the disk indicator", "Maximum length of the disk indicator", 0, G_MAXINT, 70, G_PARAM_READABLE)); } GtkWidget * nemo_places_tree_view_new (void) { return g_object_new (NEMO_TYPE_PLACES_TREE_VIEW, NULL); } static void nemo_places_tree_view_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } nemo-3.6.5/libnemo-private/nemo-signaller.h0000664000175000017500000000317713215733314017603 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Nemo * * Copyright (C) 1999, 2000 Eazel, Inc. * * Nemo is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA * * Author: John Sullivan */ /* nemo-signaller.h: Class to manage nemo-wide signals that don't * correspond to any particular object. */ #ifndef NEMO_SIGNALLER_H #define NEMO_SIGNALLER_H #include /* NemoSignaller is a class that manages signals between disconnected Nemo code. Nemo objects connect to these signals so that other objects can cause them to be emitted later, without the connecting and emit-causing objects needing to know about each other. It seems a shame to have to invent a subclass and a special object just for this purpose. Perhaps there's a better way to do this kind of thing. */ /* Get the one and only NemoSignaller to connect with or emit signals for */ GObject *nemo_signaller_get_current (void); #endif /* NEMO_SIGNALLER_H */ nemo-3.6.5/libnemo-private/nemo-metadata.h0000664000175000017500000000754213215733314017403 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-metadata.h: #defines and other metadata-related info Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: John Sullivan */ #ifndef NEMO_METADATA_H #define NEMO_METADATA_H /* Keys for getting/setting Nemo metadata. All metadata used in Nemo * should define its key here, so we can keep track of the whole set easily. * Any updates here needs to be added in nemo-metadata.c too. */ #include /* Per-file */ #define NEMO_METADATA_KEY_DEFAULT_VIEW "nemo-default-view" #define NEMO_METADATA_KEY_LOCATION_BACKGROUND_COLOR "folder-background-color" #define NEMO_METADATA_KEY_LOCATION_BACKGROUND_IMAGE "folder-background-image" #define NEMO_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL "nemo-icon-view-zoom-level" #define NEMO_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT "nemo-icon-view-auto-layout" #define NEMO_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT "nemo-icon-view-tighter-layout" #define NEMO_METADATA_KEY_ICON_VIEW_SORT_BY "nemo-icon-view-sort-by" #define NEMO_METADATA_KEY_ICON_VIEW_SORT_REVERSED "nemo-icon-view-sort-reversed" #define NEMO_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED "nemo-icon-view-keep-aligned" #define NEMO_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP "nemo-icon-view-layout-timestamp" #define NEMO_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL "nemo-list-view-zoom-level" #define NEMO_METADATA_KEY_LIST_VIEW_SORT_COLUMN "nemo-list-view-sort-column" #define NEMO_METADATA_KEY_LIST_VIEW_SORT_REVERSED "nemo-list-view-sort-reversed" #define NEMO_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS "nemo-list-view-visible-columns" #define NEMO_METADATA_KEY_LIST_VIEW_COLUMN_ORDER "nemo-list-view-column-order" #define NEMO_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL "nemo-compact-view-zoom-level" #define NEMO_METADATA_KEY_WINDOW_GEOMETRY "nemo-window-geometry" #define NEMO_METADATA_KEY_WINDOW_SCROLL_POSITION "nemo-window-scroll-position" #define NEMO_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES "nemo-window-show-hidden-files" #define NEMO_METADATA_KEY_WINDOW_MAXIMIZED "nemo-window-maximized" #define NEMO_METADATA_KEY_WINDOW_STICKY "nemo-window-sticky" #define NEMO_METADATA_KEY_WINDOW_KEEP_ABOVE "nemo-window-keep-above" #define NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR "nemo-sidebar-background-color" #define NEMO_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE "nemo-sidebar-background-image" #define NEMO_METADATA_KEY_SIDEBAR_BUTTONS "nemo-sidebar-buttons" #define NEMO_METADATA_KEY_ICON_POSITION "nemo-icon-position" #define NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP "nemo-icon-position-timestamp" #define NEMO_METADATA_KEY_ANNOTATION "annotation" #define NEMO_METADATA_KEY_ICON_SCALE "icon-scale" #define NEMO_METADATA_KEY_CUSTOM_ICON "custom-icon" #define NEMO_METADATA_KEY_CUSTOM_ICON_NAME "custom-icon-name" #define NEMO_METADATA_KEY_EMBLEMS "emblems" #define NEMO_METADATA_KEY_MONITOR "monitor" #define NEMO_METADATA_KEY_DESKTOP_GRID_HORIZONTAL "desktop-horizontal" guint nemo_metadata_get_id (const char *metadata); #endif /* NEMO_METADATA_H */ nemo-3.6.5/libnemo-private/nemo-action.h0000664000175000017500000001266013215733314017075 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #ifndef NEMO_ACTION_H #define NEMO_ACTION_H #include #include #include "nemo-file.h" #define NEMO_TYPE_ACTION nemo_action_get_type() #define NEMO_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ACTION, NemoAction)) #define NEMO_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ACTION, NemoActionClass)) #define NEMO_IS_ACTION(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ACTION)) #define NEMO_IS_ACTION_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ACTION)) #define NEMO_ACTION_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ACTION, NemoActionClass)) #define SELECTION_SINGLE_KEY "s" #define SELECTION_MULTIPLE_KEY "m" #define SELECTION_ANY_KEY "any" #define SELECTION_NONE_KEY "none" #define SELECTION_NOT_NONE_KEY "notnone" #define TOKEN_EXEC_URI_LIST "%U" #define TOKEN_EXEC_FILE_LIST "%F" #define TOKEN_EXEC_PARENT "%P" #define TOKEN_EXEC_FILE_NAME "%f" #define TOKEN_EXEC_PARENT_NAME "%p" #define TOKEN_EXEC_DEVICE "%D" #define TOKEN_LABEL_FILE_NAME "%N" // Leave in for compatibility, same as TOKEN_EXEC_FILE_NAME #define ACTION_FILE_GROUP "Nemo Action" #define KEY_ACTIVE "Active" #define KEY_NAME "Name" #define KEY_COMMENT "Comment" #define KEY_EXEC "Exec" #define KEY_ICON_NAME "Icon-Name" #define KEY_STOCK_ID "Stock-Id" #define KEY_SELECTION "Selection" #define KEY_EXTENSIONS "Extensions" #define KEY_MIME_TYPES "Mimetypes" #define KEY_SEPARATOR "Separator" #define KEY_QUOTE_TYPE "Quote" #define KEY_DEPENDENCIES "Dependencies" #define KEY_CONDITIONS "Conditions" #define KEY_WHITESPACE "EscapeSpaces" #define KEY_DOUBLE_ESCAPE_QUOTES "DoubleEscapeQuotes" #define KEY_TERMINAL "Terminal" typedef struct _NemoAction NemoAction; typedef struct _NemoActionClass NemoActionClass; typedef enum { SELECTION_SINGLE = G_MAXINT - 10, SELECTION_MULTIPLE, SELECTION_NOT_NONE, SELECTION_ANY, SELECTION_NONE } SelectionType; typedef enum { QUOTE_TYPE_SINGLE = 0, QUOTE_TYPE_DOUBLE, QUOTE_TYPE_BACKTICK, QUOTE_TYPE_NONE } QuoteType; typedef enum { TOKEN_NONE = 0, TOKEN_PATH_LIST, TOKEN_URI_LIST, TOKEN_FILE_DISPLAY_NAME, TOKEN_PARENT_DISPLAY_NAME, TOKEN_PARENT_PATH, TOKEN_DEVICE } TokenType; struct _NemoAction { GtkAction parent; gchar *key_file_path; SelectionType selection_type; gchar **extensions; gchar **mimetypes; gchar *exec; gchar *parent_dir; gchar **conditions; gchar *separator; QuoteType quote_type; gchar *orig_label; gchar *orig_tt; gboolean use_parent_dir; gboolean log_output; GList *dbus; gboolean dbus_satisfied; gboolean escape_underscores; gboolean escape_space; gboolean show_in_blank_desktop; gboolean run_in_terminal; }; struct _NemoActionClass { GtkActionClass parent_class; }; GType nemo_action_get_type (void); NemoAction *nemo_action_new (const gchar *name, const gchar *path); void nemo_action_activate (NemoAction *action, GList *selection, NemoFile *parent); SelectionType nemo_action_get_selection_type (NemoAction *action); gchar **nemo_action_get_extension_list (NemoAction *action); gchar **nemo_action_get_mimetypes_list (NemoAction *action); void nemo_action_set_key_file_path (NemoAction *action, const gchar *path); void nemo_action_set_exec (NemoAction *action, const gchar *exec); void nemo_action_set_parent_dir (NemoAction *action, const gchar *parent_dir); void nemo_action_set_separator (NemoAction *action, const gchar *separator); void nemo_action_set_conditions (NemoAction *action, gchar **conditions); void nemo_action_set_orig_label (NemoAction *action, const gchar *orig_label); void nemo_action_set_orig_tt (NemoAction *action, const gchar *orig_tt); const gchar *nemo_action_get_orig_label (NemoAction *action); const gchar *nemo_action_get_orig_tt (NemoAction *action); gchar **nemo_action_get_conditions (NemoAction *action); gchar *nemo_action_get_label (NemoAction *action, GList *selection, NemoFile *parent); gchar *nemo_action_get_tt (NemoAction *action, GList *selection, NemoFile *parent); void nemo_action_set_extensions (NemoAction *action, gchar **extensions); void nemo_action_set_mimetypes (NemoAction *action, gchar **mimetypes); gboolean nemo_action_get_dbus_satisfied (NemoAction *action); gboolean nemo_action_get_visibility (NemoAction *action, GList *selection, NemoFile *parent); #endif /* NEMO_ACTION_H */ nemo-3.6.5/libnemo-private/nemo-file-dnd.h0000664000175000017500000000311113215733314017271 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-drag.h - Drag & drop handling code that operated on NemoFile objects. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Pavel Cisler , */ #ifndef NEMO_FILE_DND_H #define NEMO_FILE_DND_H #include #include #define NEMO_FILE_DND_ERASE_KEYWORD "erase" gboolean nemo_drag_can_accept_item (NemoFile *drop_target_item, const char *item_uri); gboolean nemo_drag_can_accept_items (NemoFile *drop_target_item, const GList *items); gboolean nemo_drag_can_accept_info (NemoFile *drop_target_item, NemoIconDndTargetType drag_type, const GList *items); #endif /* NEMO_FILE_DND_H */ nemo-3.6.5/libnemo-private/nemo-dbus-manager.h0000664000175000017500000000224113215733314020157 0ustar fabiofabio/* * nemo-dbus-manager: nemo DBus interface * * Copyright (C) 2010, Red Hat, Inc. * * Nemo is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Nemo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Suite 500, MA 02110-1335, USA. * * Author: Cosimo Cecchi * */ #ifndef __NEMO_DBUS_MANAGER_H__ #define __NEMO_DBUS_MANAGER_H__ #include #include typedef struct _NemoDBusManager NemoDBusManager; typedef struct _NemoDBusManagerClass NemoDBusManagerClass; GType nemo_dbus_manager_get_type (void); NemoDBusManager * nemo_dbus_manager_new (void); #endif /* __NEMO_DBUS_MANAGER_H__ */ nemo-3.6.5/libnemo-private/nemo-global-preferences.h0000664000175000017500000003000413215733314021347 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- */ /* nemo-global-preferences.h - Nemo specific preference keys and functions. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ramiro Estrugo */ #ifndef NEMO_GLOBAL_PREFERENCES_H #define NEMO_GLOBAL_PREFERENCES_H #include G_BEGIN_DECLS /* Trash options */ #define NEMO_PREFERENCES_CONFIRM_TRASH "confirm-trash" #define NEMO_PREFERENCES_ENABLE_DELETE "enable-delete" #define NEMO_PREFERENCES_SWAP_TRASH_DELETE "swap-trash-delete" /* Desktop options */ #define NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR "desktop-is-home-dir" /* Display */ #define NEMO_PREFERENCES_SHOW_HIDDEN_FILES "show-hidden-files" #define NEMO_PREFERENCES_SHOW_ADVANCED_PERMISSIONS "show-advanced-permissions" #define NEMO_PREFERENCES_DATE_FORMAT "date-format" /* Mouse */ #define NEMO_PREFERENCES_MOUSE_USE_EXTRA_BUTTONS "mouse-use-extra-buttons" #define NEMO_PREFERENCES_MOUSE_FORWARD_BUTTON "mouse-forward-button" #define NEMO_PREFERENCES_MOUSE_BACK_BUTTON "mouse-back-button" typedef enum { NEMO_DATE_FORMAT_LOCALE, NEMO_DATE_FORMAT_ISO, NEMO_DATE_FORMAT_INFORMAL } NemoDateFormat; typedef enum { NEMO_NEW_TAB_POSITION_AFTER_CURRENT_TAB, NEMO_NEW_TAB_POSITION_END, } NemoNewTabPosition; /* Sidebar panels */ #define NEMO_PREFERENCES_TREE_SHOW_ONLY_DIRECTORIES "show-only-directories" /* Single/Double click preference */ #define NEMO_PREFERENCES_CLICK_POLICY "click-policy" /* Quick renames with two single clicks and pause in-between*/ #define NEMO_PREFERENCES_CLICK_TO_RENAME "quick-renames-with-pause-in-between" /* Activating executable text files */ #define NEMO_PREFERENCES_EXECUTABLE_TEXT_ACTIVATION "executable-text-activation" /* Spatial or browser mode */ #define NEMO_PREFERENCES_ALWAYS_USE_BROWSER "always-use-browser" #define NEMO_PREFERENCES_NEW_TAB_POSITION "tabs-open-position" #define NEMO_PREFERENCES_SHOW_LOCATION_ENTRY "show-location-entry" #define NEMO_PREFERENCES_SHOW_PREVIOUS_ICON_TOOLBAR "show-previous-icon-toolbar" #define NEMO_PREFERENCES_SHOW_NEXT_ICON_TOOLBAR "show-next-icon-toolbar" #define NEMO_PREFERENCES_SHOW_UP_ICON_TOOLBAR "show-up-icon-toolbar" #define NEMO_PREFERENCES_SHOW_EDIT_ICON_TOOLBAR "show-edit-icon-toolbar" #define NEMO_PREFERENCES_SHOW_RELOAD_ICON_TOOLBAR "show-reload-icon-toolbar" #define NEMO_PREFERENCES_SHOW_HOME_ICON_TOOLBAR "show-home-icon-toolbar" #define NEMO_PREFERENCES_SHOW_COMPUTER_ICON_TOOLBAR "show-computer-icon-toolbar" #define NEMO_PREFERENCES_SHOW_SEARCH_ICON_TOOLBAR "show-search-icon-toolbar" #define NEMO_PREFERENCES_SHOW_NEW_FOLDER_ICON_TOOLBAR "show-new-folder-icon-toolbar" #define NEMO_PREFERENCES_SHOW_OPEN_IN_TERMINAL_TOOLBAR "show-open-in-terminal-toolbar" #define NEMO_PREFERENCES_SHOW_ICON_VIEW_ICON_TOOLBAR "show-icon-view-icon-toolbar" #define NEMO_PREFERENCES_SHOW_LIST_VIEW_ICON_TOOLBAR "show-list-view-icon-toolbar" #define NEMO_PREFERENCES_SHOW_COMPACT_VIEW_ICON_TOOLBAR "show-compact-view-icon-toolbar" #define NEMO_PREFERENCES_SHOW_ROOT_WARNING "show-root-warning" /* Which views should be displayed for new windows */ #define NEMO_WINDOW_STATE_START_WITH_STATUS_BAR "start-with-status-bar" #define NEMO_WINDOW_STATE_START_WITH_SIDEBAR "start-with-sidebar" #define NEMO_WINDOW_STATE_START_WITH_TOOLBAR "start-with-toolbar" #define NEMO_WINDOW_STATE_START_WITH_MENU_BAR "start-with-menu-bar" #define NEMO_WINDOW_STATE_SIDE_PANE_VIEW "side-pane-view" #define NEMO_WINDOW_STATE_GEOMETRY "geometry" #define NEMO_WINDOW_STATE_MAXIMIZED "maximized" #define NEMO_WINDOW_STATE_SIDEBAR_WIDTH "sidebar-width" #define NEMO_WINDOW_STATE_MY_COMPUTER_EXPANDED "my-computer-expanded" #define NEMO_WINDOW_STATE_BOOKMARKS_EXPANDED "bookmarks-expanded" #define NEMO_WINDOW_STATE_DEVICES_EXPANDED "devices-expanded" #define NEMO_WINDOW_STATE_NETWORK_EXPANDED "network-expanded" /* Sorting order */ #define NEMO_PREFERENCES_SORT_DIRECTORIES_FIRST "sort-directories-first" #define NEMO_PREFERENCES_DEFAULT_SORT_ORDER "default-sort-order" #define NEMO_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER "default-sort-in-reverse-order" /* The default folder viewer - one of the two enums below */ #define NEMO_PREFERENCES_DEFAULT_FOLDER_VIEWER "default-folder-viewer" #define NEMO_PREFERENCES_SHOW_FULL_PATH_TITLES "show-full-path-titles" #define NEMO_PREFERENCES_CLOSE_DEVICE_VIEW_ON_EJECT "close-device-view-on-device-eject" #define NEMO_PREFERENCES_START_WITH_DUAL_PANE "start-with-dual-pane" #define NEMO_PREFERENCES_IGNORE_VIEW_METADATA "ignore-view-metadata" #define NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS "show-bookmarks-in-to-menus" #define NEMO_PREFERENCES_SHOW_PLACES_IN_TO_MENUS "show-places-in-to-menus" #define NEMO_PREFERENCES_RECENT_ENABLED "remember-recent-files" #define NEMO_PREFERENCES_SIDEBAR_BOOKMARK_BREAKPOINT "sidebar-bookmark-breakpoint" #define NEMO_PREFERENCES_CONTEXT_MENUS_SHOW_ALL_ACTIONS "context-menus-show-all-actions" enum { NEMO_DEFAULT_FOLDER_VIEWER_ICON_VIEW, NEMO_DEFAULT_FOLDER_VIEWER_COMPACT_VIEW, NEMO_DEFAULT_FOLDER_VIEWER_LIST_VIEW, NEMO_DEFAULT_FOLDER_VIEWER_OTHER }; /* These IIDs are used by the preferences code and in nemo-application.c */ #define NEMO_ICON_VIEW_IID "OAFIID:Nemo_File_Manager_Icon_View" #define NEMO_COMPACT_VIEW_IID "OAFIID:Nemo_File_Manager_Compact_View" #define NEMO_LIST_VIEW_IID "OAFIID:Nemo_File_Manager_List_View" #define NEMO_DESKTOP_ICON_VIEW_IID "OAFIID:Nemo_File_Manager_Desktop_Icon_View" #define NEMO_DESKTOP_ICON_GRID_VIEW_IID "OAFIID:Nemo_File_Manager_Desktop_Icon_Grid_View" /* Icon View */ #define NEMO_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL "default-zoom-level" #define NEMO_PREFERENCES_ICON_VIEW_DEFAULT_USE_TIGHTER_LAYOUT "default-use-tighter-layout" #define NEMO_PREFERENCES_ICON_VIEW_LABELS_BESIDE_ICONS "labels-beside-icons" /* Which text attributes appear beneath icon names */ #define NEMO_PREFERENCES_ICON_VIEW_CAPTIONS "captions" /* The default size for thumbnail icons */ #define NEMO_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE "thumbnail-size" /* ellipsization preferences */ #define NEMO_PREFERENCES_ICON_VIEW_TEXT_ELLIPSIS_LIMIT "text-ellipsis-limit" #define NEMO_PREFERENCES_DESKTOP_TEXT_ELLIPSIS_LIMIT "text-ellipsis-limit" /* Compact View */ #define NEMO_PREFERENCES_COMPACT_VIEW_DEFAULT_ZOOM_LEVEL "default-zoom-level" #define NEMO_PREFERENCES_COMPACT_VIEW_ALL_COLUMNS_SAME_WIDTH "all-columns-have-same-width" /* List View */ #define NEMO_PREFERENCES_LIST_VIEW_DEFAULT_ZOOM_LEVEL "default-zoom-level" #define NEMO_PREFERENCES_LIST_VIEW_DEFAULT_VISIBLE_COLUMNS "default-visible-columns" #define NEMO_PREFERENCES_LIST_VIEW_DEFAULT_COLUMN_ORDER "default-column-order" #define NEMO_PREFERENCES_LIST_VIEW_SEARCH_VISIBLE_COLUMNS "search-visible-columns" enum { NEMO_CLICK_POLICY_SINGLE, NEMO_CLICK_POLICY_DOUBLE }; enum { NEMO_EXECUTABLE_TEXT_LAUNCH, NEMO_EXECUTABLE_TEXT_DISPLAY, NEMO_EXECUTABLE_TEXT_ASK }; typedef enum { NEMO_SPEED_TRADEOFF_ALWAYS, NEMO_SPEED_TRADEOFF_LOCAL_ONLY, NEMO_SPEED_TRADEOFF_NEVER } NemoSpeedTradeoffValue; #define NEMO_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS "show-directory-item-counts" #define NEMO_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS "show-image-thumbnails" #define NEMO_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT "thumbnail-limit" typedef enum { NEMO_COMPLEX_SEARCH_BAR, NEMO_SIMPLE_SEARCH_BAR } NemoSearchBarMode; #define NEMO_PREFERENCES_DESKTOP_FONT "font" #define NEMO_PREFERENCES_DESKTOP_HOME_VISIBLE "home-icon-visible" #define NEMO_PREFERENCES_DESKTOP_COMPUTER_VISIBLE "computer-icon-visible" #define NEMO_PREFERENCES_DESKTOP_TRASH_VISIBLE "trash-icon-visible" #define NEMO_PREFERENCES_DESKTOP_VOLUMES_VISIBLE "volumes-visible" #define NEMO_PREFERENCES_DESKTOP_NETWORK_VISIBLE "network-icon-visible" #define NEMO_PREFERENCES_DESKTOP_BACKGROUND_FADE "background-fade" #define NEMO_PREFERENCES_DESKTOP_IGNORED_DESKTOP_HANDLERS "ignored-desktop-handlers" /* bulk rename utility */ #define NEMO_PREFERENCES_BULK_RENAME_TOOL "bulk-rename-tool" /* Lockdown */ #define NEMO_PREFERENCES_LOCKDOWN_COMMAND_LINE "disable-command-line" /* Desktop background */ #define NEMO_PREFERENCES_DESKTOP_LAYOUT "desktop-layout" #define NEMO_PREFERENCES_SHOW_ORPHANED_DESKTOP_ICONS "show-orphaned-desktop-icons" #define NEMO_PREFERENCES_SHOW_DESKTOP "show-desktop-icons" /* DEPRECATED */ #define NEMO_PREFERENCES_USE_DESKTOP_GRID "use-desktop-grid" #define NEMO_PREFERENCES_DESKTOP_HORIZONTAL_GRID_ADJUST "horizontal-grid-adjust" #define NEMO_PREFERENCES_DESKTOP_VERTICAL_GRID_ADJUST "vertical-grid-adjust" /* File size unit prefix */ #define NEMO_PREFERENCES_SIZE_PREFIXES "size-prefixes" /* media handling */ #define GNOME_DESKTOP_MEDIA_HANDLING_AUTOMOUNT "automount" #define GNOME_DESKTOP_MEDIA_HANDLING_AUTOMOUNT_OPEN "automount-open" #define GNOME_DESKTOP_MEDIA_HANDLING_AUTORUN "autorun-never" /* Terminal */ #define GNOME_DESKTOP_TERMINAL_EXEC "exec" /* Tooltips */ #define NEMO_PREFERENCES_TOOLTIPS_DESKTOP "tooltips-on-desktop" #define NEMO_PREFERENCES_TOOLTIPS_ICON_VIEW "tooltips-in-icon-view" #define NEMO_PREFERENCES_TOOLTIPS_LIST_VIEW "tooltips-in-list-view" #define NEMO_PREFERENCES_TOOLTIP_FILE_TYPE "tooltips-show-file-type" #define NEMO_PREFERENCES_TOOLTIP_MOD_DATE "tooltips-show-mod-date" #define NEMO_PREFERENCES_TOOLTIP_ACCESS_DATE "tooltips-show-access-date" #define NEMO_PREFERENCES_TOOLTIP_FULL_PATH "tooltips-show-path" #define NEMO_PREFERENCES_DISABLE_MENU_WARNING "disable-menu-warning" /* Plugins */ #define NEMO_PLUGIN_PREFERENCES_DISABLED_EXTENSIONS "disabled-extensions" #define NEMO_PLUGIN_PREFERENCES_DISABLED_ACTIONS "disabled-actions" #define NEMO_PLUGIN_PREFERENCES_DISABLED_SCRIPTS "disabled-scripts" /* Connect-to server dialog last-used method */ #define NEMO_PREFERENCES_LAST_SERVER_CONNECT_METHOD "last-server-connect-method" /* File operations queue */ #define NEMO_PREFERENCES_NEVER_QUEUE_FILE_OPS "never-queue-file-ops" #define NEMO_PREFERENCES_CLICK_DOUBLE_PARENT_FOLDER "click-double-parent-folder" void nemo_global_preferences_init (void); void nemo_global_preferences_finalize (void); char *nemo_global_preferences_get_default_folder_viewer_preference_as_iid (void); char *nemo_global_preferences_get_desktop_iid (void); gboolean nemo_global_preferences_get_ignore_view_metadata (void); gint nemo_global_preferences_get_tooltip_flags (void); gboolean nemo_global_preferences_should_load_plugin (const gchar *name, const gchar *key); GSettings *nemo_preferences; GSettings *nemo_icon_view_preferences; GSettings *nemo_list_view_preferences; GSettings *nemo_compact_view_preferences; GSettings *nemo_desktop_preferences; GSettings *nemo_tree_sidebar_preferences; GSettings *nemo_window_state; GSettings *nemo_plugin_preferences; GSettings *gnome_lockdown_preferences; GSettings *gnome_background_preferences; GSettings *gnome_media_handling_preferences; GSettings *gnome_terminal_preferences; GSettings *cinnamon_privacy_preferences; GSettings *cinnamon_interface_preferences; GTimer *nemo_startup_timer; gchar **file_roller_mimetypes; G_END_DECLS #endif /* NEMO_GLOBAL_PREFERENCES_H */ nemo-3.6.5/libnemo-private/nemo-action.c0000664000175000017500000014442513215733314017075 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-action.h" #include #include #include #include "nemo-file-utilities.h" #include "nemo-program-choosing.h" #define DEBUG_FLAG NEMO_DEBUG_ACTIONS #include G_DEFINE_TYPE (NemoAction, nemo_action, GTK_TYPE_ACTION); static void nemo_action_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void nemo_action_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void nemo_action_constructed (GObject *object); static void nemo_action_finalize (GObject *gobject); static gchar *find_token_type (const gchar *str, TokenType *token_type); static gpointer parent_class; enum { PROP_0, PROP_KEY_FILE_PATH, PROP_SELECTION_TYPE, PROP_EXTENSIONS, PROP_MIMES, PROP_EXEC, PROP_PARENT_DIR, PROP_USE_PARENT_DIR, PROP_ORIG_LABEL, PROP_ORIG_TT, PROP_SEPARATOR, PROP_QUOTE_TYPE, PROP_ESCAPE_SPACE, PROP_RUN_IN_TERMINAL, PROP_CONDITIONS }; typedef struct { NemoAction *action; gchar *name; guint watch_id; gboolean exists; } DBusCondition; static void dbus_condition_free (gpointer data) { DBusCondition *cond = (DBusCondition *) data; g_free (cond->name); g_bus_unwatch_name (cond->watch_id); } static void nemo_action_init (NemoAction *action) { action->key_file_path = NULL; action->selection_type = SELECTION_SINGLE; action->extensions = NULL; action->mimetypes = NULL; action->exec = NULL; action->parent_dir = NULL; action->use_parent_dir = FALSE; action->orig_label = NULL; action->orig_tt = NULL; action->quote_type = QUOTE_TYPE_NONE; action->separator = NULL; action->conditions = NULL; action->dbus = NULL; action->dbus_satisfied = TRUE; action->escape_underscores = FALSE; action->escape_space = FALSE; action->show_in_blank_desktop = FALSE; action->run_in_terminal = FALSE; action->log_output = g_getenv ("NEMO_ACTION_VERBOSE") != NULL; } static void nemo_action_class_init (NemoActionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = nemo_action_finalize; object_class->set_property = nemo_action_set_property; object_class->get_property = nemo_action_get_property; object_class->constructed = nemo_action_constructed; g_object_class_install_property (object_class, PROP_KEY_FILE_PATH, g_param_spec_string ("key-file-path", "Key File Path", "The key file path associated with this action", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY) ); g_object_class_install_property (object_class, PROP_SELECTION_TYPE, g_param_spec_int ("selection-type", "Selection Type", "The action selection type", 0, SELECTION_NONE, SELECTION_SINGLE, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_EXTENSIONS, g_param_spec_pointer ("extensions", "Extensions", "String array of file extensions", G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_MIMES, g_param_spec_pointer ("mimetypes", "Mimetypes", "String array of file mimetypes", G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_EXEC, g_param_spec_string ("exec", "Executable String", "The command line to run", NULL, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_PARENT_DIR, g_param_spec_string ("parent-dir", "Parent directory", "The directory the action file resides in", NULL, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_USE_PARENT_DIR, g_param_spec_boolean ("use-parent-dir", "Use Parent Directory", "Execute using the full action path", FALSE, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_ORIG_LABEL, g_param_spec_string ("orig-label", "Original label string", "The starting label - with token", NULL, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_ORIG_TT, g_param_spec_string ("orig-tooltip", "Original tooltip string", "The starting tooltip - with token", NULL, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_SEPARATOR, g_param_spec_string ("separator", "Separator to insert between files in the exec line", "Separator to use between files, like comma, space, etc", NULL, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_QUOTE_TYPE, g_param_spec_int ("quote-type", "Type of quotes to use to enclose individual file names", "Type of quotes to use to enclose individual file names - none, single or double", QUOTE_TYPE_SINGLE, QUOTE_TYPE_NONE, QUOTE_TYPE_SINGLE, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_CONDITIONS, g_param_spec_pointer ("conditions", "Special show conditions", "Special conditions, like a bool gsettings key, or 'desktop'", G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_ESCAPE_SPACE, g_param_spec_boolean ("escape-space", "Escape spaces in file paths", "Escape spaces in file paths", FALSE, G_PARAM_READWRITE) ); g_object_class_install_property (object_class, PROP_RUN_IN_TERMINAL, g_param_spec_boolean ("run-in-terminal", "Run command in a terminal", "Run command in a terminal", FALSE, G_PARAM_READWRITE) ); } static void recalc_dbus_conditions (NemoAction *action) { GList *l; DBusCondition *c; gboolean cumul_found = TRUE; for (l = action->dbus; l != NULL; l = l->next) { c = (DBusCondition *) l->data; if (!c->exists) { cumul_found = FALSE; break; } } action->dbus_satisfied = cumul_found; } static void on_dbus_appeared (GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) { DBusCondition *cond = user_data; cond->exists = TRUE; recalc_dbus_conditions (cond->action); } static void on_dbus_disappeared (GDBusConnection *connection, const gchar *name, gpointer user_data) { DBusCondition *cond = user_data; cond->exists = FALSE; recalc_dbus_conditions (cond->action); } static void setup_dbus_condition (NemoAction *action, const gchar *condition) { gchar **split = g_strsplit (condition, " ", 2); if (g_strv_length (split) != 2) { g_strfreev (split); return; } if (g_strcmp0 (split[0], "dbus") != 0) { g_strfreev (split); return; } DBusCondition *cond = g_new0 (DBusCondition, 1); cond->name = g_strdup (split[0]); cond->exists = FALSE; cond->action = action; action->dbus = g_list_append (action->dbus, cond); cond->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, split[1], 0, on_dbus_appeared, on_dbus_disappeared, cond, NULL); g_strfreev (split); } static void strip_custom_modifier (const gchar *raw, gboolean *custom, gchar **out) { if (g_str_has_prefix (raw, "<") && g_str_has_suffix (raw, ">")) { gchar **split = g_strsplit_set (raw, "<>", 3); *out = g_strdup (split[1]); *custom = TRUE; g_strfreev (split); } else { *out = g_strdup (raw); *custom = FALSE; } } void nemo_action_constructed (GObject *object) { G_OBJECT_CLASS (parent_class)->constructed (object); NemoAction *action = NEMO_ACTION (object); GKeyFile *key_file = g_key_file_new(); g_key_file_load_from_file (key_file, action->key_file_path, G_KEY_FILE_NONE, NULL); gchar *orig_label = g_key_file_get_locale_string (key_file, ACTION_FILE_GROUP, KEY_NAME, NULL, NULL); gchar *orig_tt = g_key_file_get_locale_string (key_file, ACTION_FILE_GROUP, KEY_COMMENT, NULL, NULL); gchar *icon_name = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_ICON_NAME, NULL); gchar *stock_id = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_STOCK_ID, NULL); gchar *exec_raw = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_EXEC, NULL); gchar *selection_string_raw = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_SELECTION, NULL); gchar *selection_string = g_ascii_strdown (selection_string_raw, -1); g_free (selection_string_raw); gchar *separator = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_SEPARATOR, NULL); gchar *quote_type_string = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_QUOTE_TYPE, NULL); QuoteType quote_type = QUOTE_TYPE_NONE; if (quote_type_string != NULL) { if (g_strcmp0 (quote_type_string, "single") == 0) quote_type = QUOTE_TYPE_SINGLE; else if (g_strcmp0 (quote_type_string, "double") == 0) quote_type = QUOTE_TYPE_DOUBLE; else if (g_strcmp0 (quote_type_string, "backtick") == 0) quote_type = QUOTE_TYPE_BACKTICK; } SelectionType type; if (g_strcmp0 (selection_string, SELECTION_SINGLE_KEY) == 0) type = SELECTION_SINGLE; else if (g_strcmp0 (selection_string, SELECTION_MULTIPLE_KEY) == 0) type = SELECTION_MULTIPLE; else if (g_strcmp0 (selection_string, SELECTION_ANY_KEY) == 0) type = SELECTION_ANY; else if (g_strcmp0 (selection_string, SELECTION_NONE_KEY) == 0) type = SELECTION_NONE; else if (g_strcmp0 (selection_string, SELECTION_NOT_NONE_KEY) == 0) type = SELECTION_NOT_NONE; else { gint val = (int) g_ascii_strtoll (selection_string, NULL, 10); type = val > 0 ? val : SELECTION_SINGLE; } g_free (selection_string); gsize count; gchar **ext = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_EXTENSIONS, &count, NULL); gsize mime_count; gchar **mimes = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_MIME_TYPES, &mime_count, NULL); gsize condition_count; gchar **conditions = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_CONDITIONS, &condition_count, NULL); gboolean escape_space; escape_space = g_key_file_get_boolean (key_file, ACTION_FILE_GROUP, KEY_WHITESPACE, NULL); gboolean run_in_terminal; run_in_terminal = g_key_file_get_boolean (key_file, ACTION_FILE_GROUP, KEY_TERMINAL, NULL); gboolean is_desktop = FALSE; if (conditions && condition_count > 0) { guint j; gchar *condition; for (j = 0; j < condition_count; j++) { condition = conditions[j]; if (g_str_has_prefix (condition, "dbus")) { setup_dbus_condition (action, condition); } if (g_strcmp0 (condition, "desktop") == 0) { is_desktop = TRUE; } } } gchar *exec = NULL; gboolean use_parent_dir = FALSE; strip_custom_modifier (exec_raw, &use_parent_dir, &exec); g_free (exec_raw); TokenType token_type; action->show_in_blank_desktop = is_desktop && type == SELECTION_NONE && find_token_type (exec, &token_type) == NULL; GFile *file = g_file_new_for_path (action->key_file_path); GFile *parent = g_file_get_parent (file); gchar *parent_dir = g_file_get_path (parent); g_object_unref (file); g_object_unref (parent); g_object_set (action, "label", orig_label, "tooltip", orig_tt, "icon-name", icon_name, "stock-id", stock_id, "exec", exec, "selection-type", type, "extensions", ext, "mimetypes", mimes, "parent-dir", parent_dir, "use-parent-dir", use_parent_dir, "orig-label", orig_label, "orig-tooltip", orig_tt, "quote-type", quote_type, "separator", separator, "conditions", conditions, "escape-space", escape_space, "run-in-terminal", run_in_terminal, NULL); g_free (orig_label); g_free (orig_tt); g_free (icon_name); g_free (stock_id); g_free (exec); g_strfreev (ext); g_free (parent_dir); g_free (quote_type_string); g_free (separator); g_strfreev (conditions); g_key_file_free (key_file); } NemoAction * nemo_action_new (const gchar *name, const gchar *path) { GKeyFile *key_file = g_key_file_new(); g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, NULL); if (!g_key_file_has_group (key_file, ACTION_FILE_GROUP)) { g_key_file_free (key_file); return NULL; } if (g_key_file_has_key (key_file, ACTION_FILE_GROUP, KEY_ACTIVE, NULL)) { if (!g_key_file_get_boolean (key_file, ACTION_FILE_GROUP, KEY_ACTIVE, NULL)) { g_key_file_free (key_file); return NULL; } } gchar *orig_label = g_key_file_get_locale_string (key_file, ACTION_FILE_GROUP, KEY_NAME, NULL, NULL); gchar *exec_raw = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_EXEC, NULL); gchar **ext = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_EXTENSIONS, NULL, NULL); gchar **mimes = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_MIME_TYPES, NULL, NULL); gchar **deps = g_key_file_get_string_list (key_file, ACTION_FILE_GROUP, KEY_DEPENDENCIES, NULL, NULL); gchar *selection_string = g_key_file_get_string (key_file, ACTION_FILE_GROUP, KEY_SELECTION, NULL); gboolean finish = TRUE; if (deps != NULL) { guint i = 0; for (i = 0; i < g_strv_length (deps); i++) { if (g_path_is_absolute (deps[i])) { if (!g_file_test (path, G_FILE_TEST_EXISTS)) { finish = FALSE; DEBUG ("Missing action dependency: %s", deps[i]); } } else { gchar *p = g_find_program_in_path (deps[i]); if (p == NULL) { finish = FALSE; DEBUG ("Missing action dependency: %s", deps[i]); g_free (p); break; } g_free (p); } } } if (orig_label == NULL || exec_raw == NULL || (ext == NULL && mimes == NULL) || selection_string == NULL) { g_printerr ("An action definition requires, at minimum, " "a Label field, an Exec field, a Selection field, and an either an Extensions or Mimetypes field.\n" "Check the %s file for missing fields.\n", path); finish = FALSE; } g_free (orig_label); g_free (exec_raw); g_free (selection_string); g_strfreev (ext); g_strfreev (mimes); g_strfreev (deps); g_key_file_free (key_file); return finish ? g_object_new (NEMO_TYPE_ACTION, "name", name, "key-file-path", path, NULL): NULL; } static void nemo_action_finalize (GObject *object) { NemoAction *action = NEMO_ACTION (object); g_free (action->key_file_path); g_strfreev (action->extensions); g_strfreev (action->mimetypes); g_strfreev (action->conditions); g_free (action->exec); g_free (action->parent_dir); g_free (action->orig_label); g_free (action->orig_tt); if (action->dbus) { g_list_free_full (action->dbus, (GDestroyNotify) dbus_condition_free); action->dbus = NULL; } G_OBJECT_CLASS (parent_class)->finalize (object); } static void nemo_action_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NemoAction *action; action = NEMO_ACTION (object); switch (prop_id) { case PROP_KEY_FILE_PATH: nemo_action_set_key_file_path (action, g_value_get_string (value)); break; case PROP_SELECTION_TYPE: action->selection_type = g_value_get_int (value); break; case PROP_EXTENSIONS: nemo_action_set_extensions (action, g_value_get_pointer (value)); break; case PROP_MIMES: nemo_action_set_mimetypes (action, g_value_get_pointer (value)); break; case PROP_EXEC: nemo_action_set_exec (action, g_value_get_string (value)); break; case PROP_PARENT_DIR: nemo_action_set_parent_dir (action, g_value_get_string (value)); break; case PROP_USE_PARENT_DIR: action->use_parent_dir = g_value_get_boolean (value); break; case PROP_ORIG_LABEL: nemo_action_set_orig_label (action, g_value_get_string (value)); break; case PROP_ORIG_TT: nemo_action_set_orig_tt (action, g_value_get_string (value)); break; case PROP_QUOTE_TYPE: action->quote_type = g_value_get_int (value); break; case PROP_SEPARATOR: nemo_action_set_separator (action, g_value_get_string (value)); break; case PROP_CONDITIONS: nemo_action_set_conditions (action, g_value_get_pointer (value)); break; case PROP_ESCAPE_SPACE: action->escape_space = g_value_get_boolean (value); break; case PROP_RUN_IN_TERMINAL: action->run_in_terminal = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void nemo_action_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NemoAction *action; action = NEMO_ACTION (object); switch (prop_id) { case PROP_KEY_FILE_PATH: g_value_set_string (value, action->key_file_path); break; case PROP_SELECTION_TYPE: g_value_set_int (value, action->selection_type); break; case PROP_EXTENSIONS: g_value_set_pointer (value, action->extensions); break; case PROP_MIMES: g_value_set_pointer (value, action->mimetypes); break; case PROP_EXEC: g_value_set_string (value, action->exec); break; case PROP_PARENT_DIR: g_value_set_string (value, action->parent_dir); break; case PROP_USE_PARENT_DIR: g_value_set_boolean (value, action->use_parent_dir); break; case PROP_ORIG_LABEL: g_value_set_string (value, action->orig_label); break; case PROP_ORIG_TT: g_value_set_string (value, action->orig_tt); break; case PROP_QUOTE_TYPE: g_value_set_int (value, action->quote_type); break; case PROP_SEPARATOR: g_value_set_string (value, action->separator); break; case PROP_CONDITIONS: g_value_set_pointer (value, action->conditions); break; case PROP_ESCAPE_SPACE: g_value_set_boolean (value, action->escape_space); break; case PROP_RUN_IN_TERMINAL: g_value_set_boolean (value, action->run_in_terminal); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static gchar * find_token_type (const gchar *str, TokenType *token_type) { gchar *ptr = NULL; *token_type = TOKEN_NONE; ptr = g_strstr_len (str, -1, TOKEN_EXEC_FILE_LIST); if (ptr != NULL) { *token_type = TOKEN_PATH_LIST; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_EXEC_URI_LIST); if (ptr != NULL) { *token_type = TOKEN_URI_LIST; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_EXEC_PARENT); if (ptr != NULL) { *token_type = TOKEN_PARENT_PATH; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_EXEC_FILE_NAME); if (ptr != NULL) { *token_type = TOKEN_FILE_DISPLAY_NAME; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_EXEC_PARENT_NAME); if (ptr != NULL) { *token_type = TOKEN_PARENT_DISPLAY_NAME; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_LABEL_FILE_NAME); if (ptr != NULL) { *token_type = TOKEN_FILE_DISPLAY_NAME; return ptr; } ptr = g_strstr_len (str, -1, TOKEN_EXEC_DEVICE); if (ptr != NULL) { *token_type = TOKEN_DEVICE; return ptr; } return NULL; } static gchar * get_path (NemoAction *action, NemoFile *file) { gchar *ret, *quote_escaped, *orig; orig = nemo_file_get_path (file); quote_escaped = eel_str_escape_quotes (orig); if (action->escape_space) { ret = eel_str_escape_spaces (quote_escaped); } else { ret = g_strdup (quote_escaped); } g_free (orig); g_free (quote_escaped); return ret; } static GString * score_append (NemoAction *action, GString *str, const gchar *c) { if (action->escape_underscores) { gchar *escaped = eel_str_double_underscores (c); str = g_string_append (str, escaped); g_free (escaped); return str; } else { return g_string_append (str, c); } } static GString * insert_separator (NemoAction *action, GString *str) { if (action->separator == NULL) str = g_string_append (str, " "); else str = score_append (action, str, action->separator); return str; } static GString * insert_quote (NemoAction *action, GString *str) { switch (action->quote_type) { case QUOTE_TYPE_SINGLE: str = g_string_append (str, "'"); break; case QUOTE_TYPE_DOUBLE: str = g_string_append (str, "\""); break; case QUOTE_TYPE_BACKTICK: str = g_string_append (str, "`"); break; case QUOTE_TYPE_NONE: break; default: break; } return str; } static gchar * get_device_path (NemoAction *action, NemoFile *file) { GMount *mount = nemo_file_get_mount (file); GVolume *volume = g_mount_get_volume (mount); gchar *ret = NULL; if (action->escape_space) { gchar *id = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); ret = eel_str_escape_spaces (id); g_free (id); } else { ret = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); } g_object_unref (mount); g_object_unref (volume); return ret; } static gchar * get_insertion_string (NemoAction *action, TokenType token_type, GList *selection, NemoFile *parent) { GList *l; GString *str = g_string_new(""); gboolean first = TRUE; switch (token_type) { case TOKEN_PATH_LIST: if (g_list_length (selection) > 0) { for (l = selection; l != NULL; l = l->next) { if (!first) str = insert_separator (action, str); str = insert_quote (action, str); gchar *path = get_path (action, NEMO_FILE (l->data)); if (path) str = score_append (action, str, path); g_free (path); str = insert_quote (action, str); first = FALSE; } } else { goto default_parent_path; } break; case TOKEN_URI_LIST: if (g_list_length (selection) > 0) { for (l = selection; l != NULL; l = l->next) { if (!first) str = insert_separator (action, str); str = insert_quote (action, str); gchar *uri = nemo_file_get_uri (NEMO_FILE (l->data)); str = score_append (action, str, uri); g_free (uri); str = insert_quote (action, str); first = FALSE; } } else { goto default_parent_path; } break; case TOKEN_PARENT_PATH: ; default_parent_path: ; gchar *path = get_path (action, parent); if (path == NULL) { gchar *name = nemo_file_get_display_name (parent); if (g_strcmp0 (name, "x-nemo-desktop") == 0) path = nemo_get_desktop_directory (); else path = g_strdup (""); g_free (name); } str = insert_quote (action, str); str = score_append (action, str, path); str = insert_quote (action, str); g_free (path); break; case TOKEN_FILE_DISPLAY_NAME: if (g_list_length (selection) > 0) { gchar *file_display_name = nemo_file_get_display_name (NEMO_FILE (selection->data)); str = score_append (action, str, file_display_name); g_free (file_display_name); } else { goto default_parent_display_name; } break; case TOKEN_PARENT_DISPLAY_NAME: ; default_parent_display_name: ; gchar *parent_display_name; gchar *real_display_name = nemo_file_get_display_name (parent); if (g_strcmp0 (real_display_name, "x-nemo-desktop") == 0) parent_display_name = g_strdup_printf (_("Desktop")); else parent_display_name = nemo_file_get_display_name (parent); g_free (real_display_name); str = insert_quote (action, str); str = score_append (action, str, parent_display_name); str = insert_quote (action, str); g_free (parent_display_name); break; case TOKEN_DEVICE: if (g_list_length (selection) > 0) { for (l = selection; l != NULL; l = l->next) { if (!first) str = insert_separator (action, str); str = insert_quote (action, str); gchar *dev = get_device_path (action, NEMO_FILE (l->data)); if (dev) str = score_append (action, str, dev); g_free (dev); str = insert_quote (action, str); first = FALSE; } } else { goto default_parent_path; } break; case TOKEN_NONE: default: break; } gchar *ret = str->str; g_string_free (str, FALSE); return ret; } static GString * expand_action_string (NemoAction *action, GList *selection, NemoFile *parent, GString *str) { gchar *ptr; TokenType token_type; ptr = find_token_type (str->str, &token_type); while (ptr != NULL) { gint shift = ptr - str->str; gchar *insertion = get_insertion_string (action, token_type, selection, parent); str = g_string_erase (str, shift, 2); str = g_string_insert (str, shift, insertion); token_type = TOKEN_NONE; g_free (insertion); ptr = find_token_type (str->str, &token_type); } return str; } void nemo_action_activate (NemoAction *action, GList *selection, NemoFile *parent) { GError *error; GString *exec = g_string_new (action->exec); error = NULL; action->escape_underscores = FALSE; exec = expand_action_string (action, selection, parent, exec); if (action->use_parent_dir) { exec = g_string_prepend (exec, G_DIR_SEPARATOR_S); exec = g_string_prepend (exec, action->parent_dir); } DEBUG ("Action Spawning: %s", exec->str); if (action->log_output) g_printerr ("Action Spawning: %s\n", exec->str); if (action->run_in_terminal) { gint argcp; gchar **argvp; if (g_shell_parse_argv (exec->str, &argcp, &argvp, &error)) { nemo_launch_application_from_command_array (gdk_screen_get_default (), argvp[0], TRUE, (const char * const *)(argvp + sizeof (gchar))); g_strfreev (argvp); } else { DEBUG ("Could not parse arguments terminal launch. Possibly turn off Quotes and remove any from your Exec line: %s\n", error->message); g_error_free (error); } } else { if (!g_spawn_command_line_async (exec->str, &error)) { DEBUG ("Error spawning action: %s\n", error->message); g_error_free (error); } } g_string_free (exec, TRUE); } SelectionType nemo_action_get_selection_type (NemoAction *action) { return action->selection_type; } gchar ** nemo_action_get_extension_list (NemoAction *action) { return action->extensions; } gchar ** nemo_action_get_mimetypes_list (NemoAction *action) { return action->mimetypes; } void nemo_action_set_key_file_path (NemoAction *action, const gchar *path) { gchar *tmp; tmp = action->key_file_path; action->key_file_path = g_strdup (path); g_free (tmp); } void nemo_action_set_exec (NemoAction *action, const gchar *exec) { gchar *tmp; tmp = action->exec; action->exec = g_strdup (exec); g_free (tmp); } void nemo_action_set_parent_dir (NemoAction *action, const gchar *parent_dir) { gchar *tmp; tmp = action->parent_dir; action->parent_dir = g_strdup (parent_dir); g_free (tmp); } void nemo_action_set_separator (NemoAction *action, const gchar *separator) { gchar *tmp; tmp = action->separator; action->separator = g_strdup (separator); g_free (tmp); } void nemo_action_set_conditions (NemoAction *action, gchar **conditions) { gchar **tmp; tmp = action->conditions; action->conditions = g_strdupv (conditions); g_strfreev (tmp); } void nemo_action_set_orig_label (NemoAction *action, const gchar *orig_label) { gchar *tmp; tmp = action->orig_label; action->orig_label = g_strdup (orig_label); g_free (tmp); } const gchar * nemo_action_get_orig_label (NemoAction *action) { return action->orig_label; } void nemo_action_set_orig_tt (NemoAction *action, const gchar *orig_tt) { gchar *tmp; tmp = action->orig_tt; action->orig_tt = g_strdup (orig_tt); g_free (tmp); } const gchar * nemo_action_get_orig_tt (NemoAction *action) { return action->orig_tt; } gchar ** nemo_action_get_conditions (NemoAction *action) { return action->conditions; } gchar * nemo_action_get_label (NemoAction *action, GList *selection, NemoFile *parent) { const gchar *orig_label = nemo_action_get_orig_label (action); if (orig_label == NULL) return NULL; action->escape_underscores = TRUE; GString *str = g_string_new (orig_label); str = expand_action_string (action, selection, parent, str); DEBUG ("Action Label: %s", str->str); if (action->log_output) g_printerr ("Action Label: %s\n", str->str); gchar *ret = str->str; g_string_free (str, FALSE); return ret; } gchar * nemo_action_get_tt (NemoAction *action, GList *selection, NemoFile *parent) { const gchar *orig_tt = nemo_action_get_orig_tt (action); if (orig_tt == NULL) return NULL; action->escape_underscores = FALSE; GString *str = g_string_new (orig_tt); str = expand_action_string (action, selection, parent, str); DEBUG ("Action Tooltip: %s", str->str); if (action->log_output) g_printerr ("Action Tooltip: %s\n", str->str); gchar *ret = str->str; g_string_free (str, FALSE); return ret; } void nemo_action_set_extensions (NemoAction *action, gchar **extensions) { gchar **tmp; tmp = action->extensions; action->extensions = g_strdupv (extensions); g_strfreev (tmp); } void nemo_action_set_mimetypes (NemoAction *action, gchar **mimetypes) { gchar **tmp; tmp = action->mimetypes; action->mimetypes = g_strdupv (mimetypes); g_strfreev (tmp); } gboolean nemo_action_get_dbus_satisfied (NemoAction *action) { return action->dbus_satisfied; } #define EQUALS "eq" #define NOT_EQUALS "ne" #define LESS_THAN "lt" #define GREATER_THAN "gt" enum { GSETTINGS_SCHEMA_INDEX = 1, GSETTINGS_KEY_INDEX = 2, GSETTINGS_TYPE_INDEX = 3, GSETTINGS_OP_INDEX = 4, GSETTINGS_VAL_INDEX = 5, }; static gboolean operator_is_valid (const gchar *op_string) { return (g_strcmp0 (op_string, EQUALS) == 0 || g_strcmp0 (op_string, NOT_EQUALS) == 0 || g_strcmp0 (op_string, LESS_THAN) == 0 || g_strcmp0 (op_string, GREATER_THAN) == 0); } static gboolean try_vector (const gchar *op, gint vector) { if (g_strcmp0 (op, EQUALS) == 0) { return (vector == 0); } else if (g_strcmp0 (op, NOT_EQUALS) == 0) { return (vector != 0); } else if (g_strcmp0 (op, LESS_THAN) == 0) { return (vector < 0); } else if (g_strcmp0 (op, GREATER_THAN) == 0) { return (vector > 0); } return FALSE; } static gboolean check_gsettings_condition (NemoAction *action, const gchar *condition) { gchar **split = g_strsplit (condition, " ", 6); gint len = g_strv_length (split); if (len != 6 && len != 3) { g_strfreev (split); return FALSE; } if (g_strcmp0 (split[0], "gsettings") != 0) { g_strfreev (split); return FALSE; } if (len == 6 && (!g_variant_type_string_is_valid (split[GSETTINGS_TYPE_INDEX]) || !operator_is_valid (split[GSETTINGS_OP_INDEX]))) { g_printerr ("Nemo Action: Either gsettings variant type (%s) or operator (%s) is invalid.\n", split[GSETTINGS_TYPE_INDEX], split[GSETTINGS_OP_INDEX]); g_strfreev (split); return FALSE; } GSettingsSchemaSource *schema_source; gboolean ret = FALSE; const GVariantType *target_type; if (len == 3) { target_type = G_VARIANT_TYPE_BOOLEAN; } else { target_type = G_VARIANT_TYPE (split[GSETTINGS_TYPE_INDEX]); } schema_source = g_settings_schema_source_get_default(); if (g_settings_schema_source_lookup (schema_source, split[GSETTINGS_SCHEMA_INDEX], TRUE)) { GSettings *s = g_settings_new (split[GSETTINGS_SCHEMA_INDEX]); gchar **keys = g_settings_list_keys (s); guint i; for (i = 0; i < g_strv_length (keys); i++) { if (len == 3) { if (g_strcmp0 (keys[i], split[GSETTINGS_KEY_INDEX]) == 0) { GVariant *setting_var = g_settings_get_value (s, split[GSETTINGS_KEY_INDEX]); const GVariantType *setting_type = g_variant_get_type (setting_var); if (g_variant_type_equal (setting_type, target_type)) ret = g_variant_get_boolean (setting_var); g_variant_unref (setting_var); } } else { if (g_strcmp0 (keys[i], split[GSETTINGS_KEY_INDEX]) == 0) { GVariant *setting_var = g_settings_get_value (s, split[GSETTINGS_KEY_INDEX]); const GVariantType *setting_type = g_variant_get_type (setting_var); if (g_variant_type_equal (setting_type, target_type)) { GVariant *target_var = g_variant_parse (target_type, split[GSETTINGS_VAL_INDEX], NULL, NULL, NULL); if (target_var != NULL) { gint vector = g_variant_compare (setting_var, target_var); ret = try_vector (split[GSETTINGS_OP_INDEX], vector); g_variant_unref (target_var); } else { g_printerr ("Nemo Action: gsettings value could not be parsed into a valid GVariant\n"); } } g_variant_unref (setting_var); } } } g_strfreev (keys); g_object_unref (s); g_strfreev (split); return ret; } else { g_strfreev (split); return FALSE; } return FALSE; } static gboolean get_is_dir (NemoFile *file) { gboolean ret = FALSE; GFile *f = nemo_file_get_location (file); if (g_file_is_native (f)) { gchar *path; path = g_file_get_path (f); ret = g_file_test (path, G_FILE_TEST_IS_DIR); g_free (path); } else { ret = nemo_file_is_directory (file); } g_object_unref (f); return ret; } gboolean nemo_action_get_visibility (NemoAction *action, GList *selection, NemoFile *parent) { gboolean selection_type_show = FALSE; gboolean extension_type_show = TRUE; gboolean condition_type_show = TRUE; if (!nemo_action_get_dbus_satisfied (action)) goto out; gchar **conditions = nemo_action_get_conditions (action); guint condition_count = conditions != NULL ? g_strv_length (conditions) : 0; if (condition_count > 0) { guint j; gchar *condition; for (j = 0; j < condition_count; j++) { condition = conditions[j]; if (g_strcmp0 (condition, "desktop") == 0) { gchar *name = nemo_file_get_display_name (parent); if (g_strcmp0 (name, "x-nemo-desktop") != 0) condition_type_show = FALSE; g_free (name); } else if (g_strcmp0 (condition, "removable") == 0) { gboolean is_removable = FALSE; if (g_list_length (selection) > 0) { GMount *mount = nemo_file_get_mount (selection->data); if (mount) { GDrive *drive = g_mount_get_drive (mount); if (drive) { if (g_drive_is_media_removable (drive)) is_removable = TRUE; g_object_unref (drive); } } } condition_type_show = is_removable; } else if (g_str_has_prefix (condition, "gsettings")) { condition_type_show = check_gsettings_condition (action, condition); } if (!condition_type_show) break; } } if (!condition_type_show) goto out; SelectionType selection_type = nemo_action_get_selection_type (action); GList *iter; guint selected_count = g_list_length (selection); switch (selection_type) { case SELECTION_SINGLE: selection_type_show = selected_count == 1; break; case SELECTION_MULTIPLE: selection_type_show = selected_count > 1; break; case SELECTION_NOT_NONE: selection_type_show = selected_count > 0; break; case SELECTION_NONE: selection_type_show = selected_count == 0; break; case SELECTION_ANY: selection_type_show = TRUE; break; default: selection_type_show = selected_count == selection_type; break; } gchar **extensions = nemo_action_get_extension_list (action); gchar **mimetypes = nemo_action_get_mimetypes_list (action); guint ext_count = extensions != NULL ? g_strv_length (extensions) : 0; guint mime_count = mimetypes != NULL ? g_strv_length (mimetypes) : 0; if (ext_count == 1 && g_strcmp0 (extensions[0], "any") == 0) goto out; gboolean found_match = TRUE; for (iter = selection; iter != NULL && found_match; iter = iter->next) { found_match = FALSE; gboolean is_dir; gchar *raw_fn = nemo_file_get_name (NEMO_FILE (iter->data)); gchar *filename = g_ascii_strdown (raw_fn, -1); g_free (raw_fn); guint i; is_dir = get_is_dir (iter->data); if (ext_count > 0) { for (i = 0; i < ext_count; i++) { if (g_strcmp0 (extensions[i], "dir") == 0) { if (is_dir) { found_match = TRUE; break; } } else if (g_strcmp0 (extensions[i], "none") == 0) { if (g_strrstr (filename, ".") == NULL) { found_match = TRUE; break; } } else if (g_strcmp0 (extensions[i], "nodirs") == 0) { if (!is_dir) { found_match = TRUE; break; } } else { gchar *str = g_ascii_strdown (extensions[i], -1); if (g_str_has_suffix (filename, str)) { found_match = TRUE; } g_free (str); if (found_match) { break; } } } g_free (filename); } if (mime_count > 0) { for (i = 0; i < mime_count; i++) { if (nemo_file_is_mime_type (NEMO_FILE (iter->data), mimetypes[i])) { found_match = TRUE; break; } } } if (nemo_file_is_mime_type (NEMO_FILE (iter->data), "application/x-nemo-link")) { found_match = FALSE; } } extension_type_show = found_match; out: return selection_type_show && extension_type_show && condition_type_show; } nemo-3.6.5/libnemo-private/nemo-undo-manager.c0000664000175000017500000001316313215733314020167 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* NemoUndoManager - Undo/Redo transaction manager. * * Copyright (C) 2000 Eazel, Inc. * * Author: Gene Z. Ragan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #include #include #include #include #include "nemo-undo-private.h" struct NemoUndoManagerDetails { NemoUndoTransaction *transaction; /* These are used to tell undo from redo. */ gboolean current_transaction_is_redo; gboolean new_transaction_is_redo; /* These are used only so that we can complain if we get more * than one transaction inside undo. */ gboolean undo_in_progress; int num_transactions_during_undo; }; enum { CHANGED, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { char *path; char *no_undo_menu_item_label; char *no_undo_menu_item_hint; } UndoMenuHandlerConnection; G_DEFINE_TYPE (NemoUndoManager, nemo_undo_manager, G_TYPE_OBJECT) static void release_transaction (NemoUndoManager *manager) { NemoUndoTransaction *transaction; transaction = manager->details->transaction; manager->details->transaction = NULL; if (transaction != NULL) { g_object_unref (transaction); } } void nemo_undo_manager_append (NemoUndoManager *manager, NemoUndoTransaction *transaction) { NemoUndoTransaction *duplicate_transaction; /* Check, complain, and ignore the passed-in transaction if we * get more than one within a single undo operation. The single * transaction we get during the undo operation is supposed to * be the one for redoing the undo (or re-undoing the redo). */ if (manager->details->undo_in_progress) { manager->details->num_transactions_during_undo += 1; g_return_if_fail (manager->details->num_transactions_during_undo == 1); } g_return_if_fail (transaction != NULL); /* Keep a copy of this transaction (dump the old one). */ duplicate_transaction = g_object_ref (transaction); release_transaction (manager); manager->details->transaction = duplicate_transaction; manager->details->current_transaction_is_redo = manager->details->new_transaction_is_redo; /* Fire off signal indicating that the undo state has changed. */ g_signal_emit (manager, signals[CHANGED], 0); } void nemo_undo_manager_forget (NemoUndoManager *manager, NemoUndoTransaction *transaction) { /* Nothing to forget unless the item we are passed is the * transaction we are currently holding. */ if (transaction != manager->details->transaction) { return; } /* Get rid of the transaction we are holding on to. */ release_transaction (manager); /* Fire off signal indicating that the undo state has changed. */ g_signal_emit (manager, signals[CHANGED], 0); } NemoUndoManager * nemo_undo_manager_new (void) { return NEMO_UNDO_MANAGER (g_object_new (nemo_undo_manager_get_type (), NULL)); } static void nemo_undo_manager_init (NemoUndoManager *manager) { manager->details = g_new0 (NemoUndoManagerDetails, 1); } void nemo_undo_manager_undo (NemoUndoManager *manager) { NemoUndoTransaction *transaction; g_return_if_fail (NEMO_IS_UNDO_MANAGER (manager)); transaction = manager->details->transaction; manager->details->transaction = NULL; if (transaction != NULL) { /* Perform the undo. New transactions that come in * during an undo are redo transactions. New * transactions that come in during a redo are undo * transactions. Transactions that come in outside * are always undo and never redo. */ manager->details->new_transaction_is_redo = !manager->details->current_transaction_is_redo; manager->details->undo_in_progress = TRUE; manager->details->num_transactions_during_undo = 0; nemo_undo_transaction_undo (transaction); manager->details->undo_in_progress = FALSE; manager->details->new_transaction_is_redo = FALSE; /* Let go of the transaction. */ g_object_unref (transaction); /* Fire off signal indicating the undo state has changed. */ g_signal_emit (manager, signals[CHANGED], 0); } } static void finalize (GObject *object) { NemoUndoManager *manager; manager = NEMO_UNDO_MANAGER (object); release_transaction (manager); g_free (manager->details); if (G_OBJECT_CLASS (nemo_undo_manager_parent_class)->finalize) { (* G_OBJECT_CLASS (nemo_undo_manager_parent_class)->finalize) (object); } } void nemo_undo_manager_attach (NemoUndoManager *manager, GObject *target) { g_return_if_fail (NEMO_IS_UNDO_MANAGER (manager)); g_return_if_fail (G_IS_OBJECT (target)); nemo_undo_attach_undo_manager (G_OBJECT (target), manager); } static void nemo_undo_manager_class_init (NemoUndoManagerClass *class) { G_OBJECT_CLASS (class)->finalize = finalize; signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoUndoManagerClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } nemo-3.6.5/libnemo-private/nemo-default-file-icon.c0000664000175000017500000011276413215733314021110 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Default file icon used by the icon factory. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-default-file-icon.h" const int nemo_default_file_icon_width = 48; const int nemo_default_file_icon_height = 48; const unsigned char nemo_default_file_icon[] = /* This is from text-x-preview.svg in the gnome icon theme */ "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\243\255\243\31\252\254\245\307\246\251\243\374\246\251\243\377\246" "\251\243\377\246\251\242\377\246\250\242\377\246\250\242\377\246\250" "\242\377\245\250\242\377\245\250\242\377\245\250\242\377\245\250\241" "\377\245\247\241\377\245\247\241\377\245\247\241\377\244\247\241\377" "\244\247\241\377\244\247\241\377\244\247\240\377\244\246\240\377\244" "\246\240\377\244\246\240\377\243\246\240\377\243\246\240\377\243\246" "\237\377\244\247\240\371\245\251\242\333\245\247\242\216\246\246\233" "\27\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\252\254\246\277\347\351" "\346\376\377\377\376\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\374\374\374\377\362\363\361\377\353\355\352\377" "\344\345\342\377\276\300\272\371\244\245\240\366\244\247\237h\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\246\251\244\373\376\376\376\377\354\355\352\377" "\352\354\350\377\351\353\347\377\351\353\347\377\350\352\346\377\350" "\351\345\377\347\351\344\377\346\350\344\377\345\350\343\377\344\347" "\342\377\344\346\341\377\343\346\340\377\342\345\340\377\341\344\337" "\377\341\343\336\377\340\342\335\377\337\342\334\377\337\341\333\377" "\336\340\332\377\335\337\332\377\334\337\331\377\333\336\330\377\332" "\335\327\377\331\334\326\377\331\334\325\377\333\334\327\377\362\363" "\361\377\333\335\331\377\250\253\245\364\245\246\240\236\200\200\200" "\2\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\245\247\241\377\377\377\377\377\352\354\350\377\351\353\347\377\351" "\353\347\377\350\352\346\377\350\352\346\377\347\351\345\377\347\350" "\344\377\346\351\344\377\345\350\343\377\344\347\342\377\344\346\342" "\377\343\346\341\377\342\345\340\377\341\344\337\377\341\344\336\377" "\340\343\335\377\340\342\335\377\337\341\334\377\336\341\333\377\335" "\340\332\377\334\337\331\377\334\336\330\377\333\336\327\377\332\335" "\326\377\331\334\325\377\326\331\322\377\326\330\324\377\372\372\371" "\377\333\336\331\377\253\257\251\364\241\246\240\251\377\377\377\1\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\244\247\240\377" "\377\377\377\377\351\353\347\377\351\353\347\377\350\353\347\377\350" "\352\346\377\347\352\345\377\347\351\345\377\347\350\344\377\346\350" "\343\377\345\347\343\377\344\347\343\377\344\346\342\377\343\346\341" "\377\342\345\340\377\342\344\337\377\341\344\336\377\341\343\336\377" "\340\342\335\377\337\342\334\377\337\341\333\377\336\340\332\377\335" "\340\332\377\334\337\331\377\333\336\330\377\333\335\327\377\332\335" "\326\377\330\333\324\377\312\314\307\377\374\375\374\377\363\364\362" "\377\325\330\322\377\253\255\250\365\242\244\235\222\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\243\246\240\377\377\377\377\377" "\351\352\346\377\350\352\346\377\350\352\346\377\347\352\346\377\347" "\351\345\377\347\351\344\377\346\350\344\377\346\350\343\377\345\347" "\342\377\344\346\342\377\344\346\342\377\343\346\341\377\342\345\340" "\377\342\345\337\377\342\344\337\377\341\343\336\377\340\343\335\377" "\340\342\334\377\337\341\333\377\336\341\333\377\335\340\332\377\335" "\337\331\377\334\337\330\377\333\336\327\377\332\335\326\377\332\335" "\326\377\314\317\310\377\372\372\372\377\370\370\370\377\346\351\345" "\377\324\330\321\377\245\247\241\364\241\244\235Q\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\243\245\237\377\377\377\377\377\350\352\346\377" "\350\351\345\377\347\351\345\377\347\351\345\377\347\351\344\377\346" "\350\344\377\346\350\343\377\345\347\343\377\345\347\342\377\344\346" "\342\377\344\346\341\377\343\345\341\377\342\345\340\377\342\345\337" "\377\341\344\337\377\340\344\336\377\341\343\335\377\340\342\334\377" "\337\342\334\377\336\341\333\377\336\340\332\377\335\340\331\377\334" "\337\331\377\334\336\330\377\333\336\327\377\332\335\326\377\320\323" "\314\377\305\307\301\377\271\274\266\377\262\265\257\377\300\303\276" "\377\314\317\311\377\240\244\234\355\222\222\222\7\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\242\245\237\377\377\377\377\377\347\351\345\377\347\351\344" "\377\347\350\345\377\346\350\344\377\346\350\344\377\346\350\343\377" "\346\350\343\377\345\347\342\377\345\347\342\377\344\346\342\377\344" "\346\341\377\343\345\341\377\342\345\340\377\342\345\337\377\341\344" "\337\377\341\344\336\377\341\343\335\377\340\343\334\377\337\342\334" "\377\337\341\333\377\336\341\332\377\335\340\332\377\335\340\331\377" "\334\337\330\377\333\336\327\377\333\336\327\377\322\325\317\377\307" "\312\304\377\274\300\271\377\261\264\257\377\246\250\244\377\302\304" "\300\377\260\263\255\363\237\242\235h\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\241" "\244\236\377\377\377\377\377\347\351\344\377\346\350\344\377\346\350" "\344\377\346\350\344\377\345\350\343\377\346\350\343\377\345\347\342" "\377\345\347\343\377\344\347\342\377\344\346\342\377\343\346\341\377" "\343\345\341\377\342\345\340\377\342\344\337\377\342\344\337\377\341" "\343\336\377\341\343\335\377\340\343\335\377\340\342\334\377\337\342" "\333\377\336\341\333\377\336\341\332\377\335\340\331\377\335\340\331" "\377\334\337\330\377\334\337\330\377\334\337\330\377\333\335\327\377" "\331\333\325\377\322\324\317\377\306\310\303\377\273\276\271\377\322" "\325\320\377\242\244\236\312\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\241\243\235" "\377\377\377\377\377\346\350\343\377\346\350\344\377\346\350\343\377" "\345\347\343\377\345\347\343\377\345\347\342\377\345\347\342\377\345" "\347\342\377\344\347\342\377\344\346\341\377\343\346\341\377\343\345" "\340\377\342\345\340\377\342\344\337\377\341\344\337\377\341\343\336" "\377\341\343\335\377\340\342\335\377\340\342\334\377\337\341\334\377" "\337\341\334\377\336\341\333\377\336\340\333\377\335\340\332\377\335" "\337\331\377\335\337\331\377\335\337\331\377\334\337\331\377\334\337" "\331\377\334\337\331\377\334\337\331\377\336\341\333\377\350\352\347" "\377\236\240\232\370\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\240\242\234\377\377" "\377\377\377\346\347\343\377\345\350\343\377\345\347\343\377\345\347" "\343\377\345\347\342\377\344\347\342\377\345\346\342\377\344\347\342" "\377\344\346\342\377\344\346\341\377\343\346\341\377\343\345\340\377" "\342\345\340\377\342\344\337\377\341\344\337\377\342\343\337\377\341" "\343\336\377\341\342\336\377\340\342\335\377\340\341\335\377\337\341" "\334\377\336\340\333\377\336\340\333\377\336\340\333\377\336\340\333" "\377\336\340\333\377\336\340\333\377\336\340\333\377\335\340\332\377" "\335\340\332\377\335\340\332\377\337\342\334\377\363\364\362\377\233" "\235\230\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\237\242\234\377\377\377" "\377\377\345\347\342\377\345\347\342\377\345\347\343\377\345\347\342" "\377\344\347\342\377\344\346\342\377\345\346\342\377\344\346\342\377" "\344\346\341\377\344\346\341\377\343\346\341\377\343\345\340\377\342" "\345\340\377\342\344\337\377\341\344\337\377\342\344\337\377\341\343" "\336\377\341\343\336\377\340\342\335\377\340\342\335\377\337\341\334" "\377\337\341\334\377\337\341\334\377\337\341\334\377\337\341\334\377" "\337\341\334\377\337\341\334\377\337\341\334\377\337\341\334\377\336" "\341\333\377\336\341\333\377\340\343\335\377\373\373\372\377\232\235" "\227\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\237\241\233\377\377\377\377\377" "\344\347\342\377\345\346\342\377\345\347\342\377\344\347\342\377\344" "\347\342\377\344\346\341\377\344\346\342\377\344\346\342\377\344\345" "\341\377\343\346\341\377\343\346\341\377\343\345\340\377\342\345\340" "\377\342\345\337\377\341\344\340\377\341\344\337\377\341\343\337\377" "\341\343\336\377\340\342\336\377\340\342\335\377\340\342\335\377\340" "\342\335\377\340\342\335\377\340\342\335\377\340\342\335\377\340\342" "\335\377\340\342\335\377\337\342\335\377\337\342\335\377\337\342\334" "\377\337\342\334\377\341\344\336\377\375\375\375\377\232\234\226\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\236\240\233\377\377\377\377\377\344\346" "\341\377\345\346\342\377\344\346\342\377\344\347\342\377\344\346\341" "\377\344\346\341\377\343\346\342\377\344\346\341\377\344\346\341\377" "\343\345\341\377\343\345\340\377\343\345\340\377\342\345\340\377\342" "\345\337\377\341\344\340\377\341\344\337\377\342\344\337\377\341\343" "\336\377\341\343\336\377\341\343\336\377\341\343\336\377\341\343\336" "\377\341\343\336\377\341\343\336\377\341\343\336\377\341\343\336\377" "\341\343\336\377\341\343\336\377\340\343\336\377\340\343\336\377\340" "\343\335\377\342\345\337\377\375\375\375\377\231\233\226\377\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\235\240\232\377\377\377\377\377\344\346\341\377" "\343\346\341\377\344\346\342\377\344\346\341\377\344\346\341\377\344" "\346\341\377\343\346\341\377\344\346\341\377\344\345\341\377\343\345" "\341\377\343\345\340\377\343\345\340\377\342\345\341\377\342\345\340" "\377\342\345\340\377\342\344\337\377\342\344\337\377\342\344\337\377" "\342\344\337\377\342\344\337\377\342\344\337\377\342\344\337\377\342" "\344\337\377\342\344\337\377\342\344\337\377\342\344\337\377\342\344" "\337\377\342\344\337\377\341\344\337\377\341\344\337\377\341\344\337" "\377\341\343\336\377\375\375\375\377\230\233\225\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\235\237\231\377\377\377\377\377\343\345\341\377\343\346\341" "\377\344\346\341\377\344\346\341\377\344\346\341\377\343\345\341\377" "\343\346\341\377\344\346\341\377\344\346\341\377\343\345\341\377\343" "\345\340\377\343\345\340\377\343\345\341\377\342\345\340\377\342\345" "\340\377\342\345\340\377\342\345\340\377\343\345\340\377\343\345\340" "\377\343\345\340\377\343\345\340\377\343\345\340\377\343\345\340\377" "\343\345\340\377\343\345\340\377\343\345\340\377\343\345\340\377\342" "\345\340\377\342\345\340\377\342\345\340\377\342\344\340\377\342\344" "\337\377\377\377\377\377\230\232\224\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\234\236\231\377\377\377\377\377\343\345\341\377\343\345\340\377\343" "\346\341\377\344\346\341\377\344\345\341\377\343\345\341\377\343\345" "\341\377\343\346\341\377\344\346\341\377\344\346\341\377\343\345\340" "\377\343\345\340\377\343\345\341\377\343\345\341\377\343\346\341\377" "\343\346\341\377\344\346\341\377\344\346\341\377\344\346\341\377\344" "\346\341\377\344\346\341\377\344\346\341\377\344\346\341\377\344\346" "\341\377\344\346\341\377\344\346\341\377\344\346\341\377\343\346\341" "\377\343\346\341\377\343\345\341\377\343\345\341\377\343\345\341\377" "\377\377\377\377\227\231\224\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\233\236" "\230\377\377\377\377\377\343\345\340\377\343\345\340\377\343\346\341" "\377\343\346\341\377\344\346\341\377\344\346\341\377\343\345\341\377" "\343\345\341\377\344\346\341\377\344\346\341\377\344\346\341\377\344" "\346\342\377\344\346\342\377\344\346\342\377\344\346\342\377\344\346" "\342\377\345\346\342\377\345\346\342\377\345\347\342\377\345\347\342" "\377\345\347\342\377\345\347\342\377\345\347\342\377\345\347\342\377" "\345\347\342\377\345\347\342\377\345\346\342\377\345\346\342\377\344" "\346\342\377\344\346\342\377\344\346\342\377\344\346\342\377\377\377" "\377\377\226\231\223\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\233\235\227\377" "\377\377\377\377\343\345\340\377\343\345\340\377\343\345\341\377\343" "\346\341\377\344\346\341\377\344\346\341\377\344\346\342\377\344\346" "\342\377\345\346\342\377\345\347\342\377\345\347\342\377\345\347\343" "\377\345\347\343\377\345\347\343\377\345\347\343\377\346\347\343\377" "\346\347\343\377\346\347\343\377\346\347\343\377\346\347\343\377\346" "\350\343\377\346\350\343\377\346\350\343\377\346\350\343\377\346\347" "\343\377\346\347\343\377\346\347\343\377\346\347\343\377\345\347\343" "\377\345\347\343\377\345\347\343\377\345\347\343\377\377\377\377\377" "\226\230\222\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\232\234\227\377\377\377" "\377\377\343\346\341\377\344\346\341\377\344\346\342\377\344\346\342" "\377\345\346\342\377\345\347\342\377\345\347\343\377\345\347\343\377" "\345\347\343\377\346\347\343\377\346\350\343\377\346\350\344\377\346" "\350\344\377\346\350\344\377\346\350\344\377\346\350\344\377\347\350" "\344\377\347\350\344\377\347\350\344\377\347\350\344\377\347\350\344" "\377\347\350\344\377\347\350\344\377\347\350\344\377\347\350\344\377" "\347\350\344\377\347\350\344\377\346\350\344\377\346\350\344\377\346" "\350\344\377\346\350\344\377\346\350\344\377\377\377\377\377\225\227" "\222\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\231\234\226\377\377\377\377\377" "\344\346\342\377\345\346\342\377\345\347\342\377\345\347\343\377\345" "\347\343\377\346\347\343\377\346\350\344\377\346\350\344\377\346\350" "\344\377\346\350\344\377\347\350\344\377\347\351\345\377\347\351\345" "\377\347\351\345\377\347\351\345\377\347\351\345\377\350\351\345\377" "\350\351\345\377\350\351\346\377\350\351\346\377\350\351\346\377\350" "\351\346\377\350\351\346\377\350\351\346\377\350\351\346\377\350\351" "\346\377\350\351\345\377\347\351\345\377\347\351\345\377\347\351\345" "\377\347\351\345\377\347\351\345\377\377\377\377\377\224\227\221\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\231\233\225\377\377\377\377\377\345\347" "\343\377\345\347\343\377\346\347\343\377\346\350\344\377\346\350\344" "\377\346\350\344\377\347\350\344\377\347\351\345\377\347\351\345\377" "\347\351\345\377\350\351\346\377\350\351\346\377\350\352\346\377\350" "\352\346\377\350\352\346\377\350\352\346\377\351\352\346\377\351\352" "\347\377\351\352\347\377\351\352\347\377\351\352\347\377\351\352\347" "\377\351\352\347\377\351\352\347\377\351\352\347\377\351\352\347\377" "\351\352\346\377\351\352\346\377\350\352\346\377\350\352\346\377\350" "\352\346\377\350\352\346\377\377\377\377\377\224\226\220\377\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\230\232\225\377\377\377\377\377\346\350\344\377" "\346\350\344\377\346\350\344\377\347\350\344\377\347\351\345\377\347" "\351\345\377\350\351\346\377\350\351\346\377\350\352\346\377\350\352" "\346\377\351\352\346\377\351\352\347\377\351\352\347\377\351\352\347" "\377\351\353\347\377\351\353\347\377\351\353\347\377\352\353\350\377" "\352\353\350\377\352\353\350\377\352\353\350\377\352\353\350\377\352" "\353\350\377\352\353\350\377\352\353\350\377\352\353\350\377\352\353" "\350\377\351\353\347\377\351\353\347\377\351\353\347\377\351\352\347" "\377\351\352\347\377\377\377\377\377\223\225\220\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\227\232\224\377\377\377\377\377\347\350\344\377\347\351\345" "\377\347\351\345\377\350\351\345\377\350\351\346\377\350\352\346\377" "\351\352\346\377\351\352\347\377\351\352\347\377\351\353\347\377\351" "\353\347\377\352\353\350\377\352\353\350\377\352\353\350\377\352\353" "\350\377\352\354\350\377\352\354\350\377\353\354\351\377\353\354\351" "\377\353\354\351\377\353\354\351\377\353\354\351\377\353\354\351\377" "\353\354\351\377\353\354\351\377\353\354\351\377\353\354\351\377\352" "\354\350\377\352\354\350\377\352\353\350\377\352\353\350\377\352\353" "\350\377\377\377\377\377\222\224\217\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\227\231\223\377\377\377\377\377\347\351\345\377\350\351\346\377\350" "\352\346\377\350\352\346\377\351\352\347\377\351\352\347\377\351\353" "\347\377\352\353\350\377\352\353\350\377\352\353\350\377\352\354\350" "\377\353\354\351\377\353\354\351\377\353\354\351\377\353\354\351\377" "\353\354\351\377\353\355\352\377\354\355\352\377\354\355\352\377\354" "\355\352\377\354\355\352\377\354\355\352\377\354\355\352\377\354\355" "\352\377\354\355\352\377\354\355\352\377\354\355\352\377\353\355\352" "\377\353\354\351\377\353\354\351\377\353\354\351\377\353\354\351\377" "\377\377\377\377\222\224\216\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\226\230" "\223\377\377\377\377\377\350\352\346\377\350\352\346\377\351\352\347" "\377\351\352\347\377\351\353\347\377\352\353\350\377\352\353\350\377" "\352\354\350\377\353\354\351\377\353\354\351\377\353\354\351\377\354" "\355\352\377\354\355\352\377\354\355\352\377\354\355\352\377\354\355" "\352\377\354\356\353\377\354\356\353\377\355\356\353\377\355\356\353" "\377\355\356\353\377\355\356\353\377\355\356\353\377\355\356\353\377" "\355\356\353\377\355\356\353\377\354\356\353\377\354\355\353\377\354" "\355\352\377\354\355\352\377\354\355\352\377\354\355\352\377\377\377" "\377\377\221\223\216\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\225\230\222\377" "\377\377\377\377\351\352\347\377\351\352\347\377\351\353\347\377\352" "\353\350\377\352\353\350\377\352\354\350\377\353\354\351\377\353\354" "\351\377\354\355\352\377\354\355\352\377\354\355\352\377\354\355\353" "\377\355\356\353\377\355\356\353\377\355\356\353\377\355\356\353\377" "\355\356\354\377\356\356\354\377\356\356\354\377\356\357\354\377\356" "\357\354\377\356\357\354\377\356\357\354\377\356\357\354\377\356\357" "\354\377\356\356\354\377\355\356\354\377\355\356\354\377\355\356\353" "\377\355\356\353\377\355\356\353\377\354\356\353\377\377\377\377\377" "\220\222\215\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\225\227\221\377\377\377" "\377\377\351\353\347\377\352\353\350\377\352\353\350\377\352\354\350" "\377\353\354\351\377\353\354\351\377\354\355\352\377\354\355\352\377" "\354\355\352\377\354\356\353\377\355\356\353\377\355\356\353\377\355" "\356\354\377\356\357\354\377\356\357\354\377\356\357\354\377\356\357" "\355\377\357\357\355\377\357\357\355\377\357\357\355\377\357\360\355" "\377\357\360\355\377\357\360\355\377\357\360\355\377\357\357\355\377" "\357\357\355\377\356\357\355\377\356\357\355\377\356\357\354\377\356" "\357\354\377\356\356\354\377\355\356\354\377\377\377\377\377\220\222" "\215\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\224\226\221\377\377\377\377\377" "\352\353\350\377\352\353\350\377\353\354\351\377\353\354\351\377\353" "\355\352\377\354\355\352\377\354\355\352\377\355\356\353\377\355\356" "\353\377\355\356\354\377\356\356\354\377\356\357\354\377\356\357\355" "\377\357\357\355\377\357\360\355\377\357\360\356\377\357\360\356\377" "\357\360\356\377\360\360\356\377\360\360\356\377\360\360\356\377\360" "\360\356\377\360\360\356\377\360\360\356\377\360\360\356\377\357\360" "\356\377\357\360\356\377\357\360\356\377\357\360\355\377\357\357\355" "\377\356\357\355\377\356\357\354\377\377\377\377\377\217\221\214\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\223\225\220\377\377\377\377\377\352\353" "\350\377\353\354\351\377\353\354\351\377\354\355\352\377\354\355\352" "\377\354\355\353\377\355\356\353\377\355\356\353\377\356\356\354\377" "\356\357\354\377\356\357\355\377\357\357\355\377\357\360\356\377\357" "\360\356\377\360\360\356\377\360\361\356\377\360\361\357\377\360\361" "\357\377\361\361\357\377\361\361\357\377\361\361\357\377\361\361\357" "\377\361\361\357\377\361\361\357\377\361\361\357\377\360\361\357\377" "\360\361\357\377\360\361\357\377\360\360\356\377\357\360\356\377\357" "\360\356\377\357\360\355\377\377\377\377\377\216\220\213\377\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\223\225\217\377\377\377\377\377\353\354\351\377" "\353\354\351\377\354\355\352\377\354\355\352\377\354\355\353\377\355" "\356\353\377\355\356\354\377\356\357\354\377\356\357\354\377\357\357" "\355\377\357\360\355\377\357\360\356\377\360\360\356\377\360\361\357" "\377\360\361\357\377\361\361\357\377\361\362\360\377\361\362\360\377" "\362\362\360\377\362\362\360\377\362\362\360\377\362\362\360\377\362" "\362\360\377\362\362\360\377\362\362\360\377\361\362\360\377\361\362" "\360\377\361\361\357\377\361\361\357\377\360\361\357\377\360\361\356" "\377\357\360\356\377\377\377\377\377\216\220\213\377\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\222\224\217\377\377\377\377\377\353\354\351\377\353\355\352" "\377\354\355\352\377\354\355\352\377\355\356\353\377\355\356\353\377" "\356\357\354\377\356\357\354\377\357\357\355\377\357\360\355\377\357" "\360\356\377\360\361\356\377\360\361\357\377\361\361\357\377\361\362" "\360\377\361\362\360\377\362\362\360\377\362\362\361\377\362\363\361" "\377\363\363\361\377\363\363\362\377\363\363\362\377\363\363\362\377" "\363\363\361\377\362\363\361\377\362\363\361\377\362\362\361\377\362" "\362\360\377\361\362\360\377\361\361\357\377\360\361\357\377\360\361" "\357\377\377\377\377\377\215\217\212\377\377\377\377\0\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\221\223\216\377\377\377\377\377\353\354\351\377\354\355\352\377\354" "\355\352\377\354\356\353\377\355\356\353\377\355\356\354\377\356\357" "\354\377\356\357\355\377\357\360\355\377\357\360\356\377\360\360\356" "\377\360\361\357\377\361\361\357\377\361\362\360\377\362\362\360\377" "\362\362\361\377\362\363\361\377\363\363\362\377\363\363\362\377\363" "\364\362\377\364\364\363\377\364\364\363\377\364\364\363\377\364\364" "\362\377\363\364\362\377\363\363\362\377\363\363\361\377\362\363\361" "\377\362\362\360\377\361\362\360\377\361\362\360\377\360\361\357\377" "\377\377\377\377\214\216\211\377\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\221\223" "\215\377\377\377\377\377\353\354\351\377\354\355\352\377\354\355\352" "\377\355\356\353\377\355\356\353\377\356\356\354\377\356\357\354\377" "\357\357\355\377\357\360\356\377\360\360\356\377\360\361\357\377\361" "\361\357\377\361\362\360\377\362\362\360\377\362\362\361\377\362\363" "\361\377\363\363\362\377\363\364\362\377\364\364\363\377\364\364\363" "\377\365\365\363\377\365\365\364\377\365\365\364\377\364\365\363\377" "\364\364\363\377\364\364\362\377\363\363\362\377\363\363\361\377\362" "\363\361\377\362\362\360\377\361\362\360\377\361\361\357\377\377\377" "\377\377\214\216\211\377\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\220\222\215\377" "\377\377\377\377\353\354\351\377\354\355\352\377\354\355\352\377\355" "\356\353\377\355\356\353\377\356\357\354\377\356\357\354\377\357\357" "\355\377\357\360\356\377\360\360\356\377\360\361\357\377\361\361\357" "\377\361\362\360\377\362\362\360\377\362\362\361\377\362\363\361\377" "\363\363\362\377\363\364\362\377\364\364\363\377\364\365\363\377\365" "\365\364\377\365\365\364\377\365\365\364\377\365\365\364\377\364\364" "\363\377\364\364\363\377\363\363\362\377\363\363\362\377\362\363\361" "\377\362\362\360\377\361\362\360\377\361\361\357\377\377\377\377\377" "\213\215\210\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\217\221\214\377\377\377" "\377\377\353\354\351\377\354\355\352\377\354\355\352\377\355\356\353" "\377\355\356\353\377\356\356\354\377\356\357\354\377\357\357\355\377" "\357\360\355\377\357\360\356\377\360\361\356\377\360\361\357\377\361" "\361\357\377\361\362\360\377\362\362\360\377\362\363\361\377\363\363" "\362\377\363\363\362\377\364\364\362\377\364\364\363\377\364\364\363" "\377\364\364\363\377\364\364\363\377\364\364\363\377\364\364\363\377" "\363\364\362\377\363\363\362\377\362\363\361\377\362\362\361\377\362" "\362\360\377\361\362\360\377\361\361\357\377\377\377\377\377\212\214" "\207\377\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\217\221\213\377\377\377\377\377" "\353\354\351\377\354\355\352\377\354\355\352\377\354\355\353\377\355" "\356\353\377\355\356\354\377\356\357\354\377\356\357\355\377\357\360" "\355\377\357\360\356\377\360\360\356\377\360\361\357\377\361\361\357" "\377\361\362\360\377\361\362\360\377\362\362\360\377\362\363\361\377" "\362\363\361\377\363\363\362\377\363\363\362\377\363\363\362\377\363" "\364\362\377\363\364\362\377\363\363\362\377\363\363\362\377\363\363" "\361\377\362\363\361\377\362\362\361\377\362\362\360\377\361\362\360" "\377\361\361\357\377\360\361\357\377\377\377\377\377\212\214\207\377" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\0\0\0\5\216\220\213\377\377\377\377\377\353\354\351" "\377\353\354\351\377\354\355\352\377\354\355\352\377\355\356\353\377" "\355\356\353\377\355\356\354\377\356\357\354\377\356\357\355\377\357" "\360\355\377\357\360\356\377\360\360\356\377\360\361\357\377\360\361" "\357\377\361\361\357\377\361\362\360\377\361\362\360\377\362\362\360" "\377\362\362\361\377\362\362\361\377\362\363\361\377\362\363\361\377" "\362\363\361\377\362\363\361\377\362\362\361\377\362\362\360\377\362" "\362\360\377\361\362\360\377\361\362\360\377\361\361\357\377\360\361" "\357\377\360\360\356\377\377\377\377\377\211\213\206\377\0\0\0\4\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\0\0\0\10\0\0\0\21" "\215\217\212\377\377\377\377\377\352\354\350\377\353\354\351\377\353" "\354\351\377\354\355\352\377\354\355\352\377\355\356\353\377\355\356" "\353\377\355\356\354\377\356\357\354\377\356\357\355\377\357\357\355" "\377\357\360\355\377\357\360\356\377\360\360\356\377\360\361\357\377" "\360\361\357\377\361\361\357\377\361\361\357\377\361\362\360\377\361" "\362\360\377\361\362\360\377\361\362\360\377\361\362\360\377\361\362" "\360\377\361\362\360\377\361\362\360\377\361\361\357\377\360\361\357" "\377\360\361\357\377\360\361\356\377\357\360\356\377\357\360\356\377" "\377\377\377\377\210\212\205\377\0\0\0\20\0\0\0\7\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\0\0\0\4\0\0\0\17\0\0\0\37\216\220\212\374\376\376\376\377\353" "\354\351\377\352\354\350\377\353\354\351\377\353\354\351\377\354\355" "\352\377\354\355\352\377\354\356\353\377\355\356\353\377\355\356\354" "\377\356\356\354\377\356\357\354\377\356\357\355\377\357\357\355\377" "\357\360\355\377\357\360\356\377\357\360\356\377\360\360\356\377\360" "\361\356\377\360\361\357\377\360\361\357\377\360\361\357\377\360\361" "\357\377\360\361\357\377\360\361\357\377\360\361\357\377\360\361\357" "\377\360\360\356\377\360\360\356\377\357\360\356\377\357\360\356\377" "\357\360\355\377\360\360\356\377\376\376\376\377\212\214\207\374\0\0" "\0\33\0\0\0\16\0\0\0\2\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\0\0\0\6\0\0\0\22\0\0\0*\206\207" "\203\320\335\335\334\376\376\376\376\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" "\377\377\377\377\377\377\377\377\377\377\377\376\376\376\377\334\335" "\332\376\203\205\200\315\0\0\0&\0\0\0\20\0\0\0\4\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\0\0\0" "\4\0\0\0\17\0\0\0\37//,L\205\206\202\327\213\215\210\375\213\215\210" "\377\213\215\210\377\213\215\210\377\212\214\207\377\212\214\207\377" "\212\214\207\377\212\214\207\377\212\214\207\377\212\214\207\377\212" "\214\207\377\211\213\206\377\211\213\206\377\211\213\206\377\211\213" "\206\377\211\213\206\377\211\213\206\377\211\213\206\377\210\212\205" "\377\210\212\205\377\210\212\205\377\210\212\205\377\210\212\205\377" "\210\212\205\377\210\212\205\377\210\212\205\377\210\212\205\377\210" "\212\205\377\210\212\205\377\210\212\205\377\210\212\205\377\210\212" "\205\375\204\205\200\325-1-I\0\0\0\33\0\0\0\16\0\0\0\2\377\377\377\0" "\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377" "\0\377\377\377\0\0\0\0\10\0\0\0\21\0\0\0\32\0\0\0%\0\0\0+\0\0\0""2\0" "\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2" "\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0" "2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0" "\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0""2\0\0\0*\0\0\0$\0\0" "\0\30\0\0\0\20\0\0\0\7\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377" "\377\377\0\0\0\0\5\0\0\0\13\0\0\0\17\0\0\0\20\0\0\0\21\0\0\0\21\0\0\0" "\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0" "\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21" "\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0" "\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\20\0\0\0\16\0\0\0\12\0" "\0\0\4\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377\377\0\377\377" "\377\0\377\377\377\0\377\377\377\0\377\377\377\0"; nemo-3.6.5/libnemo-private/nemo-desktop-directory.h0000664000175000017500000000445613215733314021277 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-desktop-directory.h: Subclass of NemoDirectory to implement a virtual directory consisting of the desktop directory and the desktop icons Copyright (C) 2003 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Alexander Larsson */ #ifndef NEMO_DESKTOP_DIRECTORY_H #define NEMO_DESKTOP_DIRECTORY_H #include #define NEMO_TYPE_DESKTOP_DIRECTORY nemo_desktop_directory_get_type() #define NEMO_DESKTOP_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_DESKTOP_DIRECTORY, NemoDesktopDirectory)) #define NEMO_DESKTOP_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_DESKTOP_DIRECTORY, NemoDesktopDirectoryClass)) #define NEMO_IS_DESKTOP_DIRECTORY(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_DESKTOP_DIRECTORY)) #define NEMO_IS_DESKTOP_DIRECTORY_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_DESKTOP_DIRECTORY)) #define NEMO_DESKTOP_DIRECTORY_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_DESKTOP_DIRECTORY, NemoDesktopDirectoryClass)) typedef struct NemoDesktopDirectoryDetails NemoDesktopDirectoryDetails; typedef struct { NemoDirectory parent_slot; NemoDesktopDirectoryDetails *details; gint display_number; } NemoDesktopDirectory; typedef struct { NemoDirectoryClass parent_slot; } NemoDesktopDirectoryClass; GType nemo_desktop_directory_get_type (void); NemoDirectory * nemo_desktop_directory_get_real_directory (NemoDesktopDirectory *desktop_directory); #endif /* NEMO_DESKTOP_DIRECTORY_H */ nemo-3.6.5/libnemo-private/nemo-file.c0000664000175000017500000066355113215733314016545 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: f; c-basic-offset: 4; tab-width: 4 -*- nemo-file.c: Nemo file model. Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-file.h" #include "nemo-directory-notify.h" #include "nemo-directory-private.h" #include "nemo-signaller.h" #include "nemo-desktop-directory.h" #include "nemo-desktop-directory-file.h" #include "nemo-desktop-icon-file.h" #include "nemo-file-attributes.h" #include "nemo-file-private.h" #include "nemo-file-operations.h" #include "nemo-file-utilities.h" #include "nemo-global-preferences.h" #include "nemo-lib-self-check-functions.h" #include "nemo-link.h" #include "nemo-metadata.h" #include "nemo-module.h" #include "nemo-search-directory.h" #include "nemo-search-directory-file.h" #include "nemo-thumbnails.h" #include "nemo-vfs-file.h" #include "nemo-file-undo-operations.h" #include "nemo-file-undo-manager.h" #include "nemo-saved-search-file.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SELINUX #include #endif #define DEBUG_FLAG NEMO_DEBUG_FILE #include /* Time in seconds to cache getpwuid results */ #define GETPWUID_CACHE_TIME (5*60) #define ICON_NAME_THUMBNAIL_LOADING "image-loading" #undef NEMO_FILE_DEBUG_REF #undef NEMO_FILE_DEBUG_REF_VALGRIND #ifdef NEMO_FILE_DEBUG_REF_VALGRIND #include #define DEBUG_REF_PRINTF VALGRIND_PRINTF_BACKTRACE #else #define DEBUG_REF_PRINTF printf #endif /* Files that start with these characters sort after files that don't. */ #define SORT_LAST_CHAR1 '.' #define SORT_LAST_CHAR2 '#' /* Name of Nemo trash directories */ #define TRASH_DIRECTORY_NAME ".Trash" #define METADATA_ID_IS_LIST_MASK (1<<31) #define MAX_THUMBNAIL_TRIES 2 typedef enum { SHOW_HIDDEN = 1 << 0, } FilterOptions; typedef enum { NEMO_DATE_FORMAT_REGULAR = 0, NEMO_DATE_FORMAT_REGULAR_WITH_TIME = 1, NEMO_DATE_FORMAT_FULL = 2, } NemoDateCompactFormat; typedef void (* ModifyListFunction) (GList **list, NemoFile *file); enum { CHANGED, UPDATED_DEEP_COUNT_IN_PROGRESS, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; static GHashTable *symbolic_links; static GQuark attribute_name_q, attribute_size_q, attribute_type_q, attribute_detailed_type_q, attribute_modification_date_q, attribute_date_modified_q, attribute_date_modified_full_q, attribute_date_modified_with_time_q, attribute_accessed_date_q, attribute_date_accessed_q, attribute_date_accessed_full_q, attribute_mime_type_q, attribute_size_detail_q, attribute_deep_size_q, attribute_deep_file_count_q, attribute_deep_directory_count_q, attribute_deep_total_count_q, attribute_date_changed_q, attribute_date_changed_full_q, attribute_trashed_on_q, attribute_trashed_on_full_q, attribute_trash_orig_path_q, attribute_date_permissions_q, attribute_date_permissions_full_q, attribute_permissions_q, attribute_selinux_context_q, attribute_octal_permissions_q, attribute_owner_q, attribute_group_q, attribute_uri_q, attribute_where_q, attribute_link_target_q, attribute_volume_q, attribute_free_space_q; static void nemo_file_info_iface_init (NemoFileInfoIface *iface); static gboolean update_info_and_name (NemoFile *file, GFileInfo *info); static const char * nemo_file_peek_display_name (NemoFile *file); static const char * nemo_file_peek_display_name_collation_key (NemoFile *file); static void file_mount_unmounted (GMount *mount, gpointer data); static void metadata_hash_free (GHashTable *hash); G_DEFINE_TYPE_WITH_CODE (NemoFile, nemo_file, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (NEMO_TYPE_FILE_INFO, nemo_file_info_iface_init)); static void nemo_file_init (NemoFile *file) { file->details = G_TYPE_INSTANCE_GET_PRIVATE ((file), NEMO_TYPE_FILE, NemoFileDetails); file->details->desktop_monitor = -1; file->details->cached_position_x = -1; file->details->cached_position_y = -1; nemo_file_clear_info (file); nemo_file_invalidate_extension_info_internal (file); file->details->free_space = -1; } static GObject* nemo_file_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; NemoFile *file; object = (* G_OBJECT_CLASS (nemo_file_parent_class)->constructor) (type, n_construct_properties, construct_params); file = NEMO_FILE (object); /* Set to default type after full construction */ if (NEMO_FILE_GET_CLASS (file)->default_file_type != G_FILE_TYPE_UNKNOWN) { file->details->type = NEMO_FILE_GET_CLASS (file)->default_file_type; } return object; } gboolean nemo_file_set_display_name (NemoFile *file, const char *display_name, const char *edit_name, gboolean custom) { gboolean changed; if (custom && display_name == NULL) { /* We're re-setting a custom display name, invalidate it if we already set it so that the old one is re-read */ if (file->details->got_custom_display_name) { file->details->got_custom_display_name = FALSE; nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_INFO); } return FALSE; } if (display_name == NULL || *display_name == 0) { return FALSE; } if (!custom && file->details->got_custom_display_name) { return FALSE; } if (edit_name == NULL) { edit_name = display_name; } changed = FALSE; if (g_strcmp0 (eel_ref_str_peek (file->details->display_name), display_name) != 0) { changed = TRUE; eel_ref_str_unref (file->details->display_name); if (g_strcmp0 (eel_ref_str_peek (file->details->name), display_name) == 0) { file->details->display_name = eel_ref_str_ref (file->details->name); } else { file->details->display_name = eel_ref_str_new (display_name); } g_free (file->details->display_name_collation_key); file->details->display_name_collation_key = g_utf8_collate_key_for_filename (display_name, -1); } if (g_strcmp0 (eel_ref_str_peek (file->details->edit_name), edit_name) != 0) { changed = TRUE; eel_ref_str_unref (file->details->edit_name); if (g_strcmp0 (eel_ref_str_peek (file->details->display_name), edit_name) == 0) { file->details->edit_name = eel_ref_str_ref (file->details->display_name); } else { file->details->edit_name = eel_ref_str_new (edit_name); } } file->details->got_custom_display_name = custom; return changed; } static void nemo_file_clear_display_name (NemoFile *file) { eel_ref_str_unref (file->details->display_name); file->details->display_name = NULL; g_free (file->details->display_name_collation_key); file->details->display_name_collation_key = NULL; eel_ref_str_unref (file->details->edit_name); file->details->edit_name = NULL; } static gboolean foreach_metadata_free (gpointer key, gpointer value, gpointer user_data) { guint id; id = GPOINTER_TO_UINT (key); if (id & METADATA_ID_IS_LIST_MASK) { g_strfreev ((char **)value); } else { g_free ((char *)value); } return TRUE; } static void metadata_hash_free (GHashTable *hash) { g_hash_table_foreach_remove (hash, foreach_metadata_free, NULL); g_hash_table_destroy (hash); } static gboolean metadata_hash_equal (GHashTable *hash1, GHashTable *hash2) { GHashTableIter iter; gpointer key1, value1, value2; guint id; if (hash1 == NULL && hash2 == NULL) { return TRUE; } if (hash1 == NULL || hash2 == NULL) { return FALSE; } if (g_hash_table_size (hash1) != g_hash_table_size (hash2)) { return FALSE; } g_hash_table_iter_init (&iter, hash1); while (g_hash_table_iter_next (&iter, &key1, &value1)) { value2 = g_hash_table_lookup (hash2, key1); if (value2 == NULL) { return FALSE; } id = GPOINTER_TO_UINT (key1); if (id & METADATA_ID_IS_LIST_MASK) { if (!eel_g_strv_equal ((char **)value1, (char **)value2)) { return FALSE; } } else { if (strcmp ((char *)value1, (char *)value2) != 0) { return FALSE; } } } return TRUE; } static void clear_metadata (NemoFile *file) { if (file->details->metadata) { metadata_hash_free (file->details->metadata); file->details->metadata = NULL; } } static GHashTable * get_metadata_from_info (GFileInfo *info) { GHashTable *metadata; char **attrs; guint id; int i; GFileAttributeType type; gpointer value; attrs = g_file_info_list_attributes (info, "metadata"); metadata = g_hash_table_new (NULL, NULL); for (i = 0; attrs[i] != NULL; i++) { id = nemo_metadata_get_id (attrs[i] + strlen ("metadata::")); if (id == 0) { continue; } if (!g_file_info_get_attribute_data (info, attrs[i], &type, &value, NULL)) { continue; } if (type == G_FILE_ATTRIBUTE_TYPE_STRING) { g_hash_table_insert (metadata, GUINT_TO_POINTER (id), g_strdup ((char *)value)); } else if (type == G_FILE_ATTRIBUTE_TYPE_STRINGV) { id |= METADATA_ID_IS_LIST_MASK; g_hash_table_insert (metadata, GUINT_TO_POINTER (id), g_strdupv ((char **)value)); } } g_strfreev (attrs); return metadata; } gboolean nemo_file_update_metadata_from_info (NemoFile *file, GFileInfo *info) { gboolean changed = FALSE; if (g_file_info_has_namespace (info, "metadata")) { GHashTable *metadata; metadata = get_metadata_from_info (info); if (!metadata_hash_equal (metadata, file->details->metadata)) { changed = TRUE; clear_metadata (file); file->details->metadata = metadata; } else { metadata_hash_free (metadata); } } else if (file->details->metadata) { changed = TRUE; clear_metadata (file); } return changed; } void nemo_file_clear_info (NemoFile *file) { file->details->got_file_info = FALSE; if (file->details->get_info_error) { g_error_free (file->details->get_info_error); file->details->get_info_error = NULL; } /* Reset to default type, which might be other than unknown for special kinds of files like the desktop or a search directory */ file->details->type = NEMO_FILE_GET_CLASS (file)->default_file_type; if (!file->details->got_custom_display_name) { nemo_file_clear_display_name (file); } if (!file->details->got_custom_activation_uri && file->details->activation_uri != NULL) { g_free (file->details->activation_uri); file->details->activation_uri = NULL; } if (file->details->icon != NULL) { g_object_unref (file->details->icon); file->details->icon = NULL; } g_free (file->details->thumbnail_path); file->details->thumbnail_path = NULL; file->details->thumbnailing_failed = FALSE; file->details->thumbnail_throttle_count = 1; file->details->last_thumbnail_try_mtime = 0; file->details->is_launcher = FALSE; file->details->is_foreign_link = FALSE; file->details->is_trusted_link = FALSE; file->details->is_symlink = FALSE; file->details->is_hidden = FALSE; file->details->is_mountpoint = FALSE; file->details->uid = -1; file->details->gid = -1; file->details->can_read = TRUE; file->details->can_write = TRUE; file->details->can_execute = TRUE; file->details->can_delete = TRUE; file->details->can_trash = TRUE; file->details->can_rename = TRUE; file->details->can_mount = FALSE; file->details->can_unmount = FALSE; file->details->can_eject = FALSE; file->details->can_start = FALSE; file->details->can_start_degraded = FALSE; file->details->can_stop = FALSE; file->details->start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN; file->details->can_poll_for_media = FALSE; file->details->is_media_check_automatic = FALSE; file->details->has_permissions = FALSE; file->details->permissions = 0; file->details->size = -1; file->details->sort_order = 0; file->details->mtime = 0; file->details->atime = 0; file->details->ctime = 0; file->details->trash_time = 0; g_free (file->details->symlink_name); file->details->symlink_name = NULL; eel_ref_str_unref (file->details->mime_type); file->details->mime_type = NULL; g_free (file->details->selinux_context); file->details->selinux_context = NULL; g_free (file->details->description); file->details->description = NULL; eel_ref_str_unref (file->details->owner); file->details->owner = NULL; eel_ref_str_unref (file->details->owner_real); file->details->owner_real = NULL; eel_ref_str_unref (file->details->group); file->details->group = NULL; eel_ref_str_unref (file->details->filesystem_id); file->details->filesystem_id = NULL; file->details->is_desktop_orphan = FALSE; file->details->desktop_monitor = -1; clear_metadata (file); } static NemoFile * nemo_file_new_from_filename (NemoDirectory *directory, const char *filename, gboolean self_owned) { NemoFile *file; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (filename != NULL); g_assert (filename[0] != '\0'); if (NEMO_IS_DESKTOP_DIRECTORY (directory)) { if (self_owned) { file = NEMO_FILE (g_object_new (NEMO_TYPE_DESKTOP_DIRECTORY_FILE, NULL)); } else { /* This doesn't normally happen, unless the user somehow types in a uri * that references a file like this. (See #349840) */ file = NEMO_FILE (g_object_new (NEMO_TYPE_VFS_FILE, NULL)); } } else if (NEMO_IS_SEARCH_DIRECTORY (directory)) { if (self_owned) { file = NEMO_FILE (g_object_new (NEMO_TYPE_SEARCH_DIRECTORY_FILE, NULL)); } else { /* This doesn't normally happen, unless the user somehow types in a uri * that references a file like this. (See #349840) */ file = NEMO_FILE (g_object_new (NEMO_TYPE_VFS_FILE, NULL)); } } else if (g_str_has_suffix (filename, NEMO_SAVED_SEARCH_EXTENSION)) { file = NEMO_FILE (g_object_new (NEMO_TYPE_SAVED_SEARCH_FILE, NULL)); } else { file = NEMO_FILE (g_object_new (NEMO_TYPE_VFS_FILE, NULL)); } file->details->directory = nemo_directory_ref (directory); file->details->name = eel_ref_str_new (filename); #ifdef NEMO_FILE_DEBUG_REF DEBUG_REF_PRINTF("%10p ref'd", file); #endif return file; } static void modify_link_hash_table (NemoFile *file, ModifyListFunction modify_function) { char *target_uri; gboolean found; gpointer original_key; GList **list_ptr; /* Check if there is a symlink name. If none, we are OK. */ if (file->details->symlink_name == NULL) { return; } /* Create the hash table first time through. */ if (symbolic_links == NULL) { symbolic_links = g_hash_table_new (g_str_hash, g_str_equal); } target_uri = nemo_file_get_symbolic_link_target_uri (file); /* Find the old contents of the hash table. */ found = g_hash_table_lookup_extended (symbolic_links, target_uri, &original_key, (gpointer *)&list_ptr); if (!found) { list_ptr = g_new0 (GList *, 1); original_key = g_strdup (target_uri); g_hash_table_insert (symbolic_links, original_key, list_ptr); } (* modify_function) (list_ptr, file); if (*list_ptr == NULL) { g_hash_table_remove (symbolic_links, target_uri); g_free (list_ptr); g_free (original_key); } g_free (target_uri); } static void symbolic_link_weak_notify (gpointer data, GObject *where_the_object_was) { GList **list = data; /* This really shouldn't happen, but we're seeing some strange things in bug #358172 where the symlink hashtable isn't correctly updated. */ *list = g_list_remove (*list, where_the_object_was); } static void add_to_link_hash_table_list (GList **list, NemoFile *file) { if (g_list_find (*list, file) != NULL) { g_warning ("Adding file to symlink_table multiple times. " "Please add feedback of what you were doing at http://bugzilla.gnome.org/show_bug.cgi?id=358172\n"); return; } g_object_weak_ref (G_OBJECT (file), symbolic_link_weak_notify, list); *list = g_list_prepend (*list, file); } static void add_to_link_hash_table (NemoFile *file) { modify_link_hash_table (file, add_to_link_hash_table_list); } static void remove_from_link_hash_table_list (GList **list, NemoFile *file) { if (g_list_find (*list, file) != NULL) { g_object_weak_unref (G_OBJECT (file), symbolic_link_weak_notify, list); *list = g_list_remove (*list, file); } } static void remove_from_link_hash_table (NemoFile *file) { modify_link_hash_table (file, remove_from_link_hash_table_list); } NemoFile * nemo_file_new_from_info (NemoDirectory *directory, GFileInfo *info) { NemoFile *file; const char *mime_type; g_return_val_if_fail (NEMO_IS_DIRECTORY (directory), NULL); g_return_val_if_fail (info != NULL, NULL); mime_type = g_file_info_get_content_type (info); if (mime_type && strcmp (mime_type, NEMO_SAVED_SEARCH_MIMETYPE) == 0) { g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); file = NEMO_FILE (g_object_new (NEMO_TYPE_SAVED_SEARCH_FILE, NULL)); } else { file = NEMO_FILE (g_object_new (NEMO_TYPE_VFS_FILE, NULL)); } file->details->directory = nemo_directory_ref (directory); update_info_and_name (file, info); #ifdef NEMO_FILE_DEBUG_REF DEBUG_REF_PRINTF("%10p ref'd", file); #endif return file; } static NemoFile * nemo_file_get_internal (GFile *location, gboolean create) { gboolean self_owned; NemoDirectory *directory; NemoFile *file; GFile *parent; char *basename; g_assert (location != NULL); parent = g_file_get_parent (location); self_owned = FALSE; if (parent == NULL) { self_owned = TRUE; parent = g_object_ref (location); } /* Get object that represents the directory. */ directory = nemo_directory_get_internal (parent, create); g_object_unref (parent); /* Get the name for the file. */ if (self_owned && directory != NULL) { basename = nemo_directory_get_name_for_self_as_new_file (directory); } else { basename = g_file_get_basename (location); } /* Check to see if it's a file that's already known. */ if (directory == NULL) { file = NULL; } else if (self_owned) { file = directory->details->as_file; } else { file = nemo_directory_find_file_by_name (directory, basename); } /* Ref or create the file. */ if (file != NULL) { nemo_file_ref (file); } else if (create && directory != NULL) { file = nemo_file_new_from_filename (directory, basename, self_owned); if (self_owned) { g_assert (directory->details->as_file == NULL); directory->details->as_file = file; } else { nemo_directory_add_file (directory, file); } } g_free (basename); nemo_directory_unref (directory); return file; } NemoFile * nemo_file_get (GFile *location) { return nemo_file_get_internal (location, TRUE); } NemoFile * nemo_file_get_existing (GFile *location) { return nemo_file_get_internal (location, FALSE); } NemoFile * nemo_file_get_existing_by_uri (const char *uri) { GFile *location; NemoFile *file; location = g_file_new_for_uri (uri); file = nemo_file_get_internal (location, FALSE); g_object_unref (location); return file; } NemoFile * nemo_file_get_by_uri (const char *uri) { GFile *location; NemoFile *file; location = g_file_new_for_uri (uri); file = nemo_file_get_internal (location, TRUE); g_object_unref (location); return file; } gboolean nemo_file_is_self_owned (NemoFile *file) { return file->details->directory->details->as_file == file; } static void finalize (GObject *object) { NemoDirectory *directory; NemoFile *file; char *uri; file = NEMO_FILE (object); g_assert (file->details->operations_in_progress == NULL); if (file->details->is_thumbnailing) { uri = nemo_file_get_uri (file); nemo_thumbnail_remove_from_queue (uri); g_free (uri); } nemo_async_destroying_file (file); remove_from_link_hash_table (file); directory = file->details->directory; if (nemo_file_is_self_owned (file)) { directory->details->as_file = NULL; } else { if (!file->details->is_gone) { nemo_directory_remove_file (directory, file); } } if (file->details->get_info_error) { g_error_free (file->details->get_info_error); } nemo_directory_unref (directory); eel_ref_str_unref (file->details->name); eel_ref_str_unref (file->details->display_name); g_free (file->details->display_name_collation_key); eel_ref_str_unref (file->details->edit_name); if (file->details->icon) { g_object_unref (file->details->icon); } g_free (file->details->thumbnail_path); g_free (file->details->symlink_name); eel_ref_str_unref (file->details->mime_type); eel_ref_str_unref (file->details->owner); eel_ref_str_unref (file->details->owner_real); eel_ref_str_unref (file->details->group); g_free (file->details->selinux_context); g_free (file->details->description); g_free (file->details->activation_uri); g_clear_object (&file->details->custom_icon); if (file->details->thumbnail) { g_object_unref (file->details->thumbnail); } if (file->details->scaled_thumbnail) { g_object_unref (file->details->scaled_thumbnail); } if (file->details->mount) { g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file); g_object_unref (file->details->mount); } eel_ref_str_unref (file->details->filesystem_id); g_free (file->details->trash_orig_path); g_list_free_full (file->details->mime_list, g_free); g_list_free_full (file->details->pending_extension_emblems, g_free); g_list_free_full (file->details->extension_emblems, g_free); g_list_free_full (file->details->pending_info_providers, g_object_unref); if (file->details->pending_extension_attributes) { g_hash_table_destroy (file->details->pending_extension_attributes); } if (file->details->extension_attributes) { g_hash_table_destroy (file->details->extension_attributes); } if (file->details->metadata) { metadata_hash_free (file->details->metadata); } G_OBJECT_CLASS (nemo_file_parent_class)->finalize (object); } NemoFile * nemo_file_ref (NemoFile *file) { if (file == NULL) { return NULL; } g_return_val_if_fail (NEMO_IS_FILE (file), NULL); #ifdef NEMO_FILE_DEBUG_REF DEBUG_REF_PRINTF("%10p ref'd", file); #endif return g_object_ref (file); } void nemo_file_unref (NemoFile *file) { if (file == NULL) { return; } g_return_if_fail (NEMO_IS_FILE (file)); #ifdef NEMO_FILE_DEBUG_REF DEBUG_REF_PRINTF("%10p unref'd", file); #endif g_object_unref (file); } /** * nemo_file_get_parent_uri_for_display: * * Get the uri for the parent directory. * * @file: The file in question. * * Return value: A string representing the parent's location, * formatted for user display (including stripping "file://"). * If the parent is NULL, returns the empty string. */ char * nemo_file_get_parent_uri_for_display (NemoFile *file) { GFile *parent; char *result; g_assert (NEMO_IS_FILE (file)); parent = nemo_file_get_parent_location (file); if (parent) { result = g_file_get_parse_name (parent); g_object_unref (parent); } else { result = g_strdup (""); } return result; } /** * nemo_file_get_parent_uri: * * Get the uri for the parent directory. * * @file: The file in question. * * Return value: A string for the parent's location, in "raw URI" form. * Use nemo_file_get_parent_uri_for_display instead if the * result is to be displayed on-screen. * If the parent is NULL, returns the empty string. */ char * nemo_file_get_parent_uri (NemoFile *file) { g_assert (NEMO_IS_FILE (file)); if (nemo_file_is_self_owned (file)) { /* Callers expect an empty string, not a NULL. */ return g_strdup (""); } return nemo_directory_get_uri (file->details->directory); } GFile * nemo_file_get_parent_location (NemoFile *file) { g_assert (NEMO_IS_FILE (file)); if (nemo_file_is_self_owned (file)) { /* Callers expect an empty string, not a NULL. */ return NULL; } return nemo_directory_get_location (file->details->directory); } NemoFile * nemo_file_get_parent (NemoFile *file) { g_assert (NEMO_IS_FILE (file)); if (nemo_file_is_self_owned (file)) { return NULL; } return nemo_directory_get_corresponding_file (file->details->directory); } /** * nemo_file_can_read: * * Check whether the user is allowed to read the contents of this file. * * @file: The file to check. * * Return value: FALSE if the user is definitely not allowed to read * the contents of the file. If the user has read permission, or * the code can't tell whether the user has read permission, * returns TRUE (so failures must always be handled). */ gboolean nemo_file_can_read (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->can_read; } /** * nemo_file_can_write: * * Check whether the user is allowed to write to this file. * * @file: The file to check. * * Return value: FALSE if the user is definitely not allowed to write * to the file. If the user has write permission, or * the code can't tell whether the user has write permission, * returns TRUE (so failures must always be handled). */ gboolean nemo_file_can_write (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->can_write; } /** * nemo_file_can_execute: * * Check whether the user is allowed to execute this file. * * @file: The file to check. * * Return value: FALSE if the user is definitely not allowed to execute * the file. If the user has execute permission, or * the code can't tell whether the user has execute permission, * returns TRUE (so failures must always be handled). */ gboolean nemo_file_can_execute (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->can_execute; } gboolean nemo_file_can_mount (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->can_mount; } gboolean nemo_file_can_unmount (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); if (getenv("LTSP_CLIENT")) { return FALSE; } return file->details->can_unmount || (file->details->mount != NULL && g_mount_can_unmount (file->details->mount)); } gboolean nemo_file_can_eject (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); if (getenv("LTSP_CLIENT")) { return FALSE; } return file->details->can_eject || (file->details->mount != NULL && g_mount_can_eject (file->details->mount)); } gboolean nemo_file_can_start (NemoFile *file) { gboolean ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = FALSE; if (file->details->can_start) { ret = TRUE; goto out; } if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_can_start (drive); g_object_unref (drive); } } out: return ret; } gboolean nemo_file_can_start_degraded (NemoFile *file) { gboolean ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = FALSE; if (file->details->can_start_degraded) { ret = TRUE; goto out; } if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_can_start_degraded (drive); g_object_unref (drive); } } out: return ret; } gboolean nemo_file_can_poll_for_media (NemoFile *file) { gboolean ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = FALSE; if (file->details->can_poll_for_media) { ret = TRUE; goto out; } if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_can_poll_for_media (drive); g_object_unref (drive); } } out: return ret; } gboolean nemo_file_is_media_check_automatic (NemoFile *file) { gboolean ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = FALSE; if (file->details->is_media_check_automatic) { ret = TRUE; goto out; } if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_is_media_check_automatic (drive); g_object_unref (drive); } } out: return ret; } gboolean nemo_file_can_stop (NemoFile *file) { gboolean ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = FALSE; if (file->details->can_stop) { ret = TRUE; goto out; } if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_can_stop (drive); g_object_unref (drive); } } out: return ret; } GDriveStartStopType nemo_file_get_start_stop_type (NemoFile *file) { GDriveStartStopType ret; GDrive *drive; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); ret = file->details->start_stop_type; if (ret != G_DRIVE_START_STOP_TYPE_UNKNOWN) goto out; if (file->details->mount != NULL) { drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { ret = g_drive_get_start_stop_type (drive); g_object_unref (drive); } } out: return ret; } void nemo_file_mount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; if (NEMO_FILE_GET_CLASS (file)->mount == NULL) { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be mounted")); callback (file, NULL, error, callback_data); g_error_free (error); } } else { NEMO_FILE_GET_CLASS (file)->mount (file, mount_op, cancellable, callback, callback_data); } } typedef struct { NemoFile *file; NemoFileOperationCallback callback; gpointer callback_data; } UnmountData; static void unmount_done (void *callback_data) { UnmountData *data; data = (UnmountData *)callback_data; if (data->callback) { data->callback (data->file, NULL, NULL, data->callback_data); } nemo_file_unref (data->file); g_free (data); } void nemo_file_unmount (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; UnmountData *data; if (file->details->can_unmount) { if (NEMO_FILE_GET_CLASS (file)->unmount != NULL) { NEMO_FILE_GET_CLASS (file)->unmount (file, mount_op, cancellable, callback, callback_data); } else { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be unmounted")); callback (file, NULL, error, callback_data); g_error_free (error); } } } else if (file->details->mount != NULL && g_mount_can_unmount (file->details->mount)) { data = g_new0 (UnmountData, 1); data->file = nemo_file_ref (file); data->callback = callback; data->callback_data = callback_data; nemo_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, FALSE, TRUE, unmount_done, data); } else if (callback) { callback (file, NULL, NULL, callback_data); } } void nemo_file_eject (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; UnmountData *data; if (file->details->can_eject) { if (NEMO_FILE_GET_CLASS (file)->eject != NULL) { NEMO_FILE_GET_CLASS (file)->eject (file, mount_op, cancellable, callback, callback_data); } else { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be ejected")); callback (file, NULL, error, callback_data); g_error_free (error); } } } else if (file->details->mount != NULL && g_mount_can_eject (file->details->mount)) { data = g_new0 (UnmountData, 1); data->file = nemo_file_ref (file); data->callback = callback; data->callback_data = callback_data; nemo_file_operations_unmount_mount_full (NULL, file->details->mount, NULL, TRUE, TRUE, unmount_done, data); } else if (callback) { callback (file, NULL, NULL, callback_data); } } void nemo_file_start (NemoFile *file, GMountOperation *start_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; if ((file->details->can_start || file->details->can_start_degraded) && NEMO_FILE_GET_CLASS (file)->start != NULL) { NEMO_FILE_GET_CLASS (file)->start (file, start_op, cancellable, callback, callback_data); } else { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be started")); callback (file, NULL, error, callback_data); g_error_free (error); } } } static void file_stop_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; gboolean stopped; GError *error; op = callback_data; error = NULL; stopped = g_drive_stop_finish (G_DRIVE (source_object), res, &error); if (!stopped && error->domain == G_IO_ERROR && (error->code == G_IO_ERROR_FAILED_HANDLED || error->code == G_IO_ERROR_CANCELLED)) { g_error_free (error); error = NULL; } nemo_file_operation_complete (op, NULL, error); if (error) { g_error_free (error); } } void nemo_file_stop (NemoFile *file, GMountOperation *mount_op, GCancellable *cancellable, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; if (NEMO_FILE_GET_CLASS (file)->stop != NULL) { if (file->details->can_stop) { NEMO_FILE_GET_CLASS (file)->stop (file, mount_op, cancellable, callback, callback_data); } else { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be stopped")); callback (file, NULL, error, callback_data); g_error_free (error); } } } else { GDrive *drive; drive = NULL; if (file->details->mount != NULL) drive = g_mount_get_drive (file->details->mount); if (drive != NULL && g_drive_can_stop (drive)) { NemoFileOperation *op; op = nemo_file_operation_new (file, callback, callback_data); if (cancellable) { g_object_unref (op->cancellable); op->cancellable = g_object_ref (cancellable); } g_drive_stop (drive, G_MOUNT_UNMOUNT_NONE, mount_op, op->cancellable, file_stop_callback, op); } else { if (callback) { error = NULL; g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("This file cannot be stopped")); callback (file, NULL, error, callback_data); g_error_free (error); } } if (drive != NULL) { g_object_unref (drive); } } } void nemo_file_poll_for_media (NemoFile *file) { if (file->details->can_poll_for_media) { if (NEMO_FILE_GET_CLASS (file)->stop != NULL) { NEMO_FILE_GET_CLASS (file)->poll_for_media (file); } } else if (file->details->mount != NULL) { GDrive *drive; drive = g_mount_get_drive (file->details->mount); if (drive != NULL) { g_drive_poll_for_media (drive, NULL, /* cancellable */ NULL, /* GAsyncReadyCallback */ NULL); /* user_data */ g_object_unref (drive); } } } /** * nemo_file_is_desktop_directory: * * Check whether this file is the desktop directory. * * @file: The file to check. * * Return value: TRUE if this is the physical desktop directory. */ gboolean nemo_file_is_desktop_directory (NemoFile *file) { GFile *dir; dir = file->details->directory->details->location; if (dir == NULL) { return FALSE; } return nemo_is_desktop_directory_file (dir, eel_ref_str_peek (file->details->name)); } static gboolean is_desktop_file (NemoFile *file) { return nemo_file_is_mime_type (file, "application/x-desktop"); } static gboolean can_rename_desktop_file (NemoFile *file) { GFile *location; gboolean res; location = nemo_file_get_location (file); res = g_file_is_native (location); g_object_unref (location); return res; } /** * nemo_file_can_rename: * * Check whether the user is allowed to change the name of the file. * * @file: The file to check. * * Return value: FALSE if the user is definitely not allowed to change * the name of the file. If the user is allowed to change the name, or * the code can't tell whether the user is allowed to change the name, * returns TRUE (so rename failures must always be handled). */ gboolean nemo_file_can_rename (NemoFile *file) { gboolean can_rename; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); /* Nonexistent files can't be renamed. */ if (nemo_file_is_gone (file)) { return FALSE; } /* Self-owned files can't be renamed */ if (nemo_file_is_self_owned (file)) { return FALSE; } if ((is_desktop_file (file) && !can_rename_desktop_file (file)) || nemo_file_is_home (file)) { return FALSE; } can_rename = TRUE; /* Certain types of links can't be renamed */ if (NEMO_IS_DESKTOP_ICON_FILE (file)) { NemoDesktopLink *link; link = nemo_desktop_icon_file_get_link (NEMO_DESKTOP_ICON_FILE (file)); if (link != NULL) { can_rename = nemo_desktop_link_can_rename (link); g_object_unref (link); } } if (!can_rename) { return FALSE; } return file->details->can_rename; } gboolean nemo_file_can_delete (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); /* Nonexistent files can't be deleted. */ if (nemo_file_is_gone (file)) { return FALSE; } /* Self-owned files can't be deleted */ if (nemo_file_is_self_owned (file)) { return FALSE; } return file->details->can_delete; } gboolean nemo_file_can_trash (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); /* Nonexistent files can't be deleted. */ if (nemo_file_is_gone (file)) { return FALSE; } /* Self-owned files can't be deleted */ if (nemo_file_is_self_owned (file)) { return FALSE; } return file->details->can_trash; } GFile * nemo_file_get_location (NemoFile *file) { GFile *dir; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); dir = file->details->directory->details->location; if (nemo_file_is_self_owned (file)) { return g_object_ref (dir); } return g_file_get_child (dir, eel_ref_str_peek (file->details->name)); } /* Return the actual uri associated with the passed-in file. */ char * nemo_file_get_uri (NemoFile *file) { char *uri; GFile *loc; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); loc = nemo_file_get_location (file); uri = g_file_get_uri (loc); g_object_unref (loc); return uri; } /* Return the actual path associated with the passed-in file. */ char * nemo_file_get_path (NemoFile *file) { char *path; GFile *loc; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); loc = nemo_file_get_location (file); path = g_file_get_path (loc); g_object_unref (loc); return path; } char * nemo_file_get_uri_scheme (NemoFile *file) { GFile *loc; char *scheme; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (file->details->directory == NULL || file->details->directory->details->location == NULL) { return NULL; } loc = nemo_directory_get_location (file->details->directory); scheme = g_file_get_uri_scheme (loc); g_object_unref (loc); return scheme; } NemoFileOperation * nemo_file_operation_new (NemoFile *file, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; op = g_new0 (NemoFileOperation, 1); op->file = nemo_file_ref (file); op->callback = callback; op->callback_data = callback_data; op->cancellable = g_cancellable_new (); op->file->details->operations_in_progress = g_list_prepend (op->file->details->operations_in_progress, op); return op; } static void nemo_file_operation_remove (NemoFileOperation *op) { op->file->details->operations_in_progress = g_list_remove (op->file->details->operations_in_progress, op); } void nemo_file_operation_free (NemoFileOperation *op) { nemo_file_operation_remove (op); nemo_file_unref (op->file); g_object_unref (op->cancellable); if (op->free_data) { op->free_data (op->data); } if (op->undo_info != NULL) { nemo_file_undo_manager_set_action (op->undo_info); } g_free (op); } void nemo_file_operation_complete (NemoFileOperation *op, GFile *result_file, GError *error) { /* Claim that something changed even if the operation failed. * This makes it easier for some clients who see the "reverting" * as "changing back". */ nemo_file_operation_remove (op); nemo_file_changed (op->file); if (op->callback) { (* op->callback) (op->file, result_file, error, op->callback_data); } nemo_file_operation_free (op); } void nemo_file_operation_cancel (NemoFileOperation *op) { /* Cancel the operation if it's still in progress. */ g_cancellable_cancel (op->cancellable); } static void rename_get_info_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; NemoDirectory *directory; NemoFile *existing_file; char *old_name; char *old_uri; char *new_uri; const char *new_name; GFileInfo *new_info; GError *error; op = callback_data; error = NULL; new_info = g_file_query_info_finish (G_FILE (source_object), res, &error); if (new_info != NULL) { directory = op->file->details->directory; new_name = g_file_info_get_name (new_info); /* If there was another file by the same name in this * directory and it is not the same file that we are * renaming, mark it gone. */ existing_file = nemo_directory_find_file_by_name (directory, new_name); if (existing_file != NULL && existing_file != op->file) { nemo_file_mark_gone (existing_file); nemo_file_changed (existing_file); } old_uri = nemo_file_get_uri (op->file); old_name = g_strdup (eel_ref_str_peek (op->file->details->name)); update_info_and_name (op->file, new_info); g_free (old_name); new_uri = nemo_file_get_uri (op->file); nemo_directory_moved (old_uri, new_uri); g_free (new_uri); g_free (old_uri); /* the rename could have affected the display name if e.g. * we're in a vfolder where the name comes from a desktop file * and a rename affects the contents of the desktop file. */ if (op->file->details->got_custom_display_name) { nemo_file_invalidate_attributes (op->file, NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_LINK_INFO); } g_object_unref (new_info); } nemo_file_operation_complete (op, NULL, error); if (error) { g_error_free (error); } } static void rename_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; GFile *new_file; GError *error; op = callback_data; error = NULL; new_file = g_file_set_display_name_finish (G_FILE (source_object), res, &error); if (new_file != NULL) { if (op->undo_info != NULL) { nemo_file_undo_info_rename_set_data_post (NEMO_FILE_UNDO_INFO_RENAME (op->undo_info), new_file); } g_file_query_info_async (new_file, NEMO_FILE_DEFAULT_ATTRIBUTES, 0, G_PRIORITY_DEFAULT, op->cancellable, rename_get_info_callback, op); } else { nemo_file_operation_complete (op, NULL, error); g_error_free (error); } } static gboolean name_is (NemoFile *file, const char *new_name) { const char *old_name; old_name = eel_ref_str_peek (file->details->name); return strcmp (new_name, old_name) == 0; } void nemo_file_rename (NemoFile *file, const char *new_name, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; char *uri; char *old_name; char *new_file_name; gboolean success, name_changed; gboolean is_renameable_desktop_file; GFile *location; GError *error; g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (new_name != NULL); g_return_if_fail (callback != NULL); is_renameable_desktop_file = is_desktop_file (file) && can_rename_desktop_file (file); /* Return an error for incoming names containing path separators. * But not for .desktop files as '/' are allowed for them */ if (strstr (new_name, "/") != NULL && !is_renameable_desktop_file) { error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Slashes are not allowed in filenames")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* Can't rename a file that's already gone. * We need to check this here because there may be a new * file with the same name. */ if (nemo_file_is_gone (file)) { /* Claim that something changed even if the rename * failed. This makes it easier for some clients who * see the "reverting" to the old name as "changing * back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File not found")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* Test the name-hasn't-changed case explicitly, for two reasons. * (1) rename returns an error if new & old are same. * (2) We don't want to send file-changed signal if nothing changed. */ if (!NEMO_IS_DESKTOP_ICON_FILE (file) && !is_renameable_desktop_file && name_is (file, new_name)) { (* callback) (file, NULL, NULL, callback_data); return; } /* Self-owned files can't be renamed. Test the name-not-actually-changing * case before this case. */ if (nemo_file_is_self_owned (file)) { /* Claim that something changed even if the rename * failed. This makes it easier for some clients who * see the "reverting" to the old name as "changing * back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Toplevel files cannot be renamed")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } if (NEMO_IS_DESKTOP_ICON_FILE (file)) { NemoDesktopLink *link; link = nemo_desktop_icon_file_get_link (NEMO_DESKTOP_ICON_FILE (file)); old_name = nemo_file_get_display_name (file); if ((old_name != NULL && strcmp (new_name, old_name) == 0)) { success = TRUE; } else { success = (link != NULL && nemo_desktop_link_rename (link, new_name)); } if (success) { (* callback) (file, NULL, NULL, callback_data); } else { error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, _("Unable to rename desktop icon")); (* callback) (file, NULL, error, callback_data); g_error_free (error); } g_free (old_name); g_object_unref (link); return; } if (is_renameable_desktop_file) { /* Don't actually change the name if the new name is the same. * This helps for the vfolder method where this can happen and * we want to minimize actual changes */ uri = nemo_file_get_uri (file); old_name = nemo_link_local_get_text (uri); if (old_name != NULL && strcmp (new_name, old_name) == 0) { success = TRUE; name_changed = FALSE; } else { success = nemo_link_local_set_text (uri, new_name); name_changed = TRUE; } g_free (old_name); g_free (uri); if (!success) { error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, _("Unable to rename desktop file")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } if (g_str_has_suffix (new_name, ".desktop")) { new_file_name = g_strdup (new_name); } else { new_file_name = g_strdup_printf ("%s.desktop", new_name); } new_file_name = g_strdelimit (new_file_name, "/", '-'); if (name_is (file, new_file_name)) { if (name_changed) { nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_LINK_INFO); } (* callback) (file, NULL, NULL, callback_data); g_free (new_file_name); return; } } else { new_file_name = g_strdup (new_name); } /* Set up a renaming operation. */ op = nemo_file_operation_new (file, callback, callback_data); op->is_rename = TRUE; location = nemo_file_get_location (file); /* Tell the undo manager a rename is taking place */ if (!nemo_file_undo_manager_pop_flag ()) { op->undo_info = nemo_file_undo_info_rename_new (); old_name = nemo_file_get_display_name (file); nemo_file_undo_info_rename_set_data_pre (NEMO_FILE_UNDO_INFO_RENAME (op->undo_info), location, old_name, new_file_name); g_free (old_name); } /* Do the renaming. */ g_file_set_display_name_async (location, new_file_name, G_PRIORITY_DEFAULT, op->cancellable, rename_callback, op); g_free (new_file_name); g_object_unref (location); } gboolean nemo_file_rename_in_progress (NemoFile *file) { GList *node; NemoFileOperation *op; for (node = file->details->operations_in_progress; node != NULL; node = node->next) { op = node->data; if (op->is_rename) { return TRUE; } } return FALSE; } void nemo_file_cancel (NemoFile *file, NemoFileOperationCallback callback, gpointer callback_data) { GList *node, *next; NemoFileOperation *op; for (node = file->details->operations_in_progress; node != NULL; node = next) { next = node->next; op = node->data; g_assert (op->file == file); if (op->callback == callback && op->callback_data == callback_data) { nemo_file_operation_cancel (op); } } } gboolean nemo_file_matches_uri (NemoFile *file, const char *match_uri) { GFile *match_file, *location; gboolean result; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); g_return_val_if_fail (match_uri != NULL, FALSE); location = nemo_file_get_location (file); match_file = g_file_new_for_uri (match_uri); result = g_file_equal (location, match_file); g_object_unref (location); g_object_unref (match_file); return result; } int nemo_file_compare_location (NemoFile *file_1, NemoFile *file_2) { GFile *loc_a, *loc_b; gboolean res; loc_a = nemo_file_get_location (file_1); loc_b = nemo_file_get_location (file_2); res = !g_file_equal (loc_a, loc_b); g_object_unref (loc_a); g_object_unref (loc_b); return (gint) res; } gboolean nemo_file_is_local (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return nemo_directory_is_local (file->details->directory); } static void update_link (NemoFile *link_file, NemoFile *target_file) { g_assert (NEMO_IS_FILE (link_file)); g_assert (NEMO_IS_FILE (target_file)); /* FIXME bugzilla.gnome.org 42044: If we don't put any code * here then the hash table is a waste of time. */ } static GList * get_link_files (NemoFile *target_file) { char *uri; GList **link_files; if (symbolic_links == NULL) { link_files = NULL; } else { uri = nemo_file_get_uri (target_file); link_files = g_hash_table_lookup (symbolic_links, uri); g_free (uri); } if (link_files) { return nemo_file_list_copy (*link_files); } return NULL; } static void update_links_if_target (NemoFile *target_file) { GList *link_files, *p; link_files = get_link_files (target_file); for (p = link_files; p != NULL; p = p->next) { update_link (NEMO_FILE (p->data), target_file); } nemo_file_list_free (link_files); } static guint64 cached_thumbnail_limit; int cached_thumbnail_size; static int show_image_thumbs; static gboolean access_ok (const gchar *path) { if (g_access (path, R_OK|W_OK) != 0) { if (errno != ENOENT && errno != EFAULT) { return FALSE; } } return TRUE; } static gboolean update_info_internal (NemoFile *file, GFileInfo *info, gboolean update_name) { GList *node; gboolean changed; gboolean is_symlink, is_hidden, is_mountpoint; gboolean has_permissions; guint32 permissions; gboolean can_read, can_write, can_execute, can_delete, can_trash, can_rename, can_mount, can_unmount, can_eject; gboolean can_start, can_start_degraded, can_stop, can_poll_for_media, is_media_check_automatic; GDriveStartStopType start_stop_type; gboolean thumbnailing_failed; int uid, gid; goffset size; int sort_order; time_t atime, mtime, ctime; time_t trash_time; GTimeVal g_trash_time; const char * time_string; const char *symlink_name, *mime_type, *selinux_context, *name, *thumbnail_path; GFileType file_type; GIcon *icon; char *old_activation_uri; const char *activation_uri; const char *description; const char *filesystem_id; const char *trash_orig_path; const char *group, *owner, *owner_real; gboolean free_owner, free_group; if (file->details->is_gone) { return FALSE; } if (info == NULL) { nemo_file_mark_gone (file); return TRUE; } file->details->file_info_is_up_to_date = TRUE; file->details->thumbnail_access_problem = FALSE; /* FIXME bugzilla.gnome.org 42044: Need to let links that * point to the old name know that the file has been renamed. */ remove_from_link_hash_table (file); changed = FALSE; if (!file->details->got_file_info) { changed = TRUE; } file->details->got_file_info = TRUE; changed |= nemo_file_set_display_name (file, g_file_info_get_display_name (info), g_file_info_get_edit_name (info), FALSE); file_type = g_file_info_get_file_type (info); if (file->details->type != file_type) { changed = TRUE; } file->details->type = file_type; if (!file->details->got_custom_activation_uri) { activation_uri = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI); if (activation_uri == NULL) { if (file->details->activation_uri) { g_free (file->details->activation_uri); file->details->activation_uri = NULL; changed = TRUE; } } else { old_activation_uri = file->details->activation_uri; file->details->activation_uri = g_strdup (activation_uri); if (old_activation_uri) { if (strcmp (old_activation_uri, file->details->activation_uri) != 0) { changed = TRUE; } g_free (old_activation_uri); } else { changed = TRUE; } } } is_symlink = g_file_info_get_is_symlink (info); if (file->details->is_symlink != is_symlink) { changed = TRUE; } file->details->is_symlink = is_symlink; is_hidden = g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info); if (file->details->is_hidden != is_hidden) { changed = TRUE; } file->details->is_hidden = is_hidden; is_mountpoint = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT); if (file->details->is_mountpoint != is_mountpoint) { changed = TRUE; } file->details->is_mountpoint = is_mountpoint; has_permissions = g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_MODE); permissions = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE);; if (file->details->has_permissions != has_permissions || file->details->permissions != permissions) { changed = TRUE; } file->details->has_permissions = has_permissions; file->details->permissions = permissions; /* We default to TRUE for this if we can't know */ can_read = TRUE; can_write = TRUE; can_execute = TRUE; can_delete = TRUE; can_trash = TRUE; can_rename = TRUE; can_mount = FALSE; can_unmount = FALSE; can_eject = FALSE; can_start = FALSE; can_start_degraded = FALSE; can_stop = FALSE; can_poll_for_media = FALSE; is_media_check_automatic = FALSE; start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN; if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { can_read = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) { can_write = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) { can_execute = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE)) { can_delete = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) { can_trash = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME)) { can_rename = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT)) { can_mount = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT)) { can_unmount = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT)) { can_eject = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START)) { can_start = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED)) { can_start_degraded = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_START_DEGRADED); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP)) { can_stop = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_STOP); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE)) { start_stop_type = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_MOUNTABLE_START_STOP_TYPE); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL)) { can_poll_for_media = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_POLL); } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC)) { is_media_check_automatic = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_MOUNTABLE_IS_MEDIA_CHECK_AUTOMATIC); } if (file->details->can_read != can_read || file->details->can_write != can_write || file->details->can_execute != can_execute || file->details->can_delete != can_delete || file->details->can_trash != can_trash || file->details->can_rename != can_rename || file->details->can_mount != can_mount || file->details->can_unmount != can_unmount || file->details->can_eject != can_eject || file->details->can_start != can_start || file->details->can_start_degraded != can_start_degraded || file->details->can_stop != can_stop || file->details->start_stop_type != start_stop_type || file->details->can_poll_for_media != can_poll_for_media || file->details->is_media_check_automatic != is_media_check_automatic) { changed = TRUE; } file->details->can_read = can_read; file->details->can_write = can_write; file->details->can_execute = can_execute; file->details->can_delete = can_delete; file->details->can_trash = can_trash; file->details->can_rename = can_rename; file->details->can_mount = can_mount; file->details->can_unmount = can_unmount; file->details->can_eject = can_eject; file->details->can_start = can_start; file->details->can_start_degraded = can_start_degraded; file->details->can_stop = can_stop; file->details->start_stop_type = start_stop_type; file->details->can_poll_for_media = can_poll_for_media; file->details->is_media_check_automatic = is_media_check_automatic; free_owner = FALSE; owner = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER); owner_real = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL); free_group = FALSE; group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP); uid = -1; gid = -1; if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_UID)) { uid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID); if (owner == NULL) { free_owner = TRUE; owner = g_strdup_printf ("%d", uid); } } if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_GID)) { gid = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID); if (group == NULL) { free_group = TRUE; group = g_strdup_printf ("%d", gid); } } if (file->details->uid != uid || file->details->gid != gid) { changed = TRUE; } file->details->uid = uid; file->details->gid = gid; if (g_strcmp0 (eel_ref_str_peek (file->details->owner), owner) != 0) { changed = TRUE; eel_ref_str_unref (file->details->owner); file->details->owner = eel_ref_str_get_unique (owner); } if (g_strcmp0 (eel_ref_str_peek (file->details->owner_real), owner_real) != 0) { changed = TRUE; eel_ref_str_unref (file->details->owner_real); file->details->owner_real = eel_ref_str_get_unique (owner_real); } if (g_strcmp0 (eel_ref_str_peek (file->details->group), group) != 0) { changed = TRUE; eel_ref_str_unref (file->details->group); file->details->group = eel_ref_str_get_unique (group); } if (free_owner) { g_free ((char *)owner); } if (free_group) { g_free ((char *)group); } size = -1; if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE)) { size = g_file_info_get_size (info); } if (file->details->size != size) { changed = TRUE; } file->details->size = size; sort_order = g_file_info_get_sort_order (info); if (file->details->sort_order != sort_order) { changed = TRUE; } file->details->sort_order = sort_order; atime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS); ctime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED); mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); if (file->details->atime != atime || file->details->mtime != mtime || file->details->ctime != ctime) { if (file->details->thumbnail == NULL) { file->details->thumbnail_is_up_to_date = FALSE; } changed = TRUE; } file->details->atime = atime; file->details->ctime = ctime; file->details->mtime = mtime; if (file->details->thumbnail != NULL && file->details->thumbnail_mtime != 0 && file->details->thumbnail_mtime != mtime) { file->details->thumbnail_is_up_to_date = FALSE; changed = TRUE; } icon = g_file_info_get_icon (info); if (!g_icon_equal (icon, file->details->icon)) { changed = TRUE; if (file->details->icon) { g_object_unref (file->details->icon); } file->details->icon = g_object_ref (icon); } thumbnail_path = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH); if (g_strcmp0 (file->details->thumbnail_path, thumbnail_path) != 0) { changed = TRUE; g_free (file->details->thumbnail_path); if (show_image_thumbs != NEMO_SPEED_TRADEOFF_NEVER && thumbnail_path != NULL && !access_ok (thumbnail_path)) { file->details->thumbnail_access_problem = TRUE; file->details->thumbnail_path = NULL; } else { file->details->thumbnail_path = g_strdup (thumbnail_path); } } thumbnailing_failed = g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED); if (file->details->thumbnailing_failed != thumbnailing_failed) { changed = TRUE; file->details->thumbnailing_failed = thumbnailing_failed; } symlink_name = g_file_info_get_symlink_target (info); if (g_strcmp0 (file->details->symlink_name, symlink_name) != 0) { changed = TRUE; g_free (file->details->symlink_name); file->details->symlink_name = g_strdup (symlink_name); } mime_type = g_file_info_get_content_type (info); if (g_strcmp0 (eel_ref_str_peek (file->details->mime_type), mime_type) != 0) { changed = TRUE; eel_ref_str_unref (file->details->mime_type); file->details->mime_type = eel_ref_str_get_unique (mime_type); } selinux_context = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT); if (g_strcmp0 (file->details->selinux_context, selinux_context) != 0) { changed = TRUE; g_free (file->details->selinux_context); file->details->selinux_context = g_strdup (selinux_context); } description = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION); if (g_strcmp0 (file->details->description, description) != 0) { changed = TRUE; g_free (file->details->description); file->details->description = g_strdup (description); } filesystem_id = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM); if (g_strcmp0 (eel_ref_str_peek (file->details->filesystem_id), filesystem_id) != 0) { changed = TRUE; eel_ref_str_unref (file->details->filesystem_id); file->details->filesystem_id = eel_ref_str_get_unique (filesystem_id); } trash_time = 0; time_string = g_file_info_get_attribute_string (info, "trash::deletion-date"); if (time_string != NULL) { g_time_val_from_iso8601 (time_string, &g_trash_time); trash_time = g_trash_time.tv_sec; } if (file->details->trash_time != trash_time) { changed = TRUE; file->details->trash_time = trash_time; } trash_orig_path = g_file_info_get_attribute_byte_string (info, "trash::orig-path"); if (g_strcmp0 (file->details->trash_orig_path, trash_orig_path) != 0) { changed = TRUE; g_free (file->details->trash_orig_path); file->details->trash_orig_path = g_strdup (trash_orig_path); } changed |= nemo_file_update_metadata_from_info (file, info); if (update_name) { name = g_file_info_get_name (info); if (file->details->name == NULL || strcmp (eel_ref_str_peek (file->details->name), name) != 0) { changed = TRUE; node = nemo_directory_begin_file_name_change (file->details->directory, file); eel_ref_str_unref (file->details->name); if (g_strcmp0 (eel_ref_str_peek (file->details->display_name), name) == 0) { file->details->name = eel_ref_str_ref (file->details->display_name); } else { file->details->name = eel_ref_str_new (name); } if (!file->details->got_custom_display_name && g_file_info_get_display_name (info) == NULL) { /* If the file info's display name is NULL, * nemo_file_set_display_name() did * not unset the display name. */ nemo_file_clear_display_name (file); } nemo_directory_end_file_name_change (file->details->directory, file, node); } } if (changed) { add_to_link_hash_table (file); update_links_if_target (file); } return changed; } static gboolean update_info_and_name (NemoFile *file, GFileInfo *info) { return update_info_internal (file, info, TRUE); } gboolean nemo_file_update_info (NemoFile *file, GFileInfo *info) { return update_info_internal (file, info, FALSE); } static gboolean update_name_internal (NemoFile *file, const char *name, gboolean in_directory) { GList *node; g_assert (name != NULL); if (file->details->is_gone) { return FALSE; } if (name_is (file, name)) { return FALSE; } node = NULL; if (in_directory) { node = nemo_directory_begin_file_name_change (file->details->directory, file); } eel_ref_str_unref (file->details->name); file->details->name = eel_ref_str_new (name); if (!file->details->got_custom_display_name) { nemo_file_clear_display_name (file); } if (in_directory) { nemo_directory_end_file_name_change (file->details->directory, file, node); } return TRUE; } gboolean nemo_file_update_name (NemoFile *file, const char *name) { gboolean ret; ret = update_name_internal (file, name, TRUE); if (ret) { update_links_if_target (file); } return ret; } gboolean nemo_file_update_name_and_directory (NemoFile *file, const char *name, NemoDirectory *new_directory) { NemoDirectory *old_directory; FileMonitors *monitors; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); g_return_val_if_fail (NEMO_IS_DIRECTORY (file->details->directory), FALSE); g_return_val_if_fail (!file->details->is_gone, FALSE); g_return_val_if_fail (!nemo_file_is_self_owned (file), FALSE); g_return_val_if_fail (NEMO_IS_DIRECTORY (new_directory), FALSE); old_directory = file->details->directory; if (old_directory == new_directory) { if (name) { return update_name_internal (file, name, TRUE); } else { return FALSE; } } nemo_file_ref (file); /* FIXME bugzilla.gnome.org 42044: Need to let links that * point to the old name know that the file has been moved. */ remove_from_link_hash_table (file); monitors = nemo_directory_remove_file_monitors (old_directory, file); nemo_directory_remove_file (old_directory, file); file->details->directory = nemo_directory_ref (new_directory); nemo_directory_unref (old_directory); if (name) { update_name_internal (file, name, FALSE); } nemo_directory_add_file (new_directory, file); nemo_directory_add_file_monitors (new_directory, file, monitors); add_to_link_hash_table (file); update_links_if_target (file); nemo_file_unref (file); return TRUE; } void nemo_file_set_directory (NemoFile *file, NemoDirectory *new_directory) { nemo_file_update_name_and_directory (file, NULL, new_directory); } static Knowledge get_item_count (NemoFile *file, guint *count) { gboolean known, unreadable; known = nemo_file_get_directory_item_count (file, count, &unreadable); if (!known) { return UNKNOWN; } if (unreadable) { return UNKNOWABLE; } return KNOWN; } static Knowledge get_size (NemoFile *file, goffset *size) { /* If we tried and failed, then treat it like there is no size * to know. */ if (file->details->get_info_failed) { return UNKNOWABLE; } /* If the info is NULL that means we haven't even tried yet, * so it's just unknown, not unknowable. */ if (!file->details->got_file_info) { return UNKNOWN; } /* If we got info with no size in it, it means there is no * such thing as a size as far as gnome-vfs is concerned, * so "unknowable". */ if (file->details->size == -1) { return UNKNOWABLE; } /* We have a size! */ *size = file->details->size; return KNOWN; } static Knowledge get_time (NemoFile *file, time_t *time_out, NemoDateType type) { time_t time; /* If we tried and failed, then treat it like there is no size * to know. */ if (file->details->get_info_failed) { return UNKNOWABLE; } /* If the info is NULL that means we haven't even tried yet, * so it's just unknown, not unknowable. */ if (!file->details->got_file_info) { return UNKNOWN; } time = 0; switch (type) { case NEMO_DATE_TYPE_MODIFIED: time = file->details->mtime; break; case NEMO_DATE_TYPE_ACCESSED: time = file->details->atime; break; case NEMO_DATE_TYPE_TRASHED: time = file->details->trash_time; break; default: g_assert_not_reached (); break; } *time_out = time; /* If we got info with no modification time in it, it means * there is no such thing as a modification time as far as * gnome-vfs is concerned, so "unknowable". */ if (time == 0) { return UNKNOWABLE; } return KNOWN; } static int compare_directories_by_count (NemoFile *file_1, NemoFile *file_2) { /* Sort order: * Directories with unknown # of items * Directories with "unknowable" # of items * Directories with 0 items * Directories with n items */ Knowledge count_known_1, count_known_2; guint count_1, count_2; count_known_1 = get_item_count (file_1, &count_1); count_known_2 = get_item_count (file_2, &count_2); if (count_known_1 > count_known_2) { return -1; } if (count_known_1 < count_known_2) { return +1; } /* count_known_1 and count_known_2 are equal now. Check if count * details are UNKNOWABLE or UNKNOWN. */ if (count_known_1 == UNKNOWABLE || count_known_1 == UNKNOWN) { return 0; } if (count_1 < count_2) { return -1; } if (count_1 > count_2) { return +1; } return 0; } static int compare_files_by_size (NemoFile *file_1, NemoFile *file_2) { /* Sort order: * Files with unknown size. * Files with "unknowable" size. * Files with smaller sizes. * Files with large sizes. */ Knowledge size_known_1, size_known_2; goffset size_1 = 0, size_2 = 0; size_known_1 = get_size (file_1, &size_1); size_known_2 = get_size (file_2, &size_2); if (size_known_1 > size_known_2) { return -1; } if (size_known_1 < size_known_2) { return +1; } /* size_known_1 and size_known_2 are equal now. Check if size * details are UNKNOWABLE or UNKNOWN */ if (size_known_1 == UNKNOWABLE || size_known_1 == UNKNOWN) { return 0; } if (size_1 < size_2) { return -1; } if (size_1 > size_2) { return +1; } return 0; } static int compare_by_size (NemoFile *file_1, NemoFile *file_2) { /* Sort order: * Directories with n items * Directories with 0 items * Directories with "unknowable" # of items * Directories with unknown # of items * Files with large sizes. * Files with smaller sizes. * Files with "unknowable" size. * Files with unknown size. */ gboolean is_directory_1, is_directory_2; is_directory_1 = nemo_file_is_directory (file_1); is_directory_2 = nemo_file_is_directory (file_2); if (is_directory_1 && !is_directory_2) { return -1; } if (is_directory_2 && !is_directory_1) { return +1; } if (is_directory_1) { return compare_directories_by_count (file_1, file_2); } else { return compare_files_by_size (file_1, file_2); } } static int compare_by_display_name (NemoFile *file_1, NemoFile *file_2) { const char *name_1, *name_2; const char *key_1, *key_2; gboolean sort_last_1, sort_last_2; int compare=0; name_1 = nemo_file_peek_display_name (file_1); name_2 = nemo_file_peek_display_name (file_2); sort_last_1 = name_1 && (name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2); sort_last_2 = name_2 && (name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2); if (sort_last_1 && !sort_last_2) { compare = +1; } else if (!sort_last_1 && sort_last_2) { compare = -1; } else if (name_1 == NULL || name_2 == NULL) { if (name_1 && !name_2) compare = +1; else if (!name_1 && name_2) compare = -1; } else { key_1 = nemo_file_peek_display_name_collation_key (file_1); key_2 = nemo_file_peek_display_name_collation_key (file_2); compare = g_strcmp0 (key_1, key_2); } return compare; } static int compare_by_directory_name (NemoFile *file_1, NemoFile *file_2) { char *directory_1, *directory_2; int compare; if (file_1->details->directory == file_2->details->directory) { return 0; } directory_1 = nemo_file_get_parent_uri_for_display (file_1); directory_2 = nemo_file_get_parent_uri_for_display (file_2); compare = g_utf8_collate (directory_1, directory_2); g_free (directory_1); g_free (directory_2); return compare; } static gboolean file_has_note (NemoFile *file) { char *note; gboolean res; note = nemo_file_get_metadata (file, NEMO_METADATA_KEY_ANNOTATION, NULL); res = note != NULL && note[0] != 0; g_free (note); return res; } static GList * prepend_automatic_keywords (NemoFile *file, GList *names) { /* Prepend in reverse order. */ NemoFile *parent; parent = nemo_file_get_parent (file); #ifdef TRASH_IS_FAST_ENOUGH if (nemo_file_is_in_trash (file)) { names = g_list_prepend (names, g_strdup (NEMO_FILE_EMBLEM_NAME_TRASH)); } #endif if (file_has_note (file)) { names = g_list_prepend (names, g_strdup (NEMO_FILE_EMBLEM_NAME_NOTE)); } /* Trash files are assumed to be read-only, * so we want to ignore them here. */ if (!nemo_file_can_write (file) && !nemo_file_is_in_trash (file) && (parent == NULL || nemo_file_can_write (parent))) { names = g_list_prepend (names, g_strdup (NEMO_FILE_EMBLEM_NAME_CANT_WRITE)); } if (!nemo_file_can_read (file)) { names = g_list_prepend (names, g_strdup (NEMO_FILE_EMBLEM_NAME_CANT_READ)); } if (nemo_file_is_symbolic_link (file)) { names = g_list_prepend (names, g_strdup (NEMO_FILE_EMBLEM_NAME_SYMBOLIC_LINK)); } if (parent) { nemo_file_unref (parent); } return names; } static int compare_by_type (NemoFile *file_1, NemoFile *file_2, gboolean detailed) { gboolean is_directory_1; gboolean is_directory_2; char *type_string_1; char *type_string_2; int result; /* Directories go first. Then, if mime types are identical, * don't bother getting strings (for speed). This assumes * that the string is dependent entirely on the mime type, * which is true now but might not be later. */ is_directory_1 = nemo_file_is_directory (file_1); is_directory_2 = nemo_file_is_directory (file_2); if (is_directory_1 && is_directory_2) { return 0; } if (is_directory_1) { return -1; } if (is_directory_2) { return +1; } if (detailed) { type_string_1 = nemo_file_get_detailed_type_as_string (file_1); type_string_2 = nemo_file_get_detailed_type_as_string (file_2); } else { type_string_1 = nemo_file_get_type_as_string (file_1); type_string_2 = nemo_file_get_type_as_string (file_2); } if (type_string_1 == NULL || type_string_2 == NULL) { if (type_string_1 != NULL) { return -1; } if (type_string_2 != NULL) { return 1; } return 0; } result = g_utf8_collate (type_string_1, type_string_2); g_free (type_string_1); g_free (type_string_2); return result; } static int compare_by_time (NemoFile *file_1, NemoFile *file_2, NemoDateType type) { /* Sort order: * Files with unknown times. * Files with "unknowable" times. * Files with older times. * Files with newer times. */ Knowledge time_known_1, time_known_2; time_t time_1, time_2; time_1 = 0; time_2 = 0; time_known_1 = get_time (file_1, &time_1, type); time_known_2 = get_time (file_2, &time_2, type); if (time_known_1 > time_known_2) { return -1; } if (time_known_1 < time_known_2) { return +1; } /* Now time_known_1 is equal to time_known_2. Check whether * we failed to get modification times for files */ if(time_known_1 == UNKNOWABLE || time_known_1 == UNKNOWN) { return 0; } if (time_1 < time_2) { return -1; } if (time_1 > time_2) { return +1; } return 0; } static int compare_by_full_path (NemoFile *file_1, NemoFile *file_2) { int compare; compare = compare_by_directory_name (file_1, file_2); if (compare != 0) { return compare; } return compare_by_display_name (file_1, file_2); } static int nemo_file_compare_for_sort_internal (NemoFile *file_1, NemoFile *file_2, gboolean directories_first, gboolean reversed) { gboolean is_directory_1, is_directory_2; if (directories_first) { is_directory_1 = nemo_file_is_directory (file_1); is_directory_2 = nemo_file_is_directory (file_2); if (is_directory_1 && !is_directory_2) { return -1; } if (is_directory_2 && !is_directory_1) { return +1; } } if (file_1->details->sort_order < file_2->details->sort_order) { return reversed ? 1 : -1; } else if (file_1->details->sort_order > file_2->details->sort_order) { return reversed ? -1 : 1; } return 0; } /** * nemo_file_compare_for_sort: * @file_1: A file object * @file_2: Another file object * @sort_type: Sort criterion * @directories_first: Put all directories before any non-directories * @reversed: Reverse the order of the items, except that * the directories_first flag is still respected. * * Return value: int < 0 if @file_1 should come before file_2 in a * sorted list; int > 0 if @file_2 should come before file_1 in a * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note * that each named sort type may actually break ties several ways, with the name * of the sort criterion being the primary but not only differentiator. **/ int nemo_file_compare_for_sort (NemoFile *file_1, NemoFile *file_2, NemoFileSortType sort_type, gboolean directories_first, gboolean reversed) { int result; if (file_1 == file_2) { return 0; } result = nemo_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed); if (result == 0) { switch (sort_type) { case NEMO_FILE_SORT_BY_DISPLAY_NAME: result = compare_by_display_name (file_1, file_2); if (result == 0) { result = compare_by_directory_name (file_1, file_2); } break; case NEMO_FILE_SORT_BY_SIZE: /* Compare directory sizes ourselves, then if necessary * use GnomeVFS to compare file sizes. */ result = compare_by_size (file_1, file_2); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; case NEMO_FILE_SORT_BY_TYPE: result = compare_by_type (file_1, file_2, FALSE); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; case NEMO_FILE_SORT_BY_DETAILED_TYPE: result = compare_by_type (file_1, file_2, TRUE); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; case NEMO_FILE_SORT_BY_MTIME: result = compare_by_time (file_1, file_2, NEMO_DATE_TYPE_MODIFIED); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; case NEMO_FILE_SORT_BY_ATIME: result = compare_by_time (file_1, file_2, NEMO_DATE_TYPE_ACCESSED); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; case NEMO_FILE_SORT_BY_TRASHED_TIME: result = compare_by_time (file_1, file_2, NEMO_DATE_TYPE_TRASHED); if (result == 0) { result = compare_by_full_path (file_1, file_2); } break; default: g_return_val_if_reached (0); } if (reversed) { result = -result; } } return result; } int nemo_file_compare_for_sort_by_attribute_q (NemoFile *file_1, NemoFile *file_2, GQuark attribute, gboolean directories_first, gboolean reversed) { int result; if (file_1 == file_2) { return 0; } /* Convert certain attributes into NemoFileSortTypes and use * nemo_file_compare_for_sort() */ if (attribute == 0 || attribute == attribute_name_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_DISPLAY_NAME, directories_first, reversed); } else if (attribute == attribute_size_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_SIZE, directories_first, reversed); } else if (attribute == attribute_type_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_TYPE, directories_first, reversed); } else if (attribute == attribute_detailed_type_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_DETAILED_TYPE, directories_first, reversed); } else if (attribute == attribute_modification_date_q || attribute == attribute_date_modified_q || attribute == attribute_date_modified_with_time_q || attribute == attribute_date_modified_full_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_MTIME, directories_first, reversed); } else if (attribute == attribute_accessed_date_q || attribute == attribute_date_accessed_q || attribute == attribute_date_accessed_full_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_ATIME, directories_first, reversed); } else if (attribute == attribute_trashed_on_q || attribute == attribute_trashed_on_full_q) { return nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_TRASHED_TIME, directories_first, reversed); } /* it is a normal attribute, compare by strings */ result = nemo_file_compare_for_sort_internal (file_1, file_2, directories_first, reversed); if (result == 0) { char *value_1; char *value_2; value_1 = nemo_file_get_string_attribute_q (file_1, attribute); value_2 = nemo_file_get_string_attribute_q (file_2, attribute); if (value_1 != NULL && value_2 != NULL) { result = strcmp (value_1, value_2); } g_free (value_1); g_free (value_2); if (reversed) { result = -result; } } return result; } int nemo_file_compare_for_sort_by_attribute (NemoFile *file_1, NemoFile *file_2, const char *attribute, gboolean directories_first, gboolean reversed) { return nemo_file_compare_for_sort_by_attribute_q (file_1, file_2, g_quark_from_string (attribute), directories_first, reversed); } /** * nemo_file_compare_name: * @file: A file object * @pattern: A string we are comparing it with * * Return value: result of a comparison of the file name and the given pattern, * using the same sorting order as sort by name. **/ int nemo_file_compare_display_name (NemoFile *file, const char *pattern) { const char *name; int result; g_return_val_if_fail (pattern != NULL, -1); name = nemo_file_peek_display_name (file); result = g_utf8_collate (name, pattern); return result; } gboolean nemo_file_is_hidden_file (NemoFile *file) { return file->details->is_hidden; } static gboolean is_file_hidden (NemoFile *file) { return file->details->directory->details->hidden_file_hash != NULL && g_hash_table_lookup (file->details->directory->details->hidden_file_hash, eel_ref_str_peek (file->details->name)) != NULL; } /** * nemo_file_should_show: * @file: the file to check. * @show_hidden: whether we want to show hidden files or not. * * Determines if a #NemoFile should be shown. Note that when browsing * a trash directory, this function will always return %TRUE. * * Returns: %TRUE if the file should be shown, %FALSE if it shouldn't. */ gboolean nemo_file_should_show (NemoFile *file, gboolean show_hidden, gboolean show_foreign) { /* Never hide any files in trash. */ if (nemo_file_is_in_trash (file)) { return TRUE; } else { return (show_hidden || (!nemo_file_is_hidden_file (file) && !is_file_hidden (file))) && (show_foreign || !(nemo_file_is_in_desktop (file) && nemo_file_is_foreign_link (file))); } } gboolean nemo_file_is_home (NemoFile *file) { GFile *dir; dir = file->details->directory->details->location; if (dir == NULL) { return FALSE; } return nemo_is_home_directory_file (dir, eel_ref_str_peek (file->details->name)); } gboolean nemo_file_is_in_desktop (NemoFile *file) { if (file->details->directory->details->location) { return nemo_is_desktop_directory (file->details->directory->details->location); } return FALSE; } static gboolean filter_hidden_partition_callback (gpointer data, gpointer callback_data) { NemoFile *file; FilterOptions options; file = NEMO_FILE (data); options = GPOINTER_TO_INT (callback_data); return nemo_file_should_show (file, options & SHOW_HIDDEN, TRUE); } GList * nemo_file_list_filter_hidden (GList *files, gboolean show_hidden) { GList *filtered_files; GList *removed_files; /* FIXME bugzilla.gnome.org 40653: * Eventually this should become a generic filtering thingy. */ filtered_files = nemo_file_list_copy (files); filtered_files = eel_g_list_partition (filtered_files, filter_hidden_partition_callback, GINT_TO_POINTER ((show_hidden ? SHOW_HIDDEN : 0)), &removed_files); nemo_file_list_free (removed_files); return filtered_files; } char * nemo_file_get_metadata (NemoFile *file, const char *key, const char *default_metadata) { guint id; char *value; g_return_val_if_fail (key != NULL, g_strdup (default_metadata)); g_return_val_if_fail (key[0] != '\0', g_strdup (default_metadata)); if (file == NULL || file->details->metadata == NULL) { return g_strdup (default_metadata); } g_return_val_if_fail (NEMO_IS_FILE (file), g_strdup (default_metadata)); if (NEMO_FILE_GET_CLASS (file)->get_metadata) { value = NEMO_FILE_GET_CLASS (file)->get_metadata (file, key); if (value) { return value; } else { return g_strdup (default_metadata); } } id = nemo_metadata_get_id (key); value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)); if (value) { return g_strdup (value); } return g_strdup (default_metadata); } GList * nemo_file_get_metadata_list (NemoFile *file, const char *key) { GList *res; guint id; char **value; int i; g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key[0] != '\0', NULL); if (file == NULL || file->details->metadata == NULL) { return NULL; } g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (NEMO_FILE_GET_CLASS (file)->get_metadata_as_list) { return NEMO_FILE_GET_CLASS (file)->get_metadata_as_list (file, key); } id = nemo_metadata_get_id (key); id |= METADATA_ID_IS_LIST_MASK; value = g_hash_table_lookup (file->details->metadata, GUINT_TO_POINTER (id)); if (value) { res = NULL; for (i = 0; value[i] != NULL; i++) { res = g_list_prepend (res, g_strdup (value[i])); } return g_list_reverse (res); } return NULL; } void nemo_file_set_metadata (NemoFile *file, const char *key, const char *default_metadata, const char *metadata) { const char *val; g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (key != NULL); g_return_if_fail (key[0] != '\0'); val = metadata; if (val == NULL) { val = default_metadata; } NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata (file, key, val); } void nemo_file_set_metadata_list (NemoFile *file, const char *key, GList *list) { char **val; int len, i; GList *l; g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (key != NULL); g_return_if_fail (key[0] != '\0'); len = g_list_length (list); val = g_new (char *, len + 1); for (l = list, i = 0; l != NULL; l = l->next, i++) { val[i] = l->data; } val[i] = NULL; NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->set_metadata_as_list (file, key, val); g_free (val); } gboolean nemo_file_get_boolean_metadata (NemoFile *file, const char *key, gboolean default_metadata) { char *result_as_string; gboolean result; g_return_val_if_fail (key != NULL, default_metadata); g_return_val_if_fail (key[0] != '\0', default_metadata); if (file == NULL) { return default_metadata; } g_return_val_if_fail (NEMO_IS_FILE (file), default_metadata); result_as_string = nemo_file_get_metadata (file, key, default_metadata ? "true" : "false"); g_assert (result_as_string != NULL); if (g_ascii_strcasecmp (result_as_string, "true") == 0) { result = TRUE; } else if (g_ascii_strcasecmp (result_as_string, "false") == 0) { result = FALSE; } else { g_error ("boolean metadata with value other than true or false"); result = default_metadata; } g_free (result_as_string); return result; } int nemo_file_get_integer_metadata (NemoFile *file, const char *key, int default_metadata) { char *result_as_string; char default_as_string[32]; int result; char c; g_return_val_if_fail (key != NULL, default_metadata); g_return_val_if_fail (key[0] != '\0', default_metadata); if (file == NULL) { return default_metadata; } g_return_val_if_fail (NEMO_IS_FILE (file), default_metadata); g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata); result_as_string = nemo_file_get_metadata (file, key, default_as_string); /* Normally we can't get a a NULL, but we check for it here to * handle the oddball case of a non-existent directory. */ if (result_as_string == NULL) { result = default_metadata; } else { if (sscanf (result_as_string, " %d %c", &result, &c) != 1) { result = default_metadata; } g_free (result_as_string); } return result; } static gboolean get_time_from_time_string (const char *time_string, time_t *time) { long scanned_time; char c; g_assert (time != NULL); /* Only accept string if it has one integer with nothing * afterwards. */ if (time_string == NULL || sscanf (time_string, "%ld%c", &scanned_time, &c) != 1) { return FALSE; } *time = (time_t) scanned_time; return TRUE; } time_t nemo_file_get_time_metadata (NemoFile *file, const char *key) { time_t time; char *time_string; time_string = nemo_file_get_metadata (file, key, NULL); if (!get_time_from_time_string (time_string, &time)) { time = UNDEFINED_TIME; } g_free (time_string); return time; } void nemo_file_set_time_metadata (NemoFile *file, const char *key, time_t time) { char time_str[21]; char *metadata; if (time != UNDEFINED_TIME) { /* 2^64 turns out to be 20 characters */ g_snprintf (time_str, 20, "%ld", (long int)time); time_str[20] = '\0'; metadata = time_str; } else { metadata = NULL; } nemo_file_set_metadata (file, key, NULL, metadata); } void nemo_file_set_boolean_metadata (NemoFile *file, const char *key, gboolean default_metadata, gboolean metadata) { g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (key != NULL); g_return_if_fail (key[0] != '\0'); nemo_file_set_metadata (file, key, default_metadata ? "true" : "false", metadata ? "true" : "false"); } void nemo_file_set_integer_metadata (NemoFile *file, const char *key, int default_metadata, int metadata) { char value_as_string[32]; char default_as_string[32]; g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (key != NULL); g_return_if_fail (key[0] != '\0'); g_snprintf (value_as_string, sizeof (value_as_string), "%d", metadata); g_snprintf (default_as_string, sizeof (default_as_string), "%d", default_metadata); nemo_file_set_metadata (file, key, default_as_string, value_as_string); } static const char * nemo_file_peek_display_name_collation_key (NemoFile *file) { const char *res; res = file->details->display_name_collation_key; if (res == NULL) res = ""; return res; } static const char * nemo_file_peek_display_name (NemoFile *file) { const char *name; char *escaped_name; /* FIXME: for some reason we can get a NemoFile instance which is * no longer valid or could be freed somewhere else in the same time. * There's race condition somewhere. See bug 602500. */ if (file == NULL || nemo_file_is_gone (file)) return ""; /* Default to display name based on filename if its not set yet */ if (file->details->display_name == NULL) { name = eel_ref_str_peek (file->details->name); if (g_utf8_validate (name, -1, NULL)) { nemo_file_set_display_name (file, name, NULL, FALSE); } else { escaped_name = g_uri_escape_string (name, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, TRUE); nemo_file_set_display_name (file, escaped_name, NULL, FALSE); g_free (escaped_name); } } return eel_ref_str_peek (file->details->display_name); } char * nemo_file_get_display_name (NemoFile *file) { return g_strdup (nemo_file_peek_display_name (file)); } char * nemo_file_get_edit_name (NemoFile *file) { const char *res; res = eel_ref_str_peek (file->details->edit_name); if (res == NULL) res = ""; return g_strdup (res); } const char * nemo_file_peek_name (NemoFile *file) { return file->details->name; } char * nemo_file_get_name (NemoFile *file) { return g_strdup (eel_ref_str_peek (file->details->name)); } /** * nemo_file_get_description: * @file: a #NemoFile. * * Gets the standard::description key from @file, if * it has been cached. * * Returns: a string containing the value of the standard::description * key, or %NULL. */ char * nemo_file_get_description (NemoFile *file) { return g_strdup (file->details->description); } void nemo_file_monitor_add (NemoFile *file, gconstpointer client, NemoFileAttributes attributes) { g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (client != NULL); NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_add (file, client, attributes); } void nemo_file_monitor_remove (NemoFile *file, gconstpointer client) { g_return_if_fail (NEMO_IS_FILE (file)); g_return_if_fail (client != NULL); NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->monitor_remove (file, client); } gboolean nemo_file_is_launcher (NemoFile *file) { return file->details->is_launcher; } gboolean nemo_file_is_foreign_link (NemoFile *file) { return file->details->is_foreign_link; } gboolean nemo_file_is_trusted_link (NemoFile *file) { return file->details->is_trusted_link; } gboolean nemo_file_has_activation_uri (NemoFile *file) { return file->details->activation_uri != NULL; } /* Return the uri associated with the passed-in file, which may not be * the actual uri if the file is an desktop file or a nemo * xml link file. */ char * nemo_file_get_activation_uri (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (file->details->activation_uri != NULL) { return g_strdup (file->details->activation_uri); } return nemo_file_get_uri (file); } GFile * nemo_file_get_activation_location (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (file->details->activation_uri != NULL) { return g_file_new_for_uri (file->details->activation_uri); } return nemo_file_get_location (file); } char * nemo_file_get_drop_target_uri (NemoFile *file) { char *uri, *target_uri; GFile *location; NemoDesktopLink *link; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (NEMO_IS_DESKTOP_ICON_FILE (file)) { link = nemo_desktop_icon_file_get_link (NEMO_DESKTOP_ICON_FILE (file)); if (link != NULL) { location = nemo_desktop_link_get_activation_location (link); g_object_unref (link); if (location != NULL) { uri = g_file_get_uri (location); g_object_unref (location); return uri; } } } uri = nemo_file_get_uri (file); /* Check for Nemo link */ if (nemo_file_is_nemo_link (file)) { location = nemo_file_get_location (file); /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */ if (g_file_is_native (location)) { target_uri = nemo_link_local_get_link_uri (uri); if (target_uri != NULL) { g_free (uri); uri = target_uri; } } g_object_unref (location); } return uri; } static gboolean is_uri_relative (const char *uri) { char *scheme; gboolean ret; scheme = g_uri_parse_scheme (uri); ret = (scheme == NULL); g_free (scheme); return ret; } static char * get_custom_icon_metadata_uri (NemoFile *file) { char *custom_icon_uri; char *uri; char *dir_uri; uri = nemo_file_get_metadata (file, NEMO_METADATA_KEY_CUSTOM_ICON, NULL); if (uri != NULL && nemo_file_is_directory (file) && is_uri_relative (uri)) { dir_uri = nemo_file_get_uri (file); custom_icon_uri = g_build_filename (dir_uri, uri, NULL); g_free (dir_uri); g_free (uri); } else { custom_icon_uri = uri; } return custom_icon_uri; } static char * get_custom_icon_metadata_name (NemoFile *file) { char *icon_name; icon_name = nemo_file_get_metadata (file, NEMO_METADATA_KEY_CUSTOM_ICON_NAME, NULL); return icon_name; } static GIcon * get_custom_icon (NemoFile *file) { char *custom_icon_uri, *custom_icon_name; GFile *icon_file; GIcon *icon; if (file == NULL) { return NULL; } icon = NULL; /* Metadata takes precedence; first we look at the custom * icon URI, then at the custom icon name. */ custom_icon_uri = get_custom_icon_metadata_uri (file); if (custom_icon_uri) { icon_file = g_file_new_for_uri (custom_icon_uri); icon = g_file_icon_new (icon_file); g_object_unref (icon_file); g_free (custom_icon_uri); } if (icon == NULL) { custom_icon_name = get_custom_icon_metadata_name (file); if (custom_icon_name != NULL) { icon = g_themed_icon_new (custom_icon_name); g_free (custom_icon_name); } } if (icon == NULL && file->details->got_link_info && file->details->custom_icon != NULL) { icon = g_object_ref (file->details->custom_icon); } return icon; } GFilesystemPreviewType nemo_file_get_filesystem_use_preview (NemoFile *file) { GFilesystemPreviewType use_preview; NemoFile *parent; parent = nemo_file_get_parent (file); if (parent != NULL) { use_preview = parent->details->filesystem_use_preview; g_object_unref (parent); } else { use_preview = 0; } return use_preview; } gboolean nemo_file_should_show_thumbnail (NemoFile *file) { GFilesystemPreviewType use_preview; use_preview = nemo_file_get_filesystem_use_preview (file); /* If the thumbnail has already been created, don't care about the size * of the original file. */ if (file->details->thumbnail_path == NULL && nemo_file_get_size (file) > cached_thumbnail_limit) { return FALSE; } if (file->details->thumbnail_access_problem) return FALSE; if (show_image_thumbs == NEMO_SPEED_TRADEOFF_ALWAYS) { if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) { return FALSE; } else { return TRUE; } } else if (show_image_thumbs == NEMO_SPEED_TRADEOFF_NEVER) { return FALSE; } else { if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) { /* file system says to never thumbnail anything */ return FALSE; } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) { /* file system says we should treat file as if it's local */ return TRUE; } else { /* only local files */ return nemo_file_is_local (file); } } return FALSE; } static void prepend_icon_name (const char *name, GThemedIcon *icon) { g_themed_icon_prepend_name(icon, name); } GIcon * nemo_file_get_gicon (NemoFile *file, NemoFileIconFlags flags) { const char * const * names; const char *name; GPtrArray *prepend_array; GMount *mount; GIcon *icon, *mount_icon = NULL, *emblemed_icon; GEmblem *emblem; int i; gboolean is_folder = FALSE, is_inode_directory = FALSE; if (file == NULL) { return NULL; } icon = get_custom_icon (file); if (icon != NULL) { return icon; } if (file->details->icon) { icon = NULL; /* fetch the mount icon here, we'll use it later */ if (flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON || flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) { mount = nemo_file_get_mount (file); if (mount != NULL) { mount_icon = g_mount_get_icon (mount); g_object_unref (mount); } } if (((flags & NEMO_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT) || (flags & NEMO_FILE_ICON_FLAGS_FOR_OPEN_FOLDER) || (flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON) || (flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) || ((flags & NEMO_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 && nemo_file_has_open_window (file))) && G_IS_THEMED_ICON (file->details->icon)) { names = g_themed_icon_get_names (G_THEMED_ICON (file->details->icon)); prepend_array = g_ptr_array_new (); for (i = 0; names[i] != NULL; i++) { name = names[i]; if (strcmp (name, "folder") == 0) { is_folder = TRUE; } if (strcmp (name, "inode-directory") == 0) { is_inode_directory = TRUE; } } /* Here, we add icons in reverse order of precedence, * because they are later prepended */ /* "folder" should override "inode-directory", not the other way around */ if (is_inode_directory) { g_ptr_array_add (prepend_array, "folder"); } if (is_folder && (flags & NEMO_FILE_ICON_FLAGS_FOR_OPEN_FOLDER)) { g_ptr_array_add (prepend_array, "folder-open"); } if (is_folder && (flags & NEMO_FILE_ICON_FLAGS_IGNORE_VISITING) == 0 && nemo_file_has_open_window (file)) { g_ptr_array_add (prepend_array, "folder-visiting"); } if (is_folder && (flags & NEMO_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT)) { g_ptr_array_add (prepend_array, "folder-drag-accept"); } if (prepend_array->len) { /* When constructing GThemed Icon, pointers from the array * are reused, but not the array itself, so the cast is safe */ icon = g_themed_icon_new_from_names ((char**) names, -1); g_ptr_array_foreach (prepend_array, (GFunc) prepend_icon_name, icon); } g_ptr_array_free (prepend_array, TRUE); } if (icon == NULL) { icon = g_object_ref (file->details->icon); } if ((flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON) && mount_icon != NULL) { g_object_unref (icon); icon = mount_icon; } else if ((flags & NEMO_FILE_ICON_FLAGS_USE_MOUNT_ICON_AS_EMBLEM) && mount_icon != NULL && !g_icon_equal (mount_icon, icon)) { emblem = g_emblem_new (mount_icon); emblemed_icon = g_emblemed_icon_new (icon, emblem); g_object_unref (emblem); g_object_unref (icon); g_object_unref (mount_icon); icon = emblemed_icon; } else if (mount_icon != NULL) { g_object_unref (mount_icon); } return icon; } return g_themed_icon_new ("text-x-generic"); } GIcon * nemo_file_get_emblemed_icon (NemoFile *file, NemoFileIconFlags flags) { GIcon *gicon, *emblem_icon, *emblemed_icon; GEmblem *emblem; GList *emblem_icons, *l; char *emblems_to_ignore[3]; int i; gicon = nemo_file_get_gicon (file, flags); i = 0; emblems_to_ignore[i++] = NEMO_FILE_EMBLEM_NAME_TRASH; emblems_to_ignore[i++] = NEMO_FILE_EMBLEM_NAME_CANT_WRITE; emblems_to_ignore[i++] = NULL; emblem = NULL; emblem_icons = nemo_file_get_emblem_icons (file, emblems_to_ignore); emblemed_icon = g_emblemed_icon_new (gicon, NULL); g_object_unref (gicon); /* pick only the first emblem we can render for the tree view */ for (l = emblem_icons; l != NULL; l = l->next) { emblem_icon = l->data; if (nemo_icon_theme_can_render (G_THEMED_ICON (emblem_icon))) { emblem = g_emblem_new (emblem_icon); g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (emblemed_icon), emblem); g_object_unref (emblem); } } g_list_free_full (emblem_icons, g_object_unref); return emblemed_icon; } static gint get_throttle_count (NemoFile *file) { NemoFileDetails *details = file->details; gint diff = (gint)(details->mtime - details->last_thumbnail_try_mtime); if (diff != 0 && diff <= (THUMBNAIL_CREATION_DELAY_SECS * (details->thumbnail_throttle_count + 1))) { details->thumbnail_throttle_count++; } else { details->thumbnail_throttle_count = 1; } details->last_thumbnail_try_mtime = details->mtime; return details->thumbnail_throttle_count; } NemoIconInfo * nemo_file_get_icon (NemoFile *file, int size, int max_width, int scale, NemoFileIconFlags flags) { NemoIconInfo *icon; GIcon *gicon; GdkPixbuf *raw_pixbuf, *scaled_pixbuf; int modified_size; if (file == NULL) { return NULL; } gicon = get_custom_icon (file); if (gicon != NULL) { icon = nemo_icon_info_lookup (gicon, size, scale); g_object_unref (gicon); return icon; } DEBUG ("Called file_get_icon(), at size %d, force thumbnail %d", size, flags & NEMO_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE); if (flags & NEMO_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE) { modified_size = size * scale; } else { modified_size = size * scale * cached_thumbnail_size / NEMO_ICON_SIZE_STANDARD; DEBUG ("Modifying icon size to %d, as our cached thumbnail size is %d", modified_size, cached_thumbnail_size); } if (flags & NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS && nemo_file_should_show_thumbnail (file)) { if (file->details->thumbnail) { int w, h, s; double thumb_scale; raw_pixbuf = g_object_ref (file->details->thumbnail); w = gdk_pixbuf_get_width (raw_pixbuf); h = gdk_pixbuf_get_height (raw_pixbuf); if (flags & NEMO_FILE_ICON_FLAGS_PIN_HEIGHT_FOR_DESKTOP) { g_assert (max_width > 0); thumb_scale = (gdouble) modified_size / h; if (w * thumb_scale > max_width) { thumb_scale = (gdouble) max_width / w; } s = thumb_scale * h; } else { s = MAX (w, h); /* Don't scale up small thumbnails in the standard view */ if (s <= cached_thumbnail_size) { thumb_scale = (double)size / NEMO_ICON_SIZE_STANDARD; } else { thumb_scale = (double)modified_size / s; } /* Make sure that icons don't get smaller than NEMO_ICON_SIZE_SMALLEST */ if (s*thumb_scale <= NEMO_ICON_SIZE_SMALLEST) { thumb_scale = (double) NEMO_ICON_SIZE_SMALLEST / s; } } if (file->details->thumbnail_scale == thumb_scale && file->details->scaled_thumbnail != NULL) { scaled_pixbuf = file->details->scaled_thumbnail; } else { scaled_pixbuf = gdk_pixbuf_scale_simple (raw_pixbuf, MAX (w * thumb_scale, 1), MAX (h * thumb_scale, 1), GDK_INTERP_BILINEAR); /* We don't want frames around small icons */ if (!gdk_pixbuf_get_has_alpha (raw_pixbuf) || s >= 128 * scale) { nemo_thumbnail_frame_image (&scaled_pixbuf); } if (flags & NEMO_FILE_ICON_FLAGS_PIN_HEIGHT_FOR_DESKTOP) { gint check_height; check_height = gdk_pixbuf_get_height (scaled_pixbuf); if (check_height < size) { nemo_thumbnail_pad_top_and_bottom (&scaled_pixbuf, size - check_height); } } g_clear_object (&file->details->scaled_thumbnail); file->details->scaled_thumbnail = scaled_pixbuf; file->details->thumbnail_scale = thumb_scale; } g_object_unref (raw_pixbuf); /* Don't scale up if more than 25%, then read the original image instead. We don't want to compare to exactly 100%, since the zoom level 150% gives thumbnails at 144, which is ok to scale up from 128. */ if (modified_size > 128 * 1.25 * scale && !file->details->thumbnail_wants_original && nemo_can_thumbnail_internally (file)) { /* Invalidate if we resize upward */ file->details->thumbnail_wants_original = TRUE; nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_THUMBNAIL); } DEBUG ("Returning thumbnailed image, at size %d %d", (int) (w * thumb_scale), (int) (h * thumb_scale)); return nemo_icon_info_new_for_pixbuf (scaled_pixbuf, scale); } else if (file->details->thumbnail_path == NULL && file->details->can_read && !file->details->is_thumbnailing && !file->details->thumbnailing_failed) { if (nemo_can_thumbnail (file)) { nemo_create_thumbnail (file, get_throttle_count (file)); } } } if (file->details->is_thumbnailing && flags & NEMO_FILE_ICON_FLAGS_USE_THUMBNAILS) gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING); else gicon = nemo_file_get_gicon (file, flags); if (gicon) { icon = nemo_icon_info_lookup (gicon, size, scale); if (nemo_icon_info_is_fallback (icon)) { g_object_unref (icon); icon = nemo_icon_info_lookup (g_themed_icon_new ("text-x-generic"), size, scale); } g_object_unref (gicon); return icon; } else { return nemo_icon_info_lookup (g_themed_icon_new ("text-x-generic"), size, scale); } } GdkPixbuf * nemo_file_get_icon_pixbuf (NemoFile *file, int size, gboolean force_size, int scale, NemoFileIconFlags flags) { NemoIconInfo *info; GdkPixbuf *pixbuf; info = nemo_file_get_icon (file, size, 0, scale, flags); if (force_size) { pixbuf = nemo_icon_info_get_pixbuf_at_size (info, size); } else { pixbuf = nemo_icon_info_get_pixbuf (info); } g_object_unref (info); return pixbuf; } gboolean nemo_file_get_date (NemoFile *file, NemoDateType date_type, time_t *date) { if (date != NULL) { *date = 0; } g_return_val_if_fail (date_type == NEMO_DATE_TYPE_CHANGED || date_type == NEMO_DATE_TYPE_ACCESSED || date_type == NEMO_DATE_TYPE_MODIFIED || date_type == NEMO_DATE_TYPE_TRASHED || date_type == NEMO_DATE_TYPE_PERMISSIONS_CHANGED, FALSE); if (file == NULL) { return FALSE; } g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_date (file, date_type, date); } static char * nemo_file_get_where_string (NemoFile *file) { if (file == NULL) { return NULL; } g_return_val_if_fail (NEMO_IS_FILE (file), NULL); return NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_where_string (file); } static char * nemo_file_get_trash_original_file_parent_as_string (NemoFile *file) { NemoFile *orig_file, *parent; GFile *location; char *filename; if (file->details->trash_orig_path != NULL) { orig_file = nemo_file_get_trash_original_file (file); parent = nemo_file_get_parent (orig_file); location = nemo_file_get_location (parent); filename = g_file_get_parse_name (location); g_object_unref (location); nemo_file_unref (parent); nemo_file_unref (orig_file); return filename; } return NULL; } /** * nemo_file_get_date_as_string: * * Get a user-displayable string representing a file modification date. * The caller is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_date_as_string (NemoFile *file, NemoDateType date_type, NemoDateCompactFormat date_format) { time_t file_time_raw; GDateTime *file_date_time, *now; GDateTime *today_midnight; gint days_ago; gboolean use_24; const gchar *format; gchar *result; gchar *result_with_ratio; int date_format_pref; if (!nemo_file_get_date (file, date_type, &file_time_raw)) return NULL; file_date_time = g_date_time_new_from_unix_local (file_time_raw); date_format_pref = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_DATE_FORMAT); if (date_format_pref == NEMO_DATE_FORMAT_LOCALE) { result = g_date_time_format (file_date_time, "%c"); goto out; } else if (date_format_pref == NEMO_DATE_FORMAT_ISO) { result = g_date_time_format (file_date_time, "%Y-%m-%d %H:%M:%S"); goto out; } if (date_format != NEMO_DATE_FORMAT_FULL) { GDateTime *file_date; now = g_date_time_new_now_local (); today_midnight = g_date_time_new_local (g_date_time_get_year (now), g_date_time_get_month (now), g_date_time_get_day_of_month (now), 0, 0, 0); file_date = g_date_time_new_local (g_date_time_get_year (file_date_time), g_date_time_get_month (file_date_time), g_date_time_get_day_of_month (file_date_time), 0, 0, 0); days_ago = g_date_time_difference (today_midnight, file_date) / G_TIME_SPAN_DAY; use_24 = g_settings_get_boolean (cinnamon_interface_preferences, "clock-use-24h"); // Show only the time if date is on today if (days_ago < 1) { if (use_24) { /* Translators: Time in 24h format */ format = _("%H:%M"); } else { /* Translators: Time in 12h format */ format = _("%l:%M %p"); } } // Show the word "Yesterday" and time if date is on yesterday else if (days_ago < 2) { if (date_format == NEMO_DATE_FORMAT_REGULAR) { // xgettext:no-c-format format = _("Yesterday"); } else { if (use_24) { /* Translators: this is the word Yesterday followed by * a time in 24h format. i.e. "Yesterday 23:04" */ // xgettext:no-c-format format = _("Yesterday %H:%M"); } else { /* Translators: this is the word Yesterday followed by * a time in 12h format. i.e. "Yesterday 9:04 PM" */ // xgettext:no-c-format format = _("Yesterday %l:%M %p"); } } } // Show a week day and time if date is in the last week else if (days_ago < 7) { if (date_format == NEMO_DATE_FORMAT_REGULAR) { // xgettext:no-c-format format = _("%A"); } else { if (use_24) { /* Translators: this is the name of the week day followed by * a time in 24h format. i.e. "Monday 23:04" */ // xgettext:no-c-format format = _("%A %H:%M"); } else { /* Translators: this is the week day name followed by * a time in 12h format. i.e. "Monday 9:04 PM" */ // xgettext:no-c-format format = _("%A %l:%M %p"); } } } else if (g_date_time_get_year (file_date) == g_date_time_get_year (now)) { if (date_format == NEMO_DATE_FORMAT_REGULAR) { /* Translators: this is the day of the month followed * by the abbreviated month name i.e. "3 February" */ // xgettext:no-c-format format = _("%-e %B"); } else { if (use_24) { /* Translators: this is the day of the month followed * by the abbreviated month name followed by a time in * 24h format i.e. "3 February 23:04" */ // xgettext:no-c-format format = _("%-e %B %H:%M"); } else { /* Translators: this is the day of the month followed * by the abbreviated month name followed by a time in * 12h format i.e. "3 February 9:04" */ // xgettext:no-c-format format = _("%-e %B %l:%M %p"); } } } else { if (date_format == NEMO_DATE_FORMAT_REGULAR) { /* Translators: this is the day of the month followed by the abbreviated * month name followed by the year i.e. "3 Feb 2015" */ // xgettext:no-c-format format = _("%-e %b %Y"); } else { if (use_24) { /* Translators: this is the day number followed * by the abbreviated month name followed by the year followed * by a time in 24h format i.e. "3 Feb 2015 23:04" */ // xgettext:no-c-format format = _("%-e %b %Y %H:%M"); } else { /* Translators: this is the day number followed * by the abbreviated month name followed by the year followed * by a time in 12h format i.e. "3 Feb 2015 9:04 PM" */ // xgettext:no-c-format format = _("%-e %b %Y %l:%M %p"); } } } g_date_time_unref (file_date); g_date_time_unref (now); g_date_time_unref (today_midnight); } else { // xgettext:no-c-format format = _("%c"); } result = g_date_time_format (file_date_time, format); out: g_date_time_unref (file_date_time); /* Replace ":" with ratio. Replacement is done afterward because g_date_time_format * may fail with utf8 chars in some locales */ result_with_ratio = eel_str_replace_substring (result, ":", "∶"); g_free (result); return result_with_ratio; } static NemoSpeedTradeoffValue show_directory_item_count; static void show_directory_item_count_changed_callback (gpointer callback_data) { show_directory_item_count = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS); } static gboolean get_speed_tradeoff_preference_for_file (NemoFile *file, NemoSpeedTradeoffValue value) { GFilesystemPreviewType use_preview; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); use_preview = nemo_file_get_filesystem_use_preview (file); if (value == NEMO_SPEED_TRADEOFF_ALWAYS) { if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) { return FALSE; } else { return TRUE; } } if (value == NEMO_SPEED_TRADEOFF_NEVER) { return FALSE; } g_assert (value == NEMO_SPEED_TRADEOFF_LOCAL_ONLY); if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER) { /* file system says to never preview anything */ return FALSE; } else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL) { /* file system says we should treat file as if it's local */ return TRUE; } else { /* only local files */ return nemo_file_is_local (file); } } gboolean nemo_file_should_show_directory_item_count (NemoFile *file) { static gboolean show_directory_item_count_callback_added = FALSE; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); if (file->details->mime_type && strcmp (eel_ref_str_peek (file->details->mime_type), "x-directory/smb-share") == 0) { return FALSE; } /* Add the callback once for the life of our process */ if (!show_directory_item_count_callback_added) { g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS, G_CALLBACK(show_directory_item_count_changed_callback), NULL); show_directory_item_count_callback_added = TRUE; /* Peek for the first time */ show_directory_item_count_changed_callback (NULL); } return get_speed_tradeoff_preference_for_file (file, show_directory_item_count); } gboolean nemo_file_should_show_type (NemoFile *file) { char *uri; gboolean ret; g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); uri = nemo_file_get_uri (file); ret = ((strcmp (uri, "computer:///") != 0) && (strcmp (uri, "network:///") != 0) && (strcmp (uri, "smb:///") != 0)); g_free (uri); return ret; } /** * nemo_file_get_directory_item_count * * Get the number of items in a directory. * @file: NemoFile representing a directory. * @count: Place to put count. * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent * the item count from being read on this directory. Otherwise set to FALSE. * * Returns: TRUE if count is available. * **/ gboolean nemo_file_get_directory_item_count (NemoFile *file, guint *count, gboolean *count_unreadable) { if (count != NULL) { *count = 0; } if (count_unreadable != NULL) { *count_unreadable = FALSE; } g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); if (!nemo_file_is_directory (file)) { return FALSE; } if (!nemo_file_should_show_directory_item_count (file)) { return FALSE; } return NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_item_count (file, count, count_unreadable); } /** * nemo_file_get_deep_counts * * Get the statistics about items inside a directory. * @file: NemoFile representing a directory or file. * @directory_count: Place to put count of directories inside. * @files_count: Place to put count of files inside. * @unreadable_directory_count: Number of directories encountered * that were unreadable. * @total_size: Total size of all files and directories visited. * @force: Whether the deep counts should even be collected if * nemo_file_should_show_directory_item_count returns FALSE * for this file. * * Returns: Status to indicate whether sizes are available. * **/ NemoRequestStatus nemo_file_get_deep_counts (NemoFile *file, guint *directory_count, guint *file_count, guint *unreadable_directory_count, guint *hidden_count, goffset *total_size, gboolean force) { if (directory_count != NULL) { *directory_count = 0; } if (file_count != NULL) { *file_count = 0; } if (unreadable_directory_count != NULL) { *unreadable_directory_count = 0; } if (total_size != NULL) { *total_size = 0; } if (hidden_count != NULL) { *hidden_count = 0; } g_return_val_if_fail (NEMO_IS_FILE (file), NEMO_REQUEST_DONE); if (!force && !nemo_file_should_show_directory_item_count (file)) { /* Set field so an existing value isn't treated as up-to-date * when preference changes later. */ file->details->deep_counts_status = NEMO_REQUEST_NOT_STARTED; return file->details->deep_counts_status; } return NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->get_deep_counts (file, directory_count, file_count, unreadable_directory_count, hidden_count, total_size); } void nemo_file_recompute_deep_counts (NemoFile *file) { if (file->details->deep_counts_status != NEMO_REQUEST_IN_PROGRESS) { file->details->deep_counts_status = NEMO_REQUEST_NOT_STARTED; if (file->details->directory != NULL) { nemo_directory_add_file_to_work_queue (file->details->directory, file); nemo_directory_async_state_changed (file->details->directory); } } } /** * nemo_file_get_directory_item_mime_types * * Get the list of mime-types present in a directory. * @file: NemoFile representing a directory. It is an error to * call this function on a file that is not a directory. * @mime_list: Place to put the list of mime-types. * * Returns: TRUE if mime-type list is available. * **/ gboolean nemo_file_get_directory_item_mime_types (NemoFile *file, GList **mime_list) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); g_return_val_if_fail (mime_list != NULL, FALSE); if (!nemo_file_is_directory (file) || !file->details->got_mime_list) { *mime_list = NULL; return FALSE; } *mime_list = eel_g_str_list_copy (file->details->mime_list); return TRUE; } gboolean nemo_file_can_get_size (NemoFile *file) { return file->details->size == -1; } /** * nemo_file_get_size * * Get the file size. * @file: NemoFile representing the file in question. * * Returns: Size in bytes. * **/ goffset nemo_file_get_size (NemoFile *file) { /* Before we have info on the file, we don't know the size. */ if (file->details->size == -1) return 0; return file->details->size; } time_t nemo_file_get_mtime (NemoFile *file) { return file->details->mtime; } time_t nemo_file_get_ctime (NemoFile *file) { return file->details->ctime; } static void set_attributes_get_info_callback (GObject *source_object, GAsyncResult *res, gpointer callback_data) { NemoFileOperation *op; GFileInfo *new_info; GError *error; op = callback_data; error = NULL; new_info = g_file_query_info_finish (G_FILE (source_object), res, &error); if (new_info != NULL) { if (nemo_file_update_info (op->file, new_info)) { nemo_file_changed (op->file); } g_object_unref (new_info); } nemo_file_operation_complete (op, NULL, error); if (error) { g_error_free (error); } } static void set_attributes_callback (GObject *source_object, GAsyncResult *result, gpointer callback_data) { NemoFileOperation *op; GError *error; gboolean res; op = callback_data; error = NULL; res = g_file_set_attributes_finish (G_FILE (source_object), result, NULL, &error); if (res) { g_file_query_info_async (G_FILE (source_object), NEMO_FILE_DEFAULT_ATTRIBUTES, 0, G_PRIORITY_DEFAULT, op->cancellable, set_attributes_get_info_callback, op); } else { nemo_file_operation_complete (op, NULL, error); g_error_free (error); } } void nemo_file_set_attributes (NemoFile *file, GFileInfo *attributes, NemoFileOperationCallback callback, gpointer callback_data) { NemoFileOperation *op; GFile *location; op = nemo_file_operation_new (file, callback, callback_data); location = nemo_file_get_location (file); g_file_set_attributes_async (location, attributes, 0, G_PRIORITY_DEFAULT, op->cancellable, set_attributes_callback, op); g_object_unref (location); } /** * nemo_file_can_get_permissions: * * Check whether the permissions for a file are determinable. * This might not be the case for files on non-UNIX file systems. * * @file: The file in question. * * Return value: TRUE if the permissions are valid. */ gboolean nemo_file_can_get_permissions (NemoFile *file) { return file->details->has_permissions; } /** * nemo_file_can_set_permissions: * * Check whether the current user is allowed to change * the permissions of a file. * * @file: The file in question. * * Return value: TRUE if the current user can change the * permissions of @file, FALSE otherwise. It's always possible * that when you actually try to do it, you will fail. */ gboolean nemo_file_can_set_permissions (NemoFile *file) { uid_t user_id; if (file->details->uid != -1 && nemo_file_is_local (file)) { /* Check the user. */ user_id = geteuid(); /* Owner is allowed to set permissions. */ if (user_id == (uid_t) file->details->uid) { return TRUE; } /* Root is also allowed to set permissions. */ if (user_id == 0) { return TRUE; } /* Nobody else is allowed. */ return FALSE; } /* pretend to have full chmod rights when no info is available, relevant when * the FS can't provide ownership info, for instance for FTP */ return TRUE; } guint nemo_file_get_permissions (NemoFile *file) { g_return_val_if_fail (nemo_file_can_get_permissions (file), 0); return file->details->permissions; } /** * nemo_file_set_permissions: * * Change a file's permissions. This should only be called if * nemo_file_can_set_permissions returned TRUE. * * @file: NemoFile representing the file in question. * @new_permissions: New permissions value. This is the whole * set of permissions, not a delta. **/ void nemo_file_set_permissions (NemoFile *file, guint32 new_permissions, NemoFileOperationCallback callback, gpointer callback_data) { GFileInfo *info; GError *error; if (!nemo_file_can_set_permissions (file)) { /* Claim that something changed even if the permission change failed. * This makes it easier for some clients who see the "reverting" * to the old permissions as "changing back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("Not allowed to set permissions")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* Test the permissions-haven't-changed case explicitly * because we don't want to send the file-changed signal if * nothing changed. */ if (new_permissions == file->details->permissions) { (* callback) (file, NULL, NULL, callback_data); return; } if (!nemo_file_undo_manager_pop_flag ()) { NemoFileUndoInfo *undo_info; undo_info = nemo_file_undo_info_permissions_new (nemo_file_get_location (file), file->details->permissions, new_permissions); nemo_file_undo_manager_set_action (undo_info); } info = g_file_info_new (); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, new_permissions); nemo_file_set_attributes (file, info, callback, callback_data); g_object_unref (info); } /** * nemo_file_can_get_selinux_context: * * Check whether the selinux context for a file are determinable. * This might not be the case for files on non-UNIX file systems, * files without a context or systems that don't support selinux. * * @file: The file in question. * * Return value: TRUE if the permissions are valid. */ gboolean nemo_file_can_get_selinux_context (NemoFile *file) { return file->details->selinux_context != NULL; } /** * nemo_file_get_selinux_context: * * Get a user-displayable string representing a file's selinux * context * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ char * nemo_file_get_selinux_context (NemoFile *file) { char *translated; char *raw; g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (!nemo_file_can_get_selinux_context (file)) { return NULL; } raw = file->details->selinux_context; #ifdef HAVE_SELINUX if (selinux_raw_to_trans_context (raw, &translated) == 0) { char *tmp; tmp = g_strdup (translated); freecon (translated); translated = tmp; } else #endif { translated = g_strdup (raw); } return translated; } static char * get_real_name (const char *name, const char *gecos) { char *locale_string, *part_before_comma, *capitalized_login_name, *real_name; if (gecos == NULL) { return NULL; } locale_string = eel_str_strip_substring_and_after (gecos, ","); if (!g_utf8_validate (locale_string, -1, NULL)) { part_before_comma = g_locale_to_utf8 (locale_string, -1, NULL, NULL, NULL); g_free (locale_string); } else { part_before_comma = locale_string; } if (!g_utf8_validate (name, -1, NULL)) { locale_string = g_locale_to_utf8 (name, -1, NULL, NULL, NULL); } else { locale_string = g_strdup (name); } capitalized_login_name = eel_str_capitalize (locale_string); g_free (locale_string); if (capitalized_login_name == NULL) { real_name = part_before_comma; } else { real_name = eel_str_replace_substring (part_before_comma, "&", capitalized_login_name); g_free (part_before_comma); } if (g_strcmp0 (real_name, NULL) == 0 || g_strcmp0 (name, real_name) == 0 || g_strcmp0 (capitalized_login_name, real_name) == 0) { g_free (real_name); real_name = NULL; } g_free (capitalized_login_name); return real_name; } static gboolean get_group_id_from_group_name (const char *group_name, uid_t *gid) { struct group *group; g_assert (gid != NULL); group = getgrnam (group_name); if (group == NULL) { return FALSE; } *gid = group->gr_gid; return TRUE; } static gboolean get_ids_from_user_name (const char *user_name, uid_t *uid, uid_t *gid) { struct passwd *password_info; g_assert (uid != NULL || gid != NULL); password_info = getpwnam (user_name); if (password_info == NULL) { return FALSE; } if (uid != NULL) { *uid = password_info->pw_uid; } if (gid != NULL) { *gid = password_info->pw_gid; } return TRUE; } static gboolean get_user_id_from_user_name (const char *user_name, uid_t *id) { return get_ids_from_user_name (user_name, id, NULL); } static gboolean get_id_from_digit_string (const char *digit_string, uid_t *id) { long scanned_id; char c; g_assert (id != NULL); /* Only accept string if it has one integer with nothing * afterwards. */ if (sscanf (digit_string, "%ld%c", &scanned_id, &c) != 1) { return FALSE; } *id = scanned_id; return TRUE; } /** * nemo_file_can_get_owner: * * Check whether the owner a file is determinable. * This might not be the case for files on non-UNIX file systems. * * @file: The file in question. * * Return value: TRUE if the owner is valid. */ gboolean nemo_file_can_get_owner (NemoFile *file) { /* Before we have info on a file, the owner is unknown. */ return file->details->uid != -1; } /** * nemo_file_get_owner_name: * * Get the user name of the file's owner. If the owner has no * name, returns the userid as a string. The caller is responsible * for g_free-ing this string. * * @file: The file in question. * * Return value: A newly-allocated string. */ char * nemo_file_get_owner_name (NemoFile *file) { return nemo_file_get_owner_as_string (file, FALSE); } /** * nemo_file_can_set_owner: * * Check whether the current user is allowed to change * the owner of a file. * * @file: The file in question. * * Return value: TRUE if the current user can change the * owner of @file, FALSE otherwise. It's always possible * that when you actually try to do it, you will fail. */ gboolean nemo_file_can_set_owner (NemoFile *file) { /* Not allowed to set the owner if we can't * even read it. This can happen on non-UNIX file * systems. */ if (!nemo_file_can_get_owner (file)) { return FALSE; } /* Only root is also allowed to set the owner. */ return geteuid() == 0; } /** * nemo_file_set_owner: * * Set the owner of a file. This will only have any effect if * nemo_file_can_set_owner returns TRUE. * * @file: The file in question. * @user_name_or_id: The user name to set the owner to. * If the string does not match any user name, and the * string is an integer, the owner will be set to the * userid represented by that integer. * @callback: Function called when asynch owner change succeeds or fails. * @callback_data: Parameter passed back with callback function. */ void nemo_file_set_owner (NemoFile *file, const char *user_name_or_id, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; GFileInfo *info; uid_t new_id; if (!nemo_file_can_set_owner (file)) { /* Claim that something changed even if the permission * change failed. This makes it easier for some * clients who see the "reverting" to the old owner as * "changing back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("Not allowed to set owner")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* If no match treating user_name_or_id as name, try treating * it as id. */ if (!get_user_id_from_user_name (user_name_or_id, &new_id) && !get_id_from_digit_string (user_name_or_id, &new_id)) { /* Claim that something changed even if the permission * change failed. This makes it easier for some * clients who see the "reverting" to the old owner as * "changing back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Specified owner '%s' doesn't exist"), user_name_or_id); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* Test the owner-hasn't-changed case explicitly because we * don't want to send the file-changed signal if nothing * changed. */ if (new_id == (uid_t) file->details->uid) { (* callback) (file, NULL, NULL, callback_data); return; } if (!nemo_file_undo_manager_pop_flag ()) { NemoFileUndoInfo *undo_info; char* current_owner; current_owner = nemo_file_get_owner_as_string (file, FALSE); undo_info = nemo_file_undo_info_ownership_new (NEMO_FILE_UNDO_OP_CHANGE_OWNER, nemo_file_get_location (file), current_owner, user_name_or_id); nemo_file_undo_manager_set_action (undo_info); g_free (current_owner); } info = g_file_info_new (); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, new_id); nemo_file_set_attributes (file, info, callback, callback_data); g_object_unref (info); } /** * nemo_get_user_names: * * Get a list of user names. For users with a different associated * "real name", the real name follows the standard user name, separated * by a carriage return. The caller is responsible for freeing this list * and its contents. */ GList * nemo_get_user_names (void) { GList *list; char *real_name, *name; struct passwd *user; list = NULL; setpwent (); while ((user = getpwent ()) != NULL) { real_name = get_real_name (user->pw_name, user->pw_gecos); if (real_name != NULL) { name = g_strconcat (user->pw_name, "\n", real_name, NULL); } else { name = g_strdup (user->pw_name); } g_free (real_name); list = g_list_prepend (list, name); } endpwent (); return g_list_sort (list, (GCompareFunc) g_utf8_collate); } /** * nemo_file_can_get_group: * * Check whether the group a file is determinable. * This might not be the case for files on non-UNIX file systems. * * @file: The file in question. * * Return value: TRUE if the group is valid. */ gboolean nemo_file_can_get_group (NemoFile *file) { /* Before we have info on a file, the group is unknown. */ return file->details->gid != -1; } /** * nemo_file_get_group_name: * * Get the name of the file's group. If the group has no * name, returns the groupid as a string. The caller is responsible * for g_free-ing this string. * * @file: The file in question. * * Return value: A newly-allocated string. **/ char * nemo_file_get_group_name (NemoFile *file) { return g_strdup (eel_ref_str_peek (file->details->group)); } /** * nemo_file_can_set_group: * * Check whether the current user is allowed to change * the group of a file. * * @file: The file in question. * * Return value: TRUE if the current user can change the * group of @file, FALSE otherwise. It's always possible * that when you actually try to do it, you will fail. */ gboolean nemo_file_can_set_group (NemoFile *file) { uid_t user_id; /* Not allowed to set the permissions if we can't * even read them. This can happen on non-UNIX file * systems. */ if (!nemo_file_can_get_group (file)) { return FALSE; } /* Check the user. */ user_id = geteuid(); /* Owner is allowed to set group (with restrictions). */ if (user_id == (uid_t) file->details->uid) { return TRUE; } /* Root is also allowed to set group. */ if (user_id == 0) { return TRUE; } /* Nobody else is allowed. */ return FALSE; } /* Get a list of group names, filtered to only the ones * that contain the given username. If the username is * NULL, returns a list of all group names. */ static GList * nemo_get_group_names_for_user (void) { GList *list; struct group *group; int count, i; gid_t gid_list[NGROUPS_MAX + 1]; list = NULL; count = getgroups (NGROUPS_MAX + 1, gid_list); for (i = 0; i < count; i++) { group = getgrgid (gid_list[i]); if (group == NULL) break; list = g_list_prepend (list, g_strdup (group->gr_name)); } return g_list_sort (list, (GCompareFunc) g_utf8_collate); } /** * nemo_get_group_names: * * Get a list of all group names. */ GList * nemo_get_all_group_names (void) { GList *list; struct group *group; list = NULL; setgrent (); while ((group = getgrent ()) != NULL) list = g_list_prepend (list, g_strdup (group->gr_name)); endgrent (); return g_list_sort (list, (GCompareFunc) g_utf8_collate); } /** * nemo_file_get_settable_group_names: * * Get a list of all group names that the current user * can set the group of a specific file to. * * @file: The NemoFile in question. */ GList * nemo_file_get_settable_group_names (NemoFile *file) { uid_t user_id; GList *result; if (!nemo_file_can_set_group (file)) { return NULL; } /* Check the user. */ user_id = geteuid(); if (user_id == 0) { /* Root is allowed to set group to anything. */ result = nemo_get_all_group_names (); } else if (user_id == (uid_t) file->details->uid) { /* Owner is allowed to set group to any that owner is member of. */ result = nemo_get_group_names_for_user (); } else { g_warning ("unhandled case in nemo_get_settable_group_names"); result = NULL; } return result; } /** * nemo_file_set_group: * * Set the group of a file. This will only have any effect if * nemo_file_can_set_group returns TRUE. * * @file: The file in question. * @group_name_or_id: The group name to set the owner to. * If the string does not match any group name, and the * string is an integer, the group will be set to the * group id represented by that integer. * @callback: Function called when asynch group change succeeds or fails. * @callback_data: Parameter passed back with callback function. */ void nemo_file_set_group (NemoFile *file, const char *group_name_or_id, NemoFileOperationCallback callback, gpointer callback_data) { GError *error; GFileInfo *info; uid_t new_id; if (!nemo_file_can_set_group (file)) { /* Claim that something changed even if the group * change failed. This makes it easier for some * clients who see the "reverting" to the old group as * "changing back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("Not allowed to set group")); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } /* If no match treating group_name_or_id as name, try treating * it as id. */ if (!get_group_id_from_group_name (group_name_or_id, &new_id) && !get_id_from_digit_string (group_name_or_id, &new_id)) { /* Claim that something changed even if the group * change failed. This makes it easier for some * clients who see the "reverting" to the old group as * "changing back". */ nemo_file_changed (file); error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Specified group '%s' doesn't exist"), group_name_or_id); (* callback) (file, NULL, error, callback_data); g_error_free (error); return; } if (new_id == (gid_t) file->details->gid) { (* callback) (file, NULL, NULL, callback_data); return; } if (!nemo_file_undo_manager_pop_flag ()) { NemoFileUndoInfo *undo_info; char *current_group; current_group = nemo_file_get_group_name (file); undo_info = nemo_file_undo_info_ownership_new (NEMO_FILE_UNDO_OP_CHANGE_GROUP, nemo_file_get_location (file), current_group, group_name_or_id); nemo_file_undo_manager_set_action (undo_info); g_free (current_group); } info = g_file_info_new (); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, new_id); nemo_file_set_attributes (file, info, callback, callback_data); g_object_unref (info); } /** * nemo_file_get_octal_permissions_as_string: * * Get a user-displayable string representing a file's permissions * as an octal number. The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_octal_permissions_as_string (NemoFile *file) { guint32 permissions; g_assert (NEMO_IS_FILE (file)); if (!nemo_file_can_get_permissions (file)) { return NULL; } permissions = file->details->permissions; return g_strdup_printf ("%03o", permissions); } /** * nemo_file_get_permissions_as_string: * * Get a user-displayable string representing a file's permissions. The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_permissions_as_string (NemoFile *file) { guint32 permissions; gboolean is_directory; gboolean is_link; gboolean suid, sgid, sticky; if (!nemo_file_can_get_permissions (file)) { return NULL; } g_assert (NEMO_IS_FILE (file)); permissions = file->details->permissions; is_directory = nemo_file_is_directory (file); is_link = nemo_file_is_symbolic_link (file); /* We use ls conventions for displaying these three obscure flags */ suid = permissions & S_ISUID; sgid = permissions & S_ISGID; sticky = permissions & S_ISVTX; return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c", is_link ? 'l' : is_directory ? 'd' : '-', permissions & S_IRUSR ? 'r' : '-', permissions & S_IWUSR ? 'w' : '-', permissions & S_IXUSR ? (suid ? 's' : 'x') : (suid ? 'S' : '-'), permissions & S_IRGRP ? 'r' : '-', permissions & S_IWGRP ? 'w' : '-', permissions & S_IXGRP ? (sgid ? 's' : 'x') : (sgid ? 'S' : '-'), permissions & S_IROTH ? 'r' : '-', permissions & S_IWOTH ? 'w' : '-', permissions & S_IXOTH ? (sticky ? 't' : 'x') : (sticky ? 'T' : '-')); } /** * nemo_file_get_owner_as_string: * * Get a user-displayable string representing a file's owner. The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * @include_real_name: Whether or not to append the real name (if any) * for this user after the user name. * * Returns: Newly allocated string ready to display to the user. * **/ char * nemo_file_get_owner_as_string (NemoFile *file, gboolean include_real_name) { char *user_name; /* Before we have info on a file, the owner is unknown. */ if (file->details->owner == NULL && file->details->owner_real == NULL) { return NULL; } if (file->details->owner_real == NULL) { user_name = g_strdup (eel_ref_str_peek (file->details->owner)); } else if (file->details->owner == NULL) { user_name = g_strdup (eel_ref_str_peek (file->details->owner_real)); } else if (include_real_name && strcmp (eel_ref_str_peek (file->details->owner), eel_ref_str_peek (file->details->owner_real)) != 0) { user_name = g_strdup_printf ("%s - %s", eel_ref_str_peek (file->details->owner), eel_ref_str_peek (file->details->owner_real)); } else { user_name = g_strdup (eel_ref_str_peek (file->details->owner)); } return user_name; } static char * format_item_count_for_display (guint item_count, gboolean includes_directories, gboolean includes_files) { g_assert (includes_directories || includes_files); return g_strdup_printf (includes_directories ? (includes_files ? ngettext ("%'u item", "%'u items", item_count) : ngettext ("%'u folder", "%'u folders", item_count)) : ngettext ("%'u file", "%'u files", item_count), item_count); } /** * nemo_file_get_size_as_string: * * Get a user-displayable string representing a file size. The caller * is responsible for g_free-ing this string. The string is an item * count for directories. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_size_as_string (NemoFile *file) { guint item_count; gboolean count_unreadable; int prefix; if (file == NULL) { return NULL; } g_assert (NEMO_IS_FILE (file)); if (nemo_file_is_directory (file)) { if (!nemo_file_get_directory_item_count (file, &item_count, &count_unreadable)) { return NULL; } return format_item_count_for_display (item_count, TRUE, TRUE); } if (file->details->size == -1) { return NULL; } prefix = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES); return g_format_size_full (file->details->size, prefix); } /** * nemo_file_get_size_as_string_with_real_size: * * Get a user-displayable string representing a file size. The caller * is responsible for g_free-ing this string. The string is an item * count for directories. * This function adds the real size in the string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_size_as_string_with_real_size (NemoFile *file) { guint item_count; gboolean count_unreadable; int prefix; if (file == NULL) { return NULL; } g_assert (NEMO_IS_FILE (file)); if (nemo_file_is_directory (file)) { if (!nemo_file_get_directory_item_count (file, &item_count, &count_unreadable)) { return NULL; } return format_item_count_for_display (item_count, TRUE, TRUE); } if (file->details->size == -1) { return NULL; } /* If base-2 or base-2-full, then prefix will be 2 (i.e. base-2), if base-10 or base-10-long then prefix will be 0 (i.e. base-0). Prefix will be added to LONG_FORMAT */ prefix = (g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES) / 2) * 2; return g_format_size_full (file->details->size, G_FORMAT_SIZE_LONG_FORMAT + prefix); } static char * nemo_file_get_deep_count_as_string_internal (NemoFile *file, gboolean report_size, gboolean report_directory_count, gboolean report_file_count) { NemoRequestStatus status; guint directory_count; guint file_count; guint unreadable_count; guint hidden_count; guint total_count; goffset total_size; int prefix; /* Must ask for size or some kind of count, but not both. */ g_assert (!report_size || (!report_directory_count && !report_file_count)); g_assert (report_size || report_directory_count || report_file_count); if (file == NULL) { return NULL; } g_assert (NEMO_IS_FILE (file)); g_assert (nemo_file_is_directory (file)); status = nemo_file_get_deep_counts (file, &directory_count, &file_count, &unreadable_count, &hidden_count, &total_size, FALSE); /* Check whether any info is available. */ if (status == NEMO_REQUEST_NOT_STARTED) { return NULL; } total_count = file_count + directory_count; if (total_count == 0) { switch (status) { case NEMO_REQUEST_IN_PROGRESS: /* Don't return confident "zero" until we're finished looking, * because of next case. */ return NULL; case NEMO_REQUEST_DONE: /* Don't return "zero" if we there were contents but we couldn't read them. */ if (unreadable_count != 0) { return NULL; } default: break; } } /* Note that we don't distinguish the "everything was readable" case * from the "some things but not everything was readable" case here. * Callers can distinguish them using nemo_file_get_deep_counts * directly if desired. */ if (report_size) { prefix = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES); return g_format_size_full (total_size, prefix); } return format_item_count_for_display (report_directory_count ? (report_file_count ? total_count : directory_count) : file_count, report_directory_count, report_file_count); } /** * nemo_file_get_deep_size_as_string: * * Get a user-displayable string representing the size of all contained * items (only makes sense for directories). The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_deep_size_as_string (NemoFile *file) { return nemo_file_get_deep_count_as_string_internal (file, TRUE, FALSE, FALSE); } /** * nemo_file_get_deep_total_count_as_string: * * Get a user-displayable string representing the count of all contained * items (only makes sense for directories). The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_deep_total_count_as_string (NemoFile *file) { return nemo_file_get_deep_count_as_string_internal (file, FALSE, TRUE, TRUE); } /** * nemo_file_get_deep_file_count_as_string: * * Get a user-displayable string representing the count of all contained * items, not including directories. It only makes sense to call this * function on a directory. The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_deep_file_count_as_string (NemoFile *file) { return nemo_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE); } /** * nemo_file_get_deep_directory_count_as_string: * * Get a user-displayable string representing the count of all contained * directories. It only makes sense to call this * function on a directory. The caller * is responsible for g_free-ing this string. * @file: NemoFile representing the file in question. * * Returns: Newly allocated string ready to display to the user. * **/ static char * nemo_file_get_deep_directory_count_as_string (NemoFile *file) { return nemo_file_get_deep_count_as_string_internal (file, FALSE, TRUE, FALSE); } /** * nemo_file_get_string_attribute: * * Get a user-displayable string from a named attribute. Use g_free to * free this string. If the value is unknown, returns NULL. You can call * nemo_file_get_string_attribute_with_default if you want a non-NULL * default. * * @file: NemoFile representing the file in question. * @attribute_name: The name of the desired attribute. The currently supported * set includes "name", "type", "detailed_type", "mime_type", "size", "deep_size", "deep_directory_count", * "deep_file_count", "deep_total_count", "date_modified", "date_changed", "date_accessed", * "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where", * "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path" * * Returns: Newly allocated string ready to display to the user, or NULL * if the value is unknown or @attribute_name is not supported. * **/ char * nemo_file_get_string_attribute_q (NemoFile *file, GQuark attribute_q) { char *extension_attribute; if (attribute_q == attribute_name_q) { return nemo_file_get_display_name (file); } if (attribute_q == attribute_type_q) { return nemo_file_get_type_as_string (file); } if (attribute_q == attribute_detailed_type_q) { return nemo_file_get_detailed_type_as_string (file); } if (attribute_q == attribute_mime_type_q) { return nemo_file_get_mime_type (file); } if (attribute_q == attribute_size_q) { return nemo_file_get_size_as_string (file); } if (attribute_q == attribute_size_detail_q) { return nemo_file_get_size_as_string_with_real_size (file); } if (attribute_q == attribute_deep_size_q) { return nemo_file_get_deep_size_as_string (file); } if (attribute_q == attribute_deep_file_count_q) { return nemo_file_get_deep_file_count_as_string (file); } if (attribute_q == attribute_deep_directory_count_q) { return nemo_file_get_deep_directory_count_as_string (file); } if (attribute_q == attribute_deep_total_count_q) { return nemo_file_get_deep_total_count_as_string (file); } if (attribute_q == attribute_trash_orig_path_q) { return nemo_file_get_trash_original_file_parent_as_string (file); } if (attribute_q == attribute_date_modified_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_MODIFIED, NEMO_DATE_FORMAT_REGULAR); } if (attribute_q == attribute_date_modified_full_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_MODIFIED, NEMO_DATE_FORMAT_FULL); } if (attribute_q == attribute_date_modified_with_time_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_MODIFIED, NEMO_DATE_FORMAT_REGULAR_WITH_TIME); } if (attribute_q == attribute_date_changed_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_CHANGED, NEMO_DATE_FORMAT_REGULAR); } if (attribute_q == attribute_date_changed_full_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_CHANGED, NEMO_DATE_FORMAT_FULL); } if (attribute_q == attribute_date_accessed_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_ACCESSED, NEMO_DATE_FORMAT_REGULAR); } if (attribute_q == attribute_date_accessed_full_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_ACCESSED, NEMO_DATE_FORMAT_FULL); } if (attribute_q == attribute_trashed_on_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_TRASHED, NEMO_DATE_FORMAT_FULL); } if (attribute_q == attribute_trashed_on_full_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_TRASHED, NEMO_DATE_FORMAT_REGULAR); } if (attribute_q == attribute_date_permissions_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_PERMISSIONS_CHANGED, NEMO_DATE_FORMAT_FULL); } if (attribute_q == attribute_date_permissions_full_q) { return nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_PERMISSIONS_CHANGED, NEMO_DATE_FORMAT_REGULAR); } if (attribute_q == attribute_permissions_q) { return nemo_file_get_permissions_as_string (file); } if (attribute_q == attribute_selinux_context_q) { return nemo_file_get_selinux_context (file); } if (attribute_q == attribute_octal_permissions_q) { return nemo_file_get_octal_permissions_as_string (file); } if (attribute_q == attribute_owner_q) { return nemo_file_get_owner_as_string (file, TRUE); } if (attribute_q == attribute_group_q) { return nemo_file_get_group_name (file); } if (attribute_q == attribute_uri_q) { return nemo_file_get_uri (file); } if (attribute_q == attribute_where_q) { return nemo_file_get_where_string (file); } if (attribute_q == attribute_link_target_q) { return nemo_file_get_symbolic_link_target_path (file); } if (attribute_q == attribute_volume_q) { return nemo_file_get_volume_name (file); } if (attribute_q == attribute_free_space_q) { return nemo_file_get_volume_free_space (file); } extension_attribute = NULL; if (file->details->pending_extension_attributes) { extension_attribute = g_hash_table_lookup (file->details->pending_extension_attributes, GINT_TO_POINTER (attribute_q)); } if (extension_attribute == NULL && file->details->extension_attributes) { extension_attribute = g_hash_table_lookup (file->details->extension_attributes, GINT_TO_POINTER (attribute_q)); } return g_strdup (extension_attribute); } char * nemo_file_get_string_attribute (NemoFile *file, const char *attribute_name) { return nemo_file_get_string_attribute_q (file, g_quark_from_string (attribute_name)); } /** * nemo_file_get_string_attribute_with_default: * * Get a user-displayable string from a named attribute. Use g_free to * free this string. If the value is unknown, returns a string representing * the unknown value, which varies with attribute. You can call * nemo_file_get_string_attribute if you want NULL instead of a default * result. * * @file: NemoFile representing the file in question. * @attribute_name: The name of the desired attribute. See the description of * nemo_file_get_string for the set of available attributes. * * Returns: Newly allocated string ready to display to the user, or a string * such as "unknown" if the value is unknown or @attribute_name is not supported. * **/ char * nemo_file_get_string_attribute_with_default_q (NemoFile *file, GQuark attribute_q) { char *result; guint item_count; gboolean count_unreadable; NemoRequestStatus status; result = nemo_file_get_string_attribute_q (file, attribute_q); if (result != NULL) { return result; } /* Supply default values for the ones we know about. */ /* FIXME bugzilla.gnome.org 40646: * Use hash table and switch statement or function pointers for speed? */ if (attribute_q == attribute_size_q) { if (!nemo_file_should_show_directory_item_count (file)) { return g_strdup ("--"); } count_unreadable = FALSE; if (nemo_file_is_directory (file)) { nemo_file_get_directory_item_count (file, &item_count, &count_unreadable); } return g_strdup (count_unreadable ? _("? items") : "..."); } if (attribute_q == attribute_deep_size_q) { status = nemo_file_get_deep_counts (file, NULL, NULL, NULL, NULL, NULL, FALSE); if (status == NEMO_REQUEST_DONE) { /* This means no contents at all were readable */ return g_strdup (_("? bytes")); } return g_strdup ("..."); } if (attribute_q == attribute_deep_file_count_q || attribute_q == attribute_deep_directory_count_q || attribute_q == attribute_deep_total_count_q) { status = nemo_file_get_deep_counts (file, NULL, NULL, NULL, NULL, NULL, FALSE); if (status == NEMO_REQUEST_DONE) { /* This means no contents at all were readable */ return g_strdup (_("? items")); } return g_strdup ("..."); } if (attribute_q == attribute_type_q || attribute_q == attribute_detailed_type_q || attribute_q == attribute_mime_type_q) { return g_strdup (_("Unknown")); } if (attribute_q == attribute_trashed_on_q) { /* If n/a */ return g_strdup (""); } if (attribute_q == attribute_trash_orig_path_q) { /* If n/a */ return g_strdup (""); } /* Fallback, use for both unknown attributes and attributes * for which we have no more appropriate default. */ return g_strdup (_("unknown")); } char * nemo_file_get_string_attribute_with_default (NemoFile *file, const char *attribute_name) { return nemo_file_get_string_attribute_with_default_q (file, g_quark_from_string (attribute_name)); } gboolean nemo_file_is_date_sort_attribute_q (GQuark attribute_q) { if (attribute_q == attribute_modification_date_q || attribute_q == attribute_date_modified_q || attribute_q == attribute_date_modified_full_q || attribute_q == attribute_date_modified_with_time_q || attribute_q == attribute_accessed_date_q || attribute_q == attribute_date_accessed_q || attribute_q == attribute_date_accessed_full_q || attribute_q == attribute_date_changed_q || attribute_q == attribute_date_changed_full_q || attribute_q == attribute_trashed_on_q || attribute_q == attribute_trashed_on_full_q || attribute_q == attribute_date_permissions_q || attribute_q == attribute_date_permissions_full_q) { return TRUE; } return FALSE; } struct { const char *icon_name; const char *display_name; } mime_type_map[] = { { "application-x-executable", N_("Program") }, { "audio-x-generic", N_("Audio") }, { "font-x-generic", N_("Font") }, { "image-x-generic", N_("Image") }, { "package-x-generic", N_("Archive") }, { "text-html", N_("Markup") }, { "text-x-generic", N_("Text") }, { "text-x-generic-template", N_("Text") }, { "text-x-script", N_("Program") }, { "video-x-generic", N_("Video") }, { "x-office-address-book", N_("Contacts") }, { "x-office-calendar", N_("Calendar") }, { "x-office-document", N_("Document") }, { "x-office-presentation", N_("Presentation") }, { "x-office-spreadsheet", N_("Spreadsheet") }, }; /* FIXME: remove this ifdef once we no longer need support for < 2.34 glib */ #ifdef GENERIC_ICON_API static char * get_basic_type_for_mime_type (const char *mime_type) { char *icon_name; char *basic_type = NULL; icon_name = g_content_type_get_generic_icon_name (mime_type); if (icon_name != NULL) { int i; for (i = 0; i < G_N_ELEMENTS (mime_type_map); i++) { if (strcmp (mime_type_map[i].icon_name, icon_name) == 0) { basic_type = g_strdup (gettext (mime_type_map[i].display_name)); break; } } } if (basic_type == NULL) { basic_type = g_strdup (_("Unknown")); } g_free (icon_name); return basic_type; } #else static char * get_basic_type_for_mime_type (const char *mime_type) { char *basic_type = NULL; GIcon *icon; icon = g_content_type_get_icon (mime_type); const gchar * const *icon_names = g_themed_icon_get_names (G_THEMED_ICON (icon)); if (icon_names != NULL) { int i, j; for (j = 0; j < g_strv_length ((gchar **) icon_names); j++) { for (i = 0; i < G_N_ELEMENTS (mime_type_map); i++) { if (strcmp (mime_type_map[i].icon_name, icon_names[j]) == 0) { basic_type = g_strdup (gettext (mime_type_map[i].display_name)); break; } } if (basic_type != NULL) break; } } if (basic_type == NULL) { basic_type = g_strdup (_("Unknown")); } g_object_unref (icon); return basic_type; } #endif static char * get_description (NemoFile *file, gboolean detailed) { const char *mime_type; g_assert (NEMO_IS_FILE (file)); mime_type = eel_ref_str_peek (file->details->mime_type); if (mime_type == NULL) { return NULL; } if (g_content_type_is_unknown (mime_type)) { if (nemo_file_is_executable (file)) { return g_strdup (_("Program")); } return g_strdup (_("Binary")); } if (strcmp (mime_type, "inode/directory") == 0) { return g_strdup (_("Folder")); } if (detailed) { char *description; description = g_content_type_get_description (mime_type); if (description != NULL) { return description; } } else { char *category; category = get_basic_type_for_mime_type (mime_type); if (category != NULL) { return category; } } return g_strdup (mime_type); } /* Takes ownership of string */ static char * update_description_for_link (NemoFile *file, char *string) { char *res; if (nemo_file_is_symbolic_link (file)) { g_assert (!nemo_file_is_broken_symbolic_link (file)); if (string == NULL) { return g_strdup (_("link")); } /* Note to localizers: convert file type string for file * (e.g. "folder", "plain text") to file type for symbolic link * to that kind of file (e.g. "link to folder"). */ res = g_strdup_printf (_("Link to %s"), string); g_free (string); return res; } return string; } char * nemo_file_get_type_as_string (NemoFile *file) { if (file == NULL) { return NULL; } if (nemo_file_is_broken_symbolic_link (file)) { return g_strdup (_("link (broken)")); } return update_description_for_link (file, get_description (file, FALSE)); } char * nemo_file_get_detailed_type_as_string (NemoFile *file) { if (file == NULL) { return NULL; } if (nemo_file_is_broken_symbolic_link (file)) { return g_strdup (_("link (broken)")); } return update_description_for_link (file, get_description (file, TRUE)); } /** * nemo_file_get_file_type * * Return this file's type. * @file: NemoFile representing the file in question. * * Returns: The type. * **/ GFileType nemo_file_get_file_type (NemoFile *file) { if (file == NULL) { return G_FILE_TYPE_UNKNOWN; } return file->details->type; } /** * nemo_file_get_mime_type * * Return this file's default mime type. * @file: NemoFile representing the file in question. * * Returns: The mime type. * **/ char * nemo_file_get_mime_type (NemoFile *file) { if (file != NULL) { g_return_val_if_fail (NEMO_IS_FILE (file), NULL); if (file->details->mime_type != NULL) { return g_strdup (eel_ref_str_peek (file->details->mime_type)); } } return g_strdup ("application/octet-stream"); } /** * nemo_file_is_mime_type * * Check whether a file is of a particular MIME type, or inherited * from it. * @file: NemoFile representing the file in question. * @mime_type: The MIME-type string to test (e.g. "text/plain") * * Return value: TRUE if @mime_type exactly matches the * file's MIME type. * **/ gboolean nemo_file_is_mime_type (NemoFile *file, const char *mime_type) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); g_return_val_if_fail (mime_type != NULL, FALSE); if (file->details->mime_type == NULL) { return FALSE; } return g_content_type_is_a (eel_ref_str_peek (file->details->mime_type), mime_type); } gboolean nemo_file_is_launchable (NemoFile *file) { gboolean type_can_be_executable; type_can_be_executable = FALSE; if (file->details->mime_type != NULL) { type_can_be_executable = g_content_type_can_be_executable (eel_ref_str_peek (file->details->mime_type)); } return type_can_be_executable && nemo_file_can_get_permissions (file) && nemo_file_can_execute (file) && nemo_file_is_executable (file) && !nemo_file_is_directory (file); } /** * nemo_file_get_emblem_icons * * Return the list of names of emblems that this file should display, * in canonical order. * @file: NemoFile representing the file in question. * * Returns: A list of emblem names. * **/ GList * nemo_file_get_emblem_icons (NemoFile *file, char **exclude) { GList *keywords, *l; GList *icons; char *icon_names[2]; char *keyword; int i; GIcon *icon; if (file == NULL) { return NULL; } g_return_val_if_fail (NEMO_IS_FILE (file), NULL); keywords = nemo_file_get_keywords (file); keywords = prepend_automatic_keywords (file, keywords); icons = NULL; for (l = keywords; l != NULL; l = l->next) { keyword = l->data; #ifdef TRASH_IS_FAST_ENOUGH if (strcmp (keyword, NEMO_FILE_EMBLEM_NAME_TRASH) == 0) { char *uri; gboolean file_is_trash; /* Leave out the trash emblem for the trash itself, since * putting a trash emblem on a trash icon is gilding the * lily. */ uri = nemo_file_get_uri (file); file_is_trash = strcmp (uri, EEL_TRASH_URI) == 0; g_free (uri); if (file_is_trash) { continue; } } #endif if (exclude) { for (i = 0; exclude[i] != NULL; i++) { if (strcmp (exclude[i], keyword) == 0) { continue; } } } icon_names[0] = g_strconcat ("emblem-", keyword, NULL); icon_names[1] = keyword; icon = g_themed_icon_new_from_names (icon_names, 2); g_free (icon_names[0]); icons = g_list_prepend (icons, icon); } g_list_free_full (keywords, g_free); return icons; } static GList * sort_keyword_list_and_remove_duplicates (GList *keywords) { GList *p; GList *duplicate_link; if (keywords != NULL) { keywords = g_list_sort (keywords, (GCompareFunc) g_utf8_collate); p = keywords; while (p->next != NULL) { if (strcmp ((const char *) p->data, (const char *) p->next->data) == 0) { duplicate_link = p->next; keywords = g_list_remove_link (keywords, duplicate_link); g_list_free_full (duplicate_link, g_free); } else { p = p->next; } } } return keywords; } /** * nemo_file_get_keywords * * Return this file's keywords. * @file: NemoFile representing the file in question. * * Returns: A list of keywords. * **/ GList * nemo_file_get_keywords (NemoFile *file) { GList *keywords; if (file == NULL) { return NULL; } g_return_val_if_fail (NEMO_IS_FILE (file), NULL); keywords = eel_g_str_list_copy (file->details->extension_emblems); keywords = g_list_concat (keywords, eel_g_str_list_copy (file->details->pending_extension_emblems)); keywords = g_list_concat (keywords, nemo_file_get_metadata_list (file, NEMO_METADATA_KEY_EMBLEMS)); return sort_keyword_list_and_remove_duplicates (keywords); } /** * nemo_file_is_symbolic_link * * Check if this file is a symbolic link. * @file: NemoFile representing the file in question. * * Returns: True if the file is a symbolic link. * **/ gboolean nemo_file_is_symbolic_link (NemoFile *file) { return file->details->is_symlink; } gboolean nemo_file_is_mountpoint (NemoFile *file) { return file->details->is_mountpoint; } GMount * nemo_file_get_mount (NemoFile *file) { if (file->details->mount) { return g_object_ref (file->details->mount); } return NULL; } static void file_mount_unmounted (GMount *mount, gpointer data) { NemoFile *file; file = NEMO_FILE (data); nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_MOUNT); } void nemo_file_set_mount (NemoFile *file, GMount *mount) { if (file->details->mount) { g_signal_handlers_disconnect_by_func (file->details->mount, file_mount_unmounted, file); g_object_unref (file->details->mount); file->details->mount = NULL; } if (mount) { file->details->mount = g_object_ref (mount); g_signal_connect (mount, "unmounted", G_CALLBACK (file_mount_unmounted), file); } } /** * nemo_file_is_broken_symbolic_link * * Check if this file is a symbolic link with a missing target. * @file: NemoFile representing the file in question. * * Returns: True if the file is a symbolic link with a missing target. * **/ gboolean nemo_file_is_broken_symbolic_link (NemoFile *file) { if (file == NULL) { return FALSE; } g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); /* Non-broken symbolic links return the target's type for get_file_type. */ return nemo_file_get_file_type (file) == G_FILE_TYPE_SYMBOLIC_LINK; } static void get_fs_free_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { NemoFile *file; guint64 free_space; GFileInfo *info; file = NEMO_FILE (user_data); free_space = (guint64)-1; info = g_file_query_filesystem_info_finish (G_FILE (source_object), res, NULL); if (info) { if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE)) { free_space = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE); } g_object_unref (info); } if (file->details->free_space != free_space) { file->details->free_space = free_space; nemo_file_emit_changed (file); } nemo_file_unref (file); } /** * nemo_file_get_volume_free_space * Get a nicely formatted char with free space on the file's volume * @file: NemoFile representing the file in question. * * Returns: newly-allocated copy of file size in a formatted string */ char * nemo_file_get_volume_free_space (NemoFile *file) { GFile *location; char *res; time_t now; int prefix; now = time (NULL); /* Update first time and then every 2 seconds */ if (file->details->free_space_read == 0 || (now - file->details->free_space_read) > 2) { file->details->free_space_read = now; location = nemo_file_get_location (file); g_file_query_filesystem_info_async (location, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, 0, NULL, get_fs_free_cb, nemo_file_ref (file)); g_object_unref (location); } res = NULL; if (file->details->free_space != (guint64)-1) { prefix = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES); res = g_format_size_full (file->details->free_space, prefix); } return res; } /** * nemo_file_get_volume_name * Get the path of the volume the file resides on * @file: NemoFile representing the file in question. * * Returns: newly-allocated copy of the volume name of the target file, * if the volume name isn't set, it returns the mount path of the volume */ char * nemo_file_get_volume_name (NemoFile *file) { GFile *location; char *res; GMount *mount; res = NULL; location = nemo_file_get_location (file); mount = g_file_find_enclosing_mount (location, NULL, NULL); if (mount) { res = g_strdup (g_mount_get_name (mount)); g_object_unref (mount); } g_object_unref (location); return res; } /** * nemo_file_get_symbolic_link_target_path * * Get the file path of the target of a symbolic link. It is an error * to call this function on a file that isn't a symbolic link. * @file: NemoFile representing the symbolic link in question. * * Returns: newly-allocated copy of the file path of the target of the symbolic link. */ char * nemo_file_get_symbolic_link_target_path (NemoFile *file) { if (!nemo_file_is_symbolic_link (file)) { g_warning ("File has symlink target, but is not marked as symlink"); } return g_strdup (file->details->symlink_name); } /** * nemo_file_get_symbolic_link_target_uri * * Get the uri of the target of a symbolic link. It is an error * to call this function on a file that isn't a symbolic link. * @file: NemoFile representing the symbolic link in question. * * Returns: newly-allocated copy of the uri of the target of the symbolic link. */ char * nemo_file_get_symbolic_link_target_uri (NemoFile *file) { GFile *location, *parent, *target; char *target_uri; if (!nemo_file_is_symbolic_link (file)) { g_warning ("File has symlink target, but is not marked as symlink"); } if (file->details->symlink_name == NULL) { return NULL; } else { target = NULL; location = nemo_file_get_location (file); parent = g_file_get_parent (location); g_object_unref (location); if (parent) { target = g_file_resolve_relative_path (parent, file->details->symlink_name); g_object_unref (parent); } target_uri = NULL; if (target) { target_uri = g_file_get_uri (target); g_object_unref (target); } return target_uri; } } /** * nemo_file_is_nemo_link * * Check if this file is a "nemo link", meaning a historical * nemo xml link file or a desktop file. * @file: NemoFile representing the file in question. * * Returns: True if the file is a nemo link. * **/ gboolean nemo_file_is_nemo_link (NemoFile *file) { if (file->details->mime_type == NULL) { return FALSE; } return g_content_type_equals (eel_ref_str_peek (file->details->mime_type), "application/x-desktop"); } /** * nemo_file_is_directory * * Check if this file is a directory. * @file: NemoFile representing the file in question. * * Returns: TRUE if @file is a directory. * **/ gboolean nemo_file_is_directory (NemoFile *file) { return nemo_file_get_file_type (file) == G_FILE_TYPE_DIRECTORY; } /** * nemo_file_is_user_special_directory * * Check if this file is a special platform directory. * @file: NemoFile representing the file in question. * @special_directory: GUserDirectory representing the type to test for * * Returns: TRUE if @file is a special directory of the given kind. */ gboolean nemo_file_is_user_special_directory (NemoFile *file, GUserDirectory special_directory) { gboolean is_special_dir; const gchar *special_dir; special_dir = g_get_user_special_dir (special_directory); is_special_dir = FALSE; if (special_dir) { GFile *loc; GFile *special_gfile; loc = nemo_file_get_location (file); special_gfile = g_file_new_for_path (special_dir); is_special_dir = g_file_equal (loc, special_gfile); g_object_unref (special_gfile); g_object_unref (loc); } return is_special_dir; } static const char * fallback_mime_types[] = { "application/x-gtar", "application/x-zip", "application/x-zip-compressed", "application/zip", "application/x-zip", "application/x-tar", "application/x-7z-compressed", "application/x-rar", "application/x-rar-compressed", "application/x-jar", "application/x-java-archive", "application/x-war", "application/x-ear", "application/x-arj", "application/x-gzip", "application/x-bzip-compressed-tar", "application/x-compressed-tar", "application/x-xz-compressed-tar" }; gboolean nemo_file_is_archive (NemoFile *file) { gchar *mime_type; gint i; g_return_val_if_fail (file != NULL, FALSE); mime_type = nemo_file_get_mime_type (file); if (file_roller_mimetypes != NULL) { for (i = 0; i < g_strv_length (file_roller_mimetypes); i++) { if (!strcmp (mime_type, file_roller_mimetypes[i])) { g_free (mime_type); return TRUE; } } } else { for (i = 0; i < G_N_ELEMENTS (fallback_mime_types); i++) { if (!strcmp (mime_type, fallback_mime_types[i])) { g_free (mime_type); return TRUE; } } } g_free (mime_type); return FALSE; } /** * nemo_file_is_in_trash * * Check if this file is a file in trash. * @file: NemoFile representing the file in question. * * Returns: TRUE if @file is in a trash. * **/ gboolean nemo_file_is_in_trash (NemoFile *file) { g_assert (NEMO_IS_FILE (file)); return nemo_directory_is_in_trash (file->details->directory); } /** * nemo_file_is_in_recent * * Check if this file is a file in Recent. * @file: NemoFile representing the file in question. * * Returns: TRUE if @file is in Recent. * **/ gboolean nemo_file_is_in_recent (NemoFile *file) { g_assert (NEMO_IS_FILE (file)); return nemo_directory_is_in_recent (file->details->directory); } GError * nemo_file_get_file_info_error (NemoFile *file) { if (!file->details->get_info_failed) { return NULL; } return file->details->get_info_error; } /** * nemo_file_contains_text * * Check if this file contains text. * This is private and is used to decide whether or not to read the top left text. * @file: NemoFile representing the file in question. * * Returns: TRUE if @file has a text MIME type. * **/ gboolean nemo_file_contains_text (NemoFile *file) { if (file == NULL) { return FALSE; } /* All text files inherit from text/plain */ return nemo_file_is_mime_type (file, "text/plain"); } /** * nemo_file_is_executable * * Check if this file is executable at all. * @file: NemoFile representing the file in question. * * Returns: TRUE if any of the execute bits are set. FALSE if * not, or if the permissions are unknown. * **/ gboolean nemo_file_is_executable (NemoFile *file) { if (!file->details->has_permissions) { /* File's permissions field is not valid. * Can't access specific permissions, so return FALSE. */ return FALSE; } return file->details->can_execute; } char * nemo_file_get_filesystem_id (NemoFile *file) { return g_strdup (eel_ref_str_peek (file->details->filesystem_id)); } NemoFile * nemo_file_get_trash_original_file (NemoFile *file) { GFile *location; NemoFile *original_file; original_file = NULL; if (file->details->trash_orig_path != NULL) { location = g_file_new_for_path (file->details->trash_orig_path); original_file = nemo_file_get (location); g_object_unref (location); } return original_file; } void nemo_file_mark_gone (NemoFile *file) { NemoDirectory *directory; if (file->details->is_gone) return; file->details->is_gone = TRUE; update_links_if_target (file); /* Drop it from the symlink hash ! */ remove_from_link_hash_table (file); /* Let the directory know it's gone. */ directory = file->details->directory; if (!nemo_file_is_self_owned (file)) { nemo_directory_remove_file (directory, file); } nemo_file_clear_info (file); /* FIXME bugzilla.gnome.org 42429: * Maybe we can get rid of the name too eventually, but * for now that would probably require too many if statements * everywhere anyone deals with the name. Maybe we can give it * a hard-coded "" name or something. */ } /** * nemo_file_changed * * Notify the user that this file has changed. * @file: NemoFile representing the file in question. **/ void nemo_file_changed (NemoFile *file) { GList fake_list; g_return_if_fail (NEMO_IS_FILE (file)); if (nemo_file_is_self_owned (file)) { nemo_file_emit_changed (file); } else { fake_list.data = file; fake_list.next = NULL; fake_list.prev = NULL; nemo_directory_emit_change_signals (file->details->directory, &fake_list); } } /** * nemo_file_updated_deep_count_in_progress * * Notify clients that a newer deep count is available for * the directory in question. */ void nemo_file_updated_deep_count_in_progress (NemoFile *file) { GList *link_files, *node; g_assert (NEMO_IS_FILE (file)); g_assert (nemo_file_is_directory (file)); /* Send out a signal. */ g_signal_emit (file, signals[UPDATED_DEEP_COUNT_IN_PROGRESS], 0, file); /* Tell link files pointing to this object about the change. */ link_files = get_link_files (file); for (node = link_files; node != NULL; node = node->next) { nemo_file_updated_deep_count_in_progress (NEMO_FILE (node->data)); } nemo_file_list_free (link_files); } /** * nemo_file_emit_changed * * Emit a file changed signal. * This can only be called by the directory, since the directory * also has to emit a files_changed signal. * * @file: NemoFile representing the file in question. **/ void nemo_file_emit_changed (NemoFile *file) { GList *link_files, *p; g_assert (NEMO_IS_FILE (file)); /* Send out a signal. */ g_signal_emit (file, signals[CHANGED], 0, file); /* Tell link files pointing to this object about the change. */ link_files = get_link_files (file); for (p = link_files; p != NULL; p = p->next) { if (p->data != file) { nemo_file_changed (NEMO_FILE (p->data)); } } nemo_file_list_free (link_files); } /** * nemo_file_is_gone * * Check if a file has already been deleted. * @file: NemoFile representing the file in question. * * Returns: TRUE if the file is already gone. **/ gboolean nemo_file_is_gone (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->is_gone; } /** * nemo_file_is_not_yet_confirmed * * Check if we're in a state where we don't know if a file really * exists or not, before the initial I/O is complete. * @file: NemoFile representing the file in question. * * Returns: TRUE if the file is already gone. **/ gboolean nemo_file_is_not_yet_confirmed (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return !file->details->got_file_info; } /** * nemo_file_check_if_ready * * Check whether the values for a set of file attributes are * currently available, without doing any additional work. This * is useful for callers that want to reflect updated information * when it is ready but don't want to force the work required to * obtain the information, which might be slow network calls, e.g. * * @file: The file being queried. * @file_attributes: A bit-mask with the desired information. * * Return value: TRUE if all of the specified attributes are currently readable. */ gboolean nemo_file_check_if_ready (NemoFile *file, NemoFileAttributes file_attributes) { /* To be parallel with call_when_ready, return * TRUE for NULL file. */ if (file == NULL) { return TRUE; } g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->check_if_ready (file, file_attributes); } void nemo_file_call_when_ready (NemoFile *file, NemoFileAttributes file_attributes, NemoFileCallback callback, gpointer callback_data) { if (file == NULL) { (* callback) (file, callback_data); return; } g_return_if_fail (NEMO_IS_FILE (file)); NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->call_when_ready (file, file_attributes, callback, callback_data); } void nemo_file_cancel_call_when_ready (NemoFile *file, NemoFileCallback callback, gpointer callback_data) { g_return_if_fail (callback != NULL); if (file == NULL) { return; } g_return_if_fail (NEMO_IS_FILE (file)); NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->cancel_call_when_ready (file, callback, callback_data); } static GString * add_line (GString *string, const gchar *add, gboolean prefix_newline) { if (prefix_newline) string = g_string_append (string, "\n"); return g_string_append (string, add); } gchar * nemo_file_construct_tooltip (NemoFile *file, NemoFileTooltipFlags flags) { gchar *scheme = nemo_file_get_uri_scheme (file); gchar *nice = NULL; gchar *tmp = NULL; gchar *date; gchar *ret; if (g_strcmp0 (scheme, "x-nemo-desktop") == 0) { g_free (scheme); return NULL; } GString *string = g_string_new (""); tmp = nemo_file_get_display_name (file); nice = g_strdup_printf (_("Name: %s"), tmp); string = add_line (string, nice, FALSE); g_free (nice); g_free (tmp); if (flags & NEMO_FILE_TOOLTIP_FLAGS_FILE_TYPE) { tmp = nemo_file_get_detailed_type_as_string (file); nice = g_strdup_printf (_("Type: %s"), tmp); string = add_line (string, nice, TRUE); g_free (tmp); g_free (nice); } if (nemo_file_is_directory (file)) { gint item_count; if (nemo_file_get_directory_item_count (file, &item_count, NULL)) { gchar *launchpad_sucks = THOU_TO_STR (item_count); gchar *count = g_strdup_printf (ngettext ("%s item", "%s items", item_count), launchpad_sucks); g_free (launchpad_sucks); nice = g_strdup_printf (_("Contains: %s"), count); string = add_line (string, nice, TRUE); g_free (count); g_free (nice); } } else { gchar *size_string; gint prefix; prefix = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SIZE_PREFIXES); size_string = g_format_size_full (nemo_file_get_size (file), prefix); nice = g_strdup_printf (_("Size: %s"), size_string); string = add_line (string, nice, TRUE); g_free (size_string); g_free (nice); } if (flags & NEMO_FILE_TOOLTIP_FLAGS_ACCESS_DATE) { date = nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_ACCESSED, TRUE); tmp = g_strdup_printf (_("Accessed: %s"), date); g_free (date); string = add_line (string, tmp, TRUE); g_free (tmp); } if (flags & NEMO_FILE_TOOLTIP_FLAGS_MOD_DATE) { date = nemo_file_get_date_as_string (file, NEMO_DATE_TYPE_MODIFIED, TRUE); tmp = g_strdup_printf (_("Modified: %s"), date); g_free (date); string = add_line (string, tmp, TRUE); g_free (tmp); } if (flags & NEMO_FILE_TOOLTIP_FLAGS_PATH) { NemoFile *parent = nemo_file_get_parent (file); tmp = nemo_file_get_path (parent); nice = g_strdup_printf (_("Location: %s"), tmp); string = add_line (string, nice, TRUE); g_free (tmp); g_free (nice); if (nemo_file_is_symbolic_link (file)) { tmp = nemo_file_get_symbolic_link_target_path (file); const gchar *existing_i18n = _("Link target:"); nice = g_strdup_printf ("%s %s", existing_i18n, tmp); string = add_line (string, nice, TRUE); g_free (tmp); g_free (nice); } } ret = string->str; g_string_free (string, FALSE); return ret; } gint nemo_file_get_monitor_number (NemoFile *file) { if (file->details->desktop_monitor == -1) { file->details->desktop_monitor = nemo_file_get_integer_metadata (file, NEMO_METADATA_KEY_MONITOR, -1); } return file->details->desktop_monitor; } void nemo_file_set_monitor_number (NemoFile *file, gint monitor) { nemo_file_set_integer_metadata (file, NEMO_METADATA_KEY_MONITOR, -1, monitor); file->details->desktop_monitor = monitor; } void nemo_file_get_position (NemoFile *file, GdkPoint *point) { gint x, y; if (file->details->cached_position_x == -1) { char *position_string; gboolean position_good; char c; /* Get the current position of this icon from the metadata. */ position_string = nemo_file_get_metadata (file, NEMO_METADATA_KEY_ICON_POSITION, ""); position_good = sscanf (position_string, " %d , %d %c", &x, &y, &c) == 2; g_free (position_string); if (position_good) { point->x = x; point->y = y; } else { point->x = -1; point->y = -1; } file->details->cached_position_x = x; file->details->cached_position_y = y; } else { point->x = file->details->cached_position_x; point->y = file->details->cached_position_y; } } void nemo_file_set_position (NemoFile *file, gint x, gint y) { gchar *position_string; if (x > -1 && y > -1) { position_string = g_strdup_printf ("%d,%d", x, y); } else { position_string = NULL; } nemo_file_set_metadata (file, NEMO_METADATA_KEY_ICON_POSITION, NULL, position_string); file->details->cached_position_x = x; file->details->cached_position_y = y; g_free (position_string); } gboolean nemo_file_get_is_desktop_orphan (NemoFile *file) { return file->details->is_desktop_orphan; } void nemo_file_set_is_desktop_orphan (NemoFile *file, gboolean is_desktop_orphan) { file->details->is_desktop_orphan = is_desktop_orphan; } gboolean nemo_file_has_thumbnail_access_problem (NemoFile *file) { return file->details->thumbnail_access_problem; } static void invalidate_directory_count (NemoFile *file) { file->details->directory_count_is_up_to_date = FALSE; } static void invalidate_deep_counts (NemoFile *file) { file->details->deep_counts_status = NEMO_REQUEST_NOT_STARTED; } static void invalidate_mime_list (NemoFile *file) { file->details->mime_list_is_up_to_date = FALSE; } static void invalidate_file_info (NemoFile *file) { file->details->file_info_is_up_to_date = FALSE; } static void invalidate_link_info (NemoFile *file) { file->details->link_info_is_up_to_date = FALSE; } static void invalidate_thumbnail (NemoFile *file) { file->details->thumbnail_is_up_to_date = FALSE; } static void invalidate_mount (NemoFile *file) { file->details->mount_is_up_to_date = FALSE; } void nemo_file_invalidate_extension_info_internal (NemoFile *file) { if (file->details->pending_info_providers) g_list_free_full (file->details->pending_info_providers, g_object_unref); file->details->pending_info_providers = nemo_module_get_extensions_for_type (NEMO_TYPE_INFO_PROVIDER); } void nemo_file_invalidate_attributes_internal (NemoFile *file, NemoFileAttributes file_attributes) { Request request; if (file == NULL) { return; } if (NEMO_IS_DESKTOP_ICON_FILE (file)) { /* Desktop icon files are always up to date. * If we invalidate their attributes they * will lose data, so we just ignore them. */ return; } request = nemo_directory_set_up_request (file_attributes); if (REQUEST_WANTS_TYPE (request, REQUEST_DIRECTORY_COUNT)) { invalidate_directory_count (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_DEEP_COUNT)) { invalidate_deep_counts (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_MIME_LIST)) { invalidate_mime_list (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_FILE_INFO)) { invalidate_file_info (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_LINK_INFO)) { invalidate_link_info (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_EXTENSION_INFO)) { nemo_file_invalidate_extension_info_internal (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_THUMBNAIL)) { invalidate_thumbnail (file); } if (REQUEST_WANTS_TYPE (request, REQUEST_MOUNT)) { invalidate_mount (file); } /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */ } gboolean nemo_file_has_open_window (NemoFile *file) { return file->details->has_open_window; } void nemo_file_set_has_open_window (NemoFile *file, gboolean has_open_window) { has_open_window = (has_open_window != FALSE); if (file->details->has_open_window != has_open_window) { file->details->has_open_window = has_open_window; nemo_file_changed (file); } } gboolean nemo_file_is_thumbnailing (NemoFile *file) { g_return_val_if_fail (NEMO_IS_FILE (file), FALSE); return file->details->is_thumbnailing; } void nemo_file_set_is_thumbnailing (NemoFile *file, gboolean is_thumbnailing) { g_return_if_fail (NEMO_IS_FILE (file)); file->details->is_thumbnailing = is_thumbnailing; } /** * nemo_file_invalidate_attributes * * Invalidate the specified attributes and force a reload. * @file: NemoFile representing the file in question. * @file_attributes: attributes to froget. **/ void nemo_file_invalidate_attributes (NemoFile *file, NemoFileAttributes file_attributes) { /* Cancel possible in-progress loads of any of these attributes */ nemo_directory_cancel_loading_file_attributes (file->details->directory, file, file_attributes); /* Actually invalidate the values */ nemo_file_invalidate_attributes_internal (file, file_attributes); nemo_directory_add_file_to_work_queue (file->details->directory, file); /* Kick off I/O if necessary */ nemo_directory_async_state_changed (file->details->directory); } NemoFileAttributes nemo_file_get_all_attributes (void) { return NEMO_FILE_ATTRIBUTE_INFO | NEMO_FILE_ATTRIBUTE_LINK_INFO | NEMO_FILE_ATTRIBUTE_DEEP_COUNTS | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES | NEMO_FILE_ATTRIBUTE_EXTENSION_INFO | NEMO_FILE_ATTRIBUTE_THUMBNAIL | NEMO_FILE_ATTRIBUTE_MOUNT; } void nemo_file_invalidate_all_attributes (NemoFile *file) { NemoFileAttributes all_attributes; all_attributes = nemo_file_get_all_attributes (); nemo_file_invalidate_attributes (file, all_attributes); } /** * nemo_file_dump * * Debugging call, prints out the contents of the file * fields. * * @file: file to dump. **/ void nemo_file_dump (NemoFile *file) { long size = file->details->deep_size; char *uri; const char *file_kind; uri = nemo_file_get_uri (file); g_print ("uri: %s \n", uri); if (!file->details->got_file_info) { g_print ("no file info \n"); } else if (file->details->get_info_failed) { g_print ("failed to get file info \n"); } else { g_print ("size: %ld \n", size); switch (file->details->type) { case G_FILE_TYPE_REGULAR: file_kind = "regular file"; break; case G_FILE_TYPE_DIRECTORY: file_kind = "folder"; break; case G_FILE_TYPE_SPECIAL: file_kind = "special"; break; case G_FILE_TYPE_SYMBOLIC_LINK: file_kind = "symbolic link"; break; case G_FILE_TYPE_UNKNOWN: default: file_kind = "unknown"; break; } g_print ("kind: %s \n", file_kind); if (file->details->type == G_FILE_TYPE_SYMBOLIC_LINK) { g_print ("link to %s \n", file->details->symlink_name); /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */ } /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */ } g_free (uri); } /** * nemo_file_list_ref * * Ref all the files in a list. * @list: GList of files. **/ GList * nemo_file_list_ref (GList *list) { g_list_foreach (list, (GFunc) nemo_file_ref, NULL); return list; } /** * nemo_file_list_unref * * Unref all the files in a list. * @list: GList of files. **/ void nemo_file_list_unref (GList *list) { g_list_foreach (list, (GFunc) nemo_file_unref, NULL); } /** * nemo_file_list_free * * Free a list of files after unrefing them. * @list: GList of files. **/ void nemo_file_list_free (GList *list) { nemo_file_list_unref (list); g_list_free (list); } /** * nemo_file_list_copy * * Copy the list of files, making a new ref of each, * @list: GList of files. **/ GList * nemo_file_list_copy (GList *list) { return g_list_copy (nemo_file_list_ref (list)); } GList * nemo_file_list_from_uris (GList *uri_list) { GList *l, *file_list; const char *uri; GFile *file; file_list = NULL; for (l = uri_list; l != NULL; l = l->next) { uri = l->data; file = g_file_new_for_uri (uri); file_list = g_list_prepend (file_list, file); } return g_list_reverse (file_list); } static gboolean get_attributes_for_default_sort_type (NemoFile *file, gboolean *is_recent, gboolean *is_download, gboolean *is_trash) { gboolean is_recent_dir, is_download_dir, is_desktop_dir, is_trash_dir, retval; *is_recent = FALSE; *is_download = FALSE; *is_trash = FALSE; retval = FALSE; /* special handling for certain directories */ if (file && nemo_file_is_directory (file)) { is_recent_dir = nemo_file_is_in_recent (file); is_download_dir = nemo_file_is_user_special_directory (file, G_USER_DIRECTORY_DOWNLOAD); is_desktop_dir = nemo_file_is_user_special_directory (file, G_USER_DIRECTORY_DESKTOP); is_trash_dir = nemo_file_is_in_trash (file); if (is_download_dir && !is_desktop_dir) { *is_download = TRUE; retval = TRUE; } else if (is_trash_dir) { *is_trash = TRUE; retval = TRUE; } else if (is_recent_dir) { *is_recent = TRUE; retval = TRUE; } } return retval; } NemoFileSortType nemo_file_get_default_sort_type (NemoFile *file, gboolean *reversed) { NemoFileSortType retval; gboolean is_recent, is_download, is_trash, res; retval = NEMO_FILE_SORT_NONE; is_recent = is_download = is_trash = FALSE; res = get_attributes_for_default_sort_type (file, &is_recent, &is_download, &is_trash); if (res) { if (is_recent) { retval = NEMO_FILE_SORT_BY_ATIME; } else if (is_download) { retval = NEMO_FILE_SORT_BY_MTIME; } else if (is_trash) { retval = NEMO_FILE_SORT_BY_TRASHED_TIME; } if (reversed != NULL) { *reversed = res; } } return retval; } const gchar * nemo_file_get_default_sort_attribute (NemoFile *file, gboolean *reversed) { const gchar *retval; gboolean is_recent, is_download, is_trash, res; retval = NULL; is_download = is_trash = FALSE; res = get_attributes_for_default_sort_type (file, &is_recent, &is_download, &is_trash); if (res) { if (is_recent || is_download) { retval = g_quark_to_string (attribute_date_modified_q); } else if (is_trash) { retval = g_quark_to_string (attribute_trashed_on_q); } if (reversed != NULL) { *reversed = res; } } return retval; } static int compare_by_display_name_cover (gconstpointer a, gconstpointer b) { return compare_by_display_name (NEMO_FILE (a), NEMO_FILE (b)); } /** * nemo_file_list_sort_by_display_name * * Sort the list of files by file name. * @list: GList of files. **/ GList * nemo_file_list_sort_by_display_name (GList *list) { return g_list_sort (list, compare_by_display_name_cover); } static GList *ready_data_list = NULL; typedef struct { GList *file_list; GList *remaining_files; NemoFileListCallback callback; gpointer callback_data; } FileListReadyData; static void file_list_ready_data_free (FileListReadyData *data) { GList *l; l = g_list_find (ready_data_list, data); if (l != NULL) { ready_data_list = g_list_delete_link (ready_data_list, l); nemo_file_list_free (data->file_list); g_list_free (data->remaining_files); g_free (data); } } static FileListReadyData * file_list_ready_data_new (GList *file_list, NemoFileListCallback callback, gpointer callback_data) { FileListReadyData *data; data = g_new0 (FileListReadyData, 1); data->file_list = nemo_file_list_copy (file_list); data->remaining_files = g_list_copy (file_list); data->callback = callback; data->callback_data = callback_data; ready_data_list = g_list_prepend (ready_data_list, data); return data; } static void file_list_file_ready_callback (NemoFile *file, gpointer user_data) { FileListReadyData *data; data = user_data; data->remaining_files = g_list_remove (data->remaining_files, file); if (data->remaining_files == NULL) { if (data->callback) { (*data->callback) (data->file_list, data->callback_data); } file_list_ready_data_free (data); } } void nemo_file_list_call_when_ready (GList *file_list, NemoFileAttributes attributes, NemoFileListHandle **handle, NemoFileListCallback callback, gpointer callback_data) { GList *l; FileListReadyData *data; NemoFile *file; g_return_if_fail (file_list != NULL); data = file_list_ready_data_new (file_list, callback, callback_data); if (handle) { *handle = (NemoFileListHandle *) data; } l = file_list; while (l != NULL) { file = NEMO_FILE (l->data); /* Need to do this here, as the list can be modified by this call */ l = l->next; nemo_file_call_when_ready (file, attributes, file_list_file_ready_callback, data); } } void nemo_file_list_cancel_call_when_ready (NemoFileListHandle *handle) { GList *l; NemoFile *file; FileListReadyData *data; g_return_if_fail (handle != NULL); data = (FileListReadyData *) handle; l = g_list_find (ready_data_list, data); if (l != NULL) { for (l = data->remaining_files; l != NULL; l = l->next) { file = NEMO_FILE (l->data); NEMO_FILE_CLASS (G_OBJECT_GET_CLASS (file))->cancel_call_when_ready (file, file_list_file_ready_callback, data); } file_list_ready_data_free (data); } } static void thumbnail_limit_changed_callback (gpointer user_data) { g_settings_get (nemo_preferences, NEMO_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT, "t", &cached_thumbnail_limit); /* Tell the world that icons might have changed. We could invent a narrower-scope * signal to mean only "thumbnails might have changed" if this ends up being slow * for some reason. */ emit_change_signals_for_all_files_in_all_directories (); } static void thumbnail_size_changed_callback (gpointer user_data) { cached_thumbnail_size = g_settings_get_int (nemo_icon_view_preferences, NEMO_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE); /* Tell the world that icons might have changed. We could invent a narrower-scope * signal to mean only "thumbnails might have changed" if this ends up being slow * for some reason. */ emit_change_signals_for_all_files_in_all_directories (); } static void show_thumbnails_changed_callback (gpointer user_data) { show_image_thumbs = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS); /* Tell the world that icons might have changed. We could invent a narrower-scope * signal to mean only "thumbnails might have changed" if this ends up being slow * for some reason. */ emit_change_signals_for_all_files_in_all_directories (); } static void mime_type_data_changed_callback (GObject *signaller, gpointer user_data) { /* Tell the world that icons might have changed. We could invent a narrower-scope * signal to mean only "thumbnails might have changed" if this ends up being slow * for some reason. */ emit_change_signals_for_all_files_in_all_directories (); } static void icon_theme_changed_callback (GtkIconTheme *icon_theme, gpointer user_data) { /* Clear all pixmap caches as the icon => pixmap lookup changed */ nemo_icon_info_clear_caches (); /* Tell the world that icons might have changed. We could invent a narrower-scope * signal to mean only "thumbnails might have changed" if this ends up being slow * for some reason. */ emit_change_signals_for_all_files_in_all_directories (); } static void real_set_metadata (NemoFile *file, const char *key, const char *value) { /* Dummy default impl */ } static void real_set_metadata_as_list (NemoFile *file, const char *key, char **value) { /* Dummy default impl */ } static void nemo_file_class_init (NemoFileClass *class) { GtkIconTheme *icon_theme; nemo_file_info_getter = nemo_file_get_internal; attribute_name_q = g_quark_from_static_string ("name"); attribute_size_q = g_quark_from_static_string ("size"); attribute_type_q = g_quark_from_static_string ("type"); attribute_detailed_type_q = g_quark_from_static_string ("detailed_type"); attribute_modification_date_q = g_quark_from_static_string ("modification_date"); attribute_date_modified_q = g_quark_from_static_string ("date_modified"); attribute_date_modified_full_q = g_quark_from_static_string ("date_modified_full"); attribute_date_modified_with_time_q = g_quark_from_static_string ("date_modified_with_time"); attribute_accessed_date_q = g_quark_from_static_string ("accessed_date"); attribute_date_accessed_q = g_quark_from_static_string ("date_accessed"); attribute_date_accessed_full_q = g_quark_from_static_string ("date_accessed_full"); attribute_mime_type_q = g_quark_from_static_string ("mime_type"); attribute_size_detail_q = g_quark_from_static_string ("size_detail"); attribute_deep_size_q = g_quark_from_static_string ("deep_size"); attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count"); attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count"); attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count"); attribute_date_changed_q = g_quark_from_static_string ("date_changed"); attribute_date_changed_full_q = g_quark_from_static_string ("date_changed_full"); attribute_trashed_on_q = g_quark_from_static_string ("trashed_on"); attribute_trashed_on_full_q = g_quark_from_static_string ("trashed_on_full"); attribute_trash_orig_path_q = g_quark_from_static_string ("trash_orig_path"); attribute_date_permissions_q = g_quark_from_static_string ("date_permissions"); attribute_date_permissions_full_q = g_quark_from_static_string ("date_permissions_full"); attribute_permissions_q = g_quark_from_static_string ("permissions"); attribute_selinux_context_q = g_quark_from_static_string ("selinux_context"); attribute_octal_permissions_q = g_quark_from_static_string ("octal_permissions"); attribute_owner_q = g_quark_from_static_string ("owner"); attribute_group_q = g_quark_from_static_string ("group"); attribute_uri_q = g_quark_from_static_string ("uri"); attribute_where_q = g_quark_from_static_string ("where"); attribute_link_target_q = g_quark_from_static_string ("link_target"); attribute_volume_q = g_quark_from_static_string ("volume"); attribute_free_space_q = g_quark_from_static_string ("free_space"); G_OBJECT_CLASS (class)->finalize = finalize; G_OBJECT_CLASS (class)->constructor = nemo_file_constructor; class->set_metadata = real_set_metadata; class->set_metadata_as_list = real_set_metadata_as_list; class->get_metadata = NULL; class->get_metadata_as_list = NULL; signals[CHANGED] = g_signal_new ("changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoFileClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[UPDATED_DEEP_COUNT_IN_PROGRESS] = g_signal_new ("updated_deep_count_in_progress", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoFileClass, updated_deep_count_in_progress), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_class_add_private (class, sizeof (NemoFileDetails)); thumbnail_limit_changed_callback (NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT, G_CALLBACK (thumbnail_limit_changed_callback), NULL); thumbnail_size_changed_callback (NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE, G_CALLBACK (thumbnail_size_changed_callback), NULL); show_thumbnails_changed_callback (NULL); g_signal_connect_swapped (nemo_preferences, "changed::" NEMO_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS, G_CALLBACK (show_thumbnails_changed_callback), NULL); icon_theme = gtk_icon_theme_get_default (); g_signal_connect_object (icon_theme, "changed", G_CALLBACK (icon_theme_changed_callback), NULL, 0); g_signal_connect (nemo_signaller_get_current (), "mime_data_changed", G_CALLBACK (mime_type_data_changed_callback), NULL); } static void nemo_file_add_emblem (NemoFile *file, const char *emblem_name) { if (file->details->pending_info_providers) { file->details->pending_extension_emblems = g_list_prepend (file->details->pending_extension_emblems, g_strdup (emblem_name)); } else { file->details->extension_emblems = g_list_prepend (file->details->extension_emblems, g_strdup (emblem_name)); } nemo_file_changed (file); } static void nemo_file_add_string_attribute (NemoFile *file, const char *attribute_name, const char *value) { if (file->details->pending_info_providers) { /* Lazily create hashtable */ if (!file->details->pending_extension_attributes) { file->details->pending_extension_attributes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_free); } g_hash_table_insert (file->details->pending_extension_attributes, GINT_TO_POINTER (g_quark_from_string (attribute_name)), g_strdup (value)); } else { if (!file->details->extension_attributes) { file->details->extension_attributes = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)g_free); } g_hash_table_insert (file->details->extension_attributes, GINT_TO_POINTER (g_quark_from_string (attribute_name)), g_strdup (value)); } nemo_file_changed (file); } static void nemo_file_invalidate_extension_info (NemoFile *file) { nemo_file_invalidate_attributes (file, NEMO_FILE_ATTRIBUTE_EXTENSION_INFO); } void nemo_file_info_providers_done (NemoFile *file) { g_list_free_full (file->details->extension_emblems, g_free); file->details->extension_emblems = file->details->pending_extension_emblems; file->details->pending_extension_emblems = NULL; if (file->details->extension_attributes) { g_hash_table_destroy (file->details->extension_attributes); } file->details->extension_attributes = file->details->pending_extension_attributes; file->details->pending_extension_attributes = NULL; nemo_file_changed (file); } static void nemo_file_info_iface_init (NemoFileInfoIface *iface) { iface->is_gone = nemo_file_is_gone; iface->get_name = nemo_file_get_name; iface->get_file_type = nemo_file_get_file_type; iface->get_location = nemo_file_get_location; iface->get_uri = nemo_file_get_uri; iface->get_parent_location = nemo_file_get_parent_location; iface->get_parent_uri = nemo_file_get_parent_uri; iface->get_parent_info = nemo_file_get_parent; iface->get_mount = nemo_file_get_mount; iface->get_uri_scheme = nemo_file_get_uri_scheme; iface->get_activation_uri = nemo_file_get_activation_uri; iface->get_mime_type = nemo_file_get_mime_type; iface->is_mime_type = nemo_file_is_mime_type; iface->is_directory = nemo_file_is_directory; iface->can_write = nemo_file_can_write; iface->add_emblem = nemo_file_add_emblem; iface->get_string_attribute = nemo_file_get_string_attribute; iface->add_string_attribute = nemo_file_add_string_attribute; iface->invalidate_extension_info = nemo_file_invalidate_extension_info; } #if !defined (NEMO_OMIT_SELF_CHECK) void nemo_self_check_file (void) { NemoFile *file_1; NemoFile *file_2; GList *list; /* refcount checks */ EEL_CHECK_INTEGER_RESULT (nemo_directory_number_outstanding (), 0); file_1 = nemo_file_get_by_uri ("file:///home/"); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1->details->directory)->ref_count, 1); EEL_CHECK_INTEGER_RESULT (nemo_directory_number_outstanding (), 1); nemo_file_unref (file_1); EEL_CHECK_INTEGER_RESULT (nemo_directory_number_outstanding (), 0); file_1 = nemo_file_get_by_uri ("file:///etc"); file_2 = nemo_file_get_by_uri ("file:///usr"); list = NULL; list = g_list_prepend (list, file_1); list = g_list_prepend (list, file_2); nemo_file_list_ref (list); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 2); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 2); nemo_file_list_unref (list); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1); nemo_file_list_free (list); EEL_CHECK_INTEGER_RESULT (nemo_directory_number_outstanding (), 0); /* name checks */ file_1 = nemo_file_get_by_uri ("file:///home/"); EEL_CHECK_STRING_RESULT (nemo_file_get_name (file_1), "home"); EEL_CHECK_BOOLEAN_RESULT (nemo_file_get_by_uri ("file:///home/") == file_1, TRUE); nemo_file_unref (file_1); EEL_CHECK_BOOLEAN_RESULT (nemo_file_get_by_uri ("file:///home") == file_1, TRUE); nemo_file_unref (file_1); nemo_file_unref (file_1); file_1 = nemo_file_get_by_uri ("file:///home"); EEL_CHECK_STRING_RESULT (nemo_file_get_name (file_1), "home"); nemo_file_unref (file_1); #if 0 /* ALEX: I removed this, because it was breaking distchecks. * It used to work, but when canonical uris changed from * foo: to foo:/// it broke. I don't expect it to matter * in real life */ file_1 = nemo_file_get_by_uri (":"); EEL_CHECK_STRING_RESULT (nemo_file_get_name (file_1), ":"); nemo_file_unref (file_1); #endif file_1 = nemo_file_get_by_uri ("eazel:"); EEL_CHECK_STRING_RESULT (nemo_file_get_name (file_1), "eazel"); nemo_file_unref (file_1); /* sorting */ file_1 = nemo_file_get_by_uri ("file:///etc"); file_2 = nemo_file_get_by_uri ("file:///usr"); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1)->ref_count, 1); EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2)->ref_count, 1); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) < 0, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_2, NEMO_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) > 0, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_1, NEMO_FILE_SORT_BY_DISPLAY_NAME, FALSE, FALSE) == 0, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_1, NEMO_FILE_SORT_BY_DISPLAY_NAME, TRUE, FALSE) == 0, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_1, NEMO_FILE_SORT_BY_DISPLAY_NAME, FALSE, TRUE) == 0, TRUE); EEL_CHECK_BOOLEAN_RESULT (nemo_file_compare_for_sort (file_1, file_1, NEMO_FILE_SORT_BY_DISPLAY_NAME, TRUE, TRUE) == 0, TRUE); nemo_file_unref (file_1); nemo_file_unref (file_2); } #endif /* !NEMO_OMIT_SELF_CHECK */ nemo-3.6.5/libnemo-private/nemo-ui-utilities.h0000664000175000017500000000346313215733314020247 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-ui-utilities.h - helper functions for GtkUIManager stuff Copyright (C) 2004 Red Hat, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Alexander Larsson */ #ifndef NEMO_UI_UTILITIES_H #define NEMO_UI_UTILITIES_H #include #include void nemo_ui_unmerge_ui (GtkUIManager *ui_manager, guint *merge_id, GtkActionGroup **action_group); void nemo_ui_prepare_merge_ui (GtkUIManager *ui_manager, const char *name, guint *merge_id, GtkActionGroup **action_group); GtkAction * nemo_action_from_menu_item (NemoMenuItem *item, GtkWidget *parent_widget); GdkPixbuf * nemo_ui_get_menu_icon (const char *icon_name, GtkWidget *parent_widget); #endif /* NEMO_UI_UTILITIES_H */ nemo-3.6.5/libnemo-private/nemo-file-operations.h0000664000175000017500000001552413215733314020722 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-operations: execute file operations. Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ettore Perazzoli , Pavel Cisler */ #ifndef NEMO_FILE_OPERATIONS_H #define NEMO_FILE_OPERATIONS_H #include #include typedef void (* NemoCopyCallback) (GHashTable *debuting_uris, gboolean success, gpointer callback_data); typedef void (* NemoCreateCallback) (GFile *new_file, gboolean success, gpointer callback_data); typedef void (* NemoOpCallback) (gboolean success, gpointer callback_data); typedef void (* NemoDeleteCallback) (GHashTable *debuting_uris, gboolean user_cancel, gpointer callback_data); typedef void (* NemoMountCallback) (GVolume *volume, gboolean success, GObject *callback_data_object); typedef void (* NemoUnmountCallback) (gpointer callback_data); /* FIXME: int copy_action should be an enum */ void nemo_file_operations_copy_move (const GList *item_uris, GArray *relative_item_points, const char *target_dir_uri, GdkDragAction copy_action, GtkWidget *parent_view, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_operations_copy_file (GFile *source_file, GFile *target_dir, const gchar *source_display_name, const gchar *new_name, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_operations_empty_trash (GtkWidget *parent_view); void nemo_file_operations_new_folder (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir_uri, NemoCreateCallback done_callback, gpointer done_callback_data); void nemo_file_operations_new_file (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir, const char *target_filename, const char *initial_contents, int length, NemoCreateCallback done_callback, gpointer data); void nemo_file_operations_new_file_from_template (GtkWidget *parent_view, GdkPoint *target_point, const char *parent_dir, const char *target_filename, const char *template_uri, NemoCreateCallback done_callback, gpointer data); void nemo_file_operations_delete (GList *files, GtkWindow *parent_window, NemoDeleteCallback done_callback, gpointer done_callback_data); void nemo_file_operations_trash_or_delete (GList *files, GtkWindow *parent_window, NemoDeleteCallback done_callback, gpointer done_callback_data); void nemo_file_set_permissions_recursive (const char *directory, guint32 file_permissions, guint32 file_mask, guint32 folder_permissions, guint32 folder_mask, NemoOpCallback callback, gpointer callback_data); void nemo_file_operations_unmount_mount (GtkWindow *parent_window, GMount *mount, gboolean eject, gboolean check_trash); void nemo_file_operations_unmount_mount_full (GtkWindow *parent_window, GMount *mount, GMountOperation *mount_operation, gboolean eject, gboolean check_trash, NemoUnmountCallback callback, gpointer callback_data); void nemo_file_operations_mount_volume (GtkWindow *parent_window, GVolume *volume); void nemo_file_operations_mount_volume_full (GtkWindow *parent_window, GVolume *volume, NemoMountCallback mount_callback, GObject *mount_callback_data_object); void nemo_file_operations_copy (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_operations_move (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_operations_duplicate (GList *files, GArray *relative_item_points, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_operations_link (GList *files, GArray *relative_item_points, GFile *target_dir, GtkWindow *parent_window, NemoCopyCallback done_callback, gpointer done_callback_data); void nemo_file_mark_desktop_file_trusted (GFile *file, GtkWindow *parent_window, gboolean interactive, NemoOpCallback done_callback, gpointer done_callback_data); #endif /* NEMO_FILE_OPERATIONS_H */ nemo-3.6.5/libnemo-private/nemo-cell-renderer-disk.c0000664000175000017500000002374013215733314021267 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "nemo-cell-renderer-disk.h" #include G_DEFINE_TYPE (NemoCellRendererDisk, nemo_cell_renderer_disk, GTK_TYPE_CELL_RENDERER_TEXT); static void nemo_cell_renderer_disk_init (NemoCellRendererDisk *cell); static void nemo_cell_renderer_disk_class_init (NemoCellRendererDiskClass *klass); static void nemo_cell_renderer_disk_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void nemo_cell_renderer_disk_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void nemo_cell_renderer_disk_finalize (GObject *gobject); static void nemo_cell_renderer_disk_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags); enum { PROP_DISK_FULL_PERCENTAGE = 1, PROP_SHOW_DISK_FULL_PERCENTAGE = 2, }; static gpointer parent_class; static void nemo_cell_renderer_disk_init (NemoCellRendererDisk *cell) { g_object_set (cell, "disk-full-percent", 0, "show-disk-full-percent", FALSE, NULL); } static void nemo_cell_renderer_disk_class_init (NemoCellRendererDiskClass *klass) { GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS(klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = nemo_cell_renderer_disk_finalize; object_class->get_property = nemo_cell_renderer_disk_get_property; object_class->set_property = nemo_cell_renderer_disk_set_property; cell_class->render = nemo_cell_renderer_disk_render; g_object_class_install_property (object_class, PROP_DISK_FULL_PERCENTAGE, g_param_spec_int ("disk-full-percent", "Percentage", "The fractional bar to display", 0, 100, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SHOW_DISK_FULL_PERCENTAGE, g_param_spec_boolean ("show-disk-full-percent", "Show Percentage Graph", "Whether to show the bar", FALSE, G_PARAM_READWRITE)); } GtkCellRenderer * nemo_cell_renderer_disk_new (void) { return g_object_new (NEMO_TYPE_CELL_RENDERER_DISK, NULL); } static void nemo_cell_renderer_disk_finalize (GObject *object) { G_OBJECT_CLASS (parent_class)->finalize (object); } static void nemo_cell_renderer_disk_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *psec) { NemoCellRendererDisk *celldisk = NEMO_CELL_RENDERER_DISK (object); switch (param_id) { case PROP_DISK_FULL_PERCENTAGE: g_value_set_int(value, celldisk->disk_full_percent); break; case PROP_SHOW_DISK_FULL_PERCENTAGE: g_value_set_boolean(value, celldisk->show_disk_full_percent); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, psec); break; } } static void nemo_cell_renderer_disk_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { NemoCellRendererDisk *celldisk = NEMO_CELL_RENDERER_DISK (object); switch (param_id) { case PROP_DISK_FULL_PERCENTAGE: celldisk->disk_full_percent = g_value_get_int (value); break; case PROP_SHOW_DISK_FULL_PERCENTAGE: celldisk->show_disk_full_percent = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec); break; } } static void convert_color (GdkColor *style_color, GdkRGBA *color) { color->red = style_color->red / 65535.0; color->green = style_color->green / 65535.0; color->blue = style_color->blue / 65535.0; color->alpha = 1; } static void use_default_color (GdkRGBA *color) { color->red = .5; color->green = .5; color->blue = .5; color->alpha = 1; } #define _270_DEG 270.0 * (M_PI/180.0) #define _180_DEG 180.0 * (M_PI/180.0) #define _90_DEG 90.0 * (M_PI/180.0) #define _0_DEG 0.0 static void cairo_rectangle_with_radius_corners (cairo_t *cr, gint x, gint y, gint w, gint h, gint rad) { cairo_move_to (cr, x+rad, y); cairo_line_to (cr, x+w-rad, y); cairo_arc (cr, x+w-rad, y+rad, rad, _270_DEG, _0_DEG); cairo_line_to (cr, x+w, y+h-rad); cairo_arc (cr, x+w-rad, y+h-rad, rad, _0_DEG, _90_DEG); cairo_line_to (cr, x+rad, y+h); cairo_arc (cr, x+rad, y+h-rad, rad, _90_DEG, _180_DEG); cairo_line_to (cr, x, y-rad); cairo_arc (cr, x+rad, y+rad, rad, _180_DEG, _270_DEG); } static void nemo_cell_renderer_disk_render (GtkCellRenderer *cell, cairo_t *cr, GtkWidget *widget, const GdkRectangle *background_area, const GdkRectangle *cell_area, GtkCellRendererState flags) { NemoCellRendererDisk *cellprogress = NEMO_CELL_RENDERER_DISK (cell); gint x, y, w; gint xpad, ypad; gint full; gboolean show = cellprogress->show_disk_full_percent; GtkStyleContext *context; if (show) { context = gtk_widget_get_style_context (widget); GdkColor *gdk_bg_color, *gdk_fg_color; GdkRGBA bg_color, fg_color; gint bar_width, bar_radius, bottom_padding, max_length; gtk_style_context_get_style (context, "disk-full-bg-color", &gdk_bg_color, "disk-full-fg-color", &gdk_fg_color, "disk-full-bar-width", &bar_width, "disk-full-bar-radius", &bar_radius, "disk-full-bottom-padding", &bottom_padding, "disk-full-max-length", &max_length, NULL); if (gdk_bg_color) { convert_color (gdk_bg_color, &bg_color); gdk_color_free (gdk_bg_color); } else { use_default_color (&bg_color); } if (gdk_fg_color) { convert_color (gdk_fg_color, &fg_color); gdk_color_free (gdk_fg_color); } else { use_default_color (&fg_color); } gtk_cell_renderer_get_padding (cell, &xpad, &ypad); x = cell_area->x + xpad; y = cell_area->y + cell_area->height - bar_width - bottom_padding; w = cell_area->width - xpad * 2; w = w < max_length ? w : max_length; full = (int) (((float) cellprogress->disk_full_percent / 100.0) * (float) w); gtk_style_context_save (context); cairo_save (cr); gdk_cairo_set_source_rgba (cr, &bg_color); cairo_rectangle_with_radius_corners (cr, x, y, w, bar_width, bar_radius); cairo_fill (cr); cairo_restore (cr); cairo_save (cr); gdk_cairo_set_source_rgba (cr, &fg_color); cairo_rectangle_with_radius_corners (cr, x, y, full, bar_width, bar_radius); cairo_fill (cr); cairo_restore (cr); gtk_style_context_restore (context); } GTK_CELL_RENDERER_CLASS (parent_class)->render (cell, cr, widget, background_area, cell_area, flags); } nemo-3.6.5/libnemo-private/nemo-mime-application-chooser.h0000664000175000017500000000512513215733314022506 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-mime-application-chooser.c: Manages applications for mime types Copyright (C) 2004 Novell, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but APPLICATIONOUT ANY WARRANTY; applicationout even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along application the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Dave Camp */ #ifndef NEMO_MIME_APPLICATION_CHOOSER_H #define NEMO_MIME_APPLICATION_CHOOSER_H #include #define NEMO_TYPE_MIME_APPLICATION_CHOOSER (nemo_mime_application_chooser_get_type ()) #define NEMO_MIME_APPLICATION_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_MIME_APPLICATION_CHOOSER, NemoMimeApplicationChooser)) #define NEMO_MIME_APPLICATION_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_MIME_APPLICATION_CHOOSER, NemoMimeApplicationChooserClass)) #define NEMO_IS_MIME_APPLICATION_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_MIME_APPLICATION_CHOOSER) typedef struct _NemoMimeApplicationChooser NemoMimeApplicationChooser; typedef struct _NemoMimeApplicationChooserClass NemoMimeApplicationChooserClass; typedef struct _NemoMimeApplicationChooserDetails NemoMimeApplicationChooserDetails; struct _NemoMimeApplicationChooser { GtkBox parent; NemoMimeApplicationChooserDetails *details; }; struct _NemoMimeApplicationChooserClass { GtkBoxClass parent_class; }; GType nemo_mime_application_chooser_get_type (void); GtkWidget * nemo_mime_application_chooser_new (const char *uri, GList *files, const char *mime_type, GtkWidget *ok_button); GAppInfo *nemo_mime_application_chooser_get_info (NemoMimeApplicationChooser *chooser); const gchar *nemo_mime_application_chooser_get_uri (NemoMimeApplicationChooser *chooser); #endif /* NEMO_MIME_APPLICATION_CHOOSER_H */ nemo-3.6.5/libnemo-private/nemo-bookmark.c0000664000175000017500000006071613215733314017425 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-bookmark.c - implementation of individual bookmarks. * * Copyright (C) 1999, 2000 Eazel, Inc. * Copyright (C) 2011, Red Hat, Inc. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Authors: John Sullivan * Cosimo Cecchi */ #include #include "nemo-bookmark.h" #include "nemo-metadata.h" #include #include #include #include #include #include #include #define DEBUG_FLAG NEMO_DEBUG_BOOKMARKS #include enum { CONTENTS_CHANGED, LOCATION_MOUNTED, LOOKUP_METADATA, LAST_SIGNAL }; enum { PROP_NAME = 1, PROP_CUSTOM_NAME, PROP_LOCATION, PROP_ICON, PROP_METADATA, NUM_PROPERTIES }; #define ELLIPSISED_MENU_ITEM_MIN_CHARS 32 static GParamSpec* properties[NUM_PROPERTIES] = { NULL }; static guint signals[LAST_SIGNAL] = { 0 }; struct NemoBookmarkDetails { char *name; gboolean has_custom_name; GFile *location; GIcon *icon; NemoFile *file; char *scroll_file; NemoBookmarkMetadata *metadata; }; static void nemo_bookmark_disconnect_file (NemoBookmark *file); G_DEFINE_TYPE (NemoBookmark, nemo_bookmark, G_TYPE_OBJECT); static void nemo_bookmark_set_name_internal (NemoBookmark *bookmark, const char *new_name) { if (g_strcmp0 (bookmark->details->name, new_name) != 0) { g_free (bookmark->details->name); bookmark->details->name = g_strdup (new_name); g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_NAME]); } } static void nemo_bookmark_update_icon (NemoBookmark *bookmark) { GIcon *new_icon; if (bookmark->details->file == NULL) { return; } if (!nemo_file_is_not_yet_confirmed (bookmark->details->file) && nemo_file_check_if_ready (bookmark->details->file, NEMO_FILE_ATTRIBUTES_FOR_ICON)) { DEBUG ("%s: set new icon", nemo_bookmark_get_name (bookmark)); new_icon = nemo_file_get_emblemed_icon (bookmark->details->file, 0); g_object_set (bookmark, "icon", new_icon, NULL); g_object_unref (new_icon); } } static void bookmark_set_name_from_ready_file (NemoBookmark *self, NemoFile *file) { gchar *display_name; if (self->details->has_custom_name) { return; } display_name = nemo_file_get_display_name (self->details->file); if (nemo_file_is_home (self->details->file)) { nemo_bookmark_set_custom_name (self, _("Home")); } else if (g_strcmp0 (self->details->name, display_name) != 0) { nemo_bookmark_set_custom_name (self, display_name); DEBUG ("%s: name changed to %s", nemo_bookmark_get_name (self), display_name); } g_free (display_name); } static GIcon * get_default_folder_icon (NemoBookmark *bookmark) { GIcon *ret = NULL; if (g_file_is_native (bookmark->details->location)) { ret = g_themed_icon_new (NEMO_ICON_FOLDER); } else { gchar *uri = g_file_get_uri (bookmark->details->location); if (g_str_has_prefix (uri, EEL_SEARCH_URI)) { ret = g_themed_icon_new (NEMO_ICON_FOLDER_SAVED_SEARCH); } else { ret = g_themed_icon_new (NEMO_ICON_FOLDER_REMOTE); } g_free (uri); } return ret; } static GIcon * construct_default_icon_from_metadata (NemoBookmark *bookmark) { NemoBookmarkMetadata *md = bookmark->details->metadata; GIcon *ret = NULL; if (md->icon_name) { ret = g_themed_icon_new (md->icon_name); } else if (md->icon_uri) { GFile *file = g_file_new_for_uri (md->icon_uri); ret = g_file_icon_new (file); g_object_unref (file); } else { ret = get_default_folder_icon (bookmark); } if (ret != NULL && md->emblems != NULL) { gint i = 0; GIcon *emb_icon; GEmblem *emblem; emb_icon = g_themed_icon_new (md->emblems[i]); emblem = g_emblem_new (emb_icon); ret = g_emblemed_icon_new (ret, emblem); i++; while (i < g_strv_length (md->emblems)) { emb_icon = g_themed_icon_new (md->emblems[i]); emblem = g_emblem_new (emb_icon); g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (ret), emblem); i++; } } return ret; } static void nemo_bookmark_set_icon_to_default (NemoBookmark *bookmark) { GIcon *icon, *emblemed_icon; GIcon *folder = NULL; GEmblem *emblem; folder = NULL; if (bookmark->details->metadata != NULL) { folder = construct_default_icon_from_metadata (bookmark); } if (!folder) folder = get_default_folder_icon (bookmark); if (!nemo_bookmark_uri_get_exists (bookmark)) { DEBUG ("%s: file does not exist, add emblem", nemo_bookmark_get_name (bookmark)); icon = g_themed_icon_new (GTK_STOCK_DIALOG_WARNING); emblem = g_emblem_new (icon); if (G_IS_EMBLEMED_ICON (folder)) g_emblemed_icon_add_emblem (G_EMBLEMED_ICON (folder), emblem); else { emblemed_icon = g_emblemed_icon_new (folder, emblem); folder = emblemed_icon; } g_object_unref (emblem); g_object_unref (icon); } DEBUG ("%s: setting icon to default", nemo_bookmark_get_name (bookmark)); g_object_set (bookmark, "icon", G_ICON (folder), NULL); g_object_unref (folder); } static gboolean metadata_changed (NemoBookmark *bookmark) { gboolean ret = FALSE; NemoBookmarkMetadata *data = nemo_bookmark_get_updated_metadata (bookmark); gboolean has_custom = data && (data->icon_uri || data->icon_name || data->emblems); gboolean had_custom = bookmark->details->metadata != NULL; if ((has_custom && !had_custom) || (had_custom && !has_custom)) { ret = TRUE; } else if (has_custom && had_custom) { NemoBookmarkMetadata *md = bookmark->details->metadata; ret = nemo_bookmark_metadata_compare (data, md); } return ret; } static void bookmark_file_changed_callback (NemoFile *file, NemoBookmark *bookmark) { GFile *location; g_assert (file == bookmark->details->file); DEBUG ("%s: file changed", nemo_bookmark_get_name (bookmark)); location = nemo_file_get_location (file); if (!g_file_equal (bookmark->details->location, location) && !nemo_file_is_in_trash (file)) { DEBUG ("%s: file got moved", nemo_bookmark_get_name (bookmark)); g_object_unref (bookmark->details->location); bookmark->details->location = g_object_ref (location); g_object_notify_by_pspec (G_OBJECT (bookmark), properties[PROP_LOCATION]); g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0); } g_object_unref (location); if (nemo_file_is_gone (file) || nemo_file_is_in_trash (file)) { /* The file we were monitoring has been trashed, deleted, * or moved in a way that we didn't notice. We should make * a spanking new NemoFile object for this * location so if a new file appears in this place * we will notice. However, we can't immediately do so * because creating a new NemoFile directly as a result * of noticing a file goes away may trigger i/o on that file * again, noticeing it is gone, leading to a loop. * So, the new NemoFile is created when the bookmark * is used again. However, this is not really a problem, as * we don't want to change the icon or anything about the * bookmark just because its not there anymore. */ DEBUG ("%s: trashed", nemo_bookmark_get_name (bookmark)); nemo_bookmark_disconnect_file (bookmark); nemo_bookmark_set_icon_to_default (bookmark); } else { nemo_bookmark_update_icon (bookmark); bookmark_set_name_from_ready_file (bookmark, file); if (metadata_changed (bookmark)) { g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0); } } } static void nemo_bookmark_disconnect_file (NemoBookmark *bookmark) { if (bookmark->details->file != NULL) { DEBUG ("%s: disconnecting file", nemo_bookmark_get_name (bookmark)); g_signal_handlers_disconnect_by_func (bookmark->details->file, G_CALLBACK (bookmark_file_changed_callback), bookmark); g_clear_object (&bookmark->details->file); } } static void nemo_bookmark_connect_file (NemoBookmark *bookmark) { if (bookmark->details->file != NULL) { DEBUG ("%s: file already connected, returning", nemo_bookmark_get_name (bookmark)); return; } if (nemo_bookmark_uri_get_exists (bookmark)) { DEBUG ("%s: creating file", nemo_bookmark_get_name (bookmark)); bookmark->details->file = nemo_file_get (bookmark->details->location); g_assert (!nemo_file_is_gone (bookmark->details->file)); g_signal_connect_object (bookmark->details->file, "changed", G_CALLBACK (bookmark_file_changed_callback), bookmark, 0); } /* Set icon based on available information. */ nemo_bookmark_update_icon (bookmark); if (bookmark->details->icon == NULL) { nemo_bookmark_set_icon_to_default (bookmark); } if (bookmark->details->file != NULL && nemo_file_check_if_ready (bookmark->details->file, NEMO_FILE_ATTRIBUTE_INFO)) { bookmark_set_name_from_ready_file (bookmark, bookmark->details->file); } if (bookmark->details->name == NULL) { bookmark->details->name = nemo_compute_title_for_location (bookmark->details->location); } } /* GObject methods */ static void nemo_bookmark_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { NemoBookmark *self = NEMO_BOOKMARK (object); GIcon *new_icon; switch (property_id) { case PROP_ICON: new_icon = g_value_get_object (value); if (new_icon != NULL && !g_icon_equal (self->details->icon, new_icon)) { g_clear_object (&self->details->icon); self->details->icon = g_object_ref (new_icon); } break; case PROP_LOCATION: self->details->location = g_value_dup_object (value); break; case PROP_CUSTOM_NAME: self->details->has_custom_name = g_value_get_boolean (value); break; case PROP_NAME: nemo_bookmark_set_name_internal (self, g_value_get_string (value)); break; case PROP_METADATA: if (self->details->metadata) g_clear_pointer (&self->details->metadata, nemo_bookmark_metadata_free); self->details->metadata = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_bookmark_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { NemoBookmark *self = NEMO_BOOKMARK (object); switch (property_id) { case PROP_NAME: g_value_set_string (value, self->details->name); break; case PROP_ICON: g_value_set_object (value, self->details->icon); break; case PROP_LOCATION: g_value_set_object (value, self->details->location); break; case PROP_CUSTOM_NAME: g_value_set_boolean (value, self->details->has_custom_name); break; case PROP_METADATA: g_value_set_pointer (value, self->details->metadata); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void nemo_bookmark_finalize (GObject *object) { NemoBookmark *bookmark; g_assert (NEMO_IS_BOOKMARK (object)); bookmark = NEMO_BOOKMARK (object); nemo_bookmark_disconnect_file (bookmark); g_object_unref (bookmark->details->location); g_clear_object (&bookmark->details->icon); g_clear_pointer (&bookmark->details->metadata, nemo_bookmark_metadata_free); g_free (bookmark->details->name); g_free (bookmark->details->scroll_file); G_OBJECT_CLASS (nemo_bookmark_parent_class)->finalize (object); } static void nemo_bookmark_class_init (NemoBookmarkClass *class) { GObjectClass *oclass = G_OBJECT_CLASS (class); oclass->finalize = nemo_bookmark_finalize; oclass->get_property = nemo_bookmark_get_property; oclass->set_property = nemo_bookmark_set_property; signals[CONTENTS_CHANGED] = g_signal_new ("contents-changed", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoBookmarkClass, contents_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[LOCATION_MOUNTED] = g_signal_new ("location-mounted", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoBookmarkClass, location_mounted), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 1, G_TYPE_FILE); properties[PROP_NAME] = g_param_spec_string ("name", "Bookmark's name", "The name of this bookmark", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT); properties[PROP_CUSTOM_NAME] = g_param_spec_boolean ("custom-name", "Whether the bookmark has a custom name", "Whether the bookmark has a custom name", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT); properties[PROP_LOCATION] = g_param_spec_object ("location", "Bookmark's location", "The location of this bookmark", G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY); properties[PROP_ICON] = g_param_spec_object ("icon", "Bookmark's icon", "The icon of this bookmark", G_TYPE_ICON, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_METADATA] = g_param_spec_pointer ("metadata", "Bookmark's non-gvfs metadata", "Metadata for defining the bookmark's icon", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); g_type_class_add_private (class, sizeof (NemoBookmarkDetails)); } static void nemo_bookmark_init (NemoBookmark *bookmark) { bookmark->details = G_TYPE_INSTANCE_GET_PRIVATE (bookmark, NEMO_TYPE_BOOKMARK, NemoBookmarkDetails); } const gchar * nemo_bookmark_get_name (NemoBookmark *bookmark) { g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL); return bookmark->details->name; } gboolean nemo_bookmark_get_has_custom_name (NemoBookmark *bookmark) { g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), FALSE); return (bookmark->details->has_custom_name); } /** * nemo_bookmark_set_custom_name: * * Change the user-displayed name of a bookmark. * @new_name: The new user-displayed name for this bookmark, mustn't be NULL. * **/ void nemo_bookmark_set_custom_name (NemoBookmark *bookmark, const char *new_name) { g_return_if_fail (new_name != NULL); g_return_if_fail (NEMO_IS_BOOKMARK (bookmark)); g_object_set (bookmark, "custom-name", TRUE, "name", new_name, NULL); g_signal_emit (bookmark, signals[CONTENTS_CHANGED], 0); } /** * nemo_bookmark_compare_with: * * Check whether two bookmarks are considered identical. * @a: first NemoBookmark*. * @b: second NemoBookmark*. * * Return value: 0 if @a and @b have same name and uri, 1 otherwise * (GCompareFunc style) **/ int nemo_bookmark_compare_with (gconstpointer a, gconstpointer b) { NemoBookmark *bookmark_a; NemoBookmark *bookmark_b; g_return_val_if_fail (NEMO_IS_BOOKMARK (a), 1); g_return_val_if_fail (NEMO_IS_BOOKMARK (b), 1); bookmark_a = NEMO_BOOKMARK (a); bookmark_b = NEMO_BOOKMARK (b); if (!g_file_equal (bookmark_a->details->location, bookmark_b->details->location)) { return 1; } if (g_strcmp0 (bookmark_a->details->name, bookmark_b->details->name) != 0) { return 1; } return 0; } /** * nemo_bookmark_compare_uris: * * Check whether the uris of two bookmarks are for the same location. * @a: first NemoBookmark*. * @b: second NemoBookmark*. * * Return value: 0 if @a and @b have matching uri, 1 otherwise * (GCompareFunc style) **/ int nemo_bookmark_compare_uris (gconstpointer a, gconstpointer b) { NemoBookmark *bookmark_a; NemoBookmark *bookmark_b; g_return_val_if_fail (NEMO_IS_BOOKMARK (a), 1); g_return_val_if_fail (NEMO_IS_BOOKMARK (b), 1); bookmark_a = NEMO_BOOKMARK (a); bookmark_b = NEMO_BOOKMARK (b); return !g_file_equal (bookmark_a->details->location, bookmark_b->details->location); } NemoBookmark * nemo_bookmark_copy (NemoBookmark *bookmark) { g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL); return nemo_bookmark_new (bookmark->details->location, bookmark->details->has_custom_name ? bookmark->details->name : NULL, bookmark->details->icon, bookmark->details->metadata ? nemo_bookmark_metadata_copy (bookmark->details->metadata) : NULL); } GIcon * nemo_bookmark_get_icon (NemoBookmark *bookmark) { g_return_val_if_fail (NEMO_IS_BOOKMARK (bookmark), NULL); /* Try to connect a file in case file exists now but didn't earlier. */ nemo_bookmark_connect_file (bookmark); if (bookmark->details->icon) { return g_object_ref (bookmark->details->icon); } return NULL; } GFile * nemo_bookmark_get_location (NemoBookmark *bookmark) { g_return_val_if_fail(NEMO_IS_BOOKMARK (bookmark), NULL); /* Try to connect a file in case file exists now but didn't earlier. * This allows a bookmark to update its image properly in the case * where a new file appears with the same URI as a previously-deleted * file. Calling connect_file here means that attempts to activate the * bookmark will update its image if possible. */ nemo_bookmark_connect_file (bookmark); return g_object_ref (bookmark->details->location); } char * nemo_bookmark_get_uri (NemoBookmark *bookmark) { GFile *file; char *uri; file = nemo_bookmark_get_location (bookmark); uri = g_file_get_uri (file); g_object_unref (file); return uri; } NemoBookmark * nemo_bookmark_new (GFile *location, const gchar *custom_name, GIcon *icon, NemoBookmarkMetadata *md) { NemoBookmark *new_bookmark; gchar *name; if (custom_name == NULL) name = g_file_get_basename (location); else name = g_strdup (custom_name); new_bookmark = NEMO_BOOKMARK (g_object_new (NEMO_TYPE_BOOKMARK, "location", location, "icon", icon, "name", name, "custom-name", custom_name != NULL, "metadata", md, NULL)); g_free (name); return new_bookmark; } static GtkWidget * create_image_widget_for_bookmark (NemoBookmark *bookmark) { GIcon *icon; GtkWidget *widget; icon = nemo_bookmark_get_icon (bookmark); widget = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU); g_object_unref (icon); return widget; } /** * nemo_bookmark_menu_item_new: * * Return a menu item representing a bookmark. * @bookmark: The bookmark the menu item represents. * Return value: A newly-created bookmark, not yet shown. **/ GtkWidget * nemo_bookmark_menu_item_new (NemoBookmark *bookmark) { GtkWidget *menu_item; GtkWidget *image_widget; GtkLabel *label; const char *name; name = nemo_bookmark_get_name (bookmark); menu_item = gtk_image_menu_item_new_with_label (name); label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (menu_item))); gtk_label_set_use_underline (label, FALSE); gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_END); gtk_label_set_max_width_chars (label, ELLIPSISED_MENU_ITEM_MIN_CHARS); image_widget = create_image_widget_for_bookmark (bookmark); if (image_widget != NULL) { gtk_widget_show (image_widget); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image_widget); } return menu_item; } gboolean nemo_bookmark_uri_get_exists (NemoBookmark *bookmark) { char *path_name; gboolean exists = FALSE; path_name = g_file_get_path (bookmark->details->location); if (g_file_is_native (bookmark->details->location) && g_file_test (path_name, G_FILE_TEST_EXISTS)) { exists = TRUE; } else { g_signal_emit_by_name (bookmark, "location-mounted", bookmark->details->location, &exists); } g_free (path_name); return exists; } void nemo_bookmark_set_scroll_pos (NemoBookmark *bookmark, const char *uri) { g_free (bookmark->details->scroll_file); bookmark->details->scroll_file = g_strdup (uri); } char * nemo_bookmark_get_scroll_pos (NemoBookmark *bookmark) { return g_strdup (bookmark->details->scroll_file); } void nemo_bookmark_connect (NemoBookmark *bookmark) { nemo_bookmark_connect_file (bookmark); } static gchar ** char_list_to_strv (GList *list) { GList *iter; GPtrArray *array = g_ptr_array_new (); for (iter = list; iter != NULL; iter = iter->next) { g_ptr_array_add (array, g_strdup (iter->data)); } g_ptr_array_add (array, NULL); return (char **) g_ptr_array_free (array, FALSE); } NemoBookmarkMetadata * nemo_bookmark_get_updated_metadata (NemoBookmark *bookmark) { NemoBookmarkMetadata *ret = NULL; if (!bookmark->details->file) return NULL; if (bookmark->details->file && !nemo_file_is_gone (bookmark->details->file)) { GList *custom_emblems = NULL; gchar *custom_icon_uri = NULL; gchar *custom_icon_name = NULL; custom_emblems = nemo_file_get_metadata_list (bookmark->details->file, NEMO_METADATA_KEY_EMBLEMS); custom_icon_uri = nemo_file_get_metadata (bookmark->details->file, NEMO_METADATA_KEY_CUSTOM_ICON, NULL); custom_icon_name = nemo_file_get_metadata (bookmark->details->file, NEMO_METADATA_KEY_CUSTOM_ICON_NAME, NULL); if (custom_emblems || custom_icon_uri || custom_icon_name) { ret = nemo_bookmark_metadata_new (); ret->icon_uri = custom_icon_uri; ret->icon_name = custom_icon_name; if (custom_emblems) { ret->emblems = char_list_to_strv (custom_emblems); g_list_free_full (custom_emblems, g_free); } else { ret->emblems = NULL; } } } else if (bookmark->details->metadata) { ret = nemo_bookmark_metadata_copy (bookmark->details->metadata); } return ret; } NemoBookmarkMetadata * nemo_bookmark_get_current_metadata (NemoBookmark *bookmark) { if (bookmark->details->metadata) return bookmark->details->metadata; return NULL; } NemoBookmarkMetadata * nemo_bookmark_metadata_new (void) { NemoBookmarkMetadata *meta = g_slice_new0 (NemoBookmarkMetadata); return meta; } NemoBookmarkMetadata * nemo_bookmark_metadata_copy (NemoBookmarkMetadata *meta) { NemoBookmarkMetadata *copy = nemo_bookmark_metadata_new (); copy->bookmark_name = g_strdup (meta->bookmark_name); copy->icon_name = g_strdup (meta->icon_name); copy->icon_uri = g_strdup (meta->icon_uri); copy->emblems = g_strdupv (meta->emblems); return copy; } gboolean nemo_bookmark_metadata_compare (NemoBookmarkMetadata *d1, NemoBookmarkMetadata *d2) { if (g_strcmp0 (d1->bookmark_name, d2->bookmark_name) != 0 || g_strcmp0 (d1->icon_uri, d2->icon_uri) != 0 || g_strcmp0 (d1->icon_name, d2->icon_name) != 0 || (g_strv_length (d1->emblems) != g_strv_length (d2->emblems))) return FALSE; gint i; for (i = 0; i < g_strv_length (d1->emblems); i++) { if (g_strcmp0 (d1->emblems[i], d2->emblems[i]) != 0) return FALSE; } return TRUE; } void nemo_bookmark_metadata_free (NemoBookmarkMetadata *metadata) { g_free (metadata->bookmark_name); g_free (metadata->icon_name); g_free (metadata->icon_uri); g_strfreev (metadata->emblems); g_slice_free (NemoBookmarkMetadata, metadata); }nemo-3.6.5/libnemo-private/nemo-merged-directory.c0000664000175000017500000005040513215733314021057 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-merged-directory.c: Subclass of NemoDirectory to implement the virtual merged directory. Copyright (C) 1999, 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "nemo-merged-directory.h" #include "nemo-directory-private.h" #include "nemo-directory-notify.h" #include "nemo-file.h" #include #include struct NemoMergedDirectoryDetails { GList *directories; GList *directories_not_done_loading; GHashTable *callbacks; GHashTable *monitors; }; typedef struct { NemoMergedDirectory *merged; NemoDirectoryCallback callback; gpointer callback_data; NemoFileAttributes wait_for_attributes; gboolean wait_for_file_list; GList *non_ready_directories; GList *merged_file_list; } MergedCallback; typedef struct { NemoMergedDirectory *merged; gboolean monitor_hidden_files; NemoFileAttributes monitor_attributes; } MergedMonitor; enum { ADD_REAL_DIRECTORY, REMOVE_REAL_DIRECTORY, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (NemoMergedDirectory, nemo_merged_directory, NEMO_TYPE_DIRECTORY); static guint merged_callback_hash (gconstpointer merged_callback_as_pointer) { const MergedCallback *merged_callback; merged_callback = merged_callback_as_pointer; return GPOINTER_TO_UINT (merged_callback->callback) ^ GPOINTER_TO_UINT (merged_callback->callback_data); } static gboolean merged_callback_equal (gconstpointer merged_callback_as_pointer, gconstpointer merged_callback_as_pointer_2) { const MergedCallback *merged_callback, *merged_callback_2; merged_callback = merged_callback_as_pointer; merged_callback_2 = merged_callback_as_pointer_2; return merged_callback->callback == merged_callback_2->callback && merged_callback->callback_data == merged_callback_2->callback_data; } static void merged_callback_destroy (MergedCallback *merged_callback) { g_assert (merged_callback != NULL); g_assert (NEMO_IS_MERGED_DIRECTORY (merged_callback->merged)); g_list_free (merged_callback->non_ready_directories); nemo_file_list_free (merged_callback->merged_file_list); g_free (merged_callback); } static void merged_callback_check_done (MergedCallback *merged_callback) { /* Check if we are ready. */ if (merged_callback->non_ready_directories != NULL) { return; } /* Remove from the hash table before sending it. */ g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); /* We are ready, so do the real callback. */ (* merged_callback->callback) (NEMO_DIRECTORY (merged_callback->merged), merged_callback->merged_file_list, merged_callback->callback_data); /* And we are done. */ merged_callback_destroy (merged_callback); } static void merged_callback_remove_directory (MergedCallback *merged_callback, NemoDirectory *directory) { merged_callback->non_ready_directories = g_list_remove (merged_callback->non_ready_directories, directory); merged_callback_check_done (merged_callback); } static void directory_ready_callback (NemoDirectory *directory, GList *files, gpointer callback_data) { MergedCallback *merged_callback; g_assert (NEMO_IS_DIRECTORY (directory)); g_assert (callback_data != NULL); merged_callback = callback_data; g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL); /* Update based on this call. */ merged_callback->merged_file_list = g_list_concat (merged_callback->merged_file_list, nemo_file_list_copy (files)); /* Check if we are ready. */ merged_callback_remove_directory (merged_callback, directory); } static void merged_call_when_ready (NemoDirectory *directory, NemoFileAttributes file_attributes, gboolean wait_for_file_list, NemoDirectoryCallback callback, gpointer callback_data) { NemoMergedDirectory *merged; MergedCallback search_key, *merged_callback; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); /* Check to be sure we aren't overwriting. */ search_key.callback = callback; search_key.callback_data = callback_data; if (g_hash_table_lookup (merged->details->callbacks, &search_key) != NULL) { g_warning ("tried to add a new callback while an old one was pending"); return; } /* Create a merged_callback record. */ merged_callback = g_new0 (MergedCallback, 1); merged_callback->merged = merged; merged_callback->callback = callback; merged_callback->callback_data = callback_data; merged_callback->wait_for_attributes = file_attributes; merged_callback->wait_for_file_list = wait_for_file_list; for (node = merged->details->directories; node != NULL; node = node->next) { merged_callback->non_ready_directories = g_list_prepend (merged_callback->non_ready_directories, node->data); } /* Put it in the hash table. */ g_hash_table_insert (merged->details->callbacks, merged_callback, merged_callback); /* Handle the pathological case where there are no directories. */ if (merged->details->directories == NULL) { merged_callback_check_done (merged_callback); } /* Now tell all the directories about it. */ for (node = merged->details->directories; node != NULL; node = node->next) { nemo_directory_call_when_ready (node->data, merged_callback->wait_for_attributes, merged_callback->wait_for_file_list, directory_ready_callback, merged_callback); } } static void merged_cancel_callback (NemoDirectory *directory, NemoDirectoryCallback callback, gpointer callback_data) { NemoMergedDirectory *merged; MergedCallback search_key, *merged_callback; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); /* Find the entry in the table. */ search_key.callback = callback; search_key.callback_data = callback_data; merged_callback = g_hash_table_lookup (merged->details->callbacks, &search_key); if (merged_callback == NULL) { return; } /* Remove from the hash table before working with it. */ g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); /* Tell all the directories to cancel the call. */ for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) { nemo_directory_cancel_callback (node->data, directory_ready_callback, merged_callback); } merged_callback_destroy (merged_callback); } static void build_merged_callback_list (NemoDirectory *directory, GList *file_list, gpointer callback_data) { GList **merged_list; merged_list = callback_data; *merged_list = g_list_concat (*merged_list, nemo_file_list_copy (file_list)); } /* Create a monitor on each of the directories in the list. */ static void merged_monitor_add (NemoDirectory *directory, gconstpointer client, gboolean monitor_hidden_files, NemoFileAttributes file_attributes, NemoDirectoryCallback callback, gpointer callback_data) { NemoMergedDirectory *merged; MergedMonitor *monitor; GList *node; GList *merged_callback_list; merged = NEMO_MERGED_DIRECTORY (directory); /* Map the client to a unique value so this doesn't interfere * with direct monitoring of the directory by the same client. */ monitor = g_hash_table_lookup (merged->details->monitors, client); if (monitor != NULL) { g_assert (monitor->merged == merged); } else { monitor = g_new0 (MergedMonitor, 1); monitor->merged = merged; g_hash_table_insert (merged->details->monitors, (gpointer) client, monitor); } monitor->monitor_hidden_files = monitor_hidden_files; monitor->monitor_attributes = file_attributes; /* Call through to the real directory add calls. */ merged_callback_list = NULL; for (node = merged->details->directories; node != NULL; node = node->next) { nemo_directory_file_monitor_add (node->data, monitor, monitor_hidden_files, file_attributes, build_merged_callback_list, &merged_callback_list); } if (callback != NULL) { (* callback) (directory, merged_callback_list, callback_data); } nemo_file_list_free (merged_callback_list); } static void merged_monitor_destroy (NemoMergedDirectory *merged, MergedMonitor *monitor) { GList *node; /* Call through to the real directory remove calls. */ for (node = merged->details->directories; node != NULL; node = node->next) { nemo_directory_file_monitor_remove (node->data, monitor); } g_free (monitor); } /* Remove the monitor from each of the directories in the list. */ static void merged_monitor_remove (NemoDirectory *directory, gconstpointer client) { NemoMergedDirectory *merged; MergedMonitor *monitor; merged = NEMO_MERGED_DIRECTORY (directory); /* Map the client to the value used by the earlier add call. */ monitor = g_hash_table_lookup (merged->details->monitors, client); if (monitor == NULL) { return; } g_hash_table_remove (merged->details->monitors, client); merged_monitor_destroy (merged, monitor); } static void merged_force_reload (NemoDirectory *directory) { NemoMergedDirectory *merged; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); /* Call through to the real force_reload calls. */ for (node = merged->details->directories; node != NULL; node = node->next) { nemo_directory_force_reload (node->data); } } /* Return true if any directory in the list does. */ static gboolean merged_contains_file (NemoDirectory *directory, NemoFile *file) { NemoMergedDirectory *merged; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); for (node = merged->details->directories; node != NULL; node = node->next) { if (nemo_directory_contains_file (node->data, file)) { return TRUE; } } return FALSE; } /* Return true only if all directories in the list do. */ static gboolean merged_are_all_files_seen (NemoDirectory *directory) { NemoMergedDirectory *merged; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); for (node = merged->details->directories; node != NULL; node = node->next) { if (!nemo_directory_are_all_files_seen (node->data)) { return FALSE; } } return TRUE; } /* Return true if any directory in the list does. */ static gboolean merged_is_not_empty (NemoDirectory *directory) { NemoMergedDirectory *merged; GList *node; merged = NEMO_MERGED_DIRECTORY (directory); for (node = merged->details->directories; node != NULL; node = node->next) { if (nemo_directory_is_not_empty (node->data)) { return TRUE; } } return FALSE; } static GList * merged_get_file_list (NemoDirectory *directory) { GList *dirs_file_list, *merged_dir_file_list = NULL; GList *dir_list; GList *cur_node; dirs_file_list = NULL; dir_list = NEMO_MERGED_DIRECTORY (directory)->details->directories; for (cur_node = dir_list; cur_node != NULL; cur_node = cur_node->next) { NemoDirectory *cur_dir; cur_dir = NEMO_DIRECTORY (cur_node->data); dirs_file_list = g_list_concat (dirs_file_list, nemo_directory_get_file_list (cur_dir)); } merged_dir_file_list = NEMO_DIRECTORY_CLASS (nemo_merged_directory_parent_class)->get_file_list (directory); return g_list_concat (dirs_file_list, merged_dir_file_list); } static void forward_files_added_cover (NemoDirectory *real_directory, GList *files, gpointer callback_data) { nemo_directory_emit_files_added (NEMO_DIRECTORY (callback_data), files); } static void forward_files_changed_cover (NemoDirectory *real_directory, GList *files, gpointer callback_data) { nemo_directory_emit_files_changed (NEMO_DIRECTORY (callback_data), files); } static void done_loading_callback (NemoDirectory *real_directory, NemoMergedDirectory *merged) { merged->details->directories_not_done_loading = g_list_remove (merged->details->directories_not_done_loading, real_directory); if (merged->details->directories_not_done_loading == NULL) { nemo_directory_emit_done_loading (NEMO_DIRECTORY (merged)); } } static void monitor_add_directory (gpointer key, gpointer value, gpointer callback_data) { MergedMonitor *monitor; monitor = value; nemo_directory_file_monitor_add (NEMO_DIRECTORY (callback_data), monitor, monitor->monitor_hidden_files, monitor->monitor_attributes, forward_files_added_cover, monitor->merged); } static void merged_add_real_directory (NemoMergedDirectory *merged, NemoDirectory *real_directory) { g_return_if_fail (NEMO_IS_MERGED_DIRECTORY (merged)); g_return_if_fail (NEMO_IS_DIRECTORY (real_directory)); g_return_if_fail (!NEMO_IS_MERGED_DIRECTORY (real_directory)); g_return_if_fail (g_list_find (merged->details->directories, real_directory) == NULL); /* Add to our list of directories. */ nemo_directory_ref (real_directory); merged->details->directories = g_list_prepend (merged->details->directories, real_directory); merged->details->directories_not_done_loading = g_list_prepend (merged->details->directories_not_done_loading, real_directory); g_signal_connect_object (real_directory, "done_loading", G_CALLBACK (done_loading_callback), merged, 0); /* FIXME bugzilla.gnome.org 45084: The done_loading part won't work for the case where * we have no directories in our list. */ /* Add the directory to any extant monitors. */ g_hash_table_foreach (merged->details->monitors, monitor_add_directory, real_directory); /* FIXME bugzilla.gnome.org 42541: Do we need to add the directory to callbacks too? */ g_signal_connect_object (real_directory, "files_added", G_CALLBACK (forward_files_added_cover), merged, 0); g_signal_connect_object (real_directory, "files_changed", G_CALLBACK (forward_files_changed_cover), merged, 0); } void nemo_merged_directory_add_real_directory (NemoMergedDirectory *merged, NemoDirectory *real_directory) { g_return_if_fail (NEMO_IS_MERGED_DIRECTORY (merged)); g_return_if_fail (NEMO_IS_DIRECTORY (real_directory)); g_return_if_fail (!NEMO_IS_MERGED_DIRECTORY (real_directory)); /* Quietly do nothing if asked to add something that's already there. */ if (g_list_find (merged->details->directories, real_directory) != NULL) { return; } g_signal_emit (merged, signals[ADD_REAL_DIRECTORY], 0, real_directory); } GList * nemo_merged_directory_get_real_directories (NemoMergedDirectory *merged) { return g_list_copy (merged->details->directories); } static void merged_callback_remove_directory_cover (gpointer key, gpointer value, gpointer callback_data) { merged_callback_remove_directory (value, NEMO_DIRECTORY (callback_data)); } static void monitor_remove_directory (gpointer key, gpointer value, gpointer callback_data) { nemo_directory_file_monitor_remove (NEMO_DIRECTORY (callback_data), value); } static void real_directory_notify_files_removed (NemoDirectory *real_directory) { GList *files, *l; files = nemo_directory_get_file_list (real_directory); for (l = files; l; l = l->next) { NemoFile *file; char *uri; file = NEMO_FILE (l->data); uri = nemo_file_get_uri (file); nemo_file_unref (file); l->data = uri; } if (files) { nemo_directory_notify_files_removed_by_uri (files); } g_list_free_full (files, g_free); } static void merged_remove_real_directory (NemoMergedDirectory *merged, NemoDirectory *real_directory) { g_return_if_fail (NEMO_IS_MERGED_DIRECTORY (merged)); g_return_if_fail (NEMO_IS_DIRECTORY (real_directory)); g_return_if_fail (g_list_find (merged->details->directories, real_directory) != NULL); /* Since the real directory will be going away, act as if files were removed */ real_directory_notify_files_removed (real_directory); /* Remove this directory from callbacks and monitors. */ eel_g_hash_table_safe_for_each (merged->details->callbacks, merged_callback_remove_directory_cover, real_directory); g_hash_table_foreach (merged->details->monitors, monitor_remove_directory, real_directory); /* Disconnect all the signals. */ g_signal_handlers_disconnect_matched (real_directory, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, merged); /* Remove from our list of directories. */ merged->details->directories = g_list_remove (merged->details->directories, real_directory); merged->details->directories_not_done_loading = g_list_remove (merged->details->directories_not_done_loading, real_directory); nemo_directory_unref (real_directory); } void nemo_merged_directory_remove_real_directory (NemoMergedDirectory *merged, NemoDirectory *real_directory) { g_return_if_fail (NEMO_IS_MERGED_DIRECTORY (merged)); /* Quietly do nothing if asked to remove something that's not there. */ if (g_list_find (merged->details->directories, real_directory) == NULL) { return; } g_signal_emit (merged, signals[REMOVE_REAL_DIRECTORY], 0, real_directory); } static void merged_monitor_destroy_cover (gpointer key, gpointer value, gpointer callback_data) { merged_monitor_destroy (callback_data, value); } static void merged_callback_destroy_cover (gpointer key, gpointer value, gpointer callback_data) { merged_callback_destroy (value); } static void merged_finalize (GObject *object) { NemoMergedDirectory *merged; merged = NEMO_MERGED_DIRECTORY (object); g_hash_table_foreach (merged->details->monitors, merged_monitor_destroy_cover, merged); g_hash_table_foreach (merged->details->callbacks, merged_callback_destroy_cover, NULL); g_hash_table_destroy (merged->details->callbacks); g_hash_table_destroy (merged->details->monitors); nemo_directory_list_free (merged->details->directories); g_list_free (merged->details->directories_not_done_loading); G_OBJECT_CLASS (nemo_merged_directory_parent_class)->finalize (object); } static void nemo_merged_directory_init (NemoMergedDirectory *merged) { merged->details = G_TYPE_INSTANCE_GET_PRIVATE (merged, NEMO_TYPE_MERGED_DIRECTORY, NemoMergedDirectoryDetails); merged->details->callbacks = g_hash_table_new (merged_callback_hash, merged_callback_equal); merged->details->monitors = g_hash_table_new (NULL, NULL); } static void nemo_merged_directory_class_init (NemoMergedDirectoryClass *class) { NemoDirectoryClass *directory_class; directory_class = NEMO_DIRECTORY_CLASS (class); G_OBJECT_CLASS (class)->finalize = merged_finalize; directory_class->contains_file = merged_contains_file; directory_class->call_when_ready = merged_call_when_ready; directory_class->cancel_callback = merged_cancel_callback; directory_class->file_monitor_add = merged_monitor_add; directory_class->file_monitor_remove = merged_monitor_remove; directory_class->force_reload = merged_force_reload; directory_class->are_all_files_seen = merged_are_all_files_seen; directory_class->is_not_empty = merged_is_not_empty; /* Override get_file_list so that we can return a list that includes * the files from each of the directories in NemoMergedDirectory->details->directories. */ directory_class->get_file_list = merged_get_file_list; class->add_real_directory = merged_add_real_directory; class->remove_real_directory = merged_remove_real_directory; g_type_class_add_private (class, sizeof (NemoMergedDirectoryDetails)); signals[ADD_REAL_DIRECTORY] = g_signal_new ("add_real_directory", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoMergedDirectoryClass, add_real_directory), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); signals[REMOVE_REAL_DIRECTORY] = g_signal_new ("remove_real_directory", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NemoMergedDirectoryClass, remove_real_directory), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); } nemo-3.6.5/libnemo-private/nemo-file-undo-manager.h0000664000175000017500000000567613215733314021123 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* nemo-file-undo-manager.h - Manages the undo/redo stack * * Copyright (C) 2007-2011 Amos Brocco * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. * * Author: Amos Brocco */ #ifndef __NEMO_FILE_UNDO_MANAGER_H__ #define __NEMO_FILE_UNDO_MANAGER_H__ #include #include #include #include #include typedef struct _NemoFileUndoManager NemoFileUndoManager; typedef struct _NemoFileUndoManagerClass NemoFileUndoManagerClass; typedef struct _NemoFileUndoManagerPrivate NemoFileUndoManagerPrivate; #define NEMO_TYPE_FILE_UNDO_MANAGER\ (nemo_file_undo_manager_get_type()) #define NEMO_FILE_UNDO_MANAGER(object)\ (G_TYPE_CHECK_INSTANCE_CAST((object), NEMO_TYPE_FILE_UNDO_MANAGER,\ NemoFileUndoManager)) #define NEMO_FILE_UNDO_MANAGER_CLASS(klass)\ (G_TYPE_CHECK_CLASS_CAST((klass), NEMO_TYPE_FILE_UNDO_MANAGER,\ NemoFileUndoManagerClass)) #define NEMO_IS_FILE_UNDO_MANAGER(object)\ (G_TYPE_CHECK_INSTANCE_TYPE((object), NEMO_TYPE_FILE_UNDO_MANAGER)) #define NEMO_IS_FILE_UNDO_MANAGER_CLASS(klass)\ (G_TYPE_CHECK_CLASS_TYPE((klass), NEMO_TYPE_FILE_UNDO_MANAGER)) #define NEMO_FILE_UNDO_MANAGER_GET_CLASS(object)\ (G_TYPE_INSTANCE_GET_CLASS((object), NEMO_TYPE_FILE_UNDO_MANAGER,\ NemoFileUndoManagerClass)) typedef enum { NEMO_FILE_UNDO_MANAGER_STATE_NONE, NEMO_FILE_UNDO_MANAGER_STATE_UNDO, NEMO_FILE_UNDO_MANAGER_STATE_REDO } NemoFileUndoManagerState; struct _NemoFileUndoManager { GObject parent_instance; /* < private > */ NemoFileUndoManagerPrivate* priv; }; struct _NemoFileUndoManagerClass { GObjectClass parent_class; }; GType nemo_file_undo_manager_get_type (void) G_GNUC_CONST; NemoFileUndoManager * nemo_file_undo_manager_get (void); void nemo_file_undo_manager_set_action (NemoFileUndoInfo *info); NemoFileUndoInfo *nemo_file_undo_manager_get_action (void); NemoFileUndoManagerState nemo_file_undo_manager_get_state (void); void nemo_file_undo_manager_undo (GtkWindow *parent_window); void nemo_file_undo_manager_redo (GtkWindow *parent_window); void nemo_file_undo_manager_push_flag (void); gboolean nemo_file_undo_manager_pop_flag (void); #endif /* __NEMO_FILE_UNDO_MANAGER_H__ */ nemo-3.6.5/libnemo-private/nemo-icon.h0000664000175000017500000000451413215733314016547 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* gnome-icon-container-private.h Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Ettore Perazzoli */ #ifndef NEMO_ICON_H #define NEMO_ICON_H #include #include #include #define NEMO_ICON_CONTAINER_ICON_DATA(pointer) \ ((NemoIconData *) (pointer)) typedef struct NemoIconData NemoIconData; typedef void (* NemoIconCallback) (NemoIconData *icon_data, gpointer callback_data); /* An Icon. */ typedef struct { /* Object represented by this icon. */ NemoIconData *data; /* Canvas item for the icon. */ NemoIconCanvasItem *item; /* X/Y coordinates. */ double x, y; /* * In RTL mode x is RTL x position, we use saved_ltr_x for * keeping track of x value before it gets converted into * RTL value, this is used for saving the icon position * to the nemo metafile. */ double saved_ltr_x; /* Scale factor (stretches icon). */ double scale; /* Whether this item is selected. */ eel_boolean_bit is_selected : 1; /* Whether this item was selected before rubberbanding. */ eel_boolean_bit was_selected_before_rubberband : 1; /* Whether this item is visible in the view. */ eel_boolean_bit is_visible : 1; /* Whether a monitor was set on this icon. */ eel_boolean_bit is_monitored : 1; eel_boolean_bit has_lazy_position : 1; } NemoIcon; #endif /* NEMO_ICON_CONTAINER_PRIVATE_H */ nemo-3.6.5/libnemo-private/nemo-file-changes-queue.h0000664000175000017500000000332613215733314021266 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- Copyright (C) 1999, 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Pavel Cisler */ #ifndef NEMO_FILE_CHANGES_QUEUE_H #define NEMO_FILE_CHANGES_QUEUE_H #include #include void nemo_file_changes_queue_file_added (GFile *location); void nemo_file_changes_queue_file_changed (GFile *location); void nemo_file_changes_queue_file_removed (GFile *location); void nemo_file_changes_queue_file_moved (GFile *from, GFile *to); void nemo_file_changes_queue_schedule_position_set (GFile *location, GdkPoint point, int monitor); void nemo_file_changes_queue_schedule_position_remove (GFile *location); void nemo_file_changes_consume_changes (gboolean consume_all); #endif /* NEMO_FILE_CHANGES_QUEUE_H */ nemo-3.6.5/libnemo-private/nemo-file-attributes.h0000664000175000017500000000337113215733314020722 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- nemo-file-attributes.h: #defines and other file-attribute-related info Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef NEMO_FILE_ATTRIBUTES_H #define NEMO_FILE_ATTRIBUTES_H /* Names for NemoFile attributes. These are used when registering * interest in changes to the attributes or when waiting for them. */ typedef enum { NEMO_FILE_ATTRIBUTE_INFO = 1 << 0, /* All standard info */ NEMO_FILE_ATTRIBUTE_LINK_INFO = 1 << 1, /* info from desktop links */ NEMO_FILE_ATTRIBUTE_DEEP_COUNTS = 1 << 2, NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT = 1 << 3, NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES = 1 << 4, NEMO_FILE_ATTRIBUTE_TOP_LEFT_TEXT = 1 << 5, NEMO_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT = 1 << 6, NEMO_FILE_ATTRIBUTE_EXTENSION_INFO = 1 << 7, NEMO_FILE_ATTRIBUTE_THUMBNAIL = 1 << 8, NEMO_FILE_ATTRIBUTE_MOUNT = 1 << 9, NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO = 1 << 10, } NemoFileAttributes; #endif /* NEMO_FILE_ATTRIBUTES_H */ nemo-3.6.5/libnemo-private/nemo-icon-info.h0000664000175000017500000001175213215733314017502 0ustar fabiofabio#ifndef NEMO_ICON_INFO_H #define NEMO_ICON_INFO_H #include #include #include #include #include G_BEGIN_DECLS /* Names for Nemo's different zoom levels, from tiniest items to largest items */ typedef enum { NEMO_ZOOM_LEVEL_NULL = -1, NEMO_ZOOM_LEVEL_SMALLEST = 0, NEMO_ZOOM_LEVEL_SMALLER, NEMO_ZOOM_LEVEL_SMALL, NEMO_ZOOM_LEVEL_STANDARD, NEMO_ZOOM_LEVEL_LARGE, NEMO_ZOOM_LEVEL_LARGER, NEMO_ZOOM_LEVEL_LARGEST } NemoZoomLevel; #define NEMO_ZOOM_LEVEL_N_ENTRIES (NEMO_ZOOM_LEVEL_LARGEST + 1) /* Nominal icon sizes for each Nemo zoom level. * This scheme assumes that icons are designed to * fit in a square space, though each image needn't * be square. Since individual icons can be stretched, * each icon is not constrained to this nominal size. */ #define NEMO_ICON_SIZE_SMALLEST 16 #define NEMO_ICON_SIZE_SMALLER 24 #define NEMO_ICON_SIZE_SMALL 32 #define NEMO_ICON_SIZE_STANDARD 48 #define NEMO_ICON_SIZE_LARGE 72 #define NEMO_ICON_SIZE_LARGER 96 #define NEMO_ICON_SIZE_LARGEST 192 #define NEMO_DESKTOP_ICON_SIZE_SMALL 32 #define NEMO_DESKTOP_ICON_SIZE_STANDARD 48 #define NEMO_DESKTOP_ICON_SIZE_LARGE 64 /* Maximum size of an icon that the icon factory will ever produce */ #define NEMO_ICON_MAXIMUM_SIZE 320 typedef struct _NemoIconInfo NemoIconInfo; typedef struct _NemoIconInfoClass NemoIconInfoClass; #define NEMO_TYPE_ICON_INFO (nemo_icon_info_get_type ()) #define NEMO_ICON_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NEMO_TYPE_ICON_INFO, NemoIconInfo)) #define NEMO_ICON_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NEMO_TYPE_ICON_INFO, NemoIconInfoClass)) #define NEMO_IS_ICON_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NEMO_TYPE_ICON_INFO)) #define NEMO_IS_ICON_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NEMO_TYPE_ICON_INFO)) #define NEMO_ICON_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NEMO_TYPE_ICON_INFO, NemoIconInfoClass)) GType nemo_icon_info_get_type (void) G_GNUC_CONST; NemoIconInfo * nemo_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf, int scale); NemoIconInfo * nemo_icon_info_lookup (GIcon *icon, int size, int scale); NemoIconInfo * nemo_icon_info_lookup_from_name (const char *name, int size, int scale); NemoIconInfo * nemo_icon_info_lookup_from_path (const char *path, int size, int scale); gboolean nemo_icon_info_is_fallback (NemoIconInfo *icon); GdkPixbuf * nemo_icon_info_get_pixbuf (NemoIconInfo *icon); GdkPixbuf * nemo_icon_info_get_pixbuf_nodefault (NemoIconInfo *icon); GdkPixbuf * nemo_icon_info_get_pixbuf_nodefault_at_size (NemoIconInfo *icon, gsize forced_size); GdkPixbuf * nemo_icon_info_get_pixbuf_at_size (NemoIconInfo *icon, gsize forced_size); GdkPixbuf * nemo_icon_info_get_desktop_pixbuf_at_size (NemoIconInfo *icon, gsize max_width, gsize max_height); gboolean nemo_icon_info_get_embedded_rect (NemoIconInfo *icon, GdkRectangle *rectangle); gboolean nemo_icon_info_get_attach_points (NemoIconInfo *icon, GdkPoint **points, gint *n_points); const char * nemo_icon_info_get_display_name (NemoIconInfo *icon); const char * nemo_icon_info_get_used_name (NemoIconInfo *icon); void nemo_icon_info_clear_caches (void); /* Relationship between zoom levels and icons sizes. */ guint nemo_get_icon_size_for_zoom_level (NemoZoomLevel zoom_level); guint nemo_get_list_icon_size_for_zoom_level (NemoZoomLevel zoom_level); guint nemo_get_desktop_icon_size_for_zoom_level (NemoZoomLevel zoom_level); gint nemo_get_icon_size_for_stock_size (GtkIconSize size); guint nemo_icon_get_emblem_size_for_icon_size (guint size); gboolean nemo_icon_theme_can_render (GThemedIcon *icon); GIcon * nemo_user_special_directory_get_gicon (GUserDirectory directory); G_END_DECLS #endif /* NEMO_ICON_INFO_H */ nemo-3.6.5/libnemo-private/nemo-centered-placement-grid.c0000664000175000017500000005342513215733314022301 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Copyright (C) 1999, 2000 Free Software Foundation Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. */ #include "math.h" #include #include "nemo-icon-private.h" // #include "nemo-icon-info.h" #include "nemo-file.h" NemoCenteredPlacementGrid * nemo_centered_placement_grid_new (NemoIconContainer *container, gboolean horizontal) { NemoCenteredPlacementGrid *grid; gint width, height; gint num_columns; gint num_rows; gint i; gint snap_x, snap_y; gint icon_size; GtkAllocation allocation; /* Get container dimensions */ gtk_widget_get_allocation (GTK_WIDGET (container), &allocation); icon_size = nemo_get_desktop_icon_size_for_zoom_level (container->details->zoom_level); width = nemo_icon_container_get_canvas_width (container, allocation); height = nemo_icon_container_get_canvas_height (container, allocation); snap_x = GET_VIEW_CONSTANT (container, snap_size_x); snap_y = GET_VIEW_CONSTANT (container, snap_size_y); num_columns = width / snap_x; num_rows = height / snap_y; if (num_columns == 0 || num_rows == 0) { return NULL; } grid = g_new0 (NemoCenteredPlacementGrid, 1); grid->container = container; grid->horizontal = horizontal; grid->icon_size = icon_size; grid->real_snap_x = snap_x; grid->real_snap_y = snap_y; grid->num_columns = num_columns; grid->num_rows = num_rows; grid->borders = gtk_border_new (); grid->grid_memory = g_new0 (int, (num_rows * num_columns)); grid->icon_grid = g_new0 (int *, num_columns); for (i = 0; i < num_columns; i++) { grid->icon_grid[i] = grid->grid_memory + (i * num_rows); } grid->borders->left = (width - (num_columns * snap_x)) / 2; grid->borders->right = (width - (num_columns * snap_x)) / 2; grid->borders->top = (height - (num_rows * snap_y)) / 2; grid->borders->bottom = (height - (num_rows * snap_y)) / 2; return grid; } void nemo_centered_placement_grid_free (NemoCenteredPlacementGrid *grid) { if (grid == NULL) { return; } g_free (grid->icon_grid); g_free (grid->grid_memory); gtk_border_free (grid->borders); g_free (grid); } static gboolean nemo_centered_placement_grid_position_is_free (NemoCenteredPlacementGrid *grid, gint grid_x, gint grid_y) { g_assert (grid_x >= 0 && grid_x < grid->num_columns); g_assert (grid_y >= 0 && grid_y < grid->num_rows); return grid->icon_grid[grid_x][grid_y] == 0; } static void nemo_centered_placement_grid_mark (NemoCenteredPlacementGrid *grid, gint grid_x, gint grid_y) { g_assert (grid_x >= 0 && grid_x < grid->num_columns); g_assert (grid_y >= 0 && grid_y < grid->num_rows); grid->icon_grid[grid_x][grid_y] = 1; } static void nemo_centered_placement_grid_unmark (NemoCenteredPlacementGrid *grid, gint grid_x, gint grid_y) { g_assert (grid_x >= 0 && grid_x < grid->num_columns); g_assert (grid_y >= 0 && grid_y < grid->num_rows); grid->icon_grid[grid_x][grid_y] = 0; } static void nemo_centered_placement_grid_get_next_grid_position (NemoCenteredPlacementGrid *grid, gint x_in, gint y_in, gint *x_out, gint *y_out) { gint x, y; gboolean first_line; first_line = TRUE; x = y = 0; if (grid->horizontal) { for (y = y_in; y < grid->num_rows; y++) { for (x = first_line ? x_in : 0; x < grid->num_columns; x++) { first_line = FALSE; if (x != x_in || y != y_in) { goto out; } } } } else { for (x = x_in; x < grid->num_columns; x++) { for (y = first_line ? y_in : 0; y < grid->num_rows; y++) { first_line = FALSE; if (x != x_in || y != y_in) { goto out; } } } } out: *x_out = x; *y_out = y; } void nemo_centered_placement_grid_nominal_to_icon_position (NemoCenteredPlacementGrid *grid, NemoIcon *icon, gint x_nominal, gint y_nominal, gint *x_adjusted, gint *y_adjusted) { gint icon_width; if (icon != NULL) { EelDRect icon_bounds; icon_bounds = nemo_icon_canvas_item_get_icon_rectangle (icon->item); icon_width = icon_bounds.x1 - icon_bounds.x0; } else { icon_width = grid->icon_size; } *x_adjusted = x_nominal + (grid->real_snap_x / 2) - (icon_width / 2); *y_adjusted = y_nominal + (grid->real_snap_y / 2) - GET_VIEW_CONSTANT (grid->container, icon_vertical_adjust); } void nemo_centered_placement_grid_icon_position_to_nominal (NemoCenteredPlacementGrid *grid, NemoIcon *icon, gint x_adjusted, gint y_adjusted, gint *x_nominal, gint *y_nominal) { gint icon_width; if (icon != NULL) { EelDRect icon_bounds; icon_bounds = nemo_icon_canvas_item_get_icon_rectangle (icon->item); icon_width = icon_bounds.x1 - icon_bounds.x0; } else { icon_width = grid->icon_size; } *x_nominal = x_adjusted + (icon_width / 2) - (grid->real_snap_x / 2); *y_nominal = y_adjusted - (grid->real_snap_y / 2) + GET_VIEW_CONSTANT (grid->container, icon_vertical_adjust); } void nemo_centered_placement_grid_mark_icon (NemoCenteredPlacementGrid *grid, NemoIcon *icon) { gint grid_x, grid_y; GdkRectangle rect; if (icon->x <= 0.0 && icon->y <= 0.0) { return; } nemo_centered_placement_grid_get_current_position_rect (grid, icon->x, icon->y, &rect, NULL); grid_x = rect.x / grid->real_snap_x; grid_y = rect.y / grid->real_snap_y; if ((grid_x >= 0 && grid_x < grid->num_columns) && (grid_y >= 0 && grid_y < grid->num_rows)) { nemo_centered_placement_grid_mark (grid, grid_x, grid_y); } } void nemo_centered_placement_grid_unmark_icon (NemoCenteredPlacementGrid *grid, NemoIcon *icon) { gint grid_x, grid_y; GdkRectangle rect; if (icon->x <= 0.0 && icon->y <= 0.0) { return; } nemo_centered_placement_grid_get_current_position_rect (grid, icon->x, icon->y, &rect, NULL); grid_x = rect.x / grid->real_snap_x; grid_y = rect.y / grid->real_snap_y; if ((grid_x >= 0 && grid_x < grid->num_columns) && (grid_y >= 0 && grid_y < grid->num_rows)) { nemo_centered_placement_grid_unmark (grid, grid_x, grid_y); } } void nemo_centered_placement_grid_mark_position (NemoCenteredPlacementGrid *grid, gint x, gint y) { GdkRectangle rect; gint grid_x, grid_y; if (x < 0 && y < 0) { return; } nemo_centered_placement_grid_get_current_position_rect (grid, x, y, &rect, NULL); grid_x = rect.x / grid->real_snap_x; grid_y = rect.y / grid->real_snap_y; if ((grid_x >= 0 && grid_x < grid->num_columns) && (grid_y >= 0 && grid_y < grid->num_rows)) { nemo_centered_placement_grid_mark (grid, grid_x, grid_y); } } void nemo_centered_placement_grid_unmark_position (NemoCenteredPlacementGrid *grid, gint x, gint y) { GdkRectangle rect; gint grid_x, grid_y; if (x < 0 && y < 0) { return; } nemo_centered_placement_grid_get_current_position_rect (grid, x, y, &rect, NULL); grid_x = rect.x / grid->real_snap_x; grid_y = rect.y / grid->real_snap_y; if ((grid_x >= 0 && grid_x < grid->num_columns) && (grid_y >= 0 && grid_y < grid->num_rows)) { nemo_centered_placement_grid_unmark (grid, grid_x, grid_y); } } void nemo_centered_placement_grid_pre_populate (NemoCenteredPlacementGrid *grid, GList *icons, gboolean ignore_lazy) { GList *p; NemoIcon *icon; for (p = icons; p != NULL; p = p->next) { gboolean should_mark; icon = p->data; if (ignore_lazy) { should_mark = nemo_icon_container_icon_is_positioned (icon) && !icon->has_lazy_position; } else { should_mark = nemo_icon_container_icon_is_positioned (icon); } if (should_mark) { nemo_centered_placement_grid_mark_icon (grid, icon); } } } void nemo_centered_placement_grid_get_next_position_rect (NemoCenteredPlacementGrid *grid, GdkRectangle *in_rect, GdkRectangle *out_rect, gboolean *is_free) { gint index_x, index_y, next_index_x, next_index_y; gint x, y; x = in_rect->x - grid->borders->left; y = in_rect->y - grid->borders->top; index_x = x / grid->real_snap_x; index_y = y / grid->real_snap_y; index_x = CLAMP (index_x, 0, grid->num_columns - 1); index_y = CLAMP (index_y, 0, grid->num_rows - 1); nemo_centered_placement_grid_get_next_grid_position (grid, index_x, index_y, &next_index_x, &next_index_y); next_index_x = CLAMP (next_index_x, 0, grid->num_columns - 1); next_index_y = CLAMP (next_index_y, 0, grid->num_rows - 1); out_rect->x = next_index_x * grid->real_snap_x; out_rect->y = next_index_y * grid->real_snap_y; out_rect->width = grid->real_snap_x; out_rect->height = grid->real_snap_y; out_rect->x += grid->borders->left; out_rect->y += grid->borders->top; if (is_free) { if ((next_index_x == grid->num_columns - 1) && (next_index_y == grid->num_rows - 1)) { /* Last position of the grid is our escape valve when our number if icons * exceeds possible positions in the grid - we'll allow icons to overlap * here (what else can we do? Shrink the grid till everything fits? That * could also be broken - sooner or later we need this) */ *is_free = TRUE; } else { *is_free = nemo_centered_placement_grid_position_is_free (grid, next_index_x, next_index_y); } } } void nemo_centered_placement_grid_get_current_position_rect (NemoCenteredPlacementGrid *grid, gint x, gint y, GdkRectangle *rect, gboolean *is_free) { gint index_x, index_y; x -= grid->borders->left; y -= grid->borders->top; index_x = x / grid->real_snap_x; index_y = y / grid->real_snap_y; index_x = CLAMP (index_x, 0, grid->num_columns - 1); index_y = CLAMP (index_y, 0, grid->num_rows - 1); rect->x = index_x * grid->real_snap_x; rect->y = index_y * grid->real_snap_y; rect->width = grid->real_snap_x; rect->height = grid->real_snap_y; rect->x += grid->borders->left; rect->y += grid->borders->top; if (is_free) { if ((index_x == grid->num_columns - 1) && (index_y == grid->num_rows - 1)) { /* Last position of the grid is our escape valve when our number if icons * exceeds possible positions in the grid - we'll allow icons to overlap * here (what else can we do? Shrink the grid till everything fits? That * could also be broken - sooner or later we need this) */ *is_free = TRUE; } else { *is_free = nemo_centered_placement_grid_position_is_free (grid, index_x, index_y); } } } static NemoIcon * get_icon_at_grid_position (NemoCenteredPlacementGrid *grid, gint grid_x, gint grid_y) { NemoIcon *icon; GList *l; for (l = grid->container->details->icons; l != NULL; l = l->next) { GdkRectangle rect; gint icon_grid_x, icon_grid_y; icon = l->data; nemo_centered_placement_grid_get_current_position_rect (grid, icon->x, icon->y, &rect, NULL); icon_grid_x = rect.x / grid->real_snap_x; icon_grid_y = rect.y / grid->real_snap_y; if (grid_x == icon_grid_x && grid_y == icon_grid_y) { return icon; } } return NULL; } GList * nemo_centered_placement_grid_clear_grid_for_selection (NemoCenteredPlacementGrid *grid, gint start_x, gint start_y, GList *drag_sel_list) { NemoDragSelectionItem *item; NemoIcon *icon; GList *ret_list, *icon_list, *p; GdkRectangle grid_rect; gboolean is_free; gboolean insert_before, first_line; gint grid_x, grid_y, new_grid_x, new_grid_y, iter_x, iter_y, icon_new_x, icon_new_y; gint space_needed; start_x -= grid->borders->left; start_y -= grid->borders->top; /* We need to have space_needed number of contiguous positions in the grid */ space_needed = g_list_length (drag_sel_list); /* Find where we're starting from, whether inserting before or after the current * item */ nemo_centered_placement_grid_get_current_position_rect (grid, start_x, start_y, &grid_rect, &is_free); grid_x = grid_rect.x / grid->real_snap_x; grid_y = grid_rect.y / grid->real_snap_y; insert_before = TRUE; if (!is_free) { if (grid->horizontal) { insert_before = (start_x >= grid_rect.x) && (start_x < grid_rect.x + (grid_rect.width / 2)); } else { insert_before = (start_y >= grid_rect.y) && (start_y < grid_rect.y + (grid_rect.height / 2)); } } if (!insert_before) { nemo_centered_placement_grid_get_next_grid_position (grid, grid_x, grid_y, &new_grid_x, &new_grid_y); } else { new_grid_x = grid_x; new_grid_y = grid_y; } /* Iterate thru the grid, starting at our insertion position, pick up existing icons that are in * the way until we have enough free space to lay down the original selection plus these icons. */ first_line = TRUE; icon_list = NULL; if (grid->horizontal) { for (iter_y = new_grid_y; iter_y < grid->num_rows; iter_y++) { for (iter_x = first_line ? new_grid_x : 0; iter_x < grid->num_columns; iter_x++) { first_line = FALSE; if (nemo_centered_placement_grid_position_is_free (grid, iter_x, iter_y)) { space_needed--; } else { icon = get_icon_at_grid_position (grid, iter_x, iter_y); icon_list = g_list_prepend (icon_list, icon); nemo_centered_placement_grid_unmark (grid, iter_x, iter_y); } if (space_needed == 0) { goto done_collecting; } } } } else { for (iter_x = new_grid_x; iter_x < grid->num_columns; iter_x++) { for (iter_y = first_line ? new_grid_y : 0; iter_y < grid->num_rows; iter_y++) { first_line = FALSE; if (nemo_centered_placement_grid_position_is_free (grid, iter_x, iter_y)) { space_needed--; } else { icon = get_icon_at_grid_position (grid, iter_x, iter_y); icon_list = g_list_prepend (icon_list, icon); nemo_centered_placement_grid_unmark (grid, iter_x, iter_y); } if (space_needed == 0) { goto done_collecting; } } } } done_collecting: /* Now go thru the original selection list, and modify their target positions to our grid positions */ icon_list = g_list_reverse (icon_list); iter_x = new_grid_x; iter_y = new_grid_y; for (p = drag_sel_list; p != NULL; p = p->next) { item = p->data; icon = nemo_icon_container_get_icon_by_uri (grid->container, item->uri); nemo_centered_placement_grid_nominal_to_icon_position (grid, icon, /* May be NULL if not a desktop item */ iter_x * grid->real_snap_x, iter_y * grid->real_snap_y, &icon_new_x, &icon_new_y); item->got_icon_position = TRUE; item->icon_x = icon_new_x - start_x; item->icon_y = icon_new_y - start_y; nemo_centered_placement_grid_get_next_grid_position (grid, iter_x, iter_y, &iter_x, &iter_y); } /* Build a NemoDragSelectionItem list from the NemoIcon list we picked up, setting the appropriate positions * following the original selection */ ret_list = NULL; for (p = icon_list; p != NULL; p = p->next) { icon = p->data; nemo_centered_placement_grid_nominal_to_icon_position (grid, icon, iter_x * grid->real_snap_x, iter_y * grid->real_snap_y, &icon_new_x, &icon_new_y); item = nemo_drag_selection_item_new (); item->uri = nemo_file_get_uri (NEMO_FILE (icon->data)); item->got_icon_position = TRUE; item->icon_x = icon_new_x - start_x; item->icon_y = icon_new_y - start_y; item->icon_width = grid->icon_size; item->icon_height = grid->icon_size; ret_list = g_list_prepend (ret_list, item); nemo_centered_placement_grid_get_next_grid_position (grid, iter_x, iter_y, &iter_x, &iter_y); } ret_list = g_list_reverse (ret_list); /* Return the 'push list' - extra icons to be moved, but behind the scenes, that won't be * selected once the drop is complete */ return ret_list; } nemo-3.6.5/ChangeLog0000664000175000017500000354552613215733314013207 0ustar fabiofabiocommit 16763a8b828387930641d69c04451e02d67cadd6 Author: Cosimo Cecchi Date: 2012-05-14 release: prepare for 3.4.2 M NEWS M configure.in commit 0e08c9938a4e3557f9519aa52f2f488a99e28e97 Author: Praveen Illa Date: 2012-05-14 Updated Telugu Translations M po/te.po commit 10a15760f0ba7d1b0a65693caf47a9b080742ed3 Author: Cosimo Cecchi Date: 2012-05-08 window-manage-views: don't call methods on a NULL NemoFile In got_file_info_for_view_selection_callback(), we unconditionally try to fetch information for the parent directory in case the selection is a regular file, but we should avoid doing that when the file has no parent, such as when it's the root of a web server. https://bugzilla.gnome.org/show_bug.cgi?id=675259 M src/nemo-window-manage-views.c commit c92532c8808815a776e377bf208bc194f077b169 Author: Cosimo Cecchi Date: 2012-05-07 x-content-bar: pack the media label in the content area Instead of just packing it into the GtkInfoBar's box, since that will put it after the buttons of the action area. https://bugzilla.gnome.org/show_bug.cgi?id=670129 M src/nemo-x-content-bar.c commit 7e90dabb2f38539173970fb715a53b355fb44e1c Author: Cosimo Cecchi Date: 2012-05-07 places-sidebar: disallow context menus for sidebar headings We already make them non-selectable - there's no point in having a menu for headings here. https://bugzilla.redhat.com/show_bug.cgi?id=819404 M src/nemo-places-sidebar.c commit 4e59e4cfc7bc68534664d9f72d0c7ea680b79db3 Author: Cosimo Cecchi Date: 2012-05-04 places-sidebar: don't double unref GMount objects Fixes a lot of reported crashers with NFS/Samba volumes. https://bugzilla.gnome.org/show_bug.cgi?id=674659 M src/nemo-places-sidebar.c commit c5b336f62e4d5efb330306cf9a905e70e7553171 Author: Kjartan Maraas Date: 2012-04-30 Added Norwegian bokmÃ¥l translation M po/nb.po commit fd7f5be8da08bf18d5d60314940491ff4f7fd99c Author: Ã…smund Skjæveland Date: 2012-04-29 Updated Norwegian Nynorsk translation M po/nn.po commit dad5031da0fc176ec27dcbb3a7057cc41aee399b Author: Sebastien Bacher Date: 2012-04-27 update ZERO_OR_THREE_DIGITS define to work as intended https://bugzilla.gnome.org/show_bug.cgi?id=674924 M libnemo-private/nemo-icon-canvas-item.c commit f5b824abf3f3b9304d7a63fd52d3f96036dc91ff Author: Cosimo Cecchi Date: 2012-04-24 editable-label: fix selection color in backdrop state Don't set the ACTIVE flag if we don't have focus, it just doesn't make sense. M eel/eel-editable-label.c commit dd0223773a818de92c71f119e1b42bae5157bdad Author: Djavan Fagundes Date: 2012-04-23 Fixed a string in Brazilian Portuguese translation M po/pt_BR.po commit 6b692bcaa4577aa811a18ba38ecce0d925e7613d Author: Yuri Myasoedov Date: 2012-04-23 Updated Russian translation M po/ru.po commit 9684ae22e4b4e02d8dc0b944d956ac7f7b8863f4 Author: Charles Kerr Date: 2012-04-18 link: plug a memory leak https://bugzilla.gnome.org/show_bug.cgi?id=674087 M libnemo-private/nemo-link.c commit c016565b17b2a94a1e2c7bbab9b5ae284110e578 Author: Charles Kerr Date: 2012-04-18 desktop-metadata: plug some memory leaks https://bugzilla.gnome.org/show_bug.cgi?id=674086 M libnemo-private/nemo-desktop-metadata.c commit 8118406d63b317c18cf52313a55c0f4b17093af3 Author: Cosimo Cecchi Date: 2012-04-18 list-view: don't treat clicks as on an empty area if the row is selected When the row is selected, and we right click on it, make sure we popup its context menu and not its parent's, since the selection is a stronger indication of intent. https://bugzilla.gnome.org/show_bug.cgi?id=674245 M src/nemo-list-view.c commit 2f2180c7a1e6203b3dfd9d926795aac180869fb3 Author: Christian Kirbach Date: 2012-04-18 Updated German translation (Bug #674093) M po/de.po commit ae6beb8030e3045b8bea3330e7b0507904a22e74 Author: Cosimo Cecchi Date: 2012-04-16 release: prepare for 3.4.1 M NEWS M configure.in commit bc3f1d8ffff2b3ca6336cef2bd5304c3f12b7418 Author: Cosimo Cecchi Date: 2012-04-13 undo: use g_file_info_get_attribute_byte_string for trash::orig-path Since that's what GVfs sets. https://bugzilla.gnome.org/show_bug.cgi?id=673776 M libnemo-private/nemo-file-undo-operations.c commit 17d765a598e85eaeb785938e896d1fd44abc481a Author: Milo Casagrande Date: 2012-04-06 [l10n] Updated Italian translation M po/it.po commit 0531db12b0a929fca139a3fde0846d31b602d922 Author: Abderrahim Kitouni Date: 2012-03-24 file-operations: don't mix character and byte lengths Otherwise untitled files end up with a (possibly) corrupt part of the name appended. https://bugzilla.gnome.org/show_bug.cgi?id=672761 M libnemo-private/nemo-file-operations.c commit ba04ec0e7435b21d492a39e0bafc167ba24e0f49 Author: Ryan Lortie Date: 2012-04-05 NemoFile: keep free space information directly There were previously some tricks in nemo to this effect: - when you call nemo_file_get_volume_free_space() on a NemoFile, the return result is NULL at first and later you get a "changed" signal on the file after the value is filled in - the value is being stored inside the NemoDirectory equivalent for the file that is created when the call is first performed and kept around until after the change signal fires (so that the person receiving the change signal can still get the data). This is done to save space by not expanding NemoFile. The NemoDirectory is then dropped after the change signal is done firing. - the nemo properties window has a 200ms timeout after changes to files being reported before it re-queries the properties The end result is that the NemoDirectory (which holds the information about the free space) is already freed by the time the properties window tries to update the free space display. This results in the directory being recreated and the process starting over again. The end result is that we never get the free space shown in the dialog and instead we have an infinite loop of CPU usage (fortunately repeating only every 200ms, so you get ~5% CPU usage instead of 100%). We can solve the problem by just storing the free space information directly in the NemoFile details structure and dropping the dance with NemoDirectory; nothing in NemoDirectory is actually using that information anyway. https://bugzilla.gnome.org/show_bug.cgi?id=673550 M libnemo-private/nemo-directory-private.h M libnemo-private/nemo-directory.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c commit 07f22b823cb75fc0da5dc9bc8c3805766d8baa15 Author: Praveen Illa Date: 2012-04-05 Updated Telugu Translation M po/te.po commit ae375b34c28c157950069e8bae8e033f5c12a556 Author: Nelson Benitez Leon Date: 2012-04-03 list-view: don't handle extra mouse buttons events Don't handle extra mouse button events so they can bubble up through GtkTreeview till NemoWindow where they are handled to navigate the view forward and backward. Part of bug 660006 Signed-off-by: Nelson Benitez Leon M src/nemo-list-view.c commit 3deb33d449f293b8e2597ccd7cc3bacec7b40ca2 Author: Nelson Benitez Leon Date: 2012-03-29 eel-canvas: ignore extra mouse button events Ignore button press/release events for mouse buttons greater than 5 so allowing forward and backward mouse buttons to work over icons. Part of bug 660006 Signed-off-by: Nelson Benitez Leon M eel/eel-canvas.c commit 49c753b1e2adaf7803b2fd4f1685f859d979ff74 Author: Cosimo Cecchi Date: 2012-04-02 file-operations: fix off-by-one error in copied files count TransferInfo->num_files counts from zero, so we have to increment it by one when formatting it into a string. https://bugzilla.gnome.org/show_bug.cgi?id=673345 M libnemo-private/nemo-file-operations.c commit 9b762008cf6417f1691bd94dd99c583d4e7a2c26 Author: Cosimo Cecchi Date: 2012-04-01 link: remove unused code nemo_link_local_get_additional_text() is now unused. M libnemo-private/nemo-link.c M libnemo-private/nemo-link.h commit afc9a8196ce9a94b900f532c3b7d433ef9641569 Author: Cosimo Cecchi Date: 2012-04-01 icon-container: don't show comment field for desktop files This fixes a regression introduced in commit 5a47a484e45218e83202c508b421b1a2707af270 https://bugzilla.gnome.org/show_bug.cgi?id=673316 M src/nemo-icon-view-container.c commit 3525ec8ec6b382a04affa0d02bf8ba1a1929f89b Author: Alexander Shopov Date: 2012-04-01 Updated Bulgarian translation M po/bg.po commit c2ab193ea26c67d6031fce7fe389b3832c37cc80 Author: Piotr DrÄ…g Date: 2012-03-31 Updated Polish translation M po/pl.po commit ce15200eb252536bf95c0a37939b883320f851c7 Author: Piotr DrÄ…g Date: 2012-03-29 Added Tibetan translation to LINGUAS M po/LINGUAS commit a08f87e8fe5522dbd58573a73d3e7aac70d80cff Author: tennom YK Date: 2012-03-29 Added Tibetan translation A po/bo.po commit 963ee1bd9ba64d88272bd264d76eff6846e24c7c Author: Daniel Mustieles Date: 2012-03-27 Updated Spanish translation M po/es.po commit 67b2499fc0ea6ba08063adea535a1d3529ff3053 Author: Mantas KriauÄiÅ«nas Date: 2012-03-26 Updated Lithuanian translation M po/lt.po commit b6972a97ab14dc86c2e5130feda39d3bc5c7a355 Author: Cosimo Cecchi Date: 2012-03-26 release: prepare for 3.4.0 M NEWS M configure.in commit c1551dfcfa9c92bf43c57b219535f63a9fecdad4 Author: Cosimo Cecchi Date: 2012-03-26 view: ensure we show "Open with..." entries for folders This is a regression from commit b9c51fd4eb84a9f52ee4be1bf183fc516984130b https://bugzilla.gnome.org/show_bug.cgi?id=672809 M src/nemo-view.c commit d64698322ea64fed050bd82de545e678d557f85c Author: ReÅŸat SABIQ Date: 2012-03-26 Updated Crimean Tatar (Crimean Turkish) translation M po/crh.po commit 440d5bb1693d32a7d4fb8ef16002c130b600eb80 Author: Jiro Matsuzawa Date: 2012-03-25 Updated Japanese translation. M po/ja.po commit 70b70e316cf4930036759581a935ab19475835e3 Author: Praveen Arimbrathodiyil Date: 2012-03-24 Malayalam translation updated by Aslam M po/ml.po commit afe92aa3ea0fdd988dd3bfe5851032843e6d808b Author: Sasi Bhushan Date: 2012-03-24 Updated Telugu translation M po/te.po commit 0d165b3e0b874263e6f52127194b6e9f47ea4a1b Author: Rajesh Ranjan Date: 2012-03-23 hindi translation by Chandan Kumar M po/hi.po commit adb6a12a7b0b08cfd441e4a75857797dc9875a43 Author: Timo Jyrinki Date: 2012-03-23 Updated Finnish translation by Jiri Grönroos M po/fi.po commit 982ce96d810795dd30d50cb2ff8e622fcb9ff4d6 Author: Praveen Illa Date: 2012-03-23 Updated Telugu Translation M po/te.po commit a6cb9e4697d904390cf54fdd19aa556b78bf98c0 Author: Kristjan SCHMIDT Date: 2012-03-22 Updated Esperanto translation M po/eo.po commit a5914993f533ceeef84d2d7000c64160b68d2cfb Author: Ibrahim Saed Date: 2012-03-21 Updated Arabic translation M po/ar.po commit 8d0c374a46fd90f82dea80c7d19fd8800fa67154 Author: Duarte Loreto Date: 2012-03-21 Updated Portuguese translation M po/pt.po commit 040ee44c68efb7120e9a86f56c6e325052d42a8f Author: Automatic Mirroring Date: 2012-03-21 Update Simplified Chinese translation. M po/zh_CN.po commit ef3a663a6e25040e1e96d3225654a0c774b1a823 Author: YunQiang Su Date: 2012-03-21 update Simplified Chinese (zh_CN) translation M po/zh_CN.po commit 4229689853639bce00b4a8dab7f7312aafb7da32 Author: Cosimo Cecchi Date: 2012-03-19 release: prepare for 3.3.92 M NEWS M configure.in commit a60e9887eebb8973c48c0151981a26cce7cc8793 Author: Cosimo Cecchi Date: 2012-03-19 places-sidebar: add support for the "network" volume class identifier If a GVolume has a class identifier of "network", put it (and its mount) in the Network section. This fixes e.g. NFS mounts showing in the wrong section. M src/nemo-places-sidebar.c commit a06988aefdf6cf147936737e48005170410046b2 Author: Cosimo Cecchi Date: 2012-03-19 places-sidebar: focus the first non-heading row on focus-in Instead of giving the focus to the heading, which would end up in getting stuck there, since headings are not supposed to be actionable. https://bugzilla.gnome.org/show_bug.cgi?id=672002 M src/nemo-places-sidebar.c commit 003b8773399de836e11c725f24c8a1f668a29adf Author: Cosimo Cecchi Date: 2012-03-19 places-sidebar: use gtk_tree_view_set_cursor() to move selection This will also move the scrolled window up/down when we navigate the places sidebar with keyboard. M src/nemo-places-sidebar.c commit 429d3548b72b5a29e8c0e31304db3cd51e25fcbf Author: Cosimo Cecchi Date: 2012-03-19 places-sidebar: make find_prev_or_next_row() start from the passed iter This will be useful for the next commits. M src/nemo-places-sidebar.c commit 5d2471aff8033fc319957273cf20d33420c5a6f7 Author: Carles Ferrando Date: 2012-03-19 [l10n]Updated Catalan (Valencian) translation M po/ca@valencia.po commit 3ea1074b29d7d25c7c087eeeece215a057ab3fbd Author: Joan Duran Date: 2012-03-19 [l10n] Updated Catalan translation M po/ca.po commit 63b59332d15139bd43504e0192a169cd5f924bf5 Author: Mario Blättermann Date: 2012-03-18 [l10n] Updated German translation M po/de.po commit f8f4f5a241dd99c04be8f327aed3316c9d87f1b2 Author: Cosimo Cecchi Date: 2012-03-16 icon-container: set a range base selection icon on _set_selection() If the selection we set if just one item (as it is in the case when we're going back/forward in the history), set that item as a base for range selection too, instead of just selecting it. https://bugzilla.gnome.org/show_bug.cgi?id=672127 M libnemo-private/nemo-icon-container.c commit ba281e27b804b1c61c715f4371f352b04e9d76ad Author: Cosimo Cecchi Date: 2012-03-16 eel: delete unused code We don't use EelDPoint/EelIPoint anymore; other functions here are just unused. M eel/eel-art-extensions.c M eel/eel-art-extensions.h M eel/eel-self-checks.c M eel/eel-self-checks.h commit 8e43d841355b6cd82af730bc2357f9ac1ed7c638 Author: Cosimo Cecchi Date: 2012-03-16 icon-container: avoid using EelDPoint It's going away. M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-canvas-item.h M libnemo-private/nemo-icon-container.c commit 0832acdb4371fc7de957303e220e899c8fdcdf5c Author: Cosimo Cecchi Date: 2012-03-16 icon-view: fix wheel scrolling for compact view If the smooth scroll event we get is an emulated scroll wheel, we have to emulate a right/left scroll, like we do for regular UP/DOWN events. https://bugzilla.gnome.org/show_bug.cgi?id=672185 M src/nemo-icon-view.c commit 8dcf1625bb5e38c865ebe01f53275b579093663c Author: Reinout van Schouwen Date: 2012-03-16 2012-03-16 Reinout van Schouwen - nl.po: Fixed typo M po/nl.po commit 136a20daeef2568776a1c239bac9cb66a1f66efc Author: Reinout van Schouwen Date: 2012-03-16 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ 2012-03-16 Reinout van Schouwen - nl.po: Use ‘Standaard instellen’ instead of ‘Standaard gebruiken’ M po/nl.po commit 9f6d1414dac34fef51616d7642fe52a2353d3c2b Author: Krishnababu Krothapalli Date: 2012-03-16 Translations Updated with FUEL M po/te.po commit 4273aa66a8e73e11cf3ad388bb53350c12b30e83 Author: Krishnababu Krothapalli Date: 2012-03-16 Translations Updated with FUEL M po/te.po commit 258628dbf02a540179488c94d0a6c1100ad12eab Author: Anita Reitere Date: 2012-03-14 Updated Latvian translation. M po/lv.po commit 3d275a971132a41809a3b1e5b8ac683d264d6c35 Author: Stefano Facchini Date: 2012-03-13 view: improve scroll-zooming for smooth scrolling devices Try to emulate a normal scroll event by adding deltas until the total delta reaches +1 or -1. M src/nemo-view.c commit d865bc50459fb1349a761c3c7029bad7f13fc67c Author: Cosimo Cecchi Date: 2012-03-13 pathbar: make dragging from toolbar work again This was a regression from the recent refactorings in NemoPathbar. Since we now have an event window, if we want button events to reach the parent toolbar, we have to select for such events when we realize the event window. M src/nemo-pathbar.c commit f7b54cdba55a0856b201e62818059ac5007fac35 Author: Cosimo Cecchi Date: 2012-03-13 view: threshold the delta information when scroll-zooming We don't want to zoom for every single event, since in case the device supports smooth scrolling, we will get a lot of small events. Pointed out by Stefano Facchini. M src/nemo-view.c commit 45cb82857c9cef34952da4c0488780fd8b19a61b Author: Jonh Wendell Date: 2012-03-13 Updated Brazilian Portuguese translation M po/pt_BR.po commit df6a0a0a1e721142b1be5338fcad2cc0248fdf1e Author: Cosimo Cecchi Date: 2012-03-12 build: remove unused --enable-profiler build option It's unused. https://bugzilla.gnome.org/show_bug.cgi?id=661632 M configure.in commit d9c23d83fdb5e1178f2c2f97a57b937cdab1b251 Author: Cosimo Cecchi Date: 2012-03-12 properties-window: ellipsize the Type field Or the properties window won't shrink when the file type string is long (e.g. with Archive types). https://bugzilla.gnome.org/show_bug.cgi?id=671809 M src/nemo-properties-window.c commit 73588247787b408ec43dba4156cadac97fe2d6d6 Author: Cosimo Cecchi Date: 2012-03-12 pathbar: refresh label size request every time it changes Or we might end up with buttons having the wrong size if a folder on the pathbar changes name. https://bugzilla.gnome.org/show_bug.cgi?id=671865 M src/nemo-pathbar.c commit 389845f1f6e175212554aba7645ce728f0a8f7ec Author: Cosimo Cecchi Date: 2012-03-12 pathbar: don't set use-markup before resetting the label If the label contains markup text, setting use_markup before resetting the text can spawn a warning (and we're resetting the label text right afterwards anyway). M src/nemo-pathbar.c commit 799514c57003d174b466c1fbf262f1229cf9d9df Author: Nilamdyuti Goswami Date: 2012-03-12 Assamese translation completed M po/as.po commit e6a47735728f2e9e40b7c036d94b8c7e7c996ef6 Author: Timo Jyrinki Date: 2012-03-12 Finnish translation update from http://l10n.laxstrom.name/wiki/Gnome_3.4 translation sprint M po/fi.po commit 269abde49580fe4ffa3ec0f31a4efa494860a1d5 Author: Piotr DrÄ…g Date: 2012-03-10 Updated Polish translation M po/pl.po commit 6449cbff18611f8583f98a6ce4e97b66c9667d52 Author: Seong-ho Cho Date: 2012-03-10 Updated Korean translation M po/ko.po commit 376678e92a107703ba19dd34fc4012ef4f04cf8c Author: Kristjan SCHMIDT Date: 2012-03-10 Updated Esperanto translation M po/eo.po commit 878e2a4f7ada26bb7c106e5bbdbd8434acf86c77 Author: Cosimo Cecchi Date: 2012-03-08 view: fix zoom direction for smooth scrolling case M src/nemo-view.c commit 1a76e044a2c9b834d00c4ea30f1e3af3321d8cdd Author: Cosimo Cecchi Date: 2012-03-08 view: handle smooth scroll events for zooming Instead of reaching the g_assert_not_reached() and crash. https://bugzilla.gnome.org/show_bug.cgi?id=671650 M src/nemo-view.c commit 0d46b0620b3b120cde310cb2319c309d8f3e3b82 Author: Cosimo Cecchi Date: 2012-03-07 all: remove eel_g_hash_table_new_free_at_exit() Especially when references can be owned by non-resident modules, this is just too dangerous. https://bugzilla.gnome.org/show_bug.cgi?id=670989 M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h M eel/eel-stock-dialogs.c M eel/eel-string.c M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M libnemo-private/nemo-signaller.c M libnemo-private/nemo-thumbnails.c M src/nemo-properties-window.c commit b9c51fd4eb84a9f52ee4be1bf183fc516984130b Author: Cosimo Cecchi Date: 2012-03-07 view: show applications for non launcher desktop files https://bugzilla.gnome.org/show_bug.cgi?id=319981 M src/nemo-mime-actions.c M src/nemo-view.c commit 5a47a484e45218e83202c508b421b1a2707af270 Author: Cosimo Cecchi Date: 2012-03-07 link: fix code to parse additional description for links For some reason, this was ifdeffed out. M libnemo-private/nemo-link.c M src/nemo-icon-view-container.c commit 9ff4e9194215cd955b952b1a82bd6a9d80e666cd Author: Cosimo Cecchi Date: 2012-03-07 link: remove obsolete check for application/x-gnome-app-info We stopped supporting this everywhere else ages ago. M libnemo-private/nemo-link.c commit 0ffe4ea4e0df9e5a186b3096bf1712011230a75b Author: Cosimo Cecchi Date: 2012-03-07 file-dnd: only accept launchers as DnD targets Not random desktop files. M libnemo-private/nemo-file-dnd.c commit b241fd28913e87fe01419e4922259949a11c973f Author: Cosimo Cecchi Date: 2012-03-07 file: don't consider all desktop files nemo links Only those which match application/x-desktop directly. M libnemo-private/nemo-file.c commit 1ef720295bc14630522f2496d194c7c43ccc016a Author: Cosimo Cecchi Date: 2012-03-07 directory-async: remove code that was never executed The ifdef is never defined, so we should just remove this code. M libnemo-private/nemo-directory-async.c commit b4877e5bb19d99936987dc9507fba273a55c3a5a Author: Cosimo Cecchi Date: 2012-03-07 properties-window: fix packing for desktop file properties box Fallout from GtkTable->GtkGrid migration. M src/nemo-properties-window.c commit cc05cdd37fa4e34164081222740c266ae5761508 Author: Bruce Cowan Date: 2012-03-07 Updated British English translation M po/en_GB.po commit aed94bad3ea8eaa6c603f8d85cbfb8cd1fd824fd Author: Arash Mousavi Date: 2012-03-06 Updated Persian Translation M po/fa.po commit 36b1557baf6ecc923e821d417531895640195c4f Author: Bruno Brouard Date: 2012-03-06 Updated French translation M po/fr.po commit 34e74c768d5f39a65056716429a84306c3901992 Author: Matej UrbanÄiÄ Date: 2012-03-06 Updated Slovenian translation M po/sl.po commit b1c3776dd91c29e4e9c1f020c24bb039ef730962 Author: Inaki Larranaga Murgoitio Date: 2012-03-06 Updated Basque language M po/eu.po commit 7fdd100f259046f86500da3eb64cf10bceaba2bd Author: Cosimo Cecchi Date: 2012-03-05 build: bump required GTK version to 3.3.17 I.e. the current git master. M configure.in commit df2cf158aa93e2d395b57ce2a1bf4b89bac20709 Author: Cosimo Cecchi Date: 2012-03-05 release: prepare for 3.3.91 M NEWS M configure.in commit ab5077e0bce77af4cad87a20fec8099e3db0bcc0 Author: Michael Terry Date: 2012-03-05 slot: don't ref the NemoWindowSlot when setting floating bar timeout We cancel the timeout on destruction already, and if a destroy event happens in between the timeout, this would break the assumption in NemoWindowPane that all its slots were removed during its destruction. https://bugzilla.gnome.org/show_bug.cgi?id=670591 M src/nemo-window-slot.c commit 819a5d14a33d95ba5ef25a3becec4ebccb93807b Author: Michael Terry Date: 2012-03-05 file-operations: use the right prototype for empty trash callback When unmounting, we might first prompt whether the trash should be emptied or not on the target volume. If we do so, make sure the callback from the empty trash job has the right prototype, to avoid crashing later trying to interpret a gboolean as a pointer to a data structure. https://bugzilla.gnome.org/show_bug.cgi?id=670595 M libnemo-private/nemo-file-operations.c commit 503443418709c9fb42af52c90c035b3957b0686e Author: Cosimo Cecchi Date: 2012-03-05 pathbar: copy implementation of an event window from the GTK copy In order to listen for scroll events on the whole pathbar area, we need to create an event window in realize(), created with GDK_SCROLL_MASK. Copy the code from GtkPathBar that implements this. M src/nemo-pathbar.c M src/nemo-pathbar.h commit 04116ab2876412445c788091be07d7f7321a4a94 Author: Cosimo Cecchi Date: 2012-03-05 pathbar: sync with GTK master to make scrolling work again M src/nemo-pathbar.c commit 4c83328a0ba2d511fea8cefe1464269fbaa1b35f Author: Cosimo Cecchi Date: 2012-03-05 Revert "Revert "Fix up accidental error in last commit"" Having people randomly commit unapproved controversial changes to the UI during UI freeze is so awesome... This reverts commit 50a174cfbf288f07d2f9bf44f31af41dc1535df8. M src/nemo-view.c commit 29a050d986bd5fd86ef522617966768c8c40beb7 Author: Cosimo Cecchi Date: 2012-03-05 Revert "Revert "Use ctrl-delete as the keyboard shortcut to trash files"" Having people randomly commit unapproved controversial changes to the UI during UI freeze is so awesome... This reverts commit 6c21b39cd9d22de4c92ab214e647e65fbfdfe9ac. M src/nemo-view.c commit 6c66de56871a7201c6b0c13d216a237a2e4a4af3 Author: Hannie Dumoleyn Date: 2012-03-04 Updated Dutch translation M po/nl.po commit 24bbb0d39a285546538961d917a070f1ead27bed Author: Arash Mousavi Date: 2012-03-04 Updated Persian Translations M po/fa.po commit 4a0dcfa280ebf9ade975fbefc470f9d3334b1175 Author: Nguyá»…n Thái Ngá»c Duy Date: 2012-03-04 Updated Vietnamese translation M po/vi.po commit 46ba80571e73335fa2fde48529e73b6f2b3f0453 Author: Nguyá»…n Thái Ngá»c Duy Date: 2012-03-03 po/vi: import from Damned Lies M po/vi.po commit 55660df03074e3759a88fd5cf4a45d0a0ce8830a Author: Gabor Kelemen Date: 2012-03-04 Updated Hungarian translation M po/hu.po commit 2c289a073bd0ff4b779f70885566b0783534a1da Author: Daniel Korostil Date: 2012-03-02 Uploaded Ukranian M po/uk.po commit 202b772a7b6fcd7ac758011935cc0eb4eca8454e Author: Mario Blättermann Date: 2012-02-29 [l10n] Updated German translation M po/de.po commit 6c21b39cd9d22de4c92ab214e647e65fbfdfe9ac Author: Xavier Claessens Date: 2012-02-27 Revert "Use ctrl-delete as the keyboard shortcut to trash files" This reverts commit cce40272e35b20b4aaf5f93109a05b7bb89704d5. M src/nemo-view.c commit 50a174cfbf288f07d2f9bf44f31af41dc1535df8 Author: Xavier Claessens Date: 2012-02-27 Revert "Fix up accidental error in last commit" This reverts commit c6279ac229545d7f64b64212383df2753482e233. M src/nemo-view.c commit f8f2aa2c1caa6c3eb2ad801f9b1644b505ec1e3f Author: Dr.T.Vasudevan Date: 2012-02-26 updated Tamil translation M po/ta.po commit b1de3f789a3271d459815ec6d04ece342ebf8d1c Author: Dr.T.Vasudevan Date: 2012-02-26 updated Tamil translation M po/ta.po commit b4272502dbdb48656502679e364c25ea945e1945 Author: Dr.T.Vasudevan Date: 2012-02-26 updated Tamil translation M po/ta.po commit 9c0bf9befaa286a96b4300d462954de003708340 Author: A S Alam Date: 2012-02-26 update Punjabi Translation M po/pa.po commit 94463615ff55a9217470054084f4af8e819ee9c8 Author: Abderrahim Kitouni Date: 2012-02-23 Updated Arabic translation by Ibrahim Saed and Abderrahim Kitouni M po/ar.po commit 73929f70316bd2b120a67725fdd43bc5a996149b Author: Mattias Põldaru Date: 2012-02-22 [l10n] Updated Estonian translation M po/et.po commit ab0af563ecfd50632cbb8491e634282a0f15ea07 Author: Mattias Põldaru Date: 2012-02-22 [l10n] Updated Estonian translation M po/et.po commit fa8997416110581ed48979fdf873f8fe28fcf87b Author: Ask H. Larsen Date: 2012-02-20 Updated Danish translation M po/da.po commit b05d9fd27463054916f84626f4d1a8daf9543d18 Author: МироÑлав Ðиколић Date: 2012-02-20 Updated Serbian translation M po/sr.po M po/sr@latin.po commit 30f1d93169661d1493ffca3baace20577bed4a3a Author: Cosimo Cecchi Date: 2012-02-20 release: prepare for 3.3.90 M NEWS M configure.in commit 3da42acd7a4da971294708e683394a2292c54c12 Author: Cosimo Cecchi Date: 2012-02-20 build: link eel and libnemo-private to libm M eel/Makefile.am M libnemo-private/Makefile.am commit 6fecf4844d5ae749c83a943af950ee594fc2e73d Author: Cosimo Cecchi Date: 2012-02-20 file: add a default empty implementation of set_metadata methods Otherwise we will segfault for subclasses of NemoFile that don't override the method. https://bugzilla.gnome.org/show_bug.cgi?id=669735 https://bugzilla.gnome.org/show_bug.cgi?id=669711 M libnemo-private/nemo-file.c commit 9fda64f91fdbd470e8a84991427dd1e9cb0b8ebf Author: Ihar Hrachyshka Date: 2012-02-20 Updated Belarusian translation. M po/be.po commit 67c5ba88c073c0a6620f22d7223d2bd3b450f499 Author: Ihar Hrachyshka Date: 2012-02-20 Updated Belarusian translation. M po/be.po commit f6f651bff8f5961ea4577c7aaa81ada8263a74da Author: Kjartan Maraas Date: 2012-02-20 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 448c7991f3c2fb7c2434cd7a2dab8dfae399f609 Author: Adam MatouÅ¡ek Date: 2012-02-20 Updated Czech translation M po/cs.po commit c3f5c2afdd1f740576029544d21e732759e54ba0 Author: Daniel Nylander Date: 2012-02-19 Updated Swedish translation M po/sv.po commit 720b994d93d62f346e0cde181bdfc1817916f13c Author: Yaron Shahrabani Date: 2012-02-18 Updated Hebrew translation. M po/he.po commit 0d4de6246689ab67b40dad1d206114915589d18f Author: Chao-Hsiung Liao Date: 2012-02-18 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit ea10e1a45f11ea3771b92f411a0817fd9049fc88 Author: Jiro Matsuzawa Date: 2012-02-17 [l10n] Update Japanese translation M po/ja.po commit d5cc4631ee4366bcf7f33c78bf193eb0e1cbb8b0 Author: Luca Ferretti Date: 2012-02-16 l10n: Updated Italian translation M po/it.po commit 41106223c6124fb8b427810a3e9a5b9d270777fa Author: Fábio Nogueira Date: 2012-02-16 Updated Translator Credits in Brazilian Portuguese Translation M po/pt_BR.po commit 8b21dc1de851f4e49a791cb2d878570e26985975 Author: Alexander Shopov Date: 2012-02-16 Updated Bulgarian translation M po/bg.po commit 570266ce8c0ccd0e2382cd6cf5fdd59339b9a7c1 Author: Yuri Myasoedov Date: 2012-02-15 Updated Russian translation M po/ru.po commit a7843cb0d1bff3deafed93d9c9e2c7d8d6ebf458 Author: Daniel Mustieles Date: 2012-02-15 Updated Spanish translation M po/es.po commit 4421b79de801efd5fbd7d6ef6666e2b0e3b813f9 Author: Fran Diéguez Date: 2012-02-14 Updated Galician translations M po/gl.po commit 2c7b82f2d3712f08dc940828b7a4b4de55164621 Author: Cosimo Cecchi Date: 2012-02-14 undo: add ngettext plural forms for undo operation strings Even if we don't use those strings for singular cases, this is still needed, since some languages might need to use the singular form for e.g. the x1st item. See: https://live.gnome.org/TranslationProject/DevGuidelines/Plurals https://bugzilla.gnome.org/show_bug.cgi?id=669889 M libnemo-private/nemo-file-undo-operations.c commit 01382c267728e2dd00cc8b48cd6024dbae183345 Author: Cosimo Cecchi Date: 2012-02-13 pane: don't make the toolbar for inactive pane insensitive At the same time, we have to listen for events on the toolbar items to set the active pane. M src/nemo-search-bar.c M src/nemo-search-bar.h M src/nemo-window-menus.c M src/nemo-window-pane.c commit 3787143f2bcf576a9b75600b40a324454b25beca Author: Cosimo Cecchi Date: 2012-02-13 pane: set a style class on the inactive window pane to style it Set a "nemo-inactive-pane" style class on the inactive NemoWindowPane; this allows us to theme the inactive pane state way more easily and removes a bunch of setup code. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M libnemo-private/nemo-icon-private.h M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-view.c M src/nemo-view.h M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 31dad6f9fa05dc64fc1ead54bdad9bbae4bfa713 Author: Cosimo Cecchi Date: 2012-02-13 icon-canvas-item: don't override parent container style flags When drawing the canvas item elements, don't override the parent container style flags, so we don't lose e.g. backdrop information. M libnemo-private/nemo-icon-canvas-item.c commit 457c9ccaf17e34366ea4bacb7d3a1a72094fb8d7 Author: Baurzhan Muftakhidinov Date: 2012-02-12 [l10n] Updated Kazakh translation M po/kk.po commit 47778be25cf65fbcd0151093fc7e2b3aa14b229c Author: Cosimo Cecchi Date: 2012-02-11 floating-bar: add "floating-bar" style class M src/nemo-floating-bar.c commit ef34e92b4c685c25e36d67b8b266ac6bff1489f0 Author: Yuri Myasoedov Date: 2012-02-11 Updated Russian translation M po/ru.po commit 8d064c5e5782e98bb63836b92847ff1260f4b77f Author: Tiffany Antopolski Date: 2012-02-10 po: updated en_CA.po M po/en_CA.po commit cd497dd43fabc6b9aa679fd326bb0f16334dbd59 Author: Cosimo Cecchi Date: 2012-02-08 undo: fix a double free in the Create operation strings func https://bugzilla.gnome.org/show_bug.cgi?id=669691 M libnemo-private/nemo-file-undo-operations.c commit 071f40683bda36eb47df8a2c536da282b9fb04e6 Author: Cosimo Cecchi Date: 2012-02-06 release: prepare for 3.3.5 M NEWS M configure.in commit b7a3fddf60aaeac95f85259b2d83fc3cde81959f Author: Cosimo Cecchi Date: 2012-02-06 places-sidebar: change the way we restore selection on update Instead of checking whether the URI of every item we add is a candidate for selection, cycle through all the added items after inserting. This also fixes a bug where the GtkTreeIter we used for keeping track of the last added item was not up-to-date with the actual cell, since the sort function we apply to the items will modify the position of the item in the tree itself, making the iter invalid. https://bugzilla.gnome.org/show_bug.cgi?id=668212 M src/nemo-places-sidebar.c commit 7e7a21daf15055aab8639ba684ce34a6683073fa Author: Cosimo Cecchi Date: 2012-02-06 places-sidebar: don't use an additional GtkTreeModelFilter We were using it just for GtkTreeDragSourceIface, which we can implement ourselves. M src/nemo-places-sidebar.c commit 7c5ebdbbd3c7778af230fc830b5bc6bd706f1d61 Author: Cosimo Cecchi Date: 2012-02-06 window-manage-views: fix a crash when middle-clicking desktop icons We were hitting an assertion when middle clicking a desktop icon, since we were trying to open it in a tab (same window), and we don't really want to do that on the desktop. https://bugzilla.gnome.org/show_bug.cgi?id=655576 M src/nemo-window-manage-views.c commit 4abf11d07e8d8bc86523e105db9c6c76f29e9643 Author: Cosimo Cecchi Date: 2012-02-06 window: simplify code a bit Don't export nemo_window_update_split_view_actions_sensitivity(), but alwauys call it from nemo_window_update_show_hide_menu_items(), since that's what the code always does. https://bugzilla.gnome.org/show_bug.cgi?id=669189 M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window.c commit 2626eacbd9883161d7d3b14f4e1c56a02e3eb7ce Author: Cosimo Cecchi Date: 2012-02-06 pane: don't forget to update the split view actions when closing a slot In case a slot close is requested, we should still update the split view actions sensitivity/state. https://bugzilla.gnome.org/show_bug.cgi?id=669189 M src/nemo-window-pane.c commit e8c4685f033b11034fa24007c558b8fc347024d3 Author: Cosimo Cecchi Date: 2012-02-06 desktop-background: stop any pending crossfades on widget destruction Internally, GnomeBGCrossfade depends on the GdkWindow we pass on to gnome_bg_crossfade_start() to be available during the whole crossfade. If our widget is destroyed, we have to immediately stop the crossfade, without waiting our finalization step, which happens after the widget is already gone. M libnemo-private/nemo-desktop-background.c commit 91fc1674ae71d356b06b8b549e91782a2b06758a Author: Cosimo Cecchi Date: 2012-02-06 desktop-background: unref the GnomeBG on finalize This also prevents signals being emitted from it after our destruction, as in https://bugzilla.gnome.org/show_bug.cgi?id=665796 M libnemo-private/nemo-desktop-background.c commit 9d0f892656282519059d65f10db7504ad4910b22 Author: Cosimo Cecchi Date: 2012-02-06 pane: don't access invalid memory slot->pane is already cleared in nemo_window_slot_dispose(), which will get called while the slot is destroyed; setting it here can cause an invalid memory access. M src/nemo-window-pane.c commit 1bfe1dd449bdfb80e58f6f149d87c153f13962f2 Author: Piotr DrÄ…g Date: 2012-02-04 Updated Polish translation M po/pl.po commit 6b2e19cb9957f0685eb561a6e22c1be6730e6fee Author: Cosimo Cecchi Date: 2012-01-31 undo: fix logic in the file operation callback This caused some actions not to be scheduled for redo. M libnemo-private/nemo-file-undo-operations.c commit c4099c1a20c0502dd7a12e0d1ffbfe70d4bf527a Author: Cosimo Cecchi Date: 2012-01-30 application: fix an unfortunate typo We were allocating the wrong size for the NemoApplication private structure. M src/nemo-application.c commit d60b724d5ee183b1074a137d9cc24c22b3a2259d Author: Cosimo Cecchi Date: 2012-01-30 undo: fix Redo Trash not updating the trashed mtime When we redo a trash operation, we should make sure our trashed files hash table stores the updated timestamp when we trashed the file again, or we won't be able to trash them again. M libnemo-private/nemo-file-undo-operations.c commit 2a02b02328e20ac66b8cb71140681fdd0ac384ff Author: Cosimo Cecchi Date: 2012-01-30 undo: make sure to correctly clear the undo state on operation finish Don't stack allocate the struct for the file operations return value, and make sure we don't return success for a failed operation. M libnemo-private/nemo-file-undo-operations.c commit 2944be953ef54717bb24968b0eebe468c9705db4 Author: Chao-Hsiung Liao Date: 2012-01-29 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 56a0b14e55239bf5076f1c73b30f534af1dd1a86 Author: Matej UrbanÄiÄ Date: 2012-01-28 Updated Slovenian translation M po/sl.po commit f34c331ca81e4bafd6db4c6c36c7b3625c674278 Author: Matej UrbanÄiÄ Date: 2012-01-28 Updated Slovenian translation M po/sl.po commit 3738ee50a11a2d3997c470cb19a23521c60c256e Author: Yaron Shahrabani Date: 2012-01-28 Updated Hebrew translation. M po/he.po commit 247a27a94b28304dbb0b4aaf2ff783d0d909a73c Author: Timo Jyrinki Date: 2012-01-24 Updated Finnish translation. M po/fi.po commit 9736b263c7830dad6c9de6b42f131395201b993b Author: Cosimo Cecchi Date: 2012-01-23 undo: remove some URI->GFile roundtrips in the trash undo operations We can just store GFiles directly in the hash table and use g_file_hash() and g_file_equal() instead of parsing the URIs ourselves. M libnemo-private/nemo-file-undo-operations.c commit 211d4429171e6d3e307cb175513077f61c86b640 Author: Cosimo Cecchi Date: 2012-01-23 undo: don't provide any free function for trashed hashtable values No need to call g_free() anymore. M libnemo-private/nemo-file-undo-operations.c commit 3c3096371bb8fda0766c59c9467eb8ed24ed67cf Author: Arthur Taylor Date: 2012-01-22 Make rubberband fade obey gtk animation setting. The rubberband fade-out effect should observe the gtk animation setting, intened to make life easier for people running resource contrained setups (like X11 over a network.) Signed-off-by: Arthur Taylor M libnemo-private/nemo-icon-container.c commit 125cc4026585b760071db630ffd6edcce1ad8c93 Author: Kjartan Maraas Date: 2012-01-23 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 7b74cfc6fd6279599753f777620e2537d1f23e61 Author: Daniel Mustieles Date: 2012-01-23 Updated Spanish translation M po/es.po commit 45a2f47e35002b316cb8ccb94073deaa6bb75850 Author: Fran Diéguez Date: 2012-01-22 Updated Galician translations M po/gl.po commit 362fb6464b62d6fed896d1bc53f6fc763f8fa6fb Author: Cosimo Cecchi Date: 2012-01-21 undo: rework undo for the trash operation to be asynchronous Also, make the mtime checks actually useful; we need to check the trash::deletion-date attribute and match it with the time we trashed the file (which we can easily know using g_get_current_time()). M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-undo-operations.c M libnemo-private/nemo-file-undo-operations.h commit c063418e66ed0fdc40b4fd48bc5bd29c0cbefa09 Author: Cosimo Cecchi Date: 2012-01-21 undo: fix undo move to trash We were querying the mtime of the trashed file after it was already trashed, and we were also overflowing the guint64 assigning -1 to it. M libnemo-private/nemo-file-operations.c commit bf38d260d1011c08f5e36f3d7d78e10244627e16 Author: Cosimo Cecchi Date: 2012-01-21 undo: always complete the apply action in idle The action might be synchronous. M libnemo-private/nemo-file-undo-operations.c commit 89cc154cee3e64a771499d21f410854ecc5cd8ad Author: Piotr DrÄ…g Date: 2012-01-21 Updated POTFILES.in M po/POTFILES.in commit f8e8507dcfa98e21a1454cb5290b071abec680e4 Author: Daniel Mustieles Date: 2012-01-21 Updated Spanish translation M po/es.po commit 5f338fc07e288dcc2ff6e141edc42aade01da284 Author: Cosimo Cecchi Date: 2012-01-20 undo: remove NemoFileUndoTypes M libnemo-private/Makefile.am D libnemo-private/nemo-file-undo-types.h commit 3f45de05a6a87c8d432e94375f714c3da1f8fc34 Author: Cosimo Cecchi Date: 2012-01-20 view: use NemoFileUndoInfo directly Get the info object from the manager and use that to build menus. M src/nemo-view.c commit aac633c6d66d7dd9753b645e88657a7f6257e8eb Author: Cosimo Cecchi Date: 2012-01-20 file/file-operations: adapt to changes in file undo manager And fix some typos. M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c commit 1f758301ee89b5f96bcb650f039696a7049fac44 Author: Cosimo Cecchi Date: 2012-01-20 file-undo-manager: use NemoFileUndoInfo Rework NemoFileUndoManager to use the new NemoFileUndoInfo objects. At the same time, make it use a single item instead of a queue, turning it into a state machine. This has various reasons; from a code perspective, if we keep a stack of operations, we should also keep track and invalidate items in there when something changes on the filesystem, but this can be very expensive. On the other hand in the UI we probably don't want to expose more than one item anyway. M libnemo-private/nemo-file-undo-manager.c M libnemo-private/nemo-file-undo-manager.h commit 69e79e2f9d3c8c2bbae4a0a32e58f42385c662b4 Author: Cosimo Cecchi Date: 2012-01-20 undo: turn NemoFileUndoData into NemoFileUndoInfo Make it a GObject with subclasses for each type of operations. This allows for easy sharing of the base class object with the view as well, for menu information, and provides an async API to the undo manager for the file operation. M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file-undo-operations.c M libnemo-private/nemo-file-undo-operations.h M libnemo-private/nemo-file-undo-types.h M libnemo-private/nemo-file.c commit 44b695b9af6a26fbf2979a19fd638cc3682c89bb Author: Cosimo Cecchi Date: 2012-01-18 file-operations: first pass at passing on success information We want to know if a file operation failed for some reason, so that we don't add it in the redo queue. M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-operations.h M libnemo-private/nemo-file-undo-manager.c M libnemo-private/nemo-file-undo-manager.h M libnemo-private/nemo-file-undo-operations.c M libnemo-private/nemo-file-undo-operations.h M libnemo-private/nemo-file-undo-types.h M src/nemo-places-sidebar.c M src/nemo-properties-window.c M src/nemo-tree-sidebar.c M src/nemo-view.c M test/test-copy.c commit f76844a3208033a97532222ce531bd9a04205871 Author: Cosimo Cecchi Date: 2012-01-16 undo: pass in a GtkWindow for undo operations So that dialogs triggered by the file operations can correctly be parented. M libnemo-private/nemo-file-undo-manager.c M libnemo-private/nemo-file-undo-manager.h M libnemo-private/nemo-file-undo-operations.c M libnemo-private/nemo-file-undo-types.h M src/nemo-view.c commit dcf5d6796b5adc13a4b03d36f30d9f15025e9df9 Author: Amos Brocco Date: 2012-01-16 undo: introduce undo support M libnemo-private/Makefile.am M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-private.h A libnemo-private/nemo-file-undo-manager.c A libnemo-private/nemo-file-undo-manager.h A libnemo-private/nemo-file-undo-operations.c A libnemo-private/nemo-file-undo-operations.h A libnemo-private/nemo-file-undo-types.h M libnemo-private/nemo-file.c M src/nemo-directory-view-ui.xml M src/nemo-shell-ui.xml M src/nemo-view.c M src/nemo-window-menus.c commit 88f18618ba15b952a739e410b910508f244b1fc3 Author: Vincent Untz Date: 2012-01-19 build: Support build against tracker 0.13/0.14 https://bugzilla.gnome.org/show_bug.cgi?id=667853 M configure.in commit b65b13f59e0bb20497751a5c13ea85ccb7ebb2ba Author: Daniel Mustieles Date: 2012-01-17 Updated Spanish translation M po/es.po commit 01a2c0affada3157cf5b7b8147e27d6a0a0151dc Author: Fran Diéguez Date: 2012-01-17 Updated Galician translations M po/gl.po commit 3795ec8883676e367be1d7f9d6314a1a7e781fd7 Author: Cosimo Cecchi Date: 2012-01-16 notebook: use a symbolic icon for the tab close image M src/nemo-notebook.c commit 1a5cc61ae329d3776e8d75fd46b0e9326f0e7654 Author: Kjartan Maraas Date: 2012-01-16 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 8ff0ae7d645b4c076977ab889b46a20392d3da25 Author: Cosimo Cecchi Date: 2012-01-16 release: prepare for 3.3.4 M NEWS M configure.in commit 8c778211e5c826998890d2034b828928c693e4d9 Author: Carlos Garnacho Date: 2012-01-12 eel: Queue resizes on the canvas as elements change visibility Not queueing resizes may play oddly with the size request caches in GTK+, resulting in gtk_widget_get_preferred_width/height returning 0 even after the canvas was populated. https://bugzilla.gnome.org/show_bug.cgi?id=667831 M eel/eel-canvas.c commit f1bb90717ba78533905d3f532940a390371a979c Author: Cosimo Cecchi Date: 2012-01-16 build: add nemo.gresource.xml to EXTRA_DIST Fix distcheck. M src/Makefile.am commit 132bf6802d9e36354e89469f3ef0b5daa1082299 Author: Cosimo Cecchi Date: 2012-01-16 extension: doc cleanups M docs/reference/libnemo-extension/Makefile.am M docs/reference/libnemo-extension/libnemo-extension-docs.xml M docs/reference/libnemo-extension/libnemo-extension-sections.txt commit e79c28b48008ed5e94763417b4a68b86ffcfd919 Author: Cosimo Cecchi Date: 2012-01-16 extension: add some more missing gir annotations M libnemo-extension/nemo-column-provider.c M libnemo-extension/nemo-menu-provider.c M libnemo-extension/nemo-menu.c M libnemo-extension/nemo-property-page-provider.c commit f04f79a424a03127c4d3ab44bd1363ff00ade212 Author: Cosimo Cecchi Date: 2012-01-16 build: update gitignore M data/.gitignore M src/.gitignore commit 607c8a11f41d7f1a49f67421d4b98a6edbcbcee5 Author: Cosimo Cecchi Date: 2012-01-16 module: don't access the GModule if none was returned Before checking if the GModule pulls in ORBit, we should make sure g_module_open() returned a non-NULL GModule. M libnemo-private/nemo-module.c commit 024381aac07aeb7ed161913e601fcefbf4e3f990 Author: Marcus Carlson Date: 2012-01-16 file-operations: show current file counter and total files Change the file operation strings so that both the current file counter and the total number of files are shown in the UI. https://bugzilla.gnome.org/show_bug.cgi?id=606955 M libnemo-private/nemo-file-operations.c commit e0b3e63b6fedb8bd056c80647c43f4f388c3b1ed Author: Cosimo Cecchi Date: 2012-01-16 build: require latest GLib and GTK+ This is needed for the new resources API. M configure.in commit 733c890a5d7e4615b754accc0c7906545b9a0b59 Author: Alexander Larsson Date: 2012-01-12 Move all ui files and icons into resources M icons/Makefile.am M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file-utilities.h M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-thumbnails.c M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h M src/Makefile.am M src/nemo-bookmarks-window.c M src/nemo-desktop-icon-view.c M src/nemo-file-management-properties.c M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-toolbar.c M src/nemo-view.c M src/nemo-window-menus.c A src/nemo.gresource.xml commit d6291d9ae62de65deaafd72cf9f5a5e22e627cf3 Author: Yaron Shahrabani Date: 2012-01-14 Updated Hebrew translation. M po/he.po commit 1df7de8a1ab643ebefe3d8df7ab0343f36687299 Author: Martin Pitt Date: 2012-01-05 Lazily initialize notification service Avoid spawning the notification daemon at startup through querying server caps. Instead, cache the result in server_has_persistence() and initialize it lazily. https://bugzilla.gnome.org/show_bug.cgi?id=667342 M src/nemo-progress-ui-handler.c commit 6010f04793f926d2cc3c3533ce2f8de3f24eccc6 Author: Og B. Maciel Date: 2012-01-12 Fixes wrong translation on warning about long filename. BGO #667495. M po/pt_BR.po commit 69cb7b536c0df4331b7c36aca9f71e67c8b19009 Author: Timo Jyrinki Date: 2012-01-12 Updated Finnish translation. M po/fi.po commit 6003b063ee2af39644d4138e52ae93bd5b513ac1 Author: Cosimo Cecchi Date: 2012-01-09 extension: add some annotations M libnemo-extension/nemo-file-info.c M libnemo-extension/nemo-location-widget-provider.c commit 0d0eb9b50e5fd24a09bc2b9c141950fb75d86db3 Author: Cosimo Cecchi Date: 2012-01-09 window: make nemo_window_prompt_for_location() private M src/nemo-window-menus.c M src/nemo-window.c M src/nemo-window.h commit d01abc43d6bf016b573cbd0d6b6d0dc1bd127873 Author: Cosimo Cecchi Date: 2012-01-09 window: remove unused view-as-changed signal M src/nemo-window.c commit 006e8207d13da318aa912a860930dd79f04fb085 Author: Cosimo Cecchi Date: 2012-01-09 window: remove unused zoom-changed signal M src/nemo-window.c commit d48669776205bf7732601d73d2fddec5b44a53ef Author: Cosimo Cecchi Date: 2012-01-09 pane: remove useless assertion Now that the slots are direct pages of the GtkNotebook, there's no need to ensure the slot is in the pane's list, since we already assert on gtk_notebook_page_num(slot) >= 0. M src/nemo-window-pane.c commit ec391bf3de51ab4ee7f510ab6570fc240a7754c0 Author: Cosimo Cecchi Date: 2012-01-09 slot: make NemoWindowSlot a GtkBox Simplifies management of the slot quite a bit. M src/nemo-notebook.c M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-slot.c M src/nemo-window-slot.h commit 283c4903139dc08b7b69afa117870e143cc64137 Author: Cosimo Cecchi Date: 2012-01-09 notebook: remove unused defines M src/nemo-notebook.c commit 115c960e939a1c1fa6db97a105fe92d0b70ecde8 Author: Cosimo Cecchi Date: 2012-01-09 slot: remove unused cases for NemoLocationChangeType M src/nemo-window-manage-views.c M src/nemo-window-slot.h commit 1cb66dfb4c3750a142dfd3130613b52b1d386eff Author: Cosimo Cecchi Date: 2012-01-07 search-bar: remove unused focus-in signal M src/nemo-search-bar.c M src/nemo-search-bar.h commit f49a5b864058cc5bb4b1534ab03e89d1e9fdbc34 Author: Cosimo Cecchi Date: 2012-01-07 window: move nemo_window_update_up_button() to NemoWindow M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window.c commit 2705e8019c6f6b3714b679788827c5c297798cf9 Author: Cosimo Cecchi Date: 2012-01-07 pane: cleanup M src/nemo-properties-window.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window-types.h M src/nemo-window.c M src/nemo-window.h commit 1af49b5dd84e9127785f2c507940574d6f62ecbf Author: Cosimo Cecchi Date: 2012-01-07 window: use g_clear_object M src/nemo-window-manage-views.c M src/nemo-window-menus.c commit 4d22ba9b6100556bf6f81f827b38dc9ad0626ac3 Author: Cosimo Cecchi Date: 2012-01-06 window: nuke unused functions M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h commit ed97a6ec6db1a618bc65705618e5b73748e4cd7e Author: Cosimo Cecchi Date: 2012-01-06 all: use nemo_window_slot_get_window() M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window.c commit f1f7bf476b3c932d13927e55292e8bd8b77b29d8 Author: Cosimo Cecchi Date: 2012-01-06 application: remove useless assignment M src/nemo-application.c commit e83f6e0990971ea22275bd9cf877541b7824ab14 Author: Cosimo Cecchi Date: 2012-01-06 pane: refactor to make NemoWindow a GObject property M src/nemo-window-pane.c commit 93923f66225434e42ef6bb8588e7d3fbdb3409a4 Author: Cosimo Cecchi Date: 2012-01-06 window: fold nemo_window_allow_up() into its only caller M src/nemo-window-manage-views.c M src/nemo-window.c M src/nemo-window.h commit f5db1b3062a42a649fbc11e4272399cfa70dc772 Author: Cosimo Cecchi Date: 2012-01-06 window: remove unused nemo_window_allow_back/forward M src/nemo-window.c M src/nemo-window.h commit f784b5b57503e58c49a1d55b0c664096951c9018 Author: Cosimo Cecchi Date: 2012-01-06 pane: use nemo_navigation_state_set_boolean() M src/nemo-window-pane.c commit f3eff82082f4ebd88e01d3efbe2631a15989cfa9 Author: Cosimo Cecchi Date: 2012-01-06 navigation-state: add API to sync a boolean value on a tracked action M src/nemo-navigation-state.c M src/nemo-navigation-state.h commit 9384542c1821420c01962237d23e9716bc5a8404 Author: Cosimo Cecchi Date: 2012-01-06 window: add nemo_window_get_navigation_state() M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window.c M src/nemo-window.h commit f876211d2e318580d1f28c57e7f0182f7c5bfb3a Author: Cosimo Cecchi Date: 2012-01-06 window: add nemo_window_get_main_action_group() M src/nemo-desktop-window.c M src/nemo-window-menus.c M src/nemo-window.c M src/nemo-window.h commit 419d49de7dd714095fbd63dd7093fec5c07a52fb Author: Cosimo Cecchi Date: 2012-01-06 slot: fold function into the only caller Also simplify its code a bit. M src/nemo-window-slot.c commit 7289cc044cfaa3eee69396805d4e6dd8644a9483 Author: Cosimo Cecchi Date: 2012-01-06 slot: cleanup NemoWindowSlot creation M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit b09427273f525753b4b792bfdfb333e28c2e0ea9 Author: Cosimo Cecchi Date: 2012-01-06 window: misc cleanups M src/nemo-window-bookmarks.c M src/nemo-window-private.h M src/nemo-window.c commit 33a79d4ca73be9b45b19ff28cd702103a40333c5 Author: Cosimo Cecchi Date: 2012-01-06 window: move nemo_window_open_slot to NemoWindowPane Where it should really belong. M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window.c commit 0d83fdffed7b3c8987e19f6e5ef6f304f5efdb9d Author: Cosimo Cecchi Date: 2012-01-06 slot: don't include gi18n.h in the header M src/nemo-bookmarks-window.c M src/nemo-progress-ui-handler.c M src/nemo-view-dnd.c M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit ac606bd25e13914c28702a5099905ead4e1c1510 Author: Cosimo Cecchi Date: 2012-01-06 all: use nemo_window_get_active_pane() M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window.c commit 455c8da5981db559d7d47d9f9fcb8dac8297d4ac Author: Cosimo Cecchi Date: 2012-01-06 all: use nemo_window_get_active_slot() M src/nemo-location-bar.c M src/nemo-window-bookmarks.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window-slot.c M src/nemo-window.c commit cc151a40cebda4ba7d4adc40c702f0210614105f Author: Cosimo Cecchi Date: 2012-01-02 window: remove bookmark menu placeholder path from NemoWindowClass It's not used by the only subclass we have now. M src/nemo-window-bookmarks.c M src/nemo-window.c M src/nemo-window.h commit 6c8896cfc1a52b0eec31bec3090ee5661af1931e Author: Cosimo Cecchi Date: 2012-01-02 window: remove nemo_window_get_window_type() It's unused now. M src/nemo-desktop-window.c M src/nemo-window.c M src/nemo-window.h commit f167ba4f3f3d571169c07584528e748391c5a833 Author: Cosimo Cecchi Date: 2012-01-02 view: don't use nemo_window_get_window_type() Just check if the view is a NemoDesktopIconView instead. M src/nemo-view.c commit 6561bf66c37ffcff450c7880300661ee260ec5c7 Author: Cosimo Cecchi Date: 2012-01-02 window: remove unused code M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit b5316226924feb948de5f372962c7174ff8fa10d Author: Cosimo Cecchi Date: 2012-01-02 window: remove nemo_window_show_window() Fold it into the only caller, and simplify its code. M src/nemo-window.c M src/nemo-window.h commit 1d06cfcff92afc46bcaf5b313a604b93d76cbdd9 Author: Cosimo Cecchi Date: 2012-01-02 window: remove useless assignment M src/nemo-window.c commit d84023681be2f192ccbd4fe5c3b07631c683911f Author: Cosimo Cecchi Date: 2012-01-02 window: simplify code Fold function into the only caller. M src/nemo-window.c commit 00ad5bc605488e15a6877ce94cbd0e4b1f42cdb1 Author: Ihar Hrachyshka Date: 2012-01-10 Updated Belarusian translation. M po/be.po commit 7aff7fb6b0e5b7717e06944c09de734270d85ed8 Author: Diego Escalante Urrelo Date: 2011-12-29 floating-bar: misc indentation fixes M src/nemo-floating-bar.c commit 2cd406307863c268d045487daeedeb36e22a19bf Author: Alexander Shopov Date: 2012-01-08 Updated Bulgarian translation M po/bg.po commit 669ab8445bb33f00dfeb6584fdc431ea942fda79 Author: Nguyá»…n Thái Ngá»c Duy Date: 2012-01-06 Updated Vietnamese translation M po/vi.po commit f4d439875b3a101fa195012fb8a6607542e69b9a Author: Nguyá»…n Thái Ngá»c Duy Date: 2012-01-06 po/vi: import from Damned Lies M po/vi.po commit 02c0d8b671ee9cd61374b28d1627ab8edff7fe41 Author: Mattias Põldaru Date: 2012-01-02 [l10n] Updated Estonian translation M po/et.po commit a9627858a6b49e505b97c210e95f0bafa91e0a90 Author: Jovan Naumovski Date: 2012-01-01 Updated Macedonian translation. M po/mk.po commit 54dd59e149edcc6d744bba5cd7576526e9b52075 Author: Wylmer Wang Date: 2011-12-27 Update Simplified Chinese translation M po/zh_CN.po commit aacde57c44b1259ed476507b6288416d999832f9 Author: Andreas N Date: 2011-12-26 Updated Norwegian Nynorsk translation M po/nn.po commit 1a050ded4c3625c56022a1d50b856cf298d1f2c2 Author: Xandru Armesto Date: 2011-12-22 Updated asturian translation M po/ast.po commit c6510f6b07caeeffacbfa062660e4fca0219d958 Author: Jürg Billeter Date: 2011-12-20 build: Add gmodule as dependency With GLib 2.31.4 and later, linking against GIO no longer drags in gmodule. M configure.in commit 54ae064f753582a8b0745110b45724b99eb913a4 Author: Cosimo Cecchi Date: 2011-12-19 release: prepare for 3.3.3 M NEWS M configure.in commit 2de1c3a4a0294006bbcf950f7473ff962848dc1c Author: Cosimo Cecchi Date: 2011-12-19 fdo-dbus: dist the DBus interface XML file Fixes distcheck M data/Makefile.am commit 642835db7ab148e44733206a09bf55cd14660e5a Author: Cosimo Cecchi Date: 2011-12-19 fdo-dbus: don't dist generated dbus sources Use nodist_nemo_SOURCES, like the generated object manager for org.Nemo.FileOperations M src/Makefile.am commit f35e710d3c31fc2af5ddce9c31a52d408e215276 Author: Cosimo Cecchi Date: 2011-12-19 fdo-dbus: use the right include for nemo-debug.h Fixes distcheck M src/nemo-freedesktop-dbus.c commit 85af4ef2e58b45dcd40f6ba692b12e73c6cf6ffd Author: Pierre Wieser Date: 2011-12-19 Set icons from extensions on the context menu GtkActions This way, if icons are set to display in e.g. menus, extensions one will be properly shown. https://bugzilla.gnome.org/show_bug.cgi?id=665822 M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h M src/nemo-view.c commit 773fdc3e2ba7fef4bf824c865a0f3aba14fc785a Author: Stefano Teso Date: 2011-12-04 places-sidebar: make Desktop dir bookmarkable if not shown by default See: https://bugzilla.gnome.org/show_bug.cgi?id=663956 M src/nemo-places-sidebar.c commit 2ee1b4060b1d99c67e528d626514968384277af5 Author: Nelson Benitez Leon Date: 2011-12-13 Show background menu when clicking on blank space Fixes bug 94618 M src/nemo-list-view.c commit 73b2f5e9de469f7997c8ab4d12f1aa542a4e7e54 Author: Nelson Benitez Leon Date: 2011-12-14 Fix race condition when right-clicking after rubberbanding Fixes bug 662979 M libnemo-private/nemo-icon-container.c commit 1fbc4002d38f42a5e9536dc3f1b59438d362d94e Author: Petr Kovar Date: 2011-12-15 Fix Czech translation M po/cs.po commit 6ed0cae9df696b816309b6c6d8fdb2660c66b922 Merge: 11fa184 f01e2e9 Author: Federico Mena Quintero Date: 2011-12-14 Merge branch 'freedesktop-dbus' - bgo#636269 This adds an implementation for the DBus interface org.freedesktop.NemoFileManager1. This lets applications call the file manager to show a file within a folder, to show a folder's contents, or to show a file's properties. The main work behind this is by Akshay Gupta , done during the Google Summer of Code 2011. commit f01e2e9b5fa6dcd0514bdf5efe5f76b4312f1fd3 Author: Federico Mena Quintero Date: 2011-12-14 Add an org.freedesktop.NemoFileManager1.service file for DBus Even though this registers a service for a freedesktop name with a Gnome-specific program (Nemo), we'll just do this for now. Later we can discuss in the DBus list how to launch services with generic interfaces, but specific implementations for each desktop environment. Signed-off-by: Federico Mena Quintero M data/Makefile.am A data/org.freedesktop.NemoFileManager1.service.in commit 73e5a35efcd7607d6a3ee5e8bd5e8278a86d6705 Author: Federico Mena Quintero Date: 2011-12-14 Remove superfluous helper function Signed-off-by: Federico Mena Quintero M src/nemo-properties-window.c commit 371e178550587cad04941493c6129e8e454223ab Author: Cosimo Cecchi Date: 2011-12-14 Use a single method to create properties windows Make startup_id a param of nemo_properties_window_present(). M src/nemo-freedesktop-dbus.c M src/nemo-places-sidebar.c M src/nemo-properties-window.c M src/nemo-properties-window.h M src/nemo-tree-sidebar.c M src/nemo-view.c commit 6e02005986b78879f4d3e23342c90accfa241745 Author: Cosimo Cecchi Date: 2011-12-14 properties-window: parent_widget and startup_id are not mutual Even though we don't (yet) use the same code path when building a properties window for a parent widget and for a startup_id (i.e. there's no call that sets both), there's no reason to make them mutually exclusive in code when creating the window. M src/nemo-properties-window.c commit 326f5d86a5650d201c48acacaf77752d544668da Author: Cosimo Cecchi Date: 2011-12-14 fdo-dbus: coding style cleanups M src/nemo-freedesktop-dbus.c commit c0752563fe6f2a0454069b93c9a29dae11a2e833 Author: Cosimo Cecchi Date: 2011-12-14 fdo-dbus: handle g_file_get_parent() failing g_file_get_parent() can return NULL if the file is a root element. Handle that case gracefully in the code. M src/nemo-freedesktop-dbus.c commit 8aa21c333115cec5eab0cd3965684b9b09dc7fa3 Author: Cosimo Cecchi Date: 2011-12-14 application: streamline code for creating selection list M src/nemo-application.c commit 14f7dd8cdbbe04b84c2b8f75134cefd45aaf9c4b Author: Federico Mena Quintero Date: 2011-12-13 Pass the startup_id when creating the properties window This completes the implementation of the DBus interface. Signed-off-by: Federico Mena Quintero M src/nemo-freedesktop-dbus.c commit 625dac4492e7daf7fef46c8dc4990da5d786efad Author: Federico Mena Quintero Date: 2011-12-13 Add nemo_properties_window_present_with_startup_id() This lets us pass a startup_id string instead of a parent_widget; this will be used from the Freedesktop DBus interface. Signed-off-by: Federico Mena Quintero M src/nemo-properties-window.c M src/nemo-properties-window.h commit 9868b796ec9d4761512d0a948bf0d6438be6702c Author: Federico Mena Quintero Date: 2011-12-13 Don't use nested if()s when a single one will do M src/nemo-properties-window.c commit ebc2d0728553cded8dcb5f65d0075e2e7c9d277e Author: Federico Mena Quintero Date: 2011-12-13 Use g_clear_object() instead of verbose code M src/nemo-freedesktop-dbus.c commit 08c2044e7056a9d6113dbf3613ea6303b6f0180d Author: Federico Mena Quintero Date: 2011-12-13 Implement ShowItems() vs. ShowFolders() from the DBus interface We use the new nemo_application_open_location() to do this; now we can distinguish 'open a location and select something inside it', vs. 'show a location'. Signed-off-by: Federico Mena Quintero M src/nemo-freedesktop-dbus.c commit 29ecfd7fb83c57289fc5e46a05cbead958f4b1ef Author: Federico Mena Quintero Date: 2011-12-13 Add nemo_application_open_location() This is a convenience function so that NemoFreedesktopDBus can cause the application to open a location and optionally select an item within that location. Signed-off-by: Federico Mena Quintero M src/nemo-application.c M src/nemo-application.h commit 3a899726ac482ae90f1b8fb52657ee80fef3a7fe Author: Federico Mena Quintero Date: 2011-12-13 Turn NemoFreeDesktopDBus into a GObject internally This is to match NemoDBusManager. Signed-off-by: Federico Mena Quintero M src/nemo-freedesktop-dbus.c commit 11fa1848dca3af78cd0f984f7c84f2214140f023 Author: Rudolfs Mazurs Date: 2011-12-13 Updated Latvian translation M po/lv.po commit 5294105677f371998043dde98a94847a1246c421 Author: Ryan Lortie Date: 2011-12-13 nemo application: use GActionMap g_application_set_action_group() is deprecated for favour of GActionMap, so use that instead. Bump the glib version dependency for GActionMap. M configure.in M src/nemo-application.c commit 33ca9cd5b0be3dcf092b7174591ede34edf2346d Author: Cosimo Cecchi Date: 2011-12-08 eel: remove unused eel_accessibility_set_name/description M eel/eel-accessibility.c M eel/eel-accessibility.h commit f78dee9affd9c88ce410c42cbf9c1118839d33d7 Author: Cosimo Cecchi Date: 2011-12-08 view: use ATK API directly to set accessible name/description M src/nemo-view.c M src/nemo-window-manage-views.c commit c76dc41521c9327a7aa121f35e68e10b6783f740 Author: Cosimo Cecchi Date: 2011-12-07 application: add a compatibility dummy --browser cmdline option External scripts or desktop files from previous might still call nemo with the --browser option, and it's bad to just fail in that case. Add a dummy (and hidden) cmdline option that does nothing for --browser. https://bugzilla.gnome.org/show_bug.cgi?id=665700 M src/nemo-application.c commit 4b497142b1c2361cf38c0804a283b8b419c3b623 Author: Cosimo Cecchi Date: 2011-12-07 man: remove reference to --browser option from the manual The option is not supported anymore since 3.0. https://bugzilla.gnome.org/show_bug.cgi?id=665700 M docs/nemo.1 commit ecf70ad6a66cc1450935e54ebffd95660ebc05a4 Author: Akshay Gupta Date: 2011-12-06 Implement ShowItemProperties() M src/nemo-freedesktop-dbus.c commit f65bd26d6f3691006c291f88e6c3b1add349d985 Author: Federico Mena Quintero Date: 2011-12-06 Allow creating a properties window with a NULL parent widget When the ShowItemProperties() DBus call comes in, it doesn't come from a parent widget. Instead, it has a startup ID. So, we need to be able to pass a NULL parent_widget to the properties window. Signed-off-by: Federico Mena Quintero M src/nemo-properties-window.c commit 5f3b0071d11cc864d135f35b7b85b07a5395f97a Author: Akshay Gupta Date: 2011-12-06 Implement ShowFolders() NemoApplication doesn't make a distinction between showing files and showing folders, so for now we'll use the same implementation. M src/nemo-freedesktop-dbus.c commit 08b590a4c6014d6a91a525b3183d3266788703a4 Author: Akshay Gupta Date: 2011-12-06 Implement ShowItems() Unfortunately g_application_open() and NemoApplication don't actually use the startup_id. We will have to pass this in another fashion later. M src/nemo-freedesktop-dbus.c commit e7dc7a27001dcadb8f7a2cafb26bbb3be724d801 Author: Federico Mena Quintero Date: 2011-12-06 Initialize the freedesktop DBus manager from NemoApplication Signed-off-by: Federico Mena Quintero M src/nemo-application.c commit e1a2bcecf4d4dea845194c943f82c60f8c6c6d36 Author: Federico Mena Quintero Date: 2011-12-06 Pass the NemoApplication to the freedesktop DBus manager Signed-off-by: Federico Mena Quintero M src/nemo-freedesktop-dbus.c M src/nemo-freedesktop-dbus.h commit 456afcbb6042c8f1ab73f240e5be5eabd681e090 Author: Federico Mena Quintero Date: 2011-12-06 DBus boilerplate for handling the org.freedesktop.NemoFileManager1 service Signed-off-by: Federico Mena Quintero M src/Makefile.am A src/nemo-freedesktop-dbus.c A src/nemo-freedesktop-dbus.h commit aa01e30c0d3d585bd808ed1ab53c5ca396371cd1 Author: Federico Mena Quintero Date: 2011-12-06 Generate the org.freedesktop DBus code Signed-off-by: Federico Mena Quintero M src/.gitignore M src/Makefile.am commit a3c387089e3bb9eaafe8b033bd334d151ccebe06 Author: Akshay Gupta Date: 2011-12-06 Add declaration for the org.freedesktop.NemoFileManager1 DBus interface This is not in dbus-interfaces.xml as that one has a different namespace (org.gnome.Nemo), and that makes the generated code from gdbus-codegen really ugly. By keeping a separate file for this interface, we can get pretty generated code. A data/freedesktop-dbus-interfaces.xml commit 40be4b85f51fc7b192ef7421b2ede27954997cc8 Author: Nelson Benitez Leon Date: 2011-12-02 Make 'next row' behaviour work again by making it general According to feedback on a11y list this should not hurt a11y. Fixes bug 660881 M libnemo-private/nemo-icon-container.c commit 2721796f86efd1e7e118c9531657e815bd1e0c60 Author: Cosimo Cecchi Date: 2011-12-05 idle-queue: remove unused NemoIdleQueue M libnemo-private/Makefile.am M libnemo-private/nemo-directory-private.h D libnemo-private/nemo-idle-queue.c D libnemo-private/nemo-idle-queue.h commit 896a9cf4bbadfc19c6d69fa53bd9ea46cb81989c Author: Rui Matos Date: 2011-12-02 icon-container: use a threshold to start scrolling while rubberbanding This allows us to scroll while rubberbanding when the window is maximized and thus the pointer can't possibly leave the widget area. https://bugzilla.gnome.org/show_bug.cgi?id=665383 M libnemo-private/nemo-icon-container.c commit cdf858fbfccdbca7bd8fc27f0f85e815177ee8c6 Author: Stefano Teso Date: 2011-11-30 Avoid deprecate gtk_widget_get_pointer(). M libnemo-private/nemo-icon-container.c commit 0a5838004030f64d9f27c55a3f2f49275b82b79f Author: Cosimo Cecchi Date: 2011-12-02 properties-window: initiate a new row when no sibling is provided This was the original intent of this code. M src/nemo-properties-window.c commit 098aa9334123334d500c166f13dc47f5f110cd8a Author: Cosimo Cecchi Date: 2011-12-02 window: explicitly destroy the sidebar in _destroy() When the nemo window is destroyed, make sure to explicitly destroy the sidebar before the panes. Destroying all the panes can trigger a callback back into the sidebar, which would then try to access the window pane list from the callback. The pane list was already destroyed and cleared at that point though, and we would segfault. https://bugzilla.gnome.org/show_bug.cgi?id=652320 M src/nemo-window.c commit 7e351fd5ead64be1343eea6d357a2edb25f9a721 Author: Dmitry Shachnev Date: 2011-12-01 Don't allow "New tab" (Ctrl+T) shortcut in desktop window Disable the New Tab action on the desktop. https://bugzilla.gnome.org/show_bug.cgi?id=655256 M src/nemo-desktop-window.c commit f1d9644efe457d84b9a18f250e85b5d70cb46620 Author: Praveen Illa Date: 2011-11-30 Updated Telugu Translation M po/te.po commit 780f8e4abf482628677e4f75ed502e1f18cf2411 Author: Daniel Nylander Date: 2011-11-25 Updated Swedish translation M po/sv.po commit cd99b28b903e0c3c69f142dd5c7977bb791d9cf1 Author: Cosimo Cecchi Date: 2011-11-23 places-sidebar: sort the XDG dirs section for the current locale The XDG dirs section should not hardcode an english ordering, but follow the current locale. https://bugzilla.gnome.org/show_bug.cgi?id=664464 M src/nemo-places-sidebar.c commit 786b34ff9abfae433956077a5feb2978d126ecfb Author: Stas Solovey Date: 2011-11-16 Updated Russian translation M po/ru.po commit a76dce8845b9bca8e01e67ad547ae158cff18456 Author: Thura Hlaing Date: 2011-11-14 [l10n]Added Burmese translation M po/LINGUAS A po/my.po commit 3aeff5a3d2114b77126686bd642716b21f4aa014 Author: Fran Diéguez Date: 2011-11-13 Updated Galician translations M po/gl.po commit b81330c62d232af66c5be7186f2badabecd52673 Author: Daniel Mustieles Date: 2011-11-09 Updated Spanish translation M po/es.po commit 12bc05de21fed18ac985470fa55174629de6470f Author: Kristjan SCHMIDT Date: 2011-11-04 Updated Esperanto translation M po/eo.po commit aff2f078ef222f28a8a32408260efdfc7d8be8d9 Author: Gabor Kelemen Date: 2011-10-29 Fix a small mistranslation in the Hungarian po M po/hu.po commit 9208a93c2d3f85bcb10c05c1cfc55b33b545ca46 Author: Yaron Shahrabani Date: 2011-10-27 Updated Hebrew translation. M po/he.po commit f01c138bc3567cfedb476bcc4e2a66da8b3b38ee Author: Kristjan SCHMIDT Date: 2011-10-26 Updated Esperanto translation M po/eo.po commit b3dde943b7628bf32076b3e375256a775786d05b Author: Cosimo Cecchi Date: 2011-10-25 release: bump to 3.3.1.1 3.3.1 was accidentally released with a wrong tarball, bump version and roll a tarball again. M configure.in commit f18eb3a0b04ab8b094012bb5d0d2abb0bf7b7799 Author: Cosimo Cecchi Date: 2011-10-25 build: switch to XZ M configure.in commit 628c0566f7317c25f30991652a6192d7d8f4fbd8 Author: Cosimo Cecchi Date: 2011-10-25 release: prepare for 3.3.1 M NEWS M configure.in commit 45ee835907056a95c4ae9dad5f7913620ed219d7 Author: Cosimo Cecchi Date: 2011-10-25 eel-string: don't segfault in eel_str_replace_substring for NULL strings Just check if the strings are != NULL before calling strlen() on them. M eel/eel-string.c commit 79525a6502316974bd9e28144b82290b1840dac4 Author: Matej UrbanÄiÄ Date: 2011-10-23 Updated Slovenian translation M po/sl.po commit 26a1e55ab5b8ebb8d441569bb790b0c4976c7bf8 Author: Yaron Shahrabani Date: 2011-10-22 Updated Hebrew translation. M po/he.po commit 2ce3696a73d5eda0b6213311f2bfee7a600d9256 Author: Cosimo Cecchi Date: 2011-10-19 places-sidebar: trivial cleanups M src/nemo-places-sidebar.c commit 4764a856c7a6e5a84d4067e7b105c09a93ffdbe4 Author: Cosimo Cecchi Date: 2011-10-19 places-sidebar: return if we fail to compute a drop position Instead of using an invalid GtkTreePath, which could cause a segfault later. https://bugzilla.gnome.org/show_bug.cgi?id=660876 M src/nemo-places-sidebar.c commit cda2c75df4b95a481e8b774081ec1240d47fa45f Author: Cosimo Cecchi Date: 2011-10-19 places-sidebar: don't assert we have a valid selected iter When reordering bookmarks, don't assert we have a selected iter, since it might not always be the case. https://bugzilla.gnome.org/show_bug.cgi?id=660876 M src/nemo-places-sidebar.c commit 7826dfbdc4cb9a5381b6d9845e0ba7459fcd2fe4 Author: Cosimo Cecchi Date: 2011-10-19 places-sidebar: don't call gtk_tree_model_get() with an invalid path If we click on an empty area of the sidebar, we shouldn't pop up any menu at all anyway, which is what this commit changes. Previously, we would have tried to get a GtkTreePath for the currently selected point and an iter for that (invalid) path, which would lead to gtk_tree_model_get() segfaulting on an invalid iter. https://bugzilla.gnome.org/show_bug.cgi?id=662218 M src/nemo-places-sidebar.c commit 67aaaf9f9a95de0beb8a45f97b378144b93ab9d4 Author: Daniel Mustieles Date: 2011-10-19 Updated Spanish translation M po/es.po commit 11da44db624aadcf8b71950acf05b929caa565b6 Author: Muhammet Kara Date: 2011-10-18 Updated Turkish translation M po/tr.po commit 5208c1c1a2da66ece2562c22dde8ed51d550c1cf Author: György Balló Date: 2011-10-18 Autostart only in GNOME and Unity Don't show desktop icons in other DEs, e.g Xfce and KDE uses it's own desktop implementation. https://bugzilla.gnome.org/show_bug.cgi?id=661942 M data/nemo-autostart.desktop.in commit a90444b3651272119d1d4ab65d70b41b95a87616 Author: Stefano Teso Date: 2011-10-18 places-sidebar: show a Properties item for mounts https://bugzilla.gnome.org/show_bug.cgi?id=546189 M src/nemo-places-sidebar.c commit a598148fde3f08ad69115b96c5a9a821ac16983c Author: Timothy Arceri Date: 2011-10-18 file-operations: show needed space as a secondary message When there's not enough space on the disk, show how much additional space is needed for the operation to complete, instead of a more obscure error message. https://bugzilla.gnome.org/show_bug.cgi?id=542960 M libnemo-private/nemo-file-operations.c commit c590280477db495a362339c512d73daade862329 Author: Cosimo Cecchi Date: 2011-10-18 test: don't use deprecated gtk_vbox_new() M test/test-eel-editable-label.c commit a816e00ef769a3be12a053a29e41f3da1b91c492 Author: Cosimo Cecchi Date: 2011-10-18 all: don't use deprecated GDK pointer methods Use the new GdkDevice methods instead. M eel/eel-editable-label.c M libnemo-private/nemo-dnd.c M libnemo-private/nemo-tree-view-drag-dest.c M src/nemo-notebook.c commit 0594aa1636ef960361cf60d00c58ab94c81ee5d4 Author: Cosimo Cecchi Date: 2011-10-18 all: don't use deprecated GMutex/GThread API Also, threads area always enabled, so we can remove the G_THREADS_ENABLED conditionals. Require GLib 2.31 for this. M libnemo-private/nemo-file-changes-queue.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-search-engine-simple.c commit 04975e6cbc8f82238e3611a26b474b56c46ec1d3 Author: Cosimo Cecchi Date: 2011-10-18 all: don't call g_thread_init() GLib does that for us now. M configure.in M src/nemo-main.c M test/test-copy.c M test/test-nemo-search-engine.c commit e54ace0a550b47c251634ee833884f5bc6ea4be6 Author: Cosimo Cecchi Date: 2011-10-17 editable-label: use GTK_STYLE_CLASS_ENTRY Because that's what it is actually... M eel/eel-editable-label.c commit b143b95f20755fc8425464aa11df3fa2ac2df2ea Author: Cosimo Cecchi Date: 2011-10-17 editable-label: use gtk_render_frame() instead of hardcoding a stroke This allows the stroke to use rounded corners and border images, among other things. M eel/eel-editable-label.c commit f9383acb378762a80a373f124e059aff5e571f21 Author: Cosimo Cecchi Date: 2011-10-17 editable-label: don't hardcode black for the insertion cursor Use the theme foreground/text color instead. M eel/eel-editable-label.c commit 3f95c46dff1c4f71f67d2733f0487350139775cf Author: Cosimo Cecchi Date: 2011-10-17 editable-label: remove useless code No need to call _set_background() on the editable label widget. M eel/eel-editable-label.c commit 8b87a3e86eb228d4414c3d64cc81b7bb56d27076 Author: Cosimo Cecchi Date: 2011-10-17 editable-label: make sure to size_request the padding set on the label And not the alignment, which is an offset inside the allocated size. M eel/eel-editable-label.c commit 4c74f176542935b8ea8f61f9bb9ae6cdb35466ea Author: Cosimo Cecchi Date: 2011-10-17 icon-container: use gdk_window_move() to position the typeahead popup For some reason, gtk_window_move() doesn't always work reliably, while gdk_window_move() seems to always position the window in the requested coordinates. https://bugzilla.gnome.org/show_bug.cgi?id=660807 https://bugs.launchpad.net/ubuntu/+source/nemo/+bug/857710 M libnemo-private/nemo-icon-container.c commit 9a703cea5067f68ef21b90a42856b229d5edc69d Author: Cosimo Cecchi Date: 2011-10-17 icon-container: don't associate Ctrl+F to typeahead search It won't get triggered anyway, as we bind Ctrl+F to show the search bar in NemoWindow. M libnemo-private/nemo-icon-container.c commit fea4112c35c84bdb124a567c2d84a2f2a8bd172d Author: Cosimo Cecchi Date: 2011-10-17 places-sidebar: don't crash when middle clicking on empty space gtk_tree_view_get_path_at_pos() can fail; handle that case instead of passing an invalid GtkTreePath. https://bugzilla.gnome.org/show_bug.cgi?id=657366 https://bugs.launchpad.net/ubuntu/+source/nemo/+bug/830185 M src/nemo-places-sidebar.c commit 03888c1dde59cb2dd3b243e3c72f35757a4c2e5f Author: Cosimo Cecchi Date: 2011-10-17 tree-sidebar: don't call g_free on a GObject list https://bugzilla.gnome.org/show_bug.cgi?id=660906 https://bugs.launchpad.net/ubuntu/+source/nemo/+bug/845408 M src/nemo-tree-sidebar.c commit 0a5aa2a28d82554afb684d815e8180f307ac1897 Author: Ivan Masár Date: 2011-10-16 Updated Slovak translation M po/sk.po commit 9bdca2a00b3c3f6a5e908964b4f3a2e39eec0145 Author: Jiro Matsuzawa Date: 2011-10-17 Updated Japanese translation M po/ja.po commit 4b470c16d7b7190e973b712d9f29d6bccd7f9e83 Author: Andrej ŽnidarÅ¡iÄ Date: 2011-10-14 Updated Slovenian translation M po/sl.po commit 1f23acbe5f526370db2ffec1dec09fea7e6de219 Author: Yuri Myasoedov Date: 2011-10-14 Fixed Russian translation M po/ru.po commit 04ff2cd9e6500b3f9f1052199e1321e33538225b Author: Michael Biebl Date: 2011-10-11 Fix build failure if tracker FTS is enabled M libnemo-private/nemo-search-engine-tracker.c commit 048115fa9c5c1ffa45a8df5fcb52e75f6c3d2641 Author: krishnababu k Date: 2011-10-10 Updated Telugu Translations M po/te.po commit 0dc5b59e637db6bdcc92a5b2bfce4a6a58c9a6e1 Author: Muhammet Kara Date: 2011-10-10 Updated Turkish translation M po/tr.po commit 428b468e8e6e66270cb434f14e4b1f8d7f5354c9 Author: Cosimo Cecchi Date: 2011-10-05 all: remove offset_x/offset_y parameters from eel_pop_up_context_menu() They're unused now. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h M src/nemo-places-sidebar.c M src/nemo-view.c commit 7b290a2b2fee7028e50c0ecf15d5417a7a7dc59d Author: Federico Mena Quintero Date: 2011-10-05 Remove stale 'offset' in eel_pop_up_context_menu() Also, fix the fallback timestamp for the menu popup. Signed-off-by: Federico Mena Quintero M eel/eel-gtk-extensions.c commit 61699ef56eb3091341c5f5a38189e12a11280e3e Author: Cosimo Cecchi Date: 2011-10-05 eel: remove unused eel_gdk_rgba_is_dark() M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit bcc62bec90aec23fb1ede56f0ce0181218fdc81a Author: Cosimo Cecchi Date: 2011-10-05 eel-string: remove unused code M eel/eel-string.c M eel/eel-string.h commit 3a02c89ec0329ee6a1b0eab411eb0f95308626aa Author: Cosimo Cecchi Date: 2011-10-05 all: don't use eel_strlen() M src/nemo-location-bar.c M src/nemo-window-slot.c commit fc1479fc3a614b00d0ff69bd1da62d4dee0a9af9 Author: Cosimo Cecchi Date: 2011-10-05 view: use g_str_has_prefix() instead of eel_str_has_prefix() M src/nemo-view.c commit 3daaaf4a9efa2913bbfbadf1492e670b3e83c4a0 Author: Cosimo Cecchi Date: 2011-10-05 all: don't use eel_strcmp() M eel/eel-glib-extensions.c M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-progress-info.c M src/nemo-properties-window.c M src/nemo-window-slot.c commit 96254fec43923e7ef5a3e78604cb3b6935117f91 Author: Cosimo Cecchi Date: 2011-10-05 eel: remove unused eel-gtk-macros.h file M eel/Makefile.am D eel/eel-gtk-macros.h M eel/eel.h M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-clipboard-monitor.c M libnemo-private/nemo-desktop-directory.c M libnemo-private/nemo-desktop-link-monitor.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-entry.c M libnemo-private/nemo-file.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-merged-directory.c M libnemo-private/nemo-module.c M libnemo-private/nemo-query.c M libnemo-private/nemo-search-engine-simple.c M libnemo-private/nemo-tree-view-drag-dest.c M libnemo-private/nemo-undo-manager.c M libnemo-private/nemo-undo-signal-handlers.c M src/nemo-application.c M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-location-bar.c M src/nemo-view.c M src/nemo-window-manage-views.c M src/nemo-window-slot.c commit 68732195bada37da771bab924352ca3864e2bdde Author: Cosimo Cecchi Date: 2011-10-05 view: don't use EEL_ASSIGN/EEL_IMPLEMENT macros for class signals Not that useful since we have full control over all the views. M src/nemo-view.c commit ce34c8c033d09578f7cb17b8531f6afc95555728 Author: Cosimo Cecchi Date: 2011-10-05 view: don't use EEL_INVOKE_METHOD macro M src/nemo-view.c commit 2797c72a906ed6395afd45b9fa7c516d6ef3299f Author: Cosimo Cecchi Date: 2011-10-05 all: don't use EEL_CALL_METHOD* macros M libnemo-private/nemo-directory.c M libnemo-private/nemo-directory.h M libnemo-private/nemo-file.c M src/nemo-view.c M src/nemo-window-slot.c commit 45e3ad0979d79ba017e84a9f99f605ec562c8ae8 Author: Cosimo Cecchi Date: 2011-10-05 icon-view: simplify code by removing pointless method overrides M src/nemo-icon-view.c M src/nemo-icon-view.h commit deb560128734593d9941f4a414e165b3943d61bf Author: Cosimo Cecchi Date: 2011-10-05 all: don't use EEL_CLASS_BOILERPLATE macro M libnemo-private/nemo-vfs-directory.c M libnemo-private/nemo-vfs-file.c commit f0dc94fed68eb5a52d705391053bd642a88ab1d3 Author: Cosimo Cecchi Date: 2011-10-05 all: don't use EEL_CALL_PARENT* macros Replace them with regular calls to the parent class method pointer. M libnemo-private/nemo-desktop-directory.c M libnemo-private/nemo-desktop-link-monitor.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-merged-directory.c M libnemo-private/nemo-module.c M libnemo-private/nemo-query.c M libnemo-private/nemo-search-engine-simple.c M libnemo-private/nemo-search-engine.c M libnemo-private/nemo-tree-view-drag-dest.c M src/nemo-empty-view.c M src/nemo-list-view.c M src/nemo-location-entry.c M src/nemo-view.c commit 785ee926b36165b4849903e5f4828a17aabe534c Author: Cosimo Cecchi Date: 2011-10-04 properties-window: paint the pie backgorund with the notebook color We have to reset the GtkDrawingArea background to the notebook color, in case the theme specifies them to be different. M src/nemo-properties-window.c commit 8b99f1fae29b333c9beeee3dad848099a66e731d Author: Cosimo Cecchi Date: 2011-10-04 properties-window: port the pie chart GtkTable to GtkGrid M src/nemo-properties-window.c commit 0026899cd9f5cd636b4a44ec838e2ec228b210bb Author: Cosimo Cecchi Date: 2011-10-04 properties-window: port GtkTable to GtkGrid Except for the pie chart, which will be ported in a separate commit M src/nemo-properties-window.c commit ac6797687cc3dc77e1fc6752090a7ef037252ade Author: Cosimo Cecchi Date: 2011-10-04 window: port GtkTable to GtkGrid M src/nemo-window-private.h M src/nemo-window.c commit c6903f412d204ce4ab83fa328fe7df3c81781b68 Author: Cosimo Cecchi Date: 2011-10-04 view: port GtkTable to GtkGrid M src/nemo-view.c commit 29dea2e40f6631935a9479c2cf96534308215183 Author: Cosimo Cecchi Date: 2011-10-04 desktop-item-properties: port GtkTable to GtkGrid M src/nemo-desktop-item-properties.c commit 7f3e5ce7786bfdf728169d222ef7584306f2b445 Author: Cosimo Cecchi Date: 2011-10-04 connect-server-dialog: port GtkTable to GtkGrid M src/nemo-connect-server-dialog.c commit 24658f2ba3c9a9dd12416933942370cd6ff6271c Author: Federico Mena Quintero Date: 2011-10-04 Fix confusion in the fallback size for icons Just caught this when reading the code... https://bugzilla.gnome.org/show_bug.cgi?id=660894 M libnemo-private/nemo-icon-info.c commit d8cfe1080a15fd05a306ee3a6adb5767df4fe58f Author: Kristjan SCHMIDT Date: 2011-10-03 Updated Esperanto translation M po/eo.po commit f1aae7bd99efac46a4f7b67beb53205b6cb89f47 Author: Tiffany Antopolski Date: 2011-10-03 Updated Esperanto translation M po/eo.po commit 0c80c23a771da619bfd6858397d10b2446966fa2 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-10-02 po/vi: better translation of "Go" M po/vi.po commit 530bbec3b5d663ca7e3244446d9bc73f1cf323b0 Author: Cosimo Cecchi Date: 2011-09-29 all: remove initiated_unmount logic from NemoWindow We don't really need this, and it makes the behavior way less convoluted. Now we always try to close the current slot on mount remove, except when it would be the last window at all to be closed. M src/nemo-application.c M src/nemo-places-sidebar.c M src/nemo-view.c M src/nemo-window-slot.c commit 269c6b23cf2b97f74a8c7c2654221be491b60cf4 Author: Cosimo Cecchi Date: 2011-09-29 window: add debug messages for pane closing M src/nemo-window-pane.c M src/nemo-window.c commit 379e0883d06f782fb43d32a1b5031f52c5cfc9b4 Author: Cosimo Cecchi Date: 2011-09-29 window: cleanup nemo_window_close_pane() M src/nemo-window-private.h M src/nemo-window.c commit 3ac3935e9d4a9e40b2e889cb16409cadc30bb8dd Author: Cosimo Cecchi Date: 2011-09-29 window-pane: fix switching to the other pane when closing the last slot We're closing a window slot; when it's the last slot to be closed, we used to call nemo_window_split_view_off() on the wrong pane. Even if we called it on the right pane, it wouldn't have worked anyway, because we could have removed the active pane, and that function always assumes going back to it. Also, we need to ensure that active_slot is set on the new pane, or nemo_window_set_active_slot() won't be called to restore the right window state. https://bugzilla.gnome.org/show_bug.cgi?id=652320 M src/nemo-window-pane.c commit f6bbf0f111f344276472aaa54072bf99ae7be9b2 Author: Cosimo Cecchi Date: 2011-09-29 view: don't assert on window slot signal callback ordering There's no reason to assert on the fact that inactive and active signals will be always emitted in alternate state. If this doesn't happen, just return. https://bugzilla.gnome.org/show_bug.cgi?id=652320 M src/nemo-view.c commit 1c06d97c9663ec5b77f21326490146c9a9d8f9d9 Author: Cosimo Cecchi Date: 2011-09-29 places-sidebar: disconnect volume monitor signals on dispose The GIO volume monitor can survive the sidebar, so we need to disconnect its signals handlers on dispose. https://bugzilla.gnome.org/show_bug.cgi?id=652320 M src/nemo-places-sidebar.c commit 1f61da02d767b2a767d1dc2fd8c6714c6f6a60d0 Author: Cosimo Cecchi Date: 2011-09-28 window-slot: don't go through the back list when checking a mount There's no reason the slot shouldn't be closed if one of the locations in the back history belongs to the mount (what we should do is cleaning up that location from the history, which we don't yet). M src/nemo-window-slot.c commit df47a7e142357ff404dceaf43bf3c7ae492fddcc Author: Cosimo Cecchi Date: 2011-09-28 application: avoid useless checks when removing a mount nemo_window_slot_should_close_with_mount() has the same checks and more. M src/nemo-application.c commit d49f23ae211cb24cc43efa68d46f7867dbe26364 Author: Cosimo Cecchi Date: 2011-09-28 window-pane: turn into a GtkBox, simplify code M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit eaa98a76fbc144ff1f14f2df8fb3d6873541465b Author: Cosimo Cecchi Date: 2011-09-28 desktop-link-monitor: plug a memory leak M libnemo-private/nemo-desktop-link-monitor.c commit 0d191f445da18d0bed1c8ca6d3e05dc4ffae4293 Author: Cosimo Cecchi Date: 2011-09-28 window-manage-views: plug a memory leak We have to free the new selection list when we build it ourselves. M src/nemo-window-manage-views.c commit 37386fab28267cdbedd979fff13fe1a9da81014d Author: Cosimo Cecchi Date: 2011-09-28 list-view: don't activate the previewer when there's no selection Or we'll segfault when trying to access the first item of the selection. https://bugzilla.gnome.org/show_bug.cgi?id=654857 M src/nemo-list-view.c commit 3429a6ff153c85a6a65ccb994b4cb4434e4fffcf Author: Cosimo Cecchi Date: 2011-09-28 icon-container: consolidate typeahead entry timeout handling We have crash reports coming from the search entry typeahead code. I can't really reproduce the bug, but there seems to be at least a problem with the typeahead flush timeout returning TRUE and being rescheduled. Refactor the code to better handle the flush timeout, which hopefully solves those crashes as well. https://bugzilla.gnome.org/show_bug.cgi?id=653800 M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-private.h commit 718b8641935b5a8de67e83ec12f9026aecd41e8c Author: Cosimo Cecchi Date: 2011-09-28 window: small code cleanups M src/nemo-window-private.h M src/nemo-window.c commit d3c158d6c9a6ee40fae660ab56b7d8a40074108c Author: Cosimo Cecchi Date: 2011-09-28 window: make sure to disconnect GSettings signals when finalizing The GSettings object survive the window, so handlers connected to its signals should be disconnected when the window is finalized. https://bugzilla.gnome.org/show_bug.cgi?id=655070 M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window.c commit 82a39de7a3c1265ba1a46d1140a084a12b310e32 Author: Cosimo Cecchi Date: 2011-09-28 places-sidebar: don't crash when not finding the eject symbolic icon If a theme doesn't have media-eject-symbolic, icon_info can be NULL, and we would crash trying to load a pixbuf from it anyway. Fix this and show the stock 'missing image' pixbuf when the theme doesn't have the specified icons. https://bugzilla.gnome.org/show_bug.cgi?id=660277 M src/nemo-places-sidebar.c commit 35059bec98b8ede682e582395b889dc149fc7cba Author: МироÑлав Ðиколић Date: 2011-09-28 Updated Serbian translation M po/sr.po M po/sr@latin.po commit f51bad348ab71e3203a7b76c45d307b0fafc5128 Author: Cosimo Cecchi Date: 2011-09-26 release: prepare for 3.2.0 M NEWS M configure.in commit c6299e775ae7770b5b98ede0b70e90ecd04bc742 Author: Cosimo Cecchi Date: 2011-09-26 trivial: fix a critical when opening preferences Just a trivial cleanup for a critical accidentally introduced in commit db72d73b3cd58493b1b8878a52ff8a9f5d350602 M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit 278a92edf777eb3dc623a4284ef4d81af3f77d27 Author: Andrej ŽnidarÅ¡iÄ Date: 2011-09-26 Updated Slovenian translation M po/sl.po commit 34b5833b704e174c82d943b28e59d91e9531fdbc Author: Carles Ferrando Date: 2011-09-26 [l10n]Updated Catalan (Valencian) translation M po/ca@valencia.po commit 2b296a9d0dfba07b62144e96a52368205c447561 Author: Tommi Vainikainen Date: 2011-09-26 Updated Finnish translation M po/fi.po commit 368d49124774c4bf640f617e4fcf86641dd886e7 Author: Seán de Búrca Date: 2011-09-25 Updated Irish translation M po/ga.po commit 544fcac94f70f3f35105bfad3f6dda21197d7378 Author: Andika Triwidada Date: 2011-09-25 Updated Indonesian translation M po/id.po commit dfb8d194bf9ff460b8d6a7a9e3629ab5b343bb46 Author: Lucas Lommer Date: 2011-09-24 Updated Czech translation M po/cs.po commit 5e83b5591ffccef5e9faa8bc384c7ffd59eab05e Author: Lucas Lommer Date: 2011-09-24 Updated Czech translation M po/cs.po commit 55210fff4df1ea8312b9e276f65dd3e22ec406f0 Author: Inaki Larranaga Murgoitio Date: 2011-09-24 Updated Basque language M po/eu.po commit adb9e12825aedee3b71a1bd9bb4589b22f724946 Author: Jiro Matsuzawa Date: 2011-09-23 Updated Japanese translation M po/ja.po commit a2045383fc726c4d11a1ab08837fd97d9d098a3b Author: Claude Paroz Date: 2011-09-22 Cleaned Assamese translation M po/as.po commit f07aa75bf010653bd9e1a5f5519fec8a029763de Author: Cosimo Cecchi Date: 2011-09-22 icon-canvas-item: don't draw pango layouts when renaming Fixes a regression introduced in commit 95910c94fd46f368b66f02e1961dc5f273b38c82 that causes unwanted text to be drawn while renaming a file in icon view. https://bugzilla.gnome.org/show_bug.cgi?id=659831 M libnemo-private/nemo-icon-canvas-item.c commit 2b9b06cfa8bb431f21af74a5f630646df494eb00 Author: Changwoo Ryu Date: 2011-09-23 Updated Korean translation M po/ko.po commit 9023264e0660b50253a9bf7bffe977e0b3a6fd4c Author: Joe Hansen Date: 2011-09-22 Updated Danish translation M po/da.po commit f985fe035500e57bbede9f0dfb252fc0f2569377 Author: Sweta Kothari Date: 2011-09-22 Updated Gujarati Translations M po/gu.po commit b8238d4a89de55a2e93af7f2aee15cf4148625a6 Author: Gabor Kelemen Date: 2011-09-19 Updated Hungarian translation M po/hu.po commit 2cb91c05718dc5463a52eadf24e6036adfe6e10e Author: Cosimo Cecchi Date: 2011-09-19 icon-canvas-item: don't forget to clip the embedded text rectangle When drawing the embedded text, the pango layout should be clipped to the computed rectangle. https://bugzilla.gnome.org/show_bug.cgi?id=659518 M libnemo-private/nemo-icon-canvas-item.c commit bf1f6bde79f5226388551780dcd7f148c8f55734 Author: Cosimo Cecchi Date: 2011-09-19 release: prepare for 3.1.92 M NEWS M configure.in commit 0a32dd8da8b2a9d10189ef6c8865bb4ec2ca345f Author: Cosimo Cecchi Date: 2011-09-19 users-group-cache: nuke this, as it appears to be unused M libnemo-private/Makefile.am M libnemo-private/nemo-file.c D libnemo-private/nemo-users-groups-cache.c D libnemo-private/nemo-users-groups-cache.h commit b11c8a69479b5307d946dbc5742baf5cca75ae06 Author: Mike Gorse Date: 2011-09-16 Fix accessibility for gtk 3.2, and send object:state-changed:selected The code to derive the EelCanvasAccessible class no longer works as of gtk+ 3.1.9. Currently the recommended behavior is to derive from GtkAccessible. Also, canvas items should send object:state-changed:selected events when selected and unselected; otherwise AT-SPI will not update its cache. https://bugzilla.gnome.org/show_bug.cgi?id=650897 M eel/eel-canvas.c M eel/eel-canvas.h M libnemo-private/nemo-icon-canvas-item.c commit f83324a05375ba1aa97d3e6ea91f4af323f2bd2c Author: Aurimas ÄŒernius Date: 2011-09-18 Updated Lithuanian translation M po/lt.po commit 5d549140c95ebb9e7c5cdf5d7d639cca36a22021 Author: Lê Hoàng Phương Date: 2011-09-18 po/vi.po: changed Bookmark translation from "Liên kết lưu" to "Äánh dấu" M po/vi.po commit 0d1300c2c0790ea510a9253314e0c1f92e241843 Author: Nguyá»…n VÅ© Hưng Date: 2011-09-18 Updated Vietnamese translation M po/vi.po commit 4016176dc43e4c502714d7544000dbed64c95dfe Author: Theppitak Karoonboonyanan Date: 2011-09-18 Updated Thai translation. M po/th.po commit 92e3aded0c213d33e6bbe39f4a9258f4a50a0f7c Author: Ville-Pekka Vainio Date: 2011-09-17 Updated reduced Finnish translation M po/fi.po commit c408390df407fa4b90d4d8bf49a26401ec908512 Author: Ihar Hrachyshka Date: 2011-09-17 Updated Belarusian translation (some fixes after manual testing). M po/be.po commit 8fc72b1b9122cd3dec7c40c2d8f3b24a5038ae46 Author: Alexander Shopov Date: 2011-09-17 Updated Bulgarian translation M po/bg.po commit c0f1c0988790e458351a3e6f6a9bdc494efc0797 Author: Antonio Fernandes C. Neto Date: 2011-09-17 Updated Brazilian Portuguese translation M po/pt_BR.po commit 4fde92db8333dfdb708f57e9b69d3fa74f511663 Author: Joan Duran Date: 2011-09-17 [l10n]Updated Catalan translation M po/ca.po commit 3956b5c163d1b6beda14ab3d47bf78653208c106 Author: Jiro Matsuzawa Date: 2011-09-17 Updated Japanese translation M po/ja.po commit d477edb640c0aa58550e43992fb788f54b2ec700 Author: Mario Blättermann Date: 2011-09-16 [l10n] Updated German translation M po/de.po commit c97c17c4970cb9ae9c38685005995abe2a880921 Author: Daniel Korostil Date: 2011-09-16 Uploaded Ukranian M po/uk.po commit a046d86cd13431eef4bae743c0ca505dffaecca0 Author: dmustieles Date: 2011-09-14 Updated Spanish translation M po/es.po commit cb9d902fccbc462253d60d9a39fa5ee2cce1af7d Author: Yinghua Wang Date: 2011-09-13 update Simplified Chinese (zh_CN) translation M po/zh_CN.po commit 67743ffbc62abeb2bb3511901c95fb57d4ee9d93 Author: Yinghua Wang Date: 2011-09-13 update Simplified Chinese (zh_CN) translation M po/zh_CN.po commit 78be87bc843f71670b41011b645f983bab6ba81d Author: Cosimo Cecchi Date: 2011-09-12 desktop: ensure the desktop metadata is up to date when setting as ready As part of the I/O machinery cycle internal to call_when_ready nemo_file_clear_info() can be called and clear the metadata we previously set during _init. Move the desktop metadata initialization before returning the file as ready, so it's always up to date when the view reads the settings. https://bugzilla.gnome.org/show_bug.cgi?id=655561 M libnemo-private/nemo-desktop-directory-file.c commit 6775e582bcd332eaed925f41555fe4e5c0a3dd71 Author: Cosimo Cecchi Date: 2011-09-12 file: read the emblem icon names from metadata Support for the metadata::emblems got lost during the 3.0 development, re-add support for it. M libnemo-private/nemo-file.c commit 97802bc3f6cfbd464eae6e4375cc8f7d71a218af Author: Cosimo Cecchi Date: 2011-09-12 window-manage-views: scroll to the selected location when opening an URI When opening nemo with a preselected URI, scroll the window to that location in addition to selecting the view element. https://bugzilla.gnome.org/show_bug.cgi?id=658843 M src/nemo-window-manage-views.c commit 3add5865157f6eb66ddf5729ffdf3102c020cc10 Author: Dr.T.Vasudevan Date: 2011-09-12 updated Tamil translation M po/ta.po commit d82cd5965c246173c3f8e3ce39fdde740592259e Author: Rudolfs Mazurs Date: 2011-09-11 Updated Latvian translation. M po/lv.po commit e7c643cea5a4455d34954edfad24ca62dd585156 Author: Jorge González Date: 2011-09-11 Updated Spanish translation M po/es.po commit 7fe6d3d2a4fe48d58afba8c0ee8e40fe60c5d63b Author: Cosimo Cecchi Date: 2011-09-10 tree-sidebar: don't block the parent handler when popping up a menu Otherwise the treeview will not select the row where the event happened. https://bugzilla.gnome.org/show_bug.cgi?id=601725 M src/nemo-tree-sidebar.c commit bc236c95df0b3362b4e51a404bd89e13062afa49 Author: Arash Mousavi Date: 2011-09-10 Updated Persian translation M po/fa.po commit 8873abff5de2fd8039ba52e60a835444527f7349 Author: Duarte Loreto Date: 2011-09-10 Updated Portuguese translation M po/pt.po commit a465c3b91dfadbfb590adc42fee18aaa1b61d9fc Author: Jiro Matsuzawa Date: 2011-09-10 Updated Japanese translation M po/ja.po commit 8d5e8502862f93a188a848ca79779db09e4abf85 Author: A S Alam Date: 2011-09-10 update PunjabiTranslation M po/pa.po commit d56fd8f591b3909ef58d7e191afb400de7a8f75f Author: Kristjan SCHMIDT Date: 2011-09-09 Updated Esperanto translation M po/eo.po commit 99ad534b7b2fae3fdfa15345cbeae01da5dda803 Author: Javier Jardón Date: 2011-09-09 Make maintiner mode enabled by default See http://blogs.gnome.org/desrt/2011/09/08/am_maintainer_mode-is-not-cool/ M configure.in commit a64ac652e217cfd9809f669453da6577a198ae37 Author: Yaron Shahrabani Date: 2011-09-09 Updated Hebrew translation. M po/he.po commit 2f064e560cf949b1e1bc4448eaa277f8e05180d8 Author: David Liang Date: 2011-09-09 icon-container: invalidate the layout cache on style-updated This way label sizes will be recomputed if e.g. DPI settings change. https://bugzilla.gnome.org/show_bug.cgi?id=578468 M libnemo-private/nemo-icon-container.c commit c0e6ac365cd4d4d4add0db1edf6f7506bd85e57f Author: Matthias Clasen Date: 2011-09-09 file-operations: ignore ALREADY_MOUNTED errors when mounting Don't spawn an error dialog in this case. https://bugzilla.gnome.org/show_bug.cgi?id=579645 M libnemo-private/nemo-file-operations.c commit a78d885027d6a49d712b5589fd79c822edf4e17d Author: Cosimo Cecchi Date: 2011-09-08 search-directory: stop the engine when there are no active monitors My understanding of this code suggests the engine should be stopped as soon as the active monitors reach zero. This fixes the Stop button not working while searching anyway, and doesn't seem to cause any collateral damage. https://bugzilla.gnome.org/show_bug.cgi?id=563163 M libnemo-private/nemo-search-directory.c commit fdf0036ca9fbb17b97aefabd95f994190cdc0bac Author: Piotr DrÄ…g Date: 2011-09-08 Updated Polish translation M po/pl.po commit 226595c7ed30e21247d07a063dd7d1f9221306ed Author: Luca Ferretti Date: 2011-09-08 l10n: Updated Italian translation M po/it.po commit 920aa3d94be890f241d3be415540dbde6a81df0a Author: Cosimo Cecchi Date: 2011-09-08 tracker: always reset the cancellable when starting a query Otherwise we can start a query with a cancelled object already, making it fail immediately. M libnemo-private/nemo-search-engine-tracker.c commit ee73c255d75165607c7f04defd5e8edfa3524914 Author: Cosimo Cecchi Date: 2011-09-08 window: make sure not to unref NULL GFiles The GFile pointed by parent here can be NULL after the cycle, so fold the unref in the != NULL block. M src/nemo-window-manage-views.c commit 88b08d691c17b9686938a0b20a37a19ac99cacc3 Author: Cosimo Cecchi Date: 2011-09-08 all: remove is_indexed property on NemoSearchDirectory It doesn't really make sense to artificially change the query target if we're indexed. M libnemo-private/nemo-search-directory.c M libnemo-private/nemo-search-directory.h M libnemo-private/nemo-search-engine-simple.c M libnemo-private/nemo-search-engine-tracker.c M libnemo-private/nemo-search-engine.c M libnemo-private/nemo-search-engine.h M src/nemo-query-editor.c M src/nemo-query-editor.h M src/nemo-window-pane.c M src/nemo-window-slot.c commit aef4bf26ed8b48f6519fec9531bb530783193447 Author: Cosimo Cecchi Date: 2011-09-08 tracker: respect the location URI when searching with tracker M libnemo-private/nemo-search-engine-tracker.c commit a65eb16241ea0e64e5bf2547ffdaebcaa4547574 Author: Claude Paroz Date: 2011-09-08 Updated French translation M po/fr.po commit 6f4d215dd9df1b3b0c7fb4714fda88bc2ef39590 Author: Bruce Cowan Date: 2011-09-08 Updated British English translation M po/en_GB.po commit 92e40dd094a812db6bcc3e60c0830d20b3f07b15 Author: Cosimo Cecchi Date: 2011-09-08 window: steal all accelerators/mnemonics keybindings when renaming If we're renaming, we really want to ignore all the accelerators and mnemonics coming from NemoWindow and NemoView, as they might conflict with the regular bindings expected in an editable widget, such as an editable GtkCellRendererText or EelEditableLabel. This should fix all the recent keybinding-related regressions, such as https://bugzilla.gnome.org/show_bug.cgi?id=658105 https://bugzilla.gnome.org/show_bug.cgi?id=651574 M src/nemo-window.c commit a67212a39bbcd342f0a503d693ebd80fab48ac9c Author: Cosimo Cecchi Date: 2011-09-08 view: add an is_renaming property to NemoView And keep it in sync with the renaming widget. This will be useful to forward events to the view if it's renaming. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-view.c M src/nemo-view.h commit 88b535828ddacd7ec2313d52a21f164aee535fa3 Author: Cosimo Cecchi Date: 2011-09-08 Revert "window: reverse the order of key-press event processing" This reverts commit f76c50a0e46aa7786820f76b3f71b57b44b8d7fb. M libnemo-private/nemo-icon-container.c M src/nemo-list-view.c M src/nemo-window.c commit c55fa6b75ba623b327975fdaa37d5a8e6669e7ac Author: Cosimo Cecchi Date: 2011-09-08 build: fix optional dependency check on libtracker-sparql Commit ffc7c7f98901e8a319b91716d05e521a798dbe43 didn't really work in the case where no tracker was found on the system, really forcing a build dependency. Fix this. https://bugzilla.gnome.org/show_bug.cgi?id=658545 M configure.in commit 8d8979f53cea0e8e48faa9ffba82950013e18ad0 Author: Cosimo Cecchi Date: 2011-09-07 icon-dnd: remove hardcoded highlight frame The call to gtk_render_frame() should be enough; the problem is with Adwaita which does not define a CSS style for the "dnd" class. M libnemo-private/nemo-icon-dnd.c commit 7732a6b35369c1cef56351cc491358c2f6623c5e Author: Cosimo Cecchi Date: 2011-09-07 icon-canvas-item: render the additional text with gtk_render_layout() And add a style class for it. M libnemo-private/nemo-icon-canvas-item.c commit ffc7c7f98901e8a319b91716d05e521a798dbe43 Author: Cosimo Cecchi Date: 2011-09-07 tracker: make the tracker-sparql dependency optional This way it's still possible to specify --enable-tracker=no from the configure line if you want to avoid the tracker dependency. M configure.in M libnemo-private/Makefile.am M libnemo-private/nemo-search-engine.c commit b3da52fefdbf5dc6f8f95fe381181dc47e54d5c3 Author: Stefano Teso Date: 2011-09-07 file: make sure not to use a 0 width/height when scaling the image The problem is that for extreme height-to-width ratio images, gdk_pixbuf_scale_simple () is called with either width or height = 0 (printing a critical warning to the terminal). https://bugzilla.gnome.org/show_bug.cgi?id=329010 M libnemo-private/nemo-file.c commit f1dd42ec1c86e78fa894c07ee6b0c8df60d45acb Author: Cosimo Cecchi Date: 2011-09-07 tracker: use libtracker-sparql directly It's not a problem for nemo to depend on libtracker-sparql here instead of using g_module_open() M configure.in M libnemo-private/nemo-search-engine-tracker.c commit 402b281790c1bca3fc10010008cb1ac6fb997b59 Author: Pavlos Touboulidis Date: 2011-04-11 list-view: Fix default sort order. Removed the extra "uri" element from the sort order mapping array because the settings enum values were being mapped to the wrong strings. https://bugzilla.gnome.org/show_bug.cgi?id=647491 M src/nemo-list-view.c commit ad5b834df34d6a8f3919909b63ce97cc2bda53d4 Author: mads@kiilerich.com Date: 2011-09-07 nemo-autorun-software: handle mime type x-content/unix-software only This is a consequence of the fix for https://bugs.freedesktop.org/show_bug.cgi?id=20562 . This undoes the part of cffb9cf7025 that hardcodes that media with x-content/win32-software are silently ignored, and thus improves on the fix for #524270. Wine or something could now provide a handler for win32-software. https://bugzilla.gnome.org/show_bug.cgi?id=632510 M data/nemo-autorun-software.desktop.in.in M src/nemo-autorun-software.c commit 8978c6375bbe0cd26fffded25bc4606cab2c88e6 Author: Phillip Berndt Date: 2011-02-16 nemo-autorun-software: Use /bin/sh for autorun.sh execution If the autorun file is called autorun.sh it is clearly meant for execution through a sh processor. The benefit of using /bin/sh as the executable is that autorun will also work on FAT formatted media (which does not allow autorun.sh to have +x permission set) https://bugzilla.gnome.org/show_bug.cgi?id=642511 M src/nemo-autorun-software.c commit d1bc9311392e243aa5c9af4b80a373b6dd69d741 Author: Sandro Mani Date: 2011-09-07 mime-actions: don't spawn a warning if we have only one application Don't show a confirmation dialog when we're opening a number of files with the same application. https://bugzilla.gnome.org/show_bug.cgi?id=649811 M src/nemo-mime-actions.c commit 571a6ef755a6190d442739589b686401d75ff40b Author: Tomas Bzatek Date: 2011-04-15 connect-server-dialog: Respect password save setting The "Remember this password" checkbox was not respected when password was specified and connection succeeded for the first time. https://bugzilla.gnome.org/show_bug.cgi?id=641376 M src/nemo-connect-server-dialog.c commit 0ae354ce50394d18be01ca670fdf190d63c1591e Author: Cosimo Cecchi Date: 2011-09-07 search-bar: use gtk_entry_set_icon_from_icon_name() Now that we have an image style class for entry icons, we can style the symbolic color from the theme instead of rendering this manually. This also has the side effect of fixing bugs like https://bugzilla.gnome.org/show_bug.cgi?id=651209 M src/nemo-search-bar.c commit 37e379a5a484b604bd25f0b4cb3269f6e4c942ba Author: Michael Terry Date: 2011-06-29 Look at XDG_CURRENT_DESKTOP to decide if a link is foreign https://bugzilla.gnome.org/show_bug.cgi?id=653660 M libnemo-private/nemo-link.c commit 637289f74536ed2f31e05604401203a9360c439f Author: Michael Terry Date: 2011-06-29 Add Unity to OnlyShowIn https://bugzilla.gnome.org/show_bug.cgi?id=653657 M data/nemo.desktop.in.in commit cbadf49a82c70bb6ef90d63fdc4b43f4cb108598 Author: Cosimo Cecchi Date: 2011-09-07 css: remove custom CSS stylesheet Our custom CSS stylesheet is actually very tied to Adwaita. We don't want to force this style to other GTK+ themes, so the theming information has been moved to Adwaita itself. M data/Makefile.am D data/nemo.css M src/nemo-application.c commit ca7f81e2e9adf325effa11fc55aace4a087ab61b Author: Cosimo Cecchi Date: 2011-09-07 icon-container: use the "rubberband" style class for the selection item Instead of using a custom style property. M data/nemo.css M libnemo-private/nemo-icon-container.c commit 8b676a68b698b705a6008c89d53fded1cf635981 Author: Cosimo Cecchi Date: 2011-09-07 desktop: add a nemo-desktop style class to the desktop canvas So that themes can tweak the color/background of desktop canvas items separately. M libnemo-private/nemo-icon-container.c commit 22707fdc469dfc7548adc8020e3aaf63b20ae1bf Author: Cosimo Cecchi Date: 2011-09-07 eel: remove unused eel_cairo_draw_layout_with_drop_shadows() M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 77eecef417b91bb0c48588513de473f11a5c9896 Author: Cosimo Cecchi Date: 2011-09-07 icon-container: remove unused code caching canvas item colors Caching colors in NemoIconContainer to use them in the canvas item is not needed anymore, as gtk_render_* fetches the right values directly from the style context. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-private.h commit 95910c94fd46f368b66f02e1961dc5f273b38c82 Author: Cosimo Cecchi Date: 2011-09-07 icon-canvas-item: use gtk_render_* methods instead of direct cairo Instead of hardcoding colors and using direct cairo calls to draw the canvas items frame/background/labels, use gtk_render_* methods directly. This has the advantage of making them more friendly with GTK+ themes (by adding a nemo-canvas-item style class to the canvas context when drawing) and removes a ton of convoluted cairo drawing code. M libnemo-private/nemo-icon-canvas-item.c commit 483f13c18f55e489bc15ad266d5612edf96ad95a Author: Matej UrbanÄiÄ Date: 2011-09-07 Updated Slovenian translation M po/sl.po commit 5b09cedf434b53a975074b346d511335fc735cba Author: Rui Matos Date: 2011-08-08 list-view: explicitly set cursor on file name cell renderer on rename The file name column has two cell renderers, one for the icon and another for the name string. Thus, gtk_tree_view_set_cursor() isn't enough to reliably start editing the file name cell since it will try to edit whatever is the currently focused cell in the column. https://bugzilla.gnome.org/show_bug.cgi?id=656128 M src/nemo-list-view.c commit b20d9570c840f696eae5216652d93540bcfdc6db Author: Cosimo Cecchi Date: 2011-09-07 floating-bar: remove some unused code M src/nemo-floating-bar.c commit 00b108c687408db87ebb617186aa8fa62f35c7de Author: Luke Symes Date: 2011-07-16 Don't hide the floating-bar on hover if it is interactive If there are actions set on the floating bar, avoid escaping the pointer. https://bugzilla.gnome.org/show_bug.cgi?id=654558 M src/nemo-floating-bar.c M src/nemo-window-manage-views.c commit 3f892611ab497180fae677abd6520e4cd387877f Author: Stas Solovey Date: 2011-09-07 Updated Russian translation M po/ru.po commit a21d27b66fa307adaf87918f5feb2be44d52fdca Author: Cosimo Cecchi Date: 2011-09-07 places-sidebar: don't manually highlight the symbolic eject icon Set the right style class and state when rendering the icon, so the theming engine can fetch the right color from the theme and color the symbolic icon automatically. M src/nemo-places-sidebar.c commit 1eaae29320deb8dc6f218c13584aac5bbb66acd1 Author: Ihar Hrachyshka Date: 2011-09-07 Updated Belarusian translation. M po/be.po commit 407e426fcd2413a5a27e8bbc9f455da9e3fbbe59 Author: Kjartan Maraas Date: 2011-09-06 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 62bb5efc592a1241bfb0ca5c3773eb8ad899cbcc Author: Chao-Hsiung Liao Date: 2011-09-06 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit fa72a893c4e8558d94c22cb9ed3ed6c417eb265f Author: Daniel Nylander Date: 2011-09-05 Updated Swedish translation M po/sv.po commit 2d66b738054eb27a0f624be5a4a76d038c907b4d Author: Jorge González Date: 2011-09-05 Updated Spanish translation M po/es.po commit 8478047a09576891e30d87232d332da244c8a518 Author: Fran Dieguez Date: 2011-09-05 Updated galician translations M po/gl.po commit 4060b9ee98bb080383e4d973c7ae5be1a515f785 Author: Shaun McCance Date: 2011-09-02 Update help targets and add more useful entries to help menu M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog.c M src/nemo-file-management-properties.c M src/nemo-properties-window.c M src/nemo-shell-ui.xml M src/nemo-view.c M src/nemo-window-menus.c commit 156f61454a06dddadb82990bfd4d287729352ece Author: Ihar Hrachyshka Date: 2011-09-04 Updated Belarusian translation. M po/be.po commit 80d2046dd0df5719daa6ce9b702f0c0265eb7044 Author: André Gondim Date: 2011-09-03 Updated Brazilian Portuguese translation, reviewed by Antonio Fernandes C. Neto . M po/pt_BR.po commit c687d66e473f7094c6af552a69d14d81ae4c3baf Author: Aurimas ÄŒernius Date: 2011-09-03 Updated Lithuanian translation M po/lt.po commit af0022fc388a587726f1186bbe131c666e4d50a3 Author: Tomas Bzatek Date: 2011-09-02 previewer: Fix leaked GError M src/nemo-previewer.c commit e75ff65bc233eaaff108329376ff04b007422668 Author: Stas Solovey Date: 2011-08-31 Updated Russian translation M po/ru.po commit db72d73b3cd58493b1b8878a52ff8a9f5d350602 Author: Vincent Untz Date: 2011-08-30 all: Remove preferences about sound previewing The code was removed, so no need to keep the preference. https://bugzilla.gnome.org/show_bug.cgi?id=657718 M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo.convert M libnemo-private/org.gnome.nemo.gschema.xml.in M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit 3c5cc30d554e641d6013ef196b1a2d7c9424fa41 Author: Cosimo Cecchi Date: 2011-08-29 release: prepare for 3.1.90 M NEWS M configure.in commit 3d44be7ced5267143b3eb2ffcf7118c4fec3a199 Author: Andika Triwidada Date: 2011-08-18 Updated Indonesian translation M po/id.po commit 2d3ba922514b5b5aa5db01214b0dd183a2fdb8e2 Author: A S Alam Date: 2011-08-18 update translation for Punjabi M po/pa.po commit cfb84e3f7e44b0d752541ece747cec0066f0cea9 Author: Theppitak Karoonboonyanan Date: 2011-08-14 Updated Thai translation. M po/th.po commit 945f5bfaf3abbeaf963675ffd5d476cbefde8d74 Author: Piotr DrÄ…g Date: 2011-08-12 Updated Polish translation M po/pl.po commit 7f580504c1fc5904636b9314feab5d5f881a0ea5 Author: Alexander Shopov Date: 2011-08-10 Updated Bulgarian translation M po/bg.po commit a1830fad48e6f5769aab40917f44ebc8447501d4 Author: Kjartan Maraas Date: 2011-08-10 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 484117c8383a655e0c33e1206c6eb09a35692ead Author: Hendrik Knackstedt Date: 2011-08-05 [l10n] Updated German translation M po/de.po commit 99d7f0867eacde30502c5e7d4a074bed5d046dd6 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-08-03 po/vi.po: fix "free space" translation M po/vi.po commit c997bbe8b8bfb423d03f3475088a983e59bd9168 Author: Cosimo Cecchi Date: 2011-07-31 all: remove the built-in hover audio previewer This is not really useful anymore now that we have Sushi, which is way more powerful. M icons/Makefile.am D icons/audio.svg M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-private.h M src/Makefile.am D src/nemo-audio-mime-types.h M src/nemo-icon-view.c commit 065cecec33baf0f8e181da25313cb8030db4da18 Author: Cosimo Cecchi Date: 2011-08-01 application: call Close() on the previewer when there are no windows When the last window is removed from the application object, close the previewer too. M src/nemo-application.c commit f05eaaad2ef96338622c035696148be852c4aca0 Author: Cosimo Cecchi Date: 2011-08-01 previewer: add a wrapper for the Close() remote method M src/nemo-previewer.c M src/nemo-previewer.h commit 60a31b50c2231f9e9f0d624f2ee9cff4800655db Author: Cosimo Cecchi Date: 2011-08-01 previewer: call methods directly on the GDBusConnection Initialize the DBus connection in the constructor and call methods directly on it, instead of keeping the proxy around. M src/nemo-previewer.c commit d0573ec843e73b2832ccc64c08b21c6083526fd9 Author: Lê Trưá»ng An Date: 2011-07-24 Updated Vietnamese translation M po/vi.po commit 2b684e6ea35682ab6e636ca8723fb5d4f5104307 Author: Bruno Brouard Date: 2011-07-31 Updated French translation M po/fr.po commit a1949a8980d0d932ef8effebf44d10e4727cbeb2 Author: Djavan Fagundes Date: 2011-07-28 Fixed a string in Brazilian Portuguese translation M po/pt_BR.po commit f486646784ab6cf519fc9168629b40ca8259655a Author: Henrique P. Machado Date: 2011-07-27 Fixed a string in Brazilian Portuguese translation M po/pt_BR.po commit a000844b5a6039375b0e4176dd4c0f7083b46cb7 Author: Cosimo Cecchi Date: 2011-07-27 thumbnails: make sure to cache all mime types from gdk-pixbuf G_N_ELEMENTS() does not work for heap-allocated arrays, and always returns 1, so we were not actually caching all the supported mime types for a specific pixbuf loader after the first. This should also fix nemo not thumbnailing e.g. compressed SVG images, as reported in [1]. [1] https://bugzilla.gnome.org/show_bug.cgi?id=655406 M libnemo-private/nemo-thumbnails.c commit 0ee113dc1c5affda3eabf73b4c70c77456509d20 Author: Cosimo Cecchi Date: 2011-07-25 release: prepare for 3.1.4 M NEWS M configure.in commit 475ed89d6e6ac99f46700babd16671f88bd1386c Author: Didier Roche Date: 2011-07-25 Remove "Create Launcher" entry option "Create launcher" entry from nemo seems weird as nemo doesn't draw the desktop for GNOME Shell, and this rely on a gnome-panel binary. This brings inconsistency between the two sessions. https://bugzilla.gnome.org/show_bug.cgi?id=654848 https://bugs.launchpad.net/bugs/723861 M src/nemo-actions.h M src/nemo-desktop-icon-view-ui.xml M src/nemo-desktop-icon-view.c M src/nemo-directory-view-ui.xml M src/nemo-view.c M src/nemo-view.h commit 3caf41765453c3c4cf9a73aae87b185d099598f9 Author: Antoine Jacoutot Date: 2011-06-20 Turn nemo_window_close() into a virtual method. nemo_window_close() is now a virtual method that will behaves according to NemoWindowClass: it won't do anything if the window is a NemoDesktopWindow (i.e. it won't close it) which would prevent desktop icons from disappearing. nemo_application_close_all_windows() will now skip hiding windows but close them right away. https://bugzilla.gnome.org/show_bug.cgi?id=652724 M src/nemo-application.c M src/nemo-desktop-window.c M src/nemo-window.c M src/nemo-window.h commit 2bbbc01dc6429e948aed0bbf077e1b77880352ee Author: Antoine Jacoutot Date: 2011-07-15 Move the 'File System' shortcut down the list in the sidebar. Users access more often the XDG dirs than the root filesystem, so it makes sense to move it below. https://bugzilla.gnome.org/show_bug.cgi?id=654681 M src/nemo-places-sidebar.c commit 8686479b2be23735caec35c401d24db499cb2f2c Author: Cosimo Cecchi Date: 2011-07-21 icon-names: use 'drive-harddisk-system' as File System icon Now that it has been added to gnome-icon-theme-extras. https://bugzilla.gnome.org/show_bug.cgi?id=620085 M libnemo-private/nemo-icon-names.h commit 3f42d04301d9a8fcf43f176d1e601356489eb84f Author: Cosimo Cecchi Date: 2011-07-21 window: remove 'Clear History' from the 'Go' menu This is a leftover from the past, when we used to have a global history list. Now that Nemo is not persistent and we don't have that anymore, it doesn't really make sense to keep this menu item. https://bugzilla.gnome.org/show_bug.cgi?id=654422 M src/nemo-shell-ui.xml M src/nemo-window-menus.c M src/nemo-window.c M src/nemo-window.h commit 75960497c6c8e657f010aef7d2bbbf1fda19c4ad Author: Cosimo Cecchi Date: 2011-07-21 location-bar: don't pack an useless box in the bar The bar is an horizontal box already, no need to pack another hbox in it. This also fixes content not expanding in the available width, as noted in https://bugzilla.gnome.org/show_bug.cgi?id=654389. M src/nemo-location-bar.c commit 283e9b32cae61b5501ece85d1dacb1e1c29c4b85 Author: Cosimo Cecchi Date: 2011-07-21 file: use g_format_size_full instead of printf-ing the long string Now that GLib has g_format_size_full(), we can easily format the long string (e.g. 45MB (45,123,456 bytes)) using it, instead of our custom printf function. M libnemo-private/nemo-file.c commit 3e69fb702393cf42486321c88cede4668329b4c8 Author: Ryan Lortie Date: 2011-07-20 all: switch to g_format_size() g_format_size_for_display() has been deprecated in GLib and replaced with g_format_size(). Follow that change. https://bugzilla.gnome.org/show_bug.cgi?id=654995 M configure.in M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file.c M src/nemo-properties-window.c M src/nemo-view.c commit 2160de69245ad15826f6aed1a5ef15455d7851d0 Author: Cosimo Cecchi Date: 2011-07-14 a11y: remove some unused code M eel/eel-accessibility.c M eel/eel-accessibility.h commit a7bd0741e0772f3b143e5c1d77860cce8f3d9872 Author: Ihar Hrachyshka Date: 2011-07-14 Updated Belarusian translation. M po/be.po commit 227ccadc10af524ad1104d36c1343f26be55cf67 Author: Rudolfs Mazurs Date: 2011-07-13 Updated Latvian translation. M po/lv.po commit 613f7180ca741b201e5933d1ebf41fe811a722b4 Author: Abduxukur Abdurixit Date: 2011-07-07 Added UG translation M po/ug.po commit 4d68a3bbab0e6157f83c90288b58bdfebace63c2 Author: Muhammet Kara Date: 2011-07-06 Updated Turkish translation M po/tr.po commit fb45c737e0f7080bd0f51c532311b942a20e38a1 Author: Muhammet Kara Date: 2011-07-06 Fixed a few funny errors in Turkish translation M po/tr.po commit 614b7d3b2b7d09dc4bf19a51ae56a2a087212c99 Author: Muhammet Kara Date: 2011-07-03 Updated Turkish translation M po/tr.po commit 391d537f224204803ef8b50344892166cd9808fa Author: Kjartan Maraas Date: 2011-07-02 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 5817e7ad138f053c80d9257693dbacccb88eecbf Author: Cosimo Cecchi Date: 2011-07-01 release: prepare for 3.1.3 M NEWS M configure.in commit 34bbbc57864e454bdddcc59f322bf06b56254ef6 Author: Cosimo Cecchi Date: 2011-07-01 all: remove some unneeded includes M eel/eel-gtk-extensions.c M libnemo-private/.gitignore M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-tree-view-drag-dest.c M src/.gitignore commit 5c6950277332ca53fceb27d58fa3f06101737726 Author: Cosimo Cecchi Date: 2011-07-01 all: use g_cclosure_marshal_generic() instead of generating marshallers M eel/Makefile.am M eel/eel-canvas.c M eel/eel-editable-label.c M libnemo-private/Makefile.am M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-tree-view-drag-dest.c M src/Makefile.am M src/nemo-query-editor.c M src/nemo-view.c M src/nemo-window.c commit 922307d634a0401c8cc29bee70c6335b2eb9a17c Author: Cosimo Cecchi Date: 2011-06-28 build: bump GTK+ dep to 3.1.6 We need it for GtkOverlay. M configure.in commit eb8ba09e82cbf7045d75a638ef69318e65a8a75f Author: Ihar Hrachyshka Date: 2011-06-28 Updated Belarusian translation. M po/be.po commit 49db9b14ed4e08887e4dc3e5e4cd4c184f48d4ad Author: Ihar Hrachyshka Date: 2011-06-26 Updated Belarusian translation. M po/be.po commit ff6b4f64ab2499e149d2d75e812b2e6e40d68156 Author: МироÑлав Ðиколић Date: 2011-06-25 Updated Serbian translation M po/sr.po M po/sr@latin.po commit 6ac24b5381c7a26f85b8c72662c9ac4a54269e26 Author: Cosimo Cecchi Date: 2011-06-21 application: make sure --no-default-window works when used with an URI M src/nemo-application.c commit ffd2125b13ac591428cf73ac3c0021849d36058a Author: Daniel Nylander Date: 2011-06-20 Updated Swedish translation M po/sv.po commit ea4609ff6123798edf93b0e54b8b03a2fda94fce Author: Gabor Kelemen Date: 2011-06-19 Fix an inconsistency and a too long button M po/hu.po commit 95d45f1994795942774b039ba0de6933d9ffa5c7 Author: Paolo Borelli Date: 2011-06-18 Fix gobject warning about nonexisting property NemoDesktopWindow does not have an "app" propety anymore. M src/nemo-application.c M src/nemo-desktop-window.c M src/nemo-desktop-window.h commit 4c37f5a1c1c7861b45359e36a5efd868cf3f3bb0 Author: Cosimo Cecchi Date: 2011-06-16 all: don't return a reference when getting the application singleton This simplifies the code a bit. Also, remove the useless "app" property on NemoWindow while we're at it. M src/nemo-application.c M src/nemo-application.h M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-location-bar.c M src/nemo-main.c M src/nemo-places-sidebar.c M src/nemo-progress-ui-handler.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit 2b9ebd30e880733d3f40430d1d022ae2f8a4bf77 Author: krishnababu k Date: 2011-06-15 Corrections in Telugu file M po/te.po commit 296ef2be9726185ee08552d3e8bb17d2a98a40b7 Author: Paolo Borelli Date: 2011-06-05 Add "Add Bookmark" to the sidepane context menu https://bugzilla.gnome.org/show_bug.cgi?id=651931 M src/nemo-places-sidebar.c commit 67482b37c8b6581262da28798b6b4e36419b4852 Author: krishnababu k Date: 2011-06-15 Updated Telugu Translations M po/te.po commit aa3eff54fcab36a1fab561ec8527608e12a1496b Author: Cosimo Cecchi Date: 2011-06-13 overlay: remove unused gedit-overlay-child D src/gedit-overlay-child.c D src/gedit-overlay-child.h commit 17b2ff9b002498b8e6ce28c7bf846b0daf3ce206 Author: Cosimo Cecchi Date: 2011-06-13 release: update for 3.1.2 M NEWS M configure.in commit 63e37acc17900e81605b994e8d4e6dd59f1769da Author: Cosimo Cecchi Date: 2011-06-13 floating-bar: fix background/frame rendering M src/nemo-floating-bar.c commit 752ab2718ba4f7e968678facfd8dd0ea6b0e4b26 Author: Cosimo Cecchi Date: 2011-06-13 css: cleanup the CSS file a bit M data/nemo.css commit a28a89ab8112a5207d5413e5f767f191d1d13339 Author: Cosimo Cecchi Date: 2011-06-13 floating-bar: port to GtkOverlay M src/Makefile.am D src/gedit-overlay.c D src/gedit-overlay.h M src/nemo-floating-bar.c M src/nemo-floating-bar.h M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit 6260482af6804adda242d7a8582ccdd155beb9e0 Author: Cosimo Cecchi Date: 2011-06-13 all: don't use Gtk[H/V]Box in UI files M src/nemo-bookmarks-window.ui M src/nemo-file-management-properties.ui commit d6de7f5f0ff90775445c3dc353328301c66f0de1 Author: Cosimo Cecchi Date: 2011-06-13 all: don't use deprecated Gtk[H/V]Box M libnemo-private/nemo-column-chooser.c M libnemo-private/nemo-column-chooser.h M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-mime-application-chooser.h M src/nemo-connect-server-dialog.c M src/nemo-desktop-item-properties.c M src/nemo-image-properties-page.c M src/nemo-image-properties-page.h M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-notebook.c M src/nemo-pathbar.c M src/nemo-progress-info-widget.c M src/nemo-progress-ui-handler.c M src/nemo-properties-window.c M src/nemo-query-editor.c M src/nemo-view.c M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window.c commit 2c37855719d90413705bd102ef5a29aac33f598a Author: Teliute Date: 2011-06-12 Update Simplified Chinese translation. M po/zh_CN.po commit e46d446be937d0e43ffea1bbc41381388706cf42 Author: Matej UrbanÄiÄ Date: 2011-06-10 Updated Slovenian translation M po/sl.po commit f657a12a9f1da481e7a580335b682749ac4b01cf Author: Javier Jardón Date: 2011-06-09 libnemo-private: Use 'const' instead G_CONST_RETURN M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-icon-info.h commit a8443f64b6554b640f9bd39b3470284127b7bc3f Author: Javier Jardón Date: 2011-06-09 eel: Use 'const' instead G_CONST_RETURN M eel/eel-editable-label.c M eel/eel-editable-label.h commit 253e72f88a85759fe0630aecfb9cea4011e74e5a Author: Kjartan Maraas Date: 2011-06-07 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 64d608f8cc2d6e266900e5a33402249b20dfec1e Author: Fran Diéguez Date: 2011-06-06 Updated Galician translations M po/gl.po commit 12541f6a1ab1fbf30b032dc628aca147d6de2ad0 Author: Yaron Shahrabani Date: 2011-06-04 Updated Hebrew translation. M po/he.po commit e36c6f5871f6f16833361ce57a4845d46e73f3f1 Author: Yaron Shahrabani Date: 2011-06-04 Updated Hebrew translation. M po/he.po commit 092ba8f674341769579bc515389e7bb67035824d Author: Daniel Mustieles Date: 2011-06-04 Updated Spanish translation M po/es.po commit f83bdf0081bfb5d6b8caad8848a267fecb95b85b Author: Cosimo Cecchi Date: 2011-06-03 connect-server: handle closing of the dialog while connecting If we start a connect operation, but close the dialog before providing the credential details, cancel the operation and hide the dialog, instead of segfaulting. The dialog will eventually be destroyed when the the mount operation terminates (with error). M src/nemo-connect-server-dialog.c M src/nemo-connect-server-operation.c commit e3f055c886e9db0c105de59e80573a9715c41060 Author: Cosimo Cecchi Date: 2011-06-03 eel-string: don't use deprecated gatomic API M eel/eel-string.c commit a0d9614d204d0494d329e04c1d7652e451c2573f Author: Cosimo Cecchi Date: 2011-06-03 toolbar: disconnect the GSettings callback on dispose M src/nemo-toolbar.c commit b62ab1413cca6694b9b09fc9d241bbf3581a56e6 Author: Djavan Fagundes Date: 2011-06-03 Updated Brazilian Portuguese translation M po/pt_BR.po commit a5a4bddf12ff29205757858af81fd3665a68c3f2 Author: Cosimo Cecchi Date: 2011-05-31 application: pass in the array length while looping over it M src/nemo-application.c commit d0240a4319561551adc5e0cdb94bb5486d3f3308 Author: Carles Ferrando Date: 2011-05-29 [l10n]Updated Catalan (Valencian) translation M po/ca@valencia.po commit 1f01e04e135c77722cd3d06065f4ceed20d19219 Author: Jorge González Date: 2011-05-29 Updated Spanish translation M po/es.po commit ea223de6187778ce0a0a70356009f1c24c084c57 Author: Jorge González Date: 2011-05-29 Updated Spanish translation M po/es.po commit 178bae2b656b2cae7ad39f81076fca7c65adf429 Author: Yuri Myasoedov Date: 2011-05-28 Updated Russian translation M po/ru.po commit 362696f86bce90dcfa599bf6f4e17ffd0a679860 Author: Cosimo Cecchi Date: 2011-05-25 metadata: add a metadata::custom-icon-name metadata key It's similar to metadata::custom-icon, only that it works on icon names instead of URIs. https://bugzilla.gnome.org/show_bug.cgi?id=626338 M libnemo-private/nemo-file.c M libnemo-private/nemo-metadata.c M libnemo-private/nemo-metadata.h commit fc3d9af1dff85ef27ff44ea4e71b269a2b700e7d Author: Cosimo Cecchi Date: 2011-05-24 autostart: add an autostart desktop file It will autostart nemo automatically based on the GSettings key org.gnome.desktop.background show-desktop-icons. https://bugzilla.gnome.org/show_bug.cgi?id=647267 M data/Makefile.am A data/nemo-autostart.desktop.in commit 636c06bdc3397b1c6bad78afe2094c149c59f6fb Author: Cosimo Cecchi Date: 2011-05-24 css: update for new GtkCssParser M data/nemo.css commit e239f2a150f34b7f7b4730772fae5a372a7924d1 Author: Cosimo Cecchi Date: 2011-05-23 floating-bar: copy code from Epiphany to hide the floating bar on hover This doesn't currently work perfectly if the overlay child is a GtkTreeView - more investigation is needed. In the meanwhile, it's still better than not hiding the bar ever, so here it is. https://bugzilla.gnome.org/show_bug.cgi?id=648740 M src/nemo-floating-bar.c commit f0649b5bb808aa71fcab52c3e61f5e6419928432 Author: Cosimo Cecchi Date: 2011-05-23 gedit-overlay: update from upstream M src/gedit-overlay-child.c M src/gedit-overlay.c commit 5c949fffcb0de62fd5375f546fa94dd50ec7f86f Author: Cosimo Cecchi Date: 2011-05-24 application: rewrite GApplication command line handling Do the command line parsing in local_command_line for the set of options we're interested in parsing there (e.g. directories to open, self checks and --quit); move the rest of initialization in nemo_application_startup() and use g_application_open() and a custom "quit" action to forward the requests to the main application. This also fixes these two bugs. https://bugzilla.gnome.org/show_bug.cgi?id=649336 https://bugzilla.gnome.org/show_bug.cgi?id=637157 M src/nemo-application.c M src/nemo-application.h M src/nemo-connect-server-dialog-nonmain.c M src/nemo-location-bar.c M src/nemo-places-sidebar.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c commit b9272618934a4c177166e5f7771e6ab6cabcc31b Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-05-24 po/vi.po: updated UI to match nemo-preview.page M po/vi.po commit e738e686af858c38ca7c0b32426b3a1dfea0d9a2 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-05-24 po/vi.po: fix up UI to match nemo-views.page M po/vi.po commit f76c50a0e46aa7786820f76b3f71b57b44b8d7fb Author: Cosimo Cecchi Date: 2011-05-23 window: reverse the order of key-press event processing Usually the default GtkWindow handler for key-press events processes them in the following order: - calls gtk_window_activate_key() to process mnemonics/accelerators for the toplevel window - calls gtk_window_propagate_key_event() to propagate the events to the focus widget - chains up to parent if both fail We want gtk_window_propagate_key_event() to be called before gtk_window_activate_key(), as when we're focusing an editable widget (e.g. renaming a file), we want all keybindings to apply to that, e.g. Delete, Ctrl+Delete (or Ctrl+W if we're e.g. using an emacs-mode GTK+ binding set). This interferes a bit with the type-ahead search windows that NemoIconContainer and GtkTreeView pop up; we can control the former, but not the latter, so we need a bit of a hack in NemoListView to prevent the search window to steal the pasted URI, and still not handle the event. https://bugzilla.gnome.org/show_bug.cgi?id=314431 M libnemo-private/nemo-icon-container.c M src/nemo-list-view.c M src/nemo-window.c commit fae5d9242e2edf0881a382ed8cb19599c27cdc49 Author: Cosimo Cecchi Date: 2011-05-23 query-editor: add a border around the query editor widgets https://bugzilla.gnome.org/show_bug.cgi?id=647737 M src/nemo-query-editor.c commit f5e967f964b88ad7e4cc81818e9c0092d842e0a8 Author: Stefano Teso Date: 2011-05-23 connect-server: strip the scheme if it matches the chosen method If e.g. ftp://ftp.example.com is specified as an address, and the FTP method is chosen, we should strip "ftp://" automatically from the address before connecting. https://bugzilla.gnome.org/show_bug.cgi?id=643608 M src/nemo-connect-server-dialog.c commit c17d7bec375b1a8838d6132ccced89da6b092316 Author: Cosimo Cecchi Date: 2011-05-23 location-entry: use symbolic icons for the secondary action hint https://bugzilla.gnome.org/show_bug.cgi?id=647685 M src/nemo-location-entry.c commit b30bda3e1f341b107fbe4f73f1d7b769504d23cd Author: Cosimo Cecchi Date: 2011-05-23 view: add the "view" style class to the icon container Not to the NemoView scrolled windows. M src/nemo-icon-view-container.c M src/nemo-view.c commit c78c3022f07aa790a1f21c48e4ebf62712c6b70f Author: Cosimo Cecchi Date: 2011-05-09 dbus: don't generate the docbook file M libnemo-private/Makefile.am commit 2cf6e53496967b1e00cc026e33c7b63c587c78b4 Author: Cosimo Cecchi Date: 2011-05-09 release: prepare for 3.1.1 M NEWS M configure.in commit ab6436cfa60a7f5088dd92f3d6dec74e0527b086 Author: Cosimo Cecchi Date: 2011-05-09 previewer: avoid creating the dbus proxy more than once M src/nemo-previewer.c commit 16b76b5f97dda14e2c3397345965a07ecc1cd377 Author: Cosimo Cecchi Date: 2011-05-09 previewer: don't warn out if the bus name is not owned by anybody M src/nemo-previewer.c commit a8f2c97e5f67fa1c309cf694f8ca00f5dc38abb9 Author: Cosimo Cecchi Date: 2011-05-01 previewer: don't return a new ref to the singleton It's easier to use this way, and we don't have to create a new DBus proxy every time. M src/nemo-previewer.c M src/nemo-previewer.h M src/nemo-view.c commit 71b8a7a8d66f0c927be9b7c12199d1472043ed66 Author: Alexander Larsson Date: 2011-04-29 Add close_if_already_visible argument to nemo_previewer_call_show_file As per the changes in sushi M src/nemo-previewer.c M src/nemo-previewer.h M src/nemo-view.c commit f087da3353074f7476a563ab62d5ac7cf0d65e41 Author: Cosimo Cecchi Date: 2011-04-27 previewer: drop the x/y coordinates arguments M src/nemo-previewer.c M src/nemo-previewer.h M src/nemo-view.c commit 703c5004a7b05959e3dd554974f28b46df3f0609 Author: Cosimo Cecchi Date: 2011-04-25 previewer: lazily create the DBus proxy M src/nemo-previewer.c M src/nemo-view.c commit e5bf6ef0ec8ca50990aff4afd08a4139d4a75798 Author: Cosimo Cecchi Date: 2011-04-25 debug: add a debug flag for the previewer M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h commit 034eeb090458443b97fbe9b601a045defb5435f9 Author: Cosimo Cecchi Date: 2011-04-25 list-view: hook up the previewer in list view No support for icon locations yet, but it's not implemented in the previewer either. M src/nemo-list-view.c commit ccfd4e1c1d9166c78badac8d83958270cf7aef9e Author: Cosimo Cecchi Date: 2011-04-21 all: hook up the previewer with NemoIconView M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M src/nemo-icon-view.c M src/nemo-view.c M src/nemo-view.h commit 4241ccfd39b6013d2ddd7fbd58aabf5ef1a2302d Author: Cosimo Cecchi Date: 2011-04-21 previewer: add a NemoPreviewer DBus wrapper class M src/Makefile.am A src/nemo-previewer.c A src/nemo-previewer.h commit 9669b91d70ec1cf59933df53f9c22ed16670bb90 Author: Alexander Larsson Date: 2011-05-04 Update all .gitignore files M .gitignore M data/.gitignore M eel/.gitignore M libnemo-private/.gitignore M src/.gitignore commit 7c27c4ce158d09be188b529882ecd5c6b0c17db7 Author: Alexander Larsson Date: 2011-05-04 Convert the nemo dbus support to use gdbus-codegen This required latest glib code to work. M data/Makefile.am A data/dbus-interfaces.xml M libnemo-private/Makefile.am M libnemo-private/nemo-dbus-manager.c commit fa6e44717818d7f9239558f81b90c32dceddf58a Author: Alexander Larsson Date: 2011-05-04 Add size_request to IconContainer to work around unncecessary relayouting The GtkScrolledWindow uses the widget prefered size as a guess as to whether scrollbars are needed or not in the automatic scrollbars case. If we don't report anything for them we typically get it wrong and cause two size allocate calls on the child each time, with different sizes. This (the two sizes speicifically) will cause unnecessary relayouts of the window. So, we just report the current size of the layed out icons as the prefered size. This is somewhat wrong as its depending on previous size_allocation calls rather than the "ideal" size of the widget, but since the ideal size is ignored anyway and just used for this it works well. M libnemo-private/nemo-icon-container.c commit 0cad983521edd476ece360236b6e71e4048bfc70 Author: Alexander Larsson Date: 2011-05-04 Remove old special-cased "select source folder" We now do this generically, so no need to special case it in the "go up" case. M src/nemo-window-slot.c commit b15f61369e3618f4dc2cd3cef5af3698c45706a0 Author: Alexander Larsson Date: 2011-05-04 Always select the folder you "came from" when navigating upwards We used to special case this for the up button, but that now only exists as a keyboard shortcut. This more generic approach gets the same feature also for pathbar navigation and back/forward history navigation. M src/nemo-window-manage-views.c commit e9a7007284b9520855cdbb16fa4724ca0f1739d9 Author: Alexander Larsson Date: 2011-05-04 Really open in new window on the pathbar contect menu item Turns out that we didn't pass the NEW_WINDOW flag in the handler for the LocationOpenAlternate action. This is used when right-clicking on the location label or the pathbar. M src/nemo-view.c commit 41c7cb2ae8fb98fab2cd9b0cfb59cf6dee4d476c Author: Alexander Larsson Date: 2011-05-03 icon-view: Only resort during relayout if necessary We don't need to resort unless e.g. a file changed or was added. Additionally, for weird reason this makes the keyboard focus handling work when deleting a file (file after deleted gets focus). This was broken due to a relayout happening due to a size_allocate due to a style set due to a focus change when going to/from the "are you sure" dialog. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-private.h commit 31546b509d351e89d8bc0ee23074e8e0ecddbca2 Author: Cosimo Cecchi Date: 2011-05-02 application: don't look at DESKTOP_AUTOSTART_ID anymore Now that we don't support being a session component anymore, it doesn't make sense to special case the session autostart. This also breaks opening new windows when nemo is added to ~/.config/autostart, which is now the supported way of having desktop icons automatically, as we end up reading the env variable every time when parsing the command line (as the original process will always have that set) and refuse to show a window. https://bugzilla.gnome.org/show_bug.cgi?id=649063 M src/nemo-application.c commit e251214df28bc7c0b749d1ba0be1ab2048ecd06c Author: Abduxukur Abdurixit Date: 2011-05-02 Added UG translation M po/ug.po commit a9ea2becdf91c417a64083ecdad5f80fb97e6e51 Author: Daniel Korostil Date: 2011-05-02 Uploaded Ukranian M po/uk.po commit 495cb46d54f0b551756c71fb6d5ba60e67f08d61 Author: Cosimo Cecchi Date: 2011-05-01 places-sidebar: disconnect from bookmark list changed signal on dispose This should hopefully fix this crash https://bugzilla.redhat.com/show_bug.cgi?id=699184 M src/nemo-places-sidebar.c commit ac70a95ecc44ba259b684f737bb108f1458fa9dc Author: Cosimo Cecchi Date: 2011-05-01 mime-actions: don't free the activation parameters early This fixes a segfault when clicking on the "Select Application" button when opening a file with no default applications, like in https://bugzilla.redhat.com/show_bug.cgi?id=699850 M src/nemo-mime-actions.c commit 3676b08856c4d6cc0a827e9de8f708edefdf2e44 Author: Cheng-Chia Tseng Date: 2011-05-01 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 61502a06524dd9dffac9d2ae97e9a57037343b28 Author: Daniel Nylander Date: 2011-05-01 Updated Swedish translation M po/sv.po commit 902b0cd4cc1848b44fb2445ebcc0f8157cdc092f Author: Matej UrbanÄiÄ Date: 2011-04-28 Updated Slovenian translation M po/sl.po commit 254ad76a6f861b4846cb53907dd580fb81a96b05 Author: Cosimo Cecchi Date: 2011-04-28 progress-ui-handler: don't add progress infos to the window twice We were adding them twice in case there was already one operation running. https://bugzilla.gnome.org/show_bug.cgi?id=648857 M src/nemo-progress-ui-handler.c commit 8e8f0ed6edd3c5d4f9cca0e07a5624a3d5e2ec29 Author: Cosimo Cecchi Date: 2011-04-28 places-sidebar: make sure to return if we click inside empty space https://bugzilla.gnome.org/show_bug.cgi?id=648872 M src/nemo-places-sidebar.c commit f850fcc0eee61014472e698e6bdd36093ff9dfe2 Author: Andrej ŽnidarÅ¡iÄ Date: 2011-04-27 Updated Slovenian translation M po/sl.po commit a21e3e21940b84f93e0e82320ccfbb6e9a9f2cc3 Author: Cosimo Cecchi Date: 2011-04-27 places-sidebar: use per-side border widths for the sidebar frames This adds a border to the sidebar. M data/nemo.css M src/nemo-places-sidebar.c commit f6dc5f319fb79203bd7645e49420d2a4b57c0373 Author: Cosimo Cecchi Date: 2011-04-25 toolbar: set the icon size to SMALL_TOOLBAR So that the Search button icon is drawn with a smaller size. M src/nemo-toolbar.c commit 3cf09dc4e47ca0db181dd34af22977b8e91cf0f9 Author: Ask H. Larsen Date: 2011-04-25 Updated Danish translation M po/da.po commit 7a8f54b3bbff53b17d46dc6306636852636d1609 Author: Stefano Teso Date: 2011-04-25 places-sidebar: fix opening of selected items by pressing Enter Don't use get_cursor() to open the current item in the sidebar, and use the tree selection instead, as we modify the selection manually when evaluating up/down keypresses. https://bugzilla.gnome.org/show_bug.cgi?id=648555 M src/nemo-places-sidebar.c commit 83a7d27b36120d1ae54a2f5aa4af30f04d470bf2 Author: Cosimo Cecchi Date: 2011-04-25 icon-container: don't chain up style-updated for the desktop container Chaining up resets the background to the default color, which is not what we want for the desktop container. https://bugzilla.gnome.org/show_bug.cgi?id=648137 M libnemo-private/nemo-icon-container.c commit f0d52a7a29ca0b503ed160bd21e4f1a3354f6394 Author: Abduxukur Abdurixit Date: 2011-04-24 Added UG translation M po/ug.po commit e218bff9a4f790f0915f342d764559ee399fa8ee Author: Jiro Matsuzawa Date: 2011-04-25 Updated Japanese translation M po/ja.po commit 7288e91d77f63f4014fa5247bd8a59849f302871 Author: Arash Mousavi Date: 2011-04-23 Updated Persian translation M po/fa.po commit 2f070016690ec488b1ac46d6ab2faf860e0c59b6 Author: Bruce Cowan Date: 2011-04-20 Updated British English translation M po/en_GB.po commit 630fb578c1d86d4c14118025e9c33c8959d6ecf2 Author: YunQiang Su Date: 2011-04-17 fix a mistake of Chinese(Simplified) translation M po/zh_CN.po commit 4a69d60ecf5c6b48492e7dafda7a77e719f9f060 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-04-14 Updated Vietnamese translation M po/vi.po commit 679486ff6db16138027aa85c2aadbb9d272bc984 Author: Cosimo Cecchi Date: 2011-04-12 places-sidebar: make sure the eject icon is rendered 16x16 https://bugzilla.gnome.org/show_bug.cgi?id=647570 M src/nemo-places-sidebar.c commit fde63a6c6f0484f7284fd57ff26abe9d41c93196 Author: Daniel Mustieles Date: 2011-04-11 Updated Spanish translation M po/es.po commit 902aac532bac0da871591bbe481673d2c2d83907 Author: Ã…smund Skjæveland Date: 2011-04-11 Updated Norwegian Nynorsk translation M po/nn.po commit 6c7bd69033676d2e3f5c25b4308bd59e9d540bda Author: Ã…smund Skjæveland Date: 2011-04-11 Updated Norwegian Nynorsk translation M po/nn.po commit fdbca53ae2e7c387d05136656fd9c75fd982c863 Author: Alexander Shopov Date: 2011-04-10 Updated Bulgarian translation M po/bg.po commit a96761350ad422ec084c12f649562f9a2a83963d Author: Cosimo Cecchi Date: 2011-04-08 window: treat regular files as selection when opening a location This allows to call `nemo uri:///path/to/file` from the command line to open uri:///path/to with file pre-selected. https://bugzilla.gnome.org/show_bug.cgi?id=632427 M src/nemo-window-manage-views.c commit 3751310f941ed5df4a2a027ab594df015b3f815c Author: Yaron Shahrabani Date: 2011-04-08 Updated Hebrew translation. M po/he.po commit 07a6fb24fda755288346f11afb670cb3c05028fe Author: Cosimo Cecchi Date: 2011-04-07 icon-container: clear the drag state before popping up context menu Otherwise, a fake drag state will leak into the next motion-notify event when the menu has been dismissed, causing a segfault. https://bugzilla.gnome.org/show_bug.cgi?id=550253 M libnemo-private/nemo-icon-container.c commit d8b632765ca1b70d909d4e206f40590ee379a305 Author: Cosimo Cecchi Date: 2011-04-07 search-bar: set redraw_on_allocate(), like GtkInfoBar does This fixes artifacts while resizing. A similar patch was committed to GtkInfoBar in https://bugzilla.gnome.org/show_bug.cgi?id=587716. https://bugzilla.gnome.org/show_bug.cgi?id=647013 M src/nemo-search-bar.c commit e6dc21ba3b908ed93e08e39731733c871a91e171 Author: Paul Seidler Date: 2011-04-07 libnotify: need at least 0.7.0 https://bugzilla.gnome.org/show_bug.cgi?id=647088 M configure.in commit a8539a688bf83e1ab79167e257df308d1424a103 Author: Cosimo Cecchi Date: 2011-04-07 icon-container: reset the double click counter after a double click If we don't do this, we ignore any other double click event that happen during the next 'gtk-double-click-time' interval after the first double click. Thanks to Tanyel A. Nimeu for the initial patch. https://bugzilla.gnome.org/show_bug.cgi?id=647062 M libnemo-private/nemo-icon-container.c commit f200bfbe8332c0df74335f608f68350609e435d7 Author: Cosimo Cecchi Date: 2011-04-07 preferences: use g_settings_bind_with_mapping() for radiobuttons This also fixes radiobuttons preferences not being applied when opening the properties dialog. https://bugzilla.gnome.org/show_bug.cgi?id=644478 M src/nemo-file-management-properties.c commit 392359db6d6496b325044d809d96b034a2298514 Author: Cosimo Cecchi Date: 2011-04-07 conflict-dialog: make the rename entry expand the whole width M libnemo-private/nemo-file-conflict-dialog.c commit 1457f53c27f6d2f84d0c9eb76c1c8cffd1177e95 Author: Cosimo Cecchi Date: 2011-04-07 conflict-dialog: don't force a size request on the labels This is not required anymore in GTK+ 3 M libnemo-private/nemo-file-conflict-dialog.c commit b8077a7ad65f54e397dd3fa1b32f97b838ba590e Author: Cosimo Cecchi Date: 2011-04-07 conflict-dialog: don't forget to show the primary label Reported in https://bugzilla.redhat.com/show_bug.cgi?id=693922 M libnemo-private/nemo-file-conflict-dialog.c commit f100883058fac79a913d93d1d1157498c87d7912 Author: Fran Diéguez Date: 2011-04-07 Updated Galician translations M po/gl.po commit f49b62649a092a56e2cf6203db0fef08d2ed7618 Author: Cosimo Cecchi Date: 2011-04-06 pathbar: use a NemoFile instead of a GFile as a drag target The NemoFile tracks changes in the file name, so it solves the bug reported in https://bugzilla.gnome.org/show_bug.cgi?id=581748 M src/nemo-pathbar.c M src/nemo-window-slot-dnd.c M src/nemo-window-slot-dnd.h commit 8905b1f91253cfe36fa2c42e179831097b3c9aec Author: Wouter Bolsterlee Date: 2011-04-06 Updated Dutch translation by Wouter Bolsterlee M po/nl.po commit 13793fdc3f5fd884ff5f92093244157b751bd185 Author: Cosimo Cecchi Date: 2011-04-06 window: don't avoid same-uri reloads for the desktop Otherwise it will not reload when toggling desktop-is-home-dir. M src/nemo-window-manage-views.c commit 90b2084cf3f6be689b250ddfd318e33f19f8420d Author: Cosimo Cecchi Date: 2011-04-06 desktop-window: always reset is_loaded when setting the real directory M src/nemo-desktop-window.c commit 25aa3e7f391c905236397a38cf052b0b12bc792a Author: Cosimo Cecchi Date: 2011-04-06 desktop-window: disconnect the gsettings handler on dispose M src/nemo-desktop-window.c commit 8ade659212745eb91631e00d8e878e919a13858a Author: Cosimo Cecchi Date: 2011-04-06 icon-container: don't setup the regular background on the desktop M libnemo-private/nemo-icon-container.c commit ec447586d5f7a5f60f21436a868cfe28d315f1f1 Author: Cosimo Cecchi Date: 2011-04-06 places-sidebar: always add Home as a built-in place M src/nemo-places-sidebar.c commit f9bd05d254555e70ee5295fe08919a8c9d94ca79 Author: Cosimo Cecchi Date: 2011-04-06 places-sidebar: fix a typo in the GSettings key we listen to M src/nemo-places-sidebar.c commit 19d420a28b47723d8e7deb7561cc714be336e655 Author: Cosimo Cecchi Date: 2011-04-06 window-menus: use U+2013 EN DASH in the author copyright string https://bugzilla.gnome.org/show_bug.cgi?id=646735 M src/nemo-window-menus.c commit 6dbb7d159cfc277815d990dd157e2020608698a5 Author: Marvin Schmidt Date: 2011-04-05 configure: Fix libexif check https://bugzilla.gnome.org/show_bug.cgi?id=646849 M configure.in commit 77ba57813e5eaa1fc8260f6e56ef7645093be690 Author: Rodrigo Padula de Oliveira Date: 2011-04-05 Updated Brazilian Portuguese translation M po/pt_BR.po commit 9db9888bea1f0084055bf653cfb46e7b000647c9 Author: Bruno Brouard Date: 2011-04-05 Updated French translation M po/fr.po commit 319ded082ce47f384db3bfc9d7cab2fbe80e1a85 Author: Amitakhya Phukan Date: 2011-04-05 Updated Assamese translations M po/as.po commit 5f190c65784ff9b2b72e36cd0018dfbfab524b98 Author: Daniel Nylander Date: 2011-04-05 Updated Swedish translation M po/sv.po commit aaaee6de758f70005ffdd343a4b7354e3664f471 Author: Cosimo Cecchi Date: 2011-04-04 icon-container: rework the colors used for additional text labels We now use the insensitive color for the normal state, and make them follow the filename color for selected states. This also fixes https://bugzilla.gnome.org/show_bug.cgi?id=319982, tested with the HighContrast theme. M data/nemo.css M libnemo-private/nemo-icon-container.c commit ced6d22409c3a849b86b75bb867f267a3cdad800 Author: Cosimo Cecchi Date: 2011-04-04 window-menus: don't hardcode year values in the translatable string https://bugzilla.gnome.org/show_bug.cgi?id=646735 M src/nemo-window-menus.c commit bb6578da85fff3d28e6a71f9933b1bd34e7c27bc Author: Chao-Hsiung Liao Date: 2011-04-05 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit edd3c43beb5efbc13f55d73e8c9818966a031ad1 Author: Cosimo Cecchi Date: 2011-04-04 dnd: rework handling of _NETSCAPE_URL dnd links Previously we used to to the following: * default to always "ask", unless the copy was explicit * when dropped, we did not actually ask anything but we would trigger an async mimetype query_info and: - trigger a file asking whether to download or to link for text files - silently link for HTML files - silently download for every other mimetype * if the query_info was not completed within one second, we would download by default This is somewhat broken, as the DnD icon is not what you would expect; also downloading is not usually done with DnD from the browser, and it's also expensive, so it should never be the default, but an explicit choice. It also makes it impossible to create links for anything else than text or HTML. Change the policy to always link by default, unless the user explicitly requests the copy. M libnemo-private/nemo-dnd.c M src/nemo-view-dnd.c commit 2afe78a92cc402207e7f3a0189eca95311651076 Author: Cosimo Cecchi Date: 2011-04-04 file: use a GIcon to store the custom icon of desktop files Instead of a filename string. This also has the side-effect of fixing https://bugzilla.gnome.org/show_bug.cgi?id=615509 M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-link.c M libnemo-private/nemo-link.h commit e68c6e071915fe680ed44e824ccafdb1470a39bb Author: Jordi Serratosa Date: 2011-04-04 [l10n]Fixes on Catalan translation M po/ca.po commit 3f17316c34335a9ea8a82d8940506759d88c6fcd Author: Joan Duran Date: 2011-04-04 [l10n]Updated Catalan translation M po/ca.po commit 07c70ab3a65f1d67293a467b742dda729b85156b Author: Jamil Ahmed Date: 2011-04-05 Updated Bengali translation M po/bn.po commit 35311e217ac8f11e97628316c35d6093589507b0 Author: Cosimo Cecchi Date: 2011-04-04 thumbnails: remove unused struct definition M libnemo-private/nemo-thumbnails.c commit 93a0d7fd735c1670c0787c3daa7f84003994da5d Author: Cosimo Cecchi Date: 2011-04-04 thumbnails: remove obsolete check for GLib < 2.14 compatibility M libnemo-private/nemo-thumbnails.c commit f9c6ca979f753339b91c125c363a927fceb64283 Author: Cosimo Cecchi Date: 2011-04-04 thumbnails: remove code unused for years M libnemo-private/nemo-thumbnails.c commit 088d0968f837364374bdea20eda0fa4534338202 Author: Daniel Mustieles Date: 2011-04-04 Updated Spanish translation M po/es.po commit 367572b907d1cd970135e546b3237522b9720c7d Author: Cosimo Cecchi Date: 2011-04-03 application: don't redirect windows on computer:// when unmounting It's confusing now that we don't have a desktop. Redirect to the user home instead. This also has the side effect of fixing https://bugzilla.gnome.org/show_bug.cgi?id=615963 M src/nemo-application.c commit b37f08ef618b6418711a7c70ff7485961bc9058d Author: Cosimo Cecchi Date: 2011-03-31 places-sidebar: don't return TRUE in button-release when we eject Otherwise the GtkTreeView default handler won't run cleaning up what it set up in button-press-event and the next motion-event will trigger the DnD to begin. https://bugzilla.gnome.org/show_bug.cgi?id=646302 M src/nemo-places-sidebar.c commit 2644c6ef4e7839e976d4861d6c86e16e34d46a13 Author: Cosimo Cecchi Date: 2011-03-31 icon-canvas-item: make sure to reset the default cursor ond destruction We might be destroyed while hovering while in single-click mode, so make sure the default cursor is always cleared when finalizing, if we didn't get a leave event. https://bugzilla.gnome.org/show_bug.cgi?id=315023 M libnemo-private/nemo-icon-canvas-item.c commit a47b2efd9b265f92e306e855ede0af3f19881f0c Author: Cosimo Cecchi Date: 2011-04-04 build: bump version to 3.1.0 on master M configure.in commit 7c3ba0e86f5b6ba4859457c1fd57f6f443601cab Author: Yuri Myasoedov Date: 2011-04-04 Updated Russian translation M po/ru.po commit 60ecc80a6057ebb5605f1ef1eb51e6cf8785a1e1 Author: Piotr DrÄ…g Date: 2011-04-04 Updated Polish translation M po/pl.po commit 2641de616d77df714d743a58a52228a6632a1df1 Author: Wolfgang Stöggl Date: 2011-04-04 [l10n] Updated German translation M po/de.po commit 635d472128e9687daa3b466f43765ee116921712 Author: Lukas Lommer Date: 2011-04-04 Updated Czech translation M po/cs.po commit 6efe6113d1a2ee61eaf2feed818689f25023e687 Author: Cosimo Cecchi Date: 2011-04-04 release: release 3.0.0 The future is now. M NEWS M configure.in commit acce5e1c70e10ef550cfed888a852e5048dc4b3d Author: Cosimo Cecchi Date: 2011-04-04 release: update AUTHORS M AUTHORS M src/nemo-window-menus.c commit 681e24ae18f5f4cf6275171154383fb0aeaf1d1a Author: Cosimo Cecchi Date: 2011-04-04 release: require the latest stable versions of our dependencies M configure.in commit 278425bbcd806571f7d5369e53a15d5f22e51551 Author: Cosimo Cecchi Date: 2011-04-03 window: make sure we always force opening in new windows on the desktop https://bugzilla.gnome.org/show_bug.cgi?id=646548 M src/nemo-window-manage-views.c commit 68b57af6e476253b36d8652a681bade6facbd259 Author: Cosimo Cecchi Date: 2011-04-03 places-sidebar: disconnect the gsettings handler callback in _dispose() The GSettings object is a global singleton, so it will always survive the sidebar; we should make sure to disconnect all the settings signal when destroying the sidebar. https://bugzilla.gnome.org/show_bug.cgi?id=646664 M src/nemo-places-sidebar.c commit d4cce11671471427f1b62fc658e05d4f6637b3e9 Author: Chao-Hsiung Liao Date: 2011-04-04 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 42d58b3db4b639521c0346ec8d9afc3f60c30603 Author: Inaki Larranaga Murgoitio Date: 2011-04-04 Updated Basque language M po/eu.po commit 4611ba0cd09b1c63c67930f72c90edb2e4f3b83e Author: Wolfgang Stöggl Date: 2011-04-03 [l10n] Updated German translation, umlauts fixed M po/de.po commit b35740dd52162a87a19ef8ed6a56a6736e5736ec Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-04-03 Updated Vietnamese translation M po/vi.po commit b67ee41bc6601fc26bea2457dc8865e0df5e5f98 Author: Piotr DrÄ…g Date: 2011-04-02 Updated Polish translation M po/pl.po commit ce1f95f6f8ee17cb7613564295566ffd99d8e930 Author: Shankar Prasad Date: 2011-04-02 Updated kn translations M po/kn.po commit c6fc0d81c87f6c3bdfb457a98fbb386dfa36683e Author: Shankar Prasad Date: 2011-04-02 Updated kn translations M po/kn.po commit 333ce240832b66f46d8b9bfdfa4b294c1bf26fbd Author: Shankar Prasad Date: 2011-04-02 Updated kn translations M po/kn.po commit 7ddc0b3bb207fe0b9243b90f1c73b0bcf76490d4 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-04-02 Updated Vietnamese translation M po/vi.po commit 6fc1a0b5cedba6dc28dc995eb7a0688869239c71 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-04-02 po/vi.po: import from Damned Lies M po/vi.po commit 0a10d4355e2e144d6731fa12a981841e1ea7b9b9 Author: Gabor Kelemen Date: 2011-04-01 Updated Hungarian translation M po/hu.po commit c6279ac229545d7f64b64212383df2753482e233 Author: Giorgio F. Gilestro Date: 2011-04-01 Fix up accidental error in last commit The accelerator ended up as stock id instead. M src/nemo-view.c commit cce40272e35b20b4aaf5f93109a05b7bb89704d5 Author: Giorgio F. Gilestro Date: 2011-04-01 Use ctrl-delete as the keyboard shortcut to trash files This change was made to make it harder to accidentally trigger a file delete. We still support the trash that will let you get a trashed file back, and we will get undo support to make this even easier. However, that only works if you know you deleted the wrong file, not if you accidentally hit delete while the nemo window was focused. M src/nemo-view.c commit 803783c2479258aad8f2278dde95101b9e4b90ca Author: Shankar Prasad Date: 2011-04-01 Updated kn translations M po/kn.po commit e72093c2b0490b481a6b894bf84dd46075b7ef21 Author: Jiro Matsuzawa Date: 2011-03-31 Updated Japanese translation. M po/ja.po commit 952269914060f48f941053120e6035440c8cfc6f Author: Милош Поповић Date: 2011-03-31 Added Serbian translation M po/sr.po M po/sr@latin.po commit 7421f629c9493344846890a46e475667b9aae0b1 Author: Dr.T.Vasudevan Date: 2011-03-31 Updated Tamil translation M po/ta.po commit d011084103db0ace13a7011d53f68cf9a3489464 Author: Dr.T.Vasudevan Date: 2010-12-03 Updated Tamil translation M po/ta.po commit 80fab3f7a7447efbd4323cf372f846d4d59141a5 Author: Cosimo Cecchi Date: 2011-03-30 release: update for 2.91.94 M NEWS M configure.in commit f294a4e80626793624d76d6002b094d1c0809de4 Author: Alexander Larsson Date: 2011-03-30 Fix up eject button hover in places sidebar We were calling gtk_tree_view_column_cell_get_position() without properly loading the cell attribute for the right row before. We fix this by calling gtk_tree_view_column_cell_set_cell_data(). With this in place we can also use the x_offset for the position and avoid the whole summing of widths. Due to a bug in Gtk which expands the eject icon cell renderer we have to right align it so that it lines up properly. https://bugzilla.gnome.org/show_bug.cgi?id=640741 M src/nemo-places-sidebar.c commit b57c42f7fbe7fd90cdc6ff59b2f7c160dd3198af Author: Chao-Hsiung Liao Date: 2011-03-30 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 3fd5eda0fc01f56ce9ae9b68b744651d73342259 Author: Ask H. Larsen Date: 2011-03-30 Updated Danish translation M po/da.po commit cf21e9aa47c67861422ada02c7fa327340d63140 Author: Cosimo Cecchi Date: 2011-03-29 pathbar: keep a ref to the GFile while updating the path When desktop-is-home-dir changes, we force a re-layout of all the buttons, which in turn unrefs the passed-in GFile, as the ref would belong to an old button. Fix this by assuming a ref while calling nemo_path_bar_update_path(). https://bugzilla.gnome.org/show_bug.cgi?id=551543 M src/nemo-pathbar.c commit aed2cce6c36543457f5f1ad8f8c05f2fa147b1f2 Author: Matej UrbanÄiÄ Date: 2011-03-29 Updated Slovenian translation M po/sl.po commit e7d80384ab00d52149452e77cd566ee381474b36 Author: Gintautas Miliauskas Date: 2011-03-29 Updated Lithuanian translation. M po/lt.po commit 85ae5ae7e3174c05199ff6557c1cc905ad1d1075 Author: Sandeep Shedmake Date: 2011-03-29 Updated Marathi Translations M po/mr.po commit 08665d5c7ae146c45f5f9855b3ea60c22b1372ad Author: Lukas Lommer Date: 2011-03-29 Updated Czech translation M po/cs.po commit d01f3377a2724bb6582f13c48f7cd1b97b1b869b Author: Lukas Lommer Date: 2011-03-29 Updated Czech translation M po/cs.po commit c7c860a264db211a0a68ee963ce29c7fcb2ad334 Author: Alexander Larsson Date: 2011-03-28 Make sure we free custom accessibility objects Custom accessibility objects, such as NemoIconContainerAccessible need to be freed when their corresponding widget/object dies, right now we're not unreferencing the accessible, so its always leaked. M eel/eel-accessibility.c commit 69a3e83971e2f0963d0c68f4b3e84612ff4032e8 Author: Shaun McCance Date: 2011-03-27 Fixing help buttons to go to new gnome-help pages M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog.c M src/nemo-file-management-properties.c M src/nemo-properties-window.c M src/nemo-view.c M src/nemo-window-menus.c commit ac6ec79231cf3d0cbd076ea5a76b154c9930df68 Author: Henrique P. Machado Date: 2011-03-27 Updated Brazilian Portuguese translation. M po/pt_BR.po commit fed40498e77eb037826391eabdf5f359ad72ba78 Author: Abduxukur Abdurixit Date: 2011-03-27 Added UG translation M po/ug.po commit ca8392d39f57dcbc17d2de84c90fb4e4d473f074 Author: Ivan Masár Date: 2011-03-27 Updated Slovak translation M po/sk.po commit 0889c0e56d13329a835324cf20160a69591a6757 Author: Yuri Myasoedov Date: 2011-03-27 Updated Russian translation M po/ru.po commit 5c34337057c96621d2d43690b262eab98c287a1a Author: Kjartan Maraas Date: 2011-03-26 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 4e75a3b805b007c863ad2eb4b3be62a97249c33d Author: Cosimo Cecchi Date: 2011-03-25 icon-view: clear the icon view when destroying it This ensures all NemoFiles are properly unreffed when destroying the view, and fixes a leak. M src/nemo-icon-view.c commit 199e5adb8a51c9cd54a644de60b01d9c0cd2170d Author: Cosimo Cecchi Date: 2011-03-25 release: update for 2.91.93 M NEWS M configure.in commit 7268e3f449a7ae762dcc5b72cb8a36d7ed3362e2 Author: Alexander Larsson Date: 2011-03-25 Don't leak sidebar widgets Sidebar widgets are normal widgets these days and should be standard floating stuff owned by the container they end up with. So, we should no longer ref_sink them. M src/nemo-places-sidebar.c M src/nemo-tree-sidebar.c commit d781d414e40840422c201dd61637135358c75ab3 Author: Alexander Larsson Date: 2011-03-25 Don't leak NemoFile for bookmarks in places sidebar M src/nemo-places-sidebar.c commit 695efe7cb3f9a96e7c870c36d30e2759d800d2d5 Author: Alexander Larsson Date: 2011-03-25 Better debugging for NemoDirectory leaks M libnemo-private/nemo-directory.c commit 1d48f02ea1bf274d8fb0d70b61bed337bbda06c2 Author: Alexander Larsson Date: 2011-03-25 Add custom foreach to eel_g_hash_table_new_free_at_exit This can be used to get some sort of printout for leaks in non-string hashtables. M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h M eel/eel-stock-dialogs.c M eel/eel-string.c M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M src/nemo-properties-window.c commit 1a8aadd2d02554a308c33a2b88b95c6d7ef5be7f Author: Lukas Lommer Date: 2011-03-24 Updated Czech translation M po/cs.po commit 101796d8b02133f238a757e4d754915e1d276095 Author: Kjartan Maraas Date: 2011-03-22 Updated Norwegian bokmÃ¥l translation M po/nb.po commit f45510bbb82d6ffa23bf8a54b8596fb5f34ae5e3 Author: Mattias Põldaru Date: 2011-03-22 [l10n] Updated Estonian translation M po/et.po commit 41fd10dafd7fe0240dc13bf33140e8aa22d87333 Author: Cosimo Cecchi Date: 2011-03-21 Update for 2.91.92 M NEWS M configure.in commit 2cf698346aca25a48a11edeccc34530e15843a6a Author: Cosimo Cecchi Date: 2011-03-21 file-operations: update the test to the new duplicate string behavior The test was in some cases checking for what we don't actually want to happen. Change it to match current behavior. M libnemo-private/nemo-file-operations.c commit 40947ed576b14777eb3106a3b0350b471455905d Author: Cosimo Cecchi Date: 2011-03-21 file-operations: make sure to handle correctly hidden files extensions This is a fixup of c250b5702329e71c61f6e7f4e26227925c5b1e90 M libnemo-private/nemo-file-operations.c commit 1f31ab18d932a778aa409dd3cadffb34d5f4ae54 Author: Cosimo Cecchi Date: 2011-03-21 css: apply a soft gradient to the floating bar. M data/nemo.css commit 9dc263518f71a2a06ec808be79c2bc0a9fe17129 Author: Cosimo Cecchi Date: 2011-03-21 window: make sure to never show the floating bar on the Desktop https://bugzilla.gnome.org/show_bug.cgi?id=644172 M src/nemo-desktop-icon-view.c M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window.c commit c250b5702329e71c61f6e7f4e26227925c5b1e90 Author: Cosimo Cecchi Date: 2011-03-21 Properly strip extensions when placing the duplication string We use a similar matching filter to the one we use when renaming. It's not ideal (mimetypes are hardcoded, and probably some are missing), but at least we're consistent. https://bugzilla.gnome.org/show_bug.cgi?id=351290 M eel/eel-vfs-extensions.c M eel/eel-vfs-extensions.h M libnemo-private/nemo-file-operations.c commit e0726b71cbbe3ddd9548546991a30951ecc1f21e Author: Cosimo Cecchi Date: 2011-03-21 slot: don't ref the view returned by _get_current_view() https://bugzilla.gnome.org/show_bug.cgi?id=643968 M src/nemo-window-slot-dnd.c M src/nemo-window-slot.c commit 2d71f734864647c23aa3e35374da9058beb0dc2e Author: Kristjan SCHMIDT Date: 2011-03-21 Updated Esperanto translation M po/eo.po commit ddc303bc2b23704911299ba28aab3f0e74fb88ee Author: Kristjan SCHMIDT Date: 2011-03-21 Updated Esperanto translation M po/eo.po commit 1ac3b5dd7100e75d8d579e7dc4c6fabb192a2dee Author: Kristjan SCHMIDT Date: 2011-03-21 Updated Esperanto translation M po/eo.po commit 76e10b322b5e0689c16881f10a3854e207a44c09 Author: Cosimo Cecchi Date: 2011-03-21 places: hide "Open in new Tab/Window" when using separate windows M src/nemo-places-sidebar.c commit 2cd9c4b84059f3e00ed6222ab43c34a974e2c550 Author: Cosimo Cecchi Date: 2011-03-21 view: cleanup "Open in new Tab/Window" items when using separate windows We were displaying a lot of useless entries in the menus in such case. M src/nemo-actions.h M src/nemo-directory-view-ui.xml M src/nemo-view.c commit 572ded742f9146a6bca8f5000804f291338db9b8 Author: Stefano Teso Date: 2011-03-21 view: set the right open flags when opening in a new window https://bugzilla.gnome.org/show_bug.cgi?id=644675 M src/nemo-view.c commit 58e544c260349a01242f40769e61e9b7098069fd Author: Cosimo Cecchi Date: 2011-03-21 window-pane: toggle the search button when showing a saved search https://bugzilla.gnome.org/show_bug.cgi?id=645027 M src/nemo-window-pane.c M src/nemo-window-slot.c commit 111be78c86bc824b291d9b402a2ff897b2fa2dc7 Author: Cosimo Cecchi Date: 2011-03-21 query-editor: make all the labels' appearance consistent M src/nemo-query-editor.c commit c863defffa222ec60eff29c5f31ab73131799912 Author: Cosimo Cecchi Date: 2011-03-21 query-editor: theme the query editor like the other cluebars M data/nemo.css M src/nemo-query-editor.c M src/nemo-query-editor.h commit 1469c27280be10a92aa92195023eb1bbf4a5d10c Author: Cosimo Cecchi Date: 2011-03-21 file-utilities: return "Home" as a title for the home directory Make it consistent with the rest of the UI. https://bugzilla.gnome.org/show_bug.cgi?id=645136 M libnemo-private/nemo-file-utilities.c commit dac5908d505542362cc51c5c21e0b9220715395a Author: Cosimo Cecchi Date: 2011-03-21 pathbar: don't unconditionally iterate over buttons when scrolling This should fix https://bugzilla.gnome.org/show_bug.cgi?id=645198 M src/nemo-pathbar.c commit a2d928754e9b65ce9c7ac93127b61abdd7cbb2f4 Author: Dirgita Date: 2011-03-20 Updated Indonesian translation M po/id.po commit 8129f1c78ac57aa96588228489860c315ef265c2 Author: Rudolfs Mazurs Date: 2011-03-19 Updated Latvian translation. M po/lv.po commit 71548f90dfe368b2ce3396bef6d2099e3b800bdf Author: Wouter Bolsterlee Date: 2011-03-19 Updated Dutch translation by Wouter Bolsterlee M po/nl.po commit 83587589effec5b76a6dd7032f374db4135fae12 Author: Gabor Kelemen Date: 2011-03-19 Updated Hungarian translation M po/hu.po commit 8094cacbdf5914f2a50c1a17cb93701890aafec3 Author: Lucian Adrian Grijincu Date: 2011-03-17 Updated Romanian translation M po/ro.po commit 9d27856f2e62479eca0adae87f1cf6f1bf6cf92c Author: Lucian Adrian Grijincu Date: 2011-03-17 Updated Romanian translation M po/ro.po commit e2bfbbd6d8ae577bb16cd215a2d106dcc31f6d8a Author: Cosimo Cecchi Date: 2011-03-17 view: use GTK_STYLE_CLASS_VIEW for NemoView So that NemoIconContainer also inherits the proper style class. M src/nemo-view.c commit 9c65f3b6675fb927a96a7dd52d6fec4eb700adce Author: Cosimo Cecchi Date: 2011-03-17 window: use GTK_STYLE_CLASS_SIDEBAR for the nemo sidebar M configure.in M data/nemo.css M src/nemo-window.c commit 32fdd13a6e92f9e36dc8476043c4b93f61a6eca9 Author: Gintautas Miliauskas Date: 2011-03-17 Updated Lithuanian translation. M po/lt.po commit f70c2c981adb794bf996b077f2dcfa299d689e61 Author: Mario Blättermann Date: 2011-03-17 [l10n] Updated German translation M po/de.po commit 99d84db2ccc8b7cd998a6704cc34b83cbcac4760 Author: Cosimo Cecchi Date: 2011-03-15 window-pane: use _split_view_off() to close the active pane with Ctrl+W This makes nemo' behavior consistent with what happens when F3 is pressed. M src/nemo-window-pane.c commit 633929a88b8941a4b817bd34b27ce5d8fbe3a804 Author: Cosimo Cecchi Date: 2011-03-15 css: theme the search bar and the cluebar with the proper colors M data/nemo.css commit 515610602463758c08d4ce5514219a83c3e05bfe Author: Cosimo Cecchi Date: 2011-03-15 search-bar: rework to make it more similar to the 3.0 mockups This involves rendering a background over the box, using symbolic icons and other goodness. M src/nemo-search-bar.c M src/nemo-toolbar.c commit 319cda6e9430b4aa74e052ee41086d82fc5bb530 Author: Cosimo Cecchi Date: 2011-03-15 window-slot: cleanup packing of extra widgets Don't pack them in a frame+eventbox, but just use the GtkBox. M src/nemo-window-slot.c M src/nemo-window-slot.h commit d73ded51a677700ad76201851af255f5ba6192d3 Author: Cosimo Cecchi Date: 2011-03-15 x-content-bar: make NemoXContentBar a GtkInfoBar M src/nemo-x-content-bar.c M src/nemo-x-content-bar.h commit 3b3fe092c77b685516495ae8239d6b5aa7c37072 Author: Cosimo Cecchi Date: 2011-03-15 trash-bar: make NemoTrashBar a GtkInfoBar M src/nemo-trash-bar.c M src/nemo-trash-bar.h commit a2df8af91ed91934c16a0a959c1e178b2849c46e Author: Fran Diéguez Date: 2011-03-15 Updated Galician translations M po/gl.po commit 45945cd45776a020b1f8ce5e61c0db7faa1895f4 Author: Cosimo Cecchi Date: 2011-03-15 window: add back the resize grip At the same time, add a bit more padding to the floating bar label, so that it won't be covered by the grip. Remove some margin at the bottom of the window too. M data/nemo.css M src/nemo-floating-bar.c M src/nemo-window.c commit ad8dd8389670d85e8afacb58dc7971cc2b81b9eb Author: Cosimo Cecchi Date: 2011-03-15 window-slot: let the "Loading" floating bar appear only after a timeout It will appear only if loading takes more than 500ms. M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit 275744644c95cc039efae7029a94814b47274ff7 Author: Cosimo Cecchi Date: 2011-03-15 floating-bar: don't use a yellow color for the floating bar Make it also a bit shorter. M data/nemo.css M src/nemo-floating-bar.c commit 00a9b3ae50db1cd609ee3eb4a556c851fc046906 Author: Duarte Loreto Date: 2011-03-13 Updated Portuguese translation M po/pt.po commit df4e4aa5d62e2ef23fdbf0a3ca09107e89d89ff6 Author: Ã…smund Skjæveland Date: 2011-03-13 Updated Norwegian Nynorsk translation. M po/nn.po commit 55585048b94c492fa32a60359a14472da8a4f7c4 Author: Claude Paroz Date: 2011-03-12 Updated French translation Contributed by Gérard Baylard, Bruno Brouard and Claude Paroz. M po/fr.po commit a3a69db247c58066fcd7ae9b3c6e596fa7f21060 Author: Bruce Cowan Date: 2011-03-12 Updated British English translation M po/en_GB.po commit 7536e18ed8fdf50274625837c022ce5ee843c340 Author: Tomas Bzatek Date: 2011-03-11 Bengali translation: Fix malformed format string Originally reported as https://bugzilla.redhat.com/show_bug.cgi?id=578086 Related to commits a1a8f97c9dcd9fdbbbfdddcec7f7d8da85a68dfb and 5b31e211ff20645c548949bd8d012b7bcaa39bf2 M po/bn.po commit b47b01d95f332f6a50157cb2d4940bd920455518 Author: Piotr DrÄ…g Date: 2011-03-11 Updated Polish translation M po/pl.po commit 9cf0a0a1bde02fababd047cced3c36ffa6f9543e Author: Khaled Hosny Date: 2011-03-11 Updated Arabic translation M po/ar.po commit c25ae0f18ca87c561178bd57b191fd13ec3edc38 Author: Manoj Kumar Giri Date: 2011-03-10 Updated Oriya Translation M po/or.po commit 86bd3f63bcdf7cdfdc0ebb12104856f7d085510b Author: Andrej ŽnidarÅ¡iÄ Date: 2011-03-09 Updated Slovenian translation M po/sl.po commit 85e624e496ddcbea78826545308aac09541bbfde Author: Andrej ŽnidarÅ¡iÄ Date: 2011-03-09 Updated Slovenian translation M po/sl.po commit 3800f7c7957ac155d96b0b8605197fd7de8cd943 Author: Cosimo Cecchi Date: 2011-03-08 css: make the backgorund of the floating bar button transparent M data/nemo.css commit e021dd0f9c73c4cbf6e8e00f1ca6863c99a7056c Author: Cosimo Cecchi Date: 2011-03-08 toolbar: use a raised button for Search M src/nemo-toolbar.c commit eb340743b260def298ed64a45d2b6112f7c71589 Author: Joan Duran Date: 2011-03-08 Updated Catalan translation M po/ca.po commit 30fca4b7b9afad5edb884ef7e6b8370fc88951ec Author: Kjartan Maraas Date: 2011-03-08 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 5b6d156f57ad630646c2c3e779d094b98766d529 Author: Cosimo Cecchi Date: 2011-03-07 Release 2.91.91 M NEWS M configure.in commit 9465370aad15fe7b20923ad1009a5d3314edc621 Author: Cosimo Cecchi Date: 2011-03-07 places: use iters to cycle items in the sidebar M src/nemo-places-sidebar.c commit ede178516796568e5d0b596cc720a3cb56dfaaf5 Author: Cosimo Cecchi Date: 2011-03-07 toolbar: set the primary-toolbar style class on the toolbar M src/nemo-toolbar.c commit 896138b17cf6bb8be87bfac3394af641972a364b Author: Luca Ferretti Date: 2011-03-07 Fixed a typo M po/it.po commit 894fe97a070004ad3317fa59fa8cb20851c9ab81 Author: Changwoo Ryu Date: 2011-03-06 Updated Korean translation M po/ko.po commit 96e53868862fb43b54b8e3f5cf9258615bc26fad Author: Andrej ŽnidarÅ¡iÄ Date: 2011-03-05 Updated Slovenian translation M po/sl.po commit 7af7225fce4ede640cf9eca3a2e11115bf542ff7 Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-03-05 Updated Vietnamese translation M po/vi.po commit 0e20049361db4a0d8926e98702501392e98efdcd Author: Nguyá»…n Thái Ngá»c Duy Date: 2011-03-05 po/vi.po: import from Damned Lies M po/vi.po commit 4359343f94d255929621fb4fa1f08b67ded4bf96 Author: Cosimo Cecchi Date: 2011-03-03 list-view: fix expand/fill visibility of the column editor dialog M src/nemo-list-view.c commit ab4fb0cdee781120d35f041a2198f203da2678cd Author: Daniel Korostil Date: 2011-03-02 Uploaded Ukranian M po/uk.po commit 7035f1c2d444b066e079abc50a8664bccf69fe05 Author: Daniel Nylander Date: 2011-03-01 Updated Swedish translation M po/sv.po commit 2ed8c3b4c3ac88996b6bbd961f9bc3fee6c14789 Author: Daniel Korostil Date: 2011-03-01 Uploaded Ukranian M po/uk.po commit 9b4ce4d88d5bc8374d218534f5ee616fdd64ef79 Author: Daniel Korostil Date: 2011-02-28 Uploaded Ukranian M po/uk.po commit f84f6578c5068fe3216387240420f41b2d00db41 Author: Cosimo Cecchi Date: 2011-02-28 css: don't put toolbar style here It's in gnome-themes-standard until we found a more generic way of expressing it. M data/nemo.css commit ba262758489a726afbfcbfe60f1f0c79f20d179a Author: Rudolfs Mazurs Date: 2011-02-27 Updated Latvian translation. M po/lv.po commit d12544d94d11cfe403f0a4f2f82b0ff569a623d6 Author: Gabor Kelemen Date: 2011-02-27 Updated Hungarian translation M po/hu.po commit 789d71e7edbc3f60668c305adb4da9bbdd94b4d6 Author: Stefano Teso Date: 2011-02-26 places-sidebar: skip section headers on keynav https://bugzilla.gnome.org/show_bug.cgi?id=643137 M src/nemo-places-sidebar.c commit 089315b56f78113bd26d18bb40d0132b84954ebe Author: Stefano Teso Date: 2011-02-26 typeahead-find: make sure the search widget is on-screen when maximized https://bugzilla.gnome.org/show_bug.cgi?id=642953 M libnemo-private/nemo-icon-container.c commit a5d4e41129e00461426312cdffa392b59ac30118 Author: Stefano Teso Date: 2011-02-26 bookmarks: bookmarked saved searches should use the saved-search icon https://bugzilla.gnome.org/show_bug.cgi?id=643057 M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-icon-names.h commit 02446f2cdb990fabebdefaed339227d6f52a495e Author: Cosimo Cecchi Date: 2011-02-25 icon-view: doesn't make sense to use g_timeout_add_seconds for preview https://bugzilla.gnome.org/show_bug.cgi?id=574033 M src/nemo-icon-view.c commit 5e2edee2e8dc6b4eababdff993176d591cc2a6e6 Author: Cosimo Cecchi Date: 2011-02-25 list-view: make sure not to select the extension on rename Delay calling gtk_editable_select_region() until after gtk_tree_view_set_cursor() https://bugzilla.gnome.org/show_bug.cgi?id=627110 M src/nemo-list-view.c commit a9515134c3bce4df1d1563340394b796ae40d183 Author: Stefano Teso Date: 2011-02-25 list-view: create folders in subdirectories when possible Don't always choose the tree root as parent when creating a new folder, but look at the current selection's directory. https://bugzilla.gnome.org/show_bug.cgi?id=330644 M src/nemo-list-view.c M src/nemo-view.c M src/nemo-view.h commit 97b1ff2fa3b4d706969ab40d4bf17adad281e42f Author: Cosimo Cecchi Date: 2011-02-25 list-view: unfreeze updates on focus out It's not really right, as GtkTreeView should always emit editing-canceled on the right renderer for us, but if you click away from the entry, it doesn't, so this is just a workaround until the GTK+ bug is fixed. M src/nemo-list-view.c commit 3645b11f392c649455472bc1b3a8c8f581c37c74 Author: Cosimo Cecchi Date: 2011-02-25 file: make sure not to pass g_utf8_collate() NULL strings M libnemo-private/nemo-file.c commit e939b36481815dbdf4053dba070f17d02a1efc38 Author: Cosimo Cecchi Date: 2011-02-25 desktop-file: remove obsolete x-directory/* mimetypes They got deprecated. https://bugzilla.gnome.org/show_bug.cgi?id=612694 M data/nemo.desktop.in.in commit 50ee32a1b46f0e0dea68b57c72070247bad9b7f7 Author: Cosimo Cecchi Date: 2011-02-25 window-slot: use the actual view as relative-widget Instead of special-casing the scrolled window in the overlay code, we directly set the actual view as relative-widget from the slot. M src/nemo-window-slot.c commit 23aa30fec0da95b58a9336da58115a3a04a21eb4 Author: Cosimo Cecchi Date: 2011-02-25 overlay: sync with gedit upstream As one of my patches got rejected. M src/gedit-overlay.c commit a2093ba1340334fa2733aa3ba2c00e7d1cfb683e Author: Cosimo Cecchi Date: 2011-02-25 view: remove nemo_view_get_widget() Having a function just to call a cast seems a bit weird... M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window-slot.c commit 2632e266fbc794de5e912ac1f37dfaa8f4ed0904 Author: Rodrigo Moya Date: 2011-02-25 Plug memory leak M libnemo-private/nemo-icon-info.c commit f45d398de73c1eee924e55aadba96254d8091932 Author: Rodrigo Moya Date: 2011-02-24 Guard against filename being NULL on nemo_icon_info_lookup M libnemo-private/nemo-icon-info.c commit 6c9cfec6cca8fc51049eac6c7677516b5d241677 Author: Cosimo Cecchi Date: 2011-02-24 places-sidebar: use the widget type directly instead of defining a class M data/nemo.css M src/nemo-places-sidebar.c commit 5df17020848a51d1211451274ae6816562d53503 Author: Cosimo Cecchi Date: 2011-02-24 all: remove shadows from scrolled windows and add a bottom margin To better match the mockups M src/nemo-places-sidebar.c M src/nemo-view.c M src/nemo-window.c commit c024477bd59761cfa683117dafe47cd08fda3f52 Author: Cosimo Cecchi Date: 2011-02-24 window-slot: adapt to overlay API changes M src/nemo-window-slot.c commit 2aa5c4844b3f4fe6b26c72d74ccfc9352a11f3f4 Author: Cosimo Cecchi Date: 2011-02-24 overlay: sync with upstream, and add a case for scrolled windows M src/gedit-overlay-child.c M src/gedit-overlay.c M src/gedit-overlay.h commit b220d722a0748763ebe1370a49831c24d734f7f8 Author: Cosimo Cecchi Date: 2011-02-24 all: move the floating bar to NemoWindowSlot M src/nemo-floating-bar.h M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit d0706a08eefb73aa515cb445e57c0360637cce12 Author: Cosimo Cecchi Date: 2011-02-24 places-sidebar: don't activate 'Rename' shortcut for non-bookmarks M src/nemo-places-sidebar.c commit d2c34101172415c63fe3c89e62ea1bf8bca15d9d Author: Cosimo Cecchi Date: 2011-02-24 editable-label: only clear the selection if we change to insensitive This is borrowed from GtkEntry, and should properly fix https://bugzilla.gnome.org/show_bug.cgi?id=642766 M eel/eel-editable-label.c commit 8d9cb34aec31955874b59d7d90ca4a57c6ddbcf4 Author: Kjartan Maraas Date: 2011-02-24 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit d6f2b28ea999a2d36d023c80dfd9fb4d7ffd83d6 Author: Aron Xu Date: 2011-02-24 Update Simplified Chinese translation. M po/zh_CN.po commit 18b496bc28a59987d161b5272244a808f5c06e2c Author: Cosimo Cecchi Date: 2011-02-23 places-sidebar: discard special dirs if they are assigned to the home https://bugzilla.gnome.org/show_bug.cgi?id=643121 M src/nemo-places-sidebar.c commit 24e447ed71d986f8806dfcc75a7d2c32cb47dbd0 Author: Cosimo Cecchi Date: 2011-02-23 tree-sidebar: cope with being shown in separate windows Use the same strategy as in NemoPlacesSidebar to decide where new window should be opened. M src/nemo-tree-sidebar.c commit 187604bc871c9b09be29794713c5db211d075d48 Author: Cosimo Cecchi Date: 2011-02-23 window: make sure to disconnect the sidebar changed id signal When the window is finalized. M src/nemo-window.c commit 5ae01f04d69f9e1d24cda75e9046aea4b4e96cd1 Author: Cosimo Cecchi Date: 2011-02-23 places-sidebar: respect middle-click for separate windows mode Make it consistent with the rest, i.e. close behind. This also fixes a crasher. M src/nemo-places-sidebar.c commit 0e6d9d7da5e2deac33d14261fbe9a22bbc7de192 Author: Cosimo Cecchi Date: 2011-02-23 window-pane: don't open another window when toggling off the search When 'Open new windows in separate folders' is toggled. This is not yet complete, but fixes at least one case. M src/nemo-window-pane.c commit 29e8f4564400640cc19e0fd7753ea8b2bac9d555 Author: Cosimo Cecchi Date: 2011-02-23 properties-window: add a border around the notebook This makes it visually consistent with other nemo notebooks, and with e.g. the GNOME3 control-center. M src/nemo-properties-window.c commit 4b6ba5bbccb934b9c595003ea1218913dd33d0c9 Author: Cosimo Cecchi Date: 2011-02-23 view: disconnect the statusbar visibility signal handler on finalize M src/nemo-view.c commit b6c86952f816dc698fed3ebb91231cc9e1ea5745 Author: Matej UrbanÄiÄ Date: 2011-02-23 Updated Slovenian translation M po/sl.po commit 75b7885bcd6e77bf16f7fa9d6bee44ac0c53ce94 Author: Matej UrbanÄiÄ Date: 2011-02-23 Updated Slovenian translation M po/sl.po commit 20be3147adefe2a8e2f7d03ccebe791f09fd5060 Author: Matej UrbanÄiÄ Date: 2011-02-23 Updated Slovenian translation M po/sl.po commit 3f9cc6132af4fb06b7b1467e9544c8853843183c Author: Alexander Shopov Date: 2011-02-23 Updated Bulgarian translation M po/bg.po commit 415aef2af3e8a7491ee0605f5082a696640680f8 Author: Cosimo Cecchi Date: 2011-02-22 dbus-manager: install a DBus service file M data/Makefile.am A data/org.gnome.Nemo.service.in commit b76e3c666d1da08cc70bd09a293c2ed319861bcd Author: Cosimo Cecchi Date: 2011-02-22 dbus-manager: hold the GApplication for 5 seconds upon startup This is needed so that nemo can be started as a DBus service with --no-default-window and be able to handle incoming method calls without quitting before receiving them. M libnemo-private/nemo-dbus-manager.c M libnemo-private/nemo-dbus-manager.h M src/nemo-application.c commit 25e74f522cd49af07b2be6b92cc3a7421a57f5fc Author: Cosimo Cecchi Date: 2011-02-22 Fix distcheck M po/POTFILES.in commit 32f4f370a37eced91270202ed7ff02cd4db46d8d Author: Cosimo Cecchi Date: 2011-02-22 Release 2.91.90.1 M NEWS M configure.in commit a0569367b029140ca15cdd5d0d78a3577c3d6d83 Author: Cosimo Cecchi Date: 2011-02-22 module: make modules for extension that pull in ORBit resident ORBit installs atexit() handlers, which would get unloaded together with the module now that the main process doesn't depend on GConf anymore, causing nemo to sefgault at exit. If we detect that an extension would pull in ORBit, we make the module resident to prevent that. M libnemo-private/nemo-module.c commit 8ff66dc5aeb7c573ef3deb6100fa151e9f9349e9 Author: Ivar Smolin Date: 2011-02-22 [l10n] Updated Estonian translation M po/et.po commit c40521ffbc4e990e4633be41e730b28eec26f1f5 Author: Cosimo Cecchi Date: 2011-02-21 icon-info: remove unused code M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-icon-info.h commit 150b95ca0c668568e0e5d04701048d6f1fc1636b Author: Cosimo Cecchi Date: 2011-02-21 zoom-control: remove unused NemoZoomControl M src/Makefile.am M src/nemo-window.c D src/nemo-zoom-control.c D src/nemo-zoom-control.h commit ee701773633e2b5f2a70988ca16ace47d002e382 Author: Luca Ferretti Date: 2011-02-21 Updated Italian translation M po/it.po commit 50647b100ddb52f61c50f973d89f883d346442bb Author: Cosimo Cecchi Date: 2011-02-21 Release 2.91.90 M NEWS M configure.in commit aea7f1f49601c34398f8b62b3650f7c3db8d1171 Author: Cosimo Cecchi Date: 2011-02-21 all: fix some includes M src/nemo-toolbar.c M src/nemo-window-pane.c commit b89a352e0d37193d00de7085ad4ef18f6f2d36a2 Author: Cosimo Cecchi Date: 2011-02-21 configure: depend on stable GTK+/GLib versions M configure.in commit ead6bf5b5d80a0d4937d7b8f84dd2cdc53db73e4 Author: Luca Ferretti Date: 2011-02-21 Updated Italian translation M po/it.po commit 1cfe6c78c610c616873314e2fa76cb085116cf96 Author: Cosimo Cecchi Date: 2011-02-21 tracker-engine: update to 0.10, using libtracker-sparql https://bugzilla.gnome.org/show_bug.cgi?id=642770 M libnemo-private/nemo-search-engine-tracker.c commit a8a5b8d8eae041e7ae10a553d0990fc7ee5dc3cd Author: Stefano Teso Date: 2011-02-21 icon-container: fix setting the selection when renaming Closes: bgo #642766 M libnemo-private/nemo-icon-container.c commit 6dd4e0aed74bb7da6fc471ff6f032884f93643b5 Author: Cosimo Cecchi Date: 2011-02-21 application: remove the ConsoleKit listener I just moved it to the gnome-settings-daemon plugin where it should belong. M src/nemo-application.c commit a3f2a8814453860b1fb8d4c1aa9637011b46f7fb Author: Stefano Teso Date: 2011-02-21 nemo-view: Ignore scripts directory if it's a broken symlink Closes: bgo#633683 M src/nemo-view.c commit 585e46b63b691ccc4a618ddc01b686954da287a3 Author: Yaron Shahrabani Date: 2011-02-21 Updated Hebrew translation. M po/he.po commit 527aa458d57036cb74c3f855cd1eb724da1e3ad6 Author: Cosimo Cecchi Date: 2011-02-21 window: remove another couple of unused defines M src/nemo-window-private.h commit 8ec1999f09ff40b6a1a8b511efbf36b692144503 Author: Cosimo Cecchi Date: 2011-02-21 window: remove useless defines M src/nemo-window-private.h commit 9531e7cb106f161d8a43da7ca161fac8becd3de6 Author: Cosimo Cecchi Date: 2011-02-21 window: plug a leak Don't leak the GtkSizeGroup after we add widgets to it. Also, move it to the pane, where it should belong now. M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window.c commit 243a3f883f7b2969c11ddac8c6d46521ffa5ef4d Author: A S Alam Date: 2011-02-21 update Punjabi Translation by A S Alam M po/pa.po commit 945ff33b72928e13b2206ccb869f63420cd9de94 Author: Cosimo Cecchi Date: 2011-02-20 window-menus: fix indentation M src/nemo-window-menus.c commit 322a3d0094082a32d357d0358174025c296a46dd Author: Cosimo Cecchi Date: 2011-02-20 window: fix behavior of the Search action Make the toolbar button active state consistent with the menu, and simplify the code handling it a bunch. M src/nemo-shell-ui.xml M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c M src/nemo-window.h commit eb9a291ad09d77cd01131209f68beaa04ef45626 Author: Cosimo Cecchi Date: 2011-02-20 navigation-state: bind "active" for toggle actions So that we can use this objet for "Search" M src/nemo-navigation-state.c commit 808332169bb8000c57d55e267d4abf4dcad3a481 Author: Jorge González Date: 2011-02-20 Added Spanish translation M po/es.po commit 7a3360c812ac30858ca7281c3d34fd132c454f63 Author: Matej UrbanÄiÄ Date: 2011-02-20 Updated Slovenian translation M po/sl.po commit 763109bb17cd326195ff44951977243a6e6712d1 Author: Cosimo Cecchi Date: 2011-02-19 file-operations: make sure not to show the dialog before calling _run() This had no noticeable effect before, but with gnome-shell's modal dialog animation, it causes the dialog flickering before being picked by the WM. M libnemo-private/nemo-file-operations.c commit 01c61be847dbb30f7392794ad0fec6228e82904d Author: Cosimo Cecchi Date: 2011-02-19 all: plug some memory leaks M src/gedit-overlay.c M src/nemo-floating-bar.c commit bdb71b79540e5a7265ff08bf4353dd580c32411a Author: Cosimo Cecchi Date: 2011-02-19 overlay-child: make sure to intialize required fields M src/gedit-overlay-child.c commit 89b84688b36a769478bd4593cceace6e2636c86c Author: Kjartan Maraas Date: 2011-02-19 Fix this after the window and spatial cleanups M po/POTFILES.in commit e68968479783e0ff3e4f7c8b7391471d06597306 Author: Kjartan Maraas Date: 2011-02-19 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit ddd59a578e403e815f76006477bf5eaea5b20c1e Author: Cosimo Cecchi Date: 2011-02-18 window: accumulate saving the sidebar width in GSettings We don't want to hammer DConf with writes. M src/nemo-window-private.h M src/nemo-window.c commit 56b249cc804bcea81d0308afe45ac2e5084dc6d7 Author: Cosimo Cecchi Date: 2011-02-18 floating-bar: ellipsize the description label Until we have a better way to truncate it at the right point when there's not enough space. M src/nemo-floating-bar.c commit 695d067571292c6475761e1ae4c453615f611a00 Author: Cosimo Cecchi Date: 2011-02-18 overlay: fixup allocation in the overlay Give the children the right size they request, and make sure they don't get more space allocated than the width of their parent. M src/gedit-overlay-child.c M src/gedit-overlay.c commit 1fd64c8188a513ec0321e2ff70225f9a7c52b3ad Author: Cosimo Cecchi Date: 2011-02-18 pathbar: cleanups M src/nemo-pathbar.c commit 7545af6c31ff45998167d008f3320a69d5531f7c Author: Cosimo Cecchi Date: 2011-02-18 pathbar: clean up forward declarations and unused properties No real code change here. M src/nemo-pathbar.c commit 369eaac5796263e49dd0502aedc6d9137d160132 Author: Cosimo Cecchi Date: 2011-02-18 pathbar: remove unused code M src/nemo-pathbar.c M src/nemo-pathbar.h commit 36a47b4a7ea52c860818e0e8a4f795a365ba2e2c Author: Daniel Korostil Date: 2011-02-18 Uploaded Ukranian M po/uk.po commit 2fde89de52f465051dbc85e3d00f57941275e4a7 Author: Daniel Korostil Date: 2011-02-18 Uploaded Ukranian M po/uk.po commit 6a11ecdde028a4972559491a3c0ec7799cc8c882 Author: Cosimo Cecchi Date: 2011-02-18 icon-canvas-item: make the icon frame transparent when not prelit This fixes icons on the desktop appearing weird. M libnemo-private/nemo-icon-canvas-item.c commit 1d3d4a1e954fcc15f2a9c7d933e7bc65c5330cc3 Author: Cosimo Cecchi Date: 2011-02-18 all: remove 'Tighter Layout' option It's just broken, and we already have icon view if we want something tighter. M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M libnemo-private/nemo-metadata.c M libnemo-private/nemo-metadata.h M libnemo-private/nemo.convert M libnemo-private/org.gnome.nemo.gschema.xml.in M src/nemo-actions.h M src/nemo-convert-metadata.c M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui M src/nemo-icon-view-ui.xml M src/nemo-icon-view.c M src/nemo-icon-view.h commit 822b99ee1de297fbe78548a1a7fa96d1be737f72 Author: Cosimo Cecchi Date: 2011-02-18 list-view: make sure not to activate items while chaining up The event activation is done entirely in our signal handler, and row-activated should only be used for the typeahead search box. M src/nemo-list-view.c commit 1988c7bc5feff1a2630b2603d558d1c376b12c9f Author: Cosimo Cecchi Date: 2011-02-18 views: fix alternate locaiton opening somewhat It was broken after the last changes. Also, add some comments to clarify how things work. M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-window-manage-views.c commit 491948284e453440798f14e29ba65737f44c5d46 Author: Cosimo Cecchi Date: 2011-02-18 debug: add a debug flag for the icon view M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h commit 765d81d0b68e3b2d430b9ca0716a3f67607440df Author: Alexander Larsson Date: 2011-02-18 Change compact-view all-columns-have-same-width default to false This particular option is what makes the lables-on-the side part of compact view useful (and compact) over the normal icon view. Having it off by default is just weird. M libnemo-private/org.gnome.nemo.gschema.xml.in commit 2d904c778ce5b30649c4789f35fcd3ea44e7fa59 Author: Alexander Larsson Date: 2011-02-18 Remove debug spew from previous commit M src/nemo-window-manage-views.c commit e5f4a1f0fe63b324cc62e94a46599b2e187b1121 Author: Cosimo Cecchi Date: 2011-02-17 window-manage-views: initialize a variable M src/nemo-window-manage-views.c commit bdc7f2172f9e8b1c58d3f8a8d90ae157702dde3e Author: Cosimo Cecchi Date: 2011-02-17 window-manage-views: fix an oversight in previous commit M src/nemo-window-manage-views.c commit a58eb87e294c02ec61668ef6d02d701626ef8b98 Author: Cosimo Cecchi Date: 2011-02-17 window-manage-views: don't create two windows when opening in new win We were creating two windows at startup if the 'Open in different windows' option was toggled on. M src/nemo-window-manage-views.c commit 936a1749bb79217decc47ec2e12c7f3c40823f97 Author: Cosimo Cecchi Date: 2011-02-17 window: fix some missing signal handlers/overrides M src/nemo-window.c commit cff594aeba0cb62f3316eb8a14114091ca4c6d11 Author: Cosimo Cecchi Date: 2011-02-17 window: cleanup header M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit f57a958039400b38897bf7ad5cc2f2e686921624 Author: Cosimo Cecchi Date: 2011-02-17 location-dialog: remove NemoLocationDialog The only user was NemoSpatialWindow M src/Makefile.am D src/nemo-location-dialog.c D src/nemo-location-dialog.h commit b1589b8c22baa2d9508aabe96fc8bafd99bcdb71 Author: Cosimo Cecchi Date: 2011-02-17 all: fix the desktop window without spatial mode Basically disable all the window chrome for the desktop window. M src/nemo-desktop-window.c M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit 4bf81e0d4883b9b6a6dfab120b096bea26a46a0a Author: Cosimo Cecchi Date: 2011-02-17 window: merge the navigation window XML into the shell XML There's no such distinction anymore. M src/Makefile.am D src/nemo-navigation-window-ui.xml M src/nemo-shell-ui.xml M src/nemo-window-menus.c commit df516e1f09ded17bea6a4fc4fd8b974f61e799b4 Author: Cosimo Cecchi Date: 2011-02-17 all: merge NemoNavigationWindow into NemoWindow M src/Makefile.am M src/nemo-application.c M src/nemo-application.h M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-desktop-window.c M src/nemo-desktop-window.h M src/nemo-icon-view.c M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-mime-actions.c M src/nemo-navigation-action.c D src/nemo-navigation-window-menus.c D src/nemo-navigation-window.c D src/nemo-navigation-window.h M src/nemo-notebook.c M src/nemo-places-sidebar.c M src/nemo-view.c M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-menus.c M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit 4cf05a8c91bda94aac6d403947cbb402a68019d2 Author: Cosimo Cecchi Date: 2011-02-17 window: fix class casting madness M src/nemo-window.c commit 9af483dbbea8fc6fc41f4bc726522d7583ccf677 Author: Cosimo Cecchi Date: 2011-02-17 all: merge NemoNavigationWindowSlot into NemoWindowSlot M src/Makefile.am M src/nemo-application.c M src/nemo-navigation-action.c D src/nemo-navigation-window-slot.c D src/nemo-navigation-window-slot.h M src/nemo-navigation-window.c M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c commit 238bc1452138e1aae44dcc95121b749ab4d805d0 Author: Cosimo Cecchi Date: 2011-02-17 window-pane: remove useless class vfuncs M src/nemo-window-pane.h commit 67384aa0d21e90816d5ee084b56bb43b1e94af60 Author: Cosimo Cecchi Date: 2011-02-17 all: merge NemoNavigationWindowPane into NemoWindowPane M src/Makefile.am M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-navigation-window-menus.c D src/nemo-navigation-window-pane.c D src/nemo-navigation-window-pane.h M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-notebook.c M src/nemo-toolbar.h M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 0e73140437c97c23b480f137ce8c88113900a336 Author: Cosimo Cecchi Date: 2011-02-17 all: assume all windows are navigation windows M src/nemo-application.c M src/nemo-bookmarks-window.c M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window.c commit b6b63e35792fd50cbe71bf87e44d5233cd879b3d Author: Cosimo Cecchi Date: 2011-02-17 all: remove NemoSpatialWindow M src/Makefile.am M src/nemo-bookmarks-window.c M src/nemo-desktop-window.h M src/nemo-location-dialog.c D src/nemo-spatial-window-ui.xml D src/nemo-spatial-window.c D src/nemo-spatial-window.h M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-private.h M src/nemo-window.c commit 9d70e3e2a0b8af6eef1a10749a985896ba449e37 Author: Cosimo Cecchi Date: 2011-02-17 desktop-window: make NemoDesktopWindow a navigation window We still have to fix sidebar/toolbar visibility though. M src/nemo-desktop-window.c M src/nemo-desktop-window.h commit 073e1f9454d52523837a3a2073d710206c90a808 Author: Cosimo Cecchi Date: 2011-02-17 all: remove spatial windows methods from NemoApplication M src/nemo-application.c M src/nemo-application.h M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c M src/nemo-spatial-window.c commit edc5310062e8617727423e7508951de1abe0b1b9 Author: Cosimo Cecchi Date: 2011-02-17 all: remove NemoWindowOpenMode enumeration The mode is now always decided by the GSettings preference. M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-mime-actions.c M src/nemo-mime-actions.h M src/nemo-navigation-window-pane.c M src/nemo-places-sidebar.c M src/nemo-spatial-window.c M src/nemo-tree-sidebar.c M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window-types.h commit e94fe49ef856a4658fd3fcbb228b78bb0d7b0657 Author: Alexander Larsson Date: 2011-02-17 Don't show a desktop target in copy/move to if desktop is not shown M src/nemo-view.c commit e74376ee27a232e559a3ef98918f0742d6fa376a Author: Alexander Larsson Date: 2011-02-17 Don't show desktop in sidebar if desktop is not visible or if home is desktop By default there is no more desktop anymore, so its kinda weird to have it highly visible in the ui, as there should be nothing there. M src/nemo-places-sidebar.c commit 4298e522e25ea5075090822a5497164051373a4b Author: Alexander Larsson Date: 2011-02-17 Disable the status bar by default in new windows M libnemo-private/org.gnome.nemo.gschema.xml.in commit 055b16f45c4d3c7b5b543df5b8457702f2d3164e Author: Cosimo Cecchi Date: 2011-02-17 window-bookmarks: make sure we get an icon for bookmarks in the menu M src/nemo-window-bookmarks.c commit e978429c15a5a6d99c0dfeecb2ce889d1a6d0529 Author: Cosimo Cecchi Date: 2011-02-17 search-bar: make the search bar a regular GtkBox M src/nemo-search-bar.c M src/nemo-search-bar.h commit c4060407ef76d2566d02cd6dacf06381585ace17 Author: Cosimo Cecchi Date: 2011-02-16 all: set some junctions to better fit the mockup M src/nemo-places-sidebar.c M src/nemo-view.c commit d9640b96ef746cbfe5de6ddd21ae06052aa33fa8 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window: fix text setting/unsetting on Search button M src/nemo-navigation-window.c commit 46b297a523d7f679891299d2a6a4ccac03927ed1 Author: Cosimo Cecchi Date: 2011-02-16 eel: remove unused method M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 6acaf5d7ede7054a258f555331358054e1835813 Author: Cosimo Cecchi Date: 2011-02-16 window-menus: remove sneaky code for middle-click toolbar actions We support it directly where we already care now. M src/nemo-window-menus.c commit 6fa4065d55ffa792105576fd2b99ead5913b36f0 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window: don't create custom actions for the menu items We can use normal actions for those, and use the custom actions in the toolbar, as we already do. M src/nemo-navigation-window-menus.c commit b644be6ed4f7da02a700a2f74401c4f5273dca46 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window: remvoe useless Search action from the nav group M src/nemo-navigation-window-menus.c commit 0e168f61a0012127ee0c40ef642b0818471212b7 Author: Cosimo Cecchi Date: 2011-02-16 all: remove NemoViewAsAction The rationale being the same as for NemoZoomAction M src/Makefile.am M src/nemo-navigation-window-menus.c D src/nemo-view-as-action.c D src/nemo-view-as-action.h commit 38dea32b3da5610990348be37c3f9454cec54773 Author: Cosimo Cecchi Date: 2011-02-16 all: remove NemoZoomAction Now that we don't use it on the toolbar anymore, it's useless to keep around. M src/Makefile.am M src/nemo-navigation-window-menus.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window.c D src/nemo-zoom-action.c D src/nemo-zoom-action.h commit d83173021f5adc99b5eec468e0c4d5ddfeed4218 Author: Cosimo Cecchi Date: 2011-02-16 window: just use nemo_view_set_is_active() Don't roundtrip through NemoWindowSlot, as that's what it would do anyway. M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c commit a08625badd19790faca002f1fd6c7049f2d680ba Author: Cosimo Cecchi Date: 2011-02-16 window: active_pane might be NULL if we're destroying the window M src/nemo-window.c commit a74eac5f4446928cfa00ead53f972f7de678b914 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window-pane: don't bother always setting the active pane The toolbar is insensitive when not active anyway, so this is useless. M src/nemo-navigation-window-pane.c commit 40bfe945c48bc368c11be4341a6c3f27b5543960 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window-pane: cleanup the class a bit M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit de4b00057e06fdc675d640c65c9a459f9fdb2725 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window: integrate the back/forward actions with the state So that the current back.forward state propagates to menus. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window.c M src/nemo-window-private.h commit d6df8a9d7bc4b902de76c22504f2fa63557d7985 Author: Cosimo Cecchi Date: 2011-02-16 navigation-state: add NemoNavigationState M src/Makefile.am A src/nemo-navigation-state.c A src/nemo-navigation-state.h commit 0c60fd28a1852a101caef1e4cd783b26012cd7fc Author: Cosimo Cecchi Date: 2011-02-16 toolbar: make sure to hold a ref to the action group M src/nemo-toolbar.c commit 698f109a70c063d47b4ff4adeec78724f674fe6d Author: Cosimo Cecchi Date: 2011-02-16 navigation-window: little cleanup M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.h commit e18dddb0f6ff0a91e25929b667687b87c8d20ee5 Author: Cosimo Cecchi Date: 2011-02-16 window-pane: make sure we set another pane as active when closing M src/nemo-window-pane.c commit 3634db080bcf57534b47860908370da5d5cdfad9 Author: Cosimo Cecchi Date: 2011-02-16 window-slot: move window_slot_close() to nemo-window-slot.c Why on earth should it be somewhere else? M src/nemo-application.c M src/nemo-navigation-window-pane.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-slot.h M src/nemo-window.c commit 610b14e6c85d16d519a0c9665ada09b289d21de7 Author: Cosimo Cecchi Date: 2011-02-16 window-pane: move code around Makes things more readable. M src/nemo-window-pane.c M src/nemo-window-pane.h commit a0e572e833c0e27c147d99094dc5655297a38be5 Author: Cosimo Cecchi Date: 2011-02-16 location-bar: remove manual API for setting insensitive widgets It's not needed anymore M src/nemo-location-bar.c M src/nemo-location-bar.h commit dd6b7f734252fb9a3813be9856e6c8a44c9bc01a Author: Cosimo Cecchi Date: 2011-02-16 pathbar: remove hackish API M src/nemo-pathbar.c M src/nemo-pathbar.h commit 79c27eb5fbe998a0ed2f79541b4487db5f575958 Author: Cosimo Cecchi Date: 2011-02-16 navigation-window-pane: make the whole toolbar insensitive when inactive M src/nemo-navigation-window-pane.c commit d2c02297befb39526408d938b46cd8269d9d8549 Author: Cosimo Cecchi Date: 2011-02-15 window: remove some other useless code M src/nemo-spatial-window.c M src/nemo-window-private.h M src/nemo-window.c commit 63d5316f6bf85e41bc5be76d551a19c55ab07957 Author: Cosimo Cecchi Date: 2011-02-15 window: remove unused code M src/nemo-window.c M src/nemo-window.h commit 476d462bce0bce5fdc367daea3e14be8603f5c3d Author: Cosimo Cecchi Date: 2011-02-15 all: remove the concept of global history list It's not that useful now that nemo is not a long running application anymore. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-window-manage-views.c M src/nemo-window-private.h M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c commit 8974c917ecb202a0dad4871c79dc8d7306e28feb Author: Cosimo Cecchi Date: 2011-02-15 window-menus: move bookmark-related menu code where it belongs M src/nemo-window-bookmarks.c M src/nemo-window-menus.c commit 7309d5576f28de33e9a5e5653037264110893490 Author: Cosimo Cecchi Date: 2011-02-15 ui-utilities: centralize a helper function M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h M src/nemo-navigation-window-menus.c M src/nemo-window-menus.c commit 1755d56bdfefabf0b764aa3531e93f8fb18d73b0 Author: Cosimo Cecchi Date: 2011-02-15 window-pane: remove active_slots madness We can't have more than one active slot at the same time anyway. M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 3a27963142a0ef942631f88f2576f8bc29076898 Author: Cosimo Cecchi Date: 2011-02-15 navigation-window-pane: cleanup header M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h commit c4d48d522dccb915041c9521789a47d2bea0e1e4 Author: Cosimo Cecchi Date: 2011-02-15 window: cleanup window_pane_zoom madness M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 75f4f95bed048d955cabd7e521b6cc78182a0903 Author: Cosimo Cecchi Date: 2011-02-15 search-bar: simplify boilerplate code M src/nemo-search-bar.c commit 28afe6fde1d12083b915f0040c84157ebd461df7 Author: Cosimo Cecchi Date: 2011-02-15 navigation-window: set/unset text on 'Search' according to split mode M src/nemo-navigation-window.c commit 3e0fa2ef6166160131f4d0051e3ac0c065be52e0 Author: Cosimo Cecchi Date: 2011-02-15 view: use the right label if we're searching M src/nemo-view.c commit 600352c410a57214cc8fbb9789cf6b43dde55388 Author: Cosimo Cecchi Date: 2011-02-15 navigation-window: use g_settings_bind() a little more M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h commit d05c85a0808c48b987dbc438538530f8506d9dfd Author: Cosimo Cecchi Date: 2011-02-15 style: add some junction properties M src/nemo-toolbar.c M src/nemo-view.c commit 193f850cd11d909a0af9e95ec0dea7ad91c62160 Author: Cosimo Cecchi Date: 2011-02-15 ui-utlities: remove unused function M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h commit 6ebdfd9b5477178c9ab28c19e270b9dc4a53d6df Author: Cosimo Cecchi Date: 2011-02-15 window: don't care looking for toolbar extension items As we removed them. M src/Makefile.am M src/nemo-navigation-window-slot.c M src/nemo-window-manage-views.c D src/nemo-window-toolbars.c commit d3cee086e7be525046c8a16a08b15bfa996871fa Author: Cosimo Cecchi Date: 2011-02-15 libnemo-extension: remove the ability to add toolbar items We want to fully control our toolbar now. M configure.in M libnemo-extension/nemo-menu-provider.c M libnemo-extension/nemo-menu-provider.h commit 417bb5c31758a3b321fbac0d53402bed1034c6db Author: Cosimo Cecchi Date: 2011-02-15 navigation-window: use g_settings_bind() for statusbar visibility M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h commit 1373f01db2180f080e1d7b02e1655fecb33c21f2 Author: Cosimo Cecchi Date: 2011-02-15 toolbar: fix toolbar with split pane The way we used to instantiate the toolbar, from the navigation window UIManager, did not work fine in the new UI design, as we have a toolbar for each pane now; so we must instantiate a new UIManager for each pane, and add to it the navigation action group to fetch actions from. M src/Makefile.am M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-ui.xml A src/nemo-toolbar-ui.xml M src/nemo-toolbar.c M src/nemo-toolbar.h commit 7131487c8bebbbad075b238ec03934a78cf233d9 Author: Cosimo Cecchi Date: 2011-02-15 places-sidebar: use a symbolic icon for eject M src/nemo-places-sidebar.c commit a572b7355b12a99083b7489bf991a8f929b1a80a Author: Cosimo Cecchi Date: 2011-02-15 view: accumulate floating bar status setting in a timeout We use half of the double-click-time as a good heuristic. M src/nemo-view.c commit 5a21e22cb0603a77d0a8bf89f6197c799df7ba4d Author: Cosimo Cecchi Date: 2011-02-14 css: theme things a bit more M data/nemo.css commit caf3233bfc9e7a6e4cd4ed41245ca5d02fdd46e0 Author: Cosimo Cecchi Date: 2011-02-14 window: hide resize grip M src/nemo-window.c commit acd688037d2a8ccf675526a46ee1d8180301cedd Author: Cosimo Cecchi Date: 2011-02-14 view: use the floating bar as a temporary statusbar if it's off We use a slightly different status message in this case, where we don't care about free space on the volume. M src/nemo-view.c commit dc80c71c1a742e0134401e765652672a71e46809 Author: Cosimo Cecchi Date: 2011-02-14 view: always create the floating bar in _init() And show/hide it and its components according to what we're currently doing. M src/nemo-view.c commit b30c9ad791961a6cbf5622c1e3c34b8a088c0439 Author: Cosimo Cecchi Date: 2011-02-14 floating-bar: add _cleanup_actions() M src/nemo-floating-bar.c M src/nemo-floating-bar.h commit b75521b56f24bffa320ad7bb5bc61be6fa12cb96 Author: Cosimo Cecchi Date: 2011-02-14 floating-bar: add a bit more whitespace around the label M src/nemo-floating-bar.c commit b86054a34b9933180d9e847048a26d712505b04a Author: Cosimo Cecchi Date: 2011-02-14 sq iintegrate with view M src/nemo-view.c commit da3905c073456129874867df1572c8586a9a1f00 Author: Cosimo Cecchi Date: 2011-02-14 sq look like M data/nemo.css M src/nemo-floating-bar.c commit d44378ee0adf944bb13a987e4aa79abf1b15693e Author: Cosimo Cecchi Date: 2011-02-14 icon-view: cleanup of supports_* properties M src/nemo-desktop-icon-view.c M src/nemo-icon-view.c M src/nemo-icon-view.h commit 621106fd68a9e2d86f5e62876fd3e2844c2d85ac Author: Cosimo Cecchi Date: 2011-02-14 view: refactor supports_zooming into a property M src/nemo-desktop-icon-view.c M src/nemo-view.c M src/nemo-view.h commit 8544bdb09511cff7edc0382009e6ca0d1f607cd6 Author: Cosimo Cecchi Date: 2011-02-14 desktop-icon-view: adapt the desktop icon view to recent changes M src/nemo-desktop-icon-view.c M src/nemo-icon-view.c M src/nemo-icon-view.h commit 246d7177acf8fa2ddec512e96310f5e31889cfd5 Author: Cosimo Cecchi Date: 2011-02-14 view: add a 'show-floating-bar' property for classes to override So we can disable it on the Desktop. Also, cleanup the _class_init() code a bit while we're here. M src/nemo-view.c commit fec9449efc444e1dc25eeebf474a59f3aa16b75d Author: Cosimo Cecchi Date: 2011-02-14 view: hook up the overlay in the view M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-view.c M src/nemo-view.h commit db0c274ffaa2d4d95329716cad8b5af319fa9936 Author: Cosimo Cecchi Date: 2011-02-14 floating-bar: make it more similar to the mockups M data/nemo.css M src/nemo-floating-bar.c commit 8728a440f1fb9e661d5553b30e60f57f5460007d Author: Cosimo Cecchi Date: 2011-02-14 floating-bar: make the class more flexible - add dialog-like actions - add show/hide spinner M src/nemo-floating-bar.c M src/nemo-floating-bar.h commit bcec4c4ecf1b77d7e803f4e84689c6e3b1413fcf Author: Cosimo Cecchi Date: 2011-02-14 floating-bar: add NemoFloatingBar M src/Makefile.am A src/nemo-floating-bar.c A src/nemo-floating-bar.h commit 43f310d0c2ffa2c99c21b332650a9a86b9adc0ab Author: Cosimo Cecchi Date: 2011-02-14 squash overlay M src/gedit-overlay.c commit 5ca133a198326a5aac65c3ef3ddca9af2424bdf5 Author: Cosimo Cecchi Date: 2011-02-14 overlay: update GeditOverlay from upstream M src/gedit-overlay.c commit c16127a438ff9654cbd63dbbc3859dc9916d0160 Author: Cosimo Cecchi Date: 2011-02-11 overlay: borrow GeditOverlay implementation from gedit M src/Makefile.am A src/gedit-overlay-child.c A src/gedit-overlay-child.h A src/gedit-overlay.c A src/gedit-overlay.h commit f5e17ca2b9e27437963155c459f0584eccc45deb Author: Cosimo Cecchi Date: 2011-02-11 icon-view-container: remove useless dispose impl M src/nemo-icon-view-container.c commit f718677e60eafcb4214ef8d4a9831fd2e597e5d0 Author: Cosimo Cecchi Date: 2011-02-11 view: don't emit the clear signal M src/nemo-view.c commit 24f1f12a7092312af689c49b9f57d888ce9b6b8c Author: Cosimo Cecchi Date: 2011-02-11 selection-canvas-item: add getter for 'width-pixels' M libnemo-private/nemo-selection-canvas-item.c commit 79c9f9e854284c35fc8485efed4850787799a1cf Author: Cosimo Cecchi Date: 2011-02-11 css: style the floating bar according to the mockups M data/nemo.css commit c27b221329aedbe9b18c6bf02a49193475390a2d Author: Cosimo Cecchi Date: 2011-02-11 navigation-window: use a symbolic icon for the search button M src/nemo-navigation-window-menus.c commit b4f5d1a9eb4d1389a1c198bb16a28ca35bdf5f60 Author: Cosimo Cecchi Date: 2011-02-11 navigation-window: remove spinner code M src/nemo-navigation-window.c M src/nemo-window-toolbars.c commit 42f53017794f288a7c8709b297f0f6de1c368e94 Author: Cosimo Cecchi Date: 2011-02-11 selection-canvas-item: make fade-out time configurable M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-selection-canvas-item.c M libnemo-private/nemo-selection-canvas-item.h commit 5b3208302e2bb5a3d8f2f68ac785a4aa64e8b8a6 Author: Cosimo Cecchi Date: 2011-02-11 selection-canvas-item: make sure the item is destroyed after fading out M libnemo-private/nemo-selection-canvas-item.c commit e16f5d44fa67e2222f3a3ba30842e5697d76078f Author: Cosimo Cecchi Date: 2011-02-11 icon-container: only use icon elements to calculate layout bounds Canvas items like e.g. a NemoFloatingBarItem do not add up to the layout bounds calculation. M libnemo-private/nemo-icon-container.c commit 3c749cf9da882043cc5a5cb938f8831831dec768 Author: Cosimo Cecchi Date: 2011-02-11 selection-canvas-item: remove useless Xrandr code which does nothing This code doesn't seem to actually do anything M configure.in M libnemo-private/nemo-selection-canvas-item.c commit 854d310d34de8c45a43d7b94755fde45de2540fa Author: Cosimo Cecchi Date: 2011-02-10 navigation-window: cleanup cast madness M src/nemo-navigation-window.c commit f84f5bb0379b0eea4a9e4e1df72f3038587269eb Author: Cosimo Cecchi Date: 2011-02-10 navigation-window: ensure toolbar search button toggles as expected M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit d02d193409f53d11bb68ea97683ddc2dc83a088a Author: Cosimo Cecchi Date: 2011-02-10 window-menus: set is-important to 'Search' M src/nemo-navigation-window-menus.c commit ec87bd5216871dc2cc8c539b51f45be4096bcd2f Author: Cosimo Cecchi Date: 2011-02-10 navigation-window: remove commented out code M src/nemo-navigation-window.c commit f269eb0f1ff68c1f2ede2c8533a3764cafa11cf8 Author: Cosimo Cecchi Date: 2011-02-10 window-menus: remove is-important from back/forward nav actions M src/nemo-navigation-window-menus.c commit 67946b38ce482201e0da7dbf6e955e06038fa2c9 Author: Cosimo Cecchi Date: 2011-02-10 toolbar: build the toolbar and the location bar with a GtkUIManager M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-ui.xml M src/nemo-toolbar.c M src/nemo-toolbar.h commit ba531b1184310455127fa06691f3722052a2eb6c Author: Cosimo Cecchi Date: 2011-02-10 window-menus: merge the UI from XML while initializing actions Because we need it to be ready when setting up the window pane M src/nemo-navigation-window-menus.c commit 80ea58e844365d0bb097436ed8c0359e07cfd793 Author: Cosimo Cecchi Date: 2011-02-10 navigation-window: initialize actions before setting up the pane This is needed so that the pane can use those actions to build the toolbar. We also have to remove the code that updates split view actions from _initialize_actions(), as it requires the pane is realized. It should not be much of an issue, as that code is called when loading an URI anyway (and so it is called afterwards when loading the window). M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c commit 5756ac82bab3a63708544aeef47ee5b0e9b508da Author: Cosimo Cecchi Date: 2011-02-10 navigation-action: do not use a GtkMenuToolButton As it always has dropdown arrows, which we don't want to see. Make it a Firefox-like button instead, where you can either right click or keep the mouse button pressed for an amount of time to activate the context menu. M src/nemo-navigation-action.c commit 7363013201ec2950958db529ea96c0f2442b3c53 Author: Cosimo Cecchi Date: 2011-02-09 all: remove unused GSettings keys M libnemo-private/nemo-global-preferences.h M src/nemo-file-management-properties.c commit 66c46dd6d2cdbaeae38e9b42b083c17ebf3ed65d Author: Cosimo Cecchi Date: 2011-02-09 location-bar: use dash and not underscore in signal name M src/nemo-location-bar.c commit 0ea4ca0709c361a4e2adf5e061108abf5c7017e3 Author: Cosimo Cecchi Date: 2011-02-09 navigation-window-menus: use g_settings_bind() for toolbar visibility This also reduces the code complexity by a fair bit M src/nemo-navigation-window-menus.c commit 47958798846c8bbf85f2e28abc9b66d8266e890f Author: Cosimo Cecchi Date: 2011-02-09 navigation-window: comment out old toolbar code for now M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c commit 211dda1ded746708019b11dd497dde21adfb8c4d Author: Cosimo Cecchi Date: 2011-02-09 navigation-window: cope with NemoNavigationWindowPane changes M src/nemo-navigation-window.c commit 1a95b0117e095885fc6ec4c3903c909c4f48f377 Author: Cosimo Cecchi Date: 2011-02-09 slot: remove NemoBarMode M src/nemo-navigation-window-slot.h commit ff264ed954842d933c9fa5dcd6d8b48366ce60c6 Author: Cosimo Cecchi Date: 2011-02-09 navigation-window-pane: rework to make use of NemoToolbar M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h commit 36e9be912735ce02929aaace8fb618e31bb91b59 Author: Cosimo Cecchi Date: 2011-02-09 navigation-window: don't use search_bar_is_showing() NemoToolbar is smart enough to take care of visibility alone. M src/nemo-navigation-window.c commit 865556e2e2073c41f687a4752571bfdf593deeb3 Author: Cosimo Cecchi Date: 2011-02-09 navigation-window: don't tirgger toolbar visibility with GSettings It's done internally by NemoToolbar M src/nemo-navigation-window.c commit b34fb9648fcd58f17e09590e2dc9e0dae8af3757 Author: Cosimo Cecchi Date: 2011-02-09 navigation-window: remove methods to toggle toolbar visibility This will be done automatically by NemoToolbar and inside the methods to trigger temporary visibility. M src/nemo-navigation-window.c M src/nemo-navigation-window.h commit a56b468038964ba6ceea5efae74b1520d8e2429a Author: Cosimo Cecchi Date: 2011-02-09 window-toolbars: clean up includes M src/nemo-window-toolbars.c commit bd36e2d04baeeeeafc2fcf2f00383fbc367de735 Author: Cosimo Cecchi Date: 2011-02-09 toolbar: add NemoToolbar M src/Makefile.am A src/nemo-toolbar.c A src/nemo-toolbar.h commit ca1fa0c2b05edd8e76bb6314a7cb7c1adc4f3319 Author: Cosimo Cecchi Date: 2011-02-08 navigation-bar: remove useless abstract class Merge the useful pieces into NemoLocationBar itself, which is the only implementor anyway. M src/Makefile.am M src/nemo-location-bar.c M src/nemo-location-bar.h D src/nemo-navigation-bar.c D src/nemo-navigation-bar.h M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit 6f0a2036197cf03095b0a775c35983bc42885fb1 Author: Kjartan Maraas Date: 2011-02-17 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit dde08b0914b1ec42ecfbbbee47673e8fe3975319 Author: Sweta Kothari Date: 2011-02-17 Updated Gujarati Translations M po/gu.po commit f8bea223f63eb0ed62ddf22062c94d1c76fea234 Author: Alexander Shopov Date: 2011-02-17 Updated Bulgarian translation M po/bg.po commit 8f9dda634d5143dda92a8bf987ca083225ab174c Author: Mario Blättermann Date: 2011-02-13 [l10n] Updated German translation M po/de.po commit ae6122fb8212e56f2c5a3afad5b84d532ed3ffc1 Author: Changwoo Ryu Date: 2011-02-13 Updated Korean translation M po/ko.po commit 17323012e2ebc3b65be673a7524e021f84434810 Author: Yaron Shahrabani Date: 2011-02-12 Updated Hebrew translation. M po/he.po commit b0760d0c50aea36ab95a81794f35b739c3ab08f5 Author: Chao-Hsiung Liao Date: 2011-02-11 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 06e1c2822bc543566eb71ea6f6208a3c82da67fe Author: Mahyar Moghimi Date: 2011-02-10 Updating Persian Translation M po/fa.po commit a425e4ed04d0323e1770ca4889affc4564c66a05 Author: Mahyar Moghimi Date: 2011-02-10 Updating Persian Translation M po/fa.po commit 20df7410f143960c206efce19e0f404df3265c93 Author: Mahyar Moghimi Date: 2011-02-10 Updating Persian Translation M po/fa.po commit 917a3e2097f52d2e8223011b672dffadc6674472 Author: Cosimo Cecchi Date: 2011-02-08 gsettings: rename our gschema path to /org/gnome/nemo M libnemo-private/org.gnome.nemo.gschema.xml.in commit fbabd8e4f13fb7312f3921f3a1633b586a4b048c Author: Cosimo Cecchi Date: 2011-02-08 editable-label: chain up in style_updated() M eel/eel-editable-label.c commit 4e47a409e990418f541ec9c5f5b5e1567eb04297 Author: Alexander Larsson Date: 2011-02-07 Avoid spew in the common case of non-existing desktop metadata file M libnemo-private/nemo-desktop-metadata.c commit 98feec44b9d93fc029e95b682ec29eb104c60320 Author: Craig Keogh Date: 2011-02-06 Remove configure.in ACLOCAL_FLAGS, now in Makefile.am (GNOME bug 641629) M configure.in commit 43573325a03536a93869f0a080dc0b2257e7e258 Author: Craig Keogh Date: 2011-02-06 Honor aclocal flags (GNOME bug 641629) M Makefile.am commit 01e5b514d9155e73448365d5f994a967da2d58f2 Author: Cosimo Cecchi Date: 2011-02-07 pathbar: use "Home" for the home button, instead of the username M src/nemo-pathbar.c commit df482adbbdb62f422f9c3eabb5aa1ac7a638e700 Author: Kjartan Maraas Date: 2011-02-06 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit ed109037524dec6dbf11b4a840eb9b4ea82c9e2f Author: Fran Diéguez Date: 2011-02-06 Updated Galician translations M po/gl.po commit c926b072165b822af8dfd6f5d8a413809bb6b541 Author: Cosimo Cecchi Date: 2011-02-05 bookmark: apply name and custom-name during construction M libnemo-private/nemo-bookmark.c commit 8233aadcdd5dcf57d66c7c70df4e507ed32020ed Author: Ivar Smolin Date: 2011-02-05 [l10n] Updated Estonian translation M po/et.po commit 52d148c29a931ffaee715f714e7fd507901f7054 Author: Daniel Mustieles Date: 2011-02-05 Updated Spanish translation M po/es.po commit 21527ca0cdfc3bb4fa2bba86363ffd2b8a795fd1 Author: Daniel Mustieles Date: 2011-02-05 Updated Spanish translation M po/es.po commit eb69bfd91cca98f40f1c60f1198224c6b0e9ac61 Author: Ivar Smolin Date: 2011-02-05 [l10n] Updated Estonian translation M po/et.po commit 842a639da7450449877a31f1b0a52188c737b6c6 Author: Cosimo Cecchi Date: 2011-02-04 i18n: fix POTFILES.in M po/POTFILES.in commit 9e5a32831826ad609f8ad5315e5b6f72bda5c51f Author: Cosimo Cecchi Date: 2011-02-04 Release 2.91.9 M NEWS M configure.in commit 82fb99a34a6c27f6881e0a049d9882756b615f42 Author: Stefano Teso Date: 2011-02-04 location-entry: fix auto-complete for non-local URIs https://bugzilla.gnome.org/show_bug.cgi?id=635333 M src/nemo-location-entry.c commit 1212e12456347da601a77de013082fd1beac8463 Author: Stefano Teso Date: 2011-02-04 query: don't crash with empty .savedSearch files Be more robust against empty .savedSearch files. https://bugzilla.gnome.org/show_bug.cgi?id=601205 M libnemo-private/nemo-query.c commit 8f5d29b21b2ab82250bf516f9263aa473dfd64f1 Author: Stefano Teso Date: 2011-02-04 bookmark: don't make the name/custom-name props construct-only This was probably a typo from the refactoring of the object. https://bugzilla.gnome.org/show_bug.cgi?id=641484 M libnemo-private/nemo-bookmark.c commit 59d7af27e1d62e01108058088c5f9faf980832b3 Author: Khaled Hosny Date: 2011-02-04 Updated Arabic translation M po/ar.po commit 41de4e52b43c8ed5c9118860dac7caa303ebbc5b Author: Cosimo Cecchi Date: 2011-02-04 list-view: add a FIXME comment M src/nemo-list-view.c commit 4f17fb7db7b8736ebb4fe82ddb1c279777847730 Author: Cosimo Cecchi Date: 2011-02-04 list-view: workaround a GtkTreeView regression See https://bugzilla.gnome.org/show_bug.cgi?id=641518 for details M src/nemo-list-view.c commit f324265d1795a7d23af3ece0e48ce9479e1e5bb5 Author: Luca Ferretti Date: 2011-02-04 Updated Italian translation M po/it.po commit c2bcaeb0da84d5759571e365a3a5e71e48d70952 Author: Luca Ferretti Date: 2011-02-03 connect-server-dialog: add missing mnemonics and use proper capitalization M src/nemo-connect-server-dialog.c commit 5c89e3157752fa9311f0ca5e2310885187270ac8 Author: Yaron Shahrabani Date: 2011-02-04 Updated Hebrew translation. M po/he.po commit 11cc68cbcc154f7e84975861b26c177ae92547aa Author: Cosimo Cecchi Date: 2011-02-03 progress-ui: add a notification when all transfer complete M src/nemo-progress-ui-handler.c commit 046927432a01f7a4bb7a4dc9c96005548950ca79 Author: Cosimo Cecchi Date: 2011-02-03 progress-ui: add a "Show Details" action to the notification M src/nemo-progress-ui-handler.c commit 8536b7134f75f23c044772d583402bbe1ebf6174 Author: Cosimo Cecchi Date: 2011-02-03 progress-ui: first cut implemneting file ops progress with notifications M configure.in M src/nemo-application.c M src/nemo-progress-ui-handler.c commit b9fe2ecb4894895e063c4cbda5f62b7ad54b7449 Author: Cosimo Cecchi Date: 2011-02-02 progress-info: split UI of NemoProgressInfo into its own object M libnemo-private/nemo-progress-info.c M src/Makefile.am A src/nemo-progress-info-widget.c A src/nemo-progress-info-widget.h M src/nemo-progress-ui-handler.c commit adab8f5fe5681dcb06be4d6fbaa674624b49b6b5 Author: Cosimo Cecchi Date: 2011-02-02 progress-info: add NemoProgressUIHandler It will take care of the various states of file operation progress' user interface. M src/Makefile.am M src/nemo-application.c A src/nemo-progress-ui-handler.c A src/nemo-progress-ui-handler.h commit a0f89473830575ae39a568608bc58f3f92c6f4a4 Author: Cosimo Cecchi Date: 2011-02-01 progress-info: split progress information notify into a new manager M libnemo-private/Makefile.am A libnemo-private/nemo-progress-info-manager.c A libnemo-private/nemo-progress-info-manager.h M libnemo-private/nemo-progress-info.c M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h M src/nemo-application.c M src/nemo-application.h M test/test-copy.c commit 2a86f1c60ba847951145ea3570bcf4e7a26a18f1 Author: Fran Diéguez Date: 2011-02-03 Updated Galician translations M po/gl.po commit bfece2283aacd609ce3466b6f27539b03f215e8e Author: Mattias Põldaru Date: 2011-02-03 [l10n] Updated Estonian translation M po/et.po commit 52b59769ea4944eaebdef26c271b8c1c45aa0493 Author: Daniel Nylander Date: 2011-02-02 Updated Swedish translation M po/sv.po commit eb6a4a8eaea16b6fa4d377b759e306016073d2fe Author: William Jon McCann Date: 2011-02-02 Use Files as launcher name https://bugzilla.gnome.org/show_bug.cgi?id=641256 M data/nemo.desktop.in.in commit a293b96241714a8d07e2b8aecd34ce61aff117ad Author: Cosimo Cecchi Date: 2011-02-01 eel: remove unused eel-canvas-util M eel/Makefile.am D eel/eel-canvas-util.c D eel/eel-canvas-util.h M libnemo-private/nemo-icon-canvas-item.c commit 2870f8f8ef38350451ddf36dfc704b2a0e66c616 Author: Cosimo Cecchi Date: 2011-02-01 selection-canvas-item: fix copyright header I copied it from the wrong file. M libnemo-private/nemo-selection-canvas-item.c M libnemo-private/nemo-selection-canvas-item.h commit 6b03a56dbd932de2b274bf61f78ae12f4ed7da0b Author: Cosimo Cecchi Date: 2011-02-01 icon-container: use the fade out effect for rubberbanding M libnemo-private/nemo-icon-container.c commit bd30e3d0670e437c55e82b544565a539331154d5 Author: Cosimo Cecchi Date: 2011-02-01 selection-canvas-item: implement a fade out effect M libnemo-private/nemo-selection-canvas-item.c M libnemo-private/nemo-selection-canvas-item.h commit b13969228d4d96c3ff677090e888f2aa9d026083 Author: Cosimo Cecchi Date: 2011-02-01 selection-canvas-item: simplify GObject properties M libnemo-private/nemo-selection-canvas-item.c M libnemo-private/nemo-selection-canvas-item.h commit 8853b7bf92271ff093803ccdfb3079512d12149d Author: Cosimo Cecchi Date: 2011-02-01 Move EelRectCanvasItem to its own object in libnemo-private/ eel-canvas-rect-ellipse has quite some unused code that make it hard to modify. M eel/Makefile.am D eel/eel-canvas-rect-ellipse.c D eel/eel-canvas-rect-ellipse.h M libnemo-private/Makefile.am M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c A libnemo-private/nemo-selection-canvas-item.c A libnemo-private/nemo-selection-canvas-item.h commit 67687dd50433d620ddd931d983462ca131dd48bb Author: Cosimo Cecchi Date: 2011-02-01 desktop-metadata: initialize a variable M libnemo-private/nemo-desktop-metadata.c commit 513e94c31e22d340888b139c50c43b6f2d037703 Author: Cosimo Cecchi Date: 2011-02-01 desktop-metadata: append a terminator for single-length strv values This is needed so that we can differentiate between single-length strv and regular string values when reading them back from the keyfile, which does not store the type of its values. This way, we make sure that we always respect the actual metadata type in GFileInfo. M libnemo-private/nemo-desktop-metadata.c commit 25754a54bb0889187d9b5cb45e6c32ae9321f038 Author: Cosimo Cecchi Date: 2011-02-01 desktop-metadata: group multiple desktop metadata saving calls M libnemo-private/nemo-desktop-metadata.c commit aa552113606e24d331c6c62de0f5406351600d7f Author: Cosimo Cecchi Date: 2011-01-31 Release 2.91.8 M NEWS M configure.in commit 3f55f369c00044a3d93c6bb10aa9e7c025548d5d Author: Cosimo Cecchi Date: 2011-01-31 build: remove GConf dependency altogether M configure.in commit 4227f0b1708d36d464ffce207c75b429bec1917b Author: Cosimo Cecchi Date: 2011-01-31 convert-metadata: don't migrate the desktop metadata to GConf M src/nemo-convert-metadata.c commit 389789e8f102f794780a2842e9506dc23ddd6a08 Author: Cosimo Cecchi Date: 2011-01-31 preferences: don't use GConfClient anymore M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h commit 632bf39a23e5457d76540063eff69b36e36459d0 Author: Cosimo Cecchi Date: 2011-01-31 desktop-metadata: use a keyfile instead of GConf to store it M libnemo-private/Makefile.am M libnemo-private/nemo-desktop-directory-file.c M libnemo-private/nemo-desktop-directory-file.h M libnemo-private/nemo-desktop-icon-file.c A libnemo-private/nemo-desktop-metadata.c A libnemo-private/nemo-desktop-metadata.h M libnemo-private/nemo-metadata.h commit c62a8ff91596da4d14b56a52400baa52e05c2ccc Author: Cosimo Cecchi Date: 2011-01-31 desktop-directory-file: don't use eel boilerplate M libnemo-private/nemo-desktop-directory-file.c commit 3d0dc4d6d763c70630e82f5a5c69a6745af70866 Author: Gabor Kelemen Date: 2011-01-31 Fix a mistranslation M po/hu.po commit 678c5216ebe3987b7b268d27fc0af78f09e58d94 Author: Cosimo Cecchi Date: 2011-01-30 sort-order: resync sort order property with NemoFileSortType This makes the sorting preference reliably work again. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/org.gnome.nemo.gschema.xml.in M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit 6a6c18d4d62adc14cfc41769ab5ce37793d51c16 Author: Cosimo Cecchi Date: 2011-01-30 icon-view: save sort metadata only when the user explicitly changes it M src/nemo-icon-view.c commit c1fa2a49e02552a2fb334f7cb766a32f0c201ad1 Author: Cosimo Cecchi Date: 2011-01-30 eel: remove eel_g_settings_add_auto_* functions M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit 253345f0841a38fcf02023bc2acd8bdc26842160 Author: Cosimo Cecchi Date: 2011-01-30 all: don't use eel_g_settings_add_auto_* methods It makes no sense to use caching now with GSettings, as lookup operations are fast enough. M libnemo-private/nemo-file.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-thumbnails.c M src/nemo-desktop-icon-view.c M src/nemo-icon-view.c M src/nemo-list-view.c commit e14351baf9f252a57395f2982e05ccecc504d646 Author: Cosimo Cecchi Date: 2011-01-30 icon-view: move desktop view's get_view_id to a proper implementation Instead of hardcoding IS_DESKTOP_ICON_VIEW() checks in the parent class. M src/nemo-desktop-icon-view.c M src/nemo-icon-view.c commit fdf30fd8c54c25e952ecc313af6d5325cf062452 Author: A S Alam Date: 2011-01-29 update Punjabi Translation by A S Alam M po/pa.po commit b97ee5da0bb1ab6ad4cc0f2a1d795ee7f64b5ec5 Author: Cosimo Cecchi Date: 2011-01-28 Update MAINTAINERS and DOAP files M MAINTAINERS M nemo.doap commit 454b2caf1ba89a62321486db10c87e63217031b8 Author: Cosimo Cecchi Date: 2011-01-28 application: don't call mount_removed_callback() on pre-unmount The unmount process follows this flow: - pre-unmount is emitted - GIO performs checks to see whether the volume is safe to unmount, and spawns GtkMountOperation dialogues accordingly - if everything is fine, the unmount signal is emitted So, it's wrong to close or redirect windows from pre-unmount, as the mount could actually not be unmounted after that. M src/nemo-application.c commit 35bf6c86b53b68a61389f270aa0ce1ff2715ff7c Author: Cosimo Cecchi Date: 2011-01-27 Clean up our desktop file (#640687) - remove the 'System' category - remove autostart interactions with gnome-session M data/nemo.desktop.in.in commit e7b6fd0e59ec49fbe6216c157eea2a92b384d39e Author: Tomas Bzatek Date: 2011-01-27 Clarify the reason for recent nemo_file_peek_display_name() workaround M libnemo-private/nemo-file.c commit 8f6245a80cfd571274813fe4d5d950769d02bfba Author: Tomas Bzatek Date: 2011-01-27 Prevent a crash in nemo_file_peek_display_name() on invalid NemoFile This is more a workaround only, expect assert failures at other places when something bad happens. There's a race condition somewhere, this patch only prevents immediate crash. Patch by Marcus Husar https://bugzilla.gnome.org/show_bug.cgi?id=602500 M libnemo-private/nemo-file.c commit fd03c910a73ba18459e68baaf15e8dd295acd5c1 Author: Stefano Teso Date: 2011-01-26 places-sidebar: allow keyboard navigation with Enter/Space (#637768) M src/nemo-places-sidebar.c commit 4f4c07b1f9964d437f70c89d94e9585429a69f91 Author: Fran Diéguez Date: 2011-01-27 Get Galician translations back from wrong commit M po/gl.po commit dace8ba5c2068e80bb9d99a1370f0c1a989fb72a Author: Fran Diéguez Date: 2011-01-27 QA of Galician translations M po/gl.po commit 17793d3bb90dbde51c95f73867bf75d6546cf88f Author: Fran Diéguez Date: 2011-01-27 QA of Galician translations M po/gl.po commit a63aaa68f14bec6507d36e856a4ed79d969b1be3 Author: Cosimo Cecchi Date: 2011-01-25 desktop-background: make sure to hold a ref in the 'changed' idle Otherwise we might end up accessing object fields after it was destroyed. https://bugzilla.gnome.org/show_bug.cgi?id=640420 M libnemo-private/nemo-desktop-background.c commit 6d079cc40ab1dfab5b7d60cac44b655d4d243f3d Author: Cosimo Cecchi Date: 2011-01-24 editable-label: fix some drawing regressions Also, remove the copy/pasted gtkpango code again, as we can have a better rendering without it. M eel/eel-editable-label.c commit d4230de8667764e02dbb966b5d806ff78ced2fd5 Author: Cosimo Cecchi Date: 2011-01-24 all: silence new warnings from GCC 4.6 GCC 4.6 introduced a new warning about variables declared and initialized, but not really used in the function body. Remove all of these occurrences to build cleanly. M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas.c M libnemo-private/nemo-clipboard.c M libnemo-private/nemo-desktop-icon-file.c M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-entry.c M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-saved-search-file.c M libnemo-private/nemo-search-directory-file.c M libnemo-private/nemo-vfs-directory.c M libnemo-private/nemo-vfs-file.c M nemo-sendto-extension/nemo-nste.c M src/nemo-application.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-connect-server-dialog.c M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-main.c M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-pathbar.c M src/nemo-places-sidebar.c M src/nemo-properties-window.c M src/nemo-query-editor.c M src/nemo-tree-sidebar-model.c M src/nemo-tree-sidebar.c M src/nemo-view.c M src/nemo-window-manage-views.c M src/nemo-window.c commit 155cc03271fd7db1da4af7d60dcedfe8acdc2900 Author: Funda Wang Date: 2011-01-23 Updated zh_CN translation. M po/zh_CN.po commit 7e47ccdee2c8be8b16fad0da3320141f27596bfa Author: Piotr Eljasiak Date: 2011-01-22 Fix typo (G_TYPE_INSTANCE_CHECK_TYPE -> G_TYPE_CHECK_INSTANCE_TYPE) M libnemo-private/nemo-mime-application-chooser.h M libnemo-private/nemo-module.c M libnemo-private/nemo-tree-view-drag-dest.h M src/nemo-connect-server-dialog.h M src/nemo-connect-server-operation.h M src/nemo-location-dialog.h commit 0b4bb326cae5d8df888192f4c763211dff9e7f97 Author: Kristjan SCHMIDT Date: 2011-01-22 Updated Esperanto translation M po/eo.po commit 9f539e6fa5d2832b9b4788c338bbce66f81971f9 Author: Alexander Shopov Date: 2011-01-21 Updated Bulgarian translation M po/bg.po commit 187dc50c76da193f46aa7cb856a4ce1ea964b023 Author: Chao-Hsiung Liao Date: 2011-01-20 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 484c9a1bacd254795703c014a170b5801a1f3104 Author: Cosimo Cecchi Date: 2011-01-20 eel: remove eel-gdk-pixbuf-extensions M eel/Makefile.am D eel/eel-gdk-pixbuf-extensions.c D eel/eel-gdk-pixbuf-extensions.h commit 129d90ebcd83efd7d7f2ebc75c77922bd9771b9d Author: Cosimo Cecchi Date: 2011-01-20 all: remove unused includes of eel-gdk-pixbuf-extensions M eel/eel-gtk-extensions.c M eel/eel.h M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-thumbnails.c M src/nemo-properties-window.c commit 83a83e3a2200127889c9979240049124b7e9a182 Author: Cosimo Cecchi Date: 2011-01-20 icon-info: use gdk_pixbuf_new_from_stream_at_scale() M libnemo-private/nemo-icon-info.c commit 2103a49026fd1c406f2607ef7d070b3081835982 Author: Cosimo Cecchi Date: 2011-01-20 icon-canvas-item: simplify the code a bit M libnemo-private/nemo-icon-canvas-item.c commit f58a70a92a83f8979f43ed84fd79d9b764e6d7c6 Author: Cosimo Cecchi Date: 2011-01-20 eel: remove unused eel_pixbuf_render() M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h commit 8b13a044cc226cf1347831ef566938a24aa5f9a1 Author: Cosimo Cecchi Date: 2011-01-20 general: use eel_create_spotlight_pixbuf() M src/nemo-list-model.c M src/nemo-places-sidebar.c M src/nemo-tree-sidebar-model.c commit 09f0b79d854b00469410e2466897df6db5b4d51d Author: Cosimo Cecchi Date: 2011-01-20 icon-canvas-item: remove an useless snippet of drawing code M libnemo-private/nemo-icon-canvas-item.c commit a083fa0d0bbd99f1b74d28af305efeb71859e775 Author: Cosimo Cecchi Date: 2011-01-20 icon-container: hook to style_updated instead of style_set M libnemo-private/nemo-icon-container.c commit e652eb079514451313a67408c1cc3c8188ae0161 Author: Cosimo Cecchi Date: 2011-01-20 icon-container: remove unused style properties M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-private.h commit a1fa4eaa03493d6b69c5e79db296a83532974f63 Author: Cosimo Cecchi Date: 2011-01-20 icon-canvas-item: use eel_create_spotlight_pixbuf() Instead of passing eel_pixbuf_render() always the same values M libnemo-private/nemo-icon-canvas-item.c commit 207a2499a3f19b194acb93925084bbd7800fe0bc Author: Cosimo Cecchi Date: 2011-01-20 css: move the style properties from adwaita here M data/nemo.css commit 2a1fbaf839fc7eaae505e3534acd317e9dd47b1b Author: Cosimo Cecchi Date: 2011-01-19 canvas: fix an ACTIVE -> NORMAL typo from GtkStyleContext conversion M eel/eel-canvas.c commit d0d90599476e4f21d3e07fd670b6c18b6ba06794 Author: Cosimo Cecchi Date: 2011-01-19 icon-container: fix a couple of ACTIVE -> NORMAL typos M libnemo-private/nemo-icon-container.c commit e2ca42cac78cb0287a1bbb73030e7bba8b171970 Author: Cosimo Cecchi Date: 2011-01-19 icon-container: remove useless theming properties M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c commit 5bfc3e50c91c4c6fc129e9383e3f2f20a87be0cf Author: Cosimo Cecchi Date: 2011-01-19 views: use proper background color for inactive panes M libnemo-private/nemo-icon-container.c M src/nemo-list-view.c commit d55ca5df614a56f3d9750df1fbcfcca155dce0b4 Author: Marios Zindilis Date: 2011-01-19 Updated Greek translation M po/el.po commit bd179dad12aa8175ed7e02f9421c0d1ed125bd2a Author: Maxim V. Dziumanenko Date: 2011-01-18 Updated Ukrainian translation M po/uk.po commit 9eee9ff6ca3e93d5d363725282d8ba393a1e6d01 Author: Markus T. Vartiainen Date: 2011-01-18 list-view: jump to parent with left key on collapsed rows (#639688) M src/nemo-list-view.c commit c6fa6b2062a1adf3e4945824048b3771edb35ebe Author: Cosimo Cecchi Date: 2011-01-18 places-sidebar: plug a leak and cleanup code a bit M src/nemo-places-sidebar.c commit f394ce8c052dd65c8343106964ba4431d97d261c Author: Cosimo Cecchi Date: 2011-01-18 icon-container: plug a memory leak M libnemo-private/nemo-icon-container.c commit 8f15b28dd7afdd1a5c5b9c0d54c05d978a10461a Author: Cosimo Cecchi Date: 2011-01-18 eel: plug some leaks in gsettings helpers M eel/eel-glib-extensions.c commit 04d3aa67294f300f3b0bd927be5f45666260c5d3 Author: Nicolò Chieffo <84yelo3@gmail.com> Date: 2011-01-17 progress-info: use a symbolic icon for the notification area (#596568) M libnemo-private/nemo-progress-info.c commit 12c3841911b47e1496d8c8fea2429cf3ca4bf8d0 Author: Ivar Smolin Date: 2011-01-17 [l10n] Updated Estonian translation M po/et.po commit 9e016ee923a2625ebd4d66cf18f3a6d2c903e6c8 Author: Cosimo Cecchi Date: 2011-01-17 progress-info: tie the application life to the whole file operation And not to the progress widget only, as that - starts hidden for the first seconds - is not destroyed when the operation finishes, but only hidden Using g_application_hold/release with the progress operation lifetime seems like a better way to deal with the app lifecycle. M libnemo-private/nemo-progress-info.c commit a11b54d5752d9792f9af05942901396330688cf7 Author: Ivar Smolin Date: 2011-01-16 [l10n] Updated Estonian translation M po/et.po commit 7cbc6f2ee4f85f6923bf56b4891f91c04edaae31 Author: Daniel Mustieles Date: 2011-01-16 Updated Spanish translation M po/es.po commit 8efb55bc266f8b471059b9bc83de19f4085fef48 Author: Xan Lopez Date: 2011-01-16 places-sidebar: remove unused variable It was being freed uninitialized, which caused a warning (and a build failure with -Werror). M src/nemo-places-sidebar.c commit fcd8981ef68dd351910539302965476a66f0218f Author: Ivar Smolin Date: 2011-01-14 [l10n] Updated Estonian translation M po/et.po commit bf5d259288868a70258e63960ddc0eabe96bf9c8 Author: Cosimo Cecchi Date: 2011-01-14 application: don't quit if there are pending file operations Now that we're a single-window application, this has become much more relevant. M libnemo-private/nemo-progress-info.c M libnemo-private/nemo-ui-utilities.c M libnemo-private/nemo-ui-utilities.h M src/nemo-application.c commit f4637ff4481ee6d7d1e0453a5bd3ec4ac9dca17d Author: Cosimo Cecchi Date: 2011-01-14 bookmark: don't call into nemo_file methods unconditionally As NemoBookmark's file might be NULL in some cases. M libnemo-private/nemo-bookmark.c commit c55ddd80f16e56a366fe9e746c3632521d10f042 Author: Cosimo Cecchi Date: 2011-01-14 bookmark-list: avoid setting the bookmark icon by hand When creating a bookmark from the GTK+ list, otherwise we end up overriding NemoBookmark's special casing when reloading the list M src/nemo-bookmark-list.c commit c637811c268abdecae3a3720b1f77fc7fe5bcd6a Author: Cosimo Cecchi Date: 2011-01-14 bookmark: add debug messages M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h commit ce44fecb484ff1d6ae069446e3296f223b247c87 Author: Fran Diéguez Date: 2011-01-14 Updated Galician translations M po/gl.po commit 35a9e17696c0ff126a327f61046ab9e662a1738d Author: Ivar Smolin Date: 2011-01-13 [l10n] Updated Estonian translation M po/et.po commit ae1e300376b3479e14045892caa720dd3903a89c Author: Cosimo Cecchi Date: 2011-01-12 window-manage-views: re-add an accidentally removed snipped of code M src/nemo-window-manage-views.c commit d4df96c1e5c6bde62fd55dab1cbaae8a57f2b92e Author: Cosimo Cecchi Date: 2011-01-12 all: use new NemoBookmark API M src/nemo-bookmark-list.c M src/nemo-bookmark-list.h M src/nemo-bookmarks-window.c M src/nemo-places-sidebar.c M src/nemo-window-bookmarks.c M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-slot.c commit 3aa0396da2014b35f0ef21dffd29e4953667ceb2 Author: Cosimo Cecchi Date: 2011-01-12 all: use nemo_bookmark_get_gicon() M libnemo-private/nemo-ui-utilities.c M src/nemo-bookmarks-window.c M src/nemo-window-menus.c commit f6850158283858aae24ed3f1982341bc1b587d28 Author: Cosimo Cecchi Date: 2011-01-12 file-utilities: make compute_title_for_location() return the basename As a last-resort fallback. M libnemo-private/nemo-file-utilities.c commit 7cbd07aa15a3c099dfd69ab7cdcfd3dcbea38b51 Author: Cosimo Cecchi Date: 2011-01-12 file: remove unused code M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M src/nemo-pathbar.c commit f1c782c13dd675bafffb2a4d85900da52be88f3f Author: Cosimo Cecchi Date: 2011-01-12 file: make nemo_file_get_gicon() return custom icons too M libnemo-private/nemo-file.c commit ef5ebfe5db767a2f703e1f5cc57f6ab829d5499a Author: Cosimo Cecchi Date: 2011-01-12 bookmark: refactor the object - add properties for location, name, custom name and icon - make the code less convoluted, removing the appearance-changed signal - remove _get_pixbuf(), _get_icon() should be used instead M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-bookmark.h commit 8057f745fe1e741c8f2a3756efebc7c7e15cbf68 Author: Khaled Hosny Date: 2011-01-12 Updated Arabic translation M po/ar.po commit 906cea0bc4b2deac177e417551109b8319ee78cd Author: Yaron Shahrabani Date: 2011-01-11 Updated Hebrew translation. M po/he.po commit 31461f9f4782b0df89a14812c252addaa7d6e983 Author: Cosimo Cecchi Date: 2011-01-11 mime-actions: update the filtered out desktop files for folders M src/nemo-mime-actions.c commit a22f2501c8c00f16150d1de98d7039063a4e002a Author: Cosimo Cecchi Date: 2011-01-11 desktop-files: cleanup desktop files installed by nemo In the 3.0 world, nemo doesn't have to install a hundred of desktop files, as it's just a regular application. Tweak the default desktop file to make it suitable for being the only one, and remove the others. M configure.in M data/Makefile.am D data/nemo-browser.desktop.in.in D data/nemo-computer.desktop.in.in D data/nemo-folder-handler.desktop.in.in D data/nemo-home.desktop.in.in M data/nemo.desktop.in.in M po/POTFILES.in M src/Makefile.am D src/network-scheme.desktop.in commit f2533adf30822d3839b67c5f81e410b5e212f7a7 Author: Maciej Piechotka Date: 2011-01-11 Fix handling of AM_CONDITIONAL M configure.in commit 395ba0fd8f679e6e2674eb0ce5976638edb9d979 Author: Cosimo Cecchi Date: 2011-01-11 window: remove unused and confusing code M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 48ac967bff48e7e4a38c96859ebfd2f522179fa3 Author: Cosimo Cecchi Date: 2011-01-11 desktop-window: implement the right method for setting window title https://bugzilla.gnome.org/show_bug.cgi?id=555425 M src/nemo-desktop-window.c commit f9cb9e158b365ef3d1ed27cfa0ae138f367bd42a Author: Cosimo Cecchi Date: 2011-01-11 i18n: update POTFILES.in M po/POTFILES.in commit 9367d11d3a00d5192174f744eeea9e395fcd501a Merge: 6430fd4 b13efe1 Author: Cosimo Cecchi Date: 2011-01-11 Merge branch 'refactor' commit b13efe1653ea1932bba8c3f3555729d34a21412c Author: Cosimo Cecchi Date: 2011-01-11 empty-view: fix it to make it work again with current architecture M src/Makefile.am M src/nemo-application.c M src/nemo-empty-view.c M src/nemo-empty-view.h commit d5c9bae1381cb1f322d5ee3e0efbb27e06154574 Author: Cosimo Cecchi Date: 2011-01-11 Move other files away from src/file-manager M configure.in M src/Makefile.am D src/file-manager/Makefile.am R100 src/file-manager/nemo-desktop-icon-view-ui.xml src/nemo-desktop-icon-view-ui.xml R100 src/file-manager/nemo-directory-view-ui.xml src/nemo-directory-view-ui.xml R100 src/file-manager/fm-empty-view.c src/nemo-empty-view.c R100 src/file-manager/fm-empty-view.h src/nemo-empty-view.h R100 src/file-manager/nemo-icon-view-ui.xml src/nemo-icon-view-ui.xml R100 src/file-manager/nemo-list-view-ui.xml src/nemo-list-view-ui.xml commit 70b1acf6b0d4ef68903445d4198e78c5ea4807e5 Author: Cosimo Cecchi Date: 2011-01-11 Finish renaming fm_* -> nemo_* M src/nemo-actions.h M src/nemo-desktop-icon-view.c M src/nemo-desktop-item-properties.c M src/nemo-desktop-item-properties.h M src/nemo-error-reporting.c M src/nemo-error-reporting.h M src/nemo-icon-view.c M src/nemo-list-view.c M src/nemo-properties-window.c M src/nemo-view.c commit e0538b42e65601d9ebee5beffaefebb3e425672e Author: Cosimo Cecchi Date: 2011-01-11 properties-window: move FMPropertiesWindow to NemoPropertiesWindow M src/Makefile.am M src/file-manager/Makefile.am D src/file-manager/fm-properties-window.h R099 src/file-manager/fm-ditem-page.c src/nemo-desktop-item-properties.c R100 src/file-manager/fm-ditem-page.h src/nemo-desktop-item-properties.h R093 src/file-manager/fm-properties-window.c src/nemo-properties-window.c A src/nemo-properties-window.h M src/nemo-tree-sidebar.c M src/nemo-view.c commit 690909b8eb0b346d76b28da03c9228494e700db6 Author: Cosimo Cecchi Date: 2011-01-11 Rename FMListModel/View -> NemoListModel/View And move them outside of src/file-manager M src/Makefile.am M src/file-manager/Makefile.am D src/file-manager/fm-list-model.h M src/nemo-application.c R072 src/file-manager/fm-list-model.c src/nemo-list-model.c A src/nemo-list-model.h R100 src/file-manager/fm-list-view-private.h src/nemo-list-view-private.h R080 src/file-manager/fm-list-view.c src/nemo-list-view.c R052 src/file-manager/fm-list-view.h src/nemo-list-view.h M src/nemo-view.c commit 757a5acffc9e4ac7bdbd0dcfb5eaa1f64da8a471 Author: Cosimo Cecchi Date: 2011-01-11 icon-view-container: rename FMIconContainer -> NemoIconViewContainer M src/nemo-desktop-icon-view.c M src/nemo-icon-view-container.c M src/nemo-icon-view-container.h M src/nemo-icon-view.c commit ba4c8ef658f4f3e9e46d6cae12d84f06cf0a14b2 Author: Cosimo Cecchi Date: 2011-01-11 desktop-icon-view: rename FMDesktopIconView -> NemoDesktopIconView M src/nemo-application.c M src/nemo-desktop-icon-view.c M src/nemo-desktop-icon-view.h M src/nemo-icon-view.c M src/nemo-view-dnd.c M src/nemo-view.c commit bb124418d4c131b03772acc64be3acf91903e9fb Author: Cosimo Cecchi Date: 2011-01-11 icon-view: rename FMIconView -> NemoIconView M src/nemo-application.c M src/nemo-desktop-icon-view.c M src/nemo-desktop-icon-view.h M src/nemo-icon-view-container.c M src/nemo-icon-view-container.h M src/nemo-icon-view.c M src/nemo-icon-view.h commit b20ff7a5cd1d9304c5716433de1958faedccefde Author: Cosimo Cecchi Date: 2011-01-11 Move icon views outside of src/file-manager Part of the final step towards removing src/file-manager completely; only code shuffling around, not any real code change. M src/Makefile.am M src/file-manager/Makefile.am D src/file-manager/fm-actions.h M src/file-manager/fm-list-view.c M src/file-manager/fm-properties-window.c M src/nemo-actions.h M src/nemo-application.c R100 src/file-manager/nemo-audio-mime-types.h src/nemo-audio-mime-types.h R099 src/file-manager/fm-desktop-icon-view.c src/nemo-desktop-icon-view.c R098 src/file-manager/fm-desktop-icon-view.h src/nemo-desktop-icon-view.h R099 src/file-manager/fm-error-reporting.c src/nemo-error-reporting.c R100 src/file-manager/fm-error-reporting.h src/nemo-error-reporting.h R099 src/file-manager/fm-icon-container.c src/nemo-icon-view-container.c R098 src/file-manager/fm-icon-container.h src/nemo-icon-view-container.h R099 src/file-manager/fm-icon-view.c src/nemo-icon-view.c R100 src/file-manager/fm-icon-view.h src/nemo-icon-view.h M src/nemo-view-dnd.c M src/nemo-view.c commit e1ca0591f0588d114249361c624f467126b323c9 Author: Cosimo Cecchi Date: 2011-01-11 view: drop FMDirectoryView name Big code rename/indent fix, no actual code change here. M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-container.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-icon-view.h M src/file-manager/fm-list-view.c M src/file-manager/fm-list-view.h M src/nemo-view-dnd.c M src/nemo-view.c M src/nemo-view.h commit 00578e62066c1c5dadf4a0080dcb56c215334619 Author: Cosimo Cecchi Date: 2011-01-01 view: remove useless virtual method M src/nemo-view.c M src/nemo-view.h commit 8d726bab91c50d42edcb7e9a0e4107b6b0277ade Author: Cosimo Cecchi Date: 2011-01-01 view: move icon-view-only preferences to FMIconView Instead of using virtual methods M src/file-manager/fm-icon-view.c M src/nemo-view.c M src/nemo-view.h commit 9ab314c1dd30dc2d30fc46a62e2d31059c4c340a Author: Cosimo Cecchi Date: 2010-12-31 view: remove emblems_changed code This hack should not be required anymore now that we don't have user emblems. Other emblems should be taken care of by the normal NemoFile's changed signal. M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-view.c M src/nemo-view.h commit d7de8e23fbe75e4a6ecbaf729affc9cbab9e08a3 Author: Cosimo Cecchi Date: 2010-12-31 signaller: remove unused emblems-changed signal M libnemo-private/nemo-signaller.c commit 5e57025a405e4ccbdd7a4ff51fa48d7eb4fb3671 Author: Cosimo Cecchi Date: 2010-12-31 view: remove useless virtual methods No need for some internal methods to be virtual if they're never overridden. Also, some of this code does nothing. M src/file-manager/fm-icon-container.c M src/nemo-view.c M src/nemo-view.h commit 9b29835c04fcaae84760a328a6cc70705c214506 Author: Cosimo Cecchi Date: 2010-12-31 places-sidebar: remove "Format..." action code M src/nemo-places-sidebar.c commit e4975471d233f1217bca48fae17519a285336645 Author: Cosimo Cecchi Date: 2010-12-31 view: remove commented out "Format..." action code M src/file-manager/fm-actions.h M src/file-manager/nemo-directory-view-ui.xml M src/nemo-view.c commit d0985e6d5ed7f6732bb4ee4b836192852adface2 Author: Cosimo Cecchi Date: 2010-12-31 view: remove unused flush_added_files signal M src/file-manager/fm-icon-view.c M src/nemo-view.c M src/nemo-view.h commit 7a4af383a2cb0e0257213e0e21f62e6cc82a7e58 Author: Cosimo Cecchi Date: 2010-12-31 view: don't check for allow_moves in the view superclass The property is only used by the icon view, so it's better to move the check there. M src/file-manager/fm-icon-view.c M src/nemo-view.c M src/nemo-view.h commit be2d9bba9864f2834a57b608d47140f1e20eca66 Author: Cosimo Cecchi Date: 2010-12-29 view: make nemo_view_load_location() consistent with its name M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c commit 69c2c9f8c5855a7993f23998cff3ce3eab87fd45 Author: Cosimo Cecchi Date: 2010-12-29 view: use NemoFile objects for the view selection Use them in a consistent way, so to cleanup the previous GFile/NemoFile confusion. M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-spatial-window.c M src/nemo-trash-bar.c M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit eb178062ec31bf6a877e5bc61f697f85a3f927fe Author: Cosimo Cecchi Date: 2010-12-29 spatial-window: don't unref the main loop we're about to destroy M src/nemo-spatial-window.c commit ac1fbbba66c61d61c4469949b925862fa3c6600b Author: Cosimo Cecchi Date: 2010-12-29 window: remove unused code M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 57c8b0416135ee3b5c1315b3419269d20ced233c Author: Cosimo Cecchi Date: 2010-12-29 view: split DnD code into its own module And use new method names in other classes M src/Makefile.am M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c A src/nemo-view-dnd.c A src/nemo-view-dnd.h M src/nemo-view.c M src/nemo-view.h M src/nemo-window-slot-dnd.c commit 1f734cce8b243e2c1c1fd40491ab4e38c0eb65cd Author: Cosimo Cecchi Date: 2010-12-29 view: reduce visibility of some methods No need for them to stay public. Remove some useless prototypes and reorder virtual methods, while we're at it. M src/file-manager/fm-icon-view.c M src/nemo-view.c M src/nemo-view.h commit 4c20fa07d8a587ebe8de820a0206aa8a75edc5d8 Author: Cosimo Cecchi Date: 2010-12-29 window: remove nemo_window_get_selection[_count] No need to duplicate selection handling between view and window. M src/nemo-trash-bar.c M src/nemo-trash-bar.h M src/nemo-view.c M src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window.c M src/nemo-window.h commit dedd9e11ec6ff499b82bdb7a9b9bde7927066560 Author: Cosimo Cecchi Date: 2010-12-29 Rework architecture of NemoView/FMDirectoryView As a second step after ff5c759b3784db2d0cd71e1cde613dda007c3985, this removes the NemoView/FMDirectoryView interface split, changing FMDirectoryView to be NemoView directly. Left to do: complete renaming the public fm_directory_view methods to nemo_view, and get rid of src/file-manager entirely. M libnemo-private/Makefile.am M libnemo-private/nemo-dnd.c D libnemo-private/nemo-view.c D libnemo-private/nemo-view.h M src/Makefile.am M src/file-manager/Makefile.am M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-icon-view.h M src/file-manager/fm-list-view.c M src/file-manager/fm-list-view.h M src/nemo-trash-bar.c M src/nemo-view-factory.h R098 src/file-manager/fm-directory-view.c src/nemo-view.c R087 src/file-manager/fm-directory-view.h src/nemo-view.h M src/nemo-window-manage-views.c M src/nemo-window-pane.h M src/nemo-window-slot.c M src/nemo-window-slot.h A src/nemo-window-types.h M src/nemo-window.h M src/nemo-x-content-bar.c commit 10998fbf14029163d3669f1e2a9f1676b02e7d09 Author: Cosimo Cecchi Date: 2010-12-28 main: remove unneeded code M src/nemo-main.c commit 79ef5be141a55ccce67daf42b73aa0a4affa7a13 Author: Cosimo Cecchi Date: 2010-12-28 window-slot: trivial cleanups M src/nemo-window-manage-views.c M src/nemo-window-slot.c commit acf3e032099dc2f7a156e755edb23a3dd8305fc8 Author: Cosimo Cecchi Date: 2010-12-28 window-slot: rename get_current_location -> get_current_uri M src/file-manager/fm-directory-view.c M src/nemo-places-sidebar.c M src/nemo-tree-sidebar.c M src/nemo-window-slot-dnd.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit 977fc6383dc74a320ce951d4d0b2f81f31e9cdcf Author: Cosimo Cecchi Date: 2010-12-27 window: cleanup nemo_window_reload() M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window.c M src/nemo-window.h commit ab75e5447ca5a5a5d7054c907d008816ad911c20 Author: Cosimo Cecchi Date: 2010-12-26 navigation-action: cleanup M src/nemo-navigation-action.c commit 2807b8884acab27de359a4ab51b9b57e8fb86a0f Author: Cosimo Cecchi Date: 2010-12-26 window: remove useless snippets M src/nemo-navigation-window.c commit b1011eced7e561b05dca2aa6345d3c5b3225610e Author: Cosimo Cecchi Date: 2010-12-23 window: remove useless method calls nemo_window_slot_set_content_view_widget() is called afterwards, which in turn calls again _disconnect_view() M src/nemo-window-manage-views.c commit d166f04b8886687df6f03d0e03ec16c887f9842b Author: Cosimo Cecchi Date: 2010-12-23 window: remove non existent function declaration M src/nemo-window.h commit 6ff03b33b724d882cfabb67b1f1fb4e8287e932f Author: Cosimo Cecchi Date: 2010-12-22 window: cleanup nemo_window_allow_reload() M src/nemo-window.c M src/nemo-window.h commit 553edbfbaf7e4fc171453634aa41006d49533da2 Author: Cosimo Cecchi Date: 2010-12-21 window: cleanup nemo_window_go_up() M src/nemo-window-manage-views.c M src/nemo-window-menus.c M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 558e394a8dfba5f1c92423ac45c6462461720199 Author: Cosimo Cecchi Date: 2010-12-21 window: cleanup nemo_window_go_home() M src/nemo-navigation-window-menus.c M src/nemo-window.c M src/nemo-window.h commit d9ce97b0501cb3006013080ed688aa25649a31f6 Author: Cosimo Cecchi Date: 2010-12-21 window-slot: remove commented out code M src/nemo-window-manage-views.c M src/nemo-window-slot.h commit a8d0c04c154ee8458fd5fd24091de1a8c92a6da4 Author: Cosimo Cecchi Date: 2010-12-21 window-slot: cleanup connect/disconnect_view() M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c commit 307e0edbe7457a70f4a61acdfecb1ae38d8c243b Author: Cosimo Cecchi Date: 2010-12-21 window-slot: cleanup of window_slot_open_location() functions M src/file-manager/fm-directory-view.c M src/nemo-mime-actions.c M src/nemo-navigation-window-pane.c M src/nemo-places-sidebar.c M src/nemo-spatial-window.c M src/nemo-tree-sidebar.c M src/nemo-window-manage-views.c M src/nemo-window-slot.h M src/nemo-window.c commit cfdf80763ef3f7f3f88239fdba27ce01b642ab32 Author: Cosimo Cecchi Date: 2010-12-21 window-slot: remove nemo_window_slot_open_location() It's unused. M src/nemo-window-manage-views.c M src/nemo-window-slot.h commit ad0d377ac236392a9ccaeae789e07e1af4a796e5 Author: Cosimo Cecchi Date: 2010-12-21 Rework architecture of NemoWindow/NemoWindowSlotInfo In the past, nemo was designed keeping in mind the concept that it might not just be a file browser, but a sort of platform to embed various kind of views in it. - libnemo-private: general lowlevel items, such as the icon container, NemoFile, I/O and so on - src: general widgets and UI items - src/file-manager: file manager views, agnostic of what's in src/, for the sake of being pluggable enough This is really not applicable anymore, as nemo won't go in any direction other than being a file manager; at the same time, this complicates code and architecture quite a lot. In this commit, as a first step towards a more clean codebase, we remove the NemoWindowInfo and NemoWindowSlotInfo interfaces, using NemoWindow and NemoWindowSlot directly. Note that there should be no actual code changes, only moving of pieces around. M libnemo-private/Makefile.am M libnemo-private/nemo-dnd.c M libnemo-private/nemo-dnd.h D libnemo-private/nemo-window-info.c D libnemo-private/nemo-window-info.h D libnemo-private/nemo-window-slot-info.c D libnemo-private/nemo-window-slot-info.h M src/Makefile.am M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-application.h M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog-main.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-connect-server-dialog.c M src/nemo-connect-server-dialog.h M src/nemo-location-bar.c M src/nemo-mime-actions.c M src/nemo-mime-actions.h M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-places-sidebar.c M src/nemo-places-sidebar.h M src/nemo-query-editor.h M src/nemo-spatial-window.c M src/nemo-trash-bar.c M src/nemo-tree-sidebar.c M src/nemo-tree-sidebar.h M src/nemo-view-as-action.c R098 libnemo-private/nemo-view-factory.c src/nemo-view-factory.c R094 libnemo-private/nemo-view-factory.h src/nemo-view-factory.h M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window-slot-dnd.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 4c031a4794126af08cea1774dd7ec3904d0ad25e Author: Cosimo Cecchi Date: 2010-12-21 mime-actions: move nemo-mime-actions to src/ M libnemo-private/Makefile.am M libnemo-private/nemo-program-choosing.c M src/Makefile.am M src/file-manager/Makefile.am M src/file-manager/fm-directory-view.c M src/file-manager/fm-properties-window.c R099 libnemo-private/nemo-mime-actions.c src/nemo-mime-actions.c R100 libnemo-private/nemo-mime-actions.h src/nemo-mime-actions.h M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-manage-views.c M src/nemo-window.c commit 97e67f49279ad87737541249ef09b99c4bc1d9fe Author: Cosimo Cecchi Date: 2010-12-21 dnd: move DnD slot proxying code to src/ M libnemo-private/nemo-dnd.c M libnemo-private/nemo-dnd.h M src/Makefile.am M src/nemo-notebook.c M src/nemo-pathbar.c A src/nemo-window-slot-dnd.c A src/nemo-window-slot-dnd.h commit 6430fd4a7435336a61000e2255621fb0023252d1 Author: Ivar Smolin Date: 2011-01-11 [l10n] Updated Estonian translation M po/et.po commit 63724239779c6f5f4dcb76ebde7f66f691a75786 Author: Andika Triwidada Date: 2011-01-11 Updated Indonesian translation M po/id.po commit 9022942dce517bc0fe52fdb769f6950c0aa5c444 Author: Ivar Smolin Date: 2011-01-10 [l10n] Updated Estonian translation M po/et.po commit cd976fa26099fb8c1f2084a6bae7ac0b05f5e29e Author: Cosimo Cecchi Date: 2011-01-10 Release 2.91.7 M NEWS M configure.in M po/POTFILES.in commit f6d4eed031e94570151cb4599e93d92b4612d53b Author: Cosimo Cecchi Date: 2011-01-10 debug: fix build without debugging support (#639107) M configure.in M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h M src/nemo-main.c commit ac168820fbb4db7fbdf243a0d6b118ce445cdf37 Author: Cosimo Cecchi Date: 2011-01-10 file-operations: make Create Document/Folder use the right template Make Create Document/Folder use "Untitled Document/Template/Folder %d" filename format. Based on a patch by Marcus Husar . M libnemo-private/nemo-file-operations.c commit 5846b33c5cd26ec3fe50255c628954d129c8ffc0 Author: Marcus Husar Date: 2011-01-10 Clean context menu and "File" menu (#618469) Also use "Create New Folder/Document". Part of https://bugzilla.gnome.org/show_bug.cgi?id=618469 M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml M src/nemo-tree-sidebar.c commit 0ff4fdb4c8228a358d3a0bc87b63b02751624716 Author: Fran Diéguez Date: 2011-01-10 Updated Galician translations M po/gl.po commit 8f9bb67e39a9d32be051416a474c3142539f7c3f Author: Sjoerd Simons Date: 2010-12-05 Add base libraries so building with --as-needed works M nemo-sendto-extension/Makefile.am commit 179b688c5938ba12e101a0231ba46199d2de4a5e Author: Cosimo Cecchi Date: 2011-01-10 window: remove unused code M src/nemo-window-private.h M src/nemo-window.c commit b12aeed547664d44b0b552db06a5ec7b6d9b200b Author: Cosimo Cecchi Date: 2011-01-10 bookmark: compare URIs before names M libnemo-private/nemo-bookmark.c commit 120797cec00929dac58ac4ac838719dc67e9cae0 Author: Cosimo Cecchi Date: 2011-01-10 Use a consistent name for the Home folder (#341894) Based on a patchset by Marcus Husar M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-desktop-link.c M src/file-manager/fm-directory-view.c M src/nemo-places-sidebar.c M src/nemo-tree-sidebar.c M src/nemo-window-menus.c M src/nemo-window-slot.c commit 50e0c03f67072e374f8202ba7a25221fa7f88b99 Author: Fran Diéguez Date: 2011-01-09 Updated Galician translations M po/gl.po commit 598ede33ab781b46120d2149c37f47fcb7615ca2 Author: Yuri Myasoedov Date: 2011-01-09 Updated Russian translation M po/ru.po commit cd2a6e35c5757c7ca817aeef415873d2d4d8baee Author: Matej UrbanÄiÄ Date: 2011-01-07 Updated Slovenian translation M po/sl.po commit d51bc0c99b0ca6e8bc402b7ae5848e9ced2dab46 Author: Ivar Smolin Date: 2011-01-06 [l10n] Updated Estonian translation M po/et.po commit 3ff059dcc1b76a7cde6d7111b9620d373c18b9a8 Author: Yaron Shahrabani Date: 2011-01-04 Updated Hebrew translation. M po/he.po commit f8f87d8cca0a9aa54d5a1290576eb0855098ffda Author: Ivar Smolin Date: 2011-01-02 [l10n] Updated Estonian translation M po/et.po commit 61476e9e0a776e1db74f73db1b3fa9291d997a83 Author: Daniel Nylander Date: 2010-12-29 Updated Swedish translation M po/sv.po commit 09cb61a5cc2b9e5f7b85ae619d2cc2d06bf5ef06 Author: Daniel Mustieles Date: 2010-12-29 Updated Spanish translation M po/es.po commit 811f49d1e0981f7414a57004a7fd0df95f64dfd8 Author: A S Alam Date: 2010-12-29 update Punjabi Translation M po/pa.po commit ddd507228a8a7a89c0398411f44d30e6ee9d73ed Author: Cosimo Cecchi Date: 2010-12-28 pathbar: remove buttons only if the gone file is below the current This should fix once and for all the crashers when ejecting devices. M src/nemo-pathbar.c commit 70df8fad8b1ddf470e8600f6e8e9bc953853b419 Author: Cosimo Cecchi Date: 2010-12-26 desktop-icon-view: don't use deprecated GDK grab API M src/file-manager/fm-desktop-icon-view.c commit bd151c8174796c1c5b0b6466ef8a0e3a0e214054 Author: Cosimo Cecchi Date: 2010-12-26 general: don't use deprecated gdk_app_launch_context_new() M eel/eel-gnome-extensions.c M eel/eel-gnome-extensions.h M libnemo-private/nemo-program-choosing.c M src/nemo-connect-server-dialog-main.c commit 2ff006dd583f58ff2dd687f538e59757a8bd70c4 Author: Cosimo Cecchi Date: 2010-12-26 canvas: don't use deprecated GDK grab API M eel/eel-canvas.c M eel/eel-canvas.h commit 7fa4d2202358940ef5a0dd70eb88996ac371cffd Author: Gheyret T.Kenji Date: 2010-12-23 Added UG translation M po/ug.po commit aac9a486cb310c62d1167cfe37118a70d772d41e Author: Erdal Ronahi Date: 2010-12-23 Updated Kurdish translations M po/ku.po commit 318a9bd653fb02a7c94e42139377cef5ed254dd2 Author: Cosimo Cecchi Date: 2010-12-22 Release 2.91.6 M NEWS M configure.in commit b569d2cfa31951f67229e3aab00cd7f33c1ff3db Author: Cosimo Cecchi Date: 2010-12-22 general: use nemo_launch_application instead of gdk_spawn API M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/nemo-tree-sidebar.c M src/nemo-window-menus.c commit 77ecdd69b023a16fc4d6d2895dd470c628679168 Author: Cosimo Cecchi Date: 2010-12-22 program-choosing: don't use gdk_spawn_ API M libnemo-private/nemo-program-choosing.c M libnemo-private/nemo-program-choosing.h commit 13b6a5a50db8dd35dbcbbf1d318ba747609dfb70 Author: Cosimo Cecchi Date: 2010-12-22 eel: don't use gdk_spawn_ API M eel/eel-gnome-extensions.c commit 74a8f78e2a5b06485c7daf830372a5f7b15a87b8 Author: Cosimo Cecchi Date: 2010-12-22 general: don't use gdk_cursor_unref() M eel/eel-editable-label.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M src/file-manager/fm-list-view.c M src/file-manager/fm-properties-window.c M src/nemo-window.c commit 2737d431e44e3e4dc12e9098b6e17881ca28c1f7 Author: Wouter Bolsterlee Date: 2010-12-22 Updated Dutch translation by Wouter Bolsterlee M po/nl.po commit 08462d0f0235274f1b6c2b12df47e27932b343ee Author: Cosimo Cecchi Date: 2010-12-20 Release 2.91.5 M NEWS M configure.in commit f42d5aa97de09de7052fa80abda62fabe17dfb13 Author: Cosimo Cecchi Date: 2010-12-20 smclient: remove XSMP support EggSmClient is not well-maintained, and it doesn't seem like it will ever hit GTK+, and the overall implementation seems to be poorly tested and buggy. Moreover, moving to 3.0 with nemo being an application, it makes less sense to have it save opened windows state, as it might not be always running at all. M cut-n-paste-code/libegg/Makefile.am D cut-n-paste-code/libegg/eggdesktopfile.c D cut-n-paste-code/libegg/eggdesktopfile.h D cut-n-paste-code/libegg/eggsmclient-private.h D cut-n-paste-code/libegg/eggsmclient-xsmp.c D cut-n-paste-code/libegg/eggsmclient.c D cut-n-paste-code/libegg/eggsmclient.h M po/POTFILES.in M src/Makefile.am D src/nemo-application-smclient.c D src/nemo-application-smclient.h M src/nemo-application.c M src/nemo-application.h M src/nemo-main.c commit ee06a67a632476b9758cc00eaa573e12cc3cfc91 Author: Cosimo Cecchi Date: 2010-12-20 mime-app-chooser: use g_app_info_set_as_last_used_for_content_type() Instead of add_supports_for_content_type(), which does not save the order in which custom apps have been used. M configure.in M libnemo-private/nemo-mime-application-chooser.c commit b31222dae4c63479e0fe226a761f9c78bf08b6df Author: Cosimo Cecchi Date: 2010-12-20 mime: remove some useless code As GtkAppChooserDialog already takes care of calling g_app_info_set_as_last_used_for_content_type() M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-directory-view.c commit 2c279a4a6b3480bfd3581a3a35c53eac3e996653 Author: Ivar Smolin Date: 2010-12-20 [l10n] Updated Estonian translation M po/et.po commit 3fa0ed2ca3e35719422fbc526337b52393d860d2 Author: Kjartan Maraas Date: 2010-12-19 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 9dc65e44c9f8e6c41079c0dc01220fe87fdfcecc Author: Nguyá»…n Thái Ngá»c Duy Date: 2010-12-19 po/vi.po: import some translations from Ubuntu/Maverick M po/vi.po commit dd4cecdf8071552f80ba08fdb613a88090719e59 Author: Yaron Shahrabani Date: 2010-12-19 Updated Hebrew translation. M po/he.po commit fcfe53d5bd2121e4707e70345f18faa244c2dd75 Author: Cosimo Cecchi Date: 2010-12-18 Remove reference to a non-existing old trademark notice file. https://bugzilla.gnome.org/show_bug.cgi?id=463173 M COPYING commit 196c8390fcc671ef8399c00936ac7242b118de08 Author: Jorge González Date: 2010-12-18 Updated Spanish translation M po/es.po commit 83aeec725d0d3829a54cd700329864a2cab7a21b Author: Marcus Carlson Date: 2009-10-11 Handle G_IO_ERROR_FILENAME_TOO_LONG errors nicely when renaming files https://bugzilla.gnome.org/show_bug.cgi?id=548844 M src/file-manager/fm-error-reporting.c commit 9403df1b54b442737ed96739aeacf6b6c9b58889 Author: Colin Walters Date: 2010-12-17 Fix cairo-gobject.h include $ pkg-config --cflags cairo-gobject -pthread -I/src/build/jhbuild/include/cairo $ ls /src/build/jhbuild/include/cairo/cairo-gobject.h /src/build/jhbuild/include/cairo/cairo-gobject.h M eel/eel-canvas.c commit b2d4ac40205e22e63e598ab742b56283acbc8901 Author: Colin Walters Date: 2010-12-17 nemo.desktop: Remove NoDisplay=true For GNOME 3, File Manager is moving towards being an application, and therefore, we want it to show up in the appliactions list. M data/nemo.desktop.in.in commit 67d0cbaf0ed7a8f25b3a47abbbaf0feba990e404 Author: Cosimo Cecchi Date: 2010-12-17 location-entry: don't treat '~' as a relative path Based on a patch by Reed Lipman https://bugzilla.gnome.org/show_bug.cgi?id=628802 M src/nemo-location-entry.c commit 184096f912b119edde1f538e8cdd5ea593d753ca Author: Cosimo Cecchi Date: 2010-12-17 icon-canvas-item: attempt to fix up a11y for NemoIconCanvasItem Based on an initial patch by Alban Browaeys . https://bugzilla.gnome.org/show_bug.cgi?id=637425 M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c commit 42865d5e82160ccb60fd9a890a22019dcb832527 Author: Alban Browaeys Date: 2010-10-27 icon-container: remove spurious call to gtk_adjustment_changed() https://bugzilla.gnome.org/show_bug.cgi?id=637424 M libnemo-private/nemo-icon-container.c commit bc5b8bde3070a4fe6071c9a428d38fa93be19314 Author: Jorge González Date: 2010-12-15 Updated Spanish translation M po/es.po commit 1746a53cbbd450822ff857c3e1eadf5358b22cfa Author: Cosimo Cecchi Date: 2010-12-15 application: fix a copy-paste typo M src/nemo-application.c commit 08f71aa76cd5f250613f4a2833b43a72831974fc Author: Cosimo Cecchi Date: 2010-12-15 theming: cleanup previous manually parsed CSS It's not required anymore, now that we have a proper stylesheet. M src/nemo-notebook.c M src/nemo-window.c commit 786ba61680bfaee136b4b72a53f220edb96a7db9 Author: Cosimo Cecchi Date: 2010-12-15 sidebar: set the NemoSidebar class on the sidebar treeviews So they can get the proper background. M src/nemo-places-sidebar.c M src/nemo-tree-sidebar.c commit dad5d12770817aa739ab9980faa66972144008a7 Author: Cosimo Cecchi Date: 2010-12-15 theming: add a CSS file for nemo, and initialize it at startup M data/Makefile.am A data/nemo.css M src/nemo-application.c commit 1c79bf9809b208a57661aaccadd9eb7e78874bcc Author: Cosimo Cecchi Date: 2010-12-15 connect-server-dialog: properly align labels and entries https://bugzilla.gnome.org/show_bug.cgi?id=637326 M src/nemo-connect-server-dialog.c commit 0a43cee107e20d07667fc2eabf8321898ce80fb7 Author: Luca Ferretti Date: 2010-12-15 application: fix a typo in user message M src/nemo-application.c commit 4c026bf53253715251abf076badc4c979cc073c3 Author: Cosimo Cecchi Date: 2010-12-15 icon-container: don't malloc() GdkRGBA colors manually As GdkRGBA might or might not use internally a different allocator, like g_slice. This should fix some memory corruption issues, thanks to Alban Browaeys for tracking down the bug. M libnemo-private/nemo-icon-container.c commit c1d9376601223e5dcca0a4ee47e95a8b93841d68 Author: Cosimo Cecchi Date: 2010-12-14 spatial-window: don't hook to unrealize for saving geometry M src/nemo-spatial-window.c commit e4750d78c6be4f935625a3511dbb9c3bc532aa0d Author: Cosimo Cecchi Date: 2010-12-14 desktop-icon-view: call the gnome-c-c executable to change background gnome-appearance-properties does not exist anymore. M src/file-manager/fm-desktop-icon-view.c commit 5d811bb37ef4a05edd7fa4c5868a9b68f717e056 Author: Cosimo Cecchi Date: 2010-12-14 icon-dnd: set the right style class, and use GdkRGBA M libnemo-private/nemo-icon-dnd.c commit 18e3369f02c4ff6a3eb01048e623fff8eb9aded4 Author: Cosimo Cecchi Date: 2010-12-14 tree-drag-dest: set the right style class M libnemo-private/nemo-tree-view-drag-dest.c commit 066896047e8d53076913994f9975ee1cb22fbd9d Author: Cosimo Cecchi Date: 2010-12-14 icon-canvas-item: set the right style class M libnemo-private/nemo-icon-canvas-item.c commit ef8544bec8437502f2f58c7a9e07bc9e1ecf91a4 Author: Cosimo Cecchi Date: 2010-12-13 editable-label: use gtk_style_context_get() to query standard props Also, fix a leak. M eel/eel-editable-label.c commit dccf76a36441332e96c40305373876ca32a1b110 Author: Cosimo Cecchi Date: 2010-12-13 preferences: remove exit-with-last-window preference entirely It makes no sense now that nemo doesn't do session services, such as autorun, anymore. M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo.convert M libnemo-private/org.gnome.nemo.gschema.xml.in commit 9ef4ac9ee428e7f7952efe33d0784d547ca7bdc6 Author: Cosimo Cecchi Date: 2010-12-13 application: remove 'exit-with-last-window' preference It makes no sense now that nemo doesn't do session services such as autorun anymore. M src/nemo-application.c commit 00e0ae826765aeca4c203b77a5caec4ce2be2fd7 Author: Cosimo Cecchi Date: 2010-12-13 application: destroy all the widgets when quitting Instead of calling _release(). M src/nemo-application.c commit caa55b7e757a49fb323450152e6a37e1d63eb9fb Author: Cosimo Cecchi Date: 2010-12-13 editable-label: rename copy/pasted fill renderer to 'eel' prefix To avoid library clashes with the GTK+ internal one. M eel/eel-editable-label.c commit f27c50fb25fee58b9eee6c9edfd26101684eec52 Author: Jorge González Date: 2010-12-11 Updated Spanish translation M po/es.po commit f5acdfefc39b235fd1eb9b3bdd3a724cdaa1a7fe Author: Fran Diéguez Date: 2010-12-11 Updated Galician translations M po/gl.po commit c0645b53892c1f65b9258e5cc63b701dbcbacfe7 Author: Fran Diéguez Date: 2010-12-10 Updated Galician translations M po/gl.po commit eea53d2f740ac25a13eea13baa83ecb493fa24cc Author: Cosimo Cecchi Date: 2010-12-07 file: initialize variables to stop complaints from compilers (#636643) M libnemo-private/nemo-file.c commit def31cd34118e4a3daf53819f81a5d7325b8efcb Author: Cosimo Cecchi Date: 2010-12-07 Release 2.91.4 M NEWS M configure.in commit bb68641adf3306675f3b259d0197ef74ecc9ccc0 Author: Cosimo Cecchi Date: 2010-12-07 dbus-manager: plug a leak M libnemo-private/nemo-dbus-manager.c commit 7686ba98e4283383f4e0b0146cbc693d041c5697 Author: Cosimo Cecchi Date: 2010-12-07 icon-container: plug a leak M src/file-manager/fm-icon-container.c commit 705d8144e5509d7926adec8af3d638b2e88fd837 Author: Cosimo Cecchi Date: 2010-12-07 icon-info: plug a leak M libnemo-private/nemo-icon-info.c commit 55869c3c65217f1c4386cf489f391eeb519e797d Author: Yaron Shahrabani Date: 2010-12-07 Updated Hebrew translation. M po/he.po commit ee0c6327eeaeaa0a924007cf3b56d2cd63dbe36b Author: Daniel Șerbănescu Date: 2010-12-06 Updated Romanian translation M po/ro.po commit 68a3a22297875118797eacb03ff5278024642366 Author: Daniel Șerbănescu Date: 2010-12-06 Updated Romanian translation M po/ro.po commit cb70787275e2e44cc2f3b394d1065313998fd1a3 Author: Cosimo Cecchi Date: 2010-12-06 file-operations: remove duplicate code Probably a leftover from NemoFileConflictDialog branch. M libnemo-private/nemo-file-operations.c commit c739fd781c355e47e4ef3f59e9e4008c230e83ad Author: Cosimo Cecchi Date: 2010-12-06 dbus-manager: add a 'CopyFile' remote method The interface mimics the nemo_file_operations_copy_file() I just committed. M libnemo-private/nemo-dbus-manager.c commit 4be5d548a438b2b3c02f3e7e7e0265f4c8b641fe Author: Cosimo Cecchi Date: 2010-12-06 file-operations: add nemo_file_operations_copy_file Copies a single file to a target directory, allowing to specify a custom target display name, and a custom source display name, which will be shown in the FileOperations dialog instead of the actual file name. M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-operations.h commit 52b8185908725ba9842f3d2ce8c29d7b7e3d520f Author: Cosimo Cecchi Date: 2010-12-06 file-conflict-dialog: don't use override_font Set the PangoAttributeList on the GtkLabel instead. M libnemo-private/nemo-file-conflict-dialog.c commit e3feaf8d6848a92e3d077d04177e7a637b6e628b Author: Cosimo Cecchi Date: 2010-12-06 editable-label: make the rename rectangle look a bit better Still not perfect, but still... M eel/eel-editable-label.c commit 2e5f7a23350016c67bb9e9cca86a9fb2360d79e2 Author: Cosimo Cecchi Date: 2010-12-06 icon-container: fix rendering of text on the desktop M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c commit ca9f8d8906b85a4f806d713030d02efc34fd7170 Author: Cosimo Cecchi Date: 2010-12-06 editable-label: copy-paste code from GTK+ to sync drawing with GtkLabel M eel/eel-editable-label.c commit 465f576edaf1c8b952ec152884d55db985f10778 Author: Cosimo Cecchi Date: 2010-12-06 window: pkug a leak M src/nemo-window.c commit 1ee7fc84fe8232bfc57ba832642185b2829dcc8e Merge: 1c31b7a b5302eb Author: Cosimo Cecchi Date: 2010-12-06 Merge branch 'style-context' commit b5302ebfc104aec7cc480931ede752efe9cc4325 Author: Cosimo Cecchi Date: 2010-12-06 eel: remove unused code M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h M eel/eel-gtk-extensions.c M eel/eel-lib-self-check-functions.h commit 1d3dd9693de26d91d60ed7a11f6f14df8478f6a6 Author: Cosimo Cecchi Date: 2010-12-06 eel-gdk-extensions: port to GtkStyleContext M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 076886e9a45e8dce101f1d98eb5c4168c8ded311 Author: Cosimo Cecchi Date: 2010-12-06 window: port to GtkStyleContext M src/nemo-window.c commit 507b56e3a527e28117b259dbf0dce48f1656dd7d Author: Cosimo Cecchi Date: 2010-12-06 spatial-window: port to GtkStyleContext M src/nemo-spatial-window.c commit bc5d2904fd3338455579c77781c357fe85a86913 Author: Cosimo Cecchi Date: 2010-12-06 notebook: port to GtkStyleContext M src/nemo-notebook.c commit 5fc40adf98a384f4638401d7b7ced79da6ce2b87 Author: Cosimo Cecchi Date: 2010-12-06 location-bar: port to GtkStyleContext M src/nemo-location-bar.c commit 8e5689b5ff9fb1fedf2a1102f429f4f67e811e09 Author: Cosimo Cecchi Date: 2010-12-06 properties-window: port to GtkStyleContext M src/file-manager/fm-properties-window.c commit d7c576dbc1116139a29b7d263070283c47726ba2 Author: Cosimo Cecchi Date: 2010-12-06 list-view: port to GtkStyleContext Setting inactive pane doesn't work here yet, probably due to a bug in GTK+. M src/file-manager/fm-list-view.c commit f8bdf9c68ae156506d04f198e054e9488845c173 Author: Cosimo Cecchi Date: 2010-12-06 tree-view-drag-dest: port to GtkStyleContext M libnemo-private/nemo-tree-view-drag-dest.c commit 4f23a0a89b14757dc86459c399ff6a9719bb4e01 Author: Cosimo Cecchi Date: 2010-12-06 icon-container: port to GtkStyleContext M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-icon-private.h commit fc74332e3bbcc20094ab58631666b477640e2aeb Author: Cosimo Cecchi Date: 2010-12-06 icon-canvas-item: port to GtkStyleContext M libnemo-private/nemo-icon-canvas-item.c commit 5da941e338b159c42a4b4f2581573635e3d68b11 Author: Cosimo Cecchi Date: 2010-12-06 file-conflict-dialog: port to GtkStyleContext M libnemo-private/nemo-file-conflict-dialog.c commit 020adaf997cc63a2b78ccb21c34b7f7f5244008e Author: Cosimo Cecchi Date: 2010-12-06 eel-gdk-pixbuf: use GdkRGBA everywhere M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h M eel/eel-graphic-effects.c M eel/eel-graphic-effects.h commit d6e07c7803b3d70968e7a37bcf1ef730b8ca4bac Author: Cosimo Cecchi Date: 2010-12-06 editable-label: port to GtkStyleContext There are still some rendering artifacts, but we will fix them later. M eel/eel-editable-label.c commit 5cf60d2aa1e8fd9856aed886cce6bd746f4a8074 Author: Cosimo Cecchi Date: 2010-12-06 eel-canvas: build fix for gdk_window_get_geometry API change M eel/eel-canvas.c commit 0a3aff84fececf1cfce0969ac173a736d2014130 Author: Cosimo Cecchi Date: 2010-12-06 eel-canvas: port to GtkStyleContext M eel/eel-canvas.c M eel/eel-canvas.h commit f0691e71c58bba402d896f0a236e4bd10b6e5760 Author: Cosimo Cecchi Date: 2010-12-06 eel-canvas-re: use RGBA colors only M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas-rect-ellipse.h commit 1c31b7ab0d8ed7122f385395f6844006aa4a41e2 Author: Andre Klapper Date: 2010-12-06 Fix POTFILES.in to make intltool-update work again M po/POTFILES.in commit a68bf9c76a9073db3247e8dd1e92c0c1b3b98727 Author: Fran Diéguez Date: 2010-12-05 Updated Galician translations M po/gl.po commit 59670a59c9b53a59ef587767c3e7be247b0f11cf Author: Cosimo Cecchi Date: 2010-12-04 icon-container: apply emblems from FmIconContainer This simplifies the code a bit, and also fixes emblem sizes for thumbnails. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M src/file-manager/fm-icon-container.c commit 1004a7df4357fb2772ad4289b997b16ef799fc34 Author: Cosimo Cecchi Date: 2010-12-04 file: add some debug messages for getting icons M libnemo-private/nemo-file.c commit 55098c48a050a226fdb7168440fdbeb1a1fd5da0 Author: Cosimo Cecchi Date: 2010-12-04 debug: add a flag for NemoFile M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h commit b97bad42e62d7d13d257a7785fa1b91943a0758f Author: Cosimo Cecchi Date: 2010-12-04 file-management-properties: open only one preferences window (#442263) M src/nemo-file-management-properties.c M src/nemo-file-management-properties.h M src/nemo-window-menus.c commit 1c5794a5a520ea9bdfa3865b9db702f484cabfe0 Author: Cosimo Cecchi Date: 2010-12-04 settings: remove notes and history sidebar from GSettings schemas M libnemo-private/org.gnome.nemo.gschema.xml.in commit 69e432cf94d31f07cf1d193e1fd25a693cfdc173 Author: Cosimo Cecchi Date: 2010-12-03 navigation-window: plug a leak M src/nemo-navigation-window.c commit 1eac9e307787d773ac1598d79df965d5be684f38 Merge: 2a20b38 7bce748 Author: Cosimo Cecchi Date: 2010-12-03 Merge branch 'ui-polish' commit 7bce7484e9cf5389582fd70c509abd2541ac04e5 Author: Cosimo Cecchi Date: 2010-12-03 tree-sidebar: rename and move to src/ M src/Makefile.am M src/file-manager/Makefile.am M src/nemo-navigation-window.c R099 src/file-manager/fm-tree-model.c src/nemo-tree-sidebar-model.c R100 src/file-manager/fm-tree-model.h src/nemo-tree-sidebar-model.h R099 src/file-manager/fm-tree-view.c src/nemo-tree-sidebar.c R100 src/file-manager/fm-tree-view.h src/nemo-tree-sidebar.h commit b37e7b126e70b623e86b09c69f3f7839368e0604 Author: Cosimo Cecchi Date: 2010-12-03 notes-sidebar: remove NemoNotesViewer An ancient almost-hidden feature that just doesn't fit with the current design. M po/POTFILES.in M src/Makefile.am D src/nemo-notes-viewer.c D src/nemo-notes-viewer.h commit 8bba34a56ca1fd9ae70b7821ed7b7be48d6cc8f1 Author: Cosimo Cecchi Date: 2010-12-03 side-pane: remove NemoSidePane It's an useless container now that we changed our sidebar handling. M po/POTFILES.in M src/Makefile.am D src/nemo-side-pane.c D src/nemo-side-pane.h commit 369f2490308b615d3d9b2c86b428f18d721dff33 Author: Cosimo Cecchi Date: 2010-12-03 window: update for the removal of sidebar interfaces The window now just creates one of the two sidebars, and listens to GSettings changes for toggling between the two. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window-private.h M src/nemo-window.h commit 24ba7de3289225145faf2f85f05faef67370d447 Author: Cosimo Cecchi Date: 2010-12-03 places-sidebar: don't implement NemoSidebar/Provider anymore M src/nemo-places-sidebar.c M src/nemo-places-sidebar.h commit 1fe934a9955579103b72cd86c5ba83b9c7b4966a Author: Cosimo Cecchi Date: 2010-12-03 tree-sidebar: don't implement NemoSidebar/Provider anymore M src/file-manager/fm-tree-view.c M src/file-manager/fm-tree-view.h commit 3905444bd00e45cfbbe897c1da9de7f2d2c393e2 Author: Cosimo Cecchi Date: 2010-12-03 sidebar: remove NemoSidebar and NemoSidebarProvider We'll hardcode two sidebars (Places and Tree) from now on, so there's no need for these generic interfaces now. M libnemo-private/Makefile.am D libnemo-private/nemo-sidebar-provider.c D libnemo-private/nemo-sidebar-provider.h D libnemo-private/nemo-sidebar.c D libnemo-private/nemo-sidebar.h commit bc8c0f2fb18365f84045d0bfd6107d8541fbba59 Author: Cosimo Cecchi Date: 2010-12-03 application: don't register sidebars anymore M src/nemo-application.c commit 0bfd0a8d7d69058d486ab30580e2623166a5a555 Author: Cosimo Cecchi Date: 2010-12-03 sidebar: remove NemoHistorySidebar This is part of the 3.0 redesign plans. M po/POTFILES.in M src/Makefile.am M src/nemo-application.c D src/nemo-history-sidebar.c D src/nemo-history-sidebar.h commit 2a20b38c4dc870d8f3a85dae222c125a77f40229 Author: Michael Terry Date: 2010-11-26 Add --print-uri option M src/nemo-connect-server-dialog-main.c commit 7e794ed30195f15e78b6d96a9064681a128e41d6 Author: Cosimo Cecchi Date: 2010-12-03 search-engine: remove Beagle support M libnemo-private/Makefile.am D libnemo-private/nemo-search-engine-beagle.c D libnemo-private/nemo-search-engine-beagle.h M libnemo-private/nemo-search-engine.c commit fdae502d65f3c40dee4d418bd9d21270940aa93d Author: Cosimo Cecchi Date: 2010-12-03 libnemo-extension: use a different directory for 3.0 So that old extensions do not pull in GTK+2 code. https://bugzilla.gnome.org/show_bug.cgi?id=624244 M configure.in M libnemo-extension/Makefile.am M libnemo-extension/libnemo-extension-uninstalled.pc.in M libnemo-extension/libnemo-extension.pc.in M libnemo-private/Makefile.am M nemo-sendto-extension/Makefile.am commit d9331ae959593cd81f59b39d61597278162ac7eb Author: Matthias Clasen Date: 2010-12-02 Fix the build with latest GTK+ Various GdkDrawable APIs have been replaced by GdkWindow ones, and GtkFunction is no more, use GSourceFunc instead. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-tree-view-drag-dest.c M src/nemo-desktop-window.c commit 8ee6c67b5fe1b12999c2e2f4c7f42d85a497c233 Author: Cosimo Cecchi Date: 2010-12-02 dbus-manager: add DEBUG messages for NemoDBusManager M libnemo-private/nemo-dbus-manager.c M libnemo-private/nemo-debug.c M libnemo-private/nemo-debug.h commit 5433f57cec515bce9bddecc8a569aa02b597a75e Author: Cosimo Cecchi Date: 2010-12-02 debug: fix a stupid typo M libnemo-private/nemo-debug.c commit 46d6bbb1208c409b8507dc31ef6aaf895b55ba92 Author: Cosimo Cecchi Date: 2010-12-02 debug: check for flags in DEBUG_FILES M libnemo-private/nemo-debug.c commit a440c05ceebdbfc21c8e585087574c7827e5f1f2 Author: Cosimo Cecchi Date: 2010-12-02 eel-debug: remove unused code M eel/eel-debug.c M eel/eel-debug.h commit 2f90dc16bc0a9b9fb5e862ad5759aed04b98872c Author: Cosimo Cecchi Date: 2010-12-02 debug-log: nuke nemo-debug-log M libnemo-private/Makefile.am D libnemo-private/nemo-debug-log.c D libnemo-private/nemo-debug-log.h commit 2c9da31ce8252d32eae502b584379d53631f1a91 Author: Cosimo Cecchi Date: 2010-12-02 main: don't hook up with nemo-debug-log M src/nemo-main.c commit 218670bd1f1f9d8f980460c9f2ed721ff57c04a7 Author: Cosimo Cecchi Date: 2010-12-02 general: use new DEBUG macros instead of nemo_debug_log M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-tree-view-drag-dest.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-error-reporting.c M src/file-manager/fm-list-view.c M src/file-manager/fm-tree-view.c M src/nemo-application-smclient.c M src/nemo-application.c M src/nemo-places-sidebar.c M src/nemo-window-manage-views.c commit 695b2d933406b039fb46592b90b5f844d381490c Author: Cosimo Cecchi Date: 2010-12-02 debug: add a new, simpler nemo-debug module, based on Empathy's We lose dumping the log to a file automatically, but we gain a lot in flexibility. M configure.in A libnemo-private/nemo-debug.c A libnemo-private/nemo-debug.h commit b2edace4164fbec353bba497ebb34914864bcd1a Author: Cosimo Cecchi Date: 2010-12-02 dbus-manager: add an EmptyTrash operation M libnemo-private/nemo-dbus-manager.c commit 2e210578261c9060111efba1a705c78ff2c369b9 Author: Cosimo Cecchi Date: 2010-12-02 dbus-manager: implement the CopyURIs method M libnemo-private/nemo-dbus-manager.c M libnemo-private/nemo-dbus-manager.h commit 5c9f1adb43052b19499f6ff1ad403f2222f0e091 Author: Cosimo Cecchi Date: 2010-12-02 application: make the application-id not clash with the dbus interface M src/nemo-application.c commit b238be002e446e102e056b8484666f21feb6b6f2 Author: Cosimo Cecchi Date: 2010-12-01 dbus-manager: add a skeleton of NemoDBusManager M libnemo-private/Makefile.am A libnemo-private/nemo-dbus-manager.c A libnemo-private/nemo-dbus-manager.h M src/nemo-application.c commit 41b91ea64d9731a48ffab621e293f7ff05d88acd Author: Cosimo Cecchi Date: 2010-12-01 icon-canvas-item: tweak the resize bounding box color according to style M libnemo-private/nemo-icon-canvas-item.c commit 7bd06fab98c2c61a170535b6ebd94da1a4db7466 Author: Cosimo Cecchi Date: 2010-12-01 icon-dnd: fix DnD highlighting regression M libnemo-private/nemo-icon-dnd.c commit 8cb07ccf2ddcf0cb8557c763f8905558d67736de Author: Benjamin Otte Date: 2010-12-01 eel: Use future-safe macro to query the X display M eel/eel-canvas-rect-ellipse.c commit c2c4076ceb2216ff5e696b4e78aeb63e0f86c437 Author: Benjamin Otte Date: 2010-12-01 Remove unnecessary drawable cast M libnemo-private/nemo-icon-dnd.c commit 1cfc56563e6cf867af5e3a98cfb9c87281b5f4c2 Author: Cosimo Cecchi Date: 2010-12-01 build: bump required GTK+ version M configure.in commit de8cb567358f658c167b9413a077b681123ab056 Author: Cosimo Cecchi Date: 2010-12-01 mime-application-chooser: plug a leak M libnemo-private/nemo-mime-application-chooser.c commit 466fe29b2d1790b8f61d854b0294205a9f437fd2 Author: Cosimo Cecchi Date: 2010-12-01 mime-actions: remove unused code M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-mime-actions.h commit fe8ffd8635abfcf280e06c9385bfae4dd01621a4 Author: Cosimo Cecchi Date: 2010-12-01 program-choosing: remove commented out code M libnemo-private/nemo-program-choosing.c commit c0b34d1f07b2b1b1f11f1dbab75f8b3303543078 Author: Cosimo Cecchi Date: 2010-12-01 i18n: update POTFILES.in M po/POTFILES.in commit c745b5c50ea9e103861cafb4ce210b375034dd8d Author: Cosimo Cecchi Date: 2010-12-01 mime-application-chooser: add a 'Show other applications' button Similar to GtkAppChooserDialog; the 'Add' button now adds the currently selected application, and it becomes insensitive when necessary. M libnemo-private/nemo-mime-application-chooser.c commit 677c52173a1f5ba1a8e3db8c70cd96f27fb90200 Author: Cosimo Cecchi Date: 2010-11-30 mime-application-chooser: tweak buttons ordering M libnemo-private/nemo-mime-application-chooser.c commit 2d58f04289c31c4a7de9318327e3edd111d8735d Author: Cosimo Cecchi Date: 2010-11-30 mime-application-chooser: use populate-popup for removing apps Instead of having yet another button. M libnemo-private/nemo-mime-application-chooser.c commit 3e5dcec59709514b2998963b539ec77ed9d5c46f Author: Cosimo Cecchi Date: 2010-11-23 open-with-dialog: remove NemoOpenWithDialog It's useless now that we ported everything to GtkAppChooser. M libnemo-private/Makefile.am D libnemo-private/nemo-open-with-dialog.c D libnemo-private/nemo-open-with-dialog.h commit f83be2507361b337fb7eaf59a50cdca7f49ca53c Author: Cosimo Cecchi Date: 2010-11-23 properties-window: use new NemoMimeApplicationChooser API M src/file-manager/fm-properties-window.c commit e86ded0eb9842eb9d4a0ac6c83333e9ce3ffcd0e Author: Cosimo Cecchi Date: 2010-11-23 mime-application-chooser: rewrite to make it use GtkAppChooserWidget M libnemo-private/nemo-mime-application-chooser.c M libnemo-private/nemo-mime-application-chooser.h commit 7734204774ab87e07ddec50acbb62e3f9acd1120 Author: Cosimo Cecchi Date: 2010-11-23 mime-actions: port to GtkAppChooserDialog M libnemo-private/nemo-mime-actions.c commit 34a18d5b19df317bf19e4fdc67ea0c4007ed0375 Author: Cosimo Cecchi Date: 2010-11-23 directory-view: port to GtkAppChooserDialog M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-directory-view.c commit d7acbb0c1d58205f5c97d7c80fde034088feef9f Author: Jorge González Date: 2010-11-30 Updated Spanish translation M po/es.po commit 20c94e66a20a9d2d4643ce58b2696bbf5e5334b8 Author: Cosimo Cecchi Date: 2010-11-30 build: remove old X_LIBS variable M eel/Makefile.am commit fd03f393a55ea377583b821f578951b3ace237a5 Author: Cosimo Cecchi Date: 2010-11-30 docs: remove manual for nemo-file-management-properties The binary is not installed anymore. M docs/Makefile.am D docs/nemo-file-management-properties.1 commit 41059f897c33f981ce03c1dd62bcbbd20a53c52d Author: Cosimo Cecchi Date: 2010-11-29 Release 2.91.3 M NEWS M configure.in commit b83c479d40b86d8a4e537a1c30d2375a1277898c Author: Cosimo Cecchi Date: 2010-11-29 i18n: update POTFILES.in M po/POTFILES.in commit b088cc0bcf36bcbf4551de2e972b44423c92fb4f Author: Cosimo Cecchi Date: 2010-11-29 gsettings: remove org.gnome.media-handling gschemas from nemo They don't belong here anymore now that the media preferences have been moved elsewhere. M libnemo-private/Makefile.am M libnemo-private/nemo.convert D libnemo-private/org.gnome.media-handling.gschema.xml.in commit 6cb06b98d4c492ec774b9335565994190857c82d Author: Daniel Nylander Date: 2010-11-28 Updated Swedish translation M po/sv.po commit 92706c7ce3bd9dd703d7ad118e6bb95723e6cdd8 Author: Victor Osadci Date: 2010-11-27 query-editor: identify ogg/vorbis files as music (#365095) M src/nemo-query-editor.c commit aa9b6675d8a92329a7cba69c9bdb53fa30f87858 Author: Cosimo Cecchi Date: 2010-11-26 connect-dialog: use the correct string for gvfs (#635431) M src/nemo-connect-server-dialog.c commit 9d2d96fd2968e8f8a9b1f3a46660f27d6377f145 Author: Cosimo Cecchi Date: 2010-11-25 autorun: remove nemo-autorun.[ch] M libnemo-private/Makefile.am D libnemo-private/nemo-autorun.c D libnemo-private/nemo-autorun.h M po/POTFILES.in commit 912320008beae418d71a74361c1a0d9bcdae6f60 Author: Cosimo Cecchi Date: 2010-11-25 autorun: move get_x_content_types_for_mount () to file-utilities So that we can remove nemo-autorun.[ch] M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file-utilities.h M src/file-manager/fm-directory-view.c M src/nemo-window-manage-views.c commit 9281506c5b264e81a4610a4f6a20f2a42eab207b Author: Cosimo Cecchi Date: 2010-11-25 autorun: move nemo_launch_application_for_mount () Also add the parent window parameter to it, so that we get startup notification. M libnemo-private/nemo-autorun.c M libnemo-private/nemo-autorun.h M libnemo-private/nemo-program-choosing.c M libnemo-private/nemo-program-choosing.h M src/nemo-x-content-bar.c commit 7c71b7f383ece8ad9be39fcb28b9377364a35cb3 Author: Tomas Bzatek Date: 2010-11-23 Prevent showing asserts when GFile is no longer valid after unmount M src/nemo-application.c commit 36965ee18ed890f6899588df730345986213d7d1 Author: Tomas Bzatek Date: 2010-11-23 Includes cleanup M libnemo-private/nemo-autorun.c M libnemo-private/nemo-autorun.h commit e4fb850f0fb43a08ebca016c31fece6211073cb7 Author: Tomas Bzatek Date: 2010-11-23 Remove media preferences GSettings stuff M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h commit 33df383a2692dd8d8aba802710da28a6063f3bbc Author: Tomas Bzatek Date: 2010-11-23 Remove unused autorun code M libnemo-private/nemo-autorun.c M libnemo-private/nemo-autorun.h commit 9729357aa457bbc78e6e2370015b6ccb3e73cbf6 Author: Tomas Bzatek Date: 2010-11-23 Don't autorun on nemo_file_operations_mount_volume() M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-operations.h M src/nemo-places-sidebar.c commit ab7d5069f1658edbf6516f441801d0d2599f658b Author: Tomas Bzatek Date: 2010-11-23 Drop obsolete eject-button signal watch M src/nemo-application.c commit 045224ee72d896499fc0b04ced7dccb3e135e177 Author: Tomas Bzatek Date: 2010-11-23 Includes cleanup M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-vfs-file.c M src/nemo-file-management-properties.c M src/nemo-places-sidebar.c commit 8e0a51410a116ce875d04d205d3e89398bfae970 Author: Tomas Bzatek Date: 2010-11-23 Remove autorun after mount This way we lose ability to focus already open windows after mount. Since gnome-settings-daemon uses default folder handler to show freshly mounted folder, there's little we can do. M src/nemo-application.c commit cdae5fea2a466bf09ef236499e9c442888516cb1 Author: Tomas Bzatek Date: 2010-11-23 Don't automount volumes on nemo startup M src/nemo-application.c M src/nemo-application.h commit 36831040af2e262ee8e66768152d2057139af8b8 Author: Cosimo Cecchi Date: 2010-11-15 file-management-properties: remove the properties binary We are moving the Media preferences to a separate control-center panel, as they're desktop-wide settings. The actual autorun/automount will be handled by gnome-settings-daemon. The result is that we don't need to install our old gnome-control-center capplet anymore, so we can remove all this code. M configure.in M data/Makefile.am D data/nemo-file-management-properties.desktop.in.in M src/Makefile.am D src/nemo-file-management-properties-main.c M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit a6f4e065a66eeb5d74322bfb5cfd4320135a61d1 Author: Kjartan Maraas Date: 2010-11-20 Updated Norwegian bokmÃ¥l translation M po/nb.po commit b28340da1b97026938035fdb8544c4b8722ecdc9 Author: Gheyret T.Kenji Date: 2010-11-20 Added UG translation M po/ug.po commit df382f58d0ec2a1b779cf80048ad70944c8859df Author: Tomas Bzatek Date: 2010-11-16 Use G_SETTINGS_BIND_INVERT_BOOLEAN where appropriate M src/nemo-file-management-properties.c commit a5caa0e98c844a23656cafaa9b6f985dada7bc51 Author: Javier Jardón Date: 2010-11-16 Use GSourceFunc instead GtkFunction M libnemo-private/nemo-dnd.c M libnemo-private/nemo-dnd.h M libnemo-private/nemo-icon-container.c commit 812fcf2fbf4da7c97a6fc9eca1c64f9c9c225c90 Author: Daniel Șerbănescu Date: 2010-11-14 Updated Romanian translation M po/ro.po commit d9d2ed6cde69ce2ffb2fdd6028e36a0e760672a8 Author: Lucian Adrian Grijincu Date: 2010-11-14 Updated Romanian translation M po/ro.po commit e7d2c7468f0b04e6ee87981c291d6f2ed1aa87bb Author: Theppitak Karoonboonyanan Date: 2010-11-14 Updated Thai translation. M po/th.po commit f7b5d4b653317f080547c7b18649fd45531772a4 Author: Gheyret T.Kenji Date: 2010-11-13 Added UG translation M po/ug.po commit 5afa93854e2bde4f89910cff3a98546a66d880d2 Author: Baptiste Mille-Mathias Date: 2010-11-12 libgnome-desktop build fixes More porting from libgnome* to libgnome-desktop to fix build breakage M eel/eel-gnome-extensions.c M libnemo-private/nemo-thumbnails.c M src/file-manager/fm-properties-window.c commit 7c042f64ee59d9f149252f7e78e11ca6ad7d9dbe Author: Cosimo Cecchi Date: 2010-11-12 application: fix interaction with the session manager The porting to GApplication broke the session management code that took care of saving and loading existing windows if the session saving is active. We now fix it by changing a bit our startup process, so that the EggSMClient object is actually created at the right time. M src/nemo-application-smclient.c M src/nemo-application-smclient.h M src/nemo-application.c M src/nemo-application.h commit fb574c106185e773449a6d92bd54512b2074dd01 Author: Florian Müllner Date: 2010-11-11 desktop-background: Fix include The file gnome-bg.h was moved from libgnomeui to libgnome-desktop. M configure.in M libnemo-private/nemo-desktop-background.c commit a2eb813e14be86168173e4f95385934feddf2937 Author: Javier Jardón Date: 2010-11-11 Use gtk_separator_new() instead gtk_[h|v]separator_new() M libnemo-private/nemo-column-chooser.c M src/file-manager/fm-properties-window.c commit 3b586c5e61ce80a527f2abdc6d3e45189fee6985 Author: Tomas Bzatek Date: 2010-11-10 Bump gnome-desktop requirement for new gnome-bg M configure.in commit 87d8e557c13f3d51098cfe03cf2727102e8a8937 Author: Cosimo Cecchi Date: 2010-11-10 Release 2.91.2 M NEWS M configure.in commit 7b1c3ddd655977e3a26365942d21d83abed1f75d Author: Cosimo Cecchi Date: 2010-11-09 file: remove nemo_file_get_emblem_pixbufs() It's not used anymore. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 6a276d59af54413c59188ffb0143ffa6e1fe94a1 Author: Cosimo Cecchi Date: 2010-11-09 icon-container: don't care about the emblem size Use only GIcons for emblems, not pixbufs. We used to rely on pixbufs to get emblems at a specific size, but that's not important anymore now that GTK+ takes care of it internally. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M src/file-manager/fm-icon-container.c commit b118093fbc2b5a236a4502ac6e053ab9e64a9db1 Author: Tomas Bzatek Date: 2010-11-09 Port desktop background handling to GSettings See bug 626018 for details. M libnemo-private/nemo-desktop-background.c commit 36f64c7f85e305939ec9d5ddb7bb7a6a121c0c08 Author: Matej UrbanÄiÄ Date: 2010-11-06 Updated Slovenian translation M po/sl.po commit 8fd2694ee06fbbfc0cc9452b6ce5cc0a27ff160b Author: Cosimo Cecchi Date: 2010-11-05 icon-canvas-item: remove the emblem layouting code We can directly use GTK+ for this now. M libnemo-private/nemo-icon-canvas-item.c commit 79a9c6a36256d430459b4d2a7bc37e0d691c8e5a Author: Cosimo Cecchi Date: 2010-11-05 sq M libnemo-private/nemo-icon-container.c commit a728e7b830ebeccfba6d851a5b005033ba07189b Author: Cosimo Cecchi Date: 2010-11-05 icon-container: apply emblems directly on the pixbuf Do that before setting the pixbuf to the NemoIconCanvasItem, so the logic in there can be removed. M libnemo-private/nemo-icon-container.c commit e72391a9cecd0fe11458a6633edde3e800a797aa Author: Cosimo Cecchi Date: 2010-11-05 general: use GdkPixbuf/GIcon interface to set emblems in treeviews So that emblems get composited for us also on pixbufs such as thumbnails. M configure.in M src/file-manager/fm-list-model.c M src/file-manager/fm-tree-model.c commit 4882f2ac24dfcf33e06e5e9a06dd2cd0368069ec Author: Cosimo Cecchi Date: 2010-11-04 application: fix some bad interactions with GApplication M src/nemo-application.c M src/nemo-application.h commit e038864cdaf728b1a8407dfb8e5949cf467b72b7 Author: Ivar Smolin Date: 2010-11-03 [l10n] Updated Estonian translation M po/et.po commit 72b34f160a49edc40dccfb435330e30cd14feb9c Author: Yaron Shahrabani Date: 2010-11-03 Updated Hebrew translation. M po/he.po commit a0c3d8e339625eb1f84b769a4f81fd73785556bc Author: Takayuki KUSANO Date: 2010-11-03 Updated Japanese translation M po/ja.po commit 805a147bac55d38464f97ce933b33b8e7e42432d Author: Fran Diéguez Date: 2010-11-03 Updated Galician translations M po/gl.po commit 373683da693e6f4a768c7eb6f1fc793315c23db7 Author: Cosimo Cecchi Date: 2010-11-02 pathbar: fix crasher when unmounting volumes (#627901) M src/nemo-pathbar.c commit 57f92209189de791904b014f49b8a383ca1a5bd2 Author: Cosimo Cecchi Date: 2010-11-02 build: use X11 pkg-config files instead of homebrew checks M configure.in commit 64640897a2357e6fc442e14372ca3950e4b54090 Author: Ahmed Noor Kader Mustajir Md Eusoff Date: 2010-11-02 Partial update of Malay translation M po/ms.po commit efe7e4727d56bc8872557674aa90037b255229d5 Author: Jorge González Date: 2010-11-01 Updated Spanish translation M po/es.po commit d61097230c3b77931b7fc6212f70104f1fcdab04 Author: Cosimo Cecchi Date: 2010-11-01 Release 2.91.1 M NEWS M configure.in M po/POTFILES.in commit 2b99456d621c08bd097b87726704e671c76be1a1 Author: Cosimo Cecchi Date: 2010-11-01 [eel] remove eel_gtk_adjustment* functions They should not be needed now. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 8b4271f5ad62d00b76d7e34a594c9b1819eb495e Author: Cosimo Cecchi Date: 2010-11-01 desktop-icon-view: don't use eel helper to set adjustment values M src/file-manager/fm-desktop-icon-view.c commit 3a9c6cd783507cc2fbd0a838cd6710f74e7f17dd Author: Cosimo Cecchi Date: 2010-11-01 icon-container: don't use eel helper to set adjustment values M libnemo-private/nemo-icon-container.c commit 7029d317446f26f829a794884abe07d6ce980a5f Author: Cosimo Cecchi Date: 2010-11-01 canvas: remove commented out code M eel/eel-canvas.c commit 27f14a83ca6b656c20f6f7851b11dee12bfd4540 Author: Holger Berndt Date: 2010-10-05 Add possibility to register an external bulk rename tool If the new setting "bulk-rename-tool" in org.gnome.nemo.preferences is set to a non-empty string, it is treated as a bulk renamer and gets invoked on a Rename action if multiple files are selected. Nemo appends a space separated list of URIs of all selected files to the command string. https://bugzilla.gnome.org/show_bug.cgi?id=306489 M libnemo-private/nemo-global-preferences.h M libnemo-private/org.gnome.nemo.gschema.xml.in M src/file-manager/fm-directory-view.c commit b4aa3c083ab7616f321df4ade75e4d850142eff6 Author: Bastien Nocera Date: 2010-10-29 Move nemo-sendto extension to nemo And add a check for the presence of nemo-sendto to the initialisation of the object. Building the extension is optional, though on by default. https://bugzilla.gnome.org/show_bug.cgi?id=633485 M Makefile.am M configure.in A nemo-sendto-extension/Makefile.am A nemo-sendto-extension/nemo-nste.c A nemo-sendto-extension/nemo-nste.h A nemo-sendto-extension/nemo-sendto-module.c commit 0609431a5cb3803d0b98bd333f90e3c7796f86b7 Author: Paolo Borelli Date: 2010-11-01 Use gtk_paned_new instead gtk_[h|v]paned_new M src/nemo-navigation-window.c commit 059d9a384aedcc6dcc1e249a9979922278a90f60 Author: Yaron Shahrabani Date: 2010-11-01 Updated Hebrew translation. M po/he.po commit 802e1967cdf301a50b8403cfe820097561c60033 Author: Cosimo Cecchi Date: 2010-11-01 [eel] remove unused eel_gradient code M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 7dee3226ad6b3aa1c782cc3d2969e32c5eeae3f3 Author: Cosimo Cecchi Date: 2010-11-01 [eel] remove eel_gdk_pixbuf_list_ref() M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h M libnemo-private/nemo-icon-canvas-item.c commit 00c0b9daa2053a110e17c64fb79ce4884290dc76 Author: Cosimo Cecchi Date: 2010-11-01 [eel] remove unused eel_get_filename_charset() M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit 31dfbdc19075ddf92b4f04a2f84e3111c3fb429b Author: Cosimo Cecchi Date: 2010-11-01 [eel] remove eel_gtk_widget_set_shown() It's not used anymore. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit bb145a018a9d66b748971e40be4e09a7f843b2be Author: Cosimo Cecchi Date: 2010-11-01 places-sidebar: use gtk_widget_set_visible() instead of the eel helper M src/nemo-places-sidebar.c commit 654b8f8a52d2343293c03eec304d20b7904867a1 Author: Jorge González Date: 2010-10-31 Updated Spanish translation M po/es.po commit 5e669515fd7f760382e6b7aa1449734a35a2d7f4 Author: Cosimo Cecchi Date: 2010-10-31 general: use g_list_free_full() instead of eel functions M configure.in M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h M libnemo-private/nemo-autorun.c M libnemo-private/nemo-clipboard.c M libnemo-private/nemo-debug-log.c M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-dnd.c M libnemo-private/nemo-file-changes-queue.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-merged-directory.c M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-mime-application-chooser.c M libnemo-private/nemo-open-with-dialog.c M libnemo-private/nemo-program-choosing.c M libnemo-private/nemo-query.c M libnemo-private/nemo-search-engine-beagle.c M libnemo-private/nemo-search-engine-simple.c M libnemo-private/nemo-search-engine-tracker.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-list-model.c M src/file-manager/fm-list-view.c M src/file-manager/fm-properties-window.c M src/file-manager/fm-tree-model.c M src/file-manager/fm-tree-view.c M src/nemo-application.c M src/nemo-bookmark-list.c M src/nemo-history-sidebar.c M src/nemo-navigation-window-slot.c M src/nemo-pathbar.c M src/nemo-places-sidebar.c M src/nemo-query-editor.c M src/nemo-spatial-window.c M src/nemo-trash-bar.c M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window.c commit 7d05f8804f044ef13b4f89a49a1a7b7730f3a279 Author: Cosimo Cecchi Date: 2010-10-30 build: bump GLib and GTK+ requirements M configure.in commit d8ad1ab61cdb9929a8cb4f7d393e8b501e054289 Author: Cosimo Cecchi Date: 2010-10-30 application: use prettier format strings M src/nemo-application.c commit f48796637854ca784f7458a387e3607917ef5990 Author: Cosimo Cecchi Date: 2010-10-30 application: fix interaction with SMCLient Use late-initialization, otherwise we and up locked while reading session information. Also, don't try to use that information more than once in the app lifetime. M src/nemo-application-smclient.c M src/nemo-application.c M src/nemo-application.h commit d09b45c72bb1c3573b8f1c0bc83f1d8448ba5309 Author: Cosimo Cecchi Date: 2010-10-30 smclient: backport and tweak a patch for late SMClient initialization This is a tweak of a patch bt Vincent Untz, see libegg commit dc8db697dfaf8e57fbc9fe5251675a27e8c54f44 M cut-n-paste-code/libegg/eggsmclient.c commit 2260005986d8c620669e56c4b9f2fba12e8e0625 Author: Cosimo Cecchi Date: 2010-10-30 canvas: use GTK_LAYOUT casts instead of going through the parent struct That's just confusing. M eel/eel-canvas.c commit ebee13eef39824ebe536d0e42a35337097a33942 Author: Cosimo Cecchi Date: 2010-10-30 desktop-icon-view: don't unconditionally unref the desktop background M src/file-manager/fm-desktop-icon-view.c commit e383af25948a9b93915b1c39ae379bf0eace06ac Author: Cosimo Cecchi Date: 2010-10-30 application: close desktop windows on quit M src/nemo-application.c commit 12c7a03bfe3c49078cb5b44ff2651eb9ce1edce4 Author: Matthias Clasen Date: 2010-10-28 editable-label: don't use deprecated size_request vfunc M eel/eel-editable-label.c commit b532d0d9290d1731203d971e7c679979265f0a43 Author: Cosimo Cecchi Date: 2010-10-28 window: don't use deprecated size_request vfunc Also, cleanup the size_request code a bit. M src/nemo-window.c commit 1cdd0b41bf9de69a93cb166636d7eccff9f5355f Author: Cosimo Cecchi Date: 2010-10-28 icon-container: remove size_request vfunc impl It doesn't seem to do anything useful. M libnemo-private/nemo-icon-container.c commit 22cb1accd98c1ae10938eac10cc6beda8fb6b145 Author: Cosimo Cecchi Date: 2010-10-28 pathbar: don't use deprecated size_request vfunc M src/nemo-pathbar.c commit 305d1b05896e39a5e3181247d9d4e837b4c35067 Author: Cosimo Cecchi Date: 2010-10-27 image-properties-page: don't special-case old EXIF/XMP APIs M src/nemo-image-properties-page.c commit 393df7a83c0a779784095a993db238867daeaa7a Author: Cosimo Cecchi Date: 2010-10-27 build: simplify configure script Also, don't support old exif/exempi APIs anymore. D acconfig.h M check-headers-in-Makefile.pl M configure.in M cut-n-paste-code/libegg/Makefile.am M docs/reference/libnemo-extension/Makefile.am M eel/Makefile.am M libnemo-extension/Makefile.am M libnemo-private/Makefile.am M src/Makefile.am M src/file-manager/Makefile.am M test/Makefile.am commit 8d9d6128b69e641c2b77322e8832be8ae0b9bf93 Author: Cosimo Cecchi Date: 2010-10-27 application: properly handle --no-default-window M src/nemo-application.c M src/nemo-main.c commit 13630f0b4d58e3b2be6781f3049d13c1095b0dca Author: Cosimo Cecchi Date: 2010-10-27 application: perform checks in NemoApplication if requested so M src/nemo-application.c M src/nemo-main.c commit 48f17e3726bc0e37d35714d5f18ce56498508d79 Author: Cosimo Cecchi Date: 2010-10-27 application: respect the 'exit-with-last-window' setting. If it's set, we quit immediately. M src/nemo-application.c commit df8bdf21cffc1b2370b34173487219ee3568d040 Author: Cosimo Cecchi Date: 2010-10-27 application: cleanup M src/nemo-application.c commit e0f68583d47d23738afd7695f6137e2d2552b45d Author: Cosimo Cecchi Date: 2010-10-27 application: don't unref unconditionally As we're building the NemoUndoManager in _startup() now, which might not have been called if the application is remote. M src/nemo-application.c commit e297d4108760e701b3cd276e9d4612b1933efee0 Author: Cosimo Cecchi Date: 2010-10-27 application: add the desktop windows to the application window list So that we don't quit immediately when we close the browser window. M src/nemo-application.c commit 248339e40908fc58a5edad462c77b667d5cb8315 Author: Cosimo Cecchi Date: 2010-10-27 application: remove get_n_windows() M src/nemo-application.c M src/nemo-application.h M src/nemo-window-manage-views.c commit 56dd8bb3d5594d9caffda23400f7bd64c94e5a4c Author: Cosimo Cecchi Date: 2010-10-27 application: move other init/cleanup functions in the app class Instead of mixing them between nemo-main and nemo-application M src/nemo-application.c M src/nemo-application.h M src/nemo-main.c commit 2d702e1eeb7f9a8ad1286db39f5088bf39f1229c Author: Cosimo Cecchi Date: 2010-10-27 application: make sure to initialize GTK+ during _startup() M src/nemo-application.c commit 0712652a5f3730d10bca4040b68f3dda1e98c0bf Author: Cosimo Cecchi Date: 2010-10-27 desktop-window: monitor the desktop dir key from NemoDesktopWindow Remove that code from NemoApplication, it doesn't belong there. M src/nemo-desktop-window.c commit 7500dd445df5a0cf082464f099169666727f6ec2 Author: Cosimo Cecchi Date: 2010-10-27 [src] use new GtkApplication API to handle windows Instead of old nemo-main/NemoApplication functions to register windows within the mainloop. M src/nemo-application-smclient.c M src/nemo-navigation-window-menus.c M src/nemo-window-manage-views.c M src/nemo-window.c commit a8481ee4bd8d34e792d63598fa5efb47736f9de4 Author: Cosimo Cecchi Date: 2010-10-27 main: adapt to GtkApplication changes This code should be much easier now that window lifecycle is handled by GtkApplication itself. M src/Makefile.am M src/nemo-application-smclient.c M src/nemo-application.c M src/nemo-main.c D src/nemo-main.h M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-manage-views.c M src/nemo-window.c commit b03b081e91d376140e4fc94fd885bf7d13fc57c5 Author: Cosimo Cecchi Date: 2010-10-27 application: make NemoApplication a GtkApplication subclass M src/nemo-application.c M src/nemo-application.h commit bb52a77678b732626693869e315bb78c77635a0b Author: Cosimo Cecchi Date: 2010-10-26 application: replace custom GIcon custom load/save code with GIO one M src/nemo-application-smclient.c commit dc0b129436d5c9eb712a80852768387fc2b8cd7c Author: Cosimo Cecchi Date: 2010-10-26 application: split SmClient code in its own module. M src/Makefile.am A src/nemo-application-smclient.c A src/nemo-application-smclient.h M src/nemo-application.c commit d811553a4e74106efdf8bf6c91c6d29944ed6df7 Author: Cosimo Cecchi Date: 2010-10-22 general: use new GtkScrollable interface M eel/eel-canvas.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-tree-view-drag-dest.c M src/file-manager/fm-desktop-icon-view.c commit f9aa5d9442ae918bb1e583d1543b8da0b51fb959 Author: Cosimo Cecchi Date: 2010-10-22 application: go back to libunique for now While GApplication API settles. Also, porting to the new GApplication would require quite some refactoring. M configure.in M src/nemo-application.c M src/nemo-application.h M src/nemo-main.c commit 0e755165bc561b2c61628519c090cd826f7609c6 Author: Cosimo Cecchi Date: 2010-10-22 build: bump GTK+ required version M configure.in commit 6669f155734c320617bcf79f3b5d8f315f4886f9 Author: Cosimo Cecchi Date: 2010-10-22 preferences: cleanup expand/fill flags Probably a change in GTK+ requires fixing this flags, so that the dialog doesn't look odd. M src/nemo-file-management-properties.ui commit 18fc6dd2516f9091570902640032e68b263cfddf Author: Cosimo Cecchi Date: 2010-10-22 preferences: use GtkComboBoxText in the GtkBuilder file M src/nemo-file-management-properties.ui commit f123f99bee1005cd279783f9d441f538fcf85542 Author: Cosimo Cecchi Date: 2010-10-21 [src] don't use GtkComboBox text APIs (#632651) They got replaced by GtkComboBoxText. Thanks to Mathias Clasen and Flo Gravo. M src/file-manager/fm-properties-window.c M src/nemo-file-management-properties.c M src/nemo-query-editor.c M src/nemo-view-as-action.c commit d5ad28bff6c1ebcd6e1560d2036655ffa9562e8b Author: Andrej ŽnidarÅ¡iÄ Date: 2010-10-30 Updated Slovenian translation M po/sl.po commit 9c97179025ca98641737b44bf0a6409757ee2f18 Author: Carles Ferrando Date: 2010-10-29 Updated Catalan (Valencian) translation M po/ca@valencia.po commit 716ad3f41eae1773cc260427ccf87c959a2bc3a3 Author: Jorge González Date: 2010-10-28 Updated Spanish translation M po/es.po commit 4d1464f859439b12b8c79bac919da333caea28a3 Author: Mattias Põldaru Date: 2010-10-28 [l10n] Updated Estonian translation M po/et.po commit bbd7d86fc4ef27f4df3537844fc5998e4c29949e Author: Yaron Shahrabani Date: 2010-10-26 Updated Hebrew translation. M po/he.po commit 540dc54229fee2e5e5d53453c61d4dd48537545c Author: Aron Xu Date: 2010-10-25 Update Simplified Chinese translation. M po/zh_CN.po commit 87ccfbf66ebed490eb8c921a712d8cb94e4ad817 Author: Gheyret T.Kenji Date: 2010-10-21 Added UG translation M po/ug.po commit c30f0785727ebad08f3891d594831596d16598e0 Author: Fran Diéguez Date: 2010-10-20 Updated Galician translations M po/gl.po commit 18e74876421fd38584c9dd105914d7a626aed3b7 Author: Mario Blättermann Date: 2010-10-19 [i18n] Updated German translation M po/de.po commit 1f135b5da410b7a0052d22322d740037036b39b0 Author: Tomas Bzatek Date: 2010-10-19 Use gnome global 'show-desktop-icons' settings See bug 632225 for details. M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo.convert M libnemo-private/org.gnome.nemo.gschema.xml.in M src/nemo-application.c commit c0e91e6a53dc3d920a25be1cf836c28730e193d8 Author: Милош Поповић Date: 2010-10-18 Updated Serbian Translation M po/sr.po M po/sr@latin.po commit 2c04203ef9c3be3fd209589e8ec7007889323991 Author: Mattias Põldaru Date: 2010-10-16 [l10n] Updated Estonian translation M po/et.po commit d3ab8e137ae957e5afef54bf0ec1e275b96caab5 Author: Marcus Carlson Date: 2010-07-23 image-properties-page: call gdk_pixbuf_loader_close() earlier (#558267) This helps smaller images (>8192 bytes) to signal size_prepared before reading image geometry. M src/nemo-image-properties-page.c commit 49ff3247d17e57afc3612de2f709997c8bb92408 Author: Jorge González Date: 2010-10-14 Updated Spanish translation M po/es.po commit 1cb6ea5dcb0cd384f49aac063e56d24203683602 Author: Cosimo Cecchi Date: 2010-10-14 icon-container: use the right signature for the 'preedit-changed' cb This should fix bug #629159. Thanks to Fumihito YOSHIDA to notice this. M libnemo-private/nemo-icon-container.c commit 5e383c3377ef2c2333f97102826880e86fdddef2 Author: Yaron Shahrabani Date: 2010-10-14 Updated Hebrew translation. M po/he.po commit 0f8dcf2ac394121c488afdf0fecc2b7afeb673b6 Author: Cosimo Cecchi Date: 2010-10-13 column-utilities: fix a TODO about a missing description string M libnemo-private/nemo-column-utilities.c commit b0550951f461c2033f4d1aaa4404078c7a70f220 Author: Antoine Jacoutot Date: 2010-10-13 column-utilities: disable SELinux column if !HAVE_SELINUX (#631093) M libnemo-private/nemo-column-utilities.c commit ebcbb167876f8b4491af0bc86bc29015c211b3af Author: Olivier Tilloy Date: 2010-08-17 icon-view: if possible, use the local path for the preview (#624841) This solves issues where the audio previewer is not capable of understanding some GVfs URIs. M src/file-manager/fm-icon-view.c commit 01f39f471005e788281c18da30563c0184434fff Author: Cosimo Cecchi Date: 2010-10-13 background: make the fading effect optional (#623174) This is implemented with a GSettings key. Thanks to Brian Cameron for the initial patch. M libnemo-private/nemo-desktop-background.c M libnemo-private/nemo-global-preferences.h M libnemo-private/org.gnome.nemo.gschema.xml.in commit 4cd72a64d67cdfd1d9351c52b2cf8463efd0c141 Author: Cosimo Cecchi Date: 2010-10-13 background: fix the indentation modeline M libnemo-private/nemo-desktop-background.c commit e676a40dcef267c312e27c4191adc0d22eaf1554 Author: Cosimo Cecchi Date: 2010-10-13 preferences: remove obsolete background preferences M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo.convert M libnemo-private/org.gnome.nemo.gschema.xml.in commit d26ae7b60c07057c6fbf926a3a805c29a5cfc3b2 Author: A S Alam Date: 2010-10-13 update typo in translation: Punjabi M po/pa.po commit 1620bd8a4e4ab1760c5c518dd954a4471645ce87 Author: Cosimo Cecchi Date: 2010-10-12 horizontal-splitter: remove, and use a regular GtkPaned instead The feature it was bringing in (shrink when the paned handle is double-clicked) is even confusing. M libnemo-private/Makefile.am D libnemo-private/nemo-horizontal-splitter.c D libnemo-private/nemo-horizontal-splitter.h M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window.c commit c05e2d7cdf8a5da4b9a353529ed214e7b36de8ca Author: Mattias Põldaru Date: 2010-10-11 [l10n] Updated Estonian translation M po/et.po commit 62690ab70e62ae108d1a03c0d19510c58dd882c0 Author: Jorge González Date: 2010-10-10 Updated Spanish translation M po/es.po commit 5653060d93db2686997faa8f6a10b87659d09c0a Author: Cosimo Cecchi Date: 2010-10-10 background: assume the widget is an IconContainer M libnemo-private/nemo-desktop-background.c M libnemo-private/nemo-desktop-background.h M libnemo-private/nemo-icon-dnd.c M src/file-manager/fm-desktop-icon-view.c commit 7e7691f0332a9b708217432a692cdf27e536cbcc Author: Cosimo Cecchi Date: 2010-10-10 icon-dnd: use new background API M libnemo-private/nemo-icon-dnd.c commit 843e6a9b9331a3e7a318df03b4074deb1163e386 Author: Cosimo Cecchi Date: 2010-10-10 background: make NemoDesktopBackground a singleton This avoids the need of using g_object_set_data() hacks to get the background from the desktop icon container. M libnemo-private/nemo-desktop-background.c M libnemo-private/nemo-desktop-background.h commit d4342547ebc2e26547cf8f1449bfd2e8fe4c443f Merge: eda5d36 66cd22c Author: Cosimo Cecchi Date: 2010-10-09 Merge branch 'background-untangling' commit eda5d36cadf299cf62429c1e29763b5dd3d53c40 Author: Jorge González Date: 2010-10-09 Updated Spanish translation M po/es.po commit 66cd22c908cc73954fad3e261d28ae6a05ea1bc2 Author: Cosimo Cecchi Date: 2010-10-09 background: refactor code into NemoDesktopBackground Remove the DirectoryBackground->EelBackground->GnomeBG abstraction and add a new object, NemoDesktopBackground, which is a thin wrapper around GnomeBG, which takes care of handling background changes. M eel/Makefile.am D eel/eel-background.c D eel/eel-background.h M eel/eel-lib-self-check-functions.h M eel/eel.h M libnemo-private/Makefile.am M libnemo-private/nemo-autorun.h A libnemo-private/nemo-desktop-background.c A libnemo-private/nemo-desktop-background.h D libnemo-private/nemo-directory-background.c D libnemo-private/nemo-directory-background.h M libnemo-private/nemo-icon-dnd.c M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/fm-list-view.c M test/Makefile.am M test/test.c commit 3bcd8464bcc9bdc44086275df8f6d1d29829bd8d Author: Cosimo Cecchi Date: 2010-10-08 icon-dnd: adapt to EelBackground changes. M libnemo-private/nemo-icon-dnd.c commit b6b2d222a4fc5150370589fd70811707139d3bbd Author: Cosimo Cecchi Date: 2010-10-08 directory-background: update to simplified EelBackground API EelBackground doesn't have any signals anymore, so don't try to connect to them. M libnemo-private/nemo-directory-background.c commit b137867bfaf9d1175b883d31baf18ae7e21d8549 Author: Cosimo Cecchi Date: 2010-10-08 eel-background: cleanup code not related to desktop background Remove all the EelBackground code that's not related to desktop background handling. M eel/eel-background.c M eel/eel-background.h commit c185321ed28d8aba69734039211946c739d32467 Author: Cosimo Cecchi Date: 2010-10-07 views: don't use EelBackground to set sensitive/insensitive bg Use an implementation for each view, don't relying on EelBackground. M src/file-manager/fm-empty-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c commit c31c5e360b0726788af93f6e404e1686d46b1f61 Author: Cosimo Cecchi Date: 2010-10-07 directory-view: call set_active() on subclasses to set insensitive bg Don't have a default implementation relying on EelBackground here. M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h commit ef74d171892ed7189b4a52695ae8de575d2dac1a Author: Cosimo Cecchi Date: 2010-10-07 icon-container: add set_active() This internally replaces EelBackground usage to set the non-sensitive background on non-active panes. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M libnemo-private/nemo-icon-private.h commit 42e726853157e561dc99d61180cae036f751fef8 Author: Cosimo Cecchi Date: 2010-10-07 eel-gdk-extensions: add eel_make_color_inactive() to public API M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 11c0ce912f2c6d5c933968780a53f5261f125fec Author: A S Alam Date: 2010-10-09 updating translation for Punjabi M po/pa.po commit 9e35d0ca6f10650f4d86963a3b5e986e3ec17681 Author: Changwoo Ryu Date: 2010-09-24 Updated Korean translation M po/ko.po commit 407666719856127547f5c2f3f03f6a050858239a Author: Cosimo Cecchi Date: 2010-10-06 editable-label: fix cairo drawing regressions M eel/eel-editable-label.c commit 75e101268198ce92e8165c7adda55cac69d1f93a Author: Fran Diéguez Date: 2010-10-07 Updated galician translations M po/gl.po commit a0c3ff8742e2f877b73678cff6d1a2950296e0ba Author: Yaron Shahrabani Date: 2010-10-06 Updated Hebrew translation. M po/he.po commit 31fac990215a99a034b62e626fb86e02ad751a31 Author: Cosimo Cecchi Date: 2010-10-05 Release 2.91.0.1 M NEWS M configure.in commit 33c9b6d24a60079fe6c4c1be281c76f43def6fee Author: Cosimo Cecchi Date: 2010-10-05 cell-renderer-text-ellipsized: use new GtkSizeRequest vfunctions This fixes the 'Name' column being too thin in list view. M libnemo-private/nemo-cell-renderer-text-ellipsized.c commit 61906b05ec90d5d4759ae7ff7fc7aca40fb18f15 Author: Cosimo Cecchi Date: 2010-10-05 window-toolbars: show/hide the spinner in the right order Apparently calling them in the wrong order makes new GTK+ crash. M src/nemo-window-toolbars.c commit ca6e8b6d59caa79e1095d02f107df1779107a565 Author: Cosimo Cecchi Date: 2010-10-04 Release 2.91.0 M NEWS M configure.in commit 74a0311e65f2c9fc2d03967b0607633dcb652f88 Author: Cosimo Cecchi Date: 2010-10-04 build: fix distcheck M eel/Makefile.am M src/Makefile.am commit 2053c267a79231aeb82a24adfe8f4e7da442cdb7 Author: Cosimo Cecchi Date: 2010-10-04 build: depend on 2.91.0 GTK+ and gnome-desktop M configure.in commit 64819695a13eb636df535e08e0eed6e896a8821c Author: Cosimo Cecchi Date: 2010-10-04 properties-window: split some long lines M src/file-manager/fm-properties-window.c commit 5ece5d67163e30a91e600d2f2bcf0d657d365dc4 Author: Cosimo Cecchi Date: 2010-10-04 properties-window: don't use expose-event to draw the pie chart Use GtkWidget::draw instead M src/file-manager/fm-properties-window.c commit d72087b74c871ef82b1f6a13bb5bb72b38670a52 Author: Cosimo Cecchi Date: 2010-10-04 window-toolbars: show/hide the spinner when changing its state M src/nemo-window-toolbars.c commit 3745195087a21bb46ed42925ff1d877562dbf36e Author: Cosimo Cecchi Date: 2010-09-30 build: bump GTK+ and gnome-desktop required versions M configure.in commit 098057414b38aeeddd3fcd81942324336628d341 Author: Cosimo Cecchi Date: 2010-09-30 icon-dnd: cleanup useless code M libnemo-private/nemo-icon-dnd.c commit f38bad2536faf497fe56c9a491ab852cb00514c0 Author: Cosimo Cecchi Date: 2010-09-30 icon-dnd: use negative device offsets to set the drag surface M libnemo-private/nemo-icon-dnd.c commit a136af0a01c160cdfb513c531b910b49a4a62973 Author: Cosimo Cecchi Date: 2010-09-30 icon-canvas-item: use cairo directly instead of gdk_pixbuf_composite() M libnemo-private/nemo-icon-canvas-item.c commit c6860491c432e311d585a6d92443ef821afd46d2 Author: Cosimo Cecchi Date: 2010-09-30 icon-canvas-item: set transparent background for highlight M libnemo-private/nemo-icon-canvas-item.c commit 426079ef07d5f902911f30b0a9d7de95f3020374 Author: Benjamin Otte Date: 2010-09-29 background: cope with renamings of gnome-bg APIs M eel/eel-background.c commit b1aac113ef867846fb39ee4187378c6f1a13f33e Author: Cosimo Cecchi Date: 2010-09-29 desktop-icon-view: don't use gdk_drawable_get_screen M src/file-manager/fm-desktop-icon-view.c commit 0b664aae4090704fa2e44d42f213da2cea8bd828 Author: Cosimo Cecchi Date: 2010-09-29 background: port to rendering-cleanup Based on patches from Benjamin Otte and Christian Persch. M eel/eel-background.c commit c47d18f566fa9518ca7750922da7da66d3211f3e Author: Cosimo Cecchi Date: 2010-09-29 [src] use gtk_widget_get_preferred_size() M src/nemo-pathbar.c M src/nemo-side-pane.c M src/nemo-spatial-window.c M src/nemo-zoom-control.c commit e56241830bfd2ca470ec2b1da53313c2230bc2b9 Author: Cosimo Cecchi Date: 2010-09-29 icon-container: use gtk_widget_get_preferred_size() M libnemo-private/nemo-icon-container.c commit f5192b6990cd9240d126974dd587b7b7525ae714 Author: Cosimo Cecchi Date: 2010-09-29 [libnemo-private] use eel_canvas_item_destroy Instead of gtk_object_destroy() M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c commit 910191ea13e5647e1b8c793e7585530c6ae4c9b1 Author: Christian Persch Date: 2010-09-16 [libnemo-private] Port to rendering-cleanup-next M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-canvas-item.h M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-tree-view-drag-dest.c commit 44171abea01a0c110aa029dddfb5d5afe018d086 Author: Christian Persch Date: 2010-09-16 [libnemo-private] Use gtk_widget_get_preferred_size() ... instead of the deprecated gtk_widget_get_child_requisition(). M libnemo-private/nemo-horizontal-splitter.c commit 2b7659ac4fcaa8b93ad8f409e1560aaa60dcdc12 Author: Christian Persch Date: 2010-09-16 [eel] Port EelEditableLabel to rendering-cleanup-next M eel/eel-editable-label.c commit 4963a3c9e5526ffd139b1b0b5bff18b6ea91a717 Author: Cosimo Cecchi Date: 2010-09-29 editable-label: use gtk_widget_get_preferred_size() M eel/eel-editable-label.c commit 58832e54b6a4e596693527d577e4f8fa2f3e4ccf Author: Christian Persch Date: 2010-09-16 [eel] Port the eel canvas to rendering-cleanup-next M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas.c M eel/eel-canvas.h commit d2f141f4a5435b10b43abea0822e3d0569b67886 Author: Christian Persch Date: 2010-09-16 [eel] Add eel_cairo_draw_layout_with_drop_shadow Renamed from eel_gdk_draw_layout_with_drop_shadow. M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 93e1cdfd387c47f73e51eeff924f8e2c9fad2bda Author: Cosimo Cecchi Date: 2010-09-29 undo-transaction: remove obsolete commented code M libnemo-private/nemo-undo-transaction.c M src/nemo-bookmarks-window.c commit f616fee30fb153c9f71d79b2568d2e0e5a23fd39 Author: Cosimo Cecchi Date: 2010-09-29 undo-signal-handlers: remove commented out obsolete code M libnemo-private/nemo-undo-signal-handlers.c M libnemo-private/nemo-undo-signal-handlers.h commit c5eba3314c99059aa1fff13aedcb1004966fdd55 Author: Cosimo Cecchi Date: 2010-09-29 icon-dnd: remove commented out obsolete code M libnemo-private/nemo-icon-dnd.c commit cc6cb51e827c0b15d4ef09f12d37b9f331ddcef8 Author: Cosimo Cecchi Date: 2010-09-29 [src] don't use GtkObject M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-properties-window.c M src/nemo-application.c M src/nemo-bookmarks-window.c M src/nemo-location-bar.c M src/nemo-location-dialog.c M src/nemo-location-entry.c M src/nemo-main.c M src/nemo-main.h M src/nemo-navigation-bar.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-pathbar.c M src/nemo-window-bookmarks.c M src/nemo-window-manage-views.c M src/nemo-window.c commit aef4cfcf93ef34a0b2d4c87b40fcec2b7a66dd06 Author: Cosimo Cecchi Date: 2010-09-29 [libnemo-private] don't use GtkObject M libnemo-private/nemo-autorun.c M libnemo-private/nemo-clipboard.c M libnemo-private/nemo-entry.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-mime-application-chooser.c M libnemo-private/nemo-open-with-dialog.c M libnemo-private/nemo-program-choosing.c M libnemo-private/nemo-undo-transaction.c commit b5f9acb9029c015558ab678e01fc2c8dcc8c6c82 Author: Cosimo Cecchi Date: 2010-09-29 editable-label: don't use GtkObject M eel/eel-editable-label.c commit 1f615321613751a5dbc84d5ef7f20edd104b8dc4 Author: Cosimo Cecchi Date: 2010-09-29 canvas: don't use GtkObject This implies adding a 'destroy' signal to EelCanvasItem, with similar semantics to gtk_object_destroy() M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas.c M eel/eel-canvas.h commit 5edcd42e503623c11bf55c6afba437b3013c7f45 Author: Cosimo Cecchi Date: 2010-09-29 stock-dialogs: don't use GtkObject M eel/eel-stock-dialogs.c commit 510d5fba10058535b8d8a3bb05f564122b798abd Author: Cosimo Cecchi Date: 2010-09-30 window-menus: fix a typo in the about dialog (#630624). M src/nemo-window-menus.c commit 2e59a60800a9bc837af9132b0ac234d9d14668c6 Author: Cosimo Cecchi Date: 2010-09-29 background: remove leftover GtkObject M eel/eel-background.h commit 87eb53a0701252607b494f34c677b6506f82278c Author: Cosimo Cecchi Date: 2010-09-29 background: cleanup unused code M eel/eel-background.c M eel/eel-background.h commit fbb6b024128e3c35aeb1d74f8e287e8870c9999f Author: Cosimo Cecchi Date: 2010-09-29 directory-background: don't user the 'destroy' signal of EelBackground M libnemo-private/nemo-directory-background.c commit 60044f8ef457036560fb94ad6b20cdf7bedb4f77 Author: Cosimo Cecchi Date: 2010-09-29 background: don't use GtkObject M eel/eel-background.c commit ab1229476f949fef5cd51545088c91c649be2ef1 Author: Cosimo Cecchi Date: 2010-09-28 icon-dnd: don't set 'Set as Background' sensitive outside the desktop M libnemo-private/nemo-icon-dnd.c commit 895830af57277c7fd542f3fd21f71c4cde1ea231 Author: Cosimo Cecchi Date: 2010-09-28 dnd: remove support for property/bgimage as DND type. That was used for tiled backgrounds in the 'Backgrounds and Emblems' dialog. M libnemo-private/nemo-dnd.c M libnemo-private/nemo-dnd.h M libnemo-private/nemo-file-dnd.c M libnemo-private/nemo-icon-dnd.c commit c9be35b3ee6c468a9a102b317b82b8b639637d0f Author: Cosimo Cecchi Date: 2010-09-28 directory-background: remove code for setting non-desktop window backgrounds Remove all the code that sets non-desktop window backgrounds, as we don't do that anymore. This includes avoid listening to metadata and GSettings changes. M libnemo-private/nemo-directory-background.c M libnemo-private/nemo-directory-background.h commit ab0616de55f6f817a745caac26fd2b38ae41b71b Author: Cosimo Cecchi Date: 2010-09-28 icon-view: move background setting code to FMDesktopIconView So that we avoid setting backgrounds on regular nemo windows. M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-view.c commit ecc583092aa333081205470c7cca7fb1aa68cb81 Author: Petr Kovar Date: 2010-09-29 Update Czech translation by Marek Cernocky M po/cs.po commit d2a41707084726ebdf882c8c6ec82ef46e29dcb0 Author: Damyan Ivanov Date: 2010-09-27 Updated Bulgarian translation M po/bg.po commit c0b28726fc05c7eac004ebaf4f81bb5e753285aa Author: Joan Duran Date: 2010-09-26 Updated Catalan translation M po/ca.po commit 1839f9abf3fa7ce88574649d531c88c9e3ac4bf7 Author: Mattias Põldaru Date: 2010-09-24 [l10n] Updated Estonian translation M po/et.po commit 74630527a03b3492913d0611b221ebdc5e1e76ba Author: Takayuki KUSANO Date: 2010-09-24 Updated Japanese translation M po/ja.po commit be665613c0e9233042e6e1f97b8cdb8708fdd782 Author: Khaled Hosny Date: 2010-09-23 Updated Arabic translation M po/ar.po commit f3bbee79b915276068e0a0d6ed9590c212e11a0a Author: Cosimo Cecchi Date: 2010-09-20 connect-dialog: add a missing gtk_widget_show() M src/nemo-connect-server-dialog.c commit 24100d075f747e8fc9ca3cc43a32489177f35459 Author: Cosimo Cecchi Date: 2010-09-20 connect-dialog: make the code more readable Move bits around and rename methods; no actual code change. M src/nemo-connect-server-dialog.c commit 1b79a8666fee56cdb704e8757f28acf486f7dc54 Author: Cosimo Cecchi Date: 2010-09-20 connect-dialog: display a fatal error if GVfs doesn't have methods I.e. when GVfs is not installed. M src/nemo-connect-server-dialog.c commit 1c826ed78bde5f34fd4a0f72d788b8d0824d6099 Author: Cosimo Cecchi Date: 2010-09-11 connect-dialog: fixes for the handling of iconized entries M src/nemo-connect-server-dialog.c commit 7d004452f333b7b8b804d87de49c858e8743a115 Author: Cosimo Cecchi Date: 2010-09-01 connect-dialog: integrate password handling Also, use the info bar to display warnings/errors, and tweak the UI details. M src/nemo-connect-server-dialog-main.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-connect-server-dialog.c M src/nemo-connect-server-dialog.h commit c1bebe3a29bc2dc3b01ad2277a9802d9d0bc25cd Author: Cosimo Cecchi Date: 2010-08-31 connect-operation: add NemoConnectServerOperation This is a GtkMountOperation subclass to handle password/username/domain requests directly from inside of the 'Connect to Server' dialog. M src/Makefile.am A src/nemo-connect-server-operation.c A src/nemo-connect-server-operation.h commit 156615f8d9f8b99dea3459cdd76392d01b9d80df Author: Cosimo Cecchi Date: 2010-09-20 window-menus: use new connect dialog API M src/nemo-window-menus.c commit 7848e74d812c22299962a8ae22b01dbd403929c0 Author: Cosimo Cecchi Date: 2010-09-20 connect-dialog: redesign the dialog According to Allan Day's mockups. M src/nemo-connect-server-dialog-main.c M src/nemo-connect-server-dialog.c M src/nemo-connect-server-dialog.h commit d5350003ac927bd683d4e18f7c0513b94f9220d7 Author: Cosimo Cecchi Date: 2010-08-31 navigation-window-menus: use new NemoApplication API M src/nemo-navigation-window-menus.c commit a3ce22ec6e8fcb39dafb35e04e445f4a94b8c394 Author: Cosimo Cecchi Date: 2010-08-31 bk-window: use new NemoApplication API M src/nemo-bookmarks-window.c commit adedf859ec47296106f0f0d938e70b32f0120f7c Author: Cosimo Cecchi Date: 2010-08-31 window: call the callback during the location change M src/nemo-window-manage-views.c M src/nemo-window-slot.h commit d070d631545aac9114bc271481da603587c07c7c Author: Cosimo Cecchi Date: 2010-08-31 application: change the way spatial windows are created Use a _get() function + the standard nemo_window_go_to() instead of using _present(). The new functions in nemo-window-manage-views are smart enough to take care of re-using an existent window. M src/nemo-application.c M src/nemo-application.h commit 1936e668c73b932f8cb018e278f8b7f46442fda2 Author: Cosimo Cecchi Date: 2010-08-31 spatial-window: remove affect_location_on_next_change hack M src/nemo-spatial-window.c M src/nemo-spatial-window.h commit f95927360079b1c05efb9cea0de62457eea307ab Author: Cosimo Cecchi Date: 2010-08-31 desktop-window: add a 'loaded' flag M src/nemo-desktop-window.c M src/nemo-desktop-window.h commit 54e0a1f21513babc89f980b5b02af2bf7a6ebe85 Author: Cosimo Cecchi Date: 2010-08-31 window: rewrite window-opening policies The code there was very hackish and convoluted. Rewrite it to make it at least cleaner. This will allow further cleanup later. M src/nemo-window-manage-views.c commit 24515b87a91afd32885e07e32e2b4080584673a4 Author: Cosimo Cecchi Date: 2010-08-31 window: add _full() versions of _go_to and _open() methods These also have a callback to get the result of the operation. M libnemo-private/nemo-window-info.h M libnemo-private/nemo-window-slot-info.c M libnemo-private/nemo-window-slot-info.h M src/nemo-window-manage-views.c M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 42cc7bd181d2f57dbc008bea54a40f02be40ce39 Author: Cosimo Cecchi Date: 2010-08-31 window-info: move include to nemo-window-private M libnemo-private/nemo-window-info.h M src/nemo-window-private.h commit 8d07a73b28767b7c866fe403e9ac706b8affb8a2 Author: Cosimo Cecchi Date: 2010-09-01 build: don't include marshals we don't own M libnemo-private/nemo-directory.c M libnemo-private/nemo-icon-container.c M src/file-manager/fm-directory-view.c M src/nemo-pathbar.c M src/nemo-window.c M src/nemo-zoom-control.c commit 6d3398968d9f2520a4b6f4a08e0f4ae65e2207ab Author: Cosimo Cecchi Date: 2010-09-20 list-view: check for model != NULL before unsetting the highlight The model could be NULL there as a result of the view being previously disposed. M src/file-manager/fm-list-view.c commit 7723f508ca8c9bd837a531cb018de16d627f8bd9 Author: Cosimo Cecchi Date: 2010-09-20 Revert "Clear the list model in _finalize() instead of _dispose()" This reverts commit bfe278cbf84a441a951d48dc528f20226127e1f3. M src/file-manager/fm-list-view.c commit 2e32fc01537bb2c86d9d9bbb6cc5ab2713bd723e Author: Timo Jyrinki Date: 2010-09-20 Updated Finnish translation. M po/fi.po commit 8deeb8471034b90b83ecb0e4bde0cf852e275d24 Author: Cosimo Cecchi Date: 2010-09-19 build: require GLib 2.27.0 Due to GApplication, which has been removed from 2.25.x M configure.in commit a4f454825861c1fb65e8d52979a67a81c5133974 Author: Cosimo Cecchi Date: 2010-09-19 desktop-icon-view: initialize allocation before setting it This probably fixes a number of stack-corruption crashes on 2.31.x M src/file-manager/fm-desktop-icon-view.c commit 00df45be2c133f849267f1ae485d95f672744690 Author: Cosimo Cecchi Date: 2010-09-19 build: require GTK+ 2.90.7 for GDK_KEY names M configure.in commit 78e37ae9a18925d75cf90424d92c8d3ba502848a Author: Cosimo Cecchi Date: 2010-09-19 [ui] remove 'has_separator' properties from Glade files M src/nemo-bookmarks-window.ui M src/nemo-file-management-properties.ui commit 71fa1a50145a6f06da3b805a29e75c1295fd546b Author: Cosimo Cecchi Date: 2010-09-19 [src] convert to new GDK_KEY prefix M src/file-manager/fm-directory-view.c M src/file-manager/fm-list-view.c M src/file-manager/fm-properties-window.c M src/nemo-bookmarks-window.c M src/nemo-location-entry.c M src/nemo-navigation-bar.c M src/nemo-places-sidebar.c M src/nemo-query-editor.c M src/nemo-search-bar.c M src/nemo-side-pane.c M src/nemo-spatial-window.c M src/nemo-window.c M src/nemo-zoom-control.c commit 8ee5d37f2b4776730247af75a6ce4cebcba4c550 Author: Cosimo Cecchi Date: 2010-09-19 thumbnails: don't use GDK_THREADS_* macros M libnemo-private/nemo-thumbnails.c commit 8dd87483bd187bfac80a606233b769c230343980 Author: Cosimo Cecchi Date: 2010-09-19 autorun: use gdk_error_trap_pop_ignored() M libnemo-private/nemo-autorun.c commit aeb53075ed55dc2a2ef3228917ded1b8029bfdff Author: Cosimo Cecchi Date: 2010-09-19 entry: rename GtkEditableClass->GtkEditableInterface M libnemo-private/nemo-entry.c commit 64dcbea2a005e4ed8bb4945d06a943058b8c7ba8 Author: Cosimo Cecchi Date: 2010-09-19 [ln-p] convert to new GDK_KEY prefix M libnemo-private/nemo-autorun.c M libnemo-private/nemo-entry.c M libnemo-private/nemo-icon-container.c commit 499c54a20b64051e427ff5746fc7c8dd1a1885c2 Author: Cosimo Cecchi Date: 2010-09-19 [eel] convert to new GDK_KEY prefix M eel/eel-editable-label.c commit a58bbde4ca6b11eeb1bca5fa4e62e60c0b26271b Author: Cosimo Cecchi Date: 2010-09-19 editable-label: rename GtkEditableClass->GtkEditableInterface M eel/eel-editable-label.c commit 73e2941f9b837d5d0326e6e88caa7a1e3fdcabeb Author: Cosimo Cecchi Date: 2010-09-19 Don't use gtk_dialog_set_has_separator() M libnemo-private/nemo-autorun.c M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-open-with-dialog.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-properties-window.c M src/nemo-connect-server-dialog.c M src/nemo-location-dialog.c M src/nemo-query-editor.c commit b66ce0fd23500f9727c1aac93366430285575697 Author: Cosimo Cecchi Date: 2010-09-19 Don't use GDK_DISPLAY () M libnemo-private/nemo-autorun.c M src/file-manager/fm-desktop-icon-view.c commit 36836b7dc517a588b34117e05a45bc4026e77f71 Author: Cosimo Cecchi Date: 2010-09-19 Use gtk_size_request_get_size() M eel/eel-editable-label.c M libnemo-private/nemo-horizontal-splitter.c M libnemo-private/nemo-icon-container.c M src/nemo-pathbar.c M src/nemo-side-pane.c M src/nemo-spatial-window.c M src/nemo-zoom-control.c commit 93022eda89f650a82f8a17e332973ab88b2318a8 Author: Žygimantas BeruÄka Date: 2010-09-18 Updated Lithuanian translation M po/lt.po commit cfada2b36dd274b2d2835753fc87c69affbbba58 Author: Cosimo Cecchi Date: 2010-09-17 pathbar: use another way to remove buttons (#627901) This fixes a crasher in _size_allocate() where the list of buttons did not contain valid data anymore. M src/nemo-pathbar.c commit 476d45bfd1dd71595e7d38f4d18c761fe2a85b78 Author: Cosimo Cecchi Date: 2010-09-17 Don't check for the eject button if the row doesn't have it (#628347) This sometimes caused false positives in the click-on-eject-button detection method. M src/nemo-places-sidebar.c commit bfe278cbf84a441a951d48dc528f20226127e1f3 Author: Cosimo Cecchi Date: 2010-09-17 Clear the list model in _finalize() instead of _dispose() We have the only reference to the model anyway. This fixes a crash when _end_loading() is called for a windiow before it finished loading. M src/file-manager/fm-list-view.c commit 46544c9885b7064c216f1a9401d42bdb9816bdd2 Author: Cosimo Cecchi Date: 2010-09-17 preferences: use right link for the 'Media' help page (#564866). M src/nemo-file-management-properties.c commit 31ebe40c4a68db4a1fc57e1c942b2d94efce5a42 Author: Kenneth Nielsen Date: 2010-09-16 Updated Danish translation M po/da.po commit f9a85779d9ac73f280358bd96417ea69f2694361 Author: Ivar Smolin Date: 2010-09-14 [l10n] Updated Estonian translation M po/et.po commit 72a4af08ca5139d5ad6511667dbe5631e5962ae7 Author: Ivar Smolin Date: 2010-09-13 [l10n] Updated Estonian translation M po/et.po commit 2c5a174abaeb3ce79bde382617289e358a59b102 Author: Takayuki KUSANO Date: 2010-09-13 Updated Japanese translation. M po/ja.po commit a3213bb051bb1843e7a0c1a2d47d865219b47dcd Author: Luca Ferretti Date: 2010-09-12 Updated Italian translation M po/it.po commit 802146d70642abf27a4f7dde398f775545da3794 Author: Duarte Loreto Date: 2010-09-12 Updated Portuguese translation M po/pt.po commit 4dd8de5b24c7c9774b62207cbc067b715af6942d Author: Mario Blättermann Date: 2010-09-12 [i18n] Updated German translation M po/de.po commit 8962e6db60a335e72046e2444d9c02e7d3e1182f Author: Wouter Bolsterlee Date: 2010-09-12 Updated Dutch translation by Wouter Bolsterlee M po/nl.po commit 60af1701491afbf686d1610ef7aad253f2904432 Author: Wouter Bolsterlee Date: 2010-09-12 Updated Dutch translation by Hannie Dumoleyn M po/nl.po commit f9ccf920434ba6795e4e62f3c95f927532f023c6 Author: Christian Kirbach Date: 2010-09-12 [i18n] Updated German translation M po/de.po commit e20fd8287c710dd5fcd15ed6a46efe3e5dea1b8a Author: Bruce Cowan Date: 2010-09-11 Updated British English translation M po/en_GB.po commit 1dc64c6c1ebba6a5434be80babc78e40c9dacdd7 Author: Fran Diéguez Date: 2010-09-11 Updated Galician translations M po/gl.po commit d37b72c14326182e51e797fc3af5ab9d5f310fb8 Author: Ask H. Larsen Date: 2010-09-11 Updated Danish translation M po/da.po commit adba30e6655ddf85edb179fff6626aec43520894 Author: Cosimo Cecchi Date: 2010-09-11 list-view: properly setup the editable widget (#627076) M src/file-manager/fm-list-view.c commit 265e669b9380eb11ef8ac928cce597d05dd70c7b Author: Cosimo Cecchi Date: 2010-09-10 Make file conflict strings i18n-friendly Thanks to Wouter Bolsterlee for the initial patch. M libnemo-private/nemo-file-conflict-dialog.c commit af61c416ffc291032bb2e199a03b7b071f0a77eb Author: Jorge González Date: 2010-09-09 Updated Spanish translation M po/es.po commit 2cab30a8acdca5d63937d129bdff12118a8b5cb3 Author: Jorge González Date: 2010-09-09 Updated Spanish translation M po/es.po commit fa28706c9878e0123fa4ce5576d4e4f37a91f23a Author: Takayuki KUSANO Date: 2010-09-10 Updated Japanese translation. M po/ja.po commit 94275d4a786eba1dd51d020912fa74d9b19d91ad Author: Piotr DrÄ…g Date: 2010-09-07 Updated Polish translation M po/pl.po commit 51f313e623c282d4540728e0adedbb7b0e6a21ec Author: Daniel Nylander Date: 2010-09-05 Updated Swedish translation M po/sv.po commit e3519b6a8a22d9d9b6e7b421ec5ead1654f456db Author: Matej UrbanÄiÄ Date: 2010-09-04 Updated Slovenian translation M po/sl.po commit 459216c23d064f7e2f194251a787f8f6365c29e2 Author: drtv Date: 2010-09-03 Updated Tamil translation M po/ta.po commit 9d98055c4547b0e2e7cb8920d5d1436178277a16 Author: drtv Date: 2010-09-03 Updated Tamil translation M po/ta.po commit 5a74a9e3ebab733a25afb7f73940757c698ed850 Author: Wouter Bolsterlee Date: 2010-09-02 Fix small error in Dutch translation M po/nl.po commit 430980aca7f1231df970c980e03847c02485ed34 Author: Michael Kotsarinis Date: 2010-08-31 l10n: Updated Greek translation M po/el.po commit 4f579bcdf37b188853ec1076954680bc91e175f6 Author: Bruce Cowan Date: 2010-08-31 Updated British English translation M po/en_GB.po commit 1989b4be7d56d120c8fc57e40cba6155dcbae905 Author: Mattias Põldaru Date: 2010-08-31 [l10n] Updated Estonian translation M po/et.po commit d0086feb65c640926066dcc9d263153227e1a3c1 Author: Gabor Kelemen Date: 2010-08-30 Updated Hungarian translation M po/hu.po commit da6cdb1d2e2ddea2b46a78a4ea57f496bca6a995 Author: Gabor Kelemen Date: 2010-08-29 Updated Hungarian translation M po/hu.po commit 67c01533ab809e751ec2ceb3a81fd50c9c85ef2b Author: Ivar Smolin Date: 2010-08-29 [l10n] Updated Estonian translation M po/et.po commit ff83456b73cd2f6340fd0da57788f3c7c48b455b Author: Dirgita Date: 2010-08-29 Updated Indonesian translation M po/id.po commit e3c8b309386f4040b4c8853d78b8709e12fb4de8 Author: Mattias Põldaru Date: 2010-08-27 [l10n] Updated Estonian translation M po/et.po commit e6feba5047dc17decbda673d8df2de0dbb089140 Author: Bruno Brouard Date: 2010-08-26 Updated French translation M po/fr.po commit f233f2aeb78e5fd14c0b18f7a3c5e80b5e7c84c5 Author: Cosimo Cecchi Date: 2010-08-26 connect-dialog: don't use EEL boilerplate M src/nemo-connect-server-dialog.c commit 0f70ac4bb782b3c3fb0f5e8a24032cb344fdb2cc Author: Cosimo Cecchi Date: 2010-08-26 sidebar: don't try to add non-existing special dirs M src/nemo-places-sidebar.c commit 8277ddc798fc78793364b54444fa53e9a287b5cc Author: Cosimo Cecchi Date: 2010-08-26 sidebar: don't allow selecting headers M src/nemo-places-sidebar.c commit 0f7e56b5e0ae5134ed1d8caeadcb3c684ae7f661 Author: Cosimo Cecchi Date: 2010-08-26 sidebar: add myself to the authors M src/nemo-places-sidebar.c commit 1fdfa522da3e7c672fe4202c591a928c8796bb06 Author: Cosimo Cecchi Date: 2010-08-26 sidebar: fix bookmark renaming Regression of the new sidebar. M src/nemo-places-sidebar.c commit 2f847f37f429062d58df3927d10bc52c67a4524f Author: Cosimo Cecchi Date: 2010-08-26 icon-names: fix a typo M libnemo-private/nemo-icon-names.h commit 0dc6f5ddf472ba2033cdee0ba41cf78696e4017f Merge: ce419d9 a59e586 Author: Cosimo Cecchi Date: 2010-08-25 Merge branch 'sidebar_revamp' commit a59e586adf32eea64c9c4ae08a5482d2a9c37fb1 Author: Cosimo Cecchi Date: 2010-08-25 sidebar: redesign the Places sidebar According to http://live.gnome.org/Nemo/UIRoadmap/Places M src/nemo-places-sidebar.c commit 2d9d47254908533d1eb20e16e091f91310052e93 Author: Cosimo Cecchi Date: 2010-08-25 sidebar: fix eject button highlighting M src/nemo-places-sidebar.c commit 1df83c6586560a8ae5efc96037e673e52b4b119b Author: Cosimo Cecchi Date: 2010-08-25 icon-info: add a method to fetch GIcons for user special dirs M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-icon-info.h M libnemo-private/nemo-icon-names.h commit ce419d9bc7536af2e5e4f0c6122b79070cadddca Author: Aurimas ÄŒernius Date: 2010-08-23 Updated Lithuanian translation M po/lt.po commit 1346a15744ce3aa7f8f52aade250d6a303b33bf2 Author: Aron Xu Date: 2010-08-23 Update Simplified Chinese translation. M po/zh_CN.po commit fd75e8f5e8b160eaba22ca4ed7efc852dba612a0 Author: Cosimo Cecchi Date: 2010-08-22 pathbar: release the highlight path on dispose M src/nemo-places-sidebar.c commit 6f5777b81958ce6f3dbc6bac3323d423d3dcc20b Author: Cosimo Cecchi Date: 2010-08-22 sidebar: don't update the icon if it's not visible This greatly reduces the number of times we have to create a pixbuf (only once-per-highlight now). M src/nemo-places-sidebar.c commit a43bc7def3976947b9624113d18167211e76f9b8 Author: Cosimo Cecchi Date: 2010-08-22 pathbar: make sure |path| is always valid and memory released M src/nemo-places-sidebar.c commit f4ae07c8741d2e8cc6b96450c8bb86e532b59137 Author: Cosimo Cecchi Date: 2010-08-22 sidebar: use _icon_info_lookup_from_name () M src/nemo-places-sidebar.c commit 63b2cac301970847f76f7bdbd12835117958d9be Author: Marcus Carlson Date: 2010-08-06 Add highlight to eject icon in places sidebar (#544103) M src/nemo-places-sidebar.c commit 3abe144501fcff60a65ebd621a51b45ffa5d113d Author: Cosimo Cecchi Date: 2010-08-22 Release 2.90.1 M NEWS M po/POTFILES.in commit 1f64e4b0dd9729976a16d2cf14a6b7c6691ded1e Author: Cosimo Cecchi Date: 2010-08-21 [ln-p] remove unused NemoKeepLastVerticalBox M libnemo-private/Makefile.am D libnemo-private/nemo-keep-last-vertical-box.c D libnemo-private/nemo-keep-last-vertical-box.h commit ad5e896e1ce04485a115ee684a695b42ea0378a5 Author: Cosimo Cecchi Date: 2010-08-21 [eel] reorganize Makefile.am M eel/Makefile.am commit 7e8d1dfa6a17fe9189bf2489b735cd6462f03571 Author: Cosimo Cecchi Date: 2010-08-21 [eel] remove eel_gdk_window_focus M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 6b06e0e27ca1cf29afd4fac716c58e15928a8ff8 Author: Cosimo Cecchi Date: 2010-08-21 icon-container: use gdk_window_focus M libnemo-private/nemo-icon-container.c commit fe94a33657d55a2463fa066e09a8ecbfc637c4bd Author: Cosimo Cecchi Date: 2010-08-21 [eel] remove EelAlertDialog This is unused now. M eel/Makefile.am D eel/eel-alert-dialog.c D eel/eel-alert-dialog.h commit 82c5b6c0d82ebd8a705d542fcc9aa58e6e9b0da4 Author: Cosimo Cecchi Date: 2010-08-21 [eel] use GtkMessageDialog for stock dialogs Instead of EelAlertDialog, which is going away. M eel/eel-stock-dialogs.c commit 930af7f3058eed256a42c0c1558c7307bb93f411 Author: Cosimo Cecchi Date: 2010-08-21 tree-view: don't include eel-alert-dialog.h M src/file-manager/fm-tree-view.c commit 7a3dcdd4bf667aac271be74988770e18575a7df2 Author: Cosimo Cecchi Date: 2010-08-21 mime-actions: use GtkMessageDialog Instead of EelAlertDialog, which is going away. M libnemo-private/nemo-mime-actions.c commit 51ec5861ca0697e802e8c003053211ac12f2fd54 Author: Cosimo Cecchi Date: 2010-08-21 file-operations: use GtkMessageDialog Instead of EelAlertDialog, which is going away. M libnemo-private/nemo-file-operations.c commit a2b4de80a94b4e049f1d2a7ef00a174865b5c9ec Author: Cosimo Cecchi Date: 2010-08-21 [eel] add an utility to pack details into a message dialog So that we can remove EelAlertDialog. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 394cb741c3e59df66f924771d4ef68866e602faa Author: Cosimo Cecchi Date: 2010-08-21 [eel] remove eel_gtk_signal* utilities These are unused now. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 57b66862a53298468755e12ca3712569274f0a32 Author: Cosimo Cecchi Date: 2010-08-21 [eel] remove functions to set widget backgrounds These are unused now. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 472f3e1433ecb3d5e1a7fc8707975f45dd8d0469 Author: Cosimo Cecchi Date: 2010-08-21 [eel] remove functions to handle accelerators These are unused now. M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit cab696f7d760f5ee63f0a623b13d27b76d2f2d00 Author: Cosimo Cecchi Date: 2010-08-21 bk-window: don't use _event_is_close_accelerator() M src/nemo-bookmarks-window.c commit f4432dfba1e8f545d3aeeed5989bd30bba52d160 Author: Cosimo Cecchi Date: 2010-08-21 slot: cleanup previous commit There was an unused variable left M src/nemo-window-slot.c M src/nemo-window-slot.h commit 712cf85b9c44fc93b8f506bfb03ea06cb58eb5e6 Author: Cosimo Cecchi Date: 2010-08-21 Add a border around info bars (#621366). M src/file-manager/fm-directory-view.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit 93798c75a1ae3cbd3a85a4ce79b5521b562a7074 Author: Cosimo Cecchi Date: 2010-08-21 spatial-window: cleanups - Don't do anything else than checking/scheduling a source in the conifigure-event callback - Avoid useless roundtrips through GFile - Avoid some casts, so we don't do useless type-checking in a row on the same object M src/nemo-spatial-window.c commit 5973bc50618d1fe69247e3e2ec6eb8cf3213000b Author: Cosimo Cecchi Date: 2010-08-21 window: remove dead prototypes M src/nemo-window-private.h M src/nemo-window.h commit ef13366e667f848adc6b96509612e3321554d188 Author: Cosimo Cecchi Date: 2010-08-21 desktop-window: cleanups M src/nemo-desktop-window.c commit eb88f44bd27e11607cb5466c943b9caad0202110 Author: Cosimo Cecchi Date: 2010-08-21 window: remove dead function M src/nemo-window.c M src/nemo-window.h commit cf152f9ec75714af2b14be2750f9ea84daab361a Author: Cosimo Cecchi Date: 2010-08-21 undo-manager: remove dead code M libnemo-private/nemo-undo-manager.c M libnemo-private/nemo-undo-manager.h commit 90eb723490ab0338d3d2f1acd02ae5af5fdea819 Author: Cosimo Cecchi Date: 2010-08-20 about: add some authors and update year M src/nemo-window-menus.c commit 21e75511d2466bd814a31031472323d3cd8ae6c1 Author: Cosimo Cecchi Date: 2010-08-20 [file-manager] autogenerate marshallers M src/file-manager/Makefile.am M src/file-manager/fm-directory-view.c commit 608918449f548b0d3ea3e7916c944b077ac43e87 Author: Cosimo Cecchi Date: 2010-08-20 [src] autogenerate marshallers M src/Makefile.am M src/nemo-query-editor.c M src/nemo-window.c commit 6509c91b48f52c72c868f2ca7a9b47c46b9e0bc6 Author: Cosimo Cecchi Date: 2010-08-20 [ln-p] autogenerate marshallers M libnemo-private/Makefile.am M libnemo-private/nemo-icon-container.c D libnemo-private/nemo-marshal.c D libnemo-private/nemo-marshal.list commit 75a03a440ebff23ccbf8674ca4a0e9f6475ebbb8 Author: Cosimo Cecchi Date: 2010-08-20 [eel] simplify build system We don't need the enumtypes anymore, and the marshallers can easily be autogenerated. M eel/Makefile.am M eel/eel-background.c D eel/eel-types.c D eel/eel-types.h M eel/eel.h D eel/eelmarshal.list D eel/makeenums.pl D eel/maketypes.awk D eel/update-from-egg.sh commit 52a37d6e46fc34cef6061bc91aa02847652f3c9d Author: Cosimo Cecchi Date: 2010-08-20 [ln-p] remove unused nemo-iso9660.h M libnemo-private/Makefile.am D libnemo-private/nemo-iso9660.h commit 1d660252b408f3628a2d3d5943abcf6bfdd9091b Author: Cosimo Cecchi Date: 2010-08-20 tree-model: only display the first emblem Only display the first emblem we can render. M src/file-manager/fm-tree-model.c commit 5c08250adf30f2e24b4455fd3c08e81dc3ff4987 Author: Cosimo Cecchi Date: 2010-08-20 list-model: display only the first emblem Only display the first emblem we can render. M src/file-manager/fm-list-model.c commit 110a0e8f2b9ec96b34e4b76390e3f78adc9cda30 Author: Cosimo Cecchi Date: 2010-08-20 icon-info: add nemo_icon_theme_can_render() M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-icon-info.h commit 25b48e9d1f4c847e2fc95b9b9893e63ba7081658 Author: Cosimo Cecchi Date: 2010-08-19 [ln-p] remove NemoCellRendererPixbufEmblem It's useless now. M libnemo-private/Makefile.am D libnemo-private/nemo-cell-renderer-pixbuf-emblem.c D libnemo-private/nemo-cell-renderer-pixbuf-emblem.h commit d2cbf993766d7b63f50431ab483035d01c267cdb Author: Cosimo Cecchi Date: 2010-08-19 tree-view: don't use NemoCellRendererPixbufEmblem M src/file-manager/fm-tree-view.c commit 1694d7141bbe4a29e54cff77def697a6c9b4e118 Author: Cosimo Cecchi Date: 2010-08-19 tree-model: use GEmblemedIcon Use GEmblemedIcon instead of a separate column to render emblems. M src/file-manager/fm-tree-model.c M src/file-manager/fm-tree-model.h commit 69740a3c7fd3a2e1cea99c0dc61b3c735993e4bb Author: Cosimo Cecchi Date: 2010-08-19 list-view: don't use NemoCellRendererPixbufEmblem M src/file-manager/fm-list-view.c commit a187f8a4cdcc46f56c0cb03c31b9b7c92c747a88 Author: Cosimo Cecchi Date: 2010-08-19 list-model: use GEmblemedIcon Use GEmblemedIcon instead of other columns to render emblems. M src/file-manager/fm-list-model.c M src/file-manager/fm-list-model.h commit e42ddad5109f193bf8a5b3c0c6cd7cf4b1408300 Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove eel-pango-extensions M eel/Makefile.am M eel/eel-lib-self-check-functions.h D eel/eel-pango-extensions.c D eel/eel-pango-extensions.h M eel/eel.h commit f080b86daeb571def4c092e1524e9adfc7700699 Author: Cosimo Cecchi Date: 2010-08-19 Don't include eel-pango-extensions.h M eel/eel-gtk-extensions.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-icon-canvas-item.c commit 931644a649175b1886dce5cc8e50c21380f8b8b0 Author: Cosimo Cecchi Date: 2010-08-19 [test] remove test-eel-image-scrolled It only increases compilation time M test/Makefile.am D test/test-eel-image-scrolled.c commit 2f202206fee4e1917494e3f4652e22648097c765 Author: Cosimo Cecchi Date: 2010-08-19 [eel] cleanup eel-vfs-extensions M eel/eel-vfs-extensions.c M eel/eel-vfs-extensions.h commit 230581b5d58650c1f50f7d9fda9ab3a1f211361a Author: Cosimo Cecchi Date: 2010-08-19 [eel] cleanup eel-glib-extensions M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit fbccd9bfaa9c983dccc60d040b63b86521306788 Author: Cosimo Cecchi Date: 2010-08-19 [eel] cleanup eel-gnome-extensions M eel/eel-gnome-extensions.c M eel/eel-gnome-extensions.h commit 48c6012e89fb1362e418d4bf56c05614f1515eab Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove unused eel_make_semitransparent() M eel/eel-graphic-effects.c M eel/eel-graphic-effects.h commit 9c9c619ae2d4e9dbdc9be175679abad3a174ca32 Author: Cosimo Cecchi Date: 2010-08-19 [test] remove eel-pixbuf-scale test M test/Makefile.am D test/test-eel-pixbuf-scale.c commit 7ed8e2d7b90489f41ad674aa4758728dce62fa77 Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove unused code from eel-gdk-pixbuf-extensions M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h M eel/eel-lib-self-check-functions.h commit 6b2a053985b8c37aa1038e7a01ab05d7dd15aa2e Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove unused code from eel-gdk-extensions M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit d2fb7d661a639633473c9339ea2004f18ad3fcf2 Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove eel-art-gtk-extensions M eel/Makefile.am D eel/eel-art-gtk-extensions.c D eel/eel-art-gtk-extensions.h M eel/eel.h commit 2bfd4e3694e2f726592bae5341d7e4c7464ec415 Author: Cosimo Cecchi Date: 2010-08-19 [eel] don't include eel-art-gtk-extensions.h M eel/eel-gdk-pixbuf-extensions.c commit 940dddbb6ce26138a5325f8a1352b6be6dc6b4ff Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove eel-debug-drawing M eel/Makefile.am D eel/eel-debug-drawing.c D eel/eel-debug-drawing.h commit 8447fd3670021530b6340829f27f1d689b633d3a Author: Cosimo Cecchi Date: 2010-08-19 [eel] use glib's i18n API instead of eel's M eel/eel-alert-dialog.c M eel/eel-canvas.c M eel/eel-editable-label.c M eel/eel-glib-extensions.c M eel/eel-gnome-extensions.c M eel/eel-stock-dialogs.c M eel/eel-vfs-extensions.c commit 742b9fb1550ceec9284f581c3741c0a864ca82fd Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove eel-i18n.[ch] M eel/Makefile.am D eel/eel-i18n.c D eel/eel-i18n.h commit 296efa481c76046e60481eec119da749fad15ba8 Author: Cosimo Cecchi Date: 2010-08-19 [eel] remove EelGtkContainer M eel/Makefile.am D eel/eel-gtk-container.c D eel/eel-gtk-container.h M eel/eel.h commit 3f68e342205f4446a99c1c18d34f23e33e11cae2 Author: Cosimo Cecchi Date: 2010-08-18 Revert "Add a border around info bars (#621366)." This reverts commit 48c0e19e60eee88f38a6e9c7a51211376a4c90f9. M src/file-manager/fm-directory-view.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit f5e2ed4c8a54340d26097c08eebd0b4d5f7c7cb7 Author: Baurzhan Muftakhidinov Date: 2010-08-18 l10n: Added Kazakh translation for nemo A po/kk.po commit e3b6eaf2a5c251014e9df40ff5d880ce92647db5 Author: Baurzhan Muftakhidinov Date: 2010-08-18 l10n: Added Kazakh (kk) to po/LINGUAS M po/LINGUAS commit 7397d9967125b8ef5ac39d8ad331ed22498d53cd Author: Милош Поповић Date: 2010-08-16 Updated Serbian translation M po/sr.po M po/sr@latin.po commit d433ee1280fd7fa821de5941db1c972124633c29 Author: Cosimo Cecchi Date: 2010-08-14 pathbar: walk the buttons in the right order When a file is gone, walk the button items in the right order, i.e. the reversed one, otherwise we end up removing the entire pathbar. M src/nemo-pathbar.c commit d8cfb36f697bdf9130e36cdb60c375a9b363fbbe Author: Cosimo Cecchi Date: 2010-08-14 pathbar: use g_list_free_1 where appropriate M src/nemo-pathbar.c commit 76ab7b6266b3fd050c11f6365981d21f8c22b364 Author: Cosimo Cecchi Date: 2010-08-14 pathbar: add missing modeline M src/nemo-pathbar.c commit aa43821e73d60804a3f0f2ebafb66aab53b440e1 Author: Cosimo Cecchi Date: 2010-08-13 [ln-p] use the 'outline-stippling' property on DnD M libnemo-private/nemo-icon-dnd.c commit b453aaacb0b17392eacacd8a9e378b7227da6413 Author: Cosimo Cecchi Date: 2010-08-13 [eel] add an 'outline-stippling' property to the rect item M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas-rect-ellipse.h commit b10d8c00395026719dc0840e9d82e682c7c4e436 Author: Cosimo Cecchi Date: 2010-08-13 [ln-p] properly dash the icon when resizing it M libnemo-private/nemo-icon-canvas-item.c commit 29d7b86087f6ab86f6abd6c3c08c4e1d94b92b36 Author: Cosimo Cecchi Date: 2010-08-13 [ln-p] make drawing of resize knobs work again M libnemo-private/nemo-icon-canvas-item.c commit cbdf5829637093c0a5c0a4ff4d303ad184847627 Author: Benjamin Otte Date: 2010-08-13 [ln-p] port nemo-icon-private to cairo drawing M libnemo-private/nemo-icon-private.h commit 34a376c97717cb05187b3d880e991c2d23511109 Author: Benjamin Otte Date: 2010-08-13 [ln-p] port nemo-icon-dnd to cairo drawing M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-icon-dnd.h commit 8eab39c06628da7cf919be77d922024198105f0a Author: Benjamin Otte Date: 2010-08-13 [ln-p] port NemoIconContainer to cairo drawing M libnemo-private/nemo-icon-container.c commit 89bd44de6bb11450b88d9d160593b65d62467579 Author: Benjamin Otte Date: 2010-08-13 [ln-p] port NemoIconCanvasItem to cairo drawing M libnemo-private/nemo-icon-canvas-item.c commit 6c691075c09ec23620484da00ffd43d3dfe0b75b Author: Benjamin Otte Date: 2010-08-13 [ln-p] port NemoDirectoryBackground to cairo drawing M libnemo-private/nemo-directory-background.c commit dfbf8b9b5636dceb3d6291c980d2c349afc849d7 Author: Benjamin Otte Date: 2010-08-13 [ln-p] port NemoCellRendererPixbufEmblem to cairo drawing M libnemo-private/nemo-cell-renderer-pixbuf-emblem.c commit a904f4acd546151ab37ee03bcce87869a805c323 Author: Cosimo Cecchi Date: 2010-08-13 [eel] remove dead code from eel-gtk-extensions M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h commit 172af77cfbdc4910034a100a99aa1ec2cb843495 Author: Benjamin Otte Date: 2010-08-13 [eel] port eel-gdk-pixbuf-extensions to cairo drawing M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h commit 917a27a6f69509720fadd0d50e40dbc87ae9f5d2 Author: Benjamin Otte Date: 2010-08-13 [eel] port eel-gdk-extensions to cairo drawing M eel/eel-gdk-extensions.c M eel/eel-gdk-extensions.h commit 6cb78fb15c89e53e60ee54dc8b773db6ca0def73 Author: Benjamin Otte Date: 2010-08-13 [eel] port EelEditableLabel to cairo drawing M eel/eel-editable-label.c M eel/eel-editable-label.h commit e716f82eea847e5298d773e2689642813db3d36e Author: Benjamin Otte Date: 2010-08-13 [eel] port eel-debug-drawing to cairo drawing M eel/eel-debug-drawing.c commit 759f3401bee333caf6d0ae6ae9820cdadda440e4 Author: Benjamin Otte Date: 2010-08-13 [eel] port EelCanvas to cairo drawing M eel/eel-canvas.c M eel/eel-canvas.h commit 820d4088a4d1768cf7e16de3c8ec0d7ff383f473 Author: Benjamin Otte Date: 2010-08-13 [eel] port EelCanvasRE to cairo drawing M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas-rect-ellipse.h commit 28b6813b77c4776b789231d3c64be3be01748608 Author: Benjamin Otte Date: 2010-08-13 [eel] port EelBackground to cairo drawing M eel/eel-background.c commit a9fece4d5cc759ee5d7c1f1761bbebc597a3d912 Author: Cosimo Cecchi Date: 2010-08-12 Actually check for gsettings-desktop-schemas M configure.in commit 7aca581c68aa1174f635cb79f24ba394f5ae1d3a Author: Cosimo Cecchi Date: 2010-08-12 Bump to 2.90.1 on master. M configure.in commit 8973b8b20308ae6bb24881385597294e1209a2b0 Author: Fran Diéguez Date: 2010-08-11 Updated galician translations M po/gl.po commit c938ed5839ddba4654818dacf437633d168865eb Author: Gheyret T.Kenji Date: 2010-08-11 Added UG translation M po/LINGUAS A po/ug.po commit 8ceed8e258c83975c1a7d4de71884505d64bb572 Author: Daniel Nylander Date: 2010-08-10 Updated Swedish translation M po/sv.po commit d24a302fbaad263c207cd2fded2719cf17753699 Author: Yaron Shahrabani Date: 2010-08-10 Updated Hebrew translation. M po/he.po commit 9db6cf3ed43eebf0ded2aacaaed883eface75e92 Author: Marcus Carlson Date: 2010-08-04 Better (shorter) text when emptying trash (#304336) M libnemo-private/nemo-file-operations.c commit 8598d769993843e1e6529a661fea034785ca0091 Author: Marcus Carlson Date: 2010-08-02 Adds option to open new tab in tab bar context menu (#590714) M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-window.c M src/nemo-window.h commit 489a146546100d6429fb1705c99a23e959838b2c Author: Marcus Carlson Date: 2010-08-09 Removes doublespacing strings (#577535) M libnemo-private/nemo-program-choosing.c commit 69c7b1850cf7125a3289c9a57c8335eb29a7053d Author: Marcus Carlson Date: 2010-08-04 Adds "Free space: " to the end of the current status string (#588641) M src/file-manager/fm-directory-view.c commit 19dc1d9dbf2c1be17d7ad502ba0710e76f5de9ff Author: Marcus Carlson Date: 2010-08-09 Open current folder properties on Alt+Enter and Ctrl+I (#569694) M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml commit 2b107d37a85ff03f84ecb63bb0b356dac43261f0 Author: Marcus Carlson Date: 2010-08-09 Enable scaling of icons on desktop only (#589295) M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-icon-view.h commit 5319feba3457213b656575893eeb973bde37a722 Author: Marcus Carlson Date: 2010-07-31 Hide all windows before closing when closing all windows (#441095) M src/nemo-application.c commit 59799e3e26476382ddd45d311e22db164474bbb2 Author: Marcus Carlson Date: 2010-07-05 Ellipseze bookmarks editing window renderer (#319159) M src/nemo-bookmarks-window.c commit 4bd09dd6ac7771579dc9e5af8779371c569a54ae Author: Andika Triwidada Date: 2010-08-10 Updated Indonesian translation M po/id.po commit 3988f758f0086a3b0cc149a9b7f4ebdc4bb9ef69 Author: Yaron Shahrabani Date: 2010-08-09 Updated Hebrew translation. M po/he.po commit aa27b362af03f198d5e49dbba85d662348d8ae8b Author: Nils-Christoph Fiedler Date: 2010-08-08 Updated LowGerman translation M po/nds.po commit 51ad44b586793dcc040001ae4d4d5c622c0102bb Author: Kjartan Maraas Date: 2010-08-07 Updated Norwegian bokmÃ¥l translation M po/nb.po commit ec99a1028efd2914a7ebaa5c85417168e956f4ef Author: drtv Date: 2010-08-07 Updated Tamil translation M po/ta.po commit 023076ad6a8cc79e8fcb11dfc769c801cbddc5d6 Author: drtv Date: 2010-08-07 Updated Tamil translation M po/ta.po commit 516733dba0f33edab1944649693bba271263daf4 Author: drtv Date: 2010-08-06 Updated Tamil translation M po/ta.po commit 803071c151adb67daaa669cbaa2614181157b82f Author: Fran Diéguez Date: 2010-08-05 Updated Galician translations M po/gl.po commit a9592caff33f54555d71715593879f09cfd6022a Author: Claude Paroz Date: 2010-08-05 Update POTFILES.in M po/POTFILES.in commit 0d33233e110922f614b7378f0ae9f8b94321dd06 Author: Reuben Potts Date: 2010-08-05 Added Manx translation M po/LINGUAS A po/gv.po commit 36add5d8c8107a0c2ed97a64f2a644c2362566a4 Author: Tomas Bzatek Date: 2010-08-05 Remove lockdown from monitored GConf paths M libnemo-private/nemo-global-preferences.c commit 9e219b3750a2cf60897bcd6213957cb9635dc05f Author: Tomas Bzatek Date: 2010-08-05 Require gsettings-desktop-schemas M configure.in commit 3c8b43bf6c10e83d0bd8fd97e0dae7032339ba72 Author: Tomas Bzatek Date: 2010-08-05 Convert disable-command-line lockdown to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c commit f871519fb28449c370448d8032294971ead1f162 Author: Tomas Bzatek Date: 2010-08-05 Remove unused gsettings schema keys M libnemo-private/org.gnome.nemo.gschema.xml.in commit 0c0d34f9cf2448303249122cd3baae6d1e32b93d Author: Tomas Bzatek Date: 2010-08-05 Re-enable commented-out keys in gsettings conversion file Please see bug 626106 for full story. Let's hope data mapping will work one day, for now it makes no issues. M libnemo-private/nemo.convert commit 224ea80bceb93e01cd9676c14e24c27eb556b813 Author: Sense Hofstede Date: 2010-08-04 Updated Frisian translations M po/fy.po commit 60ce7af080842792df21af6ff7fadf4a6674cf60 Author: Dirgita Date: 2010-08-04 Updated Indonesian translation M po/id.po commit 6c71e95a995db6fa15fd97fb314152481676b23a Author: Cosimo Cecchi Date: 2010-08-03 Remove useless code for handling color drops M libnemo-private/nemo-dnd.h M libnemo-private/nemo-file-dnd.c M libnemo-private/nemo-icon-dnd.c commit 5ce852673cc5d5ae45bd042f9ab07916358f349a Author: Cosimo Cecchi Date: 2010-08-03 Use the actual action for GDK_ACTION_ASK drops M libnemo-private/nemo-icon-dnd.c commit 2a980bb67b95c9d6c8218181e8c492869beb126a Author: Tomas Bzatek Date: 2010-07-30 Add GSettings migration file M libnemo-private/Makefile.am A libnemo-private/nemo.convert commit 3ea4de522ddba6ad9313dc3fdf2d6936b130913c Author: Marcus Carlson Date: 2010-08-02 Only show "Organize Desktop by Name" on Desktop (#530136) M src/file-manager/fm-icon-view.c commit f985fe76918ef299e3b580fef8922045c9a4cfed Author: Cosimo Cecchi Date: 2010-08-03 Don't unref the DBus proxy if it's NULL M libnemo-private/nemo-mime-actions.c commit 6d91cfb1d053a433cc5e17336c2e22c4e1d71673 Author: Cosimo Cecchi Date: 2010-08-01 Correctly show the multiple files warning Only show it when we're actually opening files, not folders. M libnemo-private/nemo-mime-actions.c commit 5b31e211ff20645c548949bd8d012b7bcaa39bf2 Author: Ankit Patel Date: 2010-07-27 Updated Gujarati Translations to correct dynamic variables mistakes M po/gu.po commit a1a8f97c9dcd9fdbbbfdddcec7f7d8da85a68dfb Author: Runa Bhattacharjee Date: 2010-07-27 Updated Bengali India Translation M po/bn_IN.po commit 52cf8ee6614dc311412ccecd8ea229d7b8c2a091 Author: Marcus Carlson Date: 2010-07-25 Enter key when combo box has focus validates new media dialog (#589436) M libnemo-private/nemo-autorun.c commit 915e5523947fe049e06f9bd8574760f6765e8ad7 Merge: 84b89c5 e50565b Author: Cosimo Cecchi Date: 2010-07-26 Merge branch 'remove-emblems-splitted' commit e50565bae0943c3bfe7025fc1f9728b07ef6ebd4 Author: Cosimo Cecchi Date: 2010-07-26 Remove sort by emblems in the UI file. M src/nemo-file-management-properties.ui commit 786dfd9d98dd7d313fa9cc33a7ebb500f100262c Author: Cosimo Cecchi Date: 2010-07-26 Remove emblem references from the GSettings schema. M libnemo-private/org.gnome.nemo.gschema.xml.in commit 326e6b14fbb7c106b35993ad3db8f243e38b3e44 Author: Cosimo Cecchi Date: 2010-07-26 Remove useless struct. M libnemo-private/nemo-file-private.h commit edfa318f2624bccba7b002c4176a839bf36136bd Author: Cosimo Cecchi Date: 2010-07-26 Remove useless defines. M libnemo-private/nemo-icon-names.h commit 09778cd3845fd3b6cf890d8263575e1a188fcdb2 Author: Cosimo Cecchi Date: 2010-07-26 Remove useless defines. M libnemo-private/nemo-file.h commit 23c1dbcac260018428949bb954dff65dd774ee11 Author: Cosimo Cecchi Date: 2010-07-26 Readd code to read emblems provided by extensions. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 84b89c5e4c1e7185d053c59fb6b14f72c1670e88 Author: Daniel Nylander Date: 2010-07-25 Updated Swedish translation M po/sv.po commit 2f21906e0f8d54df736a13e38f7b84013f8afb33 Author: Cosimo Cecchi Date: 2010-07-25 [data] remove other unused icons M icons/Makefile.am D icons/backgrounds.png D icons/chit_frame.png D icons/colors.png D icons/emblems.png D icons/erase.png commit 87469500d98babc7d74a74d2e6a88535a1b5ad95 Author: Cosimo Cecchi Date: 2010-07-25 [data] remove patterns M configure.in M data/Makefile.am D data/patterns/Makefile.am D data/patterns/blue_gray_rough.png D data/patterns/blue_ridge.png D data/patterns/blue_type.png D data/patterns/brushed_metal.png D data/patterns/burlap.jpg D data/patterns/camouflage.png D data/patterns/chalk.jpg D data/patterns/cork.png D data/patterns/countertop.png D data/patterns/dark-gnome.jpg D data/patterns/dots.png D data/patterns/fibers.png D data/patterns/fleur_de_lis.png D data/patterns/floral.png D data/patterns/fossil.png D data/patterns/gnome.jpg D data/patterns/green_weave.png D data/patterns/ice.png D data/patterns/manila_paper.png D data/patterns/moss_ridge.png D data/patterns/numbers.png D data/patterns/ocean_stripes.png D data/patterns/purple_marble.png D data/patterns/reset.png D data/patterns/ridged_paper.png D data/patterns/rough_paper.png D data/patterns/sky_ridge.png D data/patterns/snow_ridge.png D data/patterns/stucco.jpg D data/patterns/terracotta.png D data/patterns/wavy_white.png commit b5dd2515600f6dca2543aed45ae5455d9626ae92 Author: Cosimo Cecchi Date: 2010-07-25 [data] remove useless browser file M data/Makefile.am D data/browser.xml commit 1abbbd936663d91c8d4b854a0beed41f64d85f73 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove useless nemo-emblem-utils M libnemo-private/Makefile.am D libnemo-private/nemo-emblem-utils.c D libnemo-private/nemo-emblem-utils.h M src/file-manager/fm-properties-window.c commit f9be00dfbf7e6baa1ee66e3ed0d392b26d23b665 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove unused sort option M src/nemo-file-management-properties.c commit a147dffbf4ffbb11063f820a26537484bc67b558 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove useless variables. M src/file-manager/fm-properties-window.c commit 48df65532da4646db7250452e7cfb731f5773566 Author: Cosimo Cecchi Date: 2010-07-25 Remove [_set/_get]_keywords API from NemoFile. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 988e0ef8c5048ed7add4441f2325a5eb725b728e Author: Cosimo Cecchi Date: 2010-07-25 Remove 'Sort by Emblems' from the views. M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/file-manager/nemo-icon-view-ui.xml commit 4c465f5590f3e908b98197faeb63767193bb6e79 Author: Cosimo Cecchi Date: 2010-07-25 Remove dead code from the properties window. M src/file-manager/fm-properties-window.c commit d58d42c261db94bf0d538698939698f2aeb63d1d Author: Cosimo Cecchi Date: 2010-07-25 Remove code to handle emblems in DnD. M libnemo-private/nemo-dnd.h M libnemo-private/nemo-file-dnd.c M libnemo-private/nemo-file-dnd.h M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-tree-view-drag-dest.c commit 3e1347c1100095b38deb2431a434ad56e543aafa Author: Cosimo Cecchi Date: 2010-07-25 Remove code for handling reset backgorund in DnD. M libnemo-private/nemo-dnd.h M libnemo-private/nemo-file-dnd.c M libnemo-private/nemo-icon-dnd.c M src/file-manager/fm-properties-window.c commit 82bfad0af3902dd22e764a3cae9ad82735aac591 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove unused NemoSidebarTitle M src/Makefile.am D src/nemo-sidebar-title.c D src/nemo-sidebar-title.h commit 41b7e9fe4d944dc9adabd62c35b053bc8099c393 Author: Cosimo Cecchi Date: 2010-07-25 [eel] remove unused eel-xml-extensions. M eel/Makefile.am D eel/eel-xml-extensions.c D eel/eel-xml-extensions.h M eel/eel.h M src/nemo-navigation-window-menus.c M test/test-eel-pixbuf-scale.c commit cc4cbfcde75280055d78c61f867009820efb1749 Author: Cosimo Cecchi Date: 2010-07-25 [ln-p] remove unused NemoCustomizationData M libnemo-private/Makefile.am D libnemo-private/nemo-customization-data.c D libnemo-private/nemo-customization-data.h M src/file-manager/fm-properties-window.c commit 4ba7cefdd56ac289bb157d5d7d99034378efdebe Author: Cosimo Cecchi Date: 2010-07-25 [eel] remove unused EelWrapTable M eel/Makefile.am D eel/eel-wrap-table.c D eel/eel-wrap-table.h M eel/eel.h M src/file-manager/fm-properties-window.c commit 1ad357964e6d4e33a3fa4301245318e6e080385f Author: Cosimo Cecchi Date: 2010-07-25 [eel] remove unused EelLabeledImage M eel/Makefile.am D eel/eel-labeled-image.c D eel/eel-labeled-image.h M eel/eel.h M src/file-manager/fm-properties-window.c M test/Makefile.am D test/test-eel-labeled-image.c D test/test-nemo-wrap-table.c commit 6feed0a28d927a98aa5b09bc6622de1fc146387b Author: Cosimo Cecchi Date: 2010-07-25 [eel] remove unused EelImageTable M eel/Makefile.am D eel/eel-image-table.c D eel/eel-image-table.h M eel/eel.h M test/Makefile.am D test/test-eel-image-table.c commit 28fbb49494879666928a23aa37d36ca0e819d176 Author: Cosimo Cecchi Date: 2010-07-25 [eel] remove unused EelBackgroundBox M eel/Makefile.am D eel/eel-background-box.c D eel/eel-background-box.h commit 83af9319fe2ad9eb8af559dc1934a0fc48ed98ba Author: Cosimo Cecchi Date: 2010-07-25 [src] remove NemoInformationPanel It's old, basically unused, and unmaintained. M src/Makefile.am M src/nemo-application.c D src/nemo-information-panel.c D src/nemo-information-panel.h M src/nemo-navigation-window.h M src/nemo-window.c M src/nemo-window.h commit dc0517bb3462c3da5d7fd2afb31470cc58fac903 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove emblems from the properties window. M src/file-manager/fm-properties-window.c commit b2eb619da772af14f2e4127988a4431eedf212b6 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove NemoEmblemSidebar M src/Makefile.am M src/nemo-application.c D src/nemo-emblem-sidebar.c D src/nemo-emblem-sidebar.h commit c1a69337f031d0fce79fb6f0be52c44670145668 Author: Cosimo Cecchi Date: 2010-07-25 [src] remove NemoPropertyBrowser This is part of a complete removal of the backgrounds/emblems feature. M src/Makefile.am M src/nemo-navigation-window-menus.c D src/nemo-property-browser.c D src/nemo-property-browser.h M src/nemo-shell-ui.xml M src/nemo-window-menus.c commit 92d8c11fb694aaf44b13184c704f7ec792796922 Author: Daniel Nylander Date: 2010-07-25 Updated Swedish translation M po/sv.po commit 6fe90302d79742b7a17449569c47de9b04e83c35 Author: Aron Xu Date: 2010-07-24 Update Simplified Chinese translation. M po/zh_CN.po commit 8497f4011e7c42010b9db669b31a09cae7f57844 Author: Alexander Larsson Date: 2010-07-23 Remove gconf schemas M configure.in M libnemo-private/Makefile.am D libnemo-private/apps_nemo_preferences.schemas.in commit f58f80d4414daa520bd7287999c36b783103b70f Author: Alexander Larsson Date: 2010-07-23 Bump glib requirements for g_settings_reset M configure.in commit 31833fee708e23bb6ed16af045fa59b711076ecf Author: Alexander Larsson Date: 2010-07-23 Remove eel-enumeration, eel-gconf-extensions and eel-preferences M eel/Makefile.am D eel/eel-enumeration.c D eel/eel-enumeration.h D eel/eel-gconf-extensions.c D eel/eel-gconf-extensions.h M eel/eel-lib-self-check-functions.h D eel/eel-preferences-builder.c D eel/eel-preferences.c D eel/eel-preferences.h M eel/eel.h commit ca1c74b6df8a67e305c73adc1893e3552b763835 Author: Alexander Larsson Date: 2010-07-23 Remove last users of eel_preferences and eel_gconf M libnemo-private/nemo-desktop-link-monitor.c M libnemo-private/nemo-directory-background.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-program-choosing.c M src/file-manager/fm-tree-view.c M src/nemo-connect-server-dialog-main.c M src/nemo-file-management-properties-main.c M src/nemo-file-management-properties.c M src/nemo-history-sidebar.c M src/nemo-navigation-window-pane.c M src/nemo-pathbar.c M src/nemo-places-sidebar.c M src/nemo-window-menus.c D test/test-nemo-preferences-display.c M test/test.c commit e85f7b768edd103a48dc18993edd431fd880f5d4 Author: Alexander Larsson Date: 2010-07-23 Convert last eel_preference users to raw gconf This is moslty the lockdown stuff, but we also access the background setting. This should be converted to use the new gsettings when they land. M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/nemo-connect-server-dialog-main.c commit 02bb707335bbee09bb033f69c87baab65f8c8051 Author: Alexander Larsson Date: 2010-07-23 Initialize gsettings in nemo-connect-server M src/nemo-connect-server-dialog-main.c commit f202dab6902b28fdf1deaad7e4d259c50ef6b575 Author: Alexander Larsson Date: 2010-07-23 Remove remnants of old file-limit preference M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory.c M libnemo-private/nemo-directory.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h commit 97bbb3cd5029157fe044ad1949620ed6ee4f2278 Author: Alexander Larsson Date: 2010-07-23 Fix conversion of enable-delete M src/file-manager/fm-directory-view.c commit f495063f73e4949959678280186f99bb801f804b Author: Alexander Larsson Date: 2010-07-23 Move desktop-font preference to desktop settings M libnemo-private/nemo-global-preferences.h M libnemo-private/org.gnome.nemo.gschema.xml.in M src/file-manager/fm-desktop-icon-view.c commit 36c238331d19b9a33f13fcbaf49928f35b78ff8c Author: Alexander Larsson Date: 2010-07-23 Convert list-view preferences to gsettings Also removes unused default-use-manual-layout setting, and joins the sort order preferences of the list view and the icon view. M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-file-management-properties.c commit 000b73a429932d9816aaf5e69cd521675b39b548 Author: Alexander Larsson Date: 2010-07-23 Move the sort order prefs from view-specific to common prefs We already only have one UI setting that controls both, so it makes no sense to have two settings. M libnemo-private/org.gnome.nemo.gschema.xml.in commit 77207d5ff5bade458446d5783fe6a99fc38ac6de Author: Alexander Larsson Date: 2010-07-23 Add eel_g_settings_add_auto_strv M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit 1f2e9750da78aab404f4bda66889c9c5dc6adc94 Author: Alexander Larsson Date: 2010-07-22 Remove unused NEWS side pane prefs M libnemo-private/nemo-global-preferences.h commit 80a26e69ad2383d3aca093ed993e7ff3f8a1bc5b Author: Alexander Larsson Date: 2010-07-22 Convert compact view prefs to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-icon-view.c M src/nemo-file-management-properties.c commit 706efc521fec6035d644600b18afdfe20ac9d472 Author: Alexander Larsson Date: 2010-07-22 Convert tree sidebar prefs to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-tree-view.c M src/nemo-file-management-properties.c commit f6697ac99280f4fd9b8920d52bcc7407fd09c15c Author: Alexander Larsson Date: 2010-07-22 Convert desktop preferences to gsettings M libnemo-private/nemo-desktop-link-monitor.c M libnemo-private/nemo-desktop-link.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-container.c M libnemo-private/org.gnome.nemo.gschema.xml.in M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit 43652872e6b5644c831a9041c9d2e3e22a8ef773 Author: Alexander Larsson Date: 2010-07-22 Fix up desktop-is-home-dir gsettings conversion M libnemo-private/nemo-file-utilities.c commit 831787a7460655ebbac3499d399d72d45b1cdc60 Author: Alexander Larsson Date: 2010-07-22 Fix desktop-font gsettings conversion M src/file-manager/fm-desktop-icon-view.c commit df9c8ce6b162f37fe9372ee8b9e5c4798c9033e0 Author: Alexander Larsson Date: 2010-07-22 Convert icon-view preferences to gsettings M libnemo-private/nemo-file.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-thumbnails.c M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-icon-container.c M src/file-manager/fm-icon-view.c M src/nemo-file-management-properties.c commit 467af3b7e13fcc51ad1ecafd05bbfd4a4f7d9541 Author: Alexander Larsson Date: 2010-07-22 Add some more g_settings auto helpers to eel-glib-extensions M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit 75ade49a17470a86354eb8b591212d512c2ab08b Author: Alexander Larsson Date: 2010-07-22 Convert preview settings to gsettings M libnemo-private/nemo-file.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-icon-view.c M src/nemo-file-management-properties.c commit bcf929af833a83aba7ab58b7ae85697a288d006d Author: Alexander Larsson Date: 2010-07-22 Convert show-directory-item-counts to gsettings M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-file-management-properties.c M src/nemo-sidebar-title.c commit 4b5a2c833296abfb2ea28c0cca45d1a748d8a0d1 Author: Alexander Larsson Date: 2010-07-22 Convert show-text-in-icons to gsettings M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-file-management-properties.c commit 184d31a6773358c1d081c82e508cd4c369e6a711 Author: Alexander Larsson Date: 2010-07-22 Remove unused search-bar-type setting M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h commit 3f87495987c2db24002e48da344e96243a5c70e2 Author: Alexander Larsson Date: 2010-07-22 Convert default-folder-view to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-file-management-properties.c commit 87aa83c53183b02ca78fedf3c39b4ff15ad09e11 Author: Alexander Larsson Date: 2010-07-22 Convert sort-directories-first to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-directory-view.c M src/nemo-file-management-properties.c commit c6a6fb894cf9bd12fbd12977ab5ccd9e58540ae1 Author: Alexander Larsson Date: 2010-07-22 Conver window-state to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-application.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit adee5018f3a4985cf8d538a998f32ed9bb6a6ffd Author: Alexander Larsson Date: 2010-07-22 Convert install-mime-activation to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-mime-actions.c commit a7163bb6c91c40a8dea2e3b6c34623a0449053a4 Author: Alexander Larsson Date: 2010-07-22 convert exit with last window to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-main.c commit e167d6f663fc2c420d939f5cbb24c6463b03e8c2 Author: Alexander Larsson Date: 2010-07-22 Convert new tab position to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-mime-actions.c M src/nemo-navigation-window-menus.c M src/nemo-window-manage-views.c commit 42e9d22c84a3f54dfaa6da39243dd07c18a7cb9c Author: Alexander Larsson Date: 2010-07-22 Convert always-use-browser to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-directory-view.c M src/nemo-application.c M src/nemo-bookmarks-window.c M src/nemo-connect-server-dialog-nonmain.c M src/nemo-file-management-properties.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-window-manage-views.c commit 97d62a1d402853f2dd328a53cb7e94581b8e2498 Author: Alexander Larsson Date: 2010-07-22 Convert click-policy to GSettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-canvas-item.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-file-management-properties.c M src/nemo-history-sidebar.c commit cf4f7f10baa305cc3cbacb0b3c27c1eb45ae65f4 Author: Alexander Larsson Date: 2010-07-22 Convert executable-text-activation to GSettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-mime-actions.c M src/nemo-file-management-properties.c commit e3777c0e025815fd40908ea826f0091ecfe84fb0 Author: Alexander Larsson Date: 2010-07-22 Convert mouse prefs to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-navigation-window.c commit 202b69146a1fb42e147d1ca6f8694b27d8ada28b Author: Alexander Larsson Date: 2010-07-22 Convert date-format to gsettings M libnemo-private/nemo-directory.c M libnemo-private/nemo-file.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-file-management-properties.c commit 4c3067f86f9dfb848ab941ea8a2fb8aeb2c34944 Author: Alexander Larsson Date: 2010-07-22 Add eel_g_settings_add_auto_enum M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit 7abbb99a0e16be6050d61719a6b69197746ed7e4 Author: Alexander Larsson Date: 2010-07-22 Convert show-advanced-persmissions to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-properties-window.c commit 9318df841a5a0ccd0723e2d5dbce8d2ddfd89b1d Author: Alexander Larsson Date: 2010-07-21 Convert show-hidden-files to gsettings and merge it with show-backup-files M libnemo-private/nemo-desktop-directory-file.c M libnemo-private/nemo-desktop-directory.c M libnemo-private/nemo-desktop-icon-file.c M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory-private.h M libnemo-private/nemo-directory.c M libnemo-private/nemo-directory.h M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-merged-directory.c M libnemo-private/nemo-search-directory.c M libnemo-private/nemo-vfs-directory.c M libnemo-private/nemo-vfs-file.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-tree-model.c M src/file-manager/fm-tree-view.c M src/nemo-file-management-properties.c M src/nemo-window-menus.c M test/test-nemo-directory-async.c commit 036ae8def6b46048b8d3db36ae944f3d6c6523de Author: Alexander Larsson Date: 2010-07-21 Initialize global preferences in nemo-file-management-properties M src/nemo-file-management-properties-main.c commit f5b77ef6fb16d0378916a0b9e99161694480a0b3 Author: Alexander Larsson Date: 2010-07-21 Remove declaration of nonexisting functions M libnemo-private/nemo-file-utilities.h commit 8c13219e9a44e90e1e74ea20a440dc763b5892ed Author: Alexander Larsson Date: 2010-07-21 Convert desktop preferences to gsettings M libnemo-private/nemo-desktop-directory.c M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-desktop-icon-view.c M src/nemo-application.c M src/nemo-main.c M src/nemo-pathbar.c M src/nemo-places-sidebar.c commit 77f7a0378921b98f9b9bd0347acc25aabaa954dd Author: Alexander Larsson Date: 2010-07-21 Convert enable-delete to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-tree-view.c M src/nemo-file-management-properties.c commit 85cd2e45893a561ebd739c9bca595a1ef9a4f136 Author: Alexander Larsson Date: 2010-07-21 Convert confirm-trash preference to gsettings M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-directory-view.c M src/nemo-file-management-properties.c commit 924e9ee3ad889d9a8abc63c79c79c1cb25aaf0cf Author: Alexander Larsson Date: 2010-07-21 Convert media handling preferences to gsettings M libnemo-private/nemo-autorun.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-application.c M src/nemo-file-management-properties.c commit d6ab21e01e525f7c18b6c592802cc4f3b8764665 Author: Alexander Larsson Date: 2010-07-21 Convert side pane width to gsettings M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-navigation-window.c commit df4dcf7dc10b40af61e2922dbfd728ffdb575e76 Author: Alexander Larsson Date: 2010-07-21 Convert side pane background to gsettings M libnemo-private/nemo-global-preferences.h M src/nemo-information-panel.c commit 352e84790d3738a8d1e965ccd0f911c290dfef5d Author: Alexander Larsson Date: 2010-07-21 Convert background prefs to GSettings M libnemo-private/nemo-directory-background.c M libnemo-private/nemo-global-preferences.h commit 096b906da1e22b9ece5e568f195961ac40cae542 Author: Alexander Larsson Date: 2010-07-21 Create the global nemo_preferences GSettings object M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h commit c70466a133e6ca670e998af11bdc39aa2aec4825 Author: Alexander Larsson Date: 2010-07-21 Remove deprecated prefs for nemo theme M libnemo-private/nemo-directory-background.c M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-icon-container.c M src/nemo-property-browser.c commit a31e758e00b714a6897ebc6adf11c1599455b7f6 Author: Alexander Larsson Date: 2010-07-21 Rename sidebar ids as per the new gsettings pref names M src/file-manager/fm-tree-view.h M src/nemo-emblem-sidebar.h M src/nemo-history-sidebar.h M src/nemo-information-panel.h M src/nemo-notes-viewer.h M src/nemo-places-sidebar.h commit b33acb0abea58b2e980876ccde9fdc3bfce5c589 Author: Alexander Larsson Date: 2010-07-21 Add GSettings schemas for nemo M configure.in M libnemo-private/Makefile.am A libnemo-private/org.gnome.media-handling.gschema.xml.in A libnemo-private/org.gnome.nemo.gschema.xml.in commit ac038a0d90a4d59b564803be2698bc883672ab84 Author: Tomas Bzatek Date: 2010-07-21 Set default value for the navigation_window_saved_maximized gconf key And avoid gconftool messages like WARNING: Failed to parse default value `' for schema (/schemas/apps/nemo/preferences/navigation_window_saved_maximized) M libnemo-private/apps_nemo_preferences.schemas.in commit d992764b81b8b77efd0a68629372b569fb09dd11 Author: Fran Diéguez Date: 2010-07-21 Updated Galician translations M po/gl.po commit fed4221b81043420447bc45502314a4c1b6b12d6 Author: Chao-Hsiung Liao Date: 2010-07-20 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit bed28df1062042de23e939aeda409a9fc35d8eac Author: Mario Blättermann Date: 2010-07-18 [i18n] Updated German translation M po/de.po commit c7aae474dd404a015beb7413bab7d6d517ff2951 Author: Jorge González Date: 2010-07-18 Updated Spanish translation M po/es.po commit ab1ddd9e2bb2401a32cc0ebc587401b815504bd5 Author: Yaron Shahrabani Date: 2010-07-18 Updated Hebrew translation. M po/he.po commit faf1c74e479a6fb44fc1b51ee8e3319ee646cb81 Author: Sense Hofstede Date: 2010-07-18 Updated Frisian translations and added the language to LINGUAS M po/LINGUAS A po/fy.po commit b8f5d27f7deadb985d7574bc0547f2c616d8e9b9 Author: Cosimo Cecchi Date: 2010-07-17 Don't set a NULL argv for GApplication (#624508) M src/nemo-application.c commit 521e3c8481fcf2af398d2ed62692d415448386cd Author: Cosimo Cecchi Date: 2010-07-17 Refer to 3.0 instead of 2.32 in a string (#624286) M src/nemo-application.c commit b145c20c58e465114d372590e460a98c40a770dc Author: Diego Escalante Urrelo Date: 2010-07-15 nemo-recent: gtk_recent_manager_set_limit is deprecated Views are expected to filter results on their own, not the model. Bug #624506 M libnemo-private/nemo-recent.c commit 24bfbbb615a507b005d3b8d4bdea9efd69387ea0 Author: Mario Blättermann Date: 2010-07-16 [i18n] Updated German translation M po/de.po commit 837ed1bf4741550b9c41f041ee418af1912ee320 Author: Yaron Shahrabani Date: 2010-07-16 Updated Hebrew translation. M po/he.po commit 397f9a3b66edfde3974256c7c4ac3e031ef99328 Author: Diego Escalante Urrelo Date: 2010-07-13 Update GtkNotebook callbacks to gtk+ master GtkNotebookPage is gone in switch-page, it's just a GtkWidget now. Bug #624295 M src/nemo-navigation-window-pane.c M src/nemo-side-pane.c commit e3b7cebba5c6be648286905fe116e744eb532f16 Author: du baodao Date: 2010-07-15 Update Simplified Chinese translation. M po/zh_CN.po commit fe2322d56aace170295ba51221d0ad0cc66a1c17 Author: Paolo Borelli Date: 2010-07-15 Remove leftover comments. These eel functions do not exist anymore. M eel/eel-gdk-extensions.c commit 5fab3e456c7bf05bb2b080ef97b7aa1470390806 Author: Lucian Adrian Grijincu Date: 2010-07-15 po: Updated Romanian translation completed translation M po/ro.po commit a13a4faf32ab442734a11bf2d3855007231f8b6a Author: Lucian Adrian Grijincu Date: 2010-07-15 po: Updated Romanian translation media & trash consistency. M po/ro.po commit cde01839725762691f663d6d7cfec710024781b1 Author: Lucian Adrian Grijincu Date: 2010-07-14 po: Updated Romanian translation Signed-off-by: Lucian Adrian Grijincu M po/ro.po commit aea71b38892a2a0932472521d0414f8ad4ce9939 Author: Kjartan Maraas Date: 2010-07-13 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 683c15d3400988e5458ad91036b000c47859dec5 Author: Fran Diéguez Date: 2010-07-13 Updated Galician translations M po/gl.po commit 92076643ef6b11b9ffe5c9624ad50dccc2b6269e Author: Cosimo Cecchi Date: 2010-07-12 Release 2.31.5. M NEWS M configure.in commit 8ef7a9a1a1bdd02926b8b1fe59a6e97cf6c69574 Author: Marcus Carlson Date: 2010-07-10 Adds key binding for expanding and collapsing folders in list view https://bugzilla.gnome.org/show_bug.cgi?id=504869 M src/file-manager/fm-list-view.c commit 525b54d9a2385efdae21fd0b0da3631ba0071ce1 Author: Marcus Carlson Date: 2010-07-11 Ask for confirmation before opening more than 5 files (#596577) M libnemo-private/nemo-mime-actions.c commit b6fa38579dae68afd5b6ac71c98f7868e0a1731a Author: Marcus Carlson Date: 2010-07-10 Remove unnecessary include and remove a FIXME (#544211) Include of nemo-desktop-window.h in nemo-window.c is not needed anymore M src/nemo-window.c commit f12805d978c576e5f93f48815565f6e02fdd38ff Author: Marcus Carlson Date: 2010-07-10 Eat Control + v to not enable type ahead (#350819) M libnemo-private/nemo-icon-container.c M src/file-manager/fm-list-view.c commit 0a1cf043c9ec90b7b3da7e454eb860c5e2347866 Author: Marcus Carlson Date: 2010-07-11 Also change filename on disk when renaming a .desktop file (#145125) M libnemo-private/nemo-file.c commit 0fb0e54f06ec1090a0e3267a48bc66cc50603e82 Author: Marcus Carlson Date: 2010-07-10 Fixed typo (#624055) M src/nemo-file-management-properties.ui commit 34936ae8336e32359b3cc36b1bb2ba850313f4f5 Author: Marcus Carlson Date: 2010-07-10 Change clicked signal to toggled to not get into bad state (#440435) M src/nemo-property-browser.c commit a0bd71abc1d664d2ae3b949a3181041cdc162f2c Author: Cosimo Cecchi Date: 2010-07-10 Compile cleanly with GCC 4.5. M libnemo-private/nemo-directory-background.c M libnemo-private/nemo-icon-dnd.c M src/nemo-information-panel.c commit cd447610e3a8b32ec85d32cac7a12efcc33238ee Author: Fran Diéguez Date: 2010-07-07 Updated Galician translations M po/gl.po commit 8c033772f9ddf816103a21a6689e8a18831090fa Author: Marcus Carlson Date: 2010-07-05 Remove "Browse Folder" on Desktop when browsing is set to default (#563829) M src/file-manager/fm-directory-view.c commit 1f6f65c9547b430eb1414758a50d2aeea142869e Author: Marcus Carlson Date: 2010-07-05 Don't eat Alt+Right/Left in icon container So they do not interfere with history browsing https://bugzilla.gnome.org/show_bug.cgi?id=411664 M libnemo-private/nemo-icon-container.c commit e23140e8aea753ebb4195f1cfe728c62367fbdeb Author: Jorge González Date: 2010-07-04 Updated Spanish translation M po/es.po commit aca606ed03617ed15dc87ad34c1e0b72eda72928 Author: A. Walton Date: 2010-07-04 Use the correct icon for autorunning Open Folder According to the HIG, this icon should be 'folder-open'. This closes GNOME bug #608060. M libnemo-private/nemo-autorun.c commit c71ac3d1e00c3013a6736ac6dcf3ad074380b8a3 Author: YunQiang Su Date: 2010-07-04 Updated zh_CN translation. M po/ChangeLog M po/zh_CN.po commit 6b65b65f773e2ad27a23d40194b64fa911ae888c Author: Luca Ferretti Date: 2010-03-06 Fix mnemonics and capitalization for extra pane menu entries https://bugzilla.gnome.org/show_bug.cgi?id=612021 M src/file-manager/fm-directory-view.c M src/nemo-navigation-window-menus.c commit bb1ecb90fea17606c0eec2e36be7f60f47bb43ff Author: Ray Strode Date: 2010-07-04 Support overriding .gnome2 directory. The env var GNOME22_USER_DIR should be used for that. https://bugzilla.gnome.org/show_bug.cgi?id=614030 M libnemo-private/nemo-file-utilities.c M src/file-manager/fm-directory-view.c commit 5d86a47524e86980ec0ac21728ec76911d6bface Author: A. Walton Date: 2010-07-04 Set accessible name for the desktop. See https://bugzilla.gnome.org/show_bug.cgi?id=555425 M src/nemo-desktop-window.c commit 3094265abbfd3b70b39bb1dbd9625a81faf0fbca Author: Tomeu Vizoso Date: 2010-02-04 Use G_PASSWORD_SAVE_FOR_SESSION by default. When mounting volumes that require a password, present by default the option G_PASSWORD_SAVE_FOR_SESSION. https://bugzilla.gnome.org/show_bug.cgi?id=587909 M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-directory-view.c M src/nemo-connect-server-dialog-main.c M src/nemo-window-manage-views.c commit cfc72ae3ea86b63660e1bf153a9e33844e5b2281 Author: Thomas Karpiniec Date: 2010-06-08 Use correct logic for delaying updates while loading See http://mail.gnome.org/archives/nemo-list/2010-June/msg00023.html and https://bugzilla.gnome.org/show_bug.cgi?id=599680 for details. M src/file-manager/fm-directory-view.c commit ae1e7474830fb98eea93e1f4aadbf6e2b6caefc2 Author: Marcus Carlson Date: 2010-07-03 Properly handle G_IO_ERROR_FAILED_HANDLED (#601096). This avoid showing an useless message dialog when the user did not give authorization for mounting a device. M src/nemo-window-manage-views.c commit 41526834650640aa961d026ce5dea6025f668900 Author: Marcus Carlson Date: 2010-07-02 Change 'Close all Windows' shortcut to Ctrl+Q. Fixes bug #615808. M src/nemo-navigation-window-menus.c commit 1db7342c3fdc18ddea42266ae25ba3a6585c04b7 Author: Jorge González Date: 2010-07-01 Updated Spanish translation M po/es.po commit ab4a1d8234a63ce5c4ac96b89b624a1b216bd289 Author: Ted M Lin Date: 2009-09-02 Cleanup non-existant folders on pathbar (bug #310205). M src/nemo-pathbar.c commit 41e9a662b329c3438ee0c4c029cd4cf8d22d9574 Author: Cosimo Cecchi Date: 2010-07-01 Require GTK+ 2.90.5. So that we can drag in the right cairo dependency. M configure.in commit 375b1f4335666f9ba8d7e4f8003baecc1b9ec033 Author: Cosimo Cecchi Date: 2010-07-01 Add missing modeline. M eel/eel-canvas-rect-ellipse.c commit 3b671558f1d8ac1ee72e8af13d4ede6ab549a400 Author: Cosimo Cecchi Date: 2010-07-01 Fix build with GTK+3 master, use cairo_region_t. M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas.c M eel/eel-editable-label.c commit d1446086855ec1a673b144befff5b707244b998c Author: Cosimo Cecchi Date: 2010-07-01 Don't set has_custom_name for current location bookmark. So that renaming the relevant location can trigger updates in the listeners. M src/nemo-window-manage-views.c commit 7f6f20fd30dd989b85dbf132fd06e7e3e850d82c Author: Cosimo Cecchi Date: 2010-07-01 Remove dead code. M src/nemo-window-slot.c commit 90ebd95a7dbc3f7bef21e39c14fe04d4849fef37 Author: Marcus Carlson Date: 2010-06-30 Change "Clean Up by Name" to "Organize Desktop by Name" (#530136) M src/file-manager/fm-icon-view.c commit 83944789404d745e71f4b4a2f29c384cd44eba00 Author: Marcus Carlson Date: 2010-07-01 Ignore > 2 clicks in the icon container (#621098). M libnemo-private/nemo-icon-container.c commit 7faea402e1e37d88e5532dea712566312c981f92 Author: Kristjan Schmidt Date: 2010-06-29 Updated Esperanto translation M po/eo.po commit 9c903fd8a5b8daaa265a8d2c05603dbed9447d60 Author: Cosimo Cecchi Date: 2010-06-29 Release 2.31.4. M NEWS M configure.in commit a4e6c93d22394b086055ce92d0e06576958f969b Author: Mattias Põldaru Date: 2010-06-27 [l10n] Updated Estonian translation M po/et.po commit aaaf14437c04bd7ee8c53554e93ea47e615ae2d9 Author: Ivar Smolin Date: 2010-06-27 [l10n] Updated Estonian translation M po/et.po commit 0187296a18d2e30f5f30fab4528e42de42f7692a Author: Bastien Nocera Date: 2010-06-23 Update pkg-config files for GTK+ 3.x M libnemo-extension/libnemo-extension-uninstalled.pc.in M libnemo-extension/libnemo-extension.pc.in commit 3031b7d81721c2f54ce5412779e53ff6ebdf1fe2 Author: Bruno Brouard Date: 2010-06-23 Updated French translation M po/fr.po commit 48f2f2b3bb2abe397e799b74fd9a7140f52e307d Author: Matthias Clasen Date: 2010-06-21 Depend on the right gtk gir file We need Gtk-3.0.gir now. M libnemo-extension/Makefile.am commit 8f77b22b6091f87986abbd42d7637edf17e473a6 Author: Frédéric Péters Date: 2010-06-20 [build] link against gail-3.0 (GNOME bug 622155) M configure.in commit dc0ad00d37a68c009f555300cef427c4fb38d82c Author: Fran Diéguez Date: 2010-06-20 Updated Galician translations M po/gl.po commit f2e87dbcdb5535724a59ab9c69afe038b124b2bf Author: Matthias Clasen Date: 2010-06-19 Use the right datatype in the schema GConf calls it a bool, not a boolean. M libnemo-private/apps_nemo_preferences.schemas.in commit 45c9eb9bcbdddc91b4f53ecbd5731fc7eec88ac3 Author: Cosimo Cecchi Date: 2010-06-18 Move some variables around. M src/nemo-application.c commit e5d50bfd152e3d248519160a82908470973a539f Author: Cosimo Cecchi Date: 2010-06-18 Port to GApplication. Drop the libunique dependency. M src/nemo-application.c M src/nemo-application.h M src/nemo-main.c commit f75a6809f97033c75bf89cb6239415540953e9bb Author: Claudio Saavedra Date: 2010-06-18 Build against GTK+ 3.0 (#621938). M configure.in commit 89456b131830476d48234cd0ef32faf287496afb Author: Cosimo Cecchi Date: 2010-06-18 Use gtk_widget_get_child_requisition for the pathbar. Basically backport this GTK+ commit to make the pathbar work properly with width-for-height. http://git.gnome.org/browse/gtk+/commit/?id=0b92348077489047af98f360fd9bb3d59ee6d04a M src/nemo-pathbar.c commit c9e20bc18f5590b9377cab3b4ab5fc72108f7413 Author: Cosimo Cecchi Date: 2010-06-18 Don't fix relative paths for URIs. M src/nemo-location-entry.c commit 48c0e19e60eee88f38a6e9c7a51211376a4c90f9 Author: Cosimo Cecchi Date: 2010-06-17 Add a border around info bars (#621366). M src/file-manager/fm-directory-view.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit eae04584d51b9e058c6dcaea488880d8a43409bf Author: Cosimo Cecchi Date: 2010-06-17 Update for GLib 2.25.9 API changes (#621879). M configure.in M libnemo-private/nemo-mime-actions.c M src/nemo-application.c M src/nemo-application.h commit 5a53ae7e699edb480b76b72df99fdf1dd68eb8f8 Author: A S Alam Date: 2010-06-15 Updating Punjabi Translation by A S Alam M po/pa.po commit 877f57375a200daceafc9f5b96b9802cfc21e500 Author: A S Alam Date: 2010-06-15 Updating Punjabi Translation by A S Alam M po/pa.po commit af984bc991757eeda233c6e335cc3f35e6329a97 Author: Fran Diéguez Date: 2010-06-13 Updated Galician translations M po/gl.po commit aefc1fc8d2a49e123c4c647cfa01499d4649ef6a Author: Andrej ŽnidarÅ¡iÄ Date: 2010-06-11 Updated Slovenian translation M po/sl.po commit ca0dbef16103f523b3dfb86e795447998f060b53 Author: Cosimo Cecchi Date: 2010-06-11 [src] remove a debug printf. M src/nemo-sidebar-title.c commit d667293d865797665b50de2b972297ae61881eb6 Author: Cosimo Cecchi Date: 2010-06-11 [build] bump GTK+ required version to 2.21.2. M configure.in commit d9f80b3f407b65f559c0ca47cddac41175ac353d Author: Cosimo Cecchi Date: 2010-06-11 [test] GSEAL test-eel-image-table. M test/test-eel-image-table.c commit 78287a76d6be97428d166f781385b86e18c9b6b8 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-zoom-control. M src/nemo-zoom-control.c commit bbeb350ef219f6e94d9eba6e78d0ebbdb2201a08 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-window. M src/nemo-window.c commit 44af78c3c205f88801a8bdfa3cb0a02f7cd87d3f Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-window-manage-views. M src/nemo-window-manage-views.c commit b5407396039035e6f4e78c2d9d03891d76dd93bd Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-window-bookmarks. M src/nemo-window-bookmarks.c commit 2675ebc0873e71af0a5f8cc3463313525bfeebac Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-spatial-window. M src/nemo-spatial-window.c commit 11736c1fcbe581eab9c4a86619cfff0e71bbef38 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-sidebar-title. M src/nemo-sidebar-title.c commit 24b94447cb798ee03c9d21973f2d650c4cec2ad9 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-side-pane. M src/nemo-side-pane.c commit 2aa9bed8a98cbf68fec53b88e7d05f86f158bd07 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-query-editor. M src/nemo-query-editor.c commit 075446f3751566ec1187d6cdb3751456c9c50867 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-property-browser. M src/nemo-property-browser.c commit 06a2e40ccc45d82692997ee29e56314a45ea373f Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-places-sidebar. M src/nemo-places-sidebar.c commit 61006bd18b748c50bde01efe4abcb038a710ee11 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-pathbar. M src/nemo-pathbar.c commit 791e4c7cf2f0ee3c5f8bd55b1867daea6d891000 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-notebook. M src/nemo-notebook.c commit 2b200c5bcaee4018a9fcf82a7b1e0076f2568588 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-navigation-window. M src/nemo-navigation-window.c commit cb1e2694bdaa8c8fbad8b2541f0efe354d81b1c0 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-navigation-window-menus. M src/nemo-navigation-window-menus.c commit a0d1ca75e37fd26135fe9c85d8d86dc75e831d86 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-location-dialog. M src/nemo-location-dialog.c commit 4bba151bdacd27a193c100cf771144b7d2501548 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-location-bar. M src/nemo-location-bar.c commit eab92fb34f344fcadaaaf17beb7609a1f2cab0fa Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-information-panel. M src/nemo-information-panel.c commit 26f5fcc5efe27ca7f63b45d04a773caae6a0becd Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-emblem-sidebar. M src/nemo-emblem-sidebar.c commit 45fc9cc4fae20e69e12ca14b767277d190978c71 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-desktop-window. M src/nemo-desktop-window.c commit ac4547b030a3b0b9ed60ff9bb2f783ac10a7d62b Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-connect-server-dialog. M src/nemo-connect-server-dialog.c commit b43e268e738e8754eaa3d0e38a0cb5859f254241 Author: Cosimo Cecchi Date: 2010-06-11 [src] GSEAL nemo-application. M src/nemo-application.c commit c76136d88c314c17dbabca9ddd8808d297ceaee0 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-tree-view. M src/file-manager/fm-tree-view.c commit c764e246da912817929ae33075a3683a22bb3bf6 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-properties-window. M src/file-manager/fm-properties-window.c commit 0fe90a931acbef48d8b50b380ee05362ecdf0058 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-list-view. M src/file-manager/fm-list-view.c commit 8f9b6e75eb8eb5f9ece32963e53a69381fd65336 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-list-model. M src/file-manager/fm-list-model.c commit df190cef8cb35e0f5a717d8bd28b810ab8304137 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-icon-view. M src/file-manager/fm-icon-view.c commit eea532e7f0cf729c6e9e78744add5c8cde304ba4 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-ditem-page. M src/file-manager/fm-ditem-page.c commit 197a0101f756111b4f8712433586761c356051d3 Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-directory-view. M src/file-manager/fm-directory-view.c commit 8ba99b676c20b359c7b46b9ae4e8432fbbf4ae8f Author: Cosimo Cecchi Date: 2010-06-11 [file-manager] GSEAL fm-desktop-icon-view. M src/file-manager/fm-desktop-icon-view.c commit 0405cc8c808247eff6672a1ae69fd35c6bda841b Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-undo. M libnemo-private/nemo-undo.c commit 8ce136d19d72559a7eeb0665b61607646ecf36d6 Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-tree-view-drag-dest. M libnemo-private/nemo-tree-view-drag-dest.c commit 8ad542cf15a6a7749c672def06a5198f93a40e12 Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-progress-info. M libnemo-private/nemo-progress-info.c commit a0d555cf31a6568038fb67c004c1085bec6de8cf Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-open-with-dialog. M libnemo-private/nemo-open-with-dialog.c commit 44f222288b33de74464567a1578fbf7ea69725d7 Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-keep-last-vertical-box. M libnemo-private/nemo-keep-last-vertical-box.c commit 3711a0db65ad8ca432d0359eb11b4cd31f799df6 Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-icon-dnd. M libnemo-private/nemo-icon-dnd.c commit e57bd6003efc33bfb97fd7aa46166eba105cc2a8 Author: Cosimo Cecchi Date: 2010-06-11 [ln-p] GSEAL nemo-icon-container. M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h commit 028a80a630e17df3ba23a6778459122b2e18da0b Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-icon-canvas-item. M libnemo-private/nemo-icon-canvas-item.c commit 92d8c2a24dbf5a1a902efef0da86dd23e43208db Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-horizontal-splitter. M libnemo-private/nemo-horizontal-splitter.c commit 2206f6c82c5a49769ccdede84d74bf595a0a57c1 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-file-operations. M libnemo-private/nemo-file-operations.c commit dddf609f373f472bca41070296a54be7e67b7adf Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-file-conflict-dialog. M libnemo-private/nemo-file-conflict-dialog.c commit 0ea1e03d74713bcac0ad90a03092d8ed6d7d2528 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-entry. M libnemo-private/nemo-entry.c commit a22a367740abe58100e8137ad750176ed79f5325 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-dnd. M libnemo-private/nemo-dnd.c commit 3cd134fde66949514eb86b60795394f1aa7a2db6 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-clipboard. M libnemo-private/nemo-clipboard.c commit fd6f9364d040814346b9995570a558c1d6cb081c Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-clipboard-monitor. M libnemo-private/nemo-clipboard-monitor.c commit 392e079433aed213889b972c906d8d0b1b4290d9 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-cell-renderer-pixbuf-emblem. M libnemo-private/nemo-cell-renderer-pixbuf-emblem.c commit 3709f641bde70d96fb1feb0288521ced6dba7719 Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-bookmark. M libnemo-private/nemo-bookmark.c commit 756beaef00e01c686b061ea77d56c7aa6768d32e Author: Bastien Nocera Date: 2010-06-11 [ln-p] GSEAL nemo-autorun. M libnemo-private/nemo-autorun.c commit 47947617e14e9e3b676b0f8614bbe294f86dde86 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-wrap-table. M eel/eel-wrap-table.c commit 1db88082b3dddef066f718a44dd750a18b201dbd Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-labeled-image. M eel/eel-labeled-image.c commit 963d2dbd1cca1b92bc35f6421ae8789d1b3f4f9d Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-image-table. M eel/eel-image-table.c commit 6a2110eb0cda5f3c7d47f196b73336ec0227505b Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-gtk-extensions. M eel/eel-gtk-extensions.c commit 239c62774c44ef6e192301379db19ad53c382742 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-gtk-container. M eel/eel-gtk-container.c commit f9273be48cb62cd39aa145fa715547ec077c1670 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-editable-label. M eel/eel-editable-label.c commit 3e8a76045a33c778f423befc1c16a5e26929d00e Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-debug-drawing. M eel/eel-debug-drawing.c commit e07b688a3b8ec257a14087b696b3a02090f289ab Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-canvas. M eel/eel-canvas.c M eel/eel-canvas.h commit 191f491c9f0877c1e2c174e435898ba1e717c352 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-canvas-rect-ellipse. M eel/eel-canvas-rect-ellipse.c commit a63c3afa5c19083558c365fe6374ab5d85db3c98 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-background-box. M eel/eel-background.c commit 24cff3dc16b71105d1c096451357e6df6347b9d1 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-background-box. M eel/eel-background-box.c commit c357d232dd5cbfd7fdb3014dfff4034d01f8e66e Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-art-gtk-extensions. M eel/eel-art-gtk-extensions.c commit dae50fa5b6aeb4f811fb0d8e35da999138653cd9 Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-alert-dialog. M eel/eel-alert-dialog.c commit d104160104f50a3b2fd5e311578314e927ea73ca Author: Bastien Nocera Date: 2010-06-11 [eel] GSEAL eel-accessibility. M eel/eel-accessibility.c commit 0596f0121e6f931bfcd704cb9bcdc8ec0afdf024 Author: Cosimo Cecchi Date: 2010-06-08 Don't use 'File Browser' in the window title for browser mode (#614848). We still use it if spatial mode is the default though. Thanks to Marcus Carlson for the initial patch. M src/nemo-navigation-window.c commit c8c1dd8061d04fc002fa19cd643a95243a4a1468 Author: Cosimo Cecchi Date: 2010-06-07 Release 2.31.3. M NEWS M configure.in commit 54b044b9eaa3614498bf4a56ea915ff3a46f5e6d Author: Cosimo Cecchi Date: 2010-06-07 Update the location bar and dialog to the new API. This also fixes bug #346422. Thanks to Amos Brocco for the initial patch. M src/nemo-location-bar.c M src/nemo-location-dialog.c commit 376f9ba0bdd25794a6bd2a57caa760b8d2cbb32d Author: Cosimo Cecchi Date: 2010-06-07 Support relative paths in NemoLocationEntry. This also adds a custom 'activate' implementation which converts a relative path (if present) to an absolute one. M src/nemo-location-entry.c M src/nemo-location-entry.h commit 613b6a8292296b097660f92566de81fa71d7a878 Author: Cosimo Cecchi Date: 2010-06-07 Use the new API to order files in the list view. This also closes bug #590077. Thanks to Holger Berndt for the initial patch. M src/file-manager/fm-list-view.c commit 1459a109750d0e740fe1327cc029e342c02ce2d3 Author: Cosimo Cecchi Date: 2010-06-07 Use the new API to order files in the icon view. M src/file-manager/fm-icon-view.c commit b04bafc862ef092c1090851e6c87aabfed1eea50 Author: Cosimo Cecchi Date: 2010-06-07 Add methods to get per-file default sort type/attribute. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit e847f4196c5aabb65a1ac43688bcd1b79443b261 Author: Cosimo Cecchi Date: 2010-06-07 Add nemo_file_is_user_special_directory(). M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 0d36142a4eaa799034a25e37e95f6d66ca14f0ee Author: Theppitak Karoonboonyanan Date: 2010-06-06 Updated Thai translation. M po/th.po commit 0c8ea8597ae0616696fb52ae4396082990a85be0 Author: Sira Nokyoongtong Date: 2010-06-06 Updated Thai translation. M po/th.po commit 6cb3dae5f89887a15fa180a52e4f1362c079b1a0 Author: Cosimo Cecchi Date: 2010-06-02 Use single GTK+ header includes. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-conflict-dialog.h commit 02f961d5c892e34f88a680a7662f655b6676400b Author: Kjartan Maraas Date: 2010-06-01 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 4edc5f843a4cb0d89c21fd957dc7d6fa955cf012 Author: Alexander Larsson Date: 2010-06-01 Don't use deprecated Gtk+ api (GtkBoxChild) M libnemo-private/nemo-keep-last-vertical-box.c commit 4cebf7e4582788229f3fde7685ef44148b5cb99d Author: Ivar Smolin Date: 2010-05-31 Estonian translation updated M po/et.po commit 345e520752b627bf0d085ab6f5d480476b1dba89 Author: Cosimo Cecchi Date: 2010-05-30 Specify the expected variant type instead of using G_VARIANT_TYPE_TUPLE. Thanks to Christian Persch. M libnemo-private/nemo-file-utilities.c M src/nemo-application.c commit f1c08dcb6ff93dcdea9dfeacded9d70f7e725167 Author: Cosimo Cecchi Date: 2010-05-30 Bump required GLib version. M configure.in commit ce766ea529017649b72ea844e73c46e1d73c79b6 Author: Cosimo Cecchi Date: 2010-05-30 Use g_bus_watch_proxy() to call PackageKit methods. M libnemo-private/nemo-mime-actions.c commit 73ae91e0664b62e7b066cf5a23f6e37ea145a818 Author: Cosimo Cecchi Date: 2010-05-30 Use g_bus_watch_proxy() to initialize ConsoleKit. M src/nemo-application.c M src/nemo-application.h commit 1eb13e5686f14b006dd0f11a92219b7fe826b50e Author: Cosimo Cecchi Date: 2010-05-30 Re-use the same connection to Inhibit/Unhinibit power manager. M libnemo-private/nemo-file-utilities.c commit 8a58f4e298e844c18928e5a0681fa8ac2b9f2ee1 Author: Christian Persch Date: 2010-05-17 Port to GDBus Bug #618910. M configure.in M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-mime-actions.c M src/nemo-application.c M src/nemo-application.h commit 6cba2c2bcae95e7eca687561359b4d85c89694df Author: Alan Monfort Date: 2010-05-29 Updated Breton translation M po/br.po commit 460c57e9ad8bb725076ae90e2eb8287a90330663 Author: Alan Monfort Date: 2010-05-29 Updated Breton translation M po/br.po commit 8bc39ced44598fb0be61ffdf799c50a81d6dd272 Author: Yaron Shahrabani Date: 2010-05-29 Updated Hebrew translation. M po/he.po commit 68a877ab0fe8fef87841e06e84312eea9068794e Author: Jorge González Date: 2010-05-25 Updated Spanish translation M po/es.po commit 9708b257484931185f458ce343f1e4f88a82c6ab Author: Cosimo Cecchi Date: 2010-05-24 Release 2.31.2. M NEWS M configure.in commit 81e15c0accfe2147e0520fc8fba91fc2d97d0d2a Author: Cosimo Cecchi Date: 2010-05-24 Fix a compiler warning. M cut-n-paste-code/libegg/eggdesktopfile.c commit b0d808de8c8d1be6b8a4403fc587cc032612027a Author: Alexander Larsson Date: 2010-05-24 Change default thumbnail size from 96 to 64 Still not the same as icons (48) but makes for less jaring layouts, and lets you see more of the thumbnail content than 48 would. M libnemo-private/apps_nemo_preferences.schemas.in commit 7b75f714980293b12c2548126ba30c8af7dacecf Author: Paul Seyfert Date: 2010-05-24 Updated German translation M po/de.po commit d320b181dc169cb2720b38e65ef743803ad524ea Author: Thomas Thurman Date: 2010-05-20 Updated Shavian translation M po/en@shaw.po commit ddb325fe0c420edcae32e65ebc0b6958fa0a84e2 Author: Fran Diéguez Date: 2010-05-20 Updated Galician translations M po/gl.po commit 86d41c14159741c6803940a83a42e40a89d061d7 Author: Cosimo Cecchi Date: 2010-05-20 Split WARNING_CFLAGS into its own variable. So that we can use e.g. LIBNEMO_EXTENSIONS_CFLAGS when compiling the gir information. M configure.in M eel/Makefile.am M libnemo-extension/Makefile.am M libnemo-private/Makefile.am M src/Makefile.am M src/file-manager/Makefile.am M test/Makefile.am commit 2617e16aa55367ba3d73a33dc27376cf518d4676 Author: Cosimo Cecchi Date: 2010-05-20 Implement transparent icons for cut files in tree view. M src/file-manager/fm-tree-model.c M src/file-manager/fm-tree-model.h M src/file-manager/fm-tree-view.c commit 5b213054823f64c8125effe56f0288c54aefa625 Author: Cosimo Cecchi Date: 2010-05-20 Use the new NemoFile API in the list model. M src/file-manager/fm-list-model.c commit df11a77d4b08e170b63da4c4b67ea9730634268c Author: Cosimo Cecchi Date: 2010-05-20 Move the clipboard callbacks to NemoClipboardMonitor. M libnemo-private/nemo-clipboard-monitor.c M libnemo-private/nemo-clipboard-monitor.h M src/file-manager/fm-directory-view.c commit bbc6c3d83e51af4da3a093ef95cb17d188f162f2 Author: Cosimo Cecchi Date: 2010-05-20 Add an utility function to compare file locations. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 044952f0a5683e37545cd30d2a5296213abf70bd Author: Cosimo Cecchi Date: 2010-05-15 Implement transparent icons for cut files in list view. M src/file-manager/fm-list-model.c M src/file-manager/fm-list-model.h M src/file-manager/fm-list-view.c commit 07f768de905f42857c01434f2550c43d79eb4ed6 Author: Cosimo Cecchi Date: 2010-05-15 Implement transparent icons for cut files in icon view. M src/file-manager/fm-icon-view.c commit 03ff6b4d60473db94f351b9b3b2c0ee9490556cc Author: Cosimo Cecchi Date: 2010-05-15 Move clipboard information to NemoClipboardMonitor. So that we can use that information from more than one view at the same time. M libnemo-private/nemo-clipboard-monitor.c M libnemo-private/nemo-clipboard-monitor.h M src/file-manager/fm-directory-view.c commit 226e7ba044f15cb22e8f9c3966625c496913f3df Author: Cosimo Cecchi Date: 2010-05-15 Add an "highlighted-for-clipboard" property to the item. M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h commit 76ae23877a3e022d1d47526f1b74e5559faeb756 Author: Cosimo Cecchi Date: 2010-05-15 Move pixbuf render code to libeel. So that we'll be able to use it from outside of NemoIconCanvasItem. M eel/eel-gdk-pixbuf-extensions.c M eel/eel-gdk-pixbuf-extensions.h M libnemo-private/nemo-icon-canvas-item.c commit 97d736a0861a81f825698451249564e42d002d4b Author: Cosimo Cecchi Date: 2010-05-19 Add another missing GConf schema. M libnemo-private/apps_nemo_preferences.schemas.in commit 4309418a12b43e87a4de1f44d0641a6c902a64ce Author: Gregory J. Horvath Date: 2010-05-19 Add a missing GConf schema. M libnemo-private/apps_nemo_preferences.schemas.in commit f1148c5878e8b68c95dad8dec50aa30c6ee9b2d3 Author: Rodrigo Moya Date: 2010-05-19 Add introspection support for libnemo-extension M libnemo-extension/Makefile.am commit 8d366402ca6120e6f75051596d8ae33589ef3591 Author: Rodrigo Moya Date: 2010-05-13 Added introspection to libnemo-extension M configure.in M libnemo-extension/Makefile.am commit 1c88c7186ed298fbdd67e31cb3b8c613093c3411 Author: Adrian Bunk Date: 2010-03-29 autogen.sh: automake 1.9 is required (see configure.in) M autogen.sh commit 38986e1c0773299a7efa9f7333d5d0c513a8b66c Author: Thomas Thurman Date: 2010-05-16 Updated Shavian translation M po/en@shaw.po commit 649b0f65182f370792e00e227923a251e19ace17 Author: Fran Diéguez Date: 2010-05-16 Updated Galician translations M po/gl.po commit 0a8ec392070d9927df450ceffc4333b0a25c281c Author: Fran Diéguez Date: 2010-05-14 Updated Galician translations M po/gl.po commit 0eead029b0725cb70d9817467f820ac53b14eb60 Author: Jorge González Date: 2010-05-13 Updated Spanish translation M po/es.po commit b521530ac4cba5327ea37af7b488355f1d87399c Author: Cosimo Cecchi Date: 2010-05-13 Hide the 'Arrange by Trash Time' option if we're not in the trash. M src/file-manager/fm-actions.h M src/file-manager/fm-icon-view.c commit eab6722face64b510b8bbf330761d5b5ae7e807f Author: Cosimo Cecchi Date: 2010-05-13 Don't rely on updated metadata when resetting columns to default. M src/file-manager/fm-list-view.c commit 96da10025c3bd00ed5d748d0b91447a0137b5ef9 Author: Cosimo Cecchi Date: 2010-05-12 Define different defaults for the columns in trash. These defaults are hardcoded, but I think it's fine, as they're limited to the trash. The rest of nemo will follow the usual defaults. M src/file-manager/fm-list-view.c commit 19bbf8a1ae54cc11d51935f94209074fb2659e90 Author: Cosimo Cecchi Date: 2010-05-12 Use the new API in the preferences. M src/nemo-file-management-properties.c commit 4b3038b4ea85ce309d6fb128675611d3c912739e Author: Cosimo Cecchi Date: 2010-05-12 Use the new methods in the column chooser. The chooser becomes file-oriented as well. It will fetch the common columns if we don't provide any file, and try to fetch the specialized list if we pass a file. M libnemo-private/nemo-column-chooser.c M libnemo-private/nemo-column-chooser.h commit 14dc307c7e76f144d9fbbd091777123867b1efe4 Author: Cosimo Cecchi Date: 2010-05-12 Split the special columns. Add utility functions which return a list of columns depending on the location, separate from the 'common' set which is useful for every directory. M libnemo-private/nemo-column-utilities.c M libnemo-private/nemo-column-utilities.h commit f62cad9bae1b742b41c088449b2278eb7b6fd093 Author: Marcus Carlson Date: 2009-10-11 Adds Trashed On and Original Location as columns in List View And also an 'Arrange by Trash Time' option in Icon View. https://bugzilla.gnome.org/show_bug.cgi?id=89706 M libnemo-private/nemo-column-utilities.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-vfs-file.c M src/file-manager/fm-icon-view.c M src/file-manager/nemo-icon-view-ui.xml commit eafead25cabb9ec580c21f105f053be10dac9d5d Author: Thomas Thurman Date: 2010-05-12 Updated Shavian transliteration M po/en@shaw.po commit 6519089b3597d158618dab8d752b2d4e09494e87 Author: Khaled Hosny Date: 2010-05-12 Cleanup file header M po/ar.po commit 000092092d86c5b39b6d3a4638c860ce50d32961 Author: Khaled Hosny Date: 2010-05-12 Updated Arabic translation M po/ar.po commit 3aa7864fd2fd0459073abe0eb75b9f73fdb91653 Author: Kjartan Maraas Date: 2010-05-11 Updated Norwegian bokmÃ¥l translation M po/nb.po commit a9c3fff8710dfaae0615e48b3f6447d4b5576146 Author: Manoj Kumar Giri Date: 2010-05-11 Updated Oriya Translation M po/or.po commit 5f6b4e6f3b8ca2c27eacf5977121618fb3fb12c1 Author: Bruno Brouard Date: 2010-05-10 Updated French translation M po/fr.po commit 601c42c06e4d40de99c38eb795f20375dd2e7242 Author: Cosimo Cecchi Date: 2010-05-09 Don't add the emblem if it's equal to the icon. M libnemo-private/nemo-file.c commit 414810d3e294eaf3565127cce26fc760f147f6bf Author: Cosimo Cecchi Date: 2010-05-08 Use the mount icon as an emblem in the information sidebar. M src/nemo-sidebar-title.c commit 88781dae75003996accbf521a2d3e405d7d4fd14 Author: Cosimo Cecchi Date: 2010-05-08 Use the mount icon as an emblem in the views. M src/file-manager/fm-icon-container.c M src/file-manager/fm-list-model.c commit 7bfc3c6a7d22e1091f7985377dabd8581e1dfeac Author: Cosimo Cecchi Date: 2010-05-03 Prefer mount icons as window icons (#613733). M src/nemo-navigation-window.c M src/nemo-spatial-window.c commit 38c5b7ee06b4f8d90689dfd8fa5e010066a0b233 Author: Cosimo Cecchi Date: 2010-05-08 Add new icon flags to use mount icons. This will allow us to be more consistent with mount icons around and refactor some code as well. M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h commit 17f50da7dfbb7efdc3db74deed0cd341711ddb6e Author: Mario Blättermann Date: 2010-05-08 Updated German translation M po/de.po commit ca10b4b89df5c8123c08ad1de80139e1a52a4932 Author: Cosimo Cecchi Date: 2010-05-06 Never update icons for remote bookmarks. M libnemo-private/nemo-bookmark.c commit 108a23dc0e0be534530028612d72302c7d2a1e53 Author: Cosimo Cecchi Date: 2010-05-06 Trigger the eject button on release. M src/nemo-places-sidebar.c commit 729ce7cf7feead42d16a5b8793cd7948286c00f8 Author: Cosimo Cecchi Date: 2010-05-06 Use the new API in the places sidebar. M src/nemo-places-sidebar.c commit 6bbe1bd9ed2d9eea934ced04952b3ab4a8d74252 Author: Cosimo Cecchi Date: 2010-05-06 Set a 'folder-remote' icon for remote bookmarks. M src/nemo-connect-server-dialog.c commit 89fa909f3d406dd2e47006eeaaee051bef2b77d5 Author: Cosimo Cecchi Date: 2010-05-06 Set a 'folder-remote' icon if the URI is not native. Also, port to the new API. M src/nemo-bookmark-list.c commit e6d70ef8a41bd0c6e6685f07e85e266e3227c61c Author: Cosimo Cecchi Date: 2010-05-06 Update to the new API. M src/nemo-bookmarks-window.c M src/nemo-window-manage-views.c M src/nemo-window.c commit 856177d1dc13802e6473923d331f8f1ba91f8e51 Author: Cosimo Cecchi Date: 2010-05-06 Change NemoBookmark API. Remove _set_has_custom_name() method and use just one _new() constructor. Also, emit the CONTENTS_CHANGED signal when we're setting a new name, as that will trigger a save/reload of .gtk-bookmarks due to saving a new label. Finally, don't use gnome-fs-bookmark* icon names anymore, as they're deprecated. We now use 'folder' as a default icon, and add a 'warning' emblem when the URI does not exist. M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-bookmark.h commit 1756fb0b77aebae201ffb1ee1641a9118ca941d9 Author: Cosimo Cecchi Date: 2010-05-06 Remove a pile of hacks used to initialize bookmarks. - Make nemo_window_constructed a real GObject implementation and move bookmark initialization code there. - Don't replicate a singleton logic in nemo-window-bookmarks now that NemoBookmarkList is a real singleton - Remove get_bookmark_list() method from NemoWindowInfo, as it's not any useful anymore. M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/nemo-application.c M src/nemo-window-bookmarks.c M src/nemo-window-bookmarks.h M src/nemo-window-menus.c M src/nemo-window-private.h M src/nemo-window.c commit 03c5612730d4de29d8cb80352b1bfc42bab59742 Author: Cosimo Cecchi Date: 2010-05-06 Make NemoBookmarkList a singleton. M src/nemo-bookmark-list.c commit 00035932b2948140d95f27a473be380f189caf21 Author: Fran Diéguez Date: 2010-05-04 Updated Galician translation M po/gl.po commit 997028e6669062537b2f8ec2ce0fad2854f114b3 Author: Jorge González Date: 2010-05-04 Updated Spanish translation M po/es.po commit e6a7039162d4eb37afe329cc4d8378f9edb446c7 Author: Cosimo Cecchi Date: 2010-05-04 Release 2.31.1. M NEWS M po/POTFILES.in commit c0f8096150ea98af40248a55d6dbb77a35c0a771 Author: Jorge González Date: 2010-05-03 Updated Spanish translation M po/es.po commit abade38f2477bc807246d5b4acf8b7a753ea369e Author: Jorge González Date: 2010-05-03 Updated Spanish translation M po/es.po commit 64524ff2724bb6f0cc72fea34cb7ca3d5253cec7 Author: Cosimo Cecchi Date: 2010-05-03 Use header capitalization for "Open With" menu items (#596778). As the HIG says so. M src/file-manager/fm-directory-view.c M src/nemo-information-panel.c commit 79e155aba54ee7cfeac9363548d6b1cee221ae2f Author: Cosimo Cecchi Date: 2010-05-03 Don't give input focus to the selectable label (#591902). M src/nemo-image-properties-page.c commit e0f463562e894a2f394279d00fdf027343d2efad Author: Cosimo Cecchi Date: 2010-05-03 Change "Stretch Icon" to "Resize Icon" (#459900). M src/file-manager/fm-icon-view.c commit 5348820067ab62dd3fcac78f0acc0fef869cc2a1 Author: Cosimo Cecchi Date: 2010-05-02 Use "Cancel" as default response when activating a broken link (#341595) M libnemo-private/nemo-mime-actions.c commit fe817911c538f1018d73945af9d637e01943378b Author: Cosimo Cecchi Date: 2010-05-02 Don't force a default response. M eel/eel-stock-dialogs.c commit 846dd7c0e50b0f2db288285e615698932cf81e41 Author: Kjartan Maraas Date: 2010-05-02 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 1eac7a19cd7c4f543408809d0c0875bec849a494 Author: Fran Diéguez Date: 2010-05-01 Updated Galician translation M po/gl.po commit 777a404b76c0bcb3c3504fa9ff986c256777be8d Author: Torstein Adolf Winterseth Date: 2010-05-01 Updated Norwegian Nynorsk translation M po/nn.po commit 2a87565bcb810597dca323a943c616075ee7c6ab Author: Cosimo Cecchi Date: 2010-04-29 Let the sidebar header fill the whole width (#463111). The code for this is borrowed from Evince's sidebar implementation. M src/nemo-side-pane.c commit b281985fff427982420b7d037dff609383b3ea74 Author: Cosimo Cecchi Date: 2010-04-29 Don't let the sidebar shrink more than its requisition (#311732). This also makes us consistent with the other GNOME apps that use a sidebar widget. M src/nemo-navigation-window.c commit 842c94dbdd20bff3e9dcc1811b6e900d8d27d775 Author: Jorge González Date: 2010-04-29 Updated Spanish translation M po/es.po commit 90b32ff314a141417c2b8e3691766910420ca25e Author: Cosimo Cecchi Date: 2010-04-28 Don't ignore the return value of write() (#617092). M src/nemo-application.c commit 3683288f8a86cd714623cca3d6921315c67ec7f1 Author: Cosimo Cecchi Date: 2010-04-28 Add a 'Restore Selected Items' button in the trashbar. This makes the restore function more visible in the UI (#616304). M src/nemo-trash-bar.c M src/nemo-trash-bar.h M src/nemo-window-manage-views.c commit b87911c0caf3d957fc4e9575fd905493829f787c Author: Cosimo Cecchi Date: 2010-04-28 Move restore_from_trash() in nemo-file-utilities. This is needed so we will be able to use the function from the trash bar later. M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file-utilities.h M src/file-manager/fm-directory-view.c commit a7792d030df5f2139043f7228cb0f30bf1cdf5c1 Author: Jorge González Date: 2010-04-27 Updated Spanish translation M po/es.po commit 02ef15eabeef5cdbcb479adad90632ff12d2b791 Author: Cosimo Cecchi Date: 2010-04-27 Properly update icons as we load the thumbnails. M libnemo-private/nemo-file-conflict-dialog.c commit 9ecdac9b1a4adb3db9ac32606ff36023a3d6909e Author: Cosimo Cecchi Date: 2010-04-27 Fix size requests and wrap modes for labels. M libnemo-private/nemo-file-conflict-dialog.c commit 430d554f55632475dac94a7a9d6009c0f189b178 Author: Cosimo Cecchi Date: 2010-04-27 Initialize variables to NULL. M src/nemo-places-sidebar.c commit 47ad2649dc83faf1b3931d93d5060729344de955 Author: Cosimo Cecchi Date: 2010-04-27 Use a new icon for audio preview (#614907). Thanks to Hylke Bons for the icon. M icons/audio.svg M libnemo-private/nemo-icon-canvas-item.c commit 96a7a6bb7aa680d98f0bb05d77aa6101c25fb491 Author: Jorge González Date: 2010-04-27 Updated Spanish translation M po/es.po commit 46124f684e5db4bd05bc9575eef2b16527d58b66 Author: Cosimo Cecchi Date: 2010-04-27 Bump libnemo-extension API version (#610356). M configure.in commit 4b680e163e41a26c8ace47d43efdc72be9ede93a Author: Cosimo Cecchi Date: 2010-04-27 Don't use C++ keywords in NemoMenu (#616657). M libnemo-extension/nemo-menu.c M libnemo-extension/nemo-menu.h commit eee505e416678ce7f51999b6a4acd385a0ae99c7 Author: Cosimo Cecchi Date: 2010-04-27 Bump version to 2.31.1 on master. M configure.in commit add025f7d1502d97062a9fdce8eff85fcd27205e Author: Martin Pitt Date: 2010-03-30 Do not show Unmount when showing Eject/Safe removal Having three menu entries (unmount/eject/safe removal) in a volume/drive menu entry is too confusing. Unmount only really makes sense for internal drives, for external ones it is pretty much a "geek" option. Geeks can use palimpsest or "unmount /media/foo" from the CLI if they really want to, for everyone else it is just an unintuitive and hard to to explain menu entry. Bug: https://bugzilla.gnome.org/show_bug.cgi?id=598690 Bug-Ubuntu: https://launchpad.net/bugs/453072 (cherry picked from commit 0a5cc4c4e5b01eb8aa38dfae926502ce920efc94) M src/file-manager/fm-directory-view.c M src/nemo-places-sidebar.c commit cee1ced8e45dc9570308ba447f8e3c0edfd986ba Author: Cosimo Cecchi Date: 2010-04-15 Use display names for applications (#611378). Instead of using the simple GAppInfo name property. M libnemo-private/nemo-autorun.c M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-mime-application-chooser.c M libnemo-private/nemo-open-with-dialog.c M libnemo-private/nemo-program-choosing.c M src/file-manager/fm-directory-view.c M src/nemo-information-panel.c M src/nemo-x-content-bar.c commit 9192dd8faffd788acf54a3b98de48cd1252dd9a6 Author: Cosimo Cecchi Date: 2010-04-15 Properly set the application as default (#605814). When the checkbox is enabled in the Open With dialog, set that application as default; it the checkbox is not enabled, add the application to the supported list. M libnemo-private/nemo-open-with-dialog.c commit 3d82f47ee91f5e0ca3284aef55911bace0736243 Author: Cosimo Cecchi Date: 2010-04-26 Don't mark the regex for translation. M src/file-manager/fm-directory-view.c commit 4dd3fc4731a313803c776ee096478a6f60ef5a72 Author: Marcus Carlson Date: 2009-10-05 Adds legend to "Select Items Matching" dialog https://bugzilla.gnome.org/show_bug.cgi?id=301690 M src/file-manager/fm-directory-view.c commit a7336c72c6f6cc0b0340e218fd123bcdddb144b9 Author: Cosimo Cecchi Date: 2010-04-26 Always set the parent window in dialogs (#573788). M eel/eel-stock-dialogs.c M libnemo-private/nemo-mime-actions.c commit d63623cee6ac5cbbb74f6f31a7afa660d2037cbe Author: Cosimo Cecchi Date: 2010-04-09 Focus and sensitivity fixes. M libnemo-private/nemo-file-conflict-dialog.c commit 7e9ec46e34c899cae0eb92aabe9c826ea2abc5c6 Author: Cosimo Cecchi Date: 2010-04-09 Focus the entry after clicking on 'Reset'. M libnemo-private/nemo-file-conflict-dialog.c commit 5423c9f36cea27fac78d2fa7fee75c20a0a44d3e Author: Cosimo Cecchi Date: 2010-04-09 Tweak UI according to usability suggestions. This includes the addition of a reset button, use a single Replace/Rename button and some smaller UI candies. M libnemo-private/nemo-file-conflict-dialog.c commit e1d7563733075cd0302951db45b645bee9f71cdb Author: Cosimo Cecchi Date: 2010-04-09 Reverse broken logic. M libnemo-private/nemo-file-conflict-dialog.c commit 33da32efab246804efb745c0f9c63d88574cf5d0 Author: Cosimo Cecchi Date: 2010-04-08 Remove manual markup. Now that we use Pango to make the string bold, this is useless. M libnemo-private/nemo-file-conflict-dialog.c commit b9640f4cb9b24b567e44f7f87b75f59bddf2f073 Author: Cosimo Cecchi Date: 2010-04-08 Make the primary label bold. For that, use the same code from GtkMessageDialog. M libnemo-private/nemo-file-conflict-dialog.c commit e1a6a08cbff7884635b2e6478171c85ce555b999 Author: Cosimo Cecchi Date: 2010-04-08 Specify which file is older. That's valuable information, so display it clearly in the secondary label of the conflict dialog. M libnemo-private/nemo-file-conflict-dialog.c commit 067619c9c6fa155ff5dfff2b94f5f70e1a52dc4c Author: Cosimo Cecchi Date: 2010-04-08 Make sure NemoFiles are ready. M libnemo-private/nemo-file-conflict-dialog.c commit e84883bde6919d8bcbbc93713c80f3d537131d4e Author: Cosimo Cecchi Date: 2010-04-08 Show the file type only if it's different. Also, don't hardcode markup in strings marked for translations, as i18n don't usually like it. :) M libnemo-private/nemo-file-conflict-dialog.c commit 148dfd2b8d5492b7c9b4824133537d812782ea62 Author: Cosimo Cecchi Date: 2010-04-08 Fix indentation. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-conflict-dialog.h M libnemo-private/nemo-file-operations.c commit 8734e4268b74935aaa5418ee567340fdfd2b953f Author: Cosimo Cecchi Date: 2010-04-08 Fix a conflict after rebase. M libnemo-private/nemo-file-operations.c commit 5d5166d2cdc68ccee3cacd9d0c266de0f0bee3f5 Author: Cosimo Cecchi Date: 2009-04-22 Swap the order of files in the dialog The dialog had the source and destination files wrongly ordered, swap them. M libnemo-private/nemo-file-conflict-dialog.c commit d8a11018692ec20a8ec6a3dcb1f2d942dcb72a90 Author: Cosimo Cecchi Date: 2008-04-23 Use NemoFile machinery instead of is_dir Use the NemoFile cached data to find out whether a file is a directory instead of using GIO. M libnemo-private/nemo-file-conflict-dialog.c commit 7e44bab4b8910bb26a91fc09a8e3b0cd12455bf8 Author: Cosimo Cecchi Date: 2009-04-22 Implement support for rename in the operations code Act accordingly to a rename response from the conflict dialog. M libnemo-private/nemo-file-operations.c commit 95016daa49bdd8b951dd0fa500b9634e12e91856 Author: Cosimo Cecchi Date: 2009-04-22 Adapt the file operations code to use the new dialog Cut out of the file operations module, the code used to display conflict dialogs. Use the new dialog instead. Rename is not working yet. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-operations.c commit dc21af1dc03759661fea147a8b98a8772749b29e Author: Cosimo Cecchi Date: 2008-04-03 Implement responses from the dialog back to the file operation. Add some API to get the response type from the conflict dialog back to the file operations code. Start using that API during the operations accordingly. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-conflict-dialog.h M libnemo-private/nemo-file-operations.c commit bf607e6e3045dff76128894e87cd42affb68a44c Author: Cosimo Cecchi Date: 2008-04-03 HIG fixes Make sure the UI doesn't suck too much. M libnemo-private/nemo-file-conflict-dialog.c commit 2048c2d61db6ec557b6b572fb635a0f5a11bab09 Author: Cosimo Cecchi Date: 2008-04-02 Finish implement icon boxes in the dialog. Finish implement icon boxes in the conflict dialog. Add a main thread runner from inside the file operations, as the operation itself is done in an I/O worker thread. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-operations.c commit fee8b5095521fb6db98f866f6e0d53e8cf381783 Author: Cosimo Cecchi Date: 2008-04-02 UI and HIG fixes Use the correct markup strings in the dialog, and take care of some layouting issues. M libnemo-private/nemo-file-conflict-dialog.c commit 6f0dc097348f7c2d0ede26daf5e76634a6625db3 Author: Cosimo Cecchi Date: 2008-04-02 Use a GtkDialog. Use a GtkDialog instead of a GtkMessageDialog. Take care of some HIG fixes, and try to use icons from NemoFile. M libnemo-private/nemo-file-conflict-dialog.c M libnemo-private/nemo-file-conflict-dialog.h commit 68ac5db7bcb762bcea612239c4a9d6408924a7b2 Author: Cosimo Cecchi Date: 2008-04-02 First implementation of NemoFileConflictDialog Basic UI implementation of NemoFileConflictDialog. Add it to Makefile.am. Also, hook the dialog inside the relevant file operations and load it at the right place when doing a file operation. M libnemo-private/Makefile.am A libnemo-private/nemo-file-conflict-dialog.c A libnemo-private/nemo-file-conflict-dialog.h M libnemo-private/nemo-file-operations.c commit ce66d5d2bf1b3c028f08d1f3ed3fa6d4c7c633f1 Author: Cosimo Cecchi Date: 2010-04-12 Don't use Backspace to delete bookmarks. In the places sidebar, don't assign Backspace to deleting bookmarks, as that's confusing (and we already have Delete for it). Fix bug #340934. M src/nemo-places-sidebar.c commit a051ce374f38b1dc13663f7a099337f39302c5b2 Author: Cosimo Cecchi Date: 2010-04-12 Always return TRUE from drop-motion. Fixes the displaying of a black line when DnD-ing something in the sidebar which is not supported (#432529). M src/nemo-places-sidebar.c commit b80bfe38ac1cc4fd3561961d7f6f8b43ec786f20 Author: Cosimo Cecchi Date: 2010-04-12 Refactor the load/save code for the list. Don't use sync i/o anymore. This should also fix bug #532911. M src/nemo-bookmark-list.c M src/nemo-bookmark-list.h commit 721f9999bcac87f28780d0b6938dac66b04970f2 Author: Cosimo Cecchi Date: 2010-04-12 Bring the object to 2010. M libnemo-private/nemo-bookmark.c M libnemo-private/nemo-bookmark.h M src/nemo-bookmark-list.c M src/nemo-bookmark-list.h commit 5d84350777a40f53ae3970f2acbafb5846cb1c94 Author: Cosimo Cecchi Date: 2010-04-12 Set rate limit to the file monitor. M src/nemo-bookmark-list.c commit 2d64615521d9d6a090ef9a296e7783a73edc1f68 Author: Cosimo Cecchi Date: 2010-04-11 Remove dead code. M src/nemo-places-sidebar.c commit 006f5164b7ce1bf54fed170800ed145eb625826e Author: Cosimo Cecchi Date: 2010-04-11 Use the new NemoBookmarksList API. M src/nemo-places-sidebar.c commit 5b80a0e60516518f359596b5d6285b241d7c6cad Author: Cosimo Cecchi Date: 2010-04-11 Add a method to move bookmarks in the list. So that moving a bookmark in the list doesn't trigger two 'contents-changed' signals in a row. M src/nemo-bookmark-list.c M src/nemo-bookmark-list.h commit c87d0252bbd028ef80c3460be737c4e8ae07aa62 Author: Cosimo Cecchi Date: 2010-04-26 Preserve last selection while updating places. M src/nemo-places-sidebar.c commit 6b768ef18298bd8048f13e50094f5777b2b7e07b Author: Cosimo Cecchi Date: 2010-04-11 Use 'button-release-event' to activate bookmarks. Instead of using the 'row-activated' signal. This allows us to only open the bookmark after DnD (#606097). M src/nemo-places-sidebar.c commit 60b27c11e0dd3416eee13bdea45b280ec2562a36 Author: Cosimo Cecchi Date: 2010-04-13 Migrate confguration to XDG_CONFIG. https://bugzilla.gnome.org/show_bug.cgi?id=601476 M src/nemo-application.c commit 3c98314f94086dd241ca48bedee112d83733c183 Author: Cosimo Cecchi Date: 2010-04-13 Don't use ~/.nemo anymore (#601476). But use XDG_CONFIG to save configuration files. Patch by jarryson. M libnemo-private/nemo-file-utilities.c commit a09d41702b771fb0041fa0c4270afaa678413a2d Author: Cosimo Cecchi Date: 2010-04-13 Remove deprecated GTK+ symbols (#565038). M eel/eel-background.c M eel/eel-canvas.c M eel/eel-debug-drawing.c M eel/eel-editable-label.c M eel/eel-gtk-container.c M eel/eel-gtk-extensions.c M eel/eel-image-table.c M eel/eel-labeled-image.c M eel/eel-wrap-table.c commit 2e79c499851757bf6da55c735268e36fcc4f2552 Author: Alexander Larsson Date: 2010-04-26 Update NEWS for release M NEWS commit 7411a0f07a6505ca5205a819b2539fe95bb1a1c0 Author: Andy Owen Date: 2010-04-26 Update split view menu item sensitivity when closing extra pane M src/nemo-navigation-window.c commit 39547f935a4f766eece11513eee175fffcbad2c1 Author: Andy Owen Date: 2010-04-26 Don't crash if there is no next_pane This happened due to menu sensitivity being wrongs (bug 616179) M src/nemo-navigation-window-menus.c commit bae7b352ae02233e5f3368818bf4daa864ad9a2e Author: Mattias Põldaru Date: 2010-04-26 Estonian translation updated M po/et.po commit dae9a5f81eec0ea5ededecb4375ca76c8f3ed9d1 Author: Maxim V. Dziumanenko Date: 2010-04-24 Updated Ukrainian translation M po/uk.po commit bf052548334dc7eae0b01131a4771c9fc34301f6 Author: Maxim V. Dziumanenko Date: 2010-04-22 Updated Ukrainian translation M po/uk.po commit 3c336f6968ed198c89eaeeae8d44a71312b5682b Author: Carles Ferrando Date: 2010-04-21 Updated Catalan (Valencian) translation M po/ca@valencia.po commit 17e388240fd5947cf21081c1d3971b2c9a66eeb1 Author: Shankar Prasad Date: 2010-04-21 Updated the kn translations M po/kn.po commit 2514148ef1a3d8a22caeb2f80989d29441e816e0 Author: Jorge González Date: 2010-04-17 Updated Spanish translation M po/es.po commit 32327339b335e71f661f5f51c6f66ddb95cbd099 Author: Paolo Borelli Date: 2010-04-17 Do not use "if (spatial) ..." in window superclass Delegate behavior specific to the window type to an appopriate subclass method. M src/nemo-application.c M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit 90c1b707ce4ab0a96dc4200537ef9fae17e45e60 Author: Andika Triwidada Date: 2010-04-17 Updated Indonesian translation due bug #569491 M po/id.po commit fc18d0bfc4f6001be311be63993a90129f02520a Author: Holger Berndt Date: 2010-04-06 Let w close the extra pane The keybinding w closes the active slot until no slot is remaining, in which case it closes the window. This commit includes the extra pane layer in this chain. Fixes bug 615593 M src/nemo-window-pane.c M src/nemo-window.c commit 719c524c571fc0742382bff1c04174bb585326b8 Author: Manoj Kumar Giri Date: 2010-04-16 Updated Oriya Translation M po/or.po commit 85c0047c370b06473026b2920dc53428bd3c30ae Author: Holger Berndt Date: 2010-03-22 Fix sensitivity of "{Copy|Move} to other pane after enable/disable of extra pane" Add an "update_menus" signal to the NemoView interface, so that external events can trigger a menu sensitivity update. Fixes bug 613257. M libnemo-private/nemo-view.c M libnemo-private/nemo-view.h M src/file-manager/fm-directory-view.c M src/nemo-navigation-window-menus.c commit 543d3ddd5131546fbbb2e3e2a504d9800c4f0d62 Author: Peteris Krisjanis Date: 2010-04-15 Updated Latvian translation. M po/lv.po commit 1ec432f114b357822256349b85c7401d1ade4cf5 Author: Runa Bhattacharjee Date: 2010-04-15 Updated Bengali India Translation M po/bn_IN.po commit 183b65d95d7c6418ba74104e6c718572ae518af3 Author: Andika Triwidada Date: 2010-04-15 Updated Indonesian translation M po/id.po commit 00de9e84618738f2f41c5ac5e01e7bddc953423b Author: ReÅŸat SABIQ Date: 2010-04-14 Minor update for Crimean Tatar/Turkish translation M po/crh.po commit 9a45cd408e177c49bfbd7bced2f117c2b5f87e75 Author: Yannig Marchegay Date: 2010-04-14 Updated Occitan translation M po/oc.po commit 7fb83086b3c39aa6555b3fe2b0c3a59449cab5f2 Author: Yannig Marchegay Date: 2010-04-14 Updated Occitan translation M po/oc.po commit 73fc9b35508b3be5d959c568e92ae6870817dee2 Author: Yannig Marchegay Date: 2010-04-14 Updated Occitan translation M po/oc.po commit 27850a638a0075fb35b49c0621363bcb9ffd50d3 Author: Ani Peter Date: 2010-04-14 Updated Malayalam Translation M po/ml.po commit d88eca5a81988d62fbcbcc60037abbaae124b407 Author: Sandeep Shedmake Date: 2010-04-14 Updated Marathi Translations M po/mr.po commit 95b2c6e322a9bd15320fd6cdb37394e645b85ef4 Author: Yannig Marchegay Date: 2010-04-13 Occitan translation update M po/oc.po commit 89953c7140b285cc27a0dc4f8a771a58bee21e20 Author: Yannig Marchegay Date: 2010-04-13 Occitan translation update M po/oc.po commit 36586cd1ad3f0c12c707f052964b3c188343e78a Author: Francisco Diéguez Date: 2010-04-09 Updated Galician translations M po/gl.po commit cb4097700ddfc5992544528cc4e412ec345131aa Author: Tomas Bzatek Date: 2010-04-09 Tracker: Fix filtering by location, code cleanup This also involves code cleanup to maintain consistency with gtksearchenginetracker.c Related: bug 612725 M libnemo-private/nemo-search-engine-tracker.c commit 31b4b4adda7a9da23b611966176c7f7b7ae552cd Author: Cosimo Cecchi Date: 2010-04-09 Don't use LDFLAGS for the eel library. libeel is a convenience library now, so it should pull its dependecies using LIBADD, not LDFLAGS. Patch by Josselin Mouette (#604575). M eel/Makefile.am commit 496d3f15de295482e158194e1fe1dae3569f4524 Author: Cosimo Cecchi Date: 2010-04-09 Use gtk_widget_get_state() (#612423). Instead of the deprecated GTK_WIDGET_STATE macro. Patch by Dominique Leuenberger. M eel/eel-editable-label.c M eel/eel-gtk-extensions.c M eel/eel-labeled-image.c commit 305cf9768bd716ba9bbcd3e773511536243a9cc5 Author: Marcus Carlson Date: 2010-04-07 Fix emblem scaling with zoom >= 150% Emblem handling did not properly take zoom into account (#343540) M libnemo-private/nemo-icon-canvas-item.c commit 263051df98aace0b59fb2bd1772711dceba8e404 Author: Marcus Carlson Date: 2010-04-07 Fix crash when middle click on an invalid network share in Places https://bugzilla.gnome.org/show_bug.cgi?id=579627 M src/nemo-window-manage-views.c commit 1698377dcad6762bc0b32c4efa75d7e2c4b3fb67 Author: Tomas Bzatek Date: 2010-04-06 Support for tracker 0.8 stable release M libnemo-private/nemo-search-engine-tracker.c commit 323124d88ba4bf2d39466ee11c3f166ffebb0a01 Author: Sweta Kothari Date: 2010-04-06 Updated Gujarati Translations M po/gu.po commit ae2b3bffcb1bb5f333bc6654af3c0a3719d50b70 Author: Jordi Serratosa Date: 2010-04-02 Fixes to Catalan translation M po/ca.po commit 1b252c84a9f1efaab652679f2511d5d5a63593f4 Author: Wouter Bolsterlee Date: 2010-03-30 Dutch translation updated by Wouter Bolsterlee M po/nl.po commit 09b695b4cab81b239a3934e6c53222299fc61137 Author: Jordi Serratosa Date: 2010-03-29 Fixes to Catalan translation M po/ca.po commit 3bdca4a2c5720e239a8947348b8390da0ac7b998 Author: Alexander Larsson Date: 2010-03-29 Post release version bump M configure.in commit e414801ab9c3baba23ce82df02f59ec7fdf2f7d8 Author: Alexander Larsson Date: 2010-03-29 Bump version to 2.30.0 M configure.in commit 8174126cad82d54b25b40b883aa05d0a13abdc44 Author: Alexander Larsson Date: 2010-03-29 Require stable versions of glib/gtk+ M configure.in commit 8972aad5f0fc3f6346000845770239d39c0fd63b Author: Alexander Larsson Date: 2010-03-29 Update for release M NEWS commit 6364bbbbea855bcd5f507d08e4270956aed4083a Author: Runa Bhattacharjee Date: 2010-03-29 Typo correction and updation M po/bn_IN.po commit 313ee0e2b19d5850bbc62dae73fe315b4c450277 Author: Jamil Ahmed Date: 2010-03-27 Updated Bengali translation M po/bn.po commit be4461243fdf084bd1a2c466fd3b196e134439d7 Author: Maxim V. Dziumanenko Date: 2010-03-26 Updated Ukrainian translation M po/uk.po commit 94127c6f6c553849c033ce06e0eb3fa8a837d994 Author: Timo Jyrinki Date: 2010-03-26 Separate ejecting from safely removing and link to the relevant bug report. M po/fi.po commit 0fe43b73226164ac381d48e167c15035161f7e19 Author: Gabor Kelemen Date: 2010-03-26 Updated Hungarian translation M po/hu.po commit f9f46d46040e97f802e530706248d39a2daf99cc Author: Simos Xenitellis Date: 2010-03-25 Updated Greek translation for nemo M po/el.po commit de23258a5b70b7237cf972b4689731763eb19ebf Author: Cosimo Cecchi Date: 2010-03-25 Use a better thumbnail frame for image previews. Thanks to Hylke Bons for working on this. Closes bug #613858. M icons/thumbnail_frame.png M libnemo-private/nemo-thumbnails.h commit acb01f0fe637a64f92c1ff2188879b7c470ed0e0 Author: Tomas Bzatek Date: 2010-03-24 Unref local query object when turning search off M src/nemo-navigation-window-menus.c commit a92a7bfcb2c7bb9f171724bc97b1c163f52c0fd7 Author: Tomas Bzatek Date: 2010-03-24 Don't crash when hiding search bar with no text Happens in browser mode and only when search results pane is displayed M src/nemo-navigation-window-menus.c commit 4702bc8e74248de734c2fbcddd57191ba2fc1bd1 Author: Fran Diéguez Date: 2010-03-24 Updated Galician translation M po/gl.po commit 4297995df518bc17f5b3de9889c655c35eb05fbf Author: Inaki Larranaga Murgoitio Date: 2010-03-24 Updated Basque language M po/eu.po commit 9b458e52b43a87c0b5ff13a0634c18dc6328de8a Author: A S Alam Date: 2010-03-24 update for Punjabi by A S Alam M po/pa.po commit ffadc713c20db01c3678f947f510565affcd4887 Author: Anders Jenbo Date: 2010-03-23 Updated Danish translation M po/da.po commit 81709b3bba3630fdee8577453820a353b4757aed Author: Simos Xenitellis Date: 2010-03-23 Updated Greek translation for nemo M po/el.po commit 14b652632c63b586bf32ae6a7a0599da459fcc4a Author: Nikos Bakaoukas Date: 2010-03-23 Updated Greek translation for nemo M po/el.po commit 5bbd6545ac0114e2a6962079fdbcaae5bbe84b78 Author: Tommi Vainikainen Date: 2010-03-22 Updated Finnish translation M po/fi.po commit c18f16106fe0cf6b9c139c61728f6f5233ca0737 Author: Luke Symes Date: 2010-03-14 Don't display a border around the desktop frame. Fixes bug 605704. M src/file-manager/fm-desktop-icon-view.c commit 0a53599124a8d57b5d6ccdb8694da10bea8313d7 Author: ReÅŸat SABIQ Date: 2010-03-18 Updated Crimean Tatar (Crimean Turkish) translation M po/crh.po commit e0b4fd622a4eb31a3d9af56bb0b2d5c1fd7e3d06 Author: Bastien Nocera Date: 2010-03-17 Add AIFF as a supported audio type for preview M src/file-manager/nemo-audio-mime-types.h commit ba6a7c6e1098c5cb88fb7468e98bf9f58ff6b543 Author: Alexander Larsson Date: 2010-03-17 Set exit_with_last_window to false by default This fixes problems with show_desktop=false causing nemo to exit and gnome-session restarting nemo in a loop (#571417). This means nemo will keep running, so that it can handle automount and stuff. If you only run nemo rarely you need to set this to true. In the future we will move the automount handling to gnome-settings-daemon and then we will probably change this back. M libnemo-private/apps_nemo_preferences.schemas.in commit dfa7758c96580e06261756b6f49433befec677c4 Author: Inaki Larranaga Murgoitio Date: 2010-03-16 Updated Basque language M po/eu.po commit 1ab3721437d8371301079023c10dfa14c0eb5b5d Author: Inaki Larranaga Murgoitio Date: 2010-03-15 Updated Basque language M po/eu.po commit e61a5c23dce6af7861628ace3fb049d9a0d4c8e8 Author: Petr Kovar Date: 2010-03-15 Update Czech translation by Lucas Lommer M po/cs.po commit 863a13e1dbbcee2d7405f17b3eef6db93df437df Author: Ivar Smolin Date: 2010-03-14 Estonian translation updated M po/et.po commit e3ea8ba00461ccd43716c1360215d4d44e4fa872 Author: Fran Diéguez Date: 2010-03-13 Updtae Galician translation M po/gl.po commit 68dbac28c64ea365a09b7cbc58fba0434fad8a34 Author: Luca Ferretti Date: 2010-03-12 Updated Italian translation M po/it.po commit 797cacb28b78fede43b713dbd1fba2479bdbe943 Author: Holger Berndt Date: 2010-03-11 Remove grab_focus from list view The grab_focus interface function is now implemented in the directory view. There's no need for special handling of list views anymore. M src/file-manager/fm-list-view.c commit c78da8903804267ef7399d92753c5f5b2e811585 Author: Holger Berndt Date: 2010-03-11 Fix focus handling Move the focus to a new window's first slot. The extra pane doesn't get focus initially, which fixes bug 612203. To make this work for all views, the focus_grab interface function was implemented for the directory view class. M src/file-manager/fm-directory-view.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 34807782c143f99f0ab94dd4a1804239a5710d1a Author: Holger Berndt Date: 2010-03-11 Bring back "Don't grab focus on realize" This brings back commit 4efd42312584b46f248e2839582a87776a7baebe that was reverted in 95ae539e8d042b04ee9c6817bcc41f551ab207fc The focus issues that this introduces will be taken care of in a followup commit. M libnemo-private/nemo-icon-container.c commit dde8fff965302b2d73f3aed81d19e6f93a7c6334 Author: Padraig O'Briain Date: 2010-03-11 Don't use inline keyword Its unnecessary and breaks on e.g. sun compilers. M src/nemo-navigation-window.c M src/nemo-navigation-window.h commit c25488049229c725dde566d9c37e90c0122a6dd2 Author: Gabor Kelemen Date: 2010-03-11 Updated Hungarian translation M po/hu.po commit 44ea265c75a6cf54145002d9323b8bec52f76e3d Author: Tomas Bzatek Date: 2010-03-10 Update for 2.29.92.1 M NEWS M configure.in commit 8c8cf192d861a1a6c202624ee0b4c0ff43077080 Author: Tomas Bzatek Date: 2010-03-10 Fix compilation due to deprecated GTK_WIDGET_STATE symbol Also see https://bugzilla.gnome.org/show_bug.cgi?id=69872#c87 M libnemo-private/nemo-tree-view-drag-dest.c commit fab5d01888eb08e3721db7331011534e40afe24e Author: Duarte Loreto Date: 2010-03-10 Updated Portuguese translation M po/pt.po commit 2d40fbadb053bc7ad0d988050e58a81bfc3ea08b Author: Tomas Bzatek Date: 2010-03-09 Fix libm linking Nemo was underlinked, found by recently introduced change in Fedora: https://fedoraproject.org/wiki/Features/ChangeInImplicitDSOLinking /usr/bin/ld: ../libnemo-private/.libs/libnemo-private.a(eel-canvas.o): undefined reference to symbol 'floor@@GLIBC_2.0' /usr/bin/ld: note: 'floor@@GLIBC_2.0' is defined in DSO /lib/libm.so.6 so try adding it to the linker command line /lib/libm.so.6: could not read symbols: Invalid operation M configure.in commit 4df08e047b42ae4d11cd1edbbb7e99f95ae1b326 Author: Tomas Bzatek Date: 2010-03-08 Remove obsolete defines M configure.in commit 02afb2f5f2b95185c42ecac87af089a8ca8488ab Author: Alexander Larsson Date: 2010-03-08 Bump version to 2.29.92 M configure.in commit 7d79c4ad6db9a39ca6d37bb7eadd95ff84ac2af5 Author: Alexander Larsson Date: 2010-03-08 Update NEWS for release M NEWS commit b6958cb2d9e699c3a81ab39b9aa7766f6070a832 Author: Alexander Larsson Date: 2010-03-08 Don't close the window you initiated an unmount in. Based on patch from Luke Symes M src/nemo-application.c M src/nemo-navigation-window-slot.c commit 80dd8fb8ff0df3aa32314c633b04173517da3a36 Author: Alexander Larsson Date: 2010-03-08 Set initiated_unmount on windows while unmounting M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/nemo-places-sidebar.c commit 5e7f95842228f289b2940f23e63a2dd3b2cca842 Author: Alexander Larsson Date: 2010-03-08 Always call back from nemo_file_unmount/eject, even on success M libnemo-private/nemo-file.c commit 7fb5d7f6e4c32ab391eb9f3a61c0cab59c585874 Author: Alexander Larsson Date: 2010-03-08 Add nemo_file_operations_unmount_mount_full with a callback M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-operations.h commit 43f080c97369796043e45719933f536e0b29582f Author: Luke Symes Date: 2010-03-08 Implement the initiated_unmount property for NemoWindow. Windows will have this set to TRUE when one of their slots initiates an unmount. https://bugzilla.gnome.org/show_bug.cgi?id=611569 M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/nemo-window-private.h M src/nemo-window.c commit e1e1fe0d505bdb9b53d7204bba0abeee52f73bca Author: Tomas Bzatek Date: 2010-03-08 Load tracker/beagle at runtime Dynamically load tracker (preferred) and beagle client libraries on demand if available. This allows more flexibility for packagers and users. See bug 589345 for details. M configure.in M libnemo-private/Makefile.am M libnemo-private/nemo-search-engine-beagle.c M libnemo-private/nemo-search-engine-tracker.c M libnemo-private/nemo-search-engine.c commit bbe632e641df6f184de338b8215e390139adc573 Author: MiloÅ¡ Popović Date: 2010-03-07 Fixed typo in Serbian translation M po/sr.po M po/sr@latin.po commit e9e1dbc188983bac428bade85becbfea079306a0 Author: MiloÅ¡ Popović Date: 2010-03-07 Updated Serbian translations M po/sr.po M po/sr@latin.po commit 8217aa1931ed6f275d3651003fe3e599baaf8245 Author: Christian Kirbach Date: 2010-03-06 Updated German translation M po/de.po commit a6715be7e462109020f8450fe9781ea70e5ca128 Author: Holger Berndt Date: 2010-03-05 Bring back + for tab changing Make the first 10 tabs of every pane changable via keyboard shortcuts +1, +2 etc. This brings back non-GUI functionality that was removed together with the tab menus in e156e39e07276a4de8414bfdb82340f8762060b4 Fixes bug 609924 M src/nemo-navigation-window-menus.c commit 97ef4d40e6c743620e0629ee768b6df0effa61df Author: Kjartan Maraas Date: 2010-03-04 Updated Norwegian bokmÃ¥l translation M po/nb.po commit 4f870048b8d6754e29dd5ed0c4104f453caf7d3b Author: Rodrigo Moya Date: 2010-03-04 Replace deprecated GTK_WIDGET_* macros and depend on newer GTK+ M configure.in M libnemo-private/nemo-clipboard.c M libnemo-private/nemo-horizontal-splitter.c M libnemo-private/nemo-icon-canvas-item.c M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-progress-info.c M libnemo-private/nemo-tree-view-drag-dest.c M src/file-manager/fm-list-view.c M src/file-manager/fm-properties-window.c M src/file-manager/fm-tree-view.c M src/nemo-application.c M src/nemo-bookmarks-window.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c M src/nemo-notebook.c M src/nemo-pathbar.c M src/nemo-side-pane.c M src/nemo-spatial-window.c M src/nemo-window-manage-views.c M src/nemo-window.c M src/nemo-zoom-control.c commit af9305deb5a699fa430599685f25ad363d280808 Author: Leonid Kanter Date: 2010-03-04 Update Russian translation by Yury Kozlov M po/ru.po commit 4d742c83498df29d6f4b853dca946c0b4c4b13a3 Author: Alexander Larsson Date: 2010-03-03 Revert "Put tabs at the bottom" This reverts commit c6ee7553fd029239eff50d32dbcb57223ffa185e. We have gotten feedback that this experiment was not liked by users, so reverting. M src/nemo-notebook.c commit 7aad24446ce11d8508853cc0541590d3c8e0f99d Author: Umarzuki bin Mochlis Moktar Date: 2010-03-03 Update Malaj translation. Fixes bug 610519. M po/ms.po commit 95ae539e8d042b04ee9c6817bcc41f551ab207fc Author: Alexander Larsson Date: 2010-03-03 Revert "Don't grab focus on realize" This reverts commit 4efd42312584b46f248e2839582a87776a7baebe. We now don't store the extra view visible status, so the problem this change fixed is gone. And this change caused other focus issues, as per bug 607060. M libnemo-private/nemo-icon-container.c commit c8ded383147e0f860f9a206e9f45606bf16effe9 Author: Holger Berndt Date: 2010-02-25 Don't remember status of extra pane in a gconf key The focus for Nemo' split view mode are occasional, temporary switches to a split view mode for heavy-duty filebrowsing, not to be a permanent double pane filemanager. Therefore, neither split-view toggle status nor splitter position of a window are supposed to affect subsequently opened windows. See comments at bug 608431. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-navigation-window.c commit 0b6dd131e0d4d4ce7694b824e9925c1d021d9754 Author: Changwoo Ryu Date: 2010-03-01 Updated Korean translation M po/ko.po commit 82018666fb492bb423f4bcaccfa9bd50d868974d Author: Daniel Nylander Date: 2010-02-28 Updated Swedish translation M po/sv.po commit 582c1021a4b2f9039296a67bb45f8c3d51c327d5 Author: Piotr DrÄ…g Date: 2010-02-28 Updated Polish translation M po/pl.po commit 78ed12260a72967f7e1d135c4ffe7d51c44e3021 Author: Mario Blättermann Date: 2010-02-27 Updated German translation M po/de.po commit 1688fbbbcd1a55c7a731f65fdef31b9d7c90ed60 Author: Joan Duran Date: 2010-02-27 Updated Catalan translation M po/ca.po commit 533c274c00f1d6ab27b56e58363acd164e15d268 Author: Torstein Adolf Winterseth Date: 2010-02-27 Updated Norwegian Nynorsk translation M po/nn.po commit c7e51ada91e966af89b14c46f6fd20a4da0f5e3c Author: Bruce Cowan Date: 2010-02-24 Updated British English translation M po/en_GB.po commit 5dc02f0410a14b17bcdf74404b79c6b97a47c6e2 Author: Gintautas Miliauskas Date: 2010-02-23 Updated Lithuanian translation. M po/lt.po commit 64c484ae80012d120c3420f9fdd09915aaed32f4 Author: Alexander Shopov Date: 2010-02-23 Updated Bulgarian translation M po/bg.po commit 5f1d9d7b17a9b21d934d05e9c3e724a3ff3318a8 Author: Alexander Larsson Date: 2010-02-22 Require latest gnome-desktop for spanning bg M configure.in commit dd7f350e54b99c6644632062f44165e29a2fd8e6 Author: Alexander Larsson Date: 2010-02-22 Remove src/nemo-throbber.c from POTFILES.in M po/POTFILES.in commit 6b445d8c23b82327083ccd7a0254ccd5d001cfbc Author: Alexander Larsson Date: 2010-02-22 Update NEWS for release M NEWS commit d27a9a4260f76602a0c5e88706c1641e06515971 Author: Alexander Larsson Date: 2010-02-22 Use GtkSpinner instead of custom widget Forgot this part of the commit... M configure.in M src/Makefile.am M src/nemo-navigation-window.c M src/nemo-notebook.c M src/nemo-window-private.h M src/nemo-window-toolbars.c commit 07a6c14e4008e6ea131e5740485e8bd66547db3e Author: A. Walton Date: 2010-02-22 Use GtkSpinner instead of custom widget D src/ephy-spinner.c D src/ephy-spinner.h D src/nemo-throbber.c D src/nemo-throbber.h commit 472d7b454862e5a18a4e04f50162b1cfe41beb30 Author: Luke Symes Date: 2010-02-16 Go to computer:/// on unmount M src/nemo-application.c commit a3f5dde5051737beceeb6bc825758d0ecce1e3fd Author: Luke Symes Date: 2010-02-17 Fix location check in should_close_with_mount https://bugzilla.gnome.org/show_bug.cgi?id=318094 M src/nemo-navigation-window-slot.c commit 45f7cbb0bf331f6e99fc5cbb8dcc84f3b26455fa Author: vasudeven Date: 2010-02-21 updated Tamil translation M po/ta.po commit 8df9b4a10a31532c52f5fbc36f8dee60fa04948d Author: Alexandre Franke Date: 2010-02-20 Update French translation to show real last translator M po/fr.po commit e8099533621bdb3a24178ea05d5a88586259e319 Author: Alexandre Franke Date: 2010-02-20 Fixed French translation (closes bug 610365) M po/fr.po commit 47eaabdecb657c284366c1832206595e470242c6 Author: Khaled Hosny Date: 2010-02-19 Updated Arabic translation M po/ar.po commit 3de6a780cb9dde0c54537139a81ab8186b81ccde Author: Matthias Clasen Date: 2010-02-18 Make it possible to have backgrounds spanning multiple monitors. gnome-desktop added a new 'spanned' picture_option for this. This fixes bug 610396. M eel/eel-background.c M eel/eel-background.h M libnemo-private/nemo-directory-background.c commit 402f79e82c91b5129fa8fb11840d390a8527e2fb Author: vasudeven Date: 2010-02-18 updated Tamil translation M po/ta.po commit e570e2f6fd6ed73aa472d85409be2e01107caa5c Author: Rene Pärts Date: 2010-02-17 Estonian translation updated M po/et.po commit 5de7ed5ee5c9857615c2da8c6424fa99e365dc26 Author: Fran Diéguez Date: 2010-02-15 Updated Galician Translation M po/gl.po commit ecdea68af78c46fbf9b7ecfb77cc8f71f4cfb687 Author: vasudeven Date: 2010-02-15 updated Tamil translation M po/ta.po commit 6549e2e1ef18e20bd6023d645092ae7b3b735d2f Author: Ask H. Larsen Date: 2010-02-14 Updated Danish translation M po/da.po commit 467e375bc52d1ceb400534c5d9d2995de1b40789 Author: Claude Paroz Date: 2010-02-13 Updated French translation Contributed by Claude Paroz and Bruno Brouard M po/fr.po commit 8d7e2a397fe4a70707c9fb92a98c1dfe2b621e2e Author: Lucian Adrian Grijincu Date: 2010-02-13 Update Romanian translation M po/ro.po commit 662e19941905cf80a9131e56cefc4eab69f6e5da Author: Fran Diéguez Date: 2010-02-12 Updated Galician Translation M po/gl.po commit bbb9d918761c07e0711c058e7b8295b3d7079ff3 Author: Matej UrbanÄiÄ Date: 2010-02-11 Updated Slovenian translation M po/sl.po commit 862ba955f5f918eca3853faef00de67f1066c5c7 Author: Chao-Hsiung Liao Date: 2010-02-10 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit ef76f4421331a8575f43db2c4cd5b26a2f5952a2 Author: Tomas Bzatek Date: 2010-02-09 Post release version bump M configure.in commit 574b9a27bcb631dfa616e856f9f11131ddd1e150 Author: Tomas Bzatek Date: 2010-02-09 Update for 2.29.90 M NEWS M configure.in commit e302cf74e2374f3e3850b4341c3456199d520726 Author: Gabor Kelemen Date: 2010-02-08 Hungarian translation updated M po/hu.po commit 09c0a7dfeb8530dcf8cc871b7377d27e4c41c2bd Author: Theppitak Karoonboonyanan Date: 2010-02-08 Updated Thai translation. M po/th.po commit a38cc9eb354fb48f48c38501ccf649a9e3f412d5 Author: Henrique P. Machado Date: 2010-02-06 Updated Brazilian Portuguese translation M po/pt_BR.po commit 80ce7ee481d292fae620b878b1c83dd65d71dfbe Author: Jorge González Date: 2010-02-06 Updated Spanish translation M po/es.po commit ebca4f18692c06e8af724317a82328a84514e6b0 Author: Claude Paroz Date: 2010-02-06 Fix copy-pasted tooltip string M src/file-manager/fm-directory-view.c commit cd49c551d46a41d803d8bb76c7bef6d395e14369 Author: Jennie Petoumenou Date: 2010-01-31 Updated Greek translation M po/el.po commit fde78a67b016d7c59b86145ac31d6b46462ee1b0 Author: Mattias Põldaru Date: 2010-01-29 Updating Estonian translation M po/et.po commit cf6477ac9b5576ab0f28077d817388fc3b77637f Author: Jamil Ahmed Date: 2010-01-29 Updated Bengali translation M po/bn.po commit e7f8fdf47e421122a7d13703fd3ff6cb6cd14b82 Author: Alexander Shopov Date: 2010-01-26 Updated Bulgarian translation M po/bg.po commit 4474a1d606c486486eb88e5043da500dd5885e1d Author: Alexander Larsson Date: 2010-01-25 Post release version bump M configure.in commit 49967fd917d0ae5f3e5d63858199fd41e1cd0811 Author: Alexander Larsson Date: 2010-01-25 Update NEWS for release M NEWS commit 1b07696835481a911e44c5964eeb545537242cff Author: Khaled Hosny Date: 2010-01-23 Updated Arabic translation M po/ar.po commit e156e39e07276a4de8414bfdb82340f8762060b4 Author: Alexander Larsson Date: 2010-01-22 Remove tabs menu I don't think this menu is much use, and it clutters up the menus even for users who don't use tabs, which is against our policy of having the more advanced features affect users not using them as little as possible. Also, remove the setting to disable tabs althoughter, as with the menu removed the tabs feature is very minimal when not in use. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/file-manager/fm-tree-view.c M src/nemo-actions.h M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c M src/nemo-places-sidebar.c M src/nemo-window-private.h commit c9d59901003f635221299ca90887b830f3c0a3fa Author: Kjartan Maraas Date: 2010-01-22 Updated Norwegian bokmÃ¥l translation M po/nb.po commit ec8b9a8b58ddd9d6bf08ac9e0b875581009255b3 Author: Thomas Hindoe Paaboel Andersen Date: 2010-01-18 Replace deprecated GTK_OBJECT_TYPE with G_OBJECT_TYPE GNOME bug 565038 M eel/eel-canvas.c commit 6146cd17e4340ca3af43050e405c7ef64efd6e5d Author: Benjamin Berg Date: 2010-01-19 Use test instead of fg for eel-editable-label test Since we use base for the background we should use text for the foreground. (#548295) M eel/eel-editable-label.c commit 46af408406ace29ad8e52e26cdfb43c50c5b96ca Author: Jorge González Date: 2010-01-16 Updated Spanish translation M po/es.po commit fb138478020738917f0fe408e5c4e2fafd3c2bb8 Author: Nelson Benítez León Date: 2010-01-06 Update glib required version M configure.in commit 7fcd79f3d404a734095b4e42cfa36b45aad95c4d Author: dumol Date: 2010-01-10 Updated Romanian translation M po/ro.po commit e050b4134983ea14115d276ee41ba3e877952e52 Author: Lucian Adrian Grijincu Date: 2010-01-10 Updated Romanian translation M po/ro.po commit 344f80b837341e114f5a4f7473ad7d7cfa3c6efc Author: Daniel Nylander Date: 2010-01-09 Updated Swedish translation M po/sv.po commit c444f6d555df95ea2767992c0af6a7cdce3f0d53 Author: Maxim V. Dziumanenko Date: 2010-01-06 Update Ukrainian translation M po/uk.po commit dd151d503dbe6c12dca868b69a8bcddf8fc798b4 Author: Timo Jyrinki Date: 2010-01-06 A few fixes by me from Launchpad. M po/fi.po commit 8769220d5c95057470d58c7591732afc126b58a1 Author: Mattias Põldaru Date: 2010-01-05 Updating Estonian translation M po/et.po commit a12dd191b5b0286a975e8dbfb435ddc09ec1f930 Author: Matej UrbanÄiÄ Date: 2010-01-02 Updated Slovenian translation M po/sl.po commit 331e69edcb178fe157a2990ea9beab0cd128a6be Author: Khaled Hosny Date: 2009-12-25 Updated Arabic translation M po/ar.po commit 972d4f7a4c04f1fffe1a6ad7aa8c4fc9b5bead49 Author: Jorge González Date: 2009-12-19 Updated Spanish translation M po/es.po commit 89c29e1beb04b7f0cc751976bff052af26faf8cd Author: Alexander Larsson Date: 2009-12-17 Move the navigation bar size group to be a cross window header size group This way we can make sure we align the headers of the sidebar too. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window.c M src/nemo-side-pane.c M src/nemo-window-private.h commit 595150f7a94664fb247cef5b0af714fd7f1c0e6b Author: Alexander Larsson Date: 2009-12-17 Add nemo_side_pane_get_title M src/nemo-side-pane.c M src/nemo-side-pane.h commit f8447895dbb680a7abbb483a80d1db05e07ee730 Author: Alexander Larsson Date: 2009-12-17 Post release version bump M configure.in commit 0c33ea773fa27da99187c3bd7ddfcbb42ed6d90d Author: Alexander Larsson Date: 2009-12-17 Fix up include M src/nemo-location-bar.h commit 056ac6c3deaad63f70b61c68743cd03baa0db726 Author: Alexander Larsson Date: 2009-12-17 Dist nemo-extension-private.h M libnemo-extension/Makefile.am commit 2622cc470fa482f8b766bd9a37afc1f0597b8e08 Author: Alexander Larsson Date: 2009-12-17 Remove the rest of shave M Makefile.am M configure.in D m4/Makefile.am commit 21b1aa0144389f7f0a9645d0a734fe5881223844 Author: Alexander Larsson Date: 2009-12-17 Update NEWS for release M NEWS commit e2363ba468bca0662a7f139386432a677478f722 Author: Alexander Larsson Date: 2009-12-17 Change "enable browser" prefs to "enable spatial" Since browser is now the default we want to change the description and default state of the prefs UI for this to follow this change. M src/nemo-file-management-properties.c M src/nemo-file-management-properties.ui commit 70f2f7c8e36898553ba0c6593aee1e8ee52bd7a7 Author: Alexander Larsson Date: 2009-12-17 Add eel_preferences_builder_connect_inverted_bool M eel/eel-preferences-builder.c M eel/eel-preferences.h commit 07c0bf9cb422d38fb4c38faed7af261c5411378c Author: Alexander Larsson Date: 2009-12-17 Enable browser mode by default As discussed on the list we're moving to browser mode with the switch to gnome-shell. Gnome-shell is not quite ready yet, but we want to move towards that as early as possible so we can iron out all the details in the new behaviour. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c commit c69f3a2ba2d0bd23de5a218b8ce13d256481213a Author: Alexander Larsson Date: 2009-12-17 When showing a window for the first time, focus the active slots view M src/nemo-window.c commit cf1e32162affc91b5b3a2ca934c0dee45e3f1a2e Author: Alexander Larsson Date: 2009-12-17 Set right slot in active pane state for new views M src/nemo-window.c commit 4efd42312584b46f248e2839582a87776a7baebe Author: Alexander Larsson Date: 2009-12-17 Don't grab focus on realize This causes problems when opening up an extra view as it forces it to become focused which is not what we want. M libnemo-private/nemo-icon-container.c commit d9abc4bf2ff65009ab1521c31f0877b0e312c8a6 Author: Alexander Larsson Date: 2009-12-17 Move "go to same location as other pane" in the menus We don'r want separators around this single item, put it with the navigation stuff instead (not ideal, but ok). M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml commit ea28580ac582c6df66215b39743e3914c422f236 Author: Alexander Larsson Date: 2009-12-17 Fix typo M src/nemo-navigation-window-ui.xml commit 3fb63af8aed0f350f4eabf65085d80a4442a34b5 Author: Alexander Larsson Date: 2009-12-17 Remove switch to other pane menu item and make F6 do this instead This is a very useless menu item, its sole reason for existance is to bind a keyboard combo to it. Instead we should just choose one. Some research indicate that F6 is standard for this. In Gtk+ F6 is used for split view navigation in general, so it will toggle between the sidebar and the two views. However, you can reach the sidebar in other ways using keynav, and the more important thing is the pane toggling, so we override this and make F6 be pane switching only. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml commit b4f413314de5857867ef152384741c49f2613737 Author: Alexander Larsson Date: 2009-12-17 Replace shave with AM_SILENT_RULES M configure.in M eel/Makefile.am M libnemo-private/Makefile.am D m4/shave-libtool.in D m4/shave.in D m4/shave.m4 commit 8f3e5b8d65d5c67ce6b762c8c33efc42ee13f6c3 Author: Alexander Larsson Date: 2009-12-17 Don't focus the search entry when we're activating a pane with search This is not the right behaviour, and additionally it caused problems to do this from the focus in signal handler for the icon view, since the recursion of the focus changes caused HAS_FOCUS state to be mixed up. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c commit a9384103fe8822a351aa5256c21e00058bfef310 Author: Alexander Larsson Date: 2009-12-17 Set active pane when its search bar gets focus M src/nemo-navigation-window-pane.c commit e5806d3a65f0b6dda23d4c4c12d53a5d09cc1f52 Author: Alexander Larsson Date: 2009-12-17 Add event for search bar getting focus M src/nemo-search-bar.c M src/nemo-search-bar.h commit aecc6b6abf1e1c313d2d4473902a2b9eb0e11827 Author: Alexander Larsson Date: 2009-12-17 Minor whitespace cleanups M src/nemo-window.c commit adc968f34c1085ce4e5378fba92655082052f13d Author: Alexander Larsson Date: 2009-12-17 Move nemo_navigation_window_pane_set_active into a vfunc Now nemo_window_pane_set_active works for both navigational and spatial panes. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit 36ba547921917daa970bd2d8510e3cd1bef894bf Author: Alexander Larsson Date: 2009-12-16 Move active background color handling to the view This stuff references view implementations and should not be in the generic code. M libnemo-private/nemo-view.c M libnemo-private/nemo-view.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/fm-list-view.c M src/nemo-window-slot.c commit 096453c004a2538b816046b0388d6cfb60b618b2 Author: Alexander Larsson Date: 2009-12-16 Remove unnecessary check M src/nemo-window-manage-views.c commit d40b44e5f54a16bdf91ebf2d291732941717fdc6 Author: Alexander Larsson Date: 2009-12-16 Clean up sync_location_widgets by using vtable calls instead of type checks M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-window-pane.c M src/nemo-window-pane.h commit 7c66c6c020edf40383681a6e691c1451ff90b9f7 Author: Alexander Larsson Date: 2009-12-16 Only update toolbar items when active pane changes M src/nemo-window-manage-views.c commit cc3241aa713b99c72f30b01be9179f9b7a4635fc Author: Alexander Larsson Date: 2009-12-16 Fix indentation M src/nemo-window-slot.c commit 3a9fae22b64e4c4c3fa66520314285b4a8b836bb Author: Alexander Larsson Date: 2009-12-16 Move sync_search_widgets from window to pane Since the search widgets are per pane we need only update them for the pane, never for all the window. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-slot.c M src/nemo-window.c M src/nemo-window.h commit a6b53ce4d5b811c854ef8987d1bf6af7ab355b68 Author: Alexander Larsson Date: 2009-12-16 On view selection failure, reload the right window M src/nemo-window-manage-views.c commit 1d62423f6518be0a063e93cc160a0ffdae26ff6d Author: Alexander Larsson Date: 2009-12-16 Remove nemo_window_sync_location_widgets Not used anymore M src/nemo-window-manage-views.c M src/nemo-window-private.h commit 8a0ca66f2c2d69cc50cdbcc319f80529b1b30d00 Author: Alexander Larsson Date: 2009-12-16 Only sync the location bar on the affected pane M src/nemo-window-manage-views.c M src/nemo-window-slot.c commit bc87c744f84fe3c787fd504d811db4ba5c50de79 Author: Alexander Larsson Date: 2009-12-16 Fix window slot close crash On window close via nemo_window_close when the viewed file closed there was a ref on the slot living past the window. This caused crashes when disposing the slot as it referenced the window. We fix this by running the dispose handler when closing a slot and by making the dispose handler able to run multiple times. M src/nemo-window.c commit 9d8f34fa253c9c2812cfc7a738e4751fff18c1dd Author: Alexander Larsson Date: 2009-12-16 Remove fm_directory_view_move_copy_items_between_views not used anymore M src/file-manager/fm-directory-view.c commit ce2e90c30506cbce28addf3258938824a1a61494 Author: Alexander Larsson Date: 2009-12-16 Revert "Pass the window instead of the view to action callbacks." This reverts commit f3390c4f9a277ffd95bc5f3c6e475d9dad7d8935. It makes no sense to pass the window for all view specific callbacks. If anything needs to access the window that is easily doable from the view reference. Conflicts: src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.c commit 0a6c249015c7ab1cfa62e64428652970d397f57b Author: Alexander Larsson Date: 2009-12-16 Rearrange copy/move to menus and add home + desktop items M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml commit 3bd562283262314fc8dd9840a3c1b5d390ab1860 Author: Alexander Larsson Date: 2009-12-16 Don't disable next pane ops if tabs are disabled M src/file-manager/fm-directory-view.c commit ef9b76bc41992a0bd9bb870e64ee0749bfe74d8b Author: Alexander Larsson Date: 2009-12-16 Remove unnecessary includes M src/nemo-window.c commit dc26bef3e209d654c8f952ff4837beb34c0fa8ae Author: Alexander Larsson Date: 2009-12-16 Remove next_pane functions from NemoWindowInfo No need for these, and they put FMDirectoryView at the wrong place. M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/nemo-window.c commit 0ea5a1bfe0815f71fcacec151852bada86b477f2 Author: Alexander Larsson Date: 2009-12-16 Remove use of nemo_window_info_copy_move_selection_to_next_pane Doing this via the window is unnecessary. Also, we simplify the copy operation by not using cut+paste. M src/file-manager/fm-directory-view.c commit e0a6c302d23fde1e4781671f70d501fdeffb7c8f Author: Alexander Larsson Date: 2009-12-16 Don't use nemo_window_info_next_pane_is_writable Instead we can use get_extra_slot and other existing functions, thus avoiding referencing fm-directory-view from the main code. M src/file-manager/fm-directory-view.c commit 1545e04eaf41068c3add34792815b2df84b7fd5d Author: Alexander Larsson Date: 2009-12-16 Use window_get_extra_slot instead of get_directory_view_of_next_pane We want to remove get_directory_view_of_next_pane as the main code should not reference FMDirectoryView. M src/file-manager/fm-directory-view.c commit 6a71f0f996e7c946a10e263951a906dd9795c4dc Author: Alexander Larsson Date: 2009-12-16 Add nemo_window_info_get_extra_slot M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/nemo-window-private.h M src/nemo-window.c commit 7545b45b7c1c1f849b01814304b24af5238dba7e Author: Alexander Larsson Date: 2009-12-16 Remove unnecessary includes M src/nemo-navigation-window.c commit fa563623570eeb6a0ab8d90aae386ecbbd740721 Author: Emilio Pozuelo Monfort Date: 2009-12-15 Bug 604574 - Fix NAME section in nemo-connect-server.1 M docs/nemo-connect-server.1 commit 9c7c2c9d2cc0a8648abf2dbc851e9efec3e3df1c Author: Alexander Larsson Date: 2009-12-15 Make trash keybindings only work if the action is sensitive This fixes https://bugzilla.gnome.org/show_bug.cgi?id=603413 in a way not causing regressions. M src/file-manager/fm-directory-view.c commit d87cf7e75c37d139631807bc22c07ba879f8218f Author: Alexander Larsson Date: 2009-12-15 Use right signal handler for delete signal action This is not actually called atm, since an action overrides it, but we should do it right anyway. M src/file-manager/fm-directory-view.c commit d5d94cdf05a8f775494e5445e0c899a4548d2690 Author: Alexander Larsson Date: 2009-12-15 Revert "Disable Trash/Delete key bindings when appropriate" This reverts commit e7c171acb8060436969139210060874f3a43d835. It causes regressions (see bug 603413) Conflicts: src/file-manager/fm-directory-view.c M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml commit 75bcfea177c837215ea46c970bfea24ec04a3dae Author: Alexander Larsson Date: 2009-12-14 Don't access uninitialized variable gdk_property_get doesn't set prop_text if it fails. M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-tree-view-drag-dest.c commit fb39afae9bf1027cf405f7309685327abd67f1bf Author: Alexander Larsson Date: 2009-12-14 Better tab size This removes the minimum size of tabs, since that causes problems when there are little availible horizontal size (such as in split view), as it caused ellipsizion to only work for strings larger than the minimum set size. However, doing *just* this causes the tabs by default to be only 3 chars wide, which is obviously also bad. So we enable tab-expansio to solve this. The new situation is not ideal either, but its the best we can do before this gtk bug is fixed: https://bugzilla.gnome.org/show_bug.cgi?id=125250 M src/nemo-notebook.c commit 7fb432ba6b6816076e9eb5cd6f586df2e90ed33a Author: Alexander Larsson Date: 2009-12-14 Better split view size allocation Ensure that the views always get *some* size so that we can at least always see the scrollbars, etc. Also make the toplevel size of a pane be a fixed size, thus guaranteeing the two panes in a split view return the same size request, thereby guaranteeing a default (if unset by user) position of 50%. Without this we could get e.g. a size request from the tabs or the location bar size change causing a change in the view splitter position. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit 50fece012964a9bea091a21bb51d65bf877a1ff4 Author: Alexander Larsson Date: 2009-12-14 Don't allow the right part of the sidebar split be shrunk Views at 0x0 pixels make no sense. M libnemo-private/nemo-horizontal-splitter.c commit ee66bca8b74b1530e29414ef226e12157e92d9b7 Author: Alexander Larsson Date: 2009-12-14 Make slot label/icon update work right We move the update calls to a bit later when all the slot-internal state (like slot->location, etc) has been updated. M src/nemo-window-manage-views.c commit 53ae0522ab2ee458eb8235beaf6c8e3afefe49b6 Author: Alexander Larsson Date: 2009-12-14 Minor cleanup Use temporary variable to avoid casts. M src/nemo-navigation-window.c commit 451aafee60cd171650993c5b7640116319eebc9e Author: Alexander Larsson Date: 2009-12-11 Require latest gnome-desktop for gnome-bg changes M configure.in commit 04c26296fb78b6de1a5bf933e543734ce18bd062 Author: Alexander Larsson Date: 2009-12-11 Move status bar to under view in navigational view This means the status bar moves closer to what it shows the status of. Additionally it gives more space for the sidebar, which is not needed for the normally small status messages we have. M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window.c commit 7c1207aa1317e95762b9773f7a2ca72a96177942 Author: Alexander Larsson Date: 2009-12-11 If starting with split view, create extra slot durin construction M src/nemo-navigation-window.c commit 1a6db1b3ff79971f75ad309c22d60c14b2af2857 Author: Alexander Larsson Date: 2009-12-11 Don't show the window until all views in it are visible For the dual-pane at startup case we want to delay window change until all views are loaded. Also when switching to split view we want to delay showing until the view is loaded. M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/file-manager/fm-directory-view.c M src/nemo-navigation-window-pane.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-slot.h M src/nemo-window.c M src/nemo-window.h commit 84631cacd1909000ebd43b7267b7cacb8115d857 Author: Alexander Larsson Date: 2009-12-11 When loading a location in a slot also load in other non-loaded panes This makes sure that if a window is created with more than one pane we'll load something in each of them. M src/nemo-window-manage-views.c commit fbbf8701595d4b6ad3cef93cc83e861d35b34859 Author: Alexander Larsson Date: 2009-12-11 Fix up indentation M src/nemo-window.c commit fb87db4e78a494623921a1ad844b86448965a924 Author: Alexander Larsson Date: 2009-12-11 Update location for all active slots When the location changes for a slot we should update it if its the active slot in its pane (since each pane has a location bar), not only if its in the active pane. M src/nemo-window-manage-views.c commit 605cdcc062c77c3badcb03eb0c8f97385b4739a4 Author: Alexander Larsson Date: 2009-12-11 Remove nemo_window_get_pane_from_slot This is useless, just look at slot->pane M src/nemo-window-private.h M src/nemo-window.c commit 877da7dab374c4ae66ee57b7e5c10e672058b523 Author: Alexander Larsson Date: 2009-12-11 Only sync tab name in menu for the active pane M src/nemo-navigation-window.c commit 55f1438bf898c819504dae540a7540ec30508f1e Author: Alexander Larsson Date: 2009-12-11 Don't rewrite bookmarks file when file appearance changes We no longer write the icon to the bookmarks file so this is just unnecessary. Also this means we don't rewrite the bookmark file on each startup. M src/nemo-bookmark-list.c commit 3fab1d20298552000369480a694186fd7354f586 Author: Alexander Larsson Date: 2009-12-11 Fix up background setting for non-desktop windows M eel/eel-background.c commit c68a696dcb8884ded4571c375e368f3f3375d068 Author: Alexander Larsson Date: 2009-12-10 Only fade the desktop background, not normal windows All this flashing is just in the way, especially when the color changes as part of a pane going inactive. M eel/eel-background.c commit 6e5323188fc6af5d8920a01c3e34496df3320760 Author: Alexander Larsson Date: 2009-12-10 Remove border width on notebook This makes the view line up with the sidebar, etc. M src/nemo-navigation-window-pane.c commit 09efd40fbb2cd924bfee6650bea50e2ffb21a349 Author: Alexander Larsson Date: 2009-12-10 Remove border on statusbar https://bugzilla.gnome.org/show_bug.cgi?id=499361 M src/nemo-window.c commit 9bc68d825f3e928e736caf213b84371607a6bd41 Author: Baptiste Mille-Mathias Date: 2009-12-10 Put border around file views https://bugzilla.gnome.org/show_bug.cgi?id=499361 M src/file-manager/fm-directory-view.c commit c6ee7553fd029239eff50d32dbcb57223ffa185e Author: Alexander Larsson Date: 2009-12-10 Put tabs at the bottom There is way to much visual clutter at the top already, with the location bars and toolbars. M src/nemo-notebook.c commit 4b49aab5aa6a9ef9ab288ff2ce463affca1eacf2 Author: Alexander Larsson Date: 2009-12-10 Remove location button This takes a lot of space for something thats not commonly used. Especially with two of it visible in split view mode. Maybe we should make a preference for it, but its not interesting in the main UI. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h commit df7048157403efefb560c5d1075f04088af3048b Author: Holger Berndt Date: 2009-12-05 Improve search button handling in split view mode This commit fixes issues that were introduced in merge commit e92c336df90df012746d08d9af8121edc38b0f3c Now the escape key during temporary search toggles the search key off again, as does changing active pane during temporary searches. M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h commit 8bafe8109f2151ee1febfc4a00255b92053c2ef8 Author: Holger Berndt Date: 2009-06-25 Fix View -> Location Bar in dual pane mode. Although each pane has a separate location bar, the show/hide location bar setting is window-global instead of applying to individual panes: Either both panes have a location bar, or neither one does. Inconsistencies with remembered show/hide location bar gconf setting were also fixed. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c commit ee3c49268205cd6fd99694706a4b2b7e3aca8086 Author: Alexander Larsson Date: 2009-12-10 Remember extra pane status access windows. The status of the extra pane display is remembered in a gconf key, analog to show/hide statusbar and other window display properties. As the extra-pane action implementation does a lot of widget and action re-ordering, this can only be done when a windows is set up completely, and is thus delayed in an idle-callback. If splitting the view is to be done on startup, the showing of the window is delayed to avoid ugly visible reordering. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-actions.h M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window-slot.c M src/nemo-window.c commit 5d236a20aadd291196e6ead3a2220e9c0258b126 Author: Holger Berndt Date: 2009-06-13 Make it possible for Nemo Scripts to access the other pane. This is accomplished by placing additional variables into the environment of the script, analoguous to the single-pane ones: - NEMO_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS - NEMO_SCRIPT_NEXT_PANE_SELECTED_URIS - NEMO_SCRIPT_NEXT_PANE_CURRENT_URI If there is no second pane in the window, these are set to empty strings. M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/file-manager/fm-directory-view.c M src/nemo-window.c commit 09359fd13b52c5f5cebe55a9efae21c0290fe86f Author: Holger Berndt Date: 2009-06-13 Implement "Go to same location as other pane" menu item. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml commit a0bd4bc51d556a44ada296b3d3ec22e6c19f04f4 Author: Holger Berndt Date: 2009-06-13 Implement "Switch to other pane" menu item. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-private.h commit 0a5d182ac274a0b11a39daa41285fbf1d39b1e70 Author: Holger Berndt Date: 2009-07-20 Also draw background of inactive pane in insensitive color when in list view M src/nemo-window-slot.c commit 2f843f0ed243a1c1f184c69e166c9da710fe1618 Author: Holger Berndt Date: 2009-06-13 Draw background of inactive panes in INSENSITIVE color. In order to make it easier to visually distinguish active and inactive panes, the background of inactive panes is drawn in the theme's INSENSITIVE color. Like the inactive location bar widgets, this is only a visual marker, and does not mean that that pane is insensitive. It's still clickable, and in fact a click makes the corresponding pane active. M eel/eel-background.c M eel/eel-background.h M src/nemo-window-pane.c M src/nemo-window-slot.c M src/nemo-window-slot.h commit 4cc909a668692551db92a67bcb36b7cdeb473579 Author: Holger Berndt Date: 2009-06-11 Implement "{copy,move} to other pane" menus. M libnemo-private/nemo-window-info.c M libnemo-private/nemo-window-info.h M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/nemo-directory-view-ui.xml M src/nemo-shell-ui.xml M src/nemo-window-private.h M src/nemo-window.c commit 7191f6fa4f3013481463c1181b51b705d5c48d9a Author: Holger Berndt Date: 2009-06-11 Fix tab menus in split view mode. Only the menu of the active pane is inserted. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c M src/nemo-window.c commit c3da9152ce3efadbeaf92340ca832af6dbfc6266 Author: Holger Berndt Date: 2009-06-11 Make location bar more reactive, part 2: navigation bar Followup to the last commit: The location bar of the inactive pane now has an insensitive apprearance, but is in fact clickable/focusable. A click makes the corresponding pane active via the focus-in event of the entry widget. M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-navigation-window-pane.c commit 689fd8e7ac943f1bed48dc0f6aad4b0e418e1005 Author: Holger Berndt Date: 2009-06-11 Make location bar more reactive: path bar, toggle button and zoom control The buttons in the directory button bar are made inactive when the corresponding pane is inactive. This means that the buttons have an insensitive appearance, but are in fact clickable. Clicking on them will make the corresponding pane active while changing into the respective directory. This required the pathbar to export the button widget, done with the new function nemo_path_bar_get_button_from_button_list_entry(). M src/nemo-navigation-window-pane.c M src/nemo-pathbar.c M src/nemo-pathbar.h M src/nemo-zoom-control.c M src/nemo-zoom-control.h commit 531ff030ef016b118f174252b1ac9aee0e385c63 Author: Holger Berndt Date: 2009-06-07 Don't use a function to get the active slot. M src/nemo-window-slot.c commit f3390c4f9a277ffd95bc5f3c6e475d9dad7d8935 Author: Holger Berndt Date: 2009-06-07 Pass the window instead of the view to action callbacks. With dual pane, actions may work on more than one view. Thus it makes sense to pass the window instead of the view to the callbacks. If the callbacks want the old behaviour, they first need to get the active view of the window, and work with that. M src/file-manager/fm-directory-view.c commit 3cb24525f5e3681592900a3db49f2862debf084d Author: Holger Berndt Date: 2009-06-07 Also active/deactive panes based on focus-in-event for list views M src/file-manager/fm-list-view.c commit 02529b86015195128ebcbe3702888445727d5679 Author: Holger Berndt Date: 2009-06-06 Propagate activation in slot-info interface M libnemo-private/nemo-window-slot-info.c M libnemo-private/nemo-window-slot-info.h M src/file-manager/fm-icon-view.c M src/nemo-window-slot.c commit 01e94440638904b0bc546b1ef1081a88e92d3e8e Author: Holger Berndt Date: 2009-05-27 Start implementation of "add extra pane" menu item callback Upon activating that menu item, create new pane and pack into the split view hpane. On deactivation, delete non-active pane. M src/file-manager/fm-list-view.c M src/file-manager/fm-list-view.h M src/nemo-navigation-window-pane.c M src/nemo-navigation-window.c commit 8babbe1095134861e4e57f482557587ee9b78576 Author: Holger Berndt Date: 2009-05-25 Add skeleton for split view. Add a new menu item "View -> Extra pane", and corresponding skeleton callback functions and UI containers. M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window-private.h commit 6fc12915c7e3b8e92696630117afb5d5f5aaf60c Author: Alexander Larsson Date: 2009-12-10 Move location from toolbar to pane widget M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window.c commit e1fe45ddde92aece9aafdeb2febcfe76178e48b1 Author: Holger Berndt Date: 2009-05-24 Move notebook from window into pane This is another refactorisation commit. A notebook is also pane specific, not window specific. In particular, the following function logic has been moved: notebook_popup_menu_move_left_cb notebook_popup_menu_move_right_cb notebook_popup_menu_close_cb notebook_popup_menu_show notebook_tab_close_requested notebook_button_press_cb notebook_popup_menu_cb notebook_switch_page_cb nemo_navigation_window_pane_setup_notebook The following functions have been renamed: nemo_navigation_window_initialize_tabs_menu to nemo_navigation_window_pane_initialize_tabs_menu (also made public) nemo_window_get_slot_for_content_box to nemo_window_pane_get_slot_for_content_box M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-notebook.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window.c commit f14e7d47456867899016889756f32120dda847fb Author: Alexander Larsson Date: 2009-12-09 Move location bar entries to pane Location bar entries are pane-specific, not window specific. Therefore, it is neccessary to move significant parts of the logic around, mainly from NemoWindow to NemoWindowPane, and NemoNavigationWindow to NautilisNavigationWindowPane. In particular, the following functions have been moved into the pane: bookmark_list_get_uri_index restore_focus_widget search_bar_activate_callback search_bar_cancel_callback navigation_bar_cancel_callback navigation_bar_location_changed_callback location_button_should_be_active location_button_toggled_cb path_bar_location_changed_callback path_bar_button_pressed_callback path_bar_button_released_callback path_bar_button_drag_begin_callback path_bar_path_set_callback nemo_navigation_window_show_location_bar_temporarily nemo_navigation_window_show_navigation_bar_temporarily nemo_navigation_window_path_bar_showing nemo_navigation_window_set_bar_mode nemo_navigation_window_search_bar_showing nemo_navigation_window_hide_location_bar nemo_navigation_window_show_location_bar nemo_navigation_window_location_bar_showing nemo_window_zoom_{in,out,to_level,to_default} The location bar setup parts of nemo_navigation_window_init() have been moved to nemo_navigation_window_pane_setup_location_bar. The following fuctions have been made public: hide_temporary_bars load_view_as_menu unset_focus_widget update_up_button Much logic of the following functions has been moved to the pane, but the functions themselves have been left in the window as triggers: nemo_navigation_window_hide_temporary_bars nemo_window_sync_location_widgets M src/nemo-application.c M src/nemo-location-bar.c M src/nemo-location-bar.h M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-pane.c M src/nemo-navigation-window-pane.h M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window.c commit 014b488d184fafe59f29810d372eccebd3c66876 Author: Holger Berndt Date: 2009-05-18 Use the new NemoNavigationWindowPane class in NemoNavigationWindow's M src/nemo-navigation-window.c commit 651053fec975b95536b7e967c7e8b81732b1f740 Author: Holger Berndt Date: 2009-05-18 Add new class NemoNavigationWindowPane, derived from NemoWindowPane NemoWindowPane is the base class for window panes, while NemoNavigationWindowPane will add some functionality spefic to panes in a Nemo navigation window. M po/POTFILES.in M src/Makefile.am A src/nemo-navigation-window-pane.c A src/nemo-navigation-window-pane.h commit e1db3d61f6510a8f6cc063ba84b5fa26bebf6189 Author: Alexander Larsson Date: 2009-12-07 Associate basic slot functions to panes instead of windows. M src/nemo-application.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-manage-views.c M src/nemo-window-manage-views.h M src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window.c M src/nemo-window.h commit e7f2144e38c02f6aeba7b563e8bc1fb195616477 Author: Alexander Larsson Date: 2009-12-07 Move slots from NemoWindow to NemoWindowPane A window does not hold lists of slots anymore, but lists of panes, which in turn hold lists of slots, making a slot effectively a layer between a window and a slot. Much of the remaining part of the patch is simply replacing "window->details->active_slot" with "window->details->active_pane->active_slot" and similar changes. Commits to move corresponding parts of the logic out of the window into the pane are to follow. M src/nemo-application.c M src/nemo-location-bar.c M src/nemo-location-dialog.c M src/nemo-navigation-action.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-bookmarks.c M src/nemo-window-manage-views.c M src/nemo-window-pane.c M src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window-slot.c M src/nemo-window-toolbars.c M src/nemo-window.c commit d3ee81d3021204786c3c51bf9f651fffbd10ff0b Author: Holger Berndt Date: 2009-01-31 Associate a slot to a pane instead of a window NemoWindowSlot->window is removed and NemoWindowSlot->pane is added. All references to window is then replaces with ->pane->window. M src/nemo-application.c M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-slot.c M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-manage-views.c M src/nemo-window-slot.c M src/nemo-window-slot.h M src/nemo-window.c commit adc0b289f6f92751bd40a6005375eae2a79439c3 Author: Alexander Larsson Date: 2009-12-07 Add a NemoWindowPane to all windows M src/nemo-navigation-window.c M src/nemo-spatial-window.c M src/nemo-window-private.h M src/nemo-window.c commit daa113b66fbf4193cdb049c11bd3df9f98f4ba0a Author: Holger Berndt Date: 2009-01-30 Introduce concept of a NemoWindowPane A pane is another layer around a slot. For spatial windows, a pane will contain a single slot. For navigation windows, a pane will contain a list of slots, as well as a corresponding toolbar items. M src/Makefile.am A src/nemo-window-pane.c A src/nemo-window-pane.h M src/nemo-window-private.h M src/nemo-window.c commit 8e69e90733dcb1bd65d2fdcc2a026cb458c25ed2 Author: Alexander Larsson Date: 2009-12-09 Remove all traces of old view-as and zoom widgets M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-window.c M src/nemo-window.h commit 14def79a4e1cd7d78d0dd155fa5b643f440859e7 Author: Alexander Larsson Date: 2009-12-09 Add a view as toolbar item using the view-as action M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml commit c7aeb63442007fbdac9feff66cc4541972162738 Author: Alexander Larsson Date: 2009-12-09 Add NemoViewAsAction This is an action that makes it easy to create a view as toolbar item. M src/Makefile.am A src/nemo-view-as-action.c A src/nemo-view-as-action.h commit bff56af563ee232815c6bd0502869fac7eb97476 Author: Alexander Larsson Date: 2009-12-09 Add NemoWindow::view-as-changed M src/nemo-window.c commit 946f377fc531b47ba71f85b8d57a4f2f20c9c432 Author: Alexander Larsson Date: 2009-12-09 Use NemoZoomAction to put zoom item in toolbar M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml commit da25dfdc1e94aae68bb9ff35497e7c2481449389 Author: Alexander Larsson Date: 2009-12-09 Add NemoZoomAction This is an action that can be used to easily put zoom items in toolbars. M src/Makefile.am A src/nemo-zoom-action.c A src/nemo-zoom-action.h commit 70298f3dfc04c6c7cc995c94af7b67d97d60a66a Author: Alexander Larsson Date: 2009-12-09 Add NemoWindow::zoom-changed signal M src/nemo-window.c commit 27b7859f2aa6d61b0b4cf5ae48333dc089ddf56f Author: Alexander Larsson Date: 2009-12-09 Add VOID:INT,BOOLEAN,BOOLEAN,BOOLEAN,BOOLEAN marshaller Needed for zoom-changed signal M libnemo-private/nemo-marshal.list commit 3add7e368af3ea9f37e2f5f386543cf228b0b74f Author: Baptiste Mille-Mathias Date: 2009-12-10 Add border on sidebar (remove on header) https://bugzilla.gnome.org/show_bug.cgi?id=499361 M src/file-manager/fm-tree-view.c M src/nemo-emblem-sidebar.c M src/nemo-history-sidebar.c M src/nemo-places-sidebar.c M src/nemo-side-pane.c commit 49193a40792ba8df413a3b361940f977dc009aef Author: Alexander Larsson Date: 2009-12-10 Add shadow_type arg to eel_scrolled_wrap_table_new M eel/eel-wrap-table.c M eel/eel-wrap-table.h M src/file-manager/fm-properties-window.c M src/nemo-emblem-sidebar.c commit 60dd20355079003afe3ba342e6233834afeffd39 Author: William Jon McCann Date: 2009-12-03 Fixes to enable per-monitor backgrounds https://bugzilla.gnome.org/show_bug.cgi?id=147808 M eel/eel-background.c commit 90b8c56e64caa7fd2435cdb619c8ed83971b9519 Author: Aron Xu Date: 2009-12-09 Update Simplified Chinese translation, M po/zh_CN.po commit 2d61fcdf4987802441b7d9dab5364a28fb2dbd7c Author: Alexander Larsson Date: 2009-12-08 Don't leak NemoDirectory M libnemo-private/nemo-file.c commit ac9f08eb1f74b32c432b0a4904fb57e982202a4c Author: Alexander Larsson Date: 2009-12-08 Don't leak NemoDirectory M src/nemo-navigation-window.c commit 8c3e5abb396bb67274d9e3d769295ece33b52091 Author: Alexander Larsson Date: 2009-12-08 Use nemo_directory_unref to unref directories Its nice to have nemo_directory_ref/unref paired for help when debugging. M src/file-manager/fm-tree-model.c commit 18763611ef08a6915b4bfd03a3c0bc287ba142ca Author: Alexander Larsson Date: 2009-12-07 Forgot to add nemo-extension-private.h in last commit A libnemo-extension/nemo-extension-private.h commit 09877bd2c4da7282f3d341297af75eda197f3e33 Author: Kjartan Maraas Date: 2009-12-05 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit 881f208b876c6e4386d54a0db3fca26aaa34ff71 Author: Alexander Larsson Date: 2009-12-04 Add lookup and creator functions for NemoFileInfo objects This has been requested by many extension developers. M libnemo-extension/nemo-file-info.c M libnemo-extension/nemo-file-info.h M libnemo-private/nemo-file.c commit 002bea81792cdfe6f4e45da95a59708040566171 Author: Alexander Larsson Date: 2009-12-04 Don't change background on the initial style_set call This results in queueing an unnecessary background change which causes the EelBackground to be unrealized wrongly. This fixes https://bugzilla.gnome.org/show_bug.cgi?id=578136 M eel/eel-background.c commit fd2e7311edd0d673adc21efdd7d4c6585723c730 Author: Alexander Larsson Date: 2009-12-04 Revert commit 7b86b78e2ff6a0f1b45ac8f8a9c30cf3d0c6ae96 This is not the right solution M eel/eel-background.c commit d876890dfdbcd7c6255f14f9b910255598fcf84b Author: Khaled Hosny Date: 2009-12-04 Fix typo M po/ar.po commit 7ad4b090a3d90f9333d2efdd52f2019a1cab1292 Author: Ivar Smolin Date: 2009-12-01 Updating Estonian translation M po/et.po commit e7c171acb8060436969139210060874f3a43d835 Author: Michael Terry Date: 2009-12-01 Disable Trash/Delete key bindings when appropriate This makes trash/delete key binding be enabled/disabled just like the menu items are. M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml commit 523a87744cdf86123da2de4e42a650aa0e891259 Author: Daniel Nylander Date: 2009-11-30 Updated Swedish translation M po/sv.po commit 2fb27dad4661dfce14a1ac5c7bc23e68fec7ee5c Author: Yaron Shahrabani Date: 2009-11-30 Update Hebrew translation M po/he.po commit 529ebf07a31e3a460f0ebde97833235136e50cf4 Author: Ivar Smolin Date: 2009-11-29 Updating Estonian translation M po/et.po commit 519ec1ef646f5edeff75801e592ab8f9e7423f82 Author: Alexander Larsson Date: 2009-11-27 Don't free uninitilized errors test_dir_is_parent doesn't set error, so no need to free it. M libnemo-private/nemo-file-operations.c commit 58e8653a8b0eb885f73c65eebc5926539eef9687 Author: Gabor Kelemen Date: 2009-11-27 Updated Hungarian translation M po/hu.po commit c125ec694bb7f7159cb72a3eb15f5845fc2c10ef Author: Alexander Larsson Date: 2009-11-27 Go to default location (not root) when clicking on mount in sidebar M src/nemo-places-sidebar.c commit ce39f704ff3494893a1198697cc2ae7b12f0d7ee Author: Alexander Larsson Date: 2009-11-27 Use mount default location for desktop links M libnemo-private/nemo-desktop-link.c commit 817803aaeefd9ebf6ee1df4053f8f986943d91f5 Author: Alexander Larsson Date: 2009-11-27 Handle GMount default_location in pathbar as fake root M src/nemo-pathbar.c commit d9d860a8e2fa5d41ff941ce5dc8e80672c05d5b8 Author: Alexander Larsson Date: 2009-11-27 Clean up fake-root handling M src/nemo-pathbar.c commit 5b1159927b98b569fcb22f05986a140a7c42ba0a Author: Alexander Larsson Date: 2009-11-26 Ensure show-hidden-files UI is uptodate When we read the per-location show-hidden-files setting, also update the UI. Fixes bug #568089. M src/nemo-window-manage-views.c commit 09f24d05eae830fd0ec696267f85e02debdc95a7 Author: Jorge González Date: 2009-11-27 Updated Spanish translation M po/es.po commit 5e86595f45d8470732dee1bd820512f5229bf160 Author: Matej UrbanÄiÄ Date: 2009-11-26 Updated Slovenian translation M po/sl.po commit 04c84927339a18aac3c8ee2fa3b2f6edc88e969f Author: Nils-Christoph Fiedler Date: 2009-11-25 Updated LowGerman translation M po/nds.po commit 6f0c44a70f62395e6281604601075994fa921afc Author: Alexander Larsson Date: 2009-11-25 Add entry icon to search bar This way you can activate a search using the mouse. (Bug #598256) M src/nemo-search-bar.c commit eee73c5eb6d83955a7b7a1af9a86f8294eea218a Author: Nikos Verschore Date: 2009-11-25 Make search button a toggle button Make the search button on the toolbar toggle between search and normal mode. See: https://bugzilla.gnome.org/show_bug.cgi?id=332078 M src/nemo-navigation-window-menus.c M src/nemo-navigation-window-ui.xml M src/nemo-navigation-window.c M src/nemo-navigation-window.h M src/nemo-query-editor.c commit 6ff1e3881e070a0a235208cc10dfdc53e8faa0aa Author: Alexander Larsson Date: 2009-11-25 Avoid deprecated gtk_button_pressed/released We replace these with direct use of deprecated signals, which is not ideal either. However, it makes us not reference depcrecated symbols and makes it works. I don't know how else to solve this. M src/nemo-navigation-action.c M src/nemo-window-menus.c commit 6161343d9d3eaa4fa044613085c00415852f8b55 Author: Pierre Wieser Date: 2009-11-25 Allow absolute pathnames for plugin menu/toolbar item icons. M libnemo-private/nemo-ui-utilities.c M src/file-manager/fm-directory-view.c commit 36d83807cc0744e131e3532714849a7d1bbbf65d Author: Pierre Wieser Date: 2009-11-25 Add nemo_icon_info_lookup_from_path() M libnemo-private/nemo-icon-info.c M libnemo-private/nemo-icon-info.h commit 4ea889ee82a66fb929920589322eb0565984f31d Author: Tao Wei Date: 2009-11-24 Updated Simplified Chinese translation. M po/zh_CN.po commit 2c50a8dea92273286404ba1e87f892354fb9b777 Author: Jorge González Date: 2009-11-19 Updated Spanish translation M po/es.po commit 7a890c3f5adb8eb35e208958b293e03c691c7830 Author: Alexander Larsson Date: 2009-11-19 Ensure range checking works below zero We add an int to an unsigned and then check for underflow, but this check will never trigger for unsigned variables like an enum. We fix this by using a signed value for the addition result. M src/file-manager/fm-list-view.c commit 1f8f54f4777343dda87043e444a24c3f86e90439 Author: Alexander Larsson Date: 2009-11-19 Ensure ABS calls work on difference of unsigned values guint64 - guint64 is of type guint64, so ABS doesn't work on it. Cast to gint64 to make sure this works. M libnemo-private/nemo-file-operations.c commit 3c0cc87da5eccab0c022d5bfee6191af4a3f4ea9 Author: Matej UrbanÄiÄ Date: 2009-11-18 Updated Slovenian translation M po/sl.po commit a76fe6975c0e3a31aa8d8ab4ddf3b7afbafbe274 Author: James Dietrich Date: 2009-10-27 Complete XDS support https://bugzilla.gnome.org/show_bug.cgi?id=585790 M libnemo-private/nemo-dnd.h M libnemo-private/nemo-file-dnd.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-operations.h M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-icon-container.h M libnemo-private/nemo-icon-dnd.c M libnemo-private/nemo-marshal.list M libnemo-private/nemo-tree-view-drag-dest.c M libnemo-private/nemo-tree-view-drag-dest.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c commit f146e054849fef9300e9fc8786c11e2d9b7c91d7 Author: Marcus Carlson Date: 2009-10-12 Changed the "event-after" signal to "changed" to update the "Location" / "Go to" label Change the secondary icon in the location to a "Go" (play) icon when the label is "Go to" otherwise a clear icon https://bugzilla.gnome.org/show_bug.cgi?id=163245 M src/nemo-location-bar.c M src/nemo-location-entry.c M src/nemo-location-entry.h commit 3ee90909fa92feaf3df0964eed2b95c5d968ba98 Author: Tomas Bzatek Date: 2009-11-10 Unfreeze updates in directory list view after rename cancellation We successfully cancelled rename operation but the directory view was left in frozen state, containing pseudo items with NULL elements. Fixes bug 590591. M src/file-manager/fm-list-view.c commit e487552287e5970dbbb39199b55026f2788bb42b Author: Alexander Larsson Date: 2009-11-17 Correctly update the request counters The request counters weren't updated by nemo_directory_add_file_monitors and nemo_directory_remove_file_monitors. This can cause a number of weird problems, including those described in bug #598931. This checkin fixes this, and fixes bug #598931. M libnemo-private/nemo-directory-async.c commit f60a28846a32543849a4916d032efdf71e167548 Author: Alexander Larsson Date: 2009-11-17 Add debug code for tracking down errors in request counters nemo_directory_verify_request_counts can be uncommented and called in various places to catch when the request counters are not properly updated. M libnemo-private/nemo-directory-async.c commit 0f638d6505b3adbd2d73fa1bd5894d62d40a2844 Author: Kjartan Maraas Date: 2009-11-15 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit f829c8fe28f221a153f9bedb5f7c86073f082550 Author: Aron Xu Date: 2009-11-14 Updated Simplified Chinese translation. M po/zh_CN.po commit 50836f6b37714516a7fb561475b3fe36666b1749 Author: Alexander Shopov Date: 2009-11-13 Updated Bulgarian translation M po/bg.po commit e5247083a16425171858e2a61ec54efee8191eac Author: Thomas Thurman Date: 2009-11-11 Further Shavian translation M po/en@shaw.po commit 97d98d9c7aeef53378bd07dfac78bf9ea770383e Author: Mario Blättermann Date: 2009-11-10 Added nds to LINGUAS M po/LINGUAS commit a0216f02be4793f8d0a19a3cdff5ae1619748472 Author: Nils-Christoph Fiedler Date: 2009-11-10 Added Low German translation A po/nds.po commit 13f4560aeeedd3f1626556d688e008aaf9b97f20 Author: Thomas Thurman Date: 2009-11-10 Shavian translation M po/LINGUAS A po/en@shaw.po commit 2bad8fcd7c67439826b7174bad4d2bfa5dee36c9 Author: Kjartan Maraas Date: 2009-11-09 Single gtk/gdk includes. M eel/eel-canvas.h commit c0d618993a79f655f474532ed8d1d0118d479a68 Author: Jovan Naumovski Date: 2009-11-06 Minor fix in Macedonian translation. M po/mk.po commit 0458c87d2f5561d03eb1bae593a867135c3c14a5 Author: Matej UrbanÄiÄ Date: 2009-11-06 Updated Slovenian translation M po/sl.po commit 6613262f4e6d40d153299d7fd4726210268a2a53 Author: Cosimo Cecchi Date: 2009-11-02 Don't get drag data in list mode if we don't support the target. This fixes bug #600183. M libnemo-private/nemo-tree-view-drag-dest.c commit 71e7b576751c1192fe0c05529619f4c0aba674c0 Author: Cosimo Cecchi Date: 2009-11-02 Emit the selection-changed signal when inverting. Do emit the selection-changed signal in NemoIconContainer when we invert the selection, so that the views can update the UI items accordingly (#600308). M libnemo-private/nemo-icon-container.c commit 51150a7fb834a7e6e64511e7f7cf7070328222c8 Author: Kostas Papadimas Date: 2009-11-01 Updated Greek translation M po/el.po commit a16d73fa256e7bcf15f36136dea2bec7b37aefaf Author: Gintautas Miliauskas Date: 2009-10-30 Updated Lithuanian translation. M po/lt.po commit d727babc5ebbc7d282d80fbace69a7401eb3795e Author: Gintautas Miliauskas Date: 2009-10-25 Updated Lithuanian translation. M po/lt.po commit bf8571a78f1f8c73ea449e56fa413abb3f40b91c Author: Cosimo Cecchi Date: 2009-10-25 Move functions outside of #ifdefs (#599290) This unbreaks the build if you compile without EXIF/EXEMPI. M src/nemo-image-properties-page.c commit ec8b2f666d175860b36a29870160a41446e0c160 Author: drtvasudevan Date: 2009-10-23 Updated Tamil translation M po/ta.po commit 04025fea82e720c6704da76c5e4d786775a7fb00 Author: Tomas Bzatek Date: 2009-10-20 Handle failed connection to tracker daemon 0.7 series Also, consolidate string memory management, to be consistent and clear on a first sight. Related to changes in bug 596082. M libnemo-private/nemo-search-engine-tracker.c commit 9be1fc059a2f7ce429592be5a6e2a56e7a36a8d7 Author: Jorge González Date: 2009-10-20 Updated Spanish translation M po/es.po commit fe2d7c35cc4f35c2dfd3e9345e354bd388fceca8 Author: ReÅŸat SABIQ Date: 2009-10-20 Another minor update for Crimean Tatar (Crimean Turkish) translation M po/crh.po commit ed199bbd9762a248d9b5036b7130d8965d13dfb9 Author: ReÅŸat SABIQ Date: 2009-10-19 Update for Crimean Tatar (Crimean Turkish) translation M po/crh.po commit 7f3453af4c59331e77dc09f07fdd9b24d533620a Author: Cosimo Cecchi Date: 2009-10-18 Use separate labels for attributes (#598545). This is useful so that we can easily select the text for each attribute. M src/nemo-image-properties-page.c commit 67d827e10e34186b4d3c1410817a5f7aac507b14 Author: Kjartan Maraas Date: 2009-10-17 Updated Norwegian nynorsk translation and fixed a typo. Closes bug #598607 reported by Torstein A. W. M po/nn.po commit f2ab25b7705e4f320e0fdb33a8ad8f302cb1cf0d Author: Sveinn í Felli Date: 2009-10-16 Updated Icelandic translation M po/is.po commit 006abaefbb5d30718678a212cd595a8a7d436d58 Author: Anna Jonna Ãrmannsdóttir Date: 2009-10-02 Updated Icelandic translation M po/is.po commit d1f92784496217f82c4f38b64f51b6820efc6fba Author: Nguyá»…n Thái Ngá»c Duy Date: 2009-10-13 po/vi.po: update translation of "Places" M po/vi.po commit 16226ab944780b9b5a65fe2a38e02f4bcf470254 Author: Jorge González Date: 2009-10-11 Updated Spanish translation M po/es.po commit 3b96ca69946453a4744a58f997289b86f7d41d5d Author: drtvasudevan Date: 2009-10-10 Updated Tamil translation M po/ta.po commit 23278532505862816bd5c8c0ab7d17f7a07b4790 Author: Cosimo Cecchi Date: 2009-10-09 Always check if the drag dest supports the source. In the "drag-motion" callback, make sure we check for target != GDK_NONE before getting non-existent data for it. M libnemo-private/nemo-dnd.c M src/nemo-places-sidebar.c commit 8ef1a18f81a588525fe2cf069ecc9f58a8b6b6ba Author: Ivar Smolin Date: 2009-10-10 Updating Estonian translation M po/et.po commit a2e04a10329f5391b968f82b6110112de0dc2fad Author: Stephen Cook Date: 2009-10-07 Remove very old unnecessary FIXMEs. Closes bug #41245. M libnemo-private/nemo-global-preferences.c M src/nemo-navigation-window.c M src/nemo-window.c commit af9f607c258270cd08e3b994017bc1ca134099fc Author: A. Walton Date: 2009-10-07 Bug 589375 - Crashes with empty location in edit bookmarks Check that the length of the text in the entry is non-NULL. M src/nemo-bookmarks-window.c commit 488a462382bd43a0ad04e274441537d508669c8a Author: Matthias Clasen Date: 2009-10-07 Remove an ugly hack to detect KDE desktop (#564208). M src/nemo-application.c commit f28404dd6af7e95c8038e9f73a31f19398b148c2 Author: Xu Li Date: 2009-07-17 correct the value of GtkRecentData.app_exec in nemo_recent_add_file() M libnemo-private/nemo-recent.c commit 1dd60a63b0048e093da2e2f710bca6a922e4029e Author: Frédéric Péters Date: 2009-08-22 Remove deprecated Encoding key from desktop files M data/nemo-autorun-software.desktop.in.in M data/nemo-browser.desktop.in.in M data/nemo-computer.desktop.in.in M data/nemo-file-management-properties.desktop.in.in M data/nemo-folder-handler.desktop.in.in M data/nemo-home.desktop.in.in M data/nemo.desktop.in.in M src/network-scheme.desktop.in commit cbec5342514b7f52bf654fff418f10bea3aac7ca Author: Nelson Benítez León Date: 2009-05-01 Avoid crash when holding space bar on focused navigation buttons Fixes bgo#580926 M src/nemo-navigation-window-menus.c M src/nemo-window-menus.c commit 370ebf572e4e8d401f65fa7b575899e82fc9dfa7 Author: Cosimo Cecchi Date: 2009-10-07 Use the right GConf key for the disable_tabs setting (#580220). M libnemo-private/nemo-global-preferences.h commit 3ef9873b86ec14ccd33680acb232fa0df0eb11ce Author: Cosimo Cecchi Date: 2009-10-07 Chain up to the parent handler if we click outside any row. By doing so, the tree view widget will gain focus anyway. Fix bug #589088. M src/file-manager/fm-list-view.c commit f29571245545750e26ae84b3b383ab7619ea10bc Author: Marcus Carlson Date: 2009-10-06 Show tooltips in places sidebar https://bugzilla.gnome.org/show_bug.cgi?id=595616 M src/nemo-places-sidebar.c commit 3966879080237672d41e2aab0499a5852ef00ea9 Author: Marcus Carlson Date: 2009-10-03 Make changing visible columns instant. Wasn't like always like this before because nemo-vfs-file.c saved metadata async. https://bugzilla.gnome.org/show_bug.cgi?id=597227 M src/file-manager/fm-list-view.c commit 143fd025cc20423cc9eb8b3a255b4a102a58efce Author: Marcus Carlson Date: 2009-10-03 Adds a "Copy Anyway" option when copying files and disk space is not enough https://bugzilla.gnome.org/show_bug.cgi?id=324361 M libnemo-private/nemo-file-operations.c commit c7bfedfbf8883ddeacfdd0818d7c1af9530c4f52 Author: Marcus Carlson Date: 2009-10-06 Select all on F2 in rename mode This is a another quick way to switch from not selecting extension to selecting everything (in addition to the existing shift-F2 combo). M libnemo-private/nemo-icon-container.c M src/file-manager/fm-list-view.c commit 56f33af7601fb8a1ce28a953ae7516eb7e46c7a5 Author: Jochen Skulj Date: 2009-10-05 Updated German translation M po/de.po commit 7bff0191b0c94c6570c5ffd3d34e8b1cf30da408 Author: Denis ARNAUD Date: 2009-10-05 Updated breton translation M po/br.po commit 58a073303977708516d3a1ff4528a7ef7ace7f26 Author: Marcus Carlson Date: 2009-09-29 Adds an option to select the application to open an unkown file type upon error opening the file. https://bugzilla.gnome.org/show_bug.cgi?id=92497 M libnemo-private/nemo-mime-actions.c commit d013bf32daa0db99693bc86b6930b56c3d59b42a Author: Kostas Papadimas Date: 2009-09-29 Updated Greek translation. M po/el.po commit 3dd2ddccb759b41762026de8c3f82b0257a73ff8 Author: Jennie Petoumenou Date: 2009-09-29 Updated Greek translation M po/el.po commit 8fe1a569690abd8a472041886b883b55852d445f Author: Marcus Carlson Date: 2009-09-29 Add multiselect capability to list view Use Ctrl+shift to do multiple range selects (#410497) M src/file-manager/fm-list-view.c commit 0b8af64dc9ca5994215362f163e2c09a2d79e9bd Author: Jorge González Date: 2009-09-28 Updated Spanish translation M po/es.po commit 6abf7ba3b026306493ee40f8164e7f632f5c5265 Author: Marcus Carlson Date: 2009-09-28 Add checkbox for not associating a filetype on open with https://bugzilla.gnome.org/show_bug.cgi?id=92497 M libnemo-private/nemo-open-with-dialog.c commit b6112210f2b4c26951c4104a5d46d5b54ec58e2b Author: Alexander Larsson Date: 2009-09-28 Bump version to 2.29.1 on master M configure.in commit 80e87af1b4956e0c1dcb252564a71cf51286ab3f Author: A Date: 2009-09-28 Fix Bug 593523 - Typo in nemo volume mgmt. M src/file-manager/fm-directory-view.c commit 08e6114dbdf4553b4bcc12a38b0955da153c8efe Author: Jürg Billeter Date: 2009-09-23 Update tracker support for version 0.7 Fixes bug 596082. M configure.in M libnemo-private/nemo-search-engine-tracker.c commit a2a7f3a2a7909824c7a2643d9251c0e74f17b548 Author: Timo Jyrinki Date: 2009-09-25 Update Finnish translation (transition from â€taltio†to â€asemaâ€) M po/fi.po commit 541c225fea1d616d01862d0f6b0ff9086317540a Author: Tomas Bzatek Date: 2009-09-24 Don't rely on activation_uri when detecting mounts We test for the activation_uri (i.e. G_FILE_ATTRIBUTE_STANDARD_TARGET_URI) which is usually not exposed from computer:// items until the item is mounted (and that's up to particular gvfs volume monitor). Simply don't test for activation_uri, file type of G_FILE_TYPE_MOUNTABLE should be enough. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=518570 M libnemo-private/nemo-directory-async.c commit e15707648d6d92abe455107718a1e0a440c7fe1f Author: Christian Neumair Date: 2009-09-24 Correctly position icons for text, netscape URI and URI list drops When dropping text, a netscape URI or a URI list to the desktop, remember the position where the drop happened and position the created icon accordingly. Fixes #350022. M src/file-manager/fm-directory-view.c commit 069494e971bba9bfad5cd6997ecf9138677a9bc0 Author: Takayuki KUSANO Date: 2009-09-23 Fix Japanese translation M po/ja.po commit 6fec4348ef56f1df6f7609f9632a5bf4c6512e4d Author: Takayuki KUSANO Date: 2009-09-23 Updated Japanese translation M po/ja.po commit 1055993807fe882a3588f59fe0d93b0b0bb063d8 Author: Alexander Larsson Date: 2009-09-21 Post release version bump M configure.in commit c3b8ec1d6927ccc743e57c315cc2a3ba007ec769 Author: Alexander Larsson Date: 2009-09-21 Update for 2.28.0 release M NEWS M configure.in commit 9fc52ea33822f02e2b5ab876f7ae3ddbcea67523 Author: Shankar Prasad Date: 2009-09-21 Updated Kannada(kn) translation M po/kn.po commit 0cdc94d5345c17e2e929dbd18290ad3e933eb3e5 Author: Petr Kovar Date: 2009-09-20 Updated Czech translation by Lucas Lommer Thanks goes to Tomas Bzatek. M po/cs.po commit cd62ad01e18c0b3b0932af4a9262da1906f2f63a Author: Amitakhya Phukan Date: 2009-09-20 Updating Assamese translations M po/as.po commit 40df45a49785a31c2bdbafef3c8a99766333c5a1 Author: A S Alam Date: 2009-09-19 Updating Translation for Punjabi by A S Alam M po/pa.po commit 8823a3815e0dfcdf92059140d72556ab3acd3b8e Author: Theppitak Karoonboonyanan Date: 2009-09-19 Updated Thai translation. M po/th.po commit 0f075e8e97ad070796584d086678c0e1ad539188 Author: Takayuki KUSANO Date: 2009-09-19 Updated Japanese translation M po/ja.po commit 752e68860bd37941c5fdef3ae29113d12f8dc195 Author: Manoj Kumar Giri Date: 2009-09-18 Upadated Oriya Translation M po/or.po commit 7242f95d083cebfff768d693d2ebf4282154d508 Author: Matej UrbanÄiÄ Date: 2009-09-18 Updated Slovenian translation M po/sl.po commit a728376835fdd39fa505acb84584f7d2600801f2 Author: Luca Ferretti Date: 2009-09-18 Updated Italian translation M po/it.po commit a8097e57788ad735227489e6c51d06bedc796889 Author: Alexander Larsson Date: 2009-09-18 Don't load files for thumbnailing that we can't thumbnail anyway When zooming out we read the real image and use that as the thumbnail. However, we should only do this for files gdk-pixbuf can read as other things can't be read anyway and may potentially be very large (such as videos) since the thumbnail size limit only applies for images. M libnemo-private/nemo-file.c M libnemo-private/nemo-thumbnails.c M libnemo-private/nemo-thumbnails.h commit 4a88ecde61a52ac058999d95388ade9f668482d4 Author: Maxim V. Dziumanenko Date: 2009-09-17 Added Ukrainian translation M po/uk.po commit 51a2a0abd0bd3f6f36737b5afef3ff49a7fa602c Author: Denis ARNAUD Date: 2009-09-17 Updated breton translation M po/br.po commit 5d641153c201f4cbc4d62ac10eb2437a8be5fb78 Author: Mohammad Anwari Date: 2009-09-16 Updated Indonesian translation by Andika Triwidada M po/id.po commit adc53a499c5c143612d7e9b22340efc38240da1d Author: Ilkka Tuohela Date: 2009-09-15 Updated Finnish translation M po/fi.po commit b5af4e6c9c6af492210514af922aa0ed4029dce6 Author: Ilkka Tuohela Date: 2009-09-15 Updated Finnish translation M po/fi.po commit 8da7fdac2375f5b5d0354926b6c130ced602aaaa Author: Rajesh Ranjan Date: 2009-09-15 hindi update by Rajesh Ranjan M po/hi.po commit ba75188ad883fc3be36ebad0740512b03a6e373c Author: Sweta Kothari Date: 2009-09-15 Updated Gujarati Translations M po/gu.po commit 43275654dc3b762841339f2771137d8013f0fe43 Author: Astur Date: 2009-09-14 Updated Asturian translation M po/ast.po commit bd87d7555759021a012691d59d8707c4118a17c7 Author: Gil Forcada Date: 2009-09-14 Minor fix to Catalan translation M po/ca.po commit 96781b9d29259e175f73b87a30eaadf1e12c7490 Author: Carles Ferrando Date: 2009-09-14 Updated Catalan (Valencian) translation M po/ca@valencia.po commit d6b8cb28c7208e0776bb483cde464472249c73ba Author: Alexander Larsson Date: 2009-09-14 Avoid refing NULL icons M src/file-manager/fm-directory-view.c commit eb05225a794de9c7b9326d1e1c56f54902bb6bb5 Author: Kjartan Maraas Date: 2009-09-14 Update Norwegian bokmÃ¥l translation. M po/nb.po commit 58a9e227e519369bca5c7c9897e386110bdda242 Author: Ani Date: 2009-09-14 Updaeted Malayalam Translations M po/ml.po commit 4fb28a5541e564adff7f3a03582c2cb7ed4e294f Author: Lucian Adrian Grijincu Date: 2009-09-14 Updated Romanian translation M po/ro.po commit 979be859028ba20384eee4f907fc647a060cb9fc Author: Ilkka Tuohela Date: 2009-09-13 Updated Finnish translation M po/fi.po commit 78244d5d698786a98d00ef1513e8294825b8813c Author: Bruce Cowan Date: 2009-09-12 Updated British English translation M po/en_GB.po commit e8610aaf1e276993a9942697decc4dc81a5c0168 Author: Ask H. Larsen Date: 2009-09-12 Updated Danish translation M po/da.po commit da24fa0b829c31c4417fed03374b4ad4f63392e8 Author: Reinout van Schouwen Date: 2009-09-12 * 2009-09-12 Reinout van Schouwen - po/nl.po: Updated Dutch translation M po/nl.po commit 48744242700d5dc9de21ef6c33df8eedb757b715 Author: MiloÅ¡ Popović Date: 2009-09-11 Fixes in Serbian translation M po/sr.po M po/sr@latin.po commit 02ea89fd4f92faade026de9463aca4171f4c04d1 Author: Gabor Kelemen Date: 2009-09-11 Updated Hungarian translation M po/hu.po commit 8c636df9374993990ba8a23bbcb986e572508510 Author: Žygimantas BeruÄka Date: 2009-09-10 Updated Lithuanian translation M po/lt.po commit 46aefc46372624957509f971a325e06fe8249c21 Author: Alexander Larsson Date: 2009-09-10 Make the desktop window native so the backing pixmap is drawn by X Without this X draws the toplevel window background and then the real background is drawn from exposes, which doesn't look nice. Fixes bug #593658 M libnemo-private/nemo-icon-container.c commit 594f76e9231eeadfc7972560cf162e921d66aac6 Author: Denis ARNAUD Date: 2009-09-09 Updated breton translation M po/br.po commit d67e3e2377229e19128a2405b70580448fc5e487 Author: Sweta Kothari Date: 2009-09-09 Updated Gujarati Translations M po/gu.po commit b6e45ba165064f508aedad4212759700f0b99f7d Author: A S Alam Date: 2009-09-09 Updaitng for Punjabi M po/pa.po commit 714e8534c90addab5b795cc39c98142ddea17242 Author: Piotr DrÄ…g Date: 2009-09-09 Updated Polish translation M po/pl.po commit e6e10b6facdd8a7058fa5c283462c9f4777a1079 Author: Sandeep Shedmake Date: 2009-09-08 Updated Marathi Translations M po/mr.po commit 21e5e7d3898764a8d493dede40606a9b9e6aa7aa Author: Alexander Larsson Date: 2009-09-08 Free get_types_table internal hashtable on exit M libnemo-private/nemo-thumbnails.c commit 5b075cfa665d07ee6c57e68f6f67aaca76a3b308 Author: Alexander Larsson Date: 2009-09-08 Fix minor leak M src/nemo-application.c commit d442315c303db2def885a00d0abed257156185ce Author: Alexander Larsson Date: 2009-09-08 Free return value from nemo_file_get_metadata_list M src/file-manager/fm-list-view.c commit 75298a3ded74e42b047f95f0746ea3dca8e0a6b7 Author: Alexander Larsson Date: 2009-09-08 Print leaked unique eel_ref_str:s at exit M eel/eel-string.c commit b698cf1932da077f07d99966a4c61568a1ae081e Author: Alexander Larsson Date: 2009-09-08 Fix threadsafety issue in eel_ref_str_unref Its not safe to just decrement count if we didn't read a 1, as we could race with another decrement. M eel/eel-string.c commit 26714114eefe841c4b3eaa5a3a93b50ec69f76a8 Author: Alexander Larsson Date: 2009-09-08 Don't leak list of gconf entries M libnemo-private/nemo-desktop-directory-file.c commit 2434bd43cd43eb8ba97b1a956e4b3cd734cf2a91 Author: Alexander Larsson Date: 2009-09-07 Fix usage of sink, fixing many recently introduced leaks. The conversion away from gtk_object_sink was done wrongly causing lots of leaks. fix this. M eel/eel-background.c M eel/eel-gtk-extensions.c M libnemo-private/nemo-dnd.c M src/file-manager/fm-list-view.c M src/file-manager/fm-tree-view.c M src/nemo-emblem-sidebar.c M src/nemo-history-sidebar.c M src/nemo-information-panel.c M src/nemo-notes-viewer.c M src/nemo-places-sidebar.c M src/nemo-spatial-window.c commit b4cd0d66db105822bfa5531a146428b548aff369 Author: Alexander Larsson Date: 2009-09-07 Update to latest foocanvas This has some cleanups and fixes a memory leak that was introduced in the eel copy by removing gtk_object_sink. M eel/eel-canvas-rect-ellipse.c M eel/eel-canvas-rect-ellipse.h M eel/eel-canvas-util.c M eel/eel-canvas.c M eel/eel-canvas.h commit b17f8f7995aa1ba2b62d8272436d761bc1600bb1 Author: Alexander Larsson Date: 2009-09-07 Don't leak file metadata M libnemo-private/nemo-file.c commit 7c2c5f904d183d510e9fb4f4ac07fe7660274692 Author: Alexander Larsson Date: 2009-09-07 Free "remaining" returned from GOption M src/nemo-main.c commit 26a91c8e225f01363976485c782840135d50e6d8 Author: Alexander Larsson Date: 2009-09-07 Centralize extra view ref and sink if required Doing this in only one place makes sense as its clearer. Previously we ref:ed one extra time for the window->view ref but left the floating ref to be taked when adding the widget to a parent. This breaks when we free the view before adding it to a parent, so we need to properly sink it. M libnemo-private/nemo-view-factory.c M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-empty-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c commit c302620c144c7968c7ae35b45ab55a3124fd2923 Author: Alexander Larsson Date: 2009-09-07 post release version bump M configure.in commit d0a6955e983ba112a65140ce3b55a7dd953fd8e8 Author: Alexander Larsson Date: 2009-09-07 Update NEWS M NEWS commit bd108f3700594e5c859d89287a59733a5585e4d9 Author: Padraig O'Briain Date: 2009-09-07 Don't crash on NULL gconf value This fixes bug #589520 M libnemo-private/nemo-desktop-directory-file.c commit 02a7a84229063f329731d3db61184207a91bf12e Author: Chao-Hsiung Liao Date: 2009-09-06 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit 3af7944871692b9e0c0754ed5351ac24d2a6f9ff Author: Khaled Hosny Date: 2009-09-05 Updated Arabic translation M po/ar.po commit 41a15a48a2d452078ae7845374ad9577b30e8155 Author: Ivar Smolin Date: 2009-09-05 Updating Estonian translation M po/et.po commit 7553bdccaddb56be2b156dfcd1e409ea30b870a7 Author: Mario Blättermann Date: 2009-09-04 Updated German translation M po/de.po commit 13ecc3e0eef4d9267f9919cd79180c0ed4ce4bbf Author: Duarte Loreto Date: 2009-09-04 Updated Portuguese translation M po/pt.po commit 2a562f03810a31a0cd2be36faff5059dab2b8fe2 Author: MiloÅ¡ Popović Date: 2009-09-01 Updated Serbian translation M po/sr.po M po/sr@latin.po commit 3901a97853dad9bf2d586e401a2542aa86703e65 Author: Kjartan Maraas Date: 2009-09-01 Update Norwegian bokmÃ¥l translation. M po/nb.po commit 40164f40de5bcfec618da3f200eff5d2371f4bde Author: Shankar Prasad Date: 2009-09-01 Updated Kannada(kn) translation M po/kn.po commit e9b017891f7ab2586b92f4111637b2d02b0f4a51 Author: krishnababu k Date: 2009-08-31 Updated Telugu Translations M po/te.po commit 2cf936c4105f88a953f91c8bdf37d65553681684 Author: Joan Duran Date: 2009-08-30 Updated Catalan translation M po/ca.po commit 4d9e7a5bf3d180ae47b789b90ee56fc2cbde24c3 Author: Baris Cicek Date: 2009-08-30 Updated Turkish translation. M po/tr.po commit cf32d3a9429a08fa5fd9557c57e896d85064e9da Author: Inaki Larranaga Murgoitio Date: 2009-08-29 Updated Basque language M po/eu.po commit bd4180156f506861b335a71a4d6e54886a237527 Author: Bruno Brouard Date: 2009-08-28 Updated French translation M po/fr.po commit 04e3be13647469de3fe97c15b2fab28eb1cdd81c Author: Inaki Larranaga Murgoitio Date: 2009-08-27 Updated Basque language M po/eu.po commit 542f56ecb2af09c78dd7507d6e9f10b96d4d2e34 Author: Runa Bhattacharjee Date: 2009-08-27 Updated Bengali India Translations M po/bn_IN.po commit e6ef2d96f6adc507425123716961aa48281af83d Author: A Date: 2009-08-27 Fix test in uninhibit code M libnemo-private/nemo-file-utilities.c commit bf6bfde36bcadf43a39fb095650b7fc78741d62a Author: Matthias Clasen Date: 2009-08-26 Fix a duplicate id in a .ui file This caused nemo-file-management-properties to crash. M src/nemo-file-management-properties.ui commit 064086ef68a0692ac9050b7a0d3ded4a836c8180 Author: Marcus Carlson Date: 2009-08-26 Always show app icon for open-with in the popup menu as in the normal menu Fixes bug #591663. M src/file-manager/fm-directory-view.c commit 3bd3f5f4d7a8ef10c6133c5957025df1560e9185 Author: ifelix Date: 2009-08-26 Updated Tamil Translations M po/ta.po commit b151573894ee19b4c13f3d35ac5cac7660caee63 Author: Henrique P Machado Date: 2009-08-24 Updated Brazilian Portuguese translation. M po/pt_BR.po commit 324e267fc916d5f16e505c2f57a69c271c1388ee Author: Alexander Larsson Date: 2009-08-24 Post release version bump M configure.in commit c685eae6206409ca4bbcec4c74367e5295f40461 Author: Alexander Larsson Date: 2009-08-24 Update NEWS M NEWS commit c1755706945092334af274f3a88049976baa4763 Author: Alexander Larsson Date: 2009-08-24 Bump version to 2.27.91 M configure.in commit d8337a4b7969b43bf5712cd5e85dc5f936ed5044 Author: Ryan Lortie Date: 2009-08-22 Cancel audio preview when deleting the file Fixes #137500. M src/file-manager/fm-icon-view.c commit b9cd9a5810e044c9351d2408186fb135f4452635 Author: Jamil Ahmed Date: 2009-08-24 Updated Bengali translation M po/bn.po commit 8ddb1d53eaa01f4c076c4d96e8da1a9a812e303b Author: Changwoo Ryu Date: 2009-08-23 Update Korean translation M po/ko.po commit da36928ac4d0989d2b6c3d54f7dc522fca7491ab Author: Seán de Búrca Date: 2009-08-22 Updated Irish translation M po/ga.po commit 97915f97bcbd047de2a5fd4b6bf25b01436085d3 Author: Alexander Shopov Date: 2009-08-22 Updated Bulgarian translation M po/bg.po commit 4a7af52ab6f964b9174b59e3f71252447158ffa4 Author: Antón Méixome Date: 2009-08-19 Updated Galician Translation M po/gl.po commit 72f65592a84cb8e9ad2ccaa6bbfd7fe4fbe7371b Author: Alexander Larsson Date: 2009-08-18 Migrate old nemo metadata to gvfs on startup If ~/.nemo/metadata/migrated-to-gvfs doesn't exist, migrate and create it. M src/Makefile.am M src/nemo-application.c commit 1d14824dc8ab6f1f8573b07c11ce437ae22dc77b Author: Alexander Larsson Date: 2009-08-17 Add nemo-convert-metadata tool This can be used to convert old-style nemo metafiles to gvfs metadata. M src/Makefile.am A src/nemo-convert-metadata.c commit a557cf30fe1f3761901a7248106840add2c1d105 Author: Alexander Larsson Date: 2009-08-18 Move NEMO_DESKTOP_METADATA_GCONF_PATH to nemo-metadata.h Need this in the metadata conversion code M libnemo-private/nemo-desktop-directory-file.c M libnemo-private/nemo-metadata.h commit 7c316ae074658c8927e48ea00f4305767ea9f7dd Author: A. Walton Date: 2009-08-13 Bug 587316 – Truncate file names when deleting Files with extremely long file names could cause the dialog box to become wider than the screen. Based on a patch contributed by Marcus Carlson. M libnemo-private/nemo-file-operations.c commit ce36628b3d615204eebd60a9df67b88857321965 Author: Yaron Shahrabani Date: 2009-08-14 Updated Hebrew translation M po/he.po commit e0446d33be8ce22d1925c60db6a9b26c232020a8 Author: Jochen Skulj Date: 2009-08-13 Updated German translation M po/de.po commit 39b18f636baddcc3de5866ef3dbb6d66dc344a37 Author: Rajesh Ranjan Date: 2009-08-13 Updated Hindi Translations M po/hi.po commit bbdb3b31455d462c18afa3764293f06fb81df54b Author: Daniel Nylander Date: 2009-08-13 Updated Swedish translation M po/sv.po commit 477fdafe22aa0e3cb78ab73c7ec4e205468c0a75 Author: Matthias Clasen Date: 2009-08-12 Fix a typo M libnemo-private/apps_nemo_preferences.schemas.in commit e8f0c90ab9444511311f300f6b0596df01c38f1e Author: Seán de Búrca Date: 2009-08-11 Updated Irish translation M po/ga.po commit 13b85463fb7b9af0faac01b30e8459545e87b6f0 Author: Mattias Põldaru Date: 2009-08-11 Updating Estonian translation M po/et.po commit fdb2ccedb2bfd3b2d6dfd5759913875b8d93834a Author: A. Walton Date: 2009-08-10 Fix unintiallized GError in power management M libnemo-private/nemo-file-utilities.c commit f77c52ec952f25170338e6e896af035b4ef55cfe Author: Jorge González Date: 2009-08-10 Updated Spanish translation M po/es.po commit 37e7ceca45aea48129cf55ea2583f23330d26b91 Author: A. Walton Date: 2009-08-10 Bug 334806 – Inhibit power-manager when copying files Introduces code to inhibit GNOME power manager whenever a file operation which may not complete quickly is running. M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file-utilities.h commit 4dd0fdef1d77cb6b9be83348ff5c00293e14a991 Author: Ivar Smolin Date: 2009-08-10 Updating Estonian translation M po/et.po commit fa1d8989b1b3e4d18c3f4c097d57c76ff86a7387 Author: Luca Ferretti Date: 2009-08-09 Remove unused variable to fix the build M src/nemo-navigation-window-menus.c commit 3c5be2ea6403ad071da5e350332e2890d9d53994 Author: Khaled Hosny Date: 2009-08-08 Updated Arabic translation M po/ar.po commit eb585679b6e4fad7d252a7458177c4e0a8468298 Author: Matthias Clasen Date: 2009-08-08 Always show icons in places menu in spatial mode. Part of bug #590647. M src/nemo-spatial-window.c commit 826d5237d2ea179006b62def4db376544e74d764 Author: Marcus Carlson Date: 2009-08-08 Always show icons in the history and go menu. Part of bug #590647. M src/nemo-navigation-window-menus.c M src/nemo-window-menus.c commit 9cba51e5cb8827997eb4203c6eed4614efa34aaa Author: Marcus Carlson Date: 2009-08-08 Always show application icons in popup menus. Part of bug #590647. M src/file-manager/fm-directory-view.c commit 1604ee0ceb8026aff744981b893d8fc8da25ec6c Author: Seán de Búrca Date: 2009-08-06 Updated Irish translation M po/ga.po commit 339017547f1aa41d90cf31a6b985588f3ff64e4a Author: Antón Méixome Date: 2009-08-06 Updated Galician Translation M po/gl.po commit 47af29868f527a93acb1822b6bdb2537253a387e Author: Kjartan Maraas Date: 2009-08-06 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit a0b11f325a221c7ca46811ada00bad1035e4857a Author: Khaled Hosny Date: 2009-08-06 Misc. fixes to Arabic translation M po/ar.po commit 85bb10a2b4f7230e7a0aa5b9945d155c1a21b2b4 Author: Khaled Hosny Date: 2009-08-05 Updated Arabic translation M po/ar.po commit f8f6a95bc05353b4a68c07fc710742b9bcdc7d0d Author: A. Walton Date: 2009-08-03 Fix crash in connect server dialog Under custom locations, entering no URI will crash. M src/nemo-connect-server-dialog.c commit cfa61d576da08590bec118ce1ed03e7189a974b2 Author: A. Walton Date: 2009-08-03 Reorder assignments in mime application chooser Writing over toggle_renderer with the wrong cell renderer. M libnemo-private/nemo-mime-application-chooser.c commit a8ca44f54aea29ccb2eb0163f8ffe670fd6761b1 Author: A. Walton Date: 2009-08-03 Reverse back/forward mouse button sense. Be consistent with Firefox, etc. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M src/nemo-navigation-window.c commit aa5dbe04bc2d92e2603b34d44f486fd2bae95169 Author: Seán de Búrca Date: 2009-07-31 Updated Irish translation M po/ga.po commit 6d648632b8978590befcd867bd2c9920b6aa49ff Author: Alan Monfort Date: 2009-07-31 Updated breton translation M po/br.po commit 838d31d11e3fed0d98642397c9d986ddd5bea390 Author: Denis Arnaud Date: 2009-07-30 Updated breton translation M po/br.po commit e7d2f70203673d9a294460df164aec295db17234 Author: Denis Arnaud Date: 2009-07-30 Updated breton translation M po/br.po commit 97d348f792a2659fbb88de17d25e83c93b14414c Author: Vincent Untz Date: 2009-07-28 Respect /desktop/gnome/lockdown/disable_command_line We need to show/hide the "New Launcher" menu item in the context menu, depending on this gconf key. M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/file-manager/fm-actions.h M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-directory-view.c commit 359fa218a1a890bb87fb331acc30d62b57bc7c61 Author: Ivar Smolin Date: 2009-07-27 Updating Estonian translation M po/et.po commit aac26f4c0fce20e7cac87ca51c0629458e804ee8 Author: Mattias Põldaru Date: 2009-07-22 Updating Estonian translation M po/et.po commit 44c05bbc866fb4430a16b169aa3854bab1af6555 Author: drtvasudevan Date: 2009-07-21 Updated Tamil translation M po/ta.po commit c0c9bbc96228a8864eda9d0b7f4c82c7d1c0dba4 Author: Ivar Smolin Date: 2009-07-20 Updating Estonian translation M po/et.po commit 2a94803b44010e3c47a9f7b94894fab8d6062abc Author: Jaap A. Haitsma Date: 2009-07-18 Fix handling of small images/icons Small images with an alpha plane don't get a frame Use different scaling strategy for small images. Small images/icons won't get up scaled in default zoom view. They are shown in their actual Fixes bug #585186 M libnemo-private/nemo-file.c commit a8f82a8a00f672a3111d97070c3a6f34e2b46c90 Author: Chao-Hsiung Liao Date: 2009-07-18 Updated Traditional Chinese translation(Hong Kong and Taiwan) M po/zh_HK.po M po/zh_TW.po commit bd6db659cb232d8b8f81a9ada748025aa1d16fff Author: Alexander Larsson Date: 2009-07-14 Clean up metadata key names now that they are public Prefix all internal keys with "nemo-". Use dash, not underscore as delimitor (this is what gio file attrs use) Rename "keyword" to "emblems" Rename "default_component" to "nemo-default-view" M libnemo-private/nemo-file.c M libnemo-private/nemo-metadata.c M libnemo-private/nemo-metadata.h M src/nemo-window-manage-views.c commit c2951134aac83f4e8194e7cb71a92b5f9d273100 Author: Sweta Kothari Date: 2009-07-14 Updated Gujarati Translations M po/gu.po commit 53bcaac5fd2cf03f686f19dbdc9d889480cd8709 Author: Cosimo Cecchi Date: 2009-07-14 Post-release version bump M configure.in commit 608b7f5c2ab1c6e9c0d011e3fef3b506afa5f8ba Author: Cosimo Cecchi Date: 2009-07-14 Update for 2.27.4 M NEWS M configure.in commit e4b5573bec0215006201b9a0dda60888a32debe6 Author: Cosimo Cecchi Date: 2009-07-14 Comment out the metadata tests for now M libnemo-private/nemo-directory.c commit 91cec6f5e6bbc672d2cebef162ea797eb5e9d55d Author: Sweta Kothari Date: 2009-07-13 Updated Gujarati Translations M po/gu.po commit 9ca82f0443f49bb80beb050f1d1bb3ef2a338698 Author: Maxim V. Dziumanenko Date: 2009-07-09 Updated Ukrainian translation M po/uk.po commit 3bd36d1a3b6f576e124a41800d7138cbfa34782f Author: Maxim V. Dziumanenko Date: 2009-07-09 Updated Ukrainian translation M po/uk.po commit fd9df908248be20bc5f79def1dd96a45bb9f56c8 Author: Cosimo Cecchi Date: 2009-07-09 Don't force no horizontal scrollbar in the note viewer This causes issues with long words in the notes viewer, as the window will grow bigger along with the word. Patch by Luke Symes, fix bug #399018. M src/nemo-notes-viewer.c commit c1b58565da21a6d9e95dc920afd632da6e906fc9 Author: drtvasudevan Date: 2009-07-09 Updated Tamil translation M po/ta.po commit 560e736891e9268c73171ef3afbbc5c2bde819b9 Author: Jorge González Date: 2009-07-08 Updated Spanish translation M po/es.po commit 72a17d86468291eb64fdc549753836e76e3add6a Author: Daniel Nylander Date: 2009-07-08 Updated Swedish translation M po/sv.po commit 2eb7e673837b32fe8c7d9b4431fd76213a908a3a Author: Wang Yan Date: 2009-07-04 Don't display the timeout dialog with broken launchers Don't display the timed wait dialog if we're already reporting a broken link to the user. Fix bug #579165. Signed-off-by: Wang Yan M libnemo-private/nemo-mime-actions.c commit 45c928d3cf112f22d69b25299898301c54d9e961 Author: Cosimo Cecchi Date: 2009-07-08 Use application icons in the context menu If it's possibile, use the application icons in the open with submenu. This also removes quotation marks and useless duplicate "Open With" strings from the submenu. Patch by Marcus Carlson, fixes bug #587533 and #546916. M src/file-manager/fm-directory-view.c commit 4b434c4f73b56a92ff4bf50435487357719eebaf Author: Cosimo Cecchi Date: 2009-07-08 [build] bump up the required version of GLib M configure.in commit cf5538067776605cb031a58ce2f77271375db498 Author: David Zeuthen Date: 2009-06-30 Bug 587486 – Pass GMountOperation to unmount/eject/stop ops - Port everything to use _with_operation() variants of unmount/eject methods - This includes changing the NemoFile a bit; see the patch for details - Add support for g_drive_can_start_degraded() so we offer to start (degraded) drives even when g_drive_can_start() returns FALSE - Also add support for new mountable::* attributes so we can have "Detect Media" items in the context menu when right-clicking mounts/volumes/drives in computer:/// and on the desktop M libnemo-private/nemo-desktop-icon-file.c M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-vfs-file.c M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml M src/nemo-application.c M src/nemo-places-sidebar.c commit 8b7599a8897e5f5314b8637e7523f35285db118c Author: Daniel Nylander Date: 2009-07-07 Updated Swedish translation M po/sv.po commit 547fa8e9f8fe654b92d5b8b0f2dcc074a7ad91d8 Author: Claude Paroz Date: 2009-07-07 Updated French translation Contributed by Laurent Coudeur and Claude Paroz M po/fr.po commit 9da3dacb61a5f70b0b5a62c57f3278169fdea56a Author: Jorge González Date: 2009-07-07 Updated Spanish translation M po/es.po commit f24c7689e1efb27dd2953bdee7de8c02f183d9be Author: Alexander Larsson Date: 2009-06-30 Properly escape names used as gconf keys M libnemo-private/nemo-desktop-directory-file.c commit b8995fce159472dac07666dfb4d7e3ff1412403a Author: Alexander Larsson Date: 2009-06-29 Support metadata for the virtual desktop icons M libnemo-private/nemo-desktop-directory-file.c M libnemo-private/nemo-desktop-directory-file.h M libnemo-private/nemo-desktop-icon-file.c M libnemo-private/nemo-global-preferences.c commit 02f908f3d864f1f3bf0729158907f312e0306c05 Author: Alexander Larsson Date: 2009-06-29 Move metadata setting to a NemoFile vfunc This allows non-vfs backends to implement metadata M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-vfs-file.c commit 28d5e790dbe7752de156e01610c3e5c354064192 Author: Mattias Põldaru Date: 2009-06-26 Updating Estonian translation M po/et.po commit 65425491f90194e3034b5b49e0e333b5717d1776 Author: Alexander Larsson Date: 2009-06-26 Forgot to remove some references to removed symbols M libnemo-private/nemo-file-changes-queue.c commit 7874f2d9422618107edabd7056b7167844c389ca Author: Alexander Larsson Date: 2009-06-25 Support unsetting metadata M libnemo-private/nemo-file.c commit 99b68670ad94bfb5db1b162ae0d84e27f226d18f Author: Mattias Põldaru Date: 2009-06-25 Updating Estonian translation M po/et.po commit 22a457fd40d09139e5d7bbe6404006d0e091bc15 Author: drtvasudevan Date: 2009-06-24 Updated Tamil translation M po/ta.po commit 37be3809bc0d25d28298b38bc0b893a6fd3a665f Author: Alexander Larsson Date: 2009-06-23 Remove all traces of former nemo metadata code M libnemo-private/Makefile.am M libnemo-private/nemo-directory-async.c M libnemo-private/nemo-directory-background.c D libnemo-private/nemo-directory-metafile.c D libnemo-private/nemo-directory-metafile.h M libnemo-private/nemo-directory-private.h M libnemo-private/nemo-directory.c M libnemo-private/nemo-file-attributes.h M libnemo-private/nemo-file-changes-queue.c M libnemo-private/nemo-file-changes-queue.h M libnemo-private/nemo-file-operations.c M libnemo-private/nemo-file-utilities.c M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-link.c D libnemo-private/nemo-metafile.c D libnemo-private/nemo-metafile.h M libnemo-private/nemo-mime-actions.c M src/file-manager/fm-directory-view.c M src/file-manager/fm-properties-window.c M src/nemo-main.c M src/nemo-notes-viewer.c M src/nemo-sidebar-title.c M src/nemo-window-manage-views.c M test/test-nemo-directory-async.c commit fc4e74e6763000bac2a459e83811cf01e6cb7720 Author: Alexander Larsson Date: 2009-06-23 Use gvfs based metadata M libnemo-private/Makefile.am M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h A libnemo-private/nemo-metadata.c M libnemo-private/nemo-metadata.h M src/file-manager/fm-list-view.c commit c7b6875c98ecd25dc26853b783e1a4ffe96fab36 Author: Alexander Larsson Date: 2009-06-23 Add eel_g_strv_equal M eel/eel-glib-extensions.c M eel/eel-glib-extensions.h commit ffc93d52d4650e63e01b488ef582983919c89de3 Author: A. Walton Date: 2009-06-22 Another missed FreeBSD build fix. M libnemo-private/nemo-metafile.c commit 08144422c582077664b878fecc9878fc785b94df Author: Petr Kovar Date: 2009-06-21 Fixed Czech translation by Lucas Lommer Thanks goes to Vladimir Burian. M po/cs.po commit 22c5e7beacd28a64b4ff82ad20df0c954128ba46 Author: Jorge Gonzalez Date: 2009-06-21 Updated Spanish translation M po/es.po commit 104557839d2cfb375e5729e17c3fba3810f538e7 Author: Ivar Smolin Date: 2009-06-19 Updating Estonian translation M po/et.po commit dec816b65de82e832e29c0cea1a8c330ffa5954a Author: A. Walton Date: 2009-06-19 Fix the build. self_start_stop_type uninitialized in fm-directory-view.c M src/file-manager/fm-directory-view.c commit bcf5f921cda6f582230d3d0707f93172c3fa65e6 Author: A. Walton Date: 2009-06-19 Bug 586346 – Build failure on FreeBSD Wasn't the wrong number of arguments, it was the wrong type of argument (time_t, not long). So we add a cast to make it more explicit to the compiler there. M libnemo-private/nemo-file.c commit 0fe78fa2ae3d1a1e46996cc27c66421965bce57c Author: A. Walton Date: 2009-06-19 Bug 586346 – Build failure on FreeBSD Use g_snprint() instead of snprintf(). M libnemo-private/nemo-file.c commit 66b53e82aa5d45cec89c99ab74e86caf2c49df00 Author: David Zeuthen Date: 2009-06-17 Bug 585591 – Starting/stopping drives This is the Nemo user for the new GIO API for starting/stopping drives. See http://bugzilla.gnome.org/show_bug.cgi?id=585591 for details. M libnemo-private/nemo-file-private.h M libnemo-private/nemo-file.c M libnemo-private/nemo-file.h M libnemo-private/nemo-mime-actions.c M libnemo-private/nemo-vfs-file.c M src/file-manager/fm-actions.h M src/file-manager/fm-directory-view.c M src/file-manager/nemo-directory-view-ui.xml M src/nemo-places-sidebar.c commit 3af5d8c5bf61bdf206b9c79df0c27c0152b46496 Author: Mattias Põldaru Date: 2009-06-18 Updating Estonian translation M po/et.po commit 9ff24d6790da178fb8cba9c3c150a04ff4afea74 Author: Ivar Smolin Date: 2009-06-17 Updating Estonian translation M po/et.po commit 06e4eb732621b01c624b0e2665de523396e99f2f Author: Vincent Untz Date: 2009-06-17 Use gtk_cell_layout_get_cells instead of deprecated API M src/nemo-places-sidebar.c commit a2c338278cb82c4a2d8c4175d1db9ca7d7985d43 Author: A. Walton Date: 2009-06-17 Revert last commit as discussion in #gnome-hackers Turns out, g_app_info_should_show() is really broken, as this hides some apps we shouldn't be hiding. Wondering how we can unbreak this.. M libnemo-private/nemo-open-with-dialog.c commit e9d7b28a49d2afa5d67a34ef568a9e390df9a052 Author: A. Walton Date: 2009-06-17 Bug 586040 – "Open With" dialog duplicates Turns out, Nemo was showing GAppInfo's which shouldn't be shown in the UI. M libnemo-private/nemo-open-with-dialog.c commit b800160b430c17ddae5621a9af8b498d9092883d Author: A. Walton Date: 2009-06-16 Bug 563906 – Grammatical Error in String Fixes this bug. M src/nemo-window-manage-views.c commit 41975360a57115b5223e3466517df66b45c3fb63 Author: Alexander Larsson Date: 2009-06-15 Call g_reload_user_special_dirs_cache() when xdg-user-dirs change This means we will get the new special file icon for the changed files. Also, invalidate the file when we change it ourself so that the icon change is picked up. M libnemo-private/nemo-file-utilities.c commit a1ea86bd6c3d1123463e377e362dfffd047ef6a5 Author: Alexander Larsson Date: 2009-06-15 Post release version bump M configure.in commit e524b867b2653f6f92c8fb44f4b347b5fbc23c2c Author: Alexander Larsson Date: 2009-06-15 Update NEWS for 1.3.1 M NEWS commit b3f20601fe476d0af7b1175b14d9cb6729b96795 Author: Daniel Nylander Date: 2009-06-13 Updated sv translation (Daniel Nylander) M po/sv.po commit 5abcdbd43ef07460970ff2080dae121d908a0432 Author: A. Walton Date: 2009-06-12 Bug 547749 – "Open with" Applications not sorted. Use a sort model and add a sortable column to sort the application by name. M libnemo-private/nemo-open-with-dialog.c commit 932fa70aade6c12b1ef7a0158c0247e79546452c Author: Jorge Gonzalez Date: 2009-06-11 Updated Spanish translation M po/es.po commit 7ef11edc4d1819fe40b9c238e4d4ed31c07a9f0e Author: Manoj Kumar Giri Date: 2009-06-10 Added entries for Hindi Translation updated by Rajesh Ranjan M po/ChangeLog commit c0a359c656280dc504ea138b9e52763852ea202a Author: Manoj Kumar Giri Date: 2009-06-10 Updated Hindi Translation on behalf of Rajesh Ranjan M po/hi.po commit 4cf7e22dc55b37e5678ff69ac02d4acc5ac989fa Author: Kjartan Maraas Date: 2009-06-10 Updated Norwegian bokmÃ¥l translation. M po/nb.po commit 2316b80240b7b3c4e9627f31779b31d31cb1418d Author: Ivar Smolin Date: 2009-06-09 Updating Estonian translation M po/et.po commit 8db758307d49bf94c6e379b4439bb1fc61b7e28a Author: Cosimo Cecchi Date: 2009-06-08 Use a better string for schemas (#585134) M libnemo-private/apps_nemo_preferences.schemas.in commit 73443aae586eb99e6ca4406a03d91544def77968 Author: Runa Bhattacharjee Date: 2009-06-08 Updated Bengali India Translation M po/bn_IN.po commit 03e8e436fe57369ee1d28cfef77791dc258e8f22 Author: Mattias Põldaru Date: 2009-06-08 Updating Estonian translation M po/et.po commit 26d6ec74a5ebac6fb64e6ce0484ed96eefa7a78f Author: Petr Kovar Date: 2009-06-07 Fixed Czech translation by Lucas Lommer Thanks goes to Kamil Paral. M po/cs.po commit 437b01afc7ee7325ec8ba65bea05a13ef072063a Author: A. Walton Date: 2009-06-05 Bug 583214 – Nemo aborts when giving an empty dest. Follow up commit which fixes the code formatting and ensures the 'Open' button is insensitive when the entry is empty. M src/nemo-location-dialog.c commit 7b7a40130eb556fc7f32fb21a73c6437b29b0c73 Author: Christian Persch Date: 2009-06-04 Correct "srdcir" typo to "srcdir" M Makefile.am commit aa1afee5cc5b96161b6bb7c1639a180a39850653 Author: Theppitak Karoonboonyanan Date: 2009-06-04 Updated Thai translation. M po/th.po commit c0aa87793104abbea45fb1791a1a1cbb771f8b99 Author: Ask H. Larsen Date: 2009-05-30 Updated Danish translation M po/da.po commit 5bff677a0dc3ab5d5c68a2ef107cdbb34f133b34 Author: Cosimo Cecchi Date: 2009-05-28 Remove useless statfs/statvfs checks Those checks are now obsoletes. This also fixes bug #583264. M configure.in M src/file-manager/fm-properties-window.c commit 0133e979531cd41ca7f1d76ff5adf66ddfa7d67a Author: Cosimo Cecchi Date: 2009-05-28 Clear text in the location entry Add a clear text icon in the location entry, now that the icon entry is available in GTK+ 2.16 (#145732). M src/nemo-connect-server-dialog.c M src/nemo-location-entry.c commit 7b86b78e2ff6a0f1b45ac8f8a9c30cf3d0c6ae96 Author: Cosimo Cecchi Date: 2009-05-28 Emit APPEARANCE_CHANGED when setting the bg color Emit the APPEARANCE_CHANGED signal when we're setting the color, as we're ignoring the pending changes after the backgorund is realized, and thus we're not getting color updates (#578136). M eel/eel-background.c commit 518a1ae6ba0a3e09236f944ee655334087d5ddee Author: Cosimo Cecchi Date: 2009-05-28 Display information about the selected object Display information about the selected object in the "Information" sidebar, using thumbnails if possible. Also, remove the "Open with" buttons there for directories. Fix bug #122045, thanks to Amos Brocco. M src/nemo-information-panel.c M src/nemo-sidebar-title.c commit 4bb61206b7dd4a3510ab15e8df0288e670f816d6 Author: Alexander Larsson Date: 2009-05-27 Dist COPYING.EXTENSIONS M Makefile.am commit 7d9b6812d006d9aeecfb33d072cb382184fb901b Author: Alexander Larsson Date: 2009-05-27 Add COPYING.EXTENSIONS clarifying some extension license issues A COPYING.EXTENSIONS commit 74782b711adccfb85273ac38484e4adac8e010b4 Author: Jorge Gonzalez Date: 2009-05-26 Updated Spanish translation M po/es.po commit 152b56a058dfd0c57cdc267a63fb3099c0c74e0c Author: Yaron Shahrabani Date: 2009-05-25 Updated Hebrew translation M po/he.po commit 5fc840a5f089c627b4e38e2cf99f907ad8abb1a6 Author: drtvasudevan Date: 2009-05-25 Updated Tamil translation M po/ta.po commit 3d8011ca8c095be884b603ccea261b955fa6518b Author: JF Ding Date: 2009-05-25 Support daemon mode (exit_with_last_window preference) This can be used if you want to run nemo just to handle volume monitoring, etc. M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-main.c commit b49db4e5c9a3d21d3bc20c075e76b98b9977eedf Author: drtvasudevan Date: 2009-05-23 Updated Tamil translation M po/ta.po commit 7ea93ff768efdbc106407719b96a46fc34227273 Author: Ivar Smolin Date: 2009-05-19 Updating Estonian translation M po/et.po commit 2a005bc2c308e3960e723ed5cc8748f168acda17 Author: A. Walton Date: 2009-05-19 Bug 583214 – Nemo aborts when giving an empty dest. Fixes crash caused by passing a null path. M src/nemo-location-dialog.c commit 2eb9e588f954f8700d143fdb9d6d1e33318d9a33 Author: Alexander Shopov Date: 2009-05-19 Updated Bulgarian translation M po/bg.po commit d850d4742f41957506500c290c2756193c2a776f Author: Jorge Gonzalez Date: 2009-05-17 Updated Spanish translation M po/es.po commit 9af920dc7ab772c134ecd754be89b5d2b1aab5e0 Author: Petr Kovar Date: 2009-05-17 Fixed Czech translation by Lucas Lommer Phase two. M po/cs.po commit 173731a6dae993b5f15e334f1ebfa4756302efb8 Author: Petr Kovar Date: 2009-05-17 Updated Czech translation by Lucas Lommer M po/cs.po commit de14cf64ec9179a32617b1b26ce28d47aea2d8d9 Author: Matej Urban Date: 2009-05-15 Updated Slovenian translation M po/sl.po commit 1aba1feef00ad87da6e6e775568d3d8fea371576 Author: Matej Urban Date: 2009-05-15 Updated Slovenian translation M po/sl.po commit 776823f11bc40d78d17db36a303d69de0363d090 Author: Matej Urban Date: 2009-05-15 Updated Slovenian translation M po/sl.po commit 5fde2c7156b5bb8c0411bdbe649dd08172853d3a Author: Alexander Larsson Date: 2009-05-13 Don't crash if parent button_press_event is NULL (#582457) This fixes a crash when you press on the empty area of the toolbars. M src/nemo-navigation-window.c commit 24d9d3715194ff1145550a7fe3e9b8414ca568d2 Author: Holger Berndt Date: 2009-04-29 Allow users to define shortcuts for extension menu items M src/nemo-window-menus.c commit a2ab15477e2e2d13642567316788e12b5ace8504 Author: Tomas Bzatek Date: 2009-05-11 Properly include m4 macros fixes error messages like: ./configure: line 19939: syntax error near unexpected token `m4,' ./configure: line 19939: `SHAVE_INIT(m4, enable)' M Makefile.am commit e595852237c70e56c9d56688e2729eb59f6268fb Author: A. Walton Date: 2009-05-11 Bug 549437 – ctrl + dnd file duplication in list view Fixes bug #549437. Patch provided by "logari81". M libnemo-private/nemo-tree-view-drag-dest.c commit 9d618732420d6d2ae9f666bbb78ee486746c7940 Author: A. Walton Date: 2009-05-10 Update About dialog for 2009. M src/nemo-window-menus.c commit bf1fe66266c96139138908c1f1e1b1cc48f2bd4a Author: Marios Zindilis Date: 2009-05-10 Updated Greek translation M po/el.po commit aeda70b4fa90990a538d37122d88f0a82d0578f5 Author: Simos Xenitellis Date: 2009-05-09 Updated Greek translation M po/el.po commit f7d425f9045dae6d1d79328e66019c3ce18b1f19 Author: Simos Xenitellis Date: 2009-05-09 Updated Greek translation M po/el.po commit 35be2bdcd58e20422d2c8f0cf61b6d2a027dfd93 Author: Marios Zindilis Date: 2009-05-09 Updated Greek translation M po/el.po commit a9d7dfc3efb948a88cb5acfce3db8891e3297499 Author: Christian Kirbach Date: 2009-05-06 Updated German translation. M po/de.po commit 8d3525a3c3d414fe67f8f8b3c183c95e1282bce1 Author: Cosimo Cecchi Date: 2009-05-05 Post release version bump to 2.27.2 M configure.in commit 956bf2c75079003c91774a675091f7133cc8be35 Author: Cosimo Cecchi Date: 2009-05-05 Prepare for 2.27.1 release M NEWS M configure.in commit ec4ce1431bda72fc66ace675d860e7c2bb3bc3e6 Author: Cosimo Cecchi Date: 2009-05-05 Fix distcheck M Makefile.am M data/Makefile.am M src/nemo-main.c commit 057dabdd59a24d863d8b10dca336a3ca2bf8609f Author: Shankar Prasad Date: 2009-05-04 Updated the Kannda translations M po/kn.po commit 0a6012a48bd71c20d7cd32c05e1976f1127ce230 Author: Jorge Gonzalez Date: 2009-05-03 Updated Spanish translation M po/es.po commit a6f87ffe8133a4f9205dd1ab1d441fa06c40b497 Author: Ivar Smolin Date: 2009-05-02 Updating Estonian translation M po/et.po commit 86cacc2fd60dbed4397567edd08021513c1a60ae Author: Jorge Gonzalez Date: 2009-05-01 Updated Spanish translation M po/es.po commit bcbbc3f7853ab1a3a0f2b226312a41d5987e1d5a Author: Vladimir Melo Date: 2009-05-01 Updated Brazilian Portuguese translation. M po/pt_BR.po commit d6fa64ab439ac900a92a0467f39cdf72afa5870f Author: Cosimo Cecchi Date: 2009-05-01 Add building tips link Mention http://live.gnome.org/Nemo/Development/Nemo in the README file. M README commit 1a8adc87b49603cf14ce139e66bde0fe7bddec8e Author: Cosimo Cecchi Date: 2009-05-01 Remove a reference to SVN Also, update the GIT info page link. M HACKING commit 7e17224a1e68bb755bd281d46e0533b1dcff52d8 Author: Claude Paroz Date: 2009-04-30 Updated French translation M po/fr.po commit c51ac9926e012267d305711b949a937d917f075b Author: Gabor Kelemen Date: 2009-04-30 Mark strings as translatable, fix bug #579769 M src/nemo-file-management-properties.ui commit 23ff2a21d2925945dde6e04a47190ebfa27ae8c7 Author: Gabor Kelemen Date: 2009-04-30 Update POTFILES.*, close bug #580784 M po/POTFILES.in M po/POTFILES.skip commit a1a501224999d7abda06e9a2f7eb6da64c17d089 Author: Shankar Prasad Date: 2009-04-30 Updated Kannada translation M po/kn.po commit 90e5e1720d09188f3eabb67e502272a549c63dec Author: Maxim V. Dziumanenko Date: 2009-04-28 Updated Ukrainian translation M po/uk.po commit 48ed43f32668e5615ac64a3de55ec7ab2f254ef7 Author: Cosimo Cecchi Date: 2009-04-27 Reverse the order for folder icons overrides Use the correct order for folder icons overrides, so that we can keep track of things like "folder-visiting" or "folder-drag-accept". Patch by Krzysztof KosiÅ„ski (#567254). M libnemo-private/nemo-file.c commit 43c9802d618bcb0d035b4fb0dea4807367d893ea Author: Cosimo Cecchi Date: 2009-04-27 Don't display accelerators in Tabs menu Set use_underline == FALSE for items in the "Tabs" menu, so that folders with underscores in their names will be displayed properly in the menu items (#580392). M src/nemo-navigation-window-menus.c commit 9c0dddfbaddfe251814ff473d9f0a734c385d931 Author: Cosimo Cecchi Date: 2009-04-27 Display the application icon in the popup menu If available, display the application icon next to the "Open with" item in the file manager window menus (#546916). M src/file-manager/fm-directory-view.c commit fe4ca76584061215547edb55b8a0bab4cdb8e034 Author: Cosimo Cecchi Date: 2009-04-27 Fix DOAP file Add "mailto:" prefixes to email addresses in the DOAP file. M nemo.doap commit 7f404a39f63ceb8d906809c2092cecca7b785574 Author: Ivar Smolin Date: 2009-04-25 Updating Estonian translation M po/et.po commit cffb9cf70254086a3737b37e8fad786a6e6de414 Author: Cosimo Cecchi Date: 2009-04-23 Don't show autorun hints for Win32 software media Now that shared-mime-info supports "x-content/win32-software" vs "x-content/unix-software", use this distinction to inhibit autorun prompts/hints for media containing Win32 software (#524270). M libnemo-private/nemo-autorun.c M src/nemo-window-manage-views.c commit 7f74d06e270d89b6de1a3f23fe3388830f2c25ab Author: Olav Vitters Date: 2009-04-23 doap: Add desktop category M nemo.doap commit 9f1c7d03c45298701320f5503e8ba1afec9fb523 Author: Cosimo Cecchi Date: 2009-04-23 Add shave to the autotools setup Use shave to have some more meaningful build messages. It can be turned off by using 'make V=1'. M Makefile.am M configure.in A m4/Makefile.am A m4/shave-libtool.in A m4/shave.in A m4/shave.m4 commit 06dda37076c6e5b222f868a46fe84c070a04d680 Author: Cosimo Cecchi Date: 2009-04-23 Move desktop files into data/ Move desktop files into data/ subdirectory, so that they not clutter the top source dir. M Makefile.am M configure.in M data/Makefile.am R100 nemo-autorun-software.desktop.in.in data/nemo-autorun-software.desktop.in.in R100 nemo-browser.desktop.in.in data/nemo-browser.desktop.in.in R100 nemo-computer.desktop.in.in data/nemo-computer.desktop.in.in R100 nemo-file-management-properties.desktop.in.in data/nemo-file-management-properties.desktop.in.in R100 nemo-folder-handler.desktop.in.in data/nemo-folder-handler.desktop.in.in R100 nemo-home.desktop.in.in data/nemo-home.desktop.in.in R100 nemo.desktop.in.in data/nemo.desktop.in.in commit dd10aa3618b195a127014ba033eb522f907077a1 Author: Cosimo Cecchi Date: 2009-04-23 Fix typo in ChangeLog generation script Set the right name for the start tag in the ChangeLog generation script. M Makefile.am commit c0b27cce8d33ea8220434cf59b1e504fc9d2bcea Author: Matej Urban Date: 2009-04-22 Updated Slovenian translation M po/sl.po commit 9826f177cb72fc9f595356b773f51059bef6cd1e Author: Andrew Walton Date: 2009-04-22 Let forward/back mouse buttons work Install a handler to link forward/back mouse buttons to forward/back actions in NemoNavigationWindow, with a preference to set the right X button number in GConf. Signed-off-by: Cosimo Cecchi M libnemo-private/apps_nemo_preferences.schemas.in M libnemo-private/nemo-global-preferences.c M libnemo-private/nemo-global-preferences.h M src/nemo-navigation-window.c commit b02ef0a7ec2d0de3064d322f5da103a8dfd492d3 Author: Cosimo Cecchi Date: 2009-04-22 Remove useless function Remove nemo_has_valid_failed_thumbnail(), as that's not used anymore after the last commit. M libnemo-private/nemo-thumbnails.c M libnemo-private/nemo-thumbnails.h commit 20f4389f7cd22bd001ebf17c0c3c459cca5483ad Author: Matthias Clasen Date: 2009-04-22 Avoid duplicate function call Don't call nemo_has_valid_failed_thumbnail, as nemo_can_thumbnail will eventually call the same gnome_desktop function (#574205). Signed-off-by: Cosimo Cecchi M libnemo-private/nemo-file.c commit 3ffebcdbf5b5ba7e6b018f542fdc39522a42d1b2 Author: Cosimo Cecchi Date: 2009-04-22 Remove some more GTK+ deprecated macros Remove some other bits (hopefully the last) of deprecated GTK+ macros. M src/nemo-history-sidebar.c commit c308f7f3e96094c4d5077655960a0910dbaa605c Author: Cosimo Cecchi Date: 2009-04-22 Remove other deprecated GTK+ symbols There were still some references to deprecated GTK+ symbols in some files, or in some comments. Let's drop them all. M eel/eel-editable-label.c M eel/eel-gdk-pixbuf-extensions.c M libnemo-private/nemo-cell-renderer-text-ellipsized.h M libnemo-private/nemo-directory.h M libnemo-private/nemo-file.h M libnemo-private/nemo-saved-search-file.h M libnemo-private/nemo-undo-signal-handlers.c M src/file-manager/fm-empty-view.c M src/file-manager/fm-empty-view.h M test/test-eel-background.c commit 4485d32d41f1519313ad49d43914bbd0b78d104b Author: Jorge Gonzalez Date: 2009-04-21 Updated Spanish translation M po/es.po commit 7da1601ba6288e48dc6ed3023de03fff04d20b2d Author: Cosimo Cecchi Date: 2009-04-21 Check for NULL when sorting columns Check for a NULL value of the order array when sorting the columns. This might help when dealing with strange GConf setup issues (#524341). M libnemo-private/nemo-column-utilities.c commit 3b5af96a5f41640d447f7215a758d4de4c0220fb Author: Cosimo Cecchi Date: 2009-04-21 Update EggSMClient from libegg Re-apply the reverted string freeze break commit now that we branched. Don't check if the desktop file exists ourselves, as the Egg code will take care of that itself. Thanks to Christian Persch (#576619). M cut-n-paste-code/libegg/eggsmclient.c M src/nemo-main.c commit 60e58366e06f42b03072e06a19f8adeece0ded6a Author: Nelson Benitez Date: 2009-04-21 Use g_timeout_add_seconds where appropriate Use g_timeout_add_seconds instead of g_timeout_add where appropriate. Fix bug #574033. Signed-off-by: Cosimo Cecchi M libnemo-private/nemo-icon-container.c M libnemo-private/nemo-thumbnails.c M libnemo-private/nemo-tree-view-drag-dest.c M libnemo-private/nemo-users-groups-cache.c M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-icon-view.c M src/file-manager/fm-list-view.c M src/nemo-notes-viewer.c M src/nemo-spatial-window.c commit 99e66a93605e056c80cebb4c3ac9b6b58167ad1c Author: Matthias Clasen Date: 2009-04-21 Avoid delays in background switching Don't delay background switching, so that users will immediately see it changing when browsing the background list (#330168). Signed-off-by: Cosimo Cecchi M libnemo-private/nemo-directory-background.c commit 979d877c1803034be8a3ff69437974a1cfdbff30 Author: Cosimo Cecchi Date: 2009-04-21 Enforce {GDK,GTK}_DISABLE_DEPRECATED cflags Now that we build cleanly without deprecated symbols, widen the deprecated check policy to GDK/GTK+. M configure.in commit b695c970182bbf19f2c38bf7405db506e7c23bb0 Author: Cosimo Cecchi Date: 2009-04-21 Remove deprecated GDK/GTK+ symbols Remove all uses of deprecated GDK and GTK+ symbols, replacing them with the currently supported equivalents. Based on a patch from Tal Benavidor (#565038). M eel/eel-background-box.h M eel/eel-background.c M eel/eel-background.h M eel/eel-canvas-rect-ellipse.h M eel/eel-canvas.c M eel/eel-canvas.h M eel/eel-debug-drawing.c M eel/eel-editable-label.c M eel/eel-editable-label.h M eel/eel-gtk-extensions.c M eel/eel-gtk-extensions.h M eel/eel-gtk-macros.h M eel/eel-image-table.c M eel/eel-image-table.h M eel/eel-labeled-image.h M eel/eel-stock-dialogs.c M eel/eel-types.c M eel/eel-wrap-table.c M eel/eel-wrap-table.h M libnemo-private/nemo-autorun.c M libnemo-private/nemo-bookmark.h M libnemo-private/nemo-cell-renderer-pixbuf-emblem.h M libnemo-private/nemo-clipboard-monitor.h M libnemo-private/nemo-column-chooser.h M libnemo-private/nemo-desktop-directory-file.h M libnemo-private/nemo-desktop-directory.h M libnemo-private/nemo-desktop-icon-file.h M libnemo-private/nemo-desktop-link-monitor.h M libnemo-private/nemo-desktop-link.h M libnemo-private/nemo-directory.h M libnemo-private/nemo-dnd.c M libnemo-private/nemo-entry.h M libnemo-private/nemo-file.h M libnemo-private/nemo-horizontal-splitter.h M libnemo-private/nemo-icon-canvas-item.h M libnemo-private/nemo-icon-container.h M libnemo-private/nemo-keep-last-vertical-box.h M libnemo-private/nemo-merged-directory.h M libnemo-private/nemo-metafile.h M libnemo-private/nemo-open-with-dialog.c M libnemo-private/nemo-progress-info.c M libnemo-private/nemo-search-directory-file.h M libnemo-private/nemo-search-directory.h M libnemo-private/nemo-trash-monitor.h M libnemo-private/nemo-undo-manager.h M libnemo-private/nemo-undo-transaction.h M libnemo-private/nemo-vfs-directory.h M libnemo-private/nemo-vfs-file.h M src/file-manager/fm-desktop-icon-view.c M src/file-manager/fm-desktop-icon-view.h M src/file-manager/fm-directory-view.c M src/file-manager/fm-directory-view.h M src/file-manager/fm-icon-container.h M src/file-manager/fm-icon-view.c M src/file-manager/fm-icon-view.h M src/file-manager/fm-list-model.h M src/file-manager/fm-list-view.c M src/file-manager/fm-list-view.h M src/file-manager/fm-properties-window.c M src/file-manager/fm-properties-window.h M src/file-manager/fm-tree-model.h M src/file-manager/fm-tree-view.c M src/file-manager/fm-tree-view.h M src/nemo-application.h M src/nemo-bookmark-list.h M src/nemo-desktop-window.h M src/nemo-emblem-sidebar.c M src/nemo-emblem-sidebar.h M src/nemo-history-sidebar.c M src/nemo-history-sidebar.h M src/nemo-image-properties-page.h M src/nemo-information-panel.c M src/nemo-information-panel.h M src/nemo-location-bar.h M src/nemo-location-entry.h M src/nemo-navigation-bar.h M src/nemo-navigation-window.h M src/nemo-notes-viewer.c M src/nemo-notes-viewer.h M src/nemo-places-sidebar.c M src/nemo-places-sidebar.h M src/nemo-property-browser.h M src/nemo-query-editor.h M src/nemo-search-bar.c M src/nemo-search-bar.h M src/nemo-side-pane.h M src/nemo-sidebar-title.h M src/nemo-spatial-window.c M src/nemo-spatial-window.h M src/nemo-throbber.h M src/nemo-window-menus.c M src/nemo-window.h M src/nemo-zoom-control.h M test/test-nemo-directory-async.c M test/test.c commit e2f711533e1008b62c9db70fb3bcf877191866d4 Author: Alexander Larsson Date: 2009-04-20 Fix broken pofile Lots of duplicated strings that makes msgfmt -c check fail. M po/ha.po commit 42bea16f00e93441a601f3279702d1bd60f07592 Author: Alexander Larsson Date: 2009-04-20 Comment out invalid pofile strings msgfmt -c bs.po said: bs.po:3783: number of format specifications in 'msgid' and 'msgstr[0]' does not match msgfmt: found 1 fatal error which meant branching was impossible M po/bs.po commit f9585e4f4825ab1114cd4185ec8cdca9360da3c9 Author: Jonathon Jongsma Date: 2009-04-20 Allow shift+return during typeahead find Allow shift+rename to close parent + open when typeahead find window is active. (#579551) M libnemo-private/nemo-icon-container.c commit 1f9ed9598a3324278eaef2153b95f22962dd2558 Author: Khaled Hosny Date: 2009-04-17 Updated Arabic translation M po/ar.po commit 9c4c0254d4788ac1d7e10df30fc74cc2d64c5d09 Author: Alexander Larsson Date: 2009-04-17 Preload /desktop/gnome/background from gconf We'll be reading a lot of background settings, so we want to preload (and thus also add_dir) the gconf directory. (Fixes #578993) M libnemo-private/nemo-global-preferences.c commit e61a17f3445be7c77f092b717f1e64a1231e01c0 Author: Cosimo Cecchi Date: 2009-04-17 Fix a copy/paste typo. M README.commits commit bad7749c6cc88009ba5e0f9f96f9ab418a1f7193 Author: Alexander Larsson Date: 2009-04-17 Add .gitignore files A .gitignore A data/.gitignore A docs/reference/.gitignore A docs/reference/libnemo-extension/.gitignore A docs/reference/libnemo-extension/libnemo-extension-overrides.txt A docs/reference/libnemo-extension/libnemo-extension-sections.txt A eel/.gitignore A libnemo-private/.gitignore A po/.gitignore A src/.gitignore commit 8acf8338c97387af3b93793760a3b1d64e752a2c Author: Alexander Larsson Date: 2009-04-17 Add makefile rules to generate ChangeLog M Makefile.am commit 3f4a5c97a23acbca33836d14edb2b5c8798a6dc5 Author: Alexander Larsson Date: 2009-04-17 Add doap file with name, description and developer info A nemo.doap commit a867c35e835128647396ad5b2df498c189944ca4 Author: Alexander Larsson Date: 2009-04-17 Add README.commits, update HACKING for git M HACKING M Makefile.am A README.commits commit 4a78eabc71df08bdf3d71877c3b3cb62d1b80bff Author: Alexander Larsson Date: 2009-04-17 Move ChangeLog to ChangeLog-20090417 With the switch to git we're moving to an autogenerated ChangeLog. R099 ChangeLog ChangeLog-20090417 M Makefile.am commit 6a8673c7806ad7a014feb9bc780e0dfcadb5d71c Author: Alexander Larsson Date: 2009-04-16 Reversed check in last commit, fixed. 2009-04-16 Alexander Larsson * configure.in: Reversed check in last commit, fixed. svn path=/trunk/; revision=15188 M ChangeLog M configure.in commit ab550c223368c4d0bb9b7133e477430a38fe96d6 Author: Alexander Larsson Date: 2009-04-16 Bug 578983 – set_more_warnings check of WARNING_CFLAGS doesn't work 2009-04-16 Alexander Larsson Bug 578983 – set_more_warnings check of WARNING_CFLAGS doesn't work * configure.in: Actually check the options. svn path=/trunk/; revision=15187 M ChangeLog M configure.in commit 9870d42d6709fea0fd3c50d00f5a491902be27e5 Author: Alexander Larsson Date: 2009-04-16 Set typeahead column to the name column. 2009-04-16 Alexander Larsson * src/nemo-places-sidebar.c (nemo_places_sidebar_init): Set typeahead column to the name column. svn path=/trunk/; revision=15186 M ChangeLog M src/nemo-places-sidebar.c commit 3125825a1cb10f38779b926050d4030f45a6003a Author: Alexander Larsson Date: 2009-04-16 Bug 578468 – Change of font DPI setting does not effect desktop icons 2009-04-16 Alexander Larsson Bug 578468 – Change of font DPI setting does not effect desktop icons * libnemo-private/nemo-icon-canvas-item.c: (nemo_icon_canvas_item_invalidate_label_size): Invalidate pango layouts since the context could have changed For instance the font DPI. svn path=/trunk/; revision=15185 M ChangeLog M libnemo-private/nemo-icon-canvas-item.c commit 4323f9b47229312a60093587724e1aa102a8c926 Author: Alexander Larsson Date: 2009-04-16 Bug 579086 – Excessive white-space on right-hand side in icon view 2009-04-16 Alexander Larsson Bug 579086 – Excessive white-space on right-hand side in icon view * libnemo-private/nemo-icon-container.c: (nemo_icon_container_update_scroll_region): When using at allocation->width, take zoom into account svn path=/trunk/; revision=15184 M ChangeLog M libnemo-private/nemo-icon-container.c commit 649c39c7d8f6b3162e6f9142f3201eb254f26c8f Author: Alexander Larsson Date: 2009-04-13 Post release version bump 2009-04-13 Alexander Larsson * configure.in: Post release version bump === nemo 2.26.2 === svn path=/trunk/; revision=15183 M ChangeLog M configure.in M eel/ChangeLog M po/ChangeLog nemo-3.6.5/COPYING.LIB0000664000175000017500000006131113215733314013053 0ustar fabiofabio GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, 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 library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, 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 companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, 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 library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete 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 distribute a copy of this License along with the Library. 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 Library or any portion of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, 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 Library, 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 Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you 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. If distribution of 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 satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. 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. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library 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. 9. 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 Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library 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. 11. 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 Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library 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 Library. 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. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library 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. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library 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 Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, 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 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. 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 LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! nemo-3.6.5/generate_additional_file0000775000175000017500000000240413215733314016320 0ustar fabiofabio#!/usr/bin/python3 import os os.chdir("data") os.system("./merge_action_strings") os.chdir("..") DOMAIN = "nemo" PATH = "/usr/share/locale" import os, gettext, sys sys.path.append('/usr/lib/linuxmint/common') import additionalfiles os.environ['LANGUAGE'] = "en_US.UTF-8" gettext.install(DOMAIN, PATH) prefix = """[Desktop Entry] """ suffix = """Exec=nemo %U Icon=folder Terminal=false Type=Application StartupNotify=false Categories=GNOME;GTK;Utility;Core; MimeType=inode/directory;application/x-gnome-saved-search; Actions=open-home;open-computer;open-trash; """ additionalfiles.generate(DOMAIN, PATH, "data/nemo.desktop.in.in", prefix, _("Files"), _("Access and organize files"), suffix) prefix = """ [Desktop Action open-home] """ suffix = """Exec=nemo %U """ additionalfiles.generate(DOMAIN, PATH, "data/nemo.desktop.in.in", prefix, _("Home"), None, suffix, append=True) prefix = """ [Desktop Action open-computer] """ suffix = """Exec=nemo computer:/// """ additionalfiles.generate(DOMAIN, PATH, "data/nemo.desktop.in.in", prefix, _("Computer"), None, suffix, append=True) prefix = """ [Desktop Action open-trash] """ suffix = """Exec=nemo trash:/// """ additionalfiles.generate(DOMAIN, PATH, "data/nemo.desktop.in.in", prefix, _("Trash"), None, suffix, append=True) nemo-3.6.5/autogen.sh0000775000175000017500000000206113215733314013411 0ustar fabiofabio#!/bin/sh # Run this to generate all the initial makefiles, etc. test -n "$srcdir" || srcdir=$(dirname "$0") test -n "$srcdir" || srcdir=. olddir=$(pwd) cd $srcdir (test -f configure.ac) || { echo "*** ERROR: Directory '$srcdir' does not look like the top-level project directory ***" exit 1 } # shellcheck disable=SC2016 PKG_NAME=$(autoconf --trace 'AC_INIT:$1' configure.ac) if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then echo "*** WARNING: I am going to run 'configure' with no arguments." >&2 echo "*** If you wish to pass any to it, please specify them on the" >&2 echo "*** '$0' command line." >&2 echo "" >&2 fi mkdir -p m4 glib-gettextize --force --copy || exit 1 gtkdocize --copy || exit 1 intltoolize --force --copy --automake || exit 1 autoreconf --verbose --force --install || exit 1 cd "$olddir" if [ "$NOCONFIGURE" = "" ]; then $srcdir/configure "$@" || exit 1 if [ "$1" = "--help" ]; then exit 0 else echo "Now type 'make' to compile $PKG_NAME" || exit 1 fi else echo "Skipping configure process." fi nemo-3.6.5/utils/0000775000175000017500000000000013215733314012551 5ustar fabiofabionemo-3.6.5/utils/gvfs-info.nemo_action0000664000175000017500000000027413215733314016667 0ustar fabiofabio[Nemo Action] Active=true Name=Report GVFS info on %f Comment=Send the results of gvfs-info on %f to stdout Exec=gvfs-info %F Icon-Name=info Selection=s Extensions=any; EscapeSpaces=true nemo-3.6.5/data/0000775000175000017500000000000013215733314012322 5ustar fabiofabionemo-3.6.5/data/set-as-background.nemo_action.in0000664000175000017500000000036013215733314020454 0ustar fabiofabio[Nemo Action] Name=Set as Wallpaper... Comment=Set the selected image as your Cinnamon desktop wallpaper Exec=gsettings set org.cinnamon.desktop.background picture-uri "%U" Selection=s Mimetypes=image/*; Conditions=dbus org.Cinnamon; nemo-3.6.5/data/nemo.FileManager1.service.in0000664000175000017500000000013113215733314017474 0ustar fabiofabio[D-BUS Service] Name=org.freedesktop.FileManager1 Exec=@bindir@/nemo --no-default-window nemo-3.6.5/data/change-background.nemo_action.in0000664000175000017500000000040713215733314020507 0ustar fabiofabio[Nemo Action] Name=Change Desktop _Background Comment=Change the Cinnamon desktop background Exec=cinnamon-settings backgrounds Selection=None Icon-Name=cs-backgrounds Extensions=any; Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; nemo-3.6.5/data/dbus-interfaces.xml0000664000175000017500000000336313215733314016127 0ustar fabiofabio " nemo-3.6.5/data/mount-archive.nemo_action.in0000664000175000017500000000072613215733314017732 0ustar fabiofabio[Nemo Action] Name=Mount archive Comment=Mount %f to browse its contents Exec=/usr/lib/gvfs/gvfsd-archive file="%U" Selection=s Mimetypes=application/x-7z-compressed;application/x-cd-image;application/x-cpio;application/x-rar;application/x-rar-compressed;application/x-7z-compressed-tar;application/x-bzip-compressed-tar;application/x-compressed-tar;application/x-tar;application/zip; Stock-Id=gtk-directory Dependencies=/usr/lib/gvfs/gvfsd-archive; Selection=s nemo-3.6.5/data/action_i18n_strings.py0000664000175000017500000000277413215733314016573 0ustar fabiofabio ''' This is a dummy file for translating Nemo Action files It was generated by the extract_action_strings script on 2017-10-24 09:43:56.547380 UTC. ''' set-as-background_nemo_action_in_Name = _("Set as Wallpaper...") set-as-background_nemo_action_in_Tooltip = _("Set the selected image as your Cinnamon desktop wallpaper") add-desklets_nemo_action_in_Name = _("Add Desklets") add-desklets_nemo_action_in_Tooltip = _("Add Cinamon desklets") mount-archive_nemo_action_in_Name = _("Mount archive") mount-archive_nemo_action_in_Tooltip = _("Mount %f to browse its contents") change-background_nemo_action_in_Name = _("Change Desktop _Background") change-background_nemo_action_in_Tooltip = _("Change the Cinnamon desktop background") 92_show-expo_nemo_action_in_Name = _("Manage workspaces (Expo)") 92_show-expo_nemo_action_in_Tooltip = _("Open Expo to add, remove, or organize workspaces") new-launcher_nemo_action_in_Name = _("Create a new l_auncher here...") new-launcher_nemo_action_in_Tooltip = _("Create a new launcher in this folder") desktop-settings_nemo_action_in_Name = _("Desktop _Settings") desktop-settings_nemo_action_in_Tooltip = _("Change how your desktop works") 91_delete-workspace_nemo_action_in_Name = _("Remove workspace") 91_delete-workspace_nemo_action_in_Tooltip = _("Remove the currently active workspace") 90_new-workspace_nemo_action_in_Name = _("Jump to new workspace") 90_new-workspace_nemo_action_in_Tooltip = _("Create a new workspace and activate it") nemo-3.6.5/data/org.Cinnamon.xml0000664000175000017500000000134513215733314015377 0ustar fabiofabio nemo-3.6.5/data/icons/0000775000175000017500000000000013215733314013435 5ustar fabiofabionemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-left.png0000664000175000017500000000035013215733314023126 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEá |–_iuIDAT8ËÝÒÁ À ÐOwˆÝÂ%<¹¼9éŽàï© RhÓžÚÿÁþ=$A½w|.¥ ¥D0‡E„1ÆûÀVUˆØU…sŽ.íl9ưm­Pk…÷Þ^aEBv`FZkÈ9óQ¥WôÙ4€»¾a±HIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_scalable_collapse-menu-hover-symbolic.svg0000664000175000017500000000364013215733314026752 0ustar fabiofabio image/svg+xml Gnome Symbolic Icon Theme Gnome Symbolic Icon Theme nemo-3.6.5/data/icons/hicolor_actions_scalable_sidebar-show-symbolic.svg0000664000175000017500000000066213215733314025455 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_actions_scalable_location-symbolic.svg0000664000175000017500000000136513215733314024677 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_actions_scalable_sidebar-places-symbolic.svg0000664000175000017500000000066513215733314025747 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_apps_22x22_nemo.png0000664000175000017500000000145013215733314020502 0ustar fabiofabio‰PNG  IHDRÄ´l;sRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÜ  ((»¨IDAT8ËÕ•½n$E…¿[ÓH°?é+"b§#˳ÍIÈyRÃðH<‡‘ ìБÚ€W ˜õzlOOwÝ?‚ê­Ñ+oDI­–®ª¾>uî©.ø¿ ÈL9==}wNY–RžÌçóÛ×wGGG²¿¿ÿøàà`礳³³·Tõ}àõÁ'''?¹ûG"bîÞíšTJ)îþëñññ¿±*ðñáááϪ~8ŸÏ)¥tî¾sÅÞÞÞÛÿ¥ðüü¼_­VO€vwqw2“¯¾ùs}h¿>¾ÿüë§ µÙ¹;p„óÉÓϘ• "™dF›“AFàéíA„³–,nž³¸¾ä·Ë?ßí"3£”2%`Æ//.(¥c6Õ2ÇÝ07< wÅÌp7ª¨ŽT¨:r×/¥sw"š€"B)…n6kÊKÁÝH 3"sC½ÔFFQêÀݰÌÎÌÄÝÛÖH&[p2ŒC­¢6Nê*ê“Â:Pmd¬kªŽ uͪ_JlÀ‰…2èšÒ|!³ùi6R­¢6 :2N0«¨UÌu%£%kÛ<áný’õxÇÍj$IBž­AñŠÏæÚ¼žêA†“’HÒ¶ WËßY·ÜöW)ˆx%±mâ½gS G²ý(¶VÐìE½RuD¤Em"o£áȧt4õæ61„L²33Ì ¡P0WÆ:PD@dÓÏ{ªwÁ7#3°ÎÝ·`ÓJÕA¶µl+Úáø|Ó{à"ÚEÄ6n"u¥ÖaR+÷lUgüóÁÎ$sRÜzÇubVžIEND®B`‚nemo-3.6.5/data/icons/hicolor_status_48x48_progress-100.png0000664000175000017500000000601213215733314022305 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß9' ò —IDAThÞíš{Œ\Õ}Ç?÷9ïïÎîxe;ëµÇ 6±›µ!æa(†6V¡8¡È£iÌ£ &‚ѨŠòp "%MJ“*‰PZ *¡& ªjµŠ?0ØC·^¼~íîØ3ã¹wvfî½çžþ1wÆóX£µ³i‚Ô#ýtgîœ{Ï÷{Îïu~gàÿÛï¶)³ø.0уïzð›¸ÁÕ Äý} ` Á“l`˜M$X„ÉLDp)á`áÇb”}<Ç'ÙX@) ôÚ ÍÙÌaöǦˆ¤€ä ’<’’Óä‚{g‚>E$yl³‡³Hïü­7èæQnaŒƒØøœ @ž:O9²ñã r ÐÝ v³®Ba®d€ñ}æqo§EÃç{ø÷°›·òLÕf8D‚ϲŽoóSæp1e gIࢤ[ù0‚רËäLlC™Áï]ü€p !ˆ"ÎÑS 8ÌQ0Æ1N“£Hž";x‹Kèæ}t1È|®d,B;Çäi€ÆÏóŸæY м søwò§‚Ž?M‹m¼Ê.ö’àŸèãmRTx`ÚAu ‡ù\ÃýÜέ\Oœx[/áñ,Ÿå^žò¢™Qà&Nbs ÉÑ9‚ÇìäOy„¿¦ã‚ÀÆâüëó·m‰š¡ }ƒWÔv3’Râû)}ÇÅ÷Eõ»ïã˳Wß÷‘¾Ä—¾çTœG>yÿŸoäIþ“Xƒ]¸@šaæj¾ÉOâ»± ôq€#ÁÅMfèâñ·<ó¹÷îÑ–¯ß9п4ÒÓÓchš†”EQÀûø¾O¥RÁq¤”H) …B8Žƒ!•J…S§N¡(Š8txdêLÖºê¡=õ²…0&W,ÞbŒÁYw¢¶ˆó7ÓÉ ^àŸkò ^ÁäK+{—ßÙ“š«§Óic||œR©„ã8T**• ®ëâºnÓ=MÓP…ÉÉI2™ ™L¦þÙu]„Z$UQåf~‹ü;_mÛ:ä1n†f¯¥¶¹ÍUÜÁ ~ÀÓòX¼Ä <ÎxÄ ¢¯¯?šÍféè¨:UUQUß÷)—Ë”J%¦¦¦B i¶mS(ðý³~XQ‰ñxOïÜÞ˜âã6l³…¿ÁÆnÂ0…Â*îæœ‹€Ì¡›¥MúÀ/ØCˆïå+_¼6ŽvÄcq4MÃ÷}„8ŽC±X¤X,R*•(—«Y€ïû¸®[ÕuÙ„¤Ói|ß'O‰ÇÔKW^z §°ù÷¶áèfi@À˜Ž@„-¬G'Ùæ}‡ÙÏw)¦ºS›‡V …Ëå2B\×%ŸÏcYŠ¢ ë:†a`F´¢(màk6Q.—k6ÀÊ Ŧñ ò<‹h¢“d 냾@‚e܈ג§Œð6qžºþúë;"‘èét¯R(Èçó‹E"‘¦iÖ ³¦&‘H„ÎÎNR©©TŠD"QߨFÅb±N²a?†a®Ú´iS?Ç)s„6añ€eÜ$Z ¨@“Þ&ãÀ;üšï\ñÁ5· ëRJ&&&°,‹P(„çyuBày£££ 2™ 'Oždrr’Ó§O322R_™šÔˆX–…ëº\wÝh]]]w ¯ò|“Þ 2«­Ì6õ‘@S<‹×ÕÙuÿâEiÙl–C‡‘L&ë³ÞJ"•JqâÄ &&&Èd2d³Y,Ëb`` ÉÍ6ªY.—#›Í²ì’eª¦kŸ s° N2ˆÊjc «ˆÒÑ–‚å˜øè]ÔÑ‘¼È4M2™ ét˲êî±1hšFOOOlMµA7®€ªª”J%¤”!X0AÇÆ׿ð«v¶á‰ÒÑH yB$Ú–LrzÑâ…9|ù°V(p‡T*…®ëÔ‚X« Õ>7ÚÅtD|ß'‹!„```UU±m›µk×êsçÎý+ÞÀiÃ"1Ý (€6m®!â qûâÅŒ!„@J‰®ë¸®K,Ã0 <Ï«²ÐVu0 ƒH$B8FQlÛFJ‰išhš†ã8 P*•®X±zE÷ÿ@ë¾£¶kP T÷E,’„û/Ó— ½oA\Ó4r¹\=`)Š‚‚r¹ŒªªÄb1âñ8¦ibFPˆëºT*Êå2SSSd2„†Q_MMÓPU•P(ÄêÕ«µP"ô`V]7ø€C<t7ö¿ljhÝ%_¢nݺÓ4éïï'›Í¢ëz,@¹\Æó¼:0]×›r%MÓ‡Ãtww#„¨Gñš;vŒÑÑQ†‡‡ÙÿúO·Ù@|°ÕôÛ Øä[prN¢\.ÑÙÙÉe—]F*•ªûnUUëF\“š®7ªD‚<›èÕfÜqÝzfê Ad®¹T»`%ÚØïFàǹˆÕýÝ’§ïÞ»‹R©Ì3ÿò4CCC|ý«ßÀ0 ’É$É$±X”p8L(B À¦I"'cš&ápUï+• …‚Åd&ÃØÑ1ŠÅ© Å–Õkà™âñ8 çÍ•ˆ–ŒùÇ ¨ ¦ØÁ®V¿«¨ŠÄ‚´’ÁÁAÒé4ª¦)Ï>RË<ÏÃÕ}€ç <áá÷„ï*£5¥Q:‰EÔ¶8°ƒ]ÀTë Xlc÷“%IWífE©àû> û²p¡Â¢þÅÜsï= ! aÛ6¹\_V='D T­ Яù{EASU ]'Ñ“îÁs=|¿štµæ{ÙÓÍõˆ3dÙÆ¾ $Ù¶#+9ñC\S»ùú’×á—`ú¦D®»êùn­ÑpsŸé»éšƒ£¼¹àMš\û!ÞrÖ6.gÛYÁÕ5?;68ÆØü18Âÿð8_` 1ËUí6îÜÍ,çV’{/$ÛØ”XÜsí‰ólgÙÏ CA讆ù\„Êr¶ðÃß*Í ±‘›™B þ›ýlgGk¨µ:æ 㔸ŽPPQë4UV±†%üœÿà``H³+ÓÍ]l§ˆ‰l[ÀÇã1¾É8/™ÆJÖ¶|à2ŽÃ K™G=ÑP :Ëù—ó"?ãH¡ÏŽü󸉗ɯW[çWØÁ?ó$ðNk½tºú¤(¼Ä8ë&Ö°õ0sWñÏ12+åݧYÃ^á±&x8É>Ï×py+¨“Ψ:]ÆÅáWœ`Ä$ÜDÏFg ·s+þ}¾Ì?âFÛ[,ò|‘/3É^à8´§›Ú9kÍP"G‘ 6—s ZS9ü ]¬£ùcŽó!~=c"OånîâýìDáZŽ£´me]¾Ë·ØÏ¶@uÊV†%\ÉŸðÜG¼¹¤ÑpØI| ý¬b-ÊùeÍ |y¼Ê^¾Í÷(±?(!Z³{FóE,e-ãÃ,å³Ô$#¼Î?òFØ Œ;£3²ó\ì" ô³†«YÏ5,a) :ÏëM91Âñs^bG`¨“¾ÏøøðBgÏ:Þàht—³ŒaVÓË\âĉÓA$(@•°°)`c3Îûx…—9œNãA’vÞ§÷³wR_%” ªÇ‘@Âõ¸R5á`gÀ¿ñIý{þ¿ïùö¿æ_^îú2ì¨IEND®B`‚nemo-3.6.5/data/icons/hicolor_apps_24x24_nemo.png0000664000175000017500000000153213215733314020507 0ustar fabiofabio‰PNG  IHDRàw=øsRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÜ  \ +ßÚIDATHÇÕ•Ïj$UƧ»& Ä'Üù­àVðܺÌÆ½àd#Ì2†$.BnWJÆÅš˜ÉdÒªîý¾ã¢ª«;š ÎÌÆÛ4·«¾¯¾ß¹ç4üßWdfœžžžKzüÐÓéôéööö‡¯å²¿¿?=::ʇ–¤<>>.¯£Ý?“ôx2™TIÍ}7e&™‡‡‡ùo‚ÓéôÙîîî#¢ƒƒƒÜÙÙykÌONN8;;›îíí ‘„$¾üæloæò>úüëhË캱$2>ýø3bq‘³âÒ8=`3ÎÄÍlyÍÍü‚ëÙ%ç¿üúÞ†† ¿]?eADÐûšt"‹L!gŸÜi,¡–)n)µ¥ªc±œE# ÛØ‚&@B1™™Èƒ ‰3IáÕ…ª‚T(ꨵPÕQU˜/nÈÆ3Òã¢?=kT»•ªµX­kƒR;ª:æí-M­u0Idã08±{þ²Ê(,—ñmK-­Ðôû’hË2Ƕ©îÝ—Ý-ýÇ UäB©-²(*¨äÞÜZ]5€š¡SC®Ì7´Ý-¯æ/0†ì‹¯tb¼¾Ú}j_ {^ýžI9Yׯ.Xt3fËë;½c7{H´6Ùׯž-2r]äZ 1™ŒE ‚U+ôuΡî1ÉDZ'‹„ÆvJж[ðhº5-V³6W)r5“Ö˜F³‚×G^ª£bÙÎyÔlQj7$øçÀcÕ&›fk<½„FD˲ i¶èjK­Ý=u)‡QáLè' @ml§mº²¤iJm)¥ãN„\‘º‹éï5¹óB$”1Álñ._>§¬Ä*÷ƒ ƒøC«GËFR½ººšþüüGŠgüþâ|m0ÆÈÿ<±UE—MÛ¶_}ÿÓ/~úóÛ-€‹Ë?Þæþw›¤ßÞ¶ÞP´fÀà/Þý÷M àIEND®B`‚nemo-3.6.5/data/icons/hicolor_apps_32x32_nemo.png0000664000175000017500000000206013215733314020502 0ustar fabiofabio‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÜ "Qþ%t°IDATXÃíWËnd5=åÛâØ $Ä:½JYBšàKXð³âWØe•]Ä6!!„4“Nw__WÕaa_Ûô00 ‰qdÙ¾}»ëÔ9ÇexÝ^·ÿ{“~qqqñµ»¯DòcÁóæËåò«³³³Oÿ.€E¿p÷Õùùù ¿DWWWŸ¼ ]ö߇€å iÁ0 vyyÉCìü{!†.NNN>Ú@ò½ÓÓSüSÈW«Õâe2&)×××>`@Dpssóï˜ðóÇžøàUü ÓAwÌóÒìæŽ òÓ—_\¾»:Þôñg8Z¼ „aÀ  aÀúÃFƒ»ÂÜ`žÚh ÉÔ&¨%$`1iDÒµˆ¤e"¾ûæÇwª œà<þåÙB " ³z%+ÂÝàn°:jMaœšÂ]¡®°y®ùó¤É55“¹!Bˆ DD2un‚ðÜiðÒ ó\s÷ÖÍó3£B5A5M0§7©iÉVJu’2#DPõ# ôˆT df>3P‚ù¡ž0i„yÜu xTS NÈz»„ Á™×…ëúLs¥{leÝuõSER…ªŽ€Óã”F„e6” ‘½:Mô&´ˆÂÌjPóµ.°ÍžHy^Ø‚ 1 ¦»qÚâ( H>åÀ"p¶_þsÏ»g]i0ëw…–ÝPt·fPÒ@zNÅÙVæi;Æ ÂòÉÆê‚<°îop–Á«ž5{oÌäÏ­.»ÇYæùûl:ÝíâË7)EHZ’IÁìæ@6$»õÌŒƒ¶wÛûwæg``jw›ñGQu›_A ÊP¹`ˤ¯vî]ÀbÖÜðú®”» àéö·§ÏÖ¿âè-©ˆ”m¸ïÄ Œlc©¹@y—ù=Þu#_WâXOi„§æÀRÍØeôšî×ù™>`£˜˜£ÝÆ4×l…È|®Ë¡µžÙðÃ@HB/Ò:Aãm; ([ÑSŠ!ïÑFÿ=ª 3 ³'rf­`±—¤<››9V¨¾ÛŤã¸;"YXÏ ÜS Àè˜)ï˜è”¬ûfÉÚ"#Ç”ÔbŒ]öò°Ÿ}•„Ý®àÁÀsÓä®ÎVŠÍ0McÄnŒÈÞ{D@»µq’ù´|p Û_§dpEÀO6e³þyúËw¼—ºB|´oï§·ð6€á¾€5ýOügô;å5²üà_ÁªIEND®B`‚nemo-3.6.5/data/icons/hicolor_apps_32x32_nemo.svg0000664000175000017500000000762613215733314020532 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_actions_32x32_nemo-eject.png0000664000175000017500000000250413215733314022272 0ustar fabiofabio‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs|4k¡tIMEÞ ÐrÑIDATXÃÕWÍKcWÿ½$潘—LÃÄ4[$~Æ7¥ EÝ¥õpçн»še]2¸‘~í„ÆUA Sü(I hÍ HM1cyIš1‰ïÞw»è}iŒ/NªSJx<î½çw~çœ{Îþcþáú&" €…+®%eê«iÐ6555´»»ûE:>Èd2Éç\2™L2Nìíí}9555 ïîjÜ  urròA2™|šË娢(ìüüÜPEa¹\Ž&“ɧ“““´ò3n;€¶ÕÕÕ‡††2ÆdÆXc” A(D"‘ÏÆÇÇ—¤¼0Zk®sƽ‰‰‰·×ÖÖ¾ ©ª*jšÆXCªi4M³vtt¼7==ý~*•Ú?>>Îóüx)voœœ|k³Ù:õú&6ŠÅbª³³óÉZ&L1oÛØØx$Šb!”Òkªi  Âçó€á:J)!E±cccãONk=€û333#@`BUպƋÅ"|>ŠÅ"Àçó¡T*AÓ4Ã=ªª"LÌÌÌŒ¸_Í|ulß477ûëQJ)EWWDQD¹|5¤±X f³¹n8...ø@±–×òòò´$IþztêÆm6Û5ãÐÕÕ…r¹\w¯$Iþåååi®Ú4½^ï°QÜyVW<ש7’¾¾¾Ê£|ðz½Ãdn³@ôxÇãæWz€466ÖÉ“jQ3ÆÐÛÛ (•J/-;þþ~0Æ`pž466ÖÉûI€Åív·Å- Þúƒ†¹àv»[õF¦w3‹(Š.½¾u!„ܹ“]^^Âb±\ù'Š¢«R©T–Rz­äî*”RÂÕ 7•JeõïJ?ÇãéZA@$¹3ˆÚsãñxšÏˆF£§Š¢œN§lÄBSSÓ+ñ>ŸÏ¢Ñèi-€!¤‹ÅŽßÕ«ªŠÑÑÑ;y¿¹¹y|,;"„øôT©‚2€l8ŽB®ÔÿMWk#RÕžAA8ŽÈê­Y („B¡'Ñhô¨¶l»Ý»Ýn]£ÑèQ(z  Ïך‘ßï™››ûÔårÙë•¢×ÚYA„Ê?>ÁdúËGEQ^ÌÎÎ~’H$~¨nFÕüR¦l6K-‹ÔßßÿŽ~ÈmU©ª*VVVB;;;ßø•‡Àp$»`:<<Ìôôô ´´´¼®r[%„`ÿ`qqñ1ŸˆÎ¸³†¨žÛÛÛ1‡Ãáòz½oZ­VÓmŒçóy²¾¾þýÂÂÂcÆX À3=ûoJU—Œ±ÒÞÞÞωD"ÓÞÞîw8ŽFÙ „ Ÿ---}¾¶¶ö57þ€?ŠË.\že¶¶¶~’eùž,Ën“Éd­Ž¯®”R”J%œŸŸvvvÂóóó §§§?rÚŸoäifå3\ €6³ÙüÆððð`wwwÐét:eY– P(òù|þøøø0ïSJŸñ·Às¿óܺõÛPà½ÛÅ'™×øèÞÌK¼¤.øÈåu®ðx³ÿýãô_•?þ‡Ãpûû7IEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-up.png0000664000175000017500000000034213215733314022621 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEá ¾Ø©ŸoIDAT8ËíQ¹À ™€Æ »1™& f¥Ë‘‹áHꨳ­çN~¸Ùäèlê±—RPk5 ±J& U…ˆPD¨ª×þ•ì›XâÑ$çüìfzïˆ1²µf„RrÞ{Û`·¨ÙG~|Ä lU$Ñõ6ÒIEND®B`‚nemo-3.6.5/data/icons/hicolor_status_48x48_progress-70.png0000664000175000017500000000536313215733314022243 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß :.»B €IDAThÞíš{pTÕÇ?÷¹»ÙÝ¬ÉæUÀ$(Tˆ@À÷³b‘©:ŽZk;T‹Óvd¦cý£c­cG[j¶3vœvZ:Õ t¤N¡ŽŽ0("ZEÓtL ’lØ$ûÈ>î=÷ôÜ]v³ $˜vÐé™ùÍîžÜ=ûýžßóüNàÿã³3”±&WlX!i@5PøãSÁhņ’^$Ä饛£æ0åyÖ3€`~H‘ !‰!I"$ÁǼÉïX Ôœ­VÔÿ Ø€d ðf«ø5]¼Æ¹¨ôs“€%NžŒBy¬£ØÆe̼çé’O2À0*µ\΋¼Êw¹ žuäõwùIýàåÃ/oâ|*if:—1Ÿ&f¢¡ù Ðf¹‡€è'Å0•C>Çtnçq¶ñqŽ!K¤ÉI,žepÞ¹¤ ª¸šgx…#XEÉ1$'Hp?7eçrºðq÷q˜8]È"9Šä=,dÁdò…2¡g¢Ì}v,Q]Ñ&(*‹¸†½ôÒ‰,’£HÞå 7ñ)g¶äù—wl_¯ëꓺ¦µt )%Ž#‘Ò!›µp1òÙqpä©WÇqŽÄ‘ŽÍdüÆæoîây^ÅO hAÁϸ›'ù ü$ÔÍ›775ÏŸ½¿©q®¯ººÚÐ4 )%Š¢€wp‡L&C6›EJ‰”ÇC6›E‚L&C?Š¢ˆŽÛ‡‡¢ñ+7¾¹±ŽMlÇ(Hh çC°èr³È¤ó€háÚÐ=ÕáZ½¦¦Æèéé!•J‘ÍfÉd2d2,˲¬¢9MÓP…¾¾>"‘‘H$ÿÞ²,„šÏS¦¢Êµ¼È+üÇŠò„ TÐÌSÜÅÚQ'^<>ÓûõúúƲh4JyyùÈ"ªŠªª8ŽC:&•J1<<ŒMÓH$Äb1Ç9µ ¢  FðÔÕÖù¥wßxã^6ñ$pܽv€aqçè°ª…µ3˜Ï£>|Ç[VðÐ4 ÇqBÍfI&“$“IR©étÇq°,kÄÖei.BPSSƒã8A|¿zÑ‹n¥Ÿ/±¾ˆ€T1×%`ŒEÀ:ƒôpUxmË‚o:FeY ÇQ]×1 Ã0ò E)Ÿó‰t:ó^Üâ÷šÆý€Êo؆…(ªŸtBlâZÀ7Rõúë¯/÷ùÊ–×ÔÔ)±XŒÁÁA’É$>ŸÓ4óŽ™3ŸÏGEEáp˜p8L0̃/4£d2™'ÙØÐˆa˜‹V¯^ÝÈqÒá¹"60Ÿå…u’:!"ë(»ôò¥·µ¶¶êRJz{{‰Çãx<lÛ΋Û¶éìì$‹‰D8qâ}}}œ‘倎6Ã0ðù|x½^E!‘H ¥Ä4M4M#›ÍÒÔÔD*•ºtÁâUï9îFê'¥À¸†5kÖÜp~}c@Ó4ò KQ„¤ÓiTUÅï÷0MÃ0ò€rD,Ë"“ÉN§&‰ „À0Œ¼65MCUU<‹/Öâ;Ùå(êƒ1J =¤¸Ž/  ¢æiª,b)sx¿óëHS+ߣлØIÓ=¶(€ƒÍSFßyò²…¥,e?ýø‹àIàGxˆÇ±øÐí“r&i,²¼O7Wp9fA»ÛèÌávVáã‹ì£­xW&<¶PÆ}<Ôâå"*YM9_e•¾qZ ù%¿â ¶£#Ïdï*ê¹’y€:êÇ}2”»=£@¿Âšbn¯€ï¡‹'xš.vGÎt?0Ñxêñ±ï°žE,C™Ü]ÖÒ—Í;ìe3Ï’â€ÛBŒOE':7¼Àt`&sYÆ×ø s¹x ’š¤ƒüžig/Ðé:lzªZé£oXÎs­¾‘¥\ŵ\Íæ¤bR+Å ƒv^ãuÞb—ë¨}®½ÛSy0öíÊÈ­{{5:%̧•ÅÔQK€Êñ¹ ¨qÄH ‡^ö±Ÿ·ùèú·H³¦äß&1L×eƒ.¡Û=ö¹âÍç•N `Èwç²g `*‹2Ã%dº¦f‹¹knÛ›=›ÝþLŽÿ,!F‚ñIEND®B`‚nemo-3.6.5/data/icons/hicolor_emblems_24x24_emblem-note.png0000664000175000017500000000162113215733314022435 0ustar fabiofabio‰PNG  IHDRàw=øbKGDùC» pHYs  ÒÝ~ütIMEÓ 72ï1M>tEXtCommentCreated with The GIMP (c) 2003 Jakub 'jimmac' Steiner'3ïXÔIDATxÚÝ–ÉkQ‡¿ª×Ét›™ Îh4<˜‹"‚ ®AÁ«… 'EðˆâöOhDTTTT$.7/^¼¸ƒA0*¸o‰Cœ%3Óýƒ@ðëRdT±˜ªEQYƒˆeþ²ƒä­ w/A×å¯ôôõsêÈfRÉDuyÀS>9ä§ð’oxõ|{¯ÐÓ×Ïé£[˜•M2·%#J@ßÔo²*Dépµ ÎX°¼›Mëg³°ó §n!›i¢­µ×k/§jž3­b-åŠÀÕ›Cœ8ÔICƒ!›™A[kšl¦‰JL9·^À€úÑêÄl0Vò¹~aÃÃ9Œ1¤ÓsZRd3Mx®C¾Pžž€Z‰‹ j5$Ùl’™Í.©”G²ÉÅu°Â¥2‡–ö­ø•"JP {R¹4LcÊ'‘|ž›¦±ÑÁÄíCOs¿¸uó0Ÿ¿ S™hº{#(ЍDÕ/µ}ùg­³]i®‚G^uŽFÇØ*(#X+|-þ³ÎbÀ›*˜ù?ÅêZš"†Æ©ªû7GU³ý?þ$~R²ûšÕ®´IEND®B`‚nemo-3.6.5/data/icons/hicolor_apps_16x16_nemo.svg0000664000175000017500000000535513215733314020533 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_status_48x48_progress-0.png0000664000175000017500000000321313215733314022144 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß4§Ì˜ÛIDAThÞí™ÏoiÆ?ó¾3ã{Ë™Úi`·qâJ”V ›¶„î ¶«î¥¤Jˆ½,¨°´h9TB”h…@@½ò€àÐ B⌊lô†ZQ)-Í&®œÄ?âñ̼ïËÁöÔi›ÓBAÈôjdëÕèy¾¿ßw`ŠÿXSL1ÅÓÊ2Å/)î-~@~¸÷YK —œp‰çÍ7ëyöÿþ¿»jÛâg¶´K<ý c ZŒÑÄq‚Öjð[k´yüÔZc´AÆýøû_÷?ÌR€¸qãFýÄ©ãÖkŸò+•Š#¥ÄƒeYcä5Zkúý>qcŒÁC.—#Žc”R(¥è÷ûXÿp}h<3‰ÄÇzà·¤³åÙo/-—Íf“;wîP*•2«§iš-¥aòðáC666h44›MÚí6õz}O™³­­-šÍ&§NžÒ–—‡9idüIˆwÞ~gqf¦tÜu]Õj•v»½‡ôHȨòT*fgg)—ËYµ'=î!½^/óØ+Ÿ|eæâÅ‹_:ˆ×Ä—Þ_ùÜŠlµZÄqL†Ø¶Í¨‰ yRÔ(„FkÜúZk …J)êõ:B:çÎ³çææ®À+Ïu•Vê«KKuÖÖÖPJaŒÁ¶m’$¡P(à8išÒï÷³F5²ô8YÇqð}Ïó°,‹N§ƒ1×u‘RÇ1õz^¯÷Æ™3gÂÕÕÕõI’xßD¹|ùò[¯«RJ¶¶¶²†eYJ)¢(BA¡P \×ÅqœŒÐHH’$ôû}¢(bww—F£R Çq2oJ)BËå8{ö¬ ‚àýÕÕÕë“Ø·ù¾÷£“Ÿ>)nÞ¼‰ëºÔj5šÍ&¶mgd¢(H)3b¶m¤”xžÇ‘#GPJe]|´üž”Ò7ÆX·þxkÏè°Æw|öyÖ`÷ì"[Íš¿üwœÈ^æ€ à½ÈùuB˜a“ÚÖ»/* ø€;<€óŒDô€`?qsð2nḛ̈°¤Ãõ‚W(÷½¬«Fó„7¦÷¡SL1ýF1Åÿì© ö‡35Áÿü ðuZÃàVIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_scalable_view-compact-symbolic.svg0000664000175000017500000000041613215733314025461 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-left-free.png0000664000175000017500000000033713215733314024052 0ustar fabiofabio‰PNG  IHDRóÿabKGDúœ³Î pHYs  šœtIMEá!üBolIDAT8ËÝ’± €0 _lAåd…ì‘‘XÒ®’!²ÂS„“ ¾´t'Ù~àß! ’h­d¬ª!Ð%8Ã1Æåµ`ƒÍl‡SJp Ž0< ¦«aÎy¾|)"â_áNÒýÆZ+D„nÁp‘¾“D2u}˜aÑcIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-up-free.png0000664000175000017500000000036213215733314023542 0ustar fabiofabio‰PNG  IHDRóÿabKGDúœ³Î pHYs  šœtIMEá"6o´£IDAT8ËíQË Ã }tÄ–G`@zhD2˜±Áë)UÚ’(é9ïf¿¥gà‚Û"H~ Ý\zÛ3×ZÑZ›bï2I˜D„"B3{ïO™U5©j:òm^öKH)å·›õ0Æ@Œ‘î!„çšë½'œ³óÞÏŽµõ‘ â4ßU^ ÉtIEND®B`‚nemo-3.6.5/data/icons/hicolor_status_48x48_progress-20.png0000664000175000017500000000403513215733314022231 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß;a)"̪IDAThÞí™ml[gÇÏ}óÛMLêÄiÖ®IêJ ­F›¦„nëÔ¡P D¥iãÃ@e¥E&¤Jˆò ´ К /û4ñĵ£i¨Û ýP†ZµZš¦.ŽÛñõ½÷y>Ävì$mÒfŠ:È‘Žl___ýÿÏsÎÿœçÖíÇÄR‡Žià h€ý¡`4t|H3‰fŠ“\eŒ \à÷¼Ìa`3œMÍ4š4%4yŠ\æm~Å }§»b¬  „@ø@$H±/ñKFù?âó@;`ÝôWu2‚vp”aÞã °ˆÞ]t•ÄͼÌbÐÉ'y•7ù&ŸZîX9|¯W›±hŒáìðÏèc°“ ½˜˜KþÀLf9à žä ·Z ¤Y@›xŒïs†÷(0Ž^äWÑü‡€_pøÈÝ*R6í|†Ÿòï0†nòq4yŠÏñ»¹\Äx”op£è&Có>×ØÍ®Û©bE÷|‡xõޥܨº¹B7àAÞa’+è&CówÞª>q'`Ýö¯³,ãyË´\a,~„Ö¥4Z+|?@)9÷Y)”žUJ¡•FiúÿÛ_=õµ?ó2o’Àmz ƒä'<Áó¼”VCÀ8uêT¦oç¶w3=Ûc¶išh­B4€W(¥¨T*ø¾Ö­5‘Hß÷‘R"¥¤R©pãÆ „òâåÍNç Ÿ:ñö‰<ËëØ MþÉ.†€Ñj¹í: 3Õ™|²#Õi¥ÓiûÚµk”Ëe|ß§R©P©T‚€ 𮙦‰‚ëׯ“ÍfÉf³õ÷A ¥4c‘¸¡ð*oðžkª!ÐF?æ м;Æm€7€H̉~eË–žx.—£µµuî!†a(¥ðŸÇ¶m\×E”² ‹á8B‚  \.“Ïç›È!(•Ju’=Ý=ض3pèСžáááËC/ 5µg_<[™…ŒÆÌ^dG‰ßßù‰G-­5“““xžGWWaÖW°6ccctuu¡µFJ‰R ß÷¹té½½½u¢52B …AðÐC›ÿŸø:pòì‹g[ôA Œ$³à mŽoíÝfær9.^¼H2™¬Ëa†u—R’J¥¸zõ*“““d³Yr¹…BL&Ó$³a655E.—c玆i™‡«q.–ë¤WBÀxü‘Ç{[[“ÛÇ!›Í’N§) M kDjÊÓÑÑÁ† hkk««M#èÆ0 ƒr¹\߱͛6·™L†r¹|ÿÀÀ@jdddb¹þœ[>üð½[z\Ó4™ššª¬šòxž‡a$ \×ÅqlÛ®ª ‚€J¥‚çyÌÎÎ’Íf‘RbÛv}7MÓÄ0 "‘{÷î5]×}zddääJÜTb±è÷v|t‡qúôiÇ¡§§‡\.‡eYu°žç†aH ˜eYM½’išD£QÚÛÛ‘RÖ«xÍÇÇǹrå ƒƒƒüãüùcÀêLOOw{^™¶¶6öìÙC*•ªk·a!š¼뉪Ѡç½ÚŠûAPïLC)¡Z™k’Z˜™I®äˆwKžW‰¿õÎ9Êeßüö×ô÷÷óƒç~ˆmÛ$“IZ“I‰8Ñh”H$‚Yg;-®K$Åq¢Ñ¹¸¯T*Ì̸žÍ2:6J©4[m±õÜkU™\×¥çžr¥S‰›0 CÄc‰j[ hM__étÜ«3ZÏOKjÅ, CB9wCI(C‚ê5©T5d̦֢±J'âqâñ¸XéÜÔÂ0œUJ9Ý[ºéîôölåè±£ !‰P,™ššBé9¥ ¥¬‚ܨjz/¦a`[-n‚Žta¢ÔÜ ha¿7u㺹jÙlö…¿ýõÝo™¦ÓZ‹s9×Ô:ÜtÔ¸½ÏRÝÒ"ï‹ÜµÜKÄù÷^ ³:]ŽVÃîvOr·;ó<0\Z-–jûêTà¬Ý0E^-«>9˜Ÿ:¬Å0RU“áêG(ó÷­øÆÎ@ßÉXq­@®Ûº­ÛzNþšµ¾·úÇfÝÖmíí¿|¢@åt?kIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-bullet.png0000664000175000017500000000027713215733314022506 0ustar fabiofabio‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEá  òq¬LIDAT8Ëc`4l ­  ¸…•Zþ£áfR xŒÅ€‡Ø2á0à?‘b8 XD¤NÀ õóC(n$5G ׳ x3IEND®B`‚nemo-3.6.5/data/icons/hicolor_status_48x48_progress-40.png0000664000175000017500000000443113215733314022233 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß%° Ll¦IDAThÞí™lœuÇ_Ï÷ùqw½»ÖîÚëd£ívæ&”ŽYDåWÀÌ%–ÀÍd 3¢F¢Æ?4€(ÄIjB$ƈp3N#„ QèdY²ºvtmo»v÷ó¹çy¾ß¯ô¹Û]¯ÛÚáf1û$ŸÜõéÓ§ï÷÷óûóÀyùÿc®‹¶mÐÀ@7Ð Äû}Áhö š 4S˜`ŒQö±ßñ$›å@à¼h¦ÑG“GSB3M‘ƒ¼ÊÏØ¤ÏÔ*âœ0‘@ø€TIœë¹™3Ây„O]€µ8 èYªêd ’¬f+Ïò»¸’‹èâ" C'Ó*PFÐÃU<Ë|…OÉ3γ~¯ßkÄ¢1žÍ>»ƒU,ãJÖa&æœ`&evq/wò4{¯þ›bd·òvñ£[t Í1|~Ä6à‹5IÙtñIãá3ŠnÒÃhŽPä>´-ærã¾È> Œ ›tÍ!ƹŒ…Ô c^÷|ƒ¶ðÞ¹T„jÎS—s5¯1Á0ºIGÑüWÂÂgœ Ø–ûÿÜî»-KIÌ‹ÈVÚ®¸êc· YZk&&&( D"‚ ¨«”’ &ŸÏ“Íf9rä“““;vŒýû÷×-SÓ‘B¡€ïû\{íõæ’%Kî þÊ®–ÆÏaiX™Å| +Vö}iè£Cf>ŸÇóÂÍtË®?Ì7yžŸ‡SÙü,L‡»³ñ°€pV laÜDˆ4Dç;¼Éó¼âa!*aÔ‹†­ÃÙ‘ûèe¿`“xx\3áðSžÅ… çpöÀÿ^Öó*G‰658xƒ?ów^²³3¦5}¨>ë»É§XÏ¥ü‰q"³þó8‡xˆÀX˜>9s¿H½„=Œ"šÀ˜æA¾G™·€É¹° þÇ2ðÈ€æßˆzmUõwóÙŒ†qxFkÄsBbï‡ö6÷;;xœWØ ˜y¥ <2 ù5š¢—/kÔb9äù“ˆñY`Í|ßÐ,FÉ,äÙ™¼a9/'}cs^Î˹—ÿ«¿!ýÛõIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_scalable_sidebar-hide-symbolic.svg0000664000175000017500000000066113215733314025405 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_status_48x48_progress-80.png0000664000175000017500000000551613215733314022244 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß gbõ* ÛIDAThÞíš{ŒTÕÇ?÷93;3;îξ  euU\Á߯V-’ÚJcÔZÛXߘÖhh¬4FѶôi›Ø˜6­MÕH#ÝJ4bP| [¬ÈËîÌ,óž{ï¹§ÌñÎÌ¢€ÛFMOòË,wÏ\¾ßó{ÿÎÂÿ×çg)“=\ºb©¦í@ ŒÏ£¥+–JƤÈ0Æ»ØÆ6þÆ£\ Ìb€ùY ™@rIIÉYÞçE~ϵ@Ç‘jEýŸ0€Ø€A˜8K¸„ß0̳<ÀE@ : È:q«d¢Ëõ<É»¬áTæÁOé‘8˜”€<*œÆ<Ã-œ D8rÔý^~R?Ü6¸Š£i¥—éœJ=ÌFC›ô  ‘g ·q ÉOŠa*—|é\ƽ¬á]2ìF6È’ýØ<Ì à¨Ok2hã,~Îvb³ Y#»‘ì%ËÍ\4}šÓEˆK¹‘mdFÖÈ.$;åDN¾PiÏ4y{'ÕíEe!g³™1v kd’×yÁK|Ê‘€mØ?¸ní º®Þ¯kzDQ_!¥Äu%RºX–ëŠò¿]W~øéº.Ò•¸Òu¬’uûwVw#ò a"5/4üŒ«¸Ÿ¿¹OB@]½zuOoßÜW{ºç‡ÚÛÛ MÓR¢(м‹ëº”J%,ËBJ‰”’@ €eY!BP*•Ø·oŠ¢ˆíïå$3gÜöâm]¬b-†/¡)@†wXÀR`ØË"y`åÊ•r銥råÊ•ò §¯Å;c×´Ç;õŽŽctt”B¡€eY”J%J¥¶mcÛvÍ3MÓP…ññq‰‰D¢ú³mÛ!´P IE•×òø;÷Ôä h¡—¹jµÓÈ6\½­ù­Ô©Øu d¿=sfwS2™¤¹¹¹üUEUU\×¥X,R(Èçó!Ð4l6K:ÆuÝOCQˆF£D"e<]]a)ÄUçŸ~Uü„,Y\ï¬] ÂB®¨«jMX¬€u`pÅ ƒ+«D*{ï¾ûγÁ¦æH8‚¦i¸®‹˲Èårär9 …Åb×u±m»lë²Q©B:::p]—H$J(V?ñø¯±,OsC hc¾GÀ˜Œ@èØ· «Ô+ƒ7 2xã ð4 ÇÛâ×ö/è‹E„ضÍÄÄ™LEQÐuÃ00 £ ZQ”ðŸ(‹àÄúÃAÓ¸Pù-k°5õ“NŒUœ„&#¥ pꊮ!þÍíwÞyç5‡BMttt)étš‰‰ r¹¡PÓ4«ŽY1“P(DKK ñxœxÇimi]1gö\-™L²}ûvb±XõÔëIÄãqFFF#‘HL&Éd2ôôôÔ„Y¿™¥R)’É$}Çö©š®] ¼ÏÖÂ5ð$°—ÜÁ½Ø¼ãÍIù8El,Þf„Ó9 Ó7îv€,:ó¸ŒKñ^æÉÚS9äõMÜÈ]ôð;vc4¼%Ãwrãlö@c¹©}ÄD¿@Š ²œÌ)(hÕ3ÀZ9™ÜÊWÙÃE¼wÈD£‰ë¸’/ò< g³¥¡•µ±ø±…užédŒx0Sù:7q#‘I&ņwAÃ%ÍIò$EޢĮ¯UBè$Èñ´²œf¾ÉTÆý±®Þù¿æž¶×GžÃ½hf1“3¸[ébæAwFfof`øô+<  íåуMüGæ>b˜çw?p¨ñ< Ì$ĉ|ŸXÈ”ûË:„ôåð›YÍÃØâ3S1‰®¬ 0˜Í|–ð-¾Á|N˜‚¤&âMþÀ ±Øá9lqªFéõ7,GyVßÍbÎäÎbó‰ÒrXoÊb;C<Ës¼ÄFÏQÇ={w¦ò.`òÛ•ò­{—w5:“éc€EtÑI„š y¨²¤É’e”1^æU^a+0ìF½"Íž’?8Œez.õżéqÈ“`5¯”]¸dàŒ÷Ì:RSY”!Ó35ÃW,V®¹¬u$§ý¹\ÿšÙí·ÛÝIEND®B`‚nemo-3.6.5/data/icons/hicolor_status_48x48_progress-90.png0000664000175000017500000000572213215733314022244 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEßË׺& _IDAThÞí™}Œå}Ç?3³3û~뻽ۻخ}öal°Á>lÎ&€Á1Vi!B„д%Lš"”¤R•‡FD´”T$B‰RP ±#Š”4v ÆjÞ®—b|¶Ï··çÝõÎîíîÌ<óô]Ïï0ªŠòH?ÍÞÜÌ3ßïóüÞøãøð eº›·l”À\ è¢€þÿ‚ÑÆ-%i$9LÒŒq˜àg<έÀ| ÿØô䑜@R@RB’§È;¼È¹ HÍvWÔY°gô´ï- (‚(IÖq=ßc”_ñM®ºÀE äéó̇d‹¸ 2 qÎåžæm¶óQ–¡3M ÎXÿÜß=71+Ò#q*©S¨ôr1OñK¾Àz ~¦Â]\Ã1ŠAr¸Eá¼oOÖÍe|‡ç9„Ý6ÿ$Ç(rב™Nn°Š•bœÃHF[ä- |ž'ÏKs#wr³í;µ…g+g/`>¯ò‡‘l‘}Lð×|‡¯ñžNTO´Ó•Õ\Î^Òmß;ŒäU^ðŸ2N¶«Î½¬'ÅVËŠ˜<ÆO¶ß¸m8bÓ«1Em·1)%®+‘ÒŲl\WÔþv]\yòêº.Ò•¸Òu¬ªõ¥¿ÚòÙM<Î/‰kŠ8)†¸—õ<ÀOÒ{å/*°€×xŽ8ç ›B—Ã?óäÏþâ7?¾bÃîþ¥ážž]Ó4¤”(Šâïâº.Õj˲R"¥$ bYB„T«U&''QEŒ¼3Ý“ì ¤R)}||œr¹ŒeYT«UªÕ*¶mcÛvÓ=MÓP…‰‰ 2™ ™L¦ñÛ¶m„Z8QQåm<Åóüœ¯7}Û:Yƃ\¾Ý™†ÀVs3S(¸OÈcòÏòmÆÃFè/,èd³Y:::j“¨*ªªâº.•J…r¹ÌÔÔB4M£X,R(p]÷ä¢* ñxœX¬†§¯·/*…øÌUW]b+ߢH± à «¹¹Õ­ª- ÚºYÚô¢ ü† ò½ûîûêåÁP¤#¡i®ë"„À²,J¥¥R‰r¹L¥RÀu]lÛ®éºlBR©®ë‹Å Ç¢êy«Îû3&)ò ›Ûpt³Ô# OG ÌV6 Ñ’³Þa?SJv'o\9ªT*!°m›|>iš(ŠB @×ut]o€V¥ |Ý&*•JÝXuþ`4dèw*ÿÊvlD– ¶²OG Îr®ÆiIº†ùbüøÊ+¯ì‡#W§R}J¡P ŸÏS*•‡Ã†Ñ0̺š„Ãa:;;I&“$“Iâñx¼_J¥RƒdÿÂ~tÝX}à 7ôs” ‡ø~XÎÕþÃõç>Ó%vÓ K90ÿM®}„7€œ‡µ€ äÙÁNV²¾îgG—2:oñß|›¿g ñ~{5° v;7³‚ëIøk/$;Ø äý­ÍÖš8ÏNv±‰ý,cРݵ°1³PYÁV¾ÿ¸A6qS@ÐGàmö³“]ÆÐ¦iÚ*ŒSæ >Ž‚ŠÚ ©²šµ,á×ü‚·Í T&NqÖS$Ïwù^`0ÒêyfB@º€…,àR¾ÄÝô±à”OƯg ûöWx@Ë@Á‹£§jÎ3Ê7xˆQv‡<½—³%p²c ³ŠÏ³™Õ¬C™ÙYÖi„/‡ß²—âQÊì÷Zˆæ¬ÎvOuF̱”uüŸd)矠&æu~ÄS ³8èleÖ‡Óà„eާõý¬e=¸Œ%,%NçŒf2É1Â0¿â×¼Ä.ÏP'<}?íÓٮžîº÷yG£s¹å ±†>z‰#Fa¯UƤH"EÆI³Wx™·€1`÷’4{¦@ÞïöžÉÆ=B ¯{ö$Ôˆ+5.Eà„ØôîY³p&“2Ý#dxª¦û’Åú1·ãµf³ÚÊñ¿+86òA£ÊIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_scalable_expand-menu-hover-symbolic.svg0000664000175000017500000000422313215733314026425 0ustar fabiofabio image/svg+xml Gnome Symbolic Icon Theme Gnome Symbolic Icon Theme nemo-3.6.5/data/icons/hicolor_status_48x48_progress-30.png0000664000175000017500000000414113215733314022230 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß:€‹áîIDAThÞí™kˆ\gÇç=—9sÛífvgc“6›L 1¡¦›Ä5mQÛ¦4²•Bë‡*1µ• ¢~RšªT¤DA´ ¿(¶¡)Æ P*´$-Z/ñR"]²I7Ùdfw®gÎ9ïûúagNfv6Én"!Õ}àafÏž=üÿç}.ÿçYX²ÿ3æ»8ºT·@ì÷£Ñý£šI4EÊL2ÁÞæm~ÃóìV½€ó~  ™F3ƒ¦„¦Šfš ïò?çQ {­§"n „@ø@$ɰ]ü”q~Ï÷ù$ÐX7'=ÇUDÆ Íãïp˜»Y¸7Ý$q9o5ƒÜ˼ÊWø¾æÊ1ç÷úzó îÆ9”?ôcÖ³‚»ÙHŽÕ˜˜óþ ˜Ô8Ì“ìã p½þ›f`ñóe΢»|ÍE~Â~à–›µHÙôóq~Ä+œ&à ºÃÏ¢9G…'ø¸™ÛEœ=|‰·)3Žîð3hNsž;Ù´˜~a,èžo’hÞ;Ÿ‹¦› tÁîåM&Cwø4æx³ñ×¶ëþ£¿;ò¸e‰g,ÓJ¢ûZk”Òh­ðý¥äìÏJ¡ô¥O¥Zi”V¡ßð¿þùƒ_xçy•$©Ž:H~È#<ÃË@õzˆƒæÖo\ûVnh]|``À6M­5†a´W(¥h4ø¾Ö­5±X ß÷‘R"¥¤Ñhpá çÞ=Y›)”?úäO.çG°Ûš”ù›Æ›]dÑ}ÀÌÌ`ï¾Ì •ÍfíóçÏS¯×ñ}ŸF£A£Ñ ‚ è¸fš&†a055E>Ÿ'ŸÏG߃ @JiÆc Ðò"¯ð[žîè!ÐÇz~À§¡ótÄ"À wÜÏÝ~ûP¢P(ÐÓÓ3û!B ”Âó<êõ:µZ )%¦iR©T(•J(¥.=Ð0H§Ó¤R³x–.Oj)yðÁ]ð,*¨æ»V@ ƒ-|vnYeí*áóÔSߺ7æ&zRɦi¢”BJ‰ïûT«UªÕ*õzÏóPJÁl¬ëî^$¥$›Í¢”"•JO%ÅwÞñ.Pá×<ÞA@ý¬k°ç#\å¬LæÑáMîçyH) ‚€ééiÊå2†a`Y¶mcÛvÚ0Œ.ð­œð<¯•Üù¡á¤ëØO‚ç8L€ìÐO½à> ¾˜2±}ûöžx<±#›]n”J%¦§§©V«Äãqlj³&ñxœ¾¾>2™ ™L†t:o£jµ‘Z5„m;[vïÞ=Ä{xœægB`#;Úu’X‘ÇHÜuÏGöŒŒŒXZk&'')—ËÄb1Â0Œ\JI†ŒQ*•Èçóœ;wŽ©©).^¼ÈÉ“'£“iy‹H¹\&î¿ÿsÙ²e_ þÄá.áç°¼Ù™ÅB ¼@¸¬oÙþ5«×š…BS§NÑÛÛ½õ¹$2™ LNN’Ïç) ”Ëer¹\G™m³b±H¡P`ã†Â´Ì½€Í»ü³K†[Ñ'h®D@<¼ãáÕ==½kÇ!ŸÏ“Íf)—ËQylï¦i200m…V;èöBP¯×ÑZ#¥d劕=;wî¼ïÈ?Ž¼Þ¥Cô´XÈ ˆÕkV}yäÃ#f©TÂ÷}2™ –eÑjbsC¨õ½=/æ#¢”"™L"¥$—Ë!„ R©°mÛ6kppðü¿+„b¤ç;+udKIùК59ÆÇÇ‘R¢µÆ²,‚ ™LbÛ6aF¬tn¸Ø¶M<Çu] àR© µÆqLÓÄ÷}r¹õzý®M[7õŸP'º§»Yýd´¸ìÀ°wïÞn»}(eš&Åb1jX†a ¥Äó<„$“IR©Žã`Ûv¨E$žçQ«ÕÈçóH)±m;:MÓ4B‹Åغu«KǾÚE D¹mH¨Ëjݸûí Ü ^zé%ÇahhˆB¡€eYXÏóÃ0ÒfYV‡V2M×uéïïGJuñ–Ÿ={–±±1FFFøëßNìëzµ%¦›Ó´Z™™™UžW§¯¯Í›7“Éd¢Ú-„ˆ’¸å­XoOT}IèµÞ¸‘2 ¥„fgn•ÔJ©œî"PY$Ïk$Ž¿yŒzÝã—¿úÃÃÃ|÷éïaÛ6½½½ôôö’L&p]—X,†Ùg;éTŠ˜ëâ8®;÷FƒR©ÌT>Ïø™qªÕZSbëÙÏfeJ¥R¬ºuP#çäçïµW# „0ñdSZ³~ýz²Ù,€FëKeº¥Â0$”³s@JB4¯I¥š!cvH‹ö.L$H$¢«¼Æ1 ÖÂ|Õy`×®]Å-[7ßâº.k×ä¨Öj !‹Q©T(‹(=[iB)› @˜³U«Þ7? C‚  Þh!JÍ.Šæê½â…) =Žî9 3ø»€¿%²ËçóÏþño}Í4͸ÖÚ8öú±(!¯¸ jKÜví3Ÿ°›Ï||£p¾ðÜñãÇeTËŽr´ØÜí-x"» ln—ÝfØ-v’[ì̦sÀ¿¯w€O7å«Ól ܺm‹:s½¬hspiëp#–‘ª) Ãë_¡\ºïF€oWúZÖŠ7 ä’-Ù’-åäÿ¡YK¯àJÿ±Y²%»ñöD[‚P —PíIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-right-free.png0000664000175000017500000000032513215733314024232 0ustar fabiofabio‰PNG  IHDRóÿabKGDúœ³Î pHYs  šœtIMEá" Ùy™žbIDAT8ËÝÒ± €0 DÑ‹D^!û±d\%Cd„|Ò@C,¸þžlËÒ?¨÷.@@ 03J)1äö”Ê9Ç‘ Hº!×lO§cÄW¨µ®¯0Ë­µØÍ,V~呾•ƒlw}³IEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-none.png0000664000175000017500000000035413215733314022152 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEá & $O‘yIDAT8Ëí‘1Ä ×R^Aewü‡òZÓPð‰M‰‹.„;)m¦Ã«YYxyŒœ$ÿ“ä£mç ÷Ž”ZkS1„€œó}3I¸;Ìì’™j­ë-IŽUsU…»|ÉwÉ/YîJ ”AŒñr¼eÁìGfòËÁ image/svg+xml Gnome Symbolic Icon Theme Gnome Symbolic Icon Theme nemo-3.6.5/data/icons/hicolor_actions_scalable_expand-menu-symbolic.svg0000664000175000017500000000410313215733314025301 0ustar fabiofabio image/svg+xml Gnome Symbolic Icon Theme Gnome Symbolic Icon Theme nemo-3.6.5/data/icons/hicolor_status_48x48_progress-50.png0000664000175000017500000000466213215733314022242 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIME߯\Ç ?IDAThÞ홌eÇ?óÎÌþ¾;ïön¯Òrwí‘P[¡Ô³@P¦6ÁÐ šJ)¤ØIˆM4€ FIK415Ö„ªB@‹… E)HåÒ¤GïÊõî¶Ý»ÛÙ³3óÎë;»Ý½½öîZ ñIžìîììì÷û>?ßç…ÿËGG´™.®Ý¼Vg@+Ì£µ›×*ÆPL`1ÆÃìg?æ16K€ ôa  ˜D1…"‹"b’y™ß°HªUÄûÂDàP$q’¬á:~Á/ð¾´Æ™I@MS¿JF£‰lâIÞf—p.9³¨€Ä‰´tr)Oð<ßä3@Ó)gŽi߫Ӄh$Ê“é'f9‹¹„•ô²}Æè€NÜÉ-<dNÃ{)ðqs?bocqÕ #(Žáò(›©IʤÏòÏq—aTFq„wðy v&—‹(×s;û±BÕé0ŠCŒr«æS/´9Ýó]bÁ½3©TŸ£ .ârö0Æ ªN‡Qü‹—‚§ ؆ûÿòÌÎÛ C<`èFBPJáû ¥|ÇÅ÷eù³ïã«ã¯¾ï£|…¯|Ï)9ßþÚÖ¯ïâ1ž'N¢î!$Û¸™ø?bëÖ­½ËWž³··çÜhGG‡©ë:J)4M«ïãû>¥R ÇqPJ¡”"ã8RJ¤””J%Ž=ЦiòÀÁÂTƺìΗï\Ä=ìĬ)h`ñ_V± ªÈ¼ë€èÉΖ[:’F*•2GGG)‹8ŽC©T¢T*áº.®ëÖ]ÓuMÓ'N“N§«ï]×EJ©GÃ1Py‚çø+÷ÖÕ he9?åZ¨·Ž˜x„£¡ÈW»ºzb™L†æææòC„@ïûضM±X¤P( ¥D×ur¹Ùlß÷?PÓhjj"‘(ãYÔ¹(®¤¼ùꫯŽp’#‡¬µиˆ›¦§UQ—ÖfqŸ»ïþÁåáH¬9O ë:¾ï#¥Äqòù<ù|žb±ˆmÛø¾ëºe_WµHJI*•Â÷}‰&¢‰¸8ï‚ó¾ÈQr<Ímu| sæLÜY,`$Û“ûVõElÛFJ‰ëºLNNbYš¦a¦ibšf´¦i à+1aÛv%¸àü¾x$dÞ~É\d]ÿdÐÂ=|ˆÎÇ…4@\yå•ÍÑhìšTj‘–Íf™œœ$ŸÏF …BÕÀ¬¸I4¥µµ•d2I2™¤©©© ¾Öòù|•dOw¦ºhýúõ=¼‹Í!~UGÀVrMmŸ$æDd±‹/ýôõýýý†Rб±1,Ë"ãy^U¥”xžÇàà Ùl–t:Í‘#GçØ±c T-SÑ ˲p]—+®¸Jokk»Ðx _ˆEAes% ñ8^[kÛæeKÏÑ3™  ¥¥¥ºêÓI$“IFFF#N“Éd°,‹ÞÞÞº4[ëfd2V®X)tCߘä­†6ܨîâ5›‡“7^sãÒææ–sB¡étšT*…eYÕôX[t]§£££ ¶âZµ k- „ X,¢”BJÉ’ÅKš×­[÷¹ÿÙùbC£¹–À\, –.ëÞÒÿ©~=›Íâ8ÉdÃ0¨±é.Ty_3ñ}Ÿx<Ž”’ÞÞ^„är9Ö¬Yctvv~‡7q\(LÓL8YE6|)oX¶¬—¡¡!¤”(¥0 ×u‰Ç㘦‰çyÕBV:Ý]LÓ$‰DÐ4\.‡RŠP(„®ë8ŽCoo/ÅbñâU«Wµïó÷5îîÊý“VKà„† 6\uvWOB×u&&&ªKÓ4¤”ض‚x|˜ÁÁAúûûyý}·4,m–É`7íωÀÔÔT·mimmå /$™LVs·¢Ä­øzm *¨ã^eÅ×­v¦ž”TæJJÍe­¦¹y°íRì¥=»)mþðÇíôõõqß½÷cš&---4·´LjD"„Ãaôœ Ñ”HŽD…BD"e¿/•Jd³ãé4CÃCäó… ÅVå× 3% ºÏêTÈiñ9»µÄl„Z,Úb@)–/_N*•BèP(uÙNŒ6¾ÄÙ)˪((EôI|QÔÒ}Ђ îƒTE7öaYiÙbRÓ)3ÉüÉܹ÷žs|ÈÌí¤mì$éÖ­æ?†¹s¸óýþþŸlÉÿŽX÷z8}zÚ#À œG‚ÑôéiÆ*u¸Áoñ¿á'v9À}1,a¨ahbX¤Á;ü‰Ÿr(lÔ+â¡0Q@„@´Eš<‡ø?b–7øŸ†û½IÀÜ¡:&c‘e/'9ÏÛ¼Î3<$ß[L‡ÄZÚ–Œòa~Åï§OO·€ì†+Ç¿›Íæ—ô8_>ÿCö°gØG‰ $òžç_›æâ.ZÃc;/ò ^çmê\ÇtµSrqæ£|ŸßñÂG |¯x¼ÀÞõŽz×™¯’ꜽ—ŠŽÊ>Uôù¿{×ù‹¿ýõ)Ûß¶¥±Äݯ0Æ µÁM„h­V¾k6·?µÖmÐFGA;øÊg^þìw×›°ë% Î;WÚ³o÷›¥âÞÈȈ#¥ÄƒeY=à5ZkÚí6A`ŒÁC"‘ ”R(¥h·Ûܺu ˲ԕwþ¾¼T©äÌ™3—×CÂ^'Y™Í}n$?j g~~ž¡¡!„¸ÝN,ËBk ‚ÏóPJqóæMÂ0D)EEA@EH)¥—H‰%Q;|©Óæú"!Ö^ ÏM~zçÎbªR©000°ò!B µÆ÷}Z­ËËË(¥RÒh4¨Õjh­WÍf³d2¶nK¥^>räHr=‘!V•µûœ}õÕ¯},‘L dÒ¤”±¥ƒ  ÙlÒl6iµZø¾€Öš0 WbÝÜmP¥…B­5™L/“O>õä'{ŠÁº„÷ñ€Ο˜üÀdÒ÷}”R„aÈââ"õz˲°mÇqp'mYÖ]à»9áû~7xêý“é¤ë|q=#Žè7|><ày©ç …mV­Vcqq‘f³‰çy¸®'f7L<Ïcpp|>O>Ÿ'›ÍÆà{èÙlÆ$‹ãEÇ=pìØ±b¿$ì"zÍS'I==ú¡¦¦¦lc ø¾ÏØØQÅì†ÍÜÜccccbRApõêU&&&btÉX–E½^' Cž}ö9ùÏëóŸÎö3‰>ŸçÆ,,,P.—©T*ÔëuJ¥Òª2ÛfÕj•J¥Â¾½û„´åñNNZ÷3~?ÄKÏ¿410Ûíº.år™B¡@½^_ºK¤[yFFFbpp0®6½ {= „ ÕjÅÛ±}ÇÀÑ£G?~?\}˜Ø5þÊÔ§d­V#òù<¶mÓmb½Dî$Õ ¡nÅêµ¾Öšt:RŠR©„‚F£Á¡C‡ìÑÑѳ÷ÁôæÀt•VêÅ]»JÌÎ΢”ƒmÛ„aH:Æq¢(¢ÝnǪké^°ŽãàyÉd˲h4cp])%AP*•hµZO8p ?333ßO¯™(ÇîñÅŒ”’jµ7,˲PJáû>BÒé4™L×uq'Ô%†!ívß÷Y^^¦\.£”ÂqœØ›RJ„$ <(3™Ì+333gû!°fò¼ä×÷¾o¯¸pá®ëR,©T*ضƒð}¿; ¥ŒÙ¶½jV’R’L&F)wñ®^¿~k×®155Åß._>Õ©F'°´´4îû-Ù¿?ù|>®ÝB,ËZ¥ÝXïMTƒs{ÐëZ<Ãx2”‚Ngî–Ôz­–ë·¬IÀ÷Û©?þù­–ÏÏñ3&''ùækßÂqr¹¹étŠd2I"‘@vÀ9®K6“!‘Lâº.ÉäJÜ·Ûmjµ:7Ëefçfi6—;#¶YùìT¦L&Cñ±mªßN¼&!„•òÒ±0†={öP(RcnoKºÍ,Š""µrˆ"E¤"ÂÎ3¥u'däªÑ¢·K§S)R©”Õ¯Ö”(Š–µÖîøÎqÆÇ-&Š»8yê$H$4 ªÕ*Ú¬TšH©(r îÖ{ËB cÛd3iF #Da„Ö+‹¢;ç½ê­›rÓÊåò÷þú—7¿,¥ôŒ1Ö¥?\Z5:¬¹ êIÜÞÙç^ƒÝ½‹|`UþUùñƒ¸‘=Œv¶ËÉÍÜ_×± €E`¸ºYYÀël‘寢ë%`z¶¨K›%`ß±9x7Á÷’Еp´ùÊís|ïd`6²V|X ·dK¶d+'ÿÅÞ2ÁÚâl™`Kþ òoø)Ôñ­æIEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_scalable_sidebar-tree-symbolic.svg0000664000175000017500000000130213215733314025424 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_apps_scalable_nemo.svg0000664000175000017500000000747513215733314021521 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_status_48x48_progress-60.png0000664000175000017500000000515313215733314022237 0ustar fabiofabio‰PNG  IHDR00Wù‡bKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEß 85z}è øIDAThÞí™{Œ\eÆç:÷¶³;»Ò²»íbZ[K¯,ÂP\›`¨AÀˆ¦RZR¢‚Æ?4€Œb5jŒÄ[´iÕÚi  µå"…¦†µ»½ìî´³³s=sÎùÎç{f:³»mgÛb ñKÞÌìÙ3'Ïó½—çýÞÿ_¥Lv±w]¯.Zf  F½ëz%CHFÈ1ÄØÇ>þ̳¬fqÀü0dŒ"É") Éç}^å—¬’gêõÂD.à6P,ãV~B?/ñ]> ´úùI@Ž3¯JF!Æ\Ö°™÷ØÊÌ‚çé“8™•"*m\É&^äk\ ÄθrŒû¿<Û<ClNm~Š9Lç æÑÍL4´I E¶òwó>[ çréÀǘÎí|‡­¼GŽCÈ vÉqžapÁùZ¤ Z¸†±ƒƒ8 ë쒣乛ðù,!nã^ö‘£YgH2ÈBLE/”†îùaÿÞÉLõMkÐT–p-»¢YgHþÁ+¾ð)gvÂýÛŸß¶V×Õ'tM*êÄGH)ñ<‰”¶íàybìoÏÓ'>=ÏCzOz®]¶úÒ†/ïäY^$B´î&‚rOð p6Ô 6tÏ™wñÞî®Ù¡ÖÖVCÓ4¤”(ŠRÞÃó<Êå2¶m#¥DJI À¶m„!(—Ë;v EQÄ÷÷GÓ¹«xõvaF )@ŽwY@/Ðï«È”u@´D[üîÖD›žL&ÁÁAJ¥¶mS.—)—Ë8Žƒã8u×4MCQ†‡‡I¥R¤R©êwÇqBh¡@XE•«ÙÄþ£u:áÍÌá{ÜõÞQ§^!3øÅŽŽ®p:¦©©iì!ªŠªªxž‡eY”J%ŠÅ"B4M#ŸÏ“Ífñ<ïÄ…X,F4:†§½­="…¸ë¦›n òO’'çïµQXÂã˪ZWÖN>?ü­kÁpS4EÓ4<ÏCmÛ  …¥R ˲ð<ÇqÆb]NÔ"!ÉdÏóˆFc„¢uþÂùŸáyþÄÚ:ÐÂlŸ€1ç4Ð-‰Õ‹, Z–…ÇqÈd2är9EA×u ÃÀ0Œ*hEQ&€¯ä„eY•`á%‹"AÓ¸Pù)[quý“NœG¸M%„@½á†šB¡ðòd²]Éf³d2 …¡PÓ4«‰Y “P(Dss3‰D‚D"A,«‚¯ £B¡P%ÙÕÙ…a˜KV®\ÙÅa,òó:.0åµ}’Ú‘5„/¿ò²Ûzzzt)%CCCär9®ëVMëºôõõ‘ÍfI¥R=z”ááaŽ?Îþýû«ž©X…H.—Ãq®¿þFmÚ´i÷ ¯³uBãgÒî+³Ú(…çp§5O[7kæÅZ:æÀÄãñê®'‘H$8räCCC¤R)Òé4¹\Žîîîº2[f###¤ÓiæÍ§jº¶ 0xŸw&´ázõ§Rsx8õŽåwÌljŠ_lš&©TŠd2I.—«–ÇZ Ð4ÖÖÖ*ØJhÕ‚®õ€ªª”J%¤”!˜1}FÓŠ+®Ûö¯m/OèCÃ4ÕhÄêÌY_é¹´GËf³Ø¶M"‘@×u*"6>„*ßkób2"žç‰DBÐÝݪªäóy–-[¦·µµ}·±'„P€Ød8•"ëž·ÏšÕM?B¤”躎ã8D" ÃÀuݪU€ŽÃ0…BƒAE!ŸÏ#¥Ä4M4Mömº»»)•J—/Xº åMï͉§»±þI©%pÒêU«n¼¨£+ªi###UÁR!–e¡ª*‘H„h4Šiš†QT!â8år˲(‹¤R)„†Qõ¦¦i¨ªJ `éÒ¥Z ¸,¹šCj•€wÒ^7üöÜOÌU·lÙ‚ištuu‘N§Ñu½ À²,\×­©Óu½®WÒ4`0HKK BˆªŠWìСCôõõÑÓÓÃo½y÷„­Í’ñOÓ^CFGG;-«Dss3‹/&‘HTk·ªªÕ$®X%ÖkU"Ažhô*;n;Nµ3u…_™+%5ŸÍÅ&ÈO‘€e•ïìÞE©dñ»ßodÑ¢E¬ô1 à Ó‰„ ƒ4œašÄ¢QÁ ¦i ŽÅ}¹\&›Í1œJÑ?ÐO¡Pô[l9öéW¦h4Jç…m1.?p¸–€z:ªª*áPÄo‹)™3gÉdUS‰”'Êt¥r]WŒ\Wà Ç¿&<Ï­®µ¨UéH8L(R'èÀNvÅñ8ér]·èyžÙÙÑIg§ÂÌ®Y¬Y»$òù<###xr¬Ò¸Bø @ÕÆz•z¯(hªŠ¡ëÄ¢Z“­¸Ž‹ç ŠÆ÷{éãCõåe”4ϳÈÕN N¹R©Ô“¯íÙû ª©a$ìzyW5!O9 ªIÜÚÞg²Æn²ec+ûf쫔ͱu€·¶×ð‰ì"  h%LŒ"â NrSƒÝÃ|’[‰Ók®?Á7y_û§²Æ<düÙÙ Åê0êƒ#°šE¬àŠ@ &;ßã ^`§‡©(ùY¯ÖL>˜õ ¬ä· ¡ñõv,=\~Á³À! ?U¢fÆÀÿŒV³çœ‚ÿ1,ãUެkp$°—¿ñOv©ñSm`.$ku¢w]¯Ë¼ÄFn>ÍȶqÛÈ¥\Ë»dˆãŽ›`æ ëy 8â—ÏÓN§å©µÛ?µ0Ÿ?²ƒõlllŠ<éÚH˜¬g>» @i\ÍÏ’áQ§È[ÀðdØŽçÞu½rûòíõÔ“@”2ÜKšç¸£>>O |Ÿã"ž&O€áI¤ÔÅæ<ÎN6ÿžl÷&л®Wn¿|{†è$“bÃ'Ç#ËoH³‹·)3„ç×k•Ú2Ÿi¬¤‰Ï3ŠÊðIF y2<ÅÓ¼ÂàÀøÊs&XLWñ÷ÓNÇIŸšü™áW‘Jpüz–õuôd:H?ñ}úy8xº÷ˆ„XÈWYË–¡Lí]Vòåò:»ÙÀ3”xëܹ˜DWVÐ×Å™Ìf_à³Ìæ’s  ’ý¼Å¯ØÄ~v}ÀaÀ:W£ôñºqõ]\ÆÕ\Ç5|œÙÄhžÒ“rŒp€ý¼Ä_ù;;ÿø•&ãO€ø Ô¦n3ÐK™GKi§(Q¢4òKl‰y²äÉ3È{ØËk¼ã×öcÀ ß¤9Sr¶î7ý”ù„âþô8ä[åu©å§pÉoF}À¹šVåŒÖ¹ìk Ÿé‡šQÓªT^s»>XûLvû#¹þ PbCpïó6IEND®B`‚nemo-3.6.5/data/icons/Makefile.am0000664000175000017500000001003613215733314015471 0ustar fabiofabioNULL = public_icons_themes = \ hicolor \ $(NULL) public_icons = \ hicolor_apps_16x16_nemo.png \ hicolor_apps_22x22_nemo.png \ hicolor_apps_24x24_nemo.png \ hicolor_apps_32x32_nemo.png \ hicolor_apps_scalable_nemo.svg \ hicolor_actions_16x16_nemo-eject.png \ hicolor_actions_16x16_menu-bullet.png \ hicolor_actions_16x16_menu-sort-up.png \ hicolor_actions_16x16_menu-sort-up-free.png \ hicolor_actions_16x16_menu-sort-down.png \ hicolor_actions_16x16_menu-sort-down-free.png \ hicolor_actions_16x16_menu-sort-right.png \ hicolor_actions_16x16_menu-sort-right-free.png \ hicolor_actions_16x16_menu-sort-left.png \ hicolor_actions_16x16_menu-sort-left-free.png \ hicolor_actions_16x16_menu-none.png \ hicolor_actions_32x32_nemo-eject.png \ hicolor_actions_scalable_view-compact-symbolic.svg \ hicolor_actions_scalable_location-symbolic.svg \ hicolor_actions_scalable_sidebar-hide-symbolic.svg \ hicolor_actions_scalable_sidebar-show-symbolic.svg \ hicolor_actions_scalable_sidebar-tree-symbolic.svg \ hicolor_actions_scalable_sidebar-places-symbolic.svg \ hicolor_actions_scalable_expand-menu-symbolic.svg \ hicolor_actions_scalable_expand-menu-hover-symbolic.svg \ hicolor_actions_scalable_collapse-menu-symbolic.svg \ hicolor_actions_scalable_collapse-menu-hover-symbolic.svg \ hicolor_status_48x48_progress-0.png \ hicolor_status_48x48_progress-10.png \ hicolor_status_48x48_progress-20.png \ hicolor_status_48x48_progress-30.png \ hicolor_status_48x48_progress-40.png \ hicolor_status_48x48_progress-50.png \ hicolor_status_48x48_progress-60.png \ hicolor_status_48x48_progress-70.png \ hicolor_status_48x48_progress-80.png \ hicolor_status_48x48_progress-90.png \ hicolor_status_48x48_progress-100.png \ $(NULL) private_icons = \ hicolor_emblems_16x16_emblem-note.png \ hicolor_emblems_24x24_emblem-note.png \ hicolor_emblems_48x48_emblem-note.png \ $(NULL) noinst_DATA = \ hicolor_apps_16x16_nemo.svg \ hicolor_apps_22x22_nemo.svg \ hicolor_apps_32x32_nemo.svg \ $(NULL) EXTRA_DIST = \ $(public_icons) \ $(private_icons) \ $(noinst_DATA) \ $(NULL) ############################################################################### gtk_update_icon_cache = gtk-update-icon-cache -f -t update-icon-cache: @-if test -z "$(DESTDIR)"; then \ echo "Updating Gtk icon cache."; \ for theme in $(public_icons_themes); do \ $(gtk_update_icon_cache) $(datadir)/icons/$$theme; \ done; \ else \ echo "*** Icon cache not updated. After (un)install, run this:"; \ for theme in $(public_icons_themes); do \ echo "*** $(gtk_update_icon_cache) $(datadir)/icons/$$theme"; \ done; \ fi install-icons: for icon in $(public_icons); do \ THEME=`echo $$icon | cut -d_ -f1`; \ CONTEXT=`echo $$icon | cut -d_ -f2`; \ SIZE=`echo $$icon | cut -d_ -f3`; \ ICONFILE=`echo $$icon | cut -d_ -f4`; \ mkdir -p $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ done; \ for icon in $(private_icons); do \ THEME=`echo $$icon | cut -d_ -f1`; \ CONTEXT=`echo $$icon | cut -d_ -f2`; \ SIZE=`echo $$icon | cut -d_ -f3`; \ ICONFILE=`echo $$icon | cut -d_ -f4`; \ mkdir -p $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \ $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ done uninstall-icons: -for icon in $(public_icons); do \ THEME=`echo $$icon | cut -d_ -f1`; \ CONTEXT=`echo $$icon | cut -d_ -f2`; \ SIZE=`echo $$icon | cut -d_ -f3`; \ ICONFILE=`echo $$icon | cut -d_ -f4`; \ rm -f $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ done; \ for icon in $(private_icons); do \ THEME=`echo $$icon | cut -d_ -f1`; \ CONTEXT=`echo $$icon | cut -d_ -f2`; \ SIZE=`echo $$icon | cut -d_ -f3`; \ ICONFILE=`echo $$icon | cut -d_ -f4`; \ rm -f $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \ done install-data-local: install-icons update-icon-cache uninstall-local: uninstall-icons update-icon-cache nemo-3.6.5/data/icons/hicolor_apps_16x16_nemo.png0000664000175000017500000000100213215733314020501 0ustar fabiofabio‰PNG  IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÜ 6R?ÀH‚IDAT8Ë¥“¿nA‡¿Éº„„„ÄCðÔ)Ü厖àxJ*Dá?²ÒYT¼F¤ÔD‰ÅÄæì»ÛŠ8Ÿ}‰"±ÕîÎü¾™™…ÿ\0™LNÝý-à-£È¼ßï¿y0N…Þçy~$IË85I’«]‘»ŸçyþND\†Ãaèõzi–e{ôõzªîÝÏf³< šdYÆço¨êòIï6ÓÔÜŠO_Ž.Ó&ZU0è}ì.ÒÝNZ–ÃÇ__§Û>ªÊïùI@šƒ»a®àFQÞÞWÌ"1Öû)oDfŠc¸+æJQüñtKOÔHˆ0ÌnÔ· mîÍ”åz+µHˆ«òuÅ,b®D èF„;HkTîËbΪ\0_žß\q÷Î:t®¬ª%ËÅhwAvàĨëD:‚µÕ‚îé¶KÔH*ÙÍ´QŠ4ó ੈ\ŽF£ÉÁá³ãŸßåÉßÐÝAÎî/Wí'=º"p\ÿ2wãÑ4óÀ³IEND®B`‚nemo-3.6.5/data/icons/hicolor_emblems_16x16_emblem-note.png0000664000175000017500000000102613215733314022436 0ustar fabiofabio‰PNG  IHDR‘h6 pHYs  ÒÝ~ütIMEÓ : èDÇ>tEXtCommentCreated with The GIMP (c) 2003 Jakub 'jimmac' Steiner'3ïXkIDATxÚ’=K\A…Ïsæ‚ZDBüÀ"M°J)’@¶6B¥U¾ ó4VVY„6©£AÙM ›]A‹ F×p×\‹{ïîu‹€žbfžóžÃ0Ò5…¤æñîÿ¡ÛÃâŸS­½;ƒ³[Qzô£úlçkÁÖøäëöÑt¼Ó÷¬Ôä,(§mÛºBÿšŠwúŸo4߬ïu !)j›(£ÿ~tþyàéÆïµ÷_¶7$EÅ„t*O.Ÿí?<« /¾=,•+õêR«Õ.V :Ø’TûöøÅ‡z©\i|}€®$é{Ës3#÷Ÿ¬HÊiR23Ø&‰°H*:ªW—èHÈîzT;xÙÙ£¼R„! Àù¦¨ÞJ€ò{ P§]ÃÐÝùí 7ñ1ú%¥™Ÿf†åÕ§ùéÿ0’,ÔyÖ±Ñ[y°°³XV$ NÎu]Ü73.˜‰À ‰ûBIiFN3v9¤$®>Ïgî•` ¯øj`Kiiéfà>@ñþGù"'Ÿð@Þ¹lqÅÖÍoýáã÷ßyþÀœÚØZ`=ð „Ä• ÷äkâRÈ P_Qyàå~óÕë—ÄÃföRÂHJK>¹z×é ›õ÷%3ÿþX€í=Ë-x¦{¹Ü< øµÀi 8\ðpp-píïÿéüÆ[/šÁÈEJR"…@HB°yÛ±¡¦æÓgþüìî­ÀÀNŒã­i“¹ßn\ûă˖ß=¸Gnû®Ã>r<(„°›÷R±"¥¢,|&Qlžüå¯Y<§&2 ×$7Ú‚”!& E")¤1qýõ·ÚFš÷w·¯yµcp,mn‘—ŸÜ3Ô×â ád‡Ô4n«ñœ©{ùrN$.F â­`6ð\8äó=ùûÄ]÷ÜWéóÕtr¹T'RD T~Ф˜D2/%¤À±,“¸¶N´²±Oø[UéÍÛß2@® z ^„€åÝ ½ÀgUß™ˆ.8¹Nµt‡Ùõ÷-[N.}‚ôàv\$¸àâ×u&J¾®tÀ•\\Wx&®»¸ŒgÆI ¦(*.Fo º§ª KËcŒx0'ËèbP¼›ƒÀæHØ9´óçq)(×4“\NÇ4,LÃfÎ’Ÿ • (Cë#ÓÿÁ9R‘rb×"'I)ŸK½Cè¹q• ÈjE£eÑј1r€PÉ,¢ 9ÜåU©1À(”ÑÅ"àxQxéáŸÝtæ±_?z‡ëEÏ!ààªw¢Úì\ƒ®[(Š`ÞÒû)©ûVö$ùÒêNö¼ã‚$û†Ðr9\gŒPÉ ]ÏºÅ¡áØØ‰MÄæÞƒ5Þ‘ßîø'uð)I(oá#]Ci!Cc¾È5Q| { ÜH¡¢( ë.ª¢`š]íÏáÚ6u·RTRK´öG8f?ƒ'Þ%•Ê d2YM#° |%7ë•"4ÙžwHÌ¿‡Ì©MW.üŸŒ˜Âþæ6à©îÖ_,¡kDªuW-ÂNû-½mx ®ëb&–ecY6¶m“ÓM\ÇÁ0lLË&5–#PÂE PUˆüñF#¤˜„}ý~;¹•ؼï2žl¥ìª[hß³¡å+?ܾçåá¨'!g*ÊÛÀÕ| ×uèùhs žEI¢œc„«~,]3©Ê¡wAeIlKð ,ÛF“.AGð…&d„ƒë8„ƒ jì6C±²„Ô~¿1°…ØÜ»I쥼n%-M¯µ¯¼·y!ð´—¼öùšÙT|° ­ð¨™w;Rqé9Þ„èõ—U^…¨5Mw•ögÃæÈ{èz?Š¢àXŸ –e´–=Q‰ÅEWÓ{,”Ý~3ÕMbÞ]Œö6S5çFö6½ÒñµU-1àoÀ[€VИjÊK(ìî?þ׆DÕ-èÚ™ÑãD¢µøü~’§w“ËTÌ^†?'=ÈJÒ>'½Å§gŽbY6Ží`B¸¸Žƒæûf:*;‹ÍÌ)0Ç(©YAz …ª«oeߎW;n»¿%¼éíú€¤W>Õ”) <XvôhWOEèHEyõ¢P¼b)¶m“r˜“­Dc _(Qdd…e) Z$\äÖ TEà•£ûÓ1ÙVlŽŸ!ôŽÏGi§¬n%ûw½–ÿ<ð¾|ØkbºþSµ~*ƒÊ‡Gº’‘7´gŽùë'¢E%sÔDõõX†ÁH+ÑÒÊf]K.}œdOª°e¢´Ô¯FиnL„—Ú†ÊÆÔΨ>Ü/XL(:] ^µŒ¶=ó²ù'ðAø±Ir§C Ä  ­µ½Ç]ýâ^; ùbþãxY½¯ºS×M¶‰-"QÙ€®õÒwºS ¼ª&.®õùµæ`ºk=Áø‚‘ã#G)­^Æþ]ov4®j)¶¼¦5¤ À;çÛ*Óœ\àc ùÃ]æê5»#ÂS¾xù5VÑ€ešŒ&Û)Š×“¨¬ÇµRôÜG(’`üðã„*—(ªE$Q½”–ov4Nx~°î<àÍɺŸn ;³í=к€mÛw}d¬~aglvyV™ _)‰êå˜Fš±áN"ñzUK#gÅ%›I-›Ë¾¦7:Wµæe³aºà§CÀ- `y /±Ž[ß~¯ƒ5¯ì.-‹å¬º²áˆôW¨¼SÏK#Õù9Ó¤¤²a2øMŸüt#ÀEHÀá¬f¼÷öÚä ëw–—Ç ­®|´H TQ\þeTÕŵ(J,doÓë«Zã— þ³œ·‹‚OÅ[~¯W„" ê­ÊJ‹o|cí#‰úWEKI·=Ä¡FüóÀ®K9N‡ït"ä >•ÀÕÞL}3p7°~ÑÂÙ=ÍÏ oéK­ÞéÆÓÀíÀrï÷ ïêt*. NÞÔ D¤ø>°xH{5~äR=/.cD& ‰xV¼üÉz *ã7.Tç?ïwNâ<òò{dòC‰í%~îBcâá¥Ùd"jÁá®[PÉìK?c36c3öÿ·ÿÿ1õü‰-9IEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-down.png0000664000175000017500000000037113215733314023146 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEá õ2s¹†IDAT8Ëí‘= Ã0 …Ÿ s·Bñ$m¾ïéëx•|‰—!¤M©“²æ!}ý—NKÖ Éÿ ù`·u¡÷þL)½ZkC0„€œ³l:“|¸;ÌŒ¾ÂÌXkÝŸ’ä$ܪú†U•î’Çk.M‹É,[&PJˆ Æøs¼]ƒÑGFð¥YõsQËᔤÝIEND®B`‚nemo-3.6.5/data/icons/hicolor_apps_22x22_nemo.svg0000664000175000017500000000735313215733314020525 0ustar fabiofabio nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-right.png0000664000175000017500000000033313215733314023312 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEá .½÷BÂhIDAT8ËÝÒ± À CQ+;@s[°ÃCC0?U¤(UrJ“¸¿'Ù:éŸ4ç À䜩µú@)%B´Öž# ‰ãsä \‘k¶»àZËWÁÌè½û*˜c ߈¥ßñ+ô­ì. €Ê²F IEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_nemo-eject.png0000664000175000017500000000120413215733314022272 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs|4k¡tIMEÜ 8¶œtrIDAT8Ë…S½jbA=×I v-¹^‰,Ä2El$¸`š<ÁbîsËÙ"ø !b …4*ÑB SY¬¢2s¿Ù"{]“÷À9ßßÌù4¼C"‘@2™„Ïçƒ×ëL&ŒF#”J%T*ìc ¹\³ÙÌÃ9¿åœ?qÎWùÄ9¿Ífž\.ÆØ6N³‚kµ‚ÁàµRê'ûþ2Xišöc0Ü]\\À4M0Èd2ˆF£×Dô‹ˆŽ‰Ÿð˜ˆ®œNçÔívwªÕ*´X,†B¡àaŒ ÞW€ápø¡Ó4ƒ©Tjj‹ÇãPJ¥¥”v)%,ZÁV¢Ý;)¥])•ŽÇã°†)åå®  }> ½Orilº®Cq*„€ápŸ!ÃÒ !Nu]ÇÑf³”r+j·Ûp8{,—Ë7ÚÍfƒ£^¯‡³³³g8??Ç!4›MëøÜëõ`ë÷ûRÞ[³ý;opßï÷¡œœ ›Ízìvûà€>|ãjµ ¦Óé)›ÏçRþŽD"œˆ®˜hKÓ4oŠÅâC£Ñxub·Û…ßïï¸\®©RêÛ7®LÓ¼iµZwù|þu‡¬žêõ:Öëu'c‚ˆ¾ÑW"’DÔ%¢âb±ø^.— …”Rÿ–i^¯Ñh†a@×uÀËË Æã11™LÞèÿi|€Ú•IEND®B`‚nemo-3.6.5/data/icons/hicolor_actions_16x16_menu-sort-down-free.png0000664000175000017500000000040313215733314024061 0ustar fabiofabio‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEáæ þ^IDAT8Ëí‘;1 DÇ¢¤C¢Ìt9BîFQp¸œ ­C™K ¬XÁþ$ÚΉߓ{þŽ IÛ û`‡ñEïý’Rz¸›ÙíKž\K)ÇY³¤³»ƒ¤Hæáœd&©ÖÚò”’N’àî!è æ‚Ü’ÖךÉls¨µÂÌcüy¼EÁÔLÁ{^yQ/QYG&„)IEND®B`‚nemo-3.6.5/data/nemo.desktop.in.in0000664000175000017500000003214413215733314015671 0ustar fabiofabio[Desktop Entry] Name=Files Name[am]=á‹á‹­áˆŽá‰½ Name[bg]=Файлове Name[bg_BG]=Файлове Name[ca]=Fitxers Name[ca@valencia]=Fitxers Name[ca_ES]=Fitxers Name[ca_ES@valencia]=Fitxers Name[cs]=Soubory Name[cs_CZ]=Soubory Name[da]=Filer Name[da_DK]=Filer Name[de]=Dateien Name[de@hebrew]=Dateien Name[de_CH]=Dateien Name[de_DE]=Dateien Name[es]=Archivos Name[es_419]=Archivos Name[es_AR]=Archivos Name[es_CL]=Archivos Name[es_CO]=Archivos Name[es_CR]=Archivos Name[es_DO]=Archivos Name[es_EC]=Archivos Name[es_ES]=Archivos Name[es_MX]=Archivos Name[es_NI]=Archivos Name[es_PA]=Archivos Name[es_PE]=Archivos Name[es_PR]=Archivos Name[es_SV]=Archivos Name[es_US]=Archivos Name[es_UY]=Archivos Name[es_VE]=Archivos Name[eu]=Fitxategiak Name[fi]=Tiedostot Name[fi_FI]=Tiedostot Name[fr]=Fichiers Name[fr_CA]=Fichiers Name[fr_FR]=Fichiers Name[hr]=Nemo Name[hu]=Fájlok Name[hu_HU]=Fájlok Name[is]=Skrár Name[ko]=íŒŒì¼ Name[ko_KR]=íŒŒì¼ Name[lt]=Failai Name[lt_LT]=Failai Name[nl]=Bestanden Name[nl_NL]=Bestanden Name[pl]=Pliki Name[pl_PL]=Pliki Name[pt]=Ficheiros Name[pt_BR]=Arquivos Name[pt_PT]=Ficheiros Name[ru]=Файлы Name[sk]=Súbory Name[sk_SK]=Súbory Name[sv]=Filer Name[tr]=Dosyalar Name[tr_TR]=Dosyalar Name[uk]=Файли Name[uk_UA]=Файли Name[zh_CN]=文件 Name[zh_HK]=檔案 Comment=Access and organize files Comment[am]=á‹á‹­áˆŽá‰½ ጋር መድረሻ እና ማደራጃ Comment[bg]=ДоÑтъп и управление на файлове Comment[bg_BG]=ДоÑтъп и управление на файлове Comment[ca]=Organitzeu i accediu als fitxers Comment[ca@valencia]=Organitzeu i accediu als fitxers Comment[ca_ES]=Organitzeu i accediu als fitxers Comment[ca_ES@valencia]=Organitzeu i accediu als fitxers Comment[cs]=Přístup k souborům a jejich správa Comment[cs_CZ]=Přístup k souborům a jejich správa Comment[da]=TilgÃ¥ og organisér filer Comment[da_DK]=TilgÃ¥ og organisér filer Comment[de]=Dateien aufrufen und organisieren Comment[de@hebrew]=Dateien aufrufen und organisieren Comment[de_CH]=Dateien aufrufen und organisieren Comment[de_DE]=Dateien aufrufen und organisieren Comment[es]=Acceder a los archivos y organizarlos Comment[es_419]=Acceder a los archivos y organizarlos Comment[es_AR]=Acceder a los archivos y organizarlos Comment[es_CL]=Acceder a los archivos y organizarlos Comment[es_CO]=Acceder a los archivos y organizarlos Comment[es_CR]=Acceder a los archivos y organizarlos Comment[es_DO]=Acceder a los archivos y organizarlos Comment[es_EC]=Acceder a los archivos y organizarlos Comment[es_ES]=Acceder a los archivos y organizarlos Comment[es_MX]=Acceder a los archivos y organizarlos Comment[es_NI]=Acceder a los archivos y organizarlos Comment[es_PA]=Acceder a los archivos y organizarlos Comment[es_PE]=Acceder a los archivos y organizarlos Comment[es_PR]=Acceder a los archivos y organizarlos Comment[es_SV]=Acceder a los archivos y organizarlos Comment[es_US]=Acceder a los archivos y organizarlos Comment[es_UY]=Acceder a los archivos y organizarlos Comment[es_VE]=Acceder a los archivos y organizarlos Comment[eu]=Atzitu eta antolatu fitxategiak Comment[fi]=Avaa ja järjestä tiedostoja Comment[fi_FI]=Avaa ja järjestä tiedostoja Comment[fr]=Accéder aux fichiers et les organiser Comment[fr_CA]=Accéder aux fichiers et les organiser Comment[fr_FR]=Accéder aux fichiers et les organiser Comment[hr]=Pristupite i organizirajte datoteke Comment[hu]=Fájlok elérése és rendszerezése Comment[hu_HU]=Fájlok elérése és rendszerezése Comment[ia]=Acceder e organisar le files Comment[is]=Aðgangur og skipulag skráa Comment[it]=Accede ai file e li ed organizza Comment[ko]=íŒŒì¼ ì ‘ê·¼ ë° ì •ë¦¬ Comment[ko_KR]=íŒŒì¼ ì ‘ê·¼ ë° ì •ë¦¬ Comment[lt]=Gauti prieigÄ… prie failų ir juos tvarkyti Comment[lt_LT]=Gauti prieigÄ… prie failų ir juos tvarkyti Comment[nl]=Bestanden gebruiken en organiseren Comment[nl_NL]=Bestanden gebruiken en organiseren Comment[pl]=PorzÄ…dkowanie i dostÄ™p do plików Comment[pl_PL]=PorzÄ…dkowanie i dostÄ™p do plików Comment[pt]=Aceder e organizar ficheiros Comment[pt_BR]=Acesse e organize arquivos Comment[pt_PT]=Aceder e organizar ficheiros Comment[ru]=Управление и доÑтуп к файлам Comment[sk]=Prístup a organizácia súborov Comment[sk_SK]=Prístup a organizácia súborov Comment[sv]=Kom Ã¥t och organisera filer Comment[tr]=Dosyalara eriÅŸ ve düzenle Comment[tr_TR]=Dosyalara eriÅŸ ve düzenle Comment[uk]=ДоÑтуп до файлів та впорÑÐ´ÐºÐ¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² Comment[uk_UA]=ДоÑтуп до файлів та впорÑÐ´ÐºÐ¾Ð²ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² Comment[zh_CN]=访问和组织文件 Comment[zh_HK]=å­˜å–與組織檔案 Exec=nemo %U Icon=folder Terminal=false Type=Application StartupNotify=false Categories=GNOME;GTK;Utility;Core; MimeType=inode/directory;application/x-gnome-saved-search; Actions=open-home;open-computer;open-trash; [Desktop Action open-home] Name=Home Name[af]=Tuis Name[am]=ቤት Name[ar]=المنزل Name[ar_MA]=المنزل Name[be]=Дом Name[be@latin]=Дом Name[be_BY]=Дом Name[bg]=Домашна папка Name[bg_BG]=Домашна папка Name[bn]=হোম Name[bn_IN]=হোম Name[bs]=PoÄetni direktorij Name[ca]=Carpeta de l'usuari Name[ca@valencia]=Carpeta de l'usuari Name[ca_ES]=Carpeta de l'usuari Name[ca_ES@valencia]=Carpeta de l'usuari Name[cs]=Domov Name[cs_CZ]=Domov Name[cy]=Cartref Name[da]=Hjem Name[da_DK]=Hjem Name[de]=Persönlicher Ordner Name[de@hebrew]=Persönlicher Ordner Name[de_CH]=Persönlicher Ordner Name[de_DE]=Persönlicher Ordner Name[el]=ΠÏοσωπικός φάκελος Name[eo]=Hejmo Name[es]=Carpeta personal Name[es_419]=Carpeta personal Name[es_AR]=Carpeta personal Name[es_CL]=Carpeta personal Name[es_CO]=Carpeta personal Name[es_CR]=Carpeta personal Name[es_DO]=Carpeta personal Name[es_EC]=Carpeta personal Name[es_ES]=Carpeta personal Name[es_MX]=Carpeta personal Name[es_NI]=Carpeta personal Name[es_PA]=Carpeta personal Name[es_PE]=Carpeta personal Name[es_PR]=Carpeta personal Name[es_SV]=Carpeta personal Name[es_US]=Carpeta personal Name[es_UY]=Carpeta personal Name[es_VE]=Carpeta personal Name[et]=Kodu Name[eu]=Karpeta nagusia Name[fi]=Koti Name[fi_FI]=Koti Name[fr]=Dossier personnel Name[fr_CA]=Dossier personnel Name[fr_FR]=Dossier personnel Name[ga]=Baile Name[gd]=Dhachaigh Name[gl]=Cartafol persoal Name[gl_ES]=Cartafol persoal Name[he]=בית Name[he_IL]=בית Name[hr]=Osobna mapa Name[hu]=Saját mappa Name[hu_HU]=Saját mappa Name[ia]=Al domo Name[id]=Beranda Name[id_ID]=Beranda Name[is]=Heimamappa Name[ja]=ホーム Name[ja_JP]=ホーム Name[kab]=Agejdan Name[kk]=Үй Name[kn]=ಮನೆ Name[ko]=홈 Name[ko_KR]=홈 Name[ku]=Mal Name[ku_IQ]=Mal Name[lt]=Namai Name[lt_LT]=Namai Name[ml]=ആസàµà´¥à´¾à´¨à´‚ Name[mr]=मà¥à¤–à¥à¤¯ Name[ms]=Rumah Name[ms_MY]=Rumah Name[nb]=Hjem Name[nb_NO]=Hjem Name[nl]=Persoonlijke map Name[nl_NL]=Persoonlijke map Name[oc]=Dorsièr personal Name[pl]=Katalog domowy Name[pl_PL]=Katalog domowy Name[pt]=Pasta Pessoal Name[pt_BR]=Pasta pessoal Name[pt_PT]=Pasta Pessoal Name[ro]=Dosar personal Name[ro_RO]=Dosar personal Name[ru]=ДомашнÑÑ Ð¿Ð°Ð¿ÐºÐ° Name[sk]=Domov Name[sk_SK]=Domov Name[sl]=Domov Name[sl_SI]=Domov Name[sr]=Почетна Name[sr@Latn]=PoÄetna Name[sr@ije]=Почетна Name[sr@ijekavianlatin]=Почетна Name[sr@latin]=PoÄetna Name[sr_RS]=Почетна Name[sr_RS@latin]=PoÄetna Name[sv]=Hem Name[ta]=இலà¯à®²à®®à¯ Name[ta_LK]=இலà¯à®²à®®à¯ Name[tg]=ÐÑоÑÓ£ Name[th]=บ้าน Name[th_TH]=บ้าน Name[tr]=Ev Dizini Name[tr_TR]=Ev Dizini Name[uk]=Домівка Name[uk_UA]=Домівка Name[ur]=المنزل Name[ur_PK]=المنزل Name[vi]=Nhà Name[vi_VN]=Nhà Name[zh_CN]=主目录 Name[zh_HK]=å®¶ Name[zh_TW]=å®¶ Exec=nemo %U [Desktop Action open-computer] Name=Computer Name[af]=Rekenaar Name[am]=ኮáˆá’ዩተር Name[ar]=الحاسوب Name[ar_MA]=الحاسوب Name[ast]=Ordenador Name[be]=Кампутар Name[be@latin]=Кампутар Name[be_BY]=Кампутар Name[bg]=Компютър Name[bg_BG]=Компютър Name[bn]=কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à¦° Name[bn_IN]=কমà§à¦ªà¦¿à¦‰à¦Ÿà¦¾à¦° Name[bs]=RaÄunar Name[ca]=Ordinador Name[ca@valencia]=Ordinador Name[ca_ES]=Ordinador Name[ca_ES@valencia]=Ordinador Name[cs]=PoÄítaÄ Name[cs_CZ]=PoÄítaÄ Name[cy]=Cyfrifiadur Name[de]=Rechner Name[de@hebrew]=Rechner Name[de_CH]=Rechner Name[de_DE]=Rechner Name[el]=Υπολογιστής Name[eo]=Komputilo Name[es]=Equipo Name[es_419]=Equipo Name[es_AR]=Equipo Name[es_CL]=Equipo Name[es_CO]=Equipo Name[es_CR]=Equipo Name[es_DO]=Equipo Name[es_EC]=Equipo Name[es_ES]=Equipo Name[es_MX]=Equipo Name[es_NI]=Equipo Name[es_PA]=Equipo Name[es_PE]=Equipo Name[es_PR]=Equipo Name[es_SV]=Equipo Name[es_US]=Equipo Name[es_UY]=Equipo Name[es_VE]=Equipo Name[et]=Arvuti Name[eu]=Ordenagailua Name[fi]=Tietokone Name[fi_FI]=Tietokone Name[fr]=Poste de travail Name[fr_CA]=Poste de travail Name[fr_FR]=Poste de travail Name[gd]=Coimpiutair Name[gl]=Computador Name[gl_ES]=Computador Name[he]=מחשב Name[he_IL]=מחשב Name[hr]=RaÄunalo Name[hu]=Számítógép Name[hu_HU]=Számítógép Name[ia]=Computator Name[id]=Komputer Name[id_ID]=Komputer Name[is]=Tölva Name[ja]=コンピュータ Name[ja_JP]=コンピュータ Name[kab]=Aselkim Name[kk]=Компьютер Name[kn]=ಗಣಕ Name[ko]=컴퓨터 Name[ko_KR]=컴퓨터 Name[ku]=Komputer Name[ku_IQ]=Komputer Name[lt]=Kompiuteris Name[lt_LT]=Kompiuteris Name[ml]=à´•à´®àµà´ªàµà´¯àµ‚à´Ÿàµà´Ÿàµ¼ Name[mr]=संगणक Name[ms]=Komputer Name[ms_MY]=Komputer Name[nb]=Datamaskin Name[nb_NO]=Datamaskin Name[oc]=Ordenador Name[pl]=Komputer Name[pl_PL]=Komputer Name[pt]=Computador Name[pt_BR]=Computador Name[pt_PT]=Computador Name[ru]=Компьютер Name[sk]=PoÄítaÄ Name[sk_SK]=PoÄítaÄ Name[sl]=RaÄunalnik Name[sl_SI]=RaÄunalnik Name[sq]=Kompjuteri Name[sr]=Рачунар Name[sr@Latn]=RaÄunar Name[sr@ije]=Рачунар Name[sr@ijekavianlatin]=Рачунар Name[sr@latin]=RaÄunar Name[sr_RS]=Рачунар Name[sr_RS@latin]=RaÄunar Name[sv]=Dator Name[ta]=கணினி Name[ta_LK]=கணினி Name[tg]=Компютер Name[th]=คอมพิวเตอร์ Name[th_TH]=คอมพิวเตอร์ Name[tr]=Bilgisayar Name[tr_TR]=Bilgisayar Name[uk]=Комп’ютер Name[uk_UA]=Комп’ютер Name[ur]=کمپیوٹر Name[ur_PK]=کمپیوٹر Name[vi]=Máy tính Name[vi_VN]=Máy tính Name[zh_CN]=计算机 Name[zh_HK]=電腦 Name[zh_TW]=電腦 Exec=nemo computer:/// [Desktop Action open-trash] Name=Trash Name[af]=Asblik Name[am]=ቆሻሻ Name[ar]=المÙهملات Name[ar_MA]=المÙهملات Name[ast]=Papelera Name[be]=Сметніца Name[be@latin]=Сметніца Name[be_BY]=Сметніца Name[bg]=Кошче Name[bg_BG]=Кошче Name[bn]=টà§à¦°à§à¦¯à¦¾à¦¶ Name[bn_IN]=টà§à¦°à§à¦¯à¦¾à¦¶ Name[bs]=Smeće Name[ca]=Paperera Name[ca@valencia]=Paperera Name[ca_ES]=Paperera Name[ca_ES@valencia]=Paperera Name[cs]=KoÅ¡ Name[cs_CZ]=KoÅ¡ Name[cy]=Sbwriel Name[da]=Papirkurv Name[da_DK]=Papirkurv Name[de]=Papierkorb Name[de@hebrew]=Papierkorb Name[de_CH]=Papierkorb Name[de_DE]=Papierkorb Name[el]=ΑποÏÏίμματα Name[en_GB]=Rubbish Bin Name[eo]=Rubujo Name[es]=Papelera Name[es_419]=Papelera Name[es_AR]=Papelera Name[es_CL]=Papelera Name[es_CO]=Papelera Name[es_CR]=Papelera Name[es_DO]=Papelera Name[es_EC]=Papelera Name[es_ES]=Papelera Name[es_MX]=Papelera Name[es_NI]=Papelera Name[es_PA]=Papelera Name[es_PE]=Papelera Name[es_PR]=Papelera Name[es_SV]=Papelera Name[es_US]=Papelera Name[es_UY]=Papelera Name[es_VE]=Papelera Name[et]=Prügi Name[eu]=Zakarrontzia Name[fi]=Roskakori Name[fi_FI]=Roskakori Name[fr]=Corbeille Name[fr_CA]=Corbeille Name[fr_FR]=Corbeille Name[ga]=Bruscar Name[gd]=An sgudal Name[gl]=Lixo Name[gl_ES]=Lixo Name[he]=×שפה Name[he_IL]=×שפה Name[hr]=Smeće Name[hu]=Kuka Name[hu_HU]=Kuka Name[ia]=Immunditia Name[id]=Tempat sampah Name[id_ID]=Tempat sampah Name[is]=Rusl Name[it]=Cestino Name[ja]=ゴミ箱 Name[ja_JP]=ゴミ箱 Name[kab]=Iá¸umman Name[kk]=Себет Name[kn]=ಕಸಬà³à²Ÿà³à²Ÿà²¿ Name[ko]=휴지통 Name[ko_KR]=휴지통 Name[ku]=Avêtî Name[ku_IQ]=Avêtî Name[lt]=Å iukÅ¡linÄ— Name[lt_LT]=Å iukÅ¡linÄ— Name[ml]=à´Ÿàµà´°à´¾à´·àµ Name[mr]=कचरापेटी Name[ms]=Tong Sampah Name[ms_MY]=Tong Sampah Name[nb]=Papirkurv Name[nb_NO]=Papirkurv Name[nds]=Papierkorb Name[nl]=Prullenbak Name[nl_NL]=Prullenbak Name[oc]=Escobilhièr Name[pl]=Kosz Name[pl_PL]=Kosz Name[pt]=Lixo Name[pt_BR]=Lixeira Name[pt_PT]=Lixo Name[ro]=CoÈ™ de gunoi Name[ro_RO]=CoÈ™ de gunoi Name[ru]=Корзина Name[sk]=Kôš Name[sk_SK]=Kôš Name[sl]=Smeti Name[sl_SI]=Smeti Name[sq]=Koshi Name[sr]=Смеће Name[sr@Latn]=Kanta Name[sr@ije]=Смеће Name[sr@ijekavianlatin]=Смеће Name[sr@latin]=Kanta Name[sr_RS]=Смеће Name[sr_RS@latin]=Kanta Name[sv]=Papperskorg Name[ta]=கà¯à®ªà¯à®ªà¯ˆà®¤à¯ தொடà¯à®Ÿà®¿ Name[ta_LK]=கà¯à®ªà¯à®ªà¯ˆà®¤à¯ தொடà¯à®Ÿà®¿ Name[tg]=Сабад Name[th]=ถังขยะ Name[th_TH]=ถังขยะ Name[tr]=Çöp Name[tr_TR]=Çöp Name[uk]=Смітник Name[uk_UA]=Смітник Name[ur]=ردی Name[ur_PK]=ردی Name[vi]=Thùng rác Name[vi_VN]=Thùng rác Name[zh_CN]=回收站 Name[zh_HK]=垃圾桶 Name[zh_TW]=回收筒 Exec=nemo trash:/// nemo-3.6.5/data/desktop-settings.nemo_action.in0000664000175000017500000000035513215733314020456 0ustar fabiofabio[Nemo Action] Name=Desktop _Settings Comment=Change how your desktop works Exec=cinnamon-settings desktop Selection=None Icon-Name=cs-desktop Extensions=any; Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; nemo-3.6.5/data/merge_action_strings0000775000175000017500000000567113215733314016466 0ustar fabiofabio#!/usr/bin/python3 import os import glob import polib import codecs from gi.repository import GLib GROUP = "Nemo Action" class Main: def __init__(self): self.in_keyfiles = {} self.mo_files = {} action_files = glob.glob(os.path.join(os.getcwd(), "*.nemo_action.in")) if len(action_files) > 0: for fn in action_files: keyfile = GLib.KeyFile.new() if keyfile.load_from_file(fn, GLib.KeyFileFlags.KEEP_COMMENTS): if keyfile.has_group(GROUP): self.in_keyfiles[fn] = keyfile if len(self.in_keyfiles) > 0: for root, subFolders, files in os.walk("/usr/share/locale"): for file in files: if file == "nemo.mo": path, junk = os.path.split(root) path, locale = os.path.split(path) try: self.mo_files[locale] = polib.mofile(os.path.join(root, file)) except: print("merge_action_strings - Failed to load .mo file: %s" % (os.path.join(root, file))) if len(self.mo_files) > 0: for locale in self.mo_files.keys(): for entry in self.mo_files[locale]: self.check_name(locale, entry) for locale in self.mo_files.keys(): for entry in self.mo_files[locale]: self.check_comment(locale, entry) for fn in self.in_keyfiles.keys(): action_fn = os.path.split(fn)[1].replace(".in", "") action_path = os.path.join("..", "files", "usr", "share", "nemo", "actions", action_fn) outstring, length = self.in_keyfiles[fn].to_data() if os.path.exists(action_path): os.remove(action_path) outfile = codecs.open(action_path, 'w', 'utf-8') outfile.write(outstring) outfile.close() print("Merge complete - .nemo_action files in ../files/usr/share/nemo/actions should contain translations now.") def check_name(self, locale, entry): if entry.msgstr != '': for kf in self.in_keyfiles.keys(): try: name = self.in_keyfiles[kf].get_string(GROUP, "Name") if name == entry.msgid: self.in_keyfiles[kf].set_locale_string(GROUP, "Name", locale, entry.msgstr) except GLib.GError: pass def check_comment(self, locale, entry): if entry.msgstr != '': for kf in self.in_keyfiles.keys(): try: name = self.in_keyfiles[kf].get_string(GROUP, "Comment") if name == entry.msgid: self.in_keyfiles[kf].set_locale_string(GROUP, "Comment", locale, entry.msgstr) except GLib.GError: pass if __name__ == "__main__": Main() nemo-3.6.5/data/nemo-extras.placeholder0000664000175000017500000000007413215733314016771 0ustar fabiofabioThis file is a placeholder for the nemo extras meta-package nemo-3.6.5/data/nemo-autostart.desktop.in0000664000175000017500000000034213215733314017303 0ustar fabiofabio[Desktop Entry] Type=Application Name=Nemo Comment=Start Nemo desktop at log in Exec=nemo-desktop OnlyShowIn=X-Cinnamon; AutostartCondition=GSettings org.nemo.desktop show-desktop-icons X-GNOME-AutoRestart=true NoDisplay=true nemo-3.6.5/data/new-launcher.nemo_action.in0000664000175000017500000000040613215733314017534 0ustar fabiofabio[Nemo Action] Name=Create a new l_auncher here... Comment=Create a new launcher in this folder Exec=cinnamon-desktop-editor -mnemo-launcher -d"%P" Selection=None Stock-Id=gtk-add Extensions=any; Dependencies=cinnamon-desktop-editor; Conditions=desktop; nemo-3.6.5/data/91_delete-workspace.nemo_action.in0000664000175000017500000000052213215733314020712 0ustar fabiofabio[Nemo Action] Name=Remove workspace Comment=Remove the currently active workspace Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.RemoveCurrentWorkspace >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon;gsettings org.cinnamon number-workspaces i gt 1; Active=false nemo-3.6.5/data/add-desklets.nemo_action.in0000664000175000017500000000034013215733314017505 0ustar fabiofabio[Nemo Action] Name=Add Desklets Comment=Add Cinamon desklets Exec=cinnamon-settings desklets Selection=None Extensions=any; Icon-Name=cs-desklets Dependencies=cinnamon-settings; Conditions=desktop;dbus org.Cinnamon; nemo-3.6.5/data/nemo.xml.in0000664000175000017500000000104513215733314014407 0ustar fabiofabio <_comment>Saved search <_comment>A Nemo action definition file nemo-3.6.5/data/92_show-expo.nemo_action.in0000664000175000017500000000044713215733314017414 0ustar fabiofabio[Nemo Action] Name=Manage workspaces (Expo) Comment=Open Expo to add, remove, or organize workspaces Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.ShowExpo >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon; Active=false nemo-3.6.5/data/Makefile.am0000664000175000017500000000311613215733314014357 0ustar fabiofabioNULL= xml_in_files = nemo.xml.in xml_files = $(xml_in_files:.xml.in=.xml) @INTLTOOL_XML_RULE@ desktopdir = $(datadir)/applications desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) desktop_in_files = \ nemo.desktop.in \ nemo-autorun-software.desktop.in autostartdir = $(datadir)/applications autostart_in_files = nemo-autostart.desktop.in autostart_DATA = $(autostart_in_files:.desktop.in=.desktop) @INTLTOOL_DESKTOP_RULE@ mimedir = $(datadir)/mime/packages mime_DATA = $(xml_files) servicedir = $(datadir)/dbus-1/services service_DATA = $(service_in_files:.service.in=.service) service_in_files = \ nemo.FileManager1.service.in \ nemo.service.in nemo.service: nemo.service.in Makefile $(AM_V_GEN) sed -e "s|\@bindir\@|$(bindir)|" $< > $@ nemo.FileManager1.service: nemo.FileManager1.service.in Makefile $(AM_V_GEN) sed -e "s|\@bindir\@|$(bindir)|" $< > $@ nemodatadir = $(datadir)/nemo nemodata_DATA = \ nemo-extras.placeholder \ nemo-suggested.placeholder \ $(NULL) EXTRA_DIST = $(nemodata_DATA) \ nemo.desktop \ nemo.desktop.in \ dbus-interfaces.xml \ freedesktop-dbus-interfaces.xml \ org.Cinnamon.xml \ $(xml_in_files) \ $(desktop_in_files) \ $(service_in_files) \ $(autostart_in_files) \ $(NULL) CLEANFILES = $(xml_files) \ $(desktop_DATA) \ $(service_DATA) \ $(autostart_DATA) \ $(NULL) SUBDIRS = \ icons \ $(NULL) install-data-hook: if ENABLE_UPDATE_MIMEDB $(UPDATE_MIME_DATABASE) "$(DESTDIR)$(datadir)/mime" endif uninstall-hook: if ENABLE_UPDATE_MIMEDB $(UPDATE_MIME_DATABASE) "$(DESTDIR)$(datadir)/mime" endif nemo-3.6.5/data/nemo-autorun-software.desktop.in.in0000664000175000017500000001315713215733314021217 0ustar fabiofabio[Desktop Entry] Name=Autorun Prompt Name[af]=Autorun Prompt Name[am]=Autorun Prompt Name[ar]=محث التنÙيذ التلقائي Name[as]=অটোৰান সংকà§à§°à¦¾à¦¨à§à¦¤ পà§à§°à¦®à¦ªà§à¦Ÿ Name[ast]=Programa d'autoexecución Name[az]=Autorun Prompt Name[az_IR]=Autorun Prompt Name[be]=ПацвÑрджÑнне аўтаматычнага запуÑку Name[be@latin]=Zapyt aÅ­tamatyÄnaha Å­ruchamleÅ„nia Name[bg]=Питане за автоматично Ñтартиране Name[bg_BG]=Питане за автоматично Ñтартиране Name[bn]=অটোরান সংকà§à¦°à¦¾à¦¨à§à¦¤ পà§à¦°à§‹à¦®à¦ªà§à¦Ÿ Name[bn_IN]=অটোরান সংকà§à¦°à¦¾à¦¨à§à¦¤ পà§à¦°à¦®à¦ªà§à¦Ÿ Name[bo]=རང་འགུལ་གྱིས་འà½à½¼à½¢à¼‹à½¦à¾à¾±à½¼à½‘་ལ་གསལ་འདེབས་ Name[br]=Pedadenn emerounit Name[ca]=Pregunta d'execució automàtica Name[ca@valencia]=Pregunta d'execució automàtica Name[crh]=KendiliÄŸinden Çalışma Sorusu Name[cs]=Výzva automatického spuÅ¡tÄ›ní Name[da]=Autokørselsforespørgsel Name[de]=Autostart-Nachfrage Name[de_CH]=Autostart-Nachfrage Name[de_DE]=Autostart-Nachfrage Name[dz]=Autorun Prompt Name[el]=Ειδοποίηση αυτόματης εκτέλεσης Name[en@shaw]=Autorun Prompt Name[en_AU]=Autorun Prompt Name[en_CA]=Autorun Prompt Name[en_GB]=Autorun Prompt Name[eo]=AÅ­tomata lanĉinvito Name[es]=Pregunta de autoejecución Name[es_AR]=Pregunta de autoejecución Name[es_CL]=Pregunta de autoejecución Name[es_CO]=Pregunta de autoejecución Name[es_CR]=Pregunta de autoejecución Name[es_DO]=Pregunta de autoejecución Name[es_EC]=Pregunta de autoejecución Name[es_ES]=Pregunta de autoejecución Name[es_GT]=Pregunta de autoejecución Name[es_HN]=Pregunta de autoejecución Name[es_MX]=Pregunta de autoejecución Name[es_NI]=Pregunta de autoejecución Name[es_PA]=Pregunta de autoejecución Name[es_PE]=Pregunta de autoejecución Name[es_PR]=Pregunta de autoejecución Name[es_SV]=Pregunta de autoejecución Name[es_UY]=Pregunta de autoejecución Name[es_VE]=Pregunta de autoejecución Name[et]=Automaatkäivituse küsimus Name[et_EE]=Automaatkäivituse küsimus Name[eu]=Autoexekuzioaren galdera Name[fa]=اعلان اجرای خودکار Name[fa_IR]=اعلان اجرای خودکار Name[fi]=Automaattisuorituksen kehote Name[fr]=Invite d'exécution automatique Name[fur]=Autorun Prompt Name[fy]=Autorun Prompt Name[ga]=Autorun Prompt Name[gl]=Preguntar polo autoarrinque Name[gu]=પà«àª°à«‹àª®à«àªªà«àªŸàª¨à«‡ આપમેળે ચલાવો Name[gv]=Roie choonee hene Name[ha]=Autorun Prompt Name[he]=בקשה להפעלה ×וטומטית Name[hi]=सà¥à¤µà¤¤à¤ƒ चलाà¤à¤ पà¥à¤°à¤¾à¤‚पà¥à¤Ÿ Name[hr]=Autorun Prompt Name[hu]=Automatikus futtatás Name[hy]=Autorun Prompt Name[id]=Sapaan Jalan Otomatis Name[ig]=Autorun Prompt Name[io]=Autorun Prompt Name[is]=Sjálfkeyrslukvaðning Name[it]=Conferma esecuzione automatica Name[it_IT]=Conferma esecuzione automatica Name[ja]=オートランã®å•ã„åˆã‚ã› Name[ka]=áƒáƒ•ტáƒ-გáƒáƒ¨áƒ•ების შემáƒáƒ—áƒáƒ•áƒáƒ–ებრName[kk]=Autorun Prompt Name[km]=Autorun Prompt Name[kn]=ತಾನಾಗಿಯೆ ಚಲಾಯಿಸà³à²µ ಪà³à²°à²¾à²ªà³à²Ÿà³ Name[ko]=ìžë™ì‹œìž‘ í™•ì¸ Name[ku]=Autorun Prompt Name[li]=Autorun Prompt Name[lt]=Automatinio paleidimo raginimas Name[lv]=AutomÄtiskÄs palaiÅ¡anas uzvedne Name[mai]=Autorun Prompt Name[mg]=Autorun Prompt Name[mi]=Autorun Prompt Name[mk]=ÐвтоматÑко извршување Name[ml]=Autorun Prompt Name[mn]=Autorun Prompt Name[mr]=पà¥à¤°à¥‰à¤®à¤ªà¥à¤Ÿ आपोआप चालवा Name[ms]=Desakan Lari auto Name[ms_MY]=Desakan Lari auto Name[my]=Autorun Prompt Name[my_MM]=Autorun Prompt Name[nb]=Dialog for automatisk kjøring Name[nds]=Autorun Avfrage Name[ne]=Autorun Prompt Name[nl]=Autorun dialoogvenster Name[nl_NL]=Autorun dialoogvenster Name[nso]=Autorun Prompt Name[oc]=Demanda d'execucion automatica Name[or]=ସà­à­±à­Ÿà¬‚ଚାଳନ ପà­à¬°à­‹à¬®à­à¬ªà¬Ÿ Name[pa]=ਆਟੋ-ਰਨ ਸਵਾਲ Name[pl]=Pytanie o automatyczne uruchamianie Name[ps]=Autorun Prompt Name[pt]=Questão de Execução Automática Name[pt_BR]=Pergunta de execução automática Name[pt_PT]=Questão de Execução Automática Name[ro]=Solicitare pornire automată Name[ru]=Предложение автозапуÑка Name[si]=Autorun Prompt Name[sk]=Výzva automatického spustenia Name[sl]=Poziv samodejnega zagona Name[sr]=ÐутоматÑко покретање Name[sr@Latn]=Automatsko pokretanje Name[sr@ije]=ÐутоматÑко покретање Name[sr@latin]=Automatsko pokretanje Name[sv]=Automatisk körning Name[ta]=தானியஙà¯à®•ி தூணà¯à®Ÿà®¿ Name[ta_LK]=தானியஙà¯à®•ி தூணà¯à®Ÿà®¿ Name[te]=à°¸à±à°µà°¯à°‚చాలకంగా à°…à°¡à±à°—à± Name[th]=คำถาม Autorun Name[tk]=Autorun Prompt Name[tr]=KendiliÄŸinden Çalışma Sorusu Name[ug]=ئۆزلۈكىدىن ئىجرا ئەسكەرتىشى Name[uk]=ÐŸÑ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ Ð°Ð²Ñ‚Ð¾Ð·Ð°Ð¿ÑƒÑку Name[uz]=Autorun Prompt Name[uz@cyrillic]=Autorun Prompt Name[vi]=Há»i tá»± động chạy Name[wa]=Autorun Prompt Name[yi]=Autorun Prompt Name[yo]=Autorun Prompt Name[zh]=自动è¿è¡Œæç¤º Name[zh_CN]=自动è¿è¡Œæç¤º Name[zh_HK]=自動執行æç¤º Name[zh_TW]=自動執行æç¤º Name[zu]=Autorun Prompt TryExec=nemo-autorun-software Exec=nemo-autorun-software %u Icon=application-x-executable NoDisplay=true Terminal=false StartupNotify=false Type=Application MimeType=x-content/unix-software; X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Product=nemo X-GNOME-Bugzilla-Component=general X-GNOME-Bugzilla-Version=@VERSION@ nemo-3.6.5/data/nemo-suggested.placeholder0000664000175000017500000000010013215733314017443 0ustar fabiofabioThis file is a placeholder for the nemo suggested meta-package nemo-3.6.5/data/extract_action_strings0000775000175000017500000000417313215733314017035 0ustar fabiofabio#!/usr/bin/python3 import os import glob import datetime import sys import codecs from gi.repository import GLib GROUP = "Nemo Action" class Main: def __init__(self): if len(sys.argv) > 1: action_files = glob.glob(os.path.join(sys.argv[1], "*.nemo_action.in")) else: action_files = glob.glob(os.path.join(os.getcwd(), "*.nemo_action.in")) if len(action_files) > 0: dt = datetime.datetime outstring = """ ''' This is a dummy file for translating Nemo Action files It was generated by the extract_action_strings script on %s UTC. ''' """ % (dt.utcnow()) outstring += "\n" for fn in action_files: keyfile = GLib.KeyFile.new() if keyfile.load_from_file(fn, GLib.KeyFileFlags.NONE): if keyfile.has_group(GROUP): friendly_fn = os.path.split(fn)[1].replace(".", "_") try: name = keyfile.get_string(GROUP, "Name") name_line = '%s_Name = _("%s")\n' % (friendly_fn, name) outstring += (name_line) except GLib.GError: name = None try: tooltip = keyfile.get_string(GROUP, "Comment") tooltip_line = '%s_Tooltip = _("%s")\n' % (friendly_fn, tooltip) outstring += (tooltip_line) except GLib.GError: tooltip = None if len(sys.argv) > 1: outfilename = os.path.join(sys.argv[1], "action_i18n_strings.py") else: outfilename = os.path.join(os.getcwd(), "action_i18n_strings.py") if os.path.exists(outfilename): os.remove(outfilename) outfile = codecs.open(outfilename, 'w', 'utf-8') outfile.write(outstring) outfile.close() print("Extraction complete. Run makepot now") if __name__ == "__main__": Main() nemo-3.6.5/data/nemo.service.in0000664000175000017500000000010413215733314015242 0ustar fabiofabio[D-BUS Service] Name=org.Nemo Exec=@bindir@/nemo --no-default-windownemo-3.6.5/data/90_new-workspace.nemo_action.in0000664000175000017500000000044413215733314020243 0ustar fabiofabio[Nemo Action] Name=Jump to new workspace Comment=Create a new workspace and activate it Exec=sh -c 'dbus-send --dest=org.Cinnamon --print-reply /org/Cinnamon org.Cinnamon.JumpToNewWorkspace >/dev/null' Selection=None Extensions=any; Conditions=desktop;dbus org.Cinnamon; Active=false nemo-3.6.5/data/freedesktop-dbus-interfaces.xml0000664000175000017500000000276313215733314020443 0ustar fabiofabio nemo-3.6.5/m4/0000775000175000017500000000000013215733314011731 5ustar fabiofabionemo-3.6.5/m4/intltool.m40000664000175000017500000002636113215733314014047 0ustar fabiofabio## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*- ## Copyright (C) 2001 Eazel, Inc. ## Author: Maciej Stachowiak ## Kenneth Christiansen ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ## ## As a special exception to the GNU General Public License, if you ## distribute this file as part of a program that contains a ## configuration script generated by Autoconf, you may include it under ## the same distribution terms that you use for the rest of that program. dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) # serial 42 IT_PROG_INTLTOOL AC_DEFUN([IT_PROG_INTLTOOL], [ AC_PREREQ([2.50])dnl AC_REQUIRE([AM_NLS])dnl case "$am__api_version" in 1.[01234]) AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool]) ;; *) ;; esac INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` if test -n "$1"; then AC_MSG_CHECKING([for intltool >= $1]) AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.]) fi AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update]) AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge]) AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract]) if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi AC_SUBST([AM_DEFAULT_VERBOSITY]) INTLTOOL_V_MERGE='$(INTLTOOL__v_MERGE_$(V))' INTLTOOL__v_MERGE_='$(INTLTOOL__v_MERGE_$(AM_DEFAULT_VERBOSITY))' INTLTOOL__v_MERGE_0='@echo " ITMRG " [$]@;' AC_SUBST(INTLTOOL_V_MERGE) AC_SUBST(INTLTOOL__v_MERGE_) AC_SUBST(INTLTOOL__v_MERGE_0) INTLTOOL_V_MERGE_OPTIONS='$(intltool__v_merge_options_$(V))' intltool__v_merge_options_='$(intltool__v_merge_options_$(AM_DEFAULT_VERBOSITY))' intltool__v_merge_options_0='-q' AC_SUBST(INTLTOOL_V_MERGE_OPTIONS) AC_SUBST(intltool__v_merge_options_) AC_SUBST(intltool__v_merge_options_0) INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -p $(top_srcdir)/po $< [$]@' INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' if test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge 5000; then INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u --no-translations $< [$]@' else INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; $(INTLTOOL_V_MERGE)_it_tmp_dir=tmp.intltool.[$][$]RANDOM && mkdir [$][$]_it_tmp_dir && LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u [$][$]_it_tmp_dir $< [$]@ && rmdir [$][$]_it_tmp_dir' fi INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_V_MERGE)LC_ALL=C $(INTLTOOL_MERGE) $(INTLTOOL_V_MERGE_OPTIONS) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' _IT_SUBST(INTLTOOL_DESKTOP_RULE) _IT_SUBST(INTLTOOL_DIRECTORY_RULE) _IT_SUBST(INTLTOOL_KEYS_RULE) _IT_SUBST(INTLTOOL_PROP_RULE) _IT_SUBST(INTLTOOL_OAF_RULE) _IT_SUBST(INTLTOOL_PONG_RULE) _IT_SUBST(INTLTOOL_SERVER_RULE) _IT_SUBST(INTLTOOL_SHEET_RULE) _IT_SUBST(INTLTOOL_SOUNDLIST_RULE) _IT_SUBST(INTLTOOL_UI_RULE) _IT_SUBST(INTLTOOL_XAM_RULE) _IT_SUBST(INTLTOOL_KBD_RULE) _IT_SUBST(INTLTOOL_XML_RULE) _IT_SUBST(INTLTOOL_XML_NOMERGE_RULE) _IT_SUBST(INTLTOOL_CAVES_RULE) _IT_SUBST(INTLTOOL_SCHEMAS_RULE) _IT_SUBST(INTLTOOL_THEME_RULE) _IT_SUBST(INTLTOOL_SERVICE_RULE) _IT_SUBST(INTLTOOL_POLICY_RULE) # Check the gettext tools to make sure they are GNU AC_PATH_PROG(XGETTEXT, xgettext) AC_PATH_PROG(MSGMERGE, msgmerge) AC_PATH_PROG(MSGFMT, msgfmt) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) fi xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) fi AC_PATH_PROG(INTLTOOL_PERL, perl) if test -z "$INTLTOOL_PERL"; then AC_MSG_ERROR([perl not found]) fi AC_MSG_CHECKING([for perl >= 5.8.1]) $INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 if test $? -ne 0; then AC_MSG_ERROR([perl 5.8.1 is required for intltool]) else IT_PERL_VERSION=`$INTLTOOL_PERL -e "printf '%vd', $^V"` AC_MSG_RESULT([$IT_PERL_VERSION]) fi if test "x$2" != "xno-xml"; then AC_MSG_CHECKING([for XML::Parser]) if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then AC_MSG_RESULT([ok]) else AC_MSG_ERROR([XML::Parser perl module is required for intltool]) fi fi # Substitute ALL_LINGUAS so we can use it in po/Makefile AC_SUBST(ALL_LINGUAS) IT_PO_SUBDIR([po]) ]) # IT_PO_SUBDIR(DIRNAME) # --------------------- # All po subdirs have to be declared with this macro; the subdir "po" is # declared by IT_PROG_INTLTOOL. # AC_DEFUN([IT_PO_SUBDIR], [AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS. dnl dnl The following CONFIG_COMMANDS should be executed at the very end dnl of config.status. AC_CONFIG_COMMANDS_PRE([ AC_CONFIG_COMMANDS([$1/stamp-it], [ if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.]) fi rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp" >"$1/stamp-it.tmp" [sed '/^#/d s/^[[].*] *// /^[ ]*$/d '"s|^| $ac_top_srcdir/|" \ "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES" ] [sed '/^POTFILES =/,/[^\\]$/ { /^POTFILES =/!d r $1/POTFILES } ' "$1/Makefile.in" >"$1/Makefile"] rm -f "$1/Makefile.tmp" mv "$1/stamp-it.tmp" "$1/stamp-it" ]) ])dnl ]) # _IT_SUBST(VARIABLE) # ------------------- # Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST # AC_DEFUN([_IT_SUBST], [ AC_SUBST([$1]) m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) ] ) # deprecated macros AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL]) # A hint is needed for aclocal from Automake <= 1.9.4: # AC_DEFUN([AC_PROG_INTLTOOL], ...) nemo-3.6.5/m4/ltversion.m40000664000175000017500000000127313215733314014223 0ustar fabiofabio# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) nemo-3.6.5/m4/gtk-doc.m40000664000175000017500000000631213215733314013525 0ustar fabiofabiodnl -*- mode: autoconf -*- # serial 2 dnl Usage: dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) AC_DEFUN([GTK_DOC_CHECK], [ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"]) AC_MSG_CHECKING([for gtk-doc]) PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no]) AC_MSG_RESULT($have_gtk_doc) if test "$have_gtk_doc" = "no"; then AC_MSG_WARN([ You will not be able to create source packages with 'make dist' because $gtk_doc_requires is not found.]) fi dnl check for tools we added during development dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that dnl may not be writable by the user. Currently, automake requires that the dnl test name must end in '.test'. dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638 AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test]) AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check]) AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) dnl for overriding the documentation installation directory AC_ARG_WITH([html-dir], AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, [with_html_dir='${datadir}/gtk-doc/html']) HTML_DIR="$with_html_dir" AC_SUBST([HTML_DIR]) dnl enable/disable documentation building AC_ARG_ENABLE([gtk-doc], AS_HELP_STRING([--enable-gtk-doc], [use gtk-doc to build documentation [[default=no]]]),, [enable_gtk_doc=no]) AC_MSG_CHECKING([whether to build gtk-doc documentation]) AC_MSG_RESULT($enable_gtk_doc) if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then AC_MSG_ERROR([ You must have $gtk_doc_requires installed to build documentation for $PACKAGE_NAME. Please install gtk-doc or disable building the documentation by adding '--disable-gtk-doc' to '[$]0'.]) fi dnl don't check for glib if we build glib if test "x$PACKAGE_NAME" != "xglib"; then dnl don't fail if someone does not have glib PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) fi dnl enable/disable output formats AC_ARG_ENABLE([gtk-doc-html], AS_HELP_STRING([--enable-gtk-doc-html], [build documentation in html format [[default=yes]]]),, [enable_gtk_doc_html=yes]) AC_ARG_ENABLE([gtk-doc-pdf], AS_HELP_STRING([--enable-gtk-doc-pdf], [build documentation in pdf format [[default=no]]]),, [enable_gtk_doc_pdf=no]) if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi AC_SUBST([AM_DEFAULT_VERBOSITY]) AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes]) AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) ]) nemo-3.6.5/m4/lt~obsolete.m40000664000175000017500000001377413215733314014561 0ustar fabiofabio# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) nemo-3.6.5/m4/ltsugar.m40000664000175000017500000001044013215733314013653 0ustar fabiofabio# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) nemo-3.6.5/m4/ltoptions.m40000664000175000017500000003426213215733314014235 0ustar fabiofabio# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) nemo-3.6.5/AUTHORS0000664000175000017500000000006613215733314012463 0ustar fabiofabiohttps://github.com/linuxmint/nemo/graphs/contributors nemo-3.6.5/THANKS0000664000175000017500000000011013215733314012314 0ustar fabiofabioNemo started as a fork of Nautilus 3.4: https://live.gnome.org/Nautilus nemo-3.6.5/polkit.loc0000664000175000017500000000030213215733314013405 0ustar fabiofabio nemo-3.6.5/Makefile.am0000664000175000017500000000251613215733314013451 0ustar fabiofabioinclude $(top_srcdir)/Makefile.shared DIRS = \ eel \ libnemo-extension \ cut-n-paste-code \ libnemo-private \ src \ test \ po \ data \ icons \ docs \ files \ $(NULL) DIST_SUBDIRS = $(DIRS) SUBDIRS = $(DIRS) EXTRA_DIST= \ COPYING.LIB \ COPYING.EXTENSIONS \ COPYING-DOCS \ HACKING \ MAINTAINERS \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ Makefile.shared \ add-include-prefix \ $(NULL) DISTCLEANFILES = \ intltool-extract \ intltool-merge \ intltool-update DISTCHECK_CONFIGURE_FLAGS = --disable-update-mimedb --enable-gtk-doc distclean-local: if test "$(srcdir)" = "."; then :; else \ rm -f ChangeLog; \ fi ChangeLog: @echo Creating $@ @if test -d "$(srcdir)/.git"; then \ (GIT_DIR=$(top_srcdir)/.git ./missing --run git log NEMO_2_26_2.. --stat -M -C --name-status --date=short --no-color) | fmt --split-only > $@.tmp \ && mv -f $@.tmp $@ \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ (test -f $@ || echo git-log is required to generate this file >> $@)); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ echo A git checkout and git-log is required to generate this file >> $@); \ fi .PHONY: ChangeLog nemo-3.6.5/INSTALL0000664000175000017500000003661013215733314012450 0ustar fabiofabioInstallation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command `./configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. nemo-3.6.5/cut-n-paste-code/0000775000175000017500000000000013215733314014461 5ustar fabiofabionemo-3.6.5/cut-n-paste-code/libegg/0000775000175000017500000000000013215733314015712 5ustar fabiofabionemo-3.6.5/cut-n-paste-code/libegg/eggtreemultidnd.h0000664000175000017500000000614513215733314021254 0ustar fabiofabio/* eggtreednd.h * Copyright (C) 2001 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifndef __EGG_TREE_MULTI_DND_H__ #define __EGG_TREE_MULTI_DND_H__ #include G_BEGIN_DECLS #define EGG_TYPE_TREE_MULTI_DRAG_SOURCE (egg_tree_multi_drag_source_get_type ()) #define EGG_TREE_MULTI_DRAG_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TREE_MULTI_DRAG_SOURCE, EggTreeMultiDragSource)) #define EGG_IS_TREE_MULTI_DRAG_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TREE_MULTI_DRAG_SOURCE)) #define EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EGG_TYPE_TREE_MULTI_DRAG_SOURCE, EggTreeMultiDragSourceIface)) typedef struct _EggTreeMultiDragSource EggTreeMultiDragSource; /* Dummy typedef */ typedef struct _EggTreeMultiDragSourceIface EggTreeMultiDragSourceIface; struct _EggTreeMultiDragSourceIface { GTypeInterface g_iface; /* VTable - not signals */ gboolean (* row_draggable) (EggTreeMultiDragSource *drag_source, GList *path_list); gboolean (* drag_data_get) (EggTreeMultiDragSource *drag_source, GList *path_list, GtkSelectionData *selection_data); gboolean (* drag_data_delete) (EggTreeMultiDragSource *drag_source, GList *path_list); }; GType egg_tree_multi_drag_source_get_type (void) G_GNUC_CONST; /* Returns whether the given row can be dragged */ gboolean egg_tree_multi_drag_source_row_draggable (EggTreeMultiDragSource *drag_source, GList *path_list); /* Deletes the given row, or returns FALSE if it can't */ gboolean egg_tree_multi_drag_source_drag_data_delete (EggTreeMultiDragSource *drag_source, GList *path_list); /* Fills in selection_data with type selection_data->target based on the row * denoted by path, returns TRUE if it does anything */ gboolean egg_tree_multi_drag_source_drag_data_get (EggTreeMultiDragSource *drag_source, GList *path_list, GtkSelectionData *selection_data); void egg_tree_multi_drag_add_drag_support (GtkTreeView *tree_view); G_END_DECLS #endif /* __EGG_TREE_MULTI_DND_H__ */ nemo-3.6.5/cut-n-paste-code/libegg/eggtreemultidnd.c0000664000175000017500000002662613215733314021255 0ustar fabiofabio/* eggtreemultidnd.c * Copyright (C) 2001 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "eggtreemultidnd.h" #define EGG_TREE_MULTI_DND_STRING "EggTreeMultiDndString" typedef struct { guint pressed_button; gint x; gint y; guint motion_notify_handler; guint button_release_handler; guint drag_data_get_handler; GSList *event_list; } EggTreeMultiDndData; /* CUT-N-PASTE from gtktreeview.c */ typedef struct _TreeViewDragInfo TreeViewDragInfo; struct _TreeViewDragInfo { GdkModifierType start_button_mask; GtkTargetList *source_target_list; GdkDragAction source_actions; GtkTargetList *dest_target_list; guint source_set : 1; guint dest_set : 1; }; GType egg_tree_multi_drag_source_get_type (void) { static GType our_type = 0; if (!our_type) { const GTypeInfo our_info = { sizeof (EggTreeMultiDragSourceIface), /* class_size */ NULL, /* base_init */ NULL, /* base_finalize */ NULL, NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, /* n_preallocs */ NULL }; our_type = g_type_register_static (G_TYPE_INTERFACE, "EggTreeMultiDragSource", &our_info, 0); } return our_type; } /** * egg_tree_multi_drag_source_row_draggable: * @drag_source: a #EggTreeMultiDragSource * @path: row on which user is initiating a drag * * Asks the #EggTreeMultiDragSource whether a particular row can be used as * the source of a DND operation. If the source doesn't implement * this interface, the row is assumed draggable. * * Return value: %TRUE if the row can be dragged **/ gboolean egg_tree_multi_drag_source_row_draggable (EggTreeMultiDragSource *drag_source, GList *path_list) { EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source); g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE); g_return_val_if_fail (iface->row_draggable != NULL, FALSE); g_return_val_if_fail (path_list != NULL, FALSE); if (iface->row_draggable) return (* iface->row_draggable) (drag_source, path_list); else return TRUE; } /** * egg_tree_multi_drag_source_drag_data_delete: * @drag_source: a #EggTreeMultiDragSource * @path: row that was being dragged * * Asks the #EggTreeMultiDragSource to delete the row at @path, because * it was moved somewhere else via drag-and-drop. Returns %FALSE * if the deletion fails because @path no longer exists, or for * some model-specific reason. Should robustly handle a @path no * longer found in the model! * * Return value: %TRUE if the row was successfully deleted **/ gboolean egg_tree_multi_drag_source_drag_data_delete (EggTreeMultiDragSource *drag_source, GList *path_list) { EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source); g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE); g_return_val_if_fail (iface->drag_data_delete != NULL, FALSE); g_return_val_if_fail (path_list != NULL, FALSE); return (* iface->drag_data_delete) (drag_source, path_list); } /** * egg_tree_multi_drag_source_drag_data_get: * @drag_source: a #EggTreeMultiDragSource * @path: row that was dragged * @selection_data: a #EggSelectionData to fill with data from the dragged row * * Asks the #EggTreeMultiDragSource to fill in @selection_data with a * representation of the row at @path. @selection_data->target gives * the required type of the data. Should robustly handle a @path no * longer found in the model! * * Return value: %TRUE if data of the required type was provided **/ gboolean egg_tree_multi_drag_source_drag_data_get (EggTreeMultiDragSource *drag_source, GList *path_list, GtkSelectionData *selection_data) { EggTreeMultiDragSourceIface *iface = EGG_TREE_MULTI_DRAG_SOURCE_GET_IFACE (drag_source); g_return_val_if_fail (EGG_IS_TREE_MULTI_DRAG_SOURCE (drag_source), FALSE); g_return_val_if_fail (iface->drag_data_get != NULL, FALSE); g_return_val_if_fail (path_list != NULL, FALSE); g_return_val_if_fail (selection_data != NULL, FALSE); return (* iface->drag_data_get) (drag_source, path_list, selection_data); } static void stop_drag_check (GtkWidget *widget) { EggTreeMultiDndData *priv_data; GSList *l; priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING); for (l = priv_data->event_list; l != NULL; l = l->next) gdk_event_free (l->data); g_slist_free (priv_data->event_list); priv_data->event_list = NULL; g_signal_handler_disconnect (widget, priv_data->motion_notify_handler); g_signal_handler_disconnect (widget, priv_data->button_release_handler); } static gboolean egg_tree_multi_drag_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer data) { EggTreeMultiDndData *priv_data; GSList *l; priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING); for (l = priv_data->event_list; l != NULL; l = l->next) gtk_propagate_event (widget, l->data); stop_drag_check (widget); return FALSE; } static void selection_foreach (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { GList **list_ptr; list_ptr = (GList **) data; *list_ptr = g_list_prepend (*list_ptr, gtk_tree_row_reference_new (model, path)); } static void path_list_free (GList *path_list) { g_list_foreach (path_list, (GFunc) gtk_tree_row_reference_free, NULL); g_list_free (path_list); } static void set_context_data (GdkDragContext *context, GList *path_list) { g_object_set_data_full (G_OBJECT (context), "egg-tree-view-multi-source-row", path_list, (GDestroyNotify) path_list_free); } static GList * get_context_data (GdkDragContext *context) { return g_object_get_data (G_OBJECT (context), "egg-tree-view-multi-source-row"); } /* CUT-N-PASTE from gtktreeview.c */ static TreeViewDragInfo* get_info (GtkTreeView *tree_view) { return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info"); } static void egg_tree_multi_drag_drag_data_get (GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time) { GtkTreeView *tree_view; GtkTreeModel *model; TreeViewDragInfo *di; GList *path_list; tree_view = GTK_TREE_VIEW (widget); model = gtk_tree_view_get_model (tree_view); if (model == NULL) return; di = get_info (GTK_TREE_VIEW (widget)); if (di == NULL) return; path_list = get_context_data (context); if (path_list == NULL) return; /* We can implement the GTK_TREE_MODEL_ROW target generically for * any model; for DragSource models there are some other targets * we also support. */ if (EGG_IS_TREE_MULTI_DRAG_SOURCE (model)) { egg_tree_multi_drag_source_drag_data_get (EGG_TREE_MULTI_DRAG_SOURCE (model), path_list, selection_data); } } static gboolean egg_tree_multi_drag_motion_event (GtkWidget *widget, GdkEventMotion *event, gpointer data) { EggTreeMultiDndData *priv_data; priv_data = g_object_get_data (G_OBJECT (widget), EGG_TREE_MULTI_DND_STRING); if (gtk_drag_check_threshold (widget, priv_data->x, priv_data->y, event->x, event->y)) { GList *path_list = NULL; GtkTreeSelection *selection; GtkTreeModel *model; GdkDragContext *context; TreeViewDragInfo *di; di = get_info (GTK_TREE_VIEW (widget)); if (di == NULL) return FALSE; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)); stop_drag_check (widget); gtk_tree_selection_selected_foreach (selection, selection_foreach, &path_list); path_list = g_list_reverse (path_list); model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); if (egg_tree_multi_drag_source_row_draggable (EGG_TREE_MULTI_DRAG_SOURCE (model), path_list)) { context = gtk_drag_begin (widget, gtk_drag_source_get_target_list (widget), di->source_actions, priv_data->pressed_button, (GdkEvent*)event); set_context_data (context, path_list); gtk_drag_set_icon_default (context); } else { path_list_free (path_list); } } return TRUE; } static gboolean egg_tree_multi_drag_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkTreeView *tree_view; GtkTreePath *path = NULL; GtkTreeViewColumn *column = NULL; gint cell_x, cell_y; GtkTreeSelection *selection; EggTreeMultiDndData *priv_data; tree_view = GTK_TREE_VIEW (widget); priv_data = g_object_get_data (G_OBJECT (tree_view), EGG_TREE_MULTI_DND_STRING); if (priv_data == NULL) { priv_data = g_new0 (EggTreeMultiDndData, 1); g_object_set_data (G_OBJECT (tree_view), EGG_TREE_MULTI_DND_STRING, priv_data); } if (g_slist_find (priv_data->event_list, event)) return FALSE; if (priv_data->event_list) { /* save the event to be propagated in order */ priv_data->event_list = g_slist_append (priv_data->event_list, gdk_event_copy ((GdkEvent*)event)); return TRUE; } if (event->type == GDK_2BUTTON_PRESS) return FALSE; gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y, &path, &column, &cell_x, &cell_y); selection = gtk_tree_view_get_selection (tree_view); if (path && gtk_tree_selection_path_is_selected (selection, path)) { priv_data->pressed_button = event->button; priv_data->x = event->x; priv_data->y = event->y; priv_data->event_list = g_slist_append (priv_data->event_list, gdk_event_copy ((GdkEvent*)event)); priv_data->motion_notify_handler = g_signal_connect (G_OBJECT (tree_view), "motion_notify_event", G_CALLBACK (egg_tree_multi_drag_motion_event), NULL); priv_data->button_release_handler = g_signal_connect (G_OBJECT (tree_view), "button_release_event", G_CALLBACK (egg_tree_multi_drag_button_release_event), NULL); if (priv_data->drag_data_get_handler == 0) { priv_data->drag_data_get_handler = g_signal_connect (G_OBJECT (tree_view), "drag_data_get", G_CALLBACK (egg_tree_multi_drag_drag_data_get), NULL); } gtk_tree_path_free (path); return TRUE; } if (path) { gtk_tree_path_free (path); } return FALSE; } void egg_tree_multi_drag_add_drag_support (GtkTreeView *tree_view) { g_return_if_fail (GTK_IS_TREE_VIEW (tree_view)); g_signal_connect (G_OBJECT (tree_view), "button_press_event", G_CALLBACK (egg_tree_multi_drag_button_press_event), NULL); } nemo-3.6.5/cut-n-paste-code/libegg/update-from-egg.sh0000775000175000017500000000062613215733314021240 0ustar fabiofabio#!/bin/sh function die() { echo $* exit 1 } if test -z "$EGGDIR"; then echo "Must set EGGDIR" exit 1 fi if test -z "$EGGFILES"; then echo "Must set EGGFILES" exit 1 fi for FILE in $EGGFILES; do if cmp -s $EGGDIR/$FILE $FILE; then echo "File $FILE is unchanged" else cp $EGGDIR/$FILE $FILE || die "Could not move $EGGDIR/$FILE to $FILE" echo "Updated $FILE" fi done nemo-3.6.5/cut-n-paste-code/libegg/Makefile.am0000664000175000017500000000110413215733314017742 0ustar fabiofabioNULL= noinst_LTLIBRARIES = libegg.la AM_CPPFLAGS = $(WARN_CFLAGS) $(BASE_CFLAGS) EGG_TREE_DND_FILES = \ eggtreemultidnd.c \ eggtreemultidnd.h \ $(NULL) libegg_la_SOURCES = \ $(EGG_TREE_DND_FILES) \ $(NULL) libegg_la_CFLAGS = \ $(BASE_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED) libegg_la_LIBADD = \ $(BASE_LIBS) EXTRA_DIST = \ update-from-egg.sh \ $(NULL) EGG_TREE_DND_DIR = $(srcdir)/../../../libegg/libegg/treeviewutils regenerate-built-sources: EGGFILES="$(EGG_TREE_DND_FILES)" EGGDIR="$(EGG_TREE_DND_DIR)" $(srcdir)/update-from-egg.sh nemo-3.6.5/cut-n-paste-code/README0000664000175000017500000000117113215733314015341 0ustar fabiofabioREADME for nemo/cut-n-paste-code The code in this directory hierarchy was cut-n-pasted from somewhere else. In the soon to come, Star Trek future, this code will be available as part of standard libraries. For example, the code in libegg will be one day available as part of Gtk+. Until that happens, DON'T HACK the code, unless you are updating from the original cut-n-paste source. Instead of hacking the code in cut-n-paste-code, create subclasses and put them in libnemo-extensions. If you have any specific questions, comments or complaints about this setup, send mail to the nemo mailing list at: nemo-list@gnome.org nemo-3.6.5/cut-n-paste-code/Makefile.am0000664000175000017500000000002213215733314016507 0ustar fabiofabioSUBDIRS = libegg nemo-3.6.5/eel/0000775000175000017500000000000013215733314012156 5ustar fabiofabionemo-3.6.5/eel/eel-editable-label.c0000664000175000017500000036677613215733314015744 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include #include #include #include "eel-editable-label.h" #include "eel-accessibility.h" #include #include #include #include #include enum { MOVE_CURSOR, POPULATE_POPUP, DELETE_FROM_CURSOR, CUT_CLIPBOARD, COPY_CLIPBOARD, PASTE_CLIPBOARD, TOGGLE_OVERWRITE, LAST_SIGNAL }; enum { PROP_0, PROP_TEXT, PROP_JUSTIFY, PROP_WRAP, PROP_CURSOR_POSITION, PROP_SELECTION_BOUND }; static guint signals[LAST_SIGNAL] = { 0 }; static void eel_editable_label_editable_init (GtkEditableInterface *iface); static void eel_editable_label_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void eel_editable_label_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void eel_editable_label_finalize (GObject *object); static void eel_editable_label_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural); static void eel_editable_label_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural); static void eel_editable_label_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static void eel_editable_label_state_changed (GtkWidget *widget, GtkStateType state); static void eel_editable_label_style_updated (GtkWidget *widget); static void eel_editable_label_direction_changed (GtkWidget *widget, GtkTextDirection previous_dir); static gint eel_editable_label_draw (GtkWidget *widget, cairo_t *cr); static void eel_editable_label_realize (GtkWidget *widget); static void eel_editable_label_unrealize (GtkWidget *widget); static void eel_editable_label_map (GtkWidget *widget); static void eel_editable_label_unmap (GtkWidget *widget); static gint eel_editable_label_button_press (GtkWidget *widget, GdkEventButton *event); static gint eel_editable_label_button_release (GtkWidget *widget, GdkEventButton *event); static gint eel_editable_label_motion (GtkWidget *widget, GdkEventMotion *event); static gint eel_editable_label_key_press (GtkWidget *widget, GdkEventKey *event); static gint eel_editable_label_key_release (GtkWidget *widget, GdkEventKey *event); static gint eel_editable_label_focus_in (GtkWidget *widget, GdkEventFocus *event); static gint eel_editable_label_focus_out (GtkWidget *widget, GdkEventFocus *event); static AtkObject *eel_editable_label_get_accessible (GtkWidget *widget); static void eel_editable_label_commit_cb (GtkIMContext *context, const gchar *str, EelEditableLabel *label); static void eel_editable_label_preedit_changed_cb (GtkIMContext *context, EelEditableLabel *label); static gboolean eel_editable_label_retrieve_surrounding_cb (GtkIMContext *context, EelEditableLabel *label); static gboolean eel_editable_label_delete_surrounding_cb (GtkIMContext *slave, gint offset, gint n_chars, EelEditableLabel *label); static void eel_editable_label_clear_layout (EelEditableLabel *label); static void eel_editable_label_recompute (EelEditableLabel *label); static void eel_editable_label_ensure_layout (EelEditableLabel *label, gboolean include_preedit); static void eel_editable_label_select_region_index (EelEditableLabel *label, gint anchor_index, gint end_index); static gboolean eel_editable_label_focus (GtkWidget *widget, GtkDirectionType direction); static void eel_editable_label_move_cursor (EelEditableLabel *label, GtkMovementStep step, gint count, gboolean extend_selection); static void eel_editable_label_delete_from_cursor (EelEditableLabel *label, GtkDeleteType type, gint count); static void eel_editable_label_copy_clipboard (EelEditableLabel *label); static void eel_editable_label_cut_clipboard (EelEditableLabel *label); static void eel_editable_label_paste (EelEditableLabel *label, GdkAtom selection); static void eel_editable_label_paste_clipboard (EelEditableLabel *label); static void eel_editable_label_select_all (EelEditableLabel *label); static void eel_editable_label_do_popup (EelEditableLabel *label, GdkEventButton *event); static void eel_editable_label_toggle_overwrite (EelEditableLabel *label); static gint eel_editable_label_move_forward_word (EelEditableLabel *label, gint start); static gint eel_editable_label_move_backward_word (EelEditableLabel *label, gint start); static void eel_editable_label_reset_im_context (EelEditableLabel *label); static void eel_editable_label_check_cursor_blink (EelEditableLabel *label); static void eel_editable_label_pend_cursor_blink (EelEditableLabel *label); /* Editable implementation: */ static void editable_insert_text_emit (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position); static void editable_delete_text_emit (GtkEditable *editable, gint start_pos, gint end_pos); static void editable_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position); static void editable_delete_text (GtkEditable *editable, gint start_pos, gint end_pos); static gchar * editable_get_chars (GtkEditable *editable, gint start_pos, gint end_pos); static void editable_set_selection_bounds (GtkEditable *editable, gint start, gint end); static gboolean editable_get_selection_bounds (GtkEditable *editable, gint *start, gint *end); static void editable_real_set_position (GtkEditable *editable, gint position); static gint editable_get_position (GtkEditable *editable); G_DEFINE_TYPE_WITH_CODE (EelEditableLabel, eel_editable_label, GTK_TYPE_MISC, G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, eel_editable_label_editable_init)); static void add_move_binding (GtkBindingSet *binding_set, guint keyval, guint modmask, GtkMovementStep step, gint count) { g_assert ((modmask & GDK_SHIFT_MASK) == 0); gtk_binding_entry_add_signal (binding_set, keyval, modmask, "move_cursor", 3, G_TYPE_ENUM, step, G_TYPE_INT, count, G_TYPE_BOOLEAN, FALSE); /* Selection-extending version */ gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK, "move_cursor", 3, G_TYPE_ENUM, step, G_TYPE_INT, count, G_TYPE_BOOLEAN, TRUE); } static void eel_editable_label_class_init (EelEditableLabelClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); GtkBindingSet *binding_set; gobject_class->set_property = eel_editable_label_set_property; gobject_class->get_property = eel_editable_label_get_property; gobject_class->finalize = eel_editable_label_finalize; widget_class->get_preferred_width = eel_editable_label_get_preferred_width; widget_class->get_preferred_height = eel_editable_label_get_preferred_height; widget_class->size_allocate = eel_editable_label_size_allocate; widget_class->state_changed = eel_editable_label_state_changed; widget_class->style_updated = eel_editable_label_style_updated; widget_class->direction_changed = eel_editable_label_direction_changed; widget_class->draw = eel_editable_label_draw; widget_class->realize = eel_editable_label_realize; widget_class->unrealize = eel_editable_label_unrealize; widget_class->map = eel_editable_label_map; widget_class->unmap = eel_editable_label_unmap; widget_class->button_press_event = eel_editable_label_button_press; widget_class->button_release_event = eel_editable_label_button_release; widget_class->motion_notify_event = eel_editable_label_motion; widget_class->focus = eel_editable_label_focus; widget_class->key_press_event = eel_editable_label_key_press; widget_class->key_release_event = eel_editable_label_key_release; widget_class->focus_in_event = eel_editable_label_focus_in; widget_class->focus_out_event = eel_editable_label_focus_out; widget_class->get_accessible = eel_editable_label_get_accessible; class->move_cursor = eel_editable_label_move_cursor; class->delete_from_cursor = eel_editable_label_delete_from_cursor; class->copy_clipboard = eel_editable_label_copy_clipboard; class->cut_clipboard = eel_editable_label_cut_clipboard; class->paste_clipboard = eel_editable_label_paste_clipboard; class->toggle_overwrite = eel_editable_label_toggle_overwrite; signals[MOVE_CURSOR] = g_signal_new ("move_cursor", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, move_cursor), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, G_TYPE_INT, G_TYPE_BOOLEAN); signals[COPY_CLIPBOARD] = g_signal_new ("copy_clipboard", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, copy_clipboard), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[POPULATE_POPUP] = g_signal_new ("populate_popup", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (EelEditableLabelClass, populate_popup), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_MENU); signals[DELETE_FROM_CURSOR] = g_signal_new ("delete_from_cursor", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, delete_from_cursor), NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, GTK_TYPE_DELETE_TYPE, G_TYPE_INT); signals[CUT_CLIPBOARD] = g_signal_new ("cut_clipboard", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, cut_clipboard), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[PASTE_CLIPBOARD] = g_signal_new ("paste_clipboard", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, paste_clipboard), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[TOGGLE_OVERWRITE] = g_signal_new ("toggle_overwrite", G_TYPE_FROM_CLASS (class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EelEditableLabelClass, toggle_overwrite), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_object_class_install_property (gobject_class, PROP_TEXT, g_param_spec_string ("text", _("Text"), _("The text of the label."), NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_JUSTIFY, g_param_spec_enum ("justify", _("Justification"), _("The alignment of the lines in the text of the label relative to each other. This does NOT affect the alignment of the label within its allocation. See GtkMisc::xalign for that."), GTK_TYPE_JUSTIFICATION, GTK_JUSTIFY_LEFT, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_WRAP, g_param_spec_boolean ("wrap", _("Line wrap"), _("If set, wrap lines if the text becomes too wide."), FALSE, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CURSOR_POSITION, g_param_spec_int ("cursor_position", _("Cursor Position"), _("The current position of the insertion cursor in chars."), 0, G_MAXINT, 0, G_PARAM_READABLE)); g_object_class_install_property (gobject_class, PROP_SELECTION_BOUND, g_param_spec_int ("selection_bound", _("Selection Bound"), _("The position of the opposite end of the selection from the cursor in chars."), 0, G_MAXINT, 0, G_PARAM_READABLE)); /* * Key bindings */ binding_set = gtk_binding_set_by_class (class); /* Moving the insertion point */ add_move_binding (binding_set, GDK_KEY_Right, 0, GTK_MOVEMENT_VISUAL_POSITIONS, 1); add_move_binding (binding_set, GDK_KEY_Left, 0, GTK_MOVEMENT_VISUAL_POSITIONS, -1); add_move_binding (binding_set, GDK_KEY_KP_Right, 0, GTK_MOVEMENT_VISUAL_POSITIONS, 1); add_move_binding (binding_set, GDK_KEY_KP_Left, 0, GTK_MOVEMENT_VISUAL_POSITIONS, -1); add_move_binding (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, GTK_MOVEMENT_LOGICAL_POSITIONS, 1); add_move_binding (binding_set, GDK_KEY_b, GDK_CONTROL_MASK, GTK_MOVEMENT_LOGICAL_POSITIONS, -1); add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, 1); add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, -1); add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, 1); add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK, GTK_MOVEMENT_WORDS, -1); add_move_binding (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, GTK_MOVEMENT_PARAGRAPH_ENDS, -1); add_move_binding (binding_set, GDK_KEY_e, GDK_CONTROL_MASK, GTK_MOVEMENT_PARAGRAPH_ENDS, 1); add_move_binding (binding_set, GDK_KEY_f, GDK_MOD1_MASK, GTK_MOVEMENT_WORDS, 1); add_move_binding (binding_set, GDK_KEY_b, GDK_MOD1_MASK, GTK_MOVEMENT_WORDS, -1); add_move_binding (binding_set, GDK_KEY_Home, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1); add_move_binding (binding_set, GDK_KEY_End, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1); add_move_binding (binding_set, GDK_KEY_KP_Home, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1); add_move_binding (binding_set, GDK_KEY_KP_End, 0, GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1); add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_MOVEMENT_BUFFER_ENDS, -1); add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK, GTK_MOVEMENT_BUFFER_ENDS, 1); add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK, GTK_MOVEMENT_BUFFER_ENDS, -1); add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK, GTK_MOVEMENT_BUFFER_ENDS, 1); add_move_binding (binding_set, GDK_KEY_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1); add_move_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1); add_move_binding (binding_set, GDK_KEY_Down, 0, GTK_MOVEMENT_DISPLAY_LINES, 1); add_move_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_MOVEMENT_DISPLAY_LINES, 1); /* Select all */ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "move_cursor", 3, GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS, G_TYPE_INT, -1, G_TYPE_BOOLEAN, FALSE); gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "move_cursor", 3, GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS, G_TYPE_INT, 1, G_TYPE_BOOLEAN, TRUE); /* Deleting text */ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_CHARS, G_TYPE_INT, 1); gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_CHARS, G_TYPE_INT, 1); gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_CHARS, G_TYPE_INT, -1); /* Make this do the same as Backspace, to help with mis-typing */ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_CHARS, G_TYPE_INT, -1); gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_WORD_ENDS, G_TYPE_INT, 1); gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_WORD_ENDS, G_TYPE_INT, 1); gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, GTK_DELETE_WORD_ENDS, G_TYPE_INT, -1); /* Cut/copy/paste */ gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK, "cut_clipboard", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK, "copy_clipboard", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK, "paste_clipboard", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK, "cut_clipboard", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK, "copy_clipboard", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK, "paste_clipboard", 0); /* Overwrite */ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0, "toggle_overwrite", 0); gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0, "toggle_overwrite", 0); } static void eel_editable_label_editable_init (GtkEditableInterface *iface) { iface->do_insert_text = editable_insert_text_emit; iface->do_delete_text = editable_delete_text_emit; iface->insert_text = editable_insert_text; iface->delete_text = editable_delete_text; iface->get_chars = editable_get_chars; iface->set_selection_bounds = editable_set_selection_bounds; iface->get_selection_bounds = editable_get_selection_bounds; iface->set_position = editable_real_set_position; iface->get_position = editable_get_position; } static void eel_editable_label_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (object); switch (prop_id) { case PROP_TEXT: eel_editable_label_set_text (label, g_value_get_string (value)); break; case PROP_JUSTIFY: eel_editable_label_set_justify (label, g_value_get_enum (value)); break; case PROP_WRAP: eel_editable_label_set_line_wrap (label, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eel_editable_label_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { EelEditableLabel *label; gint offset; label = EEL_EDITABLE_LABEL (object); switch (prop_id) { case PROP_TEXT: g_value_set_string (value, label->text); break; case PROP_JUSTIFY: g_value_set_enum (value, label->jtype); break; case PROP_WRAP: g_value_set_boolean (value, label->wrap); break; case PROP_CURSOR_POSITION: offset = g_utf8_pointer_to_offset (label->text, label->text + label->selection_end); g_value_set_int (value, offset); break; case PROP_SELECTION_BOUND: offset = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); g_value_set_int (value, offset); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eel_editable_label_init (EelEditableLabel *label) { label->jtype = GTK_JUSTIFY_LEFT; label->wrap = FALSE; label->wrap_mode = PANGO_WRAP_WORD; label->layout = NULL; label->text_size = 1; label->text = g_malloc (label->text_size); label->text[0] = '\0'; label->n_bytes = 0; gtk_widget_set_can_focus (GTK_WIDGET (label), TRUE); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (label)), GTK_STYLE_CLASS_ENTRY); /* This object is completely private. No external entity can gain a reference * to it; so we create it here and destroy it in finalize(). */ label->im_context = gtk_im_multicontext_new (); g_signal_connect (G_OBJECT (label->im_context), "commit", G_CALLBACK (eel_editable_label_commit_cb), label); g_signal_connect (G_OBJECT (label->im_context), "preedit_changed", G_CALLBACK (eel_editable_label_preedit_changed_cb), label); g_signal_connect (G_OBJECT (label->im_context), "retrieve_surrounding", G_CALLBACK (eel_editable_label_retrieve_surrounding_cb), label); g_signal_connect (G_OBJECT (label->im_context), "delete_surrounding", G_CALLBACK (eel_editable_label_delete_surrounding_cb), label); } /** * eel_editable_label_new: * @str: The text of the label * * Creates a new label with the given text inside it. You can * pass %NULL to get an empty label widget. * * Return value: the new #EelEditableLabel **/ GtkWidget* eel_editable_label_new (const gchar *str) { EelEditableLabel *label; label = g_object_new (EEL_TYPE_EDITABLE_LABEL, NULL); if (str && *str) eel_editable_label_set_text (label, str); return GTK_WIDGET (label); } /** * eel_editable_label_set_text: * @label: a #EelEditableLabel * @str: The text you want to set. * * Sets the text within the #EelEditableLabel widget. It overwrites any text that * was there before. * * This will also clear any previously set mnemonic accelerators. **/ void eel_editable_label_set_text (EelEditableLabel *label, const gchar *str) { GtkEditable *editable; int tmp_pos; g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); g_return_if_fail (str != NULL); if (strcmp (label->text, str) == 0) return; editable = GTK_EDITABLE (label); gtk_editable_delete_text (editable, 0, -1); tmp_pos = 0; gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos); } /** * eel_editable_label_get_text: * @label: a #EelEditableLabel * * Fetches the text from a label widget, as displayed on the * screen. This does not include any embedded underlines * indicating mnemonics or Pango markup. (See eel_editable_label_get_label()) * * Return value: the text in the label widget. This is the internal * string used by the label, and must not be modified. **/ const gchar * eel_editable_label_get_text (EelEditableLabel *label) { g_return_val_if_fail (EEL_IS_EDITABLE_LABEL (label), NULL); return label->text; } /** * eel_editable_label_set_justify: * @label: a #EelEditableLabel * @jtype: a #GtkJustification * * Sets the alignment of the lines in the text of the label relative to * each other. %GTK_JUSTIFY_LEFT is the default value when the * widget is first created with eel_editable_label_new(). If you instead want * to set the alignment of the label as a whole, use * gtk_misc_set_alignment() instead. eel_editable_label_set_justify() has no * effect on labels containing only a single line. **/ void eel_editable_label_set_justify (EelEditableLabel *label, GtkJustification jtype) { g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); g_return_if_fail (jtype >= GTK_JUSTIFY_LEFT && jtype <= GTK_JUSTIFY_FILL); if ((GtkJustification) label->jtype != jtype) { label->jtype = jtype; /* No real need to be this drastic, but easier than duplicating the code */ eel_editable_label_recompute (label); g_object_notify (G_OBJECT (label), "justify"); gtk_widget_queue_resize (GTK_WIDGET (label)); } } /** * eel_editable_label_get_justify: * @label: a #EelEditableLabel * * Returns the justification of the label. See eel_editable_label_set_justify (). * * Return value: #GtkJustification **/ GtkJustification eel_editable_label_get_justify (EelEditableLabel *label) { g_return_val_if_fail (EEL_IS_EDITABLE_LABEL (label), 0); return label->jtype; } void eel_editable_label_set_draw_outline (EelEditableLabel *label, gboolean draw_outline) { draw_outline = draw_outline != FALSE; if (label->draw_outline != draw_outline) { label->draw_outline = draw_outline; gtk_widget_queue_draw (GTK_WIDGET (label)); } } /** * eel_editable_label_set_line_wrap: * @label: a #EelEditableLabel * @wrap: the setting * * Toggles line wrapping within the #EelEditableLabel widget. %TRUE makes it break * lines if text exceeds the widget's size. %FALSE lets the text get cut off * by the edge of the widget if it exceeds the widget size. **/ void eel_editable_label_set_line_wrap (EelEditableLabel *label, gboolean wrap) { g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); wrap = wrap != FALSE; if (label->wrap != wrap) { label->wrap = wrap; g_object_notify (G_OBJECT (label), "wrap"); gtk_widget_queue_resize (GTK_WIDGET (label)); } } void eel_editable_label_set_line_wrap_mode (EelEditableLabel *label, PangoWrapMode mode) { g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); if (label->wrap_mode != mode) { label->wrap_mode = mode; gtk_widget_queue_resize (GTK_WIDGET (label)); } } /** * eel_editable_label_get_line_wrap: * @label: a #EelEditableLabel * * Returns whether lines in the label are automatically wrapped. See eel_editable_label_set_line_wrap (). * * Return value: %TRUE if the lines of the label are automatically wrapped. */ gboolean eel_editable_label_get_line_wrap (EelEditableLabel *label) { g_return_val_if_fail (EEL_IS_EDITABLE_LABEL (label), FALSE); return label->wrap; } PangoFontDescription * eel_editable_label_get_font_description (EelEditableLabel *label) { if (label->font_desc) return pango_font_description_copy (label->font_desc); return NULL; } void eel_editable_label_set_font_description (EelEditableLabel *label, const PangoFontDescription *desc) { if (label->font_desc) pango_font_description_free (label->font_desc); if (desc) label->font_desc = pango_font_description_copy (desc); else label->font_desc = NULL; eel_editable_label_clear_layout (label); } static void eel_editable_label_finalize (GObject *object) { EelEditableLabel *label; g_assert (EEL_IS_EDITABLE_LABEL (object)); label = EEL_EDITABLE_LABEL (object); if (label->font_desc) { pango_font_description_free (label->font_desc); label->font_desc = NULL; } g_object_unref (G_OBJECT (label->im_context)); label->im_context = NULL; g_free (label->text); label->text = NULL; if (label->layout) { g_object_unref (G_OBJECT (label->layout)); label->layout = NULL; } G_OBJECT_CLASS (eel_editable_label_parent_class)->finalize (object); } static void eel_editable_label_clear_layout (EelEditableLabel *label) { if (label->layout) { g_object_unref (G_OBJECT (label->layout)); label->layout = NULL; } } static void eel_editable_label_recompute (EelEditableLabel *label) { eel_editable_label_clear_layout (label); eel_editable_label_check_cursor_blink (label); } typedef struct _LabelWrapWidth LabelWrapWidth; struct _LabelWrapWidth { gint width; PangoFontDescription *font_desc; }; static void label_wrap_width_free (gpointer data) { LabelWrapWidth *wrap_width = data; pango_font_description_free (wrap_width->font_desc); g_free (wrap_width); } static gint get_label_wrap_width (EelEditableLabel *label) { PangoLayout *layout; GtkStyleContext *style = gtk_widget_get_style_context (GTK_WIDGET (label)); PangoFontDescription *desc; LabelWrapWidth *wrap_width = g_object_get_data (G_OBJECT (style), "gtk-label-wrap-width"); if (!wrap_width) { wrap_width = g_new0 (LabelWrapWidth, 1); g_object_set_data_full (G_OBJECT (style), "gtk-label-wrap-width", wrap_width, label_wrap_width_free); } gtk_style_context_get (style, gtk_widget_get_state_flags (GTK_WIDGET (label)), GTK_STYLE_PROPERTY_FONT, &desc, NULL); if (wrap_width->font_desc && pango_font_description_equal (wrap_width->font_desc, desc)) goto out; if (wrap_width->font_desc) pango_font_description_free (wrap_width->font_desc); wrap_width->font_desc = pango_font_description_copy (desc); layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), "This long string gives a good enough length for any line to have."); pango_layout_get_size (layout, &wrap_width->width, NULL); g_object_unref (layout); out: pango_font_description_free (desc); return wrap_width->width; } static void eel_editable_label_ensure_layout (EelEditableLabel *label, gboolean include_preedit) { GtkWidget *widget; PangoRectangle logical_rect; /* Normalize for comparisons */ include_preedit = include_preedit != 0; if (label->preedit_length > 0 && include_preedit != label->layout_includes_preedit) eel_editable_label_clear_layout (label); widget = GTK_WIDGET (label); if (label->layout == NULL) { gchar *preedit_string = NULL; gint preedit_length = 0; PangoAttrList *preedit_attrs = NULL; PangoAlignment align = PANGO_ALIGN_LEFT; /* Quiet gcc */ PangoAttrList *tmp_attrs = pango_attr_list_new (); if (include_preedit) { gtk_im_context_get_preedit_string (label->im_context, &preedit_string, &preedit_attrs, NULL); preedit_length = label->preedit_length; } if (preedit_length) { GString *tmp_string = g_string_new (NULL); g_string_prepend_len (tmp_string, label->text, label->n_bytes); g_string_insert (tmp_string, label->selection_anchor, preedit_string); label->layout = gtk_widget_create_pango_layout (widget, tmp_string->str); pango_attr_list_splice (tmp_attrs, preedit_attrs, label->selection_anchor, preedit_length); g_string_free (tmp_string, TRUE); } else { label->layout = gtk_widget_create_pango_layout (widget, label->text); } label->layout_includes_preedit = include_preedit; if (label->font_desc != NULL) pango_layout_set_font_description (label->layout, label->font_desc); pango_layout_set_attributes (label->layout, tmp_attrs); if (preedit_string) g_free (preedit_string); if (preedit_attrs) pango_attr_list_unref (preedit_attrs); pango_attr_list_unref (tmp_attrs); switch (label->jtype) { case GTK_JUSTIFY_LEFT: align = PANGO_ALIGN_LEFT; break; case GTK_JUSTIFY_RIGHT: align = PANGO_ALIGN_RIGHT; break; case GTK_JUSTIFY_CENTER: align = PANGO_ALIGN_CENTER; break; case GTK_JUSTIFY_FILL: /* FIXME: This just doesn't work to do this */ align = PANGO_ALIGN_LEFT; pango_layout_set_justify (label->layout, TRUE); break; default: g_assert_not_reached (); } pango_layout_set_alignment (label->layout, align); if (label->wrap) { gint longest_paragraph; gint width, height; gint set_width; gtk_widget_get_size_request (widget, &set_width, NULL); if (set_width > 0) pango_layout_set_width (label->layout, set_width * PANGO_SCALE); else { gint wrap_width; pango_layout_set_width (label->layout, -1); pango_layout_get_extents (label->layout, NULL, &logical_rect); width = logical_rect.width; /* Try to guess a reasonable maximum width */ longest_paragraph = width; wrap_width = get_label_wrap_width (label); width = MIN (width, wrap_width); width = MIN (width, PANGO_SCALE * (gdk_screen_width () + 1) / 2); pango_layout_set_width (label->layout, width); pango_layout_get_extents (label->layout, NULL, &logical_rect); width = logical_rect.width; height = logical_rect.height; /* Unfortunately, the above may leave us with a very unbalanced looking paragraph, * so we try short search for a narrower width that leaves us with the same height */ if (longest_paragraph > 0) { gint nlines, perfect_width; nlines = pango_layout_get_line_count (label->layout); perfect_width = (longest_paragraph + nlines - 1) / nlines; if (perfect_width < width) { pango_layout_set_width (label->layout, perfect_width); pango_layout_get_extents (label->layout, NULL, &logical_rect); if (logical_rect.height <= height) width = logical_rect.width; else { gint mid_width = (perfect_width + width) / 2; if (mid_width > perfect_width) { pango_layout_set_width (label->layout, mid_width); pango_layout_get_extents (label->layout, NULL, &logical_rect); if (logical_rect.height <= height) width = logical_rect.width; } } } } pango_layout_set_width (label->layout, width); } pango_layout_set_wrap (label->layout, label->wrap_mode); } else /* !label->wrap */ pango_layout_set_width (label->layout, -1); } } static void eel_editable_label_size_request (GtkWidget *widget, GtkRequisition *requisition) { EelEditableLabel *label; gint width, height; PangoRectangle logical_rect; gint set_width; gint xpad, ypad; g_assert (EEL_IS_EDITABLE_LABEL (widget)); g_assert (requisition != NULL); label = EEL_EDITABLE_LABEL (widget); /* * If word wrapping is on, then the height requisition can depend * on: * * - Any width set on the widget via gtk_widget_set_size_request(). * - The padding of the widget (xpad, set by gtk_misc_set_padding) * * Instead of trying to detect changes to these quantities, if we * are wrapping, we just rewrap for each size request. Since * size requisitions are cached by the GTK+ core, this is not * expensive. */ if (label->wrap) eel_editable_label_recompute (label); eel_editable_label_ensure_layout (label, TRUE); gtk_misc_get_padding (&label->misc, &xpad, &ypad); width = xpad * 2; height = ypad * 2; pango_layout_get_extents (label->layout, NULL, &logical_rect); gtk_widget_get_size_request (widget, &set_width, NULL); if (label->wrap && set_width > 0) width += set_width; else width += PANGO_PIXELS (logical_rect.width); height += PANGO_PIXELS (logical_rect.height); requisition->width = width; requisition->height = height; } static void eel_editable_label_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { GtkRequisition requisition; eel_editable_label_size_request (widget, &requisition); *minimum = *natural = requisition.width; } static void eel_editable_label_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { GtkRequisition requisition; eel_editable_label_size_request (widget, &requisition); *minimum = *natural = requisition.height; } static void eel_editable_label_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); (* GTK_WIDGET_CLASS (eel_editable_label_parent_class)->size_allocate) (widget, allocation); gdk_window_move_resize (label->text_area, allocation->x, allocation->y, allocation->width, allocation->height); } static void eel_editable_label_state_changed (GtkWidget *widget, GtkStateType prev_state) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (widget); /* clear any selection if we're insensitive */ if (!gtk_widget_is_sensitive (widget)) eel_editable_label_select_region (label, 0, 0); if (GTK_WIDGET_CLASS (eel_editable_label_parent_class)->state_changed) GTK_WIDGET_CLASS (eel_editable_label_parent_class)->state_changed (widget, prev_state); } static void eel_editable_label_style_updated (GtkWidget *widget) { EelEditableLabel *label; g_assert (EEL_IS_EDITABLE_LABEL (widget)); label = EEL_EDITABLE_LABEL (widget); GTK_WIDGET_CLASS (eel_editable_label_parent_class)->style_updated (widget); /* We have to clear the layout, fonts etc. may have changed */ eel_editable_label_recompute (label); } static void eel_editable_label_direction_changed (GtkWidget *widget, GtkTextDirection previous_dir) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); if (label->layout) pango_layout_context_changed (label->layout); GTK_WIDGET_CLASS (eel_editable_label_parent_class)->direction_changed (widget, previous_dir); } static void get_layout_location (EelEditableLabel *label, gint *xp, gint *yp) { GtkMisc *misc; GtkWidget *widget; gfloat xalign, yalign; GtkRequisition req; gint x, y, xpad, ypad; GtkAllocation allocation; misc = GTK_MISC (label); widget = GTK_WIDGET (label); gtk_misc_get_alignment (misc, &xalign, &yalign); if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR) xalign = 1.0 - xalign; gtk_widget_get_preferred_size (widget, &req, NULL); gtk_misc_get_padding (misc, &xpad, &ypad); gtk_widget_get_allocation (widget, &allocation); x = floor (xpad + ((allocation.width - req.width) * xalign) + 0.5); y = floor (ypad + ((allocation.height - req.height) * yalign) + 0.5); if (xp) *xp = x; if (yp) *yp = y; } static gint eel_editable_label_get_cursor_pos (EelEditableLabel *label, PangoRectangle *strong_pos, PangoRectangle *weak_pos) { const gchar *text; const gchar *preedit_text; gint index; eel_editable_label_ensure_layout (label, TRUE); text = pango_layout_get_text (label->layout); preedit_text = text + label->selection_anchor; index = label->selection_anchor + g_utf8_offset_to_pointer (preedit_text, label->preedit_cursor) - preedit_text; pango_layout_get_cursor_pos (label->layout, index, strong_pos, weak_pos); return index; } /* Copied from gtkutil private function */ static gboolean eel_editable_label_get_block_cursor_location (EelEditableLabel *label, gint *index, PangoRectangle *pos, gboolean *at_line_end) { const gchar *text; const gchar *preedit_text; PangoLayoutLine *layout_line; PangoRectangle strong_pos, weak_pos; gint line_no; gboolean rtl; PangoContext *context; PangoFontMetrics *metrics; const PangoFontDescription *font_desc; eel_editable_label_ensure_layout (label, TRUE); text = pango_layout_get_text (label->layout); preedit_text = text + label->selection_anchor; text = g_utf8_offset_to_pointer (preedit_text, label->preedit_cursor); index[0] = label->selection_anchor + text - preedit_text; pango_layout_index_to_pos (label->layout, index[0], pos); index[1] = label->selection_anchor + g_utf8_next_char (text) - preedit_text; if (pos->width != 0) { if (at_line_end) *at_line_end = FALSE; if (pos->width < 0) /* RTL char, shift x value back to top left of rect */ { pos->x += pos->width; pos->width = -pos->width; } return TRUE; } pango_layout_index_to_line_x (label->layout, index[0], FALSE, &line_no, NULL); layout_line = pango_layout_get_line_readonly (label->layout, line_no); if (layout_line == NULL) return FALSE; text = pango_layout_get_text (label->layout); if (index[0] < layout_line->start_index + layout_line->length) { /* this may be a zero-width character in the middle of the line, * or it could be a character where line is wrapped, we do want * block cursor in latter case */ if (g_utf8_next_char (text + index[0]) - text != layout_line->start_index + layout_line->length) { /* zero-width character in the middle of the line, do not * bother with block cursor */ return FALSE; } } /* Cursor is at the line end. It may be an empty line, or it could * be on the left or on the right depending on text direction, or it * even could be in the middle of visual layout in bidi text. */ pango_layout_get_cursor_pos (label->layout, index[0], &strong_pos, &weak_pos); if (strong_pos.x != weak_pos.x) { /* do not show block cursor in this case, since the character typed * in may or may not appear at the cursor position */ return FALSE; } context = pango_layout_get_context (label->layout); /* In case when index points to the end of line, pos->x is always most right * pixel of the layout line, so we need to correct it for RTL text. */ if (layout_line->length) { if (layout_line->resolved_dir == PANGO_DIRECTION_RTL) { PangoLayoutIter *iter; PangoRectangle line_rect; gint i; gint left, right; const gchar *p; p = g_utf8_prev_char (text + index[0]); pango_layout_line_index_to_x (layout_line, p - text, FALSE, &left); pango_layout_line_index_to_x (layout_line, p - text, TRUE, &right); pos->x = MIN (left, right); iter = pango_layout_get_iter (label->layout); for (i = 0; i < line_no; i++) pango_layout_iter_next_line (iter); pango_layout_iter_get_line_extents (iter, NULL, &line_rect); pango_layout_iter_free (iter); rtl = TRUE; pos->x += line_rect.x; } else rtl = FALSE; } else { rtl = pango_context_get_base_dir (context) == PANGO_DIRECTION_RTL; } font_desc = pango_layout_get_font_description (label->layout); if (!font_desc) font_desc = pango_context_get_font_description (context); metrics = pango_context_get_metrics (context, font_desc, NULL); pos->width = pango_font_metrics_get_approximate_char_width (metrics); pango_font_metrics_unref (metrics); if (rtl) pos->x -= pos->width - 1; if (at_line_end) *at_line_end = TRUE; return pos->width != 0; } /* These functions are copies from gtk+, as they are not exported from gtk+ */ static void eel_editable_label_draw_cursor (EelEditableLabel *label, cairo_t *cr, gint xoffset, gint yoffset) { if (gtk_widget_is_drawable (GTK_WIDGET (label))) { GtkWidget *widget = GTK_WIDGET (label); gboolean block; gboolean block_at_line_end; gint range[2]; gint index; GtkStyleContext *context; PangoRectangle strong_pos; context = gtk_widget_get_style_context (widget); index = eel_editable_label_get_cursor_pos (label, NULL, NULL); if (label->overwrite_mode && eel_editable_label_get_block_cursor_location (label, range, &strong_pos, &block_at_line_end)) block = TRUE; else block = FALSE; if (!block) { gtk_render_insertion_cursor (context, cr, xoffset, yoffset, label->layout, index, gdk_keymap_get_direction (gdk_keymap_get_default ())); } else /* Block cursor */ { GdkRGBA fg_color; cairo_region_t *clip; gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fg_color); cairo_save (cr); gdk_cairo_set_source_rgba (cr, &fg_color); cairo_rectangle (cr, xoffset + PANGO_PIXELS (strong_pos.x), yoffset + PANGO_PIXELS (strong_pos.y), PANGO_PIXELS (strong_pos.width), PANGO_PIXELS (strong_pos.height)); cairo_fill (cr); if (!block_at_line_end) { GdkRGBA color; clip = gdk_pango_layout_get_clip_region (label->layout, xoffset, yoffset, range, 1); gdk_cairo_region (cr, clip); cairo_clip (cr); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_FOCUSED, &color); gdk_cairo_set_source_rgba (cr, &color); cairo_move_to (cr, xoffset, yoffset); pango_cairo_show_layout (cr, label->layout); cairo_region_destroy (clip); } cairo_restore (cr); } } } static gint eel_editable_label_draw (GtkWidget *widget, cairo_t *cr) { EelEditableLabel *label; GtkStyleContext *style; gint x, y; g_assert (EEL_IS_EDITABLE_LABEL (widget)); label = EEL_EDITABLE_LABEL (widget); style = gtk_widget_get_style_context (widget); gtk_render_background (style, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); eel_editable_label_ensure_layout (label, TRUE); if (gtk_widget_get_visible (widget) && gtk_widget_get_mapped (widget) && label->text) { get_layout_location (label, &x, &y); gtk_render_layout (style, cr, x, y, label->layout); if (label->selection_anchor != label->selection_end) { gint range[2]; const char *text; cairo_region_t *clip; GtkStateType state; GdkRGBA background_color; range[0] = label->selection_anchor; range[1] = label->selection_end; /* Handle possible preedit string */ if (label->preedit_length > 0 && range[1] > label->selection_anchor) { text = pango_layout_get_text (label->layout) + label->selection_anchor; range[1] += g_utf8_offset_to_pointer (text, label->preedit_length) - text; } if (range[0] > range[1]) { gint tmp = range[0]; range[0] = range[1]; range[1] = tmp; } clip = gdk_pango_layout_get_clip_region (label->layout, x, y, range, 1); cairo_save (cr); gdk_cairo_region (cr, clip); cairo_clip (cr); state = gtk_widget_get_state_flags (widget); state |= GTK_STATE_FLAG_SELECTED; gtk_style_context_get_background_color (style, state, &background_color); gdk_cairo_set_source_rgba (cr, &background_color); cairo_paint (cr); gtk_style_context_save (style); gtk_style_context_set_state (style, state); gtk_render_layout (style, cr, x, y, label->layout); gtk_style_context_restore (style); cairo_restore (cr); cairo_region_destroy (clip); } else if (gtk_widget_has_focus (widget)) eel_editable_label_draw_cursor (label, cr, x, y); if (label->draw_outline) { gtk_style_context_save (style); gtk_style_context_set_state (style, gtk_widget_get_state_flags (widget)); gtk_render_frame (style, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); gtk_style_context_restore (style); } } return FALSE; } static void eel_editable_label_realize (GtkWidget *widget) { EelEditableLabel *label; GdkWindowAttr attributes; gint attributes_mask; GtkAllocation allocation; GdkWindow *window; GtkStyleContext *style; gtk_widget_set_realized (widget, TRUE); label = EEL_EDITABLE_LABEL (widget); gtk_widget_get_allocation (widget, &allocation); attributes.wclass = GDK_INPUT_OUTPUT; attributes.window_type = GDK_WINDOW_CHILD; attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; attributes.visual = gtk_widget_get_visual (widget); attributes.event_mask = gtk_widget_get_events (widget) | (GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gtk_widget_set_window (widget, window); gdk_window_set_user_data (window, widget); attributes.cursor = gdk_cursor_new (GDK_XTERM); attributes.window_type = GDK_WINDOW_CHILD; attributes.wclass = GDK_INPUT_ONLY; attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_CURSOR; label->text_area = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (label->text_area, widget); gtk_im_context_set_client_window (label->im_context, label->text_area); g_object_unref (attributes.cursor); style = gtk_widget_get_style_context (widget); gtk_style_context_set_background (style, gtk_widget_get_window (widget)); } static void eel_editable_label_unrealize (GtkWidget *widget) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (widget); gtk_im_context_set_client_window (label->im_context, NULL); if (label->text_area) { gdk_window_set_user_data (label->text_area, NULL); gdk_window_destroy (label->text_area); label->text_area = NULL; } (* GTK_WIDGET_CLASS (eel_editable_label_parent_class)->unrealize) (widget); } static void eel_editable_label_map (GtkWidget *widget) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); (* GTK_WIDGET_CLASS (eel_editable_label_parent_class)->map) (widget); gdk_window_show (label->text_area); } static void eel_editable_label_unmap (GtkWidget *widget) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); gdk_window_hide (label->text_area); (* GTK_WIDGET_CLASS (eel_editable_label_parent_class)->unmap) (widget); } static void window_to_layout_coords (EelEditableLabel *label, gint *x, gint *y) { gint lx, ly; /* get layout location in gtk_widget_get_window (widget) coords */ get_layout_location (label, &lx, &ly); if (x) *x -= lx; /* go to layout */ if (y) *y -= ly; /* go to layout */ } static void get_layout_index (EelEditableLabel *label, gint x, gint y, gint *index) { gint trailing = 0; const gchar *cluster; const gchar *cluster_end; *index = 0; eel_editable_label_ensure_layout (label, TRUE); window_to_layout_coords (label, &x, &y); x *= PANGO_SCALE; y *= PANGO_SCALE; pango_layout_xy_to_index (label->layout, x, y, index, &trailing); if (*index >= label->selection_anchor && label->preedit_length) { if (*index >= label->selection_anchor + label->preedit_length) *index -= label->preedit_length; else { *index = label->selection_anchor; trailing = 0; } } cluster = label->text + *index; cluster_end = cluster; while (trailing) { cluster_end = g_utf8_next_char (cluster_end); --trailing; } *index += (cluster_end - cluster); } static void eel_editable_label_select_word (EelEditableLabel *label) { gint min, max; gint start_index = eel_editable_label_move_backward_word (label, label->selection_end); gint end_index = eel_editable_label_move_forward_word (label, label->selection_end); min = MIN (label->selection_anchor, label->selection_end); max = MAX (label->selection_anchor, label->selection_end); min = MIN (min, start_index); max = MAX (max, end_index); eel_editable_label_select_region_index (label, min, max); } static gint eel_editable_label_button_press (GtkWidget *widget, GdkEventButton *event) { EelEditableLabel *label; gint index = 0; label = EEL_EDITABLE_LABEL (widget); if (event->button == 1) { if (!gtk_widget_has_focus (widget)) gtk_widget_grab_focus (widget); if (event->type == GDK_3BUTTON_PRESS) { eel_editable_label_select_region_index (label, 0, strlen (label->text)); return TRUE; } if (event->type == GDK_2BUTTON_PRESS) { eel_editable_label_select_word (label); return TRUE; } get_layout_index (label, event->x, event->y, &index); if ((label->selection_anchor != label->selection_end) && (event->state & GDK_SHIFT_MASK)) { gint min, max; /* extend (same as motion) */ min = MIN (label->selection_anchor, label->selection_end); max = MAX (label->selection_anchor, label->selection_end); min = MIN (min, index); max = MAX (max, index); /* ensure the anchor is opposite index */ if (index == min) { gint tmp = min; min = max; max = tmp; } eel_editable_label_select_region_index (label, min, max); } else { if (event->type == GDK_3BUTTON_PRESS) eel_editable_label_select_region_index (label, 0, strlen (label->text)); else if (event->type == GDK_2BUTTON_PRESS) eel_editable_label_select_word (label); else /* start a replacement */ eel_editable_label_select_region_index (label, index, index); } return TRUE; } else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) { get_layout_index (label, event->x, event->y, &index); eel_editable_label_select_region_index (label, index, index); eel_editable_label_paste (label, GDK_SELECTION_PRIMARY); return TRUE; } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { eel_editable_label_do_popup (label, event); return TRUE; } return FALSE; } static gint eel_editable_label_button_release (GtkWidget *widget, GdkEventButton *event) { if (event->button != 1) return FALSE; /* The goal here is to return TRUE iff we ate the * button press to start selecting. */ return TRUE; } static gint eel_editable_label_motion (GtkWidget *widget, GdkEventMotion *event) { EelEditableLabel *label; gint index; gint x, y; label = EEL_EDITABLE_LABEL (widget); if ((event->state & GDK_BUTTON1_MASK) == 0) return FALSE; gdk_window_get_device_position (label->text_area, event->device, &x, &y, NULL); get_layout_index (label, x, y, &index); eel_editable_label_select_region_index (label, label->selection_anchor, index); return TRUE; } static void get_text_callback (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data_or_owner) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (user_data_or_owner); if ((label->selection_anchor != label->selection_end) && label->text) { gint start, end; gint len; start = MIN (label->selection_anchor, label->selection_end); end = MAX (label->selection_anchor, label->selection_end); len = strlen (label->text); if (end > len) end = len; if (start > len) start = len; gtk_selection_data_set_text (selection_data, label->text + start, end - start); } } static void clear_text_callback (GtkClipboard *clipboard, gpointer user_data_or_owner) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (user_data_or_owner); label->selection_anchor = label->selection_end; gtk_widget_queue_draw (GTK_WIDGET (label)); } static void eel_editable_label_select_region_index (EelEditableLabel *label, gint anchor_index, gint end_index) { GtkClipboard *clipboard; g_assert (EEL_IS_EDITABLE_LABEL (label)); if (label->selection_anchor == anchor_index && label->selection_end == end_index) return; eel_editable_label_reset_im_context (label); label->selection_anchor = anchor_index; label->selection_end = end_index; clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY); if (anchor_index != end_index) { GtkTargetList *list; GtkTargetEntry *targets; gint n_targets; list = gtk_target_list_new (NULL, 0); gtk_target_list_add_text_targets (list, 0); targets = gtk_target_table_new_from_list (list, &n_targets); gtk_clipboard_set_with_owner (clipboard, targets, n_targets, get_text_callback, clear_text_callback, G_OBJECT (label)); gtk_clipboard_set_can_store (clipboard, NULL, 0); gtk_target_table_free (targets, n_targets); gtk_target_list_unref (list); } else { if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (label)) gtk_clipboard_clear (clipboard); } gtk_widget_queue_draw (GTK_WIDGET (label)); g_object_freeze_notify (G_OBJECT (label)); g_object_notify (G_OBJECT (label), "cursor_position"); g_object_notify (G_OBJECT (label), "selection_bound"); g_object_thaw_notify (G_OBJECT (label)); } /** * eel_editable_label_select_region: * @label: a #EelEditableLabel * @start_offset: start offset (in characters not bytes) * @end_offset: end offset (in characters not bytes) * * Selects a range of characters in the label, if the label is selectable. * See eel_editable_label_set_selectable(). If the label is not selectable, * this function has no effect. If @start_offset or * @end_offset are -1, then the end of the label will be substituted. * **/ void eel_editable_label_select_region (EelEditableLabel *label, gint start_offset, gint end_offset) { g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); if (label->text) { if (start_offset < 0) start_offset = g_utf8_strlen (label->text, -1); if (end_offset < 0) end_offset = g_utf8_strlen (label->text, -1); eel_editable_label_select_region_index (label, g_utf8_offset_to_pointer (label->text, start_offset) - label->text, g_utf8_offset_to_pointer (label->text, end_offset) - label->text); } } /** * eel_editable_label_get_selection_bounds: * @label: a #EelEditableLabel * @start: return location for start of selection, as a character offset * @end: return location for end of selection, as a character offset * * Gets the selected range of characters in the label, returning %TRUE * if there's a selection. * * Return value: %TRUE if selection is non-empty **/ gboolean eel_editable_label_get_selection_bounds (EelEditableLabel *label, gint *start, gint *end) { gint start_index, end_index; gint start_offset, end_offset; gint len; g_return_val_if_fail (EEL_IS_EDITABLE_LABEL (label), FALSE); start_index = MIN (label->selection_anchor, label->selection_end); end_index = MAX (label->selection_anchor, label->selection_end); len = strlen (label->text); if (end_index > len) end_index = len; if (start_index > len) start_index = len; start_offset = g_utf8_strlen (label->text, start_index); end_offset = g_utf8_strlen (label->text, end_index); if (start_offset > end_offset) { gint tmp = start_offset; start_offset = end_offset; end_offset = tmp; } if (start) *start = start_offset; if (end) *end = end_offset; return start_offset != end_offset; } /** * eel_editable_label_get_layout: * @label: a #EelEditableLabel * * Gets the #PangoLayout used to display the label. * The layout is useful to e.g. convert text positions to * pixel positions, in combination with eel_editable_label_get_layout_offsets(). * The returned layout is owned by the label so need not be * freed by the caller. * * Return value: the #PangoLayout for this label **/ PangoLayout* eel_editable_label_get_layout (EelEditableLabel *label) { g_return_val_if_fail (EEL_IS_EDITABLE_LABEL (label), NULL); eel_editable_label_ensure_layout (label, TRUE); return label->layout; } /** * eel_editable_label_get_layout_offsets: * @label: a #EelEditableLabel * @x: location to store X offset of layout, or %NULL * @y: location to store Y offset of layout, or %NULL * * Obtains the coordinates where the label will draw the #PangoLayout * representing the text in the label; useful to convert mouse events * into coordinates inside the #PangoLayout, e.g. to take some action * if some part of the label is clicked. Of course you will need to * create a #GtkEventBox to receive the events, and pack the label * inside it, since labels are a #GTK_NO_WINDOW widget. Remember * when using the #PangoLayout functions you need to convert to * and from pixels using PANGO_PIXELS() or #PANGO_SCALE. * **/ void eel_editable_label_get_layout_offsets (EelEditableLabel *label, gint *x, gint *y) { g_return_if_fail (EEL_IS_EDITABLE_LABEL (label)); get_layout_location (label, x, y); } static void eel_editable_label_pend_cursor_blink (EelEditableLabel *label) { /* TODO */ } static void eel_editable_label_check_cursor_blink (EelEditableLabel *label) { /* TODO */ } static gint eel_editable_label_key_press (GtkWidget *widget, GdkEventKey *event) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); eel_editable_label_pend_cursor_blink (label); if (gtk_im_context_filter_keypress (label->im_context, event)) { /*TODO eel_editable_label_obscure_mouse_cursor (label);*/ label->need_im_reset = TRUE; return TRUE; } if (GTK_WIDGET_CLASS (eel_editable_label_parent_class)->key_press_event (widget, event)) /* Activate key bindings */ return TRUE; return FALSE; } static gint eel_editable_label_key_release (GtkWidget *widget, GdkEventKey *event) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); if (gtk_im_context_filter_keypress (label->im_context, event)) { label->need_im_reset = TRUE; return TRUE; } return GTK_WIDGET_CLASS (eel_editable_label_parent_class)->key_release_event (widget, event); } static void eel_editable_label_keymap_direction_changed (GdkKeymap *keymap, EelEditableLabel *label) { gtk_widget_queue_draw (GTK_WIDGET (label)); } static gint eel_editable_label_focus_in (GtkWidget *widget, GdkEventFocus *event) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); gtk_widget_queue_draw (widget); label->need_im_reset = TRUE; gtk_im_context_focus_in (label->im_context); g_signal_connect (gdk_keymap_get_default (), "direction_changed", G_CALLBACK (eel_editable_label_keymap_direction_changed), label); eel_editable_label_check_cursor_blink (label); return FALSE; } static gint eel_editable_label_focus_out (GtkWidget *widget, GdkEventFocus *event) { EelEditableLabel *label = EEL_EDITABLE_LABEL (widget); gtk_widget_queue_draw (widget); label->need_im_reset = TRUE; gtk_im_context_focus_out (label->im_context); eel_editable_label_check_cursor_blink (label); g_signal_handlers_disconnect_by_func (gdk_keymap_get_default (), (gpointer) eel_editable_label_keymap_direction_changed, label); return FALSE; } static void eel_editable_label_delete_text (EelEditableLabel *label, int start_pos, int end_pos) { int anchor, end; if (start_pos < 0) start_pos = 0; if (end_pos < 0 || end_pos > label->n_bytes) end_pos = label->n_bytes; if (start_pos < end_pos) { g_memmove (label->text + start_pos, label->text + end_pos, label->n_bytes + 1 - end_pos); label->n_bytes -= (end_pos - start_pos); anchor = label->selection_anchor; if (anchor > start_pos) anchor -= MIN (anchor, end_pos) - start_pos; end = label->selection_end; if (end > start_pos) end -= MIN (end, end_pos) - start_pos; /* We might have changed the selection */ eel_editable_label_select_region_index (label, anchor, end); eel_editable_label_recompute (label); gtk_widget_queue_resize (GTK_WIDGET (label)); g_object_notify (G_OBJECT (label), "text"); g_signal_emit_by_name (GTK_EDITABLE (label), "changed"); } } static void eel_editable_label_insert_text (EelEditableLabel *label, const gchar *new_text, gint new_text_length, gint *index) { if (new_text_length + label->n_bytes + 1 > label->text_size) { while (new_text_length + label->n_bytes + 1 > label->text_size) { if (label->text_size == 0) label->text_size = 16; else label->text_size *= 2; } label->text = g_realloc (label->text, label->text_size); } g_object_freeze_notify (G_OBJECT (label)); g_memmove (label->text + *index + new_text_length, label->text + *index, label->n_bytes - *index); memcpy (label->text + *index, new_text, new_text_length); label->n_bytes += new_text_length; /* NUL terminate for safety and convenience */ label->text[label->n_bytes] = '\0'; g_object_notify (G_OBJECT (label), "text"); if (label->selection_anchor > *index) { g_object_notify (G_OBJECT (label), "cursor_position"); g_object_notify (G_OBJECT (label), "selection_bound"); label->selection_anchor += new_text_length; } if (label->selection_end > *index) { label->selection_end += new_text_length; g_object_notify (G_OBJECT (label), "selection_bound"); } *index += new_text_length; eel_editable_label_recompute (label); gtk_widget_queue_resize (GTK_WIDGET (label)); g_object_thaw_notify (G_OBJECT (label)); g_signal_emit_by_name (GTK_EDITABLE (label), "changed"); } /* Used for im_commit_cb and inserting Unicode chars */ static void eel_editable_label_enter_text (EelEditableLabel *label, const gchar *str) { GtkEditable *editable = GTK_EDITABLE (label); gint tmp_pos; gboolean old_need_im_reset; /* Never reset the im while commiting, as that resets possible im state */ old_need_im_reset = label->need_im_reset; label->need_im_reset = FALSE; if (label->selection_end != label->selection_anchor) gtk_editable_delete_selection (editable); else { if (label->overwrite_mode) eel_editable_label_delete_from_cursor (label, GTK_DELETE_CHARS, 1); } tmp_pos = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); gtk_editable_insert_text (GTK_EDITABLE (label), str, strlen (str), &tmp_pos); tmp_pos = g_utf8_offset_to_pointer (label->text, tmp_pos) - label->text; eel_editable_label_select_region_index (label, tmp_pos, tmp_pos); label->need_im_reset = old_need_im_reset; } /* IM Context Callbacks */ static void eel_editable_label_commit_cb (GtkIMContext *context, const gchar *str, EelEditableLabel *label) { eel_editable_label_enter_text (label, str); } static void eel_editable_label_preedit_changed_cb (GtkIMContext *context, EelEditableLabel *label) { gchar *preedit_string; gint cursor_pos; gtk_im_context_get_preedit_string (label->im_context, &preedit_string, NULL, &cursor_pos); label->preedit_length = strlen (preedit_string); cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1)); label->preedit_cursor = cursor_pos; g_free (preedit_string); eel_editable_label_recompute (label); gtk_widget_queue_resize (GTK_WIDGET (label)); } static gboolean eel_editable_label_retrieve_surrounding_cb (GtkIMContext *context, EelEditableLabel *label) { gtk_im_context_set_surrounding (context, label->text, strlen (label->text) + 1, label->selection_end); return TRUE; } static gboolean eel_editable_label_delete_surrounding_cb (GtkIMContext *slave, gint offset, gint n_chars, EelEditableLabel *label) { gint current_pos; current_pos = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); gtk_editable_delete_text (GTK_EDITABLE (label), current_pos + offset, current_pos + offset + n_chars); return TRUE; } static gboolean eel_editable_label_focus (GtkWidget *widget, GtkDirectionType direction) { /* We never want to be in the tab chain */ return FALSE; } /* Compute the X position for an offset that corresponds to the "more important * cursor position for that offset. We use this when trying to guess to which * end of the selection we should go to when the user hits the left or * right arrow key. */ static void get_better_cursor (EelEditableLabel *label, gint index, gint *x, gint *y) { GtkTextDirection keymap_direction = (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; GtkTextDirection widget_direction = gtk_widget_get_direction (GTK_WIDGET (label)); gboolean split_cursor; PangoRectangle strong_pos, weak_pos; g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)), "gtk-split-cursor", &split_cursor, NULL); eel_editable_label_get_cursor_pos (label, &strong_pos, &weak_pos); if (split_cursor) { *x = strong_pos.x / PANGO_SCALE; *y = strong_pos.y / PANGO_SCALE; } else { if (keymap_direction == widget_direction) { *x = strong_pos.x / PANGO_SCALE; *y = strong_pos.y / PANGO_SCALE; } else { *x = weak_pos.x / PANGO_SCALE; *y = weak_pos.y / PANGO_SCALE; } } } static gint eel_editable_label_move_logically (EelEditableLabel *label, gint start, gint count) { gint offset = g_utf8_pointer_to_offset (label->text, label->text + start); if (label->text) { PangoLogAttr *log_attrs; gint n_attrs; gint length; eel_editable_label_ensure_layout (label, FALSE); length = g_utf8_strlen (label->text, -1); pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs); while (count > 0 && offset < length) { do offset++; while (offset < length && !log_attrs[offset].is_cursor_position); count--; } while (count < 0 && offset > 0) { do offset--; while (offset > 0 && !log_attrs[offset].is_cursor_position); count++; } g_free (log_attrs); } return g_utf8_offset_to_pointer (label->text, offset) - label->text; } static gint eel_editable_label_move_visually (EelEditableLabel *label, gint start, gint count) { gint index; index = start; while (count != 0) { int new_index, new_trailing; gboolean split_cursor; gboolean strong; eel_editable_label_ensure_layout (label, FALSE); g_object_get (gtk_widget_get_settings (GTK_WIDGET (label)), "gtk-split-cursor", &split_cursor, NULL); if (split_cursor) strong = TRUE; else { GtkTextDirection keymap_direction = (gdk_keymap_get_direction (gdk_keymap_get_default ()) == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL; strong = keymap_direction == gtk_widget_get_direction (GTK_WIDGET (label)); } if (count > 0) { pango_layout_move_cursor_visually (label->layout, strong, index, 0, 1, &new_index, &new_trailing); count--; } else { pango_layout_move_cursor_visually (label->layout, strong, index, 0, -1, &new_index, &new_trailing); count++; } if (new_index < 0 || new_index == G_MAXINT) break; index = new_index; while (new_trailing--) index = g_utf8_next_char (label->text + new_index) - label->text; } return index; } static gint eel_editable_label_move_line (EelEditableLabel *label, gint start, gint count) { int n_lines, i; int x=0; PangoLayoutLine *line; int index; eel_editable_label_ensure_layout (label, FALSE); n_lines = pango_layout_get_line_count (label->layout); for (i = 0; i < n_lines; i++) { line = pango_layout_get_line (label->layout, i); if (start >= line->start_index && start <= line->start_index + line->length) { pango_layout_line_index_to_x (line, start, FALSE, &x); break; } } if (i == n_lines) i = n_lines - 1; i += count; i = CLAMP (i, 0, n_lines - 1); line = pango_layout_get_line (label->layout, i); if (pango_layout_line_x_to_index (line, x, &index, NULL)) return index; else { if (i == n_lines - 1) return line->start_index + line->length; else return line->start_index + line->length - 1; } } static gint eel_editable_label_move_forward_word (EelEditableLabel *label, gint start) { gint new_pos = g_utf8_pointer_to_offset (label->text, label->text + start); gint length; length = g_utf8_strlen (label->text, -1); if (new_pos < length) { PangoLogAttr *log_attrs; gint n_attrs; eel_editable_label_ensure_layout (label, FALSE); pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs); /* Find the next word end, (remember, n_attrs is one more than the number of of chars) */ new_pos++; while (new_pos < (n_attrs - 1) && !log_attrs[new_pos].is_word_end) new_pos++; g_free (log_attrs); } return g_utf8_offset_to_pointer (label->text, new_pos) - label->text; } static gint eel_editable_label_move_backward_word (EelEditableLabel *label, gint start) { gint new_pos = g_utf8_pointer_to_offset (label->text, label->text + start); if (new_pos > 0) { PangoLogAttr *log_attrs; gint n_attrs; eel_editable_label_ensure_layout (label, FALSE); pango_layout_get_log_attrs (label->layout, &log_attrs, &n_attrs); new_pos -= 1; /* Find the previous word beginning */ while (new_pos > 0 && !log_attrs[new_pos].is_word_start) new_pos--; g_free (log_attrs); } return g_utf8_offset_to_pointer (label->text, new_pos) - label->text; } static void eel_editable_label_move_cursor (EelEditableLabel *label, GtkMovementStep step, gint count, gboolean extend_selection) { gint new_pos; new_pos = label->selection_end; if (label->selection_end != label->selection_anchor && !extend_selection) { /* If we have a current selection and aren't extending it, move to the * start/or end of the selection as appropriate */ switch (step) { case GTK_MOVEMENT_DISPLAY_LINES: case GTK_MOVEMENT_VISUAL_POSITIONS: { gint end_x, end_y; gint anchor_x, anchor_y; gboolean end_is_left; get_better_cursor (label, label->selection_end, &end_x, &end_y); get_better_cursor (label, label->selection_anchor, &anchor_x, &anchor_y); end_is_left = (end_y < anchor_y) || (end_y == anchor_y && end_x < anchor_x); if (count < 0) new_pos = end_is_left ? label->selection_end : label->selection_anchor; else new_pos = !end_is_left ? label->selection_end : label->selection_anchor; break; } case GTK_MOVEMENT_LOGICAL_POSITIONS: case GTK_MOVEMENT_WORDS: if (count < 0) new_pos = MIN (label->selection_end, label->selection_anchor); else new_pos = MAX (label->selection_end, label->selection_anchor); break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: case GTK_MOVEMENT_PARAGRAPH_ENDS: case GTK_MOVEMENT_BUFFER_ENDS: /* FIXME: Can do better here */ new_pos = count < 0 ? 0 : strlen (label->text); break; case GTK_MOVEMENT_PARAGRAPHS: case GTK_MOVEMENT_PAGES: case GTK_MOVEMENT_HORIZONTAL_PAGES: break; default: g_assert_not_reached (); break; } } else { switch (step) { case GTK_MOVEMENT_LOGICAL_POSITIONS: new_pos = eel_editable_label_move_logically (label, new_pos, count); break; case GTK_MOVEMENT_VISUAL_POSITIONS: new_pos = eel_editable_label_move_visually (label, new_pos, count); break; case GTK_MOVEMENT_WORDS: while (count > 0) { new_pos = eel_editable_label_move_forward_word (label, new_pos); count--; } while (count < 0) { new_pos = eel_editable_label_move_backward_word (label, new_pos); count++; } break; case GTK_MOVEMENT_DISPLAY_LINE_ENDS: case GTK_MOVEMENT_PARAGRAPH_ENDS: case GTK_MOVEMENT_BUFFER_ENDS: /* FIXME: Can do better here */ new_pos = count < 0 ? 0 : strlen (label->text); break; case GTK_MOVEMENT_DISPLAY_LINES: new_pos = eel_editable_label_move_line (label, new_pos, count); break; break; case GTK_MOVEMENT_PARAGRAPHS: case GTK_MOVEMENT_PAGES: case GTK_MOVEMENT_HORIZONTAL_PAGES: break; default: g_assert_not_reached (); break; } } if (extend_selection) eel_editable_label_select_region_index (label, label->selection_anchor, new_pos); else eel_editable_label_select_region_index (label, new_pos, new_pos); } static void eel_editable_label_reset_im_context (EelEditableLabel *label) { if (label->need_im_reset) { label->need_im_reset = 0; gtk_im_context_reset (label->im_context); } } static void eel_editable_label_delete_from_cursor (EelEditableLabel *label, GtkDeleteType type, gint count) { GtkEditable *editable = GTK_EDITABLE (label); gint start_pos = label->selection_anchor; gint end_pos = label->selection_anchor; eel_editable_label_reset_im_context (label); if (label->selection_anchor != label->selection_end) { gtk_editable_delete_selection (editable); return; } switch (type) { case GTK_DELETE_CHARS: end_pos = eel_editable_label_move_logically (label, start_pos, count); start_pos = g_utf8_pointer_to_offset (label->text, label->text + start_pos); end_pos = g_utf8_pointer_to_offset (label->text, label->text + end_pos); gtk_editable_delete_text (GTK_EDITABLE (label), MIN (start_pos, end_pos), MAX (start_pos, end_pos)); break; case GTK_DELETE_WORDS: if (count < 0) { /* Move to end of current word, or if not on a word, end of previous word */ end_pos = eel_editable_label_move_backward_word (label, end_pos); end_pos = eel_editable_label_move_forward_word (label, end_pos); } else if (count > 0) { /* Move to beginning of current word, or if not on a word, begining of next word */ start_pos = eel_editable_label_move_forward_word (label, start_pos); start_pos = eel_editable_label_move_backward_word (label, start_pos); } /* Fall through */ case GTK_DELETE_WORD_ENDS: while (count < 0) { start_pos = eel_editable_label_move_backward_word (label, start_pos); count++; } while (count > 0) { end_pos = eel_editable_label_move_forward_word (label, end_pos); count--; } start_pos = g_utf8_pointer_to_offset (label->text, label->text + start_pos); end_pos = g_utf8_pointer_to_offset (label->text, label->text + end_pos); gtk_editable_delete_text (GTK_EDITABLE (label), start_pos, end_pos); break; case GTK_DELETE_DISPLAY_LINE_ENDS: case GTK_DELETE_PARAGRAPH_ENDS: end_pos = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); if (count < 0) gtk_editable_delete_text (GTK_EDITABLE (label), 0, end_pos); else gtk_editable_delete_text (GTK_EDITABLE (label), end_pos, -1); break; case GTK_DELETE_DISPLAY_LINES: case GTK_DELETE_PARAGRAPHS: gtk_editable_delete_text (GTK_EDITABLE (label), 0, -1); break; case GTK_DELETE_WHITESPACE: /* TODO eel_editable_label_delete_whitespace (label); */ break; default: g_assert_not_reached (); break; } eel_editable_label_pend_cursor_blink (label); } static void eel_editable_label_copy_clipboard (EelEditableLabel *label) { if (label->text) { gint start, end; gint len; start = MIN (label->selection_anchor, label->selection_end); end = MAX (label->selection_anchor, label->selection_end); len = strlen (label->text); if (end > len) end = len; if (start > len) start = len; if (start != end) gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), label->text + start, end - start); } } static void eel_editable_label_cut_clipboard (EelEditableLabel *label) { if (label->text) { gint start, end; gint len; start = MIN (label->selection_anchor, label->selection_end); end = MAX (label->selection_anchor, label->selection_end); len = strlen (label->text); if (end > len) end = len; if (start > len) start = len; if (start != end) { gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), label->text + start, end - start); start = g_utf8_pointer_to_offset (label->text, label->text + start); end = g_utf8_pointer_to_offset (label->text, label->text + end); gtk_editable_delete_text (GTK_EDITABLE (label), start, end); } } } static void paste_received (GtkClipboard *clipboard, const gchar *text, gpointer data) { EelEditableLabel *label = EEL_EDITABLE_LABEL (data); GtkEditable *editable = GTK_EDITABLE (label); gint tmp_pos; if (text) { if (label->selection_end != label->selection_anchor) gtk_editable_delete_selection (editable); tmp_pos = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); gtk_editable_insert_text (GTK_EDITABLE (label), text, strlen (text), &tmp_pos); tmp_pos = g_utf8_offset_to_pointer (label->text, tmp_pos) - label->text; eel_editable_label_select_region_index (label, tmp_pos, tmp_pos); } g_object_unref (G_OBJECT (label)); } static void eel_editable_label_paste (EelEditableLabel *label, GdkAtom selection) { g_object_ref (G_OBJECT (label)); gtk_clipboard_request_text (gtk_widget_get_clipboard (GTK_WIDGET (label), selection), paste_received, label); } static void eel_editable_label_paste_clipboard (EelEditableLabel *label) { eel_editable_label_paste (label, GDK_NONE); } static void eel_editable_label_select_all (EelEditableLabel *label) { eel_editable_label_select_region_index (label, 0, strlen (label->text)); } /* Quick hack of a popup menu */ static void activate_cb (GtkWidget *menuitem, EelEditableLabel *label) { const gchar *signal = g_object_get_data (G_OBJECT (menuitem), "gtk-signal"); g_signal_emit_by_name (label, signal); } static void append_action_signal (EelEditableLabel *label, GtkWidget *menu, const gchar *stock_id, const gchar *signal, gboolean sensitive) { GtkWidget *menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL); g_object_set_data (G_OBJECT (menuitem), "gtk-signal", (char *)signal); g_signal_connect (menuitem, "activate", G_CALLBACK (activate_cb), label); gtk_widget_set_sensitive (menuitem, sensitive); gtk_widget_show (menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); } static void popup_menu_detach (GtkWidget *attach_widget, GtkMenu *menu) { EelEditableLabel *label; label = EEL_EDITABLE_LABEL (attach_widget); label->popup_menu = NULL; } static void popup_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data) { EelEditableLabel *label; GtkWidget *widget; GtkRequisition req; GtkAllocation allocation; label = EEL_EDITABLE_LABEL (user_data); widget = GTK_WIDGET (label); g_assert (gtk_widget_get_realized (widget)); gdk_window_get_origin (label->text_area, x, y); gtk_widget_get_preferred_size (widget, &req, NULL); gtk_widget_get_allocation (widget, &allocation); *x += allocation.width / 2; *y += allocation.height; *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width)); *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height)); } static void eel_editable_label_toggle_overwrite (EelEditableLabel *label) { label->overwrite_mode = !label->overwrite_mode; gtk_widget_queue_draw (GTK_WIDGET (label)); } typedef struct { EelEditableLabel *label; gint button; guint time; } PopupInfo; static void popup_targets_received (GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data) { GtkWidget *menuitem, *submenu; gboolean have_selection; gboolean clipboard_contains_text; PopupInfo *info; EelEditableLabel *label; info = user_data; label = info->label; if (gtk_widget_get_realized (GTK_WIDGET (label))) { if (label->popup_menu) gtk_widget_destroy (label->popup_menu); label->popup_menu = gtk_menu_new (); gtk_menu_attach_to_widget (GTK_MENU (label->popup_menu), GTK_WIDGET (label), popup_menu_detach); have_selection = label->selection_anchor != label->selection_end; clipboard_contains_text = gtk_selection_data_targets_include_text (data); append_action_signal (label, label->popup_menu, GTK_STOCK_CUT, "cut_clipboard", have_selection); append_action_signal (label, label->popup_menu, GTK_STOCK_COPY, "copy_clipboard", have_selection); append_action_signal (label, label->popup_menu, GTK_STOCK_PASTE, "paste_clipboard", clipboard_contains_text); menuitem = gtk_menu_item_new_with_label (_("Select All")); g_signal_connect_object (menuitem, "activate", G_CALLBACK (eel_editable_label_select_all), label, G_CONNECT_SWAPPED); gtk_widget_show (menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (label->popup_menu), menuitem); menuitem = gtk_separator_menu_item_new (); gtk_widget_show (menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (label->popup_menu), menuitem); menuitem = gtk_menu_item_new_with_label (_("Input Methods")); gtk_widget_show (menuitem); submenu = gtk_menu_new (); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu); gtk_menu_shell_append (GTK_MENU_SHELL (label->popup_menu), menuitem); gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (label->im_context), GTK_MENU_SHELL (submenu)); g_signal_emit (label, signals[POPULATE_POPUP], 0, label->popup_menu); if (info->button) gtk_menu_popup (GTK_MENU (label->popup_menu), NULL, NULL, NULL, NULL, info->button, info->time); else { gtk_menu_popup (GTK_MENU (label->popup_menu), NULL, NULL, popup_position_func, label, info->button, info->time); gtk_menu_shell_select_first (GTK_MENU_SHELL (label->popup_menu), FALSE); } } g_object_unref (label); g_free (info); } static void eel_editable_label_do_popup (EelEditableLabel *label, GdkEventButton *event) { PopupInfo *info = g_new (PopupInfo, 1); /* In order to know what entries we should make sensitive, we * ask for the current targets of the clipboard, and when * we get them, then we actually pop up the menu. */ info->label = g_object_ref (label); if (event) { info->button = event->button; info->time = event->time; } else { info->button = 0; info->time = gtk_get_current_event_time (); } gtk_clipboard_request_contents (gtk_widget_get_clipboard (GTK_WIDGET (label), GDK_SELECTION_CLIPBOARD), gdk_atom_intern ("TARGETS", FALSE), popup_targets_received, info); } /************ Editable implementation ****************/ static void editable_insert_text_emit (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); gchar buf[64]; gchar *text; int text_length; text_length = g_utf8_strlen (label->text, -1); if (*position < 0 || *position > text_length) *position = text_length; g_object_ref (G_OBJECT (editable)); if (new_text_length <= 63) text = buf; else text = g_new (gchar, new_text_length + 1); text[new_text_length] = '\0'; strncpy (text, new_text, new_text_length); g_signal_emit_by_name (editable, "insert_text", text, new_text_length, position); if (new_text_length > 63) g_free (text); g_object_unref (G_OBJECT (editable)); } static void editable_delete_text_emit (GtkEditable *editable, gint start_pos, gint end_pos) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); int text_length; text_length = g_utf8_strlen (label->text, -1); if (end_pos < 0 || end_pos > text_length) end_pos = text_length; if (start_pos < 0) start_pos = 0; if (start_pos > end_pos) start_pos = end_pos; g_object_ref (G_OBJECT (editable)); g_signal_emit_by_name (editable, "delete_text", start_pos, end_pos); g_object_unref (G_OBJECT (editable)); } static void editable_insert_text (GtkEditable *editable, const gchar *new_text, gint new_text_length, gint *position) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); gint index; if (new_text_length < 0) new_text_length = strlen (new_text); index = g_utf8_offset_to_pointer (label->text, *position) - label->text; eel_editable_label_insert_text (label, new_text, new_text_length, &index); *position = g_utf8_pointer_to_offset (label->text, label->text + index); } static void editable_delete_text (GtkEditable *editable, gint start_pos, gint end_pos) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); int text_length; gint start_index, end_index; text_length = g_utf8_strlen (label->text, -1); if (end_pos < 0 || end_pos > text_length) end_pos = text_length; if (start_pos < 0) start_pos = 0; if (start_pos > end_pos) start_pos = end_pos; start_index = g_utf8_offset_to_pointer (label->text, start_pos) - label->text; end_index = g_utf8_offset_to_pointer (label->text, end_pos) - label->text; eel_editable_label_delete_text (label, start_index, end_index); } static gchar * editable_get_chars (GtkEditable *editable, gint start_pos, gint end_pos) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); int text_length; gint start_index, end_index; text_length = g_utf8_strlen (label->text, -1); if (end_pos < 0 || end_pos > text_length) end_pos = text_length; if (start_pos < 0) start_pos = 0; if (start_pos > end_pos) start_pos = end_pos; start_index = g_utf8_offset_to_pointer (label->text, start_pos) - label->text; end_index = g_utf8_offset_to_pointer (label->text, end_pos) - label->text; return g_strndup (label->text + start_index, end_index - start_index); } static void editable_set_selection_bounds (GtkEditable *editable, gint start, gint end) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); int text_length; gint start_index, end_index; text_length = g_utf8_strlen (label->text, -1); if (end < 0 || end > text_length) end = text_length; if (start < 0) start = text_length; if (start > text_length) start = text_length; eel_editable_label_reset_im_context (label); start_index = g_utf8_offset_to_pointer (label->text, start) - label->text; end_index = g_utf8_offset_to_pointer (label->text, end) - label->text; eel_editable_label_select_region_index (label, start_index, end_index); } static gboolean editable_get_selection_bounds (GtkEditable *editable, gint *start, gint *end) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); *start = g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); *end = g_utf8_pointer_to_offset (label->text, label->text + label->selection_end); return (label->selection_anchor != label->selection_end); } static void editable_real_set_position (GtkEditable *editable, gint position) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); int text_length; int index; text_length = g_utf8_strlen (label->text, -1); if (position < 0 || position > text_length) position = text_length; index = g_utf8_offset_to_pointer (label->text, position) - label->text; if (index != label->selection_anchor || index != label->selection_end) { eel_editable_label_select_region_index (label, index, index); } } static gint editable_get_position (GtkEditable *editable) { EelEditableLabel *label = EEL_EDITABLE_LABEL (editable); return g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor); } static AtkObjectClass *a11y_parent_class = NULL; static const char* eel_editable_label_accessible_data = "eel-editable-label-accessible-data"; /************ Accessible implementation ****************/ typedef struct { GailTextUtil *textutil; gint selection_anchor; gint selection_end; const gchar *signal_name; gint position; gint length; } EelEditableLabelAccessiblePrivate; typedef struct { EelEditableLabel* label; gint position; } EelEditableLabelAccessiblePaste; static gchar* eel_editable_label_accessible_get_text (AtkText *text, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabelAccessiblePrivate *priv; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; priv = g_object_get_data (G_OBJECT (text), eel_editable_label_accessible_data); return gail_text_util_get_substring (priv->textutil, start_pos, end_pos); } static gunichar eel_editable_label_accessible_get_character_at_offset (AtkText *text, gint offset) { GtkWidget *widget; EelEditableLabelAccessiblePrivate *priv; gchar *string; gchar *index; gunichar unichar; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return '\0'; priv = g_object_get_data (G_OBJECT (text), eel_editable_label_accessible_data); string = gail_text_util_get_substring (priv->textutil, 0, -1); if (offset >= g_utf8_strlen (string, -1)) { unichar = '\0'; } else { index = g_utf8_offset_to_pointer (string, offset); unichar = g_utf8_get_char(index); } g_free(string); return unichar; } static gchar* eel_editable_label_accessible_get_text_before_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GtkWidget *widget; EelEditableLabel *label; EelEditableLabelAccessiblePrivate *priv; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; label = EEL_EDITABLE_LABEL (widget); priv = g_object_get_data (G_OBJECT (text), eel_editable_label_accessible_data); return gail_text_util_get_text (priv->textutil, eel_editable_label_get_layout (label), GAIL_BEFORE_OFFSET, boundary_type, offset, start_offset, end_offset); } static gchar* eel_editable_label_accessible_get_text_at_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GtkWidget *widget; EelEditableLabel *label; EelEditableLabelAccessiblePrivate *priv; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; label = EEL_EDITABLE_LABEL (widget); priv = g_object_get_data (G_OBJECT (text), eel_editable_label_accessible_data); return gail_text_util_get_text (priv->textutil, eel_editable_label_get_layout (label), GAIL_AT_OFFSET, boundary_type, offset, start_offset, end_offset); } static gchar* eel_editable_label_accessible_get_text_after_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GtkWidget *widget; EelEditableLabel *label; EelEditableLabelAccessiblePrivate *priv; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; label = EEL_EDITABLE_LABEL (widget); priv = g_object_get_data (G_OBJECT (text), eel_editable_label_accessible_data); return gail_text_util_get_text (priv->textutil, eel_editable_label_get_layout (label), GAIL_AFTER_OFFSET, boundary_type, offset, start_offset, end_offset); } static gint eel_editable_label_accessible_get_caret_offset (AtkText *text) { GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return 0; return gtk_editable_get_position (GTK_EDITABLE (widget)); } static gboolean eel_editable_label_accessible_set_caret_offset (AtkText *text, gint offset) { GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return FALSE; gtk_editable_set_position (GTK_EDITABLE (widget), offset); return TRUE; } static gint eel_editable_label_accessible_get_character_count (AtkText *text) { GtkWidget *widget; EelEditableLabel *label; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return 0; label = EEL_EDITABLE_LABEL (widget); return g_utf8_strlen (eel_editable_label_get_text (label), -1); } static gint eel_editable_label_accessible_get_n_selections (AtkText *text) { GtkWidget *widget; EelEditableLabel *label; gint select_start, select_end; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return -1; label = EEL_EDITABLE_LABEL (widget); gtk_editable_get_selection_bounds (GTK_EDITABLE (label), &select_start, &select_end); if (select_start != select_end) return 1; else return 0; } static gchar* eel_editable_label_accessible_get_selection (AtkText *text, gint selection_num, gint *start_pos, gint *end_pos) { GtkWidget *widget; EelEditableLabel *label; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; /* Only let the user get the selection if one is set, and if the * selection_num is 0. */ if (selection_num != 0) return NULL; label = EEL_EDITABLE_LABEL (widget); gtk_editable_get_selection_bounds (GTK_EDITABLE (label), start_pos, end_pos); if (*start_pos != *end_pos) return gtk_editable_get_chars (GTK_EDITABLE (label), *start_pos, *end_pos); else return NULL; } static gboolean eel_editable_label_accessible_add_selection (AtkText *text, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabel *label; gint select_start, select_end; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return FALSE; label = EEL_EDITABLE_LABEL (widget); gtk_editable_get_selection_bounds (GTK_EDITABLE (label), &select_start, &select_end); /* If there is already a selection, then don't allow another to be added, * since EelEditableLabel only supports one selected region. */ if (select_start == select_end) { gtk_editable_select_region (GTK_EDITABLE (label), start_pos, end_pos); return TRUE; } else return FALSE; } static gboolean eel_editable_label_accessible_remove_selection (AtkText *text, gint selection_num) { GtkWidget *widget; EelEditableLabel *label; gint select_start, select_end, caret_pos; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return FALSE; if (selection_num != 0) return FALSE; label = EEL_EDITABLE_LABEL (widget); gtk_editable_get_selection_bounds (GTK_EDITABLE (label), &select_start, &select_end); if (select_start != select_end) { /* Setting the start & end of the selected region to the caret position * turns off the selection. */ caret_pos = gtk_editable_get_position (GTK_EDITABLE (label)); gtk_editable_select_region (GTK_EDITABLE (label), caret_pos, caret_pos); return TRUE; } else return FALSE; } static gboolean eel_editable_label_accessible_set_selection (AtkText *text, gint selection_num, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabel *label; gint select_start, select_end; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return FALSE; /* Only let the user move the selection if one is set, and if the * selection_num is 0 */ if (selection_num != 0) return FALSE; label = EEL_EDITABLE_LABEL (widget); gtk_editable_get_selection_bounds (GTK_EDITABLE (label), &select_start, &select_end); if (select_start != select_end) { gtk_editable_select_region (GTK_EDITABLE (label), start_pos, end_pos); return TRUE; } else return FALSE; } static AtkAttributeSet* eel_editable_label_accessible_get_run_attributes (AtkText *text, gint offset, gint *start_offset, gint *end_offset) { GtkWidget *widget; EelEditableLabel *label; AtkAttributeSet *at_set = NULL; GtkTextDirection dir; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; label = EEL_EDITABLE_LABEL (widget); dir = gtk_widget_get_direction (widget); if (dir == GTK_TEXT_DIR_RTL) { at_set = gail_misc_add_attribute (at_set, ATK_TEXT_ATTR_DIRECTION, g_strdup (atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, dir))); } at_set = gail_misc_layout_get_run_attributes (at_set, eel_editable_label_get_layout (label), label->text, offset, start_offset, end_offset); return at_set; } static AtkAttributeSet* eel_editable_label_accessible_get_default_attributes (AtkText *text) { GtkWidget *widget; EelEditableLabel *label; AtkAttributeSet *at_set = NULL; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return NULL; label = EEL_EDITABLE_LABEL (widget); at_set = gail_misc_get_default_attributes (at_set, eel_editable_label_get_layout (label), widget); return at_set; } static void eel_editable_label_accessible_get_character_extents (AtkText *text, gint offset, gint *x, gint *y, gint *width, gint *height, AtkCoordType coords) { GtkWidget *widget; EelEditableLabel *label; PangoRectangle char_rect; gint index, cursor_index, x_layout, y_layout; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); eel_editable_label_get_layout_offsets (label, &x_layout, &y_layout); index = g_utf8_offset_to_pointer (label->text, offset) - label->text; cursor_index = label->selection_anchor; if (index > cursor_index) index += label->preedit_length; pango_layout_index_to_pos (eel_editable_label_get_layout(label), index, &char_rect); gail_misc_get_extents_from_pango_rectangle (widget, &char_rect, x_layout, y_layout, x, y, width, height, coords); } static gint eel_editable_label_accessible_get_offset_at_point (AtkText *text, gint x, gint y, AtkCoordType coords) { GtkWidget *widget; EelEditableLabel *label; gint index, cursor_index, x_layout, y_layout; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return -1; label = EEL_EDITABLE_LABEL (widget); eel_editable_label_get_layout_offsets (label, &x_layout, &y_layout); index = gail_misc_get_index_at_point_in_layout (widget, eel_editable_label_get_layout(label), x_layout, y_layout, x, y, coords); if (index == -1) { if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW) return g_utf8_strlen (label->text, -1); return index; } else { cursor_index = label->selection_anchor; if (index >= cursor_index && label->preedit_length) { if (index >= cursor_index + label->preedit_length) index -= label->preedit_length; else index = cursor_index; } return g_utf8_pointer_to_offset (label->text, label->text + index); } } static void atk_text_interface_init (AtkTextIface *iface) { g_assert (iface != NULL); iface->get_text = eel_editable_label_accessible_get_text; iface->get_character_at_offset = eel_editable_label_accessible_get_character_at_offset; iface->get_text_before_offset = eel_editable_label_accessible_get_text_before_offset; iface->get_text_at_offset = eel_editable_label_accessible_get_text_at_offset; iface->get_text_after_offset = eel_editable_label_accessible_get_text_after_offset; iface->get_caret_offset = eel_editable_label_accessible_get_caret_offset; iface->set_caret_offset = eel_editable_label_accessible_set_caret_offset; iface->get_character_count = eel_editable_label_accessible_get_character_count; iface->get_n_selections = eel_editable_label_accessible_get_n_selections; iface->get_selection = eel_editable_label_accessible_get_selection; iface->add_selection = eel_editable_label_accessible_add_selection; iface->remove_selection = eel_editable_label_accessible_remove_selection; iface->set_selection = eel_editable_label_accessible_set_selection; iface->get_run_attributes = eel_editable_label_accessible_get_run_attributes; iface->get_default_attributes = eel_editable_label_accessible_get_default_attributes; iface->get_character_extents = eel_editable_label_accessible_get_character_extents; iface->get_offset_at_point = eel_editable_label_accessible_get_offset_at_point; } static void eel_editable_label_accessible_set_text_contents (AtkEditableText *text, const gchar *string) { GtkWidget *widget; EelEditableLabel *label; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); eel_editable_label_set_text (label, string); } static void eel_editable_label_accessible_insert_text (AtkEditableText *text, const gchar *string, gint length, gint *position) { GtkWidget *widget; EelEditableLabel *label; GtkEditable *editable; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); editable = GTK_EDITABLE (label); gtk_editable_insert_text (editable, string, length, position); } static void eel_editable_label_accessible_copy_text (AtkEditableText *text, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabel *label; GtkEditable *editable; gchar *str; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); editable = GTK_EDITABLE (label); str = gtk_editable_get_chars (editable, start_pos, end_pos); gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), str, -1); } static void eel_editable_label_accessible_cut_text (AtkEditableText *text, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabel *label; GtkEditable *editable; gchar *str; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); editable = GTK_EDITABLE (label); str = gtk_editable_get_chars (editable, start_pos, end_pos); gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), str, -1); gtk_editable_delete_text (editable, start_pos, end_pos); } static void eel_editable_label_accessible_delete_text (AtkEditableText *text, gint start_pos, gint end_pos) { GtkWidget *widget; EelEditableLabel *label; GtkEditable *editable; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; label = EEL_EDITABLE_LABEL (widget); editable = GTK_EDITABLE (label); gtk_editable_delete_text (editable, start_pos, end_pos); } static void eel_editable_label_accessible_paste_received (GtkClipboard *clipboard, const gchar *text, gpointer data) { EelEditableLabelAccessiblePaste* paste_struct = (EelEditableLabelAccessiblePaste *)data; if (text) gtk_editable_insert_text (GTK_EDITABLE (paste_struct->label), text, -1, &(paste_struct->position)); g_object_unref (paste_struct->label); } static void eel_editable_label_accessible_paste_text (AtkEditableText *text, gint position) { GtkWidget *widget; GtkEditable *editable; EelEditableLabelAccessiblePaste paste_struct; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text)); if (widget == NULL) /* State is defunct */ return; editable = GTK_EDITABLE (widget); if (!gtk_editable_get_editable (editable)) return; paste_struct.label = EEL_EDITABLE_LABEL (widget); paste_struct.position = position; g_object_ref (paste_struct.label); gtk_clipboard_request_text (gtk_clipboard_get (GDK_NONE), eel_editable_label_accessible_paste_received, &paste_struct); } static void atk_editable_text_interface_init (AtkEditableTextIface *iface) { g_assert (iface != NULL); iface->set_text_contents = eel_editable_label_accessible_set_text_contents; iface->insert_text = eel_editable_label_accessible_insert_text; iface->copy_text = eel_editable_label_accessible_copy_text; iface->cut_text = eel_editable_label_accessible_cut_text; iface->delete_text = eel_editable_label_accessible_delete_text; iface->paste_text = eel_editable_label_accessible_paste_text; } static void eel_editable_label_accessible_notify_insert (AtkObject *accessible) { EelEditableLabelAccessiblePrivate *priv; priv = g_object_get_data (G_OBJECT (accessible), eel_editable_label_accessible_data); if (priv->signal_name) { g_signal_emit_by_name (accessible, priv->signal_name, priv->position, priv->length); priv->signal_name = NULL; } } static gboolean eel_editable_label_accessible_idle_notify_insert (gpointer data) { eel_editable_label_accessible_notify_insert (data); return FALSE; } /* Note arg1 returns the character at the start of the insert. * arg2 returns the number of characters inserted. */ static void eel_editable_label_accessible_insert_text_cb (EelEditableLabel *label, gchar *arg1, gint arg2, gpointer arg3) { AtkObject *accessible; EelEditableLabelAccessiblePrivate *priv; gint *position = (gint *) arg3; accessible = gtk_widget_get_accessible (GTK_WIDGET (label)); priv = g_object_get_data (G_OBJECT (accessible), eel_editable_label_accessible_data); if (!priv->signal_name) { priv->signal_name = "text_changed::insert"; priv->position = *position; priv->length = arg2; } /* * The signal will be emitted when the cursor position is updated. * or in an idle handler if it not updated. */ g_idle_add (eel_editable_label_accessible_idle_notify_insert, accessible); } /* Note arg1 returns the start of the delete range, arg2 returns the * end of the delete range if multiple characters are deleted. */ static void eel_editable_label_accessible_delete_text_cb (EelEditableLabel *label, gint arg1, gint arg2) { AtkObject *accessible; /* * Zero length text deleted so ignore */ if (arg2 - arg1 == 0) return; accessible = gtk_widget_get_accessible (GTK_WIDGET (label)); g_signal_emit_by_name (accessible, "text_changed::delete", arg1, arg2 - arg1); } static void eel_editable_label_accessible_changed_cb (EelEditableLabel *label) { AtkObject *accessible; EelEditableLabelAccessiblePrivate *priv; accessible = gtk_widget_get_accessible (GTK_WIDGET (label)); priv = g_object_get_data (G_OBJECT (accessible), eel_editable_label_accessible_data); gail_text_util_text_setup (priv->textutil, eel_editable_label_get_text (label)); } static gboolean check_for_selection_change (AtkObject *accessible, GtkWidget *widget) { EelEditableLabelAccessiblePrivate *priv; EelEditableLabel *label; gboolean ret_val = FALSE; priv = g_object_get_data (G_OBJECT (accessible), eel_editable_label_accessible_data); label = EEL_EDITABLE_LABEL (widget); if (label->selection_anchor != label->selection_end) { if (label->selection_anchor != priv->selection_anchor || label->selection_end != priv->selection_end) /* * This check is here as this function can be called * for notification of selection_end and selection_anchor. * The values of selection_anchor and selection_end may be the same * for both notifications and we only want to generate one * text_selection_changed signal. */ ret_val = TRUE; } else { /* We had a selection */ ret_val = (priv->selection_anchor != priv->selection_end); } priv->selection_anchor = label->selection_anchor; priv->selection_end = label->selection_end; return ret_val; } static void eel_editable_label_accessible_notify_gtk (GObject *obj, GParamSpec *pspec) { GtkWidget *widget; AtkObject *accessible; EelEditableLabel *label; widget = GTK_WIDGET (obj); label = EEL_EDITABLE_LABEL (widget); accessible = gtk_widget_get_accessible (widget); if (strcmp (pspec->name, "cursor-position") == 0) { eel_editable_label_accessible_notify_insert (accessible); if (check_for_selection_change (accessible, widget)) g_signal_emit_by_name (accessible, "text_selection_changed"); /* * The label cursor position has moved so generate the signal. */ g_signal_emit_by_name (accessible, "text_caret_moved", g_utf8_pointer_to_offset (label->text, label->text + label->selection_anchor)); } else if (strcmp (pspec->name, "selection-bound") == 0) { eel_editable_label_accessible_notify_insert (accessible); if (check_for_selection_change (accessible, widget)) g_signal_emit_by_name (accessible, "text_selection_changed"); } } static void eel_editable_label_accessible_initialize (AtkObject *accessible, gpointer widget) { EelEditableLabelAccessiblePrivate *priv; EelEditableLabel *label; a11y_parent_class->initialize (accessible, widget); label = EEL_EDITABLE_LABEL (widget); priv = g_new0 (EelEditableLabelAccessiblePrivate, 1); priv->textutil = gail_text_util_new (); gail_text_util_text_setup (priv->textutil, eel_editable_label_get_text (EEL_EDITABLE_LABEL (widget))); priv->selection_anchor = label->selection_anchor; priv->selection_end = label->selection_end; g_object_set_data (G_OBJECT (accessible), eel_editable_label_accessible_data, priv); g_signal_connect (widget, "insert-text", G_CALLBACK (eel_editable_label_accessible_insert_text_cb), NULL); g_signal_connect (widget, "delete-text", G_CALLBACK (eel_editable_label_accessible_delete_text_cb), NULL); g_signal_connect (widget, "changed", G_CALLBACK (eel_editable_label_accessible_changed_cb), NULL); g_signal_connect (widget, "notify", G_CALLBACK (eel_editable_label_accessible_notify_gtk), NULL); atk_object_set_role (accessible, ATK_ROLE_TEXT); } static const gchar* eel_editable_label_accessible_get_name (AtkObject *accessible) { if (accessible->name != NULL) return accessible->name; else { GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (widget == NULL) /* State is defunct */ return NULL; g_assert (EEL_IS_EDITABLE_LABEL (widget)); return eel_editable_label_get_text (EEL_EDITABLE_LABEL (widget)); } } static AtkStateSet* eel_editable_label_accessible_ref_state_set (AtkObject *accessible) { AtkStateSet *state_set; GtkWidget *widget; state_set = a11y_parent_class->ref_state_set (accessible); widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (widget == NULL) return state_set; atk_state_set_add_state (state_set, ATK_STATE_EDITABLE); atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE); return state_set; } static void eel_editable_label_accessible_finalize (GObject *object) { EelEditableLabelAccessiblePrivate *priv; priv = g_object_get_data (object, eel_editable_label_accessible_data); g_object_unref (priv->textutil); g_free (priv); G_OBJECT_CLASS (a11y_parent_class)->finalize (object); } static void eel_editable_label_accessible_class_init (AtkObjectClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); a11y_parent_class = g_type_class_peek_parent (klass); klass->initialize = eel_editable_label_accessible_initialize; klass->get_name = eel_editable_label_accessible_get_name; klass->ref_state_set = eel_editable_label_accessible_ref_state_set; gobject_class->finalize = eel_editable_label_accessible_finalize; } static AtkObject * eel_editable_label_get_accessible (GtkWidget *widget) { static GType type = 0; AtkObject *accessible; if ((accessible = eel_accessibility_get_atk_object (widget))) return accessible; if (!type) { const GInterfaceInfo atk_editable_text_info = { (GInterfaceInitFunc) atk_editable_text_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; const GInterfaceInfo atk_text_info = { (GInterfaceInitFunc) atk_text_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; type = eel_accessibility_create_derived_type ("EelEditableLabelAccessible", G_TYPE_FROM_INSTANCE (widget), eel_editable_label_accessible_class_init); if (!type) return NULL; g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); } accessible = g_object_new (type, NULL); return eel_accessibility_set_atk_object_return (widget, accessible); } nemo-3.6.5/eel/eel-art-extensions.h0000664000175000017500000000506613215733314016064 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-art-extensions.h - interface of libart extension functions. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler Ramiro Estrugo */ #ifndef EEL_ART_EXTENSIONS_H #define EEL_ART_EXTENSIONS_H #include G_BEGIN_DECLS typedef struct { double x0, y0, x1, y1; } EelDRect; typedef struct { /*< public >*/ int x0, y0, x1, y1; } EelIRect; extern const EelDRect eel_drect_empty; extern const EelIRect eel_irect_empty; void eel_irect_copy (EelIRect *dest, const EelIRect *src); void eel_irect_union (EelIRect *dest, const EelIRect *src1, const EelIRect *src2); void eel_irect_intersect (EelIRect *dest, const EelIRect *src1, const EelIRect *src2); gboolean eel_irect_equal (EelIRect rectangle_a, EelIRect rectangle_b); gboolean eel_irect_hits_irect (EelIRect rectangle_a, EelIRect rectangle_b); EelIRect eel_irect_offset_by (EelIRect rectangle, int x, int y); EelIRect eel_irect_scale_by (EelIRect rectangle, double scale); gboolean eel_irect_is_empty (const EelIRect *rectangle); gboolean eel_irect_contains_point (EelIRect outer_rectangle, int x, int y); int eel_irect_get_width (EelIRect rectangle); int eel_irect_get_height (EelIRect rectangle); void eel_drect_union (EelDRect *dest, const EelDRect *src1, const EelDRect *src2); G_END_DECLS #endif /* EEL_ART_EXTENSIONS_H */ nemo-3.6.5/eel/eel-glib-extensions.c0000664000175000017500000002227213215733314016204 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-glib-extensions.c - implementation of new functions that conceptually belong in glib. Perhaps some of these will be actually rolled into glib someday. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan */ #include #include "eel-glib-extensions.h" #include "eel-debug.h" #include "eel-lib-self-check-functions.h" #include "eel-string.h" #include #include #include /** * eel_g_str_list_equal * * Compares two lists of C strings to see if they are equal. * @list_a: First list. * @list_b: Second list. * * Return value: TRUE if the lists contain the same strings. **/ gboolean eel_g_str_list_equal (GList *list_a, GList *list_b) { GList *p, *q; for (p = list_a, q = list_b; p != NULL && q != NULL; p = p->next, q = q->next) { if (g_strcmp0 (p->data, q->data) != 0) { return FALSE; } } return p == NULL && q == NULL; } /** * eel_g_str_list_copy * * @list: List of strings and/or NULLs to copy. * Return value: Deep copy of @list. **/ GList * eel_g_str_list_copy (GList *list) { return g_list_copy_deep (list, (GCopyFunc) g_strdup, NULL); } gboolean eel_g_strv_equal (char **a, char **b) { int i; if (g_strv_length (a) != g_strv_length (b)) { return FALSE; } for (i = 0; a[i] != NULL; i++) { if (strcmp (a[i], b[i]) != 0) { return FALSE; } } return TRUE; } static int compare_pointers (gconstpointer pointer_1, gconstpointer pointer_2) { if ((const char *) pointer_1 < (const char *) pointer_2) { return -1; } if ((const char *) pointer_1 > (const char *) pointer_2) { return +1; } return 0; } gboolean eel_g_lists_sort_and_check_for_intersection (GList **list_1, GList **list_2) { GList *node_1, *node_2; int compare_result; *list_1 = g_list_sort (*list_1, compare_pointers); *list_2 = g_list_sort (*list_2, compare_pointers); node_1 = *list_1; node_2 = *list_2; while (node_1 != NULL && node_2 != NULL) { compare_result = compare_pointers (node_1->data, node_2->data); if (compare_result == 0) { return TRUE; } if (compare_result <= 0) { node_1 = node_1->next; } if (compare_result >= 0) { node_2 = node_2->next; } } return FALSE; } /** * eel_g_list_partition * * Parition a list into two parts depending on whether the data * elements satisfy a provided predicate. Order is preserved in both * of the resulting lists, and the original list is consumed. A list * of the items that satisfy the predicate is returned, and the list * of items not satisfying the predicate is returned via the failed * out argument. * * @list: List to partition. * @predicate: Function to call on each element. * @user_data: Data to pass to function. * @failed: The GList * variable pointed to by this argument will be * set to the list of elements for which the predicate returned * false. */ GList * eel_g_list_partition (GList *list, EelPredicateFunction predicate, gpointer user_data, GList **failed) { GList *predicate_true; GList *predicate_false; GList *reverse; GList *p; GList *next; predicate_true = NULL; predicate_false = NULL; reverse = g_list_reverse (list); for (p = reverse; p != NULL; p = next) { next = p->next; if (next != NULL) { next->prev = NULL; } if (predicate (p->data, user_data)) { p->next = predicate_true; if (predicate_true != NULL) { predicate_true->prev = p; } predicate_true = p; } else { p->next = predicate_false; if (predicate_false != NULL) { predicate_false->prev = p; } predicate_false = p; } } *failed = predicate_false; return predicate_true; } typedef struct { GList *keys; GList *values; } FlattenedHashTable; static void flatten_hash_table_element (gpointer key, gpointer value, gpointer callback_data) { FlattenedHashTable *flattened_table; flattened_table = callback_data; flattened_table->keys = g_list_prepend (flattened_table->keys, key); flattened_table->values = g_list_prepend (flattened_table->values, value); } void eel_g_hash_table_safe_for_each (GHashTable *hash_table, GHFunc callback, gpointer callback_data) { FlattenedHashTable flattened; GList *p, *q; flattened.keys = NULL; flattened.values = NULL; g_hash_table_foreach (hash_table, flatten_hash_table_element, &flattened); for (p = flattened.keys, q = flattened.values; p != NULL; p = p->next, q = q->next) { (* callback) (p->data, q->data, callback_data); } g_list_free (flattened.keys); g_list_free (flattened.values); } /** * eel_g_object_list_copy * * Copy the list of objects, ref'ing each one. * @list: GList of objects. **/ GList * eel_g_object_list_copy (GList *list) { g_list_foreach (list, (GFunc) g_object_ref, NULL); return g_list_copy (list); } #if !defined (EEL_OMIT_SELF_CHECK) static gboolean eel_test_predicate (gpointer data, gpointer callback_data) { return g_ascii_strcasecmp (data, callback_data) <= 0; } void eel_self_check_glib_extensions (void) { GList *compare_list_1; GList *compare_list_2; GList *compare_list_3; GList *compare_list_4; GList *compare_list_5; GList *list_to_partition; GList *expected_passed; GList *expected_failed; GList *actual_passed; GList *actual_failed; /* eel_g_str_list_equal */ /* We g_strdup because identical string constants can be shared. */ compare_list_1 = NULL; compare_list_1 = g_list_append (compare_list_1, g_strdup ("Apple")); compare_list_1 = g_list_append (compare_list_1, g_strdup ("zebra")); compare_list_1 = g_list_append (compare_list_1, g_strdup ("!@#!@$#@$!")); compare_list_2 = NULL; compare_list_2 = g_list_append (compare_list_2, g_strdup ("Apple")); compare_list_2 = g_list_append (compare_list_2, g_strdup ("zebra")); compare_list_2 = g_list_append (compare_list_2, g_strdup ("!@#!@$#@$!")); compare_list_3 = NULL; compare_list_3 = g_list_append (compare_list_3, g_strdup ("Apple")); compare_list_3 = g_list_append (compare_list_3, g_strdup ("zebra")); compare_list_4 = NULL; compare_list_4 = g_list_append (compare_list_4, g_strdup ("Apple")); compare_list_4 = g_list_append (compare_list_4, g_strdup ("zebra")); compare_list_4 = g_list_append (compare_list_4, g_strdup ("!@#!@$#@$!")); compare_list_4 = g_list_append (compare_list_4, g_strdup ("foobar")); compare_list_5 = NULL; compare_list_5 = g_list_append (compare_list_5, g_strdup ("Apple")); compare_list_5 = g_list_append (compare_list_5, g_strdup ("zzzzzebraaaaaa")); compare_list_5 = g_list_append (compare_list_5, g_strdup ("!@#!@$#@$!")); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_2), TRUE); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_3), FALSE); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_4), FALSE); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (compare_list_1, compare_list_5), FALSE); g_list_free_full (compare_list_1, g_free); g_list_free_full (compare_list_2, g_free); g_list_free_full (compare_list_3, g_free); g_list_free_full (compare_list_4, g_free); g_list_free_full (compare_list_5, g_free); /* eel_g_list_partition */ list_to_partition = NULL; list_to_partition = g_list_append (list_to_partition, (gpointer) "Cadillac"); list_to_partition = g_list_append (list_to_partition, (gpointer) "Pontiac"); list_to_partition = g_list_append (list_to_partition, (gpointer) "Ford"); list_to_partition = g_list_append (list_to_partition, (gpointer) "Range Rover"); expected_passed = NULL; expected_passed = g_list_append (expected_passed, (gpointer) "Cadillac"); expected_passed = g_list_append (expected_passed, (gpointer) "Ford"); expected_failed = NULL; expected_failed = g_list_append (expected_failed, (gpointer) "Pontiac"); expected_failed = g_list_append (expected_failed, (gpointer) "Range Rover"); actual_passed = eel_g_list_partition (list_to_partition, eel_test_predicate, (gpointer) "m", &actual_failed); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (expected_passed, actual_passed), TRUE); EEL_CHECK_BOOLEAN_RESULT (eel_g_str_list_equal (expected_failed, actual_failed), TRUE); /* Don't free "list_to_partition", since it is consumed * by eel_g_list_partition. */ g_list_free (expected_passed); g_list_free (actual_passed); g_list_free (expected_failed); g_list_free (actual_failed); } #endif /* !EEL_OMIT_SELF_CHECK */ nemo-3.6.5/eel/eel-canvas.c0000664000175000017500000034157113215733314014353 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ /* * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation * All rights reserved. * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ /* @NOTATION@ */ /* * EelCanvas widget - Tk-like canvas widget for Gnome * * EelCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. * * * Authors: Federico Mena * Raph Levien */ /* * TO-DO list for the canvas: * * - Allow to specify whether EelCanvasImage sizes are in units or pixels (scale or don't scale). * * - Implement a flag for eel_canvas_item_reparent() that tells the function to keep the item * visually in the same place, that is, to keep it in the same place with respect to the canvas * origin. * * - GC put functions for items. * * - Widget item (finish it). * * - GList *eel_canvas_gimme_all_items_contained_in_this_area (EelCanvas *canvas, Rectangle area); * * - Retrofit all the primitive items with microtile support. * * - Curve support for line item. * * - Arc item (Havoc has it; to be integrated in EelCanvasEllipse). * * - Sane font handling API. * * - Get_arg methods for items: * - How to fetch the outline width and know whether it is in pixels or units? */ #include #include #include #include #include #include #include #include #include "eel-canvas.h" static void eel_canvas_request_update (EelCanvas *canvas); static void group_add (EelCanvasGroup *group, EelCanvasItem *item); static void group_remove (EelCanvasGroup *group, EelCanvasItem *item); static void redraw_and_repick_if_mapped (EelCanvasItem *item); /*** EelCanvasItem ***/ /* Some convenience stuff */ #define GCI_UPDATE_MASK (EEL_CANVAS_UPDATE_REQUESTED | EEL_CANVAS_UPDATE_DEEP) #define GCI_EPSILON 1e-18 enum { ITEM_PROP_0, ITEM_PROP_PARENT, ITEM_PROP_VISIBLE }; enum { ITEM_DESTROY, ITEM_EVENT, ITEM_LAST_SIGNAL }; static void eel_canvas_item_class_init (EelCanvasItemClass *klass); static void eel_canvas_item_init (EelCanvasItem *item); static int emit_event (EelCanvas *canvas, GdkEvent *event); static guint item_signals[ITEM_LAST_SIGNAL] = { 0 }; static GObjectClass *item_parent_class; static gpointer accessible_item_parent_class; static gpointer accessible_parent_class; /** * eel_canvas_item_get_type: * * Registers the &EelCanvasItem class if necessary, and returns the type ID * associated to it. * * Return value: The type ID of the &EelCanvasItem class. **/ GType eel_canvas_item_get_type (void) { static GType canvas_item_type = 0; if (!canvas_item_type) { static const GTypeInfo canvas_item_info = { sizeof (EelCanvasItemClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eel_canvas_item_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (EelCanvasItem), 0, /* n_preallocs */ (GInstanceInitFunc) eel_canvas_item_init }; canvas_item_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, "EelCanvasItem", &canvas_item_info, 0); } return canvas_item_type; } /* Object initialization function for EelCanvasItem */ static void eel_canvas_item_init (EelCanvasItem *item) { item->flags |= EEL_CANVAS_ITEM_VISIBLE; } /** * eel_canvas_item_new: * @parent: The parent group for the new item. * @type: The object type of the item. * @first_arg_name: A list of object argument name/value pairs, NULL-terminated, * used to configure the item. For example, "fill_color", "black", * "width_units", 5.0, NULL. * @Varargs: * * Creates a new canvas item with @parent as its parent group. The item is * created at the top of its parent's stack, and starts up as visible. The item * is of the specified @type, for example, it can be * eel_canvas_rect_get_type(). The list of object arguments/value pairs is * used to configure the item. * * Return value: The newly-created item. **/ EelCanvasItem * eel_canvas_item_new (EelCanvasGroup *parent, GType type, const gchar *first_arg_name, ...) { EelCanvasItem *item; va_list args; g_return_val_if_fail (EEL_IS_CANVAS_GROUP (parent), NULL); g_return_val_if_fail (g_type_is_a (type, eel_canvas_item_get_type ()), NULL); item = EEL_CANVAS_ITEM (g_object_new (type, NULL)); va_start (args, first_arg_name); eel_canvas_item_construct (item, parent, first_arg_name, args); va_end (args); return item; } /* Performs post-creation operations on a canvas item (adding it to its parent * group, etc.) */ static void item_post_create_setup (EelCanvasItem *item) { group_add (EEL_CANVAS_GROUP (item->parent), item); redraw_and_repick_if_mapped (item); } /* Set_property handler for canvas items */ static void eel_canvas_item_set_property (GObject *gobject, guint param_id, const GValue *value, GParamSpec *pspec) { EelCanvasItem *item; g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject)); item = EEL_CANVAS_ITEM (gobject); switch (param_id) { case ITEM_PROP_PARENT: if (item->parent != NULL) { g_warning ("Cannot set `parent' argument after item has " "already been constructed."); } else if (g_value_get_object (value)) { item->parent = EEL_CANVAS_ITEM (g_value_get_object (value)); item->canvas = item->parent->canvas; item_post_create_setup (item); } break; case ITEM_PROP_VISIBLE: if (g_value_get_boolean (value)) { eel_canvas_item_show (item); } else { eel_canvas_item_hide (item); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); break; } } /* Get_property handler for canvas items */ static void eel_canvas_item_get_property (GObject *gobject, guint param_id, GValue *value, GParamSpec *pspec) { EelCanvasItem *item; g_return_if_fail (EEL_IS_CANVAS_ITEM (gobject)); item = EEL_CANVAS_ITEM (gobject); switch (param_id) { case ITEM_PROP_VISIBLE: g_value_set_boolean (value, item->flags & EEL_CANVAS_ITEM_VISIBLE); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); break; } } /** * eel_canvas_item_construct: * @item: An unconstructed canvas item. * @parent: The parent group for the item. * @first_arg_name: The name of the first argument for configuring the item. * @args: The list of arguments used to configure the item. * * Constructs a canvas item; meant for use only by item implementations. **/ void eel_canvas_item_construct (EelCanvasItem *item, EelCanvasGroup *parent, const gchar *first_arg_name, va_list args) { g_return_if_fail (EEL_IS_CANVAS_GROUP (parent)); g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); item->parent = EEL_CANVAS_ITEM (parent); item->canvas = item->parent->canvas; g_object_set_valist (G_OBJECT (item), first_arg_name, args); item_post_create_setup (item); } static void redraw_and_repick_if_mapped (EelCanvasItem *item) { if (item->flags & EEL_CANVAS_ITEM_MAPPED) { eel_canvas_item_request_redraw (item); item->canvas->need_repick = TRUE; } } /* Dispose handler for canvas items */ static void eel_canvas_item_dispose (GObject *object) { EelCanvasItem *item; g_return_if_fail (EEL_IS_CANVAS_ITEM (object)); item = EEL_CANVAS_ITEM (object); if (item->canvas) { eel_canvas_item_request_redraw (item); /* Make the canvas forget about us */ if (item == item->canvas->current_item) { item->canvas->current_item = NULL; item->canvas->need_repick = TRUE; } if (item == item->canvas->new_current_item) { item->canvas->new_current_item = NULL; item->canvas->need_repick = TRUE; } eel_canvas_item_ungrab (item, GDK_CURRENT_TIME); if (item == item->canvas->focused_item) item->canvas->focused_item = NULL; /* Normal destroy stuff */ if (item->flags & EEL_CANVAS_ITEM_MAPPED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); if (item->flags & EEL_CANVAS_ITEM_REALIZED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unrealize) (item); if (item->parent) group_remove (EEL_CANVAS_GROUP (item->parent), item); item->canvas = NULL; } g_object_set_data (object, "in-destruction", GINT_TO_POINTER (1)); g_signal_emit (object, item_signals[ITEM_DESTROY], 0); g_object_set_data (object, "in-destruction", NULL); G_OBJECT_CLASS (item_parent_class)->dispose (object); } void eel_canvas_item_destroy (EelCanvasItem *item) { if (g_object_get_data (G_OBJECT (item), "in-destruction") == NULL) { g_object_run_dispose (G_OBJECT (item)); } } /* Realize handler for canvas items */ static void eel_canvas_item_realize (EelCanvasItem *item) { if (item->parent && !(item->parent->flags & EEL_CANVAS_ITEM_REALIZED)) (* EEL_CANVAS_ITEM_GET_CLASS (item->parent)->realize) (item->parent); if (item->parent == NULL && !gtk_widget_get_realized (GTK_WIDGET (item->canvas))) gtk_widget_realize (GTK_WIDGET (item->canvas)); item->flags |= EEL_CANVAS_ITEM_REALIZED; eel_canvas_item_request_update (item); } /* Unrealize handler for canvas items */ static void eel_canvas_item_unrealize (EelCanvasItem *item) { if (item->flags & EEL_CANVAS_ITEM_MAPPED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); item->flags &= ~(EEL_CANVAS_ITEM_REALIZED); } /* Map handler for canvas items */ static void eel_canvas_item_map (EelCanvasItem *item) { item->flags |= EEL_CANVAS_ITEM_MAPPED; } /* Unmap handler for canvas items */ static void eel_canvas_item_unmap (EelCanvasItem *item) { item->flags &= ~(EEL_CANVAS_ITEM_MAPPED); } /* Update handler for canvas items */ static void eel_canvas_item_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags) { item->flags &= ~(EEL_CANVAS_ITEM_NEED_UPDATE); item->flags &= ~(EEL_CANVAS_ITEM_NEED_DEEP_UPDATE); } /* * This routine invokes the update method of the item * Please notice, that we take parent to canvas pixel matrix as argument * unlike virtual method ::update, whose argument is item 2 canvas pixel * matrix * * I will try to force somewhat meaningful naming for affines (Lauris) * General naming rule is FROM2TO, where FROM and TO are abbreviations * So p2cpx is Parent2CanvasPixel and i2cpx is Item2CanvasPixel * I hope that this helps to keep track of what really happens * */ static void eel_canvas_item_invoke_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags) { int child_flags; child_flags = flags; /* apply object flags to child flags */ child_flags &= ~EEL_CANVAS_UPDATE_REQUESTED; if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE) child_flags |= EEL_CANVAS_UPDATE_REQUESTED; if (item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE) child_flags |= EEL_CANVAS_UPDATE_DEEP; if (child_flags & GCI_UPDATE_MASK) { if (EEL_CANVAS_ITEM_GET_CLASS (item)->update) EEL_CANVAS_ITEM_GET_CLASS (item)->update (item, i2w_dx, i2w_dy, child_flags); } /* If this fail you probably forgot to chain up to * EelCanvasItem::update from a derived class */ g_return_if_fail (!(item->flags & EEL_CANVAS_ITEM_NEED_UPDATE)); } /* * This routine invokes the point method of the item. * The arguments x, y should be in the parent item local coordinates. */ static double eel_canvas_item_invoke_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) { /* Calculate x & y in item local coordinates */ if (EEL_CANVAS_ITEM_GET_CLASS (item)->point) return EEL_CANVAS_ITEM_GET_CLASS (item)->point (item, x, y, cx, cy, actual_item); return 1e18; } /** * eel_canvas_item_set: * @item: A canvas item. * @first_arg_name: The list of object argument name/value pairs used to configure the item. * @Varargs: * * Configures a canvas item. The arguments in the item are set to the specified * values, and the item is repainted as appropriate. **/ void eel_canvas_item_set (EelCanvasItem *item, const gchar *first_arg_name, ...) { va_list args; va_start (args, first_arg_name); eel_canvas_item_set_valist (item, first_arg_name, args); va_end (args); } /** * eel_canvas_item_set_valist: * @item: A canvas item. * @first_arg_name: The name of the first argument used to configure the item. * @args: The list of object argument name/value pairs used to configure the item. * * Configures a canvas item. The arguments in the item are set to the specified * values, and the item is repainted as appropriate. **/ void eel_canvas_item_set_valist (EelCanvasItem *item, const gchar *first_arg_name, va_list args) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_object_set_valist (G_OBJECT (item), first_arg_name, args); item->canvas->need_repick = TRUE; } /** * eel_canvas_item_move: * @item: A canvas item. * @dx: Horizontal offset. * @dy: Vertical offset. * * Moves a canvas item by creating an affine transformation matrix for * translation by using the specified values. This happens in item * local coordinate system, so if you have nontrivial transform, it * most probably does not do, what you want. **/ void eel_canvas_item_move (EelCanvasItem *item, double dx, double dy) { g_return_if_fail (item != NULL); g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (!EEL_CANVAS_ITEM_GET_CLASS (item)->translate) { g_warning ("Item type %s does not implement translate method.\n", g_type_name (G_OBJECT_TYPE (item))); return; } (* EEL_CANVAS_ITEM_GET_CLASS (item)->translate) (item, dx, dy); if (item->flags & EEL_CANVAS_ITEM_MAPPED) item->canvas->need_repick = TRUE; if (!(item->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)) { item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE; if (item->parent != NULL) eel_canvas_item_request_update (item->parent); else eel_canvas_request_update (item->canvas); } } static void eel_canvas_queue_resize (EelCanvas *canvas) { if (gtk_widget_is_drawable (GTK_WIDGET (canvas))) gtk_widget_queue_resize (GTK_WIDGET (canvas)); } /* Convenience function to reorder items in a group's child list. This puts the * specified link after the "before" link. Returns TRUE if the list was changed. */ static gboolean put_item_after (GList *link, GList *before) { EelCanvasGroup *parent; if (link == before) return FALSE; parent = EEL_CANVAS_GROUP (EEL_CANVAS_ITEM (link->data)->parent); if (before == NULL) { if (link == parent->item_list) return FALSE; link->prev->next = link->next; if (link->next) link->next->prev = link->prev; else parent->item_list_end = link->prev; link->prev = before; link->next = parent->item_list; link->next->prev = link; parent->item_list = link; } else { if ((link == parent->item_list_end) && (before == parent->item_list_end->prev)) return FALSE; if (link->next) link->next->prev = link->prev; if (link->prev) link->prev->next = link->next; else { parent->item_list = link->next; parent->item_list->prev = NULL; } link->prev = before; link->next = before->next; link->prev->next = link; if (link->next) link->next->prev = link; else parent->item_list_end = link; } return TRUE; } /** * eel_canvas_item_raise: * @item: A canvas item. * @positions: Number of steps to raise the item. * * Raises the item in its parent's stack by the specified number of positions. * If the number of positions is greater than the distance to the top of the * stack, then the item is put at the top. **/ void eel_canvas_item_raise (EelCanvasItem *item, int positions) { GList *link, *before; EelCanvasGroup *parent; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (positions >= 0); if (!item->parent || positions == 0) return; parent = EEL_CANVAS_GROUP (item->parent); link = g_list_find (parent->item_list, item); g_assert (link != NULL); for (before = link; positions && before; positions--) before = before->next; if (!before) before = parent->item_list_end; if (put_item_after (link, before)) { redraw_and_repick_if_mapped (item); } } /** * eel_canvas_item_lower: * @item: A canvas item. * @positions: Number of steps to lower the item. * * Lowers the item in its parent's stack by the specified number of positions. * If the number of positions is greater than the distance to the bottom of the * stack, then the item is put at the bottom. **/ void eel_canvas_item_lower (EelCanvasItem *item, int positions) { GList *link, *before; EelCanvasGroup *parent; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (positions >= 1); if (!item->parent || positions == 0) return; parent = EEL_CANVAS_GROUP (item->parent); link = g_list_find (parent->item_list, item); g_assert (link != NULL); if (link->prev) for (before = link->prev; positions && before; positions--) before = before->prev; else before = NULL; if (put_item_after (link, before)) { redraw_and_repick_if_mapped (item); } } /** * eel_canvas_item_raise_to_top: * @item: A canvas item. * * Raises an item to the top of its parent's stack. **/ void eel_canvas_item_raise_to_top (EelCanvasItem *item) { GList *link; EelCanvasGroup *parent; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (!item->parent) return; parent = EEL_CANVAS_GROUP (item->parent); link = g_list_find (parent->item_list, item); g_assert (link != NULL); if (put_item_after (link, parent->item_list_end)) { redraw_and_repick_if_mapped (item); } } /** * eel_canvas_item_lower_to_bottom: * @item: A canvas item. * * Lowers an item to the bottom of its parent's stack. **/ void eel_canvas_item_lower_to_bottom (EelCanvasItem *item) { GList *link; EelCanvasGroup *parent; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (!item->parent) return; parent = EEL_CANVAS_GROUP (item->parent); link = g_list_find (parent->item_list, item); g_assert (link != NULL); if (put_item_after (link, NULL)) { redraw_and_repick_if_mapped (item); } } /** * eel_canvas_item_send_behind: * @item: A canvas item. * @behind_item: The canvas item to put item behind, or NULL * * Moves item to a in the position in the stacking order so that * it is placed immediately below behind_item, or at the top if * behind_item is NULL. **/ void eel_canvas_item_send_behind (EelCanvasItem *item, EelCanvasItem *behind_item) { GList *item_list; int item_position, behind_position; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (behind_item == NULL) { eel_canvas_item_raise_to_top (item); return; } g_return_if_fail (EEL_IS_CANVAS_ITEM (behind_item)); g_return_if_fail (item->parent == behind_item->parent); item_list = EEL_CANVAS_GROUP (item->parent)->item_list; item_position = g_list_index (item_list, item); g_assert (item_position != -1); behind_position = g_list_index (item_list, behind_item); g_assert (behind_position != -1); g_assert (item_position != behind_position); if (item_position == behind_position - 1) { return; } if (item_position < behind_position) { eel_canvas_item_raise (item, (behind_position - 1) - item_position); } else { eel_canvas_item_lower (item, item_position - behind_position); } } /** * eel_canvas_item_show: * @item: A canvas item. * * Shows a canvas item. If the item was already shown, then no action is taken. **/ void eel_canvas_item_show (EelCanvasItem *item) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (!(item->flags & EEL_CANVAS_ITEM_VISIBLE)) { item->flags |= EEL_CANVAS_ITEM_VISIBLE; if (!(item->flags & EEL_CANVAS_ITEM_REALIZED)) (* EEL_CANVAS_ITEM_GET_CLASS (item)->realize) (item); if (item->parent != NULL) { if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) && (item->parent->flags & EEL_CANVAS_ITEM_MAPPED)) (* EEL_CANVAS_ITEM_GET_CLASS (item)->map) (item); } else { if (!(item->flags & EEL_CANVAS_ITEM_MAPPED) && gtk_widget_get_mapped (GTK_WIDGET (item->canvas))) (* EEL_CANVAS_ITEM_GET_CLASS (item)->map) (item); } redraw_and_repick_if_mapped (item); eel_canvas_queue_resize (item->canvas); } } /** * eel_canvas_item_hide: * @item: A canvas item. * * Hides a canvas item. If the item was already hidden, then no action is * taken. **/ void eel_canvas_item_hide (EelCanvasItem *item) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (item->flags & EEL_CANVAS_ITEM_VISIBLE) { item->flags &= ~EEL_CANVAS_ITEM_VISIBLE; redraw_and_repick_if_mapped (item); if (item->flags & EEL_CANVAS_ITEM_MAPPED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); eel_canvas_queue_resize (item->canvas); /* No need to unrealize when we just want to hide */ } } /** * eel_canvas_item_grab: * @item: A canvas item. * @event_mask: Mask of events that will be sent to this item. * @cursor: If non-NULL, the cursor that will be used while the grab is active. * @etime: The timestamp required for grabbing the mouse, or GDK_CURRENT_TIME. * * Specifies that all events that match the specified event mask should be sent * to the specified item, and also grabs the mouse by calling * gdk_pointer_grab(). The event mask is also used when grabbing the pointer. * If @cursor is not NULL, then that cursor is used while the grab is active. * The @etime parameter is the timestamp required for grabbing the mouse. * * Return value: If an item was already grabbed, it returns %GDK_GRAB_ALREADY_GRABBED. If * the specified item was hidden by calling eel_canvas_item_hide(), then it * returns %GDK_GRAB_NOT_VIEWABLE. Else, it returns the result of calling * gdk_pointer_grab(). **/ GdkGrabStatus eel_canvas_item_grab (EelCanvasItem *item, GdkEventMask event_mask, GdkCursor *cursor, guint32 timestamp) { GdkGrabStatus retval; GdkDisplay *display; GdkDeviceManager *manager; GdkDevice *device; g_return_val_if_fail (EEL_IS_CANVAS_ITEM (item), GDK_GRAB_NOT_VIEWABLE); g_return_val_if_fail (gtk_widget_get_mapped (GTK_WIDGET (item->canvas)), GDK_GRAB_NOT_VIEWABLE); if (item->canvas->grabbed_item) return GDK_GRAB_ALREADY_GRABBED; if (!(item->flags & EEL_CANVAS_ITEM_MAPPED)) return GDK_GRAB_NOT_VIEWABLE; display = gtk_widget_get_display (GTK_WIDGET (item->canvas)); manager = gdk_display_get_device_manager (display); device = gdk_device_manager_get_client_pointer (manager); retval = gdk_device_grab (device, gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)), GDK_OWNERSHIP_NONE, FALSE, event_mask, cursor, timestamp); if (retval != GDK_GRAB_SUCCESS) return retval; item->canvas->grabbed_item = item; item->canvas->grabbed_event_mask = event_mask; item->canvas->current_item = item; /* So that events go to the grabbed item */ return retval; } /** * eel_canvas_item_ungrab: * @item: A canvas item that holds a grab. * @etime: The timestamp for ungrabbing the mouse. * * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the * mouse. **/ void eel_canvas_item_ungrab (EelCanvasItem *item, guint32 etime) { GdkDisplay *display; GdkDeviceManager *manager; GdkDevice *device; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); if (item->canvas->grabbed_item != item) return; display = gtk_widget_get_display (GTK_WIDGET (item->canvas)); manager = gdk_display_get_device_manager (display); device = gdk_device_manager_get_client_pointer (manager); item->canvas->grabbed_item = NULL; gdk_device_ungrab (device, etime); } /** * eel_canvas_item_w2i: * @item: A canvas item. * @x: X coordinate to convert (input/output value). * @y: Y coordinate to convert (input/output value). * * Converts a coordinate pair from world coordinates to item-relative * coordinates. **/ void eel_canvas_item_w2i (EelCanvasItem *item, double *x, double *y) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); item = item->parent; while (item) { if (EEL_IS_CANVAS_GROUP (item)) { *x -= EEL_CANVAS_GROUP (item)->xpos; *y -= EEL_CANVAS_GROUP (item)->ypos; } item = item->parent; } } /** * eel_canvas_item_i2w: * @item: A canvas item. * @x: X coordinate to convert (input/output value). * @y: Y coordinate to convert (input/output value). * * Converts a coordinate pair from item-relative coordinates to world * coordinates. **/ void eel_canvas_item_i2w (EelCanvasItem *item, double *x, double *y) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); item = item->parent; while (item) { if (EEL_IS_CANVAS_GROUP (item)) { *x += EEL_CANVAS_GROUP (item)->xpos; *y += EEL_CANVAS_GROUP (item)->ypos; } item = item->parent; } } /* Returns whether the item is an inferior of or is equal to the parent. */ static int is_descendant (EelCanvasItem *item, EelCanvasItem *parent) { for (; item; item = item->parent) if (item == parent) return TRUE; return FALSE; } /** * eel_canvas_item_reparent: * @item: A canvas item. * @new_group: A canvas group. * * Changes the parent of the specified item to be the new group. The item keeps * its group-relative coordinates as for its old parent, so the item may change * its absolute position within the canvas. **/ void eel_canvas_item_reparent (EelCanvasItem *item, EelCanvasGroup *new_group) { g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (EEL_IS_CANVAS_GROUP (new_group)); /* Both items need to be in the same canvas */ g_return_if_fail (item->canvas == EEL_CANVAS_ITEM (new_group)->canvas); /* The group cannot be an inferior of the item or be the item itself -- * this also takes care of the case where the item is the root item of * the canvas. */ g_return_if_fail (!is_descendant (EEL_CANVAS_ITEM (new_group), item)); /* Everything is ok, now actually reparent the item */ g_object_ref (G_OBJECT (item)); /* protect it from the unref in group_remove */ eel_canvas_item_request_redraw (item); group_remove (EEL_CANVAS_GROUP (item->parent), item); item->parent = EEL_CANVAS_ITEM (new_group); /* item->canvas is unchanged. */ group_add (new_group, item); /* Redraw and repick */ redraw_and_repick_if_mapped (item); g_object_unref (G_OBJECT (item)); } /** * eel_canvas_item_grab_focus: * @item: A canvas item. * * Makes the specified item take the keyboard focus, so all keyboard events will * be sent to it. If the canvas widget itself did not have the focus, it grabs * it as well. **/ void eel_canvas_item_grab_focus (EelCanvasItem *item) { EelCanvasItem *focused_item; GdkEvent ev; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas))); focused_item = item->canvas->focused_item; if (focused_item) { ev.focus_change.type = GDK_FOCUS_CHANGE; ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)); ev.focus_change.send_event = FALSE; ev.focus_change.in = FALSE; emit_event (item->canvas, &ev); } item->canvas->focused_item = item; gtk_widget_grab_focus (GTK_WIDGET (item->canvas)); if (focused_item) { ev.focus_change.type = GDK_FOCUS_CHANGE; ev.focus_change.window = gtk_layout_get_bin_window (GTK_LAYOUT (item->canvas)); ev.focus_change.send_event = FALSE; ev.focus_change.in = TRUE; emit_event (item->canvas, &ev); } } /** * eel_canvas_item_get_bounds: * @item: A canvas item. * @x1: Leftmost edge of the bounding box (return value). * @y1: Upper edge of the bounding box (return value). * @x2: Rightmost edge of the bounding box (return value). * @y2: Lower edge of the bounding box (return value). * * Queries the bounding box of a canvas item. The bounds are returned in the * coordinate system of the item's parent. **/ void eel_canvas_item_get_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { double tx1, ty1, tx2, ty2; g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); tx1 = ty1 = tx2 = ty2 = 0.0; /* Get the item's bounds in its coordinate system */ if (EEL_CANVAS_ITEM_GET_CLASS (item)->bounds) (* EEL_CANVAS_ITEM_GET_CLASS (item)->bounds) (item, &tx1, &ty1, &tx2, &ty2); /* Return the values */ if (x1) *x1 = tx1; if (y1) *y1 = ty1; if (x2) *x2 = tx2; if (y2) *y2 = ty2; } /** * eel_canvas_item_request_update * @item: A canvas item. * * To be used only by item implementations. Requests that the canvas queue an * update for the specified item. **/ void eel_canvas_item_request_update (EelCanvasItem *item) { if (NULL == item->canvas) return; g_return_if_fail (!item->canvas->doing_update); if (item->flags & EEL_CANVAS_ITEM_NEED_UPDATE) return; item->flags |= EEL_CANVAS_ITEM_NEED_UPDATE; if (item->parent != NULL) { /* Recurse up the tree */ eel_canvas_item_request_update (item->parent); } else { /* Have reached the top of the tree, make sure the update call gets scheduled. */ eel_canvas_request_update (item->canvas); } } /** * eel_canvas_item_request_update * @item: A canvas item. * * Convenience function that informs a canvas that the specified item needs * to be repainted. To be used by item implementations **/ void eel_canvas_item_request_redraw (EelCanvasItem *item) { if (item->flags & EEL_CANVAS_ITEM_MAPPED) eel_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2 + 1, item->y2 + 1); } /*** EelCanvasGroup ***/ enum { GROUP_PROP_0, GROUP_PROP_X, GROUP_PROP_Y }; static void eel_canvas_group_class_init (EelCanvasGroupClass *klass); static void eel_canvas_group_init (EelCanvasGroup *group); static void eel_canvas_group_set_property(GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void eel_canvas_group_get_property(GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void eel_canvas_group_destroy (EelCanvasItem *object); static void eel_canvas_group_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags); static void eel_canvas_group_unrealize (EelCanvasItem *item); static void eel_canvas_group_map (EelCanvasItem *item); static void eel_canvas_group_unmap (EelCanvasItem *item); static void eel_canvas_group_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region); static double eel_canvas_group_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item); static void eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy); static void eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2); static EelCanvasItemClass *group_parent_class; /** * eel_canvas_group_get_type: * * Registers the &EelCanvasGroup class if necessary, and returns the type ID * associated to it. * * Return value: The type ID of the &EelCanvasGroup class. **/ GType eel_canvas_group_get_type (void) { static GType group_type = 0; if (!group_type) { static const GTypeInfo group_info = { sizeof (EelCanvasGroupClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eel_canvas_group_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (EelCanvasGroup), 0, /* n_preallocs */ (GInstanceInitFunc) eel_canvas_group_init }; group_type = g_type_register_static (eel_canvas_item_get_type (), "EelCanvasGroup", &group_info, 0); } return group_type; } /* Class initialization function for EelCanvasGroupClass */ static void eel_canvas_group_class_init (EelCanvasGroupClass *klass) { GObjectClass *gobject_class; EelCanvasItemClass *item_class; gobject_class = (GObjectClass *) klass; item_class = (EelCanvasItemClass *) klass; group_parent_class = g_type_class_peek_parent (klass); gobject_class->set_property = eel_canvas_group_set_property; gobject_class->get_property = eel_canvas_group_get_property; g_object_class_install_property (gobject_class, GROUP_PROP_X, g_param_spec_double ("x", _("X"), _("X"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, GROUP_PROP_Y, g_param_spec_double ("y", _("Y"), _("Y"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE)); item_class->destroy = eel_canvas_group_destroy; item_class->update = eel_canvas_group_update; item_class->unrealize = eel_canvas_group_unrealize; item_class->map = eel_canvas_group_map; item_class->unmap = eel_canvas_group_unmap; item_class->draw = eel_canvas_group_draw; item_class->point = eel_canvas_group_point; item_class->translate = eel_canvas_group_translate; item_class->bounds = eel_canvas_group_bounds; } /* Object initialization function for EelCanvasGroup */ static void eel_canvas_group_init (EelCanvasGroup *group) { group->xpos = 0.0; group->ypos = 0.0; } /* Set_property handler for canvas groups */ static void eel_canvas_group_set_property (GObject *gobject, guint param_id, const GValue *value, GParamSpec *pspec) { EelCanvasItem *item; EelCanvasGroup *group; double old; gboolean moved; g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject)); item = EEL_CANVAS_ITEM (gobject); group = EEL_CANVAS_GROUP (gobject); moved = FALSE; switch (param_id) { case GROUP_PROP_X: old = group->xpos; group->xpos = g_value_get_double (value); if (old != group->xpos) moved = TRUE; break; case GROUP_PROP_Y: old = group->ypos; group->ypos = g_value_get_double (value); if (old != group->ypos) moved = TRUE; break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); break; } if (moved) { item->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE; if (item->parent != NULL) eel_canvas_item_request_update (item->parent); else eel_canvas_request_update (item->canvas); } } /* Get_property handler for canvas groups */ static void eel_canvas_group_get_property (GObject *gobject, guint param_id, GValue *value, GParamSpec *pspec) { EelCanvasGroup *group; g_return_if_fail (EEL_IS_CANVAS_GROUP (gobject)); group = EEL_CANVAS_GROUP (gobject); switch (param_id) { case GROUP_PROP_X: g_value_set_double (value, group->xpos); break; case GROUP_PROP_Y: g_value_set_double (value, group->ypos); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, param_id, pspec); break; } } /* Destroy handler for canvas groups */ static void eel_canvas_group_destroy (EelCanvasItem *object) { EelCanvasGroup *group; EelCanvasItem *child; GList *list; g_return_if_fail (EEL_IS_CANVAS_GROUP (object)); group = EEL_CANVAS_GROUP (object); list = group->item_list; while (list) { child = list->data; list = list->next; eel_canvas_item_destroy (child); } if (EEL_CANVAS_ITEM_CLASS (group_parent_class)->destroy) (* EEL_CANVAS_ITEM_CLASS (group_parent_class)->destroy) (object); } /* Update handler for canvas groups */ static void eel_canvas_group_update (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags) { EelCanvasGroup *group; GList *list; EelCanvasItem *i; double bbox_x0, bbox_y0, bbox_x1, bbox_y1; gboolean first = TRUE; group = EEL_CANVAS_GROUP (item); (* group_parent_class->update) (item, i2w_dx, i2w_dy, flags); bbox_x0 = 0; bbox_y0 = 0; bbox_x1 = 0; bbox_y1 = 0; for (list = group->item_list; list; list = list->next) { i = list->data; eel_canvas_item_invoke_update (i, i2w_dx + group->xpos, i2w_dy + group->ypos, flags); if (first) { first = FALSE; bbox_x0 = i->x1; bbox_y0 = i->y1; bbox_x1 = i->x2; bbox_y1 = i->y2; } else { bbox_x0 = MIN (bbox_x0, i->x1); bbox_y0 = MIN (bbox_y0, i->y1); bbox_x1 = MAX (bbox_x1, i->x2); bbox_y1 = MAX (bbox_y1, i->y2); } } item->x1 = bbox_x0; item->y1 = bbox_y0; item->x2 = bbox_x1; item->y2 = bbox_y1; } /* Unrealize handler for canvas groups */ static void eel_canvas_group_unrealize (EelCanvasItem *item) { EelCanvasGroup *group; GList *list; EelCanvasItem *i; group = EEL_CANVAS_GROUP (item); /* Unmap group before children to avoid flash */ if (item->flags & EEL_CANVAS_ITEM_MAPPED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); for (list = group->item_list; list; list = list->next) { i = list->data; if (i->flags & EEL_CANVAS_ITEM_REALIZED) (* EEL_CANVAS_ITEM_GET_CLASS (i)->unrealize) (i); } (* group_parent_class->unrealize) (item); } /* Map handler for canvas groups */ static void eel_canvas_group_map (EelCanvasItem *item) { EelCanvasGroup *group; GList *list; EelCanvasItem *i; group = EEL_CANVAS_GROUP (item); for (list = group->item_list; list; list = list->next) { i = list->data; if ((i->flags & EEL_CANVAS_ITEM_VISIBLE) && !(i->flags & EEL_CANVAS_ITEM_MAPPED)) { if (!(i->flags & EEL_CANVAS_ITEM_REALIZED)) (* EEL_CANVAS_ITEM_GET_CLASS (i)->realize) (i); (* EEL_CANVAS_ITEM_GET_CLASS (i)->map) (i); } } (* group_parent_class->map) (item); } /* Unmap handler for canvas groups */ static void eel_canvas_group_unmap (EelCanvasItem *item) { EelCanvasGroup *group; GList *list; EelCanvasItem *i; group = EEL_CANVAS_GROUP (item); for (list = group->item_list; list; list = list->next) { i = list->data; if (i->flags & EEL_CANVAS_ITEM_MAPPED) (* EEL_CANVAS_ITEM_GET_CLASS (i)->unmap) (i); } (* group_parent_class->unmap) (item); } /* Draw handler for canvas groups */ static void eel_canvas_group_draw (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region) { EelCanvasGroup *group; GList *list; EelCanvasItem *child = NULL; group = EEL_CANVAS_GROUP (item); for (list = group->item_list; list; list = list->next) { child = list->data; if ((child->flags & EEL_CANVAS_ITEM_MAPPED) && (EEL_CANVAS_ITEM_GET_CLASS (child)->draw)) { GdkRectangle child_rect; child_rect.x = child->x1; child_rect.y = child->y1; child_rect.width = child->x2 - child->x1 + 1; child_rect.height = child->y2 - child->y1 + 1; if (cairo_region_contains_rectangle (region, &child_rect) != CAIRO_REGION_OVERLAP_OUT) EEL_CANVAS_ITEM_GET_CLASS (child)->draw (child, cr, region); } } } /* Point handler for canvas groups */ static double eel_canvas_group_point (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item) { EelCanvasGroup *group; GList *list; EelCanvasItem *child, *point_item; int x1, y1, x2, y2; double gx, gy; double dist, best; int has_point; group = EEL_CANVAS_GROUP (item); x1 = cx - item->canvas->close_enough; y1 = cy - item->canvas->close_enough; x2 = cx + item->canvas->close_enough; y2 = cy + item->canvas->close_enough; best = 0.0; *actual_item = NULL; gx = x - group->xpos; gy = y - group->ypos; dist = 0.0; /* keep gcc happy */ for (list = group->item_list; list; list = list->next) { child = list->data; if ((child->x1 > x2) || (child->y1 > y2) || (child->x2 < x1) || (child->y2 < y1)) continue; point_item = NULL; /* cater for incomplete item implementations */ if ((child->flags & EEL_CANVAS_ITEM_MAPPED) && EEL_CANVAS_ITEM_GET_CLASS (child)->point) { dist = eel_canvas_item_invoke_point (child, gx, gy, cx, cy, &point_item); has_point = TRUE; } else has_point = FALSE; if (has_point && point_item && ((int) (dist * item->canvas->pixels_per_unit + 0.5) <= item->canvas->close_enough)) { best = dist; *actual_item = point_item; } } return best; } void eel_canvas_group_translate (EelCanvasItem *item, double dx, double dy) { EelCanvasGroup *group; group = EEL_CANVAS_GROUP (item); group->xpos += dx; group->ypos += dy; } /* Bounds handler for canvas groups */ static void eel_canvas_group_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2) { EelCanvasGroup *group; EelCanvasItem *child; GList *list; double tx1, ty1, tx2, ty2; double minx, miny, maxx, maxy; int set; group = EEL_CANVAS_GROUP (item); /* Get the bounds of the first visible item */ child = NULL; /* Unnecessary but eliminates a warning. */ set = FALSE; for (list = group->item_list; list; list = list->next) { child = list->data; if (child->flags & EEL_CANVAS_ITEM_MAPPED) { set = TRUE; eel_canvas_item_get_bounds (child, &minx, &miny, &maxx, &maxy); break; } } /* If there were no visible items, return an empty bounding box */ if (!set) { *x1 = *y1 = *x2 = *y2 = 0.0; return; } /* Now we can grow the bounds using the rest of the items */ list = list->next; for (; list; list = list->next) { child = list->data; if (!(child->flags & EEL_CANVAS_ITEM_MAPPED)) continue; eel_canvas_item_get_bounds (child, &tx1, &ty1, &tx2, &ty2); if (tx1 < minx) minx = tx1; if (ty1 < miny) miny = ty1; if (tx2 > maxx) maxx = tx2; if (ty2 > maxy) maxy = ty2; } /* Make the bounds be relative to our parent's coordinate system */ if (item->parent) { minx += group->xpos; miny += group->ypos; maxx += group->xpos; maxy += group->ypos; } *x1 = minx; *y1 = miny; *x2 = maxx; *y2 = maxy; } /* Adds an item to a group */ static void group_add (EelCanvasGroup *group, EelCanvasItem *item) { g_object_ref_sink (item); /* FIXME: relatively inefficient way to add to the list, appending to the list causes it to be read from the top each time. prepend, followed by a reverse if necessary is the recommended approach. However as this list append is a number of levels of call down, correcting it is not as easy as it could be */ if (!group->item_list) { group->item_list = g_list_append (group->item_list, item); group->item_list_end = group->item_list; } else group->item_list_end = g_list_append (group->item_list_end, item)->next; if ((item->flags & EEL_CANVAS_ITEM_VISIBLE) && (group->item.flags & EEL_CANVAS_ITEM_MAPPED)) { if (!(item->flags & EEL_CANVAS_ITEM_REALIZED)) (* EEL_CANVAS_ITEM_GET_CLASS (item)->realize) (item); if (!(item->flags & EEL_CANVAS_ITEM_MAPPED)) (* EEL_CANVAS_ITEM_GET_CLASS (item)->map) (item); } if (item->flags & EEL_CANVAS_ITEM_VISIBLE) eel_canvas_queue_resize (EEL_CANVAS_ITEM (group)->canvas); } /* Removes an item from a group */ static void group_remove (EelCanvasGroup *group, EelCanvasItem *item) { GList *children; g_return_if_fail (EEL_IS_CANVAS_GROUP (group)); g_return_if_fail (EEL_IS_CANVAS_ITEM (item)); for (children = group->item_list; children; children = children->next) if (children->data == item) { if (item->flags & EEL_CANVAS_ITEM_MAPPED) { (* EEL_CANVAS_ITEM_GET_CLASS (item)->unmap) (item); } if (item->flags & EEL_CANVAS_ITEM_REALIZED) (* EEL_CANVAS_ITEM_GET_CLASS (item)->unrealize) (item); if (item->flags & EEL_CANVAS_ITEM_VISIBLE) eel_canvas_queue_resize (item->canvas); /* Unparent the child */ item->parent = NULL; /* item->canvas = NULL; */ g_object_unref (G_OBJECT (item)); /* Remove it from the list */ if (children == group->item_list_end) group->item_list_end = children->prev; group->item_list = g_list_remove_link (group->item_list, children); g_list_free (children); break; } } /*** EelCanvas ***/ enum { DRAW_BACKGROUND, LAST_SIGNAL }; static void eel_canvas_class_init (EelCanvasClass *klass); static void eel_canvas_init (EelCanvas *canvas); static void eel_canvas_destroy (GtkWidget *object); static void eel_canvas_map (GtkWidget *widget); static void eel_canvas_unmap (GtkWidget *widget); static void eel_canvas_realize (GtkWidget *widget); static void eel_canvas_unrealize (GtkWidget *widget); static void eel_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gint eel_canvas_button (GtkWidget *widget, GdkEventButton *event); static gint eel_canvas_motion (GtkWidget *widget, GdkEventMotion *event); static gint eel_canvas_draw (GtkWidget *widget, cairo_t *cr); static gint eel_canvas_key (GtkWidget *widget, GdkEventKey *event); static gint eel_canvas_crossing (GtkWidget *widget, GdkEventCrossing *event); static gint eel_canvas_focus_in (GtkWidget *widget, GdkEventFocus *event); static gint eel_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event); static void eel_canvas_request_update_real (EelCanvas *canvas); static void eel_canvas_draw_background (EelCanvas *canvas, cairo_t *cr); static AtkObject *eel_canvas_get_accessible (GtkWidget *widget); static GtkLayoutClass *canvas_parent_class; static guint canvas_signals[LAST_SIGNAL] = { 0 }; /** * eel_canvas_get_type: * * Registers the &EelCanvas class if necessary, and returns the type ID * associated to it. * * Return value: The type ID of the &EelCanvas class. **/ GType eel_canvas_get_type (void) { static GType canvas_type = 0; if (!canvas_type) { static const GTypeInfo canvas_info = { sizeof (EelCanvasClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eel_canvas_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (EelCanvas), 0, /* n_preallocs */ (GInstanceInitFunc) eel_canvas_init }; canvas_type = g_type_register_static (gtk_layout_get_type (), "EelCanvas", &canvas_info, 0); } return canvas_type; } static void eel_canvas_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eel_canvas_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void eel_canvas_accessible_adjustment_changed (GtkAdjustment *adjustment, AtkObject *obj) { /* The scrollbars have changed */ g_signal_emit_by_name (obj, "visible_data_changed"); } static void accessible_destroy_cb (GtkWidget *widget, AtkObject *obj) { gtk_accessible_set_widget (GTK_ACCESSIBLE(obj), NULL); atk_object_notify_state_change (obj, ATK_STATE_DEFUNCT, TRUE); } static gboolean accessible_focus_cb (GtkWidget *widget, GdkEventFocus *event) { atk_object_notify_state_change ((AtkObject *)gtk_widget_get_accessible (widget), ATK_STATE_FOCUSED, event->in); return FALSE; } static void accessible_notify_cb (GObject *obj, GParamSpec *pspec) { GtkWidget* widget = GTK_WIDGET (obj); AtkObject* atk_obj = gtk_widget_get_accessible (widget); AtkState state; gboolean value; if (strcmp (pspec->name, "visible") == 0) { state = ATK_STATE_VISIBLE; value = gtk_widget_get_visible (widget); } else if (strcmp (pspec->name, "sensitive") == 0) { state = ATK_STATE_SENSITIVE; value = gtk_widget_get_sensitive (widget); atk_object_notify_state_change (atk_obj, ATK_STATE_ENABLED, value); } else { g_assert_not_reached (); } atk_object_notify_state_change (atk_obj, state, value); } /* Translate GtkWidget::size-allocate to AtkComponent::bounds-changed */ static void accessible_size_allocate_cb (GtkWidget *widget, GtkAllocation *allocation) { AtkObject* accessible = gtk_widget_get_accessible (widget); AtkRectangle rect; rect.x = allocation->x; rect.y = allocation->y; rect.width = allocation->width; rect.height = allocation->height; g_signal_emit_by_name (accessible, "bounds_changed", &rect); } /* Translate GtkWidget mapped state into AtkObject showing */ static void accessible_map_cb (GtkWidget *widget) { AtkObject *accessible = gtk_widget_get_accessible (widget); atk_object_notify_state_change (accessible, ATK_STATE_SHOWING, gtk_widget_get_mapped (widget)); } static void eel_canvas_accessible_initialize (AtkObject *obj, gpointer data) { EelCanvas *canvas = data; if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize != NULL) { ATK_OBJECT_CLASS (accessible_parent_class)->initialize (obj, data); } gtk_accessible_set_widget (GTK_ACCESSIBLE (obj), GTK_WIDGET (data)); g_signal_connect (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)), "value_changed", G_CALLBACK (eel_canvas_accessible_adjustment_changed), obj); g_signal_connect (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)), "value_changed", G_CALLBACK (eel_canvas_accessible_adjustment_changed), obj); obj->role = ATK_ROLE_LAYERED_PANE; /* below adapted from gtkwidgetaccessible.c */ g_signal_connect_after (canvas, "destroy", G_CALLBACK (accessible_destroy_cb), obj); g_signal_connect_after (canvas, "focus-in-event", G_CALLBACK (accessible_focus_cb), NULL); g_signal_connect_after (canvas, "focus-out-event", G_CALLBACK (accessible_focus_cb), NULL); g_signal_connect (canvas, "notify::visible", G_CALLBACK (accessible_notify_cb), NULL); g_signal_connect (canvas, "notify::sensitive", G_CALLBACK (accessible_notify_cb), NULL); g_signal_connect (canvas, "size-allocate", G_CALLBACK (accessible_size_allocate_cb), NULL); g_signal_connect (canvas, "map", G_CALLBACK (accessible_map_cb), NULL); g_signal_connect (canvas, "unmap", G_CALLBACK (accessible_map_cb), NULL); } static gint eel_canvas_accessible_get_n_children (AtkObject* obj) { GtkWidget *widget; EelCanvas *canvas; EelCanvasGroup *root_group; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); if (widget == NULL) { return 0; } g_return_val_if_fail (EEL_IS_CANVAS (widget), 0); canvas = EEL_CANVAS (widget); root_group = eel_canvas_root (canvas); g_return_val_if_fail (root_group, 0); return 1; } static AtkObject* eel_canvas_accessible_ref_child (AtkObject *obj, gint i) { GtkWidget *widget; EelCanvas *canvas; EelCanvasGroup *root_group; AtkObject *atk_object; /* Canvas only has one child, so return NULL if index is non zero */ if (i != 0) { return NULL; } widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); if (widget == NULL) { return NULL; } canvas = EEL_CANVAS (widget); root_group = eel_canvas_root (canvas); g_return_val_if_fail (root_group, NULL); atk_object = atk_gobject_accessible_for_object (G_OBJECT (root_group)); return g_object_ref (atk_object); } static gboolean eel_canvas_accessible_all_parents_visible (GtkWidget *widget) { GtkWidget *iter_parent = NULL; gboolean result = TRUE; for (iter_parent = gtk_widget_get_parent (widget); iter_parent != NULL; iter_parent = gtk_widget_get_parent (iter_parent)) { if (!gtk_widget_get_visible (iter_parent)) { result = FALSE; break; } } return result; } static gboolean eel_canvas_accessible_on_screen (GtkWidget *widget) { GtkAllocation allocation; GtkWidget *viewport; gboolean return_value = TRUE; gtk_widget_get_allocation (widget, &allocation); viewport = gtk_widget_get_ancestor (widget, GTK_TYPE_VIEWPORT); if (viewport) { GtkAllocation viewport_allocation; GtkAdjustment *adjustment; GdkRectangle visible_rect; gtk_widget_get_allocation (viewport, &viewport_allocation); adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (viewport)); visible_rect.y = gtk_adjustment_get_value (adjustment); adjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (viewport)); visible_rect.x = gtk_adjustment_get_value (adjustment); visible_rect.width = viewport_allocation.width; visible_rect.height = viewport_allocation.height; if (((allocation.x + allocation.width) < visible_rect.x) || ((allocation.y + allocation.height) < visible_rect.y) || (allocation.x > (visible_rect.x + visible_rect.width)) || (allocation.y > (visible_rect.y + visible_rect.height))) { return_value = FALSE; } } else { /* Check whether the widget has been placed off the screen. * The widget may be MAPPED as when toolbar items do not * fit on the toolbar. */ if (allocation.x + allocation.width <= 0 && allocation.y + allocation.height <= 0) { return_value = FALSE; } } return return_value; } static AtkStateSet * eel_canvas_accessible_ref_state_set (AtkObject *accessible) { GtkWidget *widget; AtkStateSet *state_set; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); state_set = ATK_OBJECT_CLASS (accessible_parent_class)->ref_state_set (accessible); if (widget == NULL) { atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT); } else { if (gtk_widget_is_sensitive (widget)) { atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); atk_state_set_add_state (state_set, ATK_STATE_ENABLED); } if (gtk_widget_get_can_focus (widget)) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE); } /* * We do not currently generate notifications when an ATK object * corresponding to a GtkWidget changes visibility by being scrolled * on or off the screen. The testcase for this is the main window * of the testgtk application in which a set of buttons in a GtkVBox * is in a scrolled window with a viewport. * * To generate the notifications we would need to do the following: * 1) Find the GtkViewport among the ancestors of the objects * 2) Create an accessible for the viewport * 3) Connect to the value-changed signal on the viewport * 4) When the signal is received we need to traverse the children * of the viewport and check whether the children are visible or not * visible; we may want to restrict this to the widgets for which * accessible objects have been created. * 5) We probably need to store a variable on_screen in the * GtkWidgetAccessible data structure so we can determine whether * the value has changed. */ if (gtk_widget_get_visible (widget)) { atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); if (eel_canvas_accessible_on_screen (widget) && gtk_widget_get_mapped (widget) && eel_canvas_accessible_all_parents_visible (widget)) { atk_state_set_add_state (state_set, ATK_STATE_SHOWING); } } if (gtk_widget_has_focus (widget)) { if (g_object_get_data (G_OBJECT (accessible), "gail-focus-object") == NULL) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); } } if (gtk_widget_has_default (widget)) { atk_state_set_add_state (state_set, ATK_STATE_DEFAULT); } } return state_set; } static void eel_canvas_accessible_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type) { GdkWindow *window; gint x_window, y_window; gint x_toplevel, y_toplevel; GtkWidget *widget; GtkAllocation allocation; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) { return; } gtk_widget_get_allocation (widget, &allocation); *width = allocation.width; *height = allocation.height; if (!eel_canvas_accessible_on_screen (widget) || !gtk_widget_is_drawable (widget)) { *x = G_MININT; *y = G_MININT; return; } if (gtk_widget_get_parent (widget)) { *x = allocation.x; *y = allocation.y; window = gtk_widget_get_parent_window (widget); } else { *x = 0; *y = 0; window = gtk_widget_get_window (widget); } gdk_window_get_origin (window, &x_window, &y_window); *x += x_window; *y += y_window; if (coord_type == ATK_XY_WINDOW) { window = gdk_window_get_toplevel (gtk_widget_get_window (widget)); gdk_window_get_origin (window, &x_toplevel, &y_toplevel); *x -= x_toplevel; *y -= y_toplevel; } } static void eel_canvas_accessible_get_size (AtkComponent *component, gint *width, gint *height) { GtkWidget *widget; widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) { return; } *width = gtk_widget_get_allocated_width (widget); *height = gtk_widget_get_allocated_height (widget); } static void eel_canvas_accessible_component_init (gpointer iface, gpointer data) { AtkComponentIface *component; g_assert (G_TYPE_FROM_INTERFACE(iface) == ATK_TYPE_COMPONENT); component = iface; component->get_extents = eel_canvas_accessible_get_extents; component->get_size = eel_canvas_accessible_get_size; } G_DEFINE_TYPE_WITH_CODE (EelCanvasAccessible, eel_canvas_accessible, GTK_TYPE_ACCESSIBLE, G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, eel_canvas_accessible_component_init)) static void eel_canvas_accessible_class_init (EelCanvasAccessibleClass *klass) { AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); accessible_parent_class = g_type_class_peek_parent (klass); atk_class->initialize = eel_canvas_accessible_initialize; atk_class->get_n_children = eel_canvas_accessible_get_n_children; atk_class->ref_child = eel_canvas_accessible_ref_child; /* below adapted from gtkwidgetaccessible.c */ atk_class->ref_state_set = eel_canvas_accessible_ref_state_set; } static void eel_canvas_accessible_init (EelCanvasAccessible *accessible) { } static AtkObject * eel_canvas_accessible_create (GObject *for_object) { GType type; AtkObject *accessible; EelCanvas *canvas; canvas = EEL_CANVAS (for_object); g_return_val_if_fail (canvas != NULL, NULL); type = eel_canvas_accessible_get_type (); if (type == G_TYPE_INVALID) { return atk_no_op_object_new (for_object); } accessible = g_object_new (type, NULL); atk_object_initialize (accessible, for_object); return accessible; } static GType eel_canvas_accessible_factory_get_accessible_type (void) { return eel_canvas_accessible_get_type (); } static AtkObject* eel_canvas_accessible_factory_create_accessible (GObject *obj) { g_return_val_if_fail (G_IS_OBJECT (obj), NULL); return eel_canvas_accessible_create (obj); } static void eel_canvas_accessible_factory_class_init (AtkObjectFactoryClass *klass) { klass->create_accessible = eel_canvas_accessible_factory_create_accessible; klass->get_accessible_type = eel_canvas_accessible_factory_get_accessible_type; } static GType eel_canvas_accessible_factory_get_type (void) { static GType type = 0; if (!type) { static const GTypeInfo tinfo = { sizeof (AtkObjectFactoryClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eel_canvas_accessible_factory_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (AtkObjectFactory), 0, /* n_preallocs */ NULL }; type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY, "EelCanvasAccessibilityFactory", &tinfo, 0); } return type; } /* Class initialization function for EelCanvasClass */ static void eel_canvas_class_init (EelCanvasClass *klass) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; gobject_class = (GObjectClass *)klass; widget_class = (GtkWidgetClass *) klass; canvas_parent_class = g_type_class_peek_parent (klass); gobject_class->set_property = eel_canvas_set_property; gobject_class->get_property = eel_canvas_get_property; widget_class->destroy = eel_canvas_destroy; widget_class->map = eel_canvas_map; widget_class->unmap = eel_canvas_unmap; widget_class->realize = eel_canvas_realize; widget_class->unrealize = eel_canvas_unrealize; widget_class->size_allocate = eel_canvas_size_allocate; widget_class->button_press_event = eel_canvas_button; widget_class->button_release_event = eel_canvas_button; widget_class->motion_notify_event = eel_canvas_motion; widget_class->draw = eel_canvas_draw; widget_class->key_press_event = eel_canvas_key; widget_class->key_release_event = eel_canvas_key; widget_class->enter_notify_event = eel_canvas_crossing; widget_class->leave_notify_event = eel_canvas_crossing; widget_class->focus_in_event = eel_canvas_focus_in; widget_class->focus_out_event = eel_canvas_focus_out; widget_class->get_accessible = eel_canvas_get_accessible; klass->draw_background = eel_canvas_draw_background; klass->request_update = eel_canvas_request_update_real; canvas_signals[DRAW_BACKGROUND] = g_signal_new ("draw_background", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (EelCanvasClass, draw_background), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, CAIRO_GOBJECT_TYPE_CONTEXT); atk_registry_set_factory_type (atk_get_default_registry (), EEL_TYPE_CANVAS, eel_canvas_accessible_factory_get_type ()); } /* Callback used when the root item of a canvas is destroyed. The user should * never ever do this, so we panic if this happens. */ static void panic_root_destroyed (GtkWidget *object, gpointer data) { g_error ("Eeeek, root item %p of canvas %p was destroyed!", object, data); } /* Object initialization function for EelCanvas */ static void eel_canvas_init (EelCanvas *canvas) { guint width, height; gtk_widget_set_can_focus (GTK_WIDGET (canvas), TRUE); gtk_widget_set_redraw_on_allocate (GTK_WIDGET (canvas), FALSE); canvas->scroll_x1 = 0.0; canvas->scroll_y1 = 0.0; gtk_layout_get_size (GTK_LAYOUT (canvas), &width, &height); canvas->scroll_x2 = width; canvas->scroll_y2 = height; canvas->pixels_per_unit = 1.0; canvas->pick_event.type = GDK_LEAVE_NOTIFY; canvas->pick_event.crossing.x = 0; canvas->pick_event.crossing.y = 0; gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas), NULL); gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas), NULL); /* Create the root item as a special case */ canvas->root = EEL_CANVAS_ITEM (g_object_new (eel_canvas_group_get_type (), NULL)); canvas->root->canvas = canvas; g_object_ref_sink (canvas->root); canvas->root_destroy_id = g_signal_connect (G_OBJECT (canvas->root), "destroy", G_CALLBACK (panic_root_destroyed), canvas); canvas->need_repick = TRUE; canvas->doing_update = FALSE; } /* Convenience function to remove the idle handler of a canvas */ static void remove_idle (EelCanvas *canvas) { if (canvas->idle_id == 0) return; g_source_remove (canvas->idle_id); canvas->idle_id = 0; } /* Removes the transient state of the canvas (idle handler, grabs). */ static void shutdown_transients (EelCanvas *canvas) { /* We turn off the need_redraw flag, since if the canvas is mapped again * it will request a redraw anyways. We do not turn off the need_update * flag, though, because updates are not queued when the canvas remaps * itself. */ if (canvas->need_redraw) { canvas->need_redraw = FALSE; } if (canvas->grabbed_item) { eel_canvas_item_ungrab (canvas->grabbed_item, GDK_CURRENT_TIME); } remove_idle (canvas); } /* Destroy handler for EelCanvas */ static void eel_canvas_destroy (GtkWidget *object) { EelCanvas *canvas; g_return_if_fail (EEL_IS_CANVAS (object)); /* remember, destroy can be run multiple times! */ canvas = EEL_CANVAS (object); if (canvas->root_destroy_id) { g_signal_handler_disconnect (G_OBJECT (canvas->root), canvas->root_destroy_id); canvas->root_destroy_id = 0; } if (canvas->root) { EelCanvasItem *root = canvas->root; canvas->root = NULL; eel_canvas_item_destroy (root); g_object_unref (root); } shutdown_transients (canvas); if (GTK_WIDGET_CLASS (canvas_parent_class)->destroy) (* GTK_WIDGET_CLASS (canvas_parent_class)->destroy) (object); } /** * eel_canvas_new: * @void: * * Creates a new empty canvas. If you wish to use the * &EelCanvasImage item inside this canvas, then you must push the gdk_imlib * visual and colormap before calling this function, and they can be popped * afterwards. * * Return value: A newly-created canvas. **/ GtkWidget * eel_canvas_new (void) { return GTK_WIDGET (g_object_new (eel_canvas_get_type (), NULL)); } /* Map handler for the canvas */ static void eel_canvas_map (GtkWidget *widget) { EelCanvas *canvas; g_return_if_fail (EEL_IS_CANVAS (widget)); /* Normal widget mapping stuff */ if (GTK_WIDGET_CLASS (canvas_parent_class)->map) (* GTK_WIDGET_CLASS (canvas_parent_class)->map) (widget); canvas = EEL_CANVAS (widget); /* Map items */ if ((canvas->root->flags & EEL_CANVAS_ITEM_VISIBLE) && !(canvas->root->flags & EEL_CANVAS_ITEM_MAPPED) && EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->map) (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->map) (canvas->root); } /* Unmap handler for the canvas */ static void eel_canvas_unmap (GtkWidget *widget) { EelCanvas *canvas; g_return_if_fail (EEL_IS_CANVAS (widget)); canvas = EEL_CANVAS (widget); shutdown_transients (canvas); /* Unmap items */ if (EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->unmap) (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->unmap) (canvas->root); /* Normal widget unmapping stuff */ if (GTK_WIDGET_CLASS (canvas_parent_class)->unmap) (* GTK_WIDGET_CLASS (canvas_parent_class)->unmap) (widget); } /* Realize handler for the canvas */ static void eel_canvas_realize (GtkWidget *widget) { EelCanvas *canvas; g_return_if_fail (EEL_IS_CANVAS (widget)); /* Normal widget realization stuff */ if (GTK_WIDGET_CLASS (canvas_parent_class)->realize) (* GTK_WIDGET_CLASS (canvas_parent_class)->realize) (widget); canvas = EEL_CANVAS (widget); gdk_window_set_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)), (gdk_window_get_events (gtk_layout_get_bin_window (GTK_LAYOUT (canvas))) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK)); /* Create our own temporary pixmap gc and realize all the items */ (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->realize) (canvas->root); } /* Unrealize handler for the canvas */ static void eel_canvas_unrealize (GtkWidget *widget) { EelCanvas *canvas; g_return_if_fail (EEL_IS_CANVAS (widget)); canvas = EEL_CANVAS (widget); shutdown_transients (canvas); /* Unrealize items and parent widget */ (* EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->unrealize) (canvas->root); if (GTK_WIDGET_CLASS (canvas_parent_class)->unrealize) (* GTK_WIDGET_CLASS (canvas_parent_class)->unrealize) (widget); } /* Handles scrolling of the canvas. Adjusts the scrolling and zooming offset to * keep as much as possible of the canvas scrolling region in view. */ static void scroll_to (EelCanvas *canvas, int cx, int cy) { int scroll_width, scroll_height; int right_limit, bottom_limit; int old_zoom_xofs, old_zoom_yofs; int changed_x = FALSE, changed_y = FALSE; int canvas_width, canvas_height; GtkAllocation allocation; GtkAdjustment *vadjustment, *hadjustment; guint width, height; gtk_widget_get_allocation (GTK_WIDGET (canvas), &allocation); canvas_width = allocation.width; canvas_height = allocation.height; scroll_width = floor ((canvas->scroll_x2 - canvas->scroll_x1) * canvas->pixels_per_unit + 0.5); scroll_height = floor ((canvas->scroll_y2 - canvas->scroll_y1) * canvas->pixels_per_unit + 0.5); right_limit = scroll_width - canvas_width; bottom_limit = scroll_height - canvas_height; old_zoom_xofs = canvas->zoom_xofs; old_zoom_yofs = canvas->zoom_yofs; if (right_limit < 0) { cx = 0; if (canvas->center_scroll_region) { canvas->zoom_xofs = (canvas_width - scroll_width) / 2; scroll_width = canvas_width; } else { canvas->zoom_xofs = 0; } } else if (cx < 0) { cx = 0; canvas->zoom_xofs = 0; } else if (cx > right_limit) { cx = right_limit; canvas->zoom_xofs = 0; } else canvas->zoom_xofs = 0; if (bottom_limit < 0) { cy = 0; if (canvas->center_scroll_region) { canvas->zoom_yofs = (canvas_height - scroll_height) / 2; scroll_height = canvas_height; } else { canvas->zoom_yofs = 0; } } else if (cy < 0) { cy = 0; canvas->zoom_yofs = 0; } else if (cy > bottom_limit) { cy = bottom_limit; canvas->zoom_yofs = 0; } else canvas->zoom_yofs = 0; if ((canvas->zoom_xofs != old_zoom_xofs) || (canvas->zoom_yofs != old_zoom_yofs)) { /* This can only occur, if either canvas size or widget size changes */ /* So I think we can request full redraw here */ /* More stuff - we have to mark root as needing fresh affine (Lauris) */ if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)) { canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE; eel_canvas_request_update (canvas); } gtk_widget_queue_draw (GTK_WIDGET (canvas)); } hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)); vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)); if (((int) gtk_adjustment_get_value (hadjustment)) != cx) { gtk_adjustment_set_value (hadjustment, cx); changed_x = TRUE; } if (((int) gtk_adjustment_get_value (vadjustment)) != cy) { gtk_adjustment_set_value (vadjustment, cy); changed_y = TRUE; } gtk_layout_get_size (&canvas->layout, &width, &height); if ((scroll_width != (int) width )|| (scroll_height != (int) height)) { gtk_layout_set_size (GTK_LAYOUT (canvas), scroll_width, scroll_height); } /* Signal GtkLayout that it should do a redraw. */ if (changed_x) g_signal_emit_by_name (hadjustment, "value_changed"); if (changed_y) g_signal_emit_by_name (vadjustment, "value_changed"); } /* Size allocation handler for the canvas */ static void eel_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { EelCanvas *canvas; GtkAdjustment *vadjustment, *hadjustment; g_return_if_fail (EEL_IS_CANVAS (widget)); g_return_if_fail (allocation != NULL); if (GTK_WIDGET_CLASS (canvas_parent_class)->size_allocate) (* GTK_WIDGET_CLASS (canvas_parent_class)->size_allocate) (widget, allocation); canvas = EEL_CANVAS (widget); /* Recenter the view, if appropriate */ hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)); vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)); gtk_adjustment_set_page_size (hadjustment, allocation->width); gtk_adjustment_set_page_increment (hadjustment, allocation->width / 2); gtk_adjustment_set_page_size (vadjustment, allocation->height); gtk_adjustment_set_page_increment (vadjustment, allocation->height / 2); scroll_to (canvas, gtk_adjustment_get_value (hadjustment), gtk_adjustment_get_value (vadjustment)); g_signal_emit_by_name (hadjustment, "changed"); g_signal_emit_by_name (vadjustment, "changed"); } /* Emits an event for an item in the canvas, be it the current item, grabbed * item, or focused item, as appropriate. */ static int emit_event (EelCanvas *canvas, GdkEvent *event) { GdkEvent ev; gint finished; EelCanvasItem *item; EelCanvasItem *parent; guint mask; /* Could be an old pick event */ if (!gtk_widget_get_realized (GTK_WIDGET (canvas))) { return FALSE; } /* Perform checks for grabbed items */ if (canvas->grabbed_item && !is_descendant (canvas->current_item, canvas->grabbed_item)) { return FALSE; } if (canvas->grabbed_item) { switch ((int) event->type) { case GDK_ENTER_NOTIFY: mask = GDK_ENTER_NOTIFY_MASK; break; case GDK_LEAVE_NOTIFY: mask = GDK_LEAVE_NOTIFY_MASK; break; case GDK_MOTION_NOTIFY: mask = GDK_POINTER_MOTION_MASK; break; case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: mask = GDK_BUTTON_PRESS_MASK; break; case GDK_BUTTON_RELEASE: mask = GDK_BUTTON_RELEASE_MASK; break; case GDK_KEY_PRESS: mask = GDK_KEY_PRESS_MASK; break; case GDK_KEY_RELEASE: mask = GDK_KEY_RELEASE_MASK; break; default: mask = 0; break; } if (!(mask & canvas->grabbed_event_mask)) return FALSE; } /* Convert to world coordinates -- we have two cases because of diferent * offsets of the fields in the event structures. */ ev = *event; switch ((int) ev.type) { case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: eel_canvas_window_to_world (canvas, ev.crossing.x, ev.crossing.y, &ev.crossing.x, &ev.crossing.y); break; case GDK_MOTION_NOTIFY: eel_canvas_window_to_world (canvas, ev.motion.x, ev.motion.y, &ev.motion.x, &ev.motion.y); break; case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: eel_canvas_window_to_world (canvas, ev.motion.x, ev.motion.y, &ev.motion.x, &ev.motion.y); break; case GDK_BUTTON_RELEASE: eel_canvas_window_to_world (canvas, ev.motion.x, ev.motion.y, &ev.motion.x, &ev.motion.y); break; default: break; } /* Choose where we send the event */ item = canvas->current_item; if (canvas->focused_item && ((event->type == GDK_KEY_PRESS) || (event->type == GDK_KEY_RELEASE) || (event->type == GDK_FOCUS_CHANGE))) item = canvas->focused_item; /* The event is propagated up the hierarchy (for if someone connected to * a group instead of a leaf event), and emission is stopped if a * handler returns TRUE, just like for GtkWidget events. */ finished = FALSE; while (item && !finished) { g_object_ref (item); g_signal_emit ( G_OBJECT (item), item_signals[ITEM_EVENT], 0, &ev, &finished); parent = item->parent; g_object_unref (item); item = parent; } return finished; } /* Re-picks the current item in the canvas, based on the event's coordinates. * Also emits enter/leave events for items as appropriate. */ static int pick_current_item (EelCanvas *canvas, GdkEvent *event) { int button_down; double x, y; int cx, cy; int retval; retval = FALSE; /* If a button is down, we'll perform enter and leave events on the * current item, but not enter on any other item. This is more or less * like X pointer grabbing for canvas items. */ button_down = canvas->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK); if (!button_down) canvas->left_grabbed_item = FALSE; /* Save the event in the canvas. This is used to synthesize enter and * leave events in case the current item changes. It is also used to * re-pick the current item if the current one gets deleted. Also, * synthesize an enter event. */ if (event != &canvas->pick_event) { if ((event->type == GDK_MOTION_NOTIFY) || (event->type == GDK_BUTTON_RELEASE)) { /* these fields have the same offsets in both types of events */ canvas->pick_event.crossing.type = GDK_ENTER_NOTIFY; canvas->pick_event.crossing.window = event->motion.window; canvas->pick_event.crossing.send_event = event->motion.send_event; canvas->pick_event.crossing.subwindow = NULL; canvas->pick_event.crossing.x = event->motion.x; canvas->pick_event.crossing.y = event->motion.y; canvas->pick_event.crossing.mode = GDK_CROSSING_NORMAL; canvas->pick_event.crossing.detail = GDK_NOTIFY_NONLINEAR; canvas->pick_event.crossing.focus = FALSE; canvas->pick_event.crossing.state = event->motion.state; /* these fields don't have the same offsets in both types of events */ if (event->type == GDK_MOTION_NOTIFY) { canvas->pick_event.crossing.x_root = event->motion.x_root; canvas->pick_event.crossing.y_root = event->motion.y_root; } else { canvas->pick_event.crossing.x_root = event->button.x_root; canvas->pick_event.crossing.y_root = event->button.y_root; } } else canvas->pick_event = *event; } /* Don't do anything else if this is a recursive call */ if (canvas->in_repick) return retval; /* LeaveNotify means that there is no current item, so we don't look for one */ if (canvas->pick_event.type != GDK_LEAVE_NOTIFY) { /* these fields don't have the same offsets in both types of events */ if (canvas->pick_event.type == GDK_ENTER_NOTIFY) { x = canvas->pick_event.crossing.x; y = canvas->pick_event.crossing.y; } else { x = canvas->pick_event.motion.x; y = canvas->pick_event.motion.y; } /* canvas pixel coords */ cx = (int) (x + 0.5); cy = (int) (y + 0.5); /* world coords */ eel_canvas_c2w (canvas, cx, cy, &x, &y); /* find the closest item */ if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED) eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy, &canvas->new_current_item); else canvas->new_current_item = NULL; } else canvas->new_current_item = NULL; if ((canvas->new_current_item == canvas->current_item) && !canvas->left_grabbed_item) return retval; /* current item did not change */ /* Synthesize events for old and new current items */ if ((canvas->new_current_item != canvas->current_item) && (canvas->current_item != NULL) && !canvas->left_grabbed_item) { GdkEvent new_event; new_event = canvas->pick_event; new_event.type = GDK_LEAVE_NOTIFY; new_event.crossing.detail = GDK_NOTIFY_ANCESTOR; new_event.crossing.subwindow = NULL; canvas->in_repick = TRUE; retval = emit_event (canvas, &new_event); canvas->in_repick = FALSE; } /* new_current_item may have been set to NULL during the call to emit_event() above */ if ((canvas->new_current_item != canvas->current_item) && button_down) { canvas->left_grabbed_item = TRUE; return retval; } /* Handle the rest of cases */ canvas->left_grabbed_item = FALSE; canvas->current_item = canvas->new_current_item; if (canvas->current_item != NULL) { GdkEvent new_event; new_event = canvas->pick_event; new_event.type = GDK_ENTER_NOTIFY; new_event.crossing.detail = GDK_NOTIFY_ANCESTOR; new_event.crossing.subwindow = NULL; retval = emit_event (canvas, &new_event); } return retval; } /* Button event handler for the canvas */ static gint eel_canvas_button (GtkWidget *widget, GdkEventButton *event) { EelCanvas *canvas; int mask; int retval; g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); /* Don't handle extra mouse button events */ if (event->button > 5) return FALSE; retval = FALSE; canvas = EEL_CANVAS (widget); /* * dispatch normally regardless of the event's window if an item has * has a pointer grab in effect */ if (!canvas->grabbed_item && event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas))) return retval; switch (event->button) { case 1: mask = GDK_BUTTON1_MASK; break; case 2: mask = GDK_BUTTON2_MASK; break; case 3: mask = GDK_BUTTON3_MASK; break; case 4: mask = GDK_BUTTON4_MASK; break; case 5: mask = GDK_BUTTON5_MASK; break; default: mask = 0; } switch ((int) event->type) { case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: /* Pick the current item as if the button were not pressed, and * then process the event. */ event->state ^= mask; canvas->state = event->state; pick_current_item (canvas, (GdkEvent *) event); event->state ^= mask; canvas->state = event->state; retval = emit_event (canvas, (GdkEvent *) event); break; case GDK_BUTTON_RELEASE: /* Process the event as if the button were pressed, then repick * after the button has been released */ canvas->state = event->state; retval = emit_event (canvas, (GdkEvent *) event); event->state ^= mask; canvas->state = event->state; pick_current_item (canvas, (GdkEvent *) event); event->state ^= mask; break; default: g_assert_not_reached (); } return retval; } /* Motion event handler for the canvas */ static gint eel_canvas_motion (GtkWidget *widget, GdkEventMotion *event) { EelCanvas *canvas; g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); canvas = EEL_CANVAS (widget); if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas))) return FALSE; canvas->state = event->state; pick_current_item (canvas, (GdkEvent *) event); return emit_event (canvas, (GdkEvent *) event); } /* Key event handler for the canvas */ static gint eel_canvas_key (GtkWidget *widget, GdkEventKey *event) { EelCanvas *canvas; g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); canvas = EEL_CANVAS (widget); if (emit_event (canvas, (GdkEvent *) event)) return TRUE; if (event->type == GDK_KEY_RELEASE) return GTK_WIDGET_CLASS (canvas_parent_class)->key_release_event (widget, event); else return GTK_WIDGET_CLASS (canvas_parent_class)->key_press_event (widget, event); } /* Crossing event handler for the canvas */ static gint eel_canvas_crossing (GtkWidget *widget, GdkEventCrossing *event) { EelCanvas *canvas; g_return_val_if_fail (EEL_IS_CANVAS (widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); canvas = EEL_CANVAS (widget); if (event->window != gtk_layout_get_bin_window (GTK_LAYOUT (canvas))) return FALSE; canvas->state = event->state; return pick_current_item (canvas, (GdkEvent *) event); } /* Focus in handler for the canvas */ static gint eel_canvas_focus_in (GtkWidget *widget, GdkEventFocus *event) { EelCanvas *canvas; canvas = EEL_CANVAS (widget); if (canvas->focused_item) return emit_event (canvas, (GdkEvent *) event); else return FALSE; } static AtkObject * eel_canvas_get_accessible (GtkWidget *widget) { return atk_gobject_accessible_for_object (G_OBJECT (widget)); } /* Focus out handler for the canvas */ static gint eel_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event) { EelCanvas *canvas; canvas = EEL_CANVAS (widget); if (canvas->focused_item) return emit_event (canvas, (GdkEvent *) event); else return FALSE; } static cairo_region_t * eel_cairo_get_clip_region (cairo_t *cr) { cairo_rectangle_list_t *list; cairo_region_t *region; int i; list = cairo_copy_clip_rectangle_list (cr); if (list->status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) { cairo_rectangle_int_t clip_rect; cairo_rectangle_list_destroy (list); if (!gdk_cairo_get_clip_rectangle (cr, &clip_rect)) return NULL; return cairo_region_create_rectangle (&clip_rect); } region = cairo_region_create (); for (i = list->num_rectangles - 1; i >= 0; --i) { cairo_rectangle_t *rect = &list->rectangles[i]; cairo_rectangle_int_t clip_rect; clip_rect.x = floor (rect->x); clip_rect.y = floor (rect->y); clip_rect.width = ceil (rect->x + rect->width) - clip_rect.x; clip_rect.height = ceil (rect->y + rect->height) - clip_rect.y; if (cairo_region_union_rectangle (region, &clip_rect) != CAIRO_STATUS_SUCCESS) { cairo_region_destroy (region); region = NULL; break; } } cairo_rectangle_list_destroy (list); return region; } /* Expose handler for the canvas */ static gboolean eel_canvas_draw (GtkWidget *widget, cairo_t *cr) { EelCanvas *canvas; GdkWindow *bin_window; cairo_region_t *region; if (!gdk_cairo_get_clip_rectangle (cr, NULL)) return FALSE; bin_window = gtk_layout_get_bin_window (GTK_LAYOUT (widget)); if (!gtk_cairo_should_draw_window (cr, bin_window)) return FALSE; cairo_save (cr); gtk_cairo_transform_to_window (cr, widget, bin_window); region = eel_cairo_get_clip_region (cr); if (region == NULL) { cairo_restore (cr); return FALSE; } #ifdef VERBOSE g_print ("Draw\n"); #endif /* If there are any outstanding items that need updating, do them now */ canvas = EEL_CANVAS (widget); if (canvas->idle_id) { g_source_remove (canvas->idle_id); canvas->idle_id = 0; } if (canvas->need_update) { g_return_val_if_fail (!canvas->doing_update, FALSE); canvas->doing_update = TRUE; eel_canvas_item_invoke_update (canvas->root, 0, 0, 0); g_return_val_if_fail (canvas->doing_update, FALSE); canvas->doing_update = FALSE; canvas->need_update = FALSE; } /* Hmmm. Would like to queue antiexposes if the update marked anything that is gonna get redrawn as invalid */ g_signal_emit (G_OBJECT (canvas), canvas_signals[DRAW_BACKGROUND], 0, cr); if (canvas->root->flags & EEL_CANVAS_ITEM_MAPPED) EEL_CANVAS_ITEM_GET_CLASS (canvas->root)->draw (canvas->root, cr, region); cairo_restore (cr); /* Chain up to get exposes on child widgets */ if (GTK_WIDGET_CLASS (canvas_parent_class)->draw) GTK_WIDGET_CLASS (canvas_parent_class)->draw (widget, cr); cairo_region_destroy (region); return FALSE; } static void eel_canvas_draw_background (EelCanvas *canvas, cairo_t *cr) { cairo_rectangle_int_t rect; GtkStyleContext *style_context; GdkRGBA color; if (!gdk_cairo_get_clip_rectangle (cr, &rect)) return; cairo_save (cr); /* By default, we use the style background. */ style_context = gtk_widget_get_style_context (GTK_WIDGET (canvas)); gtk_style_context_get_background_color (style_context, GTK_STATE_FLAG_NORMAL, &color); gdk_cairo_set_source_rgba (cr, &color); gdk_cairo_rectangle (cr, &rect); cairo_fill (cr); cairo_restore (cr); } static void do_update (EelCanvas *canvas) { /* Cause the update if necessary */ update_again: if (canvas->need_update) { g_return_if_fail (!canvas->doing_update); canvas->doing_update = TRUE; eel_canvas_item_invoke_update (canvas->root, 0, 0, 0); g_return_if_fail (canvas->doing_update); canvas->doing_update = FALSE; canvas->need_update = FALSE; } /* Pick new current item */ while (canvas->need_repick) { canvas->need_repick = FALSE; pick_current_item (canvas, &canvas->pick_event); } /* it is possible that during picking we emitted an event in which the user then called some function which then requested update of something. Without this we'd be left in a state where need_update would have been left TRUE and the canvas would have been left unpainted. */ if (canvas->need_update) { goto update_again; } } /* Idle handler for the canvas. It deals with pending updates and redraws. */ static gint idle_handler (gpointer data) { EelCanvas *canvas; canvas = EEL_CANVAS (data); do_update (canvas); /* Reset idle id */ canvas->idle_id = 0; return FALSE; } /* Convenience function to add an idle handler to a canvas */ static void add_idle (EelCanvas *canvas) { if (!canvas->idle_id) { /* We let the update idle handler have higher priority * than the redraw idle handler so the canvas state * will be updated during the expose event. canvas in * expose_event. */ canvas->idle_id = g_idle_add_full (GDK_PRIORITY_REDRAW - 20, idle_handler, canvas, NULL); } } /** * eel_canvas_root: * @canvas: A canvas. * * Queries the root group of a canvas. * * Return value: The root group of the specified canvas. **/ EelCanvasGroup * eel_canvas_root (EelCanvas *canvas) { g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL); return EEL_CANVAS_GROUP (canvas->root); } /** * eel_canvas_set_scroll_region: * @canvas: A canvas. * @x1: Leftmost limit of the scrolling region. * @y1: Upper limit of the scrolling region. * @x2: Rightmost limit of the scrolling region. * @y2: Lower limit of the scrolling region. * * Sets the scrolling region of a canvas to the specified rectangle. The canvas * will then be able to scroll only within this region. The view of the canvas * is adjusted as appropriate to display as much of the new region as possible. **/ void eel_canvas_set_scroll_region (EelCanvas *canvas, double x1, double y1, double x2, double y2) { double wxofs, wyofs; int xofs, yofs; g_return_if_fail (EEL_IS_CANVAS (canvas)); if ((canvas->scroll_x1 == x1) && (canvas->scroll_y1 == y1) && (canvas->scroll_x2 == x2) && (canvas->scroll_y2 == y2)) { return; } /* * Set the new scrolling region. If possible, do not move the visible contents of the * canvas. */ eel_canvas_c2w (canvas, gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))) + canvas->zoom_xofs, gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))) + canvas->zoom_yofs, /*canvas->zoom_xofs, canvas->zoom_yofs,*/ &wxofs, &wyofs); canvas->scroll_x1 = x1; canvas->scroll_y1 = y1; canvas->scroll_x2 = x2; canvas->scroll_y2 = y2; eel_canvas_w2c (canvas, wxofs, wyofs, &xofs, &yofs); scroll_to (canvas, xofs, yofs); canvas->need_repick = TRUE; if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)) { canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE; eel_canvas_request_update (canvas); } } /** * eel_canvas_get_scroll_region: * @canvas: A canvas. * @x1: Leftmost limit of the scrolling region (return value). * @y1: Upper limit of the scrolling region (return value). * @x2: Rightmost limit of the scrolling region (return value). * @y2: Lower limit of the scrolling region (return value). * * Queries the scrolling region of a canvas. **/ void eel_canvas_get_scroll_region (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2) { g_return_if_fail (EEL_IS_CANVAS (canvas)); if (x1) *x1 = canvas->scroll_x1; if (y1) *y1 = canvas->scroll_y1; if (x2) *x2 = canvas->scroll_x2; if (y2) *y2 = canvas->scroll_y2; } void eel_canvas_set_center_scroll_region (EelCanvas *canvas, gboolean center_scroll_region) { g_return_if_fail (EEL_IS_CANVAS (canvas)); canvas->center_scroll_region = center_scroll_region != 0; scroll_to (canvas, gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (&canvas->layout))), gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (&canvas->layout)))); } /** * eel_canvas_set_pixels_per_unit: * @canvas: A canvas. * @n: The number of pixels that correspond to one canvas unit. * * Sets the zooming factor of a canvas by specifying the number of pixels that * correspond to one canvas unit. **/ void eel_canvas_set_pixels_per_unit (EelCanvas *canvas, double n) { GtkWidget *widget; double cx, cy; int x1, y1; int center_x, center_y; GdkWindow *window; GdkWindowAttr attributes; gint attributes_mask; GtkAllocation allocation; GtkAdjustment *vadjustment, *hadjustment; g_return_if_fail (EEL_IS_CANVAS (canvas)); g_return_if_fail (n > EEL_CANVAS_EPSILON); widget = GTK_WIDGET (canvas); gtk_widget_get_allocation (widget, &allocation); center_x = allocation.width / 2; center_y = allocation.height / 2; /* Find the coordinates of the screen center in units. */ hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas)); vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas)); cx = (gtk_adjustment_get_value (hadjustment) + center_x) / canvas->pixels_per_unit + canvas->scroll_x1 + canvas->zoom_xofs; cy = (gtk_adjustment_get_value (vadjustment) + center_y) / canvas->pixels_per_unit + canvas->scroll_y1 + canvas->zoom_yofs; /* Now calculate the new offset of the upper left corner. (round not truncate) */ x1 = ((cx - canvas->scroll_x1) * n) - center_x + .5; y1 = ((cy - canvas->scroll_y1) * n) - center_y + .5; canvas->pixels_per_unit = n; if (!(canvas->root->flags & EEL_CANVAS_ITEM_NEED_DEEP_UPDATE)) { canvas->root->flags |= EEL_CANVAS_ITEM_NEED_DEEP_UPDATE; eel_canvas_request_update (canvas); } /* Map a background None window over the bin_window to avoid * scrolling the window scroll causing exposes. */ window = NULL; if (gtk_widget_get_mapped (widget)) { attributes.window_type = GDK_WINDOW_CHILD; gtk_widget_get_allocation (widget, &allocation); attributes.x = allocation.x; attributes.y = allocation.y; attributes.width = allocation.width; attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gdk_window_set_user_data (window, widget); gdk_window_show (window); } scroll_to (canvas, x1, y1); /* If we created a an overlapping background None window, remove it how. * * TODO: We would like to temporarily set the bin_window background to * None to avoid clearing the bin_window to the background, but gdk doesn't * expose enought to let us do this, so we get a flash-effect here. At least * it looks better than scroll + expose. */ if (window != NULL) { gdk_window_hide (window); gdk_window_set_user_data (window, NULL); gdk_window_destroy (window); } canvas->need_repick = TRUE; } /** * eel_canvas_scroll_to: * @canvas: A canvas. * @cx: Horizontal scrolling offset in canvas pixel units. * @cy: Vertical scrolling offset in canvas pixel units. * * Makes a canvas scroll to the specified offsets, given in canvas pixel units. * The canvas will adjust the view so that it is not outside the scrolling * region. This function is typically not used, as it is better to hook * scrollbars to the canvas layout's scrolling adjusments. **/ void eel_canvas_scroll_to (EelCanvas *canvas, int cx, int cy) { g_return_if_fail (EEL_IS_CANVAS (canvas)); scroll_to (canvas, cx, cy); } /** * eel_canvas_get_scroll_offsets: * @canvas: A canvas. * @cx: Horizontal scrolling offset (return value). * @cy: Vertical scrolling offset (return value). * * Queries the scrolling offsets of a canvas. The values are returned in canvas * pixel units. **/ void eel_canvas_get_scroll_offsets (EelCanvas *canvas, int *cx, int *cy) { g_return_if_fail (EEL_IS_CANVAS (canvas)); if (cx) *cx = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))); if (cy) *cy = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))); } /** * eel_canvas_update_now: * @canvas: A canvas. * * Forces an immediate update and redraw of a canvas. If the canvas does not * have any pending update or redraw requests, then no action is taken. This is * typically only used by applications that need explicit control of when the * display is updated, like games. It is not needed by normal applications. */ void eel_canvas_update_now (EelCanvas *canvas) { g_return_if_fail (EEL_IS_CANVAS (canvas)); if (!(canvas->need_update || canvas->need_redraw)) return; remove_idle (canvas); do_update (canvas); } /** * eel_canvas_get_item_at: * @canvas: A canvas. * @x: X position in world coordinates. * @y: Y position in world coordinates. * * Looks for the item that is under the specified position, which must be * specified in world coordinates. * * Return value: The sought item, or NULL if no item is at the specified * coordinates. **/ EelCanvasItem * eel_canvas_get_item_at (EelCanvas *canvas, double x, double y) { EelCanvasItem *item; double dist; int cx, cy; g_return_val_if_fail (EEL_IS_CANVAS (canvas), NULL); eel_canvas_w2c (canvas, x, y, &cx, &cy); dist = eel_canvas_item_invoke_point (canvas->root, x, y, cx, cy, &item); if ((int) (dist * canvas->pixels_per_unit + 0.5) <= canvas->close_enough) return item; else return NULL; } /* Queues an update of the canvas */ static void eel_canvas_request_update (EelCanvas *canvas) { EEL_CANVAS_GET_CLASS (canvas)->request_update (canvas); } static void eel_canvas_request_update_real (EelCanvas *canvas) { canvas->need_update = TRUE; add_idle (canvas); } /** * eel_canvas_request_redraw: * @canvas: A canvas. * @x1: Leftmost coordinate of the rectangle to be redrawn. * @y1: Upper coordinate of the rectangle to be redrawn. * @x2: Rightmost coordinate of the rectangle to be redrawn, plus 1. * @y2: Lower coordinate of the rectangle to be redrawn, plus 1. * * Convenience function that informs a canvas that the specified rectangle needs * to be repainted. The rectangle includes @x1 and @y1, but not @x2 and @y2. * To be used only by item implementations. **/ void eel_canvas_request_redraw (EelCanvas *canvas, int x1, int y1, int x2, int y2) { GdkRectangle bbox; g_return_if_fail (EEL_IS_CANVAS (canvas)); if (!gtk_widget_is_drawable (GTK_WIDGET (canvas)) || (x1 >= x2) || (y1 >= y2)) return; bbox.x = x1; bbox.y = y1; bbox.width = x2 - x1; bbox.height = y2 - y1; gdk_window_invalidate_rect (gtk_layout_get_bin_window (GTK_LAYOUT (canvas)), &bbox, FALSE); } /** * eel_canvas_w2c: * @canvas: A canvas. * @wx: World X coordinate. * @wy: World Y coordinate. * @cx: X pixel coordinate (return value). * @cy: Y pixel coordinate (return value). * * Converts world coordinates into canvas pixel coordinates. **/ void eel_canvas_w2c (EelCanvas *canvas, double wx, double wy, int *cx, int *cy) { double zoom; g_return_if_fail (EEL_IS_CANVAS (canvas)); zoom = canvas->pixels_per_unit; if (cx) *cx = floor ((wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs + 0.5); if (cy) *cy = floor ((wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs + 0.5); } /** * eel_canvas_w2c: * @canvas: A canvas. * @world: rectangle in world coordinates. * @canvas: rectangle in canvase coordinates. * * Converts rectangles in world coordinates into canvas pixel coordinates. **/ void eel_canvas_w2c_rect_d (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2) { eel_canvas_w2c_d (canvas, *x1, *y1, x1, y1); eel_canvas_w2c_d (canvas, *x2, *y2, x2, y2); } /** * eel_canvas_w2c_d: * @canvas: A canvas. * @wx: World X coordinate. * @wy: World Y coordinate. * @cx: X pixel coordinate (return value). * @cy: Y pixel coordinate (return value). * * Converts world coordinates into canvas pixel coordinates. This version * produces coordinates in floating point coordinates, for greater precision. **/ void eel_canvas_w2c_d (EelCanvas *canvas, double wx, double wy, double *cx, double *cy) { double zoom; g_return_if_fail (EEL_IS_CANVAS (canvas)); zoom = canvas->pixels_per_unit; if (cx) *cx = (wx - canvas->scroll_x1)*zoom + canvas->zoom_xofs; if (cy) *cy = (wy - canvas->scroll_y1)*zoom + canvas->zoom_yofs; } /** * eel_canvas_c2w: * @canvas: A canvas. * @cx: Canvas pixel X coordinate. * @cy: Canvas pixel Y coordinate. * @wx: X world coordinate (return value). * @wy: Y world coordinate (return value). * * Converts canvas pixel coordinates to world coordinates. **/ void eel_canvas_c2w (EelCanvas *canvas, int cx, int cy, double *wx, double *wy) { double zoom; g_return_if_fail (EEL_IS_CANVAS (canvas)); zoom = canvas->pixels_per_unit; if (wx) *wx = (cx - canvas->zoom_xofs)/zoom + canvas->scroll_x1; if (wy) *wy = (cy - canvas->zoom_yofs)/zoom + canvas->scroll_y1; } /** * eel_canvas_window_to_world: * @canvas: A canvas. * @winx: Window-relative X coordinate. * @winy: Window-relative Y coordinate. * @worldx: X world coordinate (return value). * @worldy: Y world coordinate (return value). * * Converts window-relative coordinates into world coordinates. You can use * this when you need to convert mouse coordinates into world coordinates, for * example. * Window coordinates are really the same as canvas coordinates now, but this * function is here for backwards compatibility reasons. **/ void eel_canvas_window_to_world (EelCanvas *canvas, double winx, double winy, double *worldx, double *worldy) { g_return_if_fail (EEL_IS_CANVAS (canvas)); if (worldx) *worldx = canvas->scroll_x1 + ((winx - canvas->zoom_xofs) / canvas->pixels_per_unit); if (worldy) *worldy = canvas->scroll_y1 + ((winy - canvas->zoom_yofs) / canvas->pixels_per_unit); } /** * eel_canvas_world_to_window: * @canvas: A canvas. * @worldx: World X coordinate. * @worldy: World Y coordinate. * @winx: X window-relative coordinate. * @winy: Y window-relative coordinate. * * Converts world coordinates into window-relative coordinates. * Window coordinates are really the same as canvas coordinates now, but this * function is here for backwards compatibility reasons. **/ void eel_canvas_world_to_window (EelCanvas *canvas, double worldx, double worldy, double *winx, double *winy) { g_return_if_fail (EEL_IS_CANVAS (canvas)); if (winx) *winx = (canvas->pixels_per_unit)*(worldx - canvas->scroll_x1) + canvas->zoom_xofs; if (winy) *winy = (canvas->pixels_per_unit)*(worldy - canvas->scroll_y1) + canvas->zoom_yofs; } static gboolean boolean_handled_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, const GValue *handler_return, gpointer data) { gboolean signal_handled; signal_handled = g_value_get_boolean (handler_return); g_value_set_boolean (return_accu, signal_handled); return !signal_handled; } static guint eel_canvas_item_accessible_add_focus_handler (AtkComponent *component, AtkFocusHandler handler) { GSignalMatchType match_type; guint signal_id; match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC; signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT); if (!g_signal_handler_find (component, match_type, signal_id, 0, NULL, (gpointer) handler, NULL)) { return g_signal_connect_closure_by_id (component, signal_id, 0, g_cclosure_new ( G_CALLBACK (handler), NULL, (GClosureNotify) NULL), FALSE); } return 0; } static void eel_canvas_item_accessible_get_item_extents (EelCanvasItem *item, GdkRectangle *rect) { double bx1, bx2, by1, by2; gint scroll_x, scroll_y; gint x1, x2, y1, y2; eel_canvas_item_get_bounds (item, &bx1, &by1, &bx2, &by2); eel_canvas_w2c_rect_d (item->canvas, &bx1, &by1, &bx2, &by2); eel_canvas_get_scroll_offsets (item->canvas, &scroll_x, &scroll_y); x1 = floor (bx1 + .5); y1 = floor (by1 + .5); x2 = floor (bx2 + .5); y2 = floor (by2 + .5); rect->x = x1 - scroll_x; rect->y = y1 - scroll_y; rect->width = x2 - x1; rect->height = y2 - y1; } static gboolean eel_canvas_item_accessible_is_item_in_window (EelCanvasItem *item, GdkRectangle *rect) { GtkWidget *widget; gboolean retval; widget = GTK_WIDGET (item->canvas); if (gtk_widget_get_window (widget)) { int window_width, window_height; gdk_window_get_geometry (gtk_widget_get_window (widget), NULL, NULL, &window_width, &window_height); /* * Check whether rectangles intersect */ if (rect->x + rect->width < 0 || rect->y + rect->height < 0 || rect->x > window_width || rect->y > window_height) { retval = FALSE; } else { retval = TRUE; } } else { retval = FALSE; } return retval; } static void eel_canvas_item_accessible_get_extents (AtkComponent *component, gint *x, gint *y, gint *width, gint *height, AtkCoordType coord_type) { GObject *obj; EelCanvasItem *item; gint window_x, window_y; gint toplevel_x, toplevel_y; GdkRectangle rect; GdkWindow *window; GtkWidget *canvas; obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component)); if (obj == NULL) { /* item is defunct */ return; } /* Get the CanvasItem */ item = EEL_CANVAS_ITEM (obj); /* If this item has no parent canvas, something's broken */ g_return_if_fail (GTK_IS_WIDGET (item->canvas)); eel_canvas_item_accessible_get_item_extents (item, &rect); *width = rect.width; *height = rect.height; if (!eel_canvas_item_accessible_is_item_in_window (item, &rect)) { *x = G_MININT; *y = G_MININT; return; } canvas = GTK_WIDGET (item->canvas); window = gtk_widget_get_parent_window (canvas); gdk_window_get_origin (window, &window_x, &window_y); *x = rect.x + window_x; *y = rect.y + window_y; if (coord_type == ATK_XY_WINDOW) { window = gdk_window_get_toplevel (gtk_widget_get_window (canvas)); gdk_window_get_origin (window, &toplevel_x, &toplevel_y); *x -= toplevel_x; *y -= toplevel_y; } return; } static gint eel_canvas_item_accessible_get_mdi_zorder (AtkComponent *component) { GObject *g_obj; EelCanvasItem *item; g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component)); if (g_obj == NULL) { /* Object is defunct */ return -1; } item = EEL_CANVAS_ITEM (g_obj); if (item->parent) { return g_list_index (EEL_CANVAS_GROUP (item->parent)->item_list, item); } else { g_return_val_if_fail (item->canvas->root == item, -1); return 0; } } static gboolean eel_canvas_item_accessible_grab_focus (AtkComponent *component) { GObject *obj; EelCanvasItem *item; GtkWidget *toplevel; obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component)); item = EEL_CANVAS_ITEM (obj); if (item == NULL) { /* item is defunct */ return FALSE; } eel_canvas_item_grab_focus (item); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->canvas)); if (gtk_widget_is_toplevel (toplevel)) { gtk_window_present (GTK_WINDOW (toplevel)); } return TRUE; } static void eel_canvas_item_accessible_remove_focus_handler (AtkComponent *component, guint handler_id) { g_signal_handler_disconnect (component, handler_id); } static void eel_canvas_item_accessible_component_interface_init (AtkComponentIface *iface) { g_return_if_fail (iface != NULL); iface->add_focus_handler = eel_canvas_item_accessible_add_focus_handler; iface->get_extents = eel_canvas_item_accessible_get_extents; iface->get_mdi_zorder = eel_canvas_item_accessible_get_mdi_zorder; iface->grab_focus = eel_canvas_item_accessible_grab_focus; iface->remove_focus_handler = eel_canvas_item_accessible_remove_focus_handler; } static gboolean eel_canvas_item_accessible_is_item_on_screen (EelCanvasItem *item) { GdkRectangle rect; eel_canvas_item_accessible_get_item_extents (item, &rect); return eel_canvas_item_accessible_is_item_in_window (item, &rect); } static void eel_canvas_item_accessible_initialize (AtkObject *obj, gpointer data) { if (ATK_OBJECT_CLASS (accessible_item_parent_class)->initialize != NULL) ATK_OBJECT_CLASS (accessible_item_parent_class)->initialize (obj, data); g_object_set_data (G_OBJECT (obj), "atk-component-layer", GINT_TO_POINTER (ATK_LAYER_MDI)); } static AtkStateSet* eel_canvas_item_accessible_ref_state_set (AtkObject *accessible) { GObject *obj; EelCanvasItem *item; AtkStateSet *state_set; state_set = ATK_OBJECT_CLASS (accessible_item_parent_class)->ref_state_set (accessible); obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); item = EEL_CANVAS_ITEM (obj); if (item == NULL) { atk_state_set_add_state (state_set, ATK_STATE_DEFUNCT); } else { if (item->flags & EEL_CANVAS_ITEM_VISIBLE) { atk_state_set_add_state (state_set, ATK_STATE_VISIBLE); if (eel_canvas_item_accessible_is_item_on_screen (item)) { atk_state_set_add_state (state_set, ATK_STATE_SHOWING); } } if (gtk_widget_get_can_focus (GTK_WIDGET (item->canvas))) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE); if (item->canvas->focused_item == item) { atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); } } } return state_set; } static void eel_canvas_item_accessible_class_init (AtkObjectClass *klass) { accessible_item_parent_class = g_type_class_peek_parent (klass); klass->initialize = eel_canvas_item_accessible_initialize; klass->ref_state_set = eel_canvas_item_accessible_ref_state_set; } static GType eel_canvas_item_accessible_get_type (void) { static GType type = 0; if (!type) { static const GInterfaceInfo atk_component_info = { (GInterfaceInitFunc) eel_canvas_item_accessible_component_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; AtkObjectFactory *factory; GType parent_atk_type; GTypeQuery query; GTypeInfo tinfo = { 0 }; factory = atk_registry_get_factory (atk_get_default_registry(), G_TYPE_INITIALLY_UNOWNED); if (!factory) { return G_TYPE_INVALID; } parent_atk_type = atk_object_factory_get_accessible_type (factory); if (!parent_atk_type) { return G_TYPE_INVALID; } g_type_query (parent_atk_type, &query); tinfo.class_init = (GClassInitFunc) eel_canvas_item_accessible_class_init; tinfo.class_size = query.class_size; tinfo.instance_size = query.instance_size; type = g_type_register_static (parent_atk_type, "EelCanvasItemAccessibility", &tinfo, 0); g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); } return type; } static AtkObject * eel_canvas_item_accessible_create (GObject *for_object) { GType type; AtkObject *accessible; EelCanvasItem *item; item = EEL_CANVAS_ITEM (for_object); g_return_val_if_fail (item != NULL, NULL); type = eel_canvas_item_accessible_get_type (); if (type == G_TYPE_INVALID) { return atk_no_op_object_new (for_object); } accessible = g_object_new (type, NULL); atk_object_initialize (accessible, for_object); return accessible; } static GType eel_canvas_item_accessible_factory_get_accessible_type (void) { return eel_canvas_item_accessible_get_type (); } static AtkObject* eel_canvas_item_accessible_factory_create_accessible (GObject *obj) { g_return_val_if_fail (G_IS_OBJECT (obj), NULL); return eel_canvas_item_accessible_create (obj); } static void eel_canvas_item_accessible_factory_class_init (AtkObjectFactoryClass *klass) { klass->create_accessible = eel_canvas_item_accessible_factory_create_accessible; klass->get_accessible_type = eel_canvas_item_accessible_factory_get_accessible_type; } static GType eel_canvas_item_accessible_factory_get_type (void) { static GType type = 0; if (!type) { static const GTypeInfo tinfo = { sizeof (AtkObjectFactoryClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) eel_canvas_item_accessible_factory_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (AtkObjectFactory), 0, /* n_preallocs */ NULL }; type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY, "EelCanvasItemAccessibilityFactory", &tinfo, 0); } return type; } /* Class initialization function for EelCanvasItemClass */ static void eel_canvas_item_class_init (EelCanvasItemClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; item_parent_class = g_type_class_peek_parent (klass); gobject_class->set_property = eel_canvas_item_set_property; gobject_class->get_property = eel_canvas_item_get_property; gobject_class->dispose = eel_canvas_item_dispose; g_object_class_install_property (gobject_class, ITEM_PROP_PARENT, g_param_spec_object ("parent", NULL, NULL, EEL_TYPE_CANVAS_ITEM, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, ITEM_PROP_VISIBLE, g_param_spec_boolean ("visible", NULL, NULL, TRUE, G_PARAM_READWRITE)); item_signals[ITEM_EVENT] = g_signal_new ("event", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (EelCanvasItemClass, event), boolean_handled_accumulator, NULL, g_cclosure_marshal_generic, G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); item_signals[ITEM_DESTROY] = g_signal_new ("destroy", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (EelCanvasItemClass, destroy), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); klass->realize = eel_canvas_item_realize; klass->unrealize = eel_canvas_item_unrealize; klass->map = eel_canvas_item_map; klass->unmap = eel_canvas_item_unmap; klass->update = eel_canvas_item_update; atk_registry_set_factory_type (atk_get_default_registry (), EEL_TYPE_CANVAS_ITEM, eel_canvas_item_accessible_factory_get_type ()); } nemo-3.6.5/eel/eel-debug.h0000664000175000017500000000275013215733314014164 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-debug.h: Eel debugging aids. Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef EEL_DEBUG_H #define EEL_DEBUG_H #include G_BEGIN_DECLS typedef void (* EelFunction) (void); void eel_make_warnings_and_criticals_stop_in_debugger (void); /* A way to do cleanup at exit for compatibility with shutdown tools * like the ones in Bonobo. */ void eel_debug_shut_down (void); void eel_debug_call_at_shutdown (EelFunction function); void eel_debug_call_at_shutdown_with_data (GFreeFunc function, gpointer data); G_END_DECLS #endif /* EEL_DEBUG_H */ nemo-3.6.5/eel/eel-accessibility.h0000664000175000017500000001142113215733314015720 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-accessibility.h - Utility functions for accessibility Copyright (C) 2002 Anders Carlsson The Eel Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Eel Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Eel Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Anders Carlsson */ #ifndef EEL_ACCESSIBILITY_H #define EEL_ACCESSIBILITY_H #include #include #include #include void eel_accessibility_set_up_label_widget_relation (GtkWidget *label, GtkWidget *widget); typedef void (*EelAccessibilityClassInitFn) (AtkObjectClass *klass); AtkObject *eel_accessibility_get_atk_object (gpointer object); AtkObject *eel_accessibility_for_object (gpointer object); gpointer eel_accessibility_get_gobject (AtkObject *object); AtkObject *eel_accessibility_set_atk_object_return (gpointer object, AtkObject *atk_object); GType eel_accessibility_create_derived_type (const char *type_name, GType existing_gobject_with_proxy, EelAccessibilityClassInitFn class_init); char* eel_accessibility_text_get_text (AtkText *text, gint start_pos, gint end_pos); gunichar eel_accessibility_text_get_character_at_offset (AtkText *text, gint offset); char* eel_accessibility_text_get_text_before_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset); char* eel_accessibility_text_get_text_at_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset); char* eel_accessibility_text_get_text_after_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset); gint eel_accessibility_text_get_character_count (AtkText *text); #define EEL_TYPE_ACCESSIBLE_TEXT (eel_accessible_text_get_type ()) #define EEL_IS_ACCESSIBLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_ACCESSIBLE_TEXT) #define EEL_ACCESSIBLE_TEXT(obj) G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_ACCESSIBLE_TEXT, EelAccessibleText) #define EEL_ACCESSIBLE_TEXT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEL_TYPE_ACCESSIBLE_TEXT, EelAccessibleTextIface)) /* Instead of implementing the AtkText interface, implement this */ typedef struct _EelAccessibleText EelAccessibleText; typedef struct { GTypeInterface parent; GailTextUtil *(*get_text) (GObject *text); PangoLayout *(*get_layout) (GObject *text); } EelAccessibleTextIface; GType eel_accessible_text_get_type (void); #endif /* EEL_ACCESSIBILITY_H */ nemo-3.6.5/eel/eel-self-checks.h0000664000175000017500000000644313215733314015270 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-self-checks.h: The self-check framework. Copyright (C) 1999 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #ifndef EEL_SELF_CHECKS_H #define EEL_SELF_CHECKS_H #include #include #define EEL_CHECK_RESULT(type, expression, expected_value) \ G_STMT_START { \ eel_before_check (#expression, __FILE__, __LINE__); \ eel_check_##type##_result (expression, expected_value); \ } G_STMT_END #define EEL_CHECK_BOOLEAN_RESULT(expression, expected_value) \ EEL_CHECK_RESULT(boolean, expression, expected_value) #define EEL_CHECK_INTEGER_RESULT(expression, expected_value) \ EEL_CHECK_RESULT(integer, expression, expected_value) #define EEL_CHECK_DOUBLE_RESULT(expression, expected_value) \ EEL_CHECK_RESULT(double, expression, expected_value) #define EEL_CHECK_STRING_RESULT(expression, expected_value) \ EEL_CHECK_RESULT(string, expression, expected_value) #define EEL_CHECK_RECTANGLE_RESULT(expression, expected_x0, expected_y0, expected_x1, expected_y1) \ G_STMT_START { \ eel_before_check (#expression, __FILE__, __LINE__); \ eel_check_rectangle_result (expression, expected_x0, expected_y0, expected_x1, expected_y1); \ } G_STMT_END void eel_exit_if_self_checks_failed (void); void eel_before_check_function (const char *name); void eel_after_check_function (void); void eel_before_check (const char *expression, const char *file_name, int line_number); void eel_after_check (void); /* Both 'result' and 'expected' get freed with g_free */ void eel_report_check_failure (char *result, char *expected); void eel_check_boolean_result (gboolean result, gboolean expected_value); void eel_check_integer_result (long result, long expected_value); void eel_check_double_result (double result, double expected_value); void eel_check_rectangle_result (EelIRect result, int expected_x0, int expected_y0, int expected_x1, int expected_y1); void eel_check_string_result (char *result, const char *expected_value); #define EEL_SELF_CHECK_FUNCTION_PROTOTYPE(function) \ void function (void); #define EEL_CALL_SELF_CHECK_FUNCTION(function) \ eel_before_check_function (#function); \ function (); \ eel_after_check_function (); #endif /* EEL_SELF_CHECKS_H */ nemo-3.6.5/eel/eel-vfs-extensions.h0000664000175000017500000000460213215733314016067 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-vfs-extensions.h - gnome-vfs extensions. Its likely some of these will be part of gnome-vfs in the future. Copyright (C) 1999, 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler Pavel Cisler Mike Fleming John Sullivan */ #ifndef EEL_VFS_EXTENSIONS_H #define EEL_VFS_EXTENSIONS_H #include G_BEGIN_DECLS #define EEL_TRASH_URI "trash:" #define EEL_DESKTOP_URI "x-nemo-desktop:" #define EEL_SEARCH_URI "x-nemo-search:" gboolean eel_uri_is_trash (const char *uri); gboolean eel_uri_is_trash_folder (const char *uri); gboolean eel_uri_is_in_trash (const char *uri); gboolean eel_uri_is_desktop (const char *uri); gboolean eel_uri_is_search (const char *uri); gboolean eel_uri_is_recent (const char *uri); char * eel_make_valid_utf8 (const char *name); char * eel_filename_strip_extension (const char *filename); void eel_filename_get_rename_region (const char *filename, int *start_offset, int *end_offset); char * eel_filename_get_extension_offset (const char *filename); G_END_DECLS #endif /* EEL_VFS_EXTENSIONS_H */ nemo-3.6.5/eel/eel-debug.c0000664000175000017500000000521613215733314014157 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-debug.c: Eel debugging aids. Copyright (C) 2000, 2001 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #include "eel-debug.h" #include #include #include typedef struct { gpointer data; GFreeFunc function; } ShutdownFunction; static GList *shutdown_functions; /* Raise a SIGINT signal to get the attention of the debugger. * When not running under the debugger, we don't want to stop, * so we ignore the signal for just the moment that we raise it. */ static void eel_stop_in_debugger (void) { void (* saved_handler) (int); saved_handler = signal (SIGINT, SIG_IGN); raise (SIGINT); signal (SIGINT, saved_handler); } /* Stop in the debugger after running the default log handler. * This makes certain kinds of messages stop in the debugger * without making them fatal (you can continue). */ static void log_handler (const char *domain, GLogLevelFlags level, const char *message, gpointer data) { g_log_default_handler (domain, level, message, data); if ((level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) != 0) { eel_stop_in_debugger (); } } void eel_make_warnings_and_criticals_stop_in_debugger (void) { g_log_set_default_handler (log_handler, NULL); } void eel_debug_shut_down (void) { ShutdownFunction *f; while (shutdown_functions != NULL) { f = shutdown_functions->data; shutdown_functions = g_list_remove (shutdown_functions, f); f->function (f->data); g_free (f); } } void eel_debug_call_at_shutdown (EelFunction function) { eel_debug_call_at_shutdown_with_data ((GFreeFunc) function, NULL); } void eel_debug_call_at_shutdown_with_data (GFreeFunc function, gpointer data) { ShutdownFunction *f; f = g_new (ShutdownFunction, 1); f->data = data; f->function = function; shutdown_functions = g_list_prepend (shutdown_functions, f); } nemo-3.6.5/eel/eel-art-extensions.c0000664000175000017500000001062013215733314016047 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-art-extensions.c - implementation of libart extension functions. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler Ramiro Estrugo */ #include #include "eel-art-extensions.h" #include "eel-lib-self-check-functions.h" #include const EelDRect eel_drect_empty = { 0.0, 0.0, 0.0, 0.0 }; const EelIRect eel_irect_empty = { 0, 0, 0, 0 }; void eel_irect_copy (EelIRect *dest, const EelIRect *src) { dest->x0 = src->x0; dest->y0 = src->y0; dest->x1 = src->x1; dest->y1 = src->y1; } void eel_irect_union (EelIRect *dest, const EelIRect *src1, const EelIRect *src2) { if (eel_irect_is_empty (src1)) { eel_irect_copy (dest, src2); } else if (eel_irect_is_empty (src2)) { eel_irect_copy (dest, src1); } else { dest->x0 = MIN (src1->x0, src2->x0); dest->y0 = MIN (src1->y0, src2->y0); dest->x1 = MAX (src1->x1, src2->x1); dest->y1 = MAX (src1->y1, src2->y1); } } void eel_irect_intersect (EelIRect *dest, const EelIRect *src1, const EelIRect *src2) { dest->x0 = MAX (src1->x0, src2->x0); dest->y0 = MAX (src1->y0, src2->y0); dest->x1 = MIN (src1->x1, src2->x1); dest->y1 = MIN (src1->y1, src2->y1); } gboolean eel_irect_is_empty (const EelIRect *src) { return (src->x1 <= src->x0 || src->y1 <= src->y0); } /** * eel_irect_get_width: * * @rectangle: An EelIRect. * * Returns: The width of the rectangle. * */ int eel_irect_get_width (EelIRect rectangle) { return rectangle.x1 - rectangle.x0; } /** * eel_irect_get_height: * * @rectangle: An EelIRect. * * Returns: The height of the rectangle. * */ int eel_irect_get_height (EelIRect rectangle) { return rectangle.y1 - rectangle.y0; } static void eel_drect_copy (EelDRect *dest, const EelDRect *src) { dest->x0 = src->x0; dest->y0 = src->y0; dest->x1 = src->x1; dest->y1 = src->y1; } static gboolean eel_drect_is_empty (const EelDRect *src) { return (src->x1 <= src->x0 || src->y1 <= src->y0); } void eel_drect_union (EelDRect *dest, const EelDRect *src1, const EelDRect *src2) { if (eel_drect_is_empty (src1)) { eel_drect_copy (dest, src2); } else if (eel_drect_is_empty (src2)) { eel_drect_copy (dest, src1); } else { dest->x0 = MIN (src1->x0, src2->x0); dest->y0 = MIN (src1->y0, src2->y0); dest->x1 = MAX (src1->x1, src2->x1); dest->y1 = MAX (src1->y1, src2->y1); } } /** * eel_irect_contains_point: * * @rectangle: An EelIRect. * @x: X coordinate to test. * @y: Y coordinate to test. * * Returns: A boolean value indicating whether the rectangle * contains the x,y coordinate. * */ gboolean eel_irect_contains_point (EelIRect rectangle, int x, int y) { return x >= rectangle.x0 && x <= rectangle.x1 && y >= rectangle.y0 && y <= rectangle.y1; } gboolean eel_irect_hits_irect (EelIRect rectangle_a, EelIRect rectangle_b) { EelIRect intersection; eel_irect_intersect (&intersection, &rectangle_a, &rectangle_b); return !eel_irect_is_empty (&intersection); } gboolean eel_irect_equal (EelIRect rectangle_a, EelIRect rectangle_b) { return rectangle_a.x0 == rectangle_b.x0 && rectangle_a.y0 == rectangle_b.y0 && rectangle_a.x1 == rectangle_b.x1 && rectangle_a.y1 == rectangle_b.y1; } EelIRect eel_irect_offset_by (EelIRect rectangle, int x, int y) { rectangle.x0 += x; rectangle.x1 += x; rectangle.y0 += y; rectangle.y1 += y; return rectangle; } EelIRect eel_irect_scale_by (EelIRect rectangle, double scale) { rectangle.x0 *= scale; rectangle.x1 *= scale; rectangle.y0 *= scale; rectangle.y1 *= scale; return rectangle; } nemo-3.6.5/eel/eel-graphic-effects.h0000664000175000017500000000317713215733314016134 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-graphic-effects.h: Pixmap manipulation routines for graphical effects. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Andy Hertzfeld */ #ifndef EEL_GRAPHIC_EFFECTS_H #define EEL_GRAPHIC_EFFECTS_H #include #include /* return a lightened pixbuf for pre-lighting */ GdkPixbuf *eel_create_spotlight_pixbuf (GdkPixbuf *source_pixbuf); /* return a pixbuf colorized with the color specified by the parameters */ GdkPixbuf* eel_create_colorized_pixbuf (GdkPixbuf *source_pixbuf, GdkRGBA *color); /* embed in image in a frame */ GdkPixbuf *eel_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset); #endif /* EEL_GRAPHIC_EFFECTS_H */ nemo-3.6.5/eel/check-program.c0000664000175000017500000000323213215733314015044 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* check-program.c: A simple driver for eel self checks. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Ramiro Estrugo */ #include #include #include #include #include #include #include #include #include int main (int argc, char *argv[]) { #if !defined (EEL_OMIT_SELF_CHECK) eel_make_warnings_and_criticals_stop_in_debugger (); LIBXML_TEST_VERSION gtk_init (&argc, &argv); /* Run the checks for eel twice. */ eel_run_lib_self_checks (); eel_exit_if_self_checks_failed (); eel_run_lib_self_checks (); eel_exit_if_self_checks_failed (); eel_debug_shut_down (); #endif /* !EEL_OMIT_SELF_CHECK */ return EXIT_SUCCESS; } nemo-3.6.5/eel/eel-gtk-extensions.c0000664000175000017500000002552413215733314016057 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gtk-extensions.c - implementation of new functions that operate on gtk classes. Perhaps some of these should be rolled into gtk someday. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan Ramiro Estrugo Darin Adler */ #include #include "eel-gtk-extensions.h" #include "eel-glib-extensions.h" #include "eel-gnome-extensions.h" #include "eel-string.h" #include #include #include #include #include #include #include #include /* This number is fairly arbitrary. Long enough to show a pretty long * menu title, but not so long to make a menu grotesquely wide. */ #define MAXIMUM_MENU_TITLE_LENGTH 48 /* Used for window position & size sanity-checking. The sizes are big enough to prevent * at least normal-sized gnome panels from obscuring the window at the screen edges. */ #define MINIMUM_ON_SCREEN_WIDTH 100 #define MINIMUM_ON_SCREEN_HEIGHT 100 /** * eel_gtk_window_get_geometry_string: * @window: a #GtkWindow * * Obtains the geometry string for this window, suitable for * set_geometry_string(); assumes the window has NorthWest gravity * * Return value: geometry string, must be freed **/ char* eel_gtk_window_get_geometry_string (GtkWindow *window) { char *str; int w, h, x, y; g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); g_return_val_if_fail (gtk_window_get_gravity (window) == GDK_GRAVITY_NORTH_WEST, NULL); gtk_window_get_position (window, &x, &y); gtk_window_get_size (window, &w, &h); str = g_strdup_printf ("%dx%d+%d+%d", w, h, x, y); return str; } static void sanity_check_window_position (int *left, int *top) { g_assert (left != NULL); g_assert (top != NULL); /* Make sure the top of the window is on screen, for * draggability (might not be necessary with all window managers, * but seems reasonable anyway). Make sure the top of the window * isn't off the bottom of the screen, or so close to the bottom * that it might be obscured by the panel. */ *top = CLAMP (*top, 0, gdk_screen_height() - MINIMUM_ON_SCREEN_HEIGHT); /* FIXME bugzilla.eazel.com 669: * If window has negative left coordinate, set_uposition sends it * somewhere else entirely. Not sure what level contains this bug (XWindows?). * Hacked around by pinning the left edge to zero, which just means you * can't set a window to be partly off the left of the screen using * this routine. */ /* Make sure the left edge of the window isn't off the right edge of * the screen, or so close to the right edge that it might be * obscured by the panel. */ *left = CLAMP (*left, 0, gdk_screen_width() - MINIMUM_ON_SCREEN_WIDTH); } static void sanity_check_window_dimensions (guint *width, guint *height) { g_assert (width != NULL); g_assert (height != NULL); /* Pin the size of the window to the screen, so we don't end up in * a state where the window is so big essential parts of it can't * be reached (might not be necessary with all window managers, * but seems reasonable anyway). */ *width = MIN (*width, gdk_screen_width()); *height = MIN (*height, gdk_screen_height()); } /** * eel_gtk_window_set_initial_geometry: * * Sets the position and size of a GtkWindow before the * GtkWindow is shown. It is an error to call this on a window that * is already on-screen. Takes into account screen size, and does * some sanity-checking on the passed-in values. * * @window: A non-visible GtkWindow * @geometry_flags: A EelGdkGeometryFlags value defining which of * the following parameters have defined values * @left: pixel coordinate for left of window * @top: pixel coordinate for top of window * @width: width of window in pixels * @height: height of window in pixels */ static void eel_gtk_window_set_initial_geometry (GtkWindow *window, EelGdkGeometryFlags geometry_flags, int left, int top, guint width, guint height) { GdkScreen *screen; int real_left, real_top; int screen_width, screen_height; g_return_if_fail (GTK_IS_WINDOW (window)); /* Setting the default size doesn't work when the window is already showing. * Someday we could make this move an already-showing window, but we don't * need that functionality yet. */ g_return_if_fail (!gtk_widget_get_visible (GTK_WIDGET (window))); if ((geometry_flags & EEL_GDK_X_VALUE) && (geometry_flags & EEL_GDK_Y_VALUE)) { real_left = left; real_top = top; screen = gtk_window_get_screen (window); screen_width = gdk_screen_get_width (screen); screen_height = gdk_screen_get_height (screen); /* This is sub-optimal. GDK doesn't allow us to set win_gravity * to South/East types, which should be done if using negative * positions (so that the right or bottom edge of the window * appears at the specified position, not the left or top). * However it does seem to be consistent with other GNOME apps. */ if (geometry_flags & EEL_GDK_X_NEGATIVE) { real_left = screen_width - real_left; } if (geometry_flags & EEL_GDK_Y_NEGATIVE) { real_top = screen_height - real_top; } sanity_check_window_position (&real_left, &real_top); gtk_window_move (window, real_left, real_top); } if ((geometry_flags & EEL_GDK_WIDTH_VALUE) && (geometry_flags & EEL_GDK_HEIGHT_VALUE)) { sanity_check_window_dimensions (&width, &height); gtk_window_set_default_size (GTK_WINDOW (window), (int)width, (int)height); } } /** * eel_gtk_window_set_initial_geometry_from_string: * * Sets the position and size of a GtkWindow before the * GtkWindow is shown. The geometry is passed in as a string. * It is an error to call this on a window that * is already on-screen. Takes into account screen size, and does * some sanity-checking on the passed-in values. * * @window: A non-visible GtkWindow * @geometry_string: A string suitable for use with eel_gdk_parse_geometry * @minimum_width: If the width from the string is smaller than this, * use this for the width. * @minimum_height: If the height from the string is smaller than this, * use this for the height. * @ignore_position: If true position data from string will be ignored. */ void eel_gtk_window_set_initial_geometry_from_string (GtkWindow *window, const char *geometry_string, guint minimum_width, guint minimum_height, gboolean ignore_position) { int left, top; guint width, height; EelGdkGeometryFlags geometry_flags; g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (geometry_string != NULL); /* Setting the default size doesn't work when the window is already showing. * Someday we could make this move an already-showing window, but we don't * need that functionality yet. */ g_return_if_fail (!gtk_widget_get_visible (GTK_WIDGET (window))); geometry_flags = eel_gdk_parse_geometry (geometry_string, &left, &top, &width, &height); /* Make sure the window isn't smaller than makes sense for this window. * Other sanity checks are performed in set_initial_geometry. */ if (geometry_flags & EEL_GDK_WIDTH_VALUE) { width = MAX (width, minimum_width); } if (geometry_flags & EEL_GDK_HEIGHT_VALUE) { height = MAX (height, minimum_height); } /* Ignore saved window position if requested. */ if (ignore_position) { geometry_flags &= ~(EEL_GDK_X_VALUE | EEL_GDK_Y_VALUE); } eel_gtk_window_set_initial_geometry (window, geometry_flags, left, top, width, height); } /** * eel_pop_up_context_menu: * * Pop up a context menu under the mouse. * The menu is sunk after use, so it will be destroyed unless the * caller first ref'ed it. * * This function is more of a helper function than a gtk extension, * so perhaps it belongs in a different file. * * @menu: The menu to pop up under the mouse. * @offset_x: Ignored. * @offset_y: Ignored. * @event: The event that invoked this popup menu, or #NULL if there * is no event available. This is used to get the timestamp for the menu's popup. * In case no event is provided, gtk_get_current_event_time() will be used automatically. **/ void eel_pop_up_context_menu (GtkMenu *menu, GdkEventButton *event) { int button; g_return_if_fail (GTK_IS_MENU (menu)); /* The event button needs to be 0 if we're popping up this menu from * a button release, else a 2nd click outside the menu with any button * other than the one that invoked the menu will be ignored (instead * of dismissing the menu). This is a subtle fragility of the GTK menu code. */ if (event) { button = event->type == GDK_BUTTON_RELEASE ? 0 : event->button; } else { button = 0; } gtk_menu_popup (menu, /* menu */ NULL, /* parent_menu_shell */ NULL, /* parent_menu_item */ NULL, /* popup_position_func */ NULL, /* popup_position_data */ button, /* button */ event ? event->time : gtk_get_current_event_time ()); /* activate_time */ g_object_ref_sink (menu); g_object_unref (menu); } GtkMenuItem * eel_gtk_menu_append_separator (GtkMenu *menu) { return eel_gtk_menu_insert_separator (menu, -1); } GtkMenuItem * eel_gtk_menu_insert_separator (GtkMenu *menu, int index) { GtkWidget *menu_item; menu_item = gtk_separator_menu_item_new (); gtk_widget_show (menu_item); gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menu_item, index); return GTK_MENU_ITEM (menu_item); } void eel_gtk_message_dialog_set_details_label (GtkMessageDialog *dialog, const gchar *details_text) { GtkWidget *content_area, *expander, *label; content_area = gtk_message_dialog_get_message_area (dialog); expander = gtk_expander_new_with_mnemonic (_("Show more _details")); gtk_expander_set_spacing (GTK_EXPANDER (expander), 6); label = gtk_label_new (details_text); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_selectable (GTK_LABEL (label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_container_add (GTK_CONTAINER (expander), label); gtk_box_pack_start (GTK_BOX (content_area), expander, FALSE, FALSE, 0); gtk_widget_show (label); gtk_widget_show (expander); } nemo-3.6.5/eel/eel.h0000664000175000017500000000251413215733314013076 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel.h Copyright (C) 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Maciej Stachowiak */ #ifndef EEL_H #define EEL_H #include #include #include #include #include #include #include #include #include #include #endif /* EEL_H */ nemo-3.6.5/eel/check-eel0000775000175000017500000000007313215733314013724 0ustar fabiofabio#!/bin/sh ./check-program --g-fatal-warnings --sm-disable nemo-3.6.5/eel/eel-gtk-extensions.h0000664000175000017500000000452513215733314016062 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gtk-extensions.h - interface for new functions that operate on gtk classes. Perhaps some of these should be rolled into gtk someday. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan Ramiro Estrugo */ #ifndef EEL_GTK_EXTENSIONS_H #define EEL_GTK_EXTENSIONS_H #include #include #include /* GtkWindow */ void eel_gtk_window_set_initial_geometry_from_string (GtkWindow *window, const char *geometry_string, guint minimum_width, guint minimum_height, gboolean ignore_position); char * eel_gtk_window_get_geometry_string (GtkWindow *window); /* GtkMenu and GtkMenuItem */ void eel_pop_up_context_menu (GtkMenu *menu, GdkEventButton *event); GtkMenuItem * eel_gtk_menu_append_separator (GtkMenu *menu); GtkMenuItem * eel_gtk_menu_insert_separator (GtkMenu *menu, int index); /* GtkMessageDialog */ void eel_gtk_message_dialog_set_details_label (GtkMessageDialog *dialog, const gchar *details_text); #endif /* EEL_GTK_EXTENSIONS_H */ nemo-3.6.5/eel/eel-vfs-extensions.c0000664000175000017500000001013113215733314016054 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-vfs-extensions.c - gnome-vfs extensions. Its likely some of these will be part of gnome-vfs in the future. Copyright (C) 1999, 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler Pavel Cisler Mike Fleming John Sullivan */ #include #include "eel-vfs-extensions.h" #include "eel-glib-extensions.h" #include "eel-lib-self-check-functions.h" #include #include #include #include "eel-string.h" #include #include gboolean eel_uri_is_trash (const char *uri) { return g_str_has_prefix (uri, "trash:"); } gboolean eel_uri_is_recent (const char *uri) { return g_str_has_prefix (uri, "recent:"); } gboolean eel_uri_is_search (const char *uri) { return g_str_has_prefix (uri, EEL_SEARCH_URI); } gboolean eel_uri_is_desktop (const char *uri) { return g_str_has_prefix (uri, EEL_DESKTOP_URI); } char * eel_make_valid_utf8 (const char *name) { GString *string; const char *remainder, *invalid; int remaining_bytes, valid_bytes; string = NULL; remainder = name; remaining_bytes = strlen (name); while (remaining_bytes != 0) { if (g_utf8_validate (remainder, remaining_bytes, &invalid)) { break; } valid_bytes = invalid - remainder; if (string == NULL) { string = g_string_sized_new (remaining_bytes); } g_string_append_len (string, remainder, valid_bytes); g_string_append_c (string, '?'); remaining_bytes -= valid_bytes + 1; remainder = invalid + 1; } if (string == NULL) { return g_strdup (name); } g_string_append (string, remainder); g_string_append (string, _(" (invalid Unicode)")); g_assert (g_utf8_validate (string->str, -1, NULL)); return g_string_free (string, FALSE); } char * eel_filename_get_extension_offset (const char *filename) { char *end, *end2; const char *start; if (filename == NULL || filename[0] == '\0') { return NULL; } /* basename must have at least one char */ start = filename + 1; end = strrchr (start, '.'); if (end == NULL || end[1] == '\0') { return NULL; } if (end != start) { if (strcmp (end, ".gz") == 0 || strcmp (end, ".bz2") == 0 || strcmp (end, ".sit") == 0 || strcmp (end, ".Z") == 0) { end2 = end - 1; while (end2 > start && *end2 != '.') { end2--; } if (end2 != start) { end = end2; } } } return end; } char * eel_filename_strip_extension (const char * filename_with_extension) { char *filename, *end; if (filename_with_extension == NULL) { return NULL; } filename = g_strdup (filename_with_extension); end = eel_filename_get_extension_offset (filename); if (end && end != filename) { *end = '\0'; } return filename; } void eel_filename_get_rename_region (const char *filename, int *start_offset, int *end_offset) { char *filename_without_extension; g_return_if_fail (start_offset != NULL); g_return_if_fail (end_offset != NULL); *start_offset = 0; *end_offset = 0; g_return_if_fail (filename != NULL); filename_without_extension = eel_filename_strip_extension (filename); *end_offset = g_utf8_strlen (filename_without_extension, -1); g_free (filename_without_extension); } nemo-3.6.5/eel/eel-glib-extensions.h0000664000175000017500000000507413215733314016212 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-glib-extensions.h - interface for new functions that conceptually belong in glib. Perhaps some of these will be actually rolled into glib someday. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: John Sullivan */ #ifndef EEL_GLIB_EXTENSIONS_H #define EEL_GLIB_EXTENSIONS_H #include #include /* A gboolean variant for bit fields. */ typedef guint eel_boolean_bit; /* Predicate. */ typedef gboolean (* EelPredicateFunction) (gpointer data, gpointer callback_data); /* GList functions. */ gboolean eel_g_lists_sort_and_check_for_intersection (GList **list_a, GList **list_b); GList * eel_g_list_partition (GList *list, EelPredicateFunction predicate, gpointer user_data, GList **removed); /* List functions for lists of C strings. */ gboolean eel_g_str_list_equal (GList *str_list_a, GList *str_list_b); GList * eel_g_str_list_copy (GList *str_list); /* List functions for lists of objects */ GList * eel_g_object_list_copy (GList *list); /* GHashTable functions */ void eel_g_hash_table_safe_for_each (GHashTable *hash_table, GHFunc callback, gpointer callback_data); /* NULL terminated string arrays (strv). */ gboolean eel_g_strv_equal (char **a, char **b); #endif /* EEL_GLIB_EXTENSIONS_H */ nemo-3.6.5/eel/eel-graphic-effects.c0000664000175000017500000002335713215733314016131 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* Eel - pixbuf manipulation routines for graphical effects. * * Copyright (C) 2000 Eazel, Inc * * Author: Andy Hertzfeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ /* This file contains pixbuf manipulation routines used for graphical effects like pre-lighting and selection hilighting */ #include #include "eel-graphic-effects.h" #include "eel-glib-extensions.h" #include #include /* shared utility to create a new pixbuf from the passed-in one */ static GdkPixbuf * create_new_pixbuf (GdkPixbuf *src) { g_assert (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB); g_assert ((!gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 3) || (gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 4)); return gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src), gdk_pixbuf_get_has_alpha (src), gdk_pixbuf_get_bits_per_sample (src), gdk_pixbuf_get_width (src), gdk_pixbuf_get_height (src)); } /* utility routine to bump the level of a color component with pinning */ static guchar lighten_component (guchar cur_value) { int new_value = cur_value; new_value += 24 + (new_value >> 3); if (new_value > 255) { new_value = 255; } return (guchar) new_value; } GdkPixbuf * eel_create_spotlight_pixbuf (GdkPixbuf* src) { GdkPixbuf *dest; int i, j; int width, height, has_alpha, src_row_stride, dst_row_stride; guchar *target_pixels, *original_pixels; guchar *pixsrc, *pixdest; g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL); g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 3) || (gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 4), NULL); g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL); dest = create_new_pixbuf (src); has_alpha = gdk_pixbuf_get_has_alpha (src); width = gdk_pixbuf_get_width (src); height = gdk_pixbuf_get_height (src); dst_row_stride = gdk_pixbuf_get_rowstride (dest); src_row_stride = gdk_pixbuf_get_rowstride (src); target_pixels = gdk_pixbuf_get_pixels (dest); original_pixels = gdk_pixbuf_get_pixels (src); for (i = 0; i < height; i++) { pixdest = target_pixels + i * dst_row_stride; pixsrc = original_pixels + i * src_row_stride; for (j = 0; j < width; j++) { *pixdest++ = lighten_component (*pixsrc++); *pixdest++ = lighten_component (*pixsrc++); *pixdest++ = lighten_component (*pixsrc++); if (has_alpha) { *pixdest++ = *pixsrc++; } } } return dest; } /* this routine colorizes the passed-in pixbuf by multiplying each pixel with the passed in color */ GdkPixbuf * eel_create_colorized_pixbuf (GdkPixbuf *src, GdkRGBA *color) { int i, j; int width, height, has_alpha, src_row_stride, dst_row_stride; guchar *target_pixels; guchar *original_pixels; guchar *pixsrc; guchar *pixdest; GdkPixbuf *dest; gint red_value, green_value, blue_value; g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL); g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 3) || (gdk_pixbuf_get_has_alpha (src) && gdk_pixbuf_get_n_channels (src) == 4), NULL); g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL); red_value = (gint) floor (color->red * 255); green_value = (gint) floor (color->green * 255); blue_value = (gint) floor (color->blue * 255); dest = create_new_pixbuf (src); has_alpha = gdk_pixbuf_get_has_alpha (src); width = gdk_pixbuf_get_width (src); height = gdk_pixbuf_get_height (src); src_row_stride = gdk_pixbuf_get_rowstride (src); dst_row_stride = gdk_pixbuf_get_rowstride (dest); target_pixels = gdk_pixbuf_get_pixels (dest); original_pixels = gdk_pixbuf_get_pixels (src); for (i = 0; i < height; i++) { pixdest = target_pixels + i*dst_row_stride; pixsrc = original_pixels + i*src_row_stride; for (j = 0; j < width; j++) { *pixdest++ = (*pixsrc++ * red_value) >> 8; *pixdest++ = (*pixsrc++ * green_value) >> 8; *pixdest++ = (*pixsrc++ * blue_value) >> 8; if (has_alpha) { *pixdest++ = *pixsrc++; } } } return dest; } /* utility to stretch a frame to the desired size */ static void draw_frame_row (GdkPixbuf *frame_image, int target_width, int source_width, int source_v_position, int dest_v_position, GdkPixbuf *result_pixbuf, int left_offset, int height) { int remaining_width, h_offset, slab_width; remaining_width = target_width; h_offset = 0; while (remaining_width > 0) { slab_width = remaining_width > source_width ? source_width : remaining_width; gdk_pixbuf_copy_area (frame_image, left_offset, source_v_position, slab_width, height, result_pixbuf, left_offset + h_offset, dest_v_position); remaining_width -= slab_width; h_offset += slab_width; } } /* utility to draw the middle section of the frame in a loop */ static void draw_frame_column (GdkPixbuf *frame_image, int target_height, int source_height, int source_h_position, int dest_h_position, GdkPixbuf *result_pixbuf, int top_offset, int width) { int remaining_height, v_offset, slab_height; remaining_height = target_height; v_offset = 0; while (remaining_height > 0) { slab_height = remaining_height > source_height ? source_height : remaining_height; gdk_pixbuf_copy_area (frame_image, source_h_position, top_offset, width, slab_height, result_pixbuf, dest_h_position, top_offset + v_offset); remaining_height -= slab_height; v_offset += slab_height; } } static GdkPixbuf * eel_stretch_frame_image (GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset, int dest_width, int dest_height, gboolean fill_flag) { GdkPixbuf *result_pixbuf; guchar *pixels_ptr; int frame_width, frame_height; int y, row_stride; int target_width, target_frame_width; int target_height, target_frame_height; frame_width = gdk_pixbuf_get_width (frame_image); frame_height = gdk_pixbuf_get_height (frame_image ); if (fill_flag) { result_pixbuf = gdk_pixbuf_scale_simple (frame_image, dest_width, dest_height, GDK_INTERP_NEAREST); } else { result_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, dest_width, dest_height); } row_stride = gdk_pixbuf_get_rowstride (result_pixbuf); pixels_ptr = gdk_pixbuf_get_pixels (result_pixbuf); /* clear the new pixbuf */ if (!fill_flag) { for (y = 0; y < dest_height; y++) { memset (pixels_ptr, 255, row_stride); pixels_ptr += row_stride; } } target_width = dest_width - left_offset - right_offset; target_frame_width = frame_width - left_offset - right_offset; target_height = dest_height - top_offset - bottom_offset; target_frame_height = frame_height - top_offset - bottom_offset; /* draw the left top corner and top row */ gdk_pixbuf_copy_area (frame_image, 0, 0, left_offset, top_offset, result_pixbuf, 0, 0); draw_frame_row (frame_image, target_width, target_frame_width, 0, 0, result_pixbuf, left_offset, top_offset); /* draw the right top corner and left column */ gdk_pixbuf_copy_area (frame_image, frame_width - right_offset, 0, right_offset, top_offset, result_pixbuf, dest_width - right_offset, 0); draw_frame_column (frame_image, target_height, target_frame_height, 0, 0, result_pixbuf, top_offset, left_offset); /* draw the bottom right corner and bottom row */ gdk_pixbuf_copy_area (frame_image, frame_width - right_offset, frame_height - bottom_offset, right_offset, bottom_offset, result_pixbuf, dest_width - right_offset, dest_height - bottom_offset); draw_frame_row (frame_image, target_width, target_frame_width, frame_height - bottom_offset, dest_height - bottom_offset, result_pixbuf, left_offset, bottom_offset); /* draw the bottom left corner and the right column */ gdk_pixbuf_copy_area (frame_image, 0, frame_height - bottom_offset, left_offset, bottom_offset, result_pixbuf, 0, dest_height - bottom_offset); draw_frame_column (frame_image, target_height, target_frame_height, frame_width - right_offset, dest_width - right_offset, result_pixbuf, top_offset, right_offset); return result_pixbuf; } /* draw an arbitrary frame around an image, with the result passed back in a newly allocated pixbuf */ GdkPixbuf * eel_embed_image_in_frame (GdkPixbuf *source_image, GdkPixbuf *frame_image, int left_offset, int top_offset, int right_offset, int bottom_offset) { GdkPixbuf *result_pixbuf; int source_width, source_height; int dest_width, dest_height; source_width = gdk_pixbuf_get_width (source_image); source_height = gdk_pixbuf_get_height (source_image); dest_width = source_width + left_offset + right_offset; dest_height = source_height + top_offset + bottom_offset; result_pixbuf = eel_stretch_frame_image (frame_image, left_offset, top_offset, right_offset, bottom_offset, dest_width, dest_height, FALSE); /* Finally, copy the source image into the framed area */ gdk_pixbuf_copy_area (source_image, 0, 0, source_width, source_height, result_pixbuf, left_offset, top_offset); return result_pixbuf; } nemo-3.6.5/eel/eel-gnome-extensions.c0000664000175000017500000001037713215733314016377 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gnome-extensions.c - implementation of new functions that operate on gnome classes. Perhaps some of these should be rolled into gnome someday. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #include #define GNOME_DESKTOP_USE_UNSTABLE_API #include "eel-gnome-extensions.h" #include /* Adapted from gio - gdesktopappinfo.c - prepend_terminal_to_vector */ static char * prepend_terminal_to_command_line (const char *command_line) { GSettings *settings; gchar *prefix = NULL; gchar *terminal = NULL; gchar *ret = NULL; g_return_val_if_fail (command_line != NULL, g_strdup (command_line)); settings = g_settings_new ("org.cinnamon.desktop.default-applications.terminal"); terminal = g_settings_get_string (settings, "exec"); if (terminal != NULL) { gchar *term_path = NULL; term_path = g_find_program_in_path (terminal); if (term_path != NULL) { gchar *exec_flag = NULL; exec_flag = g_settings_get_string (settings, "exec-arg"); if (exec_flag == NULL) { prefix = g_strdup (term_path); } else { prefix = g_strdup_printf ("%s %s", term_path, exec_flag); } g_free (exec_flag); } g_free (term_path); } g_object_unref (settings); g_free (terminal); if (prefix == NULL) { gchar *check = NULL; check = g_find_program_in_path ("gnome-terminal"); if (check != NULL) { /* Note that gnome-terminal takes -x and * as -e in gnome-terminal is broken we use that. */ prefix = g_strdup_printf ("gnome-terminal -x"); } else { check = g_find_program_in_path ("nxterm"); if (check == NULL) check = g_find_program_in_path ("color-xterm"); if (check == NULL) check = g_find_program_in_path ("rxvt"); if (check == NULL) check = g_find_program_in_path ("xterm"); if (check == NULL) check = g_find_program_in_path ("dtterm"); if (check == NULL) { check = g_strdup ("xterm"); g_warning ("couldn't find a terminal, falling back to xterm"); } prefix = g_strdup_printf ("%s -e", check); } g_free (check); } ret = g_strdup_printf ("%s %s", prefix, command_line); g_free (prefix); return ret; } /* Return a command string containing the path to a terminal on this system. */ void eel_gnome_open_terminal_on_screen (const gchar *command, GdkScreen *screen) { gchar *command_line; GAppInfo *app; GdkAppLaunchContext *ctx; GError *error = NULL; GdkDisplay *display; command_line = prepend_terminal_to_command_line (command); app = g_app_info_create_from_commandline (command_line, NULL, 0, &error); if (app != NULL && screen != NULL) { display = gdk_screen_get_display (screen); ctx = gdk_display_get_app_launch_context (display); gdk_app_launch_context_set_screen (ctx, screen); g_app_info_launch (app, NULL, G_APP_LAUNCH_CONTEXT (ctx), &error); g_object_unref (app); g_object_unref (ctx); } if (error != NULL) { g_message ("Could not start application on terminal: %s", error->message); g_error_free (error); } } nemo-3.6.5/eel/eel-accessibility.c0000664000175000017500000002174513215733314015725 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-accessibility.h - Utility functions for accessibility Copyright (C) 2002 Anders Carlsson, Sun Microsystems, Inc. The Eel Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Eel Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Eel Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Anders Carlsson Michael Meeks */ #include #include #include void eel_accessibility_set_up_label_widget_relation (GtkWidget *label, GtkWidget *widget) { AtkObject *atk_widget, *atk_label; atk_label = gtk_widget_get_accessible (label); atk_widget = gtk_widget_get_accessible (widget); /* Create the label -> widget relation */ atk_object_add_relationship (atk_label, ATK_RELATION_LABEL_FOR, atk_widget); /* Create the widget -> label relation */ atk_object_add_relationship (atk_widget, ATK_RELATION_LABELLED_BY, atk_label); } /* * Hacks to make re-using gail somewhat easier. */ /** * eel_accessibility_create_derived_type: * @type_name: the name for the new accessible type eg. NemoIconCanvasItemAccessible * @existing_gobject_with_proxy: the GType of an object that has a registered factory that * manufactures the type we want to inherit from. ie. to inherit from a GailCanvasItem * we need to pass GNOME_TYPE_CANVAS_ITEM - since GailCanvasItem is registered against * that type. * @opt_gail_parent_class: the name of the Gail class to derive from eg. GailCanvasItem * @class_init: the init function to run for this class * * This should be run to register the type, it can subsequently be run with * the same name and will not re-register it, but simply return it. * * NB. to do instance init, you prolly want to override AtkObject::initialize * * Return value: the registered type, or 0 on failure. **/ GType eel_accessibility_create_derived_type (const char *type_name, GType existing_gobject_with_proxy, EelAccessibilityClassInitFn class_init) { GType type; GType parent_atk_type; GTypeInfo tinfo = { 0 }; GTypeQuery query; AtkObjectFactory *factory; if ((type = g_type_from_name (type_name))) { return type; } factory = atk_registry_get_factory (atk_get_default_registry (), existing_gobject_with_proxy); if (!factory) { return G_TYPE_INVALID; } parent_atk_type = atk_object_factory_get_accessible_type (factory); if (!parent_atk_type) { return G_TYPE_INVALID; } /* * Figure out the size of the class and instance * we are deriving from */ g_type_query (parent_atk_type, &query); if (class_init) { tinfo.class_init = (GClassInitFunc) class_init; } tinfo.class_size = query.class_size; tinfo.instance_size = query.instance_size; /* Register the type */ type = g_type_register_static ( parent_atk_type, type_name, &tinfo, 0); return type; } static GQuark get_quark_accessible (void) { static GQuark quark_accessible_object = 0; if (!quark_accessible_object) { quark_accessible_object = g_quark_from_static_string ("accessible-object"); } return quark_accessible_object; } static GQuark get_quark_gobject (void) { static GQuark quark_accessible_gobject = 0; if (!quark_accessible_gobject) { quark_accessible_gobject = g_quark_from_static_string ("object-for-accessible"); } return quark_accessible_gobject; } /** * eel_accessibility_get_atk_object: * @object: a GObject of some sort * * gets an AtkObject associated with a GObject * * Return value: the associated accessible if one exists or NULL **/ AtkObject * eel_accessibility_get_atk_object (gpointer object) { return g_object_get_qdata (object, get_quark_accessible ()); } /** * eel_accessibilty_for_object: * @object: a GObject of some sort * * gets an AtkObject associated with a GObject and if it doesn't * exist creates a suitable accessible object. * * Return value: an associated accessible. **/ AtkObject * eel_accessibility_for_object (gpointer object) { if (GTK_IS_WIDGET (object)) return gtk_widget_get_accessible (object); return atk_gobject_accessible_for_object (object); } /** * eel_accessibility_get_gobject: * @object: an AtkObject * * gets the GObject associated with the AtkObject, for which * @object provides accessibility support. * * Return value: the accessible's associated GObject **/ gpointer eel_accessibility_get_gobject (AtkObject *object) { return g_object_get_qdata (G_OBJECT (object), get_quark_gobject ()); } static void eel_accessibility_destroy (gpointer data) { g_object_set_qdata (G_OBJECT (data), get_quark_gobject (), NULL); atk_object_notify_state_change (ATK_OBJECT (data), ATK_STATE_DEFUNCT, TRUE); g_object_unref (data); } /** * eel_accessibility_set_atk_object_return: * @object: a GObject * @atk_object: it's AtkObject * * used to register and return a new accessible object for something * * Return value: @atk_object. **/ AtkObject * eel_accessibility_set_atk_object_return (gpointer object, AtkObject *atk_object) { atk_object_initialize (atk_object, object); if (!ATK_IS_GOBJECT_ACCESSIBLE (atk_object)) { g_object_set_qdata_full (object, get_quark_accessible (), atk_object, eel_accessibility_destroy); g_object_set_qdata (G_OBJECT (atk_object), get_quark_gobject (), object); } return atk_object; } static GailTextUtil * get_simple_text (gpointer object) { GObject *gobject; EelAccessibleTextIface *aif; if (GTK_IS_ACCESSIBLE (object)) { gobject = G_OBJECT (gtk_accessible_get_widget (GTK_ACCESSIBLE (object))); } else { gobject = eel_accessibility_get_gobject (object); } if (!gobject) { return NULL; } aif = EEL_ACCESSIBLE_TEXT_GET_IFACE (gobject); if (!aif) { g_warning ("No accessible text inferface on '%s'", g_type_name_from_instance ((gpointer) gobject)); } else if (aif->get_text) { return aif->get_text (gobject); } return NULL; } char * eel_accessibility_text_get_text (AtkText *text, gint start_pos, gint end_pos) { GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, NULL); return gail_text_util_get_substring (util, start_pos, end_pos); } gunichar eel_accessibility_text_get_character_at_offset (AtkText *text, gint offset) { char *txt, *index; gint sucks1 = 0, sucks2 = -1; gunichar c; GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, 0); txt = gail_text_util_get_substring (util, sucks1, sucks2); index = g_utf8_offset_to_pointer (txt, offset); c = g_utf8_get_char (index); g_free (txt); return c; } char * eel_accessibility_text_get_text_before_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, NULL); return gail_text_util_get_text ( util, NULL, GAIL_BEFORE_OFFSET, boundary_type, offset, start_offset, end_offset); } char * eel_accessibility_text_get_text_at_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, NULL); return gail_text_util_get_text ( util, NULL, GAIL_AT_OFFSET, boundary_type, offset, start_offset, end_offset); } gchar* eel_accessibility_text_get_text_after_offset (AtkText *text, gint offset, AtkTextBoundary boundary_type, gint *start_offset, gint *end_offset) { GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, NULL); return gail_text_util_get_text ( util, NULL, GAIL_AFTER_OFFSET, boundary_type, offset, start_offset, end_offset); } gint eel_accessibility_text_get_character_count (AtkText *text) { GailTextUtil *util = get_simple_text (text); g_return_val_if_fail (util != NULL, -1); return gtk_text_buffer_get_char_count (util->buffer); } GType eel_accessible_text_get_type (void) { static GType type = 0; if (!type) { const GTypeInfo tinfo = { sizeof (AtkTextIface), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) NULL, (GClassFinalizeFunc) NULL }; type = g_type_register_static ( G_TYPE_INTERFACE, "EelAccessibleText", &tinfo, 0); } return type; } nemo-3.6.5/eel/eel-editable-label.h0000664000175000017500000001312613215733314015723 0ustar fabiofabio/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #ifndef __EEL_EDITABLE_LABEL_H__ #define __EEL_EDITABLE_LABEL_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define EEL_TYPE_EDITABLE_LABEL eel_editable_label_get_type() #define EEL_EDITABLE_LABEL(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_EDITABLE_LABEL, EelEditableLabel)) #define EEL_EDITABLE_LABEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_EDITABLE_LABEL, EelEditableLabelClass)) #define EEL_IS_EDITABLE_LABEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_EDITABLE_LABEL)) #define EEL_IS_EDITABLE_LABEL_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_EDITABLE_LABEL)) #define EEL_EDITABLE_LABEL_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_EDITABLE_LABEL, EelEditableLabelClass)) typedef struct _EelEditableLabel EelEditableLabel; typedef struct _EelEditableLabelClass EelEditableLabelClass; typedef struct _EelEditableLabelSelectionInfo EelEditableLabelSelectionInfo; struct _EelEditableLabel { GtkMisc misc; guint jtype : 2; guint wrap : 1; guint overwrite_mode : 1; guint draw_outline : 1; guint layout_includes_preedit : 1; guint padding:2; PangoWrapMode wrap_mode; GdkWindow *text_area; gchar *text; int text_size; /* allocated size, in bytes */ int n_bytes; /* length in use (not including terminating zero), in bytes */ PangoLayout *layout; int selection_anchor; /* cursor pos, byte index */ int selection_end; /* byte index */ GtkWidget *popup_menu; GtkIMContext *im_context; gboolean need_im_reset; int preedit_length; /* length of preedit string, in bytes */ int preedit_cursor; /* offset of cursor within preedit string, in chars */ PangoFontDescription *font_desc; }; struct _EelEditableLabelClass { GtkMiscClass parent_class; void (* move_cursor) (EelEditableLabel *label, GtkMovementStep step, gint count, gboolean extend_selection); void (* insert_at_cursor) (EelEditableLabel *label, const gchar *str); void (* delete_from_cursor) (EelEditableLabel *label, GtkDeleteType type, gint count); void (* cut_clipboard) (EelEditableLabel *label); void (* copy_clipboard) (EelEditableLabel *label); void (* paste_clipboard) (EelEditableLabel *label); void (* toggle_overwrite) (EelEditableLabel *label); /* Hook to customize right-click popup for selectable labels */ void (* populate_popup) (EelEditableLabel *label, GtkMenu *menu); }; GType eel_editable_label_get_type (void) G_GNUC_CONST; GtkWidget* eel_editable_label_new (const char *str); void eel_editable_label_set_text (EelEditableLabel *label, const char *str); const gchar* eel_editable_label_get_text (EelEditableLabel *label); void eel_editable_label_set_justify (EelEditableLabel *label, GtkJustification jtype); GtkJustification eel_editable_label_get_justify (EelEditableLabel *label); void eel_editable_label_set_line_wrap (EelEditableLabel *label, gboolean wrap); void eel_editable_label_set_line_wrap_mode (EelEditableLabel *label, PangoWrapMode mode); gboolean eel_editable_label_get_line_wrap (EelEditableLabel *label); void eel_editable_label_set_draw_outline (EelEditableLabel *label, gboolean wrap); void eel_editable_label_select_region (EelEditableLabel *label, gint start_offset, gint end_offset); gboolean eel_editable_label_get_selection_bounds (EelEditableLabel *label, gint *start, gint *end); PangoLayout * eel_editable_label_get_layout (EelEditableLabel *label); void eel_editable_label_get_layout_offsets (EelEditableLabel *label, gint *x, gint *y); PangoFontDescription *eel_editable_label_get_font_description (EelEditableLabel *label); void eel_editable_label_set_font_description (EelEditableLabel *label, const PangoFontDescription *desc); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* __EEL_EDITABLE_LABEL_H__ */ nemo-3.6.5/eel/README0000664000175000017500000000003513215733314013034 0ustar fabiofabioREADME for eel/eel Writeme nemo-3.6.5/eel/eel-gdk-extensions.h0000664000175000017500000000341713215733314016041 0ustar fabiofabio// /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gdk-extensions.h: Graphics routines to augment what's in gdk. Copyright (C) 1999, 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler , Ramiro Estrugo */ #ifndef EEL_GDK_EXTENSIONS_H #define EEL_GDK_EXTENSIONS_H #include /* Bits returned by eel_gdk_parse_geometry */ typedef enum { EEL_GDK_NO_VALUE = 0x00, EEL_GDK_X_VALUE = 0x01, EEL_GDK_Y_VALUE = 0x02, EEL_GDK_WIDTH_VALUE = 0x04, EEL_GDK_HEIGHT_VALUE = 0x08, EEL_GDK_ALL_VALUES = 0x0f, EEL_GDK_X_NEGATIVE = 0x10, EEL_GDK_Y_NEGATIVE = 0x20 } EelGdkGeometryFlags; /* Wrapper for XParseGeometry */ EelGdkGeometryFlags eel_gdk_parse_geometry (const char *string, int *x_return, int *y_return, guint *width_return, guint *height_return); #endif /* EEL_GDK_EXTENSIONS_H */ nemo-3.6.5/eel/eel-lib-self-check-functions.c0000664000175000017500000000233413215733314017645 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-lib-self-check-functions.c: Wrapper for all self check functions in Eel proper. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #if ! defined (EEL_OMIT_SELF_CHECK) #include "eel-lib-self-check-functions.h" void eel_run_lib_self_checks (void) { EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_CALL_SELF_CHECK_FUNCTION) } #endif /* ! EEL_OMIT_SELF_CHECK */ nemo-3.6.5/eel/eel-stock-dialogs.c0000664000175000017500000003676613215733314015652 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-stock-dialogs.c: Various standard dialogs for Eel. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #include #include "eel-stock-dialogs.h" #include "eel-glib-extensions.h" #include "eel-gtk-extensions.h" #include #include #define TIMED_WAIT_STANDARD_DURATION 2000 #define TIMED_WAIT_MIN_TIME_UP 3000 #define TIMED_WAIT_MINIMUM_DIALOG_WIDTH 300 #define RESPONSE_DETAILS 1000 typedef struct { EelCancelCallback cancel_callback; gpointer callback_data; /* Parameters for creation of the window. */ char *wait_message; GtkWindow *parent_window; /* Timer to determine when we need to create the window. */ guint timeout_handler_id; /* Window, once it's created. */ GtkDialog *dialog; /* system time (microseconds) when dialog was created */ gint64 dialog_creation_time; } TimedWait; static GHashTable *timed_wait_hash_table; static void timed_wait_dialog_destroy_callback (GtkWidget *object, gpointer callback_data); static guint timed_wait_hash (gconstpointer value) { const TimedWait *wait; wait = value; return GPOINTER_TO_UINT (wait->cancel_callback) ^ GPOINTER_TO_UINT (wait->callback_data); } static gboolean timed_wait_hash_equal (gconstpointer value1, gconstpointer value2) { const TimedWait *wait1, *wait2; wait1 = value1; wait2 = value2; return wait1->cancel_callback == wait2->cancel_callback && wait1->callback_data == wait2->callback_data; } static void timed_wait_delayed_close_destroy_dialog_callback (GtkWidget *object, gpointer callback_data) { g_source_remove (GPOINTER_TO_UINT (callback_data)); } static gboolean timed_wait_delayed_close_timeout_callback (gpointer callback_data) { guint handler_id; handler_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (callback_data), "eel-stock-dialogs/delayed_close_handler_timeout_id")); g_signal_handlers_disconnect_by_func (G_OBJECT (callback_data), G_CALLBACK (timed_wait_delayed_close_destroy_dialog_callback), GUINT_TO_POINTER (handler_id)); gtk_widget_destroy (GTK_WIDGET (callback_data)); return FALSE; } static void timed_wait_free (TimedWait *wait) { guint delayed_close_handler_id; guint64 time_up; g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) != NULL); g_hash_table_remove (timed_wait_hash_table, wait); g_free (wait->wait_message); if (wait->parent_window != NULL) { g_object_unref (wait->parent_window); } if (wait->timeout_handler_id != 0) { g_source_remove (wait->timeout_handler_id); } if (wait->dialog != NULL) { /* Make sure to detach from the "destroy" signal, or we'll * double-free. */ g_signal_handlers_disconnect_by_func (G_OBJECT (wait->dialog), G_CALLBACK (timed_wait_dialog_destroy_callback), wait); /* compute time up in milliseconds */ time_up = (g_get_monotonic_time () - wait->dialog_creation_time) / 1000; if (time_up < TIMED_WAIT_MIN_TIME_UP) { delayed_close_handler_id = g_timeout_add (TIMED_WAIT_MIN_TIME_UP - time_up, timed_wait_delayed_close_timeout_callback, wait->dialog); g_object_set_data (G_OBJECT (wait->dialog), "eel-stock-dialogs/delayed_close_handler_timeout_id", GUINT_TO_POINTER (delayed_close_handler_id)); g_signal_connect (wait->dialog, "destroy", G_CALLBACK (timed_wait_delayed_close_destroy_dialog_callback), GUINT_TO_POINTER (delayed_close_handler_id)); } else { gtk_widget_destroy (GTK_WIDGET (wait->dialog)); } } /* And the wait object itself. */ g_free (wait); } static void timed_wait_dialog_destroy_callback (GtkWidget *object, gpointer callback_data) { TimedWait *wait; wait = callback_data; g_assert (GTK_DIALOG (object) == wait->dialog); wait->dialog = NULL; /* When there's no cancel_callback, the originator will/must * call eel_timed_wait_stop which will call timed_wait_free. */ if (wait->cancel_callback != NULL) { (* wait->cancel_callback) (wait->callback_data); timed_wait_free (wait); } } static void trash_dialog_response_callback (GtkDialog *dialog, int response_id, TimedWait *wait) { gtk_widget_destroy (GTK_WIDGET (dialog)); } static gboolean timed_wait_callback (gpointer callback_data) { TimedWait *wait; GtkDialog *dialog; const char *button; wait = callback_data; /* Put up the timed wait window. */ button = wait->cancel_callback != NULL ? GTK_STOCK_CANCEL : GTK_STOCK_OK; dialog = GTK_DIALOG (gtk_message_dialog_new (wait->parent_window, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_NONE, NULL)); g_object_set (dialog, "text", wait->wait_message, "secondary-text", _("You can stop this operation by clicking cancel."), NULL); gtk_dialog_add_button (GTK_DIALOG (dialog), button, GTK_RESPONSE_OK); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); /* The contents are often very small, causing tiny little * dialogs with their titles clipped if you just let gtk * sizing do its thing. This enforces a minimum width to * make it more likely that the title won't be clipped. */ gtk_window_set_default_size (GTK_WINDOW (dialog), TIMED_WAIT_MINIMUM_DIALOG_WIDTH, -1); wait->dialog_creation_time = g_get_monotonic_time (); gtk_widget_show (GTK_WIDGET (dialog)); /* FIXME bugzilla.eazel.com 2441: * Could parent here, but it's complicated because we * don't want this window to go away just because the parent * would go away first. */ /* Make the dialog cancel the timed wait when it goes away. * Connect to "destroy" instead of "response" since we want * to be called no matter how the dialog goes away. */ g_signal_connect (dialog, "destroy", G_CALLBACK (timed_wait_dialog_destroy_callback), wait); g_signal_connect (dialog, "response", G_CALLBACK (trash_dialog_response_callback), wait); wait->timeout_handler_id = 0; wait->dialog = dialog; return FALSE; } void eel_timed_wait_start_with_duration (int duration, EelCancelCallback cancel_callback, gpointer callback_data, const char *wait_message, GtkWindow *parent_window) { TimedWait *wait; g_return_if_fail (callback_data != NULL); g_return_if_fail (wait_message != NULL); g_return_if_fail (parent_window == NULL || GTK_IS_WINDOW (parent_window)); /* Create the timed wait record. */ wait = g_new0 (TimedWait, 1); wait->wait_message = g_strdup (wait_message); wait->cancel_callback = cancel_callback; wait->callback_data = callback_data; wait->parent_window = parent_window; if (parent_window != NULL) { g_object_ref (parent_window); } /* Start the timer. */ wait->timeout_handler_id = g_timeout_add (duration, timed_wait_callback, wait); /* Put in the hash table so we can find it later. */ if (timed_wait_hash_table == NULL) { timed_wait_hash_table = g_hash_table_new (timed_wait_hash, timed_wait_hash_equal); } g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) == NULL); g_hash_table_insert (timed_wait_hash_table, wait, wait); g_assert (g_hash_table_lookup (timed_wait_hash_table, wait) == wait); } void eel_timed_wait_start (EelCancelCallback cancel_callback, gpointer callback_data, const char *wait_message, GtkWindow *parent_window) { eel_timed_wait_start_with_duration (TIMED_WAIT_STANDARD_DURATION, cancel_callback, callback_data, wait_message, parent_window); } void eel_timed_wait_stop (EelCancelCallback cancel_callback, gpointer callback_data) { TimedWait key; TimedWait *wait; g_return_if_fail (callback_data != NULL); key.cancel_callback = cancel_callback; key.callback_data = callback_data; wait = g_hash_table_lookup (timed_wait_hash_table, &key); g_return_if_fail (wait != NULL); timed_wait_free (wait); } int eel_run_simple_dialog (GtkWidget *parent, gboolean ignore_close_box, GtkMessageType message_type, const char *primary_text, const char *secondary_text, ...) { va_list button_title_args; const char *button_title; GtkWidget *dialog; GtkWidget *top_widget, *chosen_parent; int result; int response_id; /* Parent it if asked to. */ chosen_parent = NULL; if (parent != NULL) { top_widget = gtk_widget_get_toplevel (parent); if (GTK_IS_WINDOW (top_widget)) { chosen_parent = top_widget; } } /* Create the dialog. */ dialog = gtk_message_dialog_new (GTK_WINDOW (chosen_parent), 0, message_type, GTK_BUTTONS_NONE, NULL); g_object_set (dialog, "text", primary_text, "secondary-text", secondary_text, NULL); va_start (button_title_args, secondary_text); response_id = 0; while (1) { button_title = va_arg (button_title_args, const char *); if (button_title == NULL) { break; } gtk_dialog_add_button (GTK_DIALOG (dialog), button_title, response_id); gtk_dialog_set_default_response (GTK_DIALOG (dialog), response_id); response_id++; } va_end (button_title_args); /* Run it. */ gtk_widget_show (dialog); result = gtk_dialog_run (GTK_DIALOG (dialog)); while ((result == GTK_RESPONSE_NONE || result == GTK_RESPONSE_DELETE_EVENT) && ignore_close_box) { gtk_widget_show (GTK_WIDGET (dialog)); result = gtk_dialog_run (GTK_DIALOG (dialog)); } gtk_widget_destroy (dialog); return result; } static GtkDialog * create_message_dialog (const char *primary_text, const char *secondary_text, GtkMessageType type, GtkButtonsType buttons_type, GtkWindow *parent) { GtkWidget *dialog; dialog = gtk_message_dialog_new (parent, 0, type, buttons_type, NULL); g_object_set (dialog, "text", primary_text, "secondary-text", secondary_text, NULL); return GTK_DIALOG (dialog); } static GtkDialog * show_message_dialog (const char *primary_text, const char *secondary_text, GtkMessageType type, GtkButtonsType buttons_type, const char *details_text, GtkWindow *parent) { GtkDialog *dialog; dialog = create_message_dialog (primary_text, secondary_text, type, buttons_type, parent); if (details_text != NULL) { eel_gtk_message_dialog_set_details_label (GTK_MESSAGE_DIALOG (dialog), details_text); } gtk_widget_show (GTK_WIDGET (dialog)); g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); return dialog; } static GtkDialog * show_ok_dialog (const char *primary_text, const char *secondary_text, GtkMessageType type, GtkWindow *parent) { GtkDialog *dialog; dialog = show_message_dialog (primary_text, secondary_text, type, GTK_BUTTONS_OK, NULL, parent); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK); return dialog; } GtkDialog * eel_create_info_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent) { return create_message_dialog (primary_text, secondary_text, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, parent); } GtkDialog * eel_show_info_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent) { return show_ok_dialog (primary_text, secondary_text, GTK_MESSAGE_INFO, parent); } GtkDialog * eel_show_info_dialog_with_details (const char *primary_text, const char *secondary_text, const char *detailed_info, GtkWindow *parent) { GtkDialog *dialog; if (detailed_info == NULL || strcmp (primary_text, detailed_info) == 0) { return eel_show_info_dialog (primary_text, secondary_text, parent); } dialog = show_message_dialog (primary_text, secondary_text, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, detailed_info, parent); return dialog; } GtkDialog * eel_show_warning_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent) { return show_ok_dialog (primary_text, secondary_text, GTK_MESSAGE_WARNING, parent); } GtkDialog * eel_show_error_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent) { return show_ok_dialog (primary_text, secondary_text, GTK_MESSAGE_ERROR, parent); } GtkDialog * eel_show_error_dialog_with_details (const char *primary_text, const char *secondary_text, const char *detailed_error_message, GtkWindow *parent) { GtkDialog *dialog; g_return_val_if_fail (primary_text != NULL, NULL); g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL); if (detailed_error_message == NULL || strcmp (primary_text, detailed_error_message) == 0) { return eel_show_error_dialog (primary_text, secondary_text, parent); } dialog = show_message_dialog (primary_text, secondary_text, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, detailed_error_message, parent); return dialog; } /** * eel_show_yes_no_dialog: * * Create and show a dialog asking a question with two choices. * The caller needs to set up any necessary callbacks * for the buttons. Use eel_create_question_dialog instead * if any visual changes need to be made, to avoid flashiness. * @question: The text of the question. * @yes_label: The label of the "yes" button. * @no_label: The label of the "no" button. * @parent: The parent window for this dialog. */ GtkDialog * eel_show_yes_no_dialog (const char *primary_text, const char *secondary_text, const char *yes_label, const char *no_label, GtkWindow *parent) { GtkDialog *dialog = NULL; dialog = eel_create_question_dialog (primary_text, secondary_text, no_label, GTK_RESPONSE_CANCEL, yes_label, GTK_RESPONSE_YES, GTK_WINDOW (parent)); gtk_widget_show (GTK_WIDGET (dialog)); return dialog; } /** * eel_create_question_dialog: * * Create a dialog asking a question with at least two choices. * The caller needs to set up any necessary callbacks * for the buttons. The dialog is not yet shown, so that the * caller can add additional buttons or make other visual changes * without causing flashiness. * @question: The text of the question. * @answer_0: The label of the leftmost button (index 0) * @answer_1: The label of the 2nd-to-leftmost button (index 1) * @parent: The parent window for this dialog. */ GtkDialog * eel_create_question_dialog (const char *primary_text, const char *secondary_text, const char *answer_1, int response_1, const char *answer_2, int response_2, GtkWindow *parent) { GtkDialog *dialog; dialog = create_message_dialog (primary_text, secondary_text, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, parent); gtk_dialog_add_buttons (dialog, answer_1, response_1, answer_2, response_2, NULL); return dialog; } nemo-3.6.5/eel/eel-gdk-extensions.c0000664000175000017500000000453613215733314016037 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gdk-extensions.c: Graphics routines to augment what's in gdk. Copyright (C) 1999, 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler , Pavel Cisler , Ramiro Estrugo */ #include #include "eel-gdk-extensions.h" #include "eel-glib-extensions.h" #include "eel-string.h" #include #include #include #include #include EelGdkGeometryFlags eel_gdk_parse_geometry (const char *string, int *x_return, int *y_return, guint *width_return, guint *height_return) { int x11_flags; EelGdkGeometryFlags gdk_flags; g_return_val_if_fail (string != NULL, EEL_GDK_NO_VALUE); g_return_val_if_fail (x_return != NULL, EEL_GDK_NO_VALUE); g_return_val_if_fail (y_return != NULL, EEL_GDK_NO_VALUE); g_return_val_if_fail (width_return != NULL, EEL_GDK_NO_VALUE); g_return_val_if_fail (height_return != NULL, EEL_GDK_NO_VALUE); x11_flags = XParseGeometry (string, x_return, y_return, width_return, height_return); gdk_flags = EEL_GDK_NO_VALUE; if (x11_flags & XValue) { gdk_flags |= EEL_GDK_X_VALUE; } if (x11_flags & YValue) { gdk_flags |= EEL_GDK_Y_VALUE; } if (x11_flags & WidthValue) { gdk_flags |= EEL_GDK_WIDTH_VALUE; } if (x11_flags & HeightValue) { gdk_flags |= EEL_GDK_HEIGHT_VALUE; } if (x11_flags & XNegative) { gdk_flags |= EEL_GDK_X_NEGATIVE; } if (x11_flags & YNegative) { gdk_flags |= EEL_GDK_Y_NEGATIVE; } return gdk_flags; } nemo-3.6.5/eel/Makefile.am0000664000175000017500000000316213215733314014214 0ustar fabiofabioNULL= noinst_LTLIBRARIES=libeel-2.la AM_CPPFLAGS = \ -DG_LOG_DOMAIN=\"Eel\" \ -I$(top_srcdir) \ -I$(top_builddir) \ $(BASE_CFLAGS) \ $(COMMON_CFLAGS) \ $(WARN_CFLAGS) \ $(DISABLE_DEPRECATED_CFLAGS) \ -DDATADIR=\""$(datadir)"\" \ -DSOURCE_DATADIR=\""$(top_srcdir)/data"\" \ $(NULL) libeel_2_la_LDFLAGS = \ $(WARN_LDFLAGS) \ -no-undefined \ $(NULL) libeel_2_la_LIBADD = \ $(BASE_LIBS) \ $(COMMON_LIBS) \ $(RENDER_LIBS) \ -lm \ $(NULL) eel_headers = \ eel-accessibility.h \ eel-art-extensions.h \ eel-canvas.h \ eel-debug.h \ eel-editable-label.h \ eel-gdk-extensions.h \ eel-glib-extensions.h \ eel-gnome-extensions.h \ eel-graphic-effects.h \ eel-gtk-extensions.h \ eel-self-checks.h \ eel-stock-dialogs.h \ eel-string.h \ eel-vfs-extensions.h \ eel.h \ $(NULL) libeel_2_la_SOURCES = \ eel-accessibility.c \ eel-art-extensions.c \ eel-canvas.c \ eel-debug.c \ eel-editable-label.c \ eel-gdk-extensions.c \ eel-glib-extensions.c \ eel-gnome-extensions.c \ eel-graphic-effects.c \ eel-gtk-extensions.c \ eel-lib-self-check-functions.c \ eel-self-checks.c \ eel-stock-dialogs.c \ eel-string.c \ eel-vfs-extensions.c \ eel-lib-self-check-functions.h \ $(eel_headers) \ $(NULL) noinst_PROGRAMS = check-program check_program_SOURCES = check-program.c check_program_DEPENDENCIES = libeel-2.la check_program_LDADD = $(EEL_LIBS) check_program_LDFLAGS = $(WARN_LDFLAGS) $(check_program_DEPENDENCIES) -lm TESTS = check-eel EXTRA_DIST = \ check-eel \ $(NULL) nemo-3.6.5/eel/eel-string.c0000664000175000017500000005300513215733314014376 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-string.c: String routines to augment . Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #include #include "eel-string.h" #include #include #include #include #include #if !defined (EEL_OMIT_SELF_CHECK) #include "eel-lib-self-check-functions.h" #endif char * eel_str_double_underscores (const char *string) { int underscores; const char *p; char *q; char *escaped; if (string == NULL) { return NULL; } underscores = 0; for (p = string; *p != '\0'; p++) { underscores += (*p == '_'); } if (underscores == 0) { return g_strdup (string); } escaped = g_new (char, strlen (string) + underscores + 1); for (p = string, q = escaped; *p != '\0'; p++, q++) { /* Add an extra underscore. */ if (*p == '_') { *q++ = '_'; } *q = *p; } *q = '\0'; return escaped; } char * eel_str_escape_spaces (const char *string) { int spaces; const char *p; char *q; char *escaped; if (string == NULL) { return NULL; } spaces = 0; for (p = string; *p != '\0'; p++) { spaces += (*p == ' '); } if (spaces == 0) { return g_strdup (string); } escaped = g_new (char, strlen (string) + spaces + 1); for (p = string, q = escaped; *p != '\0'; p++, q++) { /* Add an extra underscore. */ if (*p == ' ') { *q++ = '\\'; } *q = *p; } *q = '\0'; return escaped; } char * eel_str_escape_quotes (const char *string) { int quotes; const char *p; char *q; char *escaped; if (string == NULL) { return NULL; } quotes = 0; for (p = string; *p != '\0'; p++) { quotes += (*p == '\'') || (*p == '\"'); } if (quotes == 0) { return g_strdup (string); } escaped = g_new (char, strlen (string) + quotes + 1); for (p = string, q = escaped; *p != '\0'; p++, q++) { if ((*p == '\'') || (*p == '\"')) { *q++ = '\\'; } *q = *p; } *q = '\0'; return escaped; } char * eel_str_capitalize (const char *string) { char *capitalized; if (string == NULL) { return NULL; } capitalized = g_strdup (string); capitalized[0] = g_ascii_toupper (capitalized[0]); return capitalized; } /* Note: eel_string_ellipsize_* that use a length in pixels * rather than characters can be found in eel_gdk_extensions.h * * FIXME bugzilla.eazel.com 5089: * we should coordinate the names of eel_string_ellipsize_* * and eel_str_*_truncate so that they match better and reflect * their different behavior. */ char * eel_str_middle_truncate (const char *string, guint truncate_length) { char *truncated; guint length; guint num_left_chars; guint num_right_chars; const char delimter[] = "..."; const guint delimter_length = strlen (delimter); const guint min_truncate_length = delimter_length + 2; if (string == NULL) { return NULL; } /* It doesnt make sense to truncate strings to less than * the size of the delimiter plus 2 characters (one on each * side) */ if (truncate_length < min_truncate_length) { return g_strdup (string); } length = g_utf8_strlen (string, -1); /* Make sure the string is not already small enough. */ if (length <= truncate_length) { return g_strdup (string); } /* Find the 'middle' where the truncation will occur. */ num_left_chars = (truncate_length - delimter_length) / 2; num_right_chars = truncate_length - num_left_chars - delimter_length; truncated = g_new (char, strlen (string) + 1); g_utf8_strncpy (truncated, string, num_left_chars); strcat (truncated, delimter); strcat (truncated, g_utf8_offset_to_pointer (string, length - num_right_chars)); return truncated; } char * eel_str_strip_substring_and_after (const char *string, const char *substring) { const char *substring_position; g_return_val_if_fail (substring != NULL, g_strdup (string)); g_return_val_if_fail (substring[0] != '\0', g_strdup (string)); if (string == NULL) { return NULL; } substring_position = strstr (string, substring); if (substring_position == NULL) { return g_strdup (string); } return g_strndup (string, substring_position - string); } char * eel_str_replace_substring (const char *string, const char *substring, const char *replacement) { int substring_length, replacement_length, result_length, remaining_length; const char *p, *substring_position; char *result, *result_position; g_return_val_if_fail (substring != NULL, g_strdup (string)); g_return_val_if_fail (substring[0] != '\0', g_strdup (string)); if (string == NULL) { return NULL; } substring_length = substring ? strlen (substring) : 0; replacement_length = replacement ? strlen (replacement) : 0; result_length = strlen (string); for (p = string; ; p = substring_position + substring_length) { substring_position = strstr (p, substring); if (substring_position == NULL) { break; } result_length += replacement_length - substring_length; } result = g_malloc (result_length + 1); result_position = result; for (p = string; ; p = substring_position + substring_length) { substring_position = strstr (p, substring); if (substring_position == NULL) { remaining_length = strlen (p); memcpy (result_position, p, remaining_length); result_position += remaining_length; break; } memcpy (result_position, p, substring_position - p); result_position += substring_position - p; memcpy (result_position, replacement, replacement_length); result_position += replacement_length; } g_assert (result_position - result == result_length); result_position[0] = '\0'; return result; } /**************** Custom printf ***********/ typedef struct { const char *start; const char *end; GString *format; int arg_pos; int width_pos; int width_format_index; int precision_pos; int precision_format_index; } ConversionInfo; enum { ARG_TYPE_INVALID, ARG_TYPE_INT, ARG_TYPE_LONG, ARG_TYPE_LONG_LONG, ARG_TYPE_SIZE, ARG_TYPE_LONG_DOUBLE, ARG_TYPE_DOUBLE, ARG_TYPE_POINTER }; typedef int ArgType; /* An int, because custom are < 0 */ static const char * get_position (const char *format, int *i) { const char *p; p = format; if (g_ascii_isdigit (*p)) { p++; while (g_ascii_isdigit (*p)) { p++; } if (*p == '$') { if (i != NULL) { *i = atoi (format) - 1; } return p + 1; } } return format; } static gboolean is_flag (char c) { return strchr ("#0- +'I", c) != NULL; } static gboolean is_length_modifier (char c) { return strchr ("hlLjzt", c) != NULL; } static ArgType get_arg_type_from_format (EelPrintfHandler *custom_handlers, const char *format, int len) { int i; char c; c = format[len-1]; if (custom_handlers != NULL) { for (i = 0; custom_handlers[i].character != 0; i++) { if (custom_handlers[i].character == c) { return -(i + 1); } } } switch (c) { case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': if (g_str_has_prefix (format, "ll")) { return ARG_TYPE_LONG_LONG; } if (g_str_has_prefix (format, "l")) { return ARG_TYPE_LONG; } if (g_str_has_prefix (format, "l")) { return ARG_TYPE_LONG; } if (g_str_has_prefix (format, "z")) { return ARG_TYPE_SIZE; } return ARG_TYPE_INT; case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': case 'a': case 'A': if (g_str_has_prefix (format, "L")) { return ARG_TYPE_LONG_DOUBLE; } return ARG_TYPE_DOUBLE; case 'c': return ARG_TYPE_INT; case 's': case 'p': case 'n': return ARG_TYPE_POINTER; } return ARG_TYPE_INVALID; } static void skip_argv (va_list *va, ArgType type, EelPrintfHandler *custom_handlers) { if (type < 0) { custom_handlers[-type - 1].skip (va); return; } switch (type) { default: case ARG_TYPE_INVALID: return; case ARG_TYPE_INT: (void) va_arg (*va, int); break; case ARG_TYPE_LONG: (void) va_arg (*va, long int); break; case ARG_TYPE_LONG_LONG: (void) va_arg (*va, long long int); break; case ARG_TYPE_SIZE: (void) va_arg (*va, gsize); break; case ARG_TYPE_LONG_DOUBLE: (void) va_arg (*va, long double); break; case ARG_TYPE_DOUBLE: (void) va_arg (*va, double); break; case ARG_TYPE_POINTER: (void) va_arg (*va, void *); break; } } static void skip_to_arg (va_list *va, ArgType *types, EelPrintfHandler *custom_handlers, int n) { int i; for (i = 0; i < n; i++) { skip_argv (va, types[i], custom_handlers); } } char * eel_strdup_vprintf_with_custom (EelPrintfHandler *custom, const char *format, va_list va_orig) { va_list va; const char *p; int num_args, i, j; ArgType *args; ArgType type; ConversionInfo *conversions; GString *f, *str; const char *flags, *width, *prec, *mod, *pos; char *s; num_args = 0; for (p = format; *p != 0; p++) { if (*p == '%') { p++; if (*p != '%') { num_args++; } } } args = g_new0 (ArgType, num_args * 3 + 1); conversions = g_new0 (ConversionInfo, num_args); /* i indexes conversions, j indexes args */ i = 0; j = 0; p = format; while (*p != 0) { if (*p != '%') { p++; continue; } p++; if (*p == '%') { p++; continue; } /* We got a real conversion: */ f = g_string_new ("%"); conversions[i].start = p - 1; /* First comes the positional arg */ pos = p; p = get_position (p, NULL); /* Then flags */ flags = p; while (is_flag (*p)) { p++; } g_string_append_len (f, flags, p - flags); /* Field width */ if (*p == '*') { p++; p = get_position (p, &j); args[j] = ARG_TYPE_INT; conversions[i].width_pos = j++; conversions[i].width_format_index = f->len; } else { conversions[i].width_pos = -1; conversions[i].width_format_index = -1; width = p; while (g_ascii_isdigit (*p)) { p++; } g_string_append_len (f, width, p - width); } /* Precision */ conversions[i].precision_pos = -1; conversions[i].precision_format_index = -1; if (*p == '.') { g_string_append_c (f, '.'); p++; if (*p == '*') { p++; p = get_position (p, &j); args[j] = ARG_TYPE_INT; conversions[i].precision_pos = j++; conversions[i].precision_format_index = f->len; } else { prec = p; while (g_ascii_isdigit (*p) || *p == '-') { p++; } g_string_append_len (f, prec, p - prec); } } /* length modifier */ mod = p; while (is_length_modifier (*p)) { p++; } /* conversion specifier */ if (*p != 0) p++; g_string_append_len (f, mod, p - mod); get_position (pos, &j); args[j] = get_arg_type_from_format (custom, mod, p - mod); conversions[i].arg_pos = j++; conversions[i].format = f; conversions[i].end = p; i++; } g_assert (i == num_args); str = g_string_new (""); p = format; for (i = 0; i < num_args; i++) { g_string_append_len (str, p, conversions[i].start - p); p = conversions[i].end; if (conversions[i].precision_pos != -1) { char *val; G_VA_COPY(va, va_orig); skip_to_arg (&va, args, custom, conversions[i].precision_pos); val = g_strdup_vprintf ("%d", va); va_end (va); g_string_insert (conversions[i].format, conversions[i].precision_format_index, val); g_free (val); } if (conversions[i].width_pos != -1) { char *val; G_VA_COPY(va, va_orig); skip_to_arg (&va, args, custom, conversions[i].width_pos); val = g_strdup_vprintf ("%d", va); va_end (va); g_string_insert (conversions[i].format, conversions[i].width_format_index, val); g_free (val); } G_VA_COPY(va, va_orig); skip_to_arg (&va, args, custom, conversions[i].arg_pos); type = args[conversions[i].arg_pos]; if (type < 0) { s = custom[-type - 1].to_string (conversions[i].format->str, va); g_string_append (str, s); g_free (s); } else{ g_string_append_vprintf (str, conversions[i].format->str, va); } va_end (va); g_string_free (conversions[i].format, TRUE); } g_string_append (str, p); g_free (args); g_free (conversions); return g_string_free (str, FALSE); } char * eel_strdup_printf_with_custom (EelPrintfHandler *handlers, const char *format, ...) { va_list va; char *res; va_start (va, format); res = eel_strdup_vprintf_with_custom (handlers, format, va); va_end (va); return res; } /*********** refcounted strings ****************/ G_LOCK_DEFINE_STATIC (unique_ref_strs); static GHashTable *unique_ref_strs = NULL; static eel_ref_str eel_ref_str_new_internal (const char *string, int start_count) { char *res; volatile gint *count; gsize len; len = strlen (string); res = g_malloc (sizeof (gint) + len + 1); count = (volatile gint *)res; *count = start_count; res += sizeof(gint); memcpy (res, string, len + 1); return res; } eel_ref_str eel_ref_str_new (const char *string) { if (string == NULL) { return NULL; } return eel_ref_str_new_internal (string, 1); } eel_ref_str eel_ref_str_get_unique (const char *string) { eel_ref_str res; if (string == NULL) { return NULL; } G_LOCK (unique_ref_strs); if (unique_ref_strs == NULL) { unique_ref_strs = g_hash_table_new (g_str_hash, g_str_equal); } res = g_hash_table_lookup (unique_ref_strs, string); if (res != NULL) { eel_ref_str_ref (res); } else { res = eel_ref_str_new_internal (string, 0x80000001); g_hash_table_insert (unique_ref_strs, res, res); } G_UNLOCK (unique_ref_strs); return res; } eel_ref_str eel_ref_str_ref (eel_ref_str str) { volatile gint *count; count = (volatile gint *)((char *)str - sizeof (gint)); g_atomic_int_add (count, 1); return str; } void eel_ref_str_unref (eel_ref_str str) { volatile gint *count; gint old_ref; if (str == NULL) return; count = (volatile gint *)((char *)str - sizeof (gint)); retry_atomic_decrement: old_ref = g_atomic_int_get (count); if (old_ref == 1) { g_free ((char *)count); } else if (old_ref == 0x80000001) { G_LOCK (unique_ref_strs); /* Need to recheck after taking lock to avoid races with _get_unique() */ if (g_atomic_int_add (count, -1) == 0x80000001) { g_hash_table_remove (unique_ref_strs, (char *)str); g_free ((char *)count); } G_UNLOCK (unique_ref_strs); } else if (!g_atomic_int_compare_and_exchange (count, old_ref, old_ref - 1)) { goto retry_atomic_decrement; } } #if !defined (EEL_OMIT_SELF_CHECK) static void verify_printf (const char *format, ...) { va_list va; char *orig, *new; va_start (va, format); orig = g_strdup_vprintf (format, va); va_end (va); va_start (va, format); new = eel_strdup_vprintf_with_custom (NULL, format, va); va_end (va); EEL_CHECK_STRING_RESULT (new, orig); g_free (orig); } static char * custom1_to_string (char *format, va_list va) { int i; i = va_arg (va, int); return g_strdup_printf ("c1-%d-", i); } static void custom1_skip (va_list *va) { (void) va_arg (*va, int); } static char * custom2_to_string (char *format, va_list va) { char *s; s = va_arg (va, char *); return g_strdup_printf ("c2-%s-", s); } static void custom2_skip (va_list *va) { (void) va_arg (*va, char *); } static EelPrintfHandler handlers[] = { { 'N', custom1_to_string, custom1_skip }, { 'Y', custom2_to_string, custom2_skip }, { 0 } }; static void verify_custom (const char *orig, const char *format, ...) { char *new; va_list va; va_start (va, format); new = eel_strdup_vprintf_with_custom (handlers, format, va); va_end (va); EEL_CHECK_STRING_RESULT (new, orig); } void eel_self_check_string (void) { EEL_CHECK_STRING_RESULT (eel_str_double_underscores (NULL), NULL); EEL_CHECK_STRING_RESULT (eel_str_double_underscores (""), ""); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_"), "__"); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo"), "foo"); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar"), "foo__bar"); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_bar_2"), "foo__bar__2"); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("_foo"), "__foo"); EEL_CHECK_STRING_RESULT (eel_str_double_underscores ("foo_"), "foo__"); EEL_CHECK_STRING_RESULT (eel_str_capitalize (NULL), NULL); EEL_CHECK_STRING_RESULT (eel_str_capitalize (""), ""); EEL_CHECK_STRING_RESULT (eel_str_capitalize ("foo"), "Foo"); EEL_CHECK_STRING_RESULT (eel_str_capitalize ("Foo"), "Foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 0), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 1), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 3), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 4), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 5), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 6), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("foo", 7), "foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 0), "a_much_longer_foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 1), "a_much_longer_foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 2), "a_much_longer_foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 3), "a_much_longer_foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 4), "a_much_longer_foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 5), "a...o"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 6), "a...oo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 7), "a_...oo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 8), "a_...foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("a_much_longer_foo", 9), "a_m...foo"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 8), "so...ven"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 8), "so...odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 9), "som...ven"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 9), "som...odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 10), "som...even"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 10), "som..._odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 11), "some...even"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 11), "some..._odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 12), "some..._even"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 12), "some...g_odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 13), "somet..._even"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_even", 14), "something_even"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("something_odd", 13), "something_odd"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("ääääääääää", 5), "ä...ä"); EEL_CHECK_STRING_RESULT (eel_str_middle_truncate ("ã‚ãƒã„ã…ã†ã‡ãˆã‰", 7), "ã‚ãƒ...ãˆã‰"); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after (NULL, "bar"), NULL); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("", "bar"), ""); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo", "bar"), "foo"); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar", "bar"), "foo "); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("foo bar xxx", "bar"), "foo "); EEL_CHECK_STRING_RESULT (eel_str_strip_substring_and_after ("bar", "bar"), ""); EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", NULL), NULL); EEL_CHECK_STRING_RESULT (eel_str_replace_substring (NULL, "foo", "bar"), NULL); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", NULL), "bar"); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", ""), ""); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("", "foo", "bar"), ""); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("bar", "foo", ""), "bar"); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("xxx", "x", "foo"), "foofoofoo"); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("fff", "f", "foo"), "foofoofoo"); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "foo", "f"), "fff"); EEL_CHECK_STRING_RESULT (eel_str_replace_substring ("foofoofoo", "f", ""), "oooooo"); verify_printf ("%.*s", 2, "foo"); verify_printf ("%*.*s", 2, 4, "foo"); verify_printf ("before %5$*1$.*2$s between %6$*3$.*4$d after", 4, 5, 6, 7, "foo", G_PI); verify_custom ("c1-42- c2-foo-","%N %Y", 42 ,"foo"); verify_custom ("c1-42- bar c2-foo-","%N %s %Y", 42, "bar" ,"foo"); verify_custom ("c1-42- bar c2-foo-","%3$N %2$s %1$Y","foo", "bar", 42); } #endif /* !EEL_OMIT_SELF_CHECK */ nemo-3.6.5/eel/eel-string.h0000664000175000017500000000606013215733314014402 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-string.h: String routines to augment . Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #ifndef EEL_STRING_H #define EEL_STRING_H #include #include #include /* We use the "str" abbrevation to mean char * string, since * "string" usually means g_string instead. We use the "istr" * abbreviation to mean a case-insensitive char *. */ #define THOU_TO_STR(c) g_strdup_printf ("%'d", c); /* NULL is allowed for all the str parameters to these functions. */ /* Escape function for '_' character. */ char * eel_str_double_underscores (const char *str); /* Escape function for spaces */ char * eel_str_escape_spaces (const char *str); /* Escape function for quotes */ char * eel_str_escape_quotes (const char *str); /* Capitalize a string */ char * eel_str_capitalize (const char *str); /* Middle truncate a string to a maximum of truncate_length characters. * The resulting string will be truncated in the middle with a "..." * delimiter. */ char * eel_str_middle_truncate (const char *str, guint truncate_length); /* Remove all characters after the passed-in substring. */ char * eel_str_strip_substring_and_after (const char *str, const char *substring); /* Replace all occurrences of substring with replacement. */ char * eel_str_replace_substring (const char *str, const char *substring, const char *replacement); typedef char * eel_ref_str; eel_ref_str eel_ref_str_new (const char *string); eel_ref_str eel_ref_str_get_unique (const char *string); eel_ref_str eel_ref_str_ref (eel_ref_str str); void eel_ref_str_unref (eel_ref_str str); #define eel_ref_str_peek(__str) ((const char *)(__str)) typedef struct { char character; char *(*to_string) (char *format, va_list va); void (*skip) (va_list *va); } EelPrintfHandler; char *eel_strdup_printf_with_custom (EelPrintfHandler *handlers, const char *format, ...); char *eel_strdup_vprintf_with_custom (EelPrintfHandler *custom, const char *format, va_list va); #endif /* EEL_STRING_H */ nemo-3.6.5/eel/eel-canvas.h0000664000175000017500000004533513215733314014357 0ustar fabiofabio/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */ /* * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation * All rights reserved. * * This file is part of the Gnome Library. * * The Gnome Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * The Gnome Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with the Gnome Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, * Boston, MA 02110-1335, USA. */ /* @NOTATION@ */ /* EelCanvas widget - Tk-like canvas widget for Gnome * * EelCanvas is basically a port of the Tk toolkit's most excellent canvas * widget. Tk is copyrighted by the Regents of the University of California, * Sun Microsystems, and other parties. * * * Authors: Federico Mena * Raph Levien */ #ifndef EEL_CANVAS_H #define EEL_CANVAS_H #include #include #include G_BEGIN_DECLS /* "Small" value used by canvas stuff */ #define EEL_CANVAS_EPSILON 1e-10 /* Macros for building colors that fit in a 32-bit integer. The values are in * [0, 255]. */ #define EEL_CANVAS_COLOR(r, g, b) ((((int) (r) & 0xff) << 24) \ | (((int) (g) & 0xff) << 16) \ | (((int) (b) & 0xff) << 8) \ | 0xff) #define EEL_CANVAS_COLOR_A(r, g, b, a) ((((int) (r) & 0xff) << 24) \ | (((int) (g) & 0xff) << 16) \ | (((int) (b) & 0xff) << 8) \ | ((int) (a) & 0xff)) typedef struct _EelCanvas EelCanvas; typedef struct _EelCanvasClass EelCanvasClass; typedef struct _EelCanvasItem EelCanvasItem; typedef struct _EelCanvasItemClass EelCanvasItemClass; typedef struct _EelCanvasGroup EelCanvasGroup; typedef struct _EelCanvasGroupClass EelCanvasGroupClass; /* EelCanvasItem - base item class for canvas items * * All canvas items are derived from EelCanvasItem. The only information a * EelCanvasItem contains is its parent canvas, its parent canvas item group, * and its bounding box in world coordinates. * * Items inside a canvas are organized in a tree of EelCanvasItemGroup nodes * and EelCanvasItem leaves. Each canvas has a single root group, which can * be obtained with the eel_canvas_get_root() function. * * The abstract EelCanvasItem class does not have any configurable or * queryable attributes. */ /* Object flags for items */ enum { EEL_CANVAS_ITEM_REALIZED = 1 << 4, EEL_CANVAS_ITEM_MAPPED = 1 << 5, EEL_CANVAS_ITEM_ALWAYS_REDRAW = 1 << 6, EEL_CANVAS_ITEM_VISIBLE = 1 << 7, EEL_CANVAS_ITEM_NEED_UPDATE = 1 << 8, EEL_CANVAS_ITEM_NEED_DEEP_UPDATE = 1 << 9 }; /* Update flags for items */ enum { EEL_CANVAS_UPDATE_REQUESTED = 1 << 0, EEL_CANVAS_UPDATE_DEEP = 1 << 1 }; #define EEL_TYPE_CANVAS_ITEM (eel_canvas_item_get_type ()) #define EEL_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_ITEM, EelCanvasItem)) #define EEL_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_ITEM, EelCanvasItemClass)) #define EEL_IS_CANVAS_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_ITEM)) #define EEL_IS_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_ITEM)) #define EEL_CANVAS_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_ITEM, EelCanvasItemClass)) struct _EelCanvasItem { GInitiallyUnowned object; /* Parent canvas for this item */ EelCanvas *canvas; /* Parent canvas group for this item (a EelCanvasGroup) */ EelCanvasItem *parent; /* Bounding box for this item (in canvas coordinates) */ double x1, y1, x2, y2; /* Object flags */ guint flags; }; struct _EelCanvasItemClass { GInitiallyUnownedClass parent_class; void (* destroy) (EelCanvasItem *item); /* Tell the item to update itself. The flags are from the update flags * defined above. The item should update its internal state from its * queued state, and recompute and request its repaint area. The * update method also recomputes the bounding box of the item. */ void (* update) (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags); /* Realize an item -- create GCs, etc. */ void (* realize) (EelCanvasItem *item); /* Unrealize an item */ void (* unrealize) (EelCanvasItem *item); /* Map an item - normally only need by items with their own GdkWindows */ void (* map) (EelCanvasItem *item); /* Unmap an item */ void (* unmap) (EelCanvasItem *item); /* Draw an item of this type. (x, y) are the upper-left canvas pixel * coordinates of the drawable, a temporary pixmap, where things get * drawn. (width, height) are the dimensions of the drawable. */ void (* draw) (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region); /* Calculate the distance from an item to the specified point. It also * returns a canvas item which is the item itself in the case of the * object being an actual leaf item, or a child in case of the object * being a canvas group. (cx, cy) are the canvas pixel coordinates that * correspond to the item-relative coordinates (x, y). */ double (* point) (EelCanvasItem *item, double x, double y, int cx, int cy, EelCanvasItem **actual_item); void (* translate) (EelCanvasItem *item, double dx, double dy); /* Fetch the item's bounding box (need not be exactly tight). This * should be in item-relative coordinates. */ void (* bounds) (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2); /* Signal: an event ocurred for an item of this type. The (x, y) * coordinates are in the canvas world coordinate system. */ gboolean (* event) (EelCanvasItem *item, GdkEvent *event); /* Reserved for future expansion */ gpointer spare_vmethods [4]; }; /* Standard Gtk function */ GType eel_canvas_item_get_type (void) G_GNUC_CONST; /* Create a canvas item using the standard Gtk argument mechanism. The item is * automatically inserted at the top of the specified canvas group. The last * argument must be a NULL pointer. */ EelCanvasItem *eel_canvas_item_new (EelCanvasGroup *parent, GType type, const gchar *first_arg_name, ...); void eel_canvas_item_destroy (EelCanvasItem *item); /* Constructors for use in derived classes and language wrappers */ void eel_canvas_item_construct (EelCanvasItem *item, EelCanvasGroup *parent, const gchar *first_arg_name, va_list args); /* Configure an item using the standard Gtk argument mechanism. The last * argument must be a NULL pointer. */ void eel_canvas_item_set (EelCanvasItem *item, const gchar *first_arg_name, ...); /* Used only for language wrappers and the like */ void eel_canvas_item_set_valist (EelCanvasItem *item, const gchar *first_arg_name, va_list args); /* Move an item by the specified amount */ void eel_canvas_item_move (EelCanvasItem *item, double dx, double dy); /* Raise an item in the z-order of its parent group by the specified number of * positions. */ void eel_canvas_item_raise (EelCanvasItem *item, int positions); /* Lower an item in the z-order of its parent group by the specified number of * positions. */ void eel_canvas_item_lower (EelCanvasItem *item, int positions); /* Raise an item to the top of its parent group's z-order. */ void eel_canvas_item_raise_to_top (EelCanvasItem *item); /* Lower an item to the bottom of its parent group's z-order */ void eel_canvas_item_lower_to_bottom (EelCanvasItem *item); /* Send an item behind another item */ void eel_canvas_item_send_behind (EelCanvasItem *item, EelCanvasItem *behind_item); /* Show an item (make it visible). If the item is already shown, it has no * effect. */ void eel_canvas_item_show (EelCanvasItem *item); /* Hide an item (make it invisible). If the item is already invisible, it has * no effect. */ void eel_canvas_item_hide (EelCanvasItem *item); /* Grab the mouse for the specified item. Only the events in event_mask will be * reported. If cursor is non-NULL, it will be used during the duration of the * grab. Time is a proper X event time parameter. Returns the same values as * XGrabPointer(). */ GdkGrabStatus eel_canvas_item_grab (EelCanvasItem *item, GdkEventMask event_mask, GdkCursor *cursor, guint32 etime); /* Ungrabs the mouse -- the specified item must be the same that was passed to * eel_canvas_item_grab(). Time is a proper X event time parameter. */ void eel_canvas_item_ungrab (EelCanvasItem *item, guint32 etime); /* These functions convert from a coordinate system to another. "w" is world * coordinates and "i" is item coordinates. */ void eel_canvas_item_w2i (EelCanvasItem *item, double *x, double *y); void eel_canvas_item_i2w (EelCanvasItem *item, double *x, double *y); /* Remove the item from its parent group and make the new group its parent. The * item will be put on top of all the items in the new group. The item's * coordinates relative to its new parent to *not* change -- this means that the * item could potentially move on the screen. * * The item and the group must be in the same canvas. An item cannot be * reparented to a group that is the item itself or that is an inferior of the * item. */ void eel_canvas_item_reparent (EelCanvasItem *item, EelCanvasGroup *new_group); /* Used to send all of the keystroke events to a specific item as well as * GDK_FOCUS_CHANGE events. */ void eel_canvas_item_grab_focus (EelCanvasItem *item); /* Fetch the bounding box of the item. The bounding box may not be exactly * tight, but the canvas items will do the best they can. The returned bounding * box is in the coordinate system of the item's parent. */ void eel_canvas_item_get_bounds (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2); /* Request that the update method eventually get called. This should be used * only by item implementations. */ void eel_canvas_item_request_update (EelCanvasItem *item); /* Request a redraw of the bounding box of the canvas item */ void eel_canvas_item_request_redraw (EelCanvasItem *item); /* EelCanvasGroup - a group of canvas items * * A group is a node in the hierarchical tree of groups/items inside a canvas. * Groups serve to give a logical structure to the items. * * Consider a circuit editor application that uses the canvas for its schematic * display. Hierarchically, there would be canvas groups that contain all the * components needed for an "adder", for example -- this includes some logic * gates as well as wires. You can move stuff around in a convenient way by * doing a eel_canvas_item_move() of the hierarchical groups -- to move an * adder, simply move the group that represents the adder. * * The following arguments are available: * * name type read/write description * -------------------------------------------------------------------------------- * x double RW X coordinate of group's origin * y double RW Y coordinate of group's origin */ #define EEL_TYPE_CANVAS_GROUP (eel_canvas_group_get_type ()) #define EEL_CANVAS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_GROUP, EelCanvasGroup)) #define EEL_CANVAS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_GROUP, EelCanvasGroupClass)) #define EEL_IS_CANVAS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_GROUP)) #define EEL_IS_CANVAS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_GROUP)) #define EEL_CANVAS_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_GROUP, EelCanvasGroupClass)) struct _EelCanvasGroup { EelCanvasItem item; double xpos, ypos; /* Children of the group */ GList *item_list; GList *item_list_end; }; struct _EelCanvasGroupClass { EelCanvasItemClass parent_class; }; /* Standard Gtk function */ GType eel_canvas_group_get_type (void) G_GNUC_CONST; /*** EelCanvas ***/ #define EEL_TYPE_CANVAS (eel_canvas_get_type ()) #define EEL_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS, EelCanvas)) #define EEL_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS, EelCanvasClass)) #define EEL_IS_CANVAS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS)) #define EEL_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS)) #define EEL_CANVAS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS, EelCanvasClass)) struct _EelCanvas { GtkLayout layout; /* Root canvas group */ EelCanvasItem *root; /* The item containing the mouse pointer, or NULL if none */ EelCanvasItem *current_item; /* Item that is about to become current (used to track deletions and such) */ EelCanvasItem *new_current_item; /* Item that holds a pointer grab, or NULL if none */ EelCanvasItem *grabbed_item; /* If non-NULL, the currently focused item */ EelCanvasItem *focused_item; /* Event on which selection of current item is based */ GdkEvent pick_event; /* Scrolling region */ double scroll_x1, scroll_y1; double scroll_x2, scroll_y2; /* Scaling factor to be used for display */ double pixels_per_unit; /* Idle handler ID */ guint idle_id; /* Signal handler ID for destruction of the root item */ guint root_destroy_id; /* Internal pixel offsets when zoomed out */ int zoom_xofs, zoom_yofs; /* Last known modifier state, for deferred repick when a button is down */ int state; /* Event mask specified when grabbing an item */ guint grabbed_event_mask; /* Tolerance distance for picking items */ int close_enough; /* Whether the canvas should center the canvas in the middle of * the window if the scroll region is smaller than the window */ unsigned int center_scroll_region : 1; /* Whether items need update at next idle loop iteration */ unsigned int need_update : 1; /* Are we in the midst of an update */ unsigned int doing_update : 1; /* Whether the canvas needs redrawing at the next idle loop iteration */ unsigned int need_redraw : 1; /* Whether current item will be repicked at next idle loop iteration */ unsigned int need_repick : 1; /* For use by internal pick_current_item() function */ unsigned int left_grabbed_item : 1; /* For use by internal pick_current_item() function */ unsigned int in_repick : 1; }; struct _EelCanvasClass { GtkLayoutClass parent_class; /* Draw the background for the area given. */ void (* draw_background) (EelCanvas *canvas, cairo_t *cr); /* Private Virtual methods for groping the canvas inside bonobo */ void (* request_update) (EelCanvas *canvas); /* Reserved for future expansion */ gpointer spare_vmethods [4]; }; /* Standard Gtk function */ GType eel_canvas_get_type (void) G_GNUC_CONST; /* Creates a new canvas. You should check that the canvas is created with the * proper visual and colormap. Any visual will do unless you intend to insert * gdk_imlib images into it, in which case you should use the gdk_imlib visual. * * You should call eel_canvas_set_scroll_region() soon after calling this * function to set the desired scrolling limits for the canvas. */ GtkWidget *eel_canvas_new (void); /* Returns the root canvas item group of the canvas */ EelCanvasGroup *eel_canvas_root (EelCanvas *canvas); /* Sets the limits of the scrolling region, in world coordinates */ void eel_canvas_set_scroll_region (EelCanvas *canvas, double x1, double y1, double x2, double y2); /* Gets the limits of the scrolling region, in world coordinates */ void eel_canvas_get_scroll_region (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2); /* Sets the number of pixels that correspond to one unit in world coordinates */ void eel_canvas_set_pixels_per_unit (EelCanvas *canvas, double n); /* Wether the canvas centers the scroll region if it is smaller than the window */ void eel_canvas_set_center_scroll_region (EelCanvas *canvas, gboolean center_scroll_region); /* Scrolls the canvas to the specified offsets, given in canvas pixel coordinates */ void eel_canvas_scroll_to (EelCanvas *canvas, int cx, int cy); /* Returns the scroll offsets of the canvas in canvas pixel coordinates. You * can specify NULL for any of the values, in which case that value will not be * queried. */ void eel_canvas_get_scroll_offsets (EelCanvas *canvas, int *cx, int *cy); /* Requests that the canvas be repainted immediately instead of in the idle * loop. */ void eel_canvas_update_now (EelCanvas *canvas); /* Returns the item that is at the specified position in world coordinates, or * NULL if no item is there. */ EelCanvasItem *eel_canvas_get_item_at (EelCanvas *canvas, double x, double y); /* For use only by item type implementations. Request that the canvas * eventually redraw the specified region, specified in canvas pixel * coordinates. The region contains (x1, y1) but not (x2, y2). */ void eel_canvas_request_redraw (EelCanvas *canvas, int x1, int y1, int x2, int y2); /* These functions convert from a coordinate system to another. "w" is world * coordinates, "c" is canvas pixel coordinates (pixel coordinates that are * (0,0) for the upper-left scrolling limit and something else for the * lower-left scrolling limit). */ void eel_canvas_w2c_rect_d (EelCanvas *canvas, double *x1, double *y1, double *x2, double *y2); void eel_canvas_w2c (EelCanvas *canvas, double wx, double wy, int *cx, int *cy); void eel_canvas_w2c_d (EelCanvas *canvas, double wx, double wy, double *cx, double *cy); void eel_canvas_c2w (EelCanvas *canvas, int cx, int cy, double *wx, double *wy); /* This function takes in coordinates relative to the GTK_LAYOUT * (canvas)->bin_window and converts them to world coordinates. * These days canvas coordinates and window coordinates are the same, but * these are left for backwards compat reasons. */ void eel_canvas_window_to_world (EelCanvas *canvas, double winx, double winy, double *worldx, double *worldy); /* This is the inverse of eel_canvas_window_to_world() */ void eel_canvas_world_to_window (EelCanvas *canvas, double worldx, double worldy, double *winx, double *winy); /* Accessible implementation */ GType eel_canvas_accessible_get_type(void); typedef struct _EelCanvasAccessible EelCanvasAccessible; struct _EelCanvasAccessible { GtkAccessible parent; }; typedef struct _EelCanvasAccessibleClass EelCanvasAccessibleClass; struct _EelCanvasAccessibleClass { GtkAccessibleClass parent_class; }; G_END_DECLS #endif nemo-3.6.5/eel/eel-gnome-extensions.h0000664000175000017500000000274313215733314016402 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-gnome-extensions.h - interface for new functions that operate on gnome classes. Perhaps some of these should be rolled into gnome someday. Copyright (C) 1999, 2000, 2001 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #ifndef EEL_GNOME_EXTENSIONS_H #define EEL_GNOME_EXTENSIONS_H #include /* Open up a new terminal, optionally passing in a command to execute */ void eel_gnome_open_terminal_on_screen (const char *command, GdkScreen *screen); #endif /* EEL_GNOME_EXTENSIONS_H */ nemo-3.6.5/eel/eel-self-checks.c0000664000175000017500000001020713215733314015254 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-self-checks.c: The self-check framework. Copyright (C) 1999 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include #if ! defined (EEL_OMIT_SELF_CHECK) #include "eel-self-checks.h" #include #include #include static gboolean failed; static const char *current_expression; static const char *current_file_name; static int current_line_number; void eel_exit_if_self_checks_failed (void) { if (!failed) { return; } printf ("\n"); exit (EXIT_FAILURE); } void eel_report_check_failure (char *result, char *expected) { if (!failed) { fprintf (stderr, "\n"); } fprintf (stderr, "FAIL: check failed in %s, line %d\n", current_file_name, current_line_number); fprintf (stderr, " evaluated: %s\n", current_expression); fprintf (stderr, " expected: %s\n", expected == NULL ? "NULL" : expected); fprintf (stderr, " got: %s\n", result == NULL ? "NULL" : result); failed = TRUE; g_free (result); g_free (expected); } static char * eel_strdup_boolean (gboolean boolean) { if (boolean == FALSE) { return g_strdup ("FALSE"); } if (boolean == TRUE) { return g_strdup ("TRUE"); } return g_strdup_printf ("gboolean(%d)", boolean); } void eel_before_check (const char *expression, const char *file_name, int line_number) { current_expression = expression; current_file_name = file_name; current_line_number = line_number; } void eel_after_check (void) { /* It would be good to check here if there was a memory leak. */ } void eel_check_boolean_result (gboolean result, gboolean expected) { if (result != expected) { eel_report_check_failure (eel_strdup_boolean (result), eel_strdup_boolean (expected)); } eel_after_check (); } void eel_check_rectangle_result (EelIRect result, int expected_x0, int expected_y0, int expected_x1, int expected_y1) { if (result.x0 != expected_x0 || result.y0 != expected_y0 || result.x1 != expected_x1 || result.y1 != expected_y1) { eel_report_check_failure (g_strdup_printf ("x0=%d, y0=%d, x1=%d, y1=%d", result.x0, result.y0, result.x1, result.y1), g_strdup_printf ("x0=%d, y0=%d, x1=%d, y1=%d", expected_x0, expected_y0, expected_x1, expected_y1)); } eel_after_check (); } void eel_check_integer_result (long result, long expected) { if (result != expected) { eel_report_check_failure (g_strdup_printf ("%ld", result), g_strdup_printf ("%ld", expected)); } eel_after_check (); } void eel_check_double_result (double result, double expected) { if (result != expected) { eel_report_check_failure (g_strdup_printf ("%f", result), g_strdup_printf ("%f", expected)); } eel_after_check (); } void eel_check_string_result (char *result, const char *expected) { gboolean match; /* Stricter than eel_strcmp. * NULL does not match "" in this test. */ if (expected == NULL) { match = result == NULL; } else { match = result != NULL && strcmp (result, expected) == 0; } if (!match) { eel_report_check_failure (result, g_strdup (expected)); } else { g_free (result); } eel_after_check (); } void eel_before_check_function (const char *name) { fprintf (stderr, "running %s\n", name); } void eel_after_check_function (void) { } #endif /* ! EEL_OMIT_SELF_CHECK */ nemo-3.6.5/eel/eel-lib-self-check-functions.h0000664000175000017500000000342313215733314017652 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- eel-lib-self-check-functions.h: Wrapper and prototypes for all self-check functions in libeel. Copyright (C) 2000 Eazel, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Author: Darin Adler */ #include "eel-self-checks.h" void eel_run_lib_self_checks (void); /* Putting the prototypes for these self-check functions in each header file for the files they are defined in would make compiling the self-check framework take way too long (since one file would have to include everything). So we put the list of functions here instead. Instead of just putting prototypes here, we put this macro that can be used to do operations on the whole list of functions. */ #define EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION(macro) \ macro (eel_self_check_glib_extensions) \ macro (eel_self_check_string) \ /* Add new self-check functions to the list above this line. */ /* Generate prototypes for all the functions. */ EEL_LIB_FOR_EACH_SELF_CHECK_FUNCTION (EEL_SELF_CHECK_FUNCTION_PROTOTYPE) nemo-3.6.5/eel/eel-stock-dialogs.h0000664000175000017500000001006213215733314015634 0ustar fabiofabio/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* eel-stock-dialogs.h: Various standard dialogs for Eel. Copyright (C) 2000 Eazel, Inc. The Gnome Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The Gnome Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the Gnome Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500, Boston, MA 02110-1335, USA. Authors: Darin Adler */ #ifndef EEL_STOCK_DIALOGS_H #define EEL_STOCK_DIALOGS_H #include typedef void (* EelCancelCallback) (gpointer callback_data); /* Dialog for cancelling something that normally is fast enough not to need a dialog. */ void eel_timed_wait_start (EelCancelCallback cancel_callback, gpointer callback_data, const char *wait_message, GtkWindow *parent_window); void eel_timed_wait_start_with_duration (int duration, EelCancelCallback cancel_callback, gpointer callback_data, const char *wait_message, GtkWindow *parent_window); void eel_timed_wait_stop (EelCancelCallback cancel_callback, gpointer callback_data); /* Basic dialog with buttons. */ int eel_run_simple_dialog (GtkWidget *parent, gboolean ignore_close_box, GtkMessageType message_type, const char *primary_text, const char *secondary_text, ...); /* Variations on gnome stock dialogs; these do line wrapping, we don't * bother with non-parented versions, we allow setting the title, * primary, and secondary messages, and we return GtkDialog pointers * instead of GtkWidget pointers. */ GtkDialog *eel_show_info_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent); GtkDialog *eel_show_info_dialog_with_details (const char *primary_text, const char *secondary_text, const char *detailed_informative_message, GtkWindow *parent); GtkDialog *eel_show_warning_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent); GtkDialog *eel_show_error_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent); GtkDialog *eel_show_error_dialog_with_details (const char *primary_text, const char *secondary_text, const char *detailed_error_message, GtkWindow *parent); GtkDialog *eel_show_yes_no_dialog (const char *primary_text, const char *secondary_text, const char *yes_label, const char *no_label, GtkWindow *parent); GtkDialog *eel_create_question_dialog (const char *primary_text, const char *secondary_text, const char *answer_one, int response_one, const char *answer_two, int response_two, GtkWindow *parent); GtkDialog *eel_create_info_dialog (const char *primary_text, const char *secondary_text, GtkWindow *parent); #endif /* EEL_STOCK_DIALOGS_H */ nemo-3.6.5/po/0000775000175000017500000000000013215733314012027 5ustar fabiofabionemo-3.6.5/po/POTFILES.skip0000664000175000017500000000055013215733314014144 0ustar fabiofabio# List of source files that should NOT be translated. # Please keep this file sorted alphabetically. libbackground/applier.c data/nemo-autorun-software.desktop.in data/nemo-computer.desktop.in data/nemo-file-management-properties.desktop.in data/nemo-folder-handler.desktop.in data/nemo-home.desktop.in data/nemo.desktop.in data/nemo-browser.desktop.in debian nemo-3.6.5/po/ChangeLog0000664000175000017500000125030313215733314013605 0ustar fabiofabio2010-07-04 Funda Wang * zh_CN.po: Updated zh_CN translation from YunQiang Su . 2009-06-10 Manoj Kumar Giri * hi.po: Committed Hindi Translation on behalf of Rajesh Ranjan. === nemo 2.26.2 === 2009-04-13 ReÅŸat SABIQ * crh.po: Updated Crimean Tatar (Crimean Turkish) translation. 2009-04-12 Jorge Gonzalez * es.po: Updated Spanish translation 2009-04-12 Priit Laes * et.po: Translation updated by Mattias Põldaru 2009-04-07 Philip Withnall * en_GB.po: Changes by Bruce Cowan to fix the British English date formats. (Closes: #578189) 2009-04-03 Simos Xenitellis * el.po: Updated Greek translation (Thanos Lefteris). === nemo 2.26.1 === 2009-03-30 Baris Cicek * tr.po: Updated Turkish translation. 2009-03-25 Shankar Prasad * kn.po: Updated few correction to Kannada translations. 2009-03-23 Kenneth Nielsen * da.po: Updated Danish translation by Ask H. Larsen 2009-03-21 Goran Rakic * sr.po, sr@latin.po: Updated Serbian translation by MiloÅ¡ Popović. 2009-03-19 Claude Paroz * LINGUAS: * crh.po: Added Crimean Tatar translation on behalf of ReÅŸat SABIQ. 2009-03-18 Djihed Afifi * ar.po: Updated Arabic translation by Khaled Hosny. 2009-03-17 Nikos Charonitakis * el.po: Updated Greek translation by Pierros Papadeas. 2009-03-17 Ignacio Casal Quinteiro * gl.po: Updated Galician translation by Suso Baleato. 2009-03-17 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-03-16 Hendrik Richter * de.po: Updated German translation, fix #575448. 2009-03-16 Ankitkumar Patel * gu.po: Updated Gujarati Translations. 2009-03-16 Ankitkumar Patel * gu.po: Updated Gujarati Translations. === nemo 2.26.0 === 2009-03-16 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2009-03-16 Amitakhya Phukan * as.po: Updated Assamese translations. 2009-03-16 Amitakhya Phukan * as.po: Updated Assamese translations. 2009-03-16 Petr Kovar * cs.po: Updated Czech translation by Lucas Lommer. 2009-03-15 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2009-03-15 Kostas Papadimas * el.po: Updated Greek Translation by Pierros Papadeas 2009-03-14 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2009-03-14 MiÈ™u Moldovan * ro.po: Updated Romanian translation by Adi Roiban 2009-03-14 Sandeep Shedmake * mr.po: Updated Marathi Translations. 2009-03-14 Krishnababu K * te.po: Updated Telugu Translation. 2009-03-14 Kenneth Nielsen * da.po: Updated Danish translation by Ask H. Larsen 2009-03-13 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2009-03-13 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2009-03-13 Priit Laes * et.po: Translation updated by Mattias Põldaru 2009-03-12 Duarte Loreto * pt.po: Fixed an error on the Portuguese translation. 2009-03-12 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation 2009-03-11 Krishnababu K * te.po: Updated Telugu Translation. === nemo 2.25.93 === 2009-03-11 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2009-03-10 Nickolay V. Shmyrev * ru.po: Updated Russian translation by Yuriy Penkin. 2009-03-10 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2009-03-10 I. Felix * ta.po: Tamil Translation updated 2009-03-10 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2009-03-09 Dwayne Bailey * nso.po: Fixed broken Northern Sotho gconf translations (fixes bug #569493). 2009-03-08 Petr Kovar * cs.po: Fixed Czech translation by Lucas Lommer (fixes bug #568087]. 2009-03-07 Mario Blättermann * de.po: Updated German translation by Wolfgang Stöggl. 2009-03-07 Ilkka Tuohela * fi.po: Updated Finnish translation. 2009-03-06 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2009-03-05 Tomasz Dominikowski * pl.po: Updated Polish translation 2009-03-05 Tomasz Dominikowski * pl.po: Updated Polish translation 2009-03-05 Tomasz Dominikowski * pl.po: Updated Polish translation 2009-03-05 Tomasz Dominikowski * pl.po: Updated Polish translation 2009-03-03 Claude Paroz * fr.po: Updated French translation by Laurent Coudeur and Bruno Brouard. 2009-03-04 Takeshi AIHANA * ja.po: Updated Japanese translation. 2009-03-03 Manoj Kumar Giri * or.po: Upadted Oriya Translation. 2009-03-03 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2009-03-03 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2009-03-02 Milo Casagrande * it.po: Updated Italian translation by Luca Ferretti 2009-03-02 Hendrik Richter * de.po: Updated German translation. 2009-03-02 Hendrik Richter * de.po: Updated German translation. === nemo 2.25.92 === 2009-03-02 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan 2009-03-02 Shankar Prasad * kn.po: Updated Kannada translations. 2009-03-01 Tomasz Dominikowski * pl.po: Updated Polish translation 2009-02-28 Gabor Kelemen * hu.po: Translation updated. 2009-02-38 Yair Hershkovitz * he.po: Updated Hebrew translation. 2009-02-28 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2009-02-27 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2009-02-27 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2009-02-27 Luca Ferretti * it.po: Updated Italian translation. 2009-02-26 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-02-26 Ilkka Tuohela * fi.po: Updated Finnish translation. 2009-02-26 Changwoo Ryu * ko.po: Updated Korean translation. 2009-02-25 Og Maciel * pt_BR.po: Updated Brazilian Portuguese translation by André Gondim and reviewed by myself. 2009-02-25 Duarte Loreto * pt.po: Updated Portuguese translation. 2009-02-24 Wouter Bolsterlee * nl.po: Updated Dutch translation by Wouter Bolsterlee. 2009-02-24 Wadim Dziedzic * pl.po: Updated Polish translation 2009-02-24 Philip Withnall * en_GB.po: Updated British English translation. 2009-02-24 Jorge Gonzalez * es.po: Updated Spanish translation by Juan Jesús Ojeda and me 2009-02-24 Daniel Nylander * sv.po: Updated Swedish translation. 2009-02-23 Og Maciel * pt_BR.po: Updated Brazilian Portuguese translation by André Gondim and reviewed by Vladimir Melo. 2009-02-23 Philip Withnall * en_GB.po: Updated British English translation. 2009-02-23 Gabor Kelemen * hu.po: Translation updated. 2009-02-23 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2009-02-23 Wouter Bolsterlee * nl.po: Updated Dutch translation by Wouter Bolsterlee. 2009-02-23 Priit Laes * et.po: Translation updated by Ivar Smolin 2009-02-21 Christian Kirbach * de.po: Updated German translation. 2009-02-20 Jani Monoses * ro.po: Updated Romanian translation by Adi Roiban 2009-02-20 Daniel Nylander * sv.po: Updated Swedish translation. 2009-02-20 Claude Paroz * fr.po: Updated French translation by Bruno Brouard. 2009-02-20 Sweta Kothari * gu.po: Committed Gujarati Translation. 2009-02-20 Priit Laes * et.po: Translation updated by Mattias Põldaru 2009-02-20 Takeshi AIHANA * ja.po: Updated Japanese translation. 2009-02-19 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2009-02-19 Gabor Kelemen * hu.po: Translation updated. 2009-02-19 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan 2009-02-18 Andre Klapper * cs.po: Updated Czech translation by Lucas Lommer 2009-02-18 Priit Laes * et.po: Translation updated by Ivar Smolin 2009-02-18 Sandeep Shedmake * mr.po: Bug fix for #571898. 2009-02-18 Changwoo Ryu * ko.po: Updated Korean translation. 2009-02-17 Gabor Kelemen * hu.po: Translation updated. 2009-02-17 Sweta Kothari * gu.po: Committed Gujarati Translation. 2009-02-17 Daniel Nylander * sv.po: Updated Swedish translation. 2009-02-17 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2009-02-16 Ilkka Tuohela * fi.po: Updated Finnish translation. === nemo 2.25.91 === 2009-02-16 Sweta Kothari * gu.po: Committed Gujarati Translation. 2009-02-15 Duarte Loreto * pt.po: Updated Portuguese translation. 2009-02-15 Kenneth Nielsen * da.po: Updated Danish translation by Ask H. Larsen 2009-02-14 Jorge Gonzalez * es.po: Updated Spanish translation, fixes bug #569457 2009-02-14 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation by Ihar Hrachyshka. 2009-02-14 Daniel Nylander * sv.po: Updated Swedish translation. 2009-02-14 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2009-02-14 Wouter Bolsterlee * nl.po: Updated Dutch translation by Wouter Bolsterlee. 2009-02-13 Jorge Gonzalez * es.po: Updated Spanish translation 2009-02-13 Clytie Siddall * vi.po: Updated Vietnamese translation. 2009-02-13 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2009-02-13 Gabor Kelemen * hu.po: Translation updated. 2009-02-12 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2009-02-12 Sweta Kothari * gu.po: Committed Gujarati Translation. 2009-02-11 Jonh Wendell * pt_BR.po: Updated Brazilian Portuguese translation. 2009-02-10 Daniel Nylander * sv.po: Updated Swedish translation. 2009-02-10 Gil Forcada * ast.po: Updated Asturian translation on behalf of Mikel González. 2009-02-10 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-02-09 Takeshi AIHANA * ja.po: Updated Japanese translation. 2009-02-07 Goran Rakić * sr.po, sr@latin.po: Updated Serbian translation wrt bug #570838. 2009-02-07 Clytie Siddall * vi.po: Updated Vietnamese translation. 2008-06-25 Christian Kirbach * de.po: Updated German translation. 2009-02-04 Manoj Kumar Giri * or.po: Updated Oriya Translation. 2009-02-04 Manoj Kumar Giri * or.po: Updated Oriya Translation. 2009-02-04 Runa Bhattachajee * bn_IN.po: Updated the gconf values wrt bug #569497 2009-02-03 Manoj Kumar Giri * or.po: Updated Oriya Translation. 2009-02-02 Jorge Gonzalez * es.po: Updated Spanish translation. === nemo 2.25.4 === 2009-01-31 Daniel Nylander * sv.po: Updated Swedish translation. 2009-01-30 Jorge Gonzalez * es.po: Updated Spanish translation. 2009-01-30 Ilkka Tuohela * fi.po: Updated Finnish translation. 2009-01-29 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-01-29 Changwoo Ryu * ko.po: Updated Korean translation. 2009-01-29 Sandeep Shedmake * mr.po: Bug fix for #569503. 2009-01-29 Jovan Naumovski * mk.po: Bug fix for #569495. 2009-01-29 Funda Wang * zh_CN.po: Updated zh_CN translation. 2009-01-27 Jonh Wendell * pt_BR.po: Brazilian Portuguese translation updated by Fabrício Godoy. 2009-01-25 Andre Klapper * de.po: Updated German translation. 2009-01-24 Raivis DEjus * lv.po: Updated Latvian translation. 2009-01-21 A. Walton * cs.po: * de.po: * es.po: * et.po: * eu.po: * fr.po: * ha.po: * he.po: * hu.po: * ig.po: * it.po: * nb.po: * sk.po: * sl.po: * sr.po: * sr@latin.po: * sv.po: * uz.po: * uz@cyrillic.po: * yo.po: Bug 568503 – Misspelled word "progam"->"program" Fixing message ids. === nemo 2.25.3 === 2009-01-17 Thomas Thurman * ig.po: Added Igbo translation by Sylvester Onye. * yo.po Added Yoruba translation by Sunday Ayo Fajuyitan. * ha.po: Added Hausa translation by Saudat Mohammed. * LINGUAS: added Igbo, Yoruba and Hausa. 2009-01-17 Jorge Gonzalez * es.po: Updated Spanish translation. 2009-01-13 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-01-13 Gabor Kelemen * hu.po: Translation updated. 2009-01-12 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2009-01-08 Daniel Nylander * sv.po: Updated Swedish translation. 2009-01-06 Nurali Abdurahmonov * uz.po: Added uzbek translation * uz@cyrillic.po: Added uzbek cyrillic translation * LINGUAS: added uz and uz@cyrillic 2009-01-06 Luca Ferretti * it.po: Updated Italian translation. 2009-01-03 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-12-29 Hendrik Richter * de.po: Updated German translation. 2008-12-27 Luca Ferretti * it.po: Updated Italian translation. 2008-12-21 Marcel Telka * sk.po: Updated Slovak translation. 2008-12-16 Jorge Gonzalez * es.po: Updated Spanish translation. 2008-12-15 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-12-15 Claude Paroz * fr.po: Updated French translation. === nemo 2.25.2 === 2008-12-15 Alexander Larsson * POTFILES.in: * *.po: Imported eel pofiles 2008-12-08 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-12-07 Mario Blättermann * de.po: Some fixes in German translation 2008-12-03 Goran Rakić * sr.po, sr@latin.po: Fixed Ubuntu bug lp#197224. === nemo 2.25.1 === 2008-12-01 Alexander Larsson * POTFILES.in: * POTFILES.skip: Update 2008-11-11 Mark Krapivner * he.po: Fixed a few errors 2008-11-09 Petr Kovar * cs.po: Fixed Czech translation (thanks to Kamil Paral). 2008-11-09 Leonardo Ferreira Fontenelle * pt_BR.po: Merged from branch gnome-2-24 minor improvements in the Brazilian Portuguese translation. 2008-11-09 Goran Rakić * sr.po, sr@latin.po: Updated Serbian Translation (by MiloÅ¡ Popović). 2008-11-08 Jorge Gonzalez * es.po: Updated Spanish translation. 2008-11-08 Inaki Larranaga Murgoitio * eu.po: Fixed some errors and updated Basque translation. 2008-11-06 Luca Ferretti * it.po: Updated Italian translation. 2008-10-28 Daniel Nylander * sv.po: Updated Swedish translation. 2008-10-27 Cosimo Cecchi * POTFILES.in: update after the move away from libgnome/bonobo/glade. Thanks to Frederic Peters (#558134). 2008-10-25 Leonardo Ferreira Fontenelle * pt_BR.po: Merged from branch gnome-2-24 improvements in Brazilian Portuguese translation by Fabrício Godoy. 2008-10-25 Priit Laes * et.po: Translation updated by Priit Laes 2008-10-23 Andre Klapper * LINGUAS: Added ast. * ast.po: Added Asturian translation on behalf of Mikel González. 2008-10-20 Jordi Mallach * ca@valencia.po: Updated Valencian (Southern Catalan) translation from the Catalan file. 2008-10-12 Leonardo Ferreira Fontenelle * pt_BR.po: Merged from branch gnome-2-24 terminology fixes in Brazilian Portuguese translation by Vladimir Melo. 2008-10-09 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-10-07 Simos Xenitellis * el.po: Updated Greek translation. 2008-10-05 Daniel Nylander * sv.po: Updated Swedish translation. 2008-10-01 Matic Zgur * sl.po: Updated Slovenian translation. 2008-09-27 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-09-27 Laurent Dhima * sq.po: Updated Albanian Translation. 2008-09-25 Jovan Naumovski * mk.po: Updated Macedonian translation. 2008-09-22 Goran Rakić * sr.po, sr@latin.po: Updated Serbian Translation. 2008-09-22 Timo Jyrinki * fi.po: Updated Finnish translation. 2008-09-22 Nikos Charonitakis * el.po: Updated Greek translation. 2008-09-22 Kenneth Nielsen * da.po: Updated Danish translation by Kenneth Nielsen 2008-09-22 Goran Rakić * sr.po, sr@latin.po: Updated Serbian Translation (by MiloÅ¡ Popović). 2008-09-22 Mugurel Tudor * ro.po: Updated Romanian translation by MiÅŸu Moldovan 2008-09-21 Wadim Dziedzic * pl.po: Updated Polish translation 2008-09-21 Alexandre Prokoudine * ru.po: Updated Russian translation by Yuri Penkin 2008-09-20 Kenneth Nielsen * da.po: Updated Danish translation by Ask H. Larsen 2008-09-20 Laurent Dhima * sq.po: Updated Albanian Translation. 2008-09-20 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-09-20 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-09-20 Goran Rakić * sr.po, sr@latin.po: Updated Serbian translation (by MiloÅ¡ Popović). 2008-09-19 Og Maciel * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo. 2008-09-19 Gabor Kelemen * hu.po: Translation updated. 2008-09-18 Kostas Papadimas * el.po: Updated Greek Translation by Athanasios Lefteris 2008-09-18 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2008-09-18 Djihed Afifi * ar.po: Updated Arabic Translation by Anas Afif Emad. 2008-09-15 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2008-09-15 Djihed Afifi * ar.po: Updated Arabic Translation by Anas Afif Emad. 2008-09-15 I. Felix * ta.po: Tamil Translation error corrected. 2008-09-14 Praveen Arimbrathodiyil * ml.po: Malayalam translation updated. 2008-09-14 Robert-André Mauchin * af.po: Updated Afrikaans translation by Friedel Wolff. 2008-09-14 Luca Ferretti * it.po: Updated Italian translation. 2008-09-14 Petr Kovar * cs.po: Updated Czech translation by Kamil Paral (bug #551977). 2008-09-14 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-09-12 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-09-12 Reinout van Schouwen * nl.po: Translation updated by Reinout van Schouwen. 2008-09-11 Hendrik Richter * de.po: Updated German translation. 2008-09-10 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-09-09 Og Maciel * pt_BR.po: Revision of Brazilian Portuguese translation by Vladimir Melo. 2008-09-09 Robert Sedak * hr.po: Updated Croatian translation. 2008-09-09 Sandeep Shedmake * mr.po: Updated Marathi Translations 2008-09-09 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-09-09 Laurent Dhima * sq.po: Updated Albanian Translation. 2008-09-09 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan 2008-09-09 Baris Cicek * tr.po: Updated Turkish translation 2008-09-08 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2008-09-07 Duarte Loreto * pt.po: Updated Portuguese translation. 2008-09-07 Reinout van Schouwen * nl.po: Translation updated by Reinout van Schouwen. 2008-09-06 Luca Ferretti * it.po: Updated Italian translation. 2008-09-06 Philip Withnall * en_GB.po: Updated British English translation. 2008-09-06 Claude Paroz * fr.po: Updated French translation. 2008-09-06 Funda Wang * zh_CN.po: Updated zh_CN translation. 2008-09-05 Gil Forcada * ca.po: Minor fix by Joan Duran. 2008-09-05 Tomasz Dominikowski * pl.po: Updated Polish translation 2008-09-04 Robert-André Mauchin * LINGUAS: * ps.po: Added Pashto translations by Zabeeh Khan. 2008-09-04 Daniel Nylander * sv.po: Updated Swedish translation. 2008-09-03 Hendrik Richter * de.po: Updated German translation. 2008-09-02 Og Maciel * pt_BR.po: Updated Brazilian Portuguese translation by Og Maciel. 2008-09-02 Nguyá»…n Thái Ngá»c Duy * vi.po: Updated Vietnamese translation 2008-09-02 Jorge Gonzalez * es.po: Updated Spanish translation 2008-09-02 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-09-01 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2008-09-01 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-09-01 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2008-09-01 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-09-01 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-09-01 Hendrik Richter * de.po: Updated German translation. 2008-09-01 Hendrik Richter * de.po: Updated German translation. 2008-08-31 Seán de Búrca * ga.po: Updated Irish translation. 2008-08-30 Og Maciel * pt_BR.po: Fixes Bug #549897. 2008-08-30 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-08-30 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-08-29 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-29 Hendrik Richter * de.po: Updated German translation. 2008-08-29 Rajesh Ranjan * mai.po: Added Maithili translation. 2008-08-28 Daniel Nylander * sv.po: Updated Swedish translation. 2008-08-28 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-08-28 Hendrik Richter * de.po: Updated German translation. 2008-08-28 Petr Kovar * cs.po: Updated Czech translation. 2008-08-27 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-08-27 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-08-26 Yair Hershkovitz * he.po: Updated Hebrew translation by Mark Krapivner. 2008-08-25 Og Maciel * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo. 2008-08-26 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-25 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-08-25 Goran Rakic * LINGUAS, sr@latin.po, sr@Latn.po: Conversion from sr@Latn to sr@latin. 2008-08-25 Jovan Naumovski * mk.po: Updated Macedonian translation. 2008-08-24 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-08-24 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-08-21 Shankar Prasad * kn.po: Updated Kannada translations. 2008-08-20 Shankar Prasad * kn.po: Updated Kannada translations. 2008-08-20 Shankar Prasad * kn.po: Updated Kannada translations. 2008-08-19 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-08-19 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-19 Shankar Prasad * kn.po: Updated Kannada translations. 2008-08-19 Luca Ferretti * it.po: Updated Italian translation. 2008-08-18 Claude Paroz * fr.po: Updated French translation by Robert-André Mauchin and Claude Paroz. 2008-08-17 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-17 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-08-16 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-08-16 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-08-16 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-08-15 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-08-14 Duarte Loreto * pt.po: Updated Portuguese translation. 2008-08-14 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2008-08-14 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-08-13 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-13 Petr Kovar * cs.po: Updated Czech translation by Lucas Lommer. 2008-08-13 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-08-12 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-08-09 Luca Ferretti * it.po: Updated Italian translation. 2008-08-09 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-08-08 Petr Kovar * cs.po: Updated Czech translation by Lucas Lommer. 2008-08-08 Hendrik Richter * de.po: Updated German translation. 2008-08-07 Wadim Dziedzic * pl.po: Updated Polish translation 2008-08-07 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-08-06 Ignacio Casal Quinteiro * gl.po: Updated Galician translation 2008-08-06 Daniel Nylander * sv.po: Updated Swedish translation. 2008-08-6 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2008-08-05 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-05 Daniel Nylander * sv.po: Updated Swedish translation. 2008-08-04 Jorge Gonzalez * es.po: Updated Spanish translation 2008-08-03 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-07-29 Colin Walters * oc.po: Revert last commit, it broke the build. 2008-07-29 Funda Wang * zh_CN.po: Updated zh_CN translation. 2008-07-29 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2008-07-28 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-07-28 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-07-25 Daniel Nylander * sv.po: Updated Swedish translation. 2008-07-25 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-07-24 Leonardo Ferreira Fontenelle * pt_BR.po: Terminology improvements by Vladimir Melo. 2008-07-24 Jorge Gonzalez * es.po: Updated Spanish translation 2008-07-22 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-07-21 Hendrik Richter * de.po: Fixed German translation by Jens Seidel . 2008-07-21 Hendrik Richter * de.po: Updated German translation, fix #543972. 2008-07-21 Hendrik Richter * de.po: Updated German translation, fix #543973. 2008-07-17 Hendrik Richter * de.po: Fixed German translation by Jens Seidel . 2008-07-16 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-07-16 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-07-13 Jorge Gonzalez * es.po: Updated Spanish translation 2008-07-12 Daniel Nylander * sv.po: Updated Swedish translation. 2008-07-12 Claude Paroz * fr.po: Updated French translation by Bruno Brouard and Claude Paroz. 2008-07-10 Gabor Kelemen * hu.po: Translation updated by Máté Åry. 2008-07-10 Matej UrbanÄiÄ * sl.po: Updated Slovenian Translation. 2008-07-10 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-07-09 Kjartan Maraas * POTFILES.in: Add missing files. * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-07-04 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-07-02 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-06-27 Changwoo Ryu * ko.po: Updated Korean translation. 2008-06-25 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-06-24 Daniel Nylander * sv.po: Updated Swedish translation. 2008-06-19 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-06-18 Gabor Kelemen * hu.po: Translation updated by Máté Åry. 2008-06-17 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-06-15 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-06-14 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-06-14 Jorge Gonzalez * es.po: Updated Spanish translation 2008-06-11 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2008-06-11 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-06-10 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-06-08 Funda Wang * zh_CN.po: Updated zh_CN translation. 2008-06-07 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-06-05 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-06-05 Roozbeh Pournader * fa.po: Fixed a bad message in Persian translation (fixes bug #511623, reported by Hedayat Vatankhah, patch by Elnaz Sarbar) ==================== 2.23.3 ==================== 2008-06-01 Jovan Naumovski * mk.po: Updated Macedonian translation. 2008-06-02 Clytie Siddall * vi.po: Updated Vietnamese translation. 2008-05-25 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-05-24 Vincent van Adrighem * nl.po: Translation updated by Tino Meinen. 2008-05-24 Jorge Gonzalez * es.po: Updated Spanish translation 2008-05-23 Jorge Gonzalez * es.po: Updated Spanish translation 2008-05-23 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-05-19 Djihed Afifi * ar.po: Updated Arabic Translation by Djihed Afifi. 2008-05-14 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. === nemo 2.23.2 === 2008-05-10 Jorge Gonzalez * es.po: Updated Spanish translation 2008-05-06 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-05-03 Jorge Gonzalez * es.po: Updated Spanish translation 2008-05-02 Cosimo Cecchi * oc.po: Reverted last update of Occitan translation, it was breaking the build. (#530970). 2008-04-30 Jorge Gonzalez * es.po: Updated Spanish translation 2008-04-30 Andre Klapper * LINGUAS: * fur.po: Added Friulian translation on behalf of the Friulian team. Fixes bug #530509. 2008-04-30 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-04-29 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-04-29 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-04-24 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2008-04-23 Jorge Gonzalez * es.po: Updated Spanish translation by Alberto Caso, fixes LP bug #197224 2008-04-22 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-04-21 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-04-19 Daniel Nylander * sv.po: Updated Swedish translation. 2008-04-14 Michael Terry * io.po: Added partial Ido translation. 2008-04-13 Jorge Gonzalez * es.po: Updated Spanish translation, fixes bug #526626 2008-04-11 Marcel Telka * POTFILES.in: Updated. 2008-04-11 Jorge Gonzalez * es.po: Updated Spanish translation 2008-04-10 Jordi Mallach * ca@valencia.po: New Valencian-Catalan translation, based on the current Catalan file. 2008-04-10 Jordi Mallach * ca.po: Fix typo in Catalan translation. 2008-04-07 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-04-01 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2008-04-01 Claude Paroz * fr.po: Removed fuzzy generated by commit 14017. 2008-03-31 Eskild Hustvedt * nn.po: Updated Norwegian Nynorsk translation 2008-03-30 Jorge Gonzalez * es.po: Updated Spanish translation === nemo 2.22.1 === 2008-03-23 Nguyá»…n Thái Ngá»c Duy * vi.po: Update Vietnamese translation 2008-03-22 Nikos Charonitakis * el.po: Updated Greek translation. 2008-03-20 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2008-03-15 Alexander Nyakhaychyk * be.po: Updated Belarusian Translation. 2008-03-14 Andre Klapper * de.po: Added missing mnemonic to German version. 2008-03-12 Stéphane Raimbault * fr.po: Fixed French translation. 2008-03-12 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-03-11 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-03-10 Ani Peter * it.po: Fixed (maybe) duplicate shortcuts. 2008-03-10 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-03-09 Vasiliy Faronov * ru.po: Updated Russian translation. 2008-03-09 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-03-09 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2008-03-09 Kostas Papadimas * el.po: Updated Greek translation 2008-03-09 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan 2008-03-09 Kenneth Nielsen * da.po: Updated Danish translation 2008-03-08 Maxim Dziumanenko * uk.po: Update Ukrainian translation. 2008-03-08 Wadim Dziedzic * pl.po: Updated polish translation 2008-03-08 Baris Cicek * tr.po: Updated Turkish translation. 2008-03-08 Djihed Afifi * ar.po: Updated Arabic Translation by Djihed Afifi. 2008-03-08 Guntupalli Karunakar * hi.po: Fix plural errors. 2008-03-08 Daniel Nylander * sv.po: Updated Swedish translation. 2008-03-08 Runa Bhattacharjee * bn_IN.po: Corrected errors related to plural forms 2008-03-07 Andre Klapper * cs.po: Updated Czech translation on behalf of Lucas Lommer. 2008-03-07 Sunil Mohan Adapa * te.po: Updated Telugu translation done by Krishna Babu K . 2008-03-07 Gabor Kelemen * hu.po: Translation updated 2008-03-06 Wadim Dziedzic * pl.po: Updated polish translation 2008-03-05 Ani Peter * ml.po: Updated Malayalam Translation 2008-03-05 Wouter Bolsterlee * nl.po: Updated Dutch translation by Tino Meinen. 2008-03-05 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2008-03-04 Petr Kovar * cs.po: Fixed Czech translation by Lucas Lommer, thanks to Kamil Paral (bug #520256). 2008-03-04 Hendrik Richter * de.po: Updated German translation. 2008-03-03 Jorge Gonzalez * es.po: Updated Spanish translation 2008-03-03 Rahul Bhalerao * mr.po: Updated Marathi translations from Sandeep Shedmake. 2008-03-03 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-03-03 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-03-03 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-03-03 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2008-03-03 Duarte Loreto * pt.po: Updated Portuguese translation. 2008-03-03 Reinout van Schouwen * nl.po: Translation updated by Reinout van Schouwen. 2008-03-03 Philip Withnall * en_GB.po: Updated British English translation. 2008-03-02 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2008-03-02 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-03-02 Petr Kovar * cs.po: Updated Czech translation by Lucas Lommer. 2008-03-01 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2008-03-01 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2008-02-29 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-02-29 Daniel Nylander * sv.po: Updated Swedish translation. 2008-02-29 Luca Ferretti * it.po: Updated Italian translation. 2008-02-28 Jorge Gonzalez * es.po: Updated Spanish translation 2008-02-28 Hendrik Richter * de.po: Updated German translation. 2008-02-28 Luca Ferretti * it.po: Updated Italian translation. 2008-02-27 Luca Ferretti * it.po: Updated Italian translation. 2008-02-27 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-02-27 Claude Paroz * fr.po: Updated French translation. 2008-02-27 Jorge Gonzalez * es.po: Updated Spanish translation 2008-02-27 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2008-02-27 Djihed Afifi * ar.po: Updated Arabic Translation by Abdelmonam Kouka. 2008-02-27 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-02-27 Arangel Angov * mk.po: Updated Macedonian translation. 2008-02-26 Leonardo Ferreira Fontenelle * pt_BR.po: Brazilian Portuguese translation updated by Vladimir Melo. 2008-02-26 Djihed Afifi * ar.po: Updated Arabic Translation by Abdelmonam Kouka. 2008-02-26 Changwoo Ryu * ko.po: Updated Korean translation. 2008-02-26 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-02-26 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-02-26 Luca Ferretti * POTFILES.in: * POTFILES.skip: Restore the removed connect to server files 2008-02-26 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-02-26 Daniel Nylander * sv.po: Updated Swedish translation. === nemo 2.21.92 === 2008-02-25 Gil Forcada * ca.po: Updated Catalan translation by Joan Duran. 2008-02-24 Leonardo Ferreira Fontenelle * pt_BR.po: Brazilian Portuguese translation updated by Vladimir Melo and myself. 2008-02-22 Petr Kovar * cs.po: Updated Czech translation by Kamil Paral. 2008-02-22 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2008-02-22 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-02-22 Arangel Angov * mk.po: Updated Macedonian translation. 2008-02-21 Stéphane Raimbault * fr.po: Updated French translation by Robert-André Mauchin, Bruno Brouad et Claude Paroz. 2008-02-21 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-02-21 Takeshi AIHANA * ja.po: Updated Japanese translation. 2008-02-21 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2008-02-21 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-02-21 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-02-21 Funda Wang * zh_CN.po: Update Simplified Chinese translation. 2008-02-20 Duarte Loreto * pt.po: Updated Portuguese translation. 2008-02-20 Hendrik Richter * de.po: Updated German translation. 2008-02-20 Daniel Nylander * sv.po: Updated Swedish translation. 2008-02-20 Jorge Gonzalez * es.po: Updated Spanish translation 2008-02-20 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2008-02-19 Djihed Afifi * ar.po: Updated Arabic Translation by Abdelmonam Kouka. 2008-02-19 Daniel Nylander * sv.po: Updated Swedish translation. 2008-02-19 Alexander Larsson * POTFILES.in: Removed nemo-file-operations-progress.c 2008-02-18 Hendrik Richter * de.po: Updated German translation. 2008-02-18 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-02-18 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-02-17 Nguyá»…n Thái Ngá»c Duy * vi.po: Updated Vietnamese translation 2008-02-17 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2008-02-16 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-02-16 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2008-02-16 Arangel Angov * mk.po: Updated Macedonian translation. 2008-02-14 Jorge Gonzalez * es.po: Updated Spanish translation 2008-02-14 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-02-14 Runa Bhattacharjee * kn.po: Updated Translation for Kannada by Shankar Prasad 2008-02-14 Pawan Chitrakar * ne.po: Updated Nepali Translation. 2008-02-14 Ilkka Tuohela * fi.po: Updated Finnish translation. 2008-02-14 Arangel Angov * mk.po: Updated Macedonian Translation. 2008-02-13 Jonh Wendell * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo and Pedro de Medeiros. 2008-02-13 Luca Ferretti * it.po: Updated Italian translation. 2008-02-13 Yannig Marchegay * oc.po: Updated Occitan translation. === nemo 2.21.91 === 2008-02-11 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2008-02-10 Vasiliy Faronov * ru.po: Updated Russian translation. 2008-02-10 Duarte Loreto * pt.po: Updated Portuguese translation. 2008-02-08 Hendrik Richter * de.po: Updated German translation. 2008-02-08 Hendrik Richter * de.po: Updated German translation. 2008-02-08 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-02-08 Jorge Gonzalez * es.po: Updated Spanish translation 2008-02-07 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2008-02-07 Nikos Charonitakis * el.po: Updated Greek translation. 2008-02-06 Alexander Larsson * it.po: Fix mistranslation (#510308) 2008-02-05 Yair Hershkovitz * he.po: Updated Hebrew translation by Mark Krapviner. 2008-02-04 Luca Ferretti * it.po: Updated Italian translation. 2008-02-04 Danishka Navin * si.po: Updated Sinhala translation. 2008-02-03 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-02-03 Yair Hershkovitz * he.po: Updated Hebrew translation by Mark Krapviner. 2008-02-02 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-02-02 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2008-02-01 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2008-02-01 Runa Bhattacharjee * kn.po: Updated Kannada Translations by Shankar Prasad. 2008-01-31 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2008-01-30 Funda Wang * zh_CN.po: Update Simplified Chinese translation. 2008-01-29 Daniel Nylander * sv.po: Updated Swedish translation. 2008-01-29 Yannig Marchegay * oc.po: Updated Occitan translation. 2008-01-29 Jorge Gonzalez * es.po: Updated Spanish translation 2008-01-29 Jonh Wendell * pt_BR.po: Brazilian Portuguese translation updated by Vladimir Melo. 2008-01-28 Daniel Nylander * sv.po: Updated Swedish translation. === nemo 2.21.90 === 2008-01-28 Luca Ferretti * it.po: Updated Italian translation. 2008-01-28 Jorge Gonzalez * es.po: Updated Spanish translation 2008-01-27 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2008-01-27 Jovan Naumovski * mk.po: Updated Macedonian translation. 2008-01-26 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-01-26 Jorge Gonzalez * es.po: Updated Spanish translation 2008-01-26 Jovan Naumovski * mk.po: Updated Macedonian translation. 2008-01-25 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-01-24 Daniel Nylander * sv.po: Updated Swedish translation. 2008-01-23 Luca Ferretti * it.po: Updated Italian translation. 2008-01-22 Jorge Gonzalez * es.po: Updated Spanish translation. 2008-01-22 Yair Hershkovitz * he.po: Updated Hebrew translation. === nemo 2.21.6 === 2008-01-21 Alexander Larsson * POTFILES.in: * POTFILES.skip: Add new files 2008-01-21 Changwoo Ryu * ko.po: Updated Korean translation. 2008-01-20 Luca Ferretti * it.po: Updated Italian translation. 2008-01-19 Jorge Gonzalez * es.po: Updated Spanish translation 2008-01-18 Gil Forcada * tr.po: Updated Turkish translation to pass msgfmt -cv. 2008-01-17 Gabor Kelemen * hu.po: Translation updated 2008-01-16 Sunil Mohan Adapa * te.po: Updated Telugu translation done by Krishna Babu K . 2008-01-15 Luca Ferretti * it.po: Updated Italian translation. 2008-01-15 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2008-01-15 Daniel Nylander * sv.po: Updated Swedish translation. 2008-01-14 Jorge Gonzalez * es.po: Updated Spanish translation === nemo 2.21.5 === 2008-01-14 Alexander Larsson * POTFILES.in: Add nemo-autorun.c 2008-01-14 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2008-01-14 Priit Laes * et.po: Translation updated by Ivar Smolin 2008-01-11 Changwoo Ryu * ko.po: Updated Korean translation by Namhyung Kim. 2008-01-10 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2008-01-10 Luca Ferretti * it.po: Updated Italian translation. 2008-01-09 Yair Hershkovitz * he.po: Updated Hebrew translation. 2008-01-09 Alexander Larsson * POTFILES.skip: Add the removed connect to server files to skip instead === nemo 2.21.2 === 2008-01-07 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2008-01-06 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2008-01-05 Clytie Siddall * vi.po: Updated Vietnamese translation. 2007-01-04 Jorge Gonzalez * es.po: Updated Spanish translation 2008-01-03 Daniel Nylander * sv.po: Updated Swedish translation. 2007-12-31 Yannig Marchegay * oc.po: Updated Occitan translation. 2007-12-26 Seán de Búrca * ga.po: Updated Irish translation. * POTFILES.in: Add missing files. 2007-12-26 Djihed Afifi * ar.po: Updated Arabic Translation by Djihed Afifi. 2007-12-24 Djihed Afifi * ar.po: Updated Arabic Translation by Abou Manal. 2007-12-22 Seán de Búrca * ga.po: Updated Irish translation. === nemo 2.20.1 === 2007-12-20 Alexander Larsson * POTFILES.in: Remove removed files 2007-12-17 Daniel Nylander * sv.po: Updated Swedish translation. 2007-12-16 Jorge Gonzalez * es.po: Updated Spanish translation 2007-12-11 Jorge Gonzalez * es.po: Updated Spanish translation 2007-12-11 Rahul Balerao * mr.po: Added Marathi translations given by Sandeep Shedmake * LINGUAS: Added an entry for mr. 2007-12-11 Kostas Papadimas * el.po: Updated Greek translation 2007-12-10 Matej UrbanÄiÄ * sl.po: Updated Slovenian Translation. 2007-12-09 Jorge Gonzalez * es.po: Updated Spanish translation 2007-12-08 Leonardo Ferreira Fontenelle * pt_BR.po: Translation of "delete" fixed by Rodrigo Flores. 2007-11-27 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-12-06 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-12-04 Andre Klapper * de.po: Updated German translation. 2007-12-03 Andre Klapper * de.po: Updated German translation. 2007-12-03 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2007-12-01 Jorge Gonzalez * es.po: Updated Spanish translation 2007-12-01 UrbanÄiÄ Matej * sl.po: Updated Slovenian translation. 2007-11-30 Andre Klapper * POTFILES.in: Update list of files. 2007-11-27 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-11-25 Nickolay V. Shmyrev * ru.po: Updated Russian translation by Vasiliy Faronov 2007-11-21 Gil Forcada * ca.po: Updated Catalan translation by David Planella. 2007-11-15 Priit Laes * et.po: Translation updated by Ivar Smolin. 2007-11-12 Matej UrbanÄiÄ * sl.po: Updated Slovenian translation. 2007-11-07 Daniel Nylander * sv.po: Updated Swedish translation. 2007-11-06 Jorge Gonzalez * es.po: Updated Spanish translation 2007-11-06 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-10-31 Ilkka Tuohela * fi.po: Updated Finnish translation. 2007-10-29 Gabor Kelemen * hu.po: Translation updated 2007-10-28 Mohammad DAMT * id.po: Updated Indonesian translation by Huda Toriq 2007-10-27 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-10-23 Djihed Afifi * ar.po: Updated Arabic Translation by Sohaib Afifi. 2007-10-21 Djihed Afifi * ar.po: Updated Arabic Translation by Sohaib Afifi. 2007-10-19 Matej UrbanÄiÄ * sl.po: Updated Slovenian translation. 2007-10-15 Yair Hershkovitz * he.po: Updated Hebrew translation. 2007-10-06 Jovan Naumovski * mk.po: Minor fixes in Macedonian translation. 2007-10-04 Danishka Navin * si.po: Updated Sinhala translation by Danishka Navin. 2007-10-02 Thierry Randrianiriana * mg.po: Updated Malagasy translation. 2007-09-22 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-09-19 Danilo Å egan * sr.po, sr@Latn.po: Minor updates. === nemo 2.20.0 === 2007-09-17 Wouter Bolsterlee * nl.po: Translation updated by Wouter Bolsterlee. 2007-09-17 Djihed Afifi * ar.po: Updated Arabic Translation by Sohaib Afifi. 2007-09-17 Amitakhya Phukan * LINGUAS: Added as to LINGUAS. * as.po: Added and updated assamese translations. 2007-09-16 Inaki Larranaga Murgoitio * eu.po: Updated Basque translation. 2007-09-16 Daniel Nylander * sv.po: Updated Swedish translation. 2007-09-16 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2007-09-15 Nickolay V. Shmyrev * ru.po: Updated Russian translation. 2007-09-15 Kostas Papadimas * el.po: Updated Greek Translation. 2007-09-15 Mugurel Tudor * ro.po: Updated Romanian translation. 2007-09-15 Andre Klapper * sk.po: Updated Slovak translation on behalf of Peter Tuharsky . 2007-09-15 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2007-09-14 Takeshi AIHANA * ja.po: Translation improved. 2007-09-13 Djihed Afifi * ar.po: Updated Arabic Translation by Sohaib Afifi. 2007-09-13 Pramod Raghavendra * kn.po: Updated Kannada translation. * LINGUAS: Added Kannada (kn) to the list of languages. 2007-09-12 Maxim Dziumanenko * uk.po: Update Ukrainian translation. 2007-09-10 Danilo Å egan * sr.po, sr@Latn.po: Updated Serbian translation. 2007-09-10 Ani Peter * ml.po: Updated Malayalam Translation 2007-09-08 Duarte Loreto * pt.po: Updated Portuguese translation. 2007-09-07 Gabor Kelemen * hu.po: Translation updated. 2007-09-07 Jovan Naumovski * mk.po: Updated Macedonian translation. 2007-09-03 Andre Klapper * de.po: fixing a typo. 2007-09-03 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2007-09-03 Clytie Siddall * vi.po: Updated Vietnamese translation. 2007-09-02 Jovan Naumovski * mk.po: Updated Macedonian translation. 2007-08-29 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan === nemo 2.19.91 === 2007-08-26 Gabor Kelemen * hu.po: Translation updated. 2007-08-24 Kenneth Nielsen * da.po: Updated Danish translation 2007-08-23 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-08-20 Raphael Higino * pt_BR.po: Updated Brazilian Portuguese translation by Vladimir Melo . 2007-08-20 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-08-20 Daniel Nylander * sv.po: Updated Swedish translation. 2007-08-20 Luca Ferretti * it.po: Updated Italian translation. 2007-08-16 Priit Laes * et.po: Estonian translation updates by Ivar Smolin 2007-08-17 Stéphane Raimbault * fr.po: Updated French translation. 2007-08-16 Takeshi AIHANA * ja.po: Updated Japanese translation. 2007-08-16 Priit Laes * et.po: Estonian translation update by Ivar Smolin. 2007-08-16 Ankit Patel * gu.po: Updated Gujarati Translation. 2007-08-15 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2007-08-15 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2007-08-15 Ilkka Tuohela * fi.po: Updated Finnish translation. 2007-08-15 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-08-15 Hendrik Richter * de.po: Updated German translation. 2007-08-15 Hendrik Richter * de.po: intltool-update de 2007-08-15 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2007-08-15 Daniel Nylander * sv.po: Updated Swedish translation. 2007-08-15 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-08-14 Jorge Gonzalez * es.po: Updated Spanish translation 2007-08-13 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-08-13 Ilkka Tuohela * fi.po: Updated Finnish translation. 2007-08-12 Hendrik Richter * de.po: Updated German translation. 2007-08-12 Jovan Naumovski * mk.po: Updated Macedonian translation. 2007-08-09 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-08-09 Kjartan Maraas * nb.po: Updated translation from Espen Stefansen. 2007-08-08 Ankit Patel * gu.po: Updated Gujarati Translation. 2007-08-08 I. Felix * ta.po: Tamil Translation updated by Tirumurthi Vasudevan 2007-08-08 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-08-07 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2007-08-06 Daniel Nylander * sv.po: Updated Swedish translation. 2007-08-05 Leonardo Ferreira Fontenelle * pt_BR.po: s/_Conteúdo/S_umário; see bug #461308. 2007-08-05 Inaki Laranaga Murgoitio * eu.po: Updated Basque translation. 2007-08-05 Leonardo Ferreira Fontenelle * pt_BR.po: Brazilian Portuguese translation updated and reviewed by Og Maciel and me. 2007-08-05 Jorge Gonzalez * es.po: Updated Spanish translation 2007-08-04 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-08-04 Takeshi AIHANA * ja.po: Updated Japanese translation. 2007-08-03 Ihar Hrachyshka * be@latin.po: Updated Belarusian Latin translation. 2007-08-03 Ani Peter * ml.po: Updated Malayalam Translation 2007-08-02 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-07-30 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-07-30 Priit Laes * et.po: Estonian translation update by Ivar Smolin. 2007-07-26 Funda Wang * zh_CN.po: Updated Simplified Chinese translation 2007-07-25 Daniel Nylander * sv.po: Updated Swedish translation. 2007-07-25 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-07-24 Jorge Gonzalez * es.po: Updated Spanish translation 2007-07-24 Priit Laes * et.po: Estonian translation update by Ivar Smolin. 2007-07-24 Luca Ferretti * it.po: Updated Italian translation. 2007-07-21 Leonardo Ferreira Fontenelle * pt_BR.po: Brazilian Portuguese translation updated by Og Maciel . 2007-07-21 Nguyá»…n Thái Ngá»c Duy * vi.po: Updated Vietnamese translation. 2007-07-21 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-07-18 Gabor Kelemen * hu.po: Translation updated - this time really :). 2007-07-18 Gabor Kelemen * hu.po: Translation updated. 2007-07-17 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2007-07-16 Ilkka Tuohela * fi.po: Updated Finnish translation. 2007-07-12 Changwoo Ryu * ko.po: Updated Korean translation by Eunju Kim. 2007-07-08 Takeshi AIHANA * ja.po: Updated Japanese translation. 2007-07-06 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation. 2007-07-04 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation. 2007-07-03 Jovan Naumovski * mk.po: Updated Macedonian translation. 2007-07-02 Nguyá»…n Thái Ngá»c Duy * vi.po: Updated Vietnamese translation. 2007-07-02 Nikos Charonitakis * el.po: Updated el.po to match pot file. 2007-07-02 Nikos Charonitakis * el.po: Updated Greek translation. 2007-07-02 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation. >>>>>>> .r13263 2007-06-29 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-06-29 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-06-29 Changwoo Ryu * ko.po: Updated Korean translation. 2007-06-28 Priit Laes * et.po: Estonian translation update by Ivar Smolin. 2007-06-27 Clytie Siddall * vi.po: Updated Vietnamese translation. 2007-06-27 Thierry Randrianiriana * mg.po: Updated Malagasy translation. 2007-06-26 Guilherme de S. Pastore * ja.po: Fixed typo (Sitcky -> Sticky) in the Japanese translation, as reported by Kobayashi Noritada on the Debian BTS. 2007-06-23 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-06-23 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-06-22 I. Felix * si.po: Sinhala Translation updated by Danishka Navin * LINGUAS: Added Sinhala (si) to The List of Languages. 2007-06-21 Thierry Randrianiriana * mg.po: Updated Malagasy translation. 2007-06-19 Daniel Nylander * sv.po: Updated Swedish translation. 2007-06-19 Jorge Gonzalez * es.po: Updated Spanish translation 2007-06-18 Jorge Gonzalez * es.po: Updated Spanish translation 2007-06-18 Priit Laes * et.po: Estonian translation update by Ivar Smolin. 2007-06-13 Pema Geyleg * dz.po: Updated dzongkha translation 2007-06-13 Yair Hershkovitz * he.po: Updated Hebrew translation. 2007-06-10 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-06-06 Subhransu Behera * or.po: Updated Oriya Translation. 2007-06-05 Subhransu Behera * or.po: Updated Oriya Translation. 2007-06-02 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2007-05-31 Priit Laes * et.po: Updated Estonian translation by Ivar Smolin . 2007-05-29 Hendrik Richter * de.po: Updated German translation, by Daniel Schindler 2007-05-28 Ihar Hrachyshka * be@latin.po: Added Belarusian Latin translation by Ales Navicki. 2007-05-18 Priit Laes * et.po: Updated Estonian translation by Ivar Smolin . 2007-05-18 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-05-15 David Lodge * en_GB.po: Updated British English translation 2007-05-14 Daniel Nylander * sv.po: Updated Swedish translation. === nemo 2.19.2 === 2007-05-12 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2007-05-10 Jorge Gonzalez * es.po: Updated Spanish translation 2007-05-08 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-05-04 Jorge Gonzalez * es.po: Updated Spanish translation 2007-05-03 Daniel Nylander * sv.po: Updated Swedish translation. 2007-05-2 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2007-04-23 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-04-23 David Lodge * en_GB.po: Updated British English translation 2007-04-22 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2007-04-22 Jorge Gonzalez * es.po: Updated Spanish translation. 2007-04-21 Daniel Nylander * sv.po: Updated Swedish translation. 2007-04-15 Christophe Merlet * oc.po: Added Occitan translation from Yannig MARCHEGAY (Kokoyaya) . * LINGUAS: Added "oc". 2007-04-14 Djihed Afifi * ar.po: Updated Arabic Translation by Youssef Chahibi. 2007-04-13 Daniel Nylander * sv.po: Updated Swedish translation. 2007-04-11 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-04-10 Daniel Nylander * sv.po: Updated Swedish translation. 2007-04-08 Leonardo Ferreira Fontenelle * pt_BR.po: Fixes in Brazilian Portuguese translation. Originally sent to branch gnome-2-18. 2007-04-04 Daniel Nylander * sv.po: Updated Swedish translation. 2007-04-02 Jakub Friedl * cs.po: Updated the Czech translation. 2007-03-19 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation from Espen Stefansen. 2007-03-18 Daniel Nylander * sv.po: Updated Swedish translation. 2007-03-17 Jovan Naumovski * mk.po: Updated Macedonian translation. 2007-03-17 Stéphane Raimbault * fr.po: Updated French translation. 2007-03-17 Leonardo Ferreira Fontenelle * pt_BR.po: Fix and update in Brazilian Portuguese translation. 2007-03-17 Takeshi AIHANA * ja.po: Updated Japanese translation. 2007-03-16 Duarte Loreto * pt.po: Updated Portuguese translation. 2007-03-16 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation. 2007-03-16 Ankit Patel * gu.po: Updated Gujarati Translation. 2007-03-15 Ankit Patel * gu.po: Updated Gujarati Translation. === nemo 2.18.0 === 2007-03-14 Runa Bhattacharjee * bn_IN.po: Updated Bengali India Translation. 2007-03-11 Gabor Kelemen * hu.po: Translation updated. 2007-03-08 Jakub Friedl * cs.po: Updated Czech translation. 2007-03-06 Ankit Patel * gu.po: Updated Gujarati Translation. 2007-03-05 Goran Rakić * sr.po, sr@Latn.po: Updated Serbian translation. 2007-03-05 Maxim Dziumanenko * uk.po: Update Ukrainian translation. 2007-03-04 Erdal Ronahi * ku.po: Updated Kurdish translation 2007-03-04 Thierry Randrianiriana * mg.po: Updated Malagasy translation. 2007-03-04 Pema Geyleg * dz.po: Updated Dzongkha Translation. 2007-03-04 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2007-03-03 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2007-03-03 Guillaume Savaton * eo.po: Added Esperanto translation. 2007-02-28 Daniel Nylander * sv.po: Updated Swedish translation. 2007-02-27 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2007-02-27 Hendrik Richter * de.po: Updated German translation. 2007-02-27 Jakub Friedl * cs.po: Updated Czech translation. 2007-02-26 Stéphane Raimbault * fr.po: Fixed French translation by Christophe Bliard and Stéphane Raimbault. === nemo 2.17.92 === 2007-02-25 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-02-24 Nguyá»…n Thái Ngá»c Duy * vi.po: Updated Vietnamese translation. 2007-02-23 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-02-22 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2007-02-22 Abel Cheung * zh_CN.po: Updated simplified Chinese translation on behalf of Funda Wang. 2007-02-21 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2007-02-21 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-02-20 Leonid Kanter * ru.po: Updated Russian translation 2007-02-18 Ole Laursen * da.po: Fixed a problem reported by Armijn Hemel, also updated the translation with the few new strings. 2007-02-18 Priit Laes * et.po: Updated Estonian translation by Ivar Smolin . 2007-02-17 Leonardo Ferreira Fontenelle * pt_BR.po: Updated Brazilian Portuguese translation. 2007-02-16 Takeshi AIHANA * ja.po: Updated Japanese translation. 2007-02-15 Duarte Loreto * pt.po: Updated Portuguese translation. 2007-02-12 Gabor Kelemen * hu.po: Translation updated. 2007-02-12 Ilkka Tuohela * fi.po: Updated Finnish translation. === nemo 2.17.91 === 2007-02-11 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2007-02-11 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2007-02-11 Stéphane Raimbault * fr.po: Updated French translation by Jonathan Ernst. 2007-02-09 David Lodge * en_GB.po: Updated English (British) translation 2007-02-8 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2007-02-08 Luca Ferretti * it.po: Updated Italian translation. 2007-02-07 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-02-07 Ihar Hrachyshka * be.po: Updated Belarusian translation. 2007-02-07 Daniel Nylander * sv.po: Updated Swedish translation. 2007-02-07 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-02-06 Stéphane Raimbault * fr.po: Updated French translation by Jonathan Ernst. 2007-02-05 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2007-02-04 Gabor Kelemen * hu.po: Translation updated. 2007-02-04 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-02-04 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2007-02-03 Ilkka Tuohela * fi.po: Updated Finnish translation. 2007-01-31 Wouter Bolsterlee * nl.po: Translation updated by Wouter Bolsterlee. 2007-01-31 Ihar Hrachyshka * be.po: Updated Belarusian translation. 2007-01-31 Priit Laes * et.po: Updated Estonian translation by Ivar Smolin . 2007-01-27 Stéphane Raimbault * fr.po: Updated French translation by Robert-André Mauchin. 2007-01-26 Luca Ferretti * it.po: Updated Italian translation. 2007-01-24 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2007-01-23 David Lodge * en_GB.po: Updated English (British) translation 2007-01-23 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2007-01-23 Daniel Nylander * sv.po: Updated Swedish translation. 2007-01-15 Yair Hershkovitz * he.po: Updated Hebrew translation. 2007-01-13 Ole Laursen * da.po: Updated Danish translation. 2007-01-10 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2007-01-07 Priit Laes * et.po: Updated Estonian Translation. 2007-01-06 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2007-01-03 Jakub Friedl * cs.po: Updated Czech Translation. 2007-01-03 Djihed Afifi * ar.po: Updated Arabic Translation by Khaled Hosny. 2007-01-01 David Lodge * en_GB.po: Updated English (British) translation 2007-01-01 Daniel Nylander * sv.po: Updated Swedish translation. 2006-12-29 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-12-29 Kjartan Maraas * POTFILES.skip: Add some files. * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-12-29 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-12-27 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-12-26 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-12-26 Luca Ferretti * it.po: Updated Italian translation. 2006-12-24 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-12-24 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2006-12-23 Raivis Dejus * lv.po: Updated Latvian Translation. 2006-12-21 Ales Nyakhaychyk * be.po: Updated Belarusian Translation by Ihar Hrachyshka. 2006-12-20 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-12-20 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-12-18 Francisco Javier F. Serrador * es.po: Updated Spanish translation. === nemo 2.17.1 === 2006-12-18 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-12-15 Luca Ferretti * it.po: Updated Italian translation. 2006-12-15 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-12-14 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-12-13 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-12-11 Lucas Rocha * pt_BR.po: Updated Brazilian Portuguese translation by Leonardo Ferreira Fontenelle 2006-12-11 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-12-07 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-12-04 Luca Ferretti * it.po: Updated Italian translation. 2006-11-28 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-11-28 Daniel Nylander * sv.po: Updated Swedish translation. 2006-11-24 Jovan Naumovski * mk.po: Updated Macedonian translation. 2006-11-24 Yair Hershkovitz * he.po: Updated Hebrew translation. 2006-11-24 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-11-24 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-11-23 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-11-23 Yair Hershkovitz * he.po: Updated Hebrew translation. === nemo 2.16.3 === 2006-11-19 Wouter Bolsterlee * pl.po: Translation updated by wadim dziedzic. 2006-11-19 Matic Zgur * sl.po: Updated Slovenian translation. 2006-11-18 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-11-16 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-11-10 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-11-09 Hendrik Richter * de.po: Updated German translation, fix #372962. 2006-11-9 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-11-08 Priit Laes * et.po: Translation updated by Ivar Smolin. === nemo 2.16.2 === 2006-11-07 Alexander Larsson * POTFILES.in: Update for desktop.in.in change. 2006-11-06 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-11-6 Djihed Afifi * ar.po: Updated Arabic Translation. 2006-11-05 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-11-03 Hendrik Richter * de.po: Updated German translation, fix #369439. 2006-11-03 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-11-01 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-30 Djihed Afifi * ar.po Updated Arabic Translation. 2006-10-30 Satoru SATOH * ja.po: Fixed wrong plural form entries. 2006-10-23 Priit Laes * et.po: Translation updated. 2006-10-23 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-20 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-10-19 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-16 Luca Ferretti * it.po: Updated Italian translation. 2006-10-15 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-10-15 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-15 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-15 Matic Zgur * sl.po: Updated Slovenian translation. 2006-10-12 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-11 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-09 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-10-08 Hendrik Richter * de.po: Updated German translation, fix #331278. 2006-10-07 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-05 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-10-04 Priit Laes * et.po: Translation updated by Ivar Smolin. === nemo 2.16.1 === 2006-10-02 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-09-28 Priit Laes * et.po: Translation updated. 2006-09-27 Luca Ferretti * it.po: Updated Italian translation. 2006-09-26 Jordi Mallach * ca.po: Updated Catalan translation. 2006-09-25 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-09-20 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-09-16 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-09-15 Wouter Bolsterlee * nl.po: Translation updated by Wouter Bolsterlee. 2006-09-12 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-09-09 David Lodge * en_GB.po: Updated British English translation. 2006-09-08 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-09-06 Simos Xenitellis * el.po: Fixed typo, noted by Konstantinos Togias. 2006-09-05 Lucas Rocha * pt_BR.po: Updated Brazilian Portuguese translation by Evandro Fernandes Giovanini . 2006-09-04 Abel Cheung * zh_HK.po: Updated Chinese (Hong Kong) translation. * zh_TW.po: Updated Chinese (Taiwan) translation. 2006-09-04 Runa Bhattacharjee * bn_IN.po: Fixed Fuzzies and changed accelerator keys to English. 2006-09-04 Kostas Papadimas * el.po: Updated Greek translation. 2006-09-04 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2006-09-04 I. Felix * ta.po: Updated Tamil Translation. 2006-09-01 Maxim Dziumanenko * uk.po: Update Ukrainian translation. 2006-09-01 Ani Peter * ml.po: Updated Malayalam translation 2006-09-01 Jovan Naumovski * mk.po: Updated Macedonian translation. 2006-08-31 Duarte Loreto * pt.po: Updated Portuguese translation. 2006-08-31 Ani Peter * ml.po: Updated Malayalam translation 2006-08-31 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2006-08-31 Jovan Naumovski * mk.po: Updated Macedonian translation. 2006-08-30 Jovan Naumovski * mk.po: Updated Macedonian translation. 2006-08-30 Subhransu Behera * or.po: Updated Oriya Translation. 2006-08-30 Gabor Kelemen * hu.po: Translation updated. 2006-08-29 Subhransu Behera * or.po: Updated Oriya Translation. 2006-08-28 Subhransu Behera * or.po: Updated Oriya Translation. 2006-08-28 Subhransu Behera * or.po: Updated Oriya Translation. 2006-08-28 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-27 Gintautas Miliauskas * lt.po: Updated Lithuanian translation. 2006-08-27 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-08-26 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-08-26 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-25 Hendrik Richter * de.po: Updated German translation. 2006-08-25 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-08-24 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-23 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-08-22 Jordi Mas * ca.po: Updates Catalan translation === nemo 2.15.92 === 2006-08-20 Wouter Bolsterlee * nl.po: Translation updated by Wouter Bolsterlee. 2006-08-19 Matic Žgur * sl.po: Updated Slovenian translation. 2006-08-17 Jordi Mas * ca.po: Fixes small mistakes in Catalan translation 2006-08-17 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-08-16 Leonid Kanter * ru.po: Updated Russian translation 2006-08-16 Daniel Nylander * sv.po: Updated Swedish translation. 2006-08-16 Gabor Kelemen * hu.po: Translation updated by Mate ORY. 2006-08-15 Hendrik Richter * de.po: Updated German translation. 2006-08-15 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-15 Satoru SATOH * ja.po: Updated Japanese translation. 2006-08-12 Changwoo Ryu * ko.po: Updated Korean translation. 2006-08-12 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-11 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-08-10 Guntupalli Karunakar * dz.po: Updated Dzongkha translation by Dzongkhalinux team, DIT 2006-08-09 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-08-09 Raivis Dejus * lv.po: Updated Latvian translation. 2006-08-08 Baris Cicek * tr.po: Updated Turkish Translation === nemo 2.15.91 === 2006-08-07 Inaki Larranaga * eu.po: Updated Basque translation. 2006-08-06 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-08-06 Bastien Nocera * en_GB.po: Update British English translation, and made sure Trash wasn't left untranslated (Closes: #325088) 2006-08-05 Alexander Shopov * bg.po: Updated Bulgarian translation with bugfixes prompted by Zlatko Popov 2006-08-03 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-08-03 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-08-02 Ahmad Riza H Nst * id.po: updated. 2006-08-01 Jovan Naumovski * mk.po: Updated Macedonian translation. 2006-08-01 Subhransu Behera * or.po: Updated Oriya Translation. 2006-08-01 Subhransu Behera * or.po: Added New File for Oriya Translation. * LINGUAS: Added Oriya (or) to The List of Languages. 2006-07-31 Hendrik Richter * de.po: Updated German translation. 2006-07-29 Christophe Merlet * fr.po: Updated French translation. 2006-07-29 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-07-28 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-07-27 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-07-27 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2006-07-26 Jakub Friedl * cs.po: Updated Czech translation. 2006-07-25 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-07-25 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-07-23 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2006-07-23 Changwoo Ryu * ko.po: Updated Korean translation. 2006-07-22 Luca Ferretti * it.po: Update Italian translation. 2006-07-22 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-07-21 Kostas Papadimas * el.po: Updated Greek translation 2006-07-18 Guntupalli Karunakar * dz.po: Updated Dzongkha translation by Dzongkhalinux team, DIT 2006-07-17 Hendrik Richter * de.po: Updated German translation. 2006-07-16 Daniel Nylander * sv.po: Updated Swedish translation. 2006-07-14 Priit Laes * et.po: Translation updated. 2006-07-13 Nickolay V. Shmyrev * ru.po: Updated Russian translation 2006-07-09 Jovan Naumovski * mk.po: Updated Macedonian translation 2006-07-08 Alexander Shopov * bg.po: Updated Bulgarian translation by Rostislav Raykov 2006-07-09 Changwoo Ryu * ko.po: Updated Korean translation. 2006-07-08 Inaki Larranaga * eu.po: Updated Basque translation. 2006-07-06 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-07-03 Runa Bhattacharjee * bn_IN.po: Added Bengali India Translation * LINGUAS: Added Bengali India (bn_IN) to the list of languages. 2006-07-03 Benoît Dejean * fr.po: Updated French translation. 2006-07-01 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-06-26 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-06-26 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2006-06-25 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-06-22 I. Felix * ta.po: Updated Tamil translation. 2006-06-22 Jakub Friedl * cs.po: Updated Czech translation. 2006-06-22 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-06-22 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-06-22 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-06-21 Nickolay V. Shmyrev * ru.po: Updated Russian translation. 2006-06-20 Raivis Dejus * lv.po: Updated Latvian translation. 2006-06-19 Jakub Friedl * cs.po: Updated Czech translation. 2006-06-19 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-06-18 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-06-18 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-06-17 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-06-15 Hendrik Richter * de.po: Updated German translation. === nemo 2.15.2 === 2006-06-11 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-06-10 Josep Puigdemont Casamajó * ca.po: Updated Catalan translation. 2006-05-30 Pema Geyleg * dz.po: Updated Dzongkha translation. 2006-05-29 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-05-28 Pema Geyleg * dz.po: updated Dzongkha translation. 2006-05-26 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-05-25 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-05-24 Daniel Nylander * sv.po: Updated Swedish translation. 2006-05-24 Inaki Larranaga * eu.po: Updated Basque translation. 2006-05-23 Jakub Friedl * cs.po: Updated Czech translation. 2006-05-19 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-05-18 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2006-05-18 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-05-16 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-05-13 Jérémy Ar Floc'h * br.po: Updated Breton translation. 2006-05-07 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-05-06 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-05-05 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-05-05 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-05-02 Øivind Hoel * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-05-02 Øivind Hoel * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-05-02 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-05-02 Alexander Larsson * LINGUAS: * mg.po: Add malagasy translation. from Thierry Randrianiriana 2006-05-02 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-05-02 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-04-30 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-04-29 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-04-28 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-04-28 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-04-27 Lukas Novotny * cs.po: Updated Czech translation. 2006-04-27 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-04-23 Chao-Hsiung Liao * zh_HK.po: Updated Traditional Chinese translation(Hong Kong). * zh_TW.po: Updated Traditional Chinese translation(Taiwan). 2006-04-22 Yair Hershkovitz * he.po: Updated Hebrew translation. 2006-04-20 Inaki Larranaga * eu.po: Updated Basque translation. 2006-04-18 Vladimer Sichinava * ka.po: Updated Georgian translation. 2006-04-18 Kjartan Maraas * LINGUAS: Remove obsolete entry for no_NO * no.po: And the translation. 2006-04-16 Ã…smund Skjæveland * nn.po: Updated Norwegian Nynorsk translation. 2006-04-16 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-04-15 Jérémy Ar Floc'h * br.po: Added Breton translation. * LINGUAS: Added Breton (br). 2006-04-14 Miloslav Trmac * cs.po: Updated Czech translation by Lukas Novotny. 2006-04-14 Ã…smund Skjæveland * nn.po: Updated Norwegian Nynorsk translation. 2006-04-14 Yair Hershkovitz * he.po: Updated Hebrew translation. 2006-04-12 Hendrik Richter * de.po: Updated German translation. 2006-04-12 Takeshi AIHANA * ja.po: Updated Japanese translation. 2006-04-10 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2006-04-08 Nikos Charonitakis * el.po: Updated Greek translation. 2006-04-05 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-04-03 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-04-02 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same. 2006-04-02 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-04-01 Yair Hershkovitz * he.po: Updated Hebrew translation. 2006-03-30 Lukas Novotny * cs.po: Updated Czech translation. 2006-03-30 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-03-28 Rhys Jones * cy.po: Updated Welsh translation. 2006-03-28 Ole Laursen * da.po: Fixed a few strings in Danish translation. 2006-03-25 Nikos Charonitakis * el.po: Updated Greek translation. 2006-03-21 Kostas Papadimas * el.po: Updated Greek Translation. 2006-03-21 Gabor Kelemen * hu.po: Hungarian translation updated by Mate ORY. 2006-03-20 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-03-20 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2006-03-20 Laurent Dhima * sq.po: Updated Albanian translation. 2006-03-20 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2006-03-20 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-03-19 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-03-19 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-03-19 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-03-19 Vincent van Adrighem * nl.po: Translation updated by Tino Meinen. 2006-03-19 Daniel Nylander * sv.po: Updated Swedish Translation. 2006-03-19 Kostas Papadimas * el.po: Updated Greek Translation. 2006-03-18 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-03-18 Guilherme de S. Pastore * pt_BR.po: Updated Brazilian Portuguese translation. 2006-03-18 Luca Ferretti * it.po: Updated Italian translation. 2006-03-18 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-03-17 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-03-17 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-03-17 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-03-17 Vladimer Sichinava * ka.po: Updated Georgian translation. 2006-03-14 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-03-13 Benoît Dejean * fr.po: Updated French translation. === nemo 2.14.0 === 2006-03-13 Runa Bhattacharjee * bn.po: Updated Bengali Translation. 2006-03-13 Lucas Rocha * pt_BR.po: Updated Brazilian Portuguese translation. 2006-03-12 Miloslav Trmac * cs.po: Updated Czech translation by Petr TomeÅ¡. 2006-03-11 Guilherme de S. Pastore * pt_BR.po: Updated Brazilian Portuguese translation. 2006-03-08 Luca Ferretti * it.po: Updated Italian translation. 2006-03-08 Kjartan Maraas * nn.po: Updated Norwegian nynorsk translation. 2006-03-06 Rajesh Ranjan * hi.po: Updated Hindi Translation. 2006-03-07 Priit Laes * et.po: Translation updated by Ivar Smolin. 2006-03-06 Daniel Nylander * sv.po: Updated Swedish translation 2006-03-05 Mugurel Tudor * ro.po: Updated Romanian translation 2006-03-04 Duarte Loreto * pt.po: Updated Portuguese translation. 2006-03-03 Maxim Dziumanenko * uk.po: Updated Ukrainian translation. 2006-02-03 Øivind Hoel * nb.po: Updated Norwegian bokmÃ¥l translation. 2006-03-02 Hendrik Richter * de.po: Updated German translation. 2006-03-02 Hendrik Richter * de.po: Updated German translation. 2006-03-02 Stanislav Brabec * km.po: Added initial Khmer translation from Keo Sophon and Leang Chumsoben based on SuSE gnome-patch-translation. 2006-02-28 Miloslav Trmac * cs.po: Updated Czech translation by Petr TomeÅ¡. 2006-02-27 Lasse Bang Mikkelsen * da.po: Updated Danish translation. === nemo 2.13.92 === 2006-02-27 Inaki Larranaga * eu.po: Fixed some typos. 2006-02-26 Lasse Bang Mikkelsen * da.po: Updated Danish translation. 2006-02-26 Ales Nyakhaychyk * be.po: Updated Belarusian translation by Ihar Hrachyshka 2006-02-25 Chao-Hsiung Liao * zh_TW.po: Updated Traditional Chinese translation(Taiwan). * zh_HK.po: Added Traditional Chinese translation(Hong Kong). 2006-02-23 Leonid Kanter * ru.po: Updated Russian translation 2006-02-23 Clytie Siddall * ka.po: Added Georgian translation by Alexander Didebulidze and Vladimer Sichinava . 2006-02-22 Inaki Larranaga * eu.po: Updated Basque translation. 2006-02-20 Theppitak Karoonboonyanan * th.po: Adjusted Thai translation. 2006-02-20 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2006-02-19 Takeshi AIHANA * ja.po: Updated Japanese translation. 2006-02-17 Kostas Papadimas * el.po: Updated Greek Translation. 2006-02-16 Rhys Jones * cy.po: Updated Welsh translation. 2006-02-16 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-02-16 Hendrik Richter * de.po: Updated German translation. 2006-02-15 Gabor Kelemen * hu.po: Hungarian translation updated by Mate ORY. 2006-02-13 Jakub Friedl * cs.po: Updated Czech translation === nemo 2.13.91 === 2006-02-11 Luca Ferretti * ut.po: Updated Italian translation 2006-02-10 Priit Laes * et.po: Translation updated. 2006-02-06 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2006-02-06 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-02-04 Laurent Dhima * sq.po: Updated Albanian translation. 2006-02-03 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same. 2002-02-02 Leonid Kanter * ru.po: fixed Russian translation 2006-02-02 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-02-01 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-02-01 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-02-01 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-02-01 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-01-31 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2006-01-31 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2006-01-31 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-01-31 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-01-31 Slobodan D. Sredojevic * sr.po, sr@Latn.po: Updated Serbian translation 2006-01-30 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-01-30 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-01-29 Erdal Ronahi * ku.po: Updated Kurdish translations. 2006-01-29 Gabor Kelemen * hu.po: Hungarian translation updated. 2006-01-29 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-01-29 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-01-29 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-01-26 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2006-01-25 Nickolay V. Shmyrev * ru.po: Update Russian translation by Artem Tuchinsky . 2006-01-23 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2006-01-22 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same. 2006-01-22 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-01-21 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-01-21 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2006-01-19 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-01-19 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-01-19 Satoru SATOH * ja.po: Updated Japanese translation 2006-01-18 Luca Ferretti * it.po: Updated Italian translation 2006-01-18 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2006-01-18 Ankit Patel * gu.po: Updated Gujarati Translation. 2006-01-17 Vincent van Adrighem * nl.po: Translation updated by Tino Meinen. 2006-01-16 Ilkka Tuohela * fi.po: Updated Finnish translation. 2006-01-16 Adam Weinberger * en_CA.po: Updated Canadian English translation. === nemo 2.13.4 === 2006-01-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2006-01-14 Gabor Kelemen * hu.po: Hungarian translation updated. 2006-01-14 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2006-01-14 Clytie Siddall * vi.po: Updated Vietnamese translation. 2006-01-12 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-01-11 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2006-01-09 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2006-01-08 Nikos Charonitakis * el.po: Updated Greek translation. 2006-01-06 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation * no.po: Updated Norwegian bokmÃ¥l translation 2006-01-03 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2006-01-02 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2006-01-02 Josep Puigdemont i Casamajó * ca.po: Updated Catalan translation. 2006-01-02 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same. 2005-12-31 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-30 Clytie Siddall * vi.po: Updated Vietnamese translation. 2005-12-28 Marcel Telka * sk.po: Updated Slovak translation. 2005-12-26 Ilkka Tuohela * fi.po: Updated Finnish translation. 2005-12-25 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-12-21 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-12-21 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-12-20 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-12-21 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-20 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-12-20 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-12-20 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-12-19 Alexander Larsson * POTFILES.in: Add missing files. 2005-12-19 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-12-18 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-17 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-12-17 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-12-17 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-12-16 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-12-15 Ilkka Tuohela * fi.po: Updated Finnish translation. 2005-12-14 Marcel Telka * sk.po: Updated Slovak translation. 2005-12-14 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-12-14 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-12-14 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-12-13 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-12-13 Theppitak Karoonboonyanan * th.po: Updated Thai translation. === nemo 2.13.3 === 2005-12-12 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-12-12 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-11 Miloslav Trmac * cs.po: Updated Czech translation. 2005-12-11 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-12-11 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-12-11 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same 2005-12-10 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-12-10 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-09 Ignacio Casal Quinteiro * gl.po: Updated Galician Translations. 2005-12-09 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-12-06 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-12-06 Ales Nyakhaychyk * be.po: Updated Belarusian translation by Vital Khilko. 2005-12-04 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-12-03 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-12-03 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same 2005-12-02 Miloslav Trmac * cs.po: Updated Czech translation. 2005-11-25 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-11-25 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-11-25 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-11-24 Marcel Telka * sk.po: Updated Slovak translation. 2005-11-24 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-11-21 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-11-21 Francisco Javier F. Serrador * es.po: #321973 Bug fix. 2005-11-20 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-11-19 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-11-17 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-11-17 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-11-17 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-11-17 Priit Laes * et.po: Translation updated. 2005-11-15 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-11-14 Marcel Telka * sk.po: Updated Slovak translation. 2005-11-14 Francisco Javier F. Serrador * es.po: Updated Spanish translation === nemo 2.13.2 === 2005-11-14 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-11-14 Ales Nyakhaychyk * be.po: Updated Belarusian translation by Vital Khilko. 2005-11-14 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-11-07 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-11-03 Miloslav Trmac * cs.po: Updated Czech translation. 2005-10-30 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-10-28 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-10-26 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-10-25 Marcel Telka * sk.po: Updated Slovak translation. === nemo 2.13.1 === 2005-10-23 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-10-21 Alexander Shopov * bg.po: Updated Bulgarian translation by Alexander Shopov 2005-10-15 Vincent van Adrighem * nl.po: Translation updated. 2005-10-13 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-10-13 Funda Wang * zh_CN.po: Corrected a typo of Simplified Chinese translation. 2005-10-05 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-10-04 Priit Laes * et.po: Translation updated by Ivar Smolin. === nemo 2.12.1 === 2005-09-29 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-09-25 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2005-09-24 Erdal Ronahi * ku.po: Updated Kurdish translation. 2005-09-18 Christian Rose * sv.po: Updated Swedish translation. 2005-09-16 Clytie Siddall * vi.po: Updated Vietnamese translation. 2005-09-14 Runa Bhattacharjee * bn.po: Updated Bengali (bn) Translation by Progga 2005-09-10 Erdal Ronahi * ku.po: Added Kurdish translation 2005-09-07 Inaki Larranaga * eu.po: Updated Basque translation. === nemo 2.12.0 === 2005-09-04 Hendrik Richter * de.po: Updated German translation. 2005-09-03 Danilo Å egan * sr.po, sr@Latn.po: Updated. 2005-09-02 Choe Hwanjin * ko.po: Updated Korean translation by Young-Ho Cha. 2005-09-01 Baris Cicek * tr.po: Updated Turkish Translation 2005-09-01 Ignacio Casal Quinteiro * gl.po: Updated Galician Translation. 2005-09-01 Francisco Javier F. Serrador * es.po: UPdated Spanish translation. 2005-08-31 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2005-08-31 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-08-31 Hendrik Richter * de.po: Updated German translation. 2005-08-30 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-08-30 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha. 2005-08-28 Mohammad DAMT * id.po: Updated Indonesian translation. 2005-08-28 Christophe Merlet * fr.po: Updated French translation. 2005-08-27 Josep Puigdemont * ca.po: Updated Catalan translation by Jordi Mallach 2005-08-27 Clytie Siddall * vi.po: Updated Vietnamese translation. 2005-08-27 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2005-08-24 Chao-Hsiung Liao * zh_TW.po: Updated Traditional Chinese translation. 2005-08-24 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-08-22 Mugurel Tudor * ro.po: Updated Romanian translation 2005-08-22 Changwoo Ryu * ko.po: Updated Korean translation. 2005-08-20 Maxim Dziumanenko * uk.po: Updated Ukrainian translataion. 2005-08-20 Roozbeh Pournader * fa.po: Upldated Persian translation by Elnaz Sarbar and myself. 2005-08-19 Rhys Jones * cy.po: Updated Welsh translation. 2005-08-19 Jens Seidel * de.po: Various typo fixes. 2005-08-19 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-08-17 Mugurel Tudor * ro.po: Updated Romanian translation 2005-08-17 Laurent Dhima * sq.po: Updated Albanian translation. 2005-08-16 Gabor Kelemen * hu.po: Hungarian translation updated. 2005-08-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-08-14 Terance Sola * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same. 2005-08-11 Duarte Loreto * pt.po: Updated Portuguese translation. 2005-08-10 Sigurd Gartmann * nn.po: Updated Norwegian Nynorsk translation. 2005-08-09 Leonid Kanter * ru.po: Updated Russian translation 2005-08-09 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-08-08 Sunil Mohan Adapa * te.po: Updated Telugu translation done by M.A.Kaleem Shyam Kalakoti 2005-08-07 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-08-07 Raphael Higino * pt_BR.po: Updated Brazilian Portuguese translation. 2005-08-06 Mohammad DAMT * id.po: Updated Indonesian translation 2005-08-06 Alexander Shopov * bg.po: Updated Bulgarian translation by Rostislav Raykov 2005-08-06 Kostas Papadimas * el.po Updated Greek Translation 2005-08-05 Miloslav Trmac * cs.po: Updated Czech translation. 2005-08-05 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-08-05 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2005-08-05 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-08-04 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-08-04 Sunil Mohan Adapa * te.po: Added Telugu translation done by Prajasakti Localisation Team 2005-08-04 Clytie Siddall * vi.po: Updated Vietnamese translation. 2005-08-04 Gabor Kelemen * hu.po: Hungarian translation updated. 2005-08-04 Marcel Telka * sk.po: Updated Slovak translation. 2005-08-04 Ilkka Tuohela *fi.po: Updated Finnish translation. 2005-08-03 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same 2005-08-03 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-08-02 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-08-01 Vincent van Adrighem * nl.po: Translation updated. 2005-07-31 Ilkka Tuohela * fi.po: Bulk updates to Finnish translation for new gnome.fi website. 2005-07-31 Pawan Chitrakar * ne.po: Updated Nepali Translation 2005-07-30 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2005-07-29 Ilkka Tuohela * fi.po: Updated Finnish translation. 2005-07-28 Ilkka Tuohela * fi.po: Bulk change to some Finnish translations. 2005-07-26 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-07-24 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same 2005-07-23 Clytie Siddall * vi.po: Updated Vietnamese translation. 2005-07-23 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-07-21 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation by Justina KlingaitÄ— and me. 2005-07-21 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-07-21 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-07-18 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-07-18 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-07-18 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-07-17 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-07-17 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-07-16 Yair Hershkovitz *he.po: Updated Hebrew translation. 2005-07-16 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. * no.po: Same 2005-07-14 Miloslav Trmac * cs.po: Updated Czech translation. 2005-07-14 Priit Laes * et.po: Translation updated. 2005-07-13 Marcel Telka * sk.po: Updated Slovak translation. 2005-07-12 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-07-12 Marcel Telka * sk.po: Updated Slovak translation. 2005-07-12 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-07-11 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-07-11 Theppitak Karoonboonyanan * th.po: Updated Thai translation. === nemo 2.11.4 === 2005-07-10 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-07-10 Danilo Å egan * sr.po, sr@Latn.po: Updated Serbian translation. 2005-07-10 Miloslav Trmac * cs.po: Updated Czech translation. 2005-07-10 Yair Hershkovitz * he.po: Updated Hebrew translation. 2005-07-10 Theppitak Karoonboonyanan * th.po: Updated Thai translation. 2005-07-09 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-07-08 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-07-08 Alexander Larsson * POTFILES.in: Added src/nemo-pathbar.c 2005-07-08 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-07-07 Alexander Shopov * bg.po: Updated Bulgarian translation by Rostislav Raykov 2005-07-06 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-07-06 Marcel Telka * sk.po: Updated Slovak translation. 2005-07-06 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-07-04 Hendrik Richter * de.po: Fixed German translation by Jens Seidel . 2005-07-04 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-07-04 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-07-03 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-07-03 Priit Laes * et.po: Translation updated. 2005-07-02 Takeshi AIHANA * ja.po: Updated Japanese translation. === nemo 2.11.3 === 2005-07-01 Alexander Larsson * POTFILES.in: Add places sidebar. 2005-07-01 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-06-30 Terance Sola * nb.po: Updated Norwegian bokml translation. * no.po: Same. 2005-06-27 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-06-27 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-06-27 Alexander Larsson * POTFILES.in: Add new files. 2005-06-26 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-06-24 Kjartan Maraas * nb.po: Updated Norwegian translation. * no.po: Same 2005-06-22 Abel Cheung * zh_TW.po: Fix language team reference. 2005-06-23 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-06-22 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-06-20 Alexander Larsson * POTFILES.in: Added fm-list-model.c 2005-06-17 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-06-14 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-06-12 Kjartan Maraas * nb.po: Update Norwegian bokml translation. * no.po: Same 2005-06-12 Priit Laes * et.po: Translation updated. 2005-06-12 Miloslav Trmac * cs.po: Updated Czech translation. 2005-06-12 Ignacio Casal Quinteiro * gl.po: Updated Galician translation. 2005-06-11 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-06-10 Alexander Shopov * bg.po: Updated Bulgarian translation by Rostislav Raykov 2005-06-08 Adam Weinberger * en_CA.po: Updated Canadian English translation. === nemo 2.11.2 === 2005-06-07 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-06-07 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-06-07 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-06-06 Ignacio Casal Quinteiro * gl.po: Updated Galician translation from Jess Bravo lvarez. 2005-06-07 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-06-06 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-06-06 Priit Laes * et.po: Translation updated. 2005-06-05 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-06-03 Christian Neumair * POTFILES.in: * POTFILES.skip: Remove libbackground/applier.c from POTFILES.in. 2005-06-02 Pawan Chitrakar * ne.po: Updated Nepali Translation 2005-06-01 Priit Laes * et.po: Translation updated. 2005-06-01 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-05-31 Terance Sola * nb.po: Updated * no.po: Updated 2005-05-29 Miloslav Trmac * cs.po: Updated Czech translation. 2005-05-27 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-05-27 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-05-26 Rhys Jones * cy.po: Merged minor updates from gnome-2-10 branch. 2005-05-25 Kjartan Maraas * nb.po: Update * no.po: Update 2005-05-23 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-05-22 Miloslav Trmac * cs.po: Updated Czech translation. 2005-05-19 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-05-18 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-05-18 Takeshi AIHANA * ja.po: Updated Japanese translation. === nemo 2.11.1 === 2005-05-15 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-05-14 Hendrik Richter * de.po: Updated German translation. 2005-05-13 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2005-05-13 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2005-05-12 David Zeuthen * zh_TW.po: Revert default font to "Sans 10" * gu.po: Revert default font to "Sans 10" 2005-05-12 Miloslav Trmac * cs.po: Updated Czech translation. 2005-05-11 Rajesh Ranjan *hi.po Updated Hindi Translation 2005-05-11 Kostas Papadimas *el.po Updated Greek Translation 2005-05-09 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-04-30 Miloslav Trmac * cs.po: Updated Czech translation. 2005-04-29 Priit Laes * et.po: Translation updated by Sven Sapelson. 2005-04-28 Kostas Papadimas * el.po: Updated Greek translation 2005-04-24 Gabor Kelemen * hu.po: Hungarian translation updated. 2005-04-22 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-04-19 David Lodge * en_GB.po: Updated British English translation. 2005-04-19 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-04-18 Gareth Owen * en_GB.po: Updated British English translation 2005-04-18 Gabor Kelemen * hu.po: Hungarian translation updated. 2005-04-11 Vincent van Adrighem * nl.po: Translation updated by Maarten Grachten. 2005-04-09 Miloslav Trmac * cs.po: Updated Czech translation. 2005-04-05 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-03-31 Steve Murphy * rw.po: Added Kinyarwanda translation. 2005-03-30 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-03-30 Josep Puigdemont * ca.po: Updated Catalan translation. 2005-03-29 Adi Attar * xh.po: Updated Xhosa translation. 2005-03-28 Abel Cheung * zh_TW.po: Updated traditional Chinese translation from GNOME HK Team 2005-03-26 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-03-26 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-03-25 Josep Puigdemont * ca.po: Updated Catalan translation. 2005-03-22 Duarte Loreto * pt.po: Updated Portuguese translation. 2005-03-22 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-03-22 Laurent Dhima * sq.po: Updated Albanian translation. 2005-03-22 Christian Rose * POTFILES.in: Added missing file entry. * sv.po: Updated Swedish translation. 2005-03-21 Takeshi AIHANA * ja.po: Fixed wrong translations. 2005-03-17 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-03-16 Roozbeh Pournader * fa.po: Updated Persian translation by Behnam Pournader . 2005-03-14 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-03-12 Baris Cicek * tr.po: Updated Turkish Translation 2005-03-10 Adi Attar * xh.po: Added Xhosa translation. 2005-03-07 Theppitak Karoonboonyanan * th.po: Updated Thai translation by Supranee Thirawatthanasuk. 2005-03-07 Martin Willemoes Hansen * da.po: Updated Danish translation. === nemo 2.10.0 === 2005-03-07 Mugurel Tudor * ro.po: Updated Romanian translation 2005-03-04 Dafydd Harries * cy.po: Updated Welsh translation. 2005-03-04 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation by Gintautas Miliauskas. 2005-03-03 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-03-02 Danilo Å egan * sr.po, sr@Latn.po: Updated Serbian translation. 2005-03-01 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2005-03-01 Alexander Larsson * POTFILES.skip: * POTFILES.in: Move some old unused files to .skip for now === nemo 2.9.92 === 2005-03-01 Alexander Larsson * POTFILES.in: Remove old files 2005-03-01 Abel Cheung * zh_TW.po: Updated traditional Chinese translation from GNOME HK Team 2005-02-28 Kostas Papadimas * el.po: Updated Greek translation. 2005-02-27 Nikos Charonitakis * el.po: Updated Greek translation. 2005-02-15 Jordi Mallach * ca.po: Updated Catalan translation. 2005-02-25 Ankit Patel * gu.po: Updated Gujarati Translation. 2005-02-24 Raphael Higino * pt_BR.po: Updated Brazilian Portuguese translation. 2005-02-24 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2005-02-24 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-02-22 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-02-22 Martin Willemoes Hansen * da.po: Updated Danish translation. 2005-02-20 Kjartan Maraas * nb.po: Spellcheck a bit * no.po: same 2005-02-20 Christophe Merlet * fr.po: Updated French translation from Vincent Carriere . 2005-02-18 Pauli Virtanen * fi.po: Updated Finnish translation. 2005-02-18 Kostas Papadimas * el.po: Updated Greek translation. 2005-02-18 Duarte Loreto * pt.po: Updated Portuguese translation. 2005-02-18 Changwoo Ryu * ko.po: Updated Korean translation. 2005-02-17 Laurent Dhima * sq.po: Updated Albanian translation. 2005-02-16 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2005-02-15 Jordi Mallach * ca.po: Updated Catalan translation. 2005-02-15 Kjartan Maraas * nb.po: Fix typo. * no.po: Same 2005-02-14 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-02-14 Hendrik Richter * de.po: Updated German translation. 2005-02-14 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-02-12 Laszlo Dvornik * hu.po: Hungarian translation updated by Gabor Kelemen. 2005-02-12 Maxim Dziumanenko * uk.po: Updated Ukrainian translation. 2005-02-12 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-02-10 Priit Laes * et.po: Translation updated. 2005-02-10 Priit Laes * et.po: Translation updated by Ivar Smolin. === nemo 2.9.91 === 2005-02-10 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-02-09 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-02-08 Leonid Kanter * ru.po: Updated Russian translation 2005-02-08 Hendrik Richter * de.po: Updated German translation. 2005-02-08 Kjartan Maraas * nb.po: Update * no.po: Update 2005-02-07 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-02-07 David Lodge * en_GB.po: Updated British translation. 2005-02-07 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-02-06 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-02-06 Nikos Charonitakis * el.po: Updated Greek translation. 2005-02-06 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-02-06 Miloslav Trmac * cs.po: Updated Czech translation. 2005-02-06 Christian Rose * sv.po: Updated Swedish translation. 2005-02-06 Pauli Virtanen * fi.po: Updated Finnish translation. 2005-02-05 Kostas Papadimas * el.po: Updated Greek translation. 2005-02-04 Gil Osher * he.po: Updated Hebrew translation. 2005-02-03 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-02-03 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-02-02 Priit Laes * et.po: Translation updated by Ivar Smolin. 2005-02-02 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2005-02-01 Jordi Mallach * ca.po: Updated Catalan translation. 2005-02-01 Kjartan Maraas * nb.po: Update * no.po: Update 2005-02-01 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-02-01 Changwoo Ryu * ko.po: Updated Korean translation. 2005-01-31 Miloslav Trmac * cs.po: Updated Czech translation. 2005-01-31 Christian Rose * sv.po: Updated Swedish translation. 2005-01-31 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-01-30 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-01-29 Priit Laes * et.po: Translation updated. 2005-01-29 Miloslav Trmac * cs.po: Updated Czech translation. 2005-01-28 Kjartan Maraas * nb.po: Update 2005-01-26 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-26 Marcel Telka * sk.po: Updated Slovak translation. 2005-01-26 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-26 Leonid Kanter * ru.po: Updated Russian translation 2005-01-26 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-01-25 Francisco Javier Fernandez * es.po: Updated Spanish translation. 2005-01-25 Adam Weinberger * en_CA.po: Updated Canadian English translation. === nemo 2.9.90 === 2005-01-25 Hendrik Richter * de.po: Updated German translation. 2005-01-24 Duarte Loreto * pt.po: Updated Portuguese translation. 2005-01-24 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-24 Hendrik Richter * de.po: Updated German translation. 2005-01-23 Ch4ristian Rose * POTFILES.in: Sorted. * sv.po: Updated Swedish translation. 2005-01-23 Hendrik Richter * de.po: Updated German translation. 2005-01-22 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2005-01-21 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-21 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-21 Kjartan Maraas * nn.po: Update this. 2005-01-21 Rhys Jones * cy.po: Corrected further minor typos in Welsh translation. 2005-01-20 Frank Arnold * de.po: Updated German translation. 2005-01-20 Miloslav Trmac * cs.po: Updated Czech translation. 2005-01-20 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-20 Christian Rose * sv.po: Updated Swedish translation. 2005-01-20 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2005-01-20 Rhys Jones * cy.po: Updated Welsh translation with new strings + many fixes. 2005-01-19 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-19 Kjartan Maraas * POTFILES.in: Add [endcoding: UTF-8] * nb.po: Update * no.po: Update 2005-01-17 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-17 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2005-01-16 Hendrik Richter * de.po: Updated German translation. 2005-01-16 Priit Laes * et.po: Translation updated. 2005-01-15 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-15 Christian Rose * sv.po: Updated Swedish translation. 2005-01-15 Kjartan Maraas * POTFILES.in: Add nemo-connect-to-server-dialog-main.c * nb.po: Update * no.po: Update 2005-01-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-13 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-13 Christian Rose * sv.po: Updated Swedish translation. 2005-01-13 Christian Rose * sv.po: Updated Swedish translation. 2005-01-12 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2005-01-10 Raphael Higino * pt_BR.po: Updated Brazilian Portuguese translation. 2005-01-12 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2005-01-11 Takeshi AIHANA * ja.po: Updated Japanese translation. 2005-01-11 Adam Weinberger * en_CA.po: Updated Canadian English translation. === nemo 2.9.2 === 2005-01-07 Kjartan Maraas * nb.po: Fixety fix * no.po: Fixfixety fix 2005-01-04 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-12-21 Christian Rose * sv.po: Updated Swedish translation. 2004-12-20 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2004-12-17 Laurent Dhima * sq.po: Updated Albanian translation. 2004-12-13 David Lodge * en_GB.po: Updated British translation. 2004-12-13 Dwayne Bailey * zu.po: Added Zulu translation by Zuza Software Foundation . 2004-12-11 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-12-08 Christian Rose * tr.po: Reverted broken tr.po update that broke the nemo build. 2004-12-05 Baris Cicek * tr.po: Fixed typo in Turkish Translation 2004-12-03 Žygimantas BeruÄka * lt.po: Updated Lithuanian translation. 2004-11-29 Dwayne Bailey * nso.po: Added Northern Sotho translation by Zuza Software Foundation . 2004-11-28 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-11-25 Kjartan Maraas * nb.po: Updated Norwegian bokmÃ¥l translation. 2004-11-25 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-11-24 Adam Weinberger * en_CA.po: Updated Canadian English translation. === nemo 2.9.1 === 2004-11-24 Miloslav Trmac * cs.po: Updated Czech translation. 2004-11-23 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-11-22 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-11-22 Alexander Larsson * POTFILES.in: * POTFILES.skip: Update after merge 2004-11-20 Marcel Telka * sk.po: Fixed typos. 2004-11-19 Hendrik Richter * de.po: Updated German translation. 2004-11-15 Meelad Zakaria * fa.po: Updated Persian translation. 2004-11-14 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2004-11-13 Meelad Zakaria * fa.po: Updated Persian translation. 2004-11-11 Alessio Frusciante * it.po: Updated translation by Luca Ferretti . 2004-11-09 Gustavo Noronha Silva * pt_BR.po: fixed strings which had mnemonics but should not (fix up-ported from gnome-2-8 branch) - Fixes http://bugzilla.gnome.org/show_bug.cgi?id=157252 === nemo 2.8.2 === 2004-10-25 Mohammad DAMT * id.po: Updated Indonesian translation 2004-10-22 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-10-19 Laszlo Dvornik * hu.po: Hungarian translation updated. 2004-10-19 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-10-17 Raphael Higino * pt_BR.po: Updated Brazilian Portuguese translation. 2004-10-17 Christophe Merlet * fr.po: Updated French translation. 2004-10-17 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-10-17 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-10-14 Miloslav Trmac * cs.po: Updated Czech translation. 2004-10-14 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-10-14 Laurent Dhima * sq.po: Updated Albanian translation. 2004-10-13 David Lodge * en_GB.po: Updated British English translation. 2004-10-13 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. === nemo 2.8.1 === 2004-10-05 Leonid Kanter * ru.po: More fixes 2004-10-03 Leonid Kanter * ru.po: Fixed Russian translation 2004-10-03 Christophe Merlet * fr.po: Updated French translation. Close #154290. 2004-09-29 Sebastien Bacher * fr.po: Fix in the French translation. 2004-09-26 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-09-24 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2004-09-15 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-09-15 Arafat Medini * ar.po: Updated Arabic translation. 2004-09-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-09-14 Alexander Larsson * ar.po: Fix up spaces. 2004-09-13 Kjartan Maraas * nb.po: Updated after getting comments from Sigurd Gartmann. * no.po: Same. === nemo 2.8.0 === 2004-09-12 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-09-12 Akagic Amila * bs.po: Updated Bosnian translation. 2004-09-12 Laszlo Dvornik * hu.po: Updated Hungarian translation by Gabor Kelemen. 2004-09-11 Dafydd Harries * cy.po: Updated Welsh translation. 2004-09-11 Abel Cheung * zh_TW.po: Updated traditional Chinese translation by GNOME HK Team. * ar.po, he.po: Mark wrong entry as fuzzy (msgfmt check failed). 2004-09-11 Christophe Merlet * fr.po: Updated French translation from Sebastien Bacher . 2004-09-09 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-09-08 Abel Cheung * zh_TW.po: Updated traditional Chinese translation by GNOME HK Team. 2004-09-08 Mugurel Tudor * ro.po: Corrected Romanian translation 2004-09-08 Mugurel Tudor * ro.po: Updated Romanian translation 2004-09-07 Alexander Shopov * bg.po: Updated Bulgarian translation 2004-09-07 Laszlo Dvornik * hu.po: Updated Hungarian translation. 2004-09-07 Nikos Charonitakis * el.po: Updated Greek translation. 2004-09-07 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2004-09-07 David Lodge * en_GB.po: Updated British translation. 2004-09-06 Kostas Papadimas * el.po: Updated Greek translation. 2004-09-05 Miloslav Trmac * cs.po: Updated Czech translation. 2004-09-04 MÉ™tin Æmirov * az.po: Translation updated. 2004-09-04 Baris Cicek * tr.po: Updated Turkish Translation 2004-09-04 Miloslav Trmac * cs.po: Updated Czech translation. 2004-09-03 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-09-02 Hendrik Richter * de.po: Updated German translation 2004-09-02 Alessio Frusciante * it.po: Updated Italiant translation by Luca Ferretti . 2004-09-02 Runa Bhattacharjee * bn.po: Updated Bengali(bn) Translation. 2004-08-31 Ã…smund Skjæveland * nn.po: Updated Norwegian Nynorsk translation. 2004-08-30 Jordi Mallach * ca.po: Updated Catalan translation. 2004-08-30 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-08-29 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2004-08-28 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-08-26 Nikos Charonitakis * el.po: Updated Greek translation. 2004-08-26 Gediminas Paulauskas * POTFILES.in: remove libnemo-private/nemo-program-chooser.c * lt.po: Updated Lithuanian translation. 2004-08-25 Maxim Dziumanenko * uk.po: Updated Ukrainian translation. 2004-08-24 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation done by Raphael Higino . 2004-08-23 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-08-23 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-08-22 Laszlo Dvornik * hu.po: Updated Hungarian translation. 2004-08-21 Changwoo Ryu * ko.po: Updated Korean translation. 2004-08-21 Danilo Å egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-08-21 Leonid Kanter * ru.po: Updated Russian translation 2004-08-21 Kjartan Maraas * nb.po: Update * no.po: these 2004-08-20 Laurent Dhima * sq.po: Updated Albanian translation. 2004-08-19 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-08-18 Pauli Virtanen * fi.po: Updated Finnish translation. 2004-08-18 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-08-18 Miloslav Trmac * cs.po: Updated Czech translation. 2004-08-18 Laurent Dhima * sq.po: Updated Albanian translation. 2004-08-18 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-08-18 Laurent Dhima * sq.po: Updated Albanian translation. 2004-08-17 Ankit Patel * gu.po: Updated Final Gujarati Translation. 2004-08-17 Christian Rose * sv.po: Updated Swedish translation. 2004-08-17 Duarte Loreto * pt.po: Updated Portuguese translation. 2004-08-16 Christian Rose * bs.po: Added Bosnian translation by Kenan Hadžiavdić . 2004-08-16 Kjartan Maraas * nb.po: Add this. 2004-08-17 Metin Amiroff * az.po: Translation updated. 2004-08-16 Francisco Javier F. Serrador * es.po: Updated Spanish translation. === nemo 2.7.4 === 2004-08-16 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-08-16 Laszlo Dvornik * hu.po: Updated Hungarian translation. 2004-08-16 Ankit Patel * gu.po: Updated Final Gujarati Translation. 2004-08-16 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-08-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-08-14 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-08-14 Gediminas Paulauskas * lt.po: Updated Lithuanian translation. 2004-08-13 Duarte Loreto * pt.po: Updated Portuguese translation. 2004-08-13 Tommi Vainikainen * fi.po: Unified some fields in po headers for Finnish team. 2004-08-13 Changwoo Ryu * ko.po: Updated Korean translation. 2004-08-13 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-08-13 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-08-13 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-08-12 Jayaradna * ta.po: Added tamil translation 2004-08-10 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2004-08-09 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-08-09 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-08-09 Martin Willemoes Hansen * da.po: Updated Danish translation 2004-08-09 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-08-09 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-08-08 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-08-07 Danilo Å egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-08-06 Laszlo Dvornik * hu.po: Updated Hungarian translation. 2004-08-04 Christian Rose * sv.po: Updated Swedish translation. 2004-08-04 Martin Willemoes Hansen * da.po: Updated Danish translation. 2004-08-02 Duarte Loreto * pt.po: Updated Portuguese translation. 2004-08-02 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-08-02 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-08-01 David Lodge * en_GB.po: Corrected British translation. 2004-08-01 Changwoo Ryu * ko.po: Updated Korean translation. 2004-07-31 Gareth Owen * en_GB.po: Corrected British English translation 2004-07-31 David Lodge * en_GB.po: Updated British translation. 2004-07-31 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-31 Francisco Javier F. Serrador * es.po: Updated Spanih translation. 2004-07-30 Miloslav Trmac * cs.po: Updated Czech translation. 2004-07-29 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-07-29 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-07-29 Gareth Owen * en_GB.po: Updated British English translation 2004-07-28 David Lodge * en_GB.po: Updated British translation. 2004-07-29 Changwoo Ryu * ko.po: Updated Korean translation. 2004-07-28 Gil Osher * he.po: Updated Hebrew translation. 2004-07-28 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-27 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-07-27 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-25 Christian Rose * sv.po: Updated Swedish translation. 2004-07-25 Miloslav Trmac * cs.po: Updated Czech translation. 2004-07-25 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation done by Raphael Higino . 2004-07-24 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-07-24 Christian Neumair * de.po: Updated German translation. 2004-07-23 Miloslav Trmac * cs.po: Updated Czech translation. 2004-07-23 Takeshi AIHANA * ja.po: Updated Japanese translation. === nemo 2.7.2 === 2004-07-21 Guntupalli Karunakar * hi.po: Updated Hindi translation. 2004-07-19 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-19 Miloslav Trmac * cs.po: Updated Czech translation. 2004-07-18 Christian Neumair * POTFILES.in: Updated (#147787, thanks to Alex Winston). * de.po: Updated German translation. 2004-07-16 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-07-14 Christian Rose * sv.po: Updated Swedish translation. 2004-07-14 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation done by Raphael Higino . 2004-07-11 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-07-10 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-08 Gustavo Noronha Silva * pt_BR.po: translation update by "Raphael Higino" 2004-07-08 Miloslav Trmac * cs.po: Updated Czech translation. 2004-07-08 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-08 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-07-07 Laurent Dhima * sq.po: Updated Albanian translation. 2004-07-07 Laszlo Dvornik * hu.po: Updated Hungarian translation. 2004-07-06 Ole Laursen * da.po: Updated Danish translation. 2004-07-05 Pawan Chitrakar * ne.po: Updated Nepali Translation 2004-07-02 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-07-02 Christian Rose * sv.po: Added links to bug reports. 2004-07-01 Laurent Dhima * sq.po: Translation updated. 2004-06-29 Christian Rose * POTFILES.skip: Removed nonexisting files. * sv.po: Updated Swedish translation. 2004-06-29 Ivan Stojmirov * mk.po: Updated Macedonian translation. 2004-06-29 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-06-28 Laurent Dhima * sq.po: Translation updated. 2004-06-28 Nikos Charonitakis * el.po Updated Greek translation. 2004-06-25 Gareth Owen * en_GB.po: Updated British English translation 2004-06-25 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-06-25 Nikos Charonitakis * el.po: Updated Greek translation. 2004-06-24 Andras Timar * hu.po: Updated Hungarian translation. 2004-06-23 Miloslav Trmac * cs.po: Updated Czech translation. 2004-06-20 Andras Timar * hu.po: Updated Hungarian translation. 2004-06-18 Andras Timar * hu.po: Updated Hungarian translation. 2004-06-17 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-06-10 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-06-09 Gareth Owen * en_GB.po: Updated British English translation 2004-06-08 Miloslav Trmac * cs.po: Updated Czech translation. 2004-06-06 Nikos Charonitakis * el.po: Updated Greek translation. 2004-06-05 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-06-05 Laurent Dhima * sq.po: Updated Albanian translation. 2004-06-04 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-06-04 Jordi Mallach * ca.po: Updated Catalan translation. 2004-06-02 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-06-02 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-06-02 Gareth Owen * en_GB.po: Updated British English translation 2004-06-02 Miloslav Trmac * cs.po: Updated Czech translation. 2004-06-01 Francisco Javier F. Serrador * es.po: Updated Spanish translation. === nemo 2.7.1 === 2004-05-31 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir Petkov 2004-05-29 Miloslav Trmac * cs.po: Updated Czech translation. 2004-05-29 Christian Rose * tk.po: Added Turkmen translation by Gurban Mühemmet Tewekgeli . 2004-05-27 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-05-27 Miloslav Trmac * cs.po: Updated Czech translation. 2004-05-25 Gareth Owen * en_GB.po: Updated British English translation 2004-05-25 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-05-25 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-05-24 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-05-24 Alexander Larsson * POTFILES.in: Add src/file-manager/fm-ditem-page.c 2004-05-18 Gareth Owen * en_GB.po: Updated British English translation 2004-05-17 Francisco Javier F. Serrador * es.po: Updated Spasnih translation. 2004-05-17 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-05-15 Alexander Winston * en_CA.po: Updated Canadian English translation. 2004-05-15 Miloslav Trmac * cs.po: Updated Czech translation. 2004-05-14 Miloslav Trmac * cs.po: Updated Czech translation. 2004-05-14 Andras Timar * hu.po: Updated Hungarian translation. === nemo 2.6.2 === 2004-05-13 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-05-08 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-05-06 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-05-04 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-05-02 Christophe Merlet * fr.po: Updated French translation. 2004-04-28 Gil Osher * he.po: Updated Hebrew translation. 2004-04-28 Jordi Mallach * ca.po: Updated Catalan translation. 2004-04-23 Gil Osher * he.po: Updated Hebrew translation. 2004-04-21 Christophe Merlet * fr.po: Updated French translation. 2004-04-21 Changwoo Ryu * ko.po: Replaced %-d with %e and %-I with %l. `-' modifier is a GNU extension. === nemo 2.6.1 === 2004-04-19 ?ygimantas Beru?ka * lt.po: Updated Lithuanian translation. 2004-04-16 I?aki Larra?aga * eu.po: Updated Basque translatiion. 2004-04-15 Andras Timar * hu.po: Updated Hungarian translation. 2004-04-12 Gareth Owen * en_GB.po: Updated British English translation 2004-04-11 ?ygimantas Beru?ka * lt.po: Updated Lithuanian translation by Mantas Kriau?i?nas. 2004-04-11 John C Barstow * mi.po: Updated M?ori translation. 2004-04-09 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-04-09 Guntupalli Karunakar * gu.po: Added Gujurati translation by Gujarati Team . 2004-04-08 Gareth Owen * en_GB.po: Updated British English tranlsation (bug 138758) 2004-04-08 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-04-06 Christophe Merlet * fr.po: Updated French translation. 2004-04-03 Sam?el J?n Gunnarsson * is.po: Updated Icelandic translation by Helgi ?ormar ?orbj?rnsson 2004-04-02 Gareth Owen * en_GB.po: Fixed small typo 2004-04-03 Mugurel Tudor * ro.po: Updated Romanian translation 2004-04-02 Christian Rose * sv.po: Fixed bug #138867 in the Swedish translation. 2004-03-31 Christian Rose * af.po: Added Afrikaans translation by Zuza Software Foundation . 2004-03-30 Dafydd Harries * cy.po: Update stupid typo in the Welsh translation. 2004-03-30 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-03-30 Jordi Mallach * ca.po: Updated Catalan translation by Aleix Badia i Bosch and me. 2004-03-28 Andras Timar * hu.po: Updated Hungarian translation. 2004-03-26 Christophe Merlet * fr.po: Updated French translation. 2004-03-24 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2004-03-24 Adam Weinberger * en_CA.po: Updated Canadian English translation. 2004-03-23 Kostas Papadimas * el.po: Updated Greek translation. 2004-03-23 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2004-03-23 Priit Laes * et.po: Translation updated. 2004-03-22 Gareth Owen * en_GB.po: Updated British translation 2004-03-22 Guntupalli Karunakar * pa.po: Updated Punjabi translation by Amanpreet Singh Alam . === nemo 2.6.0 === 2004-03-22 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2004-03-22 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. * ar.po: Mark wrong entry as fuzzy (msgfmt check failed). 2004-03-21 Alastair McKinstry * ga.po: Update Irish translation. 2004-03-21 Mugurel Tudor * ro.po: Updated Romanian translation. 2004-03-20 Robert Sedak * hr.po: Updated Croatian translation. 2004-03-19 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-03-19 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-03-19 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-03-19 Leonid Kanter * ru.po: Fixed typo in Russian translation (missed tag bracket) 2004-03-19 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-03-18 Arafat Medini * ar.po: Updated Arabic translation. 2004-03-18 Christophe Merlet * fr.po: Updated French translation. 2003-03-17 Andras Timar * hu.po: Updated Hungarian translation. 2004-03-16 Kostas Papadimas * el.po: Updated Greek translation. 2004-03-16 Dafydd Harries * cy.po: Updated Welsh translation. === nemo 2.5.91 === 2004-03-14 Maxim Dziumanenko * uk.po: Updated Ukrainian translation 2004-03-13 Vincent van Adrighem * nl.po: Translation updated. 2004-03-13 Christian Neumair * POTFILES.in: Removed medusa/search-related files as discussed on nemo-list. * POTFILES.skip: Added them here. 2004-03-13 Christophe Merlet * fr.po: Updated French translation. 2004-03-13 Alexander Shopov * bg.po: Updated Bulgarian translation by Vladimir "Kaladan" Petkov 2004-03-12 Sayamindu Dasgupta * bn.po: Updated Bengali translation (done by Progga 2004-03-11 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation done by Raphael Higino . 2004-03-11 Christian Rose * sv.po: Updated Swedish translation. 2004-03-10 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-03-10 Vincent van Adrighem * nl.po: Translation updated. 2004-03-09 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-03-09 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-03-09 Danilo ?egan * sr.po, sr@Latn.po: Fixed typos noticed by Bojan Suzi?? 2004-03-09 Francisco Javier F. Serrador * es.po: Updated Spansih translation. 2004-03-08 Alastair McKinstry * ga.po: Updated Irish translation. 2004-03-08 Danilo ?egan * sr@ije.po: Added Serbian Jekavian translation by Bojan Suzi?? . === nemo 2.5.90 === 2004-03-08 Ales Nyakhaychyk * be.po: Updated Belarusian translation. 2004-03-07 Alexander Winston * en_CA.po: Updated Canadian English translation to "1489 translated messages, 5 fuzzy translations." status. 2004-03-07 Pauli Virtanen * fi.po: Improve Finnish translation. 2004-03-06 M?tin ?mirov * az.po: Translation updated. 2004-03-06 Ales Nyakhaychyk * be.po: Updated Belarusian translation. 2004-03-06 Priit Laes * et.po: Translation updated. 2004-03-06 Priit Laes * et.po: Translation updated. 2004-03-05 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-03-04 Christian Rose * sv.po: Updated Swedish translation. 2004-03-03 Arafat Medini * ar.po: Updated faulty Arabic translation. 2004-03-03 Jody Goldberg * ar.po : remove semi-duplicated message that was breaking the build. Was gettext on crack ? or was that really a duplicate. 2004-03-04 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-03-03 Guntupalli Karunakar * pa.po: Added Punjabi translation by Amanpreet Singh Alam . 2004-03-3 Arafat Medini * ar.po: Updated Arabic translation. 2004-03-02 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-02-29 Ole Laursen * da.po: Updated Danish translation. 2004-02-28 Pauli Virtanen * fi.po: Updated Finnish translation. 2004-02-28 Christophe Merlet * fr.po: Updated French translation. 2004-02-28 Duarte Loreto * pt.po: Updated Portuguese translation. 2004-02-28 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-02-27 Christian Neumair * POTFILES.skip: Added a bunch of missing files. * de.po: Updated German translation. 2004-02-27 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-02-27 Priit Laes * et.po: Translation updated by Allan Sims. 2004-02-27 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-02-26 Guntupalli Karunakar * hi.po: Updated Hindi translation. 2004-02-26 Vincent van Adrighem * nl.po: Translation updated by Kees van den Broek. 2004-02-26 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2004-02-26 Dafydd Harries * cy.po: Updated Welsh translation. 2004-02-26 Christian Rose * sv.po: Updated Swedish translation. 2004-02-25 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-02-25 Pablo G. del Campo * es.po: Updated Spanish translation. 2004-02-25 Laurent Dhima * sq.po: Updated Albanian translation. 2004-02-25 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-02-25 Miloslav Trmac * cs.po: Updated Czech translation. 2004-02-24 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-02-24 Alastair McKinstry * ga.po: Updated Irish translation. 2004-02-24 Kostas Papadimas * el.po: Updated Greek translation. 2004-02-24 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-02-25 Changwoo Ryu * ko.po: Updated Korean translation. 2004-02-24 Takeshi AIHANA * ja.po: Updated Japanese translation. === nemo 2.5.8 === 2004-02-24 Miloslav Trmac * cs.po: Updated Czech translation. 2004-02-24 ?smund Skj?veland * nn.po: Updated Norwegian nynorsk translation. 2004-02-24 Laurent Dhima * sq.po: Updated Albanian translation. 2004-02-24 Christian Rose * sv.po: Updated Swedish translation. 2004-02-24 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-02-24 Artur Flinta * pl.po: Updated Polish translation. 2004-02-24 Dafydd Harries * cy.po: Updated translation by Bryn Salisbury and myself. 2004-02-23 Dave Camp * POTFILES.in: Added nemo-column-chooser.c 2004-02-23 Ole Laursen * da.po: Updated Danish translation. 2004-02-23 Danilo ?egan * sr.po, sr@Latn.po: Fix accelerator clash and a typo. 2004-02-23 Kostas Papadimas * el.po: Updated Greek translation. 2004-02-22 Paisa Seeluangsawat * th.po: Updated Thai translation. 2004-02-22 Nikos Charonitakis * el.po: Updated Greek translation. 2004-02-22 M?tin ?mirov * az.po: Updated Azerbaijani translation. 2004-02-22 Danilo ?egan * srr.po, sr@Latn.po: Updated Serbian translation. 2004-02-22 Christian Rose * en_CA.po: Added Canadian English translation by Adam Weinberger . 2004-02-21 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-02-21 Christian Rose * sv.po: Updated Swedish translation. 2004-02-21 Laurent Dhima * sq.po: Updated Albanian translation. 2004-02-21 Christian Neumair * de.po: Updated German translation. 2004-02-21 Miloslav Trmac * cs.po: Updated Czech translation. 2004-02-21 Artur Flinta * pl.po: Updated Polish translation. 2004-02-20 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-02-19 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2004-02-19 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-02-19 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-02-18 Alexander Larsson * POTFILES.in: Remove nemo-connect-server 2004-02-18 Alexander Larsson * POTFILES.in: Remove filesystem-attributes.xml (not used anymore) 2004-02-18 Ole Laursen * da.po: Updated Danish translation. * POTFILES.in: Removed non-existing libbackground/preview-file-selection.c. 2003-02-18 Ales Nyakhaychyk * be.po: Updated Belarusian translation. 2003-02-18 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-02-15 Paisa Seeluangsawat * th.po: Updated Thai (th) translation. 2004-02-15 Christian Rose * sv.po: Updated Swedish translation. 2004-02-15 M?tin ?mirov * az.po: Translation updated. 2004-02-13 Kostas Papadimas * el.po: Updated Greek translation. 2004-02-14 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-02-13 Christophe Merlet * fr.po: Updated French translation. 2004-02-12 Christian Rose * sv.po: Updated Swedish translation. 2004-02-12 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-02-11 Arafat Medini * ar.po: Updated Arabic translation. 2004-02-12 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. === nemo 2.5.7 === 2004-02-10 Pauli Virtanen * fi.po: Updated Finnish translation. 2004-02-10 Christian Rose * sv.po: Updated Swedish translation. 2004-02-09 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-02-09 Christian Rose * mi.po: Added Maori translation by John C Barstow . 2004-02-08 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-02-08 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-02-07 Robert Sedak * hr.po: Updated Croatian translation. 2004-02-08 Changwoo Ryu * ko.po: Updated Korean translation. 2004-02-07 Miloslav Trmac * cs.po: Updated Czech translation. 2004-02-07 Laurent Dhima * sq.po: Updated Albanian translation. 2004-02-07 Nikos Charonitakis * el.po: Updated Greek translation. 2004-02-06 Laurent Dhima * sq.po: Updated Albanian translation. 2004-02-05 Pauli Virtanen * fi.po: Updated Finnish translation. 2004-02-05 Maxim Dziumanenko * uk.po: Updated ukrainian translation. 2004-02-04 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-02-03 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-02-03 Duarte Loreto * pt.po: Updated Portuguese translation. 2004-02-02 Alastair McKinstry * ga.po: Updated Irish translation. 2004-02-01 Ole Laursen * da.po: Updated Danish translation. 2004-02-01 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-01-31 M?tin ?mirov * az.po: Updated Azerbaijani translation. 2004-01-31 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-01-31 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . 2004-01-30 Francisco Javier F. Serrador * es-po: Updated Spanish translation. 2004-01-30 Kjartan Maraas * no.po: Updated Norwegian translation. === nemo 2.5.6 === 2004-01-30 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-29 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-01-28 Miloslav Trmac * cs.po: Fixed Czech translation. 2004-01-27 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-01-27 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2004-01-27 Christophe Merlet * fr.po: Updated French translation. 2004-01-25 Funda Wang * zh_CN.po: Updated Simplified Chinese translation. 2004-01-25 Christian Neumair * de.po: Updated German translation. 2004-01-24 Changwoo Ryu * ko.po: Updated Korean translation. 2004-01-24 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-01-24 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-01-23 Christophe Merlet * fr.po: Updated French translation. 2004-01-23 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-23 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-01-22 Christian Neumair * de.po: Updated German translation. 2004-01-22 Artur Flinta * pl.po: Updated Polish translation by GNOME PL Team. 2004-01-22 Alexander Larsson * cy.po: Hmm? fix parse error 2004-01-22 Nikos Charonitakis * el.po: Updated Greek translation. 2004-01-21 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-21 Nikos Charonitakis * el.po: Updated Greek translation. 2004-01-20 Dafydd Harries * cy.po: Fixes, notably s/symyd/symud/; s/copio/cop?o/. 2004-01-18 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2004-01-18 Kjartan Maraas * no.po: Updated Norwegian translation. 2004-01-17 ?ygimantas Beru?ka * lt.po: Updated Lithuanian translation by Mantas Kriau?i?nas. 2004-01-17 Christophe Merlet * fr.po: Updated French translation. 2004-01-16 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-01-16 Duarte Loreto * pt.po: Updated and revised Portuguese translation. 2004-01-15 Laurent Dhima * sq.po: Updated Albanian translation. 2004-01-13 Christian Neumair * de.po: Updated German translation. 2004-01-13 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-01-13 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2004-01-13 Kostas Papadimas * el.po: Updated Greek translation. 2004-01-13 Vincent van Adrighem * nl.po: Translation updated by Kees van den Broek. 2004-01-13 Takeshi AIHANA * ja.po: Updated Japanese translation. 2004-01-13 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-13 Vincent van Adrighem * nl.po: Translation updated by Reinout van Schouwen. 2004-01-13 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. === nemo 2.5.5 === 2004-01-13 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-01-12 Alexander Larsson * POTFILES.in: Added missing files. 2004-01-12 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-11 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2004-01-11 Ross Golder * th.po: Reverted '%Ey' to '%Y' until a working solution has been found for displaying non-Gregorian years. 2004-01-10 Ole Laursen * da.po: Fixed some more strings. 2004-01-10 Christian Neumair * de.po: Updated German translation. 2004-01-10 Changwoo Ryu * ko.po: Updated Korean translation. 2004-01-10 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. * POTFILES.in: Added libnemo-private/nemo-file-utilities.c. 2004-01-09 Ole Laursen * da.po: Fixed some strings in Danish translation. 2004-01-08 Christophe Merlet * fr.po: Updated French translation from Sebastien Bacher . 2004-01-07 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-07 Paul Duffy * ga.po: Updated Irish translation 2004-01-06 Kjartan Maraas * POTFILES.in: Remove missing files and add some new ones. * POTFILES.skip: Remove missing files. * no.po: Update. 2004-01-06 Miloslav Trmac * cs.po: Updated Czech translation. 2004-01-05 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2004-01-04 Jordi Mallach * POTFILES.in: Removed components/text files. * ca.po: Updated Catalan translation. 2004-01-02 Sanlig Badral * mn.po: Updated Mongolian translation. 2004-01-02 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2004-01-02 Francisco Javier F. Serrador * es.po Updated Spanish translation. 2004-01-01 Ole Laursen * da.po: Partial update of Danish translation. 2004-01-01 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. === nemo 2.5.4 === 2003-12-29 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2003-12-27 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2003-12-27 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2003-12-23 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2003-12-22 Gustavo Noronha Silva * pt_BR.po: updated translation and tried to have some translations more standardized. 2003-12-21 Christian Neumair * de.po: Updated German translation. 2003-12-18 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-12-17 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2003-12-16 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. 2003-12-16 Paisa Seeluangsawat * th.po: Updated Thai (th) translation. 2003-12-15 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2003-12-14 Kjartan Maraas * no.po: Updated Norwegian translation. 2003-12-14 Miloslav Trmac * cs.po: Updated Czech translation. 2003-12-14 Kostas Papadimas * el.po: Updated Greek translation. 2003-12-14 Francisco Javier F. Serrador * es.po: Updated Spanish translation. 2003-12-14 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-12-12 Miloslav Trmac * cs.po: Updated Czech translation. 2003-12-12 Christian Neumair * POTFILES.in: Removed obsolete hardware view. 2003-12-10 Francisco Javier F. Serrador * es.po: Updated Spanish translation 2003-12-10 ?smund Skj?veland * nn.po: Updated Norwegian Nynorsk translation. * no.po: Corrected some errors in Norwegian Bokm?l translation. 2003-12-09 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-12-09 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. === nemo 2.5.3 === 2003-12-05 Paisa Seeluangsawat * th.po: Updated Thai (th) translation. 2003-12-04 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-12-03 Miloslav Trmac * cs.po: Updated Czech translation. 2003-12-03 Sanlig Badral * mn.po: Updated Mongolian translation. 2003-12-03 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-11-27 Kjartan Maraas * no.po: Update Norwegian translation. 2003-11-27 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbain translation. 2003-11-26 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . === nemo 2.5.2 === 2003-11-24 Alexander Larsson * POTFILES.in: add fm-icon-container.c 2003-11-20 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. === nemo 2.5.1.1 === 2003-11-12 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2003-11-10 Ole Laursen * da.po: Updated Danish translation. 2003-11-10 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-11-10 Pablo Gonzalo del Campo * es.po: Updated Spanish translation by Francisco Javier F. Serrador . === nemo 2.5.1 === 2003-11-09 Abel Cheung * POTFILES.in: Removed non-existant file and added 2 new .desktop.in. 2003-11-09 Christian Rose * ne.po: Updated Nepali translation by Pawan Chitrakar . 2003-11-02 KAMAGASAKO Masatoshi * ja.po: Updated Japanese translation. 2003-10-30 Kostas Papadimas * el.po: updated Greek Translation 2003-10-28 Andras Timar * hu.po: Updated Hungarian translation. 2003-10-25 Ole Laursen * da.po: Updated Danish translation. 2003-10-21 Stanislav Brabec * cs.po: Typo fix. === nemo 2.5.0 === 2003-10-20 Andras Timar * hu.po: Updated Hungarian translation. 2003-10-17 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-10-15 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. * POTFILES.in: Updated (someone [me?] missed the conflict markers). 2003-10-14 Andras Timar * hu.po: Updated Hungarian translation. 2003-10-08 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-10-07 Andras Timar * hu.po: Updated Hungarian translation. 2003-10-06 Mugurel Tudor * ro.po: Updated Romanian translation 2003-10-06 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-10-06 Danilo ?egan * POTFILES.in: Added new files, removed nonexisting file. 2003-10-01 Gustavo Maciel Dias Vieira * pt_BR.po: Applied revision by Augusta Marques da Silva . 2003-09-28 Christian Rose * sv.po: Fixed an access key conflict. * POTFILES.skip: Removed nonexisting files and added comment. 2003-09-28 Christian Rose * POTFILES.in: Added missing files. 2003-09-15 Christian Neumair * de.po: Fixed stupid wording. 2003-09-15 Artur Flinta * pl.po: Updated Polish translation. 2003-09-11 Artur Flinta * pl.po: Updated Polish translation. 2003-09-10 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-09-10 Andras Timar * hu.po: Fixed a mistranslation. === nemo 2.4.0 === 2003-09-08 Pablo Saratxaga * vi.po: Updated Vietnamese file 2003-09-07 Jordi Mallach * ca.po: Updated Catalan translation. 2003-09-06 Kjartan Maraas * POTFILES.skip: Added missing files. * no.po: Updated Norwegian translation. 2003-09-05 Jordi Mallach * ca.po: Updated Catalan translation. 2003-09-05 Taneem Ahmed * bn.po: Updated Bangla (Bengali) translation. 2002-09-04 Ivan Stojmirov * mk.po: Updated Macedonian translation 2003-09-03 Mugurel Tudor * ro.po: Updated Romanian translation 2003-09-03 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2003-09-03 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-09-02 Christian Rose * sv.po: Fix #121250. === nemo 2.3.90 === 2003-09-01 Paul Duffy * ga.po: Updated Irish translation. 2003-08-31 Kjartan Maraas * no.po: Updated Norwegian translation. 2003-08-28 Nikos Charonitakis * el.po Updated Greek translation. 2003-08-28 Christian Rose * li.po: Updated Limburgish translation by Mathieu van Woerkom . 2003-08-27 Pablo Gonzalo del Campo * es.po: Revision of Spanish translation by Francisco Javier F. Serrador . 2003-08-27 Vincent van Adrighem * nl.po: Dutch translation updated by Kees van den Broek. 2003-08-26 Dafydd Harries * cy.po: Updated Welsh translation. 2003-08-26 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2003-08-25 Duarte Loreto * pt.po: Fixed typos and missing accels in Portuguese translation. 2003-08-26 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . === nemo 2.3.9 === 2003-08-24 Kang Jeong-Hee * ko.po: Updated Korean translation. 2003-08-24 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-08-23 Kjartan Maraas * no.po: Update Norwegian translation. 2003-08-24 Changwoo Ryu * ko.po: Updated Korean translation. 2003-08-23 Danilo ?egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-08-22 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-08-20 Sam?el J?n Gunnarsson * is.po: Updated Icelandic translation 2003-08-19 Kjartan Maraas * no.po: Update Norwegian translation. 2003-08-19 Dafydd Harries * cy.po: Updated Welsh translation. Vast majority of it by Bryn Salisbury, rest by me. 2003-08-18 Metin Amiroff * az.po: Updated Azerbaijani translation. 2003-08-17 Christophe Merlet * fr.po: Updated French translation. 2003-08-17 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-08-16 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-08-15 Kostas Papadimas * el.po: updated Greek Translation 2003-08-14 Pablo Gonzalo del Campo * es.po: Updated Spanish translation by Francisco Javier F. Serrador . 2003-08-14 Christian Rose * ne.po: Added Nepali translation by Pawan Chitrakar . 2003-08-11 Dafydd Harries * cy.po: Updated Welsh translation. 2003-08-12 Danilo ?egan * be.po: Updated Belarusian translation by Ales Nyakhaychyk . 2003-08-12 Christian Neumair * de.po: Updated German translation. 2003-08-11 Dafydd Harries * cy.po: Updated Welsh translation. 2003-08-11 Ole Laursen * da.po: Updated Danish translation. 2003-08-10 Artur Flinta * pl.po: Updated Polish translation. 2003-08-09 Jordi Mallach * ca.po: Updated Catalan translation. 2003-08-09 Miloslav Trmac * cs.po: Updated Czech translation. 2003-08-09 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-08-09 Wang Jian * zh_CN.po: Updated Simplified Chinese translation by Funda Wang . 2003-08-09 Laurent Dhima * sq.po: Updated Albanian translation. 2003-08-09 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-08-09 Christophe Merlet * fr.po: Updated French translation. 2003-08-09 Takeshi AiHANA * ja.po: Updated Japanese translation. 2003-08-08 Danilo ? egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-08-08 Christian Rose * sv.po: Updated Swedish translation. === nemo 2.3.8 === 2003-08-08 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-08-08 Danilo ? egan * sr.po, sr@Latn.po: Updated Serbian translation. 2003-08-07 Miloslav Trmac * cs.po: Updated Czech translation. 2003-08-07 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-08-06 Metin Amiroff * az.po: Updated Azerbaijani translation. 2003-08-06 Wang Jian * zh_CN.po: Updated Simplified Chinese translation by Funda Wang . 2003-08-05 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti 2003-08-05 Jordi Mallach * ca.po: Updated Catalan translation. 2003-08-05 Ole Laursen * da.po: Updated Danish translation. 2003-08-04 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-08-04 Artur Flinta * pl.po: Updated Polish translation. 2003-08-01 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-07-31 Artur Flinta * pl.po: Updated Polish translation. 2003-07-29 Nikos Charonitakis * el.po: Updated Greek translation 2003-07-28 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-07-27 Telsa Gwynne * cy.po: Updated Welsh translation. Again! This from Chris M. Jackson. 2003-07-27 Telsa Gwynne * cy.po: Updated Welsh translation. 2003-07-27 Changwoo Ryu * ko.po: Updated Korean translation. 2003-07-24 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-07-22 Sam?el J?n Gunnarsson * is.po: Updated Icelandic translation 2003-07-21 Christophe Merlet * fr.po: Updated French translation. 2003-07-20 Sam?el J?n Gunnarsson * is.po: Updated Icelandic translation. 2003-07-19 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-07-17 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2003-07-17 Vincent van Adrighem * nl.po: Dutch translation updated by Kees van den Broek. 2003-07-16 Dafydd Harries * cy.po: Updated Welsh translation. 2003-07-14 Dafydd Harries * cy.po: Updated Welsh translation. I think it includes work by Chris Jackson, Telsa Gwynne, Alan Cox and me. Some of us, anyway. 2003-07-13 Kostas Papadimas * el.po: updated Greek Translation. 2003-07-12 Pablo Saratxaga * wa.po: Updated Walloon file 2003-07-10 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-07-09 Fatih Demir * tr.po: Updated Turkish translation by Gorkem. 2003-07-08 Christian Neumair * de.po: Updated German translation. 2003-07-08 Christophe Merlet * fr.po: Updated French translation. 2003-07-07 Artur Flinta * pl.po: Updated Polish translation. 2003-07-07 Miloslav Trmac * cs.po: Updated Czech translation. 2003-07-07 Vincent van Adrighem * nl.po: Dutch translation updated by Kees van den Broek. 2003-07-07 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-07-06 Christian Rose * sv.po: Updated Swedish translation. 2003-07-06 Danilo ? egan * sr.po, sr@Latn.po: Updated Serbian translation by Serbian team (Prevod.org). 2003-07-06 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-07-06 Jordi Mallach * ca.po: Updated Catalan translation. 2003-07-04 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-07-03 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2003-07-03 Artur Flinta * pl.po: Updated Polish translation. 2003-07-02 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-07-02 Artur Flinta * pl.po: Updated Polish translation. 2003-07-01 Laurent Dhima * sq.po: Updated Albanian translation. 2003-06-30 Pauli Virtanen * fi.po: Set translator_credits. 2003-06-30 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-06-29 Ole Laursen * da.po: Updated Danish translation. 2003-06-29 Miloslav Trmac * cs.po: Updated Czech translation. 2003-06-29 Dafydd Harries * cy.po: Added Welsh translation. Credit to Chris Jackson. 2003-06-28 Miloslav Trmac * cs.po: Updated Czech translation. 2003-06-28 Jordi Mallach * ca.po: Updated Catalan translation. 2003-06-28 Christian Rose * POTFILES.in: Added missing file. * sv.po: Updated Swedish translation. 2003-06-28 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-06-28 Miloslav Trmac * cs.po: Updated Czech translation. === nemo 2.3.6 === 2003-06-26 Mohammad DAMT * id.po: Added Indonesian translation by Yohanes Nugroho === nemo 2.3.5 === 2003-06-23 Vincent van Adrighem * nl.po: Dutch translation updated by Kees van den Broek. 2003-06-22 Christian Rose * sv.po: Updated Swedish translation. 2003-06-21 Sam?el J?n Gunnarsson * is.po: Updated Icelandic translation 2003-06-21 Bastien Nocera * en_GB.po: updated, translated the time and dates as well now 2003-06-19 Kostas Papadimas * el.po: updated Greek Translation. 2003-06-17 Mathieu van Woerkom * li.po: Added Limburgish translation 2003-06-16 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti 2003-06-16 Taneem Ahmed * bn.po: Added Bangla translation by Progga of Ankur group . 2003-06-16 Dmitry G. Mastrukov * ru.po: Updated Russian translation from Russian team . 2003-06-14 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-06-12 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-06-12 Jordi Mallach * ca.po: Updated Catalan translation. 2003-06-11 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-06-11 Laurent Dhima * sq.po: Updated Albanian translation. 2003-06-11 Christian Neumair * de.po: Updated German translation. === nemo 2.3.4 === 2003-06-10 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-06-09 Christophe Merlet * fr.po: Updated French translation. 2003-06-08 Christophe Merlet * fr.po: Updated French translation. 2003-06-07 Jordi Mallach * ca.po: Updated Catalan translation. 2003-06-06 Sam?=BAel J?=B3n Gunnarsson * is.po: Added Icelandic translation 2003-06-05 Jordi Mallach * ca.po: Updated Catalan translation. 2003-06-05 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-06-04 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-06-04 Abel Cheung * ta.po: Removed. Completely empty. 2003-05-30 Miloslav Trmac * cs.po: Updated Czech translation. 2003-05-30 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-05-27 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-05-27 Abel Cheung * POTFILES.in: Remove non-existant file(s), add missing files from libnemo-private/. * POTFILES.skip: Remove non-existant file(s). 2003-05-26 Pablo Saratxaga * vi.po: Updated Vietnamese file 2003-05-23 Paul Duffy * ga.po: Updated Irish translation. 2003-05-23 Christian Rose * sv.po: Updated Swedish translation. 2003-05-22 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-05-20 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-05-19 Christophe Merlet * fr.po: None! 2003-05-19 Ole Laursen * da.po: Ported Danish translation from gnome-2-2 branch, not updated yet. === nemo 2.3.2 === 2003-05-19 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-05-18 Michal Bukovjan * cs.po: Updated Czech translation. 2003-05-18 Christophe Merlet * fr.po: Updated French translation. 2003-05-16 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-05-16 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-05-12 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-05-08 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-05-07 Paul Duffy * ga.po: Updated Irish Translation. 2003-05-06 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-05-06 Miloslav Trmac * cs.po: Updated Czech translation. 2003-05-06 Danilo ? egan * sr.po, sr@Latn: Added Serbian translation by http://Prevod.org/. 2003-05-05 Paul Duffy * ga.po:Updated the Irish Translation === nemo 2.3.1 === 2003-05-05 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-05-04 Paul Duffy * ga.po: Updated Irish Translation 2003-05-03 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-04-29 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-04-27 Yanko Kaneti * POTFILES.in: Fixup the schemas.in path. 2003-04-23 Alexander Larsson * POTFILES.in: Add schemas.in file. 2003-04-22 Sanlig Badral * mn.po: Updated Mongolian translation. 2003-04-10 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. === nemo 2.2.3 === 2003-03-31 Laurent Dhima * sq.po: Updated Albanian translation. 2003-03-30 Christophe Merlet * fr.po: Updated French translation. 2003-03-30 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-03-30 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-03-27 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-03-27 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-03-27 Alessio Frusciante * it.po: Updated Italian translation by Luca Ferretti . 2003-03-26 Christian Rose * yi.po: Added Yiddish translation by Raphael Finkel . 2003-03-26 Sanlig Badral * mn.po: Updated Mongolian translation. 2003-03-26 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2003-03-26 Yuriy Syrota * uk.po: Updated Ukrainian translation. 2003-03-25 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-03-25 Ole Laursen * da.po: Updated Danish translation. 2003-03-25 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-03-25 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-03-25 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-03-25 Andras Timar * hu.po: Updated Hungarian translation. 2003-03-25 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-03-25 Jordi Mallach * ca.po: Updated Catalan translation. 2003-03-25 Metin Amiroff * az.po: Updated Azerbaijani translaion. 2003-03-25 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-03-25 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-03-25 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-03-24 Christian Rose * sv.po: Updated Swedish translation. 2003-03-24 Bastien Nocera * en_GB.po: Review the use of trash v. Wastebasket (Closes: #83764) 2003-03-23 Christophe Merlet * fr.po: Updated French translation. 2003-03-22 Christian Neumair * de.po: Updated German translation. 2003-03-22 Pablo Saratxaga * wa.po: Added Walloon file 2003-03-20 Andras Timar * hu.po: Updated Hungarian translation. 2003-03-18 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-03-17 Pablo Saratxaga * vi.po: Updated Vietnamese file 2003-03-17 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-03-17 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-03-17 Artis Trops * lv.po: Updated Latvian translation. 2003-03-17 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-03-17 Kang Jeong-Hee * ko.po: Updated Korean transltaion. 2003-03-17 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2003-03-16 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-03-16 Laurent Dhima * sq.po: Updated Albanian translation. 2003-03-16 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-03-16 Takeshi AIHANA * ja.po: Updated Japanese translation. 2003-03-16 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-03-16 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-03-15 Miloslav Trmac * cs.po: Updated Czech translation. 2003-03-15 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-03-14 Christian Rose * sv.po: Updated Swedish translation. 2003-03-14 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-03-13 Takeshi AIHANA * ja.po: Updated Japanese translation by KAMAGASAKO Masatoshi . 2003-03-13 Christian Rose * ml.po: Added Malayalam translation by FSF-India . 2003-03-13 Sanlig adral * mn.po: Updated Mongolian translation. 2003-03-12 Metin Amiroff * az.po: Updated Azerbaijani translation. === nemo 2.2.2 === 2003-03-10 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-03-10 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2003-03-09 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-03-08 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-03-08 Christian Neumair * de.po: Updated German translation. 2003-03-08 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-03-08 Vincent van Adrighem * nl.po: Dutch translation updated. 2003-03-08 Christian Rose * sv.po: Updated Swedish translation. 2003-03-08 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-03-08 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-03-06 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2003-03-06 Ole Laursen * da.po: Updated Danish translation. 2003-03-05 Kostas Papadimas * el.po: updated Greek Translation. 2003-03-05 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-03-04 Miloslav Trmac * cs.po: Updated Czech translation. 2003-03-03 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-03-03 Jordi Mallach * ca.po: Updated Catalan translation. 2003-03-03 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-03-02 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2003-03-02 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2003-03-02 Christophe Merlet * fr.po: Updated French translation. 2003-03-01 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-03-01 Laurent Dhima * sq.po: Updated Albanian translation. 2003-02-28 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-02-28 Christophe Merlet * fr.po: Updated French translation. 2003-02-28 Christian Rose * sv.po: Updated Swedish translation. 2003-02-26 Miloslav Trmac * cs.po: Updated Czech translation. 2003-02-25 Vincent van Adrighem * nl.po: Dutch translation updated. 2003-02-25 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-02-24 Vincent van Adrighem * nl.po: Dutch translation updated. 2003-02-21 Roozbeh Pournader * fa.po: Added Persian translation. 2003-02-20 Paisa Seeluangsawat * th.po: Updated Thai translation. 2003-02-18 Kostas Papadimas * el.po: updated Greek Translation. 2003-02-18 Vincent van Adrighem * nl.po: Dutch translation updated. 2003-02-16 Kjartan Maraas * no.po: Fix up all date and time formats. 2003-02-16 Christian Neumair * de.po: Updated German translation. 2003-02-15 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-02-15 Christian Rose * sv.po: Some fixes for problems catched in translation review. 2003-02-14 Dmitry G. Mastrukov * be.po: Updated Belarusian translation from Belarusian team . 2003-02-14 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-02-13 Kostas Papadimas * el.po: updated Greek Translation. 2003-02-13 Pablo Gonzalo del Campo * es.po: Fixes in various strings. 2003-02-11 Vincent van Adrighem * nl.po: Dutch translation updated. === nemo 2.2.1 === 2003-02-11 Fatih Demir * tr.po: Committed updated Turkish translation by Arman. 2003-02-10 Christophe Merlet * fr.po: Updated French translation. 2003-02-09 Christian Neumair * de.po: Updated German translation. 2003-02-07 Daniel Yacob * am.po: Updated Amharic translation. 2003-02-04 Paisa Seeluangsawat * th.po: Updated Thai translation. 2003-02-03 Paisa Seeluangsawat * th.po: Updated Thai translation. 2003-02-03 Fatih Demir * tr.po: Committed updated Turkish translation by Gorkem. 2003-02-03 Daniel Yacob * am.po: Updated Amharic translation. 2003-02-02 Duarte Loreto * pt.po: Updated Portuguese translation. 2003-01-31 Paisa Seeluangsawat * th.po: updated Thai translation. 2003-01-30 Pablo Gonzalo del Campo * es.po: Fixed a hotkey mistake. 2003-01-30 Pablo Gonzalo del Campo * es.po: Fixed a string translation mistake. 2003-01-29 Pablo Gonzalo del Campo * es.po: Fixed a string order mistake. 2003-01-29 Pablo Gonzalo del Campo * es.po: Various fixes 2003-01-29 Sanlig Badral * mn.po: updated Mongolian translation. 2003-01-29 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-01-29 Yanko Kaneti * bg.po: Updated Bulgarian translation. 2003-01-28 Pablo Gonzalo del Campo * es.po: Fixed a hotkey mistake in a contextual menu. 2003-01-28 Pablo Saratxaga * vi.po: Updated Vietnamese file 2003-01-28 Kostas Papadimas * el.po: Updated Greek translation. === nemo 2.2.0.2 === 2003-01-26 Kang Jeong-Hee * ko.po: Updated Korean translation. 2003-01-26 Abel Cheung * zh_TW.po: Finished traditional Chinese translation. (Finally!) 2003-01-25 Paisa Seeluangsawat * th.po: Added Thai translation. 2003-01-25 Christophe Fergeau * fr.po: Updated French translation 2003-01-23 Marius Andreiana * ro.po: updated 2003-01-23 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-01-23 Yuriy Syrota * uk.po: Updated Ukrainian translation. 2003-01-23 Gustavo Noronha Silva * pt_BR.po: fix on stuff 2003-01-23 Pablo Saratxaga * vi.po: Updated Vietnamese file === nemo 2.2.0.1 === 2003-01-22 Christian Rose * mn.po: Added Mongolian translation by Ochirbat Batzaya . 2003-01-21 Alessio Frusciante * it.po: Updated Italian translation. 2003-01-21 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . === nemo 2.2.0 === 2003-01-20 Christian Neumair * de.po: Updated German translation. 2003-01-20 Christian Neumair * de.po: Updated German translation. 2003-01-20 Dmitry G. Mastrukov * ru.po: updated Russian translation from Russian team . 2003-01-19 Abel Cheung * zh_TW.po: Updated traditional Chinese translation, and used correct copyright symbol. 2003-01-19 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2003-01-19 He Qiangqiang * zh_CN.po: Fixed some translations. 2003-01-18 T???=82??=B5ivo Leedj???=A2??=82??=ACrv * et.po: Added Estonian translation. 2003-01-18 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-01-17 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-01-17 Jordi Mallach * ca.po: Updated Catalan translation. 2003-01-16 Marius Andreiana * ro.po: updated 2003-01-16 Christian Neumair * de.po: Updated German translation. 2003-01-16 Alessio Frusciante * it.po: Updated Italian translation. 2003-01-16 Daniel Yacob * am.po: Updated Amharic translation. 2003-01-16 Gustavo Noronha Silva * pt_BR.po: updated translation. 2003-01-15 Laurent Dhima * sq.po: Updated Albanian translation. 2003-01-15 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-01-15 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-01-15 Ole Laursen * da.po: Updated Danish translation. 2003-01-15 Andras Timar * hu.po: Updated Hungarian translation. 2003-01-15 Artis Trops * lv.po: Updated Latvian translation. 2003-01-15 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-01-14 Christian Neumair * de.po: Updated German translation. 2003-01-14 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2003-01-14 Daniel Yacob * am.po: Updated Amharic translation. === nemo 2.1.91 === 2003-01-13 He Qiangqiang * zh_CN.po: Updated Simplified Chinese translation by Funda Wang . 2003-01-12 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-01-09 Miloslav Trmac * cs.po: Updated Czech translation. 2003-01-09 Pablo Gonzalo del Campo * es.po: Fixed a couples of shortcut in the Spanish translation. 2003-01-09 Laurent Dhima * sq.po: Updated Albanian translation. 2003-01-08 Daniel Yacob * am.po: Updated Amharic translation. 2003-01-08 Miloslav Trmac * cs.po: Updated Czech translation. 2003-01-08 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-01-08 Kang Jeong-Hee * ko.po: Updated Korean translation by Young-Ho, Cha. 2003-01-08 Ole Laursen * da.po: Updated Danish translation. 2003-01-08 Artis Trops * lv.po: Updated Latvian translation. 2003-01-08 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-01-08 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-01-08 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2003-01-07 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-01-07 Kostas Papadimas * el.po: Updated Greek translation. 2003-01-07 Andras Timar * hu.po: Updated Hungarian translation. 2003-01-02 Pablo Gonzalo del Campo * es.po: Revision and Updated Spanish translation by Francisco Javier Fernandez. 2003-01-07 Christian Rose * sv.po: Updated Swedish translation. 2003-01-07 Daniel Yacob * am.po: Updated Amharic translation. 2003-01-07 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-01-07 Artis Trops * lv.po: Updated Latvian translation. 2003-01-07 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-01-07 Naba Kumar * hi.po: New hindi translation by Bhopal team Guntupalli Karunakar === nemo 2.1.6 === 2003-01-06 Christian Rose * sv.po: Updated Swedish translation. 2003-01-05 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2003-01-05 Pauli Virtanen * fi.po: Updated Finnish translation. 2003-01-04 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2003-01-03 Christian Neumair * de.po: Updated German translation. 2003-01-03 Andras Timar * hu.po: Updated Hungarian translation. 2003-01-02 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2003-01-02 Christian Rose * sv.po: Updated Swedish translation. 2003-01-02 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2003-01-02 Christophe Merlet * fr.po: Updated French translation. 2003-01-02 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2003-01-02 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2003-01-01 Ole Laursen * da.po: Updated Danish translation. 2003-01-01 Artis Trops * lv.po: Updated Latvian translation. 2003-01-01 Hasbullah Bin Pit * ms.po: Updated Malay translation. 2002-12-26 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-12-25 Ole Laursen * da.po: Update Danish translation. 2002-12-25 Artis Trops * lv.po: Updated Latvian translation. 2002-12-23 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2002-12-20 Gil "Dolfin" Osher * he.po: Updated Hebrew translation. 2002-12-19 Yanko Kaneti * bg.po: Fully updated Bulgarian translation from Borislav Aleksandrov . 2002-12-19 Christophe Merlet * fr.po: Updated French translation. 2002-12-19 Andras Timar * hu.po: Updated Hungarian translation. 2002-12-19 Yanko Kaneti * bg.po: Updated Bulgarian translation from Borislav Aleksandrov . 2002-12-19 Christian Rose * sv.po: Updated Swedish translation. 2002-12-18 Christian Rose * sv.po: Updated Swedish translation. 2002-12-18 Alexander Larsson * POTFILES.in: Reverted incorrect change. * POTFILES.skip: Added loser, sample and music components 2002-12-17 Christophe Merlet * fr.po: Updated French translation. 2002-12-17 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-12-16 Christian Neumair * POTFILE.(in/skip): Updated. * de.po: Updated German translation. === nemo 2.1.5 === 2002-12-15 Pablo Saratxaga * vi.po: Updated Vietnamese file * mk.po,ta.po: corrected headers * zh_CN.po: fixed syntax errors 2002-12-12 Ole Laursen * da.po: Updated Danish translation. 2002-12-12 Pablo Gonzalo del Campo * es.po: Updated Spanish translation: replaced (C) with ???=82??=A9. 2002-12-11 Laurent Dhima * sq.po: Updated Albanian translation. 2002-12-11 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-12-10 Daniel Yacob * am.po: Updated Amharic translation. === nemo 2.1.4 === 2002-12-07 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-12-07 Andras Timar * hu.po: Updated Hungarian translation. 2002-12-06 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-12-06 Miloslav Trmac * cs.po: Updated Czech translation. 2002-12-05 Gil Osher * he.po: Updated Hebrew translation. 2002-12-04 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. 2002-12-04 Marius Andreiana * ro.po: updated 2002-12-03 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-12-03 Christian Rose * .cvsignore: Added files. * sv.po: Updated Swedish translation. 2002-12-03 Yuriy Syrota * uk.po: Ukrainian translation updated by Maxim Dzumanenko 2002-12-01 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-11-29 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2002-11-27 Laurent Dhima * sq.po: Added Albanian translation from gnome-2-0 branch. 2002-11-27 Ole Laursen * da.po: Updated Danish translation. === nemo 2.1.3 === 2002-11-25 Vincent van Adrighem * nl.po: Massive copy-paste from stable branch. 2002-11-25 Ole Laursen * da.po: Merged from gnome-2-0 branch. 2002-11-25 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-11-25 Yanko Kaneti * *.po: Convert all to UTF-8. 2002-11-24 Dave Camp * POTFILES.in: Remove sample and loser files. 2002-11-24 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-11-15 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-11-11 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho, Cha . 2002-11-09 Dmitry G. Mastrukov * be.po: Updated Belarusian translation * from Belarusian team . 2002-11-06 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-11-05 Hasbullah Bin Pit * ms.po: Updated Malay Translation (twice). === nemo 2.1.2 === 2002-10-31 Dave Camp * POTFILES.in: Updated. 2002-10-13 Andras Timar * hu.po: Fixed Bugzilla #96578 2002-10-22 Pablo Saratxaga * vi.po: Updated Vietnamese file 2002-10-21 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-10-13 Hasbullah Bin Pit * ms.po: Updated Malay Translation. === nemo 2.1.1 === 2002-10-12 Andras Timar * hu.po: Spellcheck and update. 2002-10-10 Andras Timar * hu.po: Fixed a typo. === nemo-2.1.0 === 2002-09-23 Marius Andreiana * ro.po: updated 2002-09-22 Pablo Saratxaga * vi.po: Updated Vietnamese file 2002-09-21 Dave Camp * az.po: * bg.po: * ca.po: * cs.po: * da.po: * de.po: * el.po: * en_GB.po: * es.po: * eu.po: * fi.po: * fr.po: * ga.po: * gl.po: * hu.po: * it.po: * ja.po: * ko.po: * lt.po: * lv.po: * ms.po: * nl.po: * nn.po: * no.po: * pl.po: * pt.po: * pt_BR.po: * ro.po: * ru.po: * sk.po: * sl.po: * sv.po: * ta.po: * tr.po: * uk.po: * vi.po: * zh_CN.po: * zh_TW.po: 2002-09-21 Dave Camp * POTFILES.in: Added new side pane files. 2002-09-16 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-09-16 Pablo Saratxaga * vi.po: Updated Vietnamese file 2002-09-14 Andras Timar * hu.po: Fixed hotkeys. 2002-09-10 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho, Cha . 2002-09-07 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2002-09-03 Peteris Krisjanis * lv.po: Updated Latvian translation. 2002-08-31 Pablo Saratxaga * vi.po: Updated Vietnamese file 2002-08-29 Jordi Mallach * ca.po: Updated Catalan translation. 2002-08-29 Marius Andreiana * ro.po: updated 2002-08-29 Vincent van Adrighem * nl.po: Dutch translation updated by Reinout van Schouwen. === nemo 2.0.6 === 2002-08-27 Emese Kovacs * hu.po: Updated Hungarian translation. 2002-08-27 Pauli Virtanen * fi.po: Updated Finnish translation. === nemo 2.0.5 === 2002-08-23 Akira TAGOH * ja.po: fix typo. 2002-08-22 Alessio Frusciante * it.po: Updated Italian translation. 2002-08-21 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-08-20 Peteris Krisjanis * lv.po: QA for Latvian translation. 2002-08-20 Yukihiro Nakai * ja.po: Update Japanese translation from Kiyoto Hashida. 2002-08-18 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-08-17 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-08-17 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2002-08-17 Christian Meyer * de.po: Updated German translation. 2002-08-17 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . 2002-08-16 Andras Timar * hu.po: Updated Hungarian translation. 2002-08-16 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-08-16 Peteris Krisjanis * lv.po: Updated Latvian translation by Artis Trops 2002-08-16 Christian Rose * sv.po: Updated Swedish translation. 2002-08-16 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-08-15 Ole Laursen * da.po: Updated Danish translation. 2002-08-15 He Qiangqiang * zh_CN.po: Fixed a typo. 2002-08-14 Christophe Merlet * fr.po: Updated French translation. 2002-08-14 Christian Meyer * de.po: Fixed some more mnemonics. *sigh* 2002-08-14 Christian Meyer * de.po: Fixed some mnemonics. === nemo 2.0.4 === 2002-08-13 Andras Timar * hu.po: Updated Hungarian translation. 2002-08-11 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-08-11 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-08-10 Vincent van Adrighem * nl.po: Reinout van Schouwen updated the Dutch translation. 2002-08-10 Christian Meyer * de.po: Fixed. 2002-08-10 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-08-09 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-08-09 Christian Meyer * de.po: Fixed accelerators, typos and other stuff. 2002-08-07 Evandro Fernandes Giovanini * pt_BR.po: Updated Brazilian Portuguese translation. 2002-08-06 Manuel Borchers * de.po: Updated German translation with mnemonics and converted to utf-8 2002-08-06 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-08-06 jacob berkman * vi.po: fix 2002-08-06 Christophe Merlet * fr.po: Updated French translation. 2002-08-05 Pablo Saratxaga * vi.po: Updated Vietnamese file === nemo 2.0.3 === 2002-08-03 Matthias Warkus * de.po: Small fixes to German translation. 2002-08-01 Christian Rose * sv.po: More fixes in Swedish translation. 2002-08-01 Christian Rose * sv.po: Another fix in Swedish translation. 2002-08-01 Christian Rose * sv.po: Fixed Swedish translation. 2002-07-29 Fatih Demir * tr.po: Committed updated Turkish translation. 2002-07-26 Gustavo Noronha Silva * pt_BR.po: Updated Brazilian translation, by Evandro Fernandes Giovanini . 2002-07-25 Ole Laursen * da.po: Updated Danish translation. === nemo 2.0.2 === 2002-07-23 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-07-23 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-07-23 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-07-23 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 2.0.1 === 2002-07-23 Gustavo Noronha Silva * pt_BR.po: update by Evandro Fernandes Giovanini 2002-07-22 Jordi Mallach * ca.po: Updated Catalan translation. 2002-07-22 Christian Rose * sv.po: Updated Swedish translation. 2002-07-22 Alexander Larsson * POTFILES.skip: Add news sidebar files. 2002-07-22 Christian Rose * sv.po: Updated Swedish translation. 2002-07-22 Jordi Mallach * ca.po: Updated Catalan translation. 2002-07-22 Changwoo Ryu * ko.po: Updated Korean translation from Youngho Cha . 2002-07-21 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-07-20 Matthias Warkus * de.po: Updated German translation. 2002-07-19 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-07-19 Ole Laursen * da.po: Unfuzzified a string. 2002-07-19 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-07-19 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-07-18 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-07-17 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-07-16 Michael Meeks * POTFILES.in: remove news files & update server files. 2002-07-15 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-07-15 Changwoo Ryu * ko.po: Updated Korean translation from Youngho Cha . 2002-07-13 Christian Rose * sv.po: Updated Swedish translation. 2002-07-13 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-07-13 Jordi Mallach * ca.po: Updated Catalan translation. 2002-07-13 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-07-13 Ole Laursen * da.po: Updated Danish translation. 2002-07-12 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-07-12 Jordi Mallach * ca.po: Updated Catalan translation. 2002-07-11 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-07-12 Christian Rose * sv.po: Updated Swedish translation. 2002-07-11 Christian Rose * sv.po: Updated Swedish translation. 2002-06-11 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-07-10 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-07-11 Christian Rose * sv.po: Updated Swedish translation. 2002-07-10 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-07-09 Changwoo Ryu * ko.po: Updated Korean translation from Michelle Kim . 2002-07-09 Christian Rose * sv.po: Updated Swedish translation. 2002-07-08 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-07-07 Christophe Fergeau * fr.po: Updated French translation. 2002-07-06 Christian Rose * sv.po: Updated Swedish translation. 2002-07-04 Peteris Krisjanis * lv.po: Updated Latvian translation. 2002-07-03 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-06-25 Changwoo Ryu * ko.po: Updated Korean translation from Young-Ho Cha . 2002-06-20 Pablo Saratxaga * vi.po: Updated Vietnamese file 2002-06-21 Changwoo Ryu * ko.po: Updated Korean translation from Young-Ho Cha . 2002-06-20 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-06-19 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-06-20 Akira TAGOH * ja.po: Updated Japanese translation. 2002-06-16 Vincent van Adrighem * nl.po: Reinout van Schouwen updated the Dutch translation. Sorry for the delay Reinout... 2002-06-16 Christophe Merlet * fr.po: Updated French translation. 2002-06-16 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-06-14 Changwoo Ryu * ko.po: Updated Korean translation. 2002-06-13 Christophe Merlet * fr.po: Updated French translation. 2002-06-12 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-06-11 Pablo Gonzalo del Campo * es.po: Fix a string in Spanish translation. 2002-06-10 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-06-10 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-06-10 Changwoo Ryu * ko.po: Updated Korean translation from Young-Ho Cha . 2002-06-10 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-06-09 Pablo Gonzalo del Campo * es.po: Fix a string in Spanish translation. 2002-06-09 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-06-09 Carlos Perello Marin * pt_BR.po: Gustavo Noronha Silva 2002-06-09 Jordi Mallach * ca.po: Updated Catalan translation. 2002-06-09 Christian Rose * sv.po: Updated Swedish translation. 2002-06-07 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-06-06 Dmitry G. Mastrukov * ru.po: updated Russian translation. 2002-06-05 Dmitry G. Mastrukov * ru.po: updated Russian translation 2002-06-05 Christian Rose * sv.po: Fix. 2002-06-04 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-06-04 Jordi Mallach * ca.po: Updated Catalan translation. 2002-06-03 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. === nemo 1.1.19 === Mon Jun 03 14:18:51 2002 George Lebl * cs.po: update 2002-06-03 German Poo Caamano * es.po: Updated Spanish translation. 2002-06-03 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-06-03 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-06-03 Christian Rose * sv.po: Small fix. 2002-06-03 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . 2002-06-03 Dmitry G. Mastrukov * ru.po: updated Russian translation 2002-06-02 Christian Rose * sv.po: Small fixes. 2002-06-02 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-06-02 Christian Rose * sv.po: Updated Swedish translation. 2002-06-02 Ole Laursen * da.po: Updated Danish translation. 2002-06-01 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-06-01 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-06-01 Christian Rose * sv.po: Updated Swedish translation. 2002-05-31 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-05-30 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2002-05-31 Ole Laursen * da.po: Updated Danish translation. 2002-05-30 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-28 Vincent van Adrighem * nl.po: Big overhaul. Reinout van Schouwen updated the Dutch translation with some help from his sister. 2002-05-28 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2002-05-28 Duarte Loreto * pt.po: Updated Portuguese translation. === nemo 1.1.18 === 2002-05-27 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-05-27 Dmitry G. Mastrukov * ru.po: updated Russian translation 2002-05-26 Ole Laursen * da.po: Updated Danish translation. 2002-05-25 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-25 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2002-05-23 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2002-05-23 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2002-05-23 Yanko Kaneti * bg.po: Added Bulgarian translation from Borislav Aleksandrov . 2002-05-21 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-05-21 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-05-21 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . 2002-05-20 Alessio Frusciante * it.po: Updated Italian translation. 2002-05-20 Vlad Harchev * ru.po: updated russian translation from Dmitry G. Mastrukov . === nemo 1.1.17 === 2002-05-16 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-05-15 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-15 Gediminas Paulauskas * lt.po: Updated Lithuanian translation. 2002-05-14 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2002-05-14 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-05-14 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-05-13 Ole Laursen * da.po: Updated Danish translation, fixed a few long-standing bugs. === nemo 1.1.16 === 2002-05-13 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-05-11 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-05-11 Ole Laursen * da.po: Updated Danish translation. 2002-05-10 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-10 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho Cha . 2002-05-09 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-08 Duarte Loreto * pt.po: Updated Portuguese translation and converted to UTF-8. 2002-05-07 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-05-06 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. === nemo 1.1.15 === 2002-05-05 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-05-05 Christophe Merlet * fr.po: Updated French translation. 2002-05-02 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2002-05-02 Changwoo Ryu * ko.po: Updated Korean translation by Young-Ho, Cha . 2002-04-30 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-04-29 Pablo Saratxaga * eu.po: Added Basque file 2002-04-29 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 1.1.14 === 2002-04-28 Fatih Demir * tr.po: Committed updated Turkish translation by Omer. 2002-04-23 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-04-23 Benedikt Roth * de.po: Fixes and updates for German translation. 2002-04-22 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 1.1.13 === 2002-04-20 Simos Xenitellis * el.po: Updated Greek translation. 2002-04-19 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-04-19 Changwoo Ryu * ko.po: Updated Korean translation from Young-Ho Cha . 2002-04-18 Pablo Saratxaga * ca.po: Updated Catalan file 2002-04-18 Vincent van Adrighem * nl.po: Updated Dutch translation by Ronald Hummelink. 2002-04-17 Pablo Saratxaga * vi.po: Added Vietnamese file 2002-04-16 Ole Laursen * da.po: Updated Danish translation. === nemo 1.1.12 === 2002-04-11 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-04-09 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-04-08 Christian Rose * POTFILES.in: Added missing file. * sv.po: Updated Swedish translation. 2002-04-06 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-04-06 Ole Laursen * da.po: Updated Danish translation. 2002-04-05 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-04-03 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-04-02 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-04-01 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-03-31 Christian Rose * sv.po: Updated Swedish translation. 2002-03-29 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-03-29 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-03-28 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-03-28 Ole Laursen * da.po: Updated Danish translation. 2002-03-28 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-03-26 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-03-26 Stanislav Visnovsky * sk.po: Updated Slovak translation. === nemo 1.1.11 === 2002-03-24 Alexander Larsson * POTFILES.in: Revert change by lark. Now make dist works again 2002-03-24 Wang Jian * zh_CN.po: Updated Simplified Chinese translation. 2002-03-21 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-03-21 German Poo-Caaman~o * es.po: Updated spanish translation from Pablo Gonzalo del Campo 2002-03-20 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-03-19 Ole Laursen * da.po: Updated Danish translation. 2002-03-18 Hasbullah Bin Pit * ms.po: Updated Malay Translation. === nemo 1.1.10 === 2002-03-17 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-03-17 Valek Filippov * ru.po: updated russian translation. 2002-03-17 Hasbullah Bin Pit * ms.po: Updated Malay Translation. 2002-03-15 Matthias Warkus * de.po: Updated German translation. 2002-03-15 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-03-15 Hasbullah Bin Pit * ms.po: Added Malay Translation. 2002-03-14 Christian Meyer * de.po: Exchanged German translation by my version. 2002-03-13 Matthias Warkus * de.po: Updated German translation 2002-03-12 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 1.1.9 === 2002-03-10 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-03-10 Christian Rose * POTFILES.in: Added missing file. * sv.po: Updated Swedish translation. 2002-03-08 Valek Filippov * ru.po: updated russian translation. 2002-03-07 Darin Adler * POTFILES.in: Zoom control doesn't have a translatable string any more. We don't need to translate x%. 2002-03-07 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-03-06 Darin Adler * POTFILES.skip: Add the libbackground file in here to quiet down intltool-update. 2002-03-06 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 1.1.8 === 2002-03-05 Carlos Perello Marin * es.po: Updated by Pablo del Campo , welcome Pablo. Also recoded as UTF-8 === nemo 1.1.7 === 2002-03-03 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-03-01 Christian Rose * sv.po: Updated Swedish translation. 2002-03-01 Pauli Virtanen * fi.po: Updated Finnish translation. 2002-03-01 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . 2002-03-01 Christophe Merlet * fr.po: Updated French translation and converted to UTF-8. 2002-02-28 Ole Laursen * da.po: Updated Danish translation. 2002-02-28 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-02-27 Darin Adler * POTFILES.in: Fix what I corrupted. 2002-02-27 Darin Adler * POTFILES.in: Remove nemo-about.c. === nemo 1.1.6 === 2002-02-26 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-02-23 Carlos Perell?? Mar??n * es.po: Updated with our translation memory && some personal updates. 2002-02-22 Darin Adler * POTFILES.in: Remove libbackground/applier.c, because it's not in the tarball, just in cvs, so it breaks tarball builds. Remove nemo-icon-text-item.c. * POTFILES.skip: Remove image-viewer. 2002-02-22 Christian Rose * sv.po: Updated Swedish translation. 2002-02-20 Michael Meeks * POTFILES.in: move image-viewer bits * POTFILES.skip: here. 2002-02-17 Wang Jian * zh_CN.po: Updated Simplified Chinese translation. 2002-02-10 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-02-10 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * POTFILES.in: Added data/*directory.in, components/tree/nemo-tree-model.c, libbackground/applier.c === nemo 1.1.5 === 2002-02-09 Darin Adler * POTFILES.in: Add nemo-dnd.c 2002-02-10 Ole Laursen * da.po: Updated Danish translation. 2002-02-09 Pauli Virtanen * fi.po: Updated Finnish translation and converted it to UTF-8. 2002-02-08 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-02-08 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2002-02-07 Changwoo Ryu * ko.po: Updated Korean translation. === nemo 1.1.4 === 2002-02-04 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-02-03 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-01-31 Christian Rose * sv.po: Updated Swedish translation. 2002-01-30 Ole Laursen * da.po: Updated Danish translation and converted it to UTF-8. 2002-01-30 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-01-30 Zbigniew Chyla * pl.po: Updated Polish translation by GNOME PL Team . === nemo 1.1.3 === 2002-01-27 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2002-01-27 Christian Rose * sv.po: Converted it to UTF-8. 2002-01-26 Christian Rose * sv.po: Updated Swedish translation. 2002-01-24 Ole Laursen * da.po: Updated Danish translation. 2002-01-23 Roy-Magne Mo * nn.po: Using translation from nemo 1.0 and converted it to UTF-8 2002-01-22 Christian Rose * sv.po: Updated Swedish translation. 2002-01-22 Seth Nickell reviewed by: * POTFILES.in: 2002-01-22 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2002-01-21 Christian Rose * sv.po: Updated Swedish translation. === nemo 1.1.2 === 2002-01-16 Darin Adler * POTFILES.skip: Removed the *.oaf.in files, so they don't need to be in here any more. 2002-01-16 Wang Jian * zh_CN.po: Updated Simplified Chinese translation. 2002-01-16 Christian Rose * POTFILES.in: Removed *oaf.in files. * POTFILES.skip: Moved them here. 2002-01-16 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. === nemo 1.1.1 === 2002-01-15 Darin Adler * POTFILES.in: So long, shell.c. 2002-01-14 Christian Rose * POTFILES.ignore: Renamed to POTFILES.skip to make intltool happier. * sv.po: Updated Swedish translation. 2002-01-09 Stanislav Visnovsky * sk.po: Updated Slovak translation 2002-01-08 Duarte Loreto * pt.po: Updated Portuguese translation. 2002-01-08 Darin Adler * POTFILES.in: So long nemo-help.desktop.in 2002-01-07 Darin Adler * POTFILES.in: Adios nemo-font-factory.c 2002-01-05 Christian Rose * sv.po: Updated Swedish translation. 2002-01-05 Christian Rose * POTFILES.in: Added missing files. * POTFILES.ignore: Added files that reportedly should not be translated. * sv.po: Updated Swedish translation. 2002-01-02 Marius Andreiana * ro.po: updated 2001-12-26 Fatih Demir * tr.po: Small correction in the charset field of the po file. 2001-12-19 Andras Timar * hu.po: Updated Hungarian translation from Emese. 2001-12-16 Duarte Loreto * pt.po: Updated Portuguese translation. 2001-12-14 Seth Nickell * POTFILES.in: Moved programs.desktop.in to applications.desktop.in 2001-12-13 Darin Adler * POTFILES.in: Removed translations for the help component. If we ever revive it, we can get the translations from here. 2001-12-06 Darin Adler * POTFILES.in: Moved mozilla component into its own module. 2001-12-05 Christian Rose * sv.po: Updated Swedish translation. 2001-12-02 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-11-28 Pablo Saratxaga * az.po: Updated Azeri file 2001-11-20 Christian Meyer * de.po: Updated German translation. 2001-11-18 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2001-11-16 Pablo Saratxaga * az.po: Updated Azeri file 2001-11-13 Wang Jian * zh_CN.po: Updated Simplified Chinese translation by Wang Jian. 2001-11-11 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-11-10 Peteris Krisjanis * lv.po: updated Latvian translation. 2001-11-08 Darin Adler * POTFILES.in: oaf -> server. 2001-11-08 Darin Adler * POTFILES.in: Remove all the link set stuff. 2001-11-08 Darin Adler * POTFILES.in: Add nemo-hyperbola-ui.xml 2001-11-07 Darin Adler * .cvsignore: Ignore glib-gettextize spoor. * POTFILES.in: Remove help converters, which have been moved to libgnome. 2001-11-07 Ole Laursen * da.po: Updated Danish translation - removed a lot of the old package management strings. 2001-11-07 Abel Cheung * zh_TW.po: A few fixes. 2001-11-07 Abel Cheung * zh_TW.po: Updated traditional Chinese translation. 2001-11-03 Carlos Perell?? Mar??n * POTFILES.in: Sync 2001-10-30 Benedikt Roth * de.po: Fix for German translation 2001-10-30 Christian Meyer * de.po: Fixed a typo, changed News-Panel to Neues-Panel. 2001-10-20 Christian Rose * sv.po: Fixed a problem with the Swedish translation. Thanks to Johan Dahlin for reporting this. 2001-10-20 Christian Rose * sv.po: Fixed a problem with the Swedish translation. Thanks to Anders Carlsson for reporting this. === nemo 1.0.5 === 2001-10-19 Darin Adler * *.po: Nemo 1.0.5 release. 2001-10-13 Carlos Perell?? Mar??n * pt.po: Added by Duarte Loreto 2001-10-12 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation. 2001-10-11 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-10-10 Matthias Warkus * de.po: Updated for release 2001-10-08 Peteris Krisjanis * lv.po: Latvian po first commit 2001-10-08 Pablo Saratxaga * az.po: Updated Azeri file 2001-10-07 Carlos Perell?? Mar??n * es.po: Fixed bug #61924 2001-10-07 Ole Laursen * da.po: Updated Danish translation. 2001-10-07 Sami Pesonen * fi.po: Updated Finnish translation by Pauli Virtanen . 2001-10-07 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-10-06 Carlos Perell?? Mar??n * es.po: Reviewed && updated. 2001-10-03 Christian Rose * sv.po: Updated Swedish translation. 2001-10-03 Valek Filippov * ru.po: updated russian translation. 2001-10-02 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-10-02 Frederic Crozat * fr.po: Add missing ' ' in which was oversizing Nemo Preference Dialog 2001-09-29 Christian Rose * sv.po: Updated Swedish translation. 2001-09-28 Pablo Saratxaga * az.po: Updated Azeri file 2001-09-24 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-09-24 Gediminas Paulauskas * lt.po: Updated Lithuanian translation. 2001-09-22 Christian Meyer * de.po: Updated German translation. 2001-09-22 Wang Jian * zh_CN.po: Updated Simpfiled Chinese translation. 2001-09-21 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation. 2001-09-21 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-09-17 Akira TAGOH * ja.po: Updated Japanese translation. 2001-09-14 Christian Rose * POTFILES.in: Added missing .desktop.in files. * sv.po: Updated Swedish translation. 2001-09-13 Pablo Saratxaga * ca.po: Updated Catalan file 2001-09-11 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-09-11 Christian Rose * sv.po: Updated Swedish translation. 2001-09-11 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-09-10 Pablo Saratxaga * ga.po: Updated Irish file 2001-09-08 Abel Cheung * Updated traditional Chinese translation. 2001-09-03 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-09-01 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-09-01 Christophe Merlet * fr.po: Updated French translation from Christophe Fergeaux . 2001-09-01 Wang Jian * zh_CN.po: Updated Simplifed Chinese. 2001-09-01 Wang Jian * zh_CN.po: Renamed from zh_CN.GB2312.po. * zh_CN.po: Updated Simplified Chinese. 2001-08-31 Yukihiro Nakai * ja.po: Update Japanese translation and overwrite Tagoh's work (w 2001-08-31 Abel Cheung * zh_TW.Big5.po: Rename to ...... * zh_TW.po: This. 2001-08-31 Akira TAGOH * ja.po: Updated Japanese translation. 2001-08-29 Wang Jian * zh_CN.GB2312.po: Translation update. 2001-08-27 Ole Laursen * da.po: Updated Danish translation. 2001-08-27 Abel Cheung * ro.po: Modified line 5010, gettext complains. * zh_CN.GB2312.po: Modified line 130, reason is the same as above. 2001-08-22 Christian Meyer * de.po: Update hence my recent changes. * POTFILE.in: Removed nemo-services-ui.xml. 2001-08-20 Christian Meyer * de.po: Updated German translation. Fixed some nasty strings. Added some comments. Fixed mawa's email. Made translation for consistent. 2001-08-19 Jesus Bravo Alvarez * gl.po: (Partially) Updated Galician translation. 2001-08-19 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-08-19 Wang Jian * zh_CN.GB2312.po: Added by Wang Jian . 2001-08-15 Darin Adler * POTFILES.in: Add the file system XML file. 2001-08-06 Yukihiro Nakai * ja.po: Update Japanese translation. 2001-07-29 Christian Meyer * de.po: Updated German translation. Corrected my email address. Changed "Factory" in translated messages to "Fabrik" 2001-07-24 Ole Laursen * da.po: Revamped a few strings in Danish translation. 2001-07-23 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-07-22 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * nn.po: Updated Norwegian (nynorsk) translation. 2001-07-21 Christian Rose * POTFILES.in: Added libnemo-private/nemo-customization-data.c. * sv.po: Updated Swedish translation. 2001-07-20 Ole Laursen * da.po: Updated & fixed a few strings in the Danish translation. 2001-07-20 Darin Adler * it.po: Current versions of libxml can't handle the " character, so we must use ' instead. For GNOME 2 we can upgrade the character. 2001-07-19 Marius Andreiana * ro.po: updated 2001-07-17 Christian Rose * sv.po: Updated Swedish translation. 2001-07-17 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-07-15 Kjartan Maraas * nn.po: Updated Norwegian (nynorsk) translation. * no.po: Updated Norwegian (bokmal) translation. 2001-07-15 Fatih Demir * tr.po: Committed updated Turkish translation by G??rkem Cetin. 2001-07-12 Christopher R. Gabriel * it.po: Updated italian translation. 2001-07-12 Christian Rose * sv.po: Translated Alex' newly added "Ext3 Volume" string. 2001-07-10 Christian Rose * sv.po: Minor fixes for the Swedish translation. 2001-07-10 Benedikt Roth * de.po: Fixed German translation * ChangeLog: Remove gettextize spam 2001-07-09 Christophe Merlet * fr.po: Updated French translation. 2001-07-05 Kjartan Maraas * no.po: Updated Norwegian translation. === Nemo 1.0.4 === 2001-07-05 Darin Adler * Makefile.i18npatch: * POTFILES.skip: * update.sh: Remove remnants of the old localization scheme. These are all superseded by xml-i18n-tools. 2001-07-05 Benedikt Roth * de.po: Updated German translation 2001-07-05 Christian Rose * sv.po: Updated Swedish translation. 2001-07-04 Pablo Saratxaga * ca.po: updated Catalan file 2001-07-01 Pablo Saratxaga * ca.po: updated Catalan file 2001-06-29 Benedikt Roth * de.po: Fixed a spelling mistake, fixed a grammar error 2001-06-27 Marius Andreiana * ro.po: updated 2001-06-23 Gediminas Paulauskas * lt.po: most obvious fixes for release. 2001-06-16 Christian Rose * sv.po: Additional small fixes. 2001-06-16 Christian Rose * sv.po: Fixed small typo in the Swedish translation. Thanks to G??ran Weinholt. 2001-06-14 Marius Andreiana * ro.po: added 2001-06-10 Pablo Saratxaga * az.po: Updated Azeri file 2001-06-08 Valek Filippov * ru.po: microupdated russian translation. Thu Jun 07 21:00:00 2001 Matthias Warkus * de.po: update for release 2001-06-07 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-06-07 Emese Kovacs * hu.po: updated Hungarian translation. 2001-06-07 Valek Filippov * ru.po: microupdated russian translation. 2001-06-07 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-06-07 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-06-06 Ole Laursen * da.po: Fixed a few things in Danish translation before release. 2001-06-06 Christian Rose * sv.po: Updated Swedish translation. Tue Jun 05 05:05:10 2001 George Lebl * cs.po: update, fix mistakes Tue Jun 05 04:50:48 2001 George Lebl * cs.po: Update czech translations 2001-06-04 Kjartan Maraas * no.po: Updated Norwegian translation. Sun Jun 03 14:37:17 2001 George Lebl * cs.po: update 2001-06-02 Christian Rose * sv.po: Updated Swedish translation. 2001-05-27 Matthias Warkus * de.po: Conflicts resolved, fixes 2001-05-26 Pablo Saratxaga * az.po: Updated Azeri file 2001-05-24 Christian Meyer * de.po: Small Update. Tue May 22 18:19:55 2001 George Lebl * cs.po: update 2001-05-21 Fatih Demir * ko.po: Updated Korean translation by Young-Ho. 2001-05-21 Pablo Saratxaga * ja.po,pl.po,uk.po,zh_TW.Big5.po: fixed syntax errors and multibyte Sat May 19 14:47:34 2001 George Lebl * cs.po: update 2001-05-17 Ole Laursen * da.po: Updated Danish translation. 2001-05-16 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-05-16 Christian Rose * sv.po: Updated Swedish translation. 2001-05-15 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-05-15 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-05-14 Christian Rose * sv.po: Updated Swedish translation. 2001-05-09 Christian Rose * sv.po: Updated Swedish translation. 2001-05-08 Valek Filippov * ru.po: updated russian translation. 2001-05-06 Jarkko Ranta * fi.po: Updated Finnish translation by Pauli Virtanen. 2001-05-05 Ole Laursen * da.po: Updated Danish translation. 2001-05-04 Ramiro Estrugo * es.po: Fix a really tiny typo. 2001-05-04 Ramiro Estrugo * POTFILES.in: * az.po: * ca.po: * cs.po: * da.po: * de.po: * el.po: * en_GB.po: * es.po: * fi.po: * fr.po: * ga.po: * gl.po: * hu.po: * it.po: * ja.po: * ko.po: * lt.po: * nl.po: * nn.po: * no.po: * pl.po: * pt_BR.po: * ru.po: * sk.po: * sl.po: * sv.po: * ta.po: * tr.po: * uk.po: * zh_TW.Big5.po: Update for more stuff moving to eel. 2001-05-03 Ramiro Estrugo * az.po: * ca.po: * cs.po: * da.po: * de.po: * el.po: * en_GB.po: * es.po: * fi.po: * fr.po: * ga.po: * gl.po: * hu.po: * it.po: * ja.po: * ko.po: * lt.po: * nl.po: * nn.po: * no.po: * pl.po: * pt_BR.po: * ru.po: * sk.po: * sl.po: * sv.po: * ta.po: * tr.po: * uk.po: * zh_TW.Big5.po: Update for libnemo-extensions -> libnemo-private renaming. 2001-05-03 Matthias Warkus * de.po: Updated German translation 2001-05-02 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-05-02 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-05-01 Pablo Gonzalo del Campo * es.po: Updated Spanish Tranlation 2001-05-01 Zbigniew Chyla * pl.po: Updated Polish translation. 2001-04-30 Ramiro Estrugo * POTFILES.in: Rename the theme directories to match their displayed name. 2001-05-01 Zbigniew Chyla * POTFILES.in: Added components/news/nemo-news.c, components/news/Nemo_View_news.oaf.in 2001-04-30 Fatih Demir * ko.po: Committed updated Korean translation by Young-Ho. 2001-04-30 Matthias Warkus * de.po: Merged my changes with Christian's, added some fixes and consistency. 2001-04-30 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-04-29 Dan Mueth * lt.po: Added updated po file from Mantas 2001-04-29 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-04-29 Fatih Demir * tr.po: Updated Turkish translation by G??rkem. 2001-04-29 Christian Meyer * de.po: Updated German translation. 2001-04-27 Darin Adler * ja.po: Removed one translation that was triggering some kind of strange bug or feature in libxml. This is a very unimportant message to translate anyway, that never shows to the user. We can re-add it some day once the problem in libxml is resolved. 2001-04-27 Valek Filippov * ru.po: updated russian translation. 2001-04-27 Christian Rose * sv.po: Updated Swedish translation. 2001-04-26 Ole Laursen * da.po: Fixed a lot of things. 2001-04-25 Christian Rose * sv.po: Updated Swedish translation. 2001-04-25 Christian Meyer * de.po: Small update for German translation. Fixed my email address. 2001-04-25 Changwoo Ryu * ko.po: Updated Korean translation, by . 2001-04-25 Christian Rose * sv.po: Updated Swedish translation. 2001-04-24 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-04-23 Stanislav Visnovsky * sk.po: Updated slovak translation. 2001-04-23 Valek Filippov * ru.po: updated russian translation. 2001-04-23 Pablo Saratxaga * pl.po: enabled the header 2001-04-22 Ole Laursen * da.po: Updated Danish translation. Sat Apr 21 14:52:14 2001 George Lebl * cs.po: update 2001-04-21 Almer S. Tigelaar For Dirk-Jan C. Binnema : * nl.po: Updated Dutch translation. 2001-04-21 Matthias Warkus * de.po: Update, commit for release. 2001-04-21 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-04-20 Christian Rose * sv.po: Updated Swedish translation. 2001-04-19 Ramiro Estrugo * POTFILES.in: Update for new and removed files. Thu Apr 19 18:29:10 2001 George Lebl * cs.po: yet another update Wed Apr 18 23:24:41 2001 George Lebl * cs.po: more then half translated now Tue Apr 17 22:31:07 2001 George Lebl * cs.po: another bunch of translations Mon Apr 16 08:06:45 2001 George Lebl * cs.po: I'm too tired to code and have a couple of ours to kill instead of going to sleep, so here's another bunch of translations, now up to like 28% translated. Damn there is a lot of strings in nemo. 2001-04-16 Zbigniew Chyla * pl.po: Updated Polish translation 2001-04-13 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kov???cs (date string fixes) 2001-04-12 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kov???cs 2001-04-12 Pablo Saratxaga * az.po: Updated Azeri file 2001-04-12 Christian Rose * sv.po: Updated and fixed Swedish translation. Thanks to G??ran Uddeborg and Per Lindstr??m . 2001-04-11 Christian Rose * sv.po: Updated Swedish translation. 2001-04-11 Fatih Demir * tr.po: Committed updated Turkish translation. 2001-04-09 Pablo Saratxaga * az.po: Updated Azeri file 2001-04-09 Akira TAGOH * ja.po: Updated Japanese translation from Satoru Sato 2001-04-07 Fatih Demir * tr.po: Committed updated Turkish translation. 2001-04-04 Ramiro Estrugo * POTFILES.in: Remove a retired file. 2001-04-04 Christian Rose * sv.po: Updated Swedish translation. 2001-04-03 Ramiro Estrugo * everything: Update for eel changes. 2001-04-03 Christian Rose * sv.po: Updated Swedish translation. 2001-03-29 Darin Adler * de.po: Added missing characters to some long lines in the first time druid indexing messages to fix wide druid window. 2001-03-27 Simos Xenitellis * el.po: Update of Greek translation. 2001-03-27 Christian Rose * sv.po: Updated Swedish translation. 2001-03-26 Christian Rose * sv.po: Updated Swedish translation. 2001-03-24 Christian Rose * sv.po: Updated Swedish translation. 2001-03-23 Gediminas Paulauskas * lt.po: Added Lithuanian translation. 2001-03-22 Fatih Demir * tr.po: Cp stable HEAD. 2001-03-16 Pablo Saratxaga * az.po: Updated Azeri file * {el,ko,sl,uk}.po: fixed charset line and/or syntax errors 2001-03-15 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-03-15 Christian Rose * sv.po: Improved the Swedish translation, thanks goes to G??ran Uddeborg . 2001-03-12 Ramiro Estrugo * ja.po: Add missing quotes at end of many lines to fix the build. 2001-03-13 Takuo KITAME * ja.po: Updated Japanese translation. 2001-03-12 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation. 2001-03-12 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kovacs , QA in running Nemo :-) 2001-03-11 Jesus Bravo Alvarez * gl.po: Partially updated Galician translation. 2001-03-11 Christian Rose * sv.po: Updated Swedish translation. 2001-03-10 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kovacs , QA in running Nemo :-) 2001-03-10 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kovacs , spelling and typo fixes by Andras Timar . 2001-03-09 Matthias Warkus * de.po: Finally commit translation 2001-03-09 Christophe Merlet * fr.po: Updated French translation. 2001-03-08 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2001-03-08 Darin Adler * sv.po: Added missing characters to some long lines in the first time druid indexing messages to fix wide druid window. 2001-03-08 Szabolcs Ban * hu.po: Update of Hungarian translation by Emese Kovacs . 2001-03-08 Christophe Merlet * fr.po: Updated French translation. Use French quote intead of simple quote. 2001-03-07 Darin Adler * fr.po: Use 'Loser' instead of "Loser", since gnome-xml (I think the problem is gnome-xml) can't handle parsing a string with an entity-escaped quote in it, even if the quote is entity-escaped. We can only change this back once OAF has been updated to require a new gnome-xml and we have beep updated to require a new OAF. 2001-03-07 Darin Adler * da.po: Fixed recently-changed da.po (checked in without a ChangeLog entry) to get rid of entries where the original text does not end with " ", but the translated text does. Apparently, the gettext framework does not allow this kind of translation, even though I can see why it could be desirable. 2001-03-07 Christophe Merlet * fr.po: Updated French translation. 2001-03-07 Mathieu Lacage * fr.po: updated frenh translation. still a long way to go before it is finished. 2001-03-07 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-03-06 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-03-06 Christian Rose * sv.po: Updated Swedish translation. 2001-03-06 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-03-06 Christian Rose * sv.po: Updated Swedish translation. 2001-03-05 Pablo Gonzalo del Campo * Updated Spanish Translation 2001-03-06 Pauli Virtanen * fi.po: Updated Finnish 2001-03-05 Darin Adler * en_GB.po: Update of "make check" test results. 2001-03-05 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-03-05 Ramiro Estrugo * ja.po: Updated Japanese translation. The only thing I updated was the localized fonts strings to make my latest round of localization fixes in nemo work in the ja locale. 2001-03-03 Christian Rose * sv.po: Updated Swedish translation. 2001-03-02 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2001-03-02 Simos Xenitellis * el.po: Updated Greek translation. 2001-03-02 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-03-02 Simos Xenitellis * el.po: Updated Greek translation. 2001-03-02 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-03-02 Simos Xenitellis * el.po: Updated Greek translation. 2001-03-02 Christian Rose * sv.po: Updated Swedish translation. 2001-03-01 Darin Adler Work around bug in xml-i18n-tools that created bug 7230 (opening images fails). * hu.po: Use single quotes for now until we have the xml-i18n-tools that can handle \" characters widely enough distributed. 2001-03-01 Darin Adler * hu.po: Fix entry that was missing " ". 2001-03-01 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-03-01 Christian Rose * sv.po: Updated Swedish translation. 2001-03-01 Christophe Merlet * fr.po: Updated French translation. 2001-03-01 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * POTFILES.in: Added missing files. 2001-02-28 Takuo KITAME * ja.po: Updated Japanese translation. 2001-02-28 Eskil Heyn Olsen * da.po: Updated the View as XXX strings, not that it helped. 2001-02-28 Darin Adler * POTFILES.in: Added nemo-password-dialog.c 2001-03-01 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-28 Christian Rose * sv.po: Updated Swedish translation. 2001-02-28 Valek Filippov * ru.po: updated russian translation. 2001-02-28 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-27 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-27 Simos Xenitellis * el.po: Updated Greek translation. 2001-02-27 Christian Rose * sv.po: Updated Swedish translation. 2001-02-27 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-02-27 Matthias Warkus * de.po: Fix, fix, update, fix, fix. 2001-02-27 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-27 Christian Rose * sv.po: Updated Swedish translation. 2001-02-26 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-27 Pauli Virtanen * fi.po: Updated Finnish translation 2001-02-26 Szabolcs Ban * hu.po: Update of Hungarian translation by emese. 2001-02-26 Christian Rose * sv.po: Updated Swedish translation. 2001-02-26 Simos Xenitellis * el.po: Translated more messages to Greek :) 2001-02-25 Matthias Warkus * de.po: Updated again. Strings keep changing! This is mayhem. Someone please do some peer review. There are just about two or three days left. 2001-02-25 Simos Xenitellis * el.po: Updated Greek translation. 2001-02-25 Fatih Demir * tr.po: Committed updated Turkish translation. 2001-02-25 Christian Rose * sv.po: Updated Swedish translation. 2001-02-24 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-24 Gene Z. Ragan * POTFILES.in: Added libnemo-extensions/nautulus-drag.c 2001-02-24 Pauli Virtanen * fi.po: Updated Finnish translation 2001-02-24 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-02-24 Christian Rose * POTFILES.in: Added missing music view files. * sv.po: Updated Swedish translation. 2001-02-24 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-24 Szabolcs Ban * hu.po: Update of Hungarian translation. 2001-02-24 Christian Rose * sv.po: Updated Swedish translation. 2001-02-23 Kjartan Maraas * no.po: Updated Norwegian translation. 2001-02-23 Matthias Warkus * de.po: Fixes and updates to German l10n. 2001-02-23 Laszlo Kovacs * POTFILES.in: components/help/hyperbola-filefmt.c added 2001-02-23 Ramiro Estrugo * POTFILES.in: Add more missing files. This three have (or soon will have) font names for localization. 2001-02-23 Christian Rose * sv.po: Updated Swedish translation. 2001-02-23 Simos Xenitellis * el.po: More updates in messages. * el.po: Updated Greek translation. 2001-02-22 Yukihiro Nakai * ja.po: Update Japanese translation. 2001-02-22 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-22 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-22 Ramiro Estrugo * po/POTFILES.in: Added new file with mozilla charset encoding strings tables. 2001-02-21 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-21 Akira TAGOH * ja.po: Updated Japanese translation. 2001-02-21 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation. 2001-02-22 Christian Rose * sv.po: Updated Swedish translation. 2001-02-21 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * da.po: Committed an update from Kenneth. 2001-02-21 Yukihiro Nakai * ja.po: Update Japanese translation. 2001-02-21 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-21 Matthias Warkus * de.po: Updated for freeze etc. 2001-02-21 Fatih Demir * ko.po: Committed updated Korean translation. 2001-02-20 Darin Adler * da.po: Another update from Kjenneth. 2001-02-21 Christian Rose * sv.po: Updated Swedish translation. 2001-02-20 Darin Adler * da.po: Update of Danish translation from Kjenneth Christiansen . 2001-02-20 Simos Xenitellis * el.po: Update of Greek translation. 2001-02-20 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * POTFILES.in: Update. 2001-02-19 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-19 Simos Xenitellis * el.po: Updated Greek translation. 2001-02-19 Christian Rose * sv.po: Updated Swedish translation. 2001-02-19 Szabolcs Ban * hu.po: Update of Hungarian translation. 2001-02-19 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-19 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-19 Simos Xenitellis * el.po: Update of Greek translation. 2001-02-18 Christian Rose * sv.po: Updated Swedish translation. 2001-02-17 Christian Rose * sv.po: Updated Swedish translation. 2001-02-16 Ramiro Estrugo * POTFILES.in: Add some mozilla stuff that needs to be localized. 2001-02-16 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-16 Christian Rose * sv.po: Updated Swedish translation. 2001-02-15 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-02-15 Christophe Merlet * fr.po: Updated French translation. 2001-02-14 Christophe Merlet * fr.po: Updated French translation. 2001-02-13 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * nn.po: Added Norwegian (nynorsk) translation. 2001-02-14 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-14 Christian Rose * sv.po: Updated Swedish translation. 2001-02-13 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-13 Christian Rose * sv.po: Updated Swedish translation. 2001-02-12 John Sullivan * sk.po: Removed an extra " " that didn't match between msgid and msgstr, breaking "make dist" 2001-02-12 Christophe Merlet * fr.po: Updated French translation. 2001-02-12 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-11 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-10 Matthias Warkus * de.po: Severely updated German translation ;) 2001-02-10 Pablo Gonzalo del Campo * es.po: Updated Spanish translation. 2001-02-09 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-07 Gustavo Maciel Dias Vieira * pt_BR.po: Updated Brazilian Portuguese translation. 2001-02-07 Pablo Gonzalo del Campo * Updated Spanish Translation 2001-02-07 Valek Filippov * ru.po: updated russian translation. 2001-02-07 Martin Norb??ck * sv.po: Updated Swedish translation 2001-02-06 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation 2001-02-06 Fatih Demir * ko.po: Committed updated Korean translation. 2001-02-05 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-05 Christian Rose * sv.po: Updated Swedish translation. 2001-02-04 Fatih Demir * tr.po: Committed updated Turkish translation by G??rkem Cetin. 2001-02-03 Pablo Gonzalo del Campo * es.po: Updated Spanish Translation. 2001-02-03 Christian Rose * sv.po: Updated Swedish translation. 2001-02-02 Martin Norb??ck * sv.po: Fixed some errors in the translation 2001-02-02 Christian Rose * sv.po: Updated Swedish translation. 2001-02-02 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-02 Martin Norb??ck * sv.po: Updated Swedish translation. 2001-01-29 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * POTFILES.in: Updated and ran it through sort. 2001-02-01 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-02-01 Martin Norb??ck * sv.po: Updated Swedish translation. 2001-01-31 Szabolcs Ban * hu.po: Terminology fixes by Andras Timar 2001-01-31 Carlos Perell?? Mar??n * es.po: Updated Spanish translation from Pablo del Campo 2001-01-31 Martin Norb??ck * sv.po: Updated Swedish translation. 2001-01-31 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-01-22 Martin Norb??ck * sv.po: Updated Swedish translation. 2001-01-30 Simos Xenitellis * el.po: Addition of initial Greek translation. 2001-01-30 Christian Rose * sv.po: Updated Swedish translation. 2001-01-29 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-01-29 Fatih Demir * ko.po: Committed updated Korean translation. 2001-01-29 Manuel de Vega Barreiro * es.po: Updated Spanish translation 2001-01-29 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-01-29 Fatih Demir * tr.po: Committed updated Turkish translation by Gorkem Cetin. 2001-01-28 Christian Rose * sv.po: Updated Swedish translation. 2001-01-27 Fatih Demir * ko.po: Committed updated Korean translation. 2001-01-26 Pablo Saratxaga * az.po: Added Azeri file * {ga,ko,pl,ta,uk}.po: corrected headers and syntax errors 2001-01-26 Valek Filippov * ru.po: updated russian translation. 2001-01-26 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-01-25 Christian Rose * sv.po: Updated Swedish translation. 2001-01-24 Christian Rose * sv.po: Updated Swedish translation. 2001-01-24 Zbigniew Chyla * pl.po: Updated Polish translation 2001-01-24 Matthias Warkus * de.po: Big update. This is NOT yet release quality, though. 2001-01-24 Szabolcs Ban * hu.po: Tons of fixes by Andras and Emese (spelling, terminology, headers) 2001-01-24 Stanislav Visnovsky * sk.po: Updated Slovak translation. 2001-01-23 Fatih Demir * tr.po: Committed updated Turkish translation. 2001-01-22 Manuel de Vega Barreiro * es.po: Updated Spanish translation 2001-01-22 Christian Rose * sv.po: Updated Swedish translation. 2001-01-22 Carlos Perell?? Mar??n * es.po: Updated Spanish translation from Pablo del Campo 2000-01-21 Akira TAGOH * ja.po: Updated Japanese translation. 2001-01-20 Kenneth Christiansen * POTFILES.in: Update 2001-01-20 Fatih Demir * ko.po: Committed updated Korean translation. 2001-01-19 Carlos Perell?? Mar??n * es.po: Updated Spanish translation from Pablo del Campo 2001-01-19 Stanislav Visnovsky * sk.po: Added initial Slovak translation. 2001-01-18 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2001-01-17 Ramiro Estrugo * POTFILES.in: Remove nemo-user-level-manager.[ch] which was just retired. 2001-01-17 Christian Rose * sv.po: Updated Swedish translation. 2001-01-15 Darin Adler * POTFILES.in: * POTFILES.skip: Move files that are not part of what's currently built from POTFILES.in to POTFILES.skip. 2001-01-15 Christian Rose * sv.po: Updated Swedish translation. 2000-11-02 Manuel de Vega Barreiro * es.po: Updated Spanish translation. 2001-01-13 Christian Rose * sv.po: Updated Swedish translation. 2001-01-10 Christian Rose * sv.po: Updated Swedish translation. 2001-01-08 Christian Rose * sv.po: Updated Swedish translation. 2001-01-07 Matthias Warkus * de.po: Updated German translation. 2001-01-07 Benedikt Roth * de.po: Updated German translation 2001-01-07 Kjenneth Christiansen * da.po: Committed update. 2001-01-06 Fatih Demir * ko.po: Committed update. 2001-01-06 Christian Rose * sv.po: Updated Swedish translation. 2001-01-05 Christian Rose * update.sh: Added new xml-18n-tools-using update.sh script from Kenneth Christiansen . * sv.po: Updated Swedish translation. 2001-01-04 Matthias Warkus * de.po: Update. 2001-01-04 Christian Rose * sv.po: Updated Swedish translation. 2001-01-02 Christian Rose * sv.po: Updated Swedish translation. 2001-01-02 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-29 Fatih Demir * ko.po: Committed updated Korean translation by YHC ;-) 2000-12-27 Christian Rose * sv.po: Updated Swedish translation. 2000-12-25 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-22 Christian Rose * sv.po: Updated Swedish translation. 2000-12-21 Valek Filippov * ru.po: updated russian translation. 2000-12-21 Christian Rose * sv.po: Updated Swedish translation. 2000-12-20 Christian Rose * sv.po: Updated Swedish translation. 2000-12-19 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-19 Christian Rose * sv.po: Updated Swedish translation. 2000-12-18 Valek Filippov * ru.po: updated russian translation. 2000-12-17 Matthias Warkus * de.po: Update-O-Rama. 2000-12-17 Szabolcs Ban * hu.po: Updated Hungarian translation. 2000-12-17 Szabolcs Ban * hu.po: Updated Hungarian translation, fixed "fixed" translation. 2000-12-16 Christian Rose * sv.po: Updated Swedish translation. 2000-12-15 Zbigniew Chyla * pl.po: Updated Polish translation 2000-12-15 Christian Rose * sv.po: Updated Swedish translation. 2000-12-14 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-14 Martin Norb??ck * sv.po: Updated Swedish translation. 2000-12-13 Christian Rose * sv.po: Updated Swedish translation. 2000-12-13 Martin Norb??ck * sv.po: Updated Swedish translation. 2000-12-13 Valek Filippov * ru.po: updated russian translation. 2000-12-13 Christian Rose * sv.po: Updated Swedish translation. 2000-12-11 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. * POTFILES.in: Updated this. 2000-12-12 Christian Rose * sv.po: Updated Swedish translation. 2000-12-11 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-09 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-12-06 Fatih Demir * ko.po: Committed updated Korean translation. 2000-12-06 Christian Rose * sv.po: Updated Swedish translation. 2000-12-05 Darin Adler * ui-extract.pl: Took out header. Since the .h files are never put anywhere anyone would see them, it's better to not have the extraneous comment that just shows up in all the pot files. 2000-12-05 Christian Rose * sv.po: Updated Swedish translation. 2000-12-04 Valek Filippov * ru.po: updated russian translation. 2000-12-02 Robert Brady * ta.po: Added Tamil translation from Veeravanallore Madhavan. 2000-12-02 Zbigniew Chyla * pl.po: Updated Polish translation 2000-12-02 Christian Rose * sv.po: Updated Swedish translation. 2000-12-01 Valek Filippov * ru.po: updated russian translation. 2000-11-28 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-11-24 Christian Rose * sv.po: Updated Swedish translation. 2000-11-21 Christian Rose * sv.po: Updated Swedish translation. 2000-11-18 Christian Rose * sv.po: Updated Swedish translation. 2000-11-17 Christian Rose * sv.po: Updated Swedish translation. 2000-11-16 Szabolcs BAN * hu.po: initial Hungarian translations. 2000-11-15 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-11-10 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-11-14 Matthias Warkus * de.po: Updated. 2000-11-13 Christian Rose * sv.po: Updated Swedish translation. 2000-11-09 Darin Adler * Makefile.i18npatch: Turns out it can be even simpler. There's no need to generate the headers when making the POTFILE. * .cvsignore: No need to ignore "headers" any more. 2000-11-09 Darin Adler * Makefile.i18npatch: Fixed the patch so it will apply successfully. Also fixed a small problem that leads to an infinite loop when building. * .cvsignore: Ignore the new "headers" file needed to make the build rules work right. 2000-11-09 Eric Brayeur * fr.po: Updated French translation. 2000-11-09 Jarkko Ranta * fi.po: Added Finnish translation 2000-11-08 Kenneth Christiansen Install new versions of the XML-translation scripts. These now works even better, and do not leave behind a "po/.headerlock" file after a build. * Makefile.i18npatch: Minor changes. * ui-extract.pl: New version which fixes bugs for XML messages with more than one newling. * update.pl: Newest release. Keeps Darin happy ;) 2000-11-08 Valek Filippov * ru.po: updated russian translation. 2000-11-08 Robert Brady * en_GB.po: s/trash/wastebasket. 2000-11-07 Fatih Demir * ko.po: Committed updated ko.po. 2000-11-07 Christian Rose * sv.po: Updated Swedish translation. 2000-11-06 Matthias Warkus * de.po: Updated. 2000-11-06 Darin Adler Install new versions of the XML-translation scripts from Kenneth. These work better, but still seem to leave behind a "po/.headerlock" file and "po/tmp" directory after a build. * Makefile.i18npatch: Copied from bonobo. * ui-extract.pl: From Kenneth. * update.pl: Fron Kenneth. 2000-11-06 Christian Rose * sv.po: Updated Swedish translation. 2000-11-04 Zbigniew Chyla * pl.po: Updated Polish translation 2000-11-04 Almer S. Tigelaar * nl.po: Add Dutch translation. 2000-11-04 Valek Filippov * ru.po: updated russian translation. 2000-11-04 Christian Rose * sv.po: Updated Swedish translation. 2000-11-03 Christian Rose * sv.po: Updated Swedish translation. 2000-11-03 Kjartan Maraas * no.po: Updated Norwegian (bokmal) translation. 2000-11-02 Carlos Perell?? Mar??n * es.po: more updates to Spanish translation. 2000-11-02 Andrew V. Samoilov * ru.po: typos fixed. 2000-11-02 Fatih Demir * ko.po: Committed updated ko.po. 2000-11-02 Carlos Perell?? Mar??n * es.po: some updates to Spanish translation. 2000-11-02 Christian Rose * sv.po: Updated Swedish translation. 2000-11-01 Christian Rose * sv.po: Updated Swedish translation. 2000-11-01 Valek Filippov * ru.po: updated russian translation. 2000-10-31 Christian Rose * sv.po: Updated Swedish translation. 2000-10-31 Valek Filippov * ru.po: updated russian translation. 2000-10-29 Kenneth Christiansen * update.pl: Started new approach 2000-10-29 Kenneth Christiansen * update.pl: Started commenting the script 2000-10-29 Kenneth Christiansen * update.pl: Changes small things 2000-10-29 Andrew V. Samoilov * ru.po: updated Russian translation. 2000-10-29 Zbigniew Chyla * pl.po: Updated Polish translation. 2000-10-29 Christian Rose * sv.po: Updated Swedish translation. 2000-10-28 Kenneth Christiansen * da.po: Updated * Added new releases of update.pl and added new ui-extract.pl script aswell 2000-10-28 Takuo Kitame * ja.po: Updated Japanese Translation. 2000-10-28 Matthias Warkus * de.po: Updated. 2000-10-28 Christopher R. Gabriel * it.po: Updated italian translation 2000-10-28 Christian Rose * sv.po: Updated Swedish translation. 2000-10-27 Maciej Stachowiak * da.po: Reverting to version 1.30 (1.31 was mistakenly checked in as a PDF file). 2000-10-27 Zbigniew Chyla * pl.po: Updated Polish translation. 2000-10-27 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-26 Matthias Warkus * de.po: Small update. 2000-10-26 Fatih Demir * ko.po: Committed updated Korean translation by Young-Ho Cha. 2000-10-25 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-24 Zbigniew Chyla * pl.po: Updated Polish translation. 2000-10-23 Fatih Demir * ko.po: Committed updated Korean translation by Young-Ho Cha. 2000-10-23 Matthias Warkus * de.po: Huge update. Everything's translated; all the "Could/Could not/Can/Cannot" stuff now translates to "Konnte nicht werden". I don't think this sounds good, but it's policy and I don't know a better solution. 2000-10-23 Christian Rose * sv.po: Updated Swedish translation. 2000-10-22 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-22 Robert Brady * en_GB.po: Added British translation. 2000-10-21 Zbigniew Chyla * pl.po: Added Polish translation. 2000-10-20 Darin Adler * po/POTFILES.in: Added some new .xml.h files. Got rid of the duplicates I put in there yesterday. 2000-10-19 Darin Adler * po/POTFILES.in: Added the new generated .xml.h files. We'll see how this works in RPM builds. For now, it's a bit inconvenient because the .xml.h files aren't checked in. I'll probably take care of that soon. 2000-10-19 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-18 Christian Rose * sv.po: Updated Swedish translation with update.sh. 2000-10-17 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-15 Christian Rose * sv.po: Updated Swedish translation with update.sh. 2000-10-13 Takuo Kitame * ja.po: Update Japanese translation. 2000-10-13 Christian Rose * sv.po: Updated Swedish translation with update.sh. 2000-10-11 Christian Rose * sv.po: Updated Swedish translation with update.sh, because update.pl is broken with the xml stuff. 2000-10-10 Christian Rose * sv.po: Updated Swedish translation. 2000-10-09 Eric Brayeur * fr.po: Updated French translation. 2000-10-09 Christian Rose * sv.po: Updated Swedish translation. 2000-10-09 Akira TAGOH * ja.po: Updated Japanese translation. 2000-10-08 Valek Filippov * ru.po: updated russian translation. 2000-10-08 Kjartan Maraas * no.po: Updated Norwegian translation. * XMLFILES.in: Added this for the new XML ui-description. * xml2pot.pl: Added this to extract strings from the .xml files * Makefile.in.in: Hacked this in to make all this work with make dist. All this is from Kenneth Christiansen. 2000-10-07 Jesus Bravo Alvarez * gl.po: Updated Galician translation. 2000-10-04 Christian Rose * sv.po: Updated Swedish translation. 2000-10-03 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-10-03 Christian Rose * sv.po: Updated Swedish translation. 2000-09-29 Valek Filippov * ru.po: updated russian translation. 2000-09-29 Christian Rose * sv.po: Updated Swedish translation. 2000-09-28 Pablo Saratxaga * sv.po,uk.po,zh_TW.Big5.po: corrected some syntax errors 2000-09-27 Christian Rose * sv.po: Updated Swedish translation. 2000-09-26 Christian Rose * sv.po: Updated Swedish translation. 2000-09-25 Christian Rose * sv.po: Updated Swedish translation. 2000-09-24 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-09-23 Christian Rose * sv.po: Updated Swedish translation. 2000-09-22 Valek Filippov * ru.po: updated russian translation. 2000-09-22 Christian Rose * sv.po: Updated Swedish translation. 2000-09-21 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-09-20 Christian Rose * sv.po: Updated Swedish translation. 2000-09-20 Kjartan Maraas * no.po: Updated Norwegian translation. * POTFILES.in: Added some more missing files. 2000-09-19 Christian Rose * sv.po: Updated Swedish translation. * POTFILES.in: Added the nemo-user-level-manager.c file. 2000-09-18 Christian Rose * sv.po: Updated Swedish translation. 2000-09-17 Christian Rose * sv.po: Updated Swedish translation. 2000-09-17 Matthias Warkus * de.po: Updates galore. 2000-09-14 Christian Rose * sv.po: Updated Swedish translation. 2000-09-13 Christian Rose * sv.po: Updated Swedish translation. 2000-09-12 Christian Rose * sv.po: Updated Swedish translation. 2000-09-09 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-09-09 Christian Rose * sv.po: Updated Swedish translation. 2000-09-07 Christian Rose * sv.po: Updated Swedish translation. 2000-09-06 Matthias Warkus * de.po: Fixes and updates. In the future, please have an eye on typos, hyphens, microsoftisms and imperatives in this translation. I've encountered a lot of them. "It's beta" is not an excuse for sloppiness! 2000-09-06 Christian Rose * sv.po: Updated Swedish translation. 2000-09-04 Kjartan Maraas * no.po: Updated Norwegian translation. * de.po: Updated German translation from Christian Meyer . 2000-09-04 Valek Filippov * ru.po: updated russian translation. 2000-09-03 Christian Rose * sv.po: Updated Swedish translation. 2000-09-02 Christian Rose * sv.po: Updated Swedish translation. 2000-09-01 Eric Brayeur * fr.po: updated french translation. 2000-08-31 Valek Filippov * ru.po: updated russian translation. 2000-08-30 Jesus Bravo Alvarez * gl.po: Updated Galician translation. 2000-08-30 Valek Filippov * ru.po: updated russian translation. 2000-08-29 Akira TAGOH * ja.po: Updated Japanese translation. 2000-08-27 Valek Filippov * ru.po: updated russian translation. 2000-08-24 Alastair McKinstry * ga.po: Added Irish translation. 2000-08-23 Yuri Syrota * uk.po: Added Ukrainian translation. 2000-08-20 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-08-19 Matthias Warkus * de.po: Updated. 2000-08-19 Valek Filippov * ru.po: updated russian translation. 2000-08-18 Valek Filippov * ru.po: updated russian translation. 2000-08-18 Christopher R. Gabriel * it.po: added italian translation 2000-08-17 Valek Filippov * ru.po: updated russian translation. 2000-08-16 Valek Filippov * ru.po: updated russian translation. 2000-08-15 Valek Filippov * ru.po: updated russian translation. 2000-08-10 Akira TAGOH * ja.po: Updated Japanese translation. 2000-08-09 Matthias Warkus * de.po: Fixed small but nasty error. 2000-08-08 Matthias Warkus * de.po: Nice large update. 2000-08-08 Valek Filippov * ru.po: updated russian translation. 2000-08-05 Fatih Demir * tr.po: Updated the Turkish translation. 2000-08-04 Valek Filippov * ru.po: updated russian translation. 2000-08-03 Fatih Demir * tr.po: Updated the Turkish translation. 2000-08-02 Valek Filippov * ru.po: updated russian translation. 2000-08-02 Pablo Saratxaga * ko.po,tr.po,zh_TW.Big5.po: corrected some syntax errors 2000-07-31 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-31 Valek Filippov * ru.po: updated russian translation. 2000-07-26 Valek Filippov * ru.po: updated russian translation. 2000-07-26 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-25 Fatih Demir * ko.po: Commited updated Korean translation by Young-Ho Cha . 2000-07-25 Valek Filippov * ru.po: updated russian translation. 2000-07-24 Matthias Warkus * de.po: Updated German translation. 2000-07-24 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-23 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-07-22 Richard Hult * sv.po: Updated Swedish translation. 2000-07-22 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-20 Valek Filippov * ru.po: updated russian translation. 2000-07-18 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-17 Andreas Hyden * sv.po: Updated Swedish translation. 2000-07-16 Valek Filippov * ru.po: updated russian translation. 2000-07-16 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-07-15 Matthias Warkus * de.po: Updated. 2000-07-15 Andreas Hyden * sv.po: Updated Swedish translation. 2000-07-11 Valek Filippov * ru.po: updated russian translation. 2000-07-10 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-09 Valek Filippov * ru.po: updated russian translation. 2000-07-09 Matthias Warkus * de.po: Updated. 2000-07-06 Fatih Demir * tr.po: Updated the Turkish translation. 2000-07-05 Valek Filippov * ru.po: updated russian translation. 2000-07-01 Eric Brayeur * fr.po: updated French translation. 2000-06-30 Fatih Demir * .cvsignore: Ignore the messages file produced by msgfmt ( on update ). * tr.po: ( Guess it .. ) Updated the Turkish translation. 2000-06-30 Valek Filippov * ru.po: updated russian translation. 2000-06-27 Valek Filippov * ru.po: updated russian translation. 2000-06-27 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-24 Valek Filippov * ru.po: updated russian translation. 2000-06-23 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-21 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-06-16 Matthias Warkus * de.po: Updated German translation. 2000-06-15 Valek Filippov * ru.po: updated russian translation. 2000-06-15 Kenneth Christiansen * da.po: update 2000-06-14 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-14 Benedikt Roth * de.po: Updated German translation. 2000-06-14 Valek Filippov * ru.po: updated russian translation. 2000-06-13 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-13 Valek Filippov * ru.po: updated russian translation. 2000-06-10 Valek Filippov * ru.po: updated russian translation. 2000-06-10 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-09 Ramiro Estrugo * po/POTFILES.in: Move the nemo-widgets classes to libnemo-extensions. 2000-06-09 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-08 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-06-08 Valek Filippov * ru.po: updated russian translation. 2000-06-06 Fatih Demir * tr.po: Updated the Turkish translation. 2000-06-05 Valek Filippov * POTFILES.in: added some files. 2000-06-04 Fatih Demir * tr.po: Updated the Turkish translation. * ko.po: Committed updated Korean translation. 2000-06-03 Valek Filippov * ru.po: updated russian translation. 2000-06-01 Valek Filippov * ru.po: updated russian translation. 2000-06-01 Benedikt Roth * de.po: Added a very beta german translation 2000-05-31 Kenneth Christiansen * README.tools: Added readme file, which explains the use of the newly checked in po tools. Please go read. 2000-05-31 Fatih Demir * tr.po: Corrected some typos. * tr.po: Updated the Turkish translation. 2000-05-31 Kenneth Christiansen * POTFILES.in: Added files * desk.pl: Script for finding missing translations in desktop files * update.pl: Script for updating and finding missing files for POTFILES.in 2000-05-28 Fatih Demir * tr.po: Die, all you fuzzy entries... 2000-05-26 Valek Filippov * updated russian translation. 2000-05-25 Robin * Slomkowski * fr.po (added) This was create by Jean-Michel Ardantz 2000-05-25 Fatih Demir * tr.po: Updated the Turkish translation. 2000-05-24 Valek Filippov * ru.po: Updated russian translation. 2000-05-23 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-05-22 Valek Filippov * ru.po: Updated russian translation. * update.sh: version 1.2.5. 2000-05-22 Yukihiro Nakai * ja.po: Update from Akira TAGOH. 2000-05-20 Fatih Demir * tr.po : Updated the Turkish translation. * ko.po : Committed ko.po's update. 2000-05-20 Yukihiro Nakai * ja.po: Update from Akira TAGOH. 2000-05-19 Yukihiro Nakai * ja.po: Initial Japanese translation from Akira Tagoh. 2000-05-18 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-05-17 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-05-17 Jesus Bravo Alvarez * gl.po: Updated Galician translation. 2000-05-17 Valek Filippov * ru.po: Updated russian translation. * update.sh: new version. 2000-05-13 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-05-12 Fatih Demir * ko.po : Committed the updated Korean translation. 2000-05-11 Fatih Demir * tr.po : Updated the Turkish translation. 2000-05-10 Fatih Demir * ko.po : Updated Korean translation from Young-Ho Cha . 2000-05-08 Andreas Hyden * sv.po: Updated Swedish translation. 2000-05-07 Andreas Hyden * sv.po: Updated Swedish translation. 2000-05-07 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-05-06 Jesus Bravo Alvarez * gl.po: Added Galician translation. 2000-05-04 Fatih Demir * tr.po : Updated the Turkish translation . 2000-05-04 Valek Filippov * ru.po: updated russian translation. 2000-05-03 Kjartan Maraas * POTFILES.in: Added music view. * no.po: Updated Norwegian translation. 2000-05-03 Fatih Demir * tr.po : Updated the Turkish translation . * ko.po : Added Korean translation by : Young-Ho Cha 2000-05-02 Kjartan Maraas * no.po: Updated Norwegian translation. * POTFILES.in: Added some more files. 2000-05-01 Valek Filippov * ru.po: Updated russian translation. 2000-04-30 Fatih Demir * tr.po : Updated it . 2000-04-29 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-04-27 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-04-27 Ramiro Estrugo * POTFILES.in: s/main/ntl-web-browser.c 2000-04-27 Valek Filippov * ru.po: Small updated russian translation. 2000-04-25 Valek Filippov * ru.po: Small updated russian translation. 2000-04-25 Kjartan Maraas * no.po: Updated Norwegian translation. 2000-04-21 Fatih Demir * update.sh : Added a nicer version of it . * tr.po : Updated the Turkish translation . 2000-04-20 Andreas Hyden sv.po: Added Swedish translation. 2000-04-19 Pablo Saratxaga * da.po: Added Danish file 2000-04-18 Kjartan Maraas * no.po: Added Norwegian translation. 2000-04-15 Fatih Demir * tr.po : Update ++++ 2000-04-15 Valek Filippov * Updatetd russian translation. 2000-04-14 Ramiro Estrugo * .cvsignore: ignore *.gmo and *.mo generated files. 2000-04-14 Ramiro Estrugo * POTFILES.in: Updated for libnemo -> libnemo-extensions changes. 2000-04-14 Fatih Demir * tr.po : Added the Turkish translation . 2000-04-14 Ramiro Estrugo * ChangeLog: Added this thing to make 'make dist' happy. nemo-3.6.5/po/POTFILES.in0000664000175000017500000000661413215733314013613 0ustar fabiofabio# List of source files containing translatable strings. # Please keep this file sorted alphabetically. [encoding: UTF-8] data/action_i18n_strings.py data/nemo.xml.in data/nemo-autorun-software.desktop.in.in data/nemo.desktop.in.in eel/eel-canvas.c eel/eel-editable-label.c eel/eel-glib-extensions.c eel/eel-gnome-extensions.c eel/eel-gtk-extensions.c eel/eel-stock-dialogs.c eel/eel-vfs-extensions.c files/usr/share/gtksourceview-2.0/language-specs/nemo_action.lang files/usr/share/gtksourceview-3.0/language-specs/nemo_action.lang libnemo-extension/nemo-column.c libnemo-extension/nemo-menu-item.c libnemo-extension/nemo-property-page.c libnemo-private/nemo-action.c libnemo-private/nemo-bookmark.c libnemo-private/nemo-clipboard.c libnemo-private/nemo-column-chooser.c libnemo-private/nemo-column-utilities.c libnemo-private/nemo-context-menu-menu-item.c libnemo-private/nemo-desktop-directory-file.c libnemo-private/nemo-desktop-icon-file.c libnemo-private/nemo-desktop-link.c libnemo-private/nemo-desktop-link-monitor.c libnemo-private/nemo-dnd.c libnemo-private/nemo-entry.c libnemo-private/nemo-file.c libnemo-private/nemo-file-conflict-dialog.c libnemo-private/nemo-file-operations.c libnemo-private/nemo-file-undo-operations.c libnemo-private/nemo-file-utilities.c libnemo-private/nemo-global-preferences.c libnemo-private/nemo-icon-canvas-item.c libnemo-private/nemo-icon-container.c libnemo-private/nemo-icon-dnd.c libnemo-private/nemo-mime-application-chooser.c libnemo-private/nemo-program-choosing.c libnemo-private/nemo-progress-info.c libnemo-private/nemo-query.c libnemo-private/nemo-search-directory-file.c libnemo-private/nemo-tree-view-drag-dest.c libnemo-private/nemo-undo-signal-handlers.c libnemo-private/nemo-vfs-file.c libnemo-private/org.nemo.gschema.xml.in src/nemo-action-config-widget.c src/nemo-application.c src/nemo-autorun-software.c src/nemo-blank-desktop-window.c src/nemo-bookmarks-window.c [type: gettext/glade]src/nemo-bookmarks-window.glade src/nemo-config-base-widget.c src/nemo-connect-server-dialog.c src/nemo-connect-server-dialog-main.c src/nemo-desktop-application.c src/nemo-desktop-icon-grid-view.c src/nemo-desktop-icon-view.c src/nemo-desktop-icon-view-ui.xml src/nemo-desktop-item-properties.c src/nemo-desktop-window.c src/nemo-directory-view-ui.xml src/nemo-error-reporting.c src/nemo-extension-config-widget.c src/nemo-file-management-properties.c [type: gettext/glade]src/nemo-file-management-properties.glade src/nemo-icon-view.c src/nemo-icon-view-container.c src/nemo-icon-view-grid-container.c src/nemo-icon-view-ui.xml src/nemo-image-properties-page.c src/nemo-interesting-folder-bar.c src/nemo-list-model.c src/nemo-list-view.c src/nemo-list-view-ui.xml src/nemo-location-bar.c src/nemo-location-entry.c src/nemo-main-application.c src/nemo-main.c src/nemo-mime-actions.c src/nemo-notebook.c src/nemo-open-with-main.c src/nemo-pathbar.c src/nemo-places-sidebar.c src/nemo-plugin-manager.c src/nemo-progress-ui-handler.c src/nemo-properties-window.c src/nemo-query-editor.c src/nemo-script-config-widget.c src/nemo-shell-ui.xml src/nemo-statusbar.c src/nemo-thumbnail-problem-bar.c src/nemo-toolbar.c src/nemo-trash-bar.c src/nemo-tree-sidebar.c src/nemo-tree-sidebar-model.c src/nemo-view.c src/nemo-view-dnd.c src/nemo-window-bookmarks.c src/nemo-window.c src/nemo-window-manage-views.c src/nemo-window-menus.c src/nemo-window-pane.c src/nemo-window-private.h src/nemo-window-slot.c src/nemo-x-content-bar.c nemo-3.6.5/po/README0000664000175000017500000000062013215733314012705 0ustar fabiofabioTranslations are done on Launchpad: https://translations.launchpad.net/linuxmint/latest/+pots/nemo From Launchpad we export two sets of files: - The mo files go to files/usr/share/locale/ and eventually end up in the nemo package itself - The po files go to po/po-files/. They are not compiled into mo files (this is done by Launchpad) but are present in this archive as source for the mo files. nemo-3.6.5/po/Makefile.in.in0000664000175000017500000001575613215733314014517 0ustar fabiofabio# Makefile for program source directory in GNU NLS utilities package. # Copyright (C) 1995, 1996, 1997 by Ulrich Drepper # Copyright (C) 2004-2008 Rodney Dawes # # This file may be copied and used freely without restrictions. It may # be used in projects which are not available under a GNU Public License, # but which still want to provide support for the GNU gettext functionality. # # - Modified by Owen Taylor to use GETTEXT_PACKAGE # instead of PACKAGE and to look for po2tbl in ./ not in intl/ # # - Modified by jacob berkman to install # Makefile.in.in and po2tbl.sed.in for use with glib-gettextize # # - Modified by Rodney Dawes for use with intltool # # We have the following line for use by intltoolize: # INTLTOOL_MAKEFILE GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = @SHELL@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ top_builddir = @top_builddir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datadir = @datadir@ datarootdir = @datarootdir@ libdir = @libdir@ localedir = @localedir@ subdir = po install_sh = @install_sh@ # Automake >= 1.8 provides @mkdir_p@. # Until it can be supposed, use the safe fallback: mkdir_p = $(install_sh) -d INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ XGETTEXT = @XGETTEXT@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ MSGMERGE = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist GENPOT = INTLTOOL_EXTRACT="$(INTLTOOL_EXTRACT)" XGETTEXT="$(XGETTEXT)" srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot ALL_LINGUAS = @ALL_LINGUAS@ PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) DISTFILES = Makefile.in.in POTFILES.in $(POFILES) EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS POTFILES = \ # This comment gets stripped out CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) .SUFFIXES: .SUFFIXES: .po .pox .gmo .mo .msg .cat AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ INTLTOOL_V_MSGFMT = $(INTLTOOL__v_MSGFMT_$(V)) INTLTOOL__v_MSGFMT_= $(INTLTOOL__v_MSGFMT_$(AM_DEFAULT_VERBOSITY)) INTLTOOL__v_MSGFMT_0 = @echo " MSGFMT" $@; .po.pox: $(MAKE) $(GETTEXT_PACKAGE).pot $(MSGMERGE) $* $(GETTEXT_PACKAGE).pot -o $*.pox .po.mo: $(INTLTOOL_V_MSGFMT)$(MSGFMT) -o $@ $< .po.gmo: $(INTLTOOL_V_MSGFMT)file=`echo $* | sed 's,.*/,,'`.gmo \ && rm -f $$file && $(GMSGFMT) -o $$file $< .po.cat: sed -f ../intl/po2msg.sed < $< > $*.msg \ && rm -f $@ && gencat $@ $*.msg all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: $(GETTEXT_PACKAGE).pot: $(POTFILES) $(GENPOT) install: install-data install-data: install-data-@USE_NLS@ install-data-no: all install-data-yes: all linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ dir=$(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $$dir; \ if test -r $$lang.gmo; then \ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ else \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ echo "installing $(srcdir)/$$lang.gmo as" \ "$$dir/$(GETTEXT_PACKAGE).mo"; \ fi; \ if test -r $$lang.gmo.m; then \ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ if test -r $(srcdir)/$$lang.gmo.m ; then \ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ $$dir/$(GETTEXT_PACKAGE).mo.m; \ echo "installing $(srcdir)/$$lang.gmo.m as" \ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ else \ true; \ fi; \ fi; \ done # Empty stubs to satisfy archaic automake needs dvi info ctags tags CTAGS TAGS ID: # Define this as empty until I found a useful application. install-exec installcheck: uninstall: linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ done check: all $(GETTEXT_PACKAGE).pot rm -f missing notexist srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m if [ -r missing -o -r notexist ]; then \ exit 1; \ fi mostlyclean: rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp rm -f .intltool-merge-cache clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES stamp-it rm -f *.mo *.msg *.cat *.cat.m *.gmo maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f Makefile.in.in distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(DISTFILES) dists="$(DISTFILES)"; \ extra_dists="$(EXTRA_DISTFILES)"; \ for file in $$extra_dists; do \ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ done; \ for file in $$dists; do \ test -f $$file || file="$(srcdir)/$$file"; \ ln $$file $(distdir) 2> /dev/null \ || cp -p $$file $(distdir); \ done update-po: Makefile $(MAKE) $(GETTEXT_PACKAGE).pot tmpdir=`pwd`; \ linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ echo "$$lang:"; \ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ if $$result; then \ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$lang.gmo failed!"; \ rm -f $$tmpdir/$$lang.new.po; \ fi; \ done Makefile POTFILES: stamp-it @if test ! -f $@; then \ rm -f stamp-it; \ $(MAKE) stamp-it; \ fi stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in cd $(top_builddir) \ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ $(SHELL) ./config.status # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nemo-3.6.5/NEWS0000664000175000017500000000111513215733314012106 0ustar fabiofabioDevelopment: 1/22/2013: - Breadcrumbs: Stylable by themes, see src/nemo-styles-fallback.css for default style information. Border radius, color, background color, and text color can be customized through that. - Sidebar Disk Indicators: Stylable by themes, again, see src/nemo-styles-fallback.css for default style information - you can customize the two colors (fore- and background), the thickness of the bar, the corner radius, the maximum length of the bar, and an amount of extra padding from the bottom of the cell.nemo-3.6.5/.gitignore0000664000175000017500000000311313215733314013377 0ustar fabiofabio########################### # Default .gitignore file for Nemo. # By default this ignores the lint from the Eclipse IDE. ################## # Eclipse Output # ################## *.pydevproject .project .metadata bin/** tmp/** tmp/**/* *.tmp *.bak *.swp *~.nib local.properties .classpath .settings/ .loadpath # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # CDT-specific .cproject # PDT-specific .buildpath *.lo *.la *.lai *.so.* *.so *.o *.a *.valid *.xml *.pc *.log *.before *.after *.m4 missing depcomp gtk-doc.make install-sh libtool ltmain.sh stamp-h1 test-driver autom4te.cache compile Makefile Makefile.in config.* !config.h.in configure data/*.desktop.in data/*.desktop data/*.service debian/tmp/* debian/nemo/* debian/nemo-dbg/* debian/nemo-data/* debian/libnemo-extension*/* debian/gir1.2*/* debian/.debhelper debian/debhelper-build-stamp debian/files debian/gir1.2-nemo-3.0.install *.substvars *.debhelper docs/reference/libnemo-extension/* eel/check-program libnemo-extension/Nemo-3.0.* libnemo-private/*.valid libnemo-private/*.xml libnemo-private/.libs libnemo-private/nemo-generated.* po/.intltool-merge-cache po/POTFILES po/stamp-it src/nemo-freedesktop-generated.* src/nemo-resources.* src/.libs src/Makefile src/Makefile.in src/nemo src/nemo-autorun-software src/nemo-connect-server src/nemo-convert-metadata src/nemo-extensions-list src/nemo-open-with src/nemo-desktop src/org.nemo.root.policy test/.libs test/test-eel-editable-label test/test-nemo-copy test/test-nemo-directory-async test/test-nemo-search-engine