pax_global_header00006660000000000000000000000064132512764210014515gustar00rootroot0000000000000052 comment=e55103c466f62a24ec3507ae8291572057048e56 phototonic-2.1/000077500000000000000000000000001325127642100135455ustar00rootroot00000000000000phototonic-2.1/.gitignore000066400000000000000000000001371325127642100155360ustar00rootroot00000000000000*.exe phototonic moc_*.cpp *.o *.obj .qmake.stash qrc_phototonic.cpp *.pro.user Makefile mingw phototonic-2.1/.travis.yml000066400000000000000000000005131325127642100156550ustar00rootroot00000000000000os: linux dist: trusty sudo: true compiler: - gcc addons: apt: packages: - libexiv2-dev before_install: - sudo add-apt-repository ppa:beineri/opt-qt58-trusty -y - sudo apt-get update -q - sudo apt-get install -y qt58-meta-minimal script: - source /opt/qt58/bin/qt58-env.sh - qmake - make -j2 phototonic-2.1/Bookmarks.cpp000066400000000000000000000053551325127642100162110ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "Bookmarks.h" BookMarks::BookMarks(QWidget *parent) : QTreeWidget(parent) { setAcceptDrops(true); setDragEnabled(false); setDragDropMode(QAbstractItemView::DropOnly); connect(this, SIGNAL(expanded( const QModelIndex &)), this, SLOT(resizeTreeColumn( const QModelIndex &))); connect(this, SIGNAL(collapsed( const QModelIndex &)), this, SLOT(resizeTreeColumn( const QModelIndex &))); setColumnCount(1); setHeaderHidden(true); reloadBookmarks(); } void BookMarks::reloadBookmarks() { clear(); QSetIterator it(Settings::bookmarkPaths); while (it.hasNext()) { QString itemPath = it.next(); QTreeWidgetItem *item = new QTreeWidgetItem(this); item->setText(0, QFileInfo(itemPath).fileName()); item->setIcon(0, QIcon(":/images/bookmarks.png")); item->setToolTip(0, itemPath); insertTopLevelItem(0, item); } } void BookMarks::resizeTreeColumn(const QModelIndex &) { resizeColumnToContents(0); } void BookMarks::removeBookmark() { if (selectedItems().size() == 1) { Settings::bookmarkPaths.remove(selectedItems().at(0)->toolTip(0)); reloadBookmarks(); } } void BookMarks::dragEnterEvent(QDragEnterEvent *event) { QModelIndexList selectedDirs = selectionModel()->selectedRows(); if (selectedDirs.size() > 0) { dndOrigSelection = selectedDirs[0]; } event->acceptProposedAction(); } void BookMarks::dragMoveEvent(QDragMoveEvent *event) { setCurrentIndex(indexAt(event->pos())); } void BookMarks::dropEvent(QDropEvent *event) { if (event->source()) { QString fileSystemTreeStr("FileSystemTree"); bool dirOp = (event->source()->metaObject()->className() == fileSystemTreeStr); emit dropOp(event->keyboardModifiers(), dirOp, event->mimeData()->urls().at(0).toLocalFile()); } } phototonic-2.1/Bookmarks.h000066400000000000000000000025621325127642100156530ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef BOOKMARKS_H #define BOOKMARKS_H #include #include "Settings.h" class BookMarks : public QTreeWidget { Q_OBJECT public: BookMarks(QWidget *parent); void reloadBookmarks(); public slots: void removeBookmark(); private: QModelIndex dndOrigSelection; private slots: void resizeTreeColumn(const QModelIndex &); protected: void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); signals: void dropOp(Qt::KeyboardModifiers keyMods, bool dirOp, QString cpMvDirPath); }; #endif // BOOKMARKS_H phototonic-2.1/COPYING000066400000000000000000001045131325127642100146040ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . phototonic-2.1/ColorsDialog.cpp000066400000000000000000000266751325127642100166520ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include #include #include #include #include "ImageViewer.h" #include "ColorsDialog.h" #include "Settings.h" ColorsDialog::ColorsDialog(QWidget *parent, ImageViewer *imageViewer) : QDialog(parent) { setWindowTitle(tr("Colors")); setWindowIcon(QIcon(":/images/colors.png")); resize(350, 300); this->imageViewer = imageViewer; QHBoxLayout *buttonsHbox = new QHBoxLayout; QPushButton *resetButton = new QPushButton(tr("Reset")); resetButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(resetButton, SIGNAL(clicked()), this, SLOT(reset())); buttonsHbox->addWidget(resetButton, 0, Qt::AlignLeft); QPushButton *okButton = new QPushButton(tr("OK")); okButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(okButton, SIGNAL(clicked()), this, SLOT(ok())); buttonsHbox->addWidget(okButton, 0, Qt::AlignRight); okButton->setDefault(true); /* hue saturation */ QLabel *hueLab = new QLabel(tr("Hue")); QLabel *satLab = new QLabel(tr("Saturation")); QLabel *lightLab = new QLabel(tr("Lightness")); hueSlider = new QSlider(Qt::Horizontal); hueSlider->setTickPosition(QSlider::TicksAbove); hueSlider->setTickInterval(25); hueSlider->setRange(-100, 100); hueSlider->setTracking(false); connect(hueSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); colorizeCheckBox = new QCheckBox(tr("Colorize"), this); colorizeCheckBox->setCheckState(Settings::colorizeEnabled ? Qt::Checked : Qt::Unchecked); connect(colorizeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(enableColorize(int))); rNegateCheckBox = new QCheckBox(tr("Negative"), this); rNegateCheckBox->setCheckState(Settings::rNegateEnabled ? Qt::Checked : Qt::Unchecked); connect(rNegateCheckBox, SIGNAL(stateChanged(int)), this, SLOT(redNegative(int))); gNegateCheckBox = new QCheckBox(tr("Negative"), this); gNegateCheckBox->setCheckState(Settings::gNegateEnabled ? Qt::Checked : Qt::Unchecked); connect(gNegateCheckBox, SIGNAL(stateChanged(int)), this, SLOT(greenNegative(int))); bNegateCheckBox = new QCheckBox(tr("Negative"), this); bNegateCheckBox->setCheckState(Settings::bNegateEnabled ? Qt::Checked : Qt::Unchecked); connect(bNegateCheckBox, SIGNAL(stateChanged(int)), this, SLOT(blueNegative(int))); saturationSlider = new QSlider(Qt::Horizontal); saturationSlider->setTickPosition(QSlider::TicksAbove); saturationSlider->setTickInterval(25); saturationSlider->setRange(-100, 100); saturationSlider->setTracking(false); connect(saturationSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); lightnessSlider = new QSlider(Qt::Horizontal); lightnessSlider->setTickPosition(QSlider::TicksAbove); lightnessSlider->setTickInterval(25); lightnessSlider->setRange(-100, 100); lightnessSlider->setTracking(false); connect(lightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); QHBoxLayout *channelsHbox = new QHBoxLayout; redCheckBox = new QCheckBox(tr("Red")); redCheckBox->setCheckable(true); redCheckBox->setChecked(Settings::hueRedChannel); connect(redCheckBox, SIGNAL(clicked()), this, SLOT(setRedChannel())); channelsHbox->addWidget(redCheckBox, 0, Qt::AlignLeft); greenCheckBox = new QCheckBox(tr("Green")); greenCheckBox->setCheckable(true); greenCheckBox->setChecked(Settings::hueGreenChannel); connect(greenCheckBox, SIGNAL(clicked()), this, SLOT(setGreenChannel())); channelsHbox->addWidget(greenCheckBox, 0, Qt::AlignLeft); blueCheckBox = new QCheckBox(tr("Blue")); blueCheckBox->setCheckable(true); blueCheckBox->setChecked(Settings::hueBlueChannel); connect(blueCheckBox, SIGNAL(clicked()), this, SLOT(setBlueChannel())); channelsHbox->addWidget(blueCheckBox, 0, Qt::AlignLeft); channelsHbox->addStretch(1); QGridLayout *hueSatLay = new QGridLayout; hueSatLay->addWidget(hueLab, 1, 0, 1, 1); hueSatLay->addWidget(hueSlider, 1, 1, 1, 1); hueSatLay->addWidget(colorizeCheckBox, 2, 1, 1, 1); hueSatLay->addWidget(satLab, 3, 0, 1, 1); hueSatLay->addWidget(saturationSlider, 3, 1, 1, 1); hueSatLay->addWidget(lightLab, 4, 0, 1, 1); hueSatLay->addWidget(lightnessSlider, 4, 1, 1, 1); hueSatLay->setColumnMinimumWidth(0, 70); QGroupBox *hueSatGroup = new QGroupBox(tr("Hue and Saturation")); hueSatGroup->setLayout(hueSatLay); QGridLayout *channelsLay = new QGridLayout; channelsLay->addLayout(channelsHbox, 5, 1, 1, 1); channelsLay->setColumnMinimumWidth(0, 70); QGroupBox *channelsGroup = new QGroupBox(tr("Affected Channels")); channelsGroup->setLayout(channelsLay); /* brightness contrast */ QLabel *brightLab = new QLabel(tr("Brightness")); QLabel *contrastLab = new QLabel(tr("Contrast")); brightSlider = new QSlider(Qt::Horizontal); brightSlider->setTickPosition(QSlider::TicksAbove); brightSlider->setTickInterval(25); brightSlider->setRange(-100, 100); brightSlider->setTracking(false); connect(brightSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); contrastSlider = new QSlider(Qt::Horizontal); contrastSlider->setTickPosition(QSlider::TicksAbove); contrastSlider->setTickInterval(25); contrastSlider->setRange(-100, 100); contrastSlider->setTracking(false); contrastSlider->setInvertedAppearance(true); connect(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); QGridLayout *brightContrastbox = new QGridLayout; brightContrastbox->addWidget(brightLab, 1, 0, 1, 1); brightContrastbox->addWidget(brightSlider, 1, 1, 1, 1); brightContrastbox->addWidget(contrastLab, 2, 0, 1, 1); brightContrastbox->addWidget(contrastSlider, 2, 1, 1, 1); brightContrastbox->setColumnMinimumWidth(0, 70); QGroupBox *brightContrastGroup = new QGroupBox(tr("Brightness and Contrast")); brightContrastGroup->setLayout(brightContrastbox); /* Channel mixer */ QLabel *redLab = new QLabel(tr("Red")); redSlider = new QSlider(Qt::Horizontal); redSlider->setTickPosition(QSlider::TicksAbove); redSlider->setTickInterval(25); redSlider->setRange(-100, 100); redSlider->setTracking(false); connect(redSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); QLabel *greenLab = new QLabel(tr("Green")); greenSlider = new QSlider(Qt::Horizontal); greenSlider->setTickPosition(QSlider::TicksAbove); greenSlider->setTickInterval(25); greenSlider->setRange(-100, 100); greenSlider->setTracking(false); connect(greenSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); QLabel *blueLab = new QLabel(tr("Blue")); blueSlider = new QSlider(Qt::Horizontal); blueSlider->setTickPosition(QSlider::TicksAbove); blueSlider->setTickInterval(25); blueSlider->setRange(-100, 100); blueSlider->setTracking(false); connect(blueSlider, SIGNAL(valueChanged(int)), this, SLOT(applyColors(int))); QGridLayout *channelMixbox = new QGridLayout; channelMixbox->addWidget(redLab, 1, 0, 1, 1); channelMixbox->addWidget(redSlider, 1, 1, 1, 1); channelMixbox->addWidget(rNegateCheckBox, 1, 2, 1, 1); channelMixbox->addWidget(greenLab, 2, 0, 1, 1); channelMixbox->addWidget(greenSlider, 2, 1, 1, 1); channelMixbox->addWidget(gNegateCheckBox, 2, 2, 1, 1); channelMixbox->addWidget(blueLab, 3, 0, 1, 1); channelMixbox->addWidget(blueSlider, 3, 1, 1, 1); channelMixbox->addWidget(bNegateCheckBox, 3, 2, 1, 1); channelMixbox->setColumnMinimumWidth(0, 70); QGroupBox *channelMixGroup = new QGroupBox(tr("Color Balance")); channelMixGroup->setLayout(channelMixbox); QVBoxLayout *mainVbox = new QVBoxLayout; mainVbox->addWidget(brightContrastGroup); mainVbox->addWidget(channelMixGroup); mainVbox->addWidget(hueSatGroup); mainVbox->addWidget(channelsGroup); mainVbox->addStretch(1); mainVbox->addLayout(buttonsHbox); setLayout(mainVbox); applyColors(0); } void ColorsDialog::applyColors(int) { if (brightSlider->value() >= 0) { Settings::brightVal = (brightSlider->value() * 500 / 100) + 100; } else { Settings::brightVal = brightSlider->value() + 100; } if (contrastSlider->value() >= 0) { Settings::contrastVal = (contrastSlider->value() * 79 / 100) + 78; } else { Settings::contrastVal = contrastSlider->value() + 79; } Settings::hueVal = hueSlider->value() * 127 / 100; if (saturationSlider->value() >= 0) { Settings::saturationVal = (saturationSlider->value() * 500 / 100) + 100; } else { Settings::saturationVal = saturationSlider->value() + 100; } if (lightnessSlider->value() >= 0) { Settings::lightnessVal = (lightnessSlider->value() * 200 / 100) + 100; } else { Settings::lightnessVal = lightnessSlider->value() + 100; } Settings::redVal = redSlider->value(); Settings::greenVal = greenSlider->value(); Settings::blueVal = blueSlider->value(); imageViewer->refresh(); } void ColorsDialog::ok() { Settings::dialogLastX = pos().x(); Settings::dialogLastY = pos().y(); accept(); } void ColorsDialog::reset() { hueSlider->setValue(0); colorizeCheckBox->setChecked(false); rNegateCheckBox->setChecked(false); gNegateCheckBox->setChecked(false); bNegateCheckBox->setChecked(false); saturationSlider->setValue(0); lightnessSlider->setValue(0); redCheckBox->setChecked(true); greenCheckBox->setChecked(true); blueCheckBox->setChecked(true); Settings::hueRedChannel = true; Settings::hueGreenChannel = true; Settings::hueBlueChannel = true; contrastSlider->setValue(0); brightSlider->setValue(0); redSlider->setValue(0); greenSlider->setValue(0); blueSlider->setValue(0); imageViewer->refresh(); } void ColorsDialog::enableColorize(int state) { Settings::colorizeEnabled = state; imageViewer->refresh(); } void ColorsDialog::redNegative(int state) { Settings::rNegateEnabled = state; imageViewer->refresh(); } void ColorsDialog::greenNegative(int state) { Settings::gNegateEnabled = state; imageViewer->refresh(); } void ColorsDialog::blueNegative(int state) { Settings::bNegateEnabled = state; imageViewer->refresh(); } void ColorsDialog::setRedChannel() { Settings::hueRedChannel = redCheckBox->isChecked(); imageViewer->refresh(); } void ColorsDialog::setGreenChannel() { Settings::hueGreenChannel = greenCheckBox->isChecked(); imageViewer->refresh(); } void ColorsDialog::setBlueChannel() { Settings::hueBlueChannel = blueCheckBox->isChecked(); imageViewer->refresh(); } phototonic-2.1/ColorsDialog.h000066400000000000000000000034111325127642100162760ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef COLORS_DIALOG_H #define COLORS_DIALOG_H #include #include "ImageViewer.h" class ColorsDialog : public QDialog { Q_OBJECT public: ColorsDialog(QWidget *parent, ImageViewer *imageViewer); public slots: void ok(); void reset(); void enableColorize(int state); void redNegative(int state); void greenNegative(int state); void blueNegative(int state); void setRedChannel(); void setGreenChannel(); void setBlueChannel(); void applyColors(int value); private: ImageViewer *imageViewer; QSlider *hueSlider; QCheckBox *colorizeCheckBox; QSlider *saturationSlider; QSlider *lightnessSlider; QCheckBox *redCheckBox; QCheckBox *greenCheckBox; QCheckBox *blueCheckBox; QSlider *brightSlider; QSlider *contrastSlider; QSlider *redSlider; QSlider *greenSlider; QSlider *blueSlider; QCheckBox *rNegateCheckBox; QCheckBox *gNegateCheckBox; QCheckBox *bNegateCheckBox; }; #endif // COLORS_DIALOG_Hphototonic-2.1/CopyMoveDialog.cpp000066400000000000000000000114201325127642100171300ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "CopyMoveDialog.h" static QString autoRename(QString &destDir, QString &currFile) { int extSep = currFile.lastIndexOf("."); QString nameOnly = currFile.left(extSep); QString extOnly = currFile.right(currFile.size() - extSep - 1); QString newFile; int idx = 1; do { newFile = QString(nameOnly + "_copy_%1." + extOnly).arg(idx); ++idx; } while (idx && (QFile::exists(destDir + QDir::separator() + newFile))); return newFile; } int CopyMoveDialog::copyOrMoveFile(bool isCopy, QString &srcFile, QString &srcPath, QString &dstPath, QString &dstDir) { int res; if (isCopy) { res = QFile::copy(srcPath, dstPath); } else { res = QFile::rename(srcPath, dstPath); } if (!res && QFile::exists(dstPath)) { QString newName = autoRename(dstDir, srcFile); QString newDestPath = dstDir + QDir::separator() + newName; if (isCopy) { res = QFile::copy(srcPath, newDestPath); } else { res = QFile::rename(srcPath, newDestPath); } dstPath = newDestPath; } return res; } CopyMoveDialog::CopyMoveDialog(QWidget *parent) : QDialog(parent) { abortOp = false; opLabel = new QLabel(""); cancelButton = new QPushButton(tr("Cancel")); cancelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(cancelButton, SIGNAL(clicked()), this, SLOT(abort())); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addWidget(opLabel); QHBoxLayout *buttonsLayout = new QHBoxLayout; buttonsLayout->addWidget(cancelButton); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(topLayout); mainLayout->addLayout(buttonsLayout, Qt::AlignRight); setLayout(mainLayout); } void CopyMoveDialog::exec(ThumbsViewer *thumbView, QString &destDir, bool pasteInCurrDir) { int res = 0; QString sourceFile; QFileInfo fileInfo; QString currFile; QString destFile; int tn; show(); if (pasteInCurrDir) { for (tn = 0; tn < Settings::copyCutFileList.size(); ++tn) { sourceFile = Settings::copyCutFileList[tn]; fileInfo = QFileInfo(sourceFile); currFile = fileInfo.fileName(); destFile = destDir + QDir::separator() + currFile; opLabel->setText((Settings::isCopyOperation ? tr("Copying \"%1\" to \"%2\".") : tr("Moving \"%1\" to \"%2\".")) .arg(sourceFile).arg(destFile)); QApplication::processEvents(); res = CopyMoveDialog::copyOrMoveFile(Settings::isCopyOperation, currFile, sourceFile, destFile, destDir); if (!res || abortOp) { break; } else { Settings::copyCutFileList[tn] = destFile; } } } else { QList rowList; for (tn = Settings::copyCutIndexList.size() - 1; tn >= 0; --tn) { sourceFile = thumbView->thumbsViewerModel->item(Settings::copyCutIndexList[tn].row())-> data(thumbView->FileNameRole).toString(); fileInfo = QFileInfo(sourceFile); currFile = fileInfo.fileName(); destFile = destDir + QDir::separator() + currFile; opLabel->setText((Settings::isCopyOperation ? tr("Copying %1 to %2.") : tr("Moving %1 to %2.")).arg(sourceFile).arg(destFile)); QApplication::processEvents(); res = copyOrMoveFile(Settings::isCopyOperation, currFile, sourceFile, destFile, destDir); if (!res || abortOp) { break; } rowList.append(Settings::copyCutIndexList[tn].row()); } if (!Settings::isCopyOperation) { qSort(rowList); for (int t = rowList.size() - 1; t >= 0; --t) thumbView->thumbsViewerModel->removeRow(rowList.at(t)); } latestRow = rowList.at(0); } nFiles = Settings::copyCutIndexList.size(); close(); } void CopyMoveDialog::abort() { abortOp = true; } phototonic-2.1/CopyMoveDialog.h000066400000000000000000000025151325127642100166020ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef COPY_MOVE_DIALOG_H #define COPY_MOVE_DIALOG_H #include #include "ThumbsViewer.h" class CopyMoveDialog : public QDialog { Q_OBJECT public slots: void abort(); public: CopyMoveDialog(QWidget *parent); static int copyOrMoveFile(bool isCopy, QString &srcFile, QString &srcPath, QString &dstPath, QString &dstDir); void exec(ThumbsViewer *thumbView, QString &destDir, bool pasteInCurrDir); int nFiles; int latestRow; private: QLabel *opLabel; QPushButton *cancelButton; bool abortOp; }; #endif // COPY_MOVE_DIALOG_Hphototonic-2.1/CopyMoveToDialog.cpp000066400000000000000000000143231325127642100174400ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov - oferkv@live.com * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "CopyMoveToDialog.h" #include "Settings.h" void CopyMoveToDialog::selection(const QItemSelection &, const QItemSelection &) { if (pathsTable->selectionModel()->selectedRows().size() > 0) { destinationLabel->setText(tr("Destination:") + " " + pathsTableModel->item( pathsTable->selectionModel()->selectedRows().at(0).row())->text()); } } void CopyMoveToDialog::pathDoubleClick(const QModelIndex &) { copyOrMove(); } void CopyMoveToDialog::savePaths() { Settings::bookmarkPaths.clear(); for (int i = 0; i < pathsTableModel->rowCount(); ++i) { Settings::bookmarkPaths.insert (pathsTableModel->itemFromIndex(pathsTableModel->index(i, 0))->text()); } } void CopyMoveToDialog::copyOrMove() { savePaths(); QModelIndexList indexesList; if ((indexesList = pathsTable->selectionModel()->selectedIndexes()).size()) { selectedPath = pathsTableModel->itemFromIndex(indexesList.first())->text(); accept(); } else { reject(); } } void CopyMoveToDialog::justClose() { savePaths(); reject(); } void CopyMoveToDialog::add() { QString dirName = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), currentPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (dirName.isEmpty()) { return; } QStandardItem *item = new QStandardItem(QIcon(":/images/bookmarks.png"), dirName); pathsTableModel->insertRow(pathsTableModel->rowCount(), item); pathsTable->selectionModel()->clearSelection(); pathsTable->selectionModel()->select(pathsTableModel->index(pathsTableModel->rowCount() - 1, 0), QItemSelectionModel::Select); } void CopyMoveToDialog::remove() { QModelIndexList indexesList; if ((indexesList = pathsTable->selectionModel()->selectedIndexes()).size()) { pathsTableModel->removeRow(indexesList.first().row()); } } CopyMoveToDialog::CopyMoveToDialog(QWidget *parent, QString thumbsPath, bool move) : QDialog(parent) { copyOp = !move; if (move) { setWindowTitle(tr("Move to...")); setWindowIcon(QIcon::fromTheme("go-next")); } else { setWindowTitle(tr("Copy to...")); setWindowIcon(QIcon::fromTheme("edit-copy")); } resize(350, 250); currentPath = thumbsPath; pathsTable = new QTableView(this); pathsTable->setSelectionBehavior(QAbstractItemView::SelectItems); pathsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); pathsTable->setEditTriggers(QAbstractItemView::NoEditTriggers); pathsTable->setSelectionBehavior(QAbstractItemView::SelectRows); pathsTable->setSelectionMode(QAbstractItemView::SingleSelection); pathsTableModel = new QStandardItemModel(this); pathsTable->setModel(pathsTableModel); pathsTable->verticalHeader()->setVisible(false); pathsTable->horizontalHeader()->setVisible(false); pathsTable->verticalHeader()->setDefaultSectionSize(pathsTable->verticalHeader()-> minimumSectionSize()); pathsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); pathsTable->setShowGrid(false); connect(pathsTable->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(selection(QItemSelection, QItemSelection))); connect(pathsTable, SIGNAL(doubleClicked( const QModelIndex &)), this, SLOT(pathDoubleClick( const QModelIndex &))); QHBoxLayout *addRemoveHbox = new QHBoxLayout; QPushButton *addButton = new QPushButton(tr("Browse...")); connect(addButton, SIGNAL(clicked()), this, SLOT(add())); QPushButton *removeButton = new QPushButton(tr("Delete Bookmark")); connect(removeButton, SIGNAL(clicked()), this, SLOT(remove())); addRemoveHbox->addWidget(removeButton, 0, Qt::AlignLeft); addRemoveHbox->addStretch(1); addRemoveHbox->addWidget(addButton, 0, Qt::AlignRight); QHBoxLayout *buttonsHbox = new QHBoxLayout; QPushButton *cancelButton = new QPushButton(tr("Cancel")); cancelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(cancelButton, SIGNAL(clicked()), this, SLOT(justClose())); QPushButton *okButton = new QPushButton(tr("OK")); okButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); okButton->setDefault(true); connect(okButton, SIGNAL(clicked()), this, SLOT(copyOrMove())); buttonsHbox->addStretch(1); buttonsHbox->addWidget(cancelButton, 0, Qt::AlignRight); buttonsHbox->addWidget(okButton, 0, Qt::AlignRight); destinationLabel = new QLabel(tr("Destination:")); QFrame *line = new QFrame(this); line->setObjectName(QString::fromUtf8("line")); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); QVBoxLayout *mainVbox = new QVBoxLayout; mainVbox->addWidget(pathsTable); mainVbox->addLayout(addRemoveHbox); mainVbox->addWidget(line); mainVbox->addWidget(destinationLabel); mainVbox->addLayout(buttonsHbox); setLayout(mainVbox); // Load paths list QSetIterator it(Settings::bookmarkPaths); while (it.hasNext()) { QStandardItem *item = new QStandardItem(QIcon(":/images/bookmarks.png"), it.next()); pathsTableModel->insertRow(pathsTableModel->rowCount(), item); } pathsTableModel->sort(0); } phototonic-2.1/CopyMoveToDialog.h000066400000000000000000000027401325127642100171050ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov - oferkv@live.com * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef COPY_MOVE_TO_DIALOG_H #define COPY_MOVE_TO_DIALOG_H #include #include #include class CopyMoveToDialog : public QDialog { Q_OBJECT public: CopyMoveToDialog(QWidget *parent, QString thumbsPath, bool move); QString selectedPath; bool copyOp; private slots: void copyOrMove(); void justClose(); void add(); void remove(); void selection(const QItemSelection &, const QItemSelection &); void pathDoubleClick(const QModelIndex &idx); private: QTableView *pathsTable; QStandardItemModel *pathsTableModel; QString currentPath; QLabel *destinationLabel; void savePaths(); }; #endif // COPY_MOVE_TO_DIALOG_Hphototonic-2.1/CropDialog.cpp000066400000000000000000000124101325127642100162720ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "CropDialog.h" #include "Settings.h" CropDialog::CropDialog(QWidget *parent, ImageViewer *imageViewer) : QDialog(parent) { setWindowTitle(tr("Cropping")); setWindowIcon(QIcon(":/images/crop.png")); resize(350, 100); if (Settings::dialogLastX) move(Settings::dialogLastX, Settings::dialogLastY); this->imageViewer = imageViewer; QHBoxLayout *buttonsHbox = new QHBoxLayout; QPushButton *resetButton = new QPushButton(tr("Reset")); connect(resetButton, SIGNAL(clicked()), this, SLOT(reset())); QPushButton *okButton = new QPushButton(tr("OK")); connect(okButton, SIGNAL(clicked()), this, SLOT(ok())); okButton->setDefault(true); buttonsHbox->addWidget(resetButton, 0, Qt::AlignLeft); buttonsHbox->addWidget(okButton, 0, Qt::AlignRight); QSlider *topSlide = new QSlider(Qt::Horizontal); topSlide->setTickPosition(QSlider::TicksAbove); topSlide->setTickInterval(10); topSlide->setTracking(false); QSlider *bottomSlide = new QSlider(Qt::Horizontal); bottomSlide->setTickPosition(QSlider::TicksAbove); bottomSlide->setTickInterval(10); bottomSlide->setTracking(false); QSlider *leftSlide = new QSlider(Qt::Horizontal); leftSlide->setTickPosition(QSlider::TicksAbove); leftSlide->setTickInterval(10); leftSlide->setTracking(false); QSlider *rightSlide = new QSlider(Qt::Horizontal); rightSlide->setTickPosition(QSlider::TicksAbove); rightSlide->setTickInterval(10); rightSlide->setTracking(false); topSpinBox = new QSpinBox; topSpinBox->setPrefix("% "); bottomSpinBox = new QSpinBox; bottomSpinBox->setPrefix("% "); leftSpinBox = new QSpinBox; leftSpinBox->setPrefix("% "); rightSpinBox = new QSpinBox; rightSpinBox->setPrefix("% "); QLabel *leftLab = new QLabel(tr("Left")); QLabel *rightLab = new QLabel(tr("Right")); QLabel *topLab = new QLabel(tr("Top")); QLabel *bottomLab = new QLabel(tr("Bottom")); QGridLayout *mainGbox = new QGridLayout; mainGbox->addWidget(leftLab, 0, 0, 1, 1); mainGbox->addWidget(leftSlide, 0, 1, 1, 1); mainGbox->addWidget(leftSpinBox, 0, 2, 1, 1); mainGbox->addWidget(rightLab, 1, 0, 1, 1); mainGbox->addWidget(rightSlide, 1, 1, 1, 1); mainGbox->addWidget(rightSpinBox, 1, 2, 1, 1); mainGbox->addWidget(topLab, 2, 0, 1, 1); mainGbox->addWidget(topSlide, 2, 1, 1, 1); mainGbox->addWidget(topSpinBox, 2, 2, 1, 1); mainGbox->addWidget(bottomLab, 3, 0, 1, 1); mainGbox->addWidget(bottomSlide, 3, 1, 1, 1); mainGbox->addWidget(bottomSpinBox, 3, 2, 1, 1); QVBoxLayout *mainVbox = new QVBoxLayout; mainVbox->addLayout(mainGbox); mainVbox->addLayout(buttonsHbox); setLayout(mainVbox); topSpinBox->setRange(0, 100); bottomSpinBox->setRange(0, 100); leftSpinBox->setRange(0, 100); rightSpinBox->setRange(0, 100); topSlide->setRange(0, 100); bottomSlide->setRange(0, 100); leftSlide->setRange(0, 100); rightSlide->setRange(0, 100); connect(topSlide, SIGNAL(valueChanged(int)), topSpinBox, SLOT(setValue(int))); connect(bottomSlide, SIGNAL(valueChanged(int)), bottomSpinBox, SLOT(setValue(int))); connect(leftSlide, SIGNAL(valueChanged(int)), leftSpinBox, SLOT(setValue(int))); connect(rightSlide, SIGNAL(valueChanged(int)), rightSpinBox, SLOT(setValue(int))); connect(topSpinBox, SIGNAL(valueChanged(int)), topSlide, SLOT(setValue(int))); connect(bottomSpinBox, SIGNAL(valueChanged(int)), bottomSlide, SLOT(setValue(int))); connect(leftSpinBox, SIGNAL(valueChanged(int)), leftSlide, SLOT(setValue(int))); connect(rightSpinBox, SIGNAL(valueChanged(int)), rightSlide, SLOT(setValue(int))); connect(topSpinBox, SIGNAL(valueChanged(int)), this, SLOT(applyCrop(int))); connect(bottomSpinBox, SIGNAL(valueChanged(int)), this, SLOT(applyCrop(int))); connect(leftSpinBox, SIGNAL(valueChanged(int)), this, SLOT(applyCrop(int))); connect(rightSpinBox, SIGNAL(valueChanged(int)), this, SLOT(applyCrop(int))); } void CropDialog::applyCrop(int) { Settings::cropLeftPercent = leftSpinBox->value(); Settings::cropTopPercent = topSpinBox->value(); Settings::cropWidthPercent = rightSpinBox->value(); Settings::cropHeightPercent = bottomSpinBox->value(); imageViewer->refresh(); } void CropDialog::ok() { Settings::dialogLastX = pos().x(); Settings::dialogLastY = pos().y(); accept(); } void CropDialog::reset() { leftSpinBox->setValue(0); rightSpinBox->setValue(0); topSpinBox->setValue(0); bottomSpinBox->setValue(0); }phototonic-2.1/CropDialog.h000066400000000000000000000023241325127642100157420ustar00rootroot00000000000000/* * Copyright (C) 2013 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef CROP_DIALOG_H #define CROP_DIALOG_H #include #include "ImageViewer.h" class CropDialog : public QDialog { Q_OBJECT public: CropDialog(QWidget *parent, ImageViewer *imageViewer); public slots: void ok(); void reset(); void applyCrop(int); private: QSpinBox *topSpinBox; QSpinBox *bottomSpinBox; QSpinBox *leftSpinBox; QSpinBox *rightSpinBox; ImageViewer *imageViewer; }; #endif // CROP_DIALOG_Hphototonic-2.1/CropRubberband.cpp000066400000000000000000000043111325127642100171420ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov - oferkv@live.com * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "CropRubberband.h" CropRubberBand::CropRubberBand(QWidget *parent) : QWidget(parent) { setWindowFlags(Qt::SubWindow); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); QHBoxLayout *topLayout = new QHBoxLayout(); topLayout->setContentsMargins(0, 0, 0, 0); QHBoxLayout *bottomLayout = new QHBoxLayout(); bottomLayout->setContentsMargins(0, 0, 0, 0); QSizeGrip *grip1 = new QSizeGrip(this); QSizeGrip *grip2 = new QSizeGrip(this); QSizeGrip *grip3 = new QSizeGrip(this); QSizeGrip *grip4 = new QSizeGrip(this); grip1->setStyleSheet("background-color: rgba(0, 0, 0, 0%)"); grip2->setStyleSheet("background-color: rgba(0, 0, 0, 0%)"); grip3->setStyleSheet("background-color: rgba(0, 0, 0, 0%)"); grip4->setStyleSheet("background-color: rgba(0, 0, 0, 0%)"); topLayout->addWidget(grip1, 0, Qt::AlignTop | Qt::AlignLeft); topLayout->addWidget(grip2, 1, Qt::AlignTop | Qt::AlignRight); bottomLayout->addWidget(grip3, 0, Qt::AlignBottom | Qt::AlignLeft); bottomLayout->addWidget(grip4, 1, Qt::AlignBottom | Qt::AlignRight); mainLayout->addLayout(topLayout); mainLayout->addLayout(bottomLayout); rubberband = new QRubberBand(QRubberBand::Rectangle, this); rubberband->setStyleSheet("background-color: rgb(255, 255, 255)"); rubberband->show(); } void CropRubberBand::resizeEvent(QResizeEvent *) { rubberband->resize(size()); } phototonic-2.1/CropRubberband.h000066400000000000000000000020231325127642100166050ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov - oferkv@live.com * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef CROPRUBBERBAND_H #define CROPRUBBERBAND_H #include class CropRubberBand : public QWidget { public: CropRubberBand(QWidget *parent = 0); private: QRubberBand *rubberband; void resizeEvent(QResizeEvent *); }; #endif // CROPRUBBERBAND_H phototonic-2.1/DirCompleter.cpp000066400000000000000000000025751325127642100166530ustar00rootroot00000000000000/* * Copyright (C) 2015 Thomas Lübking * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include "DirCompleter.h" DirCompleter::DirCompleter(QObject *parent) : QCompleter(parent) { QDirModel *model = new QDirModel; model->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); model->setLazyChildCount(true); setModel(model); } QString DirCompleter::pathFromIndex(const QModelIndex &index) const { return QCompleter::pathFromIndex(index) + "/"; } QStringList DirCompleter::splitPath(const QString &path) const { if (path.startsWith("~")) { return QCompleter::splitPath(QString(path).replace(0, 1, QDir::homePath())); } return QCompleter::splitPath(path); } phototonic-2.1/DirCompleter.h000066400000000000000000000021231325127642100163050ustar00rootroot00000000000000/* * Copyright (C) 2015 Thomas Lübking * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef DIR_COMPLETER_H #define DIR_COMPLETER_H #include class DirCompleter : public QCompleter { Q_OBJECT public: DirCompleter(QObject *parent = 0); QString pathFromIndex(const QModelIndex &index) const; public slots: QStringList splitPath(const QString &path) const; }; #endif // DIR_COMPLETER_H phototonic-2.1/ExternalAppsDialog.cpp000066400000000000000000000117551325127642100200100ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include "ExternalAppsDialog.h" #include "Settings.h" ExternalAppsDialog::ExternalAppsDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Manage External Applications")); setWindowIcon(QIcon::fromTheme("preferences-other", QIcon(":/images/phototonic.png"))); resize(350, 250); appsTable = new QTableView(this); appsTable->setSelectionBehavior(QAbstractItemView::SelectItems); appsTable->setSelectionMode(QAbstractItemView::ExtendedSelection); appsTable->setSelectionBehavior(QAbstractItemView::SelectRows); appsTableModel = new QStandardItemModel(this); appsTable->setModel(appsTableModel); appsTable->verticalHeader()->setVisible(false); appsTable->verticalHeader()->setDefaultSectionSize(appsTable->verticalHeader()->minimumSectionSize()); appsTableModel->setHorizontalHeaderItem(0, new QStandardItem(QString(tr("Name")))); appsTableModel->setHorizontalHeaderItem(1, new QStandardItem(QString(tr("Application path and arguments")))); appsTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive); appsTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); appsTable->setShowGrid(false); QHBoxLayout *externalAppsLayout = new QHBoxLayout; QPushButton *addButton = new QPushButton(tr("Choose")); connect(addButton, SIGNAL(clicked()), this, SLOT(add())); externalAppsLayout->addWidget(addButton, 0, Qt::AlignRight); QPushButton *entryButton = new QPushButton(tr("Add manually")); connect(entryButton, SIGNAL(clicked()), this, SLOT(entry())); externalAppsLayout->addWidget(entryButton, 0, Qt::AlignRight); QPushButton *removeButton = new QPushButton(tr("Delete")); connect(removeButton, SIGNAL(clicked()), this, SLOT(remove())); externalAppsLayout->addWidget(removeButton, 0, Qt::AlignRight); externalAppsLayout->addStretch(1); QHBoxLayout *buttonsLayout = new QHBoxLayout; QPushButton *okButton = new QPushButton(tr("OK")); okButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(okButton, SIGNAL(clicked()), this, SLOT(ok())); buttonsLayout->addWidget(okButton, 0, Qt::AlignRight); QVBoxLayout *externalAppsMainLayout = new QVBoxLayout; externalAppsMainLayout->addWidget(appsTable); externalAppsMainLayout->addLayout(externalAppsLayout); externalAppsMainLayout->addLayout(buttonsLayout); setLayout(externalAppsMainLayout); // Load external apps list QString key, val; QMapIterator it(Settings::externalApps); while (it.hasNext()) { it.next(); key = it.key(); val = it.value(); addTableModelItem(appsTableModel, key, val); } } void ExternalAppsDialog::ok() { int row = appsTableModel->rowCount(); Settings::externalApps.clear(); for (int i = 0; i < row; ++i) { if (!appsTableModel->itemFromIndex(appsTableModel->index(i, 1))->text().isEmpty()) { Settings::externalApps[appsTableModel->itemFromIndex(appsTableModel->index(i, 0))->text()] = appsTableModel->itemFromIndex(appsTableModel->index(i, 1))->text(); } } accept(); } void ExternalAppsDialog::add() { QString fileName = QFileDialog::getOpenFileName(this, tr("Choose Application"), "", ""); if (fileName.isEmpty()) return; QFileInfo fileInfo = QFileInfo(fileName); QString appName = fileInfo.fileName(); addTableModelItem(appsTableModel, appName, fileName); } void ExternalAppsDialog::entry() { int atRow = appsTableModel->rowCount(); QStandardItem *itemKey = new QStandardItem(QString(tr("New Application"))); appsTableModel->insertRow(atRow, itemKey); } void ExternalAppsDialog::remove() { QModelIndexList indexesList; while ((indexesList = appsTable->selectionModel()->selectedIndexes()).size()) { appsTableModel->removeRow(indexesList.first().row()); } } void ExternalAppsDialog::addTableModelItem(QStandardItemModel *model, QString &key, QString &val) { int atRow = model->rowCount(); QStandardItem *itemKey = new QStandardItem(key); QStandardItem *itemKey2 = new QStandardItem(val); model->insertRow(atRow, itemKey); model->setItem(atRow, 1, itemKey2); } phototonic-2.1/ExternalAppsDialog.h000066400000000000000000000024261325127642100174500ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef EXTERNAL_APPS_DIALOG_H #define EXTERNAL_APPS_DIALOG_H #include #include class ExternalAppsDialog : public QDialog { Q_OBJECT public: ExternalAppsDialog(QWidget *parent); public slots: void ok(); private slots: void add(); void remove(); void entry(); private: QTableView *appsTable; QStandardItemModel *appsTableModel; void addTableModelItem(QStandardItemModel *model, QString &key, QString &val); }; #endif // EXTERNAL_APPS_DIALOG_Hphototonic-2.1/FileListWidget.cpp000066400000000000000000000041541325127642100171340ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "FileListWidget.h" FileListWidget::FileListWidget(QWidget *parent) : QTreeWidget(parent) { setAcceptDrops(true); setDragEnabled(false); setDragDropMode(QAbstractItemView::DropOnly); setColumnCount(1); setHeaderHidden(true); addFileListEntry(); setMaximumHeight((int) (QFontMetrics(font()).height() * 1.6)); } void FileListWidget::addFileListEntry() { QTreeWidgetItem *item = new QTreeWidgetItem(this); item->setText(0, "File List"); item->setIcon(0, style()->standardIcon(QStyle::SP_FileDialogDetailedView)); insertTopLevelItem(0, item); } void FileListWidget::resizeTreeColumn(const QModelIndex &) { resizeColumnToContents(0); } void FileListWidget::dragEnterEvent(QDragEnterEvent *event) { QModelIndexList selectedDirs = selectionModel()->selectedRows(); if (selectedDirs.size() > 0) { dndOrigSelection = selectedDirs[0]; } event->acceptProposedAction(); } void FileListWidget::dragMoveEvent(QDragMoveEvent *event) { setCurrentIndex(indexAt(event->pos())); } void FileListWidget::dropEvent(QDropEvent *event) { if (event->source()) { QString fileSystemTreeStr("FileSystemTree"); bool dirOp = (event->source()->metaObject()->className() == fileSystemTreeStr); emit dropOp(event->keyboardModifiers(), dirOp, event->mimeData()->urls().at(0).toLocalFile()); } } phototonic-2.1/FileListWidget.h000066400000000000000000000025471325127642100166050ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef FILE_LIST_WIDGET_H #define FILE_LIST_WIDGET_H #include #include "Settings.h" class FileListWidget : public QTreeWidget { Q_OBJECT public: FileListWidget(QWidget *parent); void addFileListEntry(); private: QModelIndex dndOrigSelection; private slots: void resizeTreeColumn(const QModelIndex &); protected: void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); signals: void dropOp(Qt::KeyboardModifiers keyMods, bool dirOp, QString cpMvDirPath); }; #endif // FILE_LIST_WIDGET_H phototonic-2.1/FileSystemModel.cpp000066400000000000000000000022431325127642100173170ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "FileSystemModel.h" bool FileSystemModel::hasChildren(const QModelIndex &parent) const { if (parent.column() > 0) { return false; } if (!parent.isValid()) { return true; } if (parent.flags() & Qt::ItemNeverHasChildren) { return false; } return QDirIterator(filePath(parent), filter() | QDir::NoDotAndDotDot, QDirIterator::NoIteratorFlags).hasNext(); }phototonic-2.1/FileSystemModel.h000066400000000000000000000017731325127642100167730ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef FILE_SYSTEM_MODEL_H #define FILE_SYSTEM_MODEL_H #include class FileSystemModel : public QFileSystemModel { Q_OBJECT public: bool hasChildren(const QModelIndex &parent) const; }; #endif // FILE_SYSTEM_MODEL_H phototonic-2.1/FileSystemTree.cpp000066400000000000000000000052651325127642100171650ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "FileSystemTree.h" FileSystemTree::FileSystemTree(QWidget *parent) : QTreeView(parent) { setAcceptDrops(true); setDragEnabled(true); setDragDropMode(QAbstractItemView::InternalMove); fileSystemModel = new FileSystemModel(); fileSystemModel->setRootPath(""); setModelFlags(); setModel(fileSystemModel); for (int i = 1; i <= 3; ++i) { hideColumn(i); } setHeaderHidden(true); connect(this, SIGNAL(expanded( const QModelIndex &)), this, SLOT(resizeTreeColumn( const QModelIndex &))); connect(this, SIGNAL(collapsed( const QModelIndex &)), this, SLOT(resizeTreeColumn( const QModelIndex &))); } QModelIndex FileSystemTree::getCurrentIndex() { return selectedIndexes().first(); } void FileSystemTree::resizeTreeColumn(const QModelIndex &) { resizeColumnToContents(0); } void FileSystemTree::dragEnterEvent(QDragEnterEvent *event) { QModelIndexList selectedDirs = selectionModel()->selectedRows(); if (selectedDirs.size() > 0) { dndOrigSelection = selectedDirs[0]; event->acceptProposedAction(); } } void FileSystemTree::dragMoveEvent(QDragMoveEvent *event) { setCurrentIndex(indexAt(event->pos())); } void FileSystemTree::dropEvent(QDropEvent *event) { if (event->source()) { QString fileSystemTreeStr = "FileSystemTree"; bool dirOp = (event->source()->metaObject()->className() == fileSystemTreeStr); emit dropOp(event->keyboardModifiers(), dirOp, event->mimeData()->urls().at(0).toLocalFile()); setCurrentIndex(dndOrigSelection); } } void FileSystemTree::setModelFlags() { fileSystemModel->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot); if (Settings::showHiddenFiles) { fileSystemModel->setFilter(fileSystemModel->filter() | QDir::Hidden); } } phototonic-2.1/FileSystemTree.h000066400000000000000000000027521325127642100166300ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include #include "Settings.h" #include "FileSystemModel.h" #ifndef FILE_SYSTEM_TREE_H #define FILE_SYSTEM_TREE_H class FileSystemTree : public QTreeView { Q_OBJECT public: FileSystemTree(QWidget *parent); FileSystemModel *fileSystemModel; QModelIndex getCurrentIndex(); void setModelFlags(); protected: void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); signals: void dropOp(Qt::KeyboardModifiers keyMods, bool dirOp, QString cpMvDirPath); private: QModelIndex dndOrigSelection; private slots: void resizeTreeColumn(const QModelIndex &); }; #endif // FILE_SYSTEM_TREE_H phototonic-2.1/HISTORY.md000066400000000000000000000122611325127642100152320ustar00rootroot00000000000000# Phototonic Image Viewer ### History: ##### 4 Jul 2015 - v1.6.6 + Improved tags usability and performance + Bug fixes ##### 6 Jun 2015 - v1.6.2 + Image tags, tagging images and filtering images by tags + Delete confirmation is now configurable + Improvements to drag and drop + A more sophisticated Dir-completer + Many many more fixes and improvements, thanks to the contributors! ##### 6 Feb 2015 - v1.5.54 + Keyboard Shortcuts are now comfortably edited in a table + Enhancements to Find Duplicates feature + Many enhancements to translations and translations functionality + Fixes to the way key bindings are saved + Fixes to invalid behavior when deleting elements + Fixed folders expand indicator showing when there are no sub-folders + Fixed to the way bookmarks are saved + Added Changelog ##### 21 Nov 2014 - v1.5.1 + New toolbar in viewer mode for image manipulation actions + Added Bookmarks feature + Fixed sorting order when sorting by time and size + Added Find Duplicate Images feature + Added shortcuts for changing the focus to the Find and Path text areas + Enhancements to Copy to and Move to dialogs + Can now set thumbnails background image + Enhancements to Colors dialog, added color balance feature + Added Crop to Selection feature + Added mouse shortcuts for Reset/Original Zoom + Added feedback notification for transformation actions in viewer + Changed Cropping dialog orientation to percentage cropping for continuous image cropping + Image data now showed in sections + Many other fixes ##### 19 Sep 2014 - v1.4 + Viewer is now available in the thumbnails layout as a Dock + Thumbnails can now also be rotated according Exif orientation + Added Debian packaging scripts + Enhances to external application dialog + Added Czech translation + Added French translation + Better feedback when starting external applications + Settings dialog controls are now grouped in tabs + Added 16px size application icon + Improvements to German translation + Can now rename an image when in viewer + Added busy indicator for some actions in thumbnails layout + Changes to version scheme + Open image action now toggles closing the image when in viewer + Consolidate feedback in viewer to bubbles + Tool bars icon size is now custom + Confirmation is asked when moving folders around in the tree + Fixes to slowness and other bugs when closing image from full screen + Fixed folder focus stealing issue when creating a new folder + Fixes for some untranslated dialogs + Fix dialogs creating shadow over image under KDE + Fixes for wrong dock sizes when toggling layouts + Fixed slowness when inverting selection + Many other fixes ##### 8 Aug 2014 - v1.03 + Added translations for Polish, German and Russian. Many thanks to the translators! + Added Startup Folder options + Added Brightness and Contrast controls + Added Scale Image feature + Added option to show image name in full screen + Can now show/hide thumbnail labels in Classic and Compact modes + Added menu for docks and toolbars visibility + Improved rename dialog + Optimizations to thumbnail layouts + Fixed zooming with mouse wheel direction + Fixes thumbnails sorting case sensitivity + Fixes to menu visibility in Ubuntu + Fixes to Slide show + Many more small bug fixes ##### 14 Jul 2014 - v1.01 + Fixed image saving failure in some cases + Fixed tool bars and docks non persistent visibility state ##### 12 Jul 2014 - v1.00 + Thumbnails can be loaded and browsed recursively on a folder tree + Thumbnails are now loaded dynamically, enabling browsing very large folders + Enhancements to thumbnails filtering + Added "Copy/Move Images to..." Dialog + Can now open image with multiple external programs + Added customization for mouse behavior + Added Show Hidden Files option + Enhancements to crop dialog + Image zooming can now be controlled with mouse wheel+ctrl key + Enhancements to thumbnails loading UX + Fixes to slide show starting offset + Fixed file management issues + Fixed issues with docks state not being saved + Fixed issue with window size when exiting Phototonic while in full screen + Fixed invalid image movement when moving with keyboard ##### 17 May 2014 - v0.99 + Images can+ now be rotated freely to any angle + Added file name filtering option + Added Exif support (Exiv2 is now a dependency), metadata retained when saving images + New Image features: New Image, Copy and Paste image data + File system tree and Image Info panes can now be removed or docked anywhere + Many other small fixes and enhancements + ##### 27 Apr 2014 - v0.98 + New Colors dialog with Hue and Saturation settings + Added support for animated GIFs + Large images can now be moved around with keyboard as well as the mouse + Added notifications while in viewer ##### 11 Apr 2014 - v0.97 + Moved to Qt5 + Fixed missing icons when not in a DE + Added additional image info in status and title bars ##### 29 Mar 2014 - v0.96 + Fixed thumbnails navigation usability issues ##### 28 Mar 2014 - v0.95 + Added Open with external application option and other enhancements ##### 25 Mar 2014 - v0.94 + Icons now loaded from theme. + Added Copy Image option. ##### 22 Mar 2014 - v0.93 + Added keyboard shortcuts customization + Fixed issues related to image formats + New web site, under construction phototonic-2.1/ImagePreview.cpp000066400000000000000000000070661325127642100166460ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "ImagePreview.h" #include "Settings.h" #include "ThumbsViewer.h" ImagePreview::ImagePreview(QWidget *parent) : QWidget(parent) { imageLabel = new QLabel; imageLabel->setScaledContents(true); scrollArea = new QScrollArea; scrollArea->setContentsMargins(0, 0, 0, 0); scrollArea->setAlignment(Qt::AlignCenter); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea->verticalScrollBar()->blockSignals(true); scrollArea->horizontalScrollBar()->blockSignals(true); scrollArea->setFrameStyle(0); scrollArea->setWidget(imageLabel); scrollArea->setWidgetResizable(true); QHBoxLayout *mainLayout = new QHBoxLayout(); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); mainLayout->addWidget(scrollArea); setBackgroundColor(); setLayout(mainLayout); } QPixmap& ImagePreview::loadImage(QString imageFileName) { QImageReader imageReader(imageFileName); if (imageReader.size().isValid()) { QSize resize = imageReader.size(); resize.scale(QSize(imageLabel->width(), imageLabel->height()), Qt::KeepAspectRatio); QImage previewImage; imageReader.read(&previewImage); if (Settings::exifRotationEnabled) { imageViewer->rotateByExifRotation(previewImage, imageFileName); } previewPixmap = QPixmap::fromImage(previewImage); } else { previewPixmap = QIcon::fromTheme("image-missing", QIcon(":/images/error_image.png")).pixmap(BAD_IMAGE_SIZE, BAD_IMAGE_SIZE); } imageLabel->setPixmap(previewPixmap); resizeImagePreview(); return previewPixmap; } void ImagePreview::clear() { imageLabel->clear(); } void ImagePreview::resizeImagePreview() { const QPixmap *pixmap = imageLabel->pixmap(); if (!pixmap) { return; } QSize previewSizePixmap = pixmap->size(); if (previewSizePixmap.width() > scrollArea->width() || previewSizePixmap.height() > scrollArea->height()) { previewSizePixmap.scale(scrollArea->width(), scrollArea->height(), Qt::KeepAspectRatio); } imageLabel->setFixedSize(previewSizePixmap); imageLabel->adjustSize(); } void ImagePreview::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); resizeImagePreview(); } void ImagePreview::setBackgroundColor() { QString bgColor = "background: rgb(%1, %2, %3); "; bgColor = bgColor.arg(Settings::thumbsBackgroundColor.red()) .arg(Settings::thumbsBackgroundColor.green()).arg(Settings::thumbsBackgroundColor.blue()); QString ss = "QWidget { " + bgColor + " }"; scrollArea->setStyleSheet(ss); } void ImagePreview::setImageViewer(ImageViewer *imageViewer) { this->imageViewer = imageViewer; } phototonic-2.1/ImagePreview.h000066400000000000000000000025041325127642100163030ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef IMAGE_PREVIEW_H #define IMAGE_PREVIEW_H #include #include "ImageViewer.h" class ImagePreview : public QWidget { Q_OBJECT public: ImagePreview(QWidget *parent); QPixmap &loadImage(QString imageFileName); void resizeImagePreview(); void setBackgroundColor(); void clear(); void setImageViewer(ImageViewer *imageViewer); QScrollArea *scrollArea; protected: void resizeEvent(QResizeEvent *event); private: QLabel *imageLabel; QPixmap previewPixmap; ImageViewer *imageViewer; }; #endif // IMAGE_PREVIEW_H phototonic-2.1/ImageViewer.cpp000066400000000000000000001061531325127642100164630ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov - oferkv@live.com * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "ImageViewer.h" #include "Phototonic.h" #include "MessageBox.h" #define CLIPBOARD_IMAGE_NAME "clipboard.png" #define ROUND(x) ((int) ((x) + 0.5)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) ImageViewer::ImageViewer(QWidget *parent, MetadataCache *metadataCache) : QWidget(parent) { this->phototonic = (Phototonic *) parent; this->metadataCache = metadataCache; cursorIsHidden = false; moveImageLocked = false; mirrorLayout = LayNone; imageLabel = new QLabel; imageLabel->setScaledContents(true); isAnimation = false; animation = nullptr; scrollArea = new QScrollArea; scrollArea->setContentsMargins(0, 0, 0, 0); scrollArea->setAlignment(Qt::AlignCenter); scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea->verticalScrollBar()->blockSignals(true); scrollArea->horizontalScrollBar()->blockSignals(true); scrollArea->setFrameStyle(0); scrollArea->setWidget(imageLabel); scrollArea->setWidgetResizable(true); setBackgroundColor(); QVBoxLayout *scrollLayout = new QVBoxLayout; scrollLayout->setContentsMargins(0, 0, 0, 0); scrollLayout->setSpacing(0); scrollLayout->addWidget(scrollArea); this->setLayout(scrollLayout); imageInfoLabel = new QLabel(this); imageInfoLabel->setVisible(Settings::showImageName); imageInfoLabel->setMargin(3); imageInfoLabel->move(10, 10); imageInfoLabel->setStyleSheet("QLabel { background-color : black; color : white; border-radius: 3px} "); feedbackLabel = new QLabel(this); feedbackLabel->setVisible(false); feedbackLabel->setMargin(3); feedbackLabel->setStyleSheet("QLabel { background-color : black; color : white; border-radius: 3px} "); QGraphicsOpacityEffect *infoEffect = new QGraphicsOpacityEffect; infoEffect->setOpacity(0.5); imageInfoLabel->setGraphicsEffect(infoEffect); QGraphicsOpacityEffect *feedbackEffect = new QGraphicsOpacityEffect; feedbackEffect->setOpacity(0.5); feedbackLabel->setGraphicsEffect(feedbackEffect); mouseMovementTimer = new QTimer(this); connect(mouseMovementTimer, SIGNAL(timeout()), this, SLOT(monitorCursorState())); Settings::cropLeft = Settings::cropTop = Settings::cropWidth = Settings::cropHeight = 0; Settings::cropLeftPercent = Settings::cropTopPercent = Settings::cropWidthPercent = Settings::cropHeightPercent = 0; Settings::hueVal = 0; Settings::saturationVal = 100; Settings::lightnessVal = 100; Settings::hueRedChannel = true; Settings::hueGreenChannel = true; Settings::hueBlueChannel = true; Settings::contrastVal = 78; Settings::brightVal = 100; Settings::dialogLastX = Settings::dialogLastY = 0; newImage = false; cropRubberBand = 0; } static unsigned int getHeightByWidth(int imgWidth, int imgHeight, int newWidth) { float aspect; aspect = (float) imgWidth / (float) newWidth; return (imgHeight / aspect); } static unsigned int getWidthByHeight(int imgHeight, int imgWidth, int newHeight) { float aspect; aspect = (float) imgHeight / (float) newHeight; return (imgWidth / aspect); } static inline int calcZoom(int size) { return size * Settings::imageZoomFactor; } void ImageViewer::resizeImage() { static bool busy = false; if (busy || (!imageLabel->pixmap() && !animation)) { return; } busy = true; int imageViewWidth = this->size().width(); int imageViewHeight = this->size().height(); QSize imageSize = isAnimation ? animation->currentPixmap().size() : imageLabel->pixmap()->size(); if (tempDisableResize) { imageSize.scale(imageSize.width(), imageSize.height(), Qt::KeepAspectRatio); } else { switch (Settings::zoomInFlags) { case Disable: if (imageSize.width() <= imageViewWidth && imageSize.height() <= imageViewHeight) { imageSize.scale(calcZoom(imageSize.width()), calcZoom(imageSize.height()), Qt::KeepAspectRatio); } break; case WidthAndHeight: if (imageSize.width() <= imageViewWidth && imageSize.height() <= imageViewHeight) { imageSize.scale(calcZoom(imageViewWidth), calcZoom(imageViewHeight), Qt::KeepAspectRatio); } break; case Width: if (imageSize.width() <= imageViewWidth) { imageSize.scale(calcZoom(imageViewWidth), calcZoom(getHeightByWidth(imageSize.width(), imageSize.height(), imageViewWidth)), Qt::KeepAspectRatio); } break; case Height: if (imageSize.height() <= imageViewHeight) { imageSize.scale(calcZoom(getWidthByHeight(imageSize.height(), imageSize.width(), imageViewHeight)), calcZoom(imageViewHeight), Qt::KeepAspectRatio); } break; case Disprop: int newWidth = imageSize.width(), newHeight = imageSize.height(); if (newWidth <= imageViewWidth) { newWidth = imageViewWidth; } if (newHeight <= imageViewHeight) { newHeight = imageViewHeight; } imageSize.scale(calcZoom(newWidth), calcZoom(newHeight), Qt::IgnoreAspectRatio); break; } switch (Settings::zoomOutFlags) { case Disable: if (imageSize.width() >= imageViewWidth || imageSize.height() >= imageViewHeight) { imageSize.scale(calcZoom(imageSize.width()), calcZoom(imageSize.height()), Qt::KeepAspectRatio); } break; case WidthAndHeight: if (imageSize.width() >= imageViewWidth || imageSize.height() >= imageViewHeight) { imageSize.scale(calcZoom(imageViewWidth), calcZoom(imageViewHeight), Qt::KeepAspectRatio); } break; case Width: if (imageSize.width() >= imageViewWidth) { imageSize.scale(calcZoom(imageViewWidth), calcZoom(getHeightByWidth(imageSize.width(), imageSize.height(), imageViewWidth)), Qt::KeepAspectRatio); } break; case Height: if (imageSize.height() >= imageViewHeight) { imageSize.scale(calcZoom(getWidthByHeight(imageSize.height(), imageSize.width(), imageViewHeight)), calcZoom(imageViewHeight), Qt::KeepAspectRatio); } break; case Disprop: int newWidth = imageSize.width(), newHeight = imageSize.height(); if (newWidth >= imageViewWidth) { newWidth = imageViewWidth; } if (newHeight >= imageViewHeight) { newHeight = imageViewHeight; } imageSize.scale(calcZoom(newWidth), calcZoom(newHeight), Qt::IgnoreAspectRatio); break; } } imageLabel->setFixedSize(imageSize); imageLabel->adjustSize(); centerImage(imageSize); busy = false; } void ImageViewer::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); resizeImage(); } void ImageViewer::showEvent(QShowEvent *event) { QWidget::showEvent(event); resizeImage(); } void ImageViewer::centerImage(QSize &imgSize) { int newX = (this->size().width() - imgSize.width()) / 2; int newY = (this->size().height() - imgSize.height()) / 2; if (newX != imageLabel->pos().x() || newY != imageLabel->pos().y()) { imageLabel->move(newX, newY); } } void ImageViewer::rotateByExifRotation(QImage &image, QString &imageFullPath) { QTransform trans; long orientation = metadataCache->getImageOrientation(imageFullPath); switch (orientation) { case 1: break; case 2: image = image.mirrored(true, false); break; case 3: trans.rotate(180); image = image.transformed(trans, Qt::SmoothTransformation); break; case 4: image = image.mirrored(false, true); break; case 5: trans.rotate(90); image = image.transformed(trans, Qt::SmoothTransformation); image = image.mirrored(true, false); break; case 6: trans.rotate(90); image = image.transformed(trans, Qt::SmoothTransformation); break; case 7: trans.rotate(90); image = image.transformed(trans, Qt::SmoothTransformation); image = image.mirrored(false, true); break; case 8: trans.rotate(270); image = image.transformed(trans, Qt::SmoothTransformation); break; default: break; } } void ImageViewer::transform() { if (Settings::exifRotationEnabled) { rotateByExifRotation(viewerImage, viewerImageFullPath); } if (Settings::rotation) { QTransform trans; trans.rotate(Settings::rotation); viewerImage = viewerImage.transformed(trans, Qt::SmoothTransformation); } if (Settings::flipH || Settings::flipV) { viewerImage = viewerImage.mirrored(Settings::flipH, Settings::flipV); } int cropLeftPercentPixels = 0, cropTopPercentPixels = 0, cropWidthPercentPixels = 0, cropHeightPercentPixels = 0; bool croppingOn = false; if (Settings::cropLeftPercent || Settings::cropTopPercent || Settings::cropWidthPercent || Settings::cropHeightPercent) { croppingOn = true; cropLeftPercentPixels = (viewerImage.width() * Settings::cropLeftPercent) / 100; cropTopPercentPixels = (viewerImage.height() * Settings::cropTopPercent) / 100; cropWidthPercentPixels = (viewerImage.width() * Settings::cropWidthPercent) / 100; cropHeightPercentPixels = (viewerImage.height() * Settings::cropHeightPercent) / 100; } if (Settings::cropLeft || Settings::cropTop || Settings::cropWidth || Settings::cropHeight) { viewerImage = viewerImage.copy( Settings::cropLeft + cropLeftPercentPixels, Settings::cropTop + cropTopPercentPixels, viewerImage.width() - Settings::cropLeft - Settings::cropWidth - cropLeftPercentPixels - cropWidthPercentPixels, viewerImage.height() - Settings::cropTop - Settings::cropHeight - cropTopPercentPixels - cropHeightPercentPixels); } else { if (croppingOn) { viewerImage = viewerImage.copy( cropLeftPercentPixels, cropTopPercentPixels, viewerImage.width() - cropLeftPercentPixels - cropWidthPercentPixels, viewerImage.height() - cropTopPercentPixels - cropHeightPercentPixels); } } } void ImageViewer::mirror() { switch (mirrorLayout) { case LayDual: { mirrorImage = QImage(viewerImage.width() * 2, viewerImage.height(), QImage::Format_ARGB32); QPainter painter(&mirrorImage); painter.drawImage(0, 0, viewerImage); painter.drawImage(viewerImage.width(), 0, viewerImage.mirrored(true, false)); break; } case LayTriple: { mirrorImage = QImage(viewerImage.width() * 3, viewerImage.height(), QImage::Format_ARGB32); QPainter painter(&mirrorImage); painter.drawImage(0, 0, viewerImage); painter.drawImage(viewerImage.width(), 0, viewerImage.mirrored(true, false)); painter.drawImage(viewerImage.width() * 2, 0, viewerImage.mirrored(false, false)); break; } case LayQuad: { mirrorImage = QImage(viewerImage.width() * 2, viewerImage.height() * 2, QImage::Format_ARGB32); QPainter painter(&mirrorImage); painter.drawImage(0, 0, viewerImage); painter.drawImage(viewerImage.width(), 0, viewerImage.mirrored(true, false)); painter.drawImage(0, viewerImage.height(), viewerImage.mirrored(false, true)); painter.drawImage(viewerImage.width(), viewerImage.height(), viewerImage.mirrored(true, true)); break; } case LayVDual: { mirrorImage = QImage(viewerImage.width(), viewerImage.height() * 2, QImage::Format_ARGB32); QPainter painter(&mirrorImage); painter.drawImage(0, 0, viewerImage); painter.drawImage(0, viewerImage.height(), viewerImage.mirrored(false, true)); break; } } viewerImage = mirrorImage; } static inline int bound0To255(int val) { return ((val > 255) ? 255 : (val < 0) ? 0 : val); } static inline int hslValue(double n1, double n2, double hue) { double value; if (hue > 255) { hue -= 255; } else if (hue < 0) { hue += 255; } if (hue < 42.5) { value = n1 + (n2 - n1) * (hue / 42.5); } else if (hue < 127.5) { value = n2; } else if (hue < 170) { value = n1 + (n2 - n1) * ((170 - hue) / 42.5); } else { value = n1; } return ROUND(value * 255.0); } void rgbToHsl(int r, int g, int b, unsigned char *hue, unsigned char *sat, unsigned char *light) { double h, s, l; int min, max; int delta; if (r > g) { max = MAX(r, b); min = MIN(g, b); } else { max = MAX(g, b); min = MIN(r, b); } l = (max + min) / 2.0; if (max == min) { s = 0.0; h = 0.0; } else { delta = (max - min); if (l < 128) { s = 255 * (double) delta / (double) (max + min); } else { s = 255 * (double) delta / (double) (511 - max - min); } if (r == max) { h = (g - b) / (double) delta; } else if (g == max) { h = 2 + (b - r) / (double) delta; } else { h = 4 + (r - g) / (double) delta; } h = h * 42.5; if (h < 0) { h += 255; } else if (h > 255) { h -= 255; } } *hue = ROUND(h); *sat = ROUND(s); *light = ROUND(l); } void hslToRgb(double h, double s, double l, unsigned char *red, unsigned char *green, unsigned char *blue) { if (s == 0) { /* achromatic case */ *red = l; *green = l; *blue = l; } else { double m1, m2; if (l < 128) m2 = (l * (255 + s)) / 65025.0; else m2 = (l + s - (l * s) / 255.0) / 255.0; m1 = (l / 127.5) - m2; /* chromatic case */ *red = hslValue(m1, m2, h + 85); *green = hslValue(m1, m2, h); *blue = hslValue(m1, m2, h - 85); } } void ImageViewer::colorize() { int y, x; unsigned char hr, hg, hb; int r, g, b; QRgb *line; unsigned char h, s, l; static unsigned char contrastTransform[256]; static unsigned char brightTransform[256]; bool hasAlpha = viewerImage.hasAlphaChannel(); if (viewerImage.colorCount()) { viewerImage = viewerImage.convertToFormat(QImage::Format_RGB32); } int i; float contrast = ((float) Settings::contrastVal / 100.0); float brightness = ((float) Settings::brightVal / 100.0); for (i = 0; i < 256; ++i) { if (i < (int) (128.0f + 128.0f * tan(contrast)) && i > (int) (128.0f - 128.0f * tan(contrast))) { contrastTransform[i] = (i - 128) / tan(contrast) + 128; } else if (i >= (int) (128.0f + 128.0f * tan(contrast))) { contrastTransform[i] = 255; } else { contrastTransform[i] = 0; } } for (i = 0; i < 256; ++i) { brightTransform[i] = MIN(255, (int) ((255.0 * pow(i / 255.0, 1.0 / brightness)) + 0.5)); } for (y = 0; y < viewerImage.height(); ++y) { line = (QRgb *) viewerImage.scanLine(y); for (x = 0; x < viewerImage.width(); ++x) { r = Settings::rNegateEnabled ? bound0To255(255 - qRed(line[x])) : qRed(line[x]); g = Settings::gNegateEnabled ? bound0To255(255 - qGreen(line[x])) : qGreen(line[x]); b = Settings::bNegateEnabled ? bound0To255(255 - qBlue(line[x])) : qBlue(line[x]); r = bound0To255((r * (Settings::redVal + 100)) / 100); g = bound0To255((g * (Settings::greenVal + 100)) / 100); b = bound0To255((b * (Settings::blueVal + 100)) / 100); r = bound0To255(brightTransform[r]); g = bound0To255(brightTransform[g]); b = bound0To255(brightTransform[b]); r = bound0To255(contrastTransform[r]); g = bound0To255(contrastTransform[g]); b = bound0To255(contrastTransform[b]); rgbToHsl(r, g, b, &h, &s, &l); h = Settings::colorizeEnabled ? Settings::hueVal : h + Settings::hueVal; s = bound0To255(((s * Settings::saturationVal) / 100)); l = bound0To255(((l * Settings::lightnessVal) / 100)); hslToRgb(h, s, l, &hr, &hg, &hb); r = Settings::hueRedChannel ? hr : qRed(line[x]); g = Settings::hueGreenChannel ? hg : qGreen(line[x]); b = Settings::hueBlueChannel ? hb : qBlue(line[x]); if (hasAlpha) { line[x] = qRgba(r, g, b, qAlpha(line[x])); } else { line[x] = qRgb(r, g, b); } } } } void ImageViewer::refresh() { if (isAnimation) { return; } if (Settings::scaledWidth) { viewerImage = origImage.scaled(Settings::scaledWidth, Settings::scaledHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } else { viewerImage = origImage; } transform(); if (Settings::colorsActive || Settings::keepTransform) { colorize(); } if (mirrorLayout) { mirror(); } viewerPixmap = QPixmap::fromImage(viewerImage); imageLabel->setPixmap(viewerPixmap); resizeImage(); } QImage createImageWithOverlay(const QImage &baseImage, const QImage &overlayImage, int x, int y) { QImage imageWithOverlay = QImage(overlayImage.size(), QImage::Format_ARGB32_Premultiplied); QPainter painter(&imageWithOverlay); QImage scaledImage = baseImage.scaled(overlayImage.width(), overlayImage.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.fillRect(imageWithOverlay.rect(), Qt::transparent); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.drawImage(x, y, scaledImage); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.drawImage(0, 0, overlayImage); painter.end(); return imageWithOverlay; } void ImageViewer::reload() { isAnimation = false; if (Settings::showImageName) { if (viewerImageFullPath.left(1) == ":") { setInfo("No Image"); } else if (viewerImageFullPath.isEmpty()) { setInfo("Clipboard"); } else { setInfo(QFileInfo(viewerImageFullPath).fileName()); } } if (!Settings::keepTransform) { Settings::cropLeftPercent = Settings::cropTopPercent = Settings::cropWidthPercent = Settings::cropHeightPercent = 0; Settings::rotation = 0; Settings::flipH = Settings::flipV = false; } Settings::scaledWidth = Settings::scaledHeight = 0; Settings::cropLeft = Settings::cropTop = Settings::cropWidth = Settings::cropHeight = 0; if (newImage || viewerImageFullPath.isEmpty()) { newImage = true; viewerImageFullPath = CLIPBOARD_IMAGE_NAME; origImage.load(":/images/no_image.png"); viewerImage = origImage; viewerPixmap = QPixmap::fromImage(viewerImage); imageLabel->setPixmap(viewerPixmap); pasteImage(); return; } QImageReader imageReader(viewerImageFullPath); if (Settings::enableAnimations && imageReader.supportsAnimation()) { if (animation) { delete animation; } animation = new QMovie(viewerImageFullPath); if (animation->frameCount() > 1) { isAnimation = true; imageLabel->setMovie(animation); animation->start(); resizeImage(); return; } } if (imageReader.size().isValid() && imageReader.read(&origImage)) { viewerImage = origImage; transform(); if (Settings::colorsActive || Settings::keepTransform) { colorize(); } if (mirrorLayout) { mirror(); } viewerPixmap = QPixmap::fromImage(viewerImage); } else { viewerPixmap = QIcon::fromTheme("image-missing", QIcon(":/images/error_image.png")).pixmap(BAD_IMAGE_SIZE, BAD_IMAGE_SIZE); setInfo(imageReader.errorString()); } imageLabel->setPixmap(viewerPixmap); resizeImage(); if (Settings::setWindowIcon) { phototonic->setWindowIcon(viewerPixmap.scaled(WINDOW_ICON_SIZE, WINDOW_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } } void ImageViewer::setInfo(QString infoString) { imageInfoLabel->setText(infoString); imageInfoLabel->adjustSize(); } void ImageViewer::unsetFeedback() { feedbackLabel->clear(); feedbackLabel->setVisible(false); } void ImageViewer::setFeedback(QString feedbackString) { feedbackLabel->setText(feedbackString); feedbackLabel->setVisible(true); int margin = imageInfoLabel->isVisible() ? (imageInfoLabel->height() + 15) : 10; feedbackLabel->move(10, margin); feedbackLabel->adjustSize(); QTimer::singleShot(3000, this, SLOT(unsetFeedback())); } void ImageViewer::loadImage(QString imageFileName) { newImage = false; tempDisableResize = false; viewerImageFullPath = imageFileName; if (!Settings::keepZoomFactor) { Settings::imageZoomFactor = 1.0; } QApplication::processEvents(); reload(); } void ImageViewer::clearImage() { origImage.load(":/images/no_image.png"); viewerImage = origImage; viewerPixmap = QPixmap::fromImage(viewerImage); imageLabel->setPixmap(viewerPixmap); } void ImageViewer::monitorCursorState() { static QPoint lastPos; if (QCursor::pos() != lastPos) { lastPos = QCursor::pos(); if (cursorIsHidden) { QApplication::restoreOverrideCursor(); cursorIsHidden = false; } } else { if (!cursorIsHidden) { QApplication::setOverrideCursor(Qt::BlankCursor); cursorIsHidden = true; } } } void ImageViewer::setCursorHiding(bool hide) { if (hide) { mouseMovementTimer->start(500); } else { mouseMovementTimer->stop(); if (cursorIsHidden) { QApplication::restoreOverrideCursor(); cursorIsHidden = false; } } } void ImageViewer::mouseDoubleClickEvent(QMouseEvent *event) { QWidget::mouseDoubleClickEvent(event); while (QApplication::overrideCursor()) { QApplication::restoreOverrideCursor(); } } void ImageViewer::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { if (event->modifiers() == Qt::ControlModifier) { cropOrigin = event->pos(); if (!cropRubberBand) { cropRubberBand = new CropRubberBand(this); } cropRubberBand->show(); cropRubberBand->setGeometry(QRect(cropOrigin, event->pos()).normalized()); } else { if (cropRubberBand) { cropRubberBand->hide(); } } setMouseMoveData(true, event->x(), event->y()); QApplication::setOverrideCursor(Qt::ClosedHandCursor); event->accept(); } QWidget::mousePressEvent(event); } void ImageViewer::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { setMouseMoveData(false, 0, 0); while (QApplication::overrideCursor()) { QApplication::restoreOverrideCursor(); } if (cropRubberBand && cropRubberBand->isVisible()) { setFeedback(tr("Selection size: ") + QString::number(cropRubberBand->width()) + "x" + QString::number(cropRubberBand->height())); } } QWidget::mouseReleaseEvent(event); } void ImageViewer::cropToSelection() { if (cropRubberBand && cropRubberBand->isVisible()) { QPoint bandTopLeft = mapToGlobal(cropRubberBand->geometry().topLeft()); QPoint bandBottomRight = mapToGlobal(cropRubberBand->geometry().bottomRight()); bandTopLeft = imageLabel->mapFromGlobal(bandTopLeft); bandBottomRight = imageLabel->mapFromGlobal(bandBottomRight); double scaledX = imageLabel->rect().width(); double scaledY = imageLabel->rect().height(); scaledX = viewerPixmap.width() / scaledX; scaledY = viewerPixmap.height() / scaledY; bandTopLeft.setX(int(bandTopLeft.x() * scaledX)); bandTopLeft.setY(int(bandTopLeft.y() * scaledY)); bandBottomRight.setX(int(bandBottomRight.x() * scaledX)); bandBottomRight.setY(int(bandBottomRight.y() * scaledY)); int cropLeft = bandTopLeft.x(); int cropTop = bandTopLeft.y(); int cropWidth = viewerPixmap.width() - bandBottomRight.x(); int cropHeight = viewerPixmap.height() - bandBottomRight.y(); if (cropLeft > 0) { Settings::cropLeft += cropLeft; } if (cropTop > 0) { Settings::cropTop += cropTop; } if (cropWidth > 0) { Settings::cropWidth += cropWidth; } if (cropHeight > 0) { Settings::cropHeight += cropHeight; } cropRubberBand->hide(); refresh(); } else { MessageBox messageBox(this); messageBox.warning(tr("No selection for cropping"), tr("To make a selection, hold down the Ctrl key and select a region using the mouse.")); } } void ImageViewer::setMouseMoveData(bool lockMove, int lMouseX, int lMouseY) { moveImageLocked = lockMove; mouseX = lMouseX; mouseY = lMouseY; layoutX = imageLabel->pos().x(); layoutY = imageLabel->pos().y(); } void ImageViewer::mouseMoveEvent(QMouseEvent *event) { if (event->modifiers() == Qt::ControlModifier) { if (cropRubberBand && cropRubberBand->isVisible()) { cropRubberBand->setGeometry(QRect(cropOrigin, event->pos()).normalized()); } } else { if (moveImageLocked) { int newX = layoutX + (event->pos().x() - mouseX); int newY = layoutY + (event->pos().y() - mouseY); bool needToMove = false; if (imageLabel->size().width() > size().width()) { if (newX > 0) { newX = 0; } else if (newX < (size().width() - imageLabel->size().width())) { newX = (size().width() - imageLabel->size().width()); } needToMove = true; } else { newX = layoutX; } if (imageLabel->size().height() > size().height()) { if (newY > 0) { newY = 0; } else if (newY < (size().height() - imageLabel->size().height())) { newY = (size().height() - imageLabel->size().height()); } needToMove = true; } else { newY = layoutY; } if (needToMove) { imageLabel->move(newX, newY); } } } } void ImageViewer::keyMoveEvent(int direction) { int newX = layoutX = imageLabel->pos().x(); int newY = layoutY = imageLabel->pos().y(); bool needToMove = false; switch (direction) { case MoveLeft: newX += 50; break; case MoveRight: newX -= 50; break; case MoveUp: newY += 50; break; case MoveDown: newY -= 50; break; } if (imageLabel->size().width() > size().width()) { if (newX > 0) { newX = 0; } else if (newX < (size().width() - imageLabel->size().width())) { newX = (size().width() - imageLabel->size().width()); } needToMove = true; } else { newX = layoutX; } if (imageLabel->size().height() > size().height()) { if (newY > 0) { newY = 0; } else if (newY < (size().height() - imageLabel->size().height())) { newY = (size().height() - imageLabel->size().height()); } needToMove = true; } else { newY = layoutY; } if (needToMove) { int i; switch (direction) { case MoveLeft: for (i = imageLabel->pos().x(); i <= newX; ++i) imageLabel->move(newX, newY); break; case MoveRight: for (i = imageLabel->pos().x(); i >= newX; --i) imageLabel->move(newX, newY); break; case MoveUp: for (i = imageLabel->pos().y(); i <= newY; ++i) imageLabel->move(newX, newY); break; case MoveDown: for (i = imageLabel->pos().y(); i >= newY; --i) imageLabel->move(newX, newY); break; } } } void ImageViewer::saveImage() { Exiv2::Image::AutoPtr image; bool exifError = false; if (newImage) { saveImageAs(); return; } setFeedback(tr("Saving...")); try { image = Exiv2::ImageFactory::open(viewerImageFullPath.toStdString()); image->readMetadata(); } catch (Exiv2::Error &error) { exifError = true; } QImageReader imageReader(viewerImageFullPath); if (!viewerPixmap.save(viewerImageFullPath, imageReader.format().toUpper(), Settings::defaultSaveQuality)) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to save image.")); return; } if (!exifError) { try { image->writeMetadata(); } catch (Exiv2::Error &error) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to save Exif metadata.")); } } reload(); setFeedback(tr("Image saved.")); } void ImageViewer::saveImageAs() { Exiv2::Image::AutoPtr exifImage; Exiv2::Image::AutoPtr newExifImage; bool exifError = false; setCursorHiding(false); QString fileName = QFileDialog::getSaveFileName(this, tr("Save image as"), viewerImageFullPath, tr("Images") + " (*.jpg *.jpeg *.png *.bmp *.tif *.tiff *.ppm *.pgm *.pbm *.xbm *.xpm *.cur *.ico *.icns *.wbmp *.webp)"); if (!fileName.isEmpty()) { try { exifImage = Exiv2::ImageFactory::open(viewerImageFullPath.toStdString()); exifImage->readMetadata(); } catch (Exiv2::Error &error) { exifError = true; } if (!viewerPixmap.save(fileName, 0, Settings::defaultSaveQuality)) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to save image.")); } else { if (!exifError) { try { newExifImage = Exiv2::ImageFactory::open(fileName.toStdString()); newExifImage->setMetadata(*exifImage); newExifImage->writeMetadata(); } catch (Exiv2::Error &error) { exifError = true; } } setFeedback(tr("Image saved.")); } } if (phototonic->isFullScreen()) { setCursorHiding(true); } } void ImageViewer::contextMenuEvent(QContextMenuEvent *) { while (QApplication::overrideCursor()) { QApplication::restoreOverrideCursor(); } ImagePopUpMenu->exec(QCursor::pos()); } int ImageViewer::getImageWidthPreCropped() { return origImage.width(); } int ImageViewer::getImageHeightPreCropped() { return origImage.height(); } bool ImageViewer::isNewImage() { return newImage; } void ImageViewer::copyImage() { QApplication::clipboard()->setImage(viewerImage); } void ImageViewer::pasteImage() { if (isAnimation) { return; } if (!QApplication::clipboard()->image().isNull()) { origImage = QApplication::clipboard()->image(); refresh(); } phototonic->setWindowTitle(tr("Clipboard") + " - Phototonic"); if (Settings::setWindowIcon) { phototonic->setWindowIcon(phototonic->getDefaultWindowIcon()); } } void ImageViewer::setBackgroundColor() { QString bgColor = "background: rgb(%1, %2, %3); "; bgColor = bgColor.arg(Settings::viewerBackgroundColor.red()) .arg(Settings::viewerBackgroundColor.green()) .arg(Settings::viewerBackgroundColor.blue()); QString styleSheet = "QWidget { " + bgColor + " }"; scrollArea->setStyleSheet(styleSheet); } phototonic-2.1/ImageViewer.h000066400000000000000000000064371325127642100161340ustar00rootroot00000000000000/* * Copyright (C) 2013 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef IMAGE_VIEWER_H #define IMAGE_VIEWER_H #include #include #include "Settings.h" #include "CropRubberband.h" #include "MetadataCache.h" class Phototonic; class ImageViewer : public QWidget { Q_OBJECT public: bool tempDisableResize; int mirrorLayout; QString viewerImageFullPath; QMenu *ImagePopUpMenu; QScrollArea *scrollArea; QLabel *imageInfoLabel; CropRubberBand *cropRubberBand; enum ZoomMethods { Disable = 0, WidthAndHeight, Width, Height, Disprop }; enum MirrorLayouts { LayNone = 0, LayDual, LayTriple, LayQuad, LayVDual }; enum Movement { MoveUp = 0, MoveDown, MoveLeft, MoveRight }; ImageViewer(QWidget *parent, MetadataCache *metadataCache); void loadImage(QString imageFileName); void clearImage(); void resizeImage(); void setCursorHiding(bool hide); void refresh(); void reload(); int getImageWidthPreCropped(); int getImageHeightPreCropped(); bool isNewImage(); void keyMoveEvent(int direction); void rotateByExifRotation(QImage &image, QString &imageFullPath); void setInfo(QString infoString); void setFeedback(QString feedbackString); void setBackgroundColor(); public slots: void monitorCursorState(); void saveImage(); void saveImageAs(); void copyImage(); void pasteImage(); void cropToSelection(); private slots: void unsetFeedback(); protected: void resizeEvent(QResizeEvent *event); void showEvent(QShowEvent *event); void mouseMoveEvent(QMouseEvent *event); void contextMenuEvent(QContextMenuEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); private: Phototonic *phototonic; QLabel *imageLabel; QPixmap viewerPixmap; QImage origImage; QImage viewerImage; QImage mirrorImage; QTimer *mouseMovementTimer; QMovie *animation; bool newImage; bool cursorIsHidden; bool moveImageLocked; int mouseX; int mouseY; int layoutX; int layoutY; bool isAnimation; QLabel *feedbackLabel; QPoint cropOrigin; MetadataCache *metadataCache; void setMouseMoveData(bool lockMove, int lMouseX, int lMouseY); void centerImage(QSize &imgSize); void transform(); void mirror(); void colorize(); }; #endif // IMAGE_VIEWER_H phototonic-2.1/InfoViewer.cpp000066400000000000000000000076111325127642100163330ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "InfoViewer.h" #include "ThumbsViewer.h" InfoView::InfoView(QWidget *parent) : QWidget(parent) { infoViewerTable = new QTableView(); infoViewerTable->setSelectionMode(QAbstractItemView::ExtendedSelection); infoViewerTable->verticalHeader()->setVisible(false); infoViewerTable->verticalHeader()->setDefaultSectionSize(infoViewerTable->verticalHeader()->minimumSectionSize()); infoViewerTable->horizontalHeader()->setVisible(false); infoViewerTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); infoViewerTable->setEditTriggers(QAbstractItemView::NoEditTriggers); infoViewerTable->setSelectionBehavior(QAbstractItemView::SelectItems); infoViewerTable->setTabKeyNavigation(false); infoViewerTable->setShowGrid(false); imageInfoModel = new QStandardItemModel(this); infoViewerTable->setModel(imageInfoModel); // Menu QAction *copyAction = new QAction(tr("Copy"), this); infoViewerTable->connect(copyAction, SIGNAL(triggered()), this, SLOT(copyEntry())); infoMenu = new QMenu(""); infoMenu->addAction(copyAction); infoViewerTable->setContextMenuPolicy(Qt::CustomContextMenu); connect(infoViewerTable, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showInfoViewMenu(QPoint))); QVBoxLayout *infoViewerLayout = new QVBoxLayout; // Filter items filterLineEdit = new QLineEdit; connect(filterLineEdit, SIGNAL(textChanged( const QString&)), this, SLOT(filterItems())); filterLineEdit->setClearButtonEnabled(true); filterLineEdit->setPlaceholderText(tr("Filter Items")); infoViewerLayout->addWidget(filterLineEdit); infoViewerLayout->addWidget(infoViewerTable); infoViewerLayout->setContentsMargins(2, 2, 2, 2); infoViewerLayout->setSpacing(2); setLayout(infoViewerLayout); } void InfoView::showInfoViewMenu(QPoint pt) { selectedEntry = infoViewerTable->indexAt(pt); if (selectedEntry.isValid()) { infoMenu->popup(infoViewerTable->viewport()->mapToGlobal(pt)); } } void InfoView::clear() { imageInfoModel->clear(); } void InfoView::addEntry(QString &key, QString &value) { if (!filterLineEdit->text().isEmpty() && !key.toLower().contains(filterLineEdit->text().toLower())) { return; } int atRow = imageInfoModel->rowCount(); QStandardItem *itemKey = new QStandardItem(key); imageInfoModel->insertRow(atRow, itemKey); if (!value.isEmpty()) { QStandardItem *itemVal = new QStandardItem(value); itemVal->setToolTip(value); imageInfoModel->setItem(atRow, 1, itemVal); } } void InfoView::addTitleEntry(QString title) { int atRow = imageInfoModel->rowCount(); QStandardItem *itemKey = new QStandardItem(title); imageInfoModel->insertRow(atRow, itemKey); QFont boldFont; boldFont.setBold(true); itemKey->setData(boldFont, Qt::FontRole); } void InfoView::copyEntry() { if (selectedEntry.isValid()) { QApplication::clipboard()->setText(imageInfoModel->itemFromIndex(selectedEntry)->toolTip()); } } void InfoView::filterItems() { QItemSelection dummy; emit updateInfo(dummy); } phototonic-2.1/InfoViewer.h000066400000000000000000000025661325127642100160040ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef INFO_VIEWER_H #define INFO_VIEWER_H #include class InfoView : public QWidget { Q_OBJECT public: InfoView(QWidget *parent); void clear(); void addEntry(QString &key, QString &value); void addTitleEntry(QString title); signals: void updateInfo(QItemSelection dummy); public slots: void showInfoViewMenu(QPoint pt); void copyEntry(); private slots: void filterItems(); private: QTableView *infoViewerTable; QStandardItemModel *imageInfoModel; QModelIndex selectedEntry; QMenu *infoMenu; QLineEdit *filterLineEdit; }; #endif // INFO_VIEWER_H phototonic-2.1/MessageBox.cpp000066400000000000000000000101401325127642100163020ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "MessageBox.h" #include "Phototonic.h" MessageBox::MessageBox(QWidget *parent) : QMessageBox(parent) { setWindowIcon(QIcon(":/images/phototonic.png")); } void MessageBox::critical(const QString &title, const QString &message) { setWindowTitle(title); setText(message); setIcon(MessageBox::Critical); exec(); } void MessageBox::warning(const QString &title, const QString &message) { setWindowTitle(title); setText(message); setIcon(MessageBox::Warning); exec(); } void MessageBox::about() { QString aboutString = "

" + QString(VERSION) + "

" + tr("

Image Viewer and Organizer

") + "Qt v" + QT_VERSION_STR + "

" + tr("Home page") + "

" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
Code:Ofer Kashayov(oferkv@gmail.com)
Christopher Roy Bratusek(nano@jpberlin.de)
Krzysztof Pyrkosz(pyrkosz@o2.pl)
Roman Chistokhodov(freeslave93@gmail.com)
Thomas Lübking(thomas.luebking@gmail.com)
Tung Le(https://github.com/everbot)
Peter Mattern(https://github.com/pmattern)
Bosnian:Dino Duratović(dinomol@mail.com)
Croatian:Dino Duratović(dinomol@mail.com)
Czech:Pavel Fric(pavelfric@seznam.cz)
French:Adrien Daugabel(adrien.d@mageialinux-online.org)
David Geiger(david.david@mageialinux-online.org)
Rémi Verschelde(akien@mageia.org)
German:Jonathan Hooverman(jonathan.hooverman@gmail.com)
Polish:Robert Wojewódzki(robwoj44@poczta.onet.pl)
Krzysztof Pyrkosz(pyrkosz@o2.pl)
Portuguese:Marcos M. Nascimento(wstlmn@uol.com.br)
Russian:Ilya Alexandrovich(yast4ik@gmail.com)
Serbian:Dino Duratović(dinomol@mail.com)
" "

Phototonic is licensed under the GNU General Public License version 3

" "

Copyright © 2013-2018 Ofer Kashayov

"; setWindowTitle(tr("About")); setText(aboutString); setIconPixmap(QIcon(":/images/phototonic.png").pixmap(64, 64)); exec(); } phototonic-2.1/MessageBox.h000066400000000000000000000021361325127642100157550ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef MESSAGE_BOX_H #define MESSAGE_BOX_H #include class MessageBox : public QMessageBox { Q_OBJECT public: MessageBox(QWidget *parent); void critical(const QString &title, const QString &message); void warning(const QString &title, const QString &message); void about(); }; #endif // MESSAGE_BOX_H phototonic-2.1/MetadataCache.cpp000066400000000000000000000070001325127642100167120ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include "Settings.h" #include "MetadataCache.h" void MetadataCache::updateImageTags(QString &imageFileName, QSet tags) { cache[imageFileName].tags = tags; } bool MetadataCache::removeTagFromImage(QString &imageFileName, const QString &tagName) { return cache[imageFileName].tags.remove(tagName); } void MetadataCache::removeImage(QString &imageFileName) { cache.remove(imageFileName); } QSet &MetadataCache::getImageTags(QString &imageFileName) { return cache[imageFileName].tags; } long MetadataCache::getImageOrientation(QString &imageFileName) { if (cache.contains(imageFileName) || loadImageMetadata(imageFileName)) { return cache[imageFileName].orientation; } return 0; } void MetadataCache::setImageTags(const QString &imageFileName, QSet tags) { ImageMetadata imageMetadata; imageMetadata.tags = tags; cache.insert(imageFileName, imageMetadata); } void MetadataCache::addTagToImage(QString &imageFileName, QString &tagName) { if (cache[imageFileName].tags.contains(tagName)) { return; } cache[imageFileName].tags.insert(tagName); } void MetadataCache::clear() { cache.clear(); } bool MetadataCache::loadImageMetadata(const QString &imageFullPath) { Exiv2::Image::AutoPtr exifImage; QSet tags; long orientation = 0; try { exifImage = Exiv2::ImageFactory::open(imageFullPath.toStdString()); exifImage->readMetadata(); } catch (Exiv2::Error &error) { return false; } try { Exiv2::ExifData &exifData = exifImage->exifData(); if (!exifData.empty()) { orientation = exifData["Exif.Image.Orientation"].value().toLong(); } } catch (Exiv2::Error &error) { qWarning() << "Failed to read Exif metadata"; } try { Exiv2::IptcData &iptcData = exifImage->iptcData(); if (!iptcData.empty()) { QString key; Exiv2::IptcData::iterator end = iptcData.end(); for (Exiv2::IptcData::iterator iptcIt = iptcData.begin(); iptcIt != end; ++iptcIt) { if (iptcIt->tagName() == "Keywords") { QString tagName = QString::fromUtf8(iptcIt->toString().c_str()); tags.insert(tagName); Settings::knownTags.insert(tagName); } } } } catch (Exiv2::Error &error) { qWarning() << "Failed to read Iptc metadata"; } ImageMetadata imageMetadata; if (tags.size()) { imageMetadata.tags = tags; } if (orientation) { imageMetadata.orientation = orientation; } if (tags.size() || orientation) { cache.insert(imageFullPath, imageMetadata); } return true; } phototonic-2.1/MetadataCache.h000066400000000000000000000030401325127642100163570ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef META_DATA_CACHE_H #define META_DATA_CACHE_H #include class ImageMetadata { public: QSet tags; long orientation; }; class MetadataCache { private: QMap cache; public: void updateImageTags(QString &imageFileName, QSet tags); void addTagToImage(QString &imageFileName, QString &tagName); bool removeTagFromImage(QString &imageFileName, const QString &tagName); void removeImage(QString &imageFileName); QSet &getImageTags(QString &imageFileName); void setImageTags(const QString &imageFileName, QSet tags); void clear(); bool loadImageMetadata(const QString &imageFullPath); long getImageOrientation(QString &imageFileName); }; #endif // META_DATA_CACHE_H phototonic-2.1/Phototonic.cpp000066400000000000000000004113401325127642100164020ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "DirCompleter.h" #include "Phototonic.h" #include "Settings.h" #include "CopyMoveDialog.h" #include "ResizeDialog.h" #include "CropDialog.h" #include "ColorsDialog.h" #include "ExternalAppsDialog.h" #include "ProgressDialog.h" #include "ImagePreview.h" #include "FileListWidget.h" #include "RenameDialog.h" #include "Trashcan.h" #include "MessageBox.h" Phototonic::Phototonic(QStringList argumentsList, int filesStartAt, QWidget *parent) : QMainWindow(parent) { Settings::appSettings = new QSettings("phototonic", "phototonic"); setDockOptions(QMainWindow::AllowNestedDocks); readSettings(); createThumbsViewer(); createActions(); createMenus(); createToolBars(); createStatusBar(); createFileSystemDock(); createBookmarksDock(); createImagePreviewDock(); createImageTagsDock(); createImageViewer(); updateExternalApps(); loadShortcuts(); setupDocks(); connect(qApp, SIGNAL(focusChanged(QWidget * , QWidget * )), this, SLOT(updateActions())); restoreGeometry(Settings::appSettings->value(Settings::optionGeometry).toByteArray()); restoreState(Settings::appSettings->value(Settings::optionWindowState).toByteArray()); defaultApplicationIcon = QIcon(":/images/phototonic.png"); setWindowIcon(defaultApplicationIcon); stackedLayout = new QStackedLayout; QWidget *stackedLayoutWidget = new QWidget; stackedLayout->addWidget(thumbsViewer); stackedLayout->addWidget(imageViewer); stackedLayoutWidget->setLayout(stackedLayout); setCentralWidget(stackedLayoutWidget); processStartupArguments(argumentsList, filesStartAt); copyMoveToDialog = nullptr; colorsDialog = nullptr; cropDialog = nullptr; initComplete = true; thumbsViewer->isBusy = false; currentHistoryIdx = -1; needHistoryRecord = true; interfaceDisabled = false; refreshThumbs(true); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->setFocus(Qt::OtherFocusReason); } } void Phototonic::processStartupArguments(QStringList argumentsList, int filesStartAt) { if (argumentsList.size() > filesStartAt) { QFileInfo firstArgument(argumentsList.at(filesStartAt)); if (firstArgument.isDir()) { Settings::currentDirectory = argumentsList.at(filesStartAt); } else if (argumentsList.size() > filesStartAt + 1) { loadStartupFileList(argumentsList, filesStartAt); return; } else { Settings::currentDirectory = firstArgument.absolutePath(); QString cliFileName = Settings::currentDirectory + QDir::separator() + firstArgument.fileName(); loadImageFromCliArguments(cliFileName); QTimer::singleShot(1000, this, SLOT(updateIndexByViewerImage())); } } else { if (Settings::startupDir == Settings::SpecifiedDir) { Settings::currentDirectory = Settings::specifiedStartDir; } else if (Settings::startupDir == Settings::RememberLastDir) { Settings::currentDirectory = Settings::appSettings->value(Settings::optionLastDir).toString(); } } selectCurrentViewDir(); } QIcon &Phototonic::getDefaultWindowIcon() { return defaultApplicationIcon; } void Phototonic::loadStartupFileList(QStringList argumentsList, int filesStartAt) { Settings::filesList.clear(); for (int i = filesStartAt; i < argumentsList.size(); i++) { QFile currentFileFullPath(argumentsList[i]); QFileInfo currentFileInfo(currentFileFullPath); if (!Settings::filesList.contains(currentFileInfo.absoluteFilePath())) { Settings::filesList << currentFileInfo.absoluteFilePath(); } } fileSystemTree->clearSelection(); fileListWidget->setItemSelected(fileListWidget->itemAt(0, 0), true); Settings::isFileListLoaded = true; } bool Phototonic::event(QEvent *event) { if (event->type() == QEvent::ActivationChange || (Settings::layoutMode == ThumbViewWidget && event->type() == QEvent::MouseButtonRelease)) { thumbsViewer->loadVisibleThumbs(); } return QMainWindow::event(event); } void Phototonic::createThumbsViewer() { metadataCache = new MetadataCache; thumbsViewer = new ThumbsViewer(this, metadataCache); thumbsViewer->thumbsSortFlags = (QDir::SortFlags) Settings::appSettings->value( Settings::optionThumbsSortFlags).toInt(); thumbsViewer->thumbsSortFlags |= QDir::IgnoreCase; connect(thumbsViewer->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateActions())); imageInfoDock = new QDockWidget(tr("Image Info"), this); imageInfoDock->setObjectName("Image Info"); imageInfoDock->setWidget(thumbsViewer->infoView); connect(imageInfoDock->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setImageInfoDockVisibility())); connect(imageInfoDock, SIGNAL(visibilityChanged(bool)), this, SLOT(setImageInfoDockVisibility())); } void Phototonic::addMenuSeparator(QWidget *widget) { QAction *separator = new QAction(this); separator->setSeparator(true); widget->addAction(separator); } void Phototonic::createImageViewer() { imageViewer = new ImageViewer(this, metadataCache); connect(saveAction, SIGNAL(triggered()), imageViewer, SLOT(saveImage())); connect(saveAsAction, SIGNAL(triggered()), imageViewer, SLOT(saveImageAs())); connect(copyImageAction, SIGNAL(triggered()), imageViewer, SLOT(copyImage())); connect(pasteImageAction, SIGNAL(triggered()), imageViewer, SLOT(pasteImage())); connect(cropToSelectionAction, SIGNAL(triggered()), imageViewer, SLOT(cropToSelection())); imageViewer->ImagePopUpMenu = new QMenu(); // Widget actions imageViewer->addAction(slideShowAction); imageViewer->addAction(nextImageAction); imageViewer->addAction(prevImageAction); imageViewer->addAction(firstImageAction); imageViewer->addAction(lastImageAction); imageViewer->addAction(randomImageAction); imageViewer->addAction(zoomInAction); imageViewer->addAction(zoomOutAction); imageViewer->addAction(origZoomAction); imageViewer->addAction(resetZoomAction); imageViewer->addAction(rotateRightAction); imageViewer->addAction(rotateLeftAction); imageViewer->addAction(freeRotateRightAction); imageViewer->addAction(freeRotateLeftAction); imageViewer->addAction(flipHorizontalAction); imageViewer->addAction(flipVerticalAction); imageViewer->addAction(cropAction); imageViewer->addAction(cropToSelectionAction); imageViewer->addAction(resizeAction); imageViewer->addAction(saveAction); imageViewer->addAction(saveAsAction); imageViewer->addAction(copyImageAction); imageViewer->addAction(pasteImageAction); imageViewer->addAction(deleteAction); imageViewer->addAction(deletePermanentlyAction); imageViewer->addAction(renameAction); imageViewer->addAction(CloseImageAction); imageViewer->addAction(fullScreenAction); imageViewer->addAction(settingsAction); imageViewer->addAction(mirrorDisabledAction); imageViewer->addAction(mirrorDualAction); imageViewer->addAction(mirrorTripleAction); imageViewer->addAction(mirrorDualVerticalAction); imageViewer->addAction(mirrorQuadAction); imageViewer->addAction(keepTransformAction); imageViewer->addAction(keepZoomAction); imageViewer->addAction(refreshAction); imageViewer->addAction(colorsAction); imageViewer->addAction(moveRightAction); imageViewer->addAction(moveLeftAction); imageViewer->addAction(moveUpAction); imageViewer->addAction(moveDownAction); imageViewer->addAction(showClipboardAction); imageViewer->addAction(copyToAction); imageViewer->addAction(moveToAction); imageViewer->addAction(resizeAction); imageViewer->addAction(viewImageAction); imageViewer->addAction(exitAction); imageViewer->addAction(showViewerToolbarAction); imageViewer->addAction(externalAppsAction); // Actions addMenuSeparator(imageViewer->ImagePopUpMenu); imageViewer->ImagePopUpMenu->addAction(nextImageAction); imageViewer->ImagePopUpMenu->addAction(prevImageAction); imageViewer->ImagePopUpMenu->addAction(firstImageAction); imageViewer->ImagePopUpMenu->addAction(lastImageAction); imageViewer->ImagePopUpMenu->addAction(randomImageAction); imageViewer->ImagePopUpMenu->addAction(slideShowAction); addMenuSeparator(imageViewer->ImagePopUpMenu); zoomSubMenu = new QMenu(tr("Zoom")); zoomSubMenuAction = new QAction(tr("Zoom"), this); zoomSubMenuAction->setIcon(QIcon::fromTheme("edit-find", QIcon(":/images/zoom.png"))); zoomSubMenuAction->setMenu(zoomSubMenu); imageViewer->ImagePopUpMenu->addAction(zoomSubMenuAction); zoomSubMenu->addAction(zoomInAction); zoomSubMenu->addAction(zoomOutAction); zoomSubMenu->addAction(origZoomAction); zoomSubMenu->addAction(resetZoomAction); addMenuSeparator(zoomSubMenu); zoomSubMenu->addAction(keepZoomAction); MirroringSubMenu = new QMenu(tr("Mirroring")); mirrorSubMenuAction = new QAction(tr("Mirroring"), this); mirrorSubMenuAction->setMenu(MirroringSubMenu); mirroringActionGroup = new QActionGroup(this); mirroringActionGroup->addAction(mirrorDisabledAction); mirroringActionGroup->addAction(mirrorDualAction); mirroringActionGroup->addAction(mirrorTripleAction); mirroringActionGroup->addAction(mirrorDualVerticalAction); mirroringActionGroup->addAction(mirrorQuadAction); MirroringSubMenu->addActions(mirroringActionGroup->actions()); transformSubMenu = new QMenu(tr("Transform")); transformSubMenuAction = new QAction(tr("Transform"), this); transformSubMenuAction->setMenu(transformSubMenu); imageViewer->ImagePopUpMenu->addAction(resizeAction); imageViewer->ImagePopUpMenu->addAction(cropToSelectionAction); imageViewer->ImagePopUpMenu->addAction(transformSubMenuAction); transformSubMenu->addAction(colorsAction); transformSubMenu->addAction(rotateRightAction); transformSubMenu->addAction(rotateLeftAction); transformSubMenu->addAction(freeRotateRightAction); transformSubMenu->addAction(freeRotateLeftAction); transformSubMenu->addAction(flipHorizontalAction); transformSubMenu->addAction(flipVerticalAction); transformSubMenu->addAction(cropAction); addMenuSeparator(transformSubMenu); transformSubMenu->addAction(keepTransformAction); imageViewer->ImagePopUpMenu->addAction(mirrorSubMenuAction); addMenuSeparator(imageViewer->ImagePopUpMenu); imageViewer->ImagePopUpMenu->addAction(copyToAction); imageViewer->ImagePopUpMenu->addAction(moveToAction); imageViewer->ImagePopUpMenu->addAction(saveAction); imageViewer->ImagePopUpMenu->addAction(saveAsAction); imageViewer->ImagePopUpMenu->addAction(renameAction); imageViewer->ImagePopUpMenu->addAction(deleteAction); imageViewer->ImagePopUpMenu->addAction(deletePermanentlyAction); imageViewer->ImagePopUpMenu->addAction(openWithMenuAction); addMenuSeparator(imageViewer->ImagePopUpMenu); viewSubMenu = new QMenu(tr("View")); viewSubMenuAction = new QAction(tr("View"), this); viewSubMenuAction->setMenu(viewSubMenu); imageViewer->ImagePopUpMenu->addAction(viewSubMenuAction); viewSubMenu->addAction(fullScreenAction); viewSubMenu->addAction(showClipboardAction); viewSubMenu->addAction(showViewerToolbarAction); viewSubMenu->addAction(refreshAction); imageViewer->ImagePopUpMenu->addAction(copyImageAction); imageViewer->ImagePopUpMenu->addAction(pasteImageAction); imageViewer->ImagePopUpMenu->addAction(CloseImageAction); imageViewer->ImagePopUpMenu->addAction(exitAction); addMenuSeparator(imageViewer->ImagePopUpMenu); imageViewer->ImagePopUpMenu->addAction(settingsAction); imageViewer->setContextMenuPolicy(Qt::DefaultContextMenu); Settings::isFullScreen = Settings::appSettings->value(Settings::optionFullScreenMode).toBool(); fullScreenAction->setChecked(Settings::isFullScreen); thumbsViewer->imagePreview->setImageViewer(imageViewer); } void Phototonic::createActions() { thumbsGoToTopAction = new QAction(tr("Top"), this); thumbsGoToTopAction->setObjectName("thumbsGoTop"); thumbsGoToTopAction->setIcon(QIcon::fromTheme("go-top", QIcon(":/images/top.png"))); connect(thumbsGoToTopAction, SIGNAL(triggered()), this, SLOT(goTop())); thumbsGoToBottomAction = new QAction(tr("Bottom"), this); thumbsGoToBottomAction->setObjectName("thumbsGoBottom"); thumbsGoToBottomAction->setIcon(QIcon::fromTheme("go-bottom", QIcon(":/images/bottom.png"))); connect(thumbsGoToBottomAction, SIGNAL(triggered()), this, SLOT(goBottom())); CloseImageAction = new QAction(tr("Close Viewer"), this); CloseImageAction->setObjectName("closeImage"); connect(CloseImageAction, SIGNAL(triggered()), this, SLOT(hideViewer())); fullScreenAction = new QAction(tr("Full Screen"), this); fullScreenAction->setObjectName("fullScreen"); fullScreenAction->setCheckable(true); connect(fullScreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen())); settingsAction = new QAction(tr("Preferences"), this); settingsAction->setObjectName("settings"); settingsAction->setIcon(QIcon::fromTheme("preferences-system", QIcon(":/images/settings.png"))); connect(settingsAction, SIGNAL(triggered()), this, SLOT(showSettings())); exitAction = new QAction(tr("Exit"), this); exitAction->setObjectName("exit"); connect(exitAction, SIGNAL(triggered()), this, SLOT(close())); thumbsZoomInAction = new QAction(tr("Enlarge Thumbnails"), this); thumbsZoomInAction->setObjectName("thumbsZoomIn"); connect(thumbsZoomInAction, SIGNAL(triggered()), this, SLOT(thumbsZoomIn())); thumbsZoomInAction->setIcon(QIcon::fromTheme("zoom-in", QIcon(":/images/zoom_in.png"))); if (thumbsViewer->thumbSize == THUMB_SIZE_MAX) { thumbsZoomInAction->setEnabled(false); } thumbsZoomOutAction = new QAction(tr("Shrink Thumbnails"), this); thumbsZoomOutAction->setObjectName("thumbsZoomOut"); connect(thumbsZoomOutAction, SIGNAL(triggered()), this, SLOT(thumbsZoomOut())); thumbsZoomOutAction->setIcon(QIcon::fromTheme("zoom-out", QIcon(":/images/zoom_out.png"))); if (thumbsViewer->thumbSize == THUMB_SIZE_MIN) { thumbsZoomOutAction->setEnabled(false); } cutAction = new QAction(tr("Cut"), this); cutAction->setObjectName("cut"); cutAction->setIcon(QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"))); connect(cutAction, SIGNAL(triggered()), this, SLOT(cutThumbs())); cutAction->setEnabled(false); copyAction = new QAction(tr("Copy"), this); copyAction->setObjectName("copy"); copyAction->setIcon(QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"))); connect(copyAction, SIGNAL(triggered()), this, SLOT(copyThumbs())); copyAction->setEnabled(false); copyToAction = new QAction(tr("Copy to..."), this); copyToAction->setObjectName("copyTo"); connect(copyToAction, SIGNAL(triggered()), this, SLOT(copyImagesTo())); moveToAction = new QAction(tr("Move to..."), this); moveToAction->setObjectName("moveTo"); connect(moveToAction, SIGNAL(triggered()), this, SLOT(moveImagesTo())); deleteAction = new QAction(tr("Move to Trash"), this); deleteAction->setObjectName("moveToTrash"); deleteAction->setIcon(style()->standardIcon(QStyle::SP_TrashIcon)); connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteOperation())); deletePermanentlyAction = new QAction(tr("Delete"), this); deletePermanentlyAction->setObjectName("delete"); deletePermanentlyAction->setIcon(QIcon::fromTheme("edit-delete", QIcon(":/images/delete.png"))); connect(deletePermanentlyAction, SIGNAL(triggered()), this, SLOT(deletePermanentlyOperation())); saveAction = new QAction(tr("Save"), this); saveAction->setObjectName("save"); saveAction->setIcon(QIcon::fromTheme("document-save", QIcon(":/images/save.png"))); saveAsAction = new QAction(tr("Save As"), this); saveAsAction->setObjectName("saveAs"); saveAsAction->setIcon(QIcon::fromTheme("document-save-as", QIcon(":/images/save_as.png"))); copyImageAction = new QAction(tr("Copy Image"), this); copyImageAction->setObjectName("copyImage"); pasteImageAction = new QAction(tr("Paste Image"), this); pasteImageAction->setObjectName("pasteImage"); renameAction = new QAction(tr("Rename"), this); renameAction->setObjectName("rename"); connect(renameAction, SIGNAL(triggered()), this, SLOT(rename())); removeMetadataAction = new QAction(tr("Remove Metadata"), this); removeMetadataAction->setObjectName("removeMetadata"); connect(removeMetadataAction, SIGNAL(triggered()), this, SLOT(removeMetadata())); selectAllAction = new QAction(tr("Select All"), this); selectAllAction->setObjectName("selectAll"); connect(selectAllAction, SIGNAL(triggered()), this, SLOT(selectAllThumbs())); aboutAction = new QAction(tr("About"), this); aboutAction->setObjectName("about"); connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); // Sort actions sortByNameAction = new QAction(tr("Sort by Name"), this); sortByNameAction->setObjectName("name"); sortByTimeAction = new QAction(tr("Sort by Time"), this); sortByTimeAction->setObjectName("time"); sortBySizeAction = new QAction(tr("Sort by Size"), this); sortBySizeAction->setObjectName("size"); sortByTypeAction = new QAction(tr("Sort by Type"), this); sortByTypeAction->setObjectName("type"); sortReverseAction = new QAction(tr("Reverse Order"), this); sortReverseAction->setObjectName("reverse"); sortByNameAction->setCheckable(true); sortByTimeAction->setCheckable(true); sortBySizeAction->setCheckable(true); sortByTypeAction->setCheckable(true); sortReverseAction->setCheckable(true); connect(sortByNameAction, SIGNAL(triggered()), this, SLOT(sortThumbnails())); connect(sortByTimeAction, SIGNAL(triggered()), this, SLOT(sortThumbnails())); connect(sortBySizeAction, SIGNAL(triggered()), this, SLOT(sortThumbnails())); connect(sortByTypeAction, SIGNAL(triggered()), this, SLOT(sortThumbnails())); connect(sortReverseAction, SIGNAL(triggered()), this, SLOT(sortThumbnails())); if (thumbsViewer->thumbsSortFlags & QDir::Time) { sortByTimeAction->setChecked(true); } else if (thumbsViewer->thumbsSortFlags & QDir::Size) { sortBySizeAction->setChecked(true); } else if (thumbsViewer->thumbsSortFlags & QDir::Type) { sortByTypeAction->setChecked(true); } else { sortByNameAction->setChecked(true); } sortReverseAction->setChecked(thumbsViewer->thumbsSortFlags & QDir::Reversed); showHiddenFilesAction = new QAction(tr("Show Hidden Files"), this); showHiddenFilesAction->setObjectName("showHidden"); showHiddenFilesAction->setCheckable(true); showHiddenFilesAction->setChecked(Settings::showHiddenFiles); connect(showHiddenFilesAction, SIGNAL(triggered()), this, SLOT(showHiddenFiles())); smallToolbarIconsAction = new QAction(tr("Small Toolbar Icons"), this); smallToolbarIconsAction->setObjectName("smallToolbarIcons"); smallToolbarIconsAction->setCheckable(true); smallToolbarIconsAction->setChecked(Settings::smallToolbarIcons); connect(smallToolbarIconsAction, SIGNAL(triggered()), this, SLOT(setToolbarIconSize())); lockDocksAction = new QAction(tr("Hide Dock Title Bars"), this); lockDocksAction->setObjectName("lockDocks"); lockDocksAction->setCheckable(true); lockDocksAction->setChecked(Settings::hideDockTitlebars); connect(lockDocksAction, SIGNAL(triggered()), this, SLOT(lockDocks())); showViewerToolbarAction = new QAction(tr("Show Toolbar"), this); showViewerToolbarAction->setObjectName("showViewerToolbars"); showViewerToolbarAction->setCheckable(true); showViewerToolbarAction->setChecked(Settings::showViewerToolbar); connect(showViewerToolbarAction, SIGNAL(triggered()), this, SLOT(toggleImageViewerToolbar())); refreshAction = new QAction(tr("Reload"), this); refreshAction->setObjectName("refresh"); refreshAction->setIcon(QIcon::fromTheme("view-refresh", QIcon(":/images/refresh.png"))); connect(refreshAction, SIGNAL(triggered()), this, SLOT(reload())); includeSubDirectoriesAction = new QAction(tr("Include Sub-directories"), this); includeSubDirectoriesAction->setObjectName("subFolders"); includeSubDirectoriesAction->setIcon(QIcon(":/images/tree.png")); includeSubDirectoriesAction->setCheckable(true); connect(includeSubDirectoriesAction, SIGNAL(triggered()), this, SLOT(setIncludeSubDirs())); pasteAction = new QAction(tr("Paste Here"), this); pasteAction->setObjectName("paste"); pasteAction->setIcon(QIcon::fromTheme("edit-paste", QIcon(":/images/paste.png"))); connect(pasteAction, SIGNAL(triggered()), this, SLOT(pasteThumbs())); pasteAction->setEnabled(false); createDirectoryAction = new QAction(tr("New Directory"), this); createDirectoryAction->setObjectName("createDir"); connect(createDirectoryAction, SIGNAL(triggered()), this, SLOT(createSubDirectory())); createDirectoryAction->setIcon(QIcon::fromTheme("folder-new", QIcon(":/images/new_folder.png"))); goBackAction = new QAction(tr("Back"), this); goBackAction->setObjectName("goBack"); goBackAction->setIcon(QIcon::fromTheme("go-previous", QIcon(":/images/back.png"))); connect(goBackAction, SIGNAL(triggered()), this, SLOT(goBack())); goBackAction->setEnabled(false); goFrwdAction = new QAction(tr("Forward"), this); goFrwdAction->setObjectName("goFrwd"); goFrwdAction->setIcon(QIcon::fromTheme("go-next", QIcon(":/images/next.png"))); connect(goFrwdAction, SIGNAL(triggered()), this, SLOT(goForward())); goFrwdAction->setEnabled(false); goUpAction = new QAction(tr("Go Up"), this); goUpAction->setObjectName("up"); goUpAction->setIcon(QIcon::fromTheme("go-up", QIcon(":/images/up.png"))); connect(goUpAction, SIGNAL(triggered()), this, SLOT(goUp())); goHomeAction = new QAction(tr("Home"), this); goHomeAction->setObjectName("home"); connect(goHomeAction, SIGNAL(triggered()), this, SLOT(goHome())); goHomeAction->setIcon(QIcon::fromTheme("go-home", QIcon(":/images/home.png"))); slideShowAction = new QAction(tr("Slide Show"), this); slideShowAction->setObjectName("toggleSlideShow"); connect(slideShowAction, SIGNAL(triggered()), this, SLOT(toggleSlideShow())); slideShowAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/images/play.png"))); nextImageAction = new QAction(tr("Next Image"), this); nextImageAction->setObjectName("nextImage"); nextImageAction->setIcon(QIcon::fromTheme("go-next", QIcon(":/images/next.png"))); connect(nextImageAction, SIGNAL(triggered()), this, SLOT(loadNextImage())); prevImageAction = new QAction(tr("Previous Image"), this); prevImageAction->setObjectName("prevImage"); prevImageAction->setIcon(QIcon::fromTheme("go-previous", QIcon(":/images/back.png"))); connect(prevImageAction, SIGNAL(triggered()), this, SLOT(loadPreviousImage())); firstImageAction = new QAction(tr("First Image"), this); firstImageAction->setObjectName("firstImage"); firstImageAction->setIcon(QIcon::fromTheme("go-first", QIcon(":/images/first.png"))); connect(firstImageAction, SIGNAL(triggered()), this, SLOT(loadFirstImage())); lastImageAction = new QAction(tr("Last Image"), this); lastImageAction->setObjectName("lastImage"); lastImageAction->setIcon(QIcon::fromTheme("go-last", QIcon(":/images/last.png"))); connect(lastImageAction, SIGNAL(triggered()), this, SLOT(loadLastImage())); randomImageAction = new QAction(tr("Random Image"), this); randomImageAction->setObjectName("randomImage"); connect(randomImageAction, SIGNAL(triggered()), this, SLOT(loadRandomImage())); viewImageAction = new QAction(tr("View Image"), this); viewImageAction->setObjectName("open"); viewImageAction->setIcon(QIcon::fromTheme("document-open", QIcon(":/images/open.png"))); connect(viewImageAction, SIGNAL(triggered()), this, SLOT(viewImage())); showClipboardAction = new QAction(tr("Load Clipboard"), this); showClipboardAction->setObjectName("showClipboard"); showClipboardAction->setIcon(QIcon::fromTheme("insert-image", QIcon(":/images/new.png"))); connect(showClipboardAction, SIGNAL(triggered()), this, SLOT(newImage())); openWithSubMenu = new QMenu(tr("Open With...")); openWithMenuAction = new QAction(tr("Open With..."), this); openWithMenuAction->setObjectName("openWithMenu"); openWithMenuAction->setMenu(openWithSubMenu); externalAppsAction = new QAction(tr("External Applications"), this); externalAppsAction->setIcon(QIcon::fromTheme("preferences-other", QIcon(":/images/settings.png"))); externalAppsAction->setObjectName("chooseApp"); connect(externalAppsAction, SIGNAL(triggered()), this, SLOT(chooseExternalApp())); addBookmarkAction = new QAction(tr("Add Bookmark"), this); addBookmarkAction->setObjectName("addBookmark"); addBookmarkAction->setIcon(QIcon(":/images/new_bookmark.png")); connect(addBookmarkAction, SIGNAL(triggered()), this, SLOT(addNewBookmark())); removeBookmarkAction = new QAction(tr("Delete Bookmark"), this); removeBookmarkAction->setObjectName("deleteBookmark"); removeBookmarkAction->setIcon(QIcon::fromTheme("edit-delete", QIcon(":/images/delete.png"))); zoomOutAction = new QAction(tr("Zoom Out"), this); zoomOutAction->setObjectName("zoomOut"); connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOut())); zoomOutAction->setIcon(QIcon::fromTheme("zoom-out", QIcon(":/images/zoom_out.png"))); zoomInAction = new QAction(tr("Zoom In"), this); zoomInAction->setObjectName("zoomIn"); connect(zoomInAction, SIGNAL(triggered()), this, SLOT(zoomIn())); zoomInAction->setIcon(QIcon::fromTheme("zoom-in", QIcon(":/images/zoom_out.png"))); resetZoomAction = new QAction(tr("Reset Zoom"), this); resetZoomAction->setObjectName("resetZoom"); resetZoomAction->setIcon(QIcon::fromTheme("zoom-fit-best", QIcon(":/images/zoom.png"))); connect(resetZoomAction, SIGNAL(triggered()), this, SLOT(resetZoom())); origZoomAction = new QAction(tr("Original Size"), this); origZoomAction->setObjectName("origZoom"); origZoomAction->setIcon(QIcon::fromTheme("zoom-original", QIcon(":/images/zoom1.png"))); connect(origZoomAction, SIGNAL(triggered()), this, SLOT(origZoom())); keepZoomAction = new QAction(tr("Keep Zoom"), this); keepZoomAction->setObjectName("keepZoom"); keepZoomAction->setCheckable(true); connect(keepZoomAction, SIGNAL(triggered()), this, SLOT(keepZoom())); rotateLeftAction = new QAction(tr("Rotate 90 degree CCW"), this); rotateLeftAction->setObjectName("rotateLeft"); rotateLeftAction->setIcon(QIcon::fromTheme("object-rotate-left", QIcon(":/images/rotate_left.png"))); connect(rotateLeftAction, SIGNAL(triggered()), this, SLOT(rotateLeft())); rotateRightAction = new QAction(tr("Rotate 90 degree CW"), this); rotateRightAction->setObjectName("rotateRight"); rotateRightAction->setIcon(QIcon::fromTheme("object-rotate-right", QIcon(":/images/rotate_right.png"))); connect(rotateRightAction, SIGNAL(triggered()), this, SLOT(rotateRight())); flipHorizontalAction = new QAction(tr("Flip Horizontally"), this); flipHorizontalAction->setObjectName("flipH"); flipHorizontalAction->setIcon(QIcon::fromTheme("object-flip-horizontal", QIcon(":/images/flipH.png"))); connect(flipHorizontalAction, SIGNAL(triggered()), this, SLOT(flipHorizontal())); flipVerticalAction = new QAction(tr("Flip Vertically"), this); flipVerticalAction->setObjectName("flipV"); flipVerticalAction->setIcon(QIcon::fromTheme("object-flip-vertical", QIcon(":/images/flipV.png"))); connect(flipVerticalAction, SIGNAL(triggered()), this, SLOT(flipVertical())); cropAction = new QAction(tr("Cropping"), this); cropAction->setObjectName("crop"); cropAction->setIcon(QIcon(":/images/crop.png")); connect(cropAction, SIGNAL(triggered()), this, SLOT(cropImage())); cropToSelectionAction = new QAction(tr("Crop to Selection"), this); cropToSelectionAction->setObjectName("cropToSelection"); cropToSelectionAction->setIcon(QIcon(":/images/crop.png")); resizeAction = new QAction(tr("Scale Image"), this); resizeAction->setObjectName("resize"); resizeAction->setIcon(QIcon::fromTheme("transform-scale", QIcon(":/images/scale.png"))); connect(resizeAction, SIGNAL(triggered()), this, SLOT(scaleImage())); freeRotateLeftAction = new QAction(tr("Rotate 1 degree CCW"), this); freeRotateLeftAction->setObjectName("freeRotateLeft"); connect(freeRotateLeftAction, SIGNAL(triggered()), this, SLOT(freeRotateLeft())); freeRotateRightAction = new QAction(tr("Rotate 1 degree CW"), this); freeRotateRightAction->setObjectName("freeRotateRight"); connect(freeRotateRightAction, SIGNAL(triggered()), this, SLOT(freeRotateRight())); colorsAction = new QAction(tr("Colors"), this); colorsAction->setObjectName("colors"); connect(colorsAction, SIGNAL(triggered()), this, SLOT(showColorsDialog())); colorsAction->setIcon(QIcon(":/images/colors.png")); mirrorDisabledAction = new QAction(tr("Disable Mirror"), this); mirrorDisabledAction->setObjectName("mirrorDisabled"); mirrorDualAction = new QAction(tr("Dual Mirror"), this); mirrorDualAction->setObjectName("mirrorDual"); mirrorTripleAction = new QAction(tr("Triple Mirror"), this); mirrorTripleAction->setObjectName("mirrorTriple"); mirrorDualVerticalAction = new QAction(tr("Dual Vertical Mirror"), this); mirrorDualVerticalAction->setObjectName("mirrorVDual"); mirrorQuadAction = new QAction(tr("Quad Mirror"), this); mirrorQuadAction->setObjectName("mirrorQuad"); mirrorDisabledAction->setCheckable(true); mirrorDualAction->setCheckable(true); mirrorTripleAction->setCheckable(true); mirrorDualVerticalAction->setCheckable(true); mirrorQuadAction->setCheckable(true); connect(mirrorDisabledAction, SIGNAL(triggered()), this, SLOT(setMirrorDisabled())); connect(mirrorDualAction, SIGNAL(triggered()), this, SLOT(setMirrorDual())); connect(mirrorTripleAction, SIGNAL(triggered()), this, SLOT(setMirrorTriple())); connect(mirrorDualVerticalAction, SIGNAL(triggered()), this, SLOT(setMirrorVDual())); connect(mirrorQuadAction, SIGNAL(triggered()), this, SLOT(setMirrorQuad())); mirrorDisabledAction->setChecked(true); keepTransformAction = new QAction(tr("Keep Transformations"), this); keepTransformAction->setObjectName("keepTransform"); keepTransformAction->setCheckable(true); connect(keepTransformAction, SIGNAL(triggered()), this, SLOT(keepTransformClicked())); moveLeftAction = new QAction(tr("Move Image Left"), this); moveLeftAction->setObjectName("moveLeft"); connect(moveLeftAction, SIGNAL(triggered()), this, SLOT(moveLeft())); moveRightAction = new QAction(tr("Move Image Right"), this); moveRightAction->setObjectName("moveRight"); connect(moveRightAction, SIGNAL(triggered()), this, SLOT(moveRight())); moveUpAction = new QAction(tr("Move Image Up"), this); moveUpAction->setObjectName("moveUp"); connect(moveUpAction, SIGNAL(triggered()), this, SLOT(moveUp())); moveDownAction = new QAction(tr("Move Image Down"), this); moveDownAction->setObjectName("moveDown"); connect(moveDownAction, SIGNAL(triggered()), this, SLOT(moveDown())); invertSelectionAction = new QAction(tr("Invert Selection"), this); invertSelectionAction->setObjectName("invertSelection"); connect(invertSelectionAction, SIGNAL(triggered()), thumbsViewer, SLOT(invertSelection())); filterImagesFocusAction = new QAction(tr("Filter by Name"), this); filterImagesFocusAction->setObjectName("filterImagesFocus"); connect(filterImagesFocusAction, SIGNAL(triggered()), this, SLOT(filterImagesFocus())); setPathFocusAction = new QAction(tr("Edit Current Path"), this); setPathFocusAction->setObjectName("setPathFocus"); connect(setPathFocusAction, SIGNAL(triggered()), this, SLOT(setPathFocus())); } void Phototonic::createMenus() { fileMenu = menuBar()->addMenu(tr("&File")); fileMenu->addAction(includeSubDirectoriesAction); fileMenu->addAction(createDirectoryAction); fileMenu->addAction(showClipboardAction); fileMenu->addAction(addBookmarkAction); fileMenu->addSeparator(); fileMenu->addAction(exitAction); editMenu = menuBar()->addMenu(tr("&Edit")); editMenu->addAction(cutAction); editMenu->addAction(copyAction); editMenu->addAction(copyToAction); editMenu->addAction(moveToAction); editMenu->addAction(pasteAction); editMenu->addAction(renameAction); editMenu->addAction(removeMetadataAction); editMenu->addAction(deleteAction); editMenu->addAction(deletePermanentlyAction); editMenu->addSeparator(); editMenu->addAction(selectAllAction); editMenu->addAction(invertSelectionAction); addAction(filterImagesFocusAction); addAction(setPathFocusAction); editMenu->addSeparator(); editMenu->addAction(externalAppsAction); editMenu->addAction(settingsAction); goMenu = menuBar()->addMenu(tr("&Go")); goMenu->addAction(goBackAction); goMenu->addAction(goFrwdAction); goMenu->addAction(goUpAction); goMenu->addAction(goHomeAction); goMenu->addSeparator(); goMenu->addAction(prevImageAction); goMenu->addAction(nextImageAction); goMenu->addSeparator(); goMenu->addAction(thumbsGoToTopAction); goMenu->addAction(thumbsGoToBottomAction); viewMenu = menuBar()->addMenu(tr("&View")); viewMenu->addAction(slideShowAction); viewMenu->addSeparator(); viewMenu->addAction(thumbsZoomInAction); viewMenu->addAction(thumbsZoomOutAction); sortMenu = viewMenu->addMenu(tr("Thumbnails Sorting")); sortTypesGroup = new QActionGroup(this); sortTypesGroup->addAction(sortByNameAction); sortTypesGroup->addAction(sortByTimeAction); sortTypesGroup->addAction(sortBySizeAction); sortTypesGroup->addAction(sortByTypeAction); sortMenu->addActions(sortTypesGroup->actions()); sortMenu->addSeparator(); sortMenu->addAction(sortReverseAction); viewMenu->addSeparator(); viewMenu->addAction(showHiddenFilesAction); viewMenu->addSeparator(); viewMenu->addAction(refreshAction); // thumbs viewer context menu thumbsViewer->addAction(viewImageAction); thumbsViewer->addAction(openWithMenuAction); thumbsViewer->addAction(cutAction); thumbsViewer->addAction(copyAction); thumbsViewer->addAction(pasteAction); addMenuSeparator(thumbsViewer); thumbsViewer->addAction(copyToAction); thumbsViewer->addAction(moveToAction); thumbsViewer->addAction(renameAction); thumbsViewer->addAction(removeMetadataAction); thumbsViewer->addAction(deleteAction); thumbsViewer->addAction(deletePermanentlyAction); addMenuSeparator(thumbsViewer); thumbsViewer->addAction(selectAllAction); thumbsViewer->addAction(invertSelectionAction); thumbsViewer->setContextMenuPolicy(Qt::ActionsContextMenu); menuBar()->setVisible(true); } void Phototonic::createToolBars() { /* Edit */ editToolBar = addToolBar(tr("Edit Toolbar")); editToolBar->setObjectName("Edit"); editToolBar->addAction(cutAction); editToolBar->addAction(copyAction); editToolBar->addAction(pasteAction); editToolBar->addAction(deleteAction); editToolBar->addAction(deletePermanentlyAction); editToolBar->addAction(showClipboardAction); connect(editToolBar->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setEditToolBarVisibility())); /* Navigation */ goToolBar = addToolBar(tr("Navigation Toolbar")); goToolBar->setObjectName("Navigation"); goToolBar->addAction(goBackAction); goToolBar->addAction(goFrwdAction); goToolBar->addAction(goUpAction); goToolBar->addAction(goHomeAction); goToolBar->addAction(refreshAction); /* path bar */ pathLineEdit = new QLineEdit; pathLineEdit->setCompleter(new DirCompleter(pathLineEdit)); pathLineEdit->setMinimumWidth(200); pathLineEdit->setMaximumWidth(600); connect(pathLineEdit, SIGNAL(returnPressed()), this, SLOT(goPathBarDir())); goToolBar->addWidget(pathLineEdit); goToolBar->addAction(includeSubDirectoriesAction); connect(goToolBar->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setGoToolBarVisibility())); /* View */ viewToolBar = addToolBar(tr("View Toolbar")); viewToolBar->setObjectName("View"); viewToolBar->addAction(thumbsZoomInAction); viewToolBar->addAction(thumbsZoomOutAction); viewToolBar->addAction(slideShowAction); /* filter bar */ QAction *filterAct = new QAction(tr("Filter"), this); filterAct->setIcon(QIcon::fromTheme("edit-find", QIcon(":/images/zoom.png"))); connect(filterAct, SIGNAL(triggered()), this, SLOT(setThumbsFilter())); filterLineEdit = new QLineEdit; filterLineEdit->setMinimumWidth(100); filterLineEdit->setMaximumWidth(200); connect(filterLineEdit, SIGNAL(returnPressed()), this, SLOT(setThumbsFilter())); connect(filterLineEdit, SIGNAL(textChanged( const QString&)), this, SLOT(clearThumbsFilter())); filterLineEdit->setClearButtonEnabled(true); filterLineEdit->addAction(filterAct, QLineEdit::LeadingPosition); viewToolBar->addSeparator(); viewToolBar->addWidget(filterLineEdit); viewToolBar->addAction(settingsAction); connect(viewToolBar->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setViewToolBarVisibility())); /* image */ imageToolBar = new QToolBar(tr("Image Toolbar")); imageToolBar->setObjectName("Image"); imageToolBar->addAction(prevImageAction); imageToolBar->addAction(nextImageAction); imageToolBar->addAction(firstImageAction); imageToolBar->addAction(lastImageAction); imageToolBar->addAction(slideShowAction); imageToolBar->addSeparator(); imageToolBar->addAction(saveAction); imageToolBar->addAction(saveAsAction); imageToolBar->addAction(deleteAction); imageToolBar->addAction(deletePermanentlyAction); imageToolBar->addSeparator(); imageToolBar->addAction(zoomInAction); imageToolBar->addAction(zoomOutAction); imageToolBar->addAction(resetZoomAction); imageToolBar->addAction(origZoomAction); imageToolBar->addSeparator(); imageToolBar->addAction(resizeAction); imageToolBar->addAction(rotateRightAction); imageToolBar->addAction(rotateLeftAction); imageToolBar->addAction(flipHorizontalAction); imageToolBar->addAction(flipVerticalAction); imageToolBar->addAction(cropAction); imageToolBar->addAction(colorsAction); imageToolBar->setVisible(false); connect(imageToolBar->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setImageToolBarVisibility())); setToolbarIconSize(); } void Phototonic::setToolbarIconSize() { if (initComplete) { Settings::smallToolbarIcons = smallToolbarIconsAction->isChecked(); } int iconSize = Settings::smallToolbarIcons ? 16 : 24; QSize iconQSize(iconSize, iconSize); editToolBar->setIconSize(iconQSize); goToolBar->setIconSize(iconQSize); viewToolBar->setIconSize(iconQSize); imageToolBar->setIconSize(iconQSize); } void Phototonic::createStatusBar() { statusLabel = new QLabel(tr("Initializing...")); statusBar()->addWidget(statusLabel); busyMovie = new QMovie(":/images/busy.gif"); busyLabel = new QLabel(this); busyLabel->setMovie(busyMovie); statusBar()->addWidget(busyLabel); busyLabel->setVisible(false); statusBar()->setStyleSheet("QStatusBar::item { border: 0px solid black }; "); } void Phototonic::onFileListSelected() { if (initComplete && fileListWidget->itemAt(0, 0)->isSelected()) { Settings::isFileListLoaded = true; fileSystemTree->clearSelection(); refreshThumbs(true); } } void Phototonic::createFileSystemDock() { fileSystemDock = new QDockWidget(tr("File System"), this); fileSystemDock->setObjectName("File System"); fileListWidget = new FileListWidget(fileSystemDock); connect(fileListWidget, SIGNAL(itemSelectionChanged()), this, SLOT(onFileListSelected())); fileSystemTree = new FileSystemTree(fileSystemDock); fileSystemTree->addAction(createDirectoryAction); fileSystemTree->addAction(renameAction); fileSystemTree->addAction(deleteAction); fileSystemTree->addAction(deletePermanentlyAction); addMenuSeparator(fileSystemTree); fileSystemTree->addAction(pasteAction); addMenuSeparator(fileSystemTree); fileSystemTree->addAction(openWithMenuAction); fileSystemTree->addAction(addBookmarkAction); fileSystemTree->setContextMenuPolicy(Qt::ActionsContextMenu); connect(fileSystemTree, SIGNAL(clicked( const QModelIndex&)), this, SLOT(goSelectedDir( const QModelIndex &))); connect(fileSystemTree->fileSystemModel, SIGNAL(rowsRemoved( const QModelIndex &, int, int)), this, SLOT(checkDirState( const QModelIndex &, int, int))); connect(fileSystemTree, SIGNAL(dropOp(Qt::KeyboardModifiers, bool, QString)), this, SLOT(dropOp(Qt::KeyboardModifiers, bool, QString))); fileSystemTree->setCurrentIndex(fileSystemTree->fileSystemModel->index(QDir::currentPath())); connect(fileSystemTree->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateActions())); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); mainLayout->addWidget(fileListWidget); mainLayout->addWidget(fileSystemTree); QWidget *fileSystemTreeMainWidget = new QWidget(fileSystemDock); fileSystemTreeMainWidget->setLayout(mainLayout); fileSystemDock->setWidget(fileSystemTreeMainWidget); connect(fileSystemDock->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setFileSystemDockVisibility())); connect(fileSystemDock, SIGNAL(visibilityChanged(bool)), this, SLOT(setFileSystemDockVisibility())); addDockWidget(Qt::LeftDockWidgetArea, fileSystemDock); } void Phototonic::createBookmarksDock() { bookmarksDock = new QDockWidget(tr("Bookmarks"), this); bookmarksDock->setObjectName("Bookmarks"); bookmarks = new BookMarks(bookmarksDock); bookmarksDock->setWidget(bookmarks); connect(bookmarksDock->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setBookmarksDockVisibility())); connect(bookmarksDock, SIGNAL(visibilityChanged(bool)), this, SLOT(setBookmarksDockVisibility())); connect(bookmarks, SIGNAL(itemClicked(QTreeWidgetItem * , int)), this, SLOT(bookmarkClicked(QTreeWidgetItem * , int))); connect(removeBookmarkAction, SIGNAL(triggered()), bookmarks, SLOT(removeBookmark())); connect(bookmarks, SIGNAL(dropOp(Qt::KeyboardModifiers, bool, QString)), this, SLOT(dropOp(Qt::KeyboardModifiers, bool, QString))); addDockWidget(Qt::LeftDockWidgetArea, bookmarksDock); bookmarks->addAction(pasteAction); bookmarks->addAction(removeBookmarkAction); bookmarks->setContextMenuPolicy(Qt::ActionsContextMenu); } void Phototonic::createImagePreviewDock() { imagePreviewDock = new QDockWidget(tr("Preview"), this); imagePreviewDock->setObjectName("ImagePreview"); imagePreviewDock->setWidget(thumbsViewer->imagePreview); connect(imagePreviewDock->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setImagePreviewDockVisibility())); connect(imagePreviewDock, SIGNAL(visibilityChanged(bool)), this, SLOT(setImagePreviewDockVisibility())); addDockWidget(Qt::RightDockWidgetArea, imagePreviewDock); } void Phototonic::createImageTagsDock() { tagsDock = new QDockWidget(tr("Tags"), this); tagsDock->setObjectName("Tags"); thumbsViewer->imageTags = new ImageTags(tagsDock, thumbsViewer, metadataCache); tagsDock->setWidget(thumbsViewer->imageTags); connect(tagsDock->toggleViewAction(), SIGNAL(triggered()), this, SLOT(setTagsDockVisibility())); connect(tagsDock, SIGNAL(visibilityChanged(bool)), this, SLOT(setTagsDockVisibility())); connect(thumbsViewer->imageTags, SIGNAL(reloadThumbs()), this, SLOT(onReloadThumbs())); connect(thumbsViewer->imageTags->removeTagAction, SIGNAL(triggered()), this, SLOT(deleteOperation())); } void Phototonic::sortThumbnails() { thumbsViewer->thumbsSortFlags = QDir::IgnoreCase; if (sortByNameAction->isChecked()) { thumbsViewer->thumbsSortFlags |= QDir::Name; } else if (sortByTimeAction->isChecked()) { thumbsViewer->thumbsSortFlags |= QDir::Time; } else if (sortBySizeAction->isChecked()) { thumbsViewer->thumbsSortFlags |= QDir::Size; } else if (sortByTypeAction->isChecked()) { thumbsViewer->thumbsSortFlags |= QDir::Type; } if (sortReverseAction->isChecked()) { thumbsViewer->thumbsSortFlags |= QDir::Reversed; } refreshThumbs(false); } void Phototonic::reload() { if (Settings::layoutMode == ThumbViewWidget) { refreshThumbs(false); } else { imageViewer->reload(); } } void Phototonic::setIncludeSubDirs() { Settings::includeSubDirectories = includeSubDirectoriesAction->isChecked(); refreshThumbs(false); } void Phototonic::refreshThumbs(bool scrollToTop) { thumbsViewer->setNeedToScroll(scrollToTop); QTimer::singleShot(0, this, SLOT(onReloadThumbs())); } void Phototonic::showHiddenFiles() { Settings::showHiddenFiles = showHiddenFilesAction->isChecked(); fileSystemTree->setModelFlags(); refreshThumbs(false); } void Phototonic::toggleImageViewerToolbar() { imageToolBar->setVisible(showViewerToolbarAction->isChecked()); addToolBar(imageToolBar); Settings::showViewerToolbar = showViewerToolbarAction->isChecked(); } void Phototonic::about() { MessageBox messageBox(this); messageBox.about(); } void Phototonic::filterImagesFocus() { if (Settings::layoutMode == ThumbViewWidget) { if (!viewToolBar->isVisible()) { viewToolBar->setVisible(true); } setViewToolBarVisibility(); filterLineEdit->setFocus(Qt::OtherFocusReason); filterLineEdit->selectAll(); } } void Phototonic::setPathFocus() { if (Settings::layoutMode == ThumbViewWidget) { if (!goToolBar->isVisible()) { goToolBar->setVisible(true); } setGoToolBarVisibility(); pathLineEdit->setFocus(Qt::OtherFocusReason); pathLineEdit->selectAll(); } } void Phototonic::cleanupSender() { delete QObject::sender(); } void Phototonic::externalAppError() { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to start external application.")); } void Phototonic::runExternalApp() { QString execCommand; QString selectedFileNames(""); execCommand = Settings::externalApps[((QAction *) sender())->text()]; if (Settings::layoutMode == ImageViewWidget) { if (imageViewer->isNewImage()) { showNewImageWarning(); return; } execCommand += " \"" + imageViewer->viewerImageFullPath + "\""; } else { if (QApplication::focusWidget() == fileSystemTree) { selectedFileNames += " \"" + getSelectedPath() + "\""; } else { QModelIndexList selectedIdxList = thumbsViewer->selectionModel()->selectedIndexes(); if (selectedIdxList.size() < 1) { setStatus(tr("Invalid selection.")); return; } selectedFileNames += " "; for (int tn = selectedIdxList.size() - 1; tn >= 0; --tn) { selectedFileNames += "\"" + thumbsViewer->thumbsViewerModel->item(selectedIdxList[tn].row())->data( thumbsViewer->FileNameRole).toString(); if (tn) selectedFileNames += "\" "; } } execCommand += selectedFileNames; } QProcess *externalProcess = new QProcess(); connect(externalProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cleanupSender())); connect(externalProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(externalAppError())); externalProcess->start(execCommand); } void Phototonic::updateExternalApps() { int actionNumber = 0; QMapIterator externalAppsIterator(Settings::externalApps); QList actionList = openWithSubMenu->actions(); if (!actionList.empty()) { for (int i = 0; i < actionList.size(); ++i) { QAction *action = actionList.at(i); if (action->isSeparator()) { break; } openWithSubMenu->removeAction(action); imageViewer->removeAction(action); delete action; } openWithSubMenu->clear(); } while (externalAppsIterator.hasNext()) { ++actionNumber; externalAppsIterator.next(); QAction *extAppAct = new QAction(externalAppsIterator.key(), this); if (actionNumber < 10) { extAppAct->setShortcut(QKeySequence("Alt+" + QString::number(actionNumber))); } extAppAct->setIcon(QIcon::fromTheme(externalAppsIterator.key())); connect(extAppAct, SIGNAL(triggered()), this, SLOT(runExternalApp())); openWithSubMenu->addAction(extAppAct); imageViewer->addAction(extAppAct); } openWithSubMenu->addSeparator(); openWithSubMenu->addAction(externalAppsAction); } void Phototonic::chooseExternalApp() { ExternalAppsDialog *externalAppsDialog = new ExternalAppsDialog(this); if (Settings::slideShowActive) { toggleSlideShow(); } imageViewer->setCursorHiding(false); externalAppsDialog->exec(); updateExternalApps(); delete (externalAppsDialog); if (isFullScreen()) { imageViewer->setCursorHiding(true); } } void Phototonic::showSettings() { if (Settings::slideShowActive) { toggleSlideShow(); } imageViewer->setCursorHiding(false); SettingsDialog *settingsDialog = new SettingsDialog(this); if (settingsDialog->exec()) { imageViewer->setBackgroundColor(); thumbsViewer->setThumbColors(); thumbsViewer->imagePreview->setBackgroundColor(); Settings::imageZoomFactor = 1.0; imageViewer->imageInfoLabel->setVisible(Settings::showImageName); if (Settings::layoutMode == ImageViewWidget) { imageViewer->reload(); needThumbsRefresh = true; } else { refreshThumbs(false); } if (!Settings::setWindowIcon) { setWindowIcon(defaultApplicationIcon); } writeSettings(); } if (isFullScreen()) { imageViewer->setCursorHiding(true); } delete settingsDialog; } void Phototonic::toggleFullScreen() { if (fullScreenAction->isChecked()) { shouldMaximize = isMaximized(); showFullScreen(); Settings::isFullScreen = true; imageViewer->setCursorHiding(true); } else { showNormal(); if (shouldMaximize) { showMaximized(); } imageViewer->setCursorHiding(false); Settings::isFullScreen = false; } } void Phototonic::selectAllThumbs() { thumbsViewer->selectAll(); } void Phototonic::copyOrCutThumbs(bool isCopyOperation) { Settings::copyCutIndexList = thumbsViewer->selectionModel()->selectedIndexes(); copyCutThumbsCount = Settings::copyCutIndexList.size(); Settings::copyCutFileList.clear(); for (int thumb = 0; thumb < copyCutThumbsCount; ++thumb) { Settings::copyCutFileList.append(thumbsViewer->thumbsViewerModel->item(Settings::copyCutIndexList[thumb]. row())->data(thumbsViewer->FileNameRole).toString()); } Settings::isCopyOperation = isCopyOperation; pasteAction->setEnabled(true); QString state = QString((Settings::isCopyOperation ? tr("Copied") : tr("Cut")) + " " + tr("%n image(s) to clipboard", "", copyCutThumbsCount)); setStatus(state); } void Phototonic::cutThumbs() { copyOrCutThumbs(false); } void Phototonic::copyThumbs() { copyOrCutThumbs(true); } void Phototonic::copyImagesTo() { copyOrMoveImages(false); } void Phototonic::moveImagesTo() { copyOrMoveImages(true); } void Phototonic::copyOrMoveImages(bool isMoveOperation) { if (Settings::slideShowActive) { toggleSlideShow(); } imageViewer->setCursorHiding(false); copyMoveToDialog = new CopyMoveToDialog(this, getSelectedPath(), isMoveOperation); if (copyMoveToDialog->exec()) { if (Settings::layoutMode == ThumbViewWidget) { if (copyMoveToDialog->copyOp) { copyThumbs(); } else { cutThumbs(); } pasteThumbs(); } else { if (imageViewer->isNewImage()) { showNewImageWarning(); if (isFullScreen()) { imageViewer->setCursorHiding(true); } return; } QFileInfo fileInfo = QFileInfo(imageViewer->viewerImageFullPath); QString fileName = fileInfo.fileName(); QString destFile = copyMoveToDialog->selectedPath + QDir::separator() + fileInfo.fileName(); int result = CopyMoveDialog::copyOrMoveFile(copyMoveToDialog->copyOp, fileName, imageViewer->viewerImageFullPath, destFile, copyMoveToDialog->selectedPath); if (!result) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to copy or move image.")); } else { if (!copyMoveToDialog->copyOp) { int currentRow = thumbsViewer->getCurrentRow(); thumbsViewer->thumbsViewerModel->removeRow(currentRow); loadCurrentImage(currentRow); } } } } bookmarks->reloadBookmarks(); delete (copyMoveToDialog); copyMoveToDialog = 0; if (isFullScreen()) { imageViewer->setCursorHiding(true); } } void Phototonic::thumbsZoomIn() { if (thumbsViewer->thumbSize < THUMB_SIZE_MAX) { thumbsViewer->thumbSize += THUMB_SIZE_MIN; thumbsZoomOutAction->setEnabled(true); if (thumbsViewer->thumbSize == THUMB_SIZE_MAX) thumbsZoomInAction->setEnabled(false); refreshThumbs(false); } } void Phototonic::thumbsZoomOut() { if (thumbsViewer->thumbSize > THUMB_SIZE_MIN) { thumbsViewer->thumbSize -= THUMB_SIZE_MIN; thumbsZoomInAction->setEnabled(true); if (thumbsViewer->thumbSize == THUMB_SIZE_MIN) thumbsZoomOutAction->setEnabled(false); refreshThumbs(false); } } void Phototonic::zoomOut() { if (Settings::imageZoomFactor <= 4.0 && Settings::imageZoomFactor > 0.25) { Settings::imageZoomFactor -= 0.25; } else if (Settings::imageZoomFactor <= 8.0 && Settings::imageZoomFactor >= 4.0) { Settings::imageZoomFactor -= 0.50; } else if (Settings::imageZoomFactor <= 16.0 && Settings::imageZoomFactor >= 8.0) { Settings::imageZoomFactor -= 1.0; } else { imageViewer->setFeedback(tr("Minimum zoom")); return; } imageViewer->tempDisableResize = false; imageViewer->resizeImage(); imageViewer->setFeedback(tr("Zoom %1%").arg(QString::number(Settings::imageZoomFactor * 100))); } void Phototonic::zoomIn() { if (Settings::imageZoomFactor < 4.0 && Settings::imageZoomFactor >= 0.25) { Settings::imageZoomFactor += 0.25; } else if (Settings::imageZoomFactor < 8.0 && Settings::imageZoomFactor >= 4.0) { Settings::imageZoomFactor += 0.50; } else if (Settings::imageZoomFactor < 16.0 && Settings::imageZoomFactor >= 8.0) { Settings::imageZoomFactor += 1.00; } else { imageViewer->setFeedback(tr("Maximum zoom")); return; } imageViewer->tempDisableResize = false; imageViewer->resizeImage(); imageViewer->setFeedback(tr("Zoom %1%").arg(QString::number(Settings::imageZoomFactor * 100))); } void Phototonic::resetZoom() { Settings::imageZoomFactor = 1.0; imageViewer->tempDisableResize = false; imageViewer->resizeImage(); imageViewer->setFeedback(tr("Zoom Reset")); } void Phototonic::origZoom() { Settings::imageZoomFactor = 1.0; imageViewer->tempDisableResize = true; imageViewer->resizeImage(); imageViewer->setFeedback(tr("Original Size")); } void Phototonic::keepZoom() { Settings::keepZoomFactor = keepZoomAction->isChecked(); if (Settings::keepZoomFactor) { imageViewer->setFeedback(tr("Zoom Locked")); } else { imageViewer->setFeedback(tr("Zoom Unlocked")); } } void Phototonic::keepTransformClicked() { Settings::keepTransform = keepTransformAction->isChecked(); if (Settings::keepTransform) { imageViewer->setFeedback(tr("Transformations Locked")); if (cropDialog) { cropDialog->applyCrop(0); } } else { Settings::cropLeftPercent = Settings::cropTopPercent = Settings::cropWidthPercent = Settings::cropHeightPercent = 0; imageViewer->setFeedback(tr("Transformations Unlocked")); } imageViewer->refresh(); } void Phototonic::rotateLeft() { Settings::rotation -= 90; if (Settings::rotation < 0) Settings::rotation = 270; imageViewer->refresh(); imageViewer->setFeedback(tr("Rotation %1°").arg(QString::number(Settings::rotation))); } void Phototonic::rotateRight() { Settings::rotation += 90; if (Settings::rotation > 270) Settings::rotation = 0; imageViewer->refresh(); imageViewer->setFeedback(tr("Rotation %1°").arg(QString::number(Settings::rotation))); } void Phototonic::flipVertical() { Settings::flipV = !Settings::flipV; imageViewer->refresh(); imageViewer->setFeedback(Settings::flipV ? tr("Flipped Vertically") : tr("Unflipped Vertically")); } void Phototonic::flipHorizontal() { Settings::flipH = !Settings::flipH; imageViewer->refresh(); imageViewer->setFeedback(Settings::flipH ? tr("Flipped Horizontally") : tr("Unflipped Horizontally")); } void Phototonic::cropImage() { if (Settings::slideShowActive) { toggleSlideShow(); } if (!cropDialog) { cropDialog = new CropDialog(this, imageViewer); connect(cropDialog, SIGNAL(accepted()), this, SLOT(cleanupCropDialog())); connect(cropDialog, SIGNAL(rejected()), this, SLOT(cleanupCropDialog())); } cropDialog->show(); setInterfaceEnabled(false); cropDialog->applyCrop(0); } void Phototonic::scaleImage() { if (Settings::slideShowActive) { toggleSlideShow(); } if (Settings::layoutMode == ThumbViewWidget && thumbsViewer->selectionModel()->selectedIndexes().size() < 1) { setStatus(tr("No selection")); return; } resizeDialog = new ResizeDialog(this, imageViewer); connect(resizeDialog, SIGNAL(accepted()), this, SLOT(cleanupResizeDialog())); connect(resizeDialog, SIGNAL(rejected()), this, SLOT(cleanupResizeDialog())); resizeDialog->show(); setInterfaceEnabled(false); } void Phototonic::freeRotateLeft() { --Settings::rotation; if (Settings::rotation < 0) Settings::rotation = 359; imageViewer->refresh(); imageViewer->setFeedback(tr("Rotation %1°").arg(QString::number(Settings::rotation))); } void Phototonic::freeRotateRight() { ++Settings::rotation; if (Settings::rotation > 360) Settings::rotation = 1; imageViewer->refresh(); imageViewer->setFeedback(tr("Rotation %1°").arg(QString::number(Settings::rotation))); } void Phototonic::showColorsDialog() { if (Settings::slideShowActive) { toggleSlideShow(); } if (!colorsDialog) { colorsDialog = new ColorsDialog(this, imageViewer); connect(colorsDialog, SIGNAL(accepted()), this, SLOT(cleanupColorsDialog())); connect(colorsDialog, SIGNAL(rejected()), this, SLOT(cleanupColorsDialog())); } Settings::colorsActive = true; colorsDialog->show(); colorsDialog->applyColors(0); setInterfaceEnabled(false); } void Phototonic::moveRight() { imageViewer->keyMoveEvent(ImageViewer::MoveRight); } void Phototonic::moveLeft() { imageViewer->keyMoveEvent(ImageViewer::MoveLeft); } void Phototonic::moveUp() { imageViewer->keyMoveEvent(ImageViewer::MoveUp); } void Phototonic::moveDown() { imageViewer->keyMoveEvent(ImageViewer::MoveDown); } void Phototonic::setMirrorDisabled() { imageViewer->mirrorLayout = ImageViewer::LayNone; imageViewer->refresh(); imageViewer->setFeedback(tr("Mirroring Disabled")); } void Phototonic::setMirrorDual() { imageViewer->mirrorLayout = ImageViewer::LayDual; imageViewer->refresh(); imageViewer->setFeedback(tr("Mirroring: Dual")); } void Phototonic::setMirrorTriple() { imageViewer->mirrorLayout = ImageViewer::LayTriple; imageViewer->refresh(); imageViewer->setFeedback(tr("Mirroring: Triple")); } void Phototonic::setMirrorVDual() { imageViewer->mirrorLayout = ImageViewer::LayVDual; imageViewer->refresh(); imageViewer->setFeedback(tr("Mirroring: Dual Vertical")); } void Phototonic::setMirrorQuad() { imageViewer->mirrorLayout = ImageViewer::LayQuad; imageViewer->refresh(); imageViewer->setFeedback(tr("Mirroring: Quad")); } bool Phototonic::isValidPath(QString &path) { QDir checkPath(path); if (!checkPath.exists() || !checkPath.isReadable()) { return false; } return true; } void Phototonic::pasteThumbs() { if (!copyCutThumbsCount) { return; } QString destDir; if (copyMoveToDialog) { destDir = copyMoveToDialog->selectedPath; } else { if (QApplication::focusWidget() == bookmarks) { if (bookmarks->currentItem()) { destDir = bookmarks->currentItem()->toolTip(0); } } else { destDir = getSelectedPath(); } } if (!isValidPath(destDir)) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Can not copy or move to ") + destDir); selectCurrentViewDir(); return; } bool pasteInCurrDir = (Settings::currentDirectory == destDir); QFileInfo fileInfo; if (!Settings::isCopyOperation && pasteInCurrDir) { for (int thumb = 0; thumb < Settings::copyCutFileList.size(); ++thumb) { fileInfo = QFileInfo(Settings::copyCutFileList[thumb]); if (fileInfo.absolutePath() == destDir) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Can not move to the same directory")); return; } } } CopyMoveDialog *copyMoveDialog = new CopyMoveDialog(this); copyMoveDialog->exec(thumbsViewer, destDir, pasteInCurrDir); if (pasteInCurrDir) { for (int thumb = 0; thumb < Settings::copyCutFileList.size(); ++thumb) { thumbsViewer->addThumb(Settings::copyCutFileList[thumb]); } } else { int row = copyMoveDialog->latestRow; if (thumbsViewer->thumbsViewerModel->rowCount()) { if (row >= thumbsViewer->thumbsViewerModel->rowCount()) { row = thumbsViewer->thumbsViewerModel->rowCount() - 1; } thumbsViewer->setCurrentRow(row); thumbsViewer->selectThumbByRow(row); } } QString state = QString((Settings::isCopyOperation ? tr("Copied") : tr("Moved")) + " " + tr("%n image(s)", "", copyMoveDialog->nFiles)); setStatus(state); delete (copyMoveDialog); selectCurrentViewDir(); copyCutThumbsCount = 0; Settings::copyCutIndexList.clear(); Settings::copyCutFileList.clear(); pasteAction->setEnabled(false); thumbsViewer->loadVisibleThumbs(); } void Phototonic::loadCurrentImage(int currentRow) { bool wrapImageListTmp = Settings::wrapImageList; Settings::wrapImageList = false; if (currentRow == thumbsViewer->thumbsViewerModel->rowCount()) { thumbsViewer->setCurrentRow(currentRow - 1); } if (thumbsViewer->getNextRow() < 0 && currentRow > 0) { imageViewer->loadImage(thumbsViewer->thumbsViewerModel->item(currentRow - 1)-> data(thumbsViewer->FileNameRole).toString()); } else { if (thumbsViewer->thumbsViewerModel->rowCount() == 0) { hideViewer(); refreshThumbs(true); return; } if (currentRow > (thumbsViewer->thumbsViewerModel->rowCount() - 1)) currentRow = thumbsViewer->thumbsViewerModel->rowCount() - 1; imageViewer->loadImage(thumbsViewer->thumbsViewerModel->item(currentRow)-> data(thumbsViewer->FileNameRole).toString()); } Settings::wrapImageList = wrapImageListTmp; thumbsViewer->setImageViewerWindowTitle(); } void Phototonic::deleteImages(bool trash) { // Deleting selected thumbnails if (thumbsViewer->selectionModel()->selectedIndexes().size() < 1) { setStatus(tr("No selection")); return; } if (Settings::deleteConfirm) { MessageBox msgBox(this); msgBox.setText(trash ? tr("Move selected images to the trash?") : tr("Permanently delete selected images?")); msgBox.setWindowTitle(trash ? tr("Move to Trash") : tr("Delete images")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Yes); msgBox.setButtonText(MessageBox::Yes, tr("Yes")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); if (msgBox.exec() != MessageBox::Yes) { return; } } ProgressDialog *progressDialog = new ProgressDialog(this); progressDialog->show(); int deleteFilesCount = 0; bool deleteOk; QList rows; int row; QModelIndexList indexesList; while ((indexesList = thumbsViewer->selectionModel()->selectedIndexes()).size()) { QString fileNameFullPath = thumbsViewer->thumbsViewerModel->item( indexesList.first().row())->data(thumbsViewer->FileNameRole).toString(); progressDialog->opLabel->setText("Deleting " + fileNameFullPath); QString deleteError; if (trash) { deleteOk = Trash::moveToTrash(fileNameFullPath, deleteError) == Trash::Success; } else { QFile fileToRemove(fileNameFullPath); deleteOk = fileToRemove.remove(); if (!deleteOk) { deleteError = fileToRemove.errorString(); } } ++deleteFilesCount; if (deleteOk) { row = indexesList.first().row(); rows << row; thumbsViewer->thumbsViewerModel->removeRow(row); } else { MessageBox msgBox(this); msgBox.critical(tr("Error"), (trash ? tr("Failed to move image to the trash.") : tr("Failed to delete image.")) + "\n" + deleteError); break; } Settings::filesList.removeOne(fileNameFullPath); if (progressDialog->abortOp) { break; } } if (thumbsViewer->thumbsViewerModel->rowCount() && rows.count()) { qSort(rows.begin(), rows.end()); row = rows.at(0); if (row >= thumbsViewer->thumbsViewerModel->rowCount()) { row = thumbsViewer->thumbsViewerModel->rowCount() - 1; } thumbsViewer->setCurrentRow(row); thumbsViewer->selectThumbByRow(row); } progressDialog->close(); delete (progressDialog); QString state = QString(tr("Deleted") + " " + tr("%n image(s)", "", deleteFilesCount)); setStatus(state); } void Phototonic::deleteFromViewer(bool trash) { if (imageViewer->isNewImage()) { showNewImageWarning(); return; } if (Settings::slideShowActive) { toggleSlideShow(); } imageViewer->setCursorHiding(false); bool ok; QFileInfo fileInfo = QFileInfo(imageViewer->viewerImageFullPath); QString fileName = fileInfo.fileName(); bool deleteConfirmed = true; if (Settings::deleteConfirm) { MessageBox msgBox(this); msgBox.setText(trash ? tr("Move %1 to the trash").arg(fileName) : tr("Permanently delete %1").arg(fileName)); msgBox.setWindowTitle(trash ? tr("Move to Trash") : tr("Delete images")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Yes); msgBox.setButtonText(MessageBox::Yes, tr("Yes")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); if (msgBox.exec() != MessageBox::Yes) { deleteConfirmed = false; } } if (deleteConfirmed) { int currentRow = thumbsViewer->getCurrentRow(); QString trashError; ok = trash ? (Trash::moveToTrash(imageViewer->viewerImageFullPath, trashError) == Trash::Success) : QFile::remove(imageViewer->viewerImageFullPath); if (ok) { thumbsViewer->thumbsViewerModel->removeRow(currentRow); imageViewer->setFeedback(tr("Deleted ") + fileName); } else { MessageBox msgBox(this); msgBox.critical(tr("Error"), trash ? trashError : tr("Failed to delete image")); if (isFullScreen()) { imageViewer->setCursorHiding(true); } return; } loadCurrentImage(currentRow); } if (isFullScreen()) { imageViewer->setCursorHiding(true); } } // Main delete operation void Phototonic::deleteOperation() { if (QApplication::focusWidget() == thumbsViewer->imageTags->tagsTree) { thumbsViewer->imageTags->removeTag(); return; } if (QApplication::focusWidget() == bookmarks) { bookmarks->removeBookmark(); return; } if (QApplication::focusWidget() == fileSystemTree) { deleteDirectory(true); return; } if (Settings::layoutMode == ImageViewWidget) { deleteFromViewer(true); return; } deleteImages(true); } void Phototonic::deletePermanentlyOperation() { if (QApplication::focusWidget() == fileSystemTree) { deleteDirectory(false); return; } if (Settings::layoutMode == ImageViewWidget) { deleteFromViewer(false); return; } deleteImages(false); } void Phototonic::goTo(QString path) { Settings::isFileListLoaded = false; fileListWidget->clearSelection(); thumbsViewer->setNeedToScroll(true); fileSystemTree->setCurrentIndex(fileSystemTree->fileSystemModel->index(path)); Settings::currentDirectory = path; refreshThumbs(true); } void Phototonic::goSelectedDir(const QModelIndex &idx) { Settings::isFileListLoaded = false; fileListWidget->clearSelection(); thumbsViewer->setNeedToScroll(true); Settings::currentDirectory = getSelectedPath(); refreshThumbs(true); fileSystemTree->expand(idx); } void Phototonic::goPathBarDir() { thumbsViewer->setNeedToScroll(true); QDir checkPath(pathLineEdit->text()); if (!checkPath.exists() || !checkPath.isReadable()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Invalid Path:") + " " + pathLineEdit->text()); pathLineEdit->setText(Settings::currentDirectory); return; } Settings::currentDirectory = pathLineEdit->text(); refreshThumbs(true); selectCurrentViewDir(); } void Phototonic::bookmarkClicked(QTreeWidgetItem *item, int col) { goTo(item->toolTip(col)); } void Phototonic::setThumbsFilter() { thumbsViewer->filterString = filterLineEdit->text(); refreshThumbs(true); } void Phototonic::clearThumbsFilter() { if (filterLineEdit->text() == "") { thumbsViewer->filterString = filterLineEdit->text(); refreshThumbs(true); } } void Phototonic::goBack() { if (currentHistoryIdx > 0) { needHistoryRecord = false; goTo(pathHistoryList.at(--currentHistoryIdx)); goFrwdAction->setEnabled(true); if (currentHistoryIdx == 0) goBackAction->setEnabled(false); } } void Phototonic::goForward() { if (currentHistoryIdx < pathHistoryList.size() - 1) { needHistoryRecord = false; goTo(pathHistoryList.at(++currentHistoryIdx)); if (currentHistoryIdx == (pathHistoryList.size() - 1)) goFrwdAction->setEnabled(false); } } void Phototonic::goUp() { QFileInfo fileInfo = QFileInfo(Settings::currentDirectory); goTo(fileInfo.dir().absolutePath()); } void Phototonic::goHome() { goTo(QDir::homePath()); } void Phototonic::setCopyCutActions(bool setEnabled) { cutAction->setEnabled(setEnabled); copyAction->setEnabled(setEnabled); } void Phototonic::updateActions() { if (QApplication::focusWidget() == thumbsViewer) { bool hasSelectedItems = thumbsViewer->selectionModel()->selectedIndexes().size() > 0; setCopyCutActions(hasSelectedItems); } else if (QApplication::focusWidget() == bookmarks) { setCopyCutActions(false); } else if (QApplication::focusWidget() == fileSystemTree) { setCopyCutActions(false); } else if (Settings::layoutMode == ImageViewWidget || QApplication::focusWidget() == imageViewer->scrollArea) { setCopyCutActions(false); } else { setCopyCutActions(false); } if (Settings::layoutMode == ImageViewWidget && !interfaceDisabled) { setViewerKeyEventsEnabled(true); fullScreenAction->setEnabled(true); CloseImageAction->setEnabled(true); } else { if (QApplication::focusWidget() == imageViewer->scrollArea) { setViewerKeyEventsEnabled(true); fullScreenAction->setEnabled(false); CloseImageAction->setEnabled(false); } else { setViewerKeyEventsEnabled(false); fullScreenAction->setEnabled(false); CloseImageAction->setEnabled(false); } } } void Phototonic::writeSettings() { if (Settings::layoutMode == ThumbViewWidget) { Settings::appSettings->setValue(Settings::optionGeometry, saveGeometry()); Settings::appSettings->setValue(Settings::optionWindowState, saveState()); } Settings::appSettings->setValue(Settings::optionThumbsSortFlags, (int) thumbsViewer->thumbsSortFlags); Settings::appSettings->setValue(Settings::optionThumbsZoomLevel, thumbsViewer->thumbSize); Settings::appSettings->setValue(Settings::optionFullScreenMode, (bool) Settings::isFullScreen); Settings::appSettings->setValue(Settings::optionViewerBackgroundColor, Settings::viewerBackgroundColor); Settings::appSettings->setValue(Settings::optionThumbsBackgroundColor, Settings::thumbsBackgroundColor); Settings::appSettings->setValue(Settings::optionThumbsTextColor, Settings::thumbsTextColor); Settings::appSettings->setValue(Settings::optionThumbsPagesReadCount, (int) Settings::thumbsPagesReadCount); Settings::appSettings->setValue(Settings::optionEnableAnimations, (bool) Settings::enableAnimations); Settings::appSettings->setValue(Settings::optionExifRotationEnabled, (bool) Settings::exifRotationEnabled); Settings::appSettings->setValue(Settings::optionExifThumbRotationEnabled, (bool) Settings::exifThumbRotationEnabled); Settings::appSettings->setValue(Settings::optionReverseMouseBehavior, (bool) Settings::reverseMouseBehavior); Settings::appSettings->setValue(Settings::optionDeleteConfirm, (bool) Settings::deleteConfirm); Settings::appSettings->setValue(Settings::optionShowHiddenFiles, (bool) Settings::showHiddenFiles); Settings::appSettings->setValue(Settings::optionWrapImageList, (bool) Settings::wrapImageList); Settings::appSettings->setValue(Settings::optionImageZoomFactor, Settings::imageZoomFactor); Settings::appSettings->setValue(Settings::optionShouldMaximize, (bool) isMaximized()); Settings::appSettings->setValue(Settings::optionDefaultSaveQuality, Settings::defaultSaveQuality); Settings::appSettings->setValue(Settings::optionSlideShowDelay, Settings::slideShowDelay); Settings::appSettings->setValue(Settings::optionSlideShowRandom, (bool) Settings::slideShowRandom); Settings::appSettings->setValue(Settings::optionEditToolBarVisible, (bool) editToolBarVisible); Settings::appSettings->setValue(Settings::optionGoToolBarVisible, (bool) goToolBarVisible); Settings::appSettings->setValue(Settings::optionViewToolBarVisible, (bool) viewToolBarVisible); Settings::appSettings->setValue(Settings::optionImageToolBarVisible, (bool) imageToolBarVisible); Settings::appSettings->setValue(Settings::optionFileSystemDockVisible, (bool) Settings::fileSystemDockVisible); Settings::appSettings->setValue(Settings::optionImageInfoDockVisible, (bool) Settings::imageInfoDockVisible); Settings::appSettings->setValue(Settings::optionBookmarksDockVisible, (bool) Settings::bookmarksDockVisible); Settings::appSettings->setValue(Settings::optionTagsDockVisible, (bool) Settings::tagsDockVisible); Settings::appSettings->setValue(Settings::optionImagePreviewDockVisible, (bool) Settings::imagePreviewDockVisible); Settings::appSettings->setValue(Settings::optionStartupDir, (int) Settings::startupDir); Settings::appSettings->setValue(Settings::optionSpecifiedStartDir, Settings::specifiedStartDir); Settings::appSettings->setValue(Settings::optionThumbsBackgroundImage, Settings::thumbsBackgroundImage); Settings::appSettings->setValue(Settings::optionLastDir, Settings::startupDir == Settings::RememberLastDir ? Settings::currentDirectory : ""); Settings::appSettings->setValue(Settings::optionShowImageName, (bool) Settings::showImageName); Settings::appSettings->setValue(Settings::optionSmallToolbarIcons, (bool) Settings::smallToolbarIcons); Settings::appSettings->setValue(Settings::optionHideDockTitlebars, (bool) Settings::hideDockTitlebars); Settings::appSettings->setValue(Settings::optionShowViewerToolbar, (bool) Settings::showViewerToolbar); Settings::appSettings->setValue(Settings::optionSetWindowIcon, (bool) Settings::setWindowIcon); /* Action shortcuts */ Settings::appSettings->beginGroup(Settings::optionShortcuts); QMapIterator shortcutsIterator(Settings::actionKeys); while (shortcutsIterator.hasNext()) { shortcutsIterator.next(); Settings::appSettings->setValue(shortcutsIterator.key(), shortcutsIterator.value()->shortcut().toString()); } Settings::appSettings->endGroup(); /* External apps */ Settings::appSettings->beginGroup(Settings::optionExternalApps); Settings::appSettings->remove(""); QMapIterator eaIter(Settings::externalApps); while (eaIter.hasNext()) { eaIter.next(); Settings::appSettings->setValue(eaIter.key(), eaIter.value()); } Settings::appSettings->endGroup(); /* save bookmarks */ int idx = 0; Settings::appSettings->beginGroup(Settings::optionCopyMoveToPaths); Settings::appSettings->remove(""); QSetIterator pathsIter(Settings::bookmarkPaths); while (pathsIter.hasNext()) { Settings::appSettings->setValue("path" + QString::number(++idx), pathsIter.next()); } Settings::appSettings->endGroup(); /* save known Tags */ idx = 0; Settings::appSettings->beginGroup(Settings::optionKnownTags); Settings::appSettings->remove(""); QSetIterator tagsIter(Settings::knownTags); while (tagsIter.hasNext()) { Settings::appSettings->setValue("tag" + QString::number(++idx), tagsIter.next()); } Settings::appSettings->endGroup(); } void Phototonic::readSettings() { initComplete = false; needThumbsRefresh = false; if (!Settings::appSettings->contains(Settings::optionThumbsZoomLevel)) { resize(800, 600); Settings::appSettings->setValue(Settings::optionThumbsSortFlags, (int) 0); Settings::appSettings->setValue(Settings::optionThumbsZoomLevel, (int) 200); Settings::appSettings->setValue(Settings::optionFullScreenMode, (bool) false); Settings::appSettings->setValue(Settings::optionViewerBackgroundColor, QColor(25, 25, 25)); Settings::appSettings->setValue(Settings::optionThumbsBackgroundColor, QColor(200, 200, 200)); Settings::appSettings->setValue(Settings::optionThumbsTextColor, QColor(25, 25, 25)); Settings::appSettings->setValue(Settings::optionThumbsPagesReadCount, (int) 2); Settings::appSettings->setValue(Settings::optionViewerZoomOutFlags, (int) 1); Settings::appSettings->setValue(Settings::optionViewerZoomInFlags, (int) 0); Settings::appSettings->setValue(Settings::optionWrapImageList, (bool) false); Settings::appSettings->setValue(Settings::optionImageZoomFactor, (float) 1.0); Settings::appSettings->setValue(Settings::optionDefaultSaveQuality, (int) 90); Settings::appSettings->setValue(Settings::optionEnableAnimations, (bool) true); Settings::appSettings->setValue(Settings::optionExifRotationEnabled, (bool) true); Settings::appSettings->setValue(Settings::optionExifThumbRotationEnabled, (bool) false); Settings::appSettings->setValue(Settings::optionReverseMouseBehavior, (bool) false); Settings::appSettings->setValue(Settings::optionDeleteConfirm, (bool) true); Settings::appSettings->setValue(Settings::optionShowHiddenFiles, (bool) false); Settings::appSettings->setValue(Settings::optionSlideShowDelay, (int) 5); Settings::appSettings->setValue(Settings::optionSlideShowRandom, (bool) false); Settings::appSettings->setValue(Settings::optionEditToolBarVisible, (bool) true); Settings::appSettings->setValue(Settings::optionGoToolBarVisible, (bool) true); Settings::appSettings->setValue(Settings::optionViewToolBarVisible, (bool) true); Settings::appSettings->setValue(Settings::optionImageToolBarVisible, (bool) false); Settings::appSettings->setValue(Settings::optionFileSystemDockVisible, (bool) true); Settings::appSettings->setValue(Settings::optionBookmarksDockVisible, (bool) true); Settings::appSettings->setValue(Settings::optionTagsDockVisible, (bool) true); Settings::appSettings->setValue(Settings::optionImagePreviewDockVisible, (bool) true); Settings::appSettings->setValue(Settings::optionImageInfoDockVisible, (bool) true); Settings::appSettings->setValue(Settings::optionShowImageName, (bool) false); Settings::appSettings->setValue(Settings::optionSmallToolbarIcons, (bool) false); Settings::appSettings->setValue(Settings::optionHideDockTitlebars, (bool) false); Settings::appSettings->setValue(Settings::optionShowViewerToolbar, (bool) false); Settings::appSettings->setValue(Settings::optionSmallToolbarIcons, (bool) true); Settings::bookmarkPaths.insert(QDir::homePath()); const QString picturesLocation = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); if (!picturesLocation.isEmpty()) { Settings::bookmarkPaths.insert(picturesLocation); } } Settings::viewerBackgroundColor = Settings::appSettings->value( Settings::optionViewerBackgroundColor).value(); Settings::enableAnimations = Settings::appSettings->value(Settings::optionEnableAnimations).toBool(); Settings::exifRotationEnabled = Settings::appSettings->value(Settings::optionExifRotationEnabled).toBool(); Settings::exifThumbRotationEnabled = Settings::appSettings->value( Settings::optionExifThumbRotationEnabled).toBool(); Settings::reverseMouseBehavior = Settings::appSettings->value(Settings::optionReverseMouseBehavior).toBool(); Settings::deleteConfirm = Settings::appSettings->value(Settings::optionDeleteConfirm).toBool(); Settings::showHiddenFiles = Settings::appSettings->value(Settings::optionShowHiddenFiles).toBool(); Settings::wrapImageList = Settings::appSettings->value(Settings::optionWrapImageList).toBool(); Settings::imageZoomFactor = Settings::appSettings->value(Settings::optionImageZoomFactor).toFloat(); Settings::zoomOutFlags = Settings::appSettings->value(Settings::optionViewerZoomOutFlags).toUInt(); Settings::zoomInFlags = Settings::appSettings->value(Settings::optionViewerZoomInFlags).toUInt(); Settings::rotation = 0; Settings::keepTransform = false; shouldMaximize = Settings::appSettings->value(Settings::optionShouldMaximize).toBool(); Settings::flipH = false; Settings::flipV = false; Settings::defaultSaveQuality = Settings::appSettings->value(Settings::optionDefaultSaveQuality).toInt(); Settings::slideShowDelay = Settings::appSettings->value(Settings::optionSlideShowDelay).toInt(); Settings::slideShowRandom = Settings::appSettings->value(Settings::optionSlideShowRandom).toBool(); Settings::slideShowActive = false; editToolBarVisible = Settings::appSettings->value(Settings::optionEditToolBarVisible).toBool(); goToolBarVisible = Settings::appSettings->value(Settings::optionGoToolBarVisible).toBool(); viewToolBarVisible = Settings::appSettings->value(Settings::optionViewToolBarVisible).toBool(); imageToolBarVisible = Settings::appSettings->value(Settings::optionImageToolBarVisible).toBool(); Settings::fileSystemDockVisible = Settings::appSettings->value(Settings::optionFileSystemDockVisible).toBool(); Settings::bookmarksDockVisible = Settings::appSettings->value(Settings::optionBookmarksDockVisible).toBool(); Settings::tagsDockVisible = Settings::appSettings->value(Settings::optionTagsDockVisible).toBool(); Settings::imagePreviewDockVisible = Settings::appSettings->value(Settings::optionImagePreviewDockVisible).toBool(); Settings::imageInfoDockVisible = Settings::appSettings->value(Settings::optionImageInfoDockVisible).toBool(); Settings::startupDir = (Settings::StartupDir) Settings::appSettings->value(Settings::optionStartupDir).toInt(); Settings::specifiedStartDir = Settings::appSettings->value(Settings::optionSpecifiedStartDir).toString(); Settings::thumbsBackgroundImage = Settings::appSettings->value(Settings::optionThumbsBackgroundImage).toString(); Settings::showImageName = Settings::appSettings->value(Settings::optionShowImageName).toBool(); Settings::smallToolbarIcons = Settings::appSettings->value(Settings::optionSmallToolbarIcons).toBool(); Settings::hideDockTitlebars = Settings::appSettings->value(Settings::optionHideDockTitlebars).toBool(); Settings::showViewerToolbar = Settings::appSettings->value(Settings::optionShowViewerToolbar).toBool(); Settings::setWindowIcon = Settings::appSettings->value(Settings::optionSetWindowIcon).toBool(); /* read external apps */ Settings::appSettings->beginGroup(Settings::optionExternalApps); QStringList extApps = Settings::appSettings->childKeys(); for (int i = 0; i < extApps.size(); ++i) { Settings::externalApps[extApps.at(i)] = Settings::appSettings->value(extApps.at(i)).toString(); } Settings::appSettings->endGroup(); /* read bookmarks */ Settings::appSettings->beginGroup(Settings::optionCopyMoveToPaths); QStringList paths = Settings::appSettings->childKeys(); for (int i = 0; i < paths.size(); ++i) { Settings::bookmarkPaths.insert(Settings::appSettings->value(paths.at(i)).toString()); } Settings::appSettings->endGroup(); /* read known tags */ Settings::appSettings->beginGroup(Settings::optionKnownTags); QStringList tags = Settings::appSettings->childKeys(); for (int i = 0; i < tags.size(); ++i) { Settings::knownTags.insert(Settings::appSettings->value(tags.at(i)).toString()); } Settings::appSettings->endGroup(); Settings::isFileListLoaded = false; } void Phototonic::setupDocks() { addDockWidget(Qt::RightDockWidgetArea, imageInfoDock); addDockWidget(Qt::RightDockWidgetArea, tagsDock); menuBar()->addMenu(createPopupMenu())->setText(tr("Window")); menuBar()->addSeparator(); helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addAction(aboutAction); fileSystemDockOrigWidget = fileSystemDock->titleBarWidget(); bookmarksDockOrigWidget = bookmarksDock->titleBarWidget(); imagePreviewDockOrigWidget = imagePreviewDock->titleBarWidget(); tagsDockOrigWidget = tagsDock->titleBarWidget(); imageInfoDockOrigWidget = imageInfoDock->titleBarWidget(); fileSystemDockEmptyWidget = new QWidget; bookmarksDockEmptyWidget = new QWidget; imagePreviewDockEmptyWidget = new QWidget; tagsDockEmptyWidget = new QWidget; imageInfoDockEmptyWidget = new QWidget; lockDocks(); } void Phototonic::lockDocks() { if (initComplete) Settings::hideDockTitlebars = lockDocksAction->isChecked(); if (Settings::hideDockTitlebars) { fileSystemDock->setTitleBarWidget(fileSystemDockEmptyWidget); bookmarksDock->setTitleBarWidget(bookmarksDockEmptyWidget); imagePreviewDock->setTitleBarWidget(imagePreviewDockEmptyWidget); tagsDock->setTitleBarWidget(tagsDockEmptyWidget); imageInfoDock->setTitleBarWidget(imageInfoDockEmptyWidget); } else { fileSystemDock->setTitleBarWidget(fileSystemDockOrigWidget); bookmarksDock->setTitleBarWidget(bookmarksDockOrigWidget); imagePreviewDock->setTitleBarWidget(imagePreviewDockOrigWidget); tagsDock->setTitleBarWidget(tagsDockOrigWidget); imageInfoDock->setTitleBarWidget(imageInfoDockOrigWidget); } } QMenu *Phototonic::createPopupMenu() { QMenu *extraActsMenu = QMainWindow::createPopupMenu(); extraActsMenu->addSeparator(); extraActsMenu->addAction(smallToolbarIconsAction); extraActsMenu->addAction(lockDocksAction); return extraActsMenu; } void Phototonic::loadShortcuts() { // Add customizable key shortcut actions Settings::actionKeys[thumbsGoToTopAction->objectName()] = thumbsGoToTopAction; Settings::actionKeys[thumbsGoToBottomAction->objectName()] = thumbsGoToBottomAction; Settings::actionKeys[CloseImageAction->objectName()] = CloseImageAction; Settings::actionKeys[fullScreenAction->objectName()] = fullScreenAction; Settings::actionKeys[settingsAction->objectName()] = settingsAction; Settings::actionKeys[exitAction->objectName()] = exitAction; Settings::actionKeys[thumbsZoomInAction->objectName()] = thumbsZoomInAction; Settings::actionKeys[thumbsZoomOutAction->objectName()] = thumbsZoomOutAction; Settings::actionKeys[cutAction->objectName()] = cutAction; Settings::actionKeys[copyAction->objectName()] = copyAction; Settings::actionKeys[nextImageAction->objectName()] = nextImageAction; Settings::actionKeys[prevImageAction->objectName()] = prevImageAction; Settings::actionKeys[deletePermanentlyAction->objectName()] = deletePermanentlyAction; Settings::actionKeys[deleteAction->objectName()] = deleteAction; Settings::actionKeys[saveAction->objectName()] = saveAction; Settings::actionKeys[saveAsAction->objectName()] = saveAsAction; Settings::actionKeys[keepTransformAction->objectName()] = keepTransformAction; Settings::actionKeys[keepZoomAction->objectName()] = keepZoomAction; Settings::actionKeys[showClipboardAction->objectName()] = showClipboardAction; Settings::actionKeys[copyImageAction->objectName()] = copyImageAction; Settings::actionKeys[pasteImageAction->objectName()] = pasteImageAction; Settings::actionKeys[renameAction->objectName()] = renameAction; Settings::actionKeys[refreshAction->objectName()] = refreshAction; Settings::actionKeys[pasteAction->objectName()] = pasteAction; Settings::actionKeys[goBackAction->objectName()] = goBackAction; Settings::actionKeys[goFrwdAction->objectName()] = goFrwdAction; Settings::actionKeys[slideShowAction->objectName()] = slideShowAction; Settings::actionKeys[firstImageAction->objectName()] = firstImageAction; Settings::actionKeys[lastImageAction->objectName()] = lastImageAction; Settings::actionKeys[randomImageAction->objectName()] = randomImageAction; Settings::actionKeys[viewImageAction->objectName()] = viewImageAction; Settings::actionKeys[zoomOutAction->objectName()] = zoomOutAction; Settings::actionKeys[zoomInAction->objectName()] = zoomInAction; Settings::actionKeys[resetZoomAction->objectName()] = resetZoomAction; Settings::actionKeys[origZoomAction->objectName()] = origZoomAction; Settings::actionKeys[rotateLeftAction->objectName()] = rotateLeftAction; Settings::actionKeys[rotateRightAction->objectName()] = rotateRightAction; Settings::actionKeys[freeRotateLeftAction->objectName()] = freeRotateLeftAction; Settings::actionKeys[freeRotateRightAction->objectName()] = freeRotateRightAction; Settings::actionKeys[flipHorizontalAction->objectName()] = flipHorizontalAction; Settings::actionKeys[flipVerticalAction->objectName()] = flipVerticalAction; Settings::actionKeys[cropAction->objectName()] = cropAction; Settings::actionKeys[cropToSelectionAction->objectName()] = cropToSelectionAction; Settings::actionKeys[colorsAction->objectName()] = colorsAction; Settings::actionKeys[mirrorDisabledAction->objectName()] = mirrorDisabledAction; Settings::actionKeys[mirrorDualAction->objectName()] = mirrorDualAction; Settings::actionKeys[mirrorTripleAction->objectName()] = mirrorTripleAction; Settings::actionKeys[mirrorDualVerticalAction->objectName()] = mirrorDualVerticalAction; Settings::actionKeys[mirrorQuadAction->objectName()] = mirrorQuadAction; Settings::actionKeys[moveDownAction->objectName()] = moveDownAction; Settings::actionKeys[moveUpAction->objectName()] = moveUpAction; Settings::actionKeys[moveRightAction->objectName()] = moveRightAction; Settings::actionKeys[moveLeftAction->objectName()] = moveLeftAction; Settings::actionKeys[copyToAction->objectName()] = copyToAction; Settings::actionKeys[moveToAction->objectName()] = moveToAction; Settings::actionKeys[goUpAction->objectName()] = goUpAction; Settings::actionKeys[resizeAction->objectName()] = resizeAction; Settings::actionKeys[filterImagesFocusAction->objectName()] = filterImagesFocusAction; Settings::actionKeys[setPathFocusAction->objectName()] = setPathFocusAction; Settings::actionKeys[invertSelectionAction->objectName()] = invertSelectionAction; Settings::actionKeys[includeSubDirectoriesAction->objectName()] = includeSubDirectoriesAction; Settings::actionKeys[createDirectoryAction->objectName()] = createDirectoryAction; Settings::actionKeys[addBookmarkAction->objectName()] = addBookmarkAction; Settings::actionKeys[removeMetadataAction->objectName()] = removeMetadataAction; Settings::actionKeys[externalAppsAction->objectName()] = externalAppsAction; Settings::actionKeys[goHomeAction->objectName()] = goHomeAction; Settings::actionKeys[sortByNameAction->objectName()] = sortByNameAction; Settings::actionKeys[sortBySizeAction->objectName()] = sortBySizeAction; Settings::actionKeys[sortByTimeAction->objectName()] = sortByTimeAction; Settings::actionKeys[sortByTypeAction->objectName()] = sortByTypeAction; Settings::actionKeys[sortReverseAction->objectName()] = sortReverseAction; Settings::actionKeys[showHiddenFilesAction->objectName()] = showHiddenFilesAction; Settings::actionKeys[showViewerToolbarAction->objectName()] = showViewerToolbarAction; Settings::appSettings->beginGroup(Settings::optionShortcuts); QStringList groupKeys = Settings::appSettings->childKeys(); if (groupKeys.size()) { if (groupKeys.contains(thumbsGoToTopAction->text())) { QMapIterator key(Settings::actionKeys); while (key.hasNext()) { key.next(); if (groupKeys.contains(key.value()->text())) { key.value()->setShortcut(Settings::appSettings->value(key.value()->text()).toString()); Settings::appSettings->remove(key.value()->text()); Settings::appSettings->setValue(key.key(), key.value()->shortcut().toString()); } } } else { for (int i = 0; i < groupKeys.size(); ++i) { if (Settings::actionKeys.value(groupKeys.at(i))) Settings::actionKeys.value(groupKeys.at(i))->setShortcut (Settings::appSettings->value(groupKeys.at(i)).toString()); } } } else { thumbsGoToTopAction->setShortcut(QKeySequence("Ctrl+Home")); thumbsGoToBottomAction->setShortcut(QKeySequence("Ctrl+End")); CloseImageAction->setShortcut(Qt::Key_Escape); fullScreenAction->setShortcut(QKeySequence("Alt+Return")); settingsAction->setShortcut(QKeySequence("Ctrl+P")); exitAction->setShortcut(QKeySequence("Ctrl+Q")); cutAction->setShortcut(QKeySequence("Ctrl+X")); copyAction->setShortcut(QKeySequence("Ctrl+C")); deleteAction->setShortcut(QKeySequence("Del")); deletePermanentlyAction->setShortcut(QKeySequence("Shift+Del")); saveAction->setShortcut(QKeySequence("Ctrl+S")); copyImageAction->setShortcut(QKeySequence("Ctrl+Shift+C")); pasteImageAction->setShortcut(QKeySequence("Ctrl+Shift+V")); renameAction->setShortcut(QKeySequence("F2")); refreshAction->setShortcut(QKeySequence("F5")); pasteAction->setShortcut(QKeySequence("Ctrl+V")); goBackAction->setShortcut(QKeySequence("Alt+Left")); goFrwdAction->setShortcut(QKeySequence("Alt+Right")); goUpAction->setShortcut(QKeySequence("Alt+Up")); slideShowAction->setShortcut(QKeySequence("Ctrl+W")); nextImageAction->setShortcut(QKeySequence("PgDown")); prevImageAction->setShortcut(QKeySequence("PgUp")); firstImageAction->setShortcut(QKeySequence("Home")); lastImageAction->setShortcut(QKeySequence("End")); randomImageAction->setShortcut(QKeySequence("Ctrl+D")); viewImageAction->setShortcut(QKeySequence("Return")); zoomOutAction->setShortcut(QKeySequence("-")); zoomInAction->setShortcut(QKeySequence("+")); resetZoomAction->setShortcut(QKeySequence("*")); origZoomAction->setShortcut(QKeySequence("/")); rotateLeftAction->setShortcut(QKeySequence("Ctrl+Left")); rotateRightAction->setShortcut(QKeySequence("Ctrl+Right")); freeRotateLeftAction->setShortcut(QKeySequence("Ctrl+Shift+Left")); freeRotateRightAction->setShortcut(QKeySequence("Ctrl+Shift+Right")); flipHorizontalAction->setShortcut(QKeySequence("Ctrl+Down")); flipVerticalAction->setShortcut(QKeySequence("Ctrl+Up")); cropAction->setShortcut(QKeySequence("Ctrl+G")); cropToSelectionAction->setShortcut(QKeySequence("Ctrl+R")); colorsAction->setShortcut(QKeySequence("Ctrl+O")); mirrorDisabledAction->setShortcut(QKeySequence("Ctrl+1")); mirrorDualAction->setShortcut(QKeySequence("Ctrl+2")); mirrorTripleAction->setShortcut(QKeySequence("Ctrl+3")); mirrorDualVerticalAction->setShortcut(QKeySequence("Ctrl+4")); mirrorQuadAction->setShortcut(QKeySequence("Ctrl+5")); moveDownAction->setShortcut(QKeySequence("Down")); moveUpAction->setShortcut(QKeySequence("Up")); moveLeftAction->setShortcut(QKeySequence("Left")); moveRightAction->setShortcut(QKeySequence("Right")); copyToAction->setShortcut(QKeySequence("Ctrl+Y")); moveToAction->setShortcut(QKeySequence("Ctrl+M")); resizeAction->setShortcut(QKeySequence("Ctrl+I")); filterImagesFocusAction->setShortcut(QKeySequence("Ctrl+F")); setPathFocusAction->setShortcut(QKeySequence("Ctrl+L")); keepTransformAction->setShortcut(QKeySequence("Ctrl+K")); showHiddenFilesAction->setShortcut(QKeySequence("Ctrl+H")); } Settings::appSettings->endGroup(); } void Phototonic::closeEvent(QCloseEvent *event) { thumbsViewer->abort(); writeSettings(); hide(); if (!QApplication::clipboard()->image().isNull()) { QApplication::clipboard()->clear(); } event->accept(); } void Phototonic::setStatus(QString state) { statusLabel->setText(" " + state + " "); } void Phototonic::mouseDoubleClickEvent(QMouseEvent *event) { if (interfaceDisabled) { return; } if (event->button() == Qt::LeftButton) { if (Settings::layoutMode == ImageViewWidget) { if (Settings::reverseMouseBehavior) { fullScreenAction->setChecked(!(fullScreenAction->isChecked())); toggleFullScreen(); event->accept(); } else if (CloseImageAction->isEnabled()) { hideViewer(); event->accept(); } } else { if (QApplication::focusWidget() == thumbsViewer->imagePreview->scrollArea) { viewImage(); } } } } void Phototonic::mousePressEvent(QMouseEvent *event) { if (interfaceDisabled) { return; } if (Settings::layoutMode == ImageViewWidget) { if (event->button() == Qt::MiddleButton) { if (event->modifiers() == Qt::ShiftModifier) { origZoom(); event->accept(); return; } if (event->modifiers() == Qt::ControlModifier) { resetZoom(); event->accept(); return; } if (Settings::reverseMouseBehavior && CloseImageAction->isEnabled()) { hideViewer(); event->accept(); } else { fullScreenAction->setChecked(!(fullScreenAction->isChecked())); toggleFullScreen(); event->accept(); } } } else if (QApplication::focusWidget() == thumbsViewer->imagePreview->scrollArea) { if (event->button() == Qt::MiddleButton) { viewImage(); } } } void Phototonic::newImage() { if (Settings::layoutMode == ThumbViewWidget) { showViewer(); } imageViewer->loadImage(""); } void Phototonic::setDocksVisibility(bool visible) { fileSystemDock->setVisible(visible ? Settings::fileSystemDockVisible : false); bookmarksDock->setVisible(visible ? Settings::bookmarksDockVisible : false); imagePreviewDock->setVisible(visible ? Settings::imagePreviewDockVisible : false); tagsDock->setVisible(visible ? Settings::tagsDockVisible : false); imageInfoDock->setVisible(visible ? Settings::imageInfoDockVisible : false); menuBar()->setVisible(visible); menuBar()->setDisabled(!visible); statusBar()->setVisible(visible); editToolBar->setVisible(visible ? editToolBarVisible : false); goToolBar->setVisible(visible ? goToolBarVisible : false); viewToolBar->setVisible(visible ? viewToolBarVisible : false); imageToolBar->setVisible(visible ? imageToolBarVisible : Settings::showViewerToolbar); addToolBar(imageToolBar); setContextMenuPolicy(Qt::PreventContextMenu); } void Phototonic::viewImage() { if (Settings::layoutMode == ImageViewWidget) { hideViewer(); return; } if (QApplication::focusWidget() == fileSystemTree) { goSelectedDir(fileSystemTree->getCurrentIndex()); return; } else if (QApplication::focusWidget() == thumbsViewer || QApplication::focusWidget() == thumbsViewer->imagePreview->scrollArea || QApplication::focusWidget() == imageViewer->scrollArea) { QModelIndex selectedImageIndex; QModelIndexList selectedIndexes = thumbsViewer->selectionModel()->selectedIndexes(); if (selectedIndexes.size() > 0) { selectedImageIndex = selectedIndexes.first(); } else { if (thumbsViewer->thumbsViewerModel->rowCount() == 0) { setStatus(tr("No images")); return; } selectedImageIndex = thumbsViewer->thumbsViewerModel->indexFromItem( thumbsViewer->thumbsViewerModel->item(0)); thumbsViewer->selectionModel()->select(selectedImageIndex, QItemSelectionModel::Toggle); thumbsViewer->setCurrentRow(0); } loadSelectedThumbImage(selectedImageIndex); return; } else if (QApplication::focusWidget() == filterLineEdit) { setThumbsFilter(); return; } else if (QApplication::focusWidget() == pathLineEdit) { goPathBarDir(); return; } } void Phototonic::setEditToolBarVisibility() { editToolBarVisible = editToolBar->isVisible(); } void Phototonic::setGoToolBarVisibility() { goToolBarVisible = goToolBar->isVisible(); } void Phototonic::setViewToolBarVisibility() { viewToolBarVisible = viewToolBar->isVisible(); } void Phototonic::setImageToolBarVisibility() { imageToolBarVisible = imageToolBar->isVisible(); } void Phototonic::setFileSystemDockVisibility() { if (Settings::layoutMode != ImageViewWidget) { Settings::fileSystemDockVisible = fileSystemDock->isVisible(); } } void Phototonic::setBookmarksDockVisibility() { if (Settings::layoutMode != ImageViewWidget) { Settings::bookmarksDockVisible = bookmarksDock->isVisible(); } } void Phototonic::setImagePreviewDockVisibility() { if (Settings::layoutMode != ImageViewWidget) { Settings::imagePreviewDockVisible = imagePreviewDock->isVisible(); } } void Phototonic::setTagsDockVisibility() { if (Settings::layoutMode != ImageViewWidget) { Settings::tagsDockVisible = tagsDock->isVisible(); } } void Phototonic::setImageInfoDockVisibility() { if (Settings::layoutMode != ImageViewWidget) { Settings::imageInfoDockVisible = imageInfoDock->isVisible(); } } void Phototonic::showViewer() { if (Settings::layoutMode == ThumbViewWidget) { Settings::layoutMode = ImageViewWidget; Settings::appSettings->setValue("Geometry", saveGeometry()); Settings::appSettings->setValue("WindowState", saveState()); stackedLayout->setCurrentWidget(imageViewer); setDocksVisibility(false); if (Settings::isFullScreen) { shouldMaximize = isMaximized(); showFullScreen(); imageViewer->setCursorHiding(true); QApplication::processEvents(); } imageViewer->setFocus(Qt::OtherFocusReason); } } void Phototonic::showBusyAnimation(bool busy) { static int busyStatus = 0; if (busy) { ++busyStatus; } else { --busyStatus; } if (busyStatus > 0) { busyMovie->start(); busyLabel->setVisible(true); } else { busyLabel->setVisible(false); busyMovie->stop(); busyStatus = 0; } } void Phototonic::loadSelectedThumbImage(const QModelIndex &idx) { thumbsViewer->setCurrentRow(idx.row()); showViewer(); imageViewer->loadImage( thumbsViewer->thumbsViewerModel->item(idx.row())->data(thumbsViewer->FileNameRole).toString()); thumbsViewer->setImageViewerWindowTitle(); } void Phototonic::loadImageFromCliArguments(QString cliFileName) { QFile imageFile(cliFileName); if (!imageFile.exists()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to open file %1, file not found.").arg(cliFileName)); return; } showViewer(); imageViewer->loadImage(cliFileName); setWindowTitle(cliFileName + " - Phototonic"); } void Phototonic::toggleSlideShow() { if (Settings::slideShowActive) { Settings::slideShowActive = false; slideShowAction->setText(tr("Slide Show")); imageViewer->setFeedback(tr("Slide show stopped")); SlideShowTimer->stop(); delete SlideShowTimer; slideShowAction->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/images/play.png"))); } else { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } if (Settings::layoutMode == ThumbViewWidget) { QModelIndexList indexesList = thumbsViewer->selectionModel()->selectedIndexes(); if (indexesList.size() != 1) { thumbsViewer->setCurrentRow(0); } else { thumbsViewer->setCurrentRow(indexesList.first().row()); } showViewer(); } Settings::slideShowActive = true; SlideShowTimer = new QTimer(this); connect(SlideShowTimer, SIGNAL(timeout()), this, SLOT(slideShowHandler())); SlideShowTimer->start(Settings::slideShowDelay * 1000); slideShowAction->setText(tr("Stop Slide Show")); imageViewer->setFeedback(tr("Slide show started")); slideShowAction->setIcon(QIcon::fromTheme("media-playback-stop", QIcon(":/images/stop.png"))); slideShowHandler(); } } void Phototonic::slideShowHandler() { if (Settings::slideShowActive) { if (Settings::slideShowRandom) { loadRandomImage(); } else { int currentRow = thumbsViewer->getCurrentRow(); imageViewer->loadImage( thumbsViewer->thumbsViewerModel->item(currentRow)->data(thumbsViewer->FileNameRole).toString()); thumbsViewer->setImageViewerWindowTitle(); if (thumbsViewer->getNextRow() > 0) { thumbsViewer->setCurrentRow(thumbsViewer->getNextRow()); } else { if (Settings::wrapImageList) { thumbsViewer->setCurrentRow(0); } else { toggleSlideShow(); } } } } } void Phototonic::loadNextImage() { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } int nextThumb = thumbsViewer->getNextRow(); if (nextThumb < 0) { if (Settings::wrapImageList) { nextThumb = 0; } else { return; } } if (Settings::layoutMode == ImageViewWidget) { imageViewer->loadImage( thumbsViewer->thumbsViewerModel->item(nextThumb)->data(thumbsViewer->FileNameRole).toString()); } thumbsViewer->setCurrentRow(nextThumb); thumbsViewer->setImageViewerWindowTitle(); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->selectThumbByRow(nextThumb); } } void Phototonic::loadPreviousImage() { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } int previousThumb = thumbsViewer->getPrevRow(); if (previousThumb < 0) { if (Settings::wrapImageList) { previousThumb = thumbsViewer->getLastRow(); } else { return; } } if (Settings::layoutMode == ImageViewWidget) { imageViewer->loadImage( thumbsViewer->thumbsViewerModel->item(previousThumb)->data(thumbsViewer->FileNameRole).toString()); } thumbsViewer->setCurrentRow(previousThumb); thumbsViewer->setImageViewerWindowTitle(); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->selectThumbByRow(previousThumb); } } void Phototonic::loadFirstImage() { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } imageViewer->loadImage(thumbsViewer->thumbsViewerModel->item(0)->data(thumbsViewer->FileNameRole).toString()); thumbsViewer->setCurrentRow(0); thumbsViewer->setImageViewerWindowTitle(); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->selectThumbByRow(0); } } void Phototonic::loadLastImage() { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } int lastRow = thumbsViewer->getLastRow(); imageViewer->loadImage(thumbsViewer->thumbsViewerModel->item(lastRow)->data(thumbsViewer->FileNameRole).toString()); thumbsViewer->setCurrentRow(lastRow); thumbsViewer->setImageViewerWindowTitle(); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->selectThumbByRow(lastRow); } } void Phototonic::loadRandomImage() { if (thumbsViewer->thumbsViewerModel->rowCount() <= 0) { return; } int randomRow = thumbsViewer->getRandomRow(); imageViewer->loadImage( thumbsViewer->thumbsViewerModel->item(randomRow)->data(thumbsViewer->FileNameRole).toString()); thumbsViewer->setCurrentRow(randomRow); thumbsViewer->setImageViewerWindowTitle(); if (Settings::layoutMode == ThumbViewWidget) { thumbsViewer->selectThumbByRow(randomRow); } } void Phototonic::setViewerKeyEventsEnabled(bool enabled) { moveLeftAction->setEnabled(enabled); moveRightAction->setEnabled(enabled); moveUpAction->setEnabled(enabled); moveDownAction->setEnabled(enabled); } void Phototonic::updateIndexByViewerImage() { if (thumbsViewer->thumbsViewerModel->rowCount() > 0 && thumbsViewer->setCurrentIndexByName(imageViewer->viewerImageFullPath)) { thumbsViewer->selectCurrentIndex(); } } void Phototonic::hideViewer() { if (isFullScreen()) { showNormal(); if (shouldMaximize) { showMaximized(); } imageViewer->setCursorHiding(false); } restoreGeometry(Settings::appSettings->value(Settings::optionGeometry).toByteArray()); restoreState(Settings::appSettings->value(Settings::optionWindowState).toByteArray()); Settings::layoutMode = ThumbViewWidget; stackedLayout->setCurrentWidget(thumbsViewer); setDocksVisibility(true); while (QApplication::overrideCursor()) { QApplication::restoreOverrideCursor(); } if (Settings::slideShowActive) { toggleSlideShow(); } setThumbsViewerWindowTitle(); for (int i = 0; i <= 10 && qApp->hasPendingEvents(); ++i) { QApplication::processEvents(); } if (needThumbsRefresh) { needThumbsRefresh = false; refreshThumbs(true); } else { if (thumbsViewer->thumbsViewerModel->rowCount() > 0) { if (thumbsViewer->setCurrentIndexByName(imageViewer->viewerImageFullPath)) { thumbsViewer->selectCurrentIndex(); } } thumbsViewer->loadVisibleThumbs(); } imageViewer->clearImage(); thumbsViewer->setFocus(Qt::OtherFocusReason); setContextMenuPolicy(Qt::DefaultContextMenu); } void Phototonic::goBottom() { thumbsViewer->scrollToBottom(); } void Phototonic::goTop() { thumbsViewer->scrollToTop(); } void Phototonic::dropOp(Qt::KeyboardModifiers keyMods, bool dirOp, QString copyMoveDirPath) { QApplication::restoreOverrideCursor(); Settings::isCopyOperation = (keyMods == Qt::ControlModifier); QString destDir; if (QObject::sender() == fileSystemTree) { destDir = getSelectedPath(); } else if (QObject::sender() == bookmarks) { if (bookmarks->currentItem()) { destDir = bookmarks->currentItem()->toolTip(0); } else { addBookmark(copyMoveDirPath); return; } } else { // Unknown sender return; } MessageBox msgBox(this); if (!isValidPath(destDir)) { msgBox.critical(tr("Error"), tr("Can not move or copy images to this directory.")); selectCurrentViewDir(); return; } if (destDir == Settings::currentDirectory) { msgBox.critical(tr("Error"), tr("Destination directory is the same as the source directory.")); return; } if (dirOp) { QString dirOnly = copyMoveDirPath.right( copyMoveDirPath.size() - copyMoveDirPath.lastIndexOf(QDir::separator()) - 1); QString question = tr("Move directory %1 to %2?").arg(dirOnly).arg(destDir); MessageBox moveDirMessageBox(this); moveDirMessageBox.setText(question); moveDirMessageBox.setWindowTitle(tr("Move directory")); moveDirMessageBox.setIcon(MessageBox::Warning); moveDirMessageBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); moveDirMessageBox.setDefaultButton(MessageBox::Cancel); moveDirMessageBox.setButtonText(MessageBox::Yes, tr("Move Directory")); moveDirMessageBox.setButtonText(MessageBox::Cancel, tr("Cancel")); int ret = moveDirMessageBox.exec(); if (ret == MessageBox::Yes) { QFile dir(copyMoveDirPath); bool moveOk = dir.rename(destDir + QDir::separator() + dirOnly); if (!moveOk) { moveDirMessageBox.critical(tr("Error"), tr("Failed to move directory.")); } setStatus(tr("Directory moved")); } } else { CopyMoveDialog *copyMoveDialog = new CopyMoveDialog(this); Settings::copyCutIndexList = thumbsViewer->selectionModel()->selectedIndexes(); copyMoveDialog->exec(thumbsViewer, destDir, false); if (!Settings::isCopyOperation) { int row = copyMoveDialog->latestRow; if (thumbsViewer->thumbsViewerModel->rowCount()) { if (row >= thumbsViewer->thumbsViewerModel->rowCount()) { row = thumbsViewer->thumbsViewerModel->rowCount() - 1; } thumbsViewer->setCurrentRow(row); thumbsViewer->selectThumbByRow(row); } } QString stateString = QString((Settings::isCopyOperation ? tr("Copied") : tr("Moved")) + " " + tr("%n image(s)", "", copyMoveDialog->nFiles)); setStatus(stateString); delete (copyMoveDialog); } thumbsViewer->loadVisibleThumbs(); } void Phototonic::selectCurrentViewDir() { QModelIndex idx = fileSystemTree->fileSystemModel->index(Settings::currentDirectory); if (idx.isValid()) { fileSystemTree->setCurrentIndex(idx); } } void Phototonic::checkDirState(const QModelIndex &, int, int) { if (!initComplete) { return; } if (thumbsViewer->isBusy) { thumbsViewer->abort(); } if (!QDir().exists(Settings::currentDirectory)) { Settings::currentDirectory.clear(); QTimer::singleShot(0, this, SLOT(onReloadThumbs())); } } void Phototonic::addPathHistoryRecord(QString dir) { if (!needHistoryRecord) { needHistoryRecord = true; return; } if (pathHistoryList.size() && dir == pathHistoryList.at(currentHistoryIdx)) { return; } pathHistoryList.insert(++currentHistoryIdx, dir); // Need to clear irrelevant items from list if (currentHistoryIdx != pathHistoryList.size() - 1) { goFrwdAction->setEnabled(false); for (int i = pathHistoryList.size() - 1; i > currentHistoryIdx; --i) { pathHistoryList.removeAt(i); } } } void Phototonic::onReloadThumbs() { if (thumbsViewer->isBusy || !initComplete) { thumbsViewer->abort(); QTimer::singleShot(0, this, SLOT(onReloadThumbs())); return; } if (!Settings::isFileListLoaded) { if (Settings::currentDirectory.isEmpty()) { Settings::currentDirectory = getSelectedPath(); if (Settings::currentDirectory.isEmpty()) { return; } } QDir checkPath(Settings::currentDirectory); if (!checkPath.exists() || !checkPath.isReadable()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to open directory ") + Settings::currentDirectory); setStatus(tr("No directory selected")); return; } thumbsViewer->infoView->clear(); thumbsViewer->imagePreview->clear(); if (Settings::setWindowIcon && Settings::layoutMode == Phototonic::ThumbViewWidget) { setWindowIcon(defaultApplicationIcon); } pathLineEdit->setText(Settings::currentDirectory); addPathHistoryRecord(Settings::currentDirectory); if (currentHistoryIdx > 0) { goBackAction->setEnabled(true); } } if (Settings::layoutMode == ThumbViewWidget) { setThumbsViewerWindowTitle(); } thumbsViewer->reLoad(); } void Phototonic::setThumbsViewerWindowTitle() { if (Settings::isFileListLoaded) { setWindowTitle(tr("Files List") + " - Phototonic"); } else { setWindowTitle(Settings::currentDirectory + " - Phototonic"); } } void Phototonic::renameDir() { QModelIndexList selectedDirs = fileSystemTree->selectionModel()->selectedRows(); QFileInfo dirInfo = QFileInfo(fileSystemTree->fileSystemModel->filePath(selectedDirs[0])); bool renameOk; QString title = tr("Rename") + " " + dirInfo.completeBaseName(); QString newDirName = QInputDialog::getText(this, title, tr("New name:"), QLineEdit::Normal, dirInfo.completeBaseName(), &renameOk); if (!renameOk) { selectCurrentViewDir(); return; } if (newDirName.isEmpty()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Invalid name entered.")); selectCurrentViewDir(); return; } QFile dir(dirInfo.absoluteFilePath()); QString newFullPathName = dirInfo.absolutePath() + QDir::separator() + newDirName; renameOk = dir.rename(newFullPathName); if (!renameOk) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to rename directory.")); selectCurrentViewDir(); return; } if (Settings::currentDirectory == dirInfo.absoluteFilePath()) { fileSystemTree->setCurrentIndex(fileSystemTree->fileSystemModel->index(newFullPathName)); } else { selectCurrentViewDir(); } } void Phototonic::rename() { if (QApplication::focusWidget() == fileSystemTree) { renameDir(); return; } if (Settings::layoutMode == ImageViewWidget) { if (imageViewer->isNewImage()) { showNewImageWarning(); return; } if (thumbsViewer->thumbsViewerModel->rowCount() > 0) { if (thumbsViewer->setCurrentIndexByName(imageViewer->viewerImageFullPath)) thumbsViewer->selectCurrentIndex(); } } QString selectedImageFileName = thumbsViewer->getSingleSelectionFilename(); if (selectedImageFileName.isEmpty()) { setStatus(tr("Invalid selection")); return; } if (Settings::slideShowActive) { toggleSlideShow(); } imageViewer->setCursorHiding(false); QFile currentFileFullPath(selectedImageFileName); QFileInfo currentFileInfo(currentFileFullPath); int renameConfirmed; RenameDialog *renameDialog = new RenameDialog(this); renameDialog->setModal(true); renameDialog->setFileName(currentFileInfo.fileName()); renameConfirmed = renameDialog->exec(); QString newFileName = renameDialog->getFileName(); delete (renameDialog); if (renameConfirmed && newFileName.isEmpty()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("No name entered.")); renameConfirmed = 0; } if (renameConfirmed) { QString newFileNameFullPath = currentFileInfo.absolutePath() + QDir::separator() + newFileName; if (currentFileFullPath.rename(newFileNameFullPath)) { QModelIndexList indexesList = thumbsViewer->selectionModel()->selectedIndexes(); thumbsViewer->thumbsViewerModel->item(indexesList.first().row())->setData(newFileNameFullPath, thumbsViewer->FileNameRole); thumbsViewer->thumbsViewerModel->item(indexesList.first().row())->setData(newFileName, Qt::DisplayRole); imageViewer->setInfo(newFileName); imageViewer->viewerImageFullPath = newFileNameFullPath; if (Settings::filesList.contains(currentFileInfo.absoluteFilePath())) { Settings::filesList.replace(Settings::filesList.indexOf(currentFileInfo.absoluteFilePath()), newFileNameFullPath); } if (Settings::layoutMode == ImageViewWidget) { thumbsViewer->setImageViewerWindowTitle(); } } else { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to rename image.")); } } if (isFullScreen()) { imageViewer->setCursorHiding(true); } } void Phototonic::removeMetadata() { QModelIndexList indexList = thumbsViewer->selectionModel()->selectedIndexes(); QStringList fileList; copyCutThumbsCount = indexList.size(); for (int thumb = 0; thumb < copyCutThumbsCount; ++thumb) { fileList.append(thumbsViewer->thumbsViewerModel->item(indexList[thumb]. row())->data(thumbsViewer->FileNameRole).toString()); } if (fileList.isEmpty()) { setStatus(tr("Invalid selection")); return; } if (Settings::slideShowActive) { toggleSlideShow(); } MessageBox msgBox(this); msgBox.setText(tr("Permanently remove all Exif metadata from selected images?")); msgBox.setWindowTitle(tr("Remove Metadata")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Cancel); msgBox.setButtonText(MessageBox::Yes, tr("Remove Metadata")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); int ret = msgBox.exec(); if (ret == MessageBox::Yes) { for (int file = 0; file < fileList.size(); ++file) { Exiv2::Image::AutoPtr image; try { image = Exiv2::ImageFactory::open(fileList[file].toStdString()); image->clearMetadata(); image->writeMetadata(); metadataCache->removeImage(fileList[file]); } catch (Exiv2::Error &error) { msgBox.critical(tr("Error"), tr("Failed to remove Exif metadata.")); return; } } QItemSelection dummy; thumbsViewer->onSelectionChanged(dummy); QString state = QString(tr("Metadata removed from selected images")); setStatus(state); } } void Phototonic::deleteDirectory(bool trash) { bool removeDirectoryOk; QModelIndexList selectedDirs = fileSystemTree->selectionModel()->selectedRows(); QString deletePath = fileSystemTree->fileSystemModel->filePath(selectedDirs[0]); QModelIndex idxAbove = fileSystemTree->indexAbove(selectedDirs[0]); QFileInfo dirInfo = QFileInfo(deletePath); QString question = (trash ? tr("Move directory %1 to the trash?") : tr( "Permanently delete the directory %1 and all of its contents?")).arg( dirInfo.completeBaseName()); MessageBox msgBox(this); msgBox.setText(question); msgBox.setWindowTitle(tr("Delete directory")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Cancel); msgBox.setButtonText(MessageBox::Yes, trash ? tr("OK") : tr("Delete Directory")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); int ret = msgBox.exec(); QString trashError; if (ret == MessageBox::Yes) { if (trash) { removeDirectoryOk = Trash::moveToTrash(deletePath, trashError) == Trash::Success; } else { removeDirectoryOk = removeDirectoryOperation(deletePath); } } else { selectCurrentViewDir(); return; } if (!removeDirectoryOk) { msgBox.critical(tr("Error"), trash ? tr("Failed to move directory to the trash: %1").arg(trashError) : tr("Failed to delete directory.")); selectCurrentViewDir(); return; } QString state = QString(tr("Removed \"%1\"").arg(deletePath)); setStatus(state); if (Settings::currentDirectory == deletePath) { if (idxAbove.isValid()) { fileSystemTree->setCurrentIndex(idxAbove); } } else { selectCurrentViewDir(); } } void Phototonic::createSubDirectory() { QModelIndexList selectedDirs = fileSystemTree->selectionModel()->selectedRows(); QFileInfo dirInfo = QFileInfo(fileSystemTree->fileSystemModel->filePath(selectedDirs[0])); bool ok; QString newDirName = QInputDialog::getText(this, tr("New Sub directory"), tr("New directory name:"), QLineEdit::Normal, "", &ok); if (!ok) { selectCurrentViewDir(); return; } if (newDirName.isEmpty()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Invalid name entered.")); selectCurrentViewDir(); return; } QDir dir(dirInfo.absoluteFilePath()); ok = dir.mkdir(dirInfo.absoluteFilePath() + QDir::separator() + newDirName); if (!ok) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to create new directory.")); selectCurrentViewDir(); return; } setStatus(tr("Created %1").arg(newDirName)); fileSystemTree->expand(selectedDirs[0]); } QString Phototonic::getSelectedPath() { QModelIndexList selectedDirs = fileSystemTree->selectionModel()->selectedRows(); if (selectedDirs.size() && selectedDirs[0].isValid()) { QFileInfo dirInfo = QFileInfo(fileSystemTree->fileSystemModel->filePath(selectedDirs[0])); return dirInfo.absoluteFilePath(); } else return ""; } void Phototonic::wheelEvent(QWheelEvent *event) { if (Settings::layoutMode == ImageViewWidget) { if (event->modifiers() == Qt::ControlModifier) { if (event->delta() < 0) { zoomOut(); } else { zoomIn(); } } else if (nextImageAction->isEnabled()) { if (event->delta() < 0) { loadNextImage(); } else { loadPreviousImage(); } } event->accept(); } else if (event->modifiers() == Qt::ControlModifier && QApplication::focusWidget() == thumbsViewer) { if (event->delta() < 0) { thumbsZoomOut(); } else { thumbsZoomIn(); } } } void Phototonic::showNewImageWarning() { MessageBox msgBox(this); msgBox.warning(tr("Warning"), tr("Cannot perform action with temporary image.")); } bool Phototonic::removeDirectoryOperation(QString dirToDelete) { bool removeDirOk; QDir dir(dirToDelete); Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { if (info.isDir()) { removeDirOk = removeDirectoryOperation(info.absoluteFilePath()); } else { removeDirOk = QFile::remove(info.absoluteFilePath()); } if (!removeDirOk) { return removeDirOk; } } removeDirOk = dir.rmdir(dirToDelete); return removeDirOk; } void Phototonic::cleanupCropDialog() { setInterfaceEnabled(true); } void Phototonic::cleanupResizeDialog() { delete resizeDialog; resizeDialog = 0; setInterfaceEnabled(true); } void Phototonic::cleanupColorsDialog() { Settings::colorsActive = false; setInterfaceEnabled(true); } void Phototonic::setInterfaceEnabled(bool enable) { // actions colorsAction->setEnabled(enable); renameAction->setEnabled(enable); removeMetadataAction->setEnabled(enable); cropAction->setEnabled(enable); resizeAction->setEnabled(enable); CloseImageAction->setEnabled(enable); nextImageAction->setEnabled(enable); prevImageAction->setEnabled(enable); firstImageAction->setEnabled(enable); lastImageAction->setEnabled(enable); randomImageAction->setEnabled(enable); slideShowAction->setEnabled(enable); copyToAction->setEnabled(enable); moveToAction->setEnabled(enable); deleteAction->setEnabled(enable); deletePermanentlyAction->setEnabled(enable); settingsAction->setEnabled(enable); viewImageAction->setEnabled(enable); // other thumbsViewer->setEnabled(enable); fileSystemTree->setEnabled(enable); bookmarks->setEnabled(enable); thumbsViewer->imageTags->setEnabled(enable); menuBar()->setEnabled(enable); editToolBar->setEnabled(enable); goToolBar->setEnabled(enable); viewToolBar->setEnabled(enable); interfaceDisabled = !enable; if (enable) { if (isFullScreen()) { imageViewer->setCursorHiding(true); } } else { imageViewer->setCursorHiding(false); } } void Phototonic::addNewBookmark() { addBookmark(getSelectedPath()); } void Phototonic::addBookmark(QString path) { Settings::bookmarkPaths.insert(path); bookmarks->reloadBookmarks(); } phototonic-2.1/Phototonic.h000066400000000000000000000246171325127642100160560ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef PHOTOTONIC_H #define PHOTOTONIC_H #include #include "ImageViewer.h" #include "ThumbsViewer.h" #include "SettingsDialog.h" #include "CopyMoveToDialog.h" #include "CropDialog.h" #include "ColorsDialog.h" #include "ResizeDialog.h" #include "FileListWidget.h" #include "FileSystemTree.h" #include #define VERSION "Phototonic v2.1" class Phototonic : public QMainWindow { Q_OBJECT public: int copyCutThumbsCount; Phototonic(QStringList argumentsList, int filesStartAt, QWidget *parent = 0); QMenu *createPopupMenu(); void setStatus(QString state); void showBusyAnimation(bool busy); QIcon &getDefaultWindowIcon(); enum CentralWidgets { ThumbViewWidget = 0, ImageViewWidget }; protected: void mouseDoubleClickEvent(QMouseEvent *event); void closeEvent(QCloseEvent *event); void mousePressEvent(QMouseEvent *event); public slots: bool event(QEvent *event); void dropOp(Qt::KeyboardModifiers keyMods, bool dirOp, QString copyMoveDirPath); void showViewer(); void loadSelectedThumbImage(const QModelIndex &idx); void loadImageFromCliArguments(QString cliFileName); void hideViewer(); private slots: void about(); void sortThumbnails(); void reload(); void setIncludeSubDirs(); void showSettings(); void toggleFullScreen(); void updateActions(); void onReloadThumbs(); void renameDir(); void setThumbsViewerWindowTitle(); void rename(); void removeMetadata(); void viewImage(); void newImage(); void addNewBookmark(); void deleteDirectory(bool trash); void createSubDirectory(); void checkDirState(const QModelIndex &, int, int); void goSelectedDir(const QModelIndex &currDir); void bookmarkClicked(QTreeWidgetItem *item, int col); void goPathBarDir(); void setThumbsFilter(); void clearThumbsFilter(); void goBack(); void goTo(QString path); void goForward(); void goUp(); void goHome(); void toggleSlideShow(); void slideShowHandler(); void loadNextImage(); void loadPreviousImage(); void loadFirstImage(); void loadLastImage(); void loadRandomImage(); void updateIndexByViewerImage(); void selectAllThumbs(); void deleteOperation(); void deletePermanentlyOperation(); void cutThumbs(); void copyThumbs(); void pasteThumbs(); void thumbsZoomIn(); void thumbsZoomOut(); void zoomIn(); void zoomOut(); void resetZoom(); void origZoom(); void keepZoom(); void keepTransformClicked(); void rotateLeft(); void rotateRight(); void flipVertical(); void cropImage(); void scaleImage(); void freeRotateLeft(); void freeRotateRight(); void showColorsDialog(); void setMirrorDisabled(); void setMirrorDual(); void setMirrorTriple(); void setMirrorVDual(); void setMirrorQuad(); void flipHorizontal(); void moveRight(); void moveLeft(); void moveUp(); void moveDown(); void setDocksVisibility(bool visible); void goTop(); void goBottom(); void showHiddenFiles(); void toggleImageViewerToolbar(); void setToolbarIconSize(); void chooseExternalApp(); void updateExternalApps(); void runExternalApp(); void cleanupSender(); void externalAppError(); void setEditToolBarVisibility(); void setGoToolBarVisibility(); void setViewToolBarVisibility(); void setImageToolBarVisibility(); void setFileSystemDockVisibility(); void setBookmarksDockVisibility(); void setImagePreviewDockVisibility(); void setTagsDockVisibility(); void setImageInfoDockVisibility(); void lockDocks(); void cleanupCropDialog(); void cleanupResizeDialog(); void cleanupColorsDialog(); void filterImagesFocus(); void setPathFocus(); void copyImagesTo(); void moveImagesTo(); void onFileListSelected(); private: QMenu *fileMenu; QMenu *editMenu; QMenu *goMenu; QMenu *sortMenu; QMenu *viewMenu; QMenu *helpMenu; QMenu *zoomSubMenu; QMenu *transformSubMenu; QMenu *viewSubMenu; QMenu *MirroringSubMenu; QMenu *openWithSubMenu; QToolBar *viewToolBar; QToolBar *editToolBar; QToolBar *goToolBar; QToolBar *imageToolBar; QAction *exitAction; QAction *cutAction; QAction *copyAction; QAction *copyToAction; QAction *moveToAction; QAction *deleteAction; QAction *deletePermanentlyAction; QAction *saveAction; QAction *saveAsAction; QAction *renameAction; QAction *removeMetadataAction; QAction *selectAllAction; QAction *copyImageAction; QAction *pasteImageAction; QAction *showClipboardAction; QAction *addBookmarkAction; QAction *removeBookmarkAction; QActionGroup *sortTypesGroup; QAction *sortByNameAction; QAction *sortByTimeAction; QAction *sortBySizeAction; QAction *sortByTypeAction; QAction *sortReverseAction; QAction *refreshAction; QAction *includeSubDirectoriesAction; QAction *fullScreenAction; QAction *thumbsGoToTopAction; QAction *thumbsGoToBottomAction; QAction *CloseImageAction; QAction *settingsAction; QAction *thumbsZoomInAction; QAction *thumbsZoomOutAction; QAction *zoomSubMenuAction; QAction *zoomInAction; QAction *zoomOutAction; QAction *resetZoomAction; QAction *origZoomAction; QAction *keepZoomAction; QAction *keepTransformAction; QAction *transformSubMenuAction; QAction *viewSubMenuAction; QAction *rotateLeftAction; QAction *rotateRightAction; QAction *flipHorizontalAction; QAction *flipVerticalAction; QAction *cropAction; QAction *cropToSelectionAction; QAction *resizeAction; QAction *freeRotateLeftAction; QAction *freeRotateRightAction; QAction *colorsAction; QActionGroup *mirroringActionGroup; QAction *mirrorSubMenuAction; QAction *mirrorDisabledAction; QAction *mirrorDualAction; QAction *mirrorTripleAction; QAction *mirrorDualVerticalAction; QAction *mirrorQuadAction; QAction *moveLeftAction; QAction *moveRightAction; QAction *moveUpAction; QAction *moveDownAction; QAction *aboutAction; QAction *showHiddenFilesAction; QAction *smallToolbarIconsAction; QAction *lockDocksAction; QAction *showViewerToolbarAction; QAction *pasteAction; QAction *createDirectoryAction; QAction *goBackAction; QAction *goFrwdAction; QAction *goUpAction; QAction *goHomeAction; QAction *slideShowAction; QAction *nextImageAction; QAction *prevImageAction; QAction *firstImageAction; QAction *lastImageAction; QAction *randomImageAction; QAction *viewImageAction; QAction *filterImagesFocusAction; QAction *setPathFocusAction; QAction *openWithMenuAction; QAction *externalAppsAction; QAction *invertSelectionAction; QLineEdit *pathLineEdit; QLineEdit *filterLineEdit; QLabel *statusLabel; QDockWidget *fileSystemDock; QDockWidget *bookmarksDock; QDockWidget *imagePreviewDock; QDockWidget *tagsDock; FileSystemTree *fileSystemTree; BookMarks *bookmarks; QDockWidget *imageInfoDock; ThumbsViewer *thumbsViewer; ImageViewer *imageViewer; QList pathHistoryList; QTimer *SlideShowTimer; CopyMoveToDialog *copyMoveToDialog; QWidget *fileSystemDockOrigWidget; QWidget *bookmarksDockOrigWidget; QWidget *imagePreviewDockOrigWidget; QWidget *tagsDockOrigWidget; QWidget *imageInfoDockOrigWidget; QWidget *fileSystemDockEmptyWidget; QWidget *bookmarksDockEmptyWidget; QWidget *imagePreviewDockEmptyWidget; QWidget *tagsDockEmptyWidget; QWidget *imageInfoDockEmptyWidget; bool interfaceDisabled; MetadataCache *metadataCache; FileListWidget *fileListWidget; QStackedLayout *stackedLayout; int currentHistoryIdx; bool needHistoryRecord; bool initComplete; bool needThumbsRefresh; bool shouldMaximize; bool editToolBarVisible; bool goToolBarVisible; bool viewToolBarVisible; bool imageToolBarVisible; QMovie *busyMovie; QLabel *busyLabel; ResizeDialog *resizeDialog; ColorsDialog *colorsDialog; CropDialog *cropDialog; QIcon defaultApplicationIcon; void refreshThumbs(bool noScroll); void loadShortcuts(); void setupDocks(); void deleteImages(bool trash); void deleteFromViewer(bool trash); void loadCurrentImage(int currentRow); void selectCurrentViewDir(); void processStartupArguments(QStringList argumentsList, int filesStartAt); void loadStartupFileList(QStringList argumentsList, int filesStartAt); void addMenuSeparator(QWidget *widget); void createImageViewer(); void createThumbsViewer(); void createActions(); void createMenus(); void createToolBars(); void createStatusBar(); void createFileSystemDock(); void createBookmarksDock(); void createImagePreviewDock(); void createImageTagsDock(); void writeSettings(); void readSettings(); void addPathHistoryRecord(QString dir); bool isValidPath(QString &path); QString getSelectedPath(); void setCopyCutActions(bool setEnabled); void wheelEvent(QWheelEvent *event); void copyOrCutThumbs(bool copy); void showNewImageWarning(); bool removeDirectoryOperation(QString dirToDelete); void setInterfaceEnabled(bool enable); void addBookmark(QString path); void copyOrMoveImages(bool move); void setViewerKeyEventsEnabled(bool enabled); }; #endif // PHOTOTONIC_H phototonic-2.1/ProgressDialog.cpp000066400000000000000000000027521325127642100172030ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "ProgressDialog.h" ProgressDialog::ProgressDialog(QWidget *parent) : QDialog(parent) { opLabel = new QLabel(""); abortOp = false; cancelButton = new QPushButton(tr("Cancel")); cancelButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(cancelButton, SIGNAL(clicked()), this, SLOT(abort())); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addWidget(opLabel); QHBoxLayout *buttonsLayout = new QHBoxLayout; buttonsLayout->addWidget(cancelButton); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(topLayout); mainLayout->addLayout(buttonsLayout, Qt::AlignRight); setLayout(mainLayout); } void ProgressDialog::abort() { abortOp = true; } phototonic-2.1/ProgressDialog.h000066400000000000000000000022251325127642100166430ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef PROGRESS_DIALOG_H #define PROGRESS_DIALOG_H #include #include #include #include "Settings.h" class ProgressDialog : public QDialog { Q_OBJECT public slots: void abort(); public: QLabel *opLabel; bool abortOp; ProgressDialog(QWidget *parent); private: QPushButton *cancelButton; }; #endif // PROGRESS_DIALOG_H phototonic-2.1/README.md000066400000000000000000000063471325127642100150360ustar00rootroot00000000000000# Phototonic Image Viewer [![Build Status](https://travis-ci.org/oferkv/phototonic.svg?branch=master)](https://travis-ci.org/oferkv/phototonic) ### About Phototonic is an image viewer and organizer built with Qt and Exiv2, released under GNU General Public License v3. ### Features + Support for common image formats and GIF animation + Supports tagging images, and filtering images by tags (IPTC) + Browse thumbnails recursively down a folder tree + Dynamic thumbnails loading + Image transformation and color manipulation + Display image information and metadata + Does not depend on any desktop environment ### Screenshot ### Updates: ##### 11 Mar 2018 - v2.1 + Rotate preview by Exif rotation + Fixed bug in image filtering + Bug fixes for multiple UI issues and actions + Add shortcuts for all missing actions ##### 28 Feb 2018 - v2.0 + Move to Trash + File List support + Bug fixes ##### 15 Jan 2018 + Back after a long break + Code cleanup and removal of useless features + Lots of bug fixes + Added Remove Image Metadata action + Enhanced keyboard settings + Enhanced image info ##### 12 Nov 2015 - v1.7.1 + Changes to the way layouts are being switched, now faster and more efficient + Fixed issue with not reading image tags correctly when exif data was missing from image + Added Negate option to image tags filtering + Docks can now be nested to create more customized layouts + Some enhancements to Tags user experience and icons + Fixed issue with limited zoom functionality + Better error handling when reading corrupted images + New translations added ##### 8 Aug 2015 - v1.6.17 + Image tags improvements and bug fixes + Changes to default key mapping + Small fixes to image extensions + Fixed issue with thumb label appearing after rename when labels are not displayed + Improvements to image feedback + Some dialog usability fixes + Added Negativity settings per color channel + Fixed colors manipulations for images with alpha channel and non animated GIF images + Other Bug fixes [Older updates](HISTORY.md) ##### Optional Dependencies + qt5-imageformats (TIFF and TGA support) + qt5-svg (SVG support) ##### Quick Build Instructions on Linux ``` $ tar -zxvf phototonic.tar.gz $ cd phototonic $ qmake $ make $ make install $ sudo make install ``` ##### Building on Windows Building on Windows is only supported with mingw at the moment (the source code is probably compatible with msvc, but this was not tested yet). First get the exiv2 library. Binary version is available from http://www.exiv2.org/download.html (download mingw version) or build it manually. Note that Qt libraries must be built against the same major mingw version as exiv2 is built against (i.e. Qt built with mingw 5 and higher won't be compatible with exiv2 built with mingw 4.9). Currently exiv2 binary package for mingw is built with mingw 4.9 therefore the latest compatible Qt version available in binary is 5.6.3 (available via Qt Maintenance Tool). If using the binary package from exiv2 website, unpack the `mingw` directory to the root of the repository (only mingw/lib and mingw/include are essential). Then build phototonic as usual - via qmake + mingw32-make in the console, or via QtCreator (remember to choose the compatible Qt Kit). phototonic-2.1/RenameDialog.cpp000066400000000000000000000043731325127642100166070ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include #include #include #include "RenameDialog.h" RenameDialog::RenameDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Rename Image")); QHBoxLayout *buttonsLayout = new QHBoxLayout; QPushButton *okButton = new QPushButton(tr("Rename")); connect(okButton, SIGNAL(clicked()), this, SLOT(ok())); okButton->setDefault(true); QPushButton *cancelButton = new QPushButton(tr("Cancel")); connect(cancelButton, SIGNAL(clicked()), this, SLOT(abort())); buttonsLayout->addWidget(cancelButton, 1, Qt::AlignRight); buttonsLayout->addWidget(okButton, 0, Qt::AlignRight); QHBoxLayout *renameLayout = new QHBoxLayout; QLabel *label = new QLabel(tr("New name: ")); fileNameLineEdit = new QLineEdit(); fileNameLineEdit->setMinimumWidth(200); renameLayout->addWidget(label); renameLayout->addWidget(fileNameLineEdit); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addLayout(renameLayout); mainLayout->addLayout(buttonsLayout); setLayout(mainLayout); setWindowIcon(QIcon(":/images/phototonic.png")); setMinimumWidth(480); } void RenameDialog::ok() { accept(); } void RenameDialog::abort() { reject(); } void RenameDialog::setFileName(QString name) { fileNameLineEdit->setText(name); fileNameLineEdit->setSelection(0, name.lastIndexOf(".")); } QString RenameDialog::getFileName() { return fileNameLineEdit->text(); } phototonic-2.1/RenameDialog.h000066400000000000000000000022141325127642100162440ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef RENAME_DIALOG_H #define RENAME_DIALOG_H #include #include class RenameDialog : public QDialog { Q_OBJECT public: RenameDialog(QWidget *parent); void setFileName(QString name); QString getFileName(); public slots: void ok(); void abort(); private: QLineEdit *fileNameLineEdit; }; #endif // RENAME_DIALOG_Hphototonic-2.1/ResizeDialog.cpp000066400000000000000000000160661325127642100166430ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include #include #include #include "ImageViewer.h" #include "ResizeDialog.h" #include "Settings.h" ResizeDialog::ResizeDialog(QWidget *parent, ImageViewer *imageViewer) : QDialog(parent) { setWindowTitle(tr("Scale Image")); setWindowIcon(QIcon::fromTheme("transform-scale", QIcon(":/images/phototonic.png"))); newWidth = newHeight = 0; if (Settings::dialogLastX) { move(Settings::dialogLastX, Settings::dialogLastY); } this->imageViewer = imageViewer; width = lastWidth = imageViewer->getImageWidthPreCropped(); height = lastHeight = imageViewer->getImageHeightPreCropped(); QHBoxLayout *buttonsHbox = new QHBoxLayout; QPushButton *okButton = new QPushButton(tr("Scale")); connect(okButton, SIGNAL(clicked()), this, SLOT(ok())); okButton->setDefault(true); QPushButton *cancelButton = new QPushButton(tr("Cancel")); connect(cancelButton, SIGNAL(clicked()), this, SLOT(abort())); buttonsHbox->addWidget(cancelButton, 1, Qt::AlignRight); buttonsHbox->addWidget(okButton, 0, Qt::AlignRight); widthSpinBox = new QSpinBox; widthSpinBox->setRange(0, width * 10); widthSpinBox->setValue(width); connect(widthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(adjustSizes())); heightSpinBox = new QSpinBox; heightSpinBox->setRange(0, height * 10); heightSpinBox->setValue(height); connect(heightSpinBox, SIGNAL(valueChanged(int)), this, SLOT(adjustSizes())); QGridLayout *mainGbox = new QGridLayout; QLabel *origSizeLab = new QLabel(tr("Current size:")); QString imageSizeStr = QString::number(width) + " x " + QString::number(height); QLabel *origSizePixelsLab = new QLabel(imageSizeStr); QLabel *widthLab = new QLabel(tr("New Width:")); QLabel *heightLab = new QLabel(tr("New Height:")); QLabel *unitsLab = new QLabel(tr("Units:")); QLabel *newSizeLab = new QLabel(tr("New size:")); newSizePixelsLabel = new QLabel(imageSizeStr); pixelsRadioButton = new QRadioButton(tr("Pixels")); connect(pixelsRadioButton, SIGNAL(clicked()), this, SLOT(setUnits())); percentRadioButton = new QRadioButton(tr("Percent")); connect(percentRadioButton, SIGNAL(clicked()), this, SLOT(setUnits())); pixelsRadioButton->setChecked(true); pixelUnits = true; QCheckBox *lockAspectCb = new QCheckBox(tr("Keep aspect ratio"), this); lockAspectCb->setChecked(true); connect(lockAspectCb, SIGNAL(clicked()), this, SLOT(setAspectLock())); keepAspect = true; QHBoxLayout *radiosHbox = new QHBoxLayout; radiosHbox->addStretch(1); radiosHbox->addWidget(pixelsRadioButton); radiosHbox->addWidget(percentRadioButton); mainGbox->addWidget(origSizeLab, 2, 2, 1, 1); mainGbox->addWidget(origSizePixelsLab, 2, 4, 1, 1); mainGbox->addWidget(widthLab, 6, 2, 1, 1); mainGbox->addWidget(heightLab, 7, 2, 1, 1); mainGbox->addWidget(unitsLab, 3, 2, 1, 1); mainGbox->addWidget(widthSpinBox, 6, 4, 1, 2); mainGbox->addWidget(heightSpinBox, 7, 4, 1, 2); mainGbox->addLayout(radiosHbox, 3, 4, 1, 3); mainGbox->addWidget(lockAspectCb, 5, 2, 1, 3); mainGbox->addWidget(newSizeLab, 8, 2, 1, 1); mainGbox->addWidget(newSizePixelsLabel, 8, 4, 1, 1); mainGbox->setRowStretch(9, 1); mainGbox->setColumnStretch(3, 1); QVBoxLayout *mainVbox = new QVBoxLayout; mainVbox->addLayout(mainGbox); mainVbox->addLayout(buttonsHbox); setLayout(mainVbox); widthSpinBox->setFocus(Qt::OtherFocusReason); } void ResizeDialog::setAspectLock() { keepAspect = ((QCheckBox *) QObject::sender())->isChecked(); adjustSizes(); } void ResizeDialog::setUnits() { int newWidth; int newHeight; if (pixelsRadioButton->isChecked() && !pixelUnits) { newWidth = (width * widthSpinBox->value()) / 100; newHeight = (height * heightSpinBox->value()) / 100; widthSpinBox->setRange(0, width * 10); heightSpinBox->setRange(0, height * 10); pixelUnits = true; } else { newWidth = (100 * widthSpinBox->value()) / width; newHeight = (100 * heightSpinBox->value()) / height; widthSpinBox->setRange(0, 100 * 10); heightSpinBox->setRange(0, 100 * 10); pixelUnits = false; } widthSpinBox->setValue(newWidth); if (!keepAspect) { heightSpinBox->setValue(newHeight); } } void ResizeDialog::adjustSizes() { static bool busy = false; if (busy) { return; } busy = true; if (keepAspect) { if (pixelUnits) { QSize imageSize(width, height); if (widthSpinBox->value() > lastWidth || heightSpinBox->value() > lastHeight) { imageSize.scale(widthSpinBox->value(), heightSpinBox->value(), Qt::KeepAspectRatioByExpanding); } else { imageSize.scale(widthSpinBox->value(), heightSpinBox->value(), Qt::KeepAspectRatio); } widthSpinBox->setValue(imageSize.width()); heightSpinBox->setValue(imageSize.height()); lastWidth = widthSpinBox->value(); lastHeight = heightSpinBox->value(); newWidth = imageSize.width(); newHeight = imageSize.height(); } else { if (widthSpinBox->value() != lastWidth) { heightSpinBox->setValue(widthSpinBox->value()); } else { widthSpinBox->setValue(heightSpinBox->value()); } lastWidth = widthSpinBox->value(); lastHeight = heightSpinBox->value(); newWidth = (width * widthSpinBox->value()) / 100; newHeight = (height * heightSpinBox->value()) / 100; } } else { if (pixelUnits) { newWidth = widthSpinBox->value(); newHeight = heightSpinBox->value(); } else { newWidth = (width * widthSpinBox->value()) / 100; newHeight = (height * heightSpinBox->value()) / 100; } } newSizePixelsLabel->setText(QString::number(newWidth) + " x " + QString::number(newHeight)); busy = false; } void ResizeDialog::ok() { if (newWidth || newHeight) { Settings::scaledWidth = newWidth; Settings::scaledHeight = newHeight; imageViewer->refresh(); } accept(); } void ResizeDialog::abort() { reject(); } phototonic-2.1/ResizeDialog.h000066400000000000000000000026761325127642100163120ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef RESIZE_DIALOG_H #define RESIZE_DIALOG_H #include "ImageViewer.h" class ResizeDialog : public QDialog { Q_OBJECT public: ResizeDialog(QWidget *parent, ImageViewer *imageViewer); public slots: void ok(); void abort(); void setAspectLock(); void setUnits(); void adjustSizes(); private: int width; int height; int lastWidth; int lastHeight; bool keepAspect; bool pixelUnits; int newWidth; int newHeight; QSpinBox *widthSpinBox; QSpinBox *heightSpinBox; QRadioButton *pixelsRadioButton; QRadioButton *percentRadioButton; QLabel *newSizePixelsLabel; ImageViewer *imageViewer; }; #endif // RESIZE_DIALOG_Hphototonic-2.1/Settings.cpp000066400000000000000000000131201325127642100160460ustar00rootroot00000000000000/* * Copyright (C) 2013 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "Settings.h" namespace Settings { const char optionThumbsSortFlags[] = "optionThumbsSortFlags"; const char optionThumbsZoomLevel[] = "optionThumbsZoomLevel"; const char optionFullScreenMode[] = "optionFullScreenMode"; const char optionViewerBackgroundColor[] = "optionViewerBackgroundColor"; const char optionThumbsBackgroundColor[] = "optionThumbsBackgroundColor"; const char optionThumbsTextColor[] = "optionThumbsTextColor"; const char optionThumbsPagesReadCount[] = "optionThumbsPagesReadCount"; const char optionViewerZoomOutFlags[] = "optionViewerZoomOutFlags"; const char optionViewerZoomInFlags[] = "optionViewerZoomInFlags"; const char optionShowImageName[] = "optionShowImageName"; const char optionEnableAnimations[] = "enableAnimations"; const char optionWrapImageList[] = "wrapImageList"; const char optionExifRotationEnabled[] = "exifRotationEnabled"; const char optionExifThumbRotationEnabled[] = "exifThumbRotationEnabled"; const char optionReverseMouseBehavior[] = "reverseMouseBehavior"; const char optionDeleteConfirm[] = "deleteConfirm"; const char optionShowHiddenFiles[] = "showHiddenFiles"; const char optionImageZoomFactor[] = "imageZoomFactor"; const char optionShouldMaximize[] = "shouldMaximize"; const char optionDefaultSaveQuality[] = "defaultSaveQuality"; const char optionSlideShowDelay[] = "slideShowDelay"; const char optionSlideShowRandom[] = "slideShowRandom"; const char optionEditToolBarVisible[] = "editToolBarVisible"; const char optionGoToolBarVisible[] = "goToolBarVisible"; const char optionViewToolBarVisible[] = "viewToolBarVisible"; const char optionImageToolBarVisible[] = "imageToolBarVisible"; const char optionFileSystemDockVisible[] = "fileSystemDockVisible"; const char optionBookmarksDockVisible[] = "bookmarksDockVisible"; const char optionImagePreviewDockVisible[] = "imagePreviewDockVisible"; const char optionTagsDockVisible[] = "tagsDockVisible"; const char optionImageInfoDockVisible[] = "imageInfoDockVisible"; const char optionSmallToolbarIcons[] = "smallToolbarIcons"; const char optionHideDockTitlebars[] = "hideDockTitlebars"; const char optionStartupDir[] = "startupDir"; const char optionSpecifiedStartDir[] = "specifiedStartDir"; const char optionThumbsBackgroundImage[] = "thumbsBackgroundImage"; const char optionShowViewerToolbar[] = "showViewerToolbar"; const char optionLastDir[] = "lastDir"; const char optionGeometry[] = "Geometry"; const char optionWindowState[] = "WindowState"; const char optionShortcuts[] = "Shortcuts"; const char optionExternalApps[] = "ExternalApps"; const char optionCopyMoveToPaths[] = "CopyMoveToPaths"; const char optionKnownTags[] = "KnownTags"; const char optionSetWindowIcon[] = "setWindowIcon"; QSettings *appSettings; unsigned int layoutMode; unsigned int zoomInFlags; unsigned int zoomOutFlags; QColor viewerBackgroundColor; QColor thumbsBackgroundColor; QColor thumbsTextColor; unsigned int thumbsPagesReadCount; bool wrapImageList; bool enableAnimations; float imageZoomFactor; bool keepZoomFactor; int rotation; bool keepTransform; bool flipH; bool flipV; int scaledWidth; int scaledHeight; int defaultSaveQuality; int cropLeft; int cropTop; int cropWidth; int cropHeight; int cropLeftPercent; int cropTopPercent; int cropWidthPercent; int cropHeightPercent; int slideShowDelay; bool slideShowRandom; bool slideShowActive; QMap actionKeys; int hueVal; int saturationVal; int lightnessVal; int contrastVal; int brightVal; int redVal; int greenVal; int blueVal; bool colorsActive; bool colorizeEnabled; bool rNegateEnabled; bool gNegateEnabled; bool bNegateEnabled; bool hueRedChannel; bool hueGreenChannel; bool hueBlueChannel; bool exifRotationEnabled; bool exifThumbRotationEnabled; bool includeSubDirectories; bool showHiddenFiles; bool showViewerToolbar; QMap externalApps; QSet bookmarkPaths; QSet knownTags; bool reverseMouseBehavior; bool deleteConfirm; QModelIndexList copyCutIndexList; bool isCopyOperation; QStringList copyCutFileList; bool isFullScreen; int dialogLastX; int dialogLastY; StartupDir startupDir; QString specifiedStartDir; bool showImageName; bool smallToolbarIcons; bool hideDockTitlebars; bool tagsDockVisible; bool fileSystemDockVisible; bool bookmarksDockVisible; bool imagePreviewDockVisible; bool imageInfoDockVisible; QString currentDirectory; QString thumbsBackgroundImage; QStringList filesList; bool isFileListLoaded; bool setWindowIcon; } phototonic-2.1/Settings.h000066400000000000000000000133771325127642100155310ustar00rootroot00000000000000/* * Copyright (C) 2013 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef SETTINGS_H #define SETTINGS_H #define THUMB_SIZE_MIN 25 #define THUMB_SIZE_MAX 450 #include #include #include #include #include #include namespace Settings { enum StartupDir { RememberLastDir = 0, DefaultDir, SpecifiedDir }; extern const char optionThumbsSortFlags[]; extern const char optionThumbsZoomLevel[]; extern const char optionFullScreenMode[]; extern const char optionViewerBackgroundColor[]; extern const char optionThumbsBackgroundColor[]; extern const char optionThumbsTextColor[]; extern const char optionThumbsPagesReadCount[]; extern const char optionViewerZoomOutFlags[]; extern const char optionViewerZoomInFlags[]; extern const char optionShowImageName[]; extern const char optionEnableAnimations[]; extern const char optionWrapImageList[]; extern const char optionExifRotationEnabled[]; extern const char optionExifThumbRotationEnabled[]; extern const char optionReverseMouseBehavior[]; extern const char optionDeleteConfirm[]; extern const char optionShowHiddenFiles[]; extern const char optionImageZoomFactor[]; extern const char optionShouldMaximize[]; extern const char optionDefaultSaveQuality[]; extern const char optionSlideShowDelay[]; extern const char optionSlideShowRandom[]; extern const char optionEditToolBarVisible[]; extern const char optionGoToolBarVisible[]; extern const char optionViewToolBarVisible[]; extern const char optionImageToolBarVisible[]; extern const char optionFileSystemDockVisible[]; extern const char optionBookmarksDockVisible[]; extern const char optionImagePreviewDockVisible[]; extern const char optionTagsDockVisible[]; extern const char optionImageInfoDockVisible[]; extern const char optionSmallToolbarIcons[]; extern const char optionHideDockTitlebars[]; extern const char optionStartupDir[]; extern const char optionSpecifiedStartDir[]; extern const char optionThumbsBackgroundImage[]; extern const char optionShowViewerToolbar[]; extern const char optionLastDir[]; extern const char optionGeometry[]; extern const char optionWindowState[]; extern const char optionShortcuts[]; extern const char optionExternalApps[]; extern const char optionCopyMoveToPaths[]; extern const char optionKnownTags[]; extern const char optionSetWindowIcon[]; extern QSettings *appSettings; extern unsigned int layoutMode; extern unsigned int zoomInFlags; extern unsigned int zoomOutFlags; extern QColor viewerBackgroundColor; extern QColor thumbsBackgroundColor; extern QColor thumbsTextColor; extern unsigned int thumbsPagesReadCount; extern bool wrapImageList; extern bool enableAnimations; extern float imageZoomFactor; extern bool keepZoomFactor; extern int rotation; extern bool keepTransform; extern bool flipH; extern bool flipV; extern int scaledWidth; extern int scaledHeight; extern int defaultSaveQuality; extern int cropLeft; extern int cropTop; extern int cropWidth; extern int cropHeight; extern int cropLeftPercent; extern int cropTopPercent; extern int cropWidthPercent; extern int cropHeightPercent; extern int slideShowDelay; extern bool slideShowRandom; extern bool slideShowActive; extern QMap actionKeys; extern int hueVal; extern int saturationVal; extern int lightnessVal; extern int contrastVal; extern int brightVal; extern int redVal; extern int greenVal; extern int blueVal; extern bool colorsActive; extern bool colorizeEnabled; extern bool rNegateEnabled; extern bool gNegateEnabled; extern bool bNegateEnabled; extern bool hueRedChannel; extern bool hueGreenChannel; extern bool hueBlueChannel; extern bool exifRotationEnabled; extern bool exifThumbRotationEnabled; extern bool includeSubDirectories; extern bool showHiddenFiles; extern bool showViewerToolbar; extern QMap externalApps; extern QSet bookmarkPaths; extern QSet knownTags; extern bool reverseMouseBehavior; extern bool deleteConfirm; extern QModelIndexList copyCutIndexList; extern bool isCopyOperation; extern QStringList copyCutFileList; extern bool isFullScreen; extern int dialogLastX; extern int dialogLastY; extern StartupDir startupDir; extern QString specifiedStartDir; extern bool showImageName; extern bool smallToolbarIcons; extern bool hideDockTitlebars; extern bool fileSystemDockVisible; extern bool bookmarksDockVisible; extern bool imagePreviewDockVisible; extern bool tagsDockVisible; extern bool imageInfoDockVisible; extern QString currentDirectory; extern QString thumbsBackgroundImage; extern QStringList filesList; extern bool isFileListLoaded; extern bool setWindowIcon; } #endif // SETTINGS_H phototonic-2.1/SettingsDialog.cpp000066400000000000000000000453321325127642100172000ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "SettingsDialog.h" SettingsDialog::SettingsDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Preferences")); setWindowIcon(QIcon::fromTheme("preferences-system", QIcon(":/images/phototonic.png"))); // Zoom large images QGroupBox *fitLargeGroupBox = new QGroupBox(tr("Fit Large Images")); fitLargeRadios[0] = new QRadioButton(tr("Disable")); fitLargeRadios[1] = new QRadioButton(tr("By width or height")); fitLargeRadios[2] = new QRadioButton(tr("By width")); fitLargeRadios[3] = new QRadioButton(tr("By height")); fitLargeRadios[4] = new QRadioButton(tr("Stretch disproportionately")); QVBoxLayout *fitLargeVbox = new QVBoxLayout; for (int i = 0; i < nZoomRadios; ++i) { fitLargeVbox->addWidget(fitLargeRadios[i]); fitLargeRadios[i]->setChecked(false); } fitLargeVbox->addStretch(1); fitLargeGroupBox->setLayout(fitLargeVbox); fitLargeRadios[Settings::zoomOutFlags]->setChecked(true); // Zoom small images QGroupBox *fitSmallGroupBox = new QGroupBox(tr("Fit Small Images")); fitSmallRadios[0] = new QRadioButton(tr("Disable")); fitSmallRadios[1] = new QRadioButton(tr("By width or height")); fitSmallRadios[2] = new QRadioButton(tr("By width")); fitSmallRadios[3] = new QRadioButton(tr("By height")); fitSmallRadios[4] = new QRadioButton(tr("Stretch disproportionately")); QVBoxLayout *fitSmallVbox = new QVBoxLayout; for (int i = 0; i < nZoomRadios; ++i) { fitSmallVbox->addWidget(fitSmallRadios[i]); fitSmallRadios[i]->setChecked(false); } fitSmallVbox->addStretch(1); fitSmallGroupBox->setLayout(fitSmallVbox); fitSmallRadios[Settings::zoomInFlags]->setChecked(true); // imageViewer background color QLabel *backgroundColorLabel = new QLabel(tr("Background color:")); backgroundColorButton = new QToolButton(); backgroundColorButton->setFixedSize(48, 24); QHBoxLayout *backgroundColorHBox = new QHBoxLayout; backgroundColorHBox->addWidget(backgroundColorLabel); backgroundColorHBox->addWidget(backgroundColorButton); backgroundColorHBox->addStretch(1); connect(backgroundColorButton, SIGNAL(clicked()), this, SLOT(pickColor())); setButtonBgColor(Settings::viewerBackgroundColor, backgroundColorButton); backgroundColorButton->setAutoFillBackground(true); imageViewerBackgroundColor = Settings::viewerBackgroundColor; // Wrap image list wrapListCheckBox = new QCheckBox(tr("Wrap image list when reaching last or first image"), this); wrapListCheckBox->setChecked(Settings::wrapImageList); // Save quality QLabel *saveQualityLabel = new QLabel(tr("Default quality when saving:")); saveQualitySpinBox = new QSpinBox; saveQualitySpinBox->setRange(0, 100); saveQualitySpinBox->setValue(Settings::defaultSaveQuality); QHBoxLayout *saveQualityHbox = new QHBoxLayout; saveQualityHbox->addWidget(saveQualityLabel); saveQualityHbox->addWidget(saveQualitySpinBox); saveQualityHbox->addStretch(1); // Enable animations enableAnimCheckBox = new QCheckBox(tr("Enable GIF animation"), this); enableAnimCheckBox->setChecked(Settings::enableAnimations); // Enable image Exif rotation enableExifCheckBox = new QCheckBox(tr("Rotate image according to Exif orientation value"), this); enableExifCheckBox->setChecked(Settings::exifRotationEnabled); // Image name showImageNameCheckBox = new QCheckBox(tr("Show image file name in viewer"), this); showImageNameCheckBox->setChecked(Settings::showImageName); // Viewer options QVBoxLayout *viewerOptsBox = new QVBoxLayout; QHBoxLayout *zoomOptsBox = new QHBoxLayout; zoomOptsBox->setAlignment(Qt::AlignTop); zoomOptsBox->addWidget(fitLargeGroupBox); zoomOptsBox->addWidget(fitSmallGroupBox); zoomOptsBox->addStretch(1); viewerOptsBox->addLayout(zoomOptsBox); viewerOptsBox->addLayout(backgroundColorHBox); viewerOptsBox->addWidget(enableExifCheckBox); viewerOptsBox->addWidget(showImageNameCheckBox); viewerOptsBox->addWidget(wrapListCheckBox); viewerOptsBox->addWidget(enableAnimCheckBox); viewerOptsBox->addLayout(saveQualityHbox); viewerOptsBox->addStretch(1); // thumbsViewer background color QLabel *thumbsBackgroundColorLabel = new QLabel(tr("Thumbnails and Preview Background Color:")); thumbsColorPickerButton = new QToolButton(); thumbsColorPickerButton->setFixedSize(48, 24); QHBoxLayout *thumbsBackgroundColorLayout = new QHBoxLayout; thumbsBackgroundColorLayout->addWidget(thumbsBackgroundColorLabel); thumbsBackgroundColorLayout->addWidget(thumbsColorPickerButton); thumbsBackgroundColorLayout->addStretch(1); connect(thumbsColorPickerButton, SIGNAL(clicked()), this, SLOT(pickThumbsColor())); setButtonBgColor(Settings::thumbsBackgroundColor, thumbsColorPickerButton); thumbsColorPickerButton->setAutoFillBackground(true); thumbsBackgroundColor = Settings::thumbsBackgroundColor; // thumbsViewer text color QLabel *thumbLabelColorLabel = new QLabel(tr("Label color:")); thumbsLabelColorButton = new QToolButton(); thumbsLabelColorButton->setFixedSize(48, 24); QHBoxLayout *thumbsLabelColorLayout = new QHBoxLayout; thumbsLabelColorLayout->addWidget(thumbLabelColorLabel); thumbsLabelColorLayout->addWidget(thumbsLabelColorButton); thumbsLabelColorLayout->addStretch(1); connect(thumbsLabelColorButton, SIGNAL(clicked()), this, SLOT(pickThumbsTextColor())); setButtonBgColor(Settings::thumbsTextColor, thumbsLabelColorButton); thumbsLabelColorButton->setAutoFillBackground(true); thumbsTextColor = Settings::thumbsTextColor; // thumbsViewer background image QLabel *thumbsBackgroundImageLabel = new QLabel(tr("Background image:")); thumbsBackgroundImageLineEdit = new QLineEdit; thumbsBackgroundImageLineEdit->setClearButtonEnabled(true); thumbsBackgroundImageLineEdit->setMinimumWidth(200); QToolButton *chooseThumbsBackImageButton = new QToolButton(); chooseThumbsBackImageButton->setIcon(QIcon::fromTheme("document-open", QIcon(":/images/open.png"))); chooseThumbsBackImageButton->setFixedSize(26, 26); chooseThumbsBackImageButton->setIconSize(QSize(16, 16)); connect(chooseThumbsBackImageButton, SIGNAL(clicked()), this, SLOT(pickBackgroundImage())); QHBoxLayout *thumbsBackgroundImageLayout = new QHBoxLayout; thumbsBackgroundImageLayout->addWidget(thumbsBackgroundImageLabel); thumbsBackgroundImageLayout->addWidget(thumbsBackgroundImageLineEdit); thumbsBackgroundImageLayout->addWidget(chooseThumbsBackImageButton); thumbsBackgroundImageLayout->addStretch(1); thumbsBackgroundImageLineEdit->setText(Settings::thumbsBackgroundImage); // Thumbnail pages to read ahead QLabel *thumbsPagesReadLabel = new QLabel(tr("Number of thumbnail pages to read ahead:")); thumbPagesSpinBox = new QSpinBox; thumbPagesSpinBox->setRange(1, 10); thumbPagesSpinBox->setValue(Settings::thumbsPagesReadCount); QHBoxLayout *thumbPagesReadLayout = new QHBoxLayout; thumbPagesReadLayout->addWidget(thumbsPagesReadLabel); thumbPagesReadLayout->addWidget(thumbPagesSpinBox); thumbPagesReadLayout->addStretch(1); enableThumbExifCheckBox = new QCheckBox(tr("Rotate thumbnail according to Exif orientation value"), this); enableThumbExifCheckBox->setChecked(Settings::exifThumbRotationEnabled); // Thumbnail options QVBoxLayout *thumbsOptsBox = new QVBoxLayout; thumbsOptsBox->addLayout(thumbsBackgroundColorLayout); thumbsOptsBox->addLayout(thumbsBackgroundImageLayout); thumbsOptsBox->addLayout(thumbsLabelColorLayout); thumbsOptsBox->addWidget(enableThumbExifCheckBox); thumbsOptsBox->addLayout(thumbPagesReadLayout); thumbsOptsBox->addStretch(1); // Mouse settings reverseMouseCheckBox = new QCheckBox(tr("Swap mouse double-click and middle-click actions"), this); reverseMouseCheckBox->setChecked(Settings::reverseMouseBehavior); // Delete confirmation setting deleteConfirmCheckBox = new QCheckBox(tr("Delete confirmation"), this); deleteConfirmCheckBox->setChecked(Settings::deleteConfirm); // Startup directory QGroupBox *startupDirGroupBox = new QGroupBox(tr("Startup directory if not specified by command line")); startupDirectoryRadioButtons[Settings::RememberLastDir] = new QRadioButton(tr("Remember last")); startupDirectoryRadioButtons[Settings::DefaultDir] = new QRadioButton(tr("Default")); startupDirectoryRadioButtons[Settings::SpecifiedDir] = new QRadioButton(tr("Specify:")); startupDirLineEdit = new QLineEdit; startupDirLineEdit->setClearButtonEnabled(true); startupDirLineEdit->setMinimumWidth(300); startupDirLineEdit->setMaximumWidth(400); QToolButton *chooseStartupDirButton = new QToolButton(); chooseStartupDirButton->setIcon(QIcon::fromTheme("document-open", QIcon(":/images/open.png"))); chooseStartupDirButton->setFixedSize(26, 26); chooseStartupDirButton->setIconSize(QSize(16, 16)); connect(chooseStartupDirButton, SIGNAL(clicked()), this, SLOT(pickStartupDir())); QHBoxLayout *startupDirectoryLayout = new QHBoxLayout; startupDirectoryLayout->addWidget(startupDirectoryRadioButtons[2]); startupDirectoryLayout->addWidget(startupDirLineEdit); startupDirectoryLayout->addWidget(chooseStartupDirButton); startupDirectoryLayout->addStretch(1); QVBoxLayout *startupDirectoryMainLayout = new QVBoxLayout; for (int i = 0; i < 2; ++i) { startupDirectoryMainLayout->addWidget(startupDirectoryRadioButtons[i]); startupDirectoryRadioButtons[i]->setChecked(false); } startupDirectoryMainLayout->addLayout(startupDirectoryLayout); startupDirectoryMainLayout->addStretch(1); startupDirGroupBox->setLayout(startupDirectoryMainLayout); if (Settings::startupDir == Settings::SpecifiedDir) { startupDirectoryRadioButtons[Settings::SpecifiedDir]->setChecked(true); } else if (Settings::startupDir == Settings::RememberLastDir) { startupDirectoryRadioButtons[Settings::RememberLastDir]->setChecked(true); } else { startupDirectoryRadioButtons[Settings::DefaultDir]->setChecked(true); } startupDirLineEdit->setText(Settings::specifiedStartDir); // Keyboard shortcuts ShortcutsTable *shortcutsTable = new ShortcutsTable(); shortcutsTable->refreshShortcuts(); QGroupBox *keyboardGroupBox = new QGroupBox(tr("Keyboard")); QVBoxLayout *keyboardSettingsLayout = new QVBoxLayout; QHBoxLayout *filterShortcutsLayout = new QHBoxLayout; QLineEdit *shortcutsFilterLineEdit = new QLineEdit; shortcutsFilterLineEdit->setClearButtonEnabled(true); shortcutsFilterLineEdit->setPlaceholderText(tr("Filter Items")); connect(shortcutsFilterLineEdit, SIGNAL(textChanged( const QString&)), shortcutsTable, SLOT(setFilter( const QString&))); keyboardSettingsLayout->addWidget(new QLabel(tr("Select an entry and press a key to set a new shortcut"))); keyboardSettingsLayout->addWidget(shortcutsFilterLineEdit); keyboardSettingsLayout->addWidget(shortcutsTable); keyboardSettingsLayout->addLayout(filterShortcutsLayout); keyboardGroupBox->setLayout(keyboardSettingsLayout); // Set window icon setWindowIconCheckBox = new QCheckBox(tr("Set the application icon according to the current image"), this); setWindowIconCheckBox->setChecked(Settings::setWindowIcon); QVBoxLayout *generalSettingsLayout = new QVBoxLayout; generalSettingsLayout->addWidget(reverseMouseCheckBox); generalSettingsLayout->addWidget(deleteConfirmCheckBox); generalSettingsLayout->addWidget(startupDirGroupBox); // Slide show delay QLabel *slideDelayLab = new QLabel(tr("Delay between slides in seconds:")); slideDelaySpinBox = new QSpinBox; slideDelaySpinBox->setRange(1, 3600); slideDelaySpinBox->setValue(Settings::slideShowDelay); QHBoxLayout *slideDelayLayout = new QHBoxLayout; slideDelayLayout->addWidget(slideDelayLab); slideDelayLayout->addWidget(slideDelaySpinBox); slideDelayLayout->addStretch(1); // Slide show random slideRandomCheckBox = new QCheckBox(tr("Show random images"), this); slideRandomCheckBox->setChecked(Settings::slideShowRandom); // Slide show options QVBoxLayout *slideshowLayout = new QVBoxLayout; slideshowLayout->addLayout(slideDelayLayout); slideshowLayout->addWidget(slideRandomCheckBox); slideshowLayout->addStretch(1); QGroupBox *slideshowGroupBox = new QGroupBox(tr("Slide Show")); slideshowGroupBox->setLayout(slideshowLayout); generalSettingsLayout->addWidget(slideshowGroupBox); generalSettingsLayout->addWidget(setWindowIconCheckBox); generalSettingsLayout->addStretch(1); /* Confirmation buttons */ QHBoxLayout *confirmSettingsLayout = new QHBoxLayout; QPushButton *okButton = new QPushButton(tr("OK")); okButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(okButton, SIGNAL(clicked()), this, SLOT(saveSettings())); okButton->setDefault(true); QPushButton *closeButton = new QPushButton(tr("Cancel")); closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(closeButton, SIGNAL(clicked()), this, SLOT(abort())); confirmSettingsLayout->addWidget(closeButton, 1, Qt::AlignRight); confirmSettingsLayout->addWidget(okButton, 0, Qt::AlignRight); /* Tabs */ QTabWidget *settingsTabs = new QTabWidget; QWidget *viewerSettings = new QWidget; viewerSettings->setLayout(viewerOptsBox); settingsTabs->addTab(viewerSettings, tr("Viewer")); QWidget *thumbSettings = new QWidget; thumbSettings->setLayout(thumbsOptsBox); settingsTabs->addTab(thumbSettings, tr("Thumbnails")); QWidget *generalSettings = new QWidget; generalSettings->setLayout(generalSettingsLayout); settingsTabs->addTab(generalSettings, tr("General")); QWidget *keyboardSettings = new QWidget; keyboardSettings->setLayout(keyboardSettingsLayout); settingsTabs->addTab(keyboardSettings, tr("Keyboard")); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(settingsTabs); mainLayout->addLayout(confirmSettingsLayout); setLayout(mainLayout); } void SettingsDialog::saveSettings() { unsigned int i; for (i = 0; i < nZoomRadios; ++i) { if (fitLargeRadios[i]->isChecked()) { Settings::zoomOutFlags = i; Settings::appSettings->setValue(Settings::optionViewerZoomOutFlags, (int) Settings::zoomOutFlags); break; } } for (i = 0; i < nZoomRadios; ++i) { if (fitSmallRadios[i]->isChecked()) { Settings::zoomInFlags = i; Settings::appSettings->setValue(Settings::optionViewerZoomInFlags, (int) Settings::zoomInFlags); break; } } Settings::viewerBackgroundColor = imageViewerBackgroundColor; Settings::thumbsBackgroundColor = thumbsBackgroundColor; Settings::thumbsTextColor = thumbsTextColor; Settings::thumbsBackgroundImage = thumbsBackgroundImageLineEdit->text(); Settings::thumbsPagesReadCount = (unsigned int) thumbPagesSpinBox->value(); Settings::wrapImageList = wrapListCheckBox->isChecked(); Settings::defaultSaveQuality = saveQualitySpinBox->value(); Settings::slideShowDelay = slideDelaySpinBox->value(); Settings::slideShowRandom = slideRandomCheckBox->isChecked(); Settings::enableAnimations = enableAnimCheckBox->isChecked(); Settings::exifRotationEnabled = enableExifCheckBox->isChecked(); Settings::exifThumbRotationEnabled = enableThumbExifCheckBox->isChecked(); Settings::showImageName = showImageNameCheckBox->isChecked(); Settings::reverseMouseBehavior = reverseMouseCheckBox->isChecked(); Settings::deleteConfirm = deleteConfirmCheckBox->isChecked(); Settings::setWindowIcon = setWindowIconCheckBox->isChecked(); if (startupDirectoryRadioButtons[Settings::RememberLastDir]->isChecked()) { Settings::startupDir = Settings::RememberLastDir; } else if (startupDirectoryRadioButtons[Settings::DefaultDir]->isChecked()) { Settings::startupDir = Settings::DefaultDir; } else { Settings::startupDir = Settings::SpecifiedDir; Settings::specifiedStartDir = startupDirLineEdit->text(); } accept(); } void SettingsDialog::abort() { reject(); } void SettingsDialog::pickColor() { QColor userColor = QColorDialog::getColor(Settings::viewerBackgroundColor, this); if (userColor.isValid()) { setButtonBgColor(userColor, backgroundColorButton); imageViewerBackgroundColor = userColor; } } void SettingsDialog::setButtonBgColor(QColor &color, QToolButton *button) { QString style = "background: rgb(%1, %2, %3);"; style = style.arg(color.red()).arg(color.green()).arg(color.blue()); button->setStyleSheet(style); } void SettingsDialog::pickThumbsColor() { QColor userColor = QColorDialog::getColor(Settings::thumbsBackgroundColor, this); if (userColor.isValid()) { setButtonBgColor(userColor, thumbsColorPickerButton); thumbsBackgroundColor = userColor; } } void SettingsDialog::pickThumbsTextColor() { QColor userColor = QColorDialog::getColor(Settings::thumbsTextColor, this); if (userColor.isValid()) { setButtonBgColor(userColor, thumbsLabelColorButton); thumbsTextColor = userColor; } } void SettingsDialog::pickStartupDir() { QString dirName = QFileDialog::getExistingDirectory(this, tr("Choose Startup Directory"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); startupDirLineEdit->setText(dirName); } void SettingsDialog::pickBackgroundImage() { QString dirName = QFileDialog::getOpenFileName(this, tr("Open File"), "", tr("Images") + " (*.jpg *.jpeg *.jpe *.png *.bmp *.tiff *.tif *.ppm *.xbm *.xpm)"); thumbsBackgroundImageLineEdit->setText(dirName); } phototonic-2.1/SettingsDialog.h000066400000000000000000000043111325127642100166350ustar00rootroot00000000000000/* * Copyright (C) 2013-2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef SETTINGS_DIALOG_H #define SETTINGS_DIALOG_H #include #include "Settings.h" #include "ShortcutsTable.h" class SettingsDialog : public QDialog { Q_OBJECT public: static int const nZoomRadios = 5; SettingsDialog(QWidget *parent); private slots: void pickColor(); void pickThumbsColor(); void pickThumbsTextColor(); void pickStartupDir(); void pickBackgroundImage(); public slots: void abort(); void saveSettings(); private: QRadioButton *fitLargeRadios[nZoomRadios]; QRadioButton *fitSmallRadios[nZoomRadios]; QToolButton *backgroundColorButton; QToolButton *thumbsColorPickerButton; QToolButton *thumbsLabelColorButton; QSpinBox *thumbPagesSpinBox; QSpinBox *saveQualitySpinBox; QColor imageViewerBackgroundColor; QColor thumbsBackgroundColor; QColor thumbsTextColor; QCheckBox *wrapListCheckBox; QCheckBox *enableAnimCheckBox; QCheckBox *enableExifCheckBox; QCheckBox *enableThumbExifCheckBox; QCheckBox *showImageNameCheckBox; QCheckBox *reverseMouseCheckBox; QCheckBox *deleteConfirmCheckBox; QSpinBox *slideDelaySpinBox; QCheckBox *slideRandomCheckBox; QRadioButton *startupDirectoryRadioButtons[3]; QLineEdit *startupDirLineEdit; QLineEdit *thumbsBackgroundImageLineEdit; QCheckBox *setWindowIconCheckBox; void setButtonBgColor(QColor &color, QToolButton *button); }; #endif // SETTINGS_DIALOG_H phototonic-2.1/ShortcutsTable.cpp000066400000000000000000000141451325127642100172240ustar00rootroot00000000000000/* * Copyright (C) 2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "ShortcutsTable.h" #include "Settings.h" #include "MessageBox.h" ShortcutsTable::ShortcutsTable() { keysModel = new QStandardItemModel(); setModel(keysModel); setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::SingleSelection); setEditTriggers(QAbstractItemView::NoEditTriggers); verticalHeader()->hide(); verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); verticalHeader()->setDefaultSectionSize(verticalHeader()->minimumSectionSize()); horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); horizontalHeader()->setHighlightSections(false); horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); setColumnHidden(2, true); shortcutsMenu = new QMenu(""); clearAction = new QAction(tr("Delete shortcut"), this); connect(clearAction, SIGNAL(triggered()), this, SLOT(clearSelectedShortcut())); shortcutsMenu->addAction(clearAction); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showShortcutPopupMenu(QPoint))); shortcutsFilter.clear(); } void ShortcutsTable::addRow(QString action, QString description, QString shortcut) { keysModel->appendRow(QList() << new QStandardItem(description) << new QStandardItem(shortcut) << new QStandardItem(action)); } void ShortcutsTable::keyPressEvent(QKeyEvent *keyEvent) { if (!this->selectedIndexes().count()) { return; } QString keySequenceText; QString keyText(""); QString modifierText(""); if (keyEvent->modifiers() & Qt::ShiftModifier) modifierText += "Shift+"; if (keyEvent->modifiers() & Qt::ControlModifier) modifierText += "Ctrl+"; if (keyEvent->modifiers() & Qt::AltModifier) modifierText += "Alt+"; if ((keyEvent->key() >= Qt::Key_Shift && keyEvent->key() <= Qt::Key_ScrollLock) || (keyEvent->key() >= Qt::Key_Super_L && keyEvent->key() <= Qt::Key_Direction_R) || keyEvent->key() == Qt::Key_AltGr || keyEvent->key() < 0) { return; } keyText = QKeySequence(keyEvent->key()).toString(); keySequenceText = modifierText + keyText; if ((keyEvent->modifiers() & Qt::AltModifier) && (keyEvent->key() > Qt::Key_0 && keyEvent->key() <= Qt::Key_Colon)) { MessageBox msgBox(this); msgBox.warning(tr("Set shortcut"), tr("%1 is reserved for launching external applications.").arg(keySequenceText)); return; } QMapIterator keysIterator(Settings::actionKeys); bool needToRefreshShortCuts = false; while (keysIterator.hasNext()) { keysIterator.next(); QAction tmpAction(this); tmpAction.setShortcut(keySequenceText); if (keysIterator.value()->shortcut().toString() == tmpAction.shortcut().toString()) { if (!confirmOverwriteShortcut(keysIterator.value()->text(), keySequenceText)) { return; } Settings::actionKeys.value(keysIterator.key())->setShortcut(QKeySequence()); needToRefreshShortCuts = true; } } int row = selectedIndexes().first().row(); keysModel->item(row, 1)->setText(keySequenceText); Settings::actionKeys.value(keysModel->item(row, 2)->text())->setShortcut(QKeySequence(keySequenceText)); if (needToRefreshShortCuts) { refreshShortcuts(); } } bool ShortcutsTable::confirmOverwriteShortcut(QString action, QString shortcut) { MessageBox msgBox(this); msgBox.setText(tr("%1 is already assigned to %2, reassign shortcut?").arg(shortcut).arg(action)); msgBox.setWindowTitle(tr("Overwrite Shortcut")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Cancel); msgBox.setButtonText(MessageBox::Yes, tr("Yes")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); return (msgBox.exec() == MessageBox::Yes); } void ShortcutsTable::clearSelectedShortcut() { if (selectedEntry.isValid()) { QStandardItemModel *itemsModel = (QStandardItemModel *) model(); itemsModel->item(selectedEntry.row(), 1)->setText(""); Settings::actionKeys.value(itemsModel->item(selectedEntry.row(), 2)->text())->setShortcut(QKeySequence("")); } } void ShortcutsTable::showShortcutPopupMenu(QPoint point) { selectedEntry = indexAt(point); if (selectedEntry.isValid()) shortcutsMenu->popup(viewport()->mapToGlobal(point)); } void ShortcutsTable::setFilter(QString filter) { this->shortcutsFilter = filter; refreshShortcuts(); } void ShortcutsTable::refreshShortcuts() { keysModel->clear(); keysModel->setHorizontalHeaderItem(0, new QStandardItem(tr("Action"))); keysModel->setHorizontalHeaderItem(1, new QStandardItem(tr("Shortcut"))); QMapIterator it(Settings::actionKeys); while (it.hasNext()) { it.next(); if (!shortcutsFilter.isEmpty() && !Settings::actionKeys.value(it.key())->text().toLower().contains(shortcutsFilter.toLower())) { continue; } addRow(it.key(), Settings::actionKeys.value(it.key())->text(), Settings::actionKeys.value(it.key())->shortcut().toString()); } setColumnHidden(2, true); } phototonic-2.1/ShortcutsTable.h000066400000000000000000000027111325127642100166650ustar00rootroot00000000000000/* * Copyright (C) 2018 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef SHORTCUTS_TABLE_H #define SHORTCUTS_TABLE_H #include class ShortcutsTable : public QTableView { Q_OBJECT public: ShortcutsTable(); void addRow(QString action, QString description, QString shortcut); void refreshShortcuts(); public slots: void setFilter(QString filter); void showShortcutPopupMenu(QPoint point); void clearSelectedShortcut(); protected: void keyPressEvent(QKeyEvent *keyEvent); private: bool confirmOverwriteShortcut(QString action, QString shortcut); QStandardItemModel *keysModel; QModelIndex selectedEntry; QMenu *shortcutsMenu; QAction *clearAction; QString shortcutsFilter; }; #endif // SHORTCUTS_TABLE_H phototonic-2.1/Tags.cpp000066400000000000000000000416431325127642100151570ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "Tags.h" #include "Settings.h" #include "ProgressDialog.h" #include "MessageBox.h" ImageTags::ImageTags(QWidget *parent, ThumbsViewer *thumbsViewer, MetadataCache *metadataCache) : QWidget(parent) { tagsTree = new QTreeWidget; tagsTree->setColumnCount(2); tagsTree->setDragEnabled(false); tagsTree->setSortingEnabled(true); tagsTree->header()->close(); tagsTree->setSelectionMode(QAbstractItemView::ExtendedSelection); this->thumbView = thumbsViewer; this->metadataCache = metadataCache; negateFilterEnabled = false; tabs = new QTabBar(this); tabs->addTab(tr("Selection")); tabs->addTab(tr("Filter")); tabs->setTabIcon(0, QIcon(":/images/tag_yellow.png")); tabs->setTabIcon(1, QIcon(":/images/tag_filter_off.png")); tabs->setExpanding(false); connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabsChanged(int))); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->setContentsMargins(0, 3, 0, 0); mainLayout->setSpacing(0); mainLayout->addWidget(tabs); mainLayout->addWidget(tagsTree); setLayout(mainLayout); currentDisplayMode = SelectionTagsDisplay; dirFilteringActive = false; connect(tagsTree, SIGNAL(itemChanged(QTreeWidgetItem * , int)), this, SLOT(saveLastChangedTag(QTreeWidgetItem * , int))); connect(tagsTree, SIGNAL(itemClicked(QTreeWidgetItem * , int)), this, SLOT(tagClicked(QTreeWidgetItem * , int))); tagsTree->setContextMenuPolicy(Qt::CustomContextMenu); connect(tagsTree, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showMenu(QPoint))); addToSelectionAction = new QAction(tr("Tag"), this); addToSelectionAction->setIcon(QIcon(":/images/tag_yellow.png")); connect(addToSelectionAction, SIGNAL(triggered()), this, SLOT(addTagsToSelection())); removeFromSelectionAction = new QAction(tr("Untag"), this); connect(removeFromSelectionAction, SIGNAL(triggered()), this, SLOT(removeTagsFromSelection())); actionAddTag = new QAction(tr("New Tag"), this); actionAddTag->setIcon(QIcon(":/images/new_tag.png")); connect(actionAddTag, SIGNAL(triggered()), this, SLOT(addNewTag())); removeTagAction = new QAction(tr("Delete Tag"), this); removeTagAction->setIcon(QIcon::fromTheme("edit-delete", QIcon(":/images/delete.png"))); actionClearTagsFilter = new QAction(tr("Clear Filters"), this); actionClearTagsFilter->setIcon(QIcon(":/images/tag_filter_off.png")); connect(actionClearTagsFilter, SIGNAL(triggered()), this, SLOT(clearTagFilters())); negateAction = new QAction(tr("Negate"), this); negateAction->setCheckable(true); connect(negateAction, SIGNAL(triggered()), this, SLOT(negateFilter())); tagsMenu = new QMenu(""); tagsMenu->addAction(addToSelectionAction); tagsMenu->addAction(removeFromSelectionAction); tagsMenu->addSeparator(); tagsMenu->addAction(actionAddTag); tagsMenu->addAction(removeTagAction); tagsMenu->addSeparator(); tagsMenu->addAction(actionClearTagsFilter); tagsMenu->addAction(negateAction); } void ImageTags::redrawTagTree() { tagsTree->resizeColumnToContents(0); tagsTree->sortItems(0, Qt::AscendingOrder); } void ImageTags::showMenu(QPoint point) { QTreeWidgetItem *item = tagsTree->itemAt(point); addToSelectionAction->setEnabled(item != NULL); removeFromSelectionAction->setEnabled(item != NULL); removeTagAction->setEnabled(item != NULL); tagsMenu->popup(tagsTree->viewport()->mapToGlobal(point)); } void ImageTags::setTagIcon(QTreeWidgetItem *tagItem, TagIcons icon) { switch (icon) { case TagIconDisabled: tagItem->setIcon(0, QIcon(":/images/tag_grey.png")); break; case TagIconEnabled: tagItem->setIcon(0, QIcon(":/images/tag_yellow.png")); break; case TagIconMultiple: tagItem->setIcon(0, QIcon(":/images/tag_multi.png")); break; case TagIconFilterEnabled: tagItem->setIcon(0, QIcon(":/images/tag_filter_on.png")); break; case TagIconFilterDisabled: tagItem->setIcon(0, QIcon(":/images/tag_filter_off.png")); break; case TagIconFilterNegate: tagItem->setIcon(0, QIcon(":/images/tag_filter_negate.png")); break; } } void ImageTags::addTag(QString tagName, bool tagChecked) { QTreeWidgetItem *tagItem = new QTreeWidgetItem(); tagItem->setText(0, tagName); tagItem->setCheckState(0, tagChecked ? Qt::Checked : Qt::Unchecked); setTagIcon(tagItem, tagChecked ? TagIconEnabled : TagIconDisabled); tagsTree->addTopLevelItem(tagItem); } bool ImageTags::writeTagsToImage(QString &imageFileName, QSet &newTags) { QSet imageTags; Exiv2::Image::AutoPtr exifImage; try { exifImage = Exiv2::ImageFactory::open(imageFileName.toStdString()); exifImage->readMetadata(); Exiv2::IptcData newIptcData; /* copy existing data */ Exiv2::IptcData &iptcData = exifImage->iptcData(); if (!iptcData.empty()) { QString key; Exiv2::IptcData::iterator end = iptcData.end(); for (Exiv2::IptcData::iterator iptcIt = iptcData.begin(); iptcIt != end; ++iptcIt) { if (iptcIt->tagName() != "Keywords") { newIptcData.add(*iptcIt); } } } /* add new tags */ QSetIterator newTagsIt(newTags); while (newTagsIt.hasNext()) { QString tag = newTagsIt.next(); Exiv2::Value::AutoPtr value = Exiv2::Value::create(Exiv2::string); value->read(tag.toStdString()); Exiv2::IptcKey key("Iptc.Application2.Keywords"); newIptcData.add(key, value.get()); } exifImage->setIptcData(newIptcData); exifImage->writeMetadata(); } catch (Exiv2::Error &error) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Failed to save tags to ") + imageFileName); return false; } return true; } void ImageTags::showSelectedImagesTags() { static bool busy = false; if (busy) return; busy = true; QStringList selectedThumbs = thumbView->getSelectedThumbsList(); setActiveViewMode(SelectionTagsDisplay); int selectedThumbsNum = selectedThumbs.size(); QMap tagsCount; for (int i = 0; i < selectedThumbsNum; ++i) { QSetIterator imageTagsIter(metadataCache->getImageTags(selectedThumbs[i])); while (imageTagsIter.hasNext()) { QString imageTag = imageTagsIter.next(); tagsCount[imageTag]++; if (!Settings::knownTags.contains(imageTag)) { addTag(imageTag, true); Settings::knownTags.insert(imageTag); } } } bool imagesTagged = false, imagesTaggedMixed = false; QTreeWidgetItemIterator it(tagsTree); while (*it) { QString tagName = (*it)->text(0); int tagCountTotal = tagsCount[tagName]; if (selectedThumbsNum == 0) { (*it)->setCheckState(0, Qt::Unchecked); (*it)->setFlags((*it)->flags() & ~Qt::ItemIsUserCheckable); setTagIcon(*it, TagIconDisabled); } else if (tagCountTotal == selectedThumbsNum) { (*it)->setCheckState(0, Qt::Checked); (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); setTagIcon(*it, TagIconEnabled); imagesTagged = true; } else if (tagCountTotal) { (*it)->setCheckState(0, Qt::PartiallyChecked); (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); setTagIcon(*it, TagIconMultiple); imagesTaggedMixed = true; } else { (*it)->setCheckState(0, Qt::Unchecked); (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); setTagIcon(*it, TagIconDisabled); } ++it; } if (imagesTagged) { tabs->setTabIcon(0, QIcon(":/images/tag_yellow.png")); } else if (imagesTaggedMixed) { tabs->setTabIcon(0, QIcon(":/images/tag_multi.png")); } else { tabs->setTabIcon(0, QIcon(":/images/tag_grey.png")); } addToSelectionAction->setEnabled(selectedThumbsNum ? true : false); removeFromSelectionAction->setEnabled(selectedThumbsNum ? true : false); redrawTagTree(); busy = false; } void ImageTags::showTagsFilter() { static bool busy = false; if (busy) return; busy = true; setActiveViewMode(DirectoryTagsDisplay); QTreeWidgetItemIterator it(tagsTree); while (*it) { QString tagName = (*it)->text(0); (*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); if (imageFilteringTags.contains(tagName)) { (*it)->setCheckState(0, Qt::Checked); setTagIcon(*it, negateFilterEnabled ? TagIconFilterNegate : TagIconFilterEnabled); } else { (*it)->setCheckState(0, Qt::Unchecked); setTagIcon(*it, TagIconFilterDisabled); } ++it; } redrawTagTree(); busy = false; } void ImageTags::populateTagsTree() { tagsTree->clear(); QSetIterator knownTagsIt(Settings::knownTags); while (knownTagsIt.hasNext()) { QString tag = knownTagsIt.next(); addTag(tag, false); } redrawTagTree(); if (currentDisplayMode == SelectionTagsDisplay) { showSelectedImagesTags(); } else { showTagsFilter(); } } void ImageTags::setActiveViewMode(TagsDisplayMode mode) { currentDisplayMode = mode; actionAddTag->setVisible(currentDisplayMode == SelectionTagsDisplay); removeTagAction->setVisible(currentDisplayMode == SelectionTagsDisplay); addToSelectionAction->setVisible(currentDisplayMode == SelectionTagsDisplay); removeFromSelectionAction->setVisible(currentDisplayMode == SelectionTagsDisplay); actionClearTagsFilter->setVisible(currentDisplayMode == DirectoryTagsDisplay); negateAction->setVisible(currentDisplayMode == DirectoryTagsDisplay); } bool ImageTags::isImageFilteredOut(QString imageFileName) { QSet imageTags = metadataCache->getImageTags(imageFileName); QSetIterator filteredTagsIt(imageFilteringTags); while (filteredTagsIt.hasNext()) { if (imageTags.contains(filteredTagsIt.next())) { return negateFilterEnabled; } } return !negateFilterEnabled; } void ImageTags::resetTagsState() { tagsTree->clear(); metadataCache->clear(); } QSet ImageTags::getCheckedTags(Qt::CheckState tagState) { QSet checkedTags; QTreeWidgetItemIterator it(tagsTree); while (*it) { if ((*it)->checkState(0) == tagState) { checkedTags.insert((*it)->text(0)); } ++it; } return checkedTags; } void ImageTags::applyTagFiltering() { imageFilteringTags = getCheckedTags(Qt::Checked); if (imageFilteringTags.size()) { dirFilteringActive = true; if (negateFilterEnabled) { tabs->setTabIcon(1, QIcon(":/images/tag_filter_negate.png")); } else { tabs->setTabIcon(1, QIcon(":/images/tag_filter_on.png")); } } else { dirFilteringActive = false; tabs->setTabIcon(1, QIcon(":/images/tag_filter_off.png")); } emit reloadThumbs(); } void ImageTags::applyUserAction(QTreeWidgetItem *item) { QList tagsList; tagsList << item; applyUserAction(tagsList); } void ImageTags::applyUserAction(QList tagsList) { int processEventsCounter = 0; ProgressDialog *progressDialog = new ProgressDialog(this); progressDialog->show(); QStringList currentSelectedImages = thumbView->getSelectedThumbsList(); for (int currentImage = 0; currentImage < currentSelectedImages.size(); ++currentImage) { QString imageName = currentSelectedImages[currentImage]; for (int i = tagsList.size() - 1; i > -1; --i) { Qt::CheckState tagState = tagsList.at(i)->checkState(0); setTagIcon(tagsList.at(i), (tagState == Qt::Checked ? TagIconEnabled : TagIconDisabled)); QString tagName = tagsList.at(i)->text(0); if (tagState == Qt::Checked) { progressDialog->opLabel->setText(tr("Tagging ") + imageName); metadataCache->addTagToImage(imageName, tagName); } else { progressDialog->opLabel->setText(tr("Untagging ") + imageName); metadataCache->removeTagFromImage(imageName, tagName); } } if (!writeTagsToImage(imageName, metadataCache->getImageTags(imageName))) { metadataCache->removeImage(imageName); } ++processEventsCounter; if (processEventsCounter > 9) { processEventsCounter = 0; QApplication::processEvents(); } if (progressDialog->abortOp) { break; } } progressDialog->close(); delete (progressDialog); } void ImageTags::saveLastChangedTag(QTreeWidgetItem *item, int) { lastChangedTagItem = item; } void ImageTags::tabsChanged(int index) { if (!index) { showSelectedImagesTags(); } else { showTagsFilter(); } } void ImageTags::tagClicked(QTreeWidgetItem *item, int) { if (item == lastChangedTagItem) { if (currentDisplayMode == DirectoryTagsDisplay) { applyTagFiltering(); } else { applyUserAction(item); } lastChangedTagItem = 0; } } void ImageTags::removeTagsFromSelection() { for (int i = tagsTree->selectedItems().size() - 1; i > -1; --i) { tagsTree->selectedItems().at(i)->setCheckState(0, Qt::Unchecked); } applyUserAction(tagsTree->selectedItems()); } void ImageTags::addTagsToSelection() { for (int i = tagsTree->selectedItems().size() - 1; i > -1; --i) { tagsTree->selectedItems().at(i)->setCheckState(0, Qt::Checked); } applyUserAction(tagsTree->selectedItems()); } void ImageTags::clearTagFilters() { QTreeWidgetItemIterator it(tagsTree); while (*it) { (*it)->setCheckState(0, Qt::Unchecked); ++it; } imageFilteringTags.clear(); applyTagFiltering(); } void ImageTags::negateFilter() { negateFilterEnabled = negateAction->isChecked(); applyTagFiltering(); } void ImageTags::addNewTag() { bool ok; QString title = tr("Add a new tag"); QString newTagName = QInputDialog::getText(this, title, tr("Enter new tag name"), QLineEdit::Normal, "", &ok); if (!ok) { return; } if (newTagName.isEmpty()) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("No name entered")); return; } QSetIterator knownTagsIt(Settings::knownTags); while (knownTagsIt.hasNext()) { QString tag = knownTagsIt.next(); if (newTagName == tag) { MessageBox msgBox(this); msgBox.critical(tr("Error"), tr("Tag ") + newTagName + tr(" already exists")); return; } } addTag(newTagName, false); Settings::knownTags.insert(newTagName); redrawTagTree(); } void ImageTags::removeTag() { if (!tagsTree->selectedItems().size()) { return; } MessageBox msgBox(this); msgBox.setText(tr("Delete selected tags(s)?")); msgBox.setWindowTitle(tr("Delete tag")); msgBox.setIcon(MessageBox::Warning); msgBox.setStandardButtons(MessageBox::Yes | MessageBox::Cancel); msgBox.setDefaultButton(MessageBox::Cancel); msgBox.setButtonText(MessageBox::Yes, tr("Yes")); msgBox.setButtonText(MessageBox::Cancel, tr("Cancel")); if (msgBox.exec() != MessageBox::Yes) { return; } bool removedTagWasChecked = false; for (int i = tagsTree->selectedItems().size() - 1; i > -1; --i) { QString tagName = tagsTree->selectedItems().at(i)->text(0); Settings::knownTags.remove(tagName); if (imageFilteringTags.contains(tagName)) { imageFilteringTags.remove(tagName); removedTagWasChecked = true; } tagsTree->takeTopLevelItem(tagsTree->indexOfTopLevelItem(tagsTree->selectedItems().at(i))); } if (removedTagWasChecked) { applyTagFiltering(); } } phototonic-2.1/Tags.h000066400000000000000000000055161325127642100146230ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef TAGS_H #define TAGS_H #include #include #include "ThumbsViewer.h" #include "MetadataCache.h" class ThumbsViewer; enum TagsDisplayMode { DirectoryTagsDisplay, SelectionTagsDisplay }; enum TagIcons { TagIconDisabled, TagIconEnabled, TagIconMultiple, TagIconFilterDisabled, TagIconFilterEnabled, TagIconFilterNegate }; class ImageTags : public QWidget { Q_OBJECT public: ImageTags(QWidget *parent, ThumbsViewer *thumbsViewer, MetadataCache *metadataCache); void addTag(QString tagName, bool tagChecked); void showTagsFilter(); void showSelectedImagesTags(); void resetTagsState(); bool isImageFilteredOut(QString imagePath); void removeTag(); void populateTagsTree(); QMenu *tagsMenu; QTreeWidget *tagsTree; bool dirFilteringActive; QAction *removeTagAction; TagsDisplayMode currentDisplayMode; private: bool writeTagsToImage(QString &imageFileName, QSet &tags); QSet getCheckedTags(Qt::CheckState tagState); void setTagIcon(QTreeWidgetItem *tagItem, TagIcons icon); void setActiveViewMode(TagsDisplayMode mode); void applyUserAction(QTreeWidgetItem *item); void applyUserAction(QList tagsList); void redrawTagTree(); QSet imageFilteringTags; QAction *actionAddTag; QAction *addToSelectionAction; QAction *removeFromSelectionAction; QAction *actionClearTagsFilter; QAction *negateAction; QTreeWidgetItem *lastChangedTagItem; ThumbsViewer *thumbView; QTabBar *tabs; MetadataCache *metadataCache; bool negateFilterEnabled; private slots: void tagClicked(QTreeWidgetItem *item, int column); void saveLastChangedTag(QTreeWidgetItem *item, int column); void applyTagFiltering(); void showMenu(QPoint point); void addNewTag(); void addTagsToSelection(); void clearTagFilters(); void negateFilter(); void removeTagsFromSelection(); void tabsChanged(int index); signals: void reloadThumbs(); }; #endif // TAGS_H phototonic-2.1/ThumbsViewer.cpp000066400000000000000000000620671325127642100167100ustar00rootroot00000000000000/* * Copyright (C) 2013-2014 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "ThumbsViewer.h" #include "Phototonic.h" ThumbsViewer::ThumbsViewer(QWidget *parent, MetadataCache *metadataCache) : QListView(parent) { this->metadataCache = metadataCache; Settings::thumbsBackgroundColor = Settings::appSettings->value( Settings::optionThumbsBackgroundColor).value(); Settings::thumbsTextColor = Settings::appSettings->value(Settings::optionThumbsTextColor).value(); setThumbColors(); Settings::thumbsPagesReadCount = Settings::appSettings->value(Settings::optionThumbsPagesReadCount).toUInt(); thumbSize = Settings::appSettings->value(Settings::optionThumbsZoomLevel).toInt(); currentRow = 0; setViewMode(QListView::IconMode); setSelectionMode(QAbstractItemView::ExtendedSelection); setResizeMode(QListView::Adjust); setWordWrap(true); setDragEnabled(true); setEditTriggers(QAbstractItemView::NoEditTriggers); setUniformItemSizes(false); thumbsViewerModel = new QStandardItemModel(this); thumbsViewerModel->setSortRole(SortRole); setModel(thumbsViewerModel); connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(loadVisibleThumbs(int))); connect(this->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(onSelectionChanged(QItemSelection))); connect(this, SIGNAL(doubleClicked( const QModelIndex &)), parent, SLOT(loadSelectedThumbImage( const QModelIndex &))); thumbsDir = new QDir(); fileFilters = new QStringList; emptyImg.load(":/images/no_image.png"); QTime time = QTime::currentTime(); qsrand((uint) time.msec()); phototonic = (Phototonic *) parent; infoView = new InfoView(this); connect(infoView, SIGNAL(updateInfo(QItemSelection)), this, SLOT(onSelectionChanged(QItemSelection))); imagePreview = new ImagePreview(this); } void ThumbsViewer::setThumbColors() { QString backgroundColor = "background: rgb(%1, %2, %3); "; backgroundColor = backgroundColor.arg(Settings::thumbsBackgroundColor.red()) .arg(Settings::thumbsBackgroundColor.green()) .arg(Settings::thumbsBackgroundColor.blue()); QString styleSheet = "QListView { " + backgroundColor + "background-image: url(" + Settings::thumbsBackgroundImage + "); background-attachment: fixed; }"; setStyleSheet(styleSheet); QPalette scrollBarOriginalPalette = verticalScrollBar()->palette(); QPalette thumbViewerOriginalPalette = palette(); thumbViewerOriginalPalette.setColor(QPalette::Text, Settings::thumbsTextColor); setPalette(thumbViewerOriginalPalette); verticalScrollBar()->setPalette(scrollBarOriginalPalette); } void ThumbsViewer::selectCurrentIndex() { if (currentIndex.isValid() && thumbsViewerModel->rowCount() > 0) { scrollTo(currentIndex); setCurrentIndex(currentIndex); } } QString ThumbsViewer::getSingleSelectionFilename() { if (selectionModel()->selectedIndexes().size() == 1) return thumbsViewerModel->item(selectionModel()->selectedIndexes().first().row())->data( FileNameRole).toString(); return (""); } int ThumbsViewer::getNextRow() { if (currentRow == thumbsViewerModel->rowCount() - 1) { return -1; } return currentRow + 1; } int ThumbsViewer::getPrevRow() { if (currentRow == 0) { return -1; } return currentRow - 1; } int ThumbsViewer::getLastRow() { return thumbsViewerModel->rowCount() - 1; } int ThumbsViewer::getRandomRow() { return qrand() % (thumbsViewerModel->rowCount()); } int ThumbsViewer::getCurrentRow() { return currentRow; } void ThumbsViewer::setCurrentRow(int row) { if (row >= 0) { currentRow = row; } else { currentRow = 0; } } void ThumbsViewer::setImageViewerWindowTitle() { QString title = thumbsViewerModel->item(currentRow)->data(Qt::DisplayRole).toString() + " - [" + QString::number(currentRow + 1) + "/" + QString::number(thumbsViewerModel->rowCount()) + "] - Phototonic"; phototonic->setWindowTitle(title); } bool ThumbsViewer::setCurrentIndexByName(QString &fileName) { QModelIndexList indexList = thumbsViewerModel->match(thumbsViewerModel->index(0, 0), FileNameRole, fileName); if (indexList.size()) { currentIndex = indexList[0]; setCurrentRow(currentIndex.row()); return true; } return false; } bool ThumbsViewer::setCurrentIndexByRow(int row) { QModelIndex idx = thumbsViewerModel->indexFromItem(thumbsViewerModel->item(row)); if (idx.isValid()) { currentIndex = idx; setCurrentRow(idx.row()); return true; } return false; } void ThumbsViewer::updateImageInfoViewer(QString imageFullPath) { QImageReader imageInfoReader(imageFullPath); QString key; QString val; QFileInfo imageInfo = QFileInfo(imageFullPath); infoView->addTitleEntry(tr("Image")); key = tr("File name"); val = imageInfo.fileName(); infoView->addEntry(key, val); key = tr("Location"); val = imageInfo.path(); infoView->addEntry(key, val); key = tr("Size"); val = QString::number(imageInfo.size() / 1024.0, 'f', 2) + "K"; infoView->addEntry(key, val); key = tr("Modified"); val = imageInfo.lastModified().toString(Qt::SystemLocaleShortDate); infoView->addEntry(key, val); if (imageInfoReader.size().isValid()) { key = tr("Format"); val = imageInfoReader.format().toUpper(); infoView->addEntry(key, val); key = tr("Resolution"); val = QString::number(imageInfoReader.size().width()) + "x" + QString::number(imageInfoReader.size().height()); infoView->addEntry(key, val); key = tr("Megapixel"); val = QString::number((imageInfoReader.size().width() * imageInfoReader.size().height()) / 1000000.0, 'f', 2); infoView->addEntry(key, val); } else { imageInfoReader.read(); key = tr("Error"); val = imageInfoReader.errorString(); infoView->addEntry(key, val); } Exiv2::Image::AutoPtr exifImage; try { exifImage = Exiv2::ImageFactory::open(imageFullPath.toStdString()); exifImage->readMetadata(); } catch (Exiv2::Error &error) { return; } Exiv2::ExifData &exifData = exifImage->exifData(); if (!exifData.empty()) { Exiv2::ExifData::const_iterator end = exifData.end(); infoView->addTitleEntry("Exif"); for (Exiv2::ExifData::const_iterator md = exifData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } Exiv2::IptcData &iptcData = exifImage->iptcData(); if (!iptcData.empty()) { Exiv2::IptcData::iterator end = iptcData.end(); infoView->addTitleEntry("IPTC"); for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } Exiv2::XmpData &xmpData = exifImage->xmpData(); if (!xmpData.empty()) { Exiv2::XmpData::iterator end = xmpData.end(); infoView->addTitleEntry("XMP"); for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } } void ThumbsViewer::onSelectionChanged(const QItemSelection &) { infoView->clear(); imagePreview->clear(); if (Settings::setWindowIcon && Settings::layoutMode == Phototonic::ThumbViewWidget) { phototonic->setWindowIcon(phototonic->getDefaultWindowIcon()); } QModelIndexList indexesList = selectionModel()->selectedIndexes(); int selectedThumbs = indexesList.size(); if (selectedThumbs == 1) { int currentRow = indexesList.first().row(); QString thumbFullPath = thumbsViewerModel->item(currentRow)->data(FileNameRole).toString(); setCurrentRow(currentRow); updateImageInfoViewer(thumbFullPath); QPixmap imagePreviewPixmap = imagePreview->loadImage(thumbFullPath); if (Settings::setWindowIcon && Settings::layoutMode == Phototonic::ThumbViewWidget) { phototonic->setWindowIcon(imagePreviewPixmap.scaled(WINDOW_ICON_SIZE, WINDOW_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } } if (imageTags->currentDisplayMode == SelectionTagsDisplay) { imageTags->showSelectedImagesTags(); } if (selectedThumbs >= 1) { QString statusStr; statusStr = tr("Selected %1 of %2").arg(QString::number(selectedThumbs)) .arg(tr(" %n image(s)", "", thumbsViewerModel->rowCount())); phototonic->setStatus(statusStr); } else if (!selectedThumbs) { updateThumbsCount(); } } QStringList ThumbsViewer::getSelectedThumbsList() { QModelIndexList indexesList = selectionModel()->selectedIndexes(); QStringList SelectedThumbsPaths; for (int tn = indexesList.size() - 1; tn >= 0; --tn) { SelectedThumbsPaths << thumbsViewerModel->item(indexesList[tn].row())->data(FileNameRole).toString(); } return SelectedThumbsPaths; } void ThumbsViewer::startDrag(Qt::DropActions) { QModelIndexList indexesList = selectionModel()->selectedIndexes(); if (indexesList.isEmpty()) { return; } QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; QList urls; for (QModelIndexList::const_iterator it = indexesList.constBegin(), end = indexesList.constEnd(); it != end; ++it) { urls << QUrl(thumbsViewerModel->item(it->row())->data(FileNameRole).toString()); } mimeData->setUrls(urls); drag->setMimeData(mimeData); QPixmap pix; if (indexesList.count() > 1) { pix = QPixmap(128, 112); pix.fill(Qt::transparent); QPainter painter(&pix); painter.setBrush(Qt::NoBrush); painter.setPen(QPen(Qt::white, 2)); int x = 0, y = 0, xMax = 0, yMax = 0; for (int i = 0; i < qMin(5, indexesList.count()); ++i) { QPixmap pix = thumbsViewerModel->item(indexesList.at(i).row())->icon().pixmap(72); if (i == 4) { x = (xMax - pix.width()) / 2; y = (yMax - pix.height()) / 2; } painter.drawPixmap(x, y, pix); xMax = qMax(xMax, qMin(128, x + pix.width())); yMax = qMax(yMax, qMin(112, y + pix.height())); painter.drawRect(x + 1, y + 1, qMin(126, pix.width() - 2), qMin(110, pix.height() - 2)); x = !(x == y) * 56; y = !y * 40; } painter.end(); pix = pix.copy(0, 0, xMax, yMax); drag->setPixmap(pix); } else { pix = thumbsViewerModel->item(indexesList.at(0).row())->icon().pixmap(128); drag->setPixmap(pix); } drag->setHotSpot(QPoint(pix.width() / 2, pix.height() / 2)); drag->exec(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction, Qt::IgnoreAction); } void ThumbsViewer::abort() { isAbortThumbsLoading = true; } void ThumbsViewer::loadVisibleThumbs(int scrollBarValue) { static int lastScrollBarValue = 0; scrolledForward = (scrollBarValue >= lastScrollBarValue); lastScrollBarValue = scrollBarValue; for (;;) { int firstVisible = getFirstVisibleThumb(); int lastVisible = getLastVisibleThumb(); if (isAbortThumbsLoading || firstVisible < 0 || lastVisible < 0) { return; } if (scrolledForward) { lastVisible += ((lastVisible - firstVisible) * (Settings::thumbsPagesReadCount + 1)); if (lastVisible >= thumbsViewerModel->rowCount()) { lastVisible = thumbsViewerModel->rowCount() - 1; } } else { firstVisible -= (lastVisible - firstVisible) * (Settings::thumbsPagesReadCount + 1); if (firstVisible < 0) { firstVisible = 0; } lastVisible += 10; if (lastVisible >= thumbsViewerModel->rowCount()) { lastVisible = thumbsViewerModel->rowCount() - 1; } } if (thumbsRangeFirst == firstVisible && thumbsRangeLast == lastVisible) { return; } thumbsRangeFirst = firstVisible; thumbsRangeLast = lastVisible; loadThumbsRange(); if (isAbortThumbsLoading) { break; } } } int ThumbsViewer::getFirstVisibleThumb() { QModelIndex idx; for (int currThumb = 0; currThumb < thumbsViewerModel->rowCount(); ++currThumb) { idx = thumbsViewerModel->indexFromItem(thumbsViewerModel->item(currThumb)); if (viewport()->rect().contains(QPoint(0, visualRect(idx).y() + visualRect(idx).height() + 1))) { return idx.row(); } } return -1; } int ThumbsViewer::getLastVisibleThumb() { QModelIndex idx; for (int currThumb = thumbsViewerModel->rowCount() - 1; currThumb >= 0; --currThumb) { idx = thumbsViewerModel->indexFromItem(thumbsViewerModel->item(currThumb)); if (viewport()->rect().contains(QPoint(0, visualRect(idx).y() + visualRect(idx).height() + 1))) { return idx.row(); } } return -1; } void ThumbsViewer::loadFileList() { for (int i = 0; i < Settings::filesList.size(); i++) { addThumb(Settings::filesList[i]); } updateThumbsCount(); imageTags->populateTagsTree(); if (thumbFileInfoList.size() && selectionModel()->selectedIndexes().size() == 0) { selectThumbByRow(0); } phototonic->showBusyAnimation(false); isBusy = false; } void ThumbsViewer::reLoad() { isBusy = true; phototonic->showBusyAnimation(true); loadPrepare(); if (Settings::isFileListLoaded) { loadFileList(); return; } applyFilter(); initThumbs(); updateThumbsCount(); loadVisibleThumbs(); if (Settings::includeSubDirectories) { loadSubDirectories(); } phototonic->showBusyAnimation(false); isBusy = false; } void ThumbsViewer::loadSubDirectories() { QDirIterator dirIterator(Settings::currentDirectory, QDirIterator::Subdirectories); while (dirIterator.hasNext()) { dirIterator.next(); if (dirIterator.fileInfo().isDir() && dirIterator.fileName() != "." && dirIterator.fileName() != "..") { thumbsDir->setPath(dirIterator.filePath()); initThumbs(); updateThumbsCount(); loadVisibleThumbs(); if (isAbortThumbsLoading) { return; } } QApplication::processEvents(); } QItemSelection dummy; onSelectionChanged(dummy); } void ThumbsViewer::applyFilter() { fileFilters->clear(); QString textFilter("*"); textFilter += filterString; *fileFilters << textFilter + "*.bmp" << textFilter + "*.cur" << textFilter + "*.dds" << textFilter + "*.gif" << textFilter + "*.icns" << textFilter + "*.ico" << textFilter + "*.jpeg" << textFilter + "*.jpg" << textFilter + "*.jp2" << textFilter + "*.jpe" << textFilter + "*.mng" << textFilter + "*.pbm" << textFilter + "*.pgm" << textFilter + "*.png" << textFilter + "*.ppm" << textFilter + "*.svg" << textFilter + "*.svgz" << textFilter + "*.tga" << textFilter + "*.tif" << textFilter + "*.tiff" << textFilter + "*.wbmp" << textFilter + "*.webp" << textFilter + "*.xbm" << textFilter + "*.xpm"; thumbsDir->setNameFilters(*fileFilters); thumbsDir->setFilter(QDir::Files); if (Settings::showHiddenFiles) { thumbsDir->setFilter(thumbsDir->filter() | QDir::Hidden); } thumbsDir->setPath(Settings::currentDirectory); QDir::SortFlags tempThumbsSortFlags = thumbsSortFlags; if (tempThumbsSortFlags & QDir::Size || tempThumbsSortFlags & QDir::Time) { tempThumbsSortFlags ^= QDir::Reversed; } thumbsDir->setSorting(tempThumbsSortFlags); } void ThumbsViewer::loadPrepare() { thumbsViewerModel->clear(); setIconSize(QSize(thumbSize, thumbSize)); setSpacing(QFontMetrics(font()).height()); if (isNeedToScroll) { scrollToTop(); } isAbortThumbsLoading = false; thumbsRangeFirst = -1; thumbsRangeLast = -1; imageTags->resetTagsState(); } void ThumbsViewer::initThumbs() { thumbFileInfoList = thumbsDir->entryInfoList(); static QStandardItem *thumbItem; static int fileIndex; static QPixmap emptyPixMap; static QSize hintSize; int thumbsAddedCounter = 1; emptyPixMap = QPixmap::fromImage(emptyImg).scaled(thumbSize, thumbSize); hintSize = QSize(thumbSize, thumbSize + ((int) (QFontMetrics(font()).height() * 1.5))); for (fileIndex = 0; fileIndex < thumbFileInfoList.size(); ++fileIndex) { thumbFileInfo = thumbFileInfoList.at(fileIndex); metadataCache->loadImageMetadata(thumbFileInfo.filePath()); if (imageTags->dirFilteringActive && imageTags->isImageFilteredOut(thumbFileInfo.filePath())) { continue; } thumbItem = new QStandardItem(); thumbItem->setData(false, LoadedRole); thumbItem->setData(fileIndex, SortRole); thumbItem->setData(thumbFileInfo.filePath(), FileNameRole); thumbItem->setTextAlignment(Qt::AlignTop | Qt::AlignHCenter); thumbItem->setSizeHint(hintSize); thumbItem->setText(thumbFileInfo.fileName()); thumbsViewerModel->appendRow(thumbItem); ++thumbsAddedCounter; if (thumbsAddedCounter > 100) { thumbsAddedCounter = 1; QApplication::processEvents(); } } imageTags->populateTagsTree(); if (thumbFileInfoList.size() && selectionModel()->selectedIndexes().size() == 0) { selectThumbByRow(0); } } void ThumbsViewer::updateThumbsCount() { QString state; if (thumbsViewerModel->rowCount() > 0) { state = tr("%n image(s)", "", thumbsViewerModel->rowCount()); } else { state = tr("No images"); } thumbsDir->setPath(Settings::currentDirectory); phototonic->setStatus(state); } void ThumbsViewer::selectThumbByRow(int row) { setCurrentIndexByRow(row); selectCurrentIndex(); } void ThumbsViewer::loadThumbsRange() { static bool isInProgress = false; QImageReader thumbReader; static QSize currentThumbSize; static int currentRowCount; static QString imageFileName; QImage thumb; int currThumb; bool imageReadOk; if (isInProgress) { isAbortThumbsLoading = true; QTimer::singleShot(0, this, SLOT(loadThumbsRange())); return; } isInProgress = true; currentRowCount = thumbsViewerModel->rowCount(); for (scrolledForward ? currThumb = thumbsRangeFirst : currThumb = thumbsRangeLast; (scrolledForward ? currThumb <= thumbsRangeLast : currThumb >= thumbsRangeFirst); scrolledForward ? ++currThumb : --currThumb) { if (isAbortThumbsLoading || thumbsViewerModel->rowCount() != currentRowCount || currThumb < 0) { break; } if (thumbsViewerModel->item(currThumb)->data(LoadedRole).toBool()) { continue; } imageFileName = thumbsViewerModel->item(currThumb)->data(FileNameRole).toString(); thumbReader.setFileName(imageFileName); currentThumbSize = thumbReader.size(); imageReadOk = false; if (currentThumbSize.isValid()) { if (currentThumbSize.width() > thumbSize || currentThumbSize.height() > thumbSize) { currentThumbSize.scale(QSize(thumbSize, thumbSize), Qt::KeepAspectRatio); } thumbReader.setScaledSize(currentThumbSize); imageReadOk = thumbReader.read(&thumb); } if (imageReadOk) { if (Settings::exifThumbRotationEnabled) { imageViewer->rotateByExifRotation(thumb, imageFileName); currentThumbSize = thumb.size(); currentThumbSize.scale(QSize(thumbSize, thumbSize), Qt::KeepAspectRatio); } thumbsViewerModel->item(currThumb)->setIcon(QPixmap::fromImage(thumb)); } else { thumbsViewerModel->item(currThumb)->setIcon(QIcon::fromTheme("image-missing", QIcon(":/images/error_image.png")).pixmap( BAD_IMAGE_SIZE, BAD_IMAGE_SIZE)); currentThumbSize.setHeight(BAD_IMAGE_SIZE); currentThumbSize.setWidth(BAD_IMAGE_SIZE); } thumbsViewerModel->item(currThumb)->setData(true, LoadedRole); QApplication::processEvents(); } isInProgress = false; isAbortThumbsLoading = false; } void ThumbsViewer::addThumb(QString &imageFullPath) { metadataCache->loadImageMetadata(imageFullPath); if (imageTags->dirFilteringActive && imageTags->isImageFilteredOut(imageFullPath)) { return; } QStandardItem *thumbItem = new QStandardItem(); QImageReader thumbReader; QSize hintSize; QSize currThumbSize; static QImage thumb; hintSize = QSize(thumbSize, thumbSize + ((int) (QFontMetrics(font()).height() * 1.5))); thumbFileInfo = QFileInfo(imageFullPath); thumbItem->setData(true, LoadedRole); thumbItem->setData(0, SortRole); thumbItem->setData(thumbFileInfo.filePath(), FileNameRole); thumbItem->setTextAlignment(Qt::AlignTop | Qt::AlignHCenter); thumbItem->setData(thumbFileInfo.fileName(), Qt::DisplayRole); thumbItem->setSizeHint(hintSize); thumbReader.setFileName(imageFullPath); currThumbSize = thumbReader.size(); if (currThumbSize.isValid()) { if (currThumbSize.width() > thumbSize || currThumbSize.height() > thumbSize) { currThumbSize.scale(QSize(thumbSize, thumbSize), Qt::KeepAspectRatio); } thumbReader.setScaledSize(currThumbSize); thumb = thumbReader.read(); if (Settings::exifThumbRotationEnabled) { imageViewer->rotateByExifRotation(thumb, imageFullPath); currThumbSize = thumb.size(); currThumbSize.scale(QSize(thumbSize, thumbSize), Qt::KeepAspectRatio); } thumbItem->setIcon(QPixmap::fromImage(thumb)); } else { thumbItem->setIcon( QIcon::fromTheme("image-missing", QIcon(":/images/error_image.png")).pixmap(BAD_IMAGE_SIZE, BAD_IMAGE_SIZE)); currThumbSize.setHeight(BAD_IMAGE_SIZE); currThumbSize.setWidth(BAD_IMAGE_SIZE); } thumbsViewerModel->appendRow(thumbItem); } void ThumbsViewer::wheelEvent(QWheelEvent *event) { if (event->delta() < 0) { verticalScrollBar()->setValue(verticalScrollBar()->value() + thumbSize); } else { verticalScrollBar()->setValue(verticalScrollBar()->value() - thumbSize); } } void ThumbsViewer::mousePressEvent(QMouseEvent *event) { QListView::mousePressEvent(event); if (Settings::reverseMouseBehavior && event->button() == Qt::MiddleButton) { if (selectionModel()->selectedIndexes().size() == 1) emit(doubleClicked(selectionModel()->selectedIndexes().first())); } } void ThumbsViewer::invertSelection() { QItemSelection toggleSelection; QModelIndex firstIndex = thumbsViewerModel->index(0, 0); QModelIndex lastIndex = thumbsViewerModel->index(thumbsViewerModel->rowCount() - 1, 0); toggleSelection.select(firstIndex, lastIndex); selectionModel()->select(toggleSelection, QItemSelectionModel::Toggle); } void ThumbsViewer::setNeedToScroll(bool needToScroll) { this->isNeedToScroll = needToScroll; } void ThumbsViewer::setImageViewer(ImageViewer *imageViewer) { this->imageViewer = imageViewer; } phototonic-2.1/ThumbsViewer.h000066400000000000000000000064011325127642100163430ustar00rootroot00000000000000/* * Copyright (C) 2013 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef THUMBS_VIEWER_H #define THUMBS_VIEWER_H #include #include #include "Settings.h" #include "FileSystemTree.h" #include "Bookmarks.h" #include "InfoViewer.h" #include "Tags.h" #include "MetadataCache.h" #include "ImagePreview.h" class Phototonic; class ImageViewer; #define BAD_IMAGE_SIZE 64 #define WINDOW_ICON_SIZE 48 class ImageTags; class ThumbsViewer : public QListView { Q_OBJECT public: enum UserRoles { FileNameRole = Qt::UserRole + 1, SortRole, LoadedRole }; ThumbsViewer(QWidget *parent, MetadataCache *metadataCache); void loadPrepare(); void applyFilter(); void reLoad(); void loadFileList(); void loadSubDirectories(); void setThumbColors(); bool setCurrentIndexByName(QString &fileName); bool setCurrentIndexByRow(int row); void setCurrentRow(int row); void setImageViewerWindowTitle(); void setNeedToScroll(bool needToScroll); void selectCurrentIndex(); void addThumb(QString &imageFullPath); void abort(); void selectThumbByRow(int row); int getNextRow(); int getPrevRow(); int getLastRow(); int getRandomRow(); int getCurrentRow(); QStringList getSelectedThumbsList(); QString getSingleSelectionFilename(); void setImageViewer(ImageViewer *imageViewer); InfoView *infoView; ImagePreview *imagePreview; ImageTags *imageTags; QDir *thumbsDir; QStringList *fileFilters; QStandardItemModel *thumbsViewerModel; QDir::SortFlags thumbsSortFlags; int thumbSize; QString filterString; bool isBusy; protected: void startDrag(Qt::DropActions); void wheelEvent(QWheelEvent *event); void mousePressEvent(QMouseEvent *event); private: void initThumbs(); int getFirstVisibleThumb(); int getLastVisibleThumb(); void updateThumbsCount(); void updateImageInfoViewer(QString imageFullPath); QFileInfo thumbFileInfo; QFileInfoList thumbFileInfoList; QImage emptyImg; QModelIndex currentIndex; Phototonic *phototonic; MetadataCache *metadataCache; ImageViewer *imageViewer; bool isAbortThumbsLoading; bool isNeedToScroll; int currentRow; bool scrolledForward; int thumbsRangeFirst; int thumbsRangeLast; public slots: void loadVisibleThumbs(int scrollBarValue = 0); void onSelectionChanged(const QItemSelection &selection); void invertSelection(); private slots: void loadThumbsRange(); }; #endif // THUMBS_VIEWER_H phototonic-2.1/Trashcan.cpp000066400000000000000000000153161325127642100160220ustar00rootroot00000000000000/* * Copyright (C) 2018 Roman Chistokhodov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include #include "Trashcan.h" #if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_DARWIN) // Implementation for freedesktop systems adheres to https://specifications.freedesktop.org/trash-spec/trashspec-latest.html #include #include #include #include #include #include #include #include #include #include #include #include #include static Trash::Result moveToTrashDir(const QString& filePath, const QDir& trashDir, QString& error, const QStorageInfo& nonHomeStorage) { const QDir trashInfoDir = QDir(trashDir.filePath("info")); const QDir trashFilesDir = QDir(trashDir.filePath("files")); if (trashInfoDir.mkpath(".") && trashFilesDir.mkpath(".")) { QFileInfo fileInfo(filePath); QString fileName = fileInfo.fileName(); QString infoFileName = fileName + ".trashinfo"; int fd; const int flag = O_CREAT | O_WRONLY | O_EXCL; const int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; for (unsigned int n = 2; trashFilesDir.exists(fileName) || ((fd = open(trashInfoDir.filePath(infoFileName).toUtf8().data(), flag, mode)) == -1 && errno == EEXIST); ++n) { fileName = QString("%1.%2.%3").arg(fileInfo.baseName(), QString::number(n), fileInfo.completeSuffix()); infoFileName = fileName + ".trashinfo"; } if (fd == -1) { error = strerror(errno); return Trash::Error; } const QString moveHere = trashFilesDir.filePath(fileName); const QString deletionDate = QDateTime::currentDateTime().toString(Qt::ISODate); const QString path = nonHomeStorage.isValid() ? QDir(nonHomeStorage.rootPath()).relativeFilePath(filePath) : filePath; const QString escapedPath = QString::fromUtf8(QUrl::toPercentEncoding(path, "/")); QFile infoFile; if (infoFile.open(fd, QIODevice::WriteOnly, QFileDevice::AutoCloseHandle)) { QTextStream out(&infoFile); out << "[Trash Info]\nPath=" << escapedPath << "\nDeletionDate=" << deletionDate << '\n'; } else { error = infoFile.errorString(); return Trash::Error; } if (QDir().rename(filePath, moveHere)) { return Trash::Success; } else { error = QString("Could not rename %1 to %2").arg(filePath, moveHere); return Trash::Error; } } else { error = "Could not set up trash subdirectories"; return Trash::Error; } } Trash::Result Trash::moveToTrash(const QString &path, QString &error, Trash::Options trashOptions) { if (path.isEmpty()) { error = "Path is empty"; return Trash::Error; } const QString filePath = QFileInfo(path).absoluteFilePath(); const QStorageInfo filePathStorage(filePath); if (!filePathStorage.isValid()) { error = "Could not get device of the file being trashed"; return Trash::Error; } const QString homeDataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); const QDir homeDataDirectory(homeDataLocation); if (homeDataLocation.isEmpty() || !homeDataDirectory.exists()) { error = "Could not get home data folder"; return Trash::Error; } if (QStorageInfo(homeDataLocation) == filePathStorage || trashOptions == Trash::ForceDeletionToHomeTrash) { const QDir homeTrashDirectory = QDir(homeDataDirectory.filePath("Trash")); if (homeTrashDirectory.mkpath(".")) { return moveToTrashDir(filePath, homeTrashDirectory, error, QStorageInfo()); } else { error = "Could not ensure that home trash directory exists"; return Trash::Error; } } else { const QDir topdir = QDir(filePathStorage.rootPath()); const QDir topdirTrash = QDir(topdir.filePath(".Trash")); struct stat trashStat; if (lstat(topdirTrash.path().toUtf8().data(), &trashStat) == 0) { // should be a directory, not link, and have sticky bit if (S_ISDIR(trashStat.st_mode) && !S_ISLNK(trashStat.st_mode) && (trashStat.st_mode & S_ISVTX)) { const QString subdir = QString::number(getuid()); if (topdirTrash.mkpath(subdir)) { return moveToTrashDir(filePath, QDir(topdirTrash.filePath(subdir)), error, filePathStorage); } } } // if we're still here, $topdir/.Trash does not exist or failed some check QDir topdirUserTrash = QDir(topdir.filePath(QString(".Trash-%1").arg(getuid()))); if (topdirUserTrash.mkpath(".")) { return moveToTrashDir(filePath, topdirUserTrash, error, filePathStorage); } error = "Could not find trash directory for the disk where the file resides"; return Trash::NeedsUserInput; } } #elif defined(Q_OS_WIN) #include #include Trash::Result Trash::moveToTrash(const QString &path, QString &error, Trash::Options trashOptions) { Q_UNUSED(trashOptions); SHFILEOPSTRUCTW fileOp; ZeroMemory(&fileOp, sizeof(fileOp)); fileOp.wFunc = FO_DELETE; fileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_ALLOWUNDO; std::wstring wFileName = path.toStdWString(); wFileName.push_back('\0'); wFileName.push_back('\0'); fileOp.pFrom = wFileName.c_str(); int r = SHFileOperation(&fileOp); if (r != 0) { // Unfortunately there's no adequate way to get message from SHFileOperation failure error = QString("SHFileOperation failed with code %1").arg(r); return Trash::Error; } return Trash::Success; } #else Trash::Result Trash::moveToTrash(const QString &path, QString &error, Trash::Options trashOptions) { error = "Putting files into trashcan is not supported for this platform yet"; return Trash::Error; } #endif phototonic-2.1/Trashcan.h000066400000000000000000000022301325127642100154560ustar00rootroot00000000000000/* * Copyright (C) 2018 Roman Chistokhodov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #ifndef TRASHCAN_H #define TRASHCAN_H #include namespace Trash { typedef enum { Success, Error, NeedsUserInput } Result; typedef enum { NoOptions = 0, ForceDeletionToHomeTrash = 1 } Options; Trash::Result moveToTrash(const QString &filePath, QString &error, Options trashOptions = NoOptions); } #endif // TRASHCAN_H phototonic-2.1/images/000077500000000000000000000000001325127642100150125ustar00rootroot00000000000000phototonic-2.1/images/about.png000066400000000000000000000014041325127642100166310ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8SAHa}꒭zXYf=,R +ujE!QPA[$=x1!Ţp ]MVw\qvjwf>xR_L;Dd+蜚F`0Ò$5pMMӾ?e}*S omoou4MbH*QT"]O B6 "0>Yg$cLmFFF^TUgll,:|BXk 幹s4Mp9mNSSܼc6qQVq|| y8L>f?zݵ!@aӗ$i@#L&azz:iRԣz˲,^G_#HomC___oRyՋ~-8XXXzw:D~ppcii=C{kkUQ6YB!8X]]}zr1"r@<LQ\.9,90[`5H$w,PaJ%3ϫr3 bOOYL4&&&֊~`ΤID:_Y^^N/BIjB 'VHkvo@sc?IENDB`phototonic-2.1/images/back.png000066400000000000000000000007631325127642100164260ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<pIDAT8SKq:0<㼬!Iqrn \o67fiA7%/:5rU#f*+MX@D1:7f~^EHphk"RdYk7\u " l6k-GfA˲\$)E2sDDAպSUx< ⪪bJBQ;3mBj2~|uwk"2Aph4Z5MT* 0CHDlhLFc0 f^xt!UTq^\t:} +~D\(roYS*:@@h5 y=rIENDB`phototonic-2.1/images/bookmarks.png000066400000000000000000000011171325127642100175100ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8kSQ5%KJJ@`Pfӊ ((š젠=8)RT(bb4ږmrι!O7{s&U.,HQ=7vAཧuNgS>m IlHY_=V~zړ+J+}_yS?_@2,Ǵ?|8h P 0 cVDVn'mM W B @D9Jj2plNf#5L%՝g'S{LQ#Ru8M)h}̰x,8$Յh-gܟ qPp*V GP@äQ#Tu`g(OB~La2Hb\vZ~/yo0 xX@)U|>GiCY@)mۗil۾hD׭8WAܕA9s6(H&Jk˲.4eβ 5(`_<ϻN<Nt]?w]uG]dg|4g?lH5v?H䮰ʓHxGu.FIENDB`phototonic-2.1/images/busy.gif000066400000000000000000000253421325127642100164710ustar00rootroot00000000000000GIF89a2Ԭ! NETSCAPE2.0!,2`R8cIfj&JL׷]{?L F#2T&&d6{v[7an/pZv"x ހ~    Ƶ³ ۼҲæ ! 6m@AHC- d ŋ ȱ#ƍ-!,2켺Ĭ̤켾CL i試HM]뻞NK R\6SN҄0C"^כ$aq(\l>{}C o o   í ν ߭VrQBڤ Cꂄ3ITnjl (S\rD˗*]|!,2̴쬪ԼԼ쬮 DPgj˾n,NO~:<`/ c19,.tNתTf[@.C1zM> `0N'~~}56v77av' uutt%s#  ȿ    6-ւ8qN ੣RC:qT ."X“o\lR .ILePbѢCPJԨ !!,2䬮촶Ĭ촲Ĥ 8H > QT7_7B$H`r L@W^Vjoy$iufO6=)GD;뤀i:i  Qf:( g g '45|{8{  ||&h砞AF8B !>ķA &d@c}dHaB!lH`„[jMZ y)vPC(G D(;!իUfUB׮W-!,2䬮촶Ĭ촲Ĥ5L\0(+>HHB"d"bҨDULe_n U'e 8"|_D2  Xo@Y~@:U@  ; ϰ  < < 0`@X1Pn!Ç#F ,\POB.p ^1``We5h/7f~P`hQ]:ZAB('Eej/_" [ N b[#ʍ.r^!,2䬮촶Ĭ촲Ĥ3M<ÅҾn rMOY! $T1D6IIT Df^_p6tZ!n8oׯݫW0DqqnsD=<<q  ZZnnZ  qA BBװ ? B 4@@B"JH1bq] p X(d<!g <9R9ݚEA2sk;#XJI>+ӥOJ](`Bm YcH[ Rxp@Ņ,F՛߿{^!,2䬮촶Ĭ촲Ĥ3)0L\Ic rM?DTM G#O-uOR)T2D&M2p:g1ZZ~ ۮuݮ1oq  @\X_>>Z RCD[ZD\\  \AA  @  BB4(0 HŊ<b = 0duiM$ eKh!D Я4DdVLvb ^|J+S($Xg͎=[V 8 7 {!!,2䬮촶Ĭ촲Ĥ3)c9 3\P+MSUeAB"rX ذc`0a.8` pm^^!,2䬮촶Ĭ촲Ĥ3)cIt=5dlrM?DTg@D"fzR)PL!l ,z%S⪴`e0׾U;gW0`ZZq B q`@uF REFt  ¿ C Bۉ  DD݉ Ńpy&b4@`ֻ3j| DC"`_? i&DTDHcM,$L! V+*_υi!fo$AWw|۽_W0oZsCtA[AA]t ]^^tts sEtFFD CC0` hX@8ŊQDTJ% Q5y?Vlj-dbpnfJޒo((Hx/|1zc^xFxDDD``x xxww HIIG Fڊй:)D@`B3j `cB 2g>fB&\2%HM] 4`[fkE("  xj(*δg 0t*`[n%oʝ{Ł Z+c.\o/!,2䬮촶Ĭ촲Ĥ3)cIf9 <״tJ?DT?_#CH$b9;R)PkZ_ɷr檴`en{3uDT?0 9=Y`RU[2 p[rTifm+(H\ގc0s^_DwFxDDab abxxwH wxIIG F݋F ܹ'p[p! 4@B*l0 A&D > g(C`aF # `M6l̜U˥Ȁ6KR,QZ~ICHJXS2dӥ2QL2ox骶 VĝK.0DT?_o:R)Pk{f L"(dnUZw~I>[1f_{f_x HcFFaLLbb R cc   cII  IJJH  ,\`y1`$F#J` 0РKdžJ5r8I k%8DPQcH3@e89sd ^40@ϝd)U+DI a7VB8 rXA(ɘ1ݻxc<؛7!,2䬮촶Ĭ촲Ĥ3)cIf<MS=Wd$DbC,8׊V D)XYԬ5m 6 L[1|euzHz|FbFc  bzzyJK yzKKIǶ HڌH  b[*LHP ((A.hf! RBP[Z2 ip e QY!UB ŊT2hiSďq2S'e:Å hKݹbxp t/!,2䬮촶Ĭ촲Ĥ3)cIf0]sMj>DT?_o7eDp ;R)Pk{vBB,2_`enݦe1gaGgx I xG|M RLx  JJ  JIKK  I .Pp8ha#@ h%ZG A29ra#Gk2@¿,`X  d0P@M\+SYj9Q"b0URSԩ4hidBog՞0Ƅxb`,xw!,2䬮촶Ĭ촲Ĥ3)cIf4 3\N4վ># +DH@!S+VZL! + huFV:ǂ$1wbcI{K{IeIfd f||{M{N NNL  KێKٍ Fb[*\Р P`! ePƒ;"dH b@ P#el*kkgn(-YHaZJ3(P*C*3+blm4TFpu+ƅ,+C!,2䬮촶Ĭ촲Ĥ3)cIf0L\>DT?_o7 3HD"@fLRNVJjB"' lPenݎRc0ha}h| JKgHcNNd QMee    KKK  ȿLLJ  X@p8hᣇ#J@4@`W5ɰdɅj5* DT?_o7 wLF"HH$JVlfZoI1uMk-wAA dJ}L|Jfxxge f}}|N| |OOM  ǼǐL  8RS xSЛÇ#JdXC IRB$g%L X@$IϒLZ6` !j\µ 0D`MU2li$+ZÂ& %҅ .ʝKw wN02d !,2䬮촶Ĭ촲Ĥ3)cIfj9 <4DT?_o7 R LRNVJjJ KPenݎq"̔cJ  LMJ{J~    MM  NNLN   ,hX@I')\ȰI(0 VMBG#IdH^,0X@dbFSFҲg5 ` ^jXGo PJ@TZI:XhuNca+6&]˶Zme;  !,2䬮촶Ĭ촲Ĥ3)cIfj: A4M\' +D80J!RUT^B&D0aixf6&3$q3bI~ KIdwwc{M{ KMK 0K׏3  h@Q໧0!> 1Pb>,pAi r/'KD@ LUpΔE pAɰ% 6H(7HH! ʵ+W]n;vF!,2䬮촶촲Ĥ`)cIfj CTL绞߿7]e2)0glVViy)$.K97gs^wc>{}y_ G_G  $ 1    3`vP`Z~݊"/@`VZuTI3H؄a+f9M'/ഒ! T!ѣH5)QK^s !,2Լ쬮Լ촲 B1cIfjP<<6~49D.\6d)uF1*_o `bZ]ίO&kk   ¾úϽ ڻ ټ֩-TP& ?0pd5ig#,` N\reJ/U<9%!;phototonic-2.1/images/clear.png000066400000000000000000000012561325127642100166120ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<+IDAT8?haƟ-4J-] "4R 48tpTPK N-YWE I9Aw- W95|]j$C,yY^7yDܚ!.@LӴ7pui'`0o4ۢ(.9'<F|p\銢0m1WeG4ݶmض}^rwmma;o6lrYH$RT*F$)PdY.O=Vd^Z?<<4ٲȄ^`uU`9hHt׮cƂ"V'pa6yt%m4Ɋ b*5*'UG IB+'AS4 (ST=T0 Ht،76"g9@pЂ '^4Ͼ9&u(X=zVD]*8)G/lvB, z i~zEy@jb6-|56] ,yb`c^j&BTA3-b"h$∽./^OaO2{O0rl Z>t6ȣȡ * eU| 'f!7 8W\R. h|,T>ܲCc k MZ4SH+E-~O5{&W TtiO-#jm*2[@AwֶTc/ZLUIENDB`phototonic-2.1/images/copy.png000066400000000000000000000010351325127642100164710ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8?k@Ɵ&7H1AR\|?B@98(RiСH8H MHK};hL{}/#"b../+" AD' @qysNypgBD`f!В(AX!\9׈Fv]WťRINBldcPb_ I?DQdDqz@OtKIv=$\EـoxoYV1v<,z6@F}koϝN\"DfzIպ_,d a~?~imwoٗeX}0jPU5Ur|MD_Y3'f~>|<زb#+JDlMF|IENDB`phototonic-2.1/images/crop.png000066400000000000000000000010311325127642100164560ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME " 5)IDAT8ˍ1Q?'3Sh&V$Ha3Řb@  jtӦ D\HcQAf޻Lf5^xͻ{=޻uxEag/Fz!"88xG?J+7(b\ζ(^"ZbAV;HcN n4XZt:=(A)jnSTZ#s?{s @/K}rֺ@&R00 R(".`g_sTs@Dl6qm=ggb<==O̪NCZ-81L nx9ftؕvl>Li/0ܻ eeшLB v^Wzl>!K!FPF`6e=0EӼL\IENDB`phototonic-2.1/images/cut.png000066400000000000000000000014101325127642100163070ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8mS1Ha}cl$h"UBp+ -4T8ZݻX(j,Y TJܦҡ&)$K )7 wRrM÷1 p 'c< DdTl&IH&IJ0z;TUUt]oF"y#zSUUT;~Q4*J"fWT*Q.nu1fxAx`P*zx,ˢ,ڝ%d2YeTU8niUU/dYi1 obx,T(.~nSQ1FN5MlnnDdE:W|A(\:olA7'_^gMlmm͝4<<2&cm#Gr|YVfgg?&PZr|FM0 BVH:;;;Q<`V4V*woo/' 0鴶a̼tJ @;}}}+LӔMӔcXJQeYx<@ۛ;3\NlƿN/1X=)iMIENDB`phototonic-2.1/images/delete.png000066400000000000000000000012041325127642100167570ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œKTq?ͤ36b k BfЪ71j00ȤE ZĈ 1Piemij/=s+N#6`V"f0 <錗Hs!U]-5nƬ`l򱚂-1`-z(t#٤z۔oHVKDR ".wf"23^>r{n}~4ީ_+[?{59`1vnFb>ڗ[?Nji2c m0؀m ̉6m˖H e+QRIENDB`phototonic-2.1/images/error_image.png000066400000000000000000000077071325127642100200260ustar00rootroot00000000000000PNG  IHDR@@iq pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_FIDATx[q0}xfR $@*RIĩ N `GYVl6sD377C@j=cxzLAfm7h mx1AFgK{ udXy? 6?$]WOM4009KUР= Oq5Zl[UcrSBA&q9|zHC̞<]F%B6B3uyhZSjfgI2F ߓEaPV8a#uT}ZdcD6d#OR2B}Dano_tl*'MJJOu  ̿qOEu-?5 {t2ëYPWBFĝo_5`#/'3 LLjCZ[!:7C;vAϦ5̹u2I?ҎX_CIBCL${(iD,/L?"rjOHx: gL ~Y, w^'HϜ2a 6

V&%lcIҵLBS"6Ƕ-`8\N@KMC&g& D@lo-8رqx$x| EL&0qE3>cuI0eH1/E +a:2Z05evnT(2GQ*zt?S F3Iw l69̰6d|@( 4*OkON/|mW1x~?ofO 7)~ll|hRVY !St:!@q]"Q%mC"Cُ.|x*^#rEaڨks1.L f[` qÌ$$`4$|U=B[!IJZdEi9ѭ1 X'.IM1kRQ4a&[[e%Q{eP 71)ЎvyKNEDat+'3L|4] u'"渴|YKBׁ{>wytL9IENDB`phototonic-2.1/images/first.png000066400000000000000000000010671325127642100166530ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œ1RaG}) Cz.pih^hQE)A)F!H !nA5&i.ݫWEu{:pr\( \۞IʖTՏGaa *;|ATz'cf[~(JT*ki6TXLjBṈsTh4z{^""cj:-N5xbSl0vb3 ZV.<1 #8]F^z$Y᠋yyv ,ˢl'v\.K4͗zQRV$;0˽q 5U4D}\fo@ p9 v;rm>ȫNp8~T*6N!z-slUٿp3 P`IENDB`phototonic-2.1/images/flipH.png000066400000000000000000000007201325127642100165610ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<MIDAT8ݓKP@M:D"7KC]C\ {gmPбs tB1>Z|}qqb76MEdoY(";7 kn$4MZ"(M$I.fE(;E\.8(˲\߿ s_ׯ Rt>L61 c0$TkiCq^Ɨp4ht:e6hC=;k4juJޗ zYvv4o R:-(5P]/a]hRv۷m[r#,X&+EcVEi7$4zIENDB`phototonic-2.1/images/home.png000066400000000000000000000010141325127642100164440ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8QCtG_!d),E/JH&kc!0SW ׳*kDp=9?犪?e=p 8`BUG@m<_F62l6|A|S~&x0'aa1F}lum3?}m\n.Zto2UEDISTV8j@y jՍM< Ssct ݜɥX/%hwz \C=lmo@667m-mh4Ix̻f?jg+J&nZGj6M=LVتu[|kǭ3IY=IENDB`phototonic-2.1/images/new.png000066400000000000000000000006731325127642100163170ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<8IDAT81j@ERJS¾@|@:Pt4t $ƅ ؅MᬑF? 3 E |:n\o!8_=RuR>0mj!mpRJnVoH) f(b+Z 5 !RKl֏0 Ssb>D``4`:.U2sB$0)뺎,Kf0u<(>0,bje+%_F YNIENDB`phototonic-2.1/images/new_bookmark.png000066400000000000000000000007111325127642100201750ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<FIDAT8œjQEϠ6m%~Zʇ$aXXmHe`>΀j lE؅I]yF3ýw*BD jL$2MS3I%QU'忣f9(j5S:G@G,y?K`+ 4 ou\VVջ؁X, .uЌx0(8`:>tۣf_L Q{w*"iNPL&l8͂4wEy盢虈Ey[.3y, 7 +;^ ë8wUuE\.T* 3N6'"[k˼Z>jbnl p\FCWAdahz=0 ¡60cv27O7^gVPד~NFUo3yBU/l U~s™IENDB`phototonic-2.1/images/new_tag.png000066400000000000000000000012121325127642100171400ustar00rootroot00000000000000PNG  IHDRabKGD pHYs B(xtIME%IDAT8˅OHa?nkV0Z vPnz;Aу"JN <,Gňl8:Zlěnt/Ru@ B"D|KN^~mMMm2sX$74q~o|i"ש8R^ 4*lÚT9U`X`XXBa$In䘝nm0;3ݪ9t#G,⨵黶D5[AFCB䦤Zl\'@69 sXi+Ģ"` 8H{Q*DdSD*QvGqtjaoY43Ax<>UJa2Lfꩈ8I$!"9nD$uХHRG^7g_ 6+˲R6du]?h4gpZT-*I58m{R(jlGb a=(2-6g%~_bi2KIENDB`phototonic-2.1/images/no_image.png000066400000000000000000000001111325127642100172670ustar00rootroot00000000000000PNG  IHDRĉIDATIENDB`phototonic-2.1/images/open.png000066400000000000000000000010531325127642100164600ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8AkQ;0]Z@pvUj.\g5O/  RuхP\Hf1T(pET`{΃DUg1p?DU]f=N|60xv߀KU"ʇ(IENDB`phototonic-2.1/images/paste.png000066400000000000000000000010741325127642100166360ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT81Q iL,6FטPә`Gk@B$l VLbf`{ C]CINq߽s{rN 4Q,V~5= w `'E7U"Z{_Xl6c9wpp0+ M`X,>>%`=ݶbq#c"&cY.C=xxNZy' ƘeպP՛ZDYۭ4͋x\:aZ-{/v`">57WU \IENDB`phototonic-2.1/images/phototonic.png000066400000000000000000000073361325127642100177170ustar00rootroot00000000000000PNG  IHDR@4:> bKGDC pHYs  tIME+>ݎkIDAThۏ$]?R՗ٙݙV B@B(!_ 7 $DN$./$18Dx}Ygsٙ:uPU=ݳͪN:w9{JVJi~ y cn;܇A~sf`sZ/nooO>FYG"j#|ڻ{*EEX51DnݺEq0J]xB__Df㯺w뫵'@׫6#"Z%2`V!޼GGd5Rr48Am LZo\; J^3pU49PLc!_o]V"QMhjAV!H= g~k]g`MDsPEQX߸o',s IQ5(%nSpVq6XMշr x8I)KUhe(Ъҽ 0ւR|PXuPR c-hLSpRM~Q"2?JEG+Ūlt͖@j4ht AH@Y$I5)#8NcExbjih}4Aޟ4ZE++vv61`Lebm`㸺smʺש^偣a$!O.9W@>c͹iTޣ,lnt9֌5iblݹELAm^iG,OkZ[P<|W&;X)!k}R{L(}қkQi69QAmKoqJ#ޠV L `Fpؾo۲Zqޞa[hls< ño֯YcXz)|C N_l LMl"f @׍\XbpO7>`scZ?Qc]OX Eet%OrXѶZZAjہNb1zmkh#1)ΘBbMXf=\Z312. +WAFW@J\WG#FXMETwV-!V܌ͧ1 ֋?iT69v*~! 1]Ihպ$ΐvfHZE y(I0ڠyeէ҆'9~[_F%@W!(ך0`St2L ֺ(:]q!DDNq&Yqd4}km-X̰L2d'~No}#sϢ7͂ ,lr(U@:&sH(7cW/ cbpe4Y]'(b67 cJ;zwHYQ5yx_Bb8Ν5usAy^W38Ős?&u 1R'b-)xvL2Jۈ?ťbe3K H" V|ŭvɝY+&|RCnzU3Uxy!ַxpXex:Bw"$"P7o&ƅ }-x6R),{uֻ;1N*^`N5s͇ܼlz| /JJZBJAne(Rm (Pzp@wPXBgu$X'C1FsTnL-<D xpLJ5mR.oO6rzr+zҍ ۔kc|zL6>89B[BBZ ә.%]9Յ+QAڅ*2LFBc;}M.'C&.4\ʦ oB3ܡkhm*\T=V1Fʲ$ 9bD% QZXGϚMi`#J)6v8:xnhWllJ|XY xq8AtDIzl\}`|2D)!h:uN^ 7`5yY{B{&ƕ]FS(ۘN!dȊjKƐ9eD b/p{6ҟw=ӔMi)|~22=\efĕ{`< ULJ<3LHWe+~W~CMĞc L)c,)؋ï83t4C-"U6( ,'+2ƣ1$( UD[%t%.{Z|ƓtySeYR<ɲ8ܟ vĆC(]+BRx)(Ȳ 3vͦiZj>XUk'[p^gMXw1?yKvXRBQe߿l6CL&FDWTU5 CDjoXJ93vdzJTU=wG^{O0 !\>o7͞0 ÌF\.W1x< B9t:Kf.ϪsjoXAӴ2^MԓMTzpMe|>N_3?~\Tē3}kx p@0IENDB`phototonic-2.1/images/refresh.png000066400000000000000000000013071325127642100171570ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<DIDAT8=hq` m08T(H:dqn`ӴPCvB`)ҠvKRK&iӚOks.mHЃgx9%"% MDַ,"} 8'&&ܛkrPJSSS`PS333JR\.KP]׫B/J_ls\.J(t:Alaaa0bXw~BaH<nX.z\sssK*c"E))nCCC7j:N!"|¡PS8RJ ,`0xgggMӴ;vFOG؇f3W1M*0xBzJZm} {N{jv%NEDڦi~fi)@ f#"rxF'''Z- ЁZH"RTJYZZp8'U1gzz0d~...~v Xև6 ;LJ$\͓y"VJ4M*"^[[[o/]mLJq>`q3?bIENDB`phototonic-2.1/images/rotate_left.png000066400000000000000000000014411325127642100200300ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8}KSaƟwMO9mSU`P+"/.SaxӼR5h YL Ӷ3c8VÝCn8n>ˈbtCDutWl69SԼ(cuK""TZئ_˲;==%_.m@o84ID,v(ZZj.ٹ~||^\\@UU榦&^k (s+++]FFFgd$I&\&f0333۟xvuu$<J|r'ё"F@[iii#I%Is&i<VU?wE%;;;6?TUET*2Ԫ<wƆH$ONN>RUt(?'z} X8^ ;<qM~`qqcT*f7>\r`DX on+-xc Bl.˧(UodtN244t8C&ID"x(%"Y/p /6\{eXcx,hIENDB`phototonic-2.1/images/rotate_right.png000066400000000000000000000014001325127642100202060ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<}IDAT8}KSq??,nj1,' %S` bBF=ٳ"ERI`b=(= Dt=RvyzHtz}?=_+T""OSp,ۦ 9@ dRR =_FR$K:ΆB3N1eY2 \۶,+x:@s:7h$\{rY^^ٸ~ kpNLLZ]]P(r\/vmhh苮|K޲,gū@4'`慅p8,555@ 0 1 C_N mD"A"`iii saNӴ;^4Mk.׀@;rާ3332??@]GGGW$199A4rhvwppVVVZ+++Ʀt]:;;o׷yֶmFHDv3)xnTTTPRReYaѾwL湈d)s8Z[[|>R.N& `>sR@#P,+0'83P2IENDB`phototonic-2.1/images/save.png000066400000000000000000000011251325127642100164550ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8jQ3f5 "Bt[ Mٸ1DBB@( Q"҅AƂR$ :ΔE=p\>9W D0OYYuX,\qğµ,8tuݰ+uw,{%"\B2,"rm{H$n{^@H)rLDn4um\L?<|sכ0F:; 0;6X.?fMF?S]6\𼻽yB47 ,(t"A2D1) gdx<pl6;R0Wj: `Aqπ?<bP^߃ J=V~]P:Fhl6Ru뺿^99ՓT*uQ~R PTW"b>3ZYIENDB`phototonic-2.1/images/save_as.png000066400000000000000000000011671325127642100171460ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8ukZQP R$PdDJ)!4E(Tp떡%Ж%td) $С%]tqD88<__}4.||ppxVX?5p%"% 0NMt,1M1 G[8AY讔BӴߑH䩈2L"~zpmm-pqq?NRۑ\=uxx{o~y*^&">p zy~hPP(<BjW3LR4+J3ɤAOi0L,LT4\.H&7`7tXDRim~h4zWU7;b"!<7PRK|uooρHju/|oc_TE$,ˊ܋ղ$D"qckkZm۟|jjV`ƓD"qCD@333NLLJ-n\4S⯀h "=>>5ƀOD\q zVUVǭƸ:"||O܍p'[0:ѲSU}S]~ăTU}Hr]u{.+3݂}}}oǿj]X,(7|#=.xO|{yf~p]pIn :GeYIENDB`phototonic-2.1/images/screenshot.jpg000066400000000000000000007037151325127642100177060ustar00rootroot00000000000000JFIFHHC     C   Z gɴZl5My5hLCgҟY֦)uF_e =;CDma&җ;ur=*g=XxG}?6u ^6:ʭ=*LFR9_.RZ7}ϬNziwxLUޖjO65 v~}'RxusY۷?Gumy6lwI#ˬH- Z64-^Y^K"A^X)`RQKS필N\sh~Wc 'Dy}k=M[:%h|w>\|V+oL!`D1]#)4enozF@xSG{m@jY2޵7&u}|]@v2@ yϣ}#KC]/HZ];iC@-nbn"u2ID(*#H7>6[5@28- 5"l6 N@(68mӈYAߣ}7h ˰"tT o d%hԦ/n$ @MIP6! Y@4>ex~_jZgc=ggLEy,K5'GG~tM+8QrbhJbaKxMt4c][|՞I[SͩlZ[L]Lxb!'<)i޼/+'m_Gk^ƜSaN19#F11$|ORnՔK_Gz9N,#s2f& =CgUR*<'kXe9;Ld&&L=̧Xmn#ce{+oj;KgyLg"yK3.IV˄y^}'{[~~m-u[}W[^BôLBmQ.&& H=7i{ǂg=HAؑR9zyuYYVs@9a2q=3CcLv;f|puraۭlxtC;nK=k=n1{=gQR*<Ҙ9IJyJ2C ˆ9H uHa &WV,tGYmLS=jfr}ϼf3_,[g[)pɧ6i<~?c˚Q7]/Nĸ={'GXC NE4,խ[{V"+Kk-7h;v$'"q"sD2!R)[BD31pJL+kZb11V:k{s5[SZ&͉03jn:Q|f%m"&.bQ08zbsDƖ W~RWG{ӵr-] 5,֧:gf2<V}-WO,gI+N~IҼJy>ۛ?Avxd^Rfj"Iʒ WN_=M2˼Uvk6#J̞s)`v)C8LrXs+6'Ĝf3 )&3n6~_?KSTRE=h10jkZÙfi4"c'cpv)F1CilOzkhjjvr93Lzs2ޝKg5nwkҧ<%lվ+_/~z,tӎ3fX~bF4t퇐N:-D3&z_ov8kzώ`ua,:xDAah(u#TLHNVҫ9brceb=ӶK~.{B) S1*b`'UR*:ZU>ITLVb& `,H.Fzij&W&lZi{Sd3ژ-ڷŭ3Z}1l~3ZJOW'VQk{F8t#EߏƧ:Zڪ-MbIgORzkwmzYWK8tw21:by1<%Y&)] 16"lkJZ,-X#OߗGK~.ͺ7N&Xe10jHֹf&zˢpͣZ"^c c' YũN]-N4[W%v;\&3[<ץ45V\'~G|v̋KR]k1/^F+5*=)ZIi:_^mS[tM3Q^JTLmzOC&ʋ:bl64h$1b+W8?WK~.=o+ZW/ky>7kL2bm6i۩3X yStNԵNjs,wl+;Ka]M{\#CD{Uj-YҾ5jdGHXU%gac{eg XцczN|\_Kv~ =jFSjX 5tT.s5/'!'1"x35f Z&3Rc fy&o>+g|ijV^fN֬eL`.9tH+u Wn[3UxJpfDZZ2nƵnlCW13ꤍ#DbORGgavl#upYEywȯyڪךv$הtDiOyY.)hĈ21cNAR_羒_/s#^ޘc43x&ڼ3N}Uj˭gN3~})1/~wGZӃ*,d[U"aL^|)&c)'ի?Eqvl1supzR<`lfì9f1˪Q8S%c,2ƌI`5~/.n@ *b`'UR*kӦU=*… uOtMDQxX855k6ZKa羇emgKX|d3V8Js9+^kqZb8VǵpZ0L`hcm[j޵ץe].%h k6\ `S:Q$k3Pq38Brf1pLtgrI(bz#<~t}4M{xǥjEhhcm^L֤ϥ,)+JE\G7y,M=o-#G=k.i*kcLW n!&:qL -G8jH+iq671mYeRa'\-f:'m+E[F4`,GC<_}%hO8>^~ S:Qyu8YӖ\Lu:Lu2r3#=1t}dxaG]/Hea0>;Luyq1kk[Mhzq1qW^?-z6KgS"5h2YD%#_*8;NťM9=+=Qvl(m#Xm/=8;C$NSɰ ԑ(h`ke9:mUyX%e& c=K~.O.s ` 5tT7w]y@R Pu1k=f3Vح"y|ڼ?vvvGϟ?0v燷$m+|7&F%6]eūkŪ{LeG3s1z_L}UM4ɊEkR5{ZXDDeFyXnLQ`z>[}zjynW'Z^Eg*{TNJ%Dm^ .;ձO3m& ,+|g1o[Ns.n@kA>2 FXLLDE@{Dt|SN[+V-t:'OIm׶ӊz| 6並1/fXt~h^-N&j1;õ׵dUuy/^7k]l`K,Iί4FYzu-6TOk:Z9"&L2%g=g<;ͬͬS&*b1:tӳM^oɰg]jgo)Qm >7W]4ޮM;pAtXLLDE@j [JQO4-1.D,Wλn8͖9)ͩMJgi+WimǸL" `!bJt;eWhMti9 9= f2CtLZ^+o1έOHt[]V3o\=~Y q.Dw3K9169"aVdVeDex~_yw\>ybS:P6! Y@4>ex~_hzY||W'f[Ly*b`'UR*7Y@}%h)˃=o<`U `,TNT o%("Ai<&>w\_KvA鐻ZCe%10jn.b|CX &W q(:y[|魯D7cdً& ]"uU"m|ENz>w\_Kvb" 5tTMri\rا&A`a%hxE}+US]W:QV"484,FXqR%t3JyV2:(-TlS"t?f뎏Gz>^z1虔~yyt7'S;urt<\~yD孹XuǥV^~uH6 U%iZV6L_/<6"&>Wy`RX kbCjm_42yb+̀"AUYӔjvٌp v+ɘ^yJQ tl-x_~ٔo#MZ?q_O|S^<Cyb?w0w慦TrZco9SƛXi쏇mF=}{}i9S+NaҫyZ/y+>{@ۦ}+, P-@"!.'ɷGK~./s#?_2 ^X"AUYӔmr9&Yt:oeUNjFSTlϙc17-֗=9gDql^~?WTqoN~5li0-O[,^y]~rzwOae:]=ml:Y㋶Y/tN~۾on,"k4lǗQލ*" PWC"||>:|魯0 D3@$5U9Hr%)pJ0鐗 BbfQ얘ڴ&2LuxYw|iibLb[a?^~֦Fߚ&-׺ybޓ/׼|o;~ZWӪ]\=ߏ 8y= <ޅU9tTuLE˟KC y;Mum]_'|HۦJD'ɷGK~.֤dr^&2&&-k"1=q-Z2sDwWwn^XhWNKiWz7+Xן윾w~OVGl|fPXFyzvlɧ.zۦ}+E-@h]dJm_5 q2ΜT|O{P!\a.UrIm-t&ht,MUp"l3+NZ:oLs"fg^r#L3\H[f~;6 QdrϝuxO{.n>?FL\9{置v[,zi{ #To^g|t|ۦ-+l)(@%a'wGK~.ԬdGǻ3inH<|%[Wmm5z!YgY]-s[8î-6>|3NSI;s-\iPo^LAM4V <5R.oWa}%ḣya$5U9HmK(+.zƼ@^R$-g!"2'M/2GLšFyzW;"q9hۼ: k4*v|ƉESVz&[|'TtK"ͳϬ>nO- ob n "=*~>B|魯K<ۯzH EGųmrrÉw2w`CuDc%]eV|Y]UzKMNt-\RY3#"fb싈)?1@Y[+uo.[@d%'0By7Or]*hf6& ^oч^7W]Sz?>ƠXPB)'3_ ;CRYX^W]huhuxrp!d8-&-j!ͣ{pZ99GD2DSDKxJ!+((zҟKCn'DҵPW)4kJ5yF!z>w\_KvAs֔K-@D&'PE@ד2rz@Mt0(<bt  9} Ȧ~e8Wuۦ2t Ea%JyF!z>w\_Kv^Gx~!6P E@ AH@ #23g (g0R3 aNdg!&j;:ĀU8L 0J́M5WO4p T FRY&&7/GK~. D%MUgNR*N.QjWl,SZ A,aV*ЂlP%|m6"'bҠ10j~>B|魯>/̀@D&):·pa0@ۦGJPy`l4S) 5yF!z>w\_Kv<["AUYӔM6WTKK2 S)`eLLߣ;.n@# 5PzPΜT otO>T0 _ fC{B+D$5U9HtaJO@T0 _<ۯ Pn"AUYӔM=RW1j ģ`*b`|Isu}/9x,l"AUYӔM5TWFRk@)T0 _42^zS@$5U9HtaoeD%UK-J5yF!z>w\_Kv{ ),E-@$5U9HtaZb5 |jP4RlT0 _(&H$5U9HtaiP*P Wa}%hxZ}%6S@DVt"m|ENtC |*dBP4T6T6'b0 _5 q2ΜT or! FPX!,Wa}%h@z~oSրDVt"ڌå'."xs8:z,@t*&89LrvG1=j%N8qd[-1OYsMnbbSS n,"zi\EyD-JRnRQ^[|Isu}/3!=`X E@w[Iq7`e-k+|-lpڹ"{Wh. lqŦU;jc9qE7ezx}3ַ|WW|;.{Ǧv}ta7JיJR YH"m~>B|魯K<ۯe3)j$5U9HZv%ՇX׽n\l~7|}uEkg ]<׭DbB.l<@le{omIF:B3{ʟcǮ6_E{Ooj^| 띾}T9eYSq)lrv*H%!Yn,"diZ("MlO%D0 _ r[O'ت+͔ΜT*:|7whgSE"ʵ=9c\p_okX 3]qVfw3b6zh~ϛ+={v'O"Lᯬgk^3Rh:뵬9i_2yN91L.c:$C5b"{˼8E*6"') fS_6c)?+ͬ 7/GK~.5sh42.z+͔MUgNR*}^ qEWvvooNOBk}uq4H⇶9*iYU[W4O8-);loJظ~,{v7îp5.zN/LyFR) Yrrd*!R&2U}3/Z>F7XDҲ`K+EK RT0 _ <=C1 E@˛6#w.4^8 (5&&UیQvp_zgU{hz|vIK==G8[ss3/.ě7IJ^яhqjO>c3us)rwy!k+HipKD(S 2/O}XtaYuB, S)(͔4Sz!DoǾ7W]C&$ΜT5&=fvW= MaLg6WO Qzz@*KXNy=yWuZ7Eco)X^>>XN;ZWLi\N/HS6XM_fK3wD{`m|EMf `aM_(=\okhZ@L΢T;M:ږ<=VT}vN}:oinq!+׎)&>Bj 5n>ag]3ɟkᕎ|~<Q'5|gd9Yvc#iԑ&xvCNzϨ{m|ENxa$Jk6ȞyO?Ǿ7W]krMgNR*^ein썫LitMuG~z/FŒ;^KNk`ƻ☓lZ1Ӿs2}z33p#pXmK>^;K}4 0u899T:6d[T9gΰw_| o]L & Ba:.ݒ@[hV3SR*qYaJ޼_LO:C%6jX-Jz[M^ݳLa<"bK=VE֣n.b@8`u}|Ng$Ԕu9/lˎ+rZ ~s},lpk=O6M6JVDZ/\5O7l-[XRggn-YޣHǮYΈ=pauǦl!iNnFKW%-DYo DRVJ;NN@:P͖Y5t~,eNv{w__4ƚ]ުa)%˚O1U3Ĥ$/~m<'5gZm~J율go2hWUQEeE1O.&nese2az>F7\))m@i=<&>w<{v ZC)W,6y7ZR*fʸ&㷟rgc|E3=_͟YF|M$0˷~lcΞiƱjG=3[W^q oGGRL5^;IΆՐ%i 0(]<z>w\_KvY]Ra Lpϖij&gprP} Xt*&@d,fP}Isu}/5N?]󭻸n@):;L$[ /_@͇daYVՓ%*O+`2B&D!ܤ!K%|}.L0rav:yp C\+NN}XtlCSՆlm<+ŁK~.ѣyk}y~烨fmGbS9òw$\9m6lsзM>m5LJޭLf| AY1kxRtv!+78K5SixfbIzcۦd^ ;J[WWLFS`6<|>-_k}NͱsBX):2c*_-y-_o`r9z'P =7*w`8 )J!IHN€m|Eo/Q%[ͨ/P({ jNhYk7w>Yuw7^V 5іfzg? m^tlG3!K 0L"ڀ7?.n@bWNKMLYtژic2nm[o-ߜs~X7]{5MɼD8u;-Xf˳ K~.XMjfT<0PMɼDv:p-MoŽ\_Kv5'G@R$N"e oM#Cj. e)t7?.n@bm|Eo/Q%V}5?<^{({ jNMɼDH@'XY({ jN4 ͚ӯيpT=>|yBWs180c<#@7[&2PޚOżp]J{QIsu}/ԝ+ t0 IмImgWLM7o.|:N|ם E׹ͽgty<)|/Hp~Πo/Q̄kE,61JyF|[`WV4R9L Μ`0Lثq?}ֵ&sg/қN۫6'a_=>]j~վ<->օ"k>٥@7 [$ڠyoFwHuuYhb2 e"@@tiHuwNErBIܡX z.@<租_GwN1 ^Ɋj\842 !35@"06#%1D$P`ABpCmfb?!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(rsy BW+ 6ɶsPd Tv(0oI{jW0Y!AQP(EjTRP(0oIy+z3o_!A(:Ԧ#9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CP(r9 B!CM`o8G'DPhMz8ª]RʾYɊrpՋuur՟K-V@И~2n,GZeʩ)vPPu7F1 Elw#ȪuFqN1ZKR`b,#r$# #(MBB_|(Q #&M,%wū5Ln,hY(X x"FxzTXX.!1ZAWz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧ8""H,qLF`.$P"x)*`h&#xyc1]VQbڒ,+p, ֯!#%`LF^Nvuy"b3WxyV~_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_Oǧz}~=>_OǧM/oyy"y&//ǒ//7}%TMTx'&"rLc,X<^9-2)LF0fZק:.+5A.ĝVqa+&`X&Oz j. &&[:#mu#U 9(hIRTPr#A[E(N,:у܍O [6lgukh?& @f3c1f3c1f3c1F 4c1f3c1f3c1f3'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm4$|޳z̭\V-Җ*7ZyEL0Ӌyz7t2tX S=؋`1u$6 &/ɕ \MeiWfۘʖHM=YXY3iD!vxfRDIQ#כ׭33LV%hއVxbGIJcU*tl∮5&⻊ҋ1+QU^o#&3 L"u^"[Q*WrgY"H8 c6sTSYdB)Gg rm:ylVUcXlc5iˇ_t̺L׸Q$oh{;ɯWr&mXyͮu̔uiԪ/DݼC ŘW#oj2Uda,A杋8Tk-";O2 KSn3c q/*(RKZ*$tj澇^[aE~oLfhK-$s :h1a.%)NɥM҆8OaMcC6K(Vxvtֱ.N#E&E4[B;Z49-_LuI \Y-.5V?*j_Mgac-ڪ| |j@ߧ>LX'3M^![geоA 7o!C| 7o!C| 7o!C| 7o!C| 7)3po87 ypo87 ypo87 yKGC|AA 7o!C| 7 #ypo87 ypo87 ypo87 < 7o!C| 7o!C| 7o!C| 7o!C| 7o!C| 7o!CIXFoY_§?;4f#a"|hgaZfIR[*4&+fll66 call66 call66 call66 call66 call66 call66 call66 call66 call66 call6*1"F!Lg>3j>4M'Pn~TeȶuEax! YCW?*eϗTg;sQ-jr<~¹ Di}wJLHq aXM}ԮkIme_6sXVO_MqV(CQvVK\+Êy"S8+Ê8+Ê8+Ê8+Ê8+Ê8+Êhz_]%&>x(GG:P`̰ 6L6chCNC! 3 ȋXבciCHmLդq`3~ Y0G/q#c3Ȕ @U3IIPnF9{1o1q 6l9 a40$4$H+0z))ua޲N6٠>N^)ghLWNjJ09fi,Lk0x)0VR,%92PjL >J2paNi0%fN(4ۊRSd .3޳}ڳLE;#b.~)oio0q/ˑ.Vȗ RiFKD62 8BHnJYo䔙m?Nj 3aqQUf#iINc0F#`(\$/ 1#[D%a!"d *.2[Qfȕ2oa -e$/\d%v=gicI՘4 DChmI) l44k%F5 ܍o9FDMY| 3M0 G!!!!!!!!!!!!A٩0ZKlZ0+?Зz%&(o !СMAf(+nHJ 춁s$֣LC5% 0`0f1g&!şŞ]:.ZfE,Y.`Fac)wa y}p&n+\t F~nʐIZvA礂DG _di ѹ@$i`jyPM3݌S|CP%A_JAEmY~n0b+kXA!Ba9CeBj~.82֢Sᨵ3 Y#ϛ֝D.<47Mi-`FII Co0MCD6FCcK96D2!$ ԣ%jHjRD4 3coY/_QP:i=W91<0]L;=/PFّ(-9m@H7k-d jjjkNP#CPja "7'uRvJjK:7*7 S.aiQR ”-%0ehlZ&ƭktW#3 č_gxc81ʂl;Fqэ DDXXDEL%m(ɎcuH8H6Ɛ<Ӥ%4d0f 17엯 ЫܳJ͓,ش^!v;ug~.31dC i05 @ @ ` cX5X}1ȈgOwP\T-juKIѾEywmDj*iEĬ%I sCfO@⟘ KmQs 5G<[-!U" &"&#R1.65j&RZZHq8i6t.xx:7Y%mdqICh32 ^aJjf _bvKSY5$Y@ER,)R_^|6ח xN-d7'0W3Rn'ondamlvvNrk$a[q>}ٌaN#2 NVcDFrћPzRkJS#!*spmP-e`,c1#yn%$9S7M䄽XqddI%KU++1?y&K )$ _ rȇ<~,62if47s-ќ!CKeq %k-D4wV+FnA%%-HHRQI4 #",nR s0jkAo+1O,޳^vITӉ[mUV/^̐Xu[&_7 HRAH:S)\ImJ08Dp58rw ްb#D& 3 pJtѸa542Uj:kCz%! /c_+1[EmZI%+#)NrÓϞ;(.q~fZY?mk-I>KaeitJL8@>>} cPP3j jP5P5X5X5X5Dy;%|1QhgՙOm0O'$"H)#9  2LıJt q, vCjq6@V]uڌA_nB՘AfI'Gn8}rL̃K HBO[:mGhYx1} 5K@%)jThxϞdC&r46 )RXr.kX8 f8 `1}>AB]##,8a+5CA C R3 h’d CX5P5P5P5X5X @/՝L޳^b)K|ay F'l=/ cpnЗFr(r'0!O*!jYJô̩Eb6m~֢AB vGOva+D6M3YR퍅Ubά$ܘÍbWa+RlhYN|دb..1Q>Td9mLe!Dfj0#/Gg{c8{Б jkk$$0RL@'cRAZJA³kn$%J$Hr鄅_v<.SGvKKcC˕˕F83_ܐ7A<7/ nѺ O>7}к;O({LK((I2gݘ! N|f?3'dZy557i˓XqbBbLpJI h06R4QmmU$j5A y9]w1}ѡ*}' ' HM$ $3ဉWh-K^.CłmcNJAx;ĆvGvj3cj0R9m2ZBZb;%fRRNAd "o2H2#0ï3c0ѵç:3f<`i"m_[ma.U=x 1v-dx%+16`Gd<`j,[Ľz1S(5,0 HLO9A77Y'I+b*Bo;4܅' :X \4YMmP~S_]sIɰJA1[oJ| .X7엯uQKgCBұ8Kbc娆(C818pc q818pc q818Ym]a&Ja֟ŤF@֥8y4f|m٪Vў}Vpll9ylK|VK}TH*Ճ"lbBޑz{*y.ۚ"?z6e`yo>WI|ר_-GG}X% A*87A> H)9#H|o RW򔔼˴ Gi&$!':ܼ3rۑ\L%MFԁ7엯 ^,8ZX>R,8صl-[:˫gCzj{qjkח~\ϜGl)92 @4w%FAdjP](BRZ ( ;Zymt^/ܘLiaGyA2U]܆mH&W78"4r6*a~ΉU;xKzJ:rv˓TtS ,A8-gGPm`n'8 ѺÐ9P9CD ̌4 cPfI(YעLu:~3Szz/l0ʗSaU̪{IKvl>c9InM<%a y}wܺ*#4= 6K) 'RB(RMO!_uyJ}65$QMVmZknԢ}mQPc ~*2p6Jxo ЇF7  tn aGd-ӕt޳^R kٳga9-.Zf"Pd*Kw~%KZtx޳^u>5b5|XnA6_Ʌ__3ֵX{C?^_]%-:3`E'ͯ&Ƹ+!(;%k vITw vTgs./~%K-n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn~޳^+vLxlj UeY\l=/GI3NR_bTFj4٤u޳^E,T3K BRup(̂I"1o/0x6keBl$Yb4ԺMcq%jv$NjB[4B̗Jdκݼ3.yIOJYB%;_.+k 6n[p JtFiFiFiFiFiFiW}dARlT@{]ͫJtr6k44X%-#qIrX0iȢIvb)"E;kQ$X:* Le&l%FgiI5KtFiFiFiFiFiFhW]dS]*sٓ/Fy6i>?|flZyE]z攫2Mh?Ʀ SY5$Y@XxASUL}z2{A Y'Bu)[y+FG cCl1cHaNI8$;zM*,"Z(1 dU3R qub'5Y4iL2^=ÎJx1gOiЂliA2826GhFiFh0Zm ~== ֖T̟ ڕކu2E|B$JraJzMaSsvTżWBl7Jh-p--F[GzvK:1,T9b7[nځ \BQ^BXo/J.?$D}1yhMF+4 Q-af ?M F1weHj 3HI ->OdJqf{/glln%JI4j-LГ+38Lm6I{O2^ )CKyP\!p A.qe9lfj$@k uN_D9aIi\pa7?Зe:{R[a.?qd;2- Go&f͍-0\P޳^jPG CHϸ Z Had`,Tu  gNM#uc*}F ?]jLyNycq0))$26_8g_1)A+MN1P)A d%, <*'uFyc$ڞy MLu&e K%Jwd6 Ղ&ߺ?Зͯdӵ0d1/I\WngaJ"+s&4s3{boY/_ܫMN! u ,{ޡ̾_0E}A !!nkR7e.6 ё8dBt!"QJ\9`IRnfDfG[IJԒu!ֲb:oh6k!dfNJiDuʆۄ3huVp=#v n^c?ЗȭF!u,Eds><_TiȓKbkIj$閅l:M;%m- yEC*0H}"08(1C}p>MR_6RAd$v!Iwi7خLqF&F'iӉHo#s5 y^fK1ưI$QH4;|lvyRjoKG$cp5GrR9j5;B_OOgJŪFIyum/O6eBW7nv>+e:b&3݁b)PKzsgPJtj#m4LQkh匜d27_:wڎCn,j$қmjlGՐ/0̔y_"fĄtKb*=CP5 CP5 CP5 CP5 CP5 CP5;B_OOcc)1Hĕk׼ߥ+ƙ;"J-xwboY/_UU *k"#2fᣓ8yP_֙׋y+JǥұX.˲ !zgn NI{eyJǥJǥ/Jv[zZ=-dn&/9Q=9ّ>3J>ԓ&=3!fLLzhat'Ǧ92.{44M/LIhf^gg<ôjc1f3cPf3f5 CPf5 CCKHX5_t?Jg.~߱Ør- 5PHkZEczz CE5$\B%j _2VoŤiRzoj/&*rCMưfCHm%m7#MdEkn,W8,+-I[qrd6>ui"#*dQ>}r+,:[|^fIs߰Gf_~%$t#V {6 w3)?=1ώS۹/lرϏL(czz-ìU;4fvt$JreT)PiHJBIid56TNnJMtDMtDHВ[QYad8m&X讈܂n tBZBbf]#!qYq$tI%wYŹcȔcȔcȔaF~YÉGRhI”i/FEa 82+)´Jk4 O&3caEJ1J1J1Yi%$.WHʞ4.Ǵ[ȋ:s]TȚq31ًV$jQ9gaӪ=& [cƣeSSPiҼ87\ʅ-h38ʤGq)&""ݩ2fK7MWTXM=EVڮFͅy60{ޡ̾%KIʺ;AmюM;% Ыܷ]ďPӮJ. e(B_OO>^h\ja_ATz(3eI[ֱ4czf-.b525MwײC7cfͰwboY/_UU *k"#2(Նʁ z2Z67LOEGsmb\ qY'"cM{~Ȣ-e-2ޘ C(;뾍=A.$rLÒ d 7FYUvVja9F_qO(m5"vYҌ|'Rs#oܓ_>Qj l4 #2GgKyKI!r.%TX)v M)ɌRO8Q]c_cL -5a޳^B-I;rEh^#n?Pf_]>'mSQW+Q:[ 6dboRY6T9i$$-)}1?-e^}$ǩ";ؚiYJ[{fHmI4LpDl3Z$'v-L hQCȨ;B.]a+p}Gy (вA%H i@S& XJTz. ~=<6+YMMcMGpOlh6lX7! Ԉܹς1gd~aN*mYLz%<e%0jVzx+L"$JgZ[fo8$rZZ͎7!.aD9KLI#R b[PMoҩf$HNSJQ]$!_[KTSAarVQ k ?~yrO#?tjdc& GSrK*6[E{ ~==h6;+LPaIi9WqJUQ) TQjGZ[oֹR I%Xc%foY/_[3dǍF/%OԱHoP3_ԏ4dS_IJ`t6MͽJ4$+;#6Yjn;[DJxh[ԓUAS*&GDBE.[ 7ape&k/Gu>q>0ݐxD.&=+Zs!EvB_OO@9(-@rP9(J%@rP9( 9{#9{#9{#.RQNG7xboY/_߀fTRP劔%ŪxnLDfYԒ"_]&@Ei#mfq͵)dHJ6M3}YaǴ 5.FJQϲE4x|htFJ=[l!%'hkȃjҚФ"A땄q=fpD+ٲ8C D'lT-Ţ3%YEL7 `" if0 nۺ?З9Ϋjjjf=q62O3޳^xx2$!4+SC̶RJֶid NЧ>k %LE  IE_}uCPܘhR !JRr1gO6F'& *qKvQ_sK%m#u"Nt/wRZTo( džqxn<7 džqwyixixixixixixixixixixixixixix-NjYR*M;+B\$Ƙg^#adl26 F#adl26 F#adl26 ͬJY2cGh6}w; d&3d)<(!jⷋL_ Rͱhn>hۏf;g!> ߲h˸i :2[fZB MHĔFڷ$/PR&4IeG?c}I#B[7f *qQꔱȏN3}2EmSL#uC)@̆TGwK~ !zW(萒W)@ r9HR)@ r9HR)@ r9H/6j,.J>BCg}w xoh<3}Mr+RK]Hb|Df(vSd 9i(q]}KCA(sH#iwHrYl_a-($HFa&gL*mH#m)dD 6A F:c\sbzyiSf7Oqnd۳j dD0@] l?ЗBq3 kSo,]QˮuV([QvW$2}wai$P$%QLzZR"Ab>JېLgN/1iȐJw3Nnt6Ni4 7djxKa扶 bB^MimTPs$̏NեIk*cb(KFc%8N<؊$5mjRi$|#, V&2B_.:fMN̘57?2miz={t1}iWge~C]r+^#7D;$<^ǏK×kR_R,Da\.4$-' fH3Êְ_35i%k"F5%M|uDI.߲fyZJ"I&8;c\BRIhQ]yNاe:zRDIfO R[\"[Dex1 X'L[ʉ@߃^%=%N:lVdA@aІW%jX!1.#31곺%lC9C9C9C9C9A/l6_/e|63M;+H2 *;-)ەN̷J F fm i/դhKA6CRe~-'&[r'_A~M:d3:VƆ5YŧurA)NmV $E9mCj' Lcad<{B_Wru2Z!GjFXbtiN9}Vvtb#c~Q%ܑk`#vd6,s{` o޳qÎ.J]L\/4aA&i$<]3Q0Zk%?=??jIoHfdY%ciu,EaE.?**2m 1Ea9vKk D\Crݪb%$ Y pk$c fa'[}-IPm`ִ;(H.&O7+Ivq?3zzFBRv ^)bL~;ZU)g?5E{OuSr!9gטJr2B4"/H'AoP9FIdg?ANn#=լ0;}%fƔe)I ӺèlH3}gTHW1DJe- ϷCN𪉒MM-E,K 13zz늏SxSx_VOuJK #xt+aQZc! ꪍȳi$h5%d4|49yF;4FY}1Е$|6)5β rJsvuB_6˦z;16DIMNܙM*WFoY/_uMә~zD)1e%HԒVB3hֆ!NJR30oξ~3RzȰLkf!D3kA.h<8ǒ'#3ү'`/ȓ8*sbVl`k4rp,8 ćgv{`cӫ!Ր¸V]t/sP1$&K56TVM,(*nGJJ~GifY/tHJ2%M9JY!U!nE7 6_5 # >9!j&' >$5"9-57㵼͔9Q,$5V,L7oR"y&HK'B-؏%?TqoHE{m;%5_]mճ&F̚h&B b]fve5UTL]c p&xZ; 5bէćp#t !ʘμ(ˌdb4wcd}dgBc6Beqb?ЗcaO4ƐT8F4בc&[S?3zz{|_LQ>Seln\rIrT5Bnb6lz/AvA!ˎ@ñ2iu$٥u/s͚Ɨ-4sRJN)qP*Ԝ𐰘)4D,uK+= Y\\nm;hF3D3+"FoY/_uY>Ut; 4i˹纆e.AyN94*_'v7uK ՞Â97&OtNueX.b52q?#3zz{~"3,Yɑ 2?]*fF =U*+K%DsKT_Rz'T95RsK 1#3zz{~Ԙenݴ!ZeSνf,{{{zxk~Gw?RS,)斸[aْbՕC'ə-wӥU'{O#7엯׺}wxL2G$xL22䓫[WȜF踫&Q"خ_zw,J+TmaF +%m~qcMs͚Ɨ-4sRJbWŀj`mZCRŘdvR̎928Gs#dq̎928Gs#dq̎928Gs#dq̎928GN!S\B'7c}lo 6.2 slεeig)&o7c}lo7c}lo-5YOۏA{~')v$Yk ?ԝlo7c}lo7c}+Jĵ5BA,ў!ߞ~3#N nS/Qy#.F. lM* ;R~^k"܂ˏ_qǗpn18MpIqN9Frn&)BpVŊzԧnV7ԌWiV?E%ۍq%>1Ȩ_4&6Qė1X1=iM/('5"/xw0=ݚFX*[u6*IM\{9MNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNz4S:Sz4S:>O:>z4_4*W%STQz=NO:S:Sz=NO:>hThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThThhhhhhhhhhhJ훜~ٹ W훜~ٹ˵,^*I)GaIۉao{_fݽ79n١ ɏb9N*||B GKϚm/ȊivWi*dM[J'/{}ݽ79ݳsnkov^=ݽ?9.\r˗.\r˗.\r˗.\}.\r˗.\r˗.\r˗.\r˗.\] {{C*ݽ?9o\2E8({9d˩˩KKKKe.Oe.Re.Re.OK.˨>թuj{uj5jE֏vH6m;%G(Rl[.kf>6IK&7R7d"I_+uyFןS^}My U'ə2˗.\t_u]ev'RVB7n+8^8^8^8^8^8^8^8^8^8^8^8^J{r;MlRv{v{v{O_k8^8^8^8^8^8^8^'uqLbR)4ͦYX(}g_?+nK=o.J*X>>W;~ r?Wĝv|?tebŋ,Xbŋ,X\aC,XhhhhR>+ˋ8o6o[k/Ŀ}~b%#۵rϳ/ab.vKg^ܿG'O?4~?>h|?G'O?-ǕO>mn\|?ȾMV*>h|O?4~?>h|?G'O?&s渘1111,Xbŋ,X]uY$1CEO#F%Z.|Get&;&eR._ħϲ-ݛ{vm[wov^[CNvݽaH,p8BrmV޹v+ ,44X"M`a̿5-##DZrnFm \|Xm,[uXbŋ,m+Ov^qnlˁqnbŋ{ehk,X#Ff_LJ}ϳNKz}Wŋ,Xbŋ11,b(,XbŋR ݳ{BNaİv1b[ņOW [8QQ׍{[.\u,jd\QJ\{Gf&&&#cŋ,XıbŻv,X;nKfdvj>&} Qn͌GɗeD~ƻV,b2%y;s42qvCzض,6ˎM;BX]?Kt",bb#7w~ŻVvݶ|l5"jG=&㕋_t>,5,4(ӷณ56dg'IF\B%j?`ʋ̹}.dq.Ks]F22lZq[g,}oq/v^y%=ϙs###"˗ijbÙr3!LȻhD>,444=X \ӱ'b#$ܒıbŌLLDKsCHqe]x]ퟜgܹs######!BE3d.E/vxbN%H'ҔdjN캁Nw[d"v]22"hpu)r+8DZawݳ󗀝fnK=ϟr˗22222,P{d445FV';W% G藲t*:dz SW._5s۬1't;4OLrǡi$.Ň݋/$j#Pu6ퟜ>>|-˙#{dacbF#:fMzsl 8LB-ŷCf1f4.)u4f ŻW.-t%}M}M}M}M4[ݳ󗵯=5sYB{._G袇{Da[2Żv11,F>&%kv.pf(fnه1HR.\r˗[Cv5wq,=6 {~ri*(u)RT{FWѩ=鵿EW_u~||V(8W_T&/+JA~5TRvҋ*[uW?cKmNߟ;uyPD6[uW?TohOj+z}|WmYSQzn~h$ a.+sXMoE}Yf<\R22222.\rb2 7q{DfbXC$fM:[~r'zJ)S{TJQŻI~” g^\޼9u[[2pWzjS3oGWK"?u!s)J)F،~JQŻI~/UGs"x?~D( q憆 _rm 翎v,Xıbŋ,Xq,bGf=22222222222.d4h1'W=b/P\Ĺe26Ĵ[~rE9TVMB3%sBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBAQxo{&HFEƭضv9ܹAor˗.\R8 ȹ}Β$ ѵI:/v^GIK~3dܔJ?5qhhqD|d(l$+.\ř`3jT^ퟜ|Ut6[9ǚ);\=ߙRSN g"Hc*znŎ|M4d2,s\X{;ř̍Wl_De٫Wzmt)bR2gVȞvJTgg!%t9b]7ĚKp/{ ݳڥQ͖Y\.lIbu'SfM;Z.d/]˗r2vle4a|-s#&d̙2fLə3#&d̙2fLȹs#####&ddd\r~hi؎۷e_ԕg/f8{cwe_ԕg/f',Xbŋ,Xbŋ,Xbŋ,Xbŋ,Xݽ?9{9l[lU4s_{~rjDԏnkov]C<ퟜW/ۚݳju#Y/nFFF] %tq.˗/##"v.evlѧѧ?݉Sqv,[w Gt\KEm-EĶ/۱bŋ,Xbŋ,5M~˵-b;Cn!"אč8)Dn,^ȣIM+((M&Jx,XBGgCD$)oe˗/ڱbŋ11111111&ݽ?9vqlqNsfV#M5x=1]F6ħVNI"4ʕ#4B_v\iXG2qpB$$RP4.J6座"˗/HHYZ?TퟜOhI[B|/v"␘"émrGO4LB4ݽ?9v"jG?b?I +MJݲܜ%/:$b2Cl5.F6FD=gd*gt*,WFK ov3#1I"X#(\O"E V6g'͘:~L7So$hP\?ݽ?9vO \n lɯ{?kov]þ>g+\Mdդ+VH5f9&"ld$T[ʭ*fFP^B"ȔQ!M,IBs5eq5[N<,kӓx?UT!ce|LV̑S>ߧ>[sΤ_?kov]jLfC񳅹 2v\,]ldjco|Y/3|"N܌ucc.~f өF3#SHJ$*~Dj<5bn̋/&q2" rq5S~KˏS/Čc+ SQ+l5g.֍>>!źlq+R.HҌ~eM!j\2-XM^5wf7s5[$)A+3ZC5~_xÄGb|ε5g.Զ x0|Z>DdIO+]We.OƴJBP2011DE؅N''\~B+p=)Bڗ#^5bQB̖OIVrW|yD]ݳiqnVWŊ,I,9fJ~ Ȼ2 ոİ)WU,ku5WCYLkov]$->!yq%ohrw," [%bdՌϳ>E,[zr˗.dddddddddUw_TퟜR٪iۉ̇R˗ߵ}/Xr˗.\r˗$}S_{~rjDԏnkov]C<ퟜW/ۚݳju#Y/ퟜZ44xvlږӱoퟜOcw8{vl{BNۚݳj[5V#UM?ퟜZ5#ۚݳjy%?5g.vlڝfnK?5g.֍>>!ݽ?9v4Ghm>pgQeQdFK.at]t].1I>FKӏ9#ZR3R]7۱uvl{[ű;>ݥT<"4ŚHtME;r)![k2dbШ_MJjY8v#S2BjLCMI._|B8 rb̔4_S3DzY^ NWEx1HSr,R<-b+ԒjɲSJy O}ݽ?9v_>~IKrDXŻ2%9#)"rVJNHK&vY:Rv)MA/_)"E5csg,o!+/3h鲝7'bV22!/g.5&Fr^!eEMQR&S1G |8\eJ79l7wlS5<Т\i52EyJN#*I䊞|pV5g.֍>>!oĽbLqC\/FNN#ÉN-<#-^<̣_mdey7$B\=bb:IH҈<.[r2.d9&9?3hRǀp)&JDdEcJݳs}zaWc6YZyG1t=/cb2KC!)yBV"#F‚9 re.ՎnjY훜{˞F/wbQbBDgbx(K mvm,&B钨ĥe*{[ڷ-~})]a>[NO|-ueb.P^RE(O/$EOŘAЖ*T:4*y,J|Md(hW["rm[jݳFYR\|WZ/ٗ1n[2ɐ5xddѵ<_eB٭ݳ_NSNF u|\\HPT\H%2]֋{qg-/)'[4Qbj|C{hEfF)s+/2Ӆw}i_{~rJWWġ_=儮B#t8\%$o!E+VVQ'7 m~!_>:,?)-vE]Dꢆ<ͥ 0Z1our222.g/{w#D8+RnHRxͣMqw扖I_{~r},bnҿh3g)\HU GJUv+B8đba-rퟜrfE%(qR(ICG)JZKזS1Mp%Ot[WퟜrfC$?1 & ǒ6vl4ݢ)\I"3-r'Oպ)%"<9 YQkQض(|l>hkov^9IC%Ɋqg qL֍ǴfتqZmٱnc:RMzdLVM`qg/vlܿݽ?9x?wg/vljJѻ`/~Bٛ(|_>b??h/M)z_|N[ hR w?' %FA٫{(BW/*ݳsݽ79F`F>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ZOt1q\@ !Q 13A"02@PRaq#B`bpCS$4r?j+ Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Эj+B+B+B֫BVhVhVhVhVhVhV = Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э Э СBn5we lڀ\&lM.!pknS{^k3/چq>ג{Z5#.MN۬ 7j}W: ZnZs};H}dbױW8'gCƑk* Ӵh8DuH$}>I?$ꮂA߶ė@:\+t i>0쟸H|$twD\nꗢ`kFIA=~ ^ϳA 2D[pNʨ$@ !s\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KuRs\-1KusL5O\?s4\?sL5O˚.jSrsTeS5O\!أ{s4Np?sT.j̹2is4\=5O\>.jk5O\?sTe>k)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥)n[b똥q|ˏKuǥ.=/qneǥ.=-̸dڴ`],WfF0(ٿ (PB (PB (PGB (PB (PB (P8e\Cd3˓@Ff2(({vb7'!q*ƊXƅSL oHlGFuA"[' q5q Jc3dPS?2oc⌱],WfF0(٪(PB (PB (PB (P⌱(ٹ–lsMEfˆϕpٲefˆ͗ .= .6\6llpٲefˆ͗ +++.6OhVZݕXݕpٲSBSBSBB8zNSJeaIpUatq.0ӦJ4wOQ6u\&\0aX+B( ( g@P?2I0/ ?Ck0/ ?Ck0/ ?Ck[{L*jk0/ ?K 6G r\!5a_r\!5RL9ϦSTú;(уMc[,Sy+Ls2&py"8OtywS}ݺh]+++++++[+[+[++Fln Э Ѳl+[,/>W_ *;lkUqt.ebH~4K-Nۆ#A-fzOnɞȞ~烈=LR)R;RJPrX=vQ=iV҃rgu*TSv)蜥J>T}U/ld+Oi_? ~?~O/֟?Z'Oi_? ~?A H7?H1O__? Oi_? ~?~O/֟?Z'Ocy[ltވW눯W+z\W+r*TR9 "R`_wTT)93… :]GTʕ>TJJJ=#}pDO=2aJr^UJ*TS뜏~e=dPBG$zjP]tRNrR9L+*TTOXpDG=:SN=r2A)(ؿ97I:eJNaW+TRR\W+눸r\r/RJ*TXsQ#}P'ThLh*s*TRs  NR@J)GӱɽPBXA(Dzu_ zWUUr WԩW)S*T/2vo7LN"=YFj 2 TU`P2r*zH @WF+ktUc'}7zeJr&r=RrW\E*e9ʕ*TT*Vb;78n\7zVUt{u9`_q ѩ:!5ڭ\6wMpweT7}7=q]Xr$)DRS9hS2,Gf,je_VzZ=UbZP9RU5BNJ2NRѽ]( MdӘGv9;J*TtQT\/2voBVzYz!BZVUbZj$*JJUjwtdTOTʣ)q+M,zBuZ\ӊn97:BPBX*T*TW)R\8{b;7H@4d#aB jXV+Ū;OJd >TBcw\0O(VuVJ5U1MvC)W T.ݗ ҋUbZVJArr ea\2HS Шxپ~Yg=(PVET i@R(Avq%\A u߲*VFCUޡ3j .+W+ٲ.J rjZVU({v\P<lb㍗le1.cXzU,Gf,催 zd{Ol@T@ s((*UC]e;OLnjB :ZVUjJE!i!aGXFBT2}i۬>bqCL˓sӏiӶ nq\+޹*?.5 }i7CPW!O?T*ZGL86j1s$ˢ&)ܝ)F3Cb.E[wޱ8VѤj5긏*(W)(zR?97jbXVT(PFRP*,M, Qi:UZT+T(XV0پʨ=i@ğkN p{Gd׶;tQPO2?x>~i6;Ӄ;/L~ws{]RSQֆaoUk;9}l] GbOj:|qBo r膪Lww!g'DL*e*TRHRJ*TROD(PBZV+bXVUըWkz(;W;)*D[Bir橪PZz3V\z9=_W~W?Uǫq~s\z9=_W~W?Uǫq~s\z9=_W~W?Uǫ5j8Cs;(8;&P( =r9RPVUjXV+X*ҭVVV~eZ]p܋K{qMrd@RŸW@N }|(PZVUbXV+jIXRx,Gf4\e~uzh{KO&mz*F\EɎFmW4aNo:|w (VUjXTXC ^BЬ+g\ل9(Sq=z2 ANQ*r{|BKb;7smkfМƿƳhQ zs Oپ-7NqwZyWqWqWqWqWyWyWy\Bq +W)\Rq\\g.3ˌr9qT*T,Gf>0(پbB8⌱uF0(پ`Bv&⌱rOb;7Z5NӯPB (PB (PB (PB (PaQ#zG(ٽM Bu }… (PB # e (P!W\p~X7V+`pWV.}ڭV p q(PB (PB (PB |&2voW+g5MNZ(6rU wQ UDժjZVUjZVUjZVUjZVUj(ٽMÂ%8}#=:DfONk2\FCM:W**42sr~- ܦg&wuʕ*TReޡpDG{op + 0\R=֐**tDuɵ4!KARձQtQ+̧dҀ5Ắ9UeO fs*TRJ*TRXeޡ@QGZto}cMmr\@OycBnpOMޔұ%a|0IUC6AńHSY*>҅ "G"Q*r\RNr1?2voSq4M2#ޚaDg ;puP9;T V(:Sb 0NMe\܈yYtXiB EQEȾ;n^J*TJi8eޮ [o^5zej,*HAl5GG(* pws!;A*ˌluDzi(En'=K~e~+5J9JrI*8eަYh:NqJ3]@Fol|+Nd(PUjw*md 4ɞڨ5GXOlTB)<*4TvPH?}:~bZ}Յ6{t*rIA3p(ٽPi[jkCDߦA`'UkUXGl`|fe=*Ҙ4D,'¸ʥوn]A>4nFFZ=6ASIronW.:&@8eަ: ?!5\j()\@n^qH"{'ia}IƠO59}Fii'ҦO">ZGX}1Ao;>sGdK{KeAQ#zq_šZdL'k|DzAW@J!hWϹ\ R"МDl#F9sZQ 6O w4Gi@>v6>FXn(2(EW AaZ4 ZE27 h:Tt)RJ( Nf;)Fi :\W + V>IA>r,Gf [G"=sN*9?jI@=D z%[*ݖQRȄZV+UjZVTf>r,Gf >xvy&fZ;i ACR )Fq5@ʴ(J*zB (PB >r,Gf7LN"=TSRJ(0d*r*T4Zg8NPJr^EүWr\WJ*~8r,Gfpܸn~r,Gf2FZu*T*TSb;7CXeަ: ?b;7CXeަ?b;7bB89aQ#zuFb;7`Bv&9aQ#zn\7CXeަYh:Nb;7CXeަ: ?b;7CXeަ>\ܫ۾P(RHRp^^ߪPTd+){wz (ٽC"Ÿ}s{?4AS u o\үlu-mbg:dNE9t]ZEPžQҰ !LtNrƷڅF!;T8:SD{J`(m⌱(4ڴBf*4&`8c8>Or{ +epAI(ECA&j+| U\hm<ܛ#F/8\dUsXprtL&Xeަi ؚdG%MݕHJ2z%9uOdduM^;tPmXg_ B-cEi ъPž-P PrŨИ :-S#!Öb;7w4A͏E>|Ql^yTjlw(*몹[F*JC@Qj!D Ua-A!T;t Z}$ӢʛhiU@X6*|譃oڼ=g,?2voS,je_})SU=ҷe;|H"Aեp}7쎁ߢQ\N6HS!I@j/SiNiS74 &ӄf4 '8eިQ ḥKmSX4Pr@Wy&@Jg:|@MwZ]QHB5pEŒۀQ@DN4TAAΉT* UGmEA2(? ,Gf6- Ԁiژu"Tk2F6Jb[PZ\K( UOLyD)AQlG@ .*=cDzEN!m4ߪ XNOs.d*@4BEW6ӢgjeC]2Op(ٽ\Wq4ܨ<* j4Sjö(We3 ;ٖ5ӠRY͞9S]+=+pwSa(Tj! jiS*m.z DWJi :d=T#8QsaQ'~ TJRTkM.&QSꅇcr\e:W AhR2dtS:-|@Yk%0B$ CLTu2SHShΊ |`"'!'eZ'⌱=G>&/T e1Dj"]P> \dͥ6L׫OIjQ ot(ꊃ*AZ("D5I% Ю9ꞨVW⌱]KK@Z55DƥVv?S5ga*ZÓ.*-S=Wa(wDdt (B!BJ# j+SZ@EW~af~-LAaMXia.V{r[iC PBu )za!J{'5S\ JJTJ!|tuBhx,Gf XuB} XuGPX,> Cb;7ߏqx:BcTϢ*Ϳ(jf>5δ J6_I$UCNgU:Ju- "a}3Q%(Pz0e~>(PBs*m4ܦ;E* A:U T7mx Mawek+.KQW,[M38VVl? Q#Sl?EiRpjpѕ 6>⨟TE}UjwӳߨPFn}bZ6>}h%eb71FU麠mz.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z.^˗z*4^ׂFMGeuUZ !1"2Q34Aar #Bqs5@Rt0b$CS`cP%TDpd?KL4QZqc2Y&ZHUFF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOt.qPh#E=ѢToOt\PTK)7 x_c+mj2NC)'<Ueu*DXO IneLot)5m4%XP}TCM4YRSRy<xM,kVBICj[)B\K)jF}R{dmvuL7,48Mu-IBi8 v1e ի[NASPyR*YI^x#E=)mDQL\oTfa`^MȢoOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{E=ѢToOth'4[-IF}R{^I"4ܛOoH m 6])JEL:JԪpعWcܛk¤TE&8"1ZUT2!)82bYJsov?kHMDFQЅ$˥9` XR͡M5EԶ*jqD<Ҏa]Q0$YRղ-Yhql;,ʭ\MU@QFͪQ̪Rd6lҬ# Wʹ,$Ҷ%ykVܓTjcKR첂-6 g^7kڔg\efʅ@8pJC2؊cK)uɩcNKInZ)ja7\jlT!,S$ZS Q;!2U9;4 F W@"L;(VTk_6$^jU4"bX%*8u:~ʆjen2j ZR$2lTYѦgrNY,Jˁ ~4϶4Q-rưԼh} ̀ȓ%N76rˡA5! RcOa9F )[u~V\qX ?va3{ *1<貵aK 1pQJg".XġƧAy!Tx3"ݠYKv\ƦfX{,@J~c avRbBb9kzx/BV%eĒ63/-&τZZS K16cND,ǐPVˡ P-KRlen{`V< \e%hb>i8?m_~Ւ:hZXl~~1κl-GXqòyԑcDZ] L6-m@8*J۽/ ڤz&532tˌ 8~'/4ə3zi~0J埌/XݼM؞(#>]"q9tT Ig.$ȳED[QXwF=(QGwGE6>]@I%#EKegV]< 9tSx"0ymnǥx"q1+h2e 8pB,eZM߄)ǥTI%O҄MKː+KO6&jnQO4™tTeH¯*?%#%#?>KEdqR?Ó2"^]+Pu'y\??>DeQ3 K* 4 aL%&%&&g_ \6M+C} x8 K6mBVWd6JЛurUf$ y,(MKluJ!ڂ83QJ/2x*>Za5]WivZ$j薑e-mT*%8LǂKP: V쭌ړZIQJuTL V\+ ^RK2C(nҳₘV˩ӨJ啢]P%ۿ04i xzJTvI4 P@ ޮT4\&Mi gSEoKxȄIvT\ QBBmW)}6p˄ۖKm!H+qŢZh֢ "X4\C!eiJtuNaQhT6f%sV,~r8ԛkʖa6'\83] QSQppD@-MРR L4xߗwBnbRj/g?&埌l"_`E WZ4ጄĄܚ<⚼a@fZJPy%TqvԜJӂB*BEs-KlY/)d(kJ LO-ٵҥ[ྶɿ 4"UK Q[' o;MdVdԢ>QWÄ]eLN{N8)*au" PJ**V*Q5QNfCN!MiSUWJk&_y+uAQRsE+N 8y\%.[ɥ K %(y;N@A%uNA>S&Pq%:^]VeEIYQmVkZpSS/nP[QRPP)KƪiaKxUzuFUUL?6rYOD!ͤ,ZI ᲁeB 8٨AR0Ry }ZAQm UJWxC9 SI}#lJ8>v%9H[>u0O}߫W0&%ԩc(29% ڥaL^Shq 90,mRMޚ%'2˖B{*Md_ d%f&_w)i+ܢ>J p,]Z)%Њ9!FMJ ԭEPIE&]T.Ț-+n0Pi&߰Ke .Ų1EPX`p>2&a]nѥi'Ywf͕X!L1JIM*XMl ᠾ2/0eS/ˡ4mJBDZEk$h-vqm@sDRo jඉi6&2eiPм(T.]=Z~*fTP[[M҈n :>g"ku4ÊW&5V5)#Q&-$ysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO4ni<ѹ74FhysO44L6)-֦ulhHCjp91(hlXF`Y4h+CS $ h_b!OR k ϪaK6@/ؼ$ZǺk&V \o62E5|imVME_uKN2pUp'$j<ЦT=`BtN!rpi@UaY%*s*}Y/HTDȺDsVqJXRDˏe򯽔>4R #GpaI;. &߷*,eAj3Fh"j!ᓘiIB AiwQ8@=%8—IA]8M3^TS/J>j[C֕sb(O N{$XGBUЫё59.^ڕl%jmjj6D5a (8̈́*Q+'WӅOI}+ImMe6j{RT>11S) P&Z2MCx"0ɾ!Y67V+:YuK-6'2WAZÃmleray? ff㯀(CX)ܮ}( Ep+meQB ?;r͐҂40jT[)Cii uuDIR u4L5P@$9CBHO`ԊQ1aRM:bX#>H^eITA*SO+CZՑyuGWꎯ_:7TunQ1cuGWꎯ_:7TunQ1cuGWꎯ_:7TunQ1aHQ Mq1So M+Z_(F#EDh4Q(F#EDh4Q(F#EDh4Q(F#EDh4Q(F"u&6C3ߩ؊xYݰ_tlo͍)/iSx2hf ͘(? ߯rh<.YVfmY:wvwvaS3"KG3l#Jujm펕Xj] !4'FE9w\ɸRmTy ȷ62yk9q]_3W!?S)P,Lwc|1^/tof73ޙLwcvscu_4cF1}#18c Eɬf#ь(4:m# c'j3 ٯÖQߢe_0nk{B埌Nm|~1~1~1~1~1~1>Q_@TWO JHdޛ.`!fENPfVJTO*]$N%PJג}-(y]I)kZ{RڃdTRk'u3_>;NrGJ*5$,Gf\\E48Aڻk c'9"'B;F5#ׇjJje..);BX3T((I,Y-5J.cB/6SX+ SOPr^1i"~#mX&ڏF4bc ?S|\6vMхLaA~174o~h[n!.6eHP#T96r-&ERnkʣ&o:&,ʦ,m#P> qfZqEJ+B$GxC'tpj-$vSK 4ja໅ZK}gv䏾&9C6ƼV.*OZ䈞 V<5ƾ+glx K'_DW7c1ДKSJ]M64E؎jX{v؄$_G g"Faa1Ќ6La_R_1w&w!Yz~0I73Sj  WmZf]$0.N=nz?Fֵ$\!,JHIsNzpa c+PS6IU* @\ƕ} ϸ9|Lrdmc3= lmV[VrձLa9Dvn!T\4*@8xZb"\iJW xL)µށzx8JiUcqTEz6-6a*țxm=c} +d*ͺ)j*t]Z]@q`"1(6T^@%QyЇg!|{{=4̣ASJ)ƄR4^Mmlf)vl<: VVS d.M Ҩ Su&WGYï4ͶݦK6$j7Pq]^Qǝ \8hI*ǀcVV4 e&ΨԵ/5WSt* RSRe 4!`~;ck TPx{ <7MLPⶨIbbx9'm@HQ-EQDHM=751N!0.1J]W5~&|qF1b6]13}t{B埌lgHzKtLT?L J :_sutJGa-6 [J Yf+R—S ;m[K0 BQq>ܻ/YLHSPVUʒ)'QIpcxϸ9|Lrdm:H0>>ȸF V7X|ERqs.uV*^!x&4#DsF#4G43;v3L(jņ"Ufp&)6.zxԧOiʶ6kT / ǃx@yuJ،caA`(c|@`0|K{Ik zb:_jF@&Ƃ-+]j7XЇg!| C pEFe[m q:"}n˭ȩ@-(R[Eճ&q46FUnYՄ0lnMfܖu6+uԥP%֏mEZRβS( "eu%uCyU=]Vr]8&1]{Ik zb5a1c\a7w!Yz~0XO4׉ğlϸ9|LrdmL|_H%BQG3֥R9*U8cB%U'}J>rp41H V/lɪ!B_Q a30ڈ&TA^,q/#I1_HƟp)*L:ԽN5t3h@`l5ųx<10E)Ts} }* PY)MOSJ@&OYm3kϸ.D%Sd) ʉM5pZiBx 0›! N[N3>;NrGS^_aR-$}9W9DZ]xTSokƕb`X\ajCX9dNDY?I B=DZR[3'*8@¶*V/p~?,CKO[(tҳ1FF=&4}.FRz#ɦ1õ'm@C\ CW™,8z1aFx9A>b+"͢={$Dj&埌lgkbX?PWzwzw6E̳jC>;NrGS~_+~j_Vο 1N ?\.2 ˁ_T-o2,X\<0l8.+}VDe0a*qcceTY<Ֆ"4L\9 akkG1狾;Xta}\ @0 *$O1c|bV3gB(,m9q\n+q7%rTnjcwg?XcvLnȍ1"7dsFG48Jip ?[/y+Ti9/&/&u덕[Y&d6=a6n$8fU5_J=YڬBMB$<쏂7]@VNPo;2-f2SDy7*nM)x[u.))A!neɇ-\0EX7*O ϸ9|LrdmNz~s/Ty68)W@<HPi}v3VYiĆԲ"۳Uyp2ҳH])T8l( !Mo>ڂ0*U8m^GN*1Zmހ=8=1ERi;mrXlB z h*FF4J7#FOmV`V $iimi8R71J}1e%(Fh0U5.2W(,M|$TS*+|f0 `aC,cd=C?ֵGV+ֵo~hveriJWkʣ&o:ömyTdܴMXeeiIShB75by')'.t4eQrkm7ba,2ܻ)mHxϸ9|Lrdm*Q(Il_ R$UL$PHZp:G<''+kEmq (*qo+ͥi"8q%j}B`ђ$$fĜ)ldN)LltҋS/Z@o@CQHUk^RAX@(-o)\ _cR-) jRREƒeġoǘDRWiL]^i*VcD(-)\ D$-M 8\#pcP2>w46ӒR J g@.DתWĬa+H4W@7^ʶLRה7%1)nLiqJ_׊4vzb#紝o!bE"ʚͤ*ی6X:0]Iq(c4.Rg'* gR.eN@"3W}ͦ e^>(gSh^iS,~P/K<)7> pj FXYNi,cd=C?r%ݶGuB5ƣL&]iD9m'Oqs>o}Xp8f^l2U!$A"/Ee lp$Vݬ)uXŹv\y-B  oӨU$9~VN?Qڇ,9ѿ -̪` 1 Nqmҗ~!v2hI- m6~O3ۡI}pMk1DL!N.it?̉j-^1[TJ)4NL,VAxA8f:<0VR ,kJx8 e dj~6Siǚ<]>! #tXCyfA*ƹ;Ƿ3?( ⒨K_(1O.(aP|-K*wGɳ}JuJ}J9d?=eB6hjNEWEGu*G}JQ':FU'Mu*7ԫ>OU'Mu*溕G]JxL*5Ԫ>OU'L*溕C=,#"EVOo+ CWE}! e_'hXo(xlƈ!PHJT֔Ÿu¤Q\b?N";NrGtZBƥ k#{tov7]ݮ@Fk#{tov7]ݮ@Fk#{tov-!%Zv=Zzn␑p*ơ+5WSZH'Q2ۚiҜ[BTc_qIDB&ڬfDMf/'Y^ CN g1* GG\QrnlK$U*JXW(Vp.]c%Ae!6G s 25,_) Q2Ӄ?ʤ[hVx9uo(lb]*\YoʄҪ }·J/WxOTšBm9 WH_SCDDr:"l7&k"kfϑ BuZQ}hEi~sAur,)J6_\Z G U)DîQk&8[VTE~ʙ)JrͥdhVAϏ JDZF$H%6ɦ5μ&XU p&ʲkۖµGD##!ʾr \#DED`6 #ɓ 6I FDT??P W"ia:YܚP/o6O4_uź9"ҕb}i)c,|YxiJ(STҀx0Idɩ=mih!4F#c}vۍi~aM‚p R"`˨, w M42YCiJMZ 4݄!弦ҷ2!+iAyK6إj@Rb!/2HW= 3>$}1ǹᵜ@6*TcM[+ڲl뀔J1R.$늨i"6>Cmﶴ%UuFQiƿ`g,ɀ,=C[Z%6+u<ۮ<R P@s(N%K)QNLFMU7]P!pM4aIX-[,2)W0仫y[Dea,TY.Q)2G*[m*UAK<97 KqǕgV.tJϸ9|Lrd|yܤ0iE]>qLEi]XKjxadx ֨@R8ખx ))ڢVxQ@N7ES1DyQdiU5E@m HuC! }`vUDwg!~KOLvh6V"/u?a5?rX+6;Mygb@{CLϸ9|Lrd|dksbIO ֜d\|5J%4XEd BxaI L&AdB׍`(Dp@pSȪ9ʱ/+tS6>C! }dvUDwg!~b,Kv ʟF-LKir7C$܏捓r^S=-+W- xifT!aHQMPZSjJ_=\23lfZ3bVT۲Vbh"Uٔ͢\o(.oYqs>␴B*Dl:P2 '٢b4B e!58 g(scZJ[()Rj5+]e.&Kq$La)TݔA$cHspv%єuHam7ySy0RA8 |#2`ZCίcm 2a? 0lCK; ܻ/PnʫRVhkt"UR2?M8iW7Qk* e/n2?%e;1A JȸR! #(ܼڳi(A,|B #; 9<)k4"EAob)R $*G岙/7j-SVq;*/ j4#.Aa0dSP~|ߢ/UDpz>0,cd=C?i\axF]G7ub9ZϬӜ(vGdTPJ5CH2Y[IE<8c*-(Yyn)¿&RmRkr4u&Zd)e«1Ui+]1 *8"p6pMKAϽUAuRͨ*J(q`1Emǚ2]S(Jؠ&֤Ԭ:҆jMNUIVQaCdDȆ$ 'WOKj4  ZR2Zn Ze x$W1mnڭکe,fxfV|yN̳HRR+x=xbesSuRBfV8xAJeFk-AFP O7WMoN<J X@mp8 0/=uih( UqD_ʥ޶.:-%..萫KDS҆ւ*VFnu@:7oU&jkL#8>~ߢiJ] f|n=$F3Otn=$F3Otn=$F3Otn=$F3Otn=$F3Otn=$F3Otn=$F3Otn=$F1Otn$F3Otn=$F3Otn=$F3Otn!HwF1ѺѺѺ;twF8зJgHi(~1Ӝ?_|+9xٟ1fe]6 @j]-SξRe2ǝdqAiY&+E78{Rq $. ';SUx\ׅ~e^L$ #Fׄ]gy3 Krb^l-+UFUk(yXym-%!+\B'7iOKe݆zl"bCY}?yrhPjCdݍXqs>)zv'D؇g!~~FW慶kT 5BN^RޖA^C1,)zvQb4>iƇcC1Lh}4>iƇcC1Lh}.o1:F711Lh}4>iƇcC1Lh}4>iƇcC1ʰqZIī3(mmV~Cbmr?0m_DZ)ZqX$󕥴!Y4eda-8n…UB@`iS,BM :4lT\CQg!xFM;@FR'',e<bdVतAԼ/2HW= &}gv䏾&9C?m![l99VWN$@ th<"&D%1-i6Q*U4ò2-5kR۪QUOZV_{(|%H.h7F~2K ;Ԓ/Mr\J8ٴ^ I<5uM4 ESaky׬FۊX;!YPTRƀ pBʔ e(m4]0[M!nR*Q"06Ani(8~1I9Y8=h C pEF~Q4*RD*jYRHxZR7VxyɸR\S<8t㥪WLϸ9|LrdB=b;B 8|og7w{{;=|og7w{{;=|og7w{{;=|og7w{{;=|l)(PܯX~1%=Ci?|=22 U+@/0T̊*1eKKC-)՝fA41m AjRnJqq}gv䏾&9C?m!r<3f$:NTXJmlruӮ4䃮٥5xւWVRv4yJpp.aeƝmITPh Ջ%PBP3 Þ Őۖ*SmF<|'v埌lg$[7 pl lmN8GR$T`))_ťV :,|c&{&{&~X3#ɾN叓}叓=v%~X3#ɴ`ɞɴc}b>L>KgGi62ͥ5*+=KY4]#y{7#y{7#y{.o{EI^^**_>Oߖ7=~k}=~XaXE>L%šKѰ p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'p'RJ*=XЇ=]$%W2ҟؤ2\R -W ,oZWoњKy~aYz~5̬.R0וVyvO[ 0h%!ƱVo"hki_ Wm_hF54sU1RcF.~1DGkievߢKb_q1/wb_q1/wb_q1/wb_q1/w$?pIw%nݺ5z 6C3񓜼?_|+9xٟ0Cri/XMՑU}kΉY ԫZ#>%5z#`fWᰇ^K 6-[ҿ1gi|1_YsvA&.( c7"㵱Vo"sԯXH f/0ҙN 7w*/L(!_J Ƕ4c ԑpN[R_d\R&1ާGe_9ǴXЇy&&s|"MLǃ\[T6T? K{X/(LlҼ]; K$ɄK8]l 6EiZ[K/c\D&]CUaN B(qR^c, BT*.11:9l]~.C_C [$p%_N,8eЇ Uܞ6pm0qYJPB1H],(nF<<)Mf&S<N+)Prj(J +MEB7jh+t1u@^qvێke 2v` Ƣq8k5ԉtQ]w)EbM/QpuZqLV* RM(8.¦%rrI}֦dBʳuO mmlYUќRaC%w2N% J4C\Il~MVӏ/AN=/e8K,cd=C?{{=4̣ASJ)ƄR^a υ4Y^K% pmBAqⴃaʊe•+ :pj:\i(mdH4q4 _ *R_ ޣT c /&9C6@֣Õ>(r"ƽUVo"dki_  ECYD$R8VN¨ $B/MXE_VWDaWShMjE+bO(m3e[wI8Fj4Fc*\oESc93M_MvvB=b;B䘔zj^^jY]FM[QnW<<J?>,ft޻WtKdZ 3٫ lxnǦUGy\xaӐD O8% I(ɌӁU\iL!14M\mɳLےٮn%f-d.'~k0|bmźVm 4fnUUrEQ ` oEh+s͇qR3rė&\4\3 Zfs6KaUm4D*'6#"e9{+eلB)i(m(@:4U[4v5(\g(õ( U/188M̕Pگ<ֳSB~>>imŸ)|7&67DNWjEET QǴKx>+'jB"XGki\>4} lwtݥѿjc(~ȸMW_9>w| [bcX45B#ckiWh_aI1a?;TUS *s[/q%ԟ(.]"0o[\'[(޿gdCkJR(yRVq~6O1>BɌ`&aq4*ӁHP⺰]jZ1i* #"QeVyi,J4M]#ń58x}&qC3$@/m!O _򝭒5??Pq٥<{I\,[7*hS.Qԥ $7Fx4Oc쵛GO[#?K EVâIN8~Kir:q+"ILxZ6Bas6 K+JY cg zƶ-ҕ*K^2*MƸT0gi|15*qiP^o;igEVo"/a/k Tc\xF1@=RdDYqCT-&,1Xo6#*88^TxQ//̺nQ3 YdQT[SB)0KΕ8>TbЖl;%&y͎dxiL"? <`{S̲1-Ԙ lgyɺ23Jp'OE%)0K6Qf>dfg}iIR< aY6d%>Ѷߢ$ēYYdWNT6+eW ?1.l{ O)-LnPJt hP)%(ϼ}q-BR$.W;H}YPQR/dIrgxز)[K7Qa o.LD]#Tlm+E*i{rb[ N8főJYff\gd&ɮ\/i|)l_MnDی0$&^+D5"6K,cd=C?VG)k<;K'P썭˝N.G~c~dD_f(*tT3)bhM f4bЗiQ]ThM!(9x@D('T BMrnpqVx46nH;{Ci^> `U.H{T?OH_.6p}j]̚+ج E'!V8ŤDA*.+@PR{ROc̵h=ȹS)CehgI>8n@̓YjɃGOxE3)O4[ 4ynEUyN^DF~GGhCffC |%deɥ BnͦoѲ~ o)&Ŭ-Rܐ\Be%u,f,mCQ> g"EV۳ZUu1nHJnYu2 asie3kV@`dݖl &3d5}d??PZfjI2q/W ^⯾6JeXygBZDlodmg)xi_xWy}DLP!V?)K<& cO,/&9C6K.vQQxk_Yȉ1|]--1֨Q"a6ݢ08=U~8  [([WE`aMW}3:/.1Xo6㲯BgZ yV7y) ᾛ.u% aTc4^85Ŧ /1Vo"| r &9Di'4kfBl,cJ`aeIJONIiNB, c,[ kU~1B.lcJ+XUTEuE/Hƾhm3WubcOF15mENJ/1xEo}\ߢ$ŧTT[)(:6 @$^AnJ+,mL$4R/D0Ko)iEUJ6pRl8ەhT]pk&%^BPyTuv֜JӂzaLw& VTjnxouGٛ%YF[@pQE$#dehm"U*v7cJ*q\Yy_w)KraXQ^TC !4B&nJ$bϚ7r̦,Ѵ& ml%!Yz~"}Y5C;@&jyA p(juA8 阑Ih)g%2bPM0VǰibxM-Qb<ɞ_&9C6G.vq~83 `uB_xVi썍}xrLWUA$($5>n!VB) 7xl_gQC" <[{Ciʾri;m!O%%%qt-P8 qY7 %N!5( 㜪`um餶bPhݫ6m o4Cal-$N]Fex-Ram[pK+)QN)Ih1)<SYvÖ\Zkž-V>Mk}2 D0\P%p(OO %&bRaS4ܘ3N2OvRK}$}!Y??PL,bxTuzi<KlZqV2wҖ.3S pW\LdmLqNYV5Q?揔4|?q?)){({3E#?4|?4Z;'?4%dH>S?揔揔4|?q?q?q?q?q#E7֭[KvJRd*qZTAJcAn?>Q6kE<9>@_|4|?4|?4|?4|?4|?4G~hO~hK~hK~hG~hd4SЯB_~G>E?I-Kr4 ~Y|vB=b;B(zj^^jY]FM[QnWĶ *ul1ɾԪ68AJiLԃ}0͆}gvO,cd=C?(ɲt8h>(jO/*,R*i(a Eh_IqCV ]RUTiDho9.ۖE|CKn4yv&yC?WZVSfd;EƓ[DC/XH42trL~ȥםݪAfÀ+>O9G]3m!KgGp^i 1.,W5V]xrd>e7"ƈ..fK+|E}<Ӓɒȶ@T_%[S!ͨRЌ,ۦ 4ۡqZ삟bѺ,iaԒuֆrDgf Z TvD (&,ՐM dhe [x'>QVEy8pԱ036)Y$ uYuRMb7cpDܚ>H6F`Tovm--i&pĜәY u#)~rOw8,܇Zd[Bs3p5mjK3IQt*R-ֆǬim)}j*JEQBl8lYuU.5&] LReA#0 d{sG :O:%~n~K,L6Js K&i߄BAˍpMe(eMq8ZYOe_9'mD##!ICM.:頥Nh?Hs[%W*JPE&Jay706B YVPRZÔ.d{%`+cⲕ)&(bY$P n:9e)B ABҥ\x.#I45*qԥR|+!2*SUWD)+x4Ɔ['k~1I9Y8=h C pEFe[m q:"y.R&K/e ;10|bmźVm 4Qdeu  45>b/N c;#i% A]lpOPPp'8aŴSBLdۗiZ+,!VI S*IMq\ZQ )*aFز}!bAFE 2e6n|ȡW[Lj%4*eM6riFj/<(m`JnN]2 \ aPڭ!Ae *E2")y(BBP@>@}BIl6s'E H[q CAe P7&R2e r[)o W#;9ETqm2ԔЫvE(U/e "`ҸP"#gʶl D_Wޯ GIcrLC*mZiFaź,+v0FǭֲA-.*AF8jD`Rcp%G/nMi HQhQ\cpVļȗTkpt<>QFü d=<0;el :jO|bݛ7'Hx `oI4K\(x,hWvp[8^I.Bɢ].7ck Sitּ n7Ci2:j<baFΊ.E+0G7_|oz>}N&ڍŶߢ$ǩDZ`)My>*[e)^I:<7F6A*&H^ZA ^6ELyK"n0a(( @8=Fs}MKj2U;injWpW>-3&ĸeVHڊݝ|eDÛ'7r)HL+Cf2GUiT%ld%-Ziv9@x$]9yd^igHP8غX^8(ZY!@! @S:8zi [jvzvtO8_mV jv;['k~1%=Ci?Vҭ$-M֜)QIA<;K'P%$l.:W"@PeV7Oj_'嗕XhڳeTN Eju <+SBŠPέvA3ZB&jN#(9P_^WBTX/.hU:9NjTlUSJE &|ҜPϓDimJ k쾿lN̶RhZJEJn8SowLϸl%!Yz~2Ep ʶ㋔u)BEI6 4rn:& )ܜ\wQ%V+nςN0i6%K(2EfVYnW,LU9|u͛b/N c;#E$(T`P+]-6e4#PiQ ߢ$!jNATre qYk'E%g,T])NRB)E`8mȨ74/&ĥ9Jf$^.)YyOM:QiB_i"u% K w$ W/pmm530<',[Rلo˜d3e@,_*|To549D:+aYdRoc妙nf[s"m"S *9\?arͿ.>!!G8Y@#-^}gvO,cd=C?VG)k<;K'P~GGhC*n o=58h!ޖe!N!h,y׀(Tr)2D$-T)F\n]A۰6H.fIraneB֐KfPl !36^. <I]WH,f,mCQ>m%, j!*eJ05r3lq5 p9D^G9q>K_C ͜ʛ5{ f ș~hfӠpau?g}kd-6C39MڃGEp7ɠ&ЪN5X)2HLa SfBR:E8eKNZFE5"~XNKxK>V٠jicQ>b/N c;#ߢ$Pσ=2~nn7?sSG<N+)Prj(J +MEB$E U i qN($*BKe`)Ԩ))"p%M*[% ]އQZVx;ZZTVXYm+)Nq+qu<BIB+3:X; }.4xmN96UU *PɧZtQ%Zw)UnM.Mw]}'*̻xm$,M\Qgj8!Ybe!"Q*)1\q>K_C fW&xZy(RIFLf J`DmJLL0+l;¤ܧ)qUn.Rgr5H4RU@HJZWbQ&2uⓛWmݩ,xar+pO ZBhM 8N3q%AU UIUq)ɻ.@p*p5:l\hإғD´YLq'˾ZJM7jy'd6& E-UQJ?kr[`ϵ.[Z^~e)TҼ/[L!4]xi*TRG ěsYJe^ -lPo6 mT5l"UR͡XLRkJoLԔ.qm^_Y@U8EbLMo~yvZP$S 5dC>*m)u5Z ~g-,0y/ BҢ]fi7"2#34-#&wD\ o19yd^igHP8غ 9&P:e졢 S' ôϬZr埌lgn'OPƚkOVyvO6XЇy're9vf\h'/7cG.]E~tϬZr埌lg$[7 pl LRRG%APxK96C6QBZݧMrp`'&D?U(.vݚfT$6QnAuig z}3)a,l;!Cbp >nnB/Jn~o(B>kyΉ)wTǂi.$@pQɠjnSPɓK#&Ӂixe% U)y5'6fS6eo jhnY9w\h& aK2[`LQ0)HSbY X->q,K+FɮG ̳-6*m@ƬO9bYxum$:?2K $ *> L)X D4!JBTH$hRO<"mR̪m(5P(Jɏe:2rcN1^FSL|)&7\/.iߢ$ĶDzr͸@@ PT}y]C (794d Djih%YK[~SN*TCJp \J4ki4W0ûlː߀U0΁$Cqo¼Qvtg99:u׻&dX*>2駜rOMݲ mx4ޣ3)Sk)k+UKR7*J/(ix򈾣m+K2nejT[ѣg3nO¥V2 ZŽ#QU7c997g&jΙSh0+# Fn4ld֊BUC*Y)_!?|Lrdx)T1h^b HTP 1/ڴ11Eɩu!w;&.ٮՔ^aiq׃W qڴp( } 7EMiZ;tEq4X <1|l >;*ڿo(x.m﫞vB=b;Bj^]8RlUGM^+bݔgU7u*R.Qh_Mԩ M$MT2frͻKuqq7\y,Ån0*Z(UHXJrtUi^JRG)e*NME Q%t 52?i7im5+4C,Edlf7[ 0K*|(R$ VE!֗X2ĨIiM‚$VED6MK!uTIAJW8ϬZr埌lg&^YP1<*:=4 ziG oS:vaVjVNN9n)*rfM}ARRiGI?1gi|16_@I@h[a@*ԨjT8F`x!w;&IiθH=uኁ q]hZRl_~1h G TEXo6۬WEz?sN~GGhC N2IYBҫ5C8j%fJNh h%:q݄0lnMfܖu6+uԥQ)- Htqݞ8I-)(|%3 iN PRTT^ J%Q[ZH7' xq10|bmźVm 4!J^Z(>ߚM4%IͲSo>EIViQa]s'8eAknboMÁ(Rۓe"f>t0lnMfܖu6+uԥQfWMAR YD R>;['k~1dq:mS _~ini`5'闕aP\ZZyT $ܢBi(/aqYJQBTpI],j.&cg??P${" q9'o' tB~e4)Ym3VՔ눭H)mOz2+E 9VN&yvO+A`))!W1y_E’qpA"h$dZFv8E-O "Ƕ|IPZIQI<17JV0.JoPTzvp 2IP JC$C6.1*{u>v16;->vUuPZ)'ji*1Xic'$*f*}iP{IowbQYC&MlX+Z]c$6VyvUxOQdk1S4*ƤFri!n Dz/ڸCR紝XЅbE dA_6kF掟:nhF掟:nhF掟:nhF掟:Yx:hF:_hF:_hF:_hF:_hF:_hF:_hF:_D^>M]]?4#dTCB_?? 8(zAd Z<@=䑥xnH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nH䎌nHM8Ě^FEAKѥ;4xnh@Njp(vG3(%<qya7W0lF'a:8U,ĢUWV,Pm2B (M錳"f2.Dc^pZSϛMcPnvܤX\XVݪAͪVھvqBi|kchm5e[xm݇Udf8TbӆbIp(VŐc1>ӄZs+ )v#<=w=zv?g 2, x (ɕ*wt9rW:yZVGժ;W=zv2iy3eM y(0 T$EY7 R Ƚ(KKXl<0⿳($))2lVg|mNIܱUx@uJΰTK_T}|-֖QDL)p8] UZôK??>De_~a1Tk1~Arbp'-{FʨPxp4 Pe_/iq$gxTfQpqHE\>&}]6dWy4+EEWʴ M(bD\01S6.0Jhת *$Q~ \0N%bBҫMzVf-:b b .fEh3@r{CP )B0Q) #8Jq0PX:T3lR4!zpi !4aY%*q_ O<#'?46.*K6S>-֩ɫ]e%˻죉]e)`znq8]C%eJ䂊W@n\4˖ Wʢժ?Sl)ywfr,̇,b(3x\:T y-$V+hRN W%m @.2駜rOM'V2Z8 m%hUZ*+[*Fʔl(kEN4 |"c;#)h#DjD%8:gmxru%+a9\#Ѿ {b_Wsvl 7fOgEBfn*EUCHVl]Pp06±F8RZj8"Bai)| Zu@b f+[G2?MqIv%]{Uk*㊸m\Apۻn~4mZ'mD##"75g|nk;s_w濳75g| XU+UV{uo=՞[|ng7V}YվiT]q0,cdE.Keǃ*ŋvٵ~0n\Um(]kV&ފ;.[&]R$J7q'Jz`MZXP{/`Ҽn:#RÓI]┰Pj[QZ8.aRˍ [Q.*i2]R*$B&A#/& a@± e UDQteE%p\=->Y^8xj5}\ߢ+;J P K#]pES{|wقU!)J&{I}-kPHjx"P} m MBTpí04l,Ǫ$i2ㅶT Sɚ_~# xCYrJCvŢ@A'vRp5)F!lJ"]> w&VOх0YtJ2Ymkb}!K%`+4Y -`bUldU " ژ(|~1i nPd6So$pa i2jRY{'PW1-.AD}ЖTN(! )V}ĪTR^X)db왖]li6 *MVO1d]R@jEnQZrN}ĪTR^X)db*q)'}}}}}}}}}}}}}}}}}} H@=11oj`M)Z!6mzL7[hնII2Y|cI"–$9_OyJS NlgL'#'03'ңxuF+S>yLJ1ޏڻ_IUĄTT*~ɆtFHDڿ>OU;4HLTgl|sDkuAq&Y9:zMu i%K*KiMxŖSmz˸UL[]@t:"Px\ mY1CCsN~GGhC| Q ,_6AY&ElS\i(iRaژx:9id M4W֗}0큐Swps{HSo%U՜U~cI NeE[R-p Dx/3mI&!`_\ ldet*ꩴdke{I+❥,Y**: Zeu)٪?fD]me- ӇBܮIGIسlM8,bf [JW$U:p$JZfa+HZ^*Xͪ&9?_?&埌lg)sai^D }*Yqt,JUj,QL*Z]!7#B(_Z8.03OJXBO/6LBEmn'}J;/\]vuJgiTTQMx*sNVT@P\[<ОPQDߴBͫ x/'-цg$OTO / bCa?9U E+6)r MQ8U+}biڴ)X7#9_?G2LYkڊHuLQU`!]Xjei+EڭJ˩Զťr~½ZCߖ6eW!5J)geh__dlH!`A8+ʃ)*6s_ #ٵ;0ŧ/.ISaVQ ^5uT7J蔏8+) ǡ&ʟ^Q\MGO(vGkX61-9Z)1Qb]h5oQ1}c1 W菟YEꊫ91_*H) *Pxbo}\ߢ+N,Ҕiyn(?]RM.56DNuk&A>qm32ʭU)PonKyfЗ`P;'vYz~>W!?)>%h/QʼY I'H$_mR*X PUMЉGjɣgP)y\FHShfq>~Rm {e_\z[eG7V:G7Y~_{uV_{tcEC#I]jHEoQ$;/hWtob8ARRhI]ѺSݥJWW}T4Qɮ#mD##!W~_򝩎_HqtG6fa QWNPPV"܌Ԕw| jS(giE3p-K%r '%FڲEVEGLܒƣdm*YjKege4R@ e%ᖥ M\כvYz~>W!?)۾/8a"``M 1.fKY[5[mB[^UQ6lѤ_P/7U7$@ w$ۍ͒T5ҘMn:vms e8ɤ%D^^"OO>!Xy@'ɠЩM)hMVuVgҕ6AПa~}dS`!f`tpCKI8eduFdR6JmJsb'%IĽin!WXXMl^h"c$[vTh6 SH8RyjZ)DBE,V8S 4M*Q?ocm9Ju־y V.he(Grڇg!|\LLrdx^-O8[F]!cKe[fgV+h"2~mʭjq0{|mHJʎJZ ޘ -Y4d.8hW\Ev^ǒrդUXۨ4lJp' [ NUVUu/MhnN M%*6 iW!?+y؁aJTEϭHPhp0uo:1l.ݴޝP$O4JX ͤ!W5G V\0කٵ-J7p]zǚD,|fyIU8BGmD##!W򝶔Uh=7TZUh}!Ԅ9TS\xͦ-mBSR UXzP8Mly5ɤ(9 ҧS-SEUY6r͆Um(]jkđ褴eEKI*ƀSvYz~>W!?-#5@a k ROi[6SX$(և ӥb*- D4&(&:î *-Ško6Amm)¨ "+I$S BسmD##!W򝶒XTz o'JnʩSZ.S 2g5=h"Ѳ1)rRZ@N9ƀИe8BIɨ*8$A5[Ʊ } K5G訊f9hC >|B~&&9C?V-%J:K}Co FQ+a q.:INj£UqeVJ{(\0Ld/Yc5*6q47cdlMo[H(od&^u \s5Bocm(/17BW䈚JYZd9.\׀UO8z=tKXi-ȼ8-gQ4T+D Vc& ҵW!?-: EAE&Qx%QV3\oԭxaR jrT'BV j i*pJR즈]uO8iYU5(H!zv1S)^i:i6TKx!Md)8Ǔ]wZɐO[L̲lJTTRx*+;nő|c??P'bc;#ߢ+Nܿ/N/DN8:Nm}3yQ+ڧvu4Sn'xm2Ӛi[jc?(Qzr*IqЗD.6ArYV0 y(:F) l~E[6<1*]D_9壵6C3 )zv1Sqk_dbdZv4 #Gf9hC >|B~&&9C?蕖rR( )>4',B-WN{_J[Jo!G m9d ͥ i!Tp&]^@\N94A/*ڭR0ɲ6SIA#7Gtot߾ћ4OwFtOwFH#7Gtot7zv1S/S1QUI7ˠ4 R >!_E渊8n{{!iyd*q ."k?(DI䲵hҖiW(Dˏ8c(q9jڪh(T]RZC:4Ury/:%4aը8JUjϓo733//r6M˚A >ڋf9hC >|B~&&9C?Wn#s!FB (+ۀWp]A*_b \B 鰮$-#'"aX_'sODe[H%m>VPli[m,%aEʀ:&Fma-%I5Bma-%I5m%wP*i'6O8ɲ[X%VT,,T5*&CZBjKɠbX@MTiy4oaY%*[d%5BJVK*kLJ4Dze~mƋnfo4]!eA dR2Tb9~1:ԇqF NDWMTt*zVȣri)l ]nhloNu!QӑDUf+EF2mFm&拏 lGO:ؗF]G%0()p4"B*BEsH]v=L%.JW' ݎfԦ@mML)H.a٩; T)fe!"TD&ط&E(dF9/mT\jqɄ)Pu@Y&ɼFmoH fTC^T&՚+Ψکo p:&VŠnn %9z'%|%Kœ):\B"$W5Q4]&ݛIpC!C3&8SKsV 7JRԣƢ*o);RrN"ӶVrN_nË7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7s7YY HeI@~0p }#33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 8,!1AQaq񁑱 @0P`p?!Jk^B9UOʎjh Z$H"D$H"D$H"D$H"D$H"D$H"D$H5\j"Etp@Y[rF5&1GX= drV_Nօh{Xn0W\"F?mm2$ v+@#d QSZMy|$Q7GY𑏃$H"D$H"D$H"D$H"D$H"D$H"D$H"C-n1ӿ)4|4eE+Z/.lPېiyY7 p%qU# ԀADq3jq]SBXBǪog<<<<<<<<<<<<<+MInqF8 so^1tt(]N3xF+!+kxe*pLd3iґ M؃Pf@BBД&gh3k+ceܑYum@vkvhz6 "@SKX &Q: 4)X4#u2␱v9bMWhѿ( x*IhFN( zV!=̄PzU>5' ]qyZw^ C=]Kv*PѳG=T, ‹RQ;/[f9vHJ2MK(u,1Sw!N+2aWlΚx䭱*KZƃ|[vH?6Hǂ `Bi B%W:(Uĉ]5*%uTnwEj1t^AQ`]g4VP j nT0-ٶ`Ŕ}T2&\ݶ*׎X:59,6 Pi:?>?>?>?>?>?>?>?>?>?>?>?>?>?>?-4T=y^zמ=y^zמ=y^xNnBegہ(e޲ :1`v;=wET@GJ$jƃQJJhr.:GduvLkS( 8 s9F\\5: U! +8Z,X˛b"YI$ \Y = " K˖(4B),g]Kiu5.7\0ʀb*g{8i(ً P&ZHuz:`x3_|OOmcyL/AϢi KJ>j^C^F3IgD h,C lvx Y h1έlNB>nrt7I'ћ j0f"ha1YXrhaCttiŁ~ N'_trgVP)Etbf*mH# kAAV[l"]d Dī<#n-R_H`_XS C0Yt{\ AѬʍQR"+L`{aTC@L&J>fMOK>jND:TC0 0ICl o:XW;GEvVr˗.\r˗.\r˗.\r˗.\r˗.\rˎc84ϒߍ!Q1QP/ ^޾v܅`BƘ>*):@mAۖһ rp4UDawB4%dJ`h/U-hIr\LsmePy˖ u>TEC02%QKt+IEmP[cyrB jm6(Q3ɼʅ('6%.൯:>r [ϣ-p+gct-Ӽ}xN;wi>Ӽ}xN;vǴi>Ӽ}xN;wi>Ӽ}xN;!w{O'g3F~#?g3F~#?g3F~#?P7i>Ӽ}l{N;wi>Ӽ}xN;f -V|F~#?g3F~#?g3F~#?g3 a N;wi>Ӽ}xN;wi>Ӽ}xN;wi>Ӽ}xN;wi>Ӽ}xN;wi>Ӽ}xN;wi>Ӽ}iy;/ҴV=@&r1)WcH5vHNհ&) Aj̙TҋBm`Rr3A0 x0sM{ybY\`-ZBEEKz`n6=@^dcbVA>LF&[h(Y2u*m>>+P# .A|fmSgN :Ug. (~~8vV5C[Em]"Bus_ pa*e6mNXn96N9+˲|1jC^i~m?6Oͧi~m?6Oͧi~m?6Oͧwg)G|7 zF|C?|C?|C?|C?|C?|C?|C?|C?|C?hvv_9-M+?db֐B_ ek-FD #֊ iIxS0.巪uK )Su ғ ؏3[UAH\$wU:eqm #(x(g}!ؒU]r}.SkK" 5~cدX?e;Kvw]gy?1>vrnWye&Y]~fp,- U}$]Y<<.+1h yTMܦ'MJ#E~<>~.~Н?dBff/Y\UHШiQ$bql` ғK|q՝;vD'oN蝿;vDTUuwԊScۉ'oAo J+mw蝿;vD%i(W֥,ҵ񢽡l~#:ظShH"&3=hXeD,YA4/_˹a_H+4[M0479?ji6"޶ɑKm+5w#3:S("zaa6]bX*aCXǁqm1f@*] MӋ/9'!vo (7zKM BjݼZ}}gu]vxvo z˝jYSNcM'ygjY A8w58nSc|y>}I>zO_m?dfbby0`&|U|组&9\hCI@.8z+Pzۓ&  U 5f(E3s?MbWg҈t u' V%J]݈bU7(R_2UXRSgcq ֶ>R]+b W4VȚ,E72H#ۗ8[oLPQ Z18r u¹pfL1SVpRyj[ާ;vEJEu̔w_FkF+cH\Afu:%GEK丗I!cTi4ffhAIf#iTarԿ >z(MZQ`YW0?OS\n~<5QJA %)cOñwv suW&\9sL3!tpFA AҾԹs.DXZq-w'q3yjL4CEJoz/Ԫ3iO[3IE#GLipl8]W7S ~j` G_٬@*T_x:WB!Y8z9`}fAJ WJ8Mm #\]bņI[@`N@an0}s ޼}7x'h hYҜRl%\BYl㕩[,1d:\C~ A7H(t^8/[oMM|*ȻLEVaۺO-nLθ8MC>-bX o% jЈ4v4o*Ñ:N4UypZJptl ;I#IiP Qm)3ZFgt0u 26Dν=yx)7j|Ѧ5g2)< ! I+mr ePƢ7l}|SO tAxЛ%h2H?27A KS̃L|eC9++*y~^.GX0- Js,vpgc7XJ4chǃK,Eu)%Mt!cV&0fh) w5-eaK bcW/F@*1‡QKM7%YM!5O$y;3Cax%eWНk&"m5gqӧmDj',4MP `j2q %EjME4]:]'i*[^Ype{ rx33h+)rz%';&_ 0ɮzE3XerL 3XY(gYLs &80;3U>ĘBfkKqx҆!<_ULi,o1a]Rs䎵'g0#UMEdз 8"{_jk6ǚP`Yz]r#kpDX(c+mGFl ::]AhyJ8ãpTٳKLyx#yP%u/VF$F,V))8o>:!QRy@.%'XNs<%_31 v1qc;Nڝ甩UV@4"Unf2*hu9Ϥ].]rvFxbr&(K{UOdk  -+1:6-Udq/k^q^^eUӋ"x!}bW`;%> M{W;"j @pe*u6R/uky^Pz}SpUu%S@>YgL0o"bP[29F-) {k.s๱E!TQ47NX5ZeK}d1o%b=xf6RK0O{Zk="Rk<3$ZHkXQcj(]35R8RzBStXJ9yoRLO: =+XF5fQƖ@r־s{-30gF_X>JJpXxQة@bd;m|XFY 5 # #ks:+ߘZ3yy Zy_.Gb^-*; TXk j Dl4kHۇhQ疓k. >]A43!+fR-4#*׏4 uє>Q64WAܧzZ ӗ=Zoz]pew3[^^TE)yJԑS2@MɂXgW2-"v($v%n7E)b57@B?T5Wirѫu9AXG `b^xIv/pIRh,mDXXCX׬yfhB`vd`sB  ^LA}]`)ݡb8Za֓邫sO<.1eVB {il5#3 4VUB Qi9LYVelƛܞ_ kjY\JZu(j1tOD5fS7aIr}ty>+0UAN9+a{K/d0)kh\5qOw^<#DU~PYJt.0by[0Ŏ-;0֢'3 ?Es#.)T,bXo>:&'3RX+Xu %5Q(Qf V ȋ)~[.6c-뜪; $`|o&%OFblv0sG"9S'RBU[0[h֥7if: ߠ2ntR$k ='7ifA5 63KkAbʘ*q#a}noќЄ@|CgᗮnЬ?DAUUaYThst.>^ SBn7`UxqBk#fQ|rҙIlTÖb2&_Yqv|t{t:gV9Lz›w\M:ްZ@DD0Ff2φǘ gfz\q7.0)MSL3.aYii( 'Sz1c fL8Z5-"kli~$EY?uc(쿴U y+rqi`NIf_(A)/eh#_+p/SDF.Kf>J!'F_%T1w^<XF&~i+ F|rG1w2T{%YXs eO4iE,Y-%7yYkG3)+â%Hd&vlo% E?Z5G.ώ=pcdųY:S0ΠxHXߵ=E1+[L&peW^zZ:5'$=#2S;N_ow<*s Du q/6MYQJ]H~ܵsi:0/NA6_|negTM~#H@"ikd~?Y!̓v_Ygz<1|y2SZ+U5-!O (mazKMq0%U< ~ȑ@?Pv^U+y+F2"?3be;_imkd+D6B%4-z7υaR뷤W_R5B5pﻗÎuQpMNY>28ߐ6 U9E'$9ZeH* mx9&Lw~\ ?k7On5t5oRZJh/+\mQh+HFWq!jpsOfy:Ӕ@Bǖ^>+gpg<Q</\˻^}0BϮ&2i &̋I'O!5O$yCe ]x*ZVޟ4h`%rέ~hZyx1L`<% 5cC>~űeՔ֕,=Qatv5 ䷟!hT4R,457wfhhF" ӯTYi z3zؙ0J_ዶ4]ySkg13(ށ⭅霗M* p60+d 6y$gD㮜Ѿ< nKa (TJxU:-[Q*/Ά5ܑr]Y)P_i44q,bi)rZF 0S%qB/-LWպNj@X=ɍh"ZuL*QLl_SfQ(6^yx䘏5*2>6Z6`g*ڣ@hiwGx˿4 <C8sC!GSyL0aڃ׀8|W|MTJC"ZV?Tw~M ]xm]m#9w7tmPFo+=O$zV8ٌ9pR*ZZK bj '1vG=h{N;CviӴ=h{N;CviӴ=h{N;CC,.S's(} Xxco8xL&M{@Ų5b:<5eA šmvJn U`KFMGrjԩ>L6ͩXݝF%xIh%URb ]q^«Dh^rV(8Է5j Vc tT0ݠ2Ʈa<%黢gTFx5R\۫8Y74f< (5AL0r:V6%@0GgcAWWM>h{MEaT%,Ti "Om"?f uDWEjά4ZhL=bYFu.fqH 1ψ!hP`˧sІ EP+Mo|@iV8\J+)iJz 3 "bLcD5"*ݟ֝v Mq^L,(-jX"ipoMeЫYIzlb+]*" >z Z*T^ɤ H0 @Cv4gCXD]Qȭ7pm=fc)@c&mVdNA`<05 (}F qLT\yzoޤRD .`V|эzά::IמxQ(ә7;As45#WxvZ@еZD0ݩUP>Nj\ҿzoVWkU1G1 O*TkFUzej:%% bՅZ(Š$CB3B'l`6ɒH޲h1 %k.m&k cdtCdhm5  qk`z8Vyp/@7t@l<£QW"_IBπSA-ƧE1ªFӋѠuzm1 VTQWo4rƓ],:_7y!`?/^ݡ@2BH @Vr`EƬXXr_S%նhpK4zۇ¬vJ#-P!5W7sIګ7M냏t+[YX]|W $jj*e? ғ@*1‡QKM]`.,heyY&".SZVv8Yٚ `R1ǎrXHU{m nv0h31v>R{/\ue%6KI<߉Z)Óy*Lǚ u"@̽mܪX*LE,=Sm!d¢a(o?MM]N;wtӿN;wtӿKJk}+;N;wtӿN;wtӿM;]-\^XFwt2i[yrkdl\' ]K7MnCG1ԽDX.49SgmM(Kym(]Darf\6{FPFG+ן?Z c/ڵjիVZjիVZjիV/Qy|7^SQ:GKy J'%1dhb[554ܵ* 6k|7-h]*bgv_覠Cx_:,ш}B #/ RK,laH/c[@|"9=2Zb;q*1nb9U3|NJ>lKMeq6e+DCCBF_o)O|74+'~М9s9s9s9s 3i} 0ٝMn fVpUB5B7u@$PCSIaFb2 0[x>- Mq~~qI";Qt(m Dj ЌMOOC~5!)pkQa%-x&p53rFM Wҗ3k@##f.ж,Au4~"|o#JX+v2}{|tvJgJVFLo(xyG#>Üi6 4ݘ PK6z<%U q8%0t-䉖⸗ad{{dȈu΂qI~[Ԯ :S) ѪTq+ZPQ¬ܿlE֦X3K'[!6)d̯hEVHι+V UXT hPXP1E,XQ7S1~rȽp(|͉%hhߌ5hu&Mf>v_X^YHh)2yVLD%fiy iL~"femؗ94CUJB4 `OM"ީpY1jްs ӎn:˟)"Ry*Y~8шG'ʟiMaNB=5Wt)(´qeD^r#NkֵM^@SpmՊ,bK83팜^{r1MutQ,7N^hq<-l^Q#"xvq#,*WW!g˚fO};/uW _rSWZ&e{B*2ELtefjT&{Lp~,GltS3"Xk/۷aڋۅxu[?z:=P<ĺ6Ah-k-KLG:Ma u} *$ a93Yl3Jβ,*+!Hoxu ސmZ\}"̓шݫpۮI[%v-Űy2\s+ ]S_(1vB.>>әL =z`g~Rk̒t}}gpI7%>;O4[<4 1}szO;Ђ/(LU}1M޸1 ޘ~BiJk(˃h; L ]qiU_C8YB3w@B6űy l𵲂o}$i/UuV+a·zvQlا٣j%UTuhuÈ&+%kSG={|tKrs"CH`lʀ (i1yDS)qti^)~@N6}*V%-XA&y!34/:Cy Ɂj4NZ rj`>^n]{Jãߣr;j\zf=}?ѿNt?Y4+S7A>W,x}} Gk+ OC; YLgs,`zf~X@.9myD6[9 4@jF1r0Y*,L 1ly]1 3 S4^Uy?0[0T4<` v*n&kp\O-ALgB|b GH aĠ=R;&( (" ZxX_awmO呯+MRkbܴf4Ў@>3\w n*WmqAQhgE~q?j/Ah^)$'ܱ:/]C՛QMvy AϩA>轃TV>´q׼};/vwzCyQ, Lb+zxzQF7Za̹rr$׼qDx\4)LUM!^> %62H/2+e{2BfԘtQ蛠t z XVnks}4Z1#AKwl7)jmi]s=f~UŐm0zxm)c~T ~t>{Ea]^}"6]* Z5^HT`?; flᱴDu~~:}OAoܐ"dmz<~QWu%Ä啀h~rYM^]l'sCPr>´qکJFNvsazAYZHlٶQuh-z!Q_,4Bfz ,]Quh-z!6ؒmz~R񝿗9j);~~:9ɋLwpX M#ǷUrBU*ơMTu9Cxfi`HՀ&!KM?GYd(d&''LcE}60JQ]#k QR 3F4 ^5)5h"(sV'PeXCسBq^y^em$gQ1pC/=^7aÎvF2C8pg_?D#(CkmWvo~/藫Ǭ,ϡ#?#ЀT:rr Nv0isfMY+O(Xb*1 %E;Q)46E 3meF!$(j%7v&cCG0 xN5^<37+n@mR/YI xfE,9xr6ʣvk|2ZO)ίK:>;Z }*kS)hkq|ʑS1V٪_sߥ CKit 0/7%>iiC}1_)? Ukozo\Eڽ䵚*E{Tˡ H (@\ ÇZ.1,{ckAՁDY|6-Z_NqVfX n;">qZՁJB-(D]kB[};/pzpTc*&')CM!5O$yxsu:Dq7>:&-4FmˮeC)qQ Z$f-RZd<\և1R<(pC'gz!YD_]d#G7nBaEքYAb[hc&B-̿UuʕIJ5Kep Y#tA2iWKOXs)=c֋m^O&8*Th";OM޸ 5܅X; @w1MBCP̀HanśJ1m"",zCŘl贗TqjR 9"$F*ƀN ŲSx r7.ͮ6n\w37!Ya>IMgRRk-7gZZf.w.H<V|_^j-o[0Ӈx5/2KbS+mLt:|z-eFy2 ig=t+ 9eЃln pTX%.Yy` ER fnY]%+c9r+Z钳?$Uq? 7|7Ԋ'FSƓF:l+EbQ'j(!wU1єR겮ϠZ)2`YzR&[kagecvѳ,@U6M>}fG WË񝿗TL X^Y!45dôzf`hDC X= M_u{o&dj^\y9K0#m6^l~]љ/F9e3oxp2 \9c#1k5ЃY=Ƭ{g#5cV=k:l [B@juqȪLl'%@ٝb+\#׊{tm񝿗`W R24(k: lTT: wXWg׾EHq^b߭C= IkuƷU})i%7H+HDVp-4횙 i@LD:Ê+8l@j6-uQCB 0, Yr'i բc͵Ta(WxfRY]Ϊl:t9G/Nkюjm %EZuo&&c`ܺ`^X(7lT/!x6iS6I`- 4g5ѶcQ[)M@/z"LYvՖk ɶ\lՌwwsIl-3#Nt0(FS ۗ_SU`r1XiEP,MƁ`_Kn9P(he?ZÛPkF~؋Lg4s./ ԰ޢ RkY8]2]rtG߇};/pĦ=ϡ R![V*X2K-,`R'n(oz:FJŮ0Ձ At_K}Nmta}^ M95יw@c@%ʺP[Fn7g(mdR-} JepJt>ĥ2\e:b*4L辖sk0B9j ׉N %rij$PG,yu^pT4e26h ANؕ0$獷U# n" mVmJK1qmKqn1+9FL辖]+ܼh `%6_}l-h5P\Gi[C$]dZ K3)^ #S*ah i+ 5KC"hfX-Z:pne1MF@2hߠూє9IbgeMepӋIřΫ@iy iyjߥ:L Mn2s7uixW}dԍRn<}7zdk@Kφ] !ؘE 1z-Ȯ$]-S%8WS X!CЯ ZB DA(fmR,&0n6RP~VXȮ No*$ ̻t[};2BǁqmuYgopMBd`1x7>tix S7tQ5:p(BYȂlٹJ6nUC L]<ކJLP. K\Q^sr4@](dbXXvd5?)4_IiVhvFYc%ً [{^a1ݤ 7Y^m/YJ> 2u49PamMV:H8,`\ѓ5B`fÕmJiB J$C]dVhGBfR9F]]$0Mk)`Xrә5qfͥGtn"go7%R*Xag(r r,͵JFP b X,/A^}_"D(,l~?OS/>Ǐ J,[)Sޛ´q"fQf'(*ꩲMR5sF xW݂*5o8jڅy1ԓ+dbeV׫ (s2([f^8-G񝿗9j);~~MM޸׭ 8A!dy<,MH%% 5Ua|LDDpUNltq1E P@6ђ]SlIX*ˮs!.; q񝿗[rG;i+m6ii pQ,nM ڔB"W^}_o\K"fR`e1kBX.xNdY񝿗=N8@*1‡QKMUjxsu:G{>´q8)-flK &0u_+.v_l ::]Ahy_)U0)<@fv "nG =\/{>´q5w[-Փ2Z"k6)L)8A ''@V եZ ucT+^V(\5ouJ `V3%gVV񝿗!V#׀Vc|++'`x}^Xf,"n[/T6<3uhov nSpmՊ%#ǁ4]V| aMFws&sޝc(BP!ѭ505lJZ8ҨTEU)\Jñ;XLK*-KY.v_Z6ѓ!̯Pũtxݼ<1h{yg7J8.1E,XQ7x>SG|7% n)2JSYF\ mf:jBfW"C$Xfn_"S,+0+KK5,7y;R![V9T,sbpBS)D7B`bSXeuC׼q)HA} Zx@VO񢺱Ʈe ҁI8*p@nq%ZLn.\hxEiVd,;Y+=yD8pƓmkt[}O>j|4" k0hNo*$ E04 n.v_n *^Onx>SG|7?F%xy*5t}Exo J:"W?F`pCRԿVE^fIŤuŵE_^}_o\O*k׮.$ EKDEV?ĩh 1sɎ]s$(Ml2М*iqIM؎6C8m{p!T #֊I|KTWKA՞ Vj]7KpYbk@"'J7,;; W 뉼sx>\P2qiB!JE!8FUYMi?k"QCEmkDPs6k4*.V"&sԙgf[C+IrBJoM GK[}gfhl6:#p\[<; mpsRMn fVp)$SBs e,<4X?F,O_9'Ǥʷ}0m}YlB(Ҝǃc^-{oavsѻ9 2~>Ʋ@jj vsddMilGP u1^.o{tngq{fFH3:vy};;]ziNRO;wpӰཷya{;v:~ӮT:d ƊGd+U,0k\Jjc&^.q:!l@#DAmrJ 낃uxZQDF] dԌGNzRhQc `FY¥J캶%v"<_ UH$yńPp6Oe X~pxQD FFeqmL!/^}_墣D׿&6 Є-5s )Yn[pam7K@m*@FO-1X̼:H duEbVF]к$^13*(*!:L)u"G`; oޘu.\j *ۢak Fzxh VeV#MHp6dLEH%y{ `xw37ja++1g X:h i9jű^ ?I^LLsƄ4ghD%w0SJC>" Z0ʆҏZ4$4XayC93WtSf]!jUbw6Yal41`jbI4+ibe1f43\ C_t G~%V)>PW! %ђlSt"u\=PK5Ea K6V«=9AXז2`Fd ^+˂Y gW F [(g+YǘџldݖJqV$XhN%` ~ 7%md񝿗`W R2S= H4VKVp5M[R^}_8o(]P>FV2Fe/[ .12ԗt< !տG ccyĬa9qD[CQHnf:P]tBP6$åVli p7*+av'B@Eʜn׶v=0p- åQ^%]#vDbƹgN'X` Azw,{d_WVh rMާ ]`,4 dR2DAȃ ~eee:1by9zM޸0 @ ؞ӱ=b{N;v'Oi؞ӱ=b{NU @ +:)il=@*Wgk`UxqBk# PQʵ鮆q*(^Y nwƑGؘ4!MYam5`rQÄ;im\yeޔwA [ 0+ ʻH4xujX3q4bC¥@WG ck j^oB<-gԩΘN֧f"6[\r=*5fX+zFiJ*TwKYK"Z#z[eZuRk7daC\4U&PCw,;N9bɕU_/:鐏Ohe4&O?Q"׀ R\- 'cH/ J#S}]RTh(&p+}@vysm^U>$ J/ f&p~c?1g3~c?1e[d \|>W+q\|>W+.TD,uhG!'>mtgo/y з=aǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǧǥ)F0^ZWɕLUh/Br]BZ/>X;l9 ]bˆ׷0dε/&p,yAYE;7=%GN TxeLf I[ dg82*m)`:\wKt3JǬ@ # =fy:RˉyZ!ebsC%e|#sIRYJqle ws<*Sҷ0PގSenP^P <-0 *&71ۣoez__ WĞ=K@+]mVvR9yD ,8S18:]:]:]:]:]:]:]:]:]:]:]:]Ukiqv/\:ѷy*:(1Rƅq@j4XOq"'6B-Ho8hG o_Y5e}!00˪f菓.yX XRٰs§Ľ\Vre5j# G@3T߁T&MQ\5+85E{jE7qp#5.G^o:#ffg^5{<Iٌ8n%o*plzn4}f7O;-뒉v-}|wZ.%#3xa1`&KLHl 4/b T8QP@˝3T[$`-X`[ɭ39ʴxvݷXE*6R\՜FR/ɞ}qtg"<hp)"uhWQ '&@m>DjaTWȑt9XkcSOeoj3IXf(z"4?{ghlw+cMT m6b(1,^U5@ N+>k@UAHZyXaBY@@Re) ìFdC <Sʳ/;yd:y9Z+[6]DԐb?]0pW ]"!<îF\P 13-W!u)vʻ $q7t7VH\!@OQa`%Ox1rN YDAf`ZRbb|+.AMȗCY:sZE%k*fv }F&[h*;U;ʺӬp2BňHM jז3 ly\.^(جAc:̾L'OW0^6D%4Ыto n\[4#1K&Mui #I,pYVt] sU2^7:@fjhs ~{]s}BX ocy`g./SBSAb*l qs8&;5U 6J;2WQ=7y[h YeeeeeeeeeeenIbQ%J*TRt8 ;/ZL`h:AdyεQj n%3[sa/ \{|dGQW-} f*YWwJ &1 򜨅AT@^ 0ʵ{ͥ,ʫUV_Fm9Jcn&k@hf yMlRPj:+j hnF:2/#Q3%]@F:5o& l N-`h8r{G5:GbTO)Av y޿(1LNU,TCN/HyI!O~ҡnmpJtqRլc>R@@ A}v#I`Pc%A=ԽL@E*ϟ:zoAsM=Pur߈" 'U`ɺIfU ǵX `"w" V: X+kxV;p'HEͻZ]`KƁFs5LJ2u_m E Gɨ0Gu(e%:^@84*.Dgo.?摠Ɯ/-L`dd }RH@Rl~ij)lqFN#ŷ XGt34Fe>@: Xh.Dϖ$u C%W%kՃhZwVg/܎j=a1*&Bzg ě]rmծL0Y[F#d~UR #VT&SƢʁZ@3n$j۬ k8\j`#A/*[fM]MʍC#K*7tRҨ_!G)lq\&5/濺A* dmȦL Ѩi$ N̗#@Y䬃y8 IW >2^9_ʀmpNv"D:Bלm0aY}&KΧiFaP# x;FXOS|77Ih֍h֍h֍h֍h֍hh޿+>>>>>>>> D<<I5ɒ,%0G$Ss|ЗBԫI0RGkTKkg+?[;ف{t1UBķϟiqK˫fc"t nk(.&a=7yZi|jw(huO/P*ոz<2JSYNL;2ze~_'o4z_4]&-ЃAQN]noԾXG {m^>65e s@KpMs%08( Ϝ h&16Ψ\z`Û7,k2ZoeXV |ʘBTK*]Iٙf8PGMCA+[Z,fE't)`9J+kc׆,G̶eZB3>bc`' ,* R'9P-TDERj C@[47+sث٤EN() !!\셥(c~*-YV>nkϦ P]Kq+]δ-Kf=btLe]b.-4 UQ=2T%LJ]2iS [Sd a#! fQN^j, %ApTEe DɬT,)12nC$vVCC,PUcHܿ7:J6f(C/,2/8eer+XƙM{ho[o,N Dub Wes h"c`+eĴ JXVJm{ 09Ѭó[8o;/kLZNFIͶj~/hKgVYN q.'#O>T }j6}pB3𪣟s8s{v-_gf_ ,'߇S͌2)y ,^R?op\hh9xeqZ-7-`@EkUJ.чxsu:DPs1]RM0vKq:" J}/X,%sge8s%KQSnE?eK 2XpO63}Y۠EfUXkOٹ^E*B4GV-qSW{t:{}aAexEB7yP1<`ցiՕ+B7'R@cH4VRvJ `VY@(טvKq(mp4V/o g^jHyFS,(Q#4WXh48qk *=jJx˯"WT(ygVqϟ)땲ʵ)(K  MzY!uVπ$L[/+ͫ0 T:oEuj̳UQGFL`8 .9M:-APn('o4E=Qwb-k =Ya'"Nu cZ SATc1mV%"iY8xL^pzD U Vb2U흢2淹wpQ繬:NQ騀 ahnO ;Wߦo=_dj Wob:jmyVtBj ~v_K YRF6SAaˣTٔOOMh ڈA%@q[U8gir'<>Wy_U}'Fq: K+bb,N沞H/{f#$]Y6^84M|w"'&7Fcb?HCFY86< ]KBIπe5bMG9UA2u\G, <`Gr 5ʐO gop(_VݹP \&ն;"56jWLmA% XP09832߃U,lSb*_,iQf VQWUQDrMcL0@-+,@jHfQ{yA4r,‡ni yn 8]A e1o=HVs<<<5Mf0P-24 #0)16nfVNyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyM3@PvPāA.;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{;3vgyٞ=f{G  ~?YeqmmmmmmmK^MvZmmmmmmkmpI$I$I$I$I$I$I$@a<aI$I$I$I$I$I$I  R0rrI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$ogWߧ$I$I$I$I$I$I$I$I$I$I$I$I$I$I$II$I$I$I$I[mmmȒI$I3mmmȒI$I$I$I$I$I$x"$!:O@$m:$I$I$E -v:V񶴭F @ I$I΄ ;DI$I$I?6mmmmmO}mmmmmmmmmmmmmmmmm]I$I$>mmmmmmmmmmދI$I$I$Il@I$I$Khmmmmmmmmmm_(I$I$I$I-դmmmmmmmmmmmmmm20$I$I$I9mmmmmmmmmmmmmmmȫA$I$I$unǢIL' T3Femmmmmfm۝S) XUR.N7Q"}$6+s&%YSDcHnm%8.%©'CƲwޡmVH=9?' RI$HI$J!BաnW_c t?2i޶fw!hS$I$$ f\"17imb!h ٹ!$s$I$GĒ$ٙ6kP>Es0%TȘFVS4;SW+>!$큼̒I$I $vm Rň$8KPTulND-O^7 52I$I$&AٽIs ੫8o{n%SHrr;Jʭ"v#Lm$I$)If}7? [m@o` urKJh*0{a $I$HI$!2/`gcyf˚VA,E{e';S'zxi12̒I$I$I$vj}C,RꝠFŭ۰֋&}QL\M${:2I$I$$A٩o:LQڡUp6%Up6#q8j2ߤ$I$)$If{?asŏ2#u=x͂_646+js$I$ I$PBF G"@Աjdi*<*TSm`A`Vk̒I$%I$vhI*yYwR nOɭNxn|AK72I$ $Aٶ-&9֘1]SoJ3{D*pFZ<$I!@$IfI$I$I'Z㣨4~ctAS l*e ,$I$X $mmmi0iCݲ[dXe}&3ـ /R̒I$1vmmmm+$U%[mmmmReQB&ÝG2I$II$Aٶmmm"~jM=mmmmZm D?<$II$IfmmmZ߄KZmmmmKH x:$I $I$mmmmX)lmmm}C t$ZR~̒I$$I$vmmmmmmmmmmm[mmmmo2I$>I$Aٶmmmmmmmmmmmmmmm$Hl$IfmmmmmmmmmmMmimms$I!2I$mmmmmmmmmm}>$I$I$I%̒DI$I$vmmmmmmmmmmm􀗃I$I$I$2I#I$I$Aٶmmmmmmmmmm$A$I$IfmmmmmmmmmmL $I$I$I$$q$I$I$+4٭;lH$gDI5mmmK}0I I$I$I$G̒EI$I$nI$aIAރ* 'm_2II$I$NaCH2ѱ'g-tմ1\$I$I$I$I|$|@$I$I;慶ZI F$,9NfjUy8K6L $I$I$I$}$I$I$ieJS[UJ($IL} I$I$I̒B`I$I$h% 8%"ȄGGIڼ2RIf-I$I$I 2II$Nh22)5QJ~dq{L 8\d$I$I$I$I;|$I$I;$I | B&抷PJ{HA$I$I$H$I$I$I$A,&q1ШHz\]潛}2I$I$I$I$̒MĒI$I$hD4h QN+L6E8fp7/ I$I$I F2II$I$N D(<'U3:C]<; g,%I$I$I$A|$~@$I$I;%I I4Za)<d2kVHI$I$I$ $$I$I$6$Ml t4Ͳm70b< }0$I$I$I̒C`I$I$j( tMY9SPO9  I$I$I A2I I$I$NϨM2mQF}oZII]I$I$I$I$J$I$I;mԄ[mh$i mXI$I$I$A$1I$I$mmmm+nKjVUI,l$+}"I$I$I$H ̒I$I$I$mmmmm [[mmL"h&Rm$I$I$I$A2I7 $I$NmmmmmmmmmmA$I$I$I$ZI$I$I;mmmmmmmmmmL I$I$$$I$I$mmmmmmmmmm}2I$I$I$I$̒GI$I$mmmmmmmmmmm$I$I$I$A2I $I$Nmmmmmmmmmm$I$I$ $$A$I$I;mmmmmmmmmmHHI$I$ $ I$I$mmmmmmmmmm}2I$I$I$H̒HI$I$mmmmmmmmmmm$$I$I A2I$I$I$Nmmmmmmmmmm$A$I$I$I$ $I$I;mmmmmmmmmmHH$I$I$ $i$I$I$mmmmmmmmmm}"I$I$H ̒GI$I$mTP/n|\"`[$m- A$I$I 2II$I$NdѣgdcH"I;zH$I$I$$4@$I$I;xb.Q`*^䣳:D&\$(H@$I$I$@$I$I$mʹQHnzg`M  ) }0I I$I$I ̒DI$I$mhcY- )N-$@$I$I I2I#I$I$NߞWiͶ~[ t@iȢǷ$ I$I$I|$I$I$I;w Y. ۫Iz&S{A }@FOm7$q$I$I$m"y#Km4qDŽYŷST@ }!mw̒LI$I$mv1\m$Z.)c lDI$I$$I$oQmmoHIަ&eŝhך:PaӶKE(I$I$K$I$Immm&rﶦVAR뢨faqBA&D( 6JkI$I$I$OI$I&I$I$m>&Bh}NQǍPHދ}7I$I$I$I6q0$I$I/mIF(VmV|XNܻ?mNm$I$oI$I$ɶwұ ׿HF/ A#WuI$I6$mmmFHpw?%Xd9OEpB%.A$is RI$I&$A I$I$mЇr mle% H "ޓ$;}I$I$̙1 I$I$Nmg m6I,i`o@]IIII$I$I72WI$I$I9"7BPڶmmmTC*5#I$I$I$ȢI$I$I$s!!mmmmTvdI$I$I$s$I$I$I$m'Bmmmm J}y $I$I$M̒I$I$I$Nm=/-mmmm$ EmHI$I$I$I72I$I$I$I9? 8qmmmmґ;e*m' I$I$I$$I$I$I$k@ޅmmmmmmmdI$I$I$s$I$I$I$mcULKmmmmmmm}wI$I$I$M̒I$I$I$NmaK-~UmmmmmmmH~@$I$I$I72I$I$I$I9Әwmmmmmmm'I$I$I$$I$I$I$m[mmmmmmmmdI$I$I$s$I$I$I$mnKmmmmmmmm}wے $I$I$M̒I$I$I$NmmmmmmmmmmmI $I$I$I72I$I$I$I9mmmmmmmmmm# $I$I$I$$I$I$I$mmmm۵.bmmXBmd~I$I$I$s$I$I$I$mr[$mo'lFmm!ymw>ǐI$I$I$MmmmmnKemmđ mma!r%m6mmmmI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$IQc)9$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I%mmImmmmmmmmmmmmmmmm,!1AQ a0@qP`p?2w]}?1uϤ _X;F_ƴis~b`n╠{2qrzIzZ/6q_ˀl ؑi-e-7|;~&ңx-/@Ph.$ 9pE __vh^xJPv2;{Qw_[5ut*< (7f̻wWbk,f;8p15U6\n)Bb<*b Sڶ' e|y??agm06nqĠ ^MY=' h,O fQbJ(˅92R8Um69a-GU}m <1bb5Prwxhc~R͊,68m}hJco1/k7䀦]"/ig_>U_ZNo"O2wdAҡZҴ|MԎ7EDGu#?zZ+7mGy~(F- mjɻBxq={ߙ03~gq={ߙ3~gq=_?3~gl<1osl-Ǜ\so.]ϻ0]xwfoX6meSxn oq2qbsvːZW׀[ 7!*2};CqN!PHG iyim5)*KW):mGy|+yObx{؞'<=Obx{؞w씴})d'<=#mCbx{؞'<=`N99zn~G[e_kʕ*TSbG&>(lv*DȖ7rB٦8bJ霈)h/A X@ħK\Sr.[-u"iRJ(LLz %DRPGR;χ|f8l=Ȗ 70Arsg)YPC; @}-9aU@ DuNʆIUZ/R_@PY5WӇT&?tRTR^ z蒎17awKH6 bWCc5yXRT ql3J%%%ǢzT5RkSGyWWs9TDDDDDK|P4[4 7o 8U\GBnӎ ">蓰"DM fLbD`2vn8a4Q C=w}r儹KFK|##Wz =hq-iLWA0/MhZ*T?A74&qLqe1xDUUZ%hRZ%kZ(ؔF$H"hR;΃ ,>7hCeTC1Zٛl9F[`OQ\r$H%/AALa"%iaؑ.;ahFq 8A1@ -^7e@-B*z.u#? D|3Bn>ȗrԻޠ a.`J-zopj8@F$áNaа#iI _9c6vҶ `IQ*7S 6J A @Ԣ6A,nsyOCZZJ@Ųڀ v*T*TuR;΃v9@0,.ʛ0LIJ4ĻE@!-*Jp%AĉRFAuE1QdXC +ۼ)|>bE:Ί6DD3Q[̼Sw- ݄,b{$U[N9^h2=ݠn ֪[ J*T1+ZҴUN;΃ |4&)ac)g)~˗,$ Ъk>i~#ID$THD^ѣL~JA G fݠ)閯g]61 IhZ 4#L^H|d1.*-]GhpFY{aRd2fo@8qD`TZ\[EA h[4&7>D 馅B813 1A"1&Ra:DTH"G9R ),D01H<@<%33>κm^bEA-++@hb*,7Z: J+t e*AIrV*WA s Miz ((`sٗo sG1 ".d&_X(h$H49J3 ᗎ3{)ZedtُB@*#UC9L!}fRg(zN۴4m/% ,tݼݕx%T/[Wu#? PpZhRbP6jlUv,υF^⭻[L(s&w"0 Y.2,7*L\UeTLoD&{7w%bgsaX{f+{V{/x5|o!+P }Q%$a*$a#+DltȔaF[m(͊ <{Krr/-[W("BzwA:^- I'w@92T+0K9ȖrDw#s1UI).wOpv_hMړH{vi!vi!vi!vi!vi!vN ʐdę}'0*4k9,P1B70ol*pqCxb @g@L˛~yt.\.^r1e jөAs;|SBnYs2*4?X}rPp!s po-cpwDKnyYTE(2qK.\r\.\X*e]H:TEB5}"SN +^ثZ."VqUrm JKe΄>qж\2˗.\/kQ4GMԎQ(\M Mj^[U[UVҼW:tBnt'IԎ6f  hMn:tD|7%JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJBkAf M77R;΃M~TЛV7R;΃궅)n|7,K%dY,K%dY,K%dY,K%dY,GkAS?4&7nA@~TЛRJ*TRJ%J*TRJz>O`)/_6>Oj@e$)o(P jTRJ*TRJ*TRJ+WnA(` ɻ(E_ kyhc.DhdY[Sy֊h~҃W\LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLJ'MԎA.MgW#r53Pv3RxoEW$g|bK 7fYXh\@97MԎ%X,|7|2 1 T7ی<{__bL Uby|x`ҵ$*eU |VG+H%'ԿՏ}_ :nwԑD|7|).qjRw {΁H[KWL?7ys6o'B3=>oOP#^~߯cyD / A7MԎS˓wˊT ],qx,*{&0DśFa-u+k.*Wi}( )qyvem l`~JϢݓ0gpX@3;>6a/z9j?tH:ߨx%pQXB^f'!j̊(V?T)=^2Z3@p}f^y%yDpvj۹-7GnP;| n~\o9oe? C~1@-nDb=" mKs_ϲs1@ 麑tR~\pZ "o薿v_b[;8AK?0Û8Gr-"Vo&8}TiZT=IӮYVq/pt!7rw>28~?gf3F Oۄ}??BT[q ?^}`dϱۜ'm ĹU `%W %Jiu#?~7˓weHlY.QzeW +lHR|f[(9}uڔoȖnzbs jy bܢsvJv/|6A[fRdz!MԎ%X,|7z6 P>ցmD8F9#0472D*C!Qf4nEk0]1rp`0plH\4 }z$Qlxό h"1,C#b)PWCNA$F.M4|-6`$^"9^]₲Z WB*x)^I$"P_ϯO}_ :nwlLX~\r˗.\rŔ.\r˗.h#kV>Q/?ƋԴ^SEJ+KI~O7R;΃M~\> ˖el[-el-iu#?~h[˓w.\~.\~CNAS?&7CNA@~\ :nwԣi6&7CNA/\ :nw,cɻMӦGy~I@˓w!MԎ+˓w!MԎi`&7CNA[Bݔط>\ :nwNr\ :nw\.09(7 77 a,5W2.bz63=5Q)+tτ*a%J9]q+Oɻl^ҁ + )zp3&cvL.Ɛ+Pv[' 6U~Oh91YZAd}f!#V2;\m\m( Ґ{(.5YCӾ7R;΃궅)n|7zo.LV f70*L9Svm-%S3qPS\P~S$'AQD1x2܈ɜyS9ξhh[B|ʋy HnY{:nwNr\=B̻f/K JDoIW#P(ϴAKb2 TR#8q!6?yq}pD۷ JQw[ʸfZP;Dp3%@ʺ#R.*TRJ*TRJ)e2LS)e2LT SGy~@/4&Kǻ- m*0ċd1e0ހaN'%UKl\ Aq+1Ѹj4yam,w3`)37MԎ-]*9%gd {' TQ f㣠8o_/ۡ1bz]n\r˗.\r˗.\r˗.tH:ޥ&D/'5ry#m|ɻwBB"+9p"K1k2z.2x)futvZ '=H:ޢs\o-Ŕ~g7zP+xGx Ck N,T7@fYu q"WNmc4}.ڒ̋;#?zqw?jGL3y<w9N;O'FJeWC#62m=ӏ IQW[-6\ck#ry$~S2\'*3餧3.i,2~E3nFM*.MFM9UMr;-joTj DwRʹfa7*nBSΦPƹK$;hg>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>Ǖ>vD:>D:>~7voﱃ <=a>]X=g\}H5 {0'j<67kpa_})}̿aW}g'{8ϰxq?.zTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTE*}"}"G>ǑȿO_/-GOODz!5! y~/#b)nK)})=>Wd((((((kl(((((+-ė7/iJ(Bz%ƛ4ݣjcz$p7NS$K E54;I71&\Xh`8ƵNR>84ȨbXWu vj'`OwEEM SRȋ2m[CEFp>fav=>wB!B!B!B!B B!B!++++++++++++++++++++++++!B!B!B!B!B!B>oM&+zMg7e*Ҕ(=':O֗F_7?n~`DՂr:?:o::::/GCGOGGGGGCE~\////// 7m &BOO//Bw #_&v!?v8!{$8"6%H)7o9q<'RH\I# 5xh! 0h&$it xt5Oz_LݬIom|zlDD! "i R)l " XȘH,H]ȉ dG01"rtz<bP c[)QzNI.;'>E:/:/}t_cEC>I:O}}}p}D :c%}p}}:(裦:#}ؒ~) cO!P]>gDv32kqc)p:c$ɓjxݽ)ZWE85m綸_7-[&Hä7^:ؕm"#ΗW_V+JRBAhlhE`Л &5(xm Lͭ̓EQt=gx_@af3:_NK۶hS2dVA"CqZRDx=ؓyŹ>_/ݏ)| )ٶtCVM~""""%mk )4$ipsilŨM1nBc Z1f\Fv2bb1#EFQ8 "F64ƙF )JbBPmobRDD"**$6JdeDDæ31~X 7/d!E;VoLLT&5 = 5LVQQ:&Srz]Fo2#BӳX3LkJR)}@nBC4x 1"G~>Y&OfZbBQ6R3Bhノ(bbbbe A2 4AxzۈPFpݑaт)J_FC-6gѝHh5G2N2]HohghblOf[kAr5EL l*o,Hj+SH멻-MlAd1uaQO=NquCyƆ#$QH/g^bQ )FRZ?1dBD AkB~3Ȯ_GWƆB!:u|DВ6n1n%xC 2c=mBbe(2@18⎒"S=Ts.ulcaH\MȈf!AqfߘۀVڭABҕ 1"i5HD!43 xNGƉ $aQ3sg AЄ&&& 7&p(9"&r81GP¢1+ҢtFCD$O" Ck05q=dd\ 'bBZNCeoa7vBNKƟ3 j'o{4z]|HMP AQБb/APQD C 0BD+dw( \9yi'0%PSmeacێRom\f-W7E\k 9vr{W5&uD܋k;6jmꍫW>t7ڴ.N..\Ȝ ZDzOݍ?!4ք."dfQl OUSƛID`:dҍ*ŭz 0ܭfŔ$M]F`n /6{ H1n 9v,7{t?BaCY%QMW$w ­bOcw\ur#7lT""mՍxݜޚ[1fsoc6j7$nްWf3\g\A1٣׎ZDOA$#m!Lf JfXS)JR)ьi% )iea0etؿ_~/ 7GiOnEns;5`ڌIJq*,L q0pYbzA1MP%zF`h5׸z|rk٣3'2em,w\3hRZ8æ%r[Cl5ฌ"+C  Œ~MMP!MD\4J4]Tr'* (F%IdJ,##Kq ě2Cc%ee+VCcDEҔ)D_\!43é׿G.K% qeȚGGޯ3:h裢:h#:#N:"%?l|߇~&fLz|Hč4_7? Wlf[~3NU!-}.)Q˝|߇zhblf^(((((((((YOW"}.z|ǩ8 UkoV*}{$9xOxO8A/=&Bw) _{ywDeYeYeYeYeYeX~3KQ8ޣz=V=%_(ҵz%.{[1_' "R(ca2hT66q V\#(-d!OE)JR)JRcuR n:FJzM7 7n`fB0"~"F2N;{ $aS:[t(0Lb%LOv3UQ RAA)JR>O~=JȘ3Gmhġ(Jy.RGe1;w#[rhA`@= sV,8/z2M! lJ)(EQ`<1SV?'gz|z$bFWmp^P"tcI=Ÿg"l!Oa9', 3o!O\[ÊT4Z9dWZݵzޠ ES()wz|ǩO~=LM6Jz߮0,r\ 'Kbkj(o%Ë4wGJACLd$5i#BFm?CC]W?T5ϊ=:q?a'kbOdMȥЗ cb/qq=/߳>O~=UȮ_Jz(襢&!!lZ``"CT$(7[[eED"X83qBڂFE14\~P{Epq6{Nl|e]$Ba*7F`h_'6Ya?O<'8}+7yѺ!z/`] 7!̑+r 4d{I"Z3f-cLX7rv"3M9~Pۂ6dŸ{6 DIs)-|QY ϰO?B9uG &36f:yDM;~?O%oQҽbj!l/Dzh2N0 α'!(V VdY n^K,̾˟d]Cك'z|ǩ7#oz=n&u]xsr ́&!^y%w:@t70"8'XbtECI?8bf4o,1Oq7_C fܮ_It{ Yӱ,>dW() C4?O+"`vdҽZY=3'!F^& X (HIbyݔEn1 # mӁ([&͈Jլѣ{j0 kEq\ļE f'?KtQZ0O./Q+0ĦǍrC{ "R~ata5 [Pp];&F,vјllcCT~!?g٧z|ǩgGu ٧z|ǩ-Dz6i~3AH^f'?dL̙W8٧z|ǩ"F$mz?|zO~=UȮ_J4?O<'8}+l=>gԖqFJ4?O mGißҹJ4nξ [3f5r'j>A)^t؏Jt p#di#{7f GngOBii2Mh٧z|ǩY&~MVB<s#,@P'JnEI0)#?9:10Rrf&:ܷK{ۥ\آiTwO)`DuVKtcd^Tk }|z$bFW:ӟt2d)J"'}Ǥ/b*JC؂1<#BV1.X/Fu W`-`pd3"a58N!QFͣ5'+-b[~poVg٧z|ǩS,n$$M6|z\IVu7GD{#كY[ʃ+bTM6`{qɵ9?=C|B+0i{ABay$ۋ-d3kwR×ClDe1-+ kP$m!򛓙J* g)JR)JRl?O<'8}+D M xm$G߀DA7[_d8N'JB%-,6+),9&Q' "s1HbgaDKfS(Mߡun A)hh237?7WQ\"Y2Ӥ݈c#[\4.] velkKq(l 76_ 9<_3x|3k(Z;71(JPRAoЃiwrfQ*VF=T)JR)JR)JR)JR|߇}c_HYtqcqU:zb(zl.uRSm qll!̢l=f''yl}EJ-`e)D—ljko#xM|Y;$MF?iO)JR)JR)JR.Vx {V1-D*H,E`E@Bc#,9v ?= ܄ٖ O-n`jM3=(2#~F%Xe U*U7`}7z[H|E7%d$[~إ =>_K>XA$}IiS75^LM"'ǣrf ícR,&AfPc̼r$0Q [O: KM+eHor ͣz?7!2B'`1l3I +H 0\sM#D~iC}lTBO\ 2 E=Sݎ6E芐 EmP=i"\NXeK?7?!ߑ{ $^omӀ*ps5X ѥvFಿѾgՊ20Fp/ZD!4!BJ1ߣD2!BFFFFFFFFFFFFFF/=>gTխYTIb$ۋ;M&.LfMOL#8u8 ?tM)FR( rjEfmOVNYDFjԆ9owhp҃%3uŸ*\吲x{J$"eƛ,ՕK$ߟRJhd'mov= ?`l$e%- GĄlR2[$5W>?}ݫ(QOiHZջ'Wa_;FgwG/2~-沲QkvghL&p$.U~F6Rd ɤ s_ՐDJaoz|oY5 VT# ,~~>K VdBv_}vmڽ٥ߟ-V`__3eG"yq]+Á'o)v{.{| o1ػ$N\T6A1TrܲJ 0؃~^Q?OeYe5>& d6,`Wg ,7J;eec3@&P@ lNrCfˏӃ7j̈??EEEEEEEEEEEEEEEEEEEEEEEEEEEE_[0 { /6~? ݈'ʖc}bjOt_,C^[o=Ow2̭JSLDf⢢=>_I|߇hzF1|߇keܟdL/ed&?,!1AQaq@ 0P`p?aG7b Wx+ʁ_OgN:tӧN:tӧN:tӧN:tӧN:tӧN:tӧN:ujts </ 耵sU 7ԛf+ @6&D?t*g,>K7ġ6&Ñtͤxt鼙( *Uq*;Fg,#>)B e"6pulvlT!B=i^<:Kn8&).Ρ.}50\%6-Qfu ഹ0vE6ˢr@Ԁc9r > >©@WTH uTwpE@JrK{pEA ȡǛv؀; 8 `&7.f兡@nwB,hk$B"jRrP/;)g)/_/ >EI__/F[e )Bn`)**QSQO-.V8Rfw/k%.j0a\<llBG *-xK>T2>xB4 bj)ݔ@6FpLQbZdq3q`*-9j7Z?0\4 X Z @~Ậ՟,,,,,,,,,,,,,-ۉN+%>IEQv [C~|Ĥy Gh{ĶͲѳF9ϜbHP z%E}/s)ж /qt-e)UPsfc7 T墥tAƒao[Ytm9čAڎG^ _)T8tl2UhT*>`)~]f_RR&fT\2V([ZϑFfTGE+sSK 3$[T5NϘ{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{O{B,IE@ OF4hѣF4hѣF4hѣ"Svñ0000000000000005ƛ,*F4hѣF4hѣF4ixU[Ё%===============================================θD& pjܽx`eC֥54^ԋC@bw~r䎄iJ´UҌAZ8,<7J0P*4Yu 8z.uS)7% n7aMYISm ~V UKE[hF ` @pF KN|!`gy}:k : ,<$ȉVYۡB@ r#[* ` M2r gc0 ~c&R7.C"ç.4#)bX`t.KkWuv!KXS.$+%sX:HL5>j lzvH兴A^ HFs6=2ΊXoybBL %d5j H%y.#|̺ $$*TǑ0ډPiRRĊS> znp:(3SB mlqZ" dp:%`RяMuH[=0 P0.CYJv註4csL' Xmi+ɸ*gj%+:, l1`i[a-.!(LWUp-YZA͘ȖG!FQ J-SmRyTPq "4iTq44(S/ Ո*|!L 3 h: ,c]jF %ɲ!Z=`^gq#2Uق234]*pݴ5uG!K@5'\4/&r8h"Lāw'`DA^,uBT~;y$It0a 4b룸^Ҭ Ge {l[Yp0p,N%[Pb,gQ %\V@71, ‹Cdpz͗4`nR*gMaaP,1ǫ90&#f[M용@#@K6 /s-Ô94䍌ng-怜LIoQW? 35U 6XfSa@3*FV *W9BVmh;bk}վecB:tӧN:tӧN:p56@SN:tӧN:tQ>ѣF4hѣF4hѣF4h\W'NaSme:tӧN:rEhj 4hѣF4hѣF4hѣTq,=ɴ42X Si\)& 5T栍] cZ$/#c2YTT@) {"/i5;nSxAJtV 0SE4BA|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{|{0N@ehZCq(l|?DQ 8 5ThewaJUd4(&֋tl(IC؆MHʔg50,SI5JM#  vfpW3PLZ$Uҭ`2j\[lEW @ 'K\؜8I&+QFkQ(~kc@+UwJ}8(۸I@.ߣB5npZptR2AsuP|yK""Ѣf9πm6կ/:'WbB.E&(=_l,ŖP[Tt1GD/@mulgտ5Y%dA=)iP@Q´l(Sz А2 EOu@`(9GyDO @ @ @Dn>~T8N&L2dɓ&L2dɓ&L2dɓ&L2dɓ&[0|Zf2w_Ep!ÚJ7DwUE/Bf+_xg<BMӎo1~CBaS?XOZW䆀ShT_±46f,[nY - $h^6]m_ %_|[%@1=3Gfa9<figx=v {,;"JXt`s̫#x;NUa?p܀p B[V &W7CkM*1 ^$&t67 \As2S6(6OQYp%ZUd5ε@^2#@χX%*ԹX"iQkCVIXث7A{n[aUpe2Gos?5,3z@82JX"I6#dex5Puf* FCU  ^ ]Tc&BB q9EF$I"zDAv]g>L&KTCz뮺뮺뮰ݪ 5]RګuE*p/,]뮯 &İjմ9Bn1+G뮺뮭P l!+0Q^%RO d&"M➓=\neX{%`) ED&xͲ~Cqw+DyJU)K/3 Fm/+0M%@%4fqj4k1PXuvuE3sZy8{6$n0(g8!r(2* Z+gtx֙y`פ ^o=U PNgVM:U,/k2vp9Ja5\ey٢J ZunP)s0JdPD {B↬`bECڮ}<4ER@P:GV(8F-BE21"N: Ry~jmީ^}MĔS`yT'Kj8/x@_-i;O9 r'=Pノbj`EKiO3|ױeRq尡dVraPd`%QrV#(>rb * .**@%UNZ HC*_H1 />KPQV<ɋ7 "3>2_P(z@%F(.qBe}*!k*0v0%cLƪܲ)4,E*Q(2L$(0)X*#]<DEdGN3Ph%A('.)Ye7UfYA P7q;U) -#N 5pXP'FZ قZ aS̎;yB2}:N6Q|"W4\(ƖJNX ;bOZ9ER0gEfJ%L7=fE2G`묶ť:,oB0&4|Lbc uckxqNݣ豠%0_ 1ffj 3*3Ѐ021 5Yh e+PkpB,oH@+3*nsJׂ)rYۻ4Ֆ4]X]ͅaR z[G?jJzÅW;@ '%bceJ60 嚪<"% o.S DUͺLs2åVRO tqb[!B]Ne]9zĖ4D²EUV#7ۧ|-Z("g1A1kq`xe 'C]:fj6j<2 <"m$Y[l)Zɾ- 5xDt6z?%C9> ⏕]`QeS#Q`똎+⣦ҝ^uJvp¿5.8YV@3jy wwX nK'2+/=ᥩk/[37 rg5[pߴu~9(x>Kҟytf~QZa jy@4)qZd%;pf/Uep0L.7ՠ3;91{g;LYLb\."G 뛛sdZ_D&2|[@зj#φ>[UGI M_D;a幹C#XY-}z8#!*:N4R;֎~#r*%U`/xP,(o&UwCV1H^LAcQ0CF TxXCŽ.TX QV}SA+^ݪ$VMA6yZct19JvWӴoR_HGteߤBSP7/$`X@# VtY_n#/RK+z ԸuNx #Ɠ_T Mavk_ +7Fu7P C qq̷]p @BWixR-AvX[.([fB EϟRԘ*8wmF ZQ={ /:f z[*׏ [mEБk,3E0)' )1:{ Fڏ9k RF(pGs+m|#:G*pqތ:WJH^eީ@uGl*Lg7UaBSMaih%wQ-hctbi+#z Vc m.ǂJK' =Nrn-ģ]j(Wap1$8^ՈzM8u(b+YTJr|&^N ̣(TJ YU[ŗYQȆqsg^aZ|&"4,Onhߴ ¶Pk[+=rn{KQ0 ^8As_Xr&އx"!*ۢ"㩖\h -pQb¢P>P8 ܾ`[G k8+E*٨ F=NOyJۮ=%U꒘rvr^%"!E;F@<~SKM`8lh@Ȧ"ZAb@\ A{{(.Q#Qʩ7Wo1+a73zDJnJƨk;SJtðY\TV*\.~D-W`VwGa>h5GI 1$5ekqIѸ2QV %堞lP#"R0GߥHd1 *}BC0Z2"ZVLY[xAlDܗs36fV;̲7;Пp_3U 61X##UpU'EZUxW%>ıΦh[8X3Gɵ: J\5+i`(;fZf„kW ׿i@6:%kq 0*="+s!|T`%YAÇ*:l0ň^}gDpK֢ R,k0,4BUO,HijUgٙw+KRML9?øqOc^o0ڭt4 }mzaMJ8GB e, ^ je! `+>08UƋ?]E DHr*`w[+ucTae̠@D JVZ`0㕰ᙷwoh!xW0BuT:$ЭC9B _Z{IW<;m,8fPN\Moy*G>YbE3P%f6-LnhTK׈BqEW!Xr+U5Ι2VNjVh+XgȪ4'R@$1g]1j{Fj%blVB sPLW&~#1&%SqY 3q\~bk?^|Ay #%vrU5s6'PQE߾Au]1L)9_?,s>1@J+%,^b TZ[ ޸Γn6 )67ё* q5jxGWrd[̨Jsm`,0tmj 9 a~L[0F}H%mt ,!F@F-*%*3yCLdd?i\\;VbW Y XYG3n lW 8q7x5%zB%WX> 3QJs*SAֳA-49-bvSN H_eRZ JŴ/"Bf*Rqayee#JywiF'f>twGnEkSHA(=e-)a rM\σUۋ"br]!\n`$@)BR*%۸K֚ʀU@.VE/uɌ]X)jgiṆIPxEҤ}қ<Ԍw ?y܂}̾!6/)Dz8(J^B~!FUec5ؕ/8D1lh_?~%%BfQs$.xc$n9"*Y7(a& B9ϴ * jYTQ]H,7uٚVzāl($h[gE_ʵg< 2T~r0J:_H4 N\^:ٖ:TgF\dFw٘VV ׍:>X([\`]M]qV8?f&n+B=.-8/B\ .#Tְ;Ut, tĵFl"G 3! UfںQ7ᱠU1D%^ةA ol\qtt9ʥ=e:>me͸g~wgzVoiK;[\ᗹ)~[TČ@`R ~gIImzL7Q2aMeʶ֋[Rg%YyBÞGI{-3 t[=4Zì|33Y+ZQ 4f.eL UP@#Ҫ -,VQ٩r(WF2@kx5d@3_BTsrH*sv S+ dI:V'}E^. c 'gwLJ=["F$_b?#=-/BBG]ܥ(}w`|` 0tQ<a0 =c-Eȇ99N+em9NSN [!:X0RYr৿;c W~; /SLL1qpX@ o1jpЪ %CWDq3_r8SX5RۤLxBm#:.Lp&57M1(,sj&GJ _yC;MvBWz= zbG(KX+09)i2ܯ|w@+K-=O7E`uzL.@YR tPjօb#g`ב@Џ+B/V~X~+S@NLZK BRjM:tZTEc?p/Hf.8H! 0x)ታP|DX*Pᨈ H8@ڂ|U:%ДiYp ATYi"wqa9ݭo:?|"i_ʊ~= ǖa^ w!lz M_'*YPh1 C=e̦2i8> Q\ )gުgh4ĴK O% 28XyGg0MĮ;ʑP2 CN9ySz _iZSJx5눤:3*oak U&Mc*2gSqQˇʈk0W:,N8zÉK  ®ޤ???yվ^`Y~[ݱN R,w\>Vɩx0iw +#j*lKJQ`2J`)']B'V Q*u}%`PR}`b0-='H}o56.Rs^rp97+ʪBuG V+PTI|v.鴦̷fԯyQ8 :4:豕ݽsIYAlHc#+97f]$6/ndoN/E l-Z~czZC_?0`@SVRkm2LLdhBf2+$jµdkh #]FT]9 amh-za, P -CMb yDLIbȅ6 Nm-5\[)'R5| a$GTJJ7)/4hw(G-e):ۤ]8`0⓿:}cU5rhH6 0fk:;n1R^McdI(嘆W0US+< ֥&k` A),w*hq6p2(V(,8D[[@8)2OlTa 3) l`Dl"X\LYD g AH}^}` =.Nbtnö*H' ,pV|& U4Xe*HY)0*i5G[PC'tQCrmšp;ίD!e lL,* ;:algs)J?] nAx !<"K8!9!V TaѺa6&܃h'17qD](nlt1Xh)axPnhڋXG ޒp0omUsS|i@4U.XTjWз c7")hƭ+șD -_YaRWc]!MLArtۤ^ K 2\"2嬘ɼ)#>p X-~dƵs+ǿ>sC(RRJ1H+؈7Ky[_Voqwz(L=E^a͏2 LZڞ"@ګ~b|gDU%Nix>!A%)>ۦSB9!otQs<%n?DeeW/ƭ񄄯0l,MʼcǴD(i[~1 ^5]ՠQ`WnJD`Cl[gK2+u12-CB6MYQ ~㾽Hprd} *QLl9Dp2Ƌ]gf|D@7ϜHN6Ux[ J-h?0kG),fܔ=vcXfD*-('n/6eʠ_eUU2ZB*X k5e 1W0䂉ri/XnÑ1 UCq.`)3%C;X6 Z-32qY,?^1€T:(:&r$f@ gJˏ8"1p\c^|^`DS(7h`;U㣍 Sٜo+ !mD!A(7]K[j[pbXf,D_#sUA|QUy tBE{-*R@hN<EVGDbH%5BXI@zYuzBM%eK"3e8]֤'~o׼n'^̕Ҁ)Y[Z*jEP7-tVPP){_e-KL7Z+$!&>DL6?po십PĻzʊ0treW̿-9nw[.s1=r xA& N-YVȣM$rp@-f[w\|< B:-J-BI9Phe+ƶTm]AZ.lV.rd =b-lR# r Fhp ɞ=k'TŒ46ŜlE`% Ur[4w@ X} hߖki;\.F厁F4nIBtYu9HϾk5XIZ-hX*XkJؼT(B"0dcog^|Ob"qHO)`@< x]pDPĊo бb (qim3$PoG7M2f2 0]=@)mW5hD~ "F|V2m 3Nn-,22'Wh(((- /G5eW]*(j5מ_CEQEQEQEQ-inc"MZYYVIc[ ViOaKE>TQ.u/n8$ rˤ7u0mFȁS lp\ Vǔ2 w,}}<_5 ٤2<ԬP ( L`.Ք q i\)&ɞDv!BVLDHhBN Zy"'Ԓ!y(ja`XjKF"G @  |B0ciP!D\"C &\Vn3E0A8GwӐ9JYq#5a/VjxYe3z#JZT3Tp .ރDt$%g!fЫ[Ex` f)mpX{PTP $-%f#/_RWk}(gZذz%=Iݏv?cݏv?cݏv?cݏv?c݉@ L&ؘ2xkkz2%/ًzMCZ`XOMUaw rl|4f .M!~YHx?" 0, HHV%@Kd @،#] ~-0IFK¶K,sfiB:l_I,Ix%Mue@*DpZ|ɓ5RTJsX4֤:{mn/j"{dXnJPR}jLJ&]%~((ܞҞ at]h|Qk^  ~RyS(T R Ƶ;4o+"u\FeV@6oc[U=bAEbz&ڦfќMUe5ciӧN:tӧN:tӧN:tTܸ=|>oYƫ^^N`iA PW7!m1±m Z ^ 6͞"J 4!\ZZpjhL6F4ɊYF>iJ%b{+O^+X;BB]jaW%%\Dl~Ͷ`0˥+}Q1ApenL!GD!?7H2ĮS KEĠ\h7cb$ݨ+#" ph ZE"`Ej jtra# YmۈbR8,+_K>$t,fKKKKKK/_Ux|Ra)`;|ggggggggggggggggb(YE c Z?H@^*u>}-@ wh[Zb7U('pVi'`™vܥ{`t7cS|"nAdӷX=Xx]DԸ&_>QP(<]6'l=NEkwѨ;Eܮ L  @l@:SHXtX53rZ,\p xMǜ~`0[z0l1>1Ǐ>1>1|kOㆼr-)@‘6@.C> d]l$'b +>+}ܮ8ta1eQKjG#fYE0;=RjկܙzRC #*\3 RPݏoC/4D:T]YO]|n+ A9;1BCDp%8kQ:B";m0?9?9+uzw}Z=ti* .-Ge4],Y{*חhx2Ec kY唂Ϗ}<|\w~yl"UAe-* 99flMIG yY4[t.b \DO![`YR7/.)ϓ+[ҒGAsT덹iYPJLxw{LefY& ŏ-l(YYE>TQ.u @Wa2@ʁ“37DÙ\X"`n7{j˦+хnuen 8mVf X#s Its ǻ80+ A`^S~R(qsfLg >)|lRAp´BS@/ ܹ5eFtڮ8X5N{ # ( bĬ̾{TvxZ ̓"6[Fb?&ʠ;ZĹ3't0Z`izׇD@=@J#lh}!8|>p*yg B,#T$Mp6TRtkjp?5 %=Y_-(F;ݏoTd#i4,\pJƙ8ಠueZK>+yЎ]H5aaTs!!y=gqƛ83)_AI[Y5Ř>CFC5 40q M.׎VE !aeKMRܽ`;>qA&KeLKaDxh5 Mfʩrۈu_KPQ_o2;.e˴^LKzcgW34`(o/p)rb!ZaS%|o0p8)_$ʈK>1Up@k*D<=@,9W(kiP-$u b-F =6)C;q>+a/,߬*L?WO$Hޝ@NT͞g*ASzw9x>TمJQuR!V,7UE/~O3W8`Ѭv ( R]E(iEBc7` f)mpX{PTQ*c!Ic n! ."Ym@#$:1oO#"E!VcX -4 : T7ct]#tpGT)U[Bm\Ez1,(zFyt&nƸ.;M,X>gW'ߧ z4]1\t&\EϤIB H_g$HKHA (pxCn5- @M̆^/rs+˼ov.b/ JL-j)-kMw7HmqG+@_u~\>SzU>`B۟'eu]z=ѯBk(t5yX6X²}2QrCq1tR2ATk/t /OPpw[WQD=CwdN ڽ7njuJD*ԲʣtEF1^6W|a>duF̔c~" =0xO2sAP˅ ߌAm5 "~^Ng*ǫPk0I;D?Pxq <VW3!)>QVlLFA8폒"= 4hU9<3?w[vWۛ ɎJƽz|ȩiI:dDO^Q?p t!׏}t7_i 5t@STɣ|$ ʚ"5Օ:C>媛EpsYI&KHXeJEM7af nӠ1Z5PC$A$lõK8N-]23pC=s)a0KXjւ0i?QuqSC]=Bݳd)RpѷwE݂E#X] }1!'0U YRĺSWN3;P,= ݆0L!|h*5^BWV])3\NBeUuMA-,1B3o0v(lUG/J:UoIiu3m5WhodFzWjP}~xx:ʃqJw,M/UaE/α;^vYȣ1VN9/4Z՞`c:؎1yQ=E^`Rҏ@eOS .IH^@N; LP v"I(m~fgPJ{ 76:P &u6:N`66u=!_^jҲ2c&)eN+c>|S|*B*|V-N)H*bx)&m)6b:0MUSw }$¨ j/ 'OyҎr酩}Z5+dn3[S|FqA|WBSh[8q-nֻ|8PC\4,N3忑2Al0 J>D\>ߢu%.5JaU`<6}yB-Qsek\GdWP{C(hu--{5zhK8E^;-ڭ8DD}h1^oJ+# vb&aOG srcr`:5\Ns%41nJi[1,H5ñB1=JY8&8uɍRaLBRB;&8SuIFo.-YTӲ㪉Ю6J7R&.lܛB7E@F9(ݲHbvR"3ѕ̠n P,|iP!_f^eaF:J!% +JO}'wvA@zkG:"4p#]xW[QǺ=<{ ;v/s op.N^]ЄAmZhCn&>~gfwȌ׮"vh)Ng:qC>va=ZA.ğy(`~-wz8fJ{MҹZ0y)BeW,_R*\ A"{ VĜ#PmT *,cFEOCm$,ajg:}<>0LcHZ!9e $&._XЫwB0M`{P#%"PL;QE nOu 4 LU.~"?VkP:F 8e|[yrL]11JqT7c#Sh2 ewVH>V ܡƿu5ak 78x]KhQ q70˝qDSÂߕ ս*p(Y)jJB9HcZ48BKm]'X@)YPoH+x%1e%>idbH橍f 2=bV P4[ʵ,Zf? "c#וTTӈή1NA-Oq#Gj78 ?n{=?])ނ?rs7gؖ}Kko)0@m!n;K|Zw?R1t'4l A}8n'rPEQPQ!.bNX2./7H Fģydݫ3r^e]y RΊd8ZVu:ZVx(ɰ+;X0@4^( V9B46b(ޙ^``xea~)AQ/lNLWBa2ҷ]pdل4A =dMƙb*F 8*IOTFN!DYV4,weB4&xrk8}fWQy0 EC#v!h@&Z|<ʴ\?K, U w+Bh)#aY] *dA 4,b8zBU SU&2_+J{QV:]^Ud38o¹N_ mtO4O4s–-0TB(Hmj#!iS)>2}n 姮^Y-/---//-[r|S>;yCVXQ@ёD!kxŬCŋYIȎC.lC&BXj`1jbH*}QP)q c2‘G"h;Ⱦ~;մj[V%:!)iVJuu A3Lչ㓱ڪD= ݀c΋a,7Cn} أ dji{j06u(EgtHM2\$l`)B  &%Kځm"pҎZ`xwW8+Q#8U0QʻLY %L*)R U+2RQ&=r21UPV`,AdXECq.]&J6b)(g&s0BH  hߒ7HΈ0Z*b }-hADlx,VqMFQ7ʩtPE!Zc\Xa*E˗--\=eeeeeeeeeeeeefzz}<*,N4pcZ58 ,b5!6Ye6K݈7r#pTk镡|@ k@b؀kTډ02l|f #uEU }`7weg!fЫ[Ex` f)m%Mue@*K/jlPqd n;]M ouv±"DjTV8ּfq%eR 6;8UR-x%\C4ƾB msA+`v9 KF!(zR< Bm(8$AvfV .ۂB՚RR" rd7mqpP70, EfpU[ݬ(`2@U25 B tf!],[4*UT@ieЂaƘ.ܹIYTͮ+.dJ2>%9+-(`2x׳84`Q*7Vk\&E|8ȬlV@VPE|8ȬZlBԧbx*X9)*i+ŕ51gOPA@% (. [lJ ;@5z5ŃJe4Ŏ\T\1JL(8,'aՎx;@My|~oR Ц[Ֆ0-xtFSH4R`V@0zXTDu=轉RHkBI\_J] ؉p0<^p@G`UtNZkvS*9Q nUba@\Z/\ms/[^1oOѬѬv 9 " ;1(L!E  AUY34'VPr$<ֆ6\*Q}semHii`SAmB-@ /B q ӣ{eBm?{h hV$64*KMд34,T3h u[l8]=U9!FagNj C3<FE(ᄡYWLi#Pgj $ MQqJm!<0%AFD|O<婣ߜd4L,P#J*a1h 8sRb8ESf@L`R\";`~ NbHTB(x@uhU\H4+߰T"/YlQB.ϥh v@"<7Q!h5'nhOR2 ?u%PM- elz @(Aȸљ^fpY CUз{ejj N3A ?Vh`X r…_S"k`S> zfbX |(nM}sUc^zUTG W DZi*R:yKzQfzRYXszGp<ԻKg)^dTF& ~#JWOqxÁ0*fLGBy!Z tA(IWF) _ )` # Z ̓XWG*Phhv#mgqFNRƑdԠU2t_@-)b>IQ%“.(PjcB Gxӯ܍ 1|AjKӯ}r¯D Kq4zFD:(&y*( Q}o a Nfw Z]&`"2#+⒧QRmDt-fy@>jP)Bnյ# wCL5hTe訮 S:hh%9wdšd@x&*CP [UZ?<"lY@scaFi:IDo5݇'RC='-`ru7/K-]y&i٦+Kt@ n]`W8;rɀӠ3y_i_Xmw(r礢%Jĵa= Bә{hw[ W("k_(y^i %rN [Ⲿ6PڼI *aNYX aH5, D&אU+b*ON\L# ON\ آU6aV,"Z nwS(f|b{LJ&!ιXJ[FREяhЅM%wURe ?#({tmBs+}ey/C9Nr]4`+R!GV]LJ1-s;LRǁUwRW{[ `+@ܿh\NYNHO=~oXJxK z6ɬT7:F(hiP{AR`$}0ژ,Hu6&r{뵭(&?]IC@bBYr Q!ILMVT~tZJc$u=DR=yu+ Ba\P[?/6S B[(B iRa3'ǿz6~I/'5PO5S&UnM򷓬aH)k?}pѦ(yBb r)LSU~2iZABb0ZM& TCq=xCJhtיCXl}MB-P R hS+wjumZՉNJrU ]]CPL(nxq6EhFfLH 2 81g]1= X-e{oǩkOu)Ff@ 9_hЗ\CvB F\HAJ~f3-5ۙL}=H5kV^!H!3^lVĤUerjn0JSǕ帮s]G=VbF5sF71%g7ī*A؝N~2]F Xn Aj%qlsľrSD NUG481-0fr'yPnATFҬà ?2mPPJ^MoUSR&s40|1Ts8<1o8n*YI?xGH T+xOeK]$5aB)m(v W*d9'XF윌}"7G%1^_}s&Fl`"!>)xo<1&C[ԧ?.:ɱћ?$H=KFu \ҐM*CK%m*L9Ca1CBQm]HR.%TJsp]U~3 $2-PݏM;QЉTj(Y7V@,8rϤ<^/4l+zK$_?;xFU?Ff _^%4P2su#g!<|ܛ \>Kŏ/i阾0mԴ %QMjItN.2[klj4mn &E-/eŘ9\s̒oǑAdKm4t?+"&׿[ud 9;C,\5 rsjf+sTY+g'U /ĊԠ1܈h. 򆞧ES&N؝񤀭۫ܣTPo[c,%T+|%*tb}4= QD9)/}sB[C4U,L|9`*V ښ ǓBoI%;2V!!f@鱸@7TĺtCB@Smib+J"Yl S8bc(5ՄP"#j%?^xΚpJSmuQ)Ȉ"%ˋC⋝epܔf-7c|]^)Ck/'1o>rƸW17D$+"r(`Qx9֢\7Ĥ ;$b<w=F#b)8B%SSg [.՗fd%rۻ:W2c,1&$eIU(:h溠83|L]mA$6EY<3TP۫ԢPc4 d^ 9q'ܼPͬ K/($"[U %zE$FE#@F\P_}<|_zh t` mqv۷nݻv۷QZy=} @ Ԣ<F/6vb>g9U eu1&H j4xO$C~SDQ 6<G,$HZ",3r.(dKՆWxe)ŀs$_F+:&)DaZbc9L&IBޗHhuonaXQPDع2]B{EYaU]e$+CQ3y7 ^Вt"TG p0D cEMrTyIZyz( 1pBxHXtj!'{uZl)c:YcP0U IeCbлBde_G$H]@7p/3VeKk^KDYзULQȧ-ݜV!; q7 zX:?x On=נ磯##yu/#͈ÏD0Iz =#CB4:?L |gWArBC ͞?7H4b8-Kb]ξPhD1l(Xɵ\錇AA\q]`㋺$R(  ՗EC^JPrm6R;[Kr^9fؗ6v񉘘za=#`P>-.(}vw lv܇/3Yx?u*&؎ \15~~@=ʈSU28\'QY8d2X>[wvu(.CAsRŚ&.\qH+,Rg CAA(j\Ib;BK:U Py\ òxe.؅s9AD3oJg u \Gyx(l:Kӗ_}g d8y~b)hyk\3q%]\^U2άMAL+#(ox>yAxE"4Defk~Uy~RJ*TRJ^L2dɓ&L2dɫ*4tWf?o )4-O 12BX(QRZXi%OE7P0OUpt_xϕ#jj˳@^){KX53UG#U6)JJPs)blc9dZW^|miuAwFp[X\z1|_H% wpZP;9(َ<Ũ ھҶR~ 2@)T 5 XnpwXpJMH[VEGOH<7Sj2LO 5,`,V1PV% P 1pXߏY ejǔx|? !RMApDo6Oo,7cXh@Q2ӯ/=5gЖ:Sc|9M C6Mؕx۵kw=`9YG+)`(@)AzQK!EUp(J&lB]I(tnFnT#bLdۿU\jW -sYz :`BՋ/j@ofz,ٳf͛6lٳf͛6lٳf͛*$?gmd:m3HZqC㳅B>EHh8;^ UkP ֠}etLX })NBO  >rYT!G@ j*E CeCR"8 CućFzּeHE00?n9WNH=L;]JBw,T| 9]pJ!F͔JڼQ.!jtKS0촮-QŗFU$PWzJS:^}ʁ$<d0,O0җg,u Pv OjV1mvYnb3t^O08x09oC,Mߜ@]+!xpI=sl yYAm fC HڅAD߉%#.:ƨaMhĄE6IB)H4 OgaP%Q{#n(GmڇK`VyNAº]˟Nc`V9k kJDkgx1-vE,ɜ2*ɦ*Ը!bi[&9Ԧ֎Ո*4 XQTz. h*1sWEo - Mo%!^hzM~V3P'1 Nsp Dr!'뛫5ǫevx[_@*Öx Xb,nAJW@3Ÿ،h.!;z tX}VR  (->1>o vQI-/ طv#UDض̿pz31P(P+\IS껉7AT+Õ۫ߎ"/CAy KCCE3-g9\~SAs:&h Lwi )it͹/X_H+@_+)?[Rϵ&{E.19 Ơl%[B*Mk%|f\/X[)k0ږ8V)jn~,͕mXfPDh&Ӯ5Tkf/GV"Q5VsRdGE5 DuaIJ ^h[6ï}گ[gC1@]>򈄰 C#qynF@P@5!h¡ 2<:x5yA׳ q?|0.ӡ.zJ@R )H @Rl> ("D$HaPn~Y3,IFgJWh P:FX΅Ib 6c q7a2Q EkHDMj⢳Ei R8Amא(`R,[0llNl7D\[WYU nv188:3^oHv8+a_l1nCA`-YJsYnhljC$v:zS7 m+՗RAJFAS0=x*#ժ*ٌ-q]'~R恈g79dE`*ttsA9H4R(s_z(9pA2(7_t(j_,@F T 8=)4M u)B0o `a\y@ټQoP80/*'ZraX#M0Yp2_53$o[Et^ì2Upgf`ar]tz9У:*ǜ'˺*@!]QM #]d;g0Eƥ$,S\J>x= j)}<~G$etq_tȽUW r/]H "^KlX v5ݘkul:e aqv.䡗%Y& .+0Lư*tv]U^7TEFA9ΐf_S- -Ko Hj! 0]6.y~^^y栔Y]֑g׉MrguL:J-UIFN3 LNEA90-@y]ʺ(a2 hB(>U>U>U>U>U>U>U>U>U>U>U>U>U>U>U>U>U>U]P3]o>`C\j "὏:6iYFE.>P%T*4StX *. #E*:c t λbK.%d\3By#(#:ΊZ]r[Lehd0. 40mZb~o$TC/l f INN`9"r8p*'T\F`H> >"5K^os# ep!rŘ5^ússUW>M*j;班KҤ[W4P2-Dޏs9zG/D="2B= O9Qc5 =G`xb 1e}<~GڝoDf6 \C/FT< ϙzXݴ]Ќe T.Egģe8|Ld\ ]hFW<01њD%91  BI谜qV: )|1}'1n[diItP)a\0-${m ጰtdZo:܉jhЫ-JICyݍM;xPPu_ѣДhn7ؖQR((~-u& ka|FH#I=DVE`VeWii2[LHYg_=ưKH/r_ w2"0A3m DZ7} 1S 8e1F)Qɩ {I* 0@D.T h U$2"M/P* KIVa)VMELcfnv1Qz=, Op V">P5^"c*ᢆ_bOf5oV@ IatQBUD-4FA9Ga@iBoZl UJ53 W!O^EǘːywDa}a<+/|[o+ KBehX?EU 㿀̫@Dx`\]@?Ib$]w+ WN|w|w|w|w|w|w|w|w 9P;oىىىىىىىىىىىىىوmif17+X6,IXv v@jGK94Vv& : ՚d@@"}Q_R/AZb Oj(hf;~Hwum;G1cnԮRsOYEj2% e&YwAr?h )Zfֱ2@@tMXZ߯TɜQ!YV,X`H(4quE]ՙQKs-loEV(ͫC ܳJ#n囤6χ<3wpCUfdNEL0%A|Ae|B$\3#Aԛ(&gǑāR - .GS_n FZm78-VsӤ͚uN,ʫk*Z͑М 6 1fhv1sO0B}Pn89:}C=rxo:o}zpd `g!Q@|CRon)/C#8hCZK{,Bu TEPdXJV4S"\Ya\] 9r̾§ʇLM 3X`bC) 2Uh AbKt_GN5 V[gPZU$vW7r&|Y37R%pʩg/dz]26FalZOY(9ߘ^v)zEmrڭ+ 3X5YU嚎 +4y<Rv_d uNh? F$i>j:JVi(}"<8/, >uPPDH\*p9*s5ٜ5*P]kBsx e:)2HA1lT} 2RxiU"X / U6edZMmc'_dJ3_a&t0l4\zO+5OٚN:9I3bW-L].ŗ/@$.Mhtsp/ A.!^a ܓ ]rW,a ڶlH[["8Eb,Rp OR9:`n-"'\ԶRK[7 L 6oU/P+Gxob?z6غ.;)Cj ko}y;-b S †<.j׻` @8Q|C"Xi\[yrL@Q|C*P-tMW\:^Dc'_%֧a]JlWثS![N]U;ݧDGkR z|N Wci6(˱ VjiE`%`idirVfKjVuBhp±In&ƯV#xAS48LKMEr6d .6aÅ Ud-Gy'-KLaX@b4 :m)IA6ADj /G/H t!g>^z@jL2mX/*QQhAc*ِ4E֌IV,"Z e> @.5c'_7^ƛҭ%4MV. l{^; 85xmv^E X9]Òv"ӑ™ |2KS%-6r1td 숳dDV.JO7x20 ǂJÐ !)7@7Aȧ@0 Ha؈m*L9Yè+Z(Z.4+!OQ"JfJ\TUo<0lN՘*+: la쩵]Pf__^Y@` \C|, &254#T;s"UkA9]^j^-vZQ7 :@[`$_A^9(x:j"P7!=2#3/Pdq.U1'[Dh.Iya'mK^σBmcNJt dw[6Ua̔:UH@K> At^X1DN4a%U͇e? ZԨтQln2?9jA  ؖ/6m۞6c'_|O3x] x;a[0ehS3(!5U8-?ہ)_d6ф/w@r7AV t) g)2yV>D`!S (%&/*z@_z2ՕHwbN$넯'|5g2 `=#F0}ar]UuE+P6*D|qD2b]@SjR;v!aGRJ;ĭ2(€O  @̘}Bhj-[B~+@ކƉHtxBV04 t5kT?PG`o0&$ʘFdʪ4 Hl&c@(`A$Bp7 ۂ#a3@+Lt@͚WWWWWWWWWWWWWWWWWWWWWWWWWWWWWuu@Mcxxu, q,wq-دon)8%Y DU%#\r=gǽǽǽǽǽǽǽǽǽǽǽǽǽǽǽǽǽqj =6үn>8spFhF*fg1ЈUT+>j :,-Fۄ1fNÝ]O{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{Ϗ{B"*ӄN% F{]8[* 5Uz\]=d.BKQ۔YҌabVw?iYFDo [4 X2WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWgUBnY>f/gDԈ҅փ8"!i Zy"$ rDO r\Z&fvGpƝi)KHZpƊR')֜1` u j.N5_<ʑfl2ũ\;a6ˑ2˨IE"Yr1XCw12zG%# 0M -UVr!,  ƜD͒2HgԌV~zNp)6&tpڼ}]Ьjk:RGwNz;@{}n|AH/z 1'{ddu>Q c3 _2ȗ4k[,d9ͥ6thT4֥FS0[d GR1 KV 죷KӰ33i6'1W`"?ί\ϳZG"Wٱ!0zJ=p`MGOͲ}ɝ H?h/?!IJ-i}IENDB`phototonic-2.1/images/tag_filter_off.png000066400000000000000000000007641325127642100205010ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  IDAT8˥1QֵX,R3?:Z$dj1& K)Y )h]jDdaDW3ק1~M 񘖯o!AF#! L&Rٶm+ V< fe$ va0M۶ 1jql6f3rBz.oT J4 L>Qv/=T̥R^b ,K)뺧B(bT*: <q~oZ>ZuB*5jvԓ3y@k?l6&,n?{-0 }=k!IENDB`phototonic-2.1/images/tag_filter_on.png000066400000000000000000000007541325127642100203420ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME 4*ːyIDAT8ՒM(q?yOIK"))9 ,\7Wܖ p.RDQk!mke橧_Oyo`=3h2CNbrRj;^7@bj5}-329d0y!f4@L|灢|zhP$% 9g*y4Y[Y"~yCEy1Օek5]0r!~OmЧ |[kSOϑ1wT= ^<[3`O=؋{nx(EQ221b2!CA}cS*Ҋ׺V=g%/L%Oo隒 lԃ!7Þ}N8ws:IENDB`phototonic-2.1/images/tag_grey.png000066400000000000000000000011041325127642100173150ustar00rootroot00000000000000PNG  IHDRabKGD pHYs B(xtIME eIDAT8ˍ?A#z@!e B/puZxxp6)")RewEE?yag!@x)f2\A 9N@wwUT1iL{ݾ}MӮ'BӁy4;iwI|>ur 8t]X,~r]ql6랈%hGut]'0p8z~D"߀R@`l63N}fsrI(LT:jWd7pqqv}F_U#>Z*~ŨT*T <!m۶ aE( u %@%=Ϊ؏aFw[ZZFl!eP&ߤHd>֑ɀ#L.J#*I&?*s$(q`QV(2(eb, ?nΉ~gMMꑺ/RW|+Wk٭Ĵ;{x|>f@&fCMӝg9Jh%[NI }yy;r@}$Ξ[eIENDB`phototonic-2.1/images/tag_yellow.png000066400000000000000000000010661325127642100176710ustar00rootroot00000000000000PNG  IHDRabKGD pHYs B(xtIME-`,GIDAT8ˍ?hSQ2b B88wcPwG!89AXx]:)BA)M05R$#64^ӈ}|{DUk%vTIPUEUX jp  jG =*頦6T͉"cGV#O_ILIӷdm+@Bm,RHOIt)ʘXEO` O^Lumr{{` OoFNlYn=TuOsC>5[\/D'J83KɈl,[+\ͯ:"0_1c81fn9УGOE+1s7]2(}wׯF1ΐYy1?C&pV&IENDB`phototonic-2.1/images/top.png000066400000000000000000000010601325127642100163170ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8@Y΍ W !HU]]T$6Ur A  *Slles2Ϸ.13.X2w8qgEQ|< j:p^O`2-Y;fWVcI9V/΍TmhIENDB`phototonic-2.1/images/tree.png000066400000000000000000000011421325127642100164550ustar00rootroot00000000000000PNG  IHDRw=)IDATx^VAkA$Y ^B HAlŃGxYP)ɋ*X"xKcV 6ٙyv?` dӃy7;QU$ NrGiҠ#BJ4RZr%JϮ❥[SG>>g"9H5od$;g1iַpydUe:4*~LT+E Ь4{ AA8kw#߁W,R+J;r~ZŠJP 7*{1h/^i\3AYϜUp,L^*~DIENDB`phototonic-2.1/images/up.png000066400000000000000000000010241325127642100161410ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8@ǿߘe!LTW\gY[`,DOIieaeceY0Wt{̘gHbx{Gp*@2p@ ૈc\<ϟy$%"%Iꦪ$I6QvB .,K)RH,ΕRgu]k(β,;'|w $gJGGQm\>9W"⦆xji5k6\8&^#E֛~?sZMH~}[kݶ]9 @Eq?/ ܮVOm~f0Ƽ&G "$_X,;z"{ৈ#T IMʟ!"=s=_c9v$x|'HL]/?QwIENDB`phototonic-2.1/images/zoom.png000066400000000000000000000013231325127642100165030ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<PIDAT8MHq?Ϧ3a`Ĝ|ËD60]"ACH xT`zK2cl"`Đ:ߧ/ȟ~w=|<QU.""- PUuar0{pCU>QUDd`}}Cggg`ee%3Mw 徾0VSk W,{oB[Ѹalv3}+fgg=+8U5NgW׍M4] 6@*7`ZpoonLlooJxa4} Hݙ~bF8j/===cccd29dw\CbT 4ȁV.|>ݮRTKKKYDPD~WB!K؀Gpq^!Ñ //!"tjuuUSϖay-9pD"D"kkk`MWDc$!tuu;nD&g ePIENDB`phototonic-2.1/images/zoom1.png000066400000000000000000000013701325127642100165660ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<uIDAT8OHqrv풤9tNJu3)aU 0MGNݾ]R×J(F( E$a 7 =IR?2L.IRkP)"?%"( /۵D"DbOOَsa|z/o L,{cYmYV[4ALyweeLNwt]]\nOk\NHs,[ڂ\.KcRPh;YT.s\43NٶnOr766R",8-4uwhm#"ض eY*؜444tB3\mmmnF@DJ~ߧiڣSSSѝt%IGMM82E$Wvp =00pv7 i+RjIӴa̋־@)n lyR4y0sssǿK@͑{ڪ`0D$.~GUCD~ooozK$6Pc뿧#TIENDB`phototonic-2.1/images/zoom_in.png000066400000000000000000000013641325127642100171760ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<qIDAT8Kq_MgtÓ:eR0(IbBVQ/W 1QC)MG< :l!'1|x߼PRT 0窜l;u};ft]Oξ7DS"Rʽ񾩩ɳ5??, g===6MӖZ[[}O9+- GGG?H&`7'@[< ?!3HH"lzzzigg'+X*6 a\\.aa0dPpv{i2@iill<4߰ G:` `%n~/7/݃t)P(p8b1X,fޮz 8bKK{xxط qpp`)Jc1###.˙NT*uVQR*x^i." R<Ni| $^f%=2=/dteeENZsHf{HD6e^I+>~|>_(QJwrc9=$IENDB`phototonic-2.1/images/zoom_out.png000066400000000000000000000013271325127642100173760ustar00rootroot00000000000000PNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<TIDAT8Kq_mm˖SHAG 2@S! C ,uQ!0A&J`b9=|w!vtHE_xyJD8F)UǑx&'' mi HOOO]D(%"(<+++Fbbff&U,ݝwt]_x<|ĭH$!g2 pvv p4'LE"x|j^LLL,pMDj\>\N`0{t(KP444ln)'eYCDlf nlldvwwwJw ?55z422Ҧiږi?5M[4-;00ZWW04?@D2Jf` =I$ZZZ\L&cTJeEdXp𼫫shhvvvv tzk~~>iZ+47zLD '@R3 v=^HճLY8p8_ZZx<z!n Bh4*k3= MMM .Rx 8iIENDB`phototonic-2.1/main.cpp000066400000000000000000000040101325127642100151700ustar00rootroot00000000000000/* * Copyright (C) 2013-2015 Ofer Kashayov * This file is part of Phototonic Image Viewer. * * Phototonic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Phototonic 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 Phototonic. If not, see . */ #include "Phototonic.h" #include static void showHelp() { qInfo() << VERSION << "image viewer."; qInfo() << "Usage: phototonic [OPTION] [FILE... | DIRECTORY]"; qInfo() << " -h, --help\t\t\tshow this help and exit"; qInfo() << " -l, --lang=LANGUAGE\t\tstart with a specific translation"; } int main(int argc, char *argv[]) { QApplication QApp(argc, argv); QStringList arguments = QCoreApplication::arguments(); QLocale locale = QLocale::system(); int argumentsStartAt = 1; if (arguments.size() == 2) { if (arguments.at(1).startsWith("-")) { showHelp(); return -1; } } else if (arguments.size() >= 3 && (arguments.at(1) == "-l" || arguments.at(1) == "--lang")) { locale = QLocale(arguments.at(2)); argumentsStartAt = 3; } QTranslator qTranslator; qTranslator.load(locale, "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath)); QApp.installTranslator(&qTranslator); QTranslator qTranslatorPhototonic; qTranslatorPhototonic.load(locale, "phototonic", "_", ":/translations"); QApp.installTranslator(&qTranslatorPhototonic); Phototonic phototonic(arguments, argumentsStartAt); phototonic.show(); return QApp.exec(); } phototonic-2.1/phototonic.desktop000066400000000000000000000007511325127642100173310ustar00rootroot00000000000000[Desktop Entry] Name=Phototonic Name[de]=Phototonic Name[fr]=Phototonic Comment=View photos on your computer Comment[de]=Photos betrachten und verwalten Comment[fr]=Visionner et gérer des photos sur votre ordinateur GenericName=Image Viewer GenericName[de]=Bildbetrachter GenericName[fr]=Visionneuse d'images Exec=phototonic %F Icon=phototonic Terminal=false Type=Application Categories=Graphics;Viewer; StartupNotify=true MimeType=image/png;image/gif;image/jpeg;image/bmp;image/svg+xml; phototonic-2.1/phototonic.pro000066400000000000000000000056371325127642100164700ustar00rootroot00000000000000# # Copyright (C) 2013-2018 Ofer Kashayov # This file is part of Phototonic Image Viewer. # # Phototonic is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Phototonic 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 Phototonic. If not, see . # TEMPLATE = app TARGET = phototonic INCLUDEPATH += . INCLUDEPATH += /usr/local/include win32-g++ { MINGWEXIVPATH = $$PWD/mingw LIBS += -L$$MINGWEXIVPATH/lib/ -lexiv2 -lexpat -lz INCLUDEPATH += $$MINGWEXIVPATH/include DEPENDPATH += $$MINGWEXIVPATH/include PRE_TARGETDEPS += $$MINGWEXIVPATH/lib/libexiv2.a $$MINGWEXIVPATH/lib/libexpat.a $$MINGWEXIVPATH/lib/libz.a } else: LIBS += -L/usr/local/lib -lexiv2 QT += widgets QMAKE_CXXFLAGS += $$(CXXFLAGS) QMAKE_CFLAGS += $$(CFLAGS) QMAKE_LFLAGS += $$(LDFLAGS) CONFIG += c++11 HEADERS += Phototonic.h ThumbsViewer.h ImageViewer.h CropRubberband.h SettingsDialog.h Settings.h InfoViewer.h \ FileSystemTree.h Bookmarks.h DirCompleter.h Tags.h MetadataCache.h ShortcutsTable.h CopyMoveDialog.h \ CopyMoveToDialog.h CropDialog.h ProgressDialog.h ColorsDialog.h ResizeDialog.h ExternalAppsDialog.h \ ImagePreview.h FileSystemModel.h FileListWidget.h RenameDialog.h Trashcan.h MessageBox.h SOURCES += main.cpp Phototonic.cpp ThumbsViewer.cpp ImageViewer.cpp CropRubberband.cpp SettingsDialog.cpp \ Settings.cpp InfoViewer.cpp FileSystemTree.cpp Bookmarks.cpp DirCompleter.cpp Tags.cpp \ MetadataCache.cpp ShortcutsTable.cpp CopyMoveDialog.cpp CopyMoveToDialog.cpp CropDialog.cpp \ ProgressDialog.cpp ExternalAppsDialog.cpp ColorsDialog.cpp ResizeDialog.cpp ImagePreview.cpp \ FileSystemModel.cpp FileListWidget.cpp RenameDialog.cpp Trashcan.cpp MessageBox.cpp RESOURCES += phototonic.qrc target.path = /usr/bin/ icon.files = images/phototonic.png icon.path = /usr/share/icons/hicolor/48x48/apps icon16.files = images/icon16/phototonic.png icon16.path = /usr/share/icons/hicolor/16x16/apps iconPixmaps.files = images/icon16/phototonic.png iconPixmaps.path = /usr/share/pixmaps desktop.files = phototonic.desktop desktop.path = /usr/share/applications INSTALLS += target icon icon16 iconPixmaps desktop TRANSLATIONS = translations/phototonic_en.ts \ translations/phototonic_pl.ts \ translations/phototonic_de.ts \ translations/phototonic_ru.ts \ translations/phototonic_cs.ts \ translations/phototonic_fr.ts \ translations/phototonic_bs.ts \ translations/phototonic_hr.ts \ translations/phototonic_sr.ts \ translations/phototonic_pt.ts phototonic-2.1/phototonic.qrc000066400000000000000000000045631325127642100164520ustar00rootroot00000000000000 images/error_image.png images/no_image.png images/home.png images/next.png images/back.png images/up.png images/refresh.png images/cut.png images/copy.png images/paste.png images/delete.png images/about.png images/new_folder.png images/settings.png images/phototonic.png images/zoom_in.png images/zoom_out.png images/first.png images/last.png images/top.png images/bottom.png images/zoom.png images/zoom1.png images/rotate_left.png images/rotate_right.png images/flipH.png images/flipV.png images/save.png images/open.png images/colors.png images/new.png images/tree.png images/clear.png images/play.png images/stop.png images/crop.png images/scale.png images/save_as.png images/bookmarks.png images/new_bookmark.png images/tag_grey.png images/tag_multi.png images/tag_yellow.png images/new_tag.png images/tag_filter_on.png images/tag_filter_negate.png images/tag_filter_off.png images/busy.gif translations/phototonic_pl.qm translations/phototonic_de.qm translations/phototonic_ru.qm translations/phototonic_cs.qm translations/phototonic_fr.qm translations/phototonic_bs.qm translations/phototonic_hr.qm translations/phototonic_sr.qm translations/phototonic_pt.qm phototonic-2.1/translations/000077500000000000000000000000001325127642100162665ustar00rootroot00000000000000phototonic-2.1/translations/phototonic_bs.qm000066400000000000000000000660051325127642100215060ustar00rootroot00000000000000Z**%G*0+1by]GLb 9LbLb!Lb^^M 'VN)Nn-NP7*dTl2X3X XX Y%I\Zwikn+;xFDGFt(A?-1n" cXZ9 *5"QxY\[)ndCPeEj62rIAsnO<Ù.!zȲ,7q P! 9N< <\N9w 5^~&nTf3:h%4& 'fG; QxYQxY]Rg</nSW40IeFu0oG %ve"w(*w AYra?($CD$CHýRu } !& #<lu2/z^[tS] ]zIII rIIG!IGVIL1fZ6<6>o,Z' : :&zfR3֓^>}}Q{-AaB= hFW O(O DrP)nNUDF'l/^%.p3H~~>K]9,5t9cFuF}H5:1n_+_%C jIDYVI^)YߺInT &: +#CD%n 6 9$`>eOPtTF[k_.%E_PFk}n%HUjUOF2mjWa7 75ȜHЍD2( JDKY(4(_q6E=IY*?%8c-yCl7$]41jN#eLgg2>$A0K>"0מKמ5s6Lf=KY B]*J@ @X%h@8A:8 gl gl; lq^5 t7J4y y-U zdJH t=q & G. DK Mb N #TB Ds O a3 dgk idAL p=@ p=W q%6 *$B a  ># ' )/ 3 sQ ye yeN CV 2'`O }8K ~u ~a > ʺRN J! ص ES6 Bn  &e-) ,@~ , .; A` O PG'A Pr R> u1h u1 8g Zn+ 8 Sx T\ ڎ N`  < DC# Sd/ h`= i)# r* ] _a PE3 [  ©e <QA <^ Sc S(sA),5uY8:G9";IW6!]^ߔFiT\ao0 3WiaDodaj ru no Add manually AppMgmtDialog<Putanja i argumenti aplikacijeApplication path and arguments AppMgmtDialogIzaberiChoose AppMgmtDialog$Izaberi aplikacijuChoose Application AppMgmtDialog@Upravljaj eksternim aplikacijamaManage External Applications AppMgmtDialogImeName AppMgmtDialogNova aplikacijaNew Application AppMgmtDialog UreduOK AppMgmtDialog UkloniRemove AppMgmtDialogPogoeni kanaliAffected Channels ColorsDialog PlavaBlue ColorsDialogSvjetlost Brightness ColorsDialog(Svjetlost i kontrastBrightness and Contrast ColorsDialogBalans boja Color Balance ColorsDialog ObojiColorize ColorsDialogBojeColors ColorsDialogKontrastContrast ColorsDialog ZelenaGreen ColorsDialogNijansaHue ColorsDialog(Nijansa i zasienostHue and Saturation ColorsDialogSvjetlina Lightness ColorsDialogNegativNegative ColorsDialog UreduOK ColorsDialog CrvenaRed ColorsDialogPovratiReset ColorsDialogZasienost Saturation ColorsDialogPregledaj... Browse...CopyMoveToDialog Otka~iCancelCopyMoveToDialog Izaberi fasciklu Choose FolderCopyMoveToDialogKopiraj u... Copy to...CopyMoveToDialogDestinacija: Destination:CopyMoveToDialogPomjeri u... Move to...CopyMoveToDialog UreduOKCopyMoveToDialog UkloniRemoveCopyMoveToDialog Otka~iCancel CpMvDialog(Kopiram "%1" u "%2".Copying "%1" to "%2". CpMvDialog*Pomjeram "%1" u "%2".Moving "%1" to "%2". CpMvDialogDoleBottom CropDialog Izre~iCropping CropDialog LijevoLeft CropDialog UreduOK CropDialogPovratiReset CropDialog DesnoRight CropDialogGoreTop CropDialogVe postoji already exists ImageTags"Dodaj novu oznaku Add a new tag ImageTags Otka~iCancel ImageTagsUkloni filtere Clear Filters ImageTags Unesi ime oznakeEnter new tag name ImageTags GreakaError ImageTags4Neuspijelo snimanje oznakeFailed to save tags to  ImageTags FilterFilter ImageTagsNova oznakaNew Tag ImageTags Ime nije unesenoNo name entered ImageTagsUkloni oznaku Remove Tag ImageTags4Ukloni izabranu oznaku(e)?Remove selected tags(s)? ImageTagsUkloni oznaku Remove tag ImageTags Ozna iTag ImageTags OznakaTag  ImageTagsOzna ivanjeTagging  ImageTagsUkloni oznakuUntag ImageTags"Uklanjanje oznaka Untagging  ImageTagsDaYes ImageTagsKlipbord Clipboard ImageView GreakaError ImageViewDGreaka pri snimanju Exif podataka.Failed to save Exif metadata. ImageView4Greaka pri snimanju slike.Failed to save image. ImageViewtDr~i Ctrl dugme pritisnuto i izaberi regiju koristei mia.;Hold down the Ctrl key and select a region using the mouse. ImageView Slika snimljena. Image saved. ImageView SlikeImages ImageViewBez selekcije No selection ImageViewSnimi sliku kao Save image as ImageViewSnimam... Saving... ImageView&Veli ina selekcije:Selection size:  ImageViewKopirajCopyInfoView Phototonic%n slika%n slike%n slika %n image(s) Phototonic &Uredi&Edit Phototonic &Fajl&File Phototonic&Idi&Go Phototonic &Pomo&Help Phototonic &Alati&Tools Phototonic&Pogled&View Phototonic:Pregleda i organizator slika!

Image viewer and organizer

 PhototonicOAbout PhototonicDodaj kraticu Add Bookmark Phototonic NazadBack PhototonicKartice Bookmarks PhototonicDoleBottom PhototonicPrijavi greake Bug reports PhototonicDNemogue kopirati ili pomjeriti u Can not copy or move to  Phototonic^Nemogue kopirati ili pomjeriti u istu fasciklu'Can not copy or move to the same folder PhototonicjNemogue pomjeriti ili kopirati slike u ovu fasciklu.+Can not move or copy images to this folder. Phototonic Otka~iCancel Phototonic^Nemogue izvesti akciju sa primvremenom slikom.+Cannot perform action with temporary image. Phototonic4Klasi ne minijaturne slikeClassic Thumbs PhototonicZatvori sliku Close Image PhototonicBojeColors PhototonicKompaktnoCompact PhototonicKopiranoCopied PhototonicKopirajCopy Phototonic*Kopiraj podatke slikeCopy Image Data PhototonicKopiraj u... Copy to... PhototonicNapravljen "%1" Created "%1" Phototonic Izre~i selekcijuCrop to Selection Phototonic Izre~iCropping Phototonic Izre~iCut PhototonicIzbriaiDelete Phototonic Izbriai fasciklu Delete folder PhototonicIzbriai sliku Delete image PhototonicIzbriai slike Delete images PhototonicIzbrisanoDeleted PhototonicIzbrisanoDeleted  PhototonicROdrediana fascikla je ista kao i po etna.%Destination folder is same as source. PhototonicIsklju enoDisable Phototonic,Sidrene i alatne trakeDocks and Toolbars PhototonicDvostrukoDual Phototonic(Dvostruko vertikalno Dual Vertical Phototonic Duple slike u %1Duplicate images in %1 Phototonic UrediEdit Phototonic6Poveaj minijaturne prikazeEnlarge Thumbnails Phototonic.Unesi novo ime za "%1":Enter a new name for "%1": Phototonic GreakaError Phototonic IzaiExit PhototonicTNeuspijelo kopiranje ili pomjeranje slike.Failed to copy or move image. PhototonicHNeuspijelo pravljenje nove fascikle.Failed to create new folder. Phototonic:Neuspijelo brisanje fascikle.Failed to delete folder. Phototonic2Neuspijelo brisanje slikeFailed to delete image Phototonic4Neuspijelo brisanje slike.Failed to delete image. Phototonic>Neuspijelo pomjeranje fascikle.Failed to move folder. Phototonic<Neuspijelo otvaranje fascikle:Failed to open folder: PhototonicDNeuspijelo preimenovanje fascikle.Failed to rename folder. Phototonic>Neuspijelo preimenovanje slike.Failed to rename image. PhototonicTGreaka pri pokretanju eksterne aplikacije.%Failed to start external application. PhototonicFajl sistem File System Phototonic FilterFilter Phototonic$Filtriraj po imenuFilter by Name Phototonic&Pronai duple slikeFind Duplicate Images PhototonicPrvaFirst Phototonic$Obrni horizontalnoFlip Horizontally Phototonic Obrni vertikalnoFlip Vertically Phototonic(Obrnuto horizontalnoFlipped Horizontally Phototonic$Obrnuto vertikalnoFlipped Vertically Phototonic$Fascikla pomjerena Folder moved PhototonicNaprijedForward Phototonic4Prikaz preko cijelo ekrana Full Screen PhototonicIdi goreGo Up PhototonicPo etnaHome Phototonic Po etna stranica Home page Phototonic SlikaImage Phototonic&Informacije o slici Image Info Phototonic(Uklju i pod-fascikleInclude Sub-folders PhototonicPokreem...Initializing... Phototonic$Nevaljala putanja: Invalid Path: Phototonic*Neva~ee ime uneseno.Invalid name entered. Phototonic&Nevaljala selekcijaInvalid selection Phototonic(Nevaljala selekcija.Invalid selection. PhototonicObrni selekcijuInvert Selection PhototonicZadr~i zum Keep Zoom Phototonic ZadnjaLast PhototonicU itaj klipbordLoad Clipboard Phototonic0Zaklju aj transformacijeLock Transformations Phototonic@Upravljaj eksternim aplikacijamaManage External Applications Phototonic(Preslikaj (ogledalo) Mirroring Phototonic0Preslikavanje isklju enoMirroring Disabled Phototonic0Preslikavanje: dvostrukoMirroring: Dual PhototonicFPreslikavanje. dvostruko vertikalnoMirroring: Dual Vertical Phototonic8Preslikavanje:  etverostrukoMirroring: Quad Phototonic0Preslikavanje: trostrukoMirroring: Triple Phototonic(Pomjeri "%1" u "%2"?Move "%1" to "%2"? PhototonicPomjeri dole Move Down PhototonicPomjeri lijevo Move Left PhototonicPomjeri desno Move Right PhototonicPomjeri goreMove Up Phototonic Pomjeri fasciklu Move folder PhototonicPomjeri u... Move to... PhototonicPomjerenoMoved PhototonicImeName PhototonicNavigacija Navigation PhototonicNova fascikla New Folder Phototonic"Nova pod-fasciklaNew Sub folder Phototonic$Novo ime fascikle:New folder name: PhototonicNovo ime: New name: PhototonicSljedeaNext PhototonicNema slika No images Phototonic"Ime nije uneseno.No name entered. PhototonicBez selekcije No selection Phototonic OtvoriOpen Phototonic Otvori pomou... Open With... Phototonic&Originalna veli ina Original Size PhototonicNalijepi ovdje Paste Here Phototonic,Nalijepi podatke slikePaste Image Data PhototonicTrajno izbriaiPermanently delete PhototonicDTrajno izbriai "%1" i sav sadr~aj?0Permanently delete "%1" and all of its contents? Phototonic<Trajno izbriai odabrane slike?#Permanently delete selected images? PhototonicPostavke Preferences Phototonic ProalaPrevious Phototonic etverostrukoQuad PhototonicNasumi naRandom PhototonicU itaj ponovoReload PhototonicUkloni kraticuRemove Bookmark PhototonicUkljonjen %1" Removed "%1" PhototonicPreimenujRename PhototonicPreimenuj sliku Rename Image PhototonicPovrati zum Reset Zoom Phototonic ObrniReverse PhototonicDRotiraj 1 stepen suprotno kazaljciRotate 1 degree CCW PhototonicDRotiraj 1 stepen u smjeru kazaljkeRotate 1 degree CW PhototonicHRotiraj 90 stepeni suprotno kazaljciRotate 90 degree CCW PhototonicHRotiraj 90 stepeni u smjeru kazaljkeRotate 90 degree CW PhototonicRotacija %1 Rotation %1° Phototonic SnimiSave PhototonicSnimi kaoSave As Phototonic.Promjeni veli inu slike Scale Image PhototonicOzna i sve Select All PhototonicPostavi putanjuSet Path Phototonic2Prika~i skrivene datotekeShow Hidden Files PhototonicPrika~i natpise Show Labels Phototonic(Prika~i alatnu traku Show Toolbar Phototonic4Umanji minijaturne prikazeShrink Thumbnails PhototonicVeli inaSize PhototonicSlajd prikaz Slide Show Phototonic$Slajd prikaz po etSlide show started Phototonic0Slajd prikaz obustavljenSlide show stopped PhototonicMale ikone Small Icons PhototonicSortiraj poSort By PhototonicKockastoSquarish Phototonic*Obustani slajd prikazStop Slide Show Phototonic OznakeTags PhototonicVrijemeTime PhototonicGoreTop PhototonicTransformiai Transform Phototonic2Transformacije zaklju aneTransformations Locked Phototonic2Transformacije otklju aneTransformations Unlocked PhototonicTrostrukoTriple PhototonicTipType Phototonic,Neobrnuto horizontalnoUnflipped Horizontally Phototonic(Neobrnuto vertikalnoUnflipped Vertically Phototonic PogledView PhototonicPregleda Viewer Phototonic Pa~njaWarning PhototonicDaYes Phototonic Ubli~iZoom PhototonicUbli~i %1%Zoom %1% Phototonic Ubli~iZoom In PhototonicZum zaklju an Zoom Locked Phototonic UdaljiZoom Out PhototonicZum vraen Zoom Reset PhototonicZum otklju an Zoom Unlocked Phototonic Otka~iCancelProgressDialog Otka~iCancel ResizeDialogVisina:Height: ResizeDialogZaklju aj omjerLock aspect ratio ResizeDialogNova veli ina: New size: ResizeDialog(Originalna veli ina:Original size: ResizeDialogPostotakPercent ResizeDialogPikseliPixels ResizeDialogUveaj/SmanjiScale ResizeDialog.Promjeni veli inu slike Scale Image ResizeDialogJedinice:Units: ResizeDialog`irina:Width: ResizeDialogRDodaj razmak izmeu minijaturnih prikaza:Add space between thumbnails:SettingsDialogBoja pozadine:Background color:SettingsDialog"Pozadinska slika:Background image:SettingsDialogPo visini By heightSettingsDialogPo airiniBy widthSettingsDialog(Po airini ili visiniBy width or heightSettingsDialog Otka~iCancelSettingsDialog0Izaberi po etnu fascikluChoose Startup FolderSettingsDialogNStandardni kvalitet pri snimanju slika:#Default quality when saving images:SettingsDialogfStandardni, ili komandnom linijom odreeni argument.Default, or specified by command line argumentSettingsDialogFRazmak izmeu slajdova u sekundama: Delay between slides in seconds:SettingsDialog&Potvrda za brisanjeDelete confirmationSettingsDialogIsklju enoDisableSettingsDialog*Uklju i GIF animacijeEnable GIF animationSettingsDialogNapusti umjesto zatvaranja kada je u itana slika iz komandne linije?Exit instead of closing, when image is loaded from command lineSettingsDialog,Prilagodi velike slikeFit Large ImagesSettingsDialog*Prilagodi manje slikeFit Small ImagesSettingsDialogOpenitoGeneralSettingsDialog SlikeImagesSettingsDialog"Kratice tastatureKeyboard ShortcutsSettingsDialogBoja natpisa: Label color:SettingsDialognBroj stranica minijaturnih slika da se u ita unaprijed:(Number of thumbnail pages to read ahead:SettingsDialog UreduOKSettingsDialogOtvori fajl Open FileSettingsDialogPostavke PreferencesSettingsDialog$Zapamti posljednju Remember lastSettingsDialogJRotiraj slike prema Exif orijentaciji*Rotate image according to Exif orientationSettingsDialog\Rotiraj minijaturne slike po Exif orijentaciji/Rotate thumbnails according to Exif orientationSettingsDialog<Prika~i ime slike u pregleda uShow image file name in viewerSettingsDialogPrika~i originalnu veli inu slika koje su manje od minijaturne veli ine AppMgmtDialog Manage External Applications Upravljaj eksternim aplikacijama Name Ime Application path and arguments Putanja i argumenti aplikacije Choose Izaberi Add manually Dodaj ručno Remove Ukloni OK Uredu Choose Application Izaberi aplikaciju New Application Nova aplikacija ColorsDialog Colors Boje Reset Povrati OK Uredu Hue Nijansa Saturation Zasićenost Lightness Svjetlina Colorize Oboji Negative Negativ Red Crvena Green Zelena Blue Plava Hue and Saturation Nijansa i zasićenost Affected Channels Popravi Pogođeni kanali Brightness Svjetlost Contrast Kontrast Brightness and Contrast Svjetlost i kontrast Color Balance Balans boja CopyMoveToDialog Move to... Pomjeri u... Copy to... Kopiraj u... Browse... Pregledaj... Remove Ukloni Cancel Otkaži OK Uredu Destination: Destinacija: Choose Folder Izaberi fasciklu CpMvDialog Cancel Otkaži Copying "%1" to "%2". Kopiram "%1" u "%2". Moving "%1" to "%2". Pomjeram "%1" u "%2". CropDialog Cropping Izreži Reset Povrati OK Uredu Left Lijevo Right Desno Top Gore Bottom Dole ImageTags Image Tags Filter Filter Tag Označi Untag Ukloni oznaku New Tag Nova oznaka Remove Tag Ukloni oznaku Clear Filters Ukloni filtere Negate Error Greška Failed to save tags to Neuspijelo snimanje oznake Tagging Označivanje Untagging Uklanjanje oznaka Add a new tag Dodaj novu oznaku Enter new tag name Unesi ime oznake No name entered Ime nije uneseno Tag Oznaka already exists Već postoji Remove selected tags(s)? Ukloni izabranu oznaku(e)? Remove tag Ukloni oznaku Yes Da Cancel Otkaži ImageView Clipboard Klipbord Selection size: Veličina selekcije: No selection Bez selekcije Hold down the Ctrl key and select a region using the mouse. Drži Ctrl dugme pritisnuto i izaberi regiju koristeći miš. Saving... Snimam... Error Greška Failed to save image. Greška pri snimanju slike. Failed to save Exif metadata. Greška pri snimanju Exif podataka. Image saved. Slika snimljena. Save image as Snimi sliku kao Images Slike InfoView Copy Kopiraj Phototonic Image Info Informacije o slici Zoom Ubliži Mirroring Ovo treba popraviti Preslikaj (ogledalo) Transform Transformiši View Pogled Top Gore Bottom Dole Close Image Zatvori sliku Full Screen Prikaz preko cijelo ekrana Preferences Postavke Exit Izađi Enlarge Thumbnails Povećaj minijaturne prikaze Shrink Thumbnails Umanji minijaturne prikaze Cut Izreži Copy Kopiraj Copy to... Kopiraj u... Move to... Pomjeri u... Delete Izbriši Save Snimi Save As Snimi kao Copy Image Data Kopiraj podatke slike Paste Image Data Nalijepi podatke slike Rename Preimenuj Select All Označi sve About O Name Ime Time Vrijeme Size Veličina Type Tip Reverse Obrni Show Hidden Files Prikaži skrivene datoteke Show Labels Prikaži natpise Small Icons Male ikone Hide Docks Title Bar Sakrij naslovnu traku sidrene trake Hide Dock Title Bars Show Toolbar Prikaži alatnu traku Classic Thumbs Klasične minijaturne slike Compact Kompaktno Squarish Kockasto Reload Učitaj ponovo Include Sub-folders Uključi pod-fascikle Paste Here Nalijepi ovdje New Folder Nova fascikla Back Nazad Forward Naprijed Go Up Idi gore Home Početna Slide Show Slajd prikaz Next Sljedeća Previous Prošla First Prva Last Zadnja Random Nasumična Open Otvori Load Clipboard Učitaj klipbord Open With... Otvori pomoću... Manage External Applications Upravljaj eksternim aplikacijama Add Bookmark Dodaj kraticu Remove Bookmark Ukloni kraticu Zoom Out Udalji Zoom In Ubliži Reset Zoom Povrati zum Original Size Originalna veličina Keep Zoom Zadrži zum Rotate 90 degree CCW Rotiraj 90 stepeni suprotno kazaljci Rotate 90 degree CW Rotiraj 90 stepeni u smjeru kazaljke Flip Horizontally Obrni horizontalno Flip Vertically Obrni vertikalno Cropping Izreži Crop to Selection Izreži selekciju Scale Image Promjeni veličinu slike Rotate 1 degree CCW Rotiraj 1 stepen suprotno kazaljci Rotate 1 degree CW Rotiraj 1 stepen u smjeru kazaljke Colors Boje Find Duplicate Images Pronađi duple slike Disable Isključeno Dual Dvostruko Triple Trostruko Dual Vertical Dvostruko vertikalno Quad Četverostruko Lock Transformations Zaključaj transformacije Move Left Pomjeri lijevo Move Right Pomjeri desno Move Up Pomjeri gore Move Down Pomjeri dole Invert Selection Obrni selekciju Filter by Name Filtriraj po imenu Set Path Postavi putanju &File &Fajl &Edit &Uredi &Go &Idi &View &Pogled Sort By Sortiraj po &Tools &Alati &Help &Pomoć Edit Uredi Navigation Navigacija Filter Filter Image Slika Initializing... Pokrećem... File System Fajl sistem Bookmarks Kartice Tags Oznake <p>Image viewer and organizer</p> Pregledač i organizator slika Home page Početna stranica Bug reports Prijavi greške Error Greška Failed to start external application. Greška pri pokretanju eksterne aplikacije. Invalid selection. Nevaljala selekcija. Failed to copy or move image. Neuspijelo kopiranje ili pomjeranje slike. Minimum zoom Zoom %1% Ubliži %1% Maximum zoom Zoom Reset Zum vraćen Zoom Locked Zum zaključan Zoom Unlocked Zum otključan Transformations Locked Transformacije zaključane Transformations Unlocked Transformacije otključane Rotation %1° Rotacija %1° Failed to open file "%1", file not found. Flipped Vertically Obrnuto vertikalno Unflipped Vertically Ovo treba provjeriti Neobrnuto vertikalno Flipped Horizontally Obrnuto horizontalno Unflipped Horizontally Ovo treba provjeriti Neobrnuto horizontalno No selection Bez selekcije Mirroring Disabled Preslikavanje isključeno Mirroring: Dual Preslikavanje: dvostruko Mirroring: Triple Preslikavanje: trostruko Mirroring: Dual Vertical Preslikavanje. dvostruko vertikalno Mirroring: Quad Preslikavanje: četverostruko Can not copy or move to Nemoguće kopirati ili pomjeriti u Can not copy or move to the same folder Nemoguće kopirati ili pomjeriti u istu fasciklu Copied Kopirano Moved Pomjereno %n image(s) %n slika %n slike %n slika Permanently delete Trajno izbriši Delete image Izbriši sliku Yes Da Cancel Otkaži Deleted Izbrisano Failed to delete image Neuspijelo brisanje slike Permanently delete selected images? Trajno izbriši odabrane slike? Delete images Izbriši slike Failed to delete image. Neuspijelo brisanje slike. Deleted Izbrisano Invalid Path: Nevaljala putanja: Viewer Pregledač Docks and Toolbars Sidrene i alatne trake No images Nema slika Failed to open file "%1": file not found. Neuspijelo otvaranje fajla %1": fajl nije pronađen. Slide show stopped Slajd prikaz obustavljen Stop Slide Show Obustani slajd prikaz Slide show started Slajd prikaz počet Can not move or copy images to this folder. Nemoguće pomjeriti ili kopirati slike u ovu fasciklu. Destination folder is same as source. Odredišna fascikla je ista kao i početna. Move "%1" to "%2"? Pomjeri "%1" u "%2"? Move folder Pomjeri fasciklu Failed to move folder. Neuspijelo pomjeranje fascikle. Folder moved Fascikla pomjerena Failed to open folder: Neuspijelo otvaranje fascikle: Duplicate images in %1 Duple slike u %1 New name: Novo ime: Invalid name entered. Nevažeće ime uneseno. Failed to rename folder. Neuspijelo preimenovanje fascikle. Invalid selection Nevaljala selekcija Rename Image Preimenuj sliku Enter a new name for "%1": Unesi novo ime za "%1": No name entered. Ime nije uneseno. Failed to rename image. Neuspijelo preimenovanje slike. Permanently delete "%1" and all of its contents? Trajno izbriši "%1" i sav sadržaj? Delete folder Izbriši fasciklu Failed to delete folder. Neuspijelo brisanje fascikle. Removed "%1" Ukljonjen %1" New Sub folder Nova pod-fascikla New folder name: Novo ime fascikle: Failed to create new folder. Neuspijelo pravljenje nove fascikle. Created "%1" Napravljen "%1" Warning Pažnja Cannot perform action with temporary image. Nemoguće izvesti akciju sa primvremenom slikom. ProgressDialog Cancel Otkaži QObject Usage: phototonic [FILE or DIRECTORY]... Koristi ovako: phototonic [FAJL ili FASCIKLA]... ResizeDialog Scale Image Promjeni veličinu slike Scale Možda ima bolja jedinstvena rječ Uvećaj/Smanji Cancel Otkaži Original size: Originalna veličina: Width: Širina: Height: Visina: Units: Jedinice: New size: Nova veličina: Pixels Pikseli Percent Postotak Lock aspect ratio Zaključaj omjer SettingsDialog Preferences Postavke Fit Large Images Prilagodi velike slike Disable Isključeno By width or height Po širini ili visini By width Po širini By height Po visini Stretch disproportionately Razvuci disproporcionalno Fit Small Images Prilagodi manje slike Background color: Boja pozadine: Exit instead of closing, when image is loaded from command line Napusti umjesto zatvaranja kada je učitana slika iz komandne linije Wrap image list when reaching last or first image Ovo definitivno popraviti Umotaj listu slika pri kraju Default quality when saving images: Standardni kvalitet pri snimanju slika: Enable GIF animation Uključi GIF animacije Rotate image according to Exif orientation Rotiraj slike prema Exif orijentaciji Show image file name in viewer Prikaži ime slike u pregledaču Label color: Boja natpisa: Background image: Pozadinska slika: Add space between thumbnails: Dodaj razmak između minijaturnih prikaza: Show original size of images smaller than the thumbnail size Popraviti Prikaži originalnu veličinu slika koje su manje od minijaturne veličine Number of thumbnail pages to read ahead: Broj stranica minijaturnih slika da se učita unaprijed: Rotate thumbnails according to Exif orientation Rotiraj minijaturne slike po Exif orijentaciji Delay between slides in seconds: Razmak između slajdova u sekundama: Show random images Prikaži nasumične slike Startup folder Početna fascikla Default, or specified by command line argument Popraviti Standardni, ili komandnom linijom određeni argument Remember last Zapamti posljednju Specify: Odredi: Swap mouse left-click and middle-click actions Zamjeni akcije lijevog i srednjeg klika mišem Delete confirmation Potvrda za brisanje Keyboard Shortcuts Kratice tastature OK Uredu Cancel Otkaži Viewer Pregledač Thumbnails Minijaturni prikaz Slide Show Slajd prikaz General Općenito Choose Startup Folder Izaberi početnu fasciklu Open File Otvori fajl Images Slike ShortcutsTable Action Akcija Shortcut Prečice Delete shortcut Izbriši prečicu Set shortcut Postavi prečicu "%1" is reserved for shortcuts to external applications. Definitivno popraviti "%1" je obrnuto za prečice kod eksternih aplikacija. "%1" is already assigned to "%2" action. Popraviti "%1" je već upotrebljeno za "%2" akciju. ThumbView General Uopšteno File name Ime fajla Location Lokacija Size Veličina Modified Modificiran Format Format Resolution Rezolucija Megapixel Megapiksel Error Greška Selected %1 of%2 Izabrano %1 od %2 %n image(s) %n slika %n slike %n slika %n image(s) %n slika %n slike %n slika No images Nema slika Searching duplicate images... Tražim duple slike... Scanned %1, displaying %2 (%3 and %4) Moguće da nevalja Skeniran %1, prikazujem %2 (%3 i %4) %n original(s) %n original %n originala %n originala %n duplicate(s) %n duplikat %n duplikata %n duplikata phototonic-2.1/translations/phototonic_cs.qm000066400000000000000000000671071325127642100215130ustar00rootroot00000000000000 @c\B5BeDsEn]F2B/9-8&o'A>[**%*0X+1by`G{Lb 9LbLb!Lb`}M (UN*Nn.N~P7+qTl41XX (X hY%I\Zwipkn,HxFFHFt)A?22n"cYo9!*6OQxY^o[)ndCQeFj7crIA snPÙ."YȲ-8 Q\! 9N=4<\N:w 5`~'nUf3;%5O (fGePxPtTG[E_.%Fe_PG(}n&I@jVBF3jXh77ȜIЍD( JtDL(6 (aq7E>xJ@*@E%8c- jCl8A]43jN$RMgg3>]%A0>#v0ממ66M5=KY C\]*K|@ A%aAV8B#<=9 gl gl@ lq^7 t7J5 y-V zdJH t>< ' G0@ DL NO O #TC Ds!> a5 dgL idA p=@ p=X) q%7 *%5 a  >$ ( )1! 3A sR ye yeO CW 2'bl }8L^ ~= ~f > ʺS1 K صk ET Bn  &e. ,@~ , .< Ae O PG'Bp Pr RNepodaYilo se ulo~it zna ky do Failed to save tags to  ImageTagsFiltrovatFilter ImageTagsZna ky obrzko Image Tags ImageTagsVylou itNegate ImageTagsNov zna kaNew Tag ImageTags.Nebyl zadn ~dn nzevNo name entered ImageTags Odstranit zna ku Remove Tag ImageTags:Odstranit vybranou zna ku(y)?Remove selected tags(s)? ImageTags Odstranit zna ku Remove tag ImageTagsOpatYit zna kouTag ImageTags Zna kaTag  ImageTagsZna kuje seTagging  ImageTagsZruait zna kuUntag ImageTagsRua se zna ky  Untagging  ImageTagsAnoYes ImageTagsSchrnka Clipboard ImageView ChybaError ImageViewNNepodaYilo se ulo~it popisn data EXIF.Failed to save Exif metadata. ImageView:NepodaYilo se ulo~it obrzek.Failed to save image. ImageViewdPodr~te klvesu Ctrl a pomoc myai vyberte oblast.;Hold down the Ctrl key and select a region using the mouse. ImageViewObrzek ulo~en. Image saved. ImageViewObrzkyImages ImageView}dn vbr No selection ImageView&Ulo~it obrzek jako Save image as ImageViewUkld se... Saving... ImageView$Velikost vbru: Selection size:  ImageViewKoprovatCopyInfoView%n obrzek%n obrzky%n obrzko %n image(s) Phototonicp&ravy&Edit Phototonic&Soubor&File Phototonic &Pohyb&Go PhototonicNpo&vda&Help Phototonic&Nstroje&Tools PhototonicPo&hled&View PhototonicD<p>Prohl~e a sprvce obrzko</p>!

Image viewer and organizer

 PhototonicO programuAbout PhototonicPYidat zlo~ku Add Bookmark PhototonicZptBack PhototonicZlo~ky Bookmarks PhototonicVe slo~ce doloBottom PhototonicHlaen chyb Bug reports PhototonicLNelze koprovat nebo pYesunout obrzkyCan not copy or move to  Phototonic^Nelze pYesunout nebo koprovat do stejn slo~ky'Can not copy or move to the same folder PhototoniclNelze pYesunout nebo koprovat obrzky do tto slo~ky.+Can not move or copy images to this folder. Phototonic ZruaitCancel PhototonicT innost nelze s do asnm souborem provst.+Cannot perform action with temporary image. Phototonic Klasick nhledyClassic Thumbs PhototonicZavYt obrzek Close Image Phototonic BarvyColors Phototonic*Zabrajc mlo mstaCompact PhototonicZkoprovnoCopied PhototonicKoprovatCopy Phototonic,Koprovat data obrzkuCopy Image Data PhototonicKoprovat do... Copy to... PhototonicVytvoYeno "%1" Created "%1" PhototonicOYznout vbrCrop to Selection PhototonicOYznutCropping PhototonicVyjmoutCut Phototonic SmazatDelete PhototonicSmazat slo~ku Delete folder PhototonicSmazat obrzek Delete image PhototonicSmazat obrzky Delete images PhototonicSmaznoDeleted PhototonicSmazno Deleted  PhototonicFClov slo~ka je stejn jako zdroj.%Destination folder is same as source. PhototonicZakzatDisable Phototonic2Panely a nstrojov pruhyDocks and Toolbars PhototonicDvojiceDual PhototonicDvojice svisle Dual Vertical Phototonic(Zdvojit obrzky v %1Duplicate images in %1 Phototonic pravyEdit PhototonicZvtait nhledyEnlarge Thumbnails Phototonic4Zadat nov nzev pro "%1":Enter a new name for "%1": Phototonic ChybaError PhototonicUkon itExit Phototonic^NepodaYilo se koprovat nebo pYesunout obrzek.Failed to copy or move image. PhototonicHNepodaYilo se vytvoYit novou slo~ku.Failed to create new folder. Phototonic8NepodaYilo se smazat slo~ku.Failed to delete folder. Phototonic8NepodaYilo se smazat obrzekFailed to delete image Phototonic:NepodaYilo se smazat obrzek.Failed to delete image. Phototonic>NepodaYilo se pYesunout slo~ku.Failed to move folder. Phototonic:NepodaYilo se otevYt slo~ku:Failed to open folder: PhototonicBNepodaYilo se pYejmenovat slo~ku.Failed to rename folder. PhototonicDNepodaYilo se pYejmenovat obrzek.Failed to rename image. PhototonicJNepodaYilo se spustit vnja program.%Failed to start external application. Phototonic Souborov systm File System Phototonic FiltrFilter Phototonic*Filtrovat podle nzvuFilter by Name Phototonic,Najt zdvojen obrzkyFind Duplicate Images Phototonic PrvnFirst Phototonic&PYevrtit vodorovnFlip Horizontally Phototonic PYevrtit svisleFlip Vertically Phototonic(PYevrceno vodorovnFlipped Horizontally Phototonic"PYevrceno svisleFlipped Vertically Phototonic Slo~ka pYesunuta Folder moved Phototonic VpYedForward Phototonic$Na celou obrazovku Full Screen Phototonic"NadYzen adresYGo Up Phototonic"Za te n strnkaHome Phototonic Domovsk strnka Home page PhototonicObrzekImage Phototonic&Informace o obrzku Image Info Phototonic$Zahrnout podslo~kyInclude Sub-folders PhototonicSpouat se...Initializing... PhototonicNeplatn cesta: Invalid Path: Phototonic*Zadn neplatn nzev.Invalid name entered. PhototonicNeplatn vbrInvalid selection PhototonicNeplatn vbr.Invalid selection. PhototonicObrtit vbrInvert Selection Phototonic"Zachovat zvtaen Keep Zoom PhototonicPoslednLast PhototonicNahrt schrnkuLoad Clipboard Phototonic"Uzamknout promnyLock Transformations Phototonic2Spravovat vnja programyManage External Applications Phototonic"Nejvta zvtaen Maximum zoom Phototonic"Nejmena zvtaen Minimum zoom PhototonicZrcadlen Mirroring Phototonic$Zrcadlen zakznoMirroring Disabled Phototonic$Zrcadlen: DvojiceMirroring: Dual Phototonic2Zrcadlen: Dvojice svisleMirroring: Dual Vertical Phototonic&Zrcadlen:  tveYiceMirroring: Quad Phototonic$Zrcadlen: TrojiceMirroring: Triple Phototonic,PYesunout "%1" do "%2?Move "%1" to "%2"? PhototonicPosunout dolo Move Down PhototonicPosunout vlevo Move Left PhototonicPosunout vpravo Move Right PhototonicPosunout nahoruMove Up Phototonic PYesunout slo~ku Move folder PhototonicPYesunout do... Move to... PhototonicPYesunoutMoved Phototonic NzevName Phototonic Pohyb Navigation PhototonicNov slo~ka New Folder PhototonicNov podslo~kaNew Sub folder Phototonic$Nov nzev slo~ky:New folder name: PhototonicNov nzev: New name: Phototonic DalaNext Phototonic}dn obrzky No images Phototonic0Nebyl zadn ~dn nzev.No name entered. Phototonic}dn vbr No selection PhototonicOtevYtOpen PhototonicOtevYt s... Open With... Phototonic Povodn velikost Original Size PhototonicVlo~it zde Paste Here Phototonic&Vlo~it data obrzkuPaste Image Data PhototonicSmazat trvalePermanently delete PhototonicPSmazat trvale "%1" a veaker jeho obsah?0Permanently delete "%1" and all of its contents? Phototonic<Trvale smazat vybran obrzky?#Permanently delete selected images? PhototonicNastaven Preferences PhototonicPYedchozPrevious Phototonic tveYiceQuad PhototonicNhodnRandom PhototonicNahrt znovuReload Phototonic"Odstranit zlo~kuRemove Bookmark PhototonicOdstranno "%1" Removed "%1" PhototonicPYejmenovatRename Phototonic&PYejmenovat obrzek Rename Image Phototonic.Nastavit zvtaen znovu Reset Zoom PhototonicObrcenReverse Phototonic.Oto it o 1 stupeH vlevoRotate 1 degree CCW Phototonic0Oto it o 1 stupeH vpravoRotate 1 degree CW PhototonicOto it vlevoRotate 90 degree CCW PhototonicOto it vpravoRotate 90 degree CW PhototonicOto en %1 Rotation %1° Phototonic Ulo~itSave PhototonicUlo~it jakoSave As Phototonic.Zmnit velikost obrzku Scale Image PhototonicVybrat vae Select All PhototonicNastavit cestuSet Path Phototonic*Ukzat skryt souboryShow Hidden Files PhototonicUkzat attky Show Labels Phototonic,Ukzat nstrojov pruh Show Toolbar PhototonicZmenait nhledyShrink Thumbnails PhototonicVelikostSize PhototonicPromtn Slide Show Phototonic$Promtn spuatnoSlide show started Phototonic&Promtn zastavenoSlide show stopped PhototonicMal ikony Small Icons PhototonicXadit dleSort By Phototonic&PYibli~n  tvercovSquarish Phototonic$Zastavit promtnStop Slide Show Phototonic Zna kyTags Phototonic asTime Phototonic Ve slo~ce nahoruTop PhototonicPromna Transform Phototonic Promny zamknutyTransformations Locked Phototonic"Promny odemknutyTransformations Unlocked PhototonicTrojiceTriple PhototonicTypType Phototonic8Vodorovn pYevrcen zruaenoUnflipped Horizontally Phototonic2Svisl pYevrcen zruaenoUnflipped Vertically Phototonic PohledView PhototonicProhl~e Viewer PhototonicVarovnWarning PhototonicAnoYes PhototonicZvtaenZoom PhototonicZvtaen %1%Zoom %1% PhototonicPYibl~itZoom In Phototonic"Zvtaen zamknuto Zoom Locked PhototonicOddlitZoom Out Phototonic.Nastavit zvtaen znovu Zoom Reset Phototonic$Zvtaen odemknuto Zoom Unlocked Phototonic ZruaitCancelProgressDialog ZruaitCancel ResizeDialog Vaka:Height: ResizeDialog(Zamknout pomr stranLock aspect ratio ResizeDialogNov velikost: New size: ResizeDialog"Povodn velikost:Original size: ResizeDialogProcentoPercent ResizeDialog PixeloPixels ResizeDialogZmnit velikostScale ResizeDialog.Zmnit velikost obrzku Scale Image ResizeDialogJednotky:Units: ResizeDialog `Yka:Width: ResizeDialog6Vlo~it mezi nhledy odstup:Add space between thumbnails:SettingsDialogBarva pozad:Background color:SettingsDialogObrzek pozad:Background image:SettingsDialogPodle vaky By heightSettingsDialogPodle aYkyBy widthSettingsDialog,Podle aYky nebo vakyBy width or heightSettingsDialog ZruaitCancelSettingsDialogFVybrat slo~ku pYi spuatn programuChoose Startup FolderSettingsDialogVVchoz jakost obrazu pYi ukldn obrzko:#Default quality when saving images:SettingsDialogfVchoz nebo stanoven parametrem pYkazovho Ydku.Default, or specified by command line argumentSettingsDialogBZpo~dn mezi snmky v sekundch: Delay between slides in seconds:SettingsDialog"Potvrzen smaznDelete confirmationSettingsDialogZakzatDisableSettingsDialog&Povolit animaci GIFEnable GIF animationSettingsDialogUkon it msto zavYen, kdy~ je obrzek nahrn z pYkazovho Ydku?Exit instead of closing, when image is loaded from command lineSettingsDialog2PYizposobit velk obrzkyFit Large ImagesSettingsDialog0PYizposobit mal obrzkyFit Small ImagesSettingsDialog ObecnGeneralSettingsDialogObrzkyImagesSettingsDialog"Klvesov zkratkyKeyboard ShortcutsSettingsDialogBarva attku: Label color:SettingsDialoghPo et strnek s nhledy, je~ se maj na st dopYedu:(Number of thumbnail pages to read ahead:SettingsDialogOKOKSettingsDialogOtevYt soubor Open FileSettingsDialogNastaven PreferencesSettingsDialog.Zapamatovat si posledn Remember lastSettingsDialogXOto it obrzek podle daje o nato en v EXIF*Rotate image according to Exif orientationSettingsDialogXOto it nhledy podle daje o nato en v EXIF/Rotate thumbnails according to Exif orientationSettingsDialogVZobrazit nzev souboru obrzku v prohl~e iShow image file name in viewerSettingsDialogUkzat povodn velikost obrzko menach, ne~ je velikost nhledu AppMgmtDialog Manage External Applications Spravovat vnější programy Command Příkaz Path Cesta Add Přidat Name Název Application path and arguments Cesta k programu a argumenty Choose Vybrat Add manually Přidat ručně Remove Odstranit OK OK Choose Application Vybrat program New Application Nový program ColorsDialog Colors Barvy Reset Nastavit znovu OK OK Hue Odstín Saturation Sytost Lightness Světlost Channels Kanály Enable Povolit Colorize Obarvit Negative Negativ Red Červená Green Zelená Blue Modrá Hue and Saturation Odstín a sytost Affected Channels Ovlivněné kanály Brightness Jas Contrast Kontrast Brightness and Contrast Jas a kontrast Color Balance Vyvážení barev CopyMoveToDialog Copy or Move Images to... Kopírovat nebo přesunout obrázky do... Add Přidat Move to... Přesunout do... Copy to... Kopírovat do... Browse... Procházet... Remove Odstranit Cancel Zrušit OK OK Destination: Cíl: Destination: Cíl: Close Zavřít Copy Kopírovat Move Přesunout Choose Folder Vybrat složku CpMvDialog Cancel Zrušit Copying "%1" to "%2". Kopíruje se "%1" do "%2. Moving "%1" to "%2". Přesunuje se "%1" do "%2. Copying Kopíruje se Moving Přesunuje se to do CropDialog Cropping Oříznutí Reset Nastavit znovu OK OK Top Nahoře Left Vlevo Right Vpravo Bottom Dole ImageTags Tag Opatřit značkou Untag Zrušit značku Clear Filters Vyprázdnit filtry New Tag Nová značka Image Tags Značky obrázků Filter Filtrovat Remove Tag Odstranit značku Negate Vyloučit Error Chyba Failed to save tags to Nepodařilo se uložit značky do Tagging Značkuje se Untagging Ruší se značky Add a new tag Přidat novou značku Enter new tag name Zadat název nové značky No name entered Nebyl zadán žádný název Tag Značka already exists již existuje Remove selected tags(s)? Odstranit vybranou značku(y)? Remove tag Odstranit značku Yes Ano Cancel Zrušit ImageView Clipboard Schránka Selection size: Velikost výběru: No selection Žádný výběr Hold down the Ctrl key and select a region using the mouse. Podržte klávesu Ctrl a pomocí myši vyberte oblast. Failed to save image. Nepodařilo se uložit obrázek. Failed to save Exif metadata. Nepodařilo se uložit popisná data EXIF. Image saved. Obrázek uložen. Hold down the Ctrl key and select a region using the mouse Podržte klávesu Ctrl a pomocí myši vyberte oblast Saving... Ukládá se... Error Chyba Failed to save image Nepodařilo se uložit obrázek Failed to save Exif metadata Nepodařilo se uložit popisná data EXIF Image saved Obrázek uložen Save image as Uložit obrázek jako Images Obrázky Image Files Obrázkové soubory InfoView Copy Kopírovat KeyGrabLineEdit Set shortcut Nastavit klávesovou zkratku is reserved for shortcuts to external applications je vyhrazeno pro klávesové zkratky vnějších programů is already assigned to " je již přiřazeno činnosti " " action " Phototonic Docks and Toolbars Panely a nástrojové pruhy Image Info Informace o obrázku Zoom Zvětšení Transform Proměna Mirroring Zrcadlení Top Ve složce nahoru Bottom Ve složce dolů Close Image Zavřít obrázek Full Screen Na celou obrazovku Preferences Nastavení Exit Ukončit Enlarge Thumbnails Zvětšit náhledy Shrink Thumbnails Zmenšit náhledy Cut Vyjmout Copy Kopírovat Copy or Move to... Kopírovat nebo přesunout do... Delete Smazat Save Uložit Save As Uložit jako Copy Image Kopírovat obrázek Paste Image Vložit obrázek Rename Přejmenovat Select All Vybrat vše About O programu Name Název Time Čas Size Velikost Type Typ Reverse Obráceně Show Hidden Files Ukázat skryté soubory Show Labels Ukázat štítky Small Icons Malé ikony Hide Docks Title Bar Skrýt název panelu Classic Thumbs Klasické náhledy Compact Zabírající málo místa Squarish Přibližně čtvercové Reload Nahrát znovu Include Sub-folders Zahrnout podsložky Paste Here Vložit zde New Folder Nová složka Manage Spravovat Back Zpět Forward Vpřed Up Nahoru Home Začáteční stránka Slide Show Promítání Next Další Previous Předchozí First První Last Poslední Random Náhodný Open Otevřít Show Clipboard Ukázat schránku Open With Otevřít pomocí Manage External Applications Spravovat vnější programy Zoom Out Oddálit Zoom In Přiblížit Reset Zoom Nastavit zvětšení znovu Original Size Původní velikost Keep Zoom Zachovat zvětšení Rotate 90 degree CCW Otočit vlevo Rotate 90 degree CW Otočit vpravo Flip Horizontally Převrátit vodorovně Flip Vertically Převrátit svisle Cropping Oříznutí Scale Image Změnit velikost obrázku Rotate 1 degree CCW Otočit o 1 stupeň vlevo Rotate 1 degree CW Otočit o 1 stupeň vpravo Colors Barvy Disable Zakázat Dual Dvojice Triple Trojice Dual Vertical Dvojice svisle Quad Čtveřice Tags Značky Minimum zoom Nejmenší zvětšení Maximum zoom Největší zvětšení Rotation %1° Otočení %1° Failed to open file "%1", file not found. Failed to open file "%1": file not found. Nepodařilo se otevřít obrázek "%1": soubor nebyl nalezen. Can not move or copy images to this folder. Nelze přesunout nebo kopírovat obrázky do této složky. Destination folder is same as source. Cílová složka je stejná jako zdroj. Move "%1" to "%2"? Přesunout "%1" do "%2? Failed to move folder. Nepodařilo se přesunout složku. Failed to open folder: Nepodařilo se otevřít složku: Duplicate images in %1 Zdvojit obrázky v %1 Invalid name entered. Zadán neplatný název. Failed to rename folder. Nepodařilo se přejmenovat složku. Enter a new name for "%1": Zadat nový název pro "%1": No name entered. Nebyl zadán žádný název. Failed to rename image. Nepodařilo se přejmenovat obrázek. Permanently delete "%1" and all of its contents? Smazat trvale "%1" a veškerý jeho obsah? Failed to delete folder. Nepodařilo se smazat složku. Removed "%1" Odstraněno "%1" Failed to create new folder. Nepodařilo se vytvořit novou složku. Created "%1" Vytvořeno "%1" Cannot perform action with temporary image. Činnost nelze s dočasným souborem provést. Keep Transformations Zachovat proměny Move Left Posunout vlevo Move Right Posunout vpravo Move Up Posunout nahoru Move Down Posunout dolů Invert Selection Obrátit výběr &File &Soubor &Edit Úp&ravy &Go &Pohyb &View Po&hled Sort By Řadit dle &Help Nápo&věda Edit Úpravy Navigation Pohyb View Pohled Filter Filtr Initializing... Spouští se... File System Souborový systém <p>Image viewer and organizer</p> <p>Prohlížeč a správce obrázků</p> Failed to start external application. Nepodařilo se spustit vnější program. Invalid selection. Neplatný výběr. Failed to copy or move image. Nepodařilo se kopírovat nebo přesunout obrázek. Zoom %1% Zvětšení %1% Rotation %1u00B0 Otočení %1u00B0 Copied Zkopírováno Moved Přesunout %n image(s) %n obrázek %n obrázky %n obrázků Permanently delete Smazat trvale Failed to delete image. Nepodařilo se smazat obrázek. Deleted Smazáno Invalid Path: Neplatná cesta: Viewer Prohlížeč <p>Git build v1.03.02 ( <p>Sestavení Git v1.03.02 ( Built with Qt Sestaveno s Qt Home page Domovská stránka Bug reports Hlášení chyb Contributors:<br> Přispěvatelé:<br> Contributors / Translations:<br> Přispěvatelé/Překladatelé:<br> Translators:<br> Překladatelé:<br> Invalid selection Neplatný výběr Error Chyba Failed to start external application Nepodařilo se spustit vnější program Failed to copy or move image Nepodařilo se kopírovat nebo přesunout obrázek Can not copy or move to Nelze kopírovat nebo přesunout obrázky Can not cut and paste in the same folder Nelze vyjmout a vložit do téže složky Copied Zkopírováno Moved Přesunuto images obrázků Delete image Smazat obrázek Permanently delete Smazat trvale Failed to delete image Nepodařilo se smazat obrázek No selection Žádný výběr Delete images Smazat obrázky Permanently delete selected images? Trvale smazat vybrané obrázky? Copy to... Kopírovat do... Move to... Přesunout do... Copy Image Data Kopírovat data obrázku Paste Image Data Vložit data obrázku Hide Dock Title Bars Show Toolbar Ukázat nástrojový pruh Go Up Nadřízený adresář Load Clipboard Nahrát schránku Open With... Otevřít s... Add Bookmark Přidat záložku Remove Bookmark Odstranit záložku Crop to Selection Oříznout výběr Find Duplicate Images Najít zdvojené obrázky Lock Transformations Uzamknout proměny Filter by Name Filtrovat podle názvu Set Path Nastavit cestu &Tools &Nástroje Image Obrázek Bookmarks Záložky Contributors / Code: Přispěvatelé (kód): Contributors / Translations: Překladatelé: Zoom Zvětšení Zoom Reset Nastavit zvětšení znovu Zoom Locked Zvětšení zamknuto Zoom Unlocked Zvětšení odemknuto Transformations Locked Proměny zamknuty Transformations Unlocked Proměny odemknuty Rotation Otočení Flipped Vertically Převráceno svisle Unflipped Vertically Svislé převrácení zrušeno Flipped Horizontally Převráceno vodorovně Unflipped Horizontally Vodorovné převrácení zrušeno Mirroring Disabled Zrcadlení zakázáno Mirroring: Dual Zrcadlení: Dvojice Mirroring: Triple Zrcadlení: Trojice Mirroring: Dual Vertical Zrcadlení: Dvojice svisle Mirroring: Quad Zrcadlení: Čtveřice Can not copy or move to the same folder Nelze přesunout nebo kopírovat do stejné složky Yes Ano Cancel Zrušit Deleted Smazáno Invalid Path: Neplatná cesta: No images Žádné obrázky Failed to open file Nepodařilo se otevřít obrázek , file not found , soubor nebyl nalezen Slide show stopped Promítání zastaveno Stop Slide Show Zastavit promítání Slide show started Promítání spuštěno Can not move or copy images to this folder Nelze přesunout nebo kopírovat obrázky do této složky Destination folder is same as source Cílová složka je stejná jako zdroj Move Přesunout to do Move folder Přesunout složku Failed to move folder Nepodařilo se přesunout složku Folder moved Složka přesunuta Failed to open folder: Nepodařilo se otevřít složku: Rename Přejmenovat New name: Nový název: Invalid name entered Zadán neplatný název Failed to rename folder Nepodařilo se přejmenovat složku Rename Image Přejmenovat obrázek Enter a new name for Zadat nový název pro No name entered Nebyl zadán žádný název Failed to rename image Nepodařilo se přejmenovat obrázek and all of its contents? a veškerý jeho obsah? Delete folder Smazat složku Failed to delete folder Nepodařilo se smazat složku Removed Odstraněno New Sub folder Nová podsložka New folder name: Nová název složky: Failed to create new folder Nepodařilo se vytvořit novou složku Created Vytvořeno Executing file manager... Spustit správce souborů... Warning Varování Cannot perform action with temporary image Činnost nelze s dočasným souborem provést ProgressDialog Cancel Zrušit QObject Usage: phototonic [FILE or DIRECTORY]... Použití: phototonic [SOUBOR nebo ADRESÁŘ]... ResizeDialog Scale Image Změnit velikost obrázku Scale Změnit velikost Cancel Zrušit Original size: Původní velikost: Width: Šířka: Height: Výška: Units: Jednotky: New size: Nová velikost: Original size: Původní velikost: Width: Šířka: Height: Výška: Units: Jednotky: New size: Nová velikost: Pixels Pixelů Percent Procento Lock aspect ratio Zamknout poměr stran SettingsDialog Preferences Nastavení By width or height Podle šířky nebo výšky Default quality when saving images: Výchozí jakost obrazu při ukládání obrázků: Label color: Barva štítku: OK OK Cancel Zrušit Background color: Barva pozadí: Rotate image according to Exif orientation Otočit obrázek podle údaje o natočení v EXIF Label color: Barva štítku: Background image: Obrázek pozadí: Add space between thumbnails: Vložit mezi náhledy odstup: Show original size of images smaller than the thumbnail size Ukázat původní velikost obrázků menších, než je velikost náhledu Number of thumbnail pages to read ahead: Počet stránek s náhledy k načtení dopředu: Rotate thumbnails according to Exif orientation Otočit náhledy podle údaje o natočení v EXIF Thumbnails Náhledy Fit Large Images Přizpůsobit velké obrázky Disable Zakázat By width and height Podle šířky a výšky By width Podle šířky By height Podle výšky Stretch disproportionately Roztáhnout nepoměrně Fit Small Images Přizpůsobit malé obrázky Exit instead of closing, when image is loaded from command line Ukončit místo zavření, když je obrázek nahrán z příkazového řádku Wrap image list when reaching last or first image Zalomit seznam obrázků, když je dosaženo posledního nebo prvního obrázku Default quality when saving images: Výchozí jakost obrazu při ukládání obrázků: Enable GIF animation Povolit animaci GIF Open File Otevřít soubor Images Obrázky Rotate according to Exif orientation Otočit podle údaje o natočení v EXIF Show image file name in full screen mode Zobrazit název souboru obrázku v režimu celé obrazovky Background color: Barva pozadí: Show image file name in viewer Zobrazit název souboru obrázku v prohlížeči Background image: Obrázek pozadí: Add space between thumbnails: Vložit mezi náhledy odstup: Number of thumbnail pages to read ahead: Počet stránek s náhledy, jež se mají načíst dopředu: Delay between slides in seconds: Zpoždění mezi snímky v sekundách: Startup folder Složka při spuštění programu Default, or specified by command line argument Výchozí nebo stanovená parametrem příkazového řádku Remember last Zapamatovat si poslední Specify: Vybrat: Delete confirmation Potvrzení smazání Keyboard Shortcuts Klávesové zkratky Viewer Prohlížeč Delay between slides in seconds: Zpoždění mezi snímky v sekundách: Show random images Ukázat náhodně vybrané obrázky Slide Show Promítání Swap mouse left-click and middle-click actions Vyměnit klepnutí levým tlačítkem myši za klepnutí prostředním tlačítkem Keyboard Shortcuts: Klávesové zkratky: Keyboard and Mouse Klávesnice a myš General Obecné Choose Startup Folder Vybrat složku při spuštění programu ShortcutsTable Action Činnost Shortcut Klávesová zkratka Delete shortcut Smazat klávesovou zkratku Set shortcut Nastavit klávesovou zkratku "%1" is reserved for shortcuts to external applications. "%1" je vyhrazeno pro klávesové zkratky vnějších programů. "%1" is already assigned to "%2" action. "%1" je již přiřazeno činnosti "%2". is reserved for shortcuts to external applications je vyhrazeno pro klávesové zkratky vnějších programů is already assigned to " je již přiřazeno činnosti " " action " ThumbView images obrázků Selected Vybráno of z File name Název souboru Location Umístění Format Formát Resolution Rozlišení Megapixel Megapixelů Selected %1 of %2 Vybráno %1 z %2 Scanned %1, displaying %2 (%3 and %4) Prohledáno %1, zobrazuje se %2 (%3 a %4) %n original(s) %n originál %n originály %n originálů %n duplicate(s) %n zdvojený obrázek %n zdvojené obrázky %n zdvojených obrázků Size Velikost General Obecné Modified Změněno Error Chyba %n image(s) %n obrázek %n obrázky %n obrázků Selected %1 of%2 Vybráno %1 z%2 %n image(s) %n obrázek %n obrázky %n obrázků Searching duplicate images... Hledají se zdvojené obrázky... Scanned Prohledáno %n images, displaying %n obrázek, zobrazuje se %n obrázky, zobrazují se %n obrázků, zobrazuje se %n images ( %n obrázek ( %n obrázky ( %n obrázků ( %n originals and %n originál a %n originály a %n originálů a %n duplicates) %n zdvojený obrázek) %n zdvojené obrázky) %n zdvojených obrázků) No images Žádné obrázky phototonic-2.1/translations/phototonic_de.qm000066400000000000000000000706451325127642100214770ustar00rootroot00000000000000_**%O*0+1bycGLb LbLb"LbcM *N-Nn1NP7.?Tl7-XOX X Y%N \Zwikn/$xFRLFt,PAC52n$c]9"*9{QxYb[)ndCVeJj:rIA!snTOÙ.#\Ȳ0`; U! 9N@<\N>5w 5d~*tnYf3? %8s *fG?QxYQxYc:Rg<3SW44eFu4oG ve%*w(.w ^rf+CH$GýW4uw-M } m!& #A3lu6Nz^aVtX] ]III ILIL ILEIQ f`6`6oI &,fZ': q:)fR7֓dOC}E}V1}AaB= FW BKإ O+O IP)nSUDJl/^(p3M~~CK]=5t=F{FH5>nde+%HH jNI^I^,ߺNnY?) /r#Cx%n6%9$e>eTPtTK[_.%Jq_PK0}n)MZjZF6j\77UȜMЍDF( JDPB(9;(eaq;EBVND*D#%8c=-!MCl;k]46jN%Qg1g6>'A0I>$0מuמ96Q[=OY G*]*O@  D%ED8F!?=[ gl  gl lq^:H t7J8 y-[ zdJM tB *# G3< DP Rk S #TGn Ds"% a8 dg idE p=D p=\ q%: *'v a v >& +L )4 3 sV ye } yeT C\ 2'e }8P ~ ~ B ʺWy N ص EXa Bn,  &e1 ,@~n , .@Q A. O PG'F^ PrG R";I]d6!b^ߔKuiTbBo0+L7igD$Manuell hinzufgen Add manually AppMgmtDialog6Programmpfad und -argumenteApplication path and arguments AppMgmtDialogAuswhlenChoose AppMgmtDialog&Anwendung auswhlenChoose Application AppMgmtDialog:Externe Anwendungen verwaltenManage External Applications AppMgmtDialogNameName AppMgmtDialog Neue ApplikationNew Application AppMgmtDialogOKOK AppMgmtDialogEntfernenRemove AppMgmtDialog"Betroffene KanleAffected Channels ColorsDialogBlauBlue ColorsDialogHelligkeit Brightness ColorsDialog.Helligkeit und KontrastBrightness and Contrast ColorsDialogFarbabstimmung Color Balance ColorsDialogEinfrbenColorize ColorsDialog FarbenColors ColorsDialogKontrastContrast ColorsDialogGrnGreen ColorsDialogFarbtonHue ColorsDialog*Farbton und SttigungHue and Saturation ColorsDialogHelligkeit Lightness ColorsDialogNegativNegative ColorsDialogOKOK ColorsDialogRotRed ColorsDialogZurcksetzenReset ColorsDialogSttigung Saturation ColorsDialogDurchsuchen... Browse...CopyMoveToDialogAbbrechenCancelCopyMoveToDialog$Verzeichnis whlen Choose FolderCopyMoveToDialog Kopieren nach... Copy to...CopyMoveToDialog Ziel: Destination:CopyMoveToDialog&Verschieben nach... Move to...CopyMoveToDialogOKOKCopyMoveToDialogEntfernenRemoveCopyMoveToDialogAbbrechenCancel CpMvDialog.Kopiere "%1" nach "%2".Copying "%1" to "%2". CpMvDialog4Verschiebe "%1" nach "%2".Moving "%1" to "%2". CpMvDialog UntenBottom CropDialogZuschneidenCropping CropDialog LinksLeft CropDialogOKOK CropDialogZurcksetzenReset CropDialog RechtsRight CropDialogObenTop CropDialog$ existiert bereits already exists ImageTags(Neuen Tag hinzufgen Add a new tag ImageTagsAbbrechenCancel ImageTags&Filter zurcksetzen Clear Filters ImageTags.Namen des Tags eingebenEnter new tag name ImageTags FehlerError ImageTagsBSpeichern des Tags fehlgeschlagenFailed to save tags to  ImageTags FilterFilter ImageTagsImage Tags Image Tags ImageTagsUmkehrenNegate ImageTagsNeuer TagNew Tag ImageTags(Kein Name eingegebenNo name entered ImageTagsTag entfernen Remove Tag ImageTags@Ausgewhlte(n) Tag(s) entfernen?Remove selected tags(s)? ImageTagsTag entfernen Remove tag ImageTagsTagTag ImageTagsTagTag  ImageTagsTagging Tagging  ImageTags UntagUntag ImageTagsUntagging  Untagging  ImageTagsJaYes ImageTagsZwischenablage Clipboard ImageView FehlerError ImageViewRFehler beim Speichern der EXIF-Metadaten.Failed to save Exif metadata. ImageView,Fehler beim Speichern.Failed to save image. ImageViewHalten Sie die STRG-Taste gedrckt und markieren einen Bereich mit der Maus.;Hold down the Ctrl key and select a region using the mouse. ImageView"Bild gespeichert. Image saved. ImageView BilderImages ImageViewKeine Auswahl No selection ImageView$Bild speichern als Save image as ImageViewSpeichere... Saving... ImageView Gre auswhlen:Selection size:  ImageViewKopierenCopyInfoView%n Bild%n Bilder %n image(s) Phototonic&Bearbeiten&Edit Phototonic &Datei&File Phototonic&Los&Go Phototonic &Hilfe&Help Phototonic&Werkzeuge&Tools Phototonic&Ansicht&View Phototonic@<p>Bildbetrachter und -verwalter!

Image viewer and organizer

 PhototonicberAbout Phototonic,Lesezeichen hinzufgen Add Bookmark Phototonic ZurckBack PhototonicLesezeichen Bookmarks Phototonic UntenBottom PhototonicFehlerberichte Bug reports PhototonicNKopieren oder Verschieben nicht mglichCan not copy or move to  PhototonicxKopieren oder Verschieben in den selben Ordner nicht mglich'Can not copy or move to the same folder PhototonicVerschieben oder Kopieren von Bildern in dieses Verzeichnis nicht mglich.+Can not move or copy images to this folder. PhototonicAbbrechenCancel PhototonicpAktion kann mit temporrem Bild nicht ausgefhrt werden.+Cannot perform action with temporary image. Phototonic4Klassische MiniaturansichtClassic Thumbs PhototonicBild schlieen Close Image Phototonic FarbenColors PhototonicKompaktCompact PhototonicKopiertCopied PhototonicKopierenCopy Phototonic&Bild-Daten kopierenCopy Image Data Phototonic Kopieren nach... Copy to... PhototonicErstellt "%1" Created "%1" Phototonic.Auswahl zum ZuschneidenCrop to Selection PhototonicZuschneidenCropping PhototonicAusschneidenCut PhototonicLschenDelete Phototonic&Verzeichnis lschen Delete folder PhototonicBild lschen Delete image PhototonicBilder lschen Delete images PhototonicGelschtDeleted PhototonicGelscht Deleted  PhototonicTZiel- und Quellverzeichnis sind identisch.%Destination folder is same as source. PhototonicDeaktivierenDisable Phototonic.Dock und WerkzeugleisteDocks and Toolbars PhototonicZweifachDual Phototonic"Zweifach vertikal Dual Vertical PhototonicDuplikate in %1Duplicate images in %1 PhototonicBearbeitenEdit Phototonic8Miniaturansichten vergrernEnlarge Thumbnails Phototonic4Neuen Namen eingeben "%1":Enter a new name for "%1": Phototonic FehlerError PhototonicBeendenExit PhototonichKopieren oder Verschieben des Bildes fehlgeschlagen.Failed to copy or move image. PhototonicdErstellen des neuen Verzeichnisses fehlgeschlagen.Failed to create new folder. PhototonicTLschen des Verzeichnisses fehlgeschlagen.Failed to delete folder. PhototonicBLschen des Bildes fehlgeschlagenFailed to delete image PhototonicDLschen des Bildes fehlgeschlagen.Failed to delete image. Phototonic\Verschieben des Verzeichnisses fehlgeschlagen.Failed to move folder. Phototonicffnen der Datei fehlgeschlagen "%1": Datei wurde nicht gefunden.)Failed to open file "%1", file not found. PhototonicRffnen des Verzeichnisses fehlgeschlagen:Failed to open folder: PhototonicZUmbenennen des Verzeichnisses fehlgeschlagen.Failed to rename folder. PhototonicJUmbenennen des Bildes fehlgeschlagen.Failed to rename image. Phototonic`Externe Anwendung konnte nicht gestartet werden.%Failed to start external application. PhototonicDateisystem File System Phototonic FilterFilter Phototonic$Nach Namen filternFilter by Name PhototonicSuche DuplikateFind Duplicate Images Phototonic ErstesFirst Phototonic&Horizontal spiegelnFlip Horizontally Phototonic"Vertikal spiegelnFlip Vertically Phototonic*Horizontal gespiegeltFlipped Horizontally Phototonic&Vertikal gespiegeltFlipped Vertically Phototonic,Verzeichnis verschoben Folder moved PhototonicVorwrtsForward PhototonicVollbild Full Screen PhototonicNach obenGo Up Phototonic4Dock-Titelleiste verbergenHide Dock Title Bars Phototonic0Persnliches VerzeichnisHome PhototonicHomepage Home page PhototonicBildImage Phototonic"Bildinformationen Image Info Phototonic<Unterverzeichnisse einbeziehenInclude Sub-folders Phototonic Initialisiere...Initializing... Phototonic Ungltiger Pfad: Invalid Path: PhototonicName ungltig.Invalid name entered. Phototonic"Ungltige AuswahlInvalid selection Phototonic$Ungltige Auswahl.Invalid selection. Phototonic Auswahl umkehrenInvert Selection Phototonic Zoom beibehalten Keep Zoom PhototonicLetztesLast Phototonic(Zwischenablage ladenLoad Clipboard Phototonic8Transformationen beibehaltenLock Transformations Phototonic:Externe Anwendungen verwaltenManage External Applications PhototonicGrter Zoom Maximum zoom PhototonicKleinster Zoom Minimum zoom PhototonicSpiegeln Mirroring Phototonic(Spiegeln deaktiviertMirroring Disabled Phototonic$Spiegeln: ZweifachMirroring: Dual Phototonic6Spiegeln: Zweifach vertikalMirroring: Dual Vertical Phototonic$Spiegeln: VierfachMirroring: Quad Phototonic$Spiegeln: DreifachMirroring: Triple Phototonic4Verschiebe "%1" nach "%2"?Move "%1" to "%2"? PhototonicNach unten Move Down PhototonicNach links Move Left PhototonicNach rechts Move Right PhototonicNach obenMove Up Phototonic.Verzeichnis verschieben Move folder Phototonic&Verschieben nach... Move to... PhototonicVerschiebenMoved PhototonicNameName PhototonicNavigation Navigation Phototonic"Neues Verzeichnis New Folder Phototonic,Neues UnterverzeichnisNew Sub folder Phototonic,Neuer Verzeichnisname:New folder name: PhototonicNeuer Name: New name: Phototonic WeiterNext PhototonicKeine Bilder No images Phototonic*Kein Name eingegeben.No name entered. PhototonicKeine Auswahl No selection Phototonic ffnenOpen Phototonicffnen mit... Open With... PhototonicOriginalgre Original Size PhototonicHier einfgen Paste Here Phototonic&Bild-Daten einfgenPaste Image Data Phototonic"Endgltig lschenPermanently delete Phototonic\Endgltig lschen "%1" und der gesamte Inhalt?0Permanently delete "%1" and all of its contents? PhototoniclMchten Sie die ausgewhlten Bilder endgltig lschen?#Permanently delete selected images? PhototonicEinstellungen Preferences PhototonicVorherigesPrevious PhototonicVierfachQuad PhototonicZuflligRandom PhototonicNeu ladenReload Phototonic*Lesezeichen entfernenRemove Bookmark PhototonicEntfernt "%1" Removed "%1" PhototonicUmbenennenRename PhototonicBild umbenennen Rename Image Phototonic"Zoom zurcksetzen Reset Zoom PhototonicUmgekehrtReverse PhototonicHUm 1 gegen den Uhrzeigersinn drehenRotate 1 degree CCW Phototonic:Um 1 im Uhrzeigersinn drehenRotate 1 degree CW PhototonicD90 gegen den Uhrzeigersinn drehenRotate 90 degree CCW Phototonic690 im Uhrzeigersinn drehenRotate 90 degree CW PhototonicDrehung %1 Rotation %1° PhototonicSpeichernSave PhototonicSpeichern unterSave As PhototonicBild skalieren Scale Image PhototonicAlle auswhlen Select All PhototonicPfad setzenSet Path Phototonic6Versteckte Dateien anzeigenShow Hidden Files PhototonicNamen anzeigen Show Labels Phototonic.Werkzeugleiste anzeigen Show Toolbar Phototonic:Miniaturansichten verkleinernShrink Thumbnails Phototonic GreSize PhototonicDiashow Slide Show Phototonic"Diashow gestartetSlide show started Phototonic$Diashow angehaltenSlide show stopped PhototonicKleine Symbole Small Icons PhototonicSortieren nachSort By PhototonicQuadratischSquarish PhototonicDiashow beendenStop Slide Show PhototonicTagsTags PhototonicZeitTime PhototonicObenTop PhototonicTransformieren Transform Phototonic8Transformationen beibehaltenTransformations Locked Phototonic6Transformationen entsperrenTransformations Unlocked PhototonicDreifachTriple PhototonicTypType Phototonic<Horizontal spiegeln rckgngigUnflipped Horizontally Phototonic8Vertikal spiegeln rckgngigUnflipped Vertically PhototonicAnsichtView PhototonicBetrachterViewer PhototonicWarnungWarning PhototonicJaYes PhototonicZoomZoom PhototonicZoom %1%Zoom %1% PhototonicZoom erhhenZoom In Phototonic Zoom beibehalten Zoom Locked PhototonicZoom verringernZoom Out Phototonic"Zoom zurcksetzen Zoom Reset PhototonicZoom entsperren Zoom Unlocked PhototonicAbbrechenCancelProgressDialogAbbrechenCancel ResizeDialog Hhe:Height: ResizeDialog8Grenverhltnis beibehaltenLock aspect ratio ResizeDialogNeue Gre: New size: ResizeDialogOriginalgre:Original size: ResizeDialogProzentPercent ResizeDialog PixelPixels ResizeDialogSkalierenScale ResizeDialogBild skalieren Scale Image ResizeDialogEinheit:Units: ResizeDialogBreite:Width: ResizeDialog`Abstand zwischen den Miniaturansichten einfgen:Add space between thumbnails:SettingsDialog"Hintergrundfarbe:Background color:SettingsDialog Hintergrundbild:Background image:SettingsDialogNach Hhe By heightSettingsDialogNach BreiteBy widthSettingsDialog*Nach Breite oder HheBy width or heightSettingsDialogAbbrechenCancelSettingsDialogHVerzeichnis bei Programmstart whlenChoose Startup FolderSettingsDialogJStandard-Bildqualitt beim Speichern:#Default quality when saving images:SettingsDialog`Standard oder mit Befehlszeilenparameter angeben.Default, or specified by command line argumentSettingsDialogTVerzgerung zwischen den Dias in Sekunden: Delay between slides in seconds:SettingsDialog$Lschen besttigenDelete confirmationSettingsDialogDeaktivierenDisableSettingsDialog0GIF-Animation aktivierenEnable GIF animationSettingsDialogBeenden statt Schlieen, wenn das Bild von der Kommandozeile geladen wird?Exit instead of closing, when image is loaded from command lineSettingsDialog*Groe Bilder anpassenFit Large ImagesSettingsDialog,Kleine Bilder anpassenFit Small ImagesSettingsDialogAllgemeinGeneralSettingsDialog BilderImagesSettingsDialog&TastenkombinationenKeyboard ShortcutsSettingsDialogLabelfarbe: Label color:SettingsDialogtAnzahl der Seiten, die im Voraus eingelesen werden sollen:(Number of thumbnail pages to read ahead:SettingsDialogOKOKSettingsDialogDatei ffnen Open FileSettingsDialogEinstellungen PreferencesSettingsDialog"Letztes speichern Remember lastSettingsDialogFBild gem EXIF-Orientierung drehen*Rotate image according to Exif orientationSettingsDialog`Miniaturansichten gem EXIF-Orientierung drehen/Rotate thumbnails according to Exif orientationSettingsDialog@Dateiname im Betrachter anzeigenShow image file name in viewerSettingsDialogOriginalgre der Bilder anzeigen, wenn sie kleiner als die Miniaturansicht ist AppMgmtDialog Manage External Applications Externe Anwendungen verwalten Name Name Application path and arguments Programmpfad und -argumente Choose Auswählen Add manually Manuell hinzufügen Remove Entfernen OK OK Choose Application Anwendung auswählen New Application Neue Applikation ColorsDialog Colors Farben Reset Zurücksetzen OK OK Hue Farbton Saturation Sättigung Lightness Helligkeit Channels Kanäle Enable Aktivieren Colorize Einfärben Negative Negativ Red Rot Green Grün Blue Blau Hue and Saturation Farbton und Sättigung Affected Channels Betroffene Kanäle Brightness Helligkeit Contrast Kontrast Brightness and Contrast Helligkeit und Kontrast Color Balance Farbabstimmung CopyMoveToDialog Copy or Move Images to... Bilder kopieren oder verschieben nach... Add Hinzufügen Move to... Verschieben nach... Copy to... Kopieren nach... Browse... Durchsuchen... Remove Entfernen Cancel Abbrechen OK OK Destination: Ziel: Destination: Ziel: Close Schließen Copy Kopieren Move Verschieben Choose Folder Verzeichnis wählen CpMvDialog Cancel Abbrechen Copying "%1" to "%2". Kopiere "%1" nach "%2". Moving "%1" to "%2". Verschiebe "%1" nach "%2". Copying Kopiere Moving Verschiebe to nach CropDialog Cropping Zuschneiden Reset Zurücksetzen OK OK Top Oben Left Links Right Rechts Bottom Unten ImageTags Tag Tag Untag Untag Clear Filters Filter zurücksetzen New Tag Neuer Tag Image Tags Image Tags Filter Filter Remove Tag Tag entfernen Negate Umkehren Error Fehler Failed to save tags to Speichern des Tags fehlgeschlagen Tagging Tagging Untagging Untagging Add a new tag Neuen Tag hinzufügen Enter new tag name Namen des Tags eingeben No name entered Kein Name eingegeben Tag Tag already exists existiert bereits Remove selected tags(s)? Ausgewählte(n) Tag(s) entfernen? Remove tag Tag entfernen Yes Ja Cancel Abbrechen ImageView Clipboard Zwischenablage Selection size: Größe auswählen: No selection Keine Auswahl Hold down the Ctrl key and select a region using the mouse. Halten Sie die STRG-Taste gedrückt und markieren einen Bereich mit der Maus. Failed to save image. Fehler beim Speichern. Failed to save Exif metadata. Fehler beim Speichern der EXIF-Metadaten. Image saved. Bild gespeichert. Hold down the Ctrl key and select a region using the mouse Halten Sie die STRG-Taste gedrückt und markieren einen Bereich mit der Maus Saving... Speichere... Error Fehler Failed to save image Fehler beim Speichern Failed to save Exif metadata Fehler beim Speichern der EXIF-Metadaten Image saved Bild gespeichert Save image as Bild speichern als Images Bilder Image Files Bild-Dateien InfoView Copy Kopieren KeyGrabLineEdit Set shortcut Verknüpfung setzen is reserved for shortcuts to external applications ist für Zugriff auf externe Programme reserviert is already assigned to " ist bereits " " action " zugewiesen Phototonic Image Info Bildinformationen Zoom Zoom Transform Transformieren Top Oben Bottom Unten Close Image Bild schließen Full Screen Vollbild Preferences Einstellungen Exit Beenden Enlarge Thumbnails Miniaturansichten vergrößern Shrink Thumbnails Miniaturansichten verkleinern Cut Ausschneiden Copy Kopieren Copy to... Kopieren nach... Move to... Verschieben nach... Copy Image Data Bild-Daten kopieren Paste Image Data Bild-Daten einfügen Hide Dock Title Bars Dock-Titelleiste verbergen Show Toolbar Werkzeugleiste anzeigen Go Up Nach oben Load Clipboard Zwischenablage laden Open With... Öffnen mit... Crop to Selection Auswahl zum Zuschneiden Lock Transformations Transformationen beibehalten Filter by Name Nach Namen filtern Set Path Pfad setzen &Tools &Werkzeuge Image Bild Bookmarks Lesezeichen Tags Tags Minimum zoom Kleinster Zoom Maximum zoom Größter Zoom Rotation %1° Drehung %1° Failed to open file "%1", file not found. Öffnen der Datei fehlgeschlagen "%1": Datei wurde nicht gefunden. Failed to open file "%1": file not found. Öffnen der Datei fehlgeschlagen "%1": Datei wurde nicht gefunden. Can not move or copy images to this folder. Verschieben oder Kopieren von Bildern in dieses Verzeichnis nicht möglich. Destination folder is same as source. Ziel- und Quellverzeichnis sind identisch. Move "%1" to "%2"? Verschiebe "%1" nach "%2"? Failed to move folder. Verschieben des Verzeichnisses fehlgeschlagen. Failed to open folder: Öffnen des Verzeichnisses fehlgeschlagen: Duplicate images in %1 Duplikate in %1 Invalid name entered. Name ungültig. Failed to rename folder. Umbenennen des Verzeichnisses fehlgeschlagen. Enter a new name for "%1": Neuen Namen eingeben "%1": No name entered. Kein Name eingegeben. Failed to rename image. Umbenennen des Bildes fehlgeschlagen. Permanently delete "%1" and all of its contents? Endgültig löschen "%1" und der gesamte Inhalt? Failed to delete folder. Löschen des Verzeichnisses fehlgeschlagen. Removed "%1" Entfernt "%1" Failed to create new folder. Erstellen des neuen Verzeichnisses fehlgeschlagen. Created "%1" Erstellt "%1" Cannot perform action with temporary image. Aktion kann mit temporärem Bild nicht ausgeführt werden. Failed to start external application Externe Anwendung konnte nicht gestartet werden Zoom Zoom Zoom Reset Zoom zurücksetzen Zoom Locked Zoom beibehalten Zoom Unlocked Zoom entsperren Transformations Locked Transformationen beibehalten Transformations Unlocked Transformationen entsperren Rotation Drehung Flipped Vertically Vertikal gespiegelt Unflipped Vertically Vertikal spiegeln rückgängig Flipped Horizontally Horizontal gespiegelt Unflipped Horizontally Horizontal spiegeln rückgängig Mirroring Disabled Spiegeln deaktiviert Mirroring: Dual Spiegeln: Zweifach Mirroring: Triple Spiegeln: Dreifach Mirroring: Dual Vertical Spiegeln: Zweifach vertikal Mirroring: Quad Spiegeln: Vierfach Can not copy or move to the same folder Kopieren oder Verschieben in den selben Ordner nicht möglich Copied Kopiert Moved Verschieben Permanently delete Endgültig löschen Failed to delete image. Löschen des Bildes fehlgeschlagen. Deleted Gelöscht Invalid Path: Ungültiger Pfad: Viewer Betrachter Docks and Toolbars Dock und Werkzeugleiste Mirroring Spiegeln Delete Löschen Save Speichern Save As Speichern unter Copy Image Bild kopieren Paste Image Bild einfügen Rename Umbenennen Select All Alle auswählen About Über Name Name Time Zeit Size Größe Type Typ Reverse Umgekehrt Show Hidden Files Versteckte Dateien anzeigen Show Labels Namen anzeigen Small Icons Kleine Symbole Classic Thumbs Klassische Miniaturansicht Compact Kompakt Squarish Quadratisch Reload Neu laden Include Sub-folders Unterverzeichnisse einbeziehen Paste Here Hier einfügen New Folder Neues Verzeichnis Manage Verwalten Back Zurück Forward Vorwärts Up Übergeordnetes Verzeichnis Home Persönliches Verzeichnis Slide Show Diashow Next Weiter Previous Vorheriges First Erstes Last Letztes Random Zufällig Open Öffnen Scale Image Bild skalieren <u>Contributors</u>:<br> <u>Mitwirkende</u>:<br> <u>Translators</u>:<br> <u>Übersetzer</u>:<br> Stop Slide Show Diashow beenden New Image Neues Bild Open With Öffnen mit Manage External Applications Externe Anwendungen verwalten Add Bookmark Lesezeichen hinzufügen Remove Bookmark Lesezeichen entfernen Zoom Out Zoom verringern Zoom In Zoom erhöhen Reset Zoom Zoom zurücksetzen Original Size Originalgröße Keep Zoom Zoom beibehalten Rotate 90 degree CCW 90° gegen den Uhrzeigersinn drehen Rotate 90 degree CW 90° im Uhrzeigersinn drehen Flip Horizontally Horizontal spiegeln Flip Vertically Vertikal spiegeln Cropping Zuschneiden Rotate 1 degree CCW Um 1° gegen den Uhrzeigersinn drehen Rotate 1 degree CW Um 1° im Uhrzeigersinn drehen Colors Farben Find Duplicate Images Suche Duplikate Disable Deaktivieren Dual Zweifach Triple Dreifach Dual Vertical Zweifach vertikal Quad Vierfach Keep Transformations Transformationen beibehalten Move Left Nach links Move Right Nach rechts Move Up Nach oben Move Down Nach unten Invert Selection Auswahl umkehren File Datei Edit Bearbeiten Go Los View Ansicht Sort By Sortieren nach Help Hilfe Navigation Navigation Filter Filter Initializing... Initialisiere... File System Dateisystem <p>Image viewer and organizer</p> <p>Bildbetrachter und -verwalter <p>Built with Qt <p>Kompiliert mit Qt Home page Homepage Bug reports Fehlerberichte Contact Kontakt Translations: Übersetzungen: Copy or Move to... Kopieren oder Verschieben nach... Show Lables Label anzeigen Compact (slower) Kompakt (langsamer) Show Clipboard Zwischenablage anzeigen Resize Image Bildgröße ändern &File &Datei &Edit &Bearbeiten &Go &Los &View &Ansicht &Help &Hilfe <p>Git release <p>Git-Version Built with Qt <p>Kompiliert mit Qt Invalid selection Ungültige Auswahl Error Fehler Failed to copy or move image Kopieren oder Verschieben des Bildes fehlgeschlagen Can not copy or move to Kopieren oder Verschieben nicht möglich Can not cut and paste in the same folder Ausschneiden und Einfügen im selben Verzeichnis nicht möglich Copied Kopiert Moved Verschoben images Bilder Delete image Bild löschen Permanently delete Endgültig löschen Failed to delete image Löschen des Bildes fehlgeschlagen No selection Keine Auswahl Delete images Bilder löschen Permanently delete selected images? Möchten Sie die ausgewählten Bilder endgültig löschen? Hide Docks Title Bar Dock-Titelleisten verbergen Contributors / Code: Mitwirkende / Code: Contributors / Translations: Mitwirkende / Übersetzungen: Failed to start external application. Externe Anwendung konnte nicht gestartet werden. Invalid selection. Ungültige Auswahl. Failed to copy or move image. Kopieren oder Verschieben des Bildes fehlgeschlagen. Zoom %1% Zoom %1% Rotation %1u00B0 Drehung %1u00B0 %n image(s) %n Bild %n Bilder Yes Ja Cancel Abbrechen Deleted Gelöscht Invalid Path: Ungültiger Pfad: Preview Vorschau No images Keine Bilder Failed to open file Öffnen der Datei fehlgeschlagen , file not found , Datei wurde nicht gefunden Slide show stopped Diashow angehalten Slide show started Diashow gestartet Can not move or copy images to this folder Verschieben oder Kopieren von Bildern in dieses Verzeichnis nicht möglich Destination folder is same as source Ziel- und Quellverzeichnis sind identisch Move Verschieben to nach Move folder Verzeichnis verschieben Failed to move folder Verschieben des Verzeichnisses fehlgeschlagen Folder moved Verzeichnis verschoben Failed to open folder: Öffnen des Verzeichnisses fehlgeschlagen: Rename Umbenennen New name: Neuer Name: Invalid name entered Name ungültig Failed to rename folder Umbenennen des Verzeichnisses fehlgeschlagen Rename Image Bild umbenennen Enter a new name for Neuen Namen eingeben No name entered Kein Name eingegeben Failed to rename image Umbenennen des Bildes fehlgeschlagen and all of its contents? und der gesamte Inhalt? Delete folder Verzeichnis löschen Failed to delete folder Löschen des Verzeichnisses fehlgeschlagen Removed Entfernt New Sub folder Neues Unterverzeichnis New folder name: Neuer Verzeichnisname: Failed to create new folder Erstellen des neuen Verzeichnisses fehlgeschlagen Created Erstellt Executing file manager... Datei-Manager ausführen... Warning Warnung Cannot perform action with temporary image Aktion kann mit temporärem Bild nicht ausgeführt werden ProgressDialog Cancel Abbrechen QObject Usage: phototonic [FILE or DIRECTORY]... Usage: phototonic [FILE or DIRECTORY]... ResizeDialog Scale Image Bild skalieren Scale Skalieren Cancel Abbrechen Original size: Originalgröße: Width: Breite: Height: Höhe: Units: Einheit: New size: Neue Größe: Original size: Originalgröße: Width: Breite: Height: Höhe: Units: Einheit: New size: Neue Größe: Pixels Pixel Percent Prozent Lock aspect ratio Größenverhältnis beibehalten SettingsDialog Preferences Einstellungen By width or height Nach Breite oder Höhe Default quality when saving images: Standard-Bildqualität beim Speichern: Label color: Labelfarbe: OK OK Cancel Abbrechen Background color: Hintergrundfarbe: Rotate image according to Exif orientation Bild gemäß EXIF-Orientierung drehen Label color: Labelfarbe: Background image: Hintergrundbild: Add space between thumbnails: Abstand zwischen den Miniaturansichten einfügen: Show original size of images smaller than the thumbnail size Originalgröße der Bilder anzeigen, wenn sie kleiner als die Miniaturansicht ist Number of thumbnail pages to read ahead: Anzahl der Seiten, die im Voraus eingelesen werden sollen: Rotate thumbnails according to Exif orientation Miniaturansichten gemäß EXIF-Orientierung drehen Keyboard shortcuts Tastenkombinationen Thumbnails Miniaturansichten Fit Large Images Große Bilder anpassen Disable Deaktivieren By width and height Nach Breite und Höhe By width Nach Breite By height Nach Höhe Stretch disproportionately Unverhältnismäßig dehnen Fit Small Images Kleine Bilder anpassen Exit instead of closing, when image is loaded from command line Beenden statt Schließen, wenn das Bild von der Kommandozeile geladen wird Wrap image list when reaching last or first image Bilderliste umbrechen, wenn das letzte oder erste Bild erreicht wird Default quality when saving images: Standard-Bildqualität beim Speichern: Enable GIF animation GIF-Animation aktivieren Open File Datei öffnen Images Bilder Rotate according to Exif orientation Gemäß EXIF-Orientierung drehen Show image file name in full screen mode Name der Bilddatei im Vollbildmodus anzeigen Background color: Hintergrundfarbe: Show image file name in viewer Dateiname im Betrachter anzeigen Background image: Hintergrundbild: Add space between thumbnails: Abstand zwischen den Miniaturansichten einfügen: Number of thumbnail pages to read ahead: Anzahl der Seiten, die im Voraus eingelesen werden sollen: Delay between slides in seconds: Verzögerung zwischen den Dias in Sekunden: Startup folder Verzeichnis bei Programmstart Default, or specified by command line argument Standard oder mit Befehlszeilenparameter angeben Remember last Letztes speichern Specify: Auswählen: Delete confirmation Löschen bestätigen Keyboard Shortcuts Tastenkombinationen Viewer Betrachter Delay between slides in seconds: Verzögerung zwischen den Dias in Sekunden: Show random images Zufällig ausgewählte Bilder anzeigen Slide Show Diashow Swap mouse left-click and middle-click actions Links-Klick- und Mittel-Klick-Aktionen der Maus tauschen Keyboard Shortcuts: Tastenkombinationen: Keyboard and Mouse Tastatur und Maus General Allgemein Choose Startup Folder Verzeichnis bei Programmstart wählen ShortcutsTable Action Aktion Shortcut Verknüpfung Delete shortcut Verknüpfung löschen Set shortcut Verknüpfung setzen "%1" is reserved for shortcuts to external applications. "%1" ist für Zugriff auf externe Programme reserviert. "%1" is already assigned to "%2" action. "%1" ist bereits "%2" zugewiesen. is reserved for shortcuts to external applications ist für Zugriff auf externe Programme reserviert is already assigned to " ist bereits " " action " zugewiesen ThumbView images Bilder Selected Ausgewählt of von File name Dateiname Location Speicherort Format Format Resolution Auflösung Megapixel Megapixel Selected %1 of %2 Ausgewählt %1 von %2 Scanned %1, displaying %2 (%3 and %4) Geprüft %1, angezeigt %2 (%3 und %4) %n original(s) %n Original %n Originale %n duplicate(s) %n Duplikat %n Duplikate Size Größe General Allgemein Modified Geändert Error Fehler %n image(s) %n Bild %n Bilder Selected %1 of%2 Ausgewählt %1 von%2 %n image(s) %n Bild %n Bilder Searching duplicate images... Suche Duplikate... Scanned Geprüft %n images, displaying %n Bild, angezeigt %n Bilder, angezeigt %n images ( %n Bild ( %n Bilder ( %n originals and %n Original und %n Originale und %n duplicates) %n Duplikat) %n Duplikate) No images Keine Bilder phototonic-2.1/translations/phototonic_en.qm000066400000000000000000000374741325127642100215140ustar00rootroot000000000000000* *% *0 + =1by3YG LbdLbLb3M JNNn/N P7TlXXXY%'i=knxF.'%Ft0A!nc/9*DQxY2P[)nsdC,e& jrIA]sn v+9Ù.fȲW +! e9N K<\ Nw 53~Nn.6f3 n% nfGQxY 9QxY3 Rg<SW4[eFuvew(w03r5C$$$Iý,u!& # ~lucz^1t-]C] ;IyII QI&I)fn1,66 o b,:fRL֓4!}x},bAa,OO $P)n*UD&0l/^ p3'~~!K]5tFFH5In4K4%$ j(Q%S0`I^ߺ(xn- #C %n69$4>e+pPtT&[_.%%_P&Z}nV'Fj/IȜ'Ѝ.D aJKD)G((4qAE !%(%*"$%8c -1Clp]4:jNI)g6g>>ממs6)=)Y #]*( `@ "% "8#R\ glh gl\ lq^ t7J y-. zdJ'W t  G *E * #T$ Ds au dg < id#, p="w p=/ q% * a M >  )$ 3 s, ye ye+ C. 2'5 }8)s ~ ~ !O ʺ, ( E-_ BnV  &e ,@~  .  A! O PG'#y R ] 4q P%x 1  ©- <,8 <4& S Ss#)5u0:&";I/6!2^ߔ&iT2!o0 #i5 Add manually AppMgmtDialogApplication path and arguments AppMgmtDialogChoose AppMgmtDialogChoose Application AppMgmtDialogManage External Applications AppMgmtDialogName AppMgmtDialogNew Application AppMgmtDialogOK AppMgmtDialogRemove AppMgmtDialogAffected Channels ColorsDialogBlue ColorsDialog Brightness ColorsDialogBrightness and Contrast ColorsDialog Color Balance ColorsDialogColorize ColorsDialogColors ColorsDialogContrast ColorsDialogGreen ColorsDialogHue ColorsDialogHue and Saturation ColorsDialog Lightness ColorsDialogOK ColorsDialogRed ColorsDialogReset ColorsDialog Saturation ColorsDialog Browse...CopyMoveToDialogCancelCopyMoveToDialog Choose FolderCopyMoveToDialog Copy to...CopyMoveToDialog Destination:CopyMoveToDialog Move to...CopyMoveToDialogOKCopyMoveToDialogRemoveCopyMoveToDialogCancel CpMvDialogCopying "%1" to "%2". CpMvDialogMoving "%1" to "%2". CpMvDialogBottom CropDialogCropping CropDialogLeft CropDialogOK CropDialogReset CropDialogRight CropDialogTop CropDialog Clipboard ImageViewError ImageViewFailed to save Exif metadata. ImageViewFailed to save image. ImageView;Hold down the Ctrl key and select a region using the mouse. ImageView Image saved. ImageViewImages ImageView No selection ImageView Save image as ImageView Saving... ImageViewCopyInfoView%n image%n images %n image(s) Phototonic&Edit Phototonic&File Phototonic&Go Phototonic&Help Phototonic&Tools Phototonic&View Phototonic!

Image viewer and organizer

 PhototonicAbout Phototonic Add Bookmark PhototonicBack Phototonic Bookmarks PhototonicBottom Phototonic Bug reports PhototonicCan not copy or move to  Phototonic'Can not copy or move to the same folder Phototonic+Can not move or copy images to this folder. PhototonicCancel Phototonic+Cannot perform action with temporary image. PhototonicClassic Thumbs Phototonic Close Image PhototonicColors PhototonicCompact PhototonicCopied PhototonicCopy PhototonicCopy Image Data Phototonic Copy to... Phototonic Created "%1" PhototonicCrop to Selection PhototonicCropping PhototonicCut PhototonicDelete Phototonic Delete folder Phototonic Delete image Phototonic Delete images PhototonicDeleted Phototonic%Destination folder is same as source. PhototonicDisable PhototonicDocks and Toolbars PhototonicDual Phototonic Dual Vertical PhototonicDuplicate images in %1 PhototonicEdit PhototonicEnlarge Thumbnails PhototonicEnter a new name for "%1": PhototonicError PhototonicExit PhototonicFailed to copy or move image. PhototonicFailed to create new folder. PhototonicFailed to delete folder. PhototonicFailed to delete image PhototonicFailed to delete image. PhototonicFailed to move folder. PhototonicFailed to open folder: PhototonicFailed to rename folder. PhototonicFailed to rename image. Phototonic%Failed to start external application. Phototonic File System PhototonicFilter PhototonicFilter by Name PhototonicFind Duplicate Images PhototonicFirst PhototonicFlip Horizontally PhototonicFlip Vertically PhototonicFlipped Horizontally PhototonicFlipped Vertically Phototonic Folder moved PhototonicForward Phototonic Full Screen PhototonicGo Up PhototonicHome Phototonic Home page PhototonicImage Phototonic Image Info PhototonicInclude Sub-folders PhototonicInitializing... Phototonic Invalid Path: PhototonicInvalid name entered. PhototonicInvalid selection PhototonicInvalid selection. PhototonicInvert Selection Phototonic Keep Zoom PhototonicLast PhototonicLoad Clipboard PhototonicLock Transformations PhototonicManage External Applications Phototonic Mirroring PhototonicMirroring Disabled PhototonicMirroring: Dual PhototonicMirroring: Dual Vertical PhototonicMirroring: Quad PhototonicMirroring: Triple PhototonicMove "%1" to "%2"? Phototonic Move Down Phototonic Move Left Phototonic Move Right PhototonicMove Up Phototonic Move folder Phototonic Move to... PhototonicMoved PhototonicName Phototonic Navigation Phototonic New Folder PhototonicNew Sub folder PhototonicNew folder name: Phototonic New name: PhototonicNext Phototonic No images PhototonicNo name entered. Phototonic No selection PhototonicOpen Phototonic Open With... Phototonic Original Size Phototonic Paste Here PhototonicPaste Image Data PhototonicPermanently delete Phototonic0Permanently delete "%1" and all of its contents? Phototonic#Permanently delete selected images? Phototonic Preferences PhototonicPrevious PhototonicQuad PhototonicRandom PhototonicReload PhototonicRemove Bookmark Phototonic Removed "%1" PhototonicRename Phototonic Rename Image Phototonic Reset Zoom PhototonicReverse PhototonicRotate 1 degree CCW PhototonicRotate 1 degree CW PhototonicRotate 90 degree CCW PhototonicRotate 90 degree CW Phototonic Rotation %1° PhototonicSave PhototonicSave As Phototonic Scale Image Phototonic Select All PhototonicSet Path PhototonicShow Hidden Files Phototonic Show Labels Phototonic Show Toolbar PhototonicShrink Thumbnails PhototonicSize Phototonic Slide Show PhototonicSlide show started PhototonicSlide show stopped Phototonic Small Icons PhototonicSort By PhototonicSquarish PhototonicStop Slide Show PhototonicTime PhototonicTop Phototonic Transform PhototonicTransformations Locked PhototonicTransformations Unlocked PhototonicTriple PhototonicType PhototonicUnflipped Horizontally PhototonicUnflipped Vertically PhototonicView PhototonicViewer PhototonicWarning PhototonicYes PhototonicZoom PhototonicZoom %1% PhototonicZoom In Phototonic Zoom Locked PhototonicZoom Out Phototonic Zoom Reset Phototonic Zoom Unlocked PhototonicCancel ResizeDialogHeight: ResizeDialogLock aspect ratio ResizeDialog New size: ResizeDialogOriginal size: ResizeDialogPercent ResizeDialogPixels ResizeDialogScale ResizeDialog Scale Image ResizeDialogUnits: ResizeDialogWidth: ResizeDialogAdd space between thumbnails:SettingsDialogBackground color:SettingsDialogBackground image:SettingsDialog By heightSettingsDialogBy widthSettingsDialogCancelSettingsDialogChoose Startup FolderSettingsDialog#Default quality when saving images:SettingsDialog.Default, or specified by command line argumentSettingsDialog Delay between slides in seconds:SettingsDialogDelete confirmationSettingsDialogDisableSettingsDialogEnable GIF animationSettingsDialog?Exit instead of closing, when image is loaded from command lineSettingsDialogFit Large ImagesSettingsDialogFit Small ImagesSettingsDialogGeneralSettingsDialogImagesSettingsDialogKeyboard ShortcutsSettingsDialog Label color:SettingsDialog(Number of thumbnail pages to read ahead:SettingsDialogOKSettingsDialog Open FileSettingsDialog PreferencesSettingsDialog Remember lastSettingsDialog*Rotate image according to Exif orientationSettingsDialog/Rotate thumbnails according to Exif orientationSettingsDialog AppMgmtDialog Manage External Applications Name Application path and arguments Choose Add manually Remove OK Choose Application New Application ColorsDialog Colors Reset OK Hue Saturation Lightness Colorize Negative Red Green Blue Hue and Saturation Affected Channels Brightness Contrast Brightness and Contrast Color Balance CopyMoveToDialog Move to... Copy to... Browse... Remove Cancel OK Destination: Choose Folder CpMvDialog Cancel Copying "%1" to "%2". Moving "%1" to "%2". CropDialog Cropping Reset OK Left Right Top Bottom ImageTags Tag Untag Clear Filters New Tag Image Tags Filter Remove Tag Negate Error Failed to save tags to Tagging Untagging Add a new tag Enter new tag name No name entered Tag already exists Remove selected tags(s)? Remove tag Yes Cancel ImageView Clipboard Selection size: No selection Hold down the Ctrl key and select a region using the mouse. Saving... Error Failed to save image. Failed to save Exif metadata. Image saved. Save image as Images InfoView Copy Phototonic Image Info Zoom Mirroring Transform View Top Bottom Close Image Full Screen Preferences Exit Enlarge Thumbnails Shrink Thumbnails Cut Copy Copy to... Move to... Delete Save Save As Copy Image Data Paste Image Data Rename Select All About Name Time Size Type Reverse Show Hidden Files Show Labels Small Icons Hide Dock Title Bars Show Toolbar Classic Thumbs Compact Squarish Reload Include Sub-folders Paste Here New Folder Back Forward Go Up Home Slide Show Next Previous First Last Random Open Load Clipboard Open With... Manage External Applications Add Bookmark Remove Bookmark Zoom Out Zoom In Reset Zoom Original Size Keep Zoom Rotate 90 degree CCW Rotate 90 degree CW Flip Horizontally Flip Vertically Cropping Crop to Selection Scale Image Rotate 1 degree CCW Rotate 1 degree CW Colors Find Duplicate Images Disable Dual Triple Dual Vertical Quad Lock Transformations Move Left Move Right Move Up Move Down Invert Selection Filter by Name Set Path &File &Edit &Go &View Sort By &Tools &Help Edit Navigation Filter Image Initializing... File System Bookmarks Tags <p>Image viewer and organizer</p> Home page Bug reports Error Failed to start external application. Invalid selection. Failed to copy or move image. Minimum zoom Zoom %1% Maximum zoom Zoom Reset Zoom Locked Zoom Unlocked Transformations Locked Transformations Unlocked Rotation %1° Flipped Vertically Unflipped Vertically Flipped Horizontally Unflipped Horizontally No selection Mirroring Disabled Mirroring: Dual Mirroring: Triple Mirroring: Dual Vertical Mirroring: Quad Can not copy or move to Can not copy or move to the same folder Copied Moved %n image(s) %n image %n images Permanently delete Delete image Yes Cancel Deleted Failed to delete image Permanently delete selected images? Delete images Failed to delete image. Deleted Invalid Path: Viewer Docks and Toolbars No images Failed to open file "%1", file not found. Slide show stopped Stop Slide Show Slide show started Can not move or copy images to this folder. Destination folder is same as source. Move "%1" to "%2"? Move folder Failed to move folder. Folder moved Failed to open folder: Duplicate images in %1 New name: Invalid name entered. Failed to rename folder. Invalid selection Rename Image Enter a new name for "%1": No name entered. Failed to rename image. Permanently delete "%1" and all of its contents? Delete folder Failed to delete folder. Removed "%1" New Sub folder New folder name: Failed to create new folder. Created "%1" Warning Cannot perform action with temporary image. ProgressDialog Cancel ResizeDialog Scale Image Scale Cancel Original size: Width: Height: Units: New size: Pixels Percent Lock aspect ratio SettingsDialog Preferences Fit Large Images Disable By width By height Stretch disproportionately Fit Small Images Exit instead of closing, when image is loaded from command line Wrap image list when reaching last or first image Default quality when saving images: Enable GIF animation Rotate image according to Exif orientation Background color: By width or height Show image file name in viewer Label color: Background image: Add space between thumbnails: Show original size of images smaller than the thumbnail size Number of thumbnail pages to read ahead: Rotate thumbnails according to Exif orientation Delay between slides in seconds: Show random images Startup folder Default, or specified by command line argument Remember last Specify: Swap mouse left-click and middle-click actions Delete confirmation Keyboard Shortcuts OK Cancel Viewer Thumbnails Slide Show General Choose Startup Folder Open File Images ShortcutsTable Action Shortcut Delete shortcut Set shortcut "%1" is reserved for shortcuts to external applications. "%1" is already assigned to "%2" action. ThumbView General File name Location Size Modified Format Resolution Megapixel Error %n image(s) %n image %n images No images Selected %1 of%2 %n image(s) %n image %n images Scanned %1, displaying %2 (%3 and %4) %n original(s) %n original %n originals %n duplicate(s) %n duplicates %n duplicate %n duplicates Searching duplicate images... phototonic-2.1/translations/phototonic_fr.qm000066400000000000000000000720171325127642100215110ustar00rootroot00000000000000BEiG5HeIJ]Kx20h&o('A>b"**%*0y+1byeGLb LbQLb#Lbf+M + N-oNn2DNP7.Tl8)XX X Y%O~\Zw~ikn/fxFVMFt,AE 5n$c_9#V*:uQxYd[)n dCWeKj;rIA"asn7V!Ù.$2Ȳ0< W! 9NA<\N?[w 5fZ~*n[f3@)%9_ +RfG@QxYQxYe|Rg<4QSW45eFu5zoG ve%w(.Ew `ri(+CI$IýY(u}w- } !& #BKlu7@z^ctZ] 0]IDI *I IIMPIMIRfb66|o '>,Z'U: :*BfR8֓fDh}}X1Aa+B= 0FW zKإ#O,SO JKP)nU{UDL"l/^(p3OK~~DK]>5t?$FFH5?nggu%I jP$J`I^-/ߺP[n[+) /#Cb%n6W9$g>eVPtTM[_.%K_PLj}n)VNj\F7j^77ȜOЍ$D( HJDQ(:1(gq<E6C~O*E%8c-"Cl(qA0>%W0Lמ מ:6R=QxY Hn]*Q"@! FE%F8Gg@> gl [ gl lq^;> t7J9 y-] zdJNt tC8 *s G3 DRY T T #TH Ds" a9 dg idG/ p=F p=^ q%; *' aC  >& + )4 3S sX ye!M yeU C^ 2'h( }8R ~ ~ C ʺY{ P ص EZC Bnb ) &e1l ,@~B , T .Ao A O PG'G Pr R? Z Td/ ڎ Nh  DC} Sd3 h`B i, p r. ] g< PK c ] © <Xb <f S S\sF)15ua:=f3q:M3.?";I_d6!e ^ߔLiTdo0#8ii(Ajouter manuellement Add manually AppMgmtDialogNEmplacement et options de l'applicationApplication path and arguments AppMgmtDialogChoisirChoose AppMgmtDialog*Choisir l'applicationChoose Application AppMgmtDialogBGestion des applications externesManage External Applications AppMgmtDialogNomName AppMgmtDialog(Nouvelle ApplicationNew Application AppMgmtDialogOKOK AppMgmtDialogSupprimerRemove AppMgmtDialogCanaux affectsAffected Channels ColorsDialogBleuBlue ColorsDialogLuminosit Brightness ColorsDialog.Luminosit et ContrasteBrightness and Contrast ColorsDialog(Balance des couleurs Color Balance ColorsDialogColoriserColorize ColorsDialogCouleursColors ColorsDialogContrasteContrast ColorsDialogVertGreen ColorsDialog TeinteHue ColorsDialog(Teinte et SaturationHue and Saturation ColorsDialog Clart Lightness ColorsDialogNgatifNegative ColorsDialogOKOK ColorsDialog RougeRed ColorsDialogRinitialiserReset ColorsDialogSaturation Saturation ColorsDialogParcourir... Browse...CopyMoveToDialogAnnulerCancelCopyMoveToDialog.Slectionner le dossier Choose FolderCopyMoveToDialogCopier vers... Copy to...CopyMoveToDialogDestination : Destination:CopyMoveToDialog Dplacer vers... Move to...CopyMoveToDialogOKOKCopyMoveToDialogSupprimerRemoveCopyMoveToDialogAnnulerCancel CpMvDialog0Copie de "%1" vers "%2".Copying "%1" to "%2". CpMvDialog<Dplacement de "%1" vers "%2".Moving "%1" to "%2". CpMvDialogBasBottom CropDialog RognerCropping CropDialog GaucheLeft CropDialogOKOK CropDialogRinitialiserReset CropDialog DroiteRight CropDialogHautTop CropDialog existe dj already exists ImageTags,Ajouter un nouveau tag Add a new tag ImageTagsAnnulerCancel ImageTags&Effacer les filtres Clear Filters ImageTags8Entrer le nouveau nom du tagEnter new tag name ImageTags ErreurError ImageTagsJchec de la sauvegarde des tags vers Failed to save tags to  ImageTags FiltreFilter ImageTagsTag de l'image Image Tags ImageTagsAnnulerNegate ImageTagsNouveau tagNew Tag ImageTagsAucun nom saisiNo name entered ImageTags Supprimer le tag Remove Tag ImageTagsNSupprimer le(s) tag(s) slectionn(s) ?Remove selected tags(s)? ImageTags Supprimer le tag Remove tag ImageTags TaguerTag ImageTagsLe tag Tag  ImageTags Tague Tagging  ImageTagsDtaguerUntag ImageTagsDtague  Untagging  ImageTagsOuiYes ImageTagsPresse-papier Clipboard ImageView ErreurError ImageViewZchec de la sauvegarde des mta-donnes Exif.Failed to save Exif metadata. ImageViewDchec de la sauvegarde de l'image.Failed to save image. ImageViewMaintenez la touche Ctrl enfonce et slectionnez une rgion l'aide de la souris.;Hold down the Ctrl key and select a region using the mouse. ImageView$Image enregistre. Image saved. ImageView ImagesImages ImageView Aucune slection No selection ImageView0Enregistrer l'image sous Save image as ImageView,Sauvegarde en cours... Saving... ImageView2Slection de la taille : Selection size:  ImageView CopierCopyInfoView%n image%n images %n image(s) Phototonic&dition&Edit Phototonic&Fichier&File PhototonicA&ller &Go Phototonic &Aide&Help Phototonic&Outils&Tools PhototonicAfficha&ge&View PhototonicV<p>Visionneuse et organisatrice d'image</p>!

Image viewer and organizer

 Phototonic propos deAbout Phototonic&Ajouter aux signets Add Bookmark Phototonic RetourBack PhototonicSignets Bookmarks PhototonicBasBottom Phototonic"Rapports de bogue Bug reports PhototonicLImpossible de copier ou dplacer vers Can not copy or move to  PhototonicjImpossible de copier ou dplacer dans le mme dossier'Can not copy or move to the same folder PhototonicxImpossible de dplacer ou couper les images dans ce dossier.+Can not move or copy images to this folder. PhototonicAnnulerCancel PhototonicvImpossible d'excuter cette action avec l'image temporaire.+Cannot perform action with temporary image. PhototonicClassiqueClassic Thumbs PhototonicFermer l'image Close Image PhototonicCouleursColors PhototonicCompactCompact Phototonic CopiCopied Phototonic CopierCopy Phototonic8Copier le contenu de l'imageCopy Image Data PhototonicCopier vers... Copy to... PhototonicCr "%1" Created "%1" Phototonic6Rogner jusqu' la slectionCrop to Selection Phototonic RognerCropping Phototonic CouperCut PhototonicSupprimerDelete Phototonic(Supprimer le dossier Delete folder Phototonic"Supprimer l'image Delete image Phototonic(Supprimer les images Delete images PhototonicSupprimDeleted PhototonicSupprimDeleted  Phototonic~Le dossier de destination et le dossier source sont identiques.%Destination folder is same as source. PhototonicDsactiverDisable Phototonic0Docks et Barres d'outilsDocks and Toolbars Phototonic DoubleDual PhototonicDouble vertical Dual Vertical Phototonic2Images dupliques dans %1Duplicate images in %1 PhototonicditionEdit Phototonic,Agrandir les vignettesEnlarge Thumbnails PhototonicBSaisir un nouveau nom pour "%1" :Enter a new name for "%1": Phototonic ErreurError PhototonicQuitterExit Phototonic^chec de la copie ou du dplacement de l'image.Failed to copy or move image. PhototonicPchec de la cration du nouveau dossier.Failed to create new folder. PhototonicFchec de la suppression du dossier.Failed to delete folder. PhototonicDchec de la suppression de l'imageFailed to delete image PhototonicFchec de la suppression de l'image.Failed to delete image. Phototonic@chec du dplacement du dossier.Failed to move folder. Phototonictchec de l'ouverture du fichier "%1", fichier introuvable.)Failed to open file "%1", file not found. PhototonicBchec de l'ouverture du dossier :Failed to open folder: Phototonic<chec du renommage du dossier.Failed to rename folder. Phototonic<chec du renommage de l'image.Failed to rename image. PhototonicXchec du lancement de l'application externe.%Failed to start external application. Phototonic&Systme de fichiers File System Phototonic FiltreFilter PhototonicFiltrer par nomFilter by Name Phototonic.Rechercher des doublonsFind Duplicate Images PhototonicPremierFirst Phototonic"Miroir horizontalFlip Horizontally PhototonicMiroir verticalFlip Vertically Phototonic0Retourn l'horizontaleFlipped Horizontally Phototonic.Retourn la verticaleFlipped Vertically PhototonicDossier dplac Folder moved PhototonicAvancerForward PhototonicPlein cran Full Screen Phototonic MonterGo Up PhototonicFMasquer les barres de titre du dockHide Dock Title Bars Phototonic DbutHome PhototonicPage d'accueil Home page Phototonic ImageImage Phototonic"Information Image Image Info Phototonic2Inclure les sous-dossiersInclude Sub-folders Phototonic"Initialisation...Initializing... Phototonic,Emplacement invalide : Invalid Path: Phototonic&Nom saisi invalide.Invalid name entered. Phototonic$Slection invalideInvalid selection Phototonic&Slection invalide.Invalid selection. Phototonic*Inverser la slectionInvert Selection Phototonic"Conserver le zoom Keep Zoom PhototonicDernierLast Phototonic0Charger le presse-papierLoad Clipboard Phototonic>Verrouiller les transformationsLock Transformations Phototonic>Grer les applications externesManage External Applications PhototonicZoom maximum Maximum zoom PhototonicZoom minimum Minimum zoom PhototonicEffet miroir Mirroring Phototonic,Effet miroir dsactivMirroring Disabled Phototonic*Effet miroir : doubleMirroring: Dual Phototonic<Effet miroir : double verticalMirroring: Dual Vertical Phototonic0Effet miroir : quadrupleMirroring: Quad Phototonic*Effet miroir : tripleMirroring: Triple Phototonic>Dplacement de "%1" vers "%2" ?Move "%1" to "%2"? Phototonic(Dplacer vers le bas Move Down Phototonic.Dplacer vers la gauche Move Left Phototonic.Dplacer vers la droite Move Right Phototonic*Dplacer vers le hautMove Up Phototonic&Dplacer le dossier Move folder Phototonic Dplacer vers... Move to... PhototonicDplacerMoved PhototonicNomName PhototonicNavigation Navigation PhototonicNouveau dossier New Folder Phototonic(Nouveau sous-dossierNew Sub folder Phototonic0Nom du nouveau dossier :New folder name: PhototonicNouveau nom : New name: PhototonicSuivantNext PhototonicAucunes images No images Phototonic Aucun nom saisi.No name entered. Phototonic Aucune slection No selection Phototonic OuvrirOpen PhototonicOuvrir avec... Open With... Phototonic Taille d'origine Original Size PhototonicColler ici Paste Here Phototonic8Coller le contenu de l'imagePaste Image Data Phototonic0Supprimer dfinitivementPermanently delete PhototonicrSupprimer dfinitivement "%1" et tout ce qu'il contient ?0Permanently delete "%1" and all of its contents? PhototonicfSupprimer dfinitivement les images slectionnes ?#Permanently delete selected images? PhototonicPrfrences Preferences PhototonicPrcdentPrevious PhototonicQuadrupleQuad PhototonicAlatoireRandom PhototonicRechargerReload Phototonic&Retirer des signetsRemove Bookmark PhototonicSupprim "%1" Removed "%1" PhototonicRenommerRename Phototonic Renommer l'image Rename Image Phototonic*Rinitialiser le zoom Reset Zoom PhototonicInverserReverse Phototonic@Rotation de 1 sens anti-horaireRotate 1 degree CCW Phototonic6Rotation de 1 sens horaireRotate 1 degree CW PhototonicBRotation de 90 sens anti-horaireRotate 90 degree CCW Phototonic8Rotation de 90 sens horaireRotate 90 degree CW PhototonicRotation de %1 Rotation %1° PhototonicEnregistrerSave Phototonic Enregistrer sousSave As Phototonic,Redimensionner l'image Scale Image Phototonic"Tout slectionner Select All Phototonic"Dfinir le cheminSet Path Phototonic8Afficher les fichiers cachsShow Hidden Files Phototonic&Afficher les labels Show Labels Phototonic4Afficher la barre d'outils Show Toolbar Phototonic,Rtrcir les vignettesShrink Thumbnails Phototonic TailleSize PhototonicDiaporama Slide Show Phototonic"Diaporama dmarrSlide show started Phototonic Diaporama stoppSlide show stopped PhototonicPetites icnes Small Icons PhototonicTrier parSort By Phototonic CarrSquarish Phototonic(Arrter le diaporamaStop Slide Show PhototonicTagsTags PhototonicDateTime PhototonicHautTop PhototonicTransformer Transform Phototonic8Transformations verrouillesTransformations Locked Phototonic<Transformations dverrouillesTransformations Unlocked Phototonic TripleTriple PhototonicTypeType Phototonic.Rtabli l'horizontaleUnflipped Horizontally Phototonic,Rtabli la verticaleUnflipped Vertically PhototonicAffichageView PhototonicVisionneuseViewer PhototonicAvertissementWarning PhototonicOuiYes PhototonicZoomZoom PhototonicZoom %1%Zoom %1% PhototonicZoom avantZoom In PhototonicZoom verrouill Zoom Locked PhototonicZoom arrireZoom Out Phototonic0Rinitialisation du zoom Zoom Reset Phototonic"Zoom dverrouill Zoom Unlocked PhototonicAnnulerCancelProgressDialogAnnulerCancel ResizeDialogHauteur :Height: ResizeDialogLVrrouiller le rapport hauteur/largeurLock aspect ratio ResizeDialog"Nouvelle taille : New size: ResizeDialog$Taille d'origine :Original size: ResizeDialogPourcentPercent ResizeDialog PixelsPixels ResizeDialogRedimensionnerScale ResizeDialog8Redimensionnement de l'image Scale Image ResizeDialogUnits :Units: ResizeDialogLargeur :Width: ResizeDialogNAjouter un espace entre les vignettes :Add space between thumbnails:SettingsDialog"Couleur de fond :Background color:SettingsDialogImage de fond :Background image:SettingsDialogPar la hauteur By heightSettingsDialogPar la largeurBy widthSettingsDialog,Par largeur ou hauteurBy width or heightSettingsDialogAnnulerCancelSettingsDialog>Choisir le dossier de dmarrageChoose Startup FolderSettingsDialogjQualit par dfaut lors de la sauvegarde des images :#Default quality when saving images:SettingsDialog|Par dfaut, ou spcifi par l'argument de la ligne de commande.Default, or specified by command line argumentSettingsDialogTTemps entre les diapositives en secondes : Delay between slides in seconds:SettingsDialog2Supprimer la confirmationDelete confirmationSettingsDialogDsactiverDisableSettingsDialog.Activer l'animation GIFEnable GIF animationSettingsDialogQuitter au lieu de fermer, quand l'image est charge depuis la ligne de commande?Exit instead of closing, when image is loaded from command lineSettingsDialog:Adaptation des grandes imagesFit Large ImagesSettingsDialog:Adaptation des petites imagesFit Small ImagesSettingsDialogGnralGeneralSettingsDialog ImagesImagesSettingsDialog$Raccourcis clavierKeyboard ShortcutsSettingsDialog$Couleur du label : Label color:SettingsDialogTNombre de pages de vignettes parcourir :(Number of thumbnail pages to read ahead:SettingsDialogOKOKSettingsDialog"Ouvrir un fichier Open FileSettingsDialogPrfrences PreferencesSettingsDialog&Rappeler le dernier Remember lastSettingsDialogXRotation de l'image selon l'orientation Exif*Rotate image according to Exif orientationSettingsDialog^Rotation des vignettes selon l'orientation Exif/Rotate thumbnails according to Exif orientationSettingsDialog\Afficher le nom de l'image dans la visionneuseShow image file name in viewerSettingsDialogAfficher la taille d'origine des images qui sont plus petites que les vignettes AppMgmtDialog Manage External Applications Gestion des applications externes Name Nom Application path and arguments Emplacement et options de l'application Choose Choisir Add manually Ajouter manuellement Remove Supprimer OK OK Choose Application Choisir l'application New Application Nouvelle Application ColorsDialog Colors Couleurs Reset Réinitialiser OK OK Hue Teinte Saturation Saturation Lightness Clarté Channels Canaux Enable Activer Colorize Coloriser Negative Négatif Red Rouge Green Vert Blue Bleu Hue and Saturation Teinte et Saturation Affected Channels Canaux affectés Brightness Luminosité Contrast Contraste Brightness and Contrast Luminosité et Contraste Color Balance Balance des couleurs CopyMoveToDialog Copy or Move Images to... Copier ou Déplacer les images vers... Add Ajouter Move to... Déplacer vers... Copy to... Copier vers... Browse... Parcourir... Remove Supprimer Cancel Annuler OK OK Destination: Destination : Destination: Destination : Close Fermer Copy Copier Move Déplacer Choose Folder Sélectionner le dossier CpMvDialog Cancel Annuler Copying "%1" to "%2". Copie de "%1" vers "%2". Moving "%1" to "%2". Déplacement de "%1" vers "%2". Copying Copie de Moving Déplacement de to vers CropDialog Cropping Rogner Reset Réinitialiser OK OK Top Haut Left Gauche Right Droite Bottom Bas ImageTags Tag Taguer Untag Détaguer Clear Filters Effacer les filtres New Tag Nouveau tag Image Tags Tag de l'image Filter Filtre Remove Tag Supprimer le tag Negate Annuler Error Erreur Failed to save tags to Échec de la sauvegarde des tags vers Tagging Tague Untagging Détague Add a new tag Ajouter un nouveau tag Enter new tag name Entrer le nouveau nom du tag No name entered Aucun nom saisi Tag Le tag already exists existe déjà Remove selected tags(s)? Supprimer le(s) tag(s) sélectionné(s) ? Remove tag Supprimer le tag Yes Oui Cancel Annuler ImageView Clipboard Presse-papier Selection size: Sélection de la taille : No selection Aucune sélection Hold down the Ctrl key and select a region using the mouse. Maintenez la touche Ctrl enfoncée et sélectionnez une région à l'aide de la souris. Failed to save image. Échec de la sauvegarde de l'image. Failed to save Exif metadata. Échec de la sauvegarde des méta-données Exif. Image saved. Image enregistrée. Hold down the Ctrl key and select a region using the mouse Maintenez la touche Ctrl enfoncée et sélectionnez une région à l'aide de la souris Saving... Sauvegarde en cours... Error Erreur Failed to save image Échec de la sauvegarde de l'image Failed to save Exif metadata Échec de la sauvegarde des méta-données Exif Image saved Image enregistrée Save image as Enregistrer l'image sous Images Images Image Files Fichiers Image InfoView Copy Copier KeyGrabLineEdit Set shortcut Définir un raccourci is reserved for shortcuts to external applications est réservé pour les raccourcis d'applications externes is already assigned to " est déjà attribué à " " action " action Phototonic Docks and Toolbars Docks et Barres d'outils Image Info Information Image Zoom Zoom Transform Transformer Mirroring Effet miroir Top Haut Bottom Bas Close Image Fermer l'image Full Screen Plein écran Preferences Préférences Exit Quitter Enlarge Thumbnails Agrandir les vignettes Shrink Thumbnails Rétrécir les vignettes Cut Couper Copy Copier Copy or Move to... Copier ou Déplacer vers... Delete Supprimer Save Enregistrer Save As Enregistrer sous Copy Image Copier l'image Paste Image Coller l'image Rename Renommer Select All Tout sélectionner About À propos de Name Nom Time Date Size Taille Type Type Reverse Inverser Show Hidden Files Afficher les fichiers cachés Show Labels Afficher les labels Small Icons Petites icônes Hide Docks Title Bar Masquer la barre de titre des Docks Show Toolbar Afficher la barre d'outils Classic Thumbs Classique Compact Compact Squarish Carré Reload Recharger Include Sub-folders Inclure les sous-dossiers Paste Here Coller ici New Folder Nouveau dossier Manage Gérer Back Retour Forward Avancer Up Monter Home Début Slide Show Diaporama Next Suivant Previous Précédent First Premier Last Dernier Random Aléatoire Open Ouvrir Show Clipboard Afficher le presse-papier Open With Ouvrir avec Manage External Applications Gérer les applications externes Add Bookmark Ajouter aux signets Remove Bookmark Retirer des signets Zoom Out Zoom arrière Zoom In Zoom avant Reset Zoom Réinitialiser le zoom Original Size Taille d'origine Keep Zoom Conserver le zoom Rotate 90 degree CCW Rotation de 90° sens anti-horaire Rotate 90 degree CW Rotation de 90° sens horaire Flip Horizontally Miroir horizontal Flip Vertically Miroir vertical Cropping Rogner Crop to Selection Rogner jusqu'à la sélection Scale Image Redimensionner l'image Rotate 1 degree CCW Rotation de 1° sens anti-horaire Rotate 1 degree CW Rotation de 1° sens horaire Colors Couleurs Find Duplicate Images Rechercher des doublons Disable Désactiver Dual Double Triple Triple Dual Vertical Double vertical Quad Quadruple Tags Tags Minimum zoom Zoom minimum Maximum zoom Zoom maximum Rotation %1° Rotation de %1° Failed to open file "%1", file not found. Échec de l'ouverture du fichier "%1", fichier introuvable. Failed to open file "%1": file not found. Échec de l'ouverture du fichier "%1": fichier introuvable. Can not move or copy images to this folder. Impossible de déplacer ou couper les images dans ce dossier. Destination folder is same as source. Le dossier de destination et le dossier source sont identiques. Move "%1" to "%2"? Déplacement de "%1" vers "%2" ? Failed to move folder. Échec du déplacement du dossier. Failed to open folder: Échec de l'ouverture du dossier : Duplicate images in %1 Images dupliquées dans %1 Invalid name entered. Nom saisi invalide. Failed to rename folder. Échec du renommage du dossier. Enter a new name for "%1": Saisir un nouveau nom pour "%1" : No name entered. Aucun nom saisi. Failed to rename image. Échec du renommage de l'image. Permanently delete "%1" and all of its contents? Supprimer définitivement "%1" et tout ce qu'il contient ? Failed to delete folder. Échec de la suppression du dossier. Removed "%1" Supprimé "%1" Failed to create new folder. Échec de la création du nouveau dossier. Created "%1" Créé "%1" Cannot perform action with temporary image. Impossible d'exécuter cette action avec l'image temporaire. Keep Transformations Conserver les transformations Move Left Déplacer vers la gauche Move Right Déplacer vers la droite Move Up Déplacer vers le haut Move Down Déplacer vers le bas Invert Selection Inverser la sélection Filter by Name Filtrer par nom Set Path Définir le chemin &File &Fichier &Edit &Édition &Go A&ller à &View Afficha&ge Sort By Trier par &Tools &Outils &Help &Aide Edit Édition Navigation Navigation View Affichage Filter Filtre Initializing... Initialisation... File System Système de fichiers <p>Image viewer and organizer</p> <p>Visionneuse et organisatrice d'image</p> <p>Git release <p>Révision Git Built with Qt Compilé avec Qt Home page Page d'accueil Bug reports Rapports de bogue Failed to start external application. Échec du lancement de l'application externe. Invalid selection. Sélection invalide. Failed to copy or move image. Échec de la copie ou du déplacement de l'image. Zoom %1% Zoom à %1% Rotation %1u00B0 Rotation de %1u00B0 Copied Copié Moved Déplacer %n image(s) %n image %n images Permanently delete Supprimer définitivement Failed to delete image. Échec de la suppression de l'image. Deleted Supprimé Invalid Path: Emplacement invalide : Viewer Visionneuse Contributors:<br> Contributeurs:<br> Contributors / Translations:<br> Contributeurs / Traductions:<br> Invalid selection Sélection invalide Error Erreur Copy to... Copier vers... Move to... Déplacer vers... Copy Image Data Copier le contenu de l'image Paste Image Data Coller le contenu de l'image Hide Dock Title Bars Masquer les barres de titre du dock Go Up Monter Load Clipboard Charger le presse-papier Open With... Ouvrir avec... Lock Transformations Verrouiller les transformations Image Image Bookmarks Signets Failed to start external application Échec du lancement de l'application externe Failed to copy or move image Échec de la copie ou du déplacement de l'image Zoom Out to Zoom arrière sur Zoom In to Zoom avant sur Zoom Reset Réinitialisation du zoom Zoom Locked Zoom verrouillé Zoom Unlocked Zoom déverrouillé Transformations Locked Transformations verrouillées Transformations Unlocked Transformations déverrouillées Rotation Rotation de Flipped Vertically Retourné à la verticale Unflipped Vertically Rétabli à la verticale Flipped Horizontally Retourné à l'horizontale Unflipped Horizontally Rétabli à l'horizontale Mirroring Disabled Effet miroir désactivé Mirroring: Dual Effet miroir : double Mirroring: Triple Effet miroir : triple Mirroring: Dual Vertical Effet miroir : double vertical Mirroring: Quad Effet miroir : quadruple Can not copy or move to Impossible de copier ou déplacer vers Can not cut and paste in the same folder Impossible de couper et coller dans le même dossier Copied Copié Moved Déplacé images images Delete image Supprimer l'image Permanently delete Supprimer définitivement Failed to delete image Échec de la suppression de l'image No selection Aucune sélection Delete images Supprimer les images Permanently delete selected images? Supprimer définitivement les images sélectionnées ? Contributors / Code: Contributeurs / Code : Contributors / Translations: Contributeurs / Traductions : Zoom Zoom à Can not copy or move to the same folder Impossible de copier ou déplacer dans le même dossier image(s) image(s) Yes Oui Cancel Annuler Deleted Supprimé Invalid Path: Emplacement invalide : Preview Prévisualisation No images Aucunes images Failed to open file Échec de l'ouverture du fichier , file not found , fichier introuvable Slide show stopped Diaporama stoppé Stop Slide Show Arrêter le diaporama Slide show started Diaporama démarré Can not move or copy images to this folder Impossible de déplacer ou couper les images dans ce dossier Destination folder is same as source Le dossier de destination et le dossier source sont identiques Move Déplacer to vers Move folder Déplacer le dossier Failed to move folder Échec du déplacement du dossier Folder moved Dossier déplacé Failed to open folder: Échec de l'ouverture du dossier : Rename Renommer New name: Nouveau nom : Invalid name entered Nom saisi invalide Failed to rename folder Échec du renommage du dossier Rename Image Renommer l'image Enter a new name for Saisir un nouveau nom pour No name entered Aucun nom saisi Failed to rename image Échec du renommage de l'image and all of its contents? et tout ce qu'il contient ? Delete folder Supprimer le dossier Failed to delete folder Échec de la suppression du dossier Removed Supprimé New Sub folder Nouveau sous-dossier New folder name: Nom du nouveau dossier : Failed to create new folder Échec de la création du nouveau dossier Created Créé Executing file manager... Exécution du gestionnaire de fichiers... Warning Avertissement Cannot perform action with temporary image Impossible d'exécuter cette action avec l'image temporaire ProgressDialog Cancel Annuler QObject Usage: phototonic [FILE or DIRECTORY]... Utilisation : phototonic [FICHIER ou REPERTOIRE]... ResizeDialog Scale Image Redimensionnement de l'image Scale Redimensionner Cancel Annuler Original size: Taille d'origine : Width: Largeur : Height: Hauteur : Units: Unités : New size: Nouvelle taille : Original size: Taille d'origine : Width: Largeur : Height: Hauteur : Units: Unités : New size: Nouvelle taille : Pixels Pixels Percent Pourcent Lock aspect ratio Vérrouiller le rapport hauteur/largeur SettingsDialog Preferences Préférences Fit Large Images Adaptation des grandes images Disable Désactiver By width and height Par la largeur et la hauteur By width Par la largeur By height Par la hauteur Stretch disproportionately Étirer de manière disproportionnée Fit Small Images Adaptation des petites images Background color: Couleur de fond : Exit instead of closing, when image is loaded from command line Quitter au lieu de fermer, quand l'image est chargée depuis la ligne de commande Wrap image list when reaching last or first image Enrouler la liste d'image en arrivant à la dernière ou à la première image Default quality when saving images: Qualité par défaut lors de la sauvegarde des images : Background color: Couleur de fond : By width or height Par largeur ou hauteur Show image file name in viewer Afficher le nom de l'image dans la visionneuse Background image: Image de fond : Add space between thumbnails: Ajouter un espace entre les vignettes : Number of thumbnail pages to read ahead: Nombre de pages de vignettes à parcourir : Delay between slides in seconds: Temps entre les diapositives en secondes : Default quality when saving images: Qualité par défaut lors de la sauvegarde des images : Enable GIF animation Activer l'animation GIF Rotate image according to Exif orientation Rotation de l'image selon l'orientation Exif Show image file name in full screen mode Afficher le nom du fichier de l'image en mode plein écran Label color: Couleur du label : Background image: Image de fond : Add space between thumbnails: Ajouter un espace entre les vignettes : Show original size of images smaller than the thumbnail size Afficher la taille d'origine des images qui sont plus petites que les vignettes Number of thumbnail pages to read ahead: Nombre de pages de vignettes à parcourir : Rotate thumbnails according to Exif orientation Rotation des vignettes selon l'orientation Exif Delay between slides in seconds: Temps entre les diapositives en secondes : Label color: Couleur du label : Show random images Afficher des images aléatoires Startup folder Dossier de démarrage Default, or specified by command line argument Par défaut, ou spécifié par l'argument de la ligne de commande Remember last Rappeler le dernier Specify: Spécifier : Swap mouse left-click and middle-click actions Permuter les actions des clic gauche et clic du milieu de la souris Delete confirmation Supprimer la confirmation Keyboard Shortcuts Raccourcis clavier Open File Ouvrir un fichier Images Images Keyboard shortcuts Raccourcis clavier OK OK Cancel Annuler Viewer Visionneuse Thumbnails Vignettes Slide Show Diaporama General Général Choose Startup Folder Choisir le dossier de démarrage ShortcutsTable Action Action Shortcut Raccourci Delete shortcut Supprimer le raccourci Set shortcut Définir un raccourci "%1" is reserved for shortcuts to external applications. "%1" est réservé pour les raccourcis d'applications externes. "%1" is already assigned to "%2" action. "%1" est déjà attribué à "%2" action. is reserved for shortcuts to external applications est réservé pour les raccourcis d'applications externes is already assigned to " est déjà attribué à " " action " action ThumbView images images Selected Sélection de of sur File name Nom du fichier Location Emplacement Format Format Resolution Résolution Megapixel Mégapixel Selected %1 of %2 Sélection de %1 sur %2 Scanned %1, displaying %2 (%3 and %4) Analyse de %1, affichage de %2 (%3 et %4) %n original(s) %n original %n originaux %n duplicate(s) %n doublon %n doublons Size Taille General Général Modified Modifié Error Erreur %n image(s) %n image %n images Selected %1 of%2 Sélection de %1 sur%2 %n image(s) %n image %n images Searching duplicate images... Recherche de doublons... Scanned Analyse de %n images, displaying %n image, affichage de %n images, affichage de %n images ( %n image pertinente ( %n images pertinentes ( %n originals and %n original et %n originaux et %n duplicates) %n doublon) %n doublons) No images Aucunes images phototonic-2.1/translations/phototonic_hr.qm000066400000000000000000000660011325127642100215070ustar00rootroot00000000000000Z**%E*0+1by]GLb 9LbLb!Lb^\M 'TN)Nn-NP7*bTl2X3X XX Y%I\Zw ikn+9xFDGFt(A?+1 n"cXX9 *5 QxY\[)ndCPeEj60rIAsnO:Ù.!xȲ,7o P! 9N< <\N9w 5^~&nTf3:f%4$ 'fG;QxYQxY]}Rg</lSW40GeFu0oG %ve"w(*w AYra;("CD$CFýRu } !& #<lu2-z^[tS] ]xIII rIIGIGTIL/fZ6<6<o,Z' : :&xfR3֓^>}}Qy-AaB= hFW O(}O DpP)nNUDF%l/^%,p3H~~>K]9*5t9aFuF}H5:/n_'_%C jIDYTI^)WߺInT&8 +}#CB%n6 9$`>eOPtTF[k_.%E_PFi}n%HSjUMF2kjW_7 73ȜHЍD0( JDKW(4(_q6E=IW*?~%8c-wCl7"]41jN#cLgg2>$A0I>"0מIמ5q6Ld=KY B]*J@ @V%f@8A:8 gl gl9 lq^5 t7J4w y-U zdJH t=o & G. DK M` N #TB Ds M a3 dgi idAJ p=@ p=W q%6 *$@ a  ># ' )/ 3 sQ ye yeN CV 2'`K }8K ~u ~_ = ʺRL J ص ES4 Bn  &e-' ,@~ , .; A^ O PG'A Pr R< u1f u1 8g Zn+ 8 Sv T\ ڎ N`  < DC# Sd/ h`< i)! r* ] _] PE1 [  ©e <Q? <^ Sc S(sA ),5uY8:G9";IW6!]^ߔFiT\_o0 3UiaDodaj ru no Add manually AppMgmtDialog<Putanja i argumenti aplikacijeApplication path and arguments AppMgmtDialogIzaberiChoose AppMgmtDialog$Izaberi aplikacijuChoose Application AppMgmtDialog@Upravljaj eksternim aplikacijamaManage External Applications AppMgmtDialogImeName AppMgmtDialogNova aplikacijaNew Application AppMgmtDialog UreduOK AppMgmtDialog UkloniRemove AppMgmtDialogPogoeni kanaliAffected Channels ColorsDialog PlavaBlue ColorsDialogSvjetlost Brightness ColorsDialog(Svjetlost i kontrastBrightness and Contrast ColorsDialogBalans boja Color Balance ColorsDialog ObojiColorize ColorsDialogBojeColors ColorsDialogKontrastContrast ColorsDialog ZelenaGreen ColorsDialogNijansaHue ColorsDialog(Nijansa i zasienostHue and Saturation ColorsDialogSvjetlina Lightness ColorsDialogNegativNegative ColorsDialog UreduOK ColorsDialog CrvenaRed ColorsDialogPovratiReset ColorsDialogZasienost Saturation ColorsDialogPregledaj... Browse...CopyMoveToDialog Otka~iCancelCopyMoveToDialog Izaberi fasciklu Choose FolderCopyMoveToDialogKopiraj u... Copy to...CopyMoveToDialogDestinacija: Destination:CopyMoveToDialogPomjeri u... Move to...CopyMoveToDialog UreduOKCopyMoveToDialog UkloniRemoveCopyMoveToDialog Otka~iCancel CpMvDialog(Kopiram "%1" u "%2".Copying "%1" to "%2". CpMvDialog*Pomjeram "%1" u "%2".Moving "%1" to "%2". CpMvDialogDoleBottom CropDialog Izre~iCropping CropDialog LijevoLeft CropDialog UreduOK CropDialogPovratiReset CropDialog DesnoRight CropDialogGoreTop CropDialogve postoji already exists ImageTags"Dodaj novu oznaku Add a new tag ImageTags Otka~iCancel ImageTagsUkloni filtere Clear Filters ImageTags Unesi ime oznakeEnter new tag name ImageTags GreakaError ImageTags4Neuspijelo snimanje oznakeFailed to save tags to  ImageTags FilterFilter ImageTagsNova oznakaNew Tag ImageTagsIme nije unesnoNo name entered ImageTagsUkloni oznaku Remove Tag ImageTags4Ukloni izabrane oznaku(e)?Remove selected tags(s)? ImageTagsUkloni oznaku Remove tag ImageTags Ozna iTag ImageTags OznakaTag  ImageTagsOzna ivanjeTagging  ImageTagsUkloni oznakuUntag ImageTags"Uklanjanje oznaka Untagging  ImageTagsDaYes ImageTagsKlipbord Clipboard ImageView GreakaError ImageViewDGreaka pri snimanju Exif podataka.Failed to save Exif metadata. ImageView4Greaka pri snimanju slike.Failed to save image. ImageViewtDr~i Ctrl dugme pritisnuto i izaberi regiju koristei mia.;Hold down the Ctrl key and select a region using the mouse. ImageView Slika snimljena. Image saved. ImageView SlikeImages ImageViewBez selekcije No selection ImageViewSnimi sliku kao Save image as ImageViewSnimam... Saving... ImageView&Veli ina selekcije:Selection size:  ImageViewKopirajCopyInfoView Phototonic%n slika%n slike%n slika %n image(s) Phototonic &Uredi&Edit Phototonic &Fajl&File Phototonic&Idi&Go Phototonic &Pomo&Help Phototonic &Alati&Tools Phototonic&Pogled&View Phototonic:Pregleda i organizator slika!

Image viewer and organizer

 PhototonicOAbout PhototonicDodaj kraticu Add Bookmark Phototonic NazadBack PhototonicKartice Bookmarks PhototonicDoleBottom PhototonicPrijavi greake Bug reports PhototonicDNemogue kopirati ili pomjeriti u Can not copy or move to  Phototonic^Nemogue kopirati ili pomjeriti u istu fasciklu'Can not copy or move to the same folder PhototonicjNemogue pomjeriti ili kopirati slike u ovu fasciklu.+Can not move or copy images to this folder. Phototonic Otka~iCancel Phototonic^Nemogue izvesti akciju sa primvremenom slikom.+Cannot perform action with temporary image. Phototonic4Klasi ne minijaturne slikeClassic Thumbs PhototonicZatvori sliku Close Image PhototonicBojeColors PhototonicKompaktnoCompact PhototonicKopiranoCopied PhototonicKopirajCopy Phototonic*Kopiraj podatke slikeCopy Image Data PhototonicKopiraj u... Copy to... PhototonicNapravljen "%1" Created "%1" Phototonic Izre~i selekcijuCrop to Selection Phototonic Izre~iCropping Phototonic Izre~iCut PhototonicIzbriaiDelete Phototonic Izbriai fasciklu Delete folder PhototonicIzbriai sliku Delete image PhototonicIzbriai slike Delete images PhototonicIzbrisanoDeleted PhototonicIzbrisanoDeleted  PhototonicROdrediana fascikla je ista kao i po etna.%Destination folder is same as source. PhototonicIsklju enoDisable Phototonic,Sidrene i alatne trakeDocks and Toolbars PhototonicDvostrukoDual Phototonic(Dvostruko vertikalno Dual Vertical Phototonic Duple slike u %1Duplicate images in %1 Phototonic UrediEdit Phototonic6Poveaj minijaturne prikazeEnlarge Thumbnails Phototonic.Unesi novo ime za "%1":Enter a new name for "%1": Phototonic GreakaError Phototonic IzaiExit PhototonicTNeuspijelo kopiranje ili pomjeranje slike.Failed to copy or move image. PhototonicHNeuspijelo pravljenje nove fascikle.Failed to create new folder. Phototonic:Neuspijelo brisanje fascikle.Failed to delete folder. Phototonic2Neuspijelo brisanje slikeFailed to delete image Phototonic4Neuspijelo brisanje slike.Failed to delete image. Phototonic>Neuspijelo pomjeranje fascikle.Failed to move folder. Phototonic<Neuspijelo otvaranje fascikle:Failed to open folder: PhototonicDNeuspijelo preimenovanje fascikle.Failed to rename folder. Phototonic>Neuspijelo preimenovanje slike.Failed to rename image. PhototonicTGreaka pri pokretanju eksterne aplikacije.%Failed to start external application. PhototonicFajl sistem File System Phototonic FilterFilter Phototonic$Filtriraj po imenuFilter by Name Phototonic&Pronai duple slikeFind Duplicate Images PhototonicPrvaFirst Phototonic$Obrni horizontalnoFlip Horizontally Phototonic Obrni vertikalnoFlip Vertically Phototonic(Obrnuto horizontalnoFlipped Horizontally Phototonic$Obrnuto vertikalnoFlipped Vertically Phototonic$Fascikla pomjerena Folder moved PhototonicNaprijedForward Phototonic4Prikaz preko cijelo ekrana Full Screen PhototonicIdi goreGo Up PhototonicPo etnaHome Phototonic Po etna stranica Home page Phototonic SlikaImage Phototonic&Informacije o slici Image Info Phototonic(Uklju i pod-fascikleInclude Sub-folders PhototonicPokreem...Initializing... Phototonic$Nevaljala putanja: Invalid Path: Phototonic*Neva~ee ime uneseno.Invalid name entered. Phototonic&Nevaljala selekcijaInvalid selection Phototonic(Nevaljala selekcija.Invalid selection. PhototonicObrni selekcijuInvert Selection PhototonicZadr~i zum Keep Zoom Phototonic ZadnjaLast PhototonicU itaj klipbordLoad Clipboard Phototonic0Zaklju aj transformacijeLock Transformations Phototonic@Upravljaj eksternim aplikacijamaManage External Applications Phototonic(Preslikaj (ogledalo) Mirroring Phototonic0Preslikavanje isklju enoMirroring Disabled Phototonic0Preslikavanje: dvostrukoMirroring: Dual PhototonicFPreslikavanje. dvostruko vertikalnoMirroring: Dual Vertical Phototonic8Preslikavanje:  etverostrukoMirroring: Quad Phototonic0Preslikavanje: trostrukoMirroring: Triple Phototonic(Pomjeri "%1" u "%2"?Move "%1" to "%2"? PhototonicPomjeri dole Move Down PhototonicPomjeri lijevo Move Left PhototonicPomjeri desno Move Right PhototonicPomjeri goreMove Up Phototonic Pomjeri fasciklu Move folder PhototonicPomjeri u... Move to... PhototonicPomjerenoMoved PhototonicImeName PhototonicNavigacija Navigation PhototonicNova fascikla New Folder Phototonic"Nova pod-fasciklaNew Sub folder Phototonic$Novo ime fascikle:New folder name: PhototonicNovo ime: New name: PhototonicSljedeaNext PhototonicNema slika No images Phototonic"Ime nije uneseno.No name entered. PhototonicBez selekcije No selection Phototonic OtvoriOpen Phototonic Otvori pomou... Open With... Phototonic&Originalna veli ina Original Size PhototonicNalijepi ovdje Paste Here Phototonic,Nalijepi podatke slikePaste Image Data PhototonicTrajno izbriaiPermanently delete PhototonicDTrajno izbriai "%1" i sav sadr~aj?0Permanently delete "%1" and all of its contents? Phototonic<Trajno izbriai odabrane slike?#Permanently delete selected images? PhototonicPostavke Preferences Phototonic ProalaPrevious Phototonic etverostrukoQuad PhototonicNasumi naRandom PhototonicU itaj ponovoReload PhototonicUkloni kraticuRemove Bookmark PhototonicUkljonjen %1" Removed "%1" PhototonicPreimenujRename PhototonicPreimenuj sliku Rename Image PhototonicPovrati zum Reset Zoom Phototonic ObrniReverse PhototonicDRotiraj 1 stepen suprotno kazaljciRotate 1 degree CCW PhototonicDRotiraj 1 stepen u smjeru kazaljkeRotate 1 degree CW PhototonicHRotiraj 90 stepeni suprotno kazaljciRotate 90 degree CCW PhototonicHRotiraj 90 stepeni u smjeru kazaljkeRotate 90 degree CW PhototonicRotacija %1 Rotation %1° Phototonic SnimiSave PhototonicSnimi kaoSave As Phototonic.Promjeni veli inu slike Scale Image PhototonicOzna i sve Select All PhototonicPostavi putanjuSet Path Phototonic2Prika~i skrivene datotekeShow Hidden Files PhototonicPrika~i natpise Show Labels Phototonic(Prika~i alatnu traku Show Toolbar Phototonic4Umanji minijaturne prikazeShrink Thumbnails PhototonicVeli inaSize PhototonicSlajd prikaz Slide Show Phototonic$Slajd prikaz po etSlide show started Phototonic0Slajd prikaz obustavljenSlide show stopped PhototonicMale ikone Small Icons PhototonicSortiraj poSort By PhototonicKockastoSquarish Phototonic*Obustani slajd prikazStop Slide Show Phototonic OznakeTags PhototonicVrijemeTime PhototonicGoreTop PhototonicTransformiai Transform Phototonic2Transformacije zaklju aneTransformations Locked Phototonic2Transformacije otklju aneTransformations Unlocked PhototonicTrostrukoTriple PhototonicTipType Phototonic,Neobrnuto horizontalnoUnflipped Horizontally Phototonic(Neobrnuto vertikalnoUnflipped Vertically Phototonic PogledView PhototonicPregleda Viewer Phototonic Pa~njaWarning PhototonicDaYes Phototonic Ubli~iZoom PhototonicUbli~i %1%Zoom %1% Phototonic Ubli~iZoom In PhototonicZum zaklju an Zoom Locked Phototonic UdaljiZoom Out PhototonicZum vraen Zoom Reset PhototonicZum otklju an Zoom Unlocked Phototonic Otka~iCancelProgressDialog Otka~iCancel ResizeDialogVisina:Height: ResizeDialogZaklju aj omjerLock aspect ratio ResizeDialogNova veli ina: New size: ResizeDialog(Originalna veli ina:Original size: ResizeDialogPostotakPercent ResizeDialogPikseliPixels ResizeDialogUveaj/SmanjiScale ResizeDialog.Promjeni veli inu slike Scale Image ResizeDialogJedinice:Units: ResizeDialog`irina:Width: ResizeDialogRDodaj razmak izmeu minijaturnih prikaza:Add space between thumbnails:SettingsDialogBoja pozadine:Background color:SettingsDialog"Pozadinska slika:Background image:SettingsDialogPo visini By heightSettingsDialogPo airiniBy widthSettingsDialog(Po airini ili visiniBy width or heightSettingsDialog Otka~iCancelSettingsDialog0Izaberi po etnu fascikluChoose Startup FolderSettingsDialogNStandardni kvalitet pri snimanju slika:#Default quality when saving images:SettingsDialogfStandardni, ili komandnom linijom odreeni argument.Default, or specified by command line argumentSettingsDialogFRazmak izmeu slajdova u sekundama: Delay between slides in seconds:SettingsDialog&Potvrda za brisanjeDelete confirmationSettingsDialogIsklju enoDisableSettingsDialog*Uklju i GIF animacijeEnable GIF animationSettingsDialogNapusti umjesto zatvaranja kada je u itana slika iz komandne linije?Exit instead of closing, when image is loaded from command lineSettingsDialog,Prilagodi velike slikeFit Large ImagesSettingsDialog*Prilagodi manje slikeFit Small ImagesSettingsDialogOpenitoGeneralSettingsDialog SlikeImagesSettingsDialog"Kratice tastatureKeyboard ShortcutsSettingsDialogBoja natpisa: Label color:SettingsDialognBroj stranica minijaturnih slika da se u ita unaprijed:(Number of thumbnail pages to read ahead:SettingsDialog UreduOKSettingsDialogOtvori fajl Open FileSettingsDialogPostavke PreferencesSettingsDialog$Zapamti posljednju Remember lastSettingsDialogJRotiraj slike prema Exif orijentaciji*Rotate image according to Exif orientationSettingsDialog\Rotiraj minijaturne slike po Exif orijentaciji/Rotate thumbnails according to Exif orientationSettingsDialog<Prika~i ime slike u pregleda uShow image file name in viewerSettingsDialogPrika~i originalnu veli inu slika koje su manje od minijaturne veli ine AppMgmtDialog Manage External Applications Upravljaj eksternim aplikacijama Name Ime Application path and arguments Putanja i argumenti aplikacije Choose Izaberi Add manually Dodaj ručno Remove Ukloni OK Uredu Choose Application Izaberi aplikaciju New Application Nova aplikacija ColorsDialog Colors Boje Reset Povrati OK Uredu Hue Nijansa Saturation Zasićenost Lightness Svjetlina Colorize Oboji Negative Negativ Red Crvena Green Zelena Blue Plava Hue and Saturation Nijansa i zasićenost Affected Channels Pogođeni kanali Brightness Svjetlost Contrast Kontrast Brightness and Contrast Svjetlost i kontrast Color Balance Balans boja CopyMoveToDialog Move to... Pomjeri u... Copy to... Kopiraj u... Browse... Pregledaj... Remove Ukloni Cancel Otkaži OK Uredu Destination: Destinacija: Choose Folder Izaberi fasciklu CpMvDialog Cancel Otkaži Copying "%1" to "%2". Kopiram "%1" u "%2". Moving "%1" to "%2". Pomjeram "%1" u "%2". CropDialog Cropping Izreži Reset Povrati OK Uredu Left Lijevo Right Desno Top Gore Bottom Dole ImageTags Image Tags Filter Filter Tag Označi Untag Ukloni oznaku New Tag Nova oznaka Remove Tag Ukloni oznaku Clear Filters Ukloni filtere Negate Error Greška Failed to save tags to Neuspijelo snimanje oznake Tagging Označivanje Untagging Uklanjanje oznaka Add a new tag Dodaj novu oznaku Enter new tag name Unesi ime oznake No name entered Ime nije unesno Tag Oznaka already exists već postoji Remove selected tags(s)? Ukloni izabrane oznaku(e)? Remove tag Ukloni oznaku Yes Da Cancel Otkaži ImageView Clipboard Klipbord Selection size: Veličina selekcije: No selection Bez selekcije Hold down the Ctrl key and select a region using the mouse. Drži Ctrl dugme pritisnuto i izaberi regiju koristeći miš. Saving... Snimam... Error Greška Failed to save image. Greška pri snimanju slike. Failed to save Exif metadata. Greška pri snimanju Exif podataka. Image saved. Slika snimljena. Save image as Snimi sliku kao Images Slike InfoView Copy Kopiraj Phototonic Image Info Informacije o slici Zoom Ubliži Mirroring Ovo treba popraviti Preslikaj (ogledalo) Transform Transformiši View Pogled Top Gore Bottom Dole Close Image Zatvori sliku Full Screen Prikaz preko cijelo ekrana Preferences Postavke Exit Izađi Enlarge Thumbnails Povećaj minijaturne prikaze Shrink Thumbnails Umanji minijaturne prikaze Cut Izreži Copy Kopiraj Copy to... Kopiraj u... Move to... Pomjeri u... Delete Izbriši Save Snimi Save As Snimi kao Copy Image Data Kopiraj podatke slike Paste Image Data Nalijepi podatke slike Rename Preimenuj Select All Označi sve About O Name Ime Time Vrijeme Size Veličina Type Tip Reverse Obrni Show Hidden Files Prikaži skrivene datoteke Show Labels Prikaži natpise Small Icons Male ikone Hide Docks Title Bar Sakrij naslovnu traku sidrene trake Hide Dock Title Bars Show Toolbar Prikaži alatnu traku Classic Thumbs Klasične minijaturne slike Compact Kompaktno Squarish Kockasto Reload Učitaj ponovo Include Sub-folders Uključi pod-fascikle Paste Here Nalijepi ovdje New Folder Nova fascikla Back Nazad Forward Naprijed Go Up Idi gore Home Početna Slide Show Slajd prikaz Next Sljedeća Previous Prošla First Prva Last Zadnja Random Nasumična Open Otvori Load Clipboard Učitaj klipbord Open With... Otvori pomoću... Manage External Applications Upravljaj eksternim aplikacijama Add Bookmark Dodaj kraticu Remove Bookmark Ukloni kraticu Zoom Out Udalji Zoom In Ubliži Reset Zoom Povrati zum Original Size Originalna veličina Keep Zoom Zadrži zum Rotate 90 degree CCW Rotiraj 90 stepeni suprotno kazaljci Rotate 90 degree CW Rotiraj 90 stepeni u smjeru kazaljke Flip Horizontally Obrni horizontalno Flip Vertically Obrni vertikalno Cropping Izreži Crop to Selection Izreži selekciju Scale Image Promjeni veličinu slike Rotate 1 degree CCW Rotiraj 1 stepen suprotno kazaljci Rotate 1 degree CW Rotiraj 1 stepen u smjeru kazaljke Colors Boje Find Duplicate Images Pronađi duple slike Disable Isključeno Dual Dvostruko Triple Trostruko Dual Vertical Dvostruko vertikalno Quad Četverostruko Lock Transformations Zaključaj transformacije Move Left Pomjeri lijevo Move Right Pomjeri desno Move Up Pomjeri gore Move Down Pomjeri dole Invert Selection Obrni selekciju Filter by Name Filtriraj po imenu Set Path Postavi putanju &File &Fajl &Edit &Uredi &Go &Idi &View &Pogled Sort By Sortiraj po &Tools &Alati &Help &Pomoć Edit Uredi Navigation Navigacija Filter Filter Image Slika Initializing... Pokrećem... File System Fajl sistem Bookmarks Kartice Tags Oznake <p>Image viewer and organizer</p> Pregledač i organizator slika Home page Početna stranica Bug reports Prijavi greške Error Greška Failed to start external application. Greška pri pokretanju eksterne aplikacije. Invalid selection. Nevaljala selekcija. Failed to copy or move image. Neuspijelo kopiranje ili pomjeranje slike. Minimum zoom Zoom %1% Ubliži %1% Maximum zoom Zoom Reset Zum vraćen Zoom Locked Zum zaključan Zoom Unlocked Zum otključan Transformations Locked Transformacije zaključane Transformations Unlocked Transformacije otključane Rotation %1° Rotacija %1° Failed to open file "%1", file not found. Flipped Vertically Obrnuto vertikalno Unflipped Vertically Ovo treba provjeriti Neobrnuto vertikalno Flipped Horizontally Obrnuto horizontalno Unflipped Horizontally Ovo treba provjeriti Neobrnuto horizontalno No selection Bez selekcije Mirroring Disabled Preslikavanje isključeno Mirroring: Dual Preslikavanje: dvostruko Mirroring: Triple Preslikavanje: trostruko Mirroring: Dual Vertical Preslikavanje. dvostruko vertikalno Mirroring: Quad Preslikavanje: četverostruko Can not copy or move to Nemoguće kopirati ili pomjeriti u Can not copy or move to the same folder Nemoguće kopirati ili pomjeriti u istu fasciklu Copied Kopirano Moved Pomjereno %n image(s) %n slika %n slike %n slika Permanently delete Trajno izbriši Delete image Izbriši sliku Yes Da Cancel Otkaži Deleted Izbrisano Failed to delete image Neuspijelo brisanje slike Permanently delete selected images? Trajno izbriši odabrane slike? Delete images Izbriši slike Failed to delete image. Neuspijelo brisanje slike. Deleted Izbrisano Invalid Path: Nevaljala putanja: Viewer Pregledač Docks and Toolbars Sidrene i alatne trake No images Nema slika Failed to open file "%1": file not found. Neuspijelo otvaranje fajla %1": fajl nije pronađen. Slide show stopped Slajd prikaz obustavljen Stop Slide Show Obustani slajd prikaz Slide show started Slajd prikaz počet Can not move or copy images to this folder. Nemoguće pomjeriti ili kopirati slike u ovu fasciklu. Destination folder is same as source. Odredišna fascikla je ista kao i početna. Move "%1" to "%2"? Pomjeri "%1" u "%2"? Move folder Pomjeri fasciklu Failed to move folder. Neuspijelo pomjeranje fascikle. Folder moved Fascikla pomjerena Failed to open folder: Neuspijelo otvaranje fascikle: Duplicate images in %1 Duple slike u %1 New name: Novo ime: Invalid name entered. Nevažeće ime uneseno. Failed to rename folder. Neuspijelo preimenovanje fascikle. Invalid selection Nevaljala selekcija Rename Image Preimenuj sliku Enter a new name for "%1": Unesi novo ime za "%1": No name entered. Ime nije uneseno. Failed to rename image. Neuspijelo preimenovanje slike. Permanently delete "%1" and all of its contents? Trajno izbriši "%1" i sav sadržaj? Delete folder Izbriši fasciklu Failed to delete folder. Neuspijelo brisanje fascikle. Removed "%1" Ukljonjen %1" New Sub folder Nova pod-fascikla New folder name: Novo ime fascikle: Failed to create new folder. Neuspijelo pravljenje nove fascikle. Created "%1" Napravljen "%1" Warning Pažnja Cannot perform action with temporary image. Nemoguće izvesti akciju sa primvremenom slikom. ProgressDialog Cancel Otkaži QObject Usage: phototonic [FILE or DIRECTORY]... Koristi ovako: phototonic [FAJL ili FASCIKLA]... ResizeDialog Scale Image Promjeni veličinu slike Scale Možda ima bolja jedinstvena rječ Uvećaj/Smanji Cancel Otkaži Original size: Originalna veličina: Width: Širina: Height: Visina: Units: Jedinice: New size: Nova veličina: Pixels Pikseli Percent Postotak Lock aspect ratio Zaključaj omjer SettingsDialog Preferences Postavke Fit Large Images Prilagodi velike slike Disable Isključeno By width or height Po širini ili visini By width Po širini By height Po visini Stretch disproportionately Razvuci disproporcionalno Fit Small Images Prilagodi manje slike Background color: Boja pozadine: Exit instead of closing, when image is loaded from command line Napusti umjesto zatvaranja kada je učitana slika iz komandne linije Wrap image list when reaching last or first image Ovo definitivno popraviti Umotaj listu slika pri kraju Default quality when saving images: Standardni kvalitet pri snimanju slika: Enable GIF animation Uključi GIF animacije Rotate image according to Exif orientation Rotiraj slike prema Exif orijentaciji Show image file name in viewer Prikaži ime slike u pregledaču Label color: Boja natpisa: Background image: Pozadinska slika: Add space between thumbnails: Dodaj razmak između minijaturnih prikaza: Show original size of images smaller than the thumbnail size Popraviti Prikaži originalnu veličinu slika koje su manje od minijaturne veličine Number of thumbnail pages to read ahead: Broj stranica minijaturnih slika da se učita unaprijed: Rotate thumbnails according to Exif orientation Rotiraj minijaturne slike po Exif orijentaciji Delay between slides in seconds: Razmak između slajdova u sekundama: Show random images Prikaži nasumične slike Startup folder Početna fascikla Default, or specified by command line argument Popraviti Standardni, ili komandnom linijom određeni argument Remember last Zapamti posljednju Specify: Odredi: Swap mouse left-click and middle-click actions Zamjeni akcije lijevog i srednjeg klika mišem Delete confirmation Potvrda za brisanje Keyboard Shortcuts Kratice tastature OK Uredu Cancel Otkaži Viewer Pregledač Thumbnails Minijaturni prikaz Slide Show Slajd prikaz General Općenito Choose Startup Folder Izaberi početnu fasciklu Open File Otvori fajl Images Slike ShortcutsTable Action Akcija Shortcut Prečice Delete shortcut Izbriši prečicu Set shortcut Postavi prečicu "%1" is reserved for shortcuts to external applications. Definitivno popraviti "%1" je obrnuto za prečice kod eksternih aplikacija. "%1" is already assigned to "%2" action. Popraviti "%1" je već upotrebljeno za "%2" akciju. ThumbView General Uopćeno File name Ime fajla Location Lokacija Size Veličina Modified Modificiran Format Format Resolution Rezolucija Megapixel Megapiksel Error Greška Selected %1 of%2 Izabrano %1 od %2 %n image(s) %n slika %n slike %n slika %n image(s) %n slika %n slike %n slika No images Nema slika Searching duplicate images... Tražim duple slike... Scanned %1, displaying %2 (%3 and %4) Moguće da nevalja Skeniran %1, prikazujem %2 (%3 i %4) %n original(s) %n original %n originala %n originala %n duplicate(s) %n duplikat %n duplikata %n duplikata phototonic-2.1/translations/phototonic_pl.qm000066400000000000000000000636221325127642100215170ustar00rootroot00000000000000=_ _Ae"y[yS|qv5&*()+ H5H5/sL1f2t5Z9e;]5>e?@]AN*(&o'A>U**%0*0+1byYGLb Lb LbJLbZVM #N%Nn*vNP7&Tl/7XX MX {Y%Ei kn'pxF 8HD/Ft%)A; -2n?cS9*1uQxYXb[)nHdCLeBj2rIAsn0KOÙ.Ȳ(3 L! 9N8h<\N6w 5Z~#I nPf36%0g #fG7QxYQxYYcRg<+SW4,eFu,ve;w(&Yw *Tr]w$uC?$?ýN,uR!& #8lu.dz^W_tO] ]III IICICIH4fV6J6uo,: 6:"fR/֓Z:}K}M*+Aa"O$O @XP)nJUDBEl/^!p3ET~~:K]55t5FuF\H56n[[%? jF@TI^%ߺF>nP" '#CQ%n B6 9$\>eKPtTC%[}_.%A_PB}n!DF.jRȜEЍD!JmDG(13([q3E-9E*;s%8c-Cl3m]4.jNHgg.> !>מ}מ16Ho=GOY >i]*G@ <;%<8={7q5! gl glv lq^2J t7J0 y-QZ zdJD t9 " G+X Ik J& #T> Ds a0 dg id=; p=; p=R q%2 * aB  >  $- ),+ 3 sM ye yeK CR9 2'\W }8G ~@ ~ : ʺNy Fy EOA Bn  &e) ,@~7 , .8 A O PG'= RPrzegldarka obrazkw i organizator</p>!

Image viewer and organizer

 PhototonicOAbout PhototonicDodaj zakBadk Add Bookmark Phototonic PowrtBack PhototonicZakBadki Bookmarks Phototonic DolnyBottom PhototonicRaporty bBdw Bug reports PhototonicJNie mo|na skopiowa lub przenie[ do Can not copy or move to  PhototonicrNie mo|na skopiowa lub przenie[ do tego samego katalogu'Can not copy or move to the same folder PhototonicxNie mo|na przenie[ lub skopiowa obrazkw do tego katalogu.+Can not move or copy images to this folder. PhototonicZrezygnujCancel Phototonic`Nie mo|na wykona akcji z tymczasowym obrazkiem.+Cannot perform action with temporary image. Phototonic&Klasyczne MiniaturyClassic Thumbs PhototonicZamknij Obrazek Close Image Phototonic KoloryColors Phototonic ZwartyCompact PhototonicSkopiowanoCopied PhototonicSkopiujCopy Phototonic(Skopiuj dane obrazkaCopy Image Data PhototonicSkopiuj do... Copy to... PhototonicStworzony %1  Created "%1" Phototonic$Przytnij do wyboruCrop to Selection PhototonicPrzycinanieCropping Phototonic WytnijCut PhototonicUsuDDelete PhototonicUsuD katalog Delete folder PhototonicUsuD obrazek Delete image PhototonicUsuD obrazki Delete images PhototonicUsunitoDeleted PhototonicUsunite Deleted  PhototonicXKatalog docelowy jest taki sam jak zrdBowy.%Destination folder is same as source. Phototonic WyBczDisable Phototonic*Doki i Paski narzdziDocks and Toolbars PhototonicPodwjneDual Phototonic Podwjne Pionowe Dual Vertical Phototonic.Duplikaty obrazkw w %1Duplicate images in %1 Phototonic EdycjaEdit Phototonic$Powiksz MiniaturyEnlarge Thumbnails Phototonic:Wprowadz now nazw dla %1 :Enter a new name for "%1": PhototonicBBdError PhototonicWyj[cieExit Phototonic\Nie udaBo si skopiowa lub przenie[ obrazka.Failed to copy or move image. PhototonicNNie udaBo si stworzy nowego katalogu.Failed to create new folder. Phototonic<Nie udaBo si usun katalogu.Failed to delete folder. Phototonic8Nie udaBo si usun obrazkaFailed to delete image Phototonic:Nie udaBo si usun obrazka.Failed to delete image. PhototonicBNie udaBo si przenie[ katalogu.Failed to move folder. Phototonic@Nie udaBo si otworzy katalogu:Failed to open folder: PhototonicJNie udaBo si zmieni nazwy katalogu.Failed to rename folder. Phototonic@Nie mo|na zmieni nazwy obrazka.Failed to rename image. PhototonicJNieudany start zewntrznej aplikacji.%Failed to start external application. PhototonicSystem Plikw File System Phototonic FiltrFilter Phototonic Filtruj wg nazwyFilter by Name Phototonic2Znajdz duplikaty obrazkwFind Duplicate Images PhototonicPierwszyFirst PhototonicObr PoziomoFlip Horizontally PhototonicObr PionowoFlip Vertically Phototonic*Odwrcenie w poziomieFlipped Horizontally Phototonic&Odwrcenie w pionieFlipped Vertically Phototonic(Katalog przeniesiony Folder moved PhototonicNaprzdForward PhototonicPeBny Ekran Full Screen PhototonicIdz do gryGo Up Phototonic DomowyHome PhototonicStrona domowa Home page PhototonicObrazekImage PhototonicInfo o Obrazku Image Info Phototonic,Uwzgldnij PodkatalogiInclude Sub-folders Phototonic$Inicjalizowanie...Initializing... Phototonic,NieprawidBowa [cie|ka: Invalid Path: Phototonic@Wprowadzono nieprawidBow nazw.Invalid name entered. Phototonic2NieprawidBowe zaznaczenieInvalid selection Phototonic4NieprawidBowe zaznaczenie.Invalid selection. Phototonic$Odwr ZaznaczenieInvert Selection Phototonic*Zachowaj Powikszenie Keep Zoom PhototonicOstatniLast PhototonicWczytaj schowekLoad Clipboard Phototonic0Zablokuj przeksztaBceniaLock Transformations PhototonicDZarzdzaj Zewntrznymi AplikacjamiManage External Applications Phototonic Lustro Mirroring Phototonic Lustro wyBczoneMirroring Disabled Phototonic Lustro:podwjne Mirroring: Dual Phototonic0Lustro: podwjne pionoweMirroring: Dual Vertical Phototonic"Lustro: poczwrneMirroring: Quad Phototonic Lustro: potrjneMirroring: Triple Phototonic.Przenie[ %1  do %2 ?Move "%1" to "%2"? PhototonicPrzenie[ w DB Move Down PhototonicPrzenie[ w Lewo Move Left Phototonic Przenie[ w Prawo Move Right PhototonicPrzenie[ w GrMove Up Phototonic Przenie[ katalog Move folder PhototonicPrzenie[ do... Move to... PhototonicPrzeniesionoMoved Phototonic NazwaName PhototonicNawigacja Navigation PhototonicNowy Katalog New Folder PhototonicNowy PodkatalogNew Sub folder Phototonic,Nazwa nowego katalogu:New folder name: PhototonicNowa nazwa: New name: PhototonicNastpnyNext PhototonicBrak obrazkw No images Phototonic,Nie wprowadzono nazwy.No name entered. Phototonic Brak zaznaczenia No selection Phototonic OtwrzOpen PhototonicOtwrz Z... Open With... Phototonic$Oryginalny Rozmiar Original Size PhototonicWklej Tutaj Paste Here Phototonic$Wklej dane obrazkaPaste Image Data PhototonicTrwale usunitePermanently delete PhototonicRTrwale usun %1" i caB jego zawarto[?0Permanently delete "%1" and all of its contents? PhototonicBTrwale usun zaznaczone obrazki?#Permanently delete selected images? PhototonicPreferencje Preferences PhototonicPoprzedniPrevious PhototonicPoczwrneQuad Phototonic LosowyRandom Phototonic Wczytaj ponownieReload PhototonicUsuD zakBadkRemove Bookmark PhototonicUsunity %1  Removed "%1" PhototonicZmieD nazwRename Phototonic&ZmieD nazw Obrazka Rename Image Phototonic*Zresetuj Powikszenie Reset Zoom PhototonicOdwrotno[Reverse Phototonic,Obr 1 stopieD w lewoRotate 1 degree CCW Phototonic.Obr 1 stopieD w prawoRotate 1 degree CW Phototonic,Obr 90 stopni w lewoRotate 90 degree CCW Phototonic.Obr 90 stopni w prawoRotate 90 degree CW PhototonicObrt %1 Rotation %1° Phototonic ZapiszSave PhototonicZapisz JakoSave As PhototonicSkaluj Obrazek Scale Image Phototonic Wybierz Wszystko Select All PhototonicSet Path Phototonic$Poka| Ukryte PlikiShow Hidden Files PhototonicPoka| Etykiety Show Labels Phototonic(Poka| pasek narzdzi Show Toolbar Phototonic$Zmniejsz MiniaturyShrink Thumbnails PhototonicRozmiarSize PhototonicPokaz Slajdw Slide Show Phototonic0Pokaz slajdw rozpocztySlide show started Phototonic0Pokaz slajdw zatrzymanySlide show stopped PhototonicMaBe ikony Small Icons PhototonicSortuj WedBugSort By PhototonicKwadratowySquarish Phototonic.Zatrzymaj Pokaz SlajdwStop Slide Show PhototonicCzasTime Phototonic GrnyTop PhototonicPrzeksztaBcenie Transform Phototonic6PrzeksztaBcenia zablokowaneTransformations Locked Phototonic6PrzeksztaBcenia odblokowaneTransformations Unlocked PhototonicPotrjneTriple Phototonic RodzajType Phototonic8Cofnij odwrcenie w poziomieUnflipped Horizontally Phototonic4Cofnij odwrcenie w pionieUnflipped Vertically Phototonic WidokView PhototonicPrzegldarkaViewer PhototonicOstrze|enieWarning PhototonicTakYes PhototonicPowikszenieZoom Phototonic Powikszenie %1%Zoom %1% PhototonicPowikszZoom In Phototonic0Powikszenie zablokowane Zoom Locked PhototonicPomniejszZoom Out Phototonic$Reset powikszenia Zoom Reset Phototonic0Powikszenie odblokowane Zoom Unlocked PhototonicZrezygnujCancelProgressDialogZrezygnujCancel ResizeDialogWysoko[:Height: ResizeDialog$Zablokuj proporcjeLock aspect ratio ResizeDialogNowy rozmiar: New size: ResizeDialog&Oryginalny rozmiar:Original size: ResizeDialogProcentPercent ResizeDialogPikseliPixels ResizeDialog SkalujScale ResizeDialogSkaluj Obrazek Scale Image ResizeDialogJednostki:Units: ResizeDialogSzeroko[:Width: ResizeDialogNDodaj przestrzeD pomidzy miniaturkami:Add space between thumbnails:SettingsDialogKolor tBa:Background color:SettingsDialogObrazek tBa:Background image:SettingsDialog WedBug wysoko[ci By heightSettingsDialog"WedBug szeroko[ciBy widthSettingsDialogZrezygnujCancelSettingsDialog2Wybierz Folder PocztkowyChoose Startup FolderSettingsDialogLDomy[lna jako[ przy zapisie obrazkw:#Default quality when saving images:SettingsDialogjDomy[lny lub okre[lony przez argument wiersza poleceD.Default, or specified by command line argumentSettingsDialogROpznienie pomidzy slajdami w sekundach: Delay between slides in seconds:SettingsDialog(Potwierdzaj usuwanieDelete confirmationSettingsDialog WyBczDisableSettingsDialog(WBcz animowane GIFyEnable GIF animationSettingsDialogWyjdz zamiast zamykania, gdy obrazek jest wczytany z linii komend?Exit instead of closing, when image is loaded from command lineSettingsDialog6Dopasowanie Du|ych ObrazkwFit Large ImagesSettingsDialog6Dopasowanie MaBych ObrazkwFit Small ImagesSettingsDialog OglneGeneralSettingsDialogObrazkiImagesSettingsDialog&Skrty klawiaturoweKeyboard ShortcutsSettingsDialogKolor etykiety: Label color:SettingsDialogTLiczba stron miniatur do odczytu z przodu:(Number of thumbnail pages to read ahead:SettingsDialogOKOKSettingsDialogOtwrz plik Open FileSettingsDialogPreferencje PreferencesSettingsDialog$Zapamitaj ostatni Remember lastSettingsDialogNObr obrazek zgodnie z orientacj Exif*Rotate image according to Exif orientationSettingsDialogRObr miniatury zgodnie z orientacj Exif/Rotate thumbnails according to Exif orientationSettingsDialogPoka| oryginalny rozmiar obrazkw mniejszy ni| rozmiar miniatury AppMgmtDialog Manage External Applications Zarządzaj Zewnętrznymi Aplikacjami Name Nazwa Path Ścieżka Add Dodaj Application path and arguments Ścieżka aplikacji i argumenty Choose Wybierz Add manually Dodaj ręcznie Remove Usuń OK OK Choose Application Wybierz Aplikację New Application Nowa aplikacja Error Błąd Not an executable Nie wykonywalny ColorsDialog Colors Kolory Reset Reset OK OK Hue Barwa Saturation Nasycenie Lightness Jasność Channels Kanały Enable Włącz Colorize Kolorowanie Negative Red Czerwony Green Zielony Blue Niebieski Hue and Saturation Barwa i nasycenie Affected Channels Dotknięte kanały Brightness Jasność Contrast Kontrast Brightness and Contrast Jasność i Kontrast Color Balance Balans koloru CopyMoveToDialog Copy or Move Images to... Skopiuj lub Przenieś Obrazki do... Add Dodaj Move to... Przenieś do... Copy to... Skopiuj do... Browse... Przeglądaj... Remove Usuń Cancel Zrezygnuj OK OK Destination: Miejsce przeznaczenia: Destination: Miejsce przeznaczenia: Close Zamknij Copy Skopiuj Move Przenieś Choose Folder Wybierz Folder Choose Directory Wybierz Katalog CpMvDialog Cancel Zrezygnuj Copying "%1" to "%2". Kopiowanie „%1” do „%2”. Moving "%1" to "%2". Przenoszenie „%1” do „%2”. Copying Kopiowanie Moving Przenoszenie to do CropDialog Cropping Przycinanie Reset Reset OK OK Top Górny Left Lewy Right Prawy Bottom Dolny ImageTags Tag Untag Clear Filters New Tag Image Tags Filter Filtr Remove Tag Negate Error Błąd Failed to save tags to Tagging Untagging Add a new tag Enter new tag name No name entered Nie wprowadzono nazwy Tag already exists Remove selected tags(s)? Remove tag Yes Tak Cancel Zrezygnuj ImageView New image Nowy obrazek Clipboard Schowek Selection size: No selection Brak zaznaczenia Hold down the Ctrl key and select a region using the mouse. Przytrzymaj klawisz Ctrl i zaznacz rejon używając mysz. Failed to save image. Nie udało się zapisać obrazka. Failed to save Exif metadata. Nie udało się zapisać metadanych Exif. Image saved. Obrazek zapisany. Hold down the Ctrl key and select a region using the mouse Przytrzymaj klawisz Ctrl i zaznacz rejon używając mysz Saving... Zapisywanie... Error Błąd Failed to save image Nie udało się zapisać obrazka Failed to save Exif metadata Nie udało się zapisać metadanych Exif Image saved Obrazek zapisany Save image as Zapisz obrazek jako Images Obrazki Image Files Pliki Graficzne InfoView Copy Skopiuj KeyGrabLineEdit Set shortcut Ustaw skrót is reserved for shortcuts to external applications jest zarezerwowany dla skrótów do zewnętrznych aplikacji is already assigned to " jest już przypisany do " Already assigned to " Już przypisany do " " action " akcja Phototonic Image Info Info o Obrazku Zoom Powiększenie Transform Przekształcenie Mirror Lustro Top Górny Bottom Dolny Close Image Zamknij Obrazek Full Screen Pełny Ekran Preferences Preferencje Exit Wyjście Enlarge Thumbnails Powiększ Miniatury Shrink Thumbnails Zmniejsz Miniatury Cut Wytnij Copy Skopiuj Copy/Move to... Skopiuj/Przenieś do... Docks and Toolbars Doki i Paski narzędzi Mirroring Lustro Delete Usuń Save Zapisz Save As Zapisz Jako Copy Image Skopiuj Obrazek Paste Image Wklej Obrazek Rename Zmień nazwę Select All Wybierz Wszystko About O Name Nazwa Time Czas Size Rozmiar Type Rodzaj Reverse Odwrotność Show Hidden Files Pokaż Ukryte Pliki Show Labels Pokaż Etykiety Small Icons Małe ikony Show Toolbar Pokaż pasek narzędzi Classic Thumbs Klasyczne Miniatury Compact Zwarty Squarish Kwadratowy Reload Wczytaj ponownie Include Sub-folders Uwzględnij Podkatalogi Paste Here Wklej Tutaj New Folder Nowy Katalog Manage Zarządzaj Back Powrót Forward Naprzód Up W górę Home Domowy Slide Show Pokaz Slajdów Next Następny Previous Poprzedni First Pierwszy Last Ostatni Random Losowy Open Otwórz Open With... Otwórz Z... Scale Image Skaluj Obrazek Tags Failed to start external application. Nieudany start zewnętrznej aplikacji. Invalid selection. Nieprawidłowe zaznaczenie. Failed to copy or move image. Nie udało się skopiować lub przenieść obrazka. Minimum zoom Zoom %1% Powiększenie %1% Rotation %1u00B0 Obrót %1u00B0 Copied Skopiowano Moved Przeniesiono %n image(s) %n obrazka %n obrazków %n obrazków Permanently delete Trwale usunięte Failed to delete image. Nie udało się usunąć obrazka. Deleted Usunięto Invalid Path: Nieprawidłowa ścieżka: Failed to open file "%1": file not found. Nie udało się otworzyć pliku "%1": plik nie znaleziony. Stop Slide Show Zatrzymaj Pokaz Slajdów Can not move or copy images to this folder. Nie można przenieść lub skopiować obrazków do tego katalogu. Destination folder is same as source. Katalog docelowy jest taki sam jak źródłowy. Move "%1" to "%2"? Przenieść „%1” do „%2”? Failed to move folder. Nie udało się przenieść katalogu. Failed to open folder: Nie udało się otworzyć katalogu: Duplicate images in %1 Duplikaty obrazków w %1 Invalid name entered. Wprowadzono nieprawidłową nazwę. Failed to rename folder. Nie udało się zmienić nazwy katalogu. Enter a new name for "%1": Wprowadź nową nazwę dla „%1”: No name entered. Nie wprowadzono nazwy. Failed to rename image. Nie można zmienić nazwy obrazka. Permanently delete "%1" and all of its contents? Trwale usunąć „%1" i całą jego zawartość? Failed to delete folder. Nie udało się usunąć katalogu. Removed "%1" Usunięty „%1” Failed to create new folder. Nie udało się stworzyć nowego katalogu. Created "%1" Stworzony „%1” Cannot perform action with temporary image. Nie można wykonać akcji z tymczasowym obrazkiem. New Image Nowy Obrazek Open With Otwórz Z Manage External Applications Zarządzaj Zewnętrznymi Aplikacjami Add Bookmark Dodaj zakładkę Remove Bookmark Usuń zakładkę Zoom Out Pomniejsz Zoom In Powiększ Reset Zoom Zresetuj Powiększenie Original Size Oryginalny Rozmiar Keep Zoom Zachowaj Powiększenie Rotate 90 degree CCW Obróć 90 stopni w lewo Rotate 90 degree CW Obróć 90 stopni w prawo Flip Horizontally Obróć Poziomo Flip Vertically Obróć Pionowo Cropping Przycinanie Crop to Selection Przytnij do wyboru Rotate 1 degree CCW Obróć 1 stopień w lewo Rotate 1 degree CW Obróć 1 stopień w prawo Colors Kolory Find Duplicate Images Znajdź duplikaty obrazków Disable Wyłącz Dual Podwójne Triple Potrójne Dual Vertical Podwójne Pionowe Quad Poczwórne Failed to open file "%1", file not found. Keep Transformations Zachowaj Przekształcenia Move Left Przenieś w Lewo Move Right Przenieś w Prawo Move Up Przenieś w Górę Move Down Przenieś w Dół Invert Selection Odwróć Zaznaczenie File Plik Edit Edycja Go Idź View Widok Sort By Sortuj Według Help Pomoc Navigation Nawigacja Filter Filtr Initializing... Inicjalizowanie... File System System Plików <p>Image viewer and organizer</p> <p>Przeglądarka obrazków i organizator</p> Home page Strona domowa Bug reports Raporty błędów Copy or Move to... Skopiuj lub Przenieś do... Show Clipboard Pokaż Schowek &File &Plik &Edit &Edycja &Go &Idź &View &Widok &Help &Pomoc Built with Qt Zbudowany z Qt Translators:<br> Tłumacze:<br> Invalid selection Nieprawidłowe zaznaczenie Error Błąd Failed to copy or move image Nie udało się skopiować lub przenieść obrazka Can not copy or move to Nie można skopiować lub przenieść do Can not cut and paste in the same folder Nie można wyciąć i wkleić w tym samym katalogu Copied Skopiowane Moved Przeniesione images obrazki Delete image Usuń obrazek Permanently delete Trwale usunięte Failed to delete image Nie udało się usunąć obrazka No selection Brak zaznaczenia Maximum zoom Rotation %1° Obrót %1° Delete images Usuń obrazki Permanently delete selected images? Trwale usunąć zaznaczone obrazki? Copy to... Skopiuj do... Move to... Przenieś do... Copy Image Data Skopiuj dane obrazka Paste Image Data Wklej dane obrazka Hide Dock Title Bars Go Up Idź do góry Load Clipboard Wczytaj schowek Lock Transformations Zablokuj przekształcenia Filter by Name Filtruj wg nazwy Set Path Ustaw ścieżkę &Tools &Narzędzia Image Obrazek Bookmarks Zakładki Contributors / Code: Autorzy/Kod: Contributors / Translations: Autorzy/Tłumaczenia: Failed to start external application Nieudany start zewnętrznej aplikacji Zoom Powiększenie Zoom Reset Reset powiększenia Zoom Locked Powiększenie zablokowane Zoom Unlocked Powiększenie odblokowane Transformations Locked Przekształcenia zablokowane Transformations Unlocked Przekształcenia odblokowane Rotation Obrót Flipped Vertically Odwrócenie w pionie Unflipped Vertically Cofnij odwrócenie w pionie Flipped Horizontally Odwrócenie w poziomie Unflipped Horizontally Cofnij odwrócenie w poziomie Mirroring Disabled Lustro wyłączone Mirroring: Dual Lustro:podwójne Mirroring: Triple Lustro: potrójne Mirroring: Dual Vertical Lustro: podwójne pionowe Mirroring: Quad Lustro: poczwórne Can not copy or move to the same folder Nie można skopiować lub przenieść do tego samego katalogu image(s) obrazek(i) Yes Tak Cancel Zrezygnuj Deleted Usunięte Invalid Path: Nieprawidłowa Ścieżka: Viewer Przeglądarka No images Brak obrazków Failed to open file Nie udało się otworzyć pliku , file not found , plik nie znaleziony Slide show stopped Pokaz slajdów zatrzymany End Slide Show Zakończ Pokaz Slajdów Slide show started Pokaz slajdów rozpoczęty Can not move or copy images to this folder Nie można przenieść lub skopiować obrazków do tego katalogu Destination folder is same as source Katalog docelowy jest taki sam jak źródłowy Move Przenieś to do Move folder Przenieś katalog Failed to move folder Nie udało się przenieść katalogu Folder moved Katalog przeniesiony Failed to open folder: Nie udało się otworzyć katalogu: Rename Zmień nazwę New name: Nowa nazwa: Invalid name entered Wprowadzono nieprawidłową nazwę Failed to rename folder Nie udało się zmienić nazwy katalogu Rename Image Zmień nazwę Obrazka Enter a new name for Wprowadź nową nazwę dla No name entered Nie wprowadzono nazwy Failed to rename image Nie można zmienić nazwy obrazka and all of its contents? i całą jego zawartość? Delete folder Usuń katalog Failed to delete folder Nie udało się usunąć katalogu Removed Usunięty New Sub folder Nowy Podkatalog New folder name: Nazwa nowego katalogu: Failed to create new folder Nie udało się stworzyć nowego katalogu Created Stworzony Executing file manager... Uruchomienie managera plików... Warning Ostrzeżenie Cannot perform action with temporary image Nie można wykonać akcji z tymczasowym obrazkiem ProgressDialog Cancel Zrezygnuj QObject Usage: phototonic [FILE or DIRECTORY]... Użycie: phototonic [PLIK lub KATALOG]... ResizeDialog OK OK Scale Image Skaluj Obrazek Scale Skaluj Cancel Zrezygnuj Original size: Oryginalny rozmiar: Width: Szerokość: Height: Wysokość: Units: Jednostki: New size: Nowy rozmiar: Original size: Oryginalny rozmiar: Width: Szerokość: Height: Wysokość: Units: Jednostki: New size: Nowy rozmiar: Pixels Pikseli Percent Procent Lock aspect ratio Zablokuj proporcje SettingsDialog Preferences Preferencje By width or height Default quality when saving images: Domyślna jakość przy zapisie obrazków: Label color: Kolor etykiety: OK OK Cancel Zrezygnuj Background color: Kolor tła: Rotate image according to Exif orientation Obróć obrazek zgodnie z orientacją Exif Label color: Kolor etykiety: Background image: Obrazek tła: Add space between thumbnails: Dodaj przestrzeń pomiędzy miniaturkami: Show original size of images smaller than the thumbnail size Pokaż oryginalny rozmiar obrazków mniejszy niż rozmiar miniatury Number of thumbnail pages to read ahead: Liczba stron miniatur do odczytu z przodu: Rotate thumbnails according to Exif orientation Obróć miniatury zgodnie z orientacją Exif Thumbnails Miniatury Fit Large Images Dopasowanie Dużych Obrazków Disable Wyłącz By width and height Według szerokości i wysokości By width Według szerokości By height Według wysokości Stretch disproportionately Rozciągnij nieproporcjonalnie Fit Small Images Dopasowanie Małych Obrazków Exit instead of closing, when image is loaded from command line Wyjdź zamiast zamykania, gdy obrazek jest wczytany z linii komend Wrap image list when reaching last or first image Zawiń listę obrazków gdy osiągnie się ostatni lub pierwszy obrazek Default quality when saving images: Domyślna jakość gdy zapisywane obrazki: Enable GIF animation Włącz animowane GIFy Open File Otwórz plik Images Obrazki Rotate according to Exif orientation Obróć według orientacji Exif Show image file name in full screen mode Pokaż nazwę pliku obrazka w trybie pełnoekranowym Background color: Kolor tła: Show image file name in viewer Background image: Obrazek tła: Add space between thumbnails: Dodaj przestrzeń pomiędzy miniaturkami: Number of thumbnail pages to read ahead: Liczba stron miniatur do odczytu z przodu: Delay between slides in seconds: Opóźnienie pomiędzy slajdami w sekundach: Startup folder Folder początkowy Default, or specified by command line argument Domyślny lub określony przez argument wiersza poleceń Remember last Zapamiętaj ostatni Specify: Określ: Delete confirmation Potwierdzaj usuwanie Keyboard Shortcuts Skróty klawiaturowe Viewer Przeglądarka Delay between slides in seconds: Opóźnienie pomiędzy slajdami w sekundach: Show random images Pokaż losowe obrazki Slide Show Pokaz Slajdów Swap mouse left-click and middle-click actions Zamień akcje lewokliku i środkowego kliku myszy Keyboard Shortcuts: Skróty Klawiaturowe: Keyboard and Mouse Klawiatura i Mysz General Ogólne Choose Startup Folder Wybierz Folder Początkowy ShortcutsTable Action Akcja Shortcut Skrót Delete shortcut Usuń skrót Set shortcut Ustaw skrót "%1" is reserved for shortcuts to external applications. „%1” jest zarezerwowany dla skrótów do zewnętrznych aplikacji. "%1" is already assigned to "%2" action. „%1” jest już przypisany do akcji „%2”. is reserved for shortcuts to external applications jest zarezerwowany dla skrótów do zewnętrznych aplikacji is already assigned to "%1" action jest już przypisany do akcji "%1" is already assigned to " jest już przypisany do " " action " akcja ThumbView images obrazków Selected Wybrane of z File name Nazwa pliku Location Położenie Format Format Resolution Rozdzielczość Megapixel Megapikseli Selected %1 of%2 Wybrane %1 z%2 %n image(s) %n obrazek %n obrazków %n obrazków Selected %1 of %2 Wybrane %1 z %2 Scanned %1, displaying %2 (%3 and %4) Przeskanowanych %1, wyświetlonych %2 (%3 i %4) %n original(s) %n oryginał %n oryginałów %n oryginałów %n duplicate(s) %n duplikat %n duplikatów %n duplikatów Size Rozmiar General Ogólne Modified Zmodyfikowany Error Błąd %n image(s) %n obrazek %n obrazków %n obrazków Selected %1 of %n image(s) Wybrano %1 z %n obrazka Wybrano %1 z %n obrazków Wybrano %1 z %n obrazków Searching duplicate images... Wyszukiwanie duplikatów obrazków... Scanned Skanowane %n images, displaying %n obrazka, wyświetlonych %n obrazków, wyświetlonych %n obrazków, wyświetlonych %n images ( %n obrazka ( %n obrazków ( %n obrazków ( %n originals and %n oryginału i %n oryginałów i %n oryginałów i %n duplicates) %n duplikatu) %n duplikatów) %n duplikatów) No images Brak obrazków phototonic-2.1/translations/phototonic_pt.qm000066400000000000000000000671301325127642100215250ustar00rootroot00000000000000AZcC5D(eEF]GP/L-&o'A>\**%5*0+1by`GLb }Lb Lb"uLb`|M (8N*Nn.NP7+@Tl4`X3X dX Y%KK\Zw ikn,xFNIFt)A@2Sn#HcZ9"*6QxY_ [)ngdCS"eHj7rIA!sn=QhÙ."Ȳ-i8 R! 9N=<\N;Hw 5`~'nVf3<%5z (lfG<QxYQxY_Rg<0SW41eFu1oG ?ve$w(*w C[krc)CF $E@ýTEug } !& #=lu3z^]tU] ]III IIIMIIINaf]06>6o,Z' : :'NfR4֓`?}%}S.xAa1B= FW Kإ O)O FpP)nPUDH9l/^& p3K~~@EK]:5t;FgFuH5;naMa%E jKG[I^*YߺLnV@& ,c#C%n669$b?>eQPtTH[o_.%G_PH}n&rJjWF3jY7a7%ȜJЍD:( JDM{(6<(aq8EF?K*A%8c- Cl8x]43HjN$Ogg4>%A0G>#0מWמ66N=M'Y D]*L@ / A%Bc8CT<:^ gl gl lq^7Q t7J5 y-X zdJJC t> ' G0= DN O PK #TD Ds! a53 dg idC p=A p=YV q%7 *%D aQ  >$ ( )10 3 sS ye yeQ, CX 2'by }8M ~u ~ ?S ʺT LO ص EUd Bn ! &e. ,@~X ,. .=B A O PG'C Pr- RT i*% p K r+p ] a PGC ^0  ©M <S <a S] SsB)-5u[9~f/:I/;";IZM6!_e^ߔHiT^o0A4id Adicionar manual Add manually AppMgmtDialog0Localizao e argumentosApplication path and arguments AppMgmtDialogEscolherChoose AppMgmtDialog&Escolher aplicativoChoose Application AppMgmtDialog4Gerir aplicativos externosManage External Applications AppMgmtDialogNomeName AppMgmtDialogNovo aplicativoNew Application AppMgmtDialogOkOK AppMgmtDialogRemoverRemove AppMgmtDialogAfetar canaisAffected Channels ColorsDialogAzulBlue ColorsDialog Brilho Brightness ColorsDialog$Brilho e contrasteBrightness and Contrast ColorsDialog,Balanceamento de cores Color Balance ColorsDialogColorizarColorize ColorsDialog CoresColors ColorsDialogContrasteContrast ColorsDialog VerdeGreen ColorsDialog MatizHue ColorsDialog"Matiz e saturaoHue and Saturation ColorsDialogLuminosidade Lightness ColorsDialogNegativoNegative ColorsDialogOkOK ColorsDialogVermelhoRed ColorsDialogRestaurarReset ColorsDialogSaturao Saturation ColorsDialogProcurar... Browse...CopyMoveToDialogCancelarCancelCopyMoveToDialogEscolher pasta Choose FolderCopyMoveToDialogCopiar para... Copy to...CopyMoveToDialogDestino: Destination:CopyMoveToDialogMover para... Move to...CopyMoveToDialogOkOKCopyMoveToDialogRemoverRemoveCopyMoveToDialogCancelarCancel CpMvDialog,Copiando "%1" to "%2".Copying "%1" to "%2". CpMvDialog*Movendo "%1" to "%2".Moving "%1" to "%2". CpMvDialogInferiorBottom CropDialogRecortarCropping CropDialogEsquerdaLeft CropDialogOkOK CropDialogRestaurarReset CropDialogDireitaRight CropDialogSuperiorTop CropDialog j existe already exists ImageTags,Adcionar nova etiqueta Add a new tag ImageTagsCancelarCancel ImageTagsLimpar filtros Clear Filters ImageTags<Digite o novo nome da etiquetaEnter new tag name ImageTagsErroError ImageTags>Falha ao salvar etiquetas para Failed to save tags to  ImageTags FiltroFilter ImageTags&Etiquetas da imagem Image Tags ImageTagsInverterNegate ImageTagsNova etiquetaNew Tag ImageTags(Nenhum nome digitadoNo name entered ImageTags Remover etiqueta Remove Tag ImageTagsFRemover etiqueta(s) selecionada(s)?Remove selected tags(s)? ImageTags Remover etiqueta Remove tag ImageTagsEtiquetaTag ImageTagsEtiqueta Tag  ImageTagsEtiquetar Tagging  ImageTagsSem etiquetaUntag ImageTags$Remover etiquetas  Untagging  ImageTagsSimYes ImageTags*rea de transferncia Clipboard ImageViewErroError ImageView>Falha ao gravar metadados Eixf.Failed to save Exif metadata. ImageView.Falha ao gravar imagem.Failed to save image. ImageViewtPressione a tecla Ctrl e selecione uma regio com o mouse.;Hold down the Ctrl key and select a region using the mouse. ImageViewImagem gravada. Image saved. ImageViewImagensImages ImageView Nada selecionado No selection ImageView$Gravar imagem como Save image as ImageViewGravando... Saving... ImageView(Dimenso da seleo:Selection size:  ImageView CpiaCopyInfoView%n imagem%n imagens %n image(s) Phototonic&Editar&Edit Phototonic&Arquivos&File Phototonic&Ir&Go Phototonic &Ajuda&Help Phototonic&Ferramentas&Tools Phototonic&Visualizar&View PhototonicX<p>Visualizador e organizador de imagens</p>!

Image viewer and organizer

 Phototonic SobreAbout Phototonic.Adicionar aos favoritos Add Bookmark PhototonicRetornarBack PhototonicFavoritos Bookmarks PhototonicInferiorBottom PhototonicInformar erros Bug reports Phototonic@Impossvel copiar ou mover para Can not copy or move to  PhototonicZImpossvel copiar ou mover para a mesma pasta'Can not copy or move to the same folder PhototonicfImpossvel mover ou copiar imagens para essa pasta.+Can not move or copy images to this folder. PhototonicCancelarCancel PhototonicnNo possvel executar a ao com a imagem temporria.+Cannot perform action with temporary image. Phototonic$Miniatura clssicaClassic Thumbs PhototonicFechar imagem Close Image Phototonic CoresColors PhototonicCompactaCompact PhototonicCopiadaCopied Phototonic CopiarCopy Phototonic,Copiar dados da imagemCopy Image Data PhototonicCopiar para... Copy to... PhototonicCriada "%1" Created "%1" Phototonic(Recortar selecionadoCrop to Selection PhototonicRecortarCropping Phototonic CortarCut PhototonicExcluirDelete PhototonicExcluir pasta Delete folder PhototonicExcluir imagem Delete image PhototonicExcluir imagens Delete images PhototonicExcluidaDeleted PhototonicExcluida Deleted  PhototonicJPasta de destino a mesma da origem.%Destination folder is same as source. PhototonicDesativadoDisable Phototonic<Painis e barra de ferramentasDocks and Toolbars Phototonic DuploDual PhototonicDuplo vertical Dual Vertical Phototonic4Imagens duplicadas em "%1"Duplicate images in %1 Phototonic EditarEdit Phototonic&Aumentar miniaturasEnlarge Thumbnails Phototonic<Fornea o novo nome para "%1":Enter a new name for "%1": PhototonicErroError PhototonicSairExit Phototonic@Falha ao copiar ou mover imagem.Failed to copy or move image. Phototonic4Falha ao criar nova pasta.Failed to create new folder. Phototonic.Falha ao excluir pasta.Failed to delete folder. Phototonic.Falha ao excluir imagemFailed to delete image Phototonic0Falha ao excluir imagem.Failed to delete image. Phototonic*Falha ao mover pasta.Failed to move folder. Phototonic*Falha ao abrir pasta:Failed to open folder: Phototonic0Falha ao renomear pasta.Failed to rename folder. Phototonic2Falha ao renomear imagem.Failed to rename image. PhototonicHFalha ao iniciar aplicativo externo.%Failed to start external application. Phototonic&Sistema de arquivos File System Phototonic FiltroFilter Phototonic Filtrar por nomeFilter by Name Phototonic8Pesquisar imagens duplicadasFind Duplicate Images PhototonicPrimeiraFirst Phototonic,Inverter na horizontalFlip Horizontally Phototonic(Inverter na verticalFlip Vertically Phototonic0Inverter horizontalmenteFlipped Horizontally Phototonic,Inverter verticalmenteFlipped Vertically PhototonicPasta removida Folder moved PhototonicAvanarForward PhototonicTela cheia Full Screen PhototonicPara cimaGo Up Phototonic IncioHome PhototonicPgina inicial Home page Phototonic ImagemImage Phototonic(Informao da imagem Image Info Phototonic"Incluir subpastasInclude Sub-folders Phototonic Inicializando...Initializing... Phototonic"Caminho invlido: Invalid Path: Phototonic4Nome fornecido invlido.Invalid name entered. Phototonic Seleo invlidaInvalid selection Phototonic"Seleo invlida.Invalid selection. Phototonic Inverter seleoInvert Selection PhototonicManter zoom Keep Zoom Phototonic ltimaLast PhototonicBCarregar da rea de transfernciaLoad Clipboard Phototonic2Transformaes bloqueadasLock Transformations Phototonic4Gerir aplicativos externosManage External Applications PhototonicZoom mximo Maximum zoom PhototonicZoom mnimo Minimum zoom PhototonicEspelhamento Mirroring Phototonic.Espelhamento desativadoMirroring Disabled Phototonic&Espelhamento: DuploMirroring: Dual Phototonic8Espelhamento: Duplo verticalMirroring: Dual Vertical Phototonic.Espelhamento: QuadruploMirroring: Quad Phototonic(Espelhamento: TriploMirroring: Triple Phototonic*Mover "%1" para "%2"?Move "%1" to "%2"? Phototonic Mover para baixo Move Down Phototonic*Mover para a esquerda Move Left Phototonic(Mover para a direita Move Right PhototonicMover para cimaMove Up PhototonicMover pasta Move folder PhototonicMover para... Move to... Phototonic MovidaMoved PhototonicNomeName PhototonicNavegao Navigation PhototonicNova pasta New Folder PhototonicNova subpastaNew Sub folder Phototonic&Nome da nova pasta:New folder name: PhototonicNovo nome: New name: PhototonicPrximaNext PhototonicNenhuma imagem No images Phototonic,Nenhum nome fornecido.No name entered. Phototonic Nada selecionado No selection PhototonicAbirOpen PhototonicAbrir com... Open With... Phototonic"Dimenso original Original Size PhototonicColar aqui Paste Here Phototonic*Colar dados da imagemPaste Image Data Phototonic*Excluir em definitivoPermanently delete Phototonic\Excluir em definitivo "%1" com o seu contedo?0Permanently delete "%1" and all of its contents? Phototonic\Excluir em definitivo as imagens selecionadas?#Permanently delete selected images? PhototonicPreferncias Preferences PhototonicAnteriorPrevious PhototonicQuadruploQuad Phototonic Imagem aleatriaRandom PhototonicRecarregarReload Phototonic*Remover dos favoritosRemove Bookmark PhototonicRemovida "%1" Removed "%1" PhototonicRenomearRename PhototonicRenomear imagem Rename Image PhototonicRestaurar zoom Reset Zoom PhototonicOrdem reversaReverse Phototonic(Rotacionar 1 grau AHRotate 1 degree CCW Phototonic&Rotacionar 1 grau HRotate 1 degree CW Phototonic,Rotacionar 90 graus AHRotate 90 degree CCW Phototonic*Rotacionar 90 graus HRotate 90 degree CW PhototonicRotao %1 Rotation %1° Phototonic GravarSave PhototonicGravar comoSave As Phototonic(Redimensionar imagem Scale Image Phototonic Selecionar todas Select All Phototonic"Indicar o caminhoSet Path Phototonic0Mostrar arquivos ocultosShow Hidden Files Phototonic2Mostrar nome dos arquivos Show Labels Phototonic8Mostrar barra de ferramentas Show Toolbar Phototonic&Diminuir miniaturasShrink Thumbnails PhototonicDimensoSize Phototonic>Iniciar apresentao de imagens Slide Show Phototonic>Iniciar apresentao de imagensSlide show started Phototonic<Apresentao de imagens paradaSlide show stopped Phototoniccones pequenos Small Icons PhototonicOrdenar porSort By PhototonicQuadradaSquarish Phototonic:Parar apresentao de imagensStop Slide Show PhototonicEtiquetasTags PhototonicData do arquivoTime PhototonicSuperiorTop PhototonicTransformar Transform Phototonic2Transformaes bloqueadasTransformations Locked Phototonic8Transformaes desbloqueadasTransformations Unlocked Phototonic TriploTriple PhototonicTipoType Phototonic0Reverter horizontalmenteUnflipped Horizontally Phototonic,Reverter verticalmenteUnflipped Vertically PhototonicVisualizarView PhototonicVisualizadorViewer PhototonicCuidadoWarning PhototonicSimYes PhototonicZoomZoom PhototonicZoom %1%Zoom %1% PhototonicMais zoomZoom In PhototonicZoom bloqueado Zoom Locked PhototonicMenos zoomZoom Out PhototonicRestaurar zoom Zoom Reset Phototonic"Zoom desbloqueado Zoom Unlocked PhototonicCancelarCancelProgressDialogCancelarCancel ResizeDialogAltura:Height: ResizeDialogFixar proporoLock aspect ratio ResizeDialogNova dimenso: New size: ResizeDialog$Dimenso original:Original size: ResizeDialogPorcentualPercent ResizeDialog PixelsPixels ResizeDialogRedimensionarScale ResizeDialog(Redimensionar imagem Scale Image ResizeDialogUnidades:Units: ResizeDialogLargura:Width: ResizeDialogJAdicionar espao entre as miniaturas:Add space between thumbnails:SettingsDialogCor de fundo:Background color:SettingsDialog Imagem de fundo:Background image:SettingsDialogPela altura By heightSettingsDialogPela larguraBy widthSettingsDialog,Pela largura ou alturaBy width or heightSettingsDialogCancelarCancelSettingsDialog>Escolher pasta de inicializaoChoose Startup FolderSettingsDialogNQualidade padro quando salvar imagens:#Default quality when saving images:SettingsDialogVPadro ou especificado por linha de comando.Default, or specified by command line argumentSettingsDialogFIntervalo entre slides em segundos: Delay between slides in seconds:SettingsDialog"Confirmar excluirDelete confirmationSettingsDialogDesativarDisableSettingsDialog&Ativar animao GIFEnable GIF animationSettingsDialogSair em vez de fechar quando a imagem carregada atravez da linha de comando?Exit instead of closing, when image is loaded from command lineSettingsDialog.Ajustar imagens grandesFit Large ImagesSettingsDialog0Ajustar imagens pequenasFit Small ImagesSettingsDialog GeralGeneralSettingsDialogImagensImagesSettingsDialog Teclar de atalhoKeyboard ShortcutsSettingsDialogCor do rtulo: Label color:SettingsDialog`Nmero de pginas em miniatura para ler adiante:(Number of thumbnail pages to read ahead:SettingsDialogOkOKSettingsDialogAbrir arquivo Open FileSettingsDialogPreferncias PreferencesSettingsDialog Relembrar ltima Remember lastSettingsDialog^Rotacionar imagem de acordo com orientao Eixf*Rotate image according to Exif orientationSettingsDialogRGirar miniaturas conforme orientao Exif/Rotate thumbnails according to Exif orientationSettingsDialogPMostre o nome do arquivo no visualizadorShow image file name in viewerSettingsDialognMostrar imagem original quando menor do que a miniaturaIniciar apresentao de imagens Slide ShowSettingsDialogEspecfica:Specify:SettingsDialogPasta inicialStartup folderSettingsDialog.Esticar desproporcionalStretch disproportionatelySettingsDialogbTrocar aes do click do mouse esquerdo e do meio.Swap mouse left-click and middle-click actionsSettingsDialogMiniaturas ThumbnailsSettingsDialogVisualizadorViewerSettingsDialogVExibio cclica da apresentao de imagens1Wrap image list when reaching last or first imageSettingsDialogJ"%1" j est atribudo para "%2 ao.("%1" is already assigned to "%2" action.ShortcutsTableViewl"%1" reservado para atalhos de aplicativos externos.8"%1" is reserved for shortcuts to external applications.ShortcutsTableViewAoActionShortcutsTableViewExcluir atalhoDelete shortcutShortcutsTableViewDefinir atalho Set shortcutShortcutsTableView AtalhoShortcutShortcutsTableView %n imagem %n imagens %n image(s) ThumbView%n duplicada%n duplicadas%n duplicate(s) ThumbView%n imagem%n imagens %n image(s) ThumbView%n original%n originais%n original(s) ThumbViewErroError ThumbViewNome do arquivo File name ThumbViewFormatoFormat ThumbView GeralGeneral ThumbViewLocalizaoLocation ThumbViewMegapixel Megapixel ThumbViewModificadaModified ThumbViewNenhuma imagem No images ThumbViewResoluo Resolution ThumbViewLDigitalizada %1, exibindo %2 (%3 e %4)%Scanned %1, displaying %2 (%3 and %4) ThumbView<Procurar imagens duplicadas...Searching duplicate images... ThumbView(Selecionada %1 de %2Selected %1 of%2 ThumbViewDimensoSize ThumbViewphototonic-2.1/translations/phototonic_pt.ts000066400000000000000000001777671325127642100215600ustar00rootroot00000000000000 AppMgmtDialog Manage External Applications Gerir aplicativos externos Name Nome Application path and arguments Localização e argumentos Choose Escolher Add manually Adicionar manual Remove Remover OK Ok Choose Application Escolher aplicativo New Application Novo aplicativo ColorsDialog Colors Cores Reset Restaurar OK Ok Hue Matiz Saturation Saturação Lightness Luminosidade Colorize Colorizar Negative Negativo Red Vermelho Green Verde Blue Azul Hue and Saturation Matiz e saturação Affected Channels Afetar canais Brightness Brilho Contrast Contraste Brightness and Contrast Brilho e contraste Color Balance Balanceamento de cores CopyMoveToDialog Move to... Mover para... Copy to... Copiar para... Browse... Procurar... Remove Remover Cancel Cancelar OK Ok Destination: Destino: Choose Folder Escolher pasta CpMvDialog Cancel Cancelar Copying "%1" to "%2". Copiando "%1" to "%2". Moving "%1" to "%2". Movendo "%1" to "%2". CropDialog Cropping Recortar Reset Restaurar OK Ok Left Esquerda Right Direita Top Superior Bottom Inferior ImageTags Tag Etiqueta Untag Sem etiqueta Clear Filters Limpar filtros New Tag Nova etiqueta Image Tags Etiquetas da imagem Filter Filtro Remove Tag Remover etiqueta Negate Inverter Error Erro Failed to save tags to Falha ao salvar etiquetas para Tagging Etiquetar Untagging Remover etiquetas Add a new tag Adcionar nova etiqueta Enter new tag name Digite o novo nome da etiqueta No name entered Nenhum nome digitado Tag Etiqueta already exists já existe Remove selected tags(s)? Remover etiqueta(s) selecionada(s)? Remove tag Remover etiqueta Yes Sim Cancel Cancelar ImageView Clipboard Área de transferência Selection size: Dimensão da seleção: No selection Nada selecionado Hold down the Ctrl key and select a region using the mouse. Pressione a tecla Ctrl e selecione uma região com o mouse. Saving... Gravando... Error Erro Failed to save image. Falha ao gravar imagem. Failed to save Exif metadata. Falha ao gravar metadados Eixf. Image saved. Imagem gravada. Save image as Gravar imagem como Images Imagens InfoView Copy Cópia Phototonic Image Info Informação da imagem Zoom Zoom Mirroring Espelhamento Transform Transformar View Visualizar Top Superior Bottom Inferior Close Image Fechar imagem Full Screen Tela cheia Preferences Preferências Exit Sair Enlarge Thumbnails Aumentar miniaturas Shrink Thumbnails Diminuir miniaturas Diminuir miniaturas Cut Cortar Copy Copiar Copy to... Copiar para... Move to... Mover para... Delete Excluir Save Gravar Save As Gravar como Copy Image Data Copiar dados da imagem Paste Image Data Colar dados da imagem Rename Renomear Select All Selecionar todas About Sobre Name Nome Time Data do arquivo Size Dimensão Type Tipo Reverse Ordem reversa Show Hidden Files Mostrar arquivos ocultos Show Labels Mostrar nome dos arquivos Small Icons Ícones pequenos Hide Docks Title Bar Ocultar título dos painéis Hide Dock Title Bars Show Toolbar Mostrar barra de ferramentas Classic Thumbs Miniatura clássica Compact Compacta Squarish Quadrada Reload Recarregar Include Sub-folders Incluir subpastas Paste Here Colar aqui New Folder Nova pasta Back Retornar Forward Avançar Go Up Para cima Home Início Slide Show Iniciar apresentação de imagens Next Próxima Previous Anterior First Primeira Primeira Last Última Random Imagem aleatória Open Abir Load Clipboard Carregar da área de transferência Open With... Abrir com... Manage External Applications Gerir aplicativos externos Add Bookmark Adicionar aos favoritos Remove Bookmark Remover dos favoritos Zoom Out Menos zoom Zoom In Mais zoom Reset Zoom Restaurar zoom Original Size Dimensão original Keep Zoom Manter zoom Rotate 90 degree CCW Rotacionar 90 graus AH Rotate 90 degree CW Rotacionar 90 graus H Flip Horizontally Inverter na horizontal Flip Vertically Inverter na vertical Cropping Recortar Crop to Selection Recortar selecionado Scale Image Redimensionar imagem Rotate 1 degree CCW Rotacionar 1 grau AH Rotate 1 degree CW Rotacionar 1 grau H Colors Cores Find Duplicate Images Pesquisar imagens duplicadas Disable Desativado Dual Duplo Triple Triplo Dual Vertical Duplo vertical Quad Quadruplo Lock Transformations Transformações bloqueadas Move Left Mover para a esquerda Move Right Mover para a direita Move Up Mover para cima Move Down Mover para baixo Invert Selection Inverter seleção Filter by Name Filtrar por nome Set Path Indicar o caminho &File &Arquivos &Edit &Editar &Go &Ir &View &Visualizar Sort By Ordenar por &Tools &Ferramentas &Help &Ajuda Edit Editar Navigation Navegação Filter Filtro Image Imagem Initializing... Inicializando... File System Sistema de arquivos Bookmarks Favoritos Tags Etiquetas <p>Image viewer and organizer</p> <p>Visualizador e organizador de imagens</p> Home page Página inicial Bug reports Informar erros Error Erro Failed to start external application. Falha ao iniciar aplicativo externo. Invalid selection. Seleção inválida. Failed to copy or move image. Falha ao copiar ou mover imagem. Minimum zoom Zoom mínimo Zoom %1% Zoom %1% Maximum zoom Zoom máximo Zoom Reset Restaurar zoom Zoom Locked Zoom bloqueado Zoom Unlocked Zoom desbloqueado Transformations Locked Transformações bloqueadas Transformations Unlocked Transformações desbloqueadas Rotation %1° Rotação %1° Flipped Vertically Inverter verticalmente Unflipped Vertically Reverter verticalmente Flipped Horizontally Inverter horizontalmente Unflipped Horizontally Reverter horizontalmente No selection Nada selecionado Mirroring Disabled Espelhamento desativado Mirroring: Dual Espelhamento: Duplo Mirroring: Triple Espelhamento: Triplo Mirroring: Dual Vertical Espelhamento: Duplo vertical Mirroring: Quad Espelhamento: Quadruplo Can not copy or move to Impossível copiar ou mover para Can not copy or move to the same folder Impossível copiar ou mover para a mesma pasta Copied Copiada Moved Movida %n image(s) %n imagem %n imagens Permanently delete Excluir em definitivo Delete image Excluir imagem Yes Sim Cancel Cancelar Deleted Excluida Failed to delete image Falha ao excluir imagem Permanently delete selected images? Excluir em definitivo as imagens selecionadas? Delete images Excluir imagens Failed to delete image. Falha ao excluir imagem. Deleted Excluida Invalid Path: Caminho inválido: Viewer Visualizador Docks and Toolbars Painéis e barra de ferramentas No images Nenhuma imagem Failed to open file "%1", file not found. Failed to open file "%1": file not found. Falha ao abrir o arquivo "%1": Arquivo não encontrado. Slide show stopped Apresentação de imagens parada Stop Slide Show Parar apresentação de imagens Slide show started Iniciar apresentação de imagens Can not move or copy images to this folder. Impossível mover ou copiar imagens para essa pasta. Destination folder is same as source. Pasta de destino é a mesma da origem. Move "%1" to "%2"? Mover "%1" para "%2"? Move folder Mover pasta Failed to move folder. Falha ao mover pasta. Folder moved Pasta removida Failed to open folder: Falha ao abrir pasta: Duplicate images in %1 Imagens duplicadas em "%1" New name: Novo nome: Invalid name entered. Nome fornecido é inválido. Failed to rename folder. Falha ao renomear pasta. Invalid selection Seleção inválida Rename Image Renomear imagem Enter a new name for "%1": Forneça o novo nome para "%1": No name entered. Nenhum nome fornecido. Failed to rename image. Falha ao renomear imagem. Permanently delete "%1" and all of its contents? Excluir em definitivo "%1" com o seu conteúdo? Delete folder Excluir pasta Failed to delete folder. Falha ao excluir pasta. Removed "%1" Removida "%1" New Sub folder Nova subpasta New folder name: Nome da nova pasta: Failed to create new folder. Falha ao criar nova pasta. Created "%1" Criada "%1" Warning Cuidado Cannot perform action with temporary image. Não é possível executar a ação com a imagem temporária. ProgressDialog Cancel Cancelar QObject Usage: phototonic [FILE or DIRECTORY]... Uso: phototonic [FILE or DIRECTORY]... ResizeDialog Scale Image Redimensionar imagem Scale Redimensionar Cancel Cancelar Original size: Dimensão original: Width: Largura: Height: Altura: Units: Unidades: New size: Nova dimensão: Pixels Pixels Percent Porcentual Lock aspect ratio Fixar proporção SettingsDialog Preferences Preferências Fit Large Images Ajustar imagens grandes Disable Desativar By width Pela largura By height Pela altura Stretch disproportionately Esticar desproporcional Fit Small Images Ajustar imagens pequenas Exit instead of closing, when image is loaded from command line Sair em vez de fechar quando a imagem é carregada atravez da linha de comando Wrap image list when reaching last or first image Exibição cíclica da apresentação de imagens Default quality when saving images: Qualidade padrão quando salvar imagens: Enable GIF animation Ativar animação GIF Rotate image according to Exif orientation Rotacionar imagem de acordo com orientação Eixf Background color: Cor de fundo: By width or height Pela largura ou altura Show image file name in viewer Mostre o nome do arquivo no visualizador Label color: Cor do rótulo: Background image: Imagem de fundo: Add space between thumbnails: Adicionar espaço entre as miniaturas: Show original size of images smaller than the thumbnail size Mostrar imagem original quando menor do que a miniatura Number of thumbnail pages to read ahead: Número de páginas em miniatura para ler adiante: Rotate thumbnails according to Exif orientation Girar miniaturas conforme orientação Exif Delay between slides in seconds: Intervalo entre slides em segundos: Show random images Mostrar imagens aleatórias Startup folder Pasta inicial Default, or specified by command line argument Padrão ou especificado por linha de comando Remember last Relembrar última Specify: Específica: Swap mouse left-click and middle-click actions Trocar ações do click do mouse esquerdo e do meio Delete confirmation Confirmar excluir Keyboard Shortcuts Teclar de atalho OK Ok Cancel Cancelar Viewer Visualizador Thumbnails Miniaturas Slide Show Iniciar apresentação de imagens General Geral Choose Startup Folder Escolher pasta de inicialização Open File Abrir arquivo Images Imagens ShortcutsTable Action Ação Shortcut Atalho Delete shortcut Excluir atalho Set shortcut Definir atalho "%1" is reserved for shortcuts to external applications. "%1" é reservado para atalhos de aplicativos externos. "%1" is already assigned to "%2" action. "%1" já está atribuído para "%2 ação. ThumbView General Geral File name Nome do arquivo Location Localização Size Dimensão Modified Modificada Format Formato Resolution Resolução Megapixel Megapixel Error Erro %n image(s) %n imagem %n imagens No images Nenhuma imagem Selected %1 of%2 Selecionada %1 de %2 %n image(s) %n imagem %n imagens Scanned %1, displaying %2 (%3 and %4) Digitalizada %1, exibindo %2 (%3 e %4) %n original(s) %n original %n originais %n duplicate(s) %n duplicates %n duplicada %n duplicadas Searching duplicate images... Procurar imagens duplicadas... phototonic-2.1/translations/phototonic_ru.qm000066400000000000000000000647371325127642100215420ustar00rootroot00000000000000;P*JFO X[` [`@5_ _Ck yby|5&(*+ H5H50L2f3t6;=`%5@eAB]CV+),&o'A>X**%Q*0+"1by\bGLb %Lb LbLb\M $;N&Nn+,NP7'CTl0OX.X cX Y%Gi kn((xF NFFt%A=.JncU9g*2{QxYZ[)ndCNeDj3rIAvsnMÙ.3Ȳ)4 NT! 9N9<\N71w 5]~# nRf38%1u $kfG8QxYQxY[Rg<,SW4-eFu-vew(&w JVr_%!CA$AýOu!& #:alu/xz^YtQ] ]III IVIEwIEIJ>fX6d6oS,x: T:#CfR0֓]HeMfPtTE![_.%C_PD}n"eFF/jTȜG&ЍDNJDI(25(^\q4*E;G*=w%8c?-$Cl4]4/1jN &Jgg0> !p>Lממ26Js=IgY @a]*I@ >1%>8?m86U gl gl lq^3H t7J1 y-SL zdJF t;P #t G, K L@ #T@ Ds a1, dg id?+ p== p=T q%3 *! a  > $ )- 3 sO yeX yeL CT= 2'^ }8J ~h ~/ ; ʺP? H EQ Bn>  &e*D ,@~ .9k AB O PG'? R))5uW%5:E7";IUy6![t^ߔDiTZo0Ov0i`S >1028BL 2@CG=CN Add manually AppMgmtDialog:CBL : ?@8;>65=8N 8 0@3C<5=BKApplication path and arguments AppMgmtDialogK1@0BLChoose AppMgmtDialog$K1@0BL ?@8;>65=85Choose Application AppMgmtDialog@#?@02;5=85 2=5H=8<8 ?@8;>65=8O<8Manage External Applications AppMgmtDialog<OName AppMgmtDialog >2>5 ?@8;>65=85New Application AppMgmtDialogOKOK AppMgmtDialog#40;8BLRemove AppMgmtDialog,0459AB2>20==K5 :0=0;KAffected Channels ColorsDialog !8=89Blue ColorsDialog/@:>ABL Brightness ColorsDialog./@:>ABL 8 :>=B@0AB=>ABLBrightness and Contrast ColorsDialog&25B>2>9 10;0=A Color Balance ColorsDialog 0A:@0A8BLColorize ColorsDialog &25B0Colors ColorsDialog>=B@0AB=>ABLContrast ColorsDialog5;Q=K9Green ColorsDialogBB5=>:Hue ColorsDialog,BB5=>: 8 =0AKI5==>ABLHue and Saturation ColorsDialog/@:>ABL Lightness ColorsDialogOKOK ColorsDialog@0A=K9Red ColorsDialog!1@>A8BLReset ColorsDialog0AKI5==>ABL Saturation ColorsDialog17>@... Browse...CopyMoveToDialog B<5=0CancelCopyMoveToDialogK1@0BL ?0?:C Choose FolderCopyMoveToDialog>?8@>20BL 2... Copy to...CopyMoveToDialog&5;520O ?0?:0: Destination:CopyMoveToDialog 5@5<5AB8BL 2... Move to...CopyMoveToDialogOKOKCopyMoveToDialog#40;8BLRemoveCopyMoveToDialog B<5=0Cancel CpMvDialog0>?8@>20=85 "%1" 2 "%2".Copying "%1" to "%2". CpMvDialog05@5<5I5=85 "%1" 2 "%2".Moving "%1" to "%2". CpMvDialog !=87CBottom CropDialog1@57:0Cropping CropDialog !;520Left CropDialogOKOK CropDialog!1@>A8BLReset CropDialog !?@020Right CropDialog !25@ECTop CropDialog B<5=0Cancel ImageTags H81:0Error ImageTags $8;LB@Filter ImageTags0Yes ImageTagsCD5@ >1<5=0 Clipboard ImageView H81:0Error ImageViewJ5 C40;>AL A>E@0=8BL <5B040==K5 Exif.Failed to save Exif metadata. ImageViewB5 C40;>AL A>E@0=8BL 87>1@065=85.Failed to save image. ImageView06<8B5 :;028HC Ctrl 8 2K45;8B5 >1;0ABL 87>1@065=8O A ?><>ILN <KH8.;Hold down the Ctrl key and select a region using the mouse. ImageView,7>1@065=85 A>E@0=5=>. Image saved. ImageView7>1@065=8OImages ImageView5B 2K45;5=8O No selection ImageView2!>E@0=8BL 87>1@065=85 :0: Save image as ImageView!>E@0=5=85... Saving... ImageView>?8@>20BLCopyInfoView%n 87>1@065=85%n 87>1@065=8O%n 87>1@065=89 %n image(s) Phototonic&@02:0&Edit Phototonic &$09;&File Phototonic&5@5E>4&Go Phototonic&!?@02:0&Help Phototonic&=AB@C<5=BK&Tools Phototonic&84&View PhototonicV<p>@>A<>B@I8: 8 >@30=0975@ 87>1@065=89</p>!

Image viewer and organizer

 Phototonic ?@>3@0<<5About Phototonic">1028BL 70:;04:C Add Bookmark Phototonic 0704Back Phototonic0:;04:8 Bookmarks Phototonic=87Bottom Phototonic(!>>1I5=8O >1 >H81:0E Bug reports PhototonicP52>7<>6=> :>?8@>20BL 8;8 ?5@5<5AB8BL 2 Can not copy or move to  Phototonict52>7<>6=> :>?8@>20BL 8;8 ?5@5<5AB8BL 2 >4=C 8 BC 65 ?0?:C'Can not copy or move to the same folder Phototonic|52>7<>6=> ?5@5<5AB8BL 8;8 :>?8@>20BL 87>1@065=8O 2 MBC ?0?:C.+Can not move or copy images to this folder. Phototonic B<5=0Cancel Phototonicn52>7<>6=> 2K?>;=8BL 459AB285 A 2@5<5==K< 87>1@065=85<.+Cannot perform action with temporary image. Phototonic&;0AA8G5A:85 MA:87KClassic Thumbs Phototonic&0:@KBL 87>1@065=85 Close Image Phototonic &25B0Colors Phototonic><?0:B=K9 284Compact Phototonic!:>?8@>20=>Copied Phototonic>?8@>20BLCopy Phototonic<>?8@>20BL 87>1@065=85 2 1CD5@Copy Image Data Phototonic>?8@>20BL 2... Copy to... Phototonic!>740=0 "%1" Created "%1" Phototonic(1@570BL 2 2K45;5=85Crop to Selection Phototonic1@57:0Cropping PhototonicK@570BLCut Phototonic#40;8BLDelete Phototonic#40;8BL ?0?:C Delete folder Phototonic&#40;8BL 87>1@065=85 Delete image Phototonic&#40;8BL 87>1@065=8O Delete images Phototonic#40;5=>Deleted PhototonicL0?:0 =07=0G5=8O A>2?0405B A 8AE>4=>9.%Destination folder is same as source. Phototonic0?@5B8BLDisable Phototonic4>:8 8 ?0=5;8 8=AB@C<5=B>2Docks and Toolbars Phototonic 2064KDual Phototonic&2064K ?> 25@B8:0;8 Dual Vertical Phototonic<>2B>@ONI85AO 87>1@065=8O 2 %1Duplicate images in %1 Phototonic @02:0Edit Phototonic #25;8G8BL MA:87KEnlarge Thumbnails Phototonic62548B5 =>2>5 8<O 4;O "%1":Enter a new name for "%1": Phototonic H81:0Error Phototonic K9B8Exit Phototonicd5 C40;>AL :>?8@>20BL 8;8 ?5@5<5AB8BL 87>1@065=85.Failed to copy or move image. Phototonic>5 C40;>AL A>740BL =>2CN ?0?:C.Failed to create new folder. Phototonic25 C40;>AL C40;8BL ?0?:C.Failed to delete folder. Phototonic<5 C40;>AL C40;8BL 87>1@065=85Failed to delete image Phototonic>5 C40;>AL C40;8BL 87>1@065=85.Failed to delete image. Phototonic:5 C40;>AL ?5@5<5AB8BL ?0?:C.Failed to move folder. Phototonic25 C40;>AL >B:@KBL ?0?:C:Failed to open folder: Phototonic>5 C40;>AL ?5@58<5=>20BL ?0?:C.Failed to rename folder. PhototonicJ5 C40;>AL ?5@58<5=>20BL 87>1@065=85.Failed to rename image. PhototonicP5 C40;>AL 70?CAB8BL 2=5H=55 ?@8;>65=85.%Failed to start external application. Phototonic $09;>20O A8AB5<0 File System Phototonic $8;LB@Filter Phototonic($8;LB@>20BL ?> 8<5=8Filter by Name Phototonic>09B8 ?>2B>@ONI85AO 87>1@065=8OFind Duplicate Images Phototonic 5@2>5First Phototonic.B@078BL ?> 3>@87>=B0;8Flip Horizontally Phototonic*B@078BL ?> 25@B8:0;8Flip Vertically Phototonic.B@065=> ?> 3>@87>=B0;8Flipped Horizontally Phototonic*B@065=> ?> 25@B8:0;8Flipped Vertically Phototonic 0?:0 ?5@5<5I5=0 Folder moved Phototonic ?5@Q4Forward Phototonic> 25AL M:@0= Full Screen Phototonic 25@EGo Up Phototonic ><>9Home Phototonic"><0H=OO AB@0=8F0 Home page Phototonic7>1@065=85Image Phototonic0=D>@<0F8O > 87>1@065=88 Image Info Phototonic :;NG0O ?>4?0?:8Include Sub-folders Phototonic =8F80;870F8O...Initializing... Phototonic$5?@028;L=K9 ?CBL: Invalid Path: Phototonic22545=> =5?@028;L=>5 8<O.Invalid name entered. Phototonic,5?@028;L=>5 2K45;5=85Invalid selection Phototonic.5?@028;L=>5 2K45;5=85.Invalid selection. Phototonic.=25@B8@>20BL 2K45;5=85Invert Selection Phototonic"!>E@0=8BL <0AHB01 Keep Zoom Phototonic>A;54=55Last Phototonic<AB028BL 87>1@065=85 87 1CD5@0Load Clipboard Phototonic80D8:A8@>20BL ?@5>1@07>20=8OLock Transformations Phototonic@#?@02;5=85 2=5H=8<8 ?@8;>65=8O<8Manage External Applications Phototonic5@:0;8@>20=85 Mirroring Phototonic05@:0;8@>20=85 >B:;NG5=>Mirroring Disabled Phototonic,5@:0;8@>20=85: 42064KMirroring: Dual PhototonicF5@:0;8@>20=85: 42064K ?> 25@B8:0;8Mirroring: Dual Vertical Phototonic25@:0;8@>20=85: G5BK@564KMirroring: Quad Phototonic,5@:0;8@>20=85: B@864KMirroring: Triple Phototonic05@5<5AB8BL "%1" 2 "%2"?Move "%1" to "%2"? Phototonic!428=CBL 2=87 Move Down Phototonic!428=CBL 2;52> Move Left Phototonic!428=CBL 2?@02> Move Right Phototonic!428=CBL 225@EMove Up Phototonic"5@5<5AB8BL ?0?:C Move folder Phototonic 5@5<5AB8BL 2... Move to... Phototonic5@5<5AB8BLMoved Phototonic<OName Phototonic02830F8O Navigation Phototonic>20O ?0?:0 New Folder Phototonic>20O ?>4?0?:0New Sub folder Phototonic <O =>2>9 ?0?:8:New folder name: Phototonic>2>5 8<O: New name: Phototonic!;54CNI55Next Phototonic5B 87>1@065=89 No images Phototonic(<O =5 1K;> 22545=>.No name entered. Phototonic5B 2K45;5=8O No selection PhototonicB:@KBLOpen Phototonic(B:@KBL A ?><>ILN... Open With... PhototonicAE>4=K9 @07<5@ Original Size PhototonicAB028BL 745AL Paste Here Phototonic<AB028BL 87>1@065=85 87 1CD5@0Paste Image Data Phototonic 02A5340 C40;8BLPermanently delete PhototonicR02A5340 C40;8BL "%1" 8 2AQ 5Q A>45@68>5?0Permanently delete "%1" and all of its contents? PhototonicP02A5340 C40;8BL 2K45;5==K5 87>1@065=8O?#Permanently delete selected images? Phototonic0AB@>9:8 Preferences Phototonic@54K4CI55Previous Phototonic'5BK@564KQuad Phototonic!;CG09=>5Random Phototonic1=>28BLReload Phototonic #40;8BL 70:;04:CRemove Bookmark Phototonic#40;5=0 "%1" Removed "%1" Phototonic5@58<5=>20BLRename Phototonic25@58<5=>20BL 87>1@065=85 Rename Image Phototonic !1@>A8BL <0AHB01 Reset Zoom Phototonic 1@0B=K9 ?>@O4>:Reverse PhototonicL>25@=CBL =0 1 ?@>B82 G0A>2>9 AB@5;:8Rotate 1 degree CCW PhototonicD>25@=CBL =0 1 ?> G0A>2>9 AB@5;:5Rotate 1 degree CW PhototonicN>25@=CBL =0 90 ?@>B82 G0A>2>9 AB@5;:8Rotate 90 degree CCW PhototonicF>25@=CBL =0 90 ?> G0A>2>9 AB@5;:5Rotate 90 degree CW Phototonic>2>@>B %1 Rotation %1° Phototonic!>E@0=8BLSave Phototonic!>E@0=8BL :0:Save As Phototonic40AHB018@>20BL 87>1@065=85 Scale Image PhototonicK1@0BL 2AQ Select All Phototonic#AB0=>28BL ?CBLSet Path Phototonic,>:070BL A:@KBK5 D09;KShow Hidden Files Phototonic>:070BL <5B:8 Show Labels Phototonic8>:070BL ?0=5;L 8=AB@C<5=B>2 Show Toolbar Phototonic #<5=LH8BL MA:87KShrink Thumbnails Phototonic  07<5@Size Phototonic!;094-H>C Slide Show Phototonic$0G0;>AL A;094-H>CSlide show started Phototonic*!;094-H>C >AB0=>2;5=>Slide show stopped Phototonic 0;5=L:85 7=0G:8 Small Icons Phototonic#?>@O4>G8BL ?>Sort By Phototonic @O<>C3>;L=8:0<8Squarish Phototonic&AB0=>28B A;094-H>CStop Slide Show Phototonic @5<OTime Phototonic 25@ETop Phototonic@5>1@07>20BL Transform Phototonic8@5>1@07>20=8O 70D8:A8@>20=KTransformations Locked Phototonic:@5>1@07>20=8O @071;>:8@>20=KTransformations Unlocked Phototonic "@864KTriple Phototonic"8?Type Phototonic\>72@0I5=> 2 8AE>4=>5 ?>;>65=85 ?> 3>@87>=B0;8Unflipped Horizontally PhototonicX>72@0I5=> 2 8AE>4=>5 ?>;>65=85 ?> 25@B8:0;8Unflipped Vertically Phototonic84View Phototonic@>A<>B@I8:Viewer Phototonic=8<0=85Warning Phototonic0Yes PhototonicC<Zoom PhototonicC< %1%Zoom %1% Phototonic@81;878BLZoom In Phototonic(0AHB01 70D8:A8@>20= Zoom Locked PhototonicB40;8BLZoom Out Phototonic !1@>A8BL <0AHB01 Zoom Reset Phototonic*0AHB01 @071;>:8@>20= Zoom Unlocked Phototonic B<5=0CancelProgressDialog B<5=0Cancel ResizeDialogKA>B0:Height: ResizeDialog@0D8:A8@>20BL A>>B=>H5=85 AB>@>=Lock aspect ratio ResizeDialog>2K9 @07<5@: New size: ResizeDialog,5@2>=0G0;L=K9 @07<5@:Original size: ResizeDialog@>F5=BKPercent ResizeDialog8:A5;8Pixels ResizeDialog0AHB018@>20BLScale ResizeDialog40AHB018@>20BL 87>1@065=85 Scale Image ResizeDialog48=8FK:Units: ResizeDialog(8@8=0:Width: ResizeDialog>>1028BL ?@>15; <564C MA:870<8:Add space between thumbnails:SettingsDialog&25B D>=0:Background color:SettingsDialog($>=>2>5 87>1@065=85:Background image:SettingsDialog> 2KA>B5 By heightSettingsDialog> H8@8=5By widthSettingsDialog B<5=0CancelSettingsDialog.K1@0BL AB0@B>2CN ?0?:CChoose Startup FolderSettingsDialogd0G5AB2> ?> C<>;G0=8N ?@8 A>E@>0=5=88 87>1@065=89:#Default quality when saving images:SettingsDialogl> C<>;G0=8N, 8;8 7040==0O 0@3C<5=B>< :><0=4=>9 AB@>:8.Default, or specified by command line argumentSettingsDialogF045@6:0 <564C A;0940<8 2 A5:C=40E: Delay between slides in seconds:SettingsDialog0?@5B8BLDisableSettingsDialog*:;NG8BL GIF-0=8<0F8NEnable GIF animationSettingsDialogKE>4 2<5AB> 70:@KB8O, :>340 87>1@065=85 703@C65=> 87 :><0=4=>9 AB@>:8?Exit instead of closing, when image is loaded from command lineSettingsDialog:>43>=OBL 1>;LH85 87>1@065=8OFit Large ImagesSettingsDialog>>43>=OBL <0;5=L:85 87>1@065=8OFit Small ImagesSettingsDialog 1I85GeneralSettingsDialog7>1@065=8OImagesSettingsDialog !>G5B0=8O :;028HKeyboard ShortcutsSettingsDialog&25B 8<5=8: Label color:SettingsDialogf>;8G5AB2> AB@0=8F A MA:870<8 703@C605<K<8 70@0=55:(Number of thumbnail pages to read ahead:SettingsDialogOKOKSettingsDialogB:@KBL D09; Open FileSettingsDialog0AB@>9:8 PreferencesSettingsDialog&0?><=8BL ?>A;54=NN Remember lastSettingsDialogb>2>@0G820BL 87>1@065=85 A>3;0A=> >@85=B0F88 EXIF*Rotate image according to Exif orientationSettingsDialogX>2>@0G820BL MA:87K A>3;0A=> >@85=B0F88 EXIF/Rotate thumbnails according to Exif orientationSettingsDialog>:07K20BL =0AB>OI89 @07<5@ 87>1@065=89, :>B>@K5 <5=LH5 G5< @07<5@ MA:870:07K20BL A;CG09=K5 87>1@065=8OShow random imagesSettingsDialog!;094-H>C Slide ShowSettingsDialog040BL:Specify:SettingsDialog0G0;L=0O ?0?:0Startup folderSettingsDialog2?8A0BL =5?@>?>@F8>=0;L=>Stretch disproportionatelySettingsDialogt><5=OBL <5AB0<8 459AB28O ?> ;52><C 8 A@54=5<C I5;G:C <KH8.Swap mouse left-click and middle-click actionsSettingsDialog -A:87K ThumbnailsSettingsDialog@>A<>B@I8:ViewerSettingsDialog0:>;LF520BL A?8A>: 87>1@065=89 ?@8 4>AB865=88 ?>A;54=53> 8;8 ?5@2>3> 87>1@065=8O1Wrap image list when reaching last or first imageSettingsDialogB%1 C65 ?@8A2>5=> 459AB28N %2.("%1" is already assigned to "%2" action.ShortcutsTableView"%1" 70@575@28@>20=> 4;O A>G5B0=89 :;028H 4;O 2=5H=8E ?@8;>65=89.8"%1" is reserved for shortcuts to external applications.ShortcutsTableView59AB285ActionShortcutsTableView0#40;8BL A>G5B0=85 :;028HDelete shortcutShortcutsTableView4@8A2>8BL A>G5B0=85 :;028H Set shortcutShortcutsTableView !>G5B0=85 :;028HShortcutShortcutsTableView %n 87>1@065=8O %n 87>1@065=89 %n 87>1@065=89 %n image(s) ThumbView%n :>?8O%n :>?88%n :>?89%n duplicate(s) ThumbView%n 87>1@065=85%n 87>1@065=8O%n 87>1@065=89 %n image(s) ThumbView%n >@838=0;%n >@838=0;0%n >@838=0;>2%n original(s) ThumbView H81:0Error ThumbView<O D09;0 File name ThumbView $>@<0BFormat ThumbView 1I85General ThumbView5AB>?>;>65=85Location ThumbView530?8:A5;59 Megapixel ThumbView7<5=Q=Modified ThumbView5B 87>1@065=89 No images ThumbView 07@5H5=85 Resolution ThumbViewJ@>A<>B@5=> %1, ?>:070=> %2 (%3 8 %4)%Scanned %1, displaying %2 (%3 and %4) ThumbView4>8A: :>?89 87>1@065=89...Searching duplicate images... ThumbViewK1@0=> %1 87%2Selected %1 of%2 ThumbView  07<5@Size ThumbView ) , phototonic-2.1/translations/phototonic_ru.ts000066400000000000000000002143621325127642100215420ustar00rootroot00000000000000 AppMgmtDialog Manage External Applications Управление внешними приложениями Name Имя Application path and arguments Путь к приложению и аргументы Choose Выбрать Add manually Добавить вручную Remove Удалить OK OK Choose Application Выбрать приложение New Application Новое приложение ColorsDialog Colors Цвета Reset Сбросить OK OK Hue Оттенок Saturation Насыщенность Lightness Яркость Colorize Раскрасить Negative Red Красный Green Зелёный Blue Синий Hue and Saturation Оттенок и насыщенность Affected Channels Задействованные каналы Brightness Яркость Contrast Контрастность Brightness and Contrast Яркость и контрастность Color Balance Цветовой баланс CopyMoveToDialog Move to... Переместить в... Copy to... Копировать в... Browse... Обзор... Remove Удалить Cancel Отмена OK OK Destination: Целевая папка: Choose Folder Выбрать папку CpMvDialog Cancel Отмена Copying "%1" to "%2". Копирование "%1" в "%2". Moving "%1" to "%2". Перемещение "%1" в "%2". CropDialog Cropping Обрезка Reset Сбросить OK OK Top Сверху Left Слева Right Справа Bottom Снизу ImageTags Tag Untag Clear Filters New Tag Image Tags Filter Фильтр Remove Tag Negate Error Ошибка Failed to save tags to Tagging Untagging Add a new tag Enter new tag name No name entered Tag already exists Remove selected tags(s)? Remove tag Yes Да Cancel Отмена ImageView Clipboard Буфер обмена Selection size: No selection Нет выделения Hold down the Ctrl key and select a region using the mouse. Зажмите клавишу Ctrl и выделите область изображения с помощью мыши. Failed to save image. Не удалось сохранить изображение. Failed to save Exif metadata. Не удалось сохранить метаданные Exif. Image saved. Изображение сохранено. Saving... Сохранение... Error Ошибка Save image as Сохранить изображение как Images Изображения InfoView Copy Копировать Phototonic Image Info Информация о изображении Zoom Зум Transform Преобразовать Top Вверх Bottom Вниз Close Image Закрыть изображение Full Screen Во весь экран Preferences Настройки Exit Выйти Enlarge Thumbnails Увеличить эскизы Shrink Thumbnails Уменьшить эскизы Cut Вырезать Copy Копировать Rotation %1° Поворот %1° Docks and Toolbars Доки и панели инструментов Mirroring Зеркалирование Delete Удалить Save Сохранить Save As Сохранить как Rename Переименовать Select All Выбрать всё About О программе Name Имя Time Время Size Размер Type Тип Reverse Обратный порядок Show Hidden Files Показать скрытые файлы Show Labels Показать метки Small Icons Маленькие значки Hide Docks Title Bar Спрятать заголовки доков Classic Thumbs Классические эскизы Compact Компактный вид Squarish Прямоугольниками Reload Обновить Include Sub-folders Включая подпапки Paste Here Вставить здесь New Folder Новая папка Back Назад Forward Вперёд Up Вверх Home Домой Slide Show Слайд-шоу Next Следующее Previous Предыдущее First Первое Last Последнее Random Случайное Open Открыть Open With... Открыть с помощью... Scale Image Масштабировать изображение Contributors / Code: Участники / код: Contributors / Translations: Участники / переводчики: Failed to start external application. Не удалось запустить внешнее приложение. Invalid selection. Неправильное выделение. Failed to copy or move image. Не удалось копировать или переместить изображение. Zoom %1% Зум %1% Copied Скопировано Moved Переместить %n image(s) %n изображение %n изображения %n изображений Permanently delete Навсегда удалить Yes Да Cancel Отмена Failed to delete image. Не удалось удалить изображение. Deleted Удалено Invalid Path: Неправильный путь: Failed to open file "%1": file not found. Не удалось открыть файл "%1": файл не найден. Stop Slide Show Остановит слайд-шоу Duplicate images in %1 Повторяющиеся изображения в %1 Enter a new name for "%1": Введите новое имя для "%1": No name entered. Имя не было введено. Failed to rename image. Не удалось переименовать изображение. Permanently delete "%1" and all of its contents? Навсегда удалить "%1" и всё её содержиое? Failed to delete folder. Не удалось удалить папку. Removed "%1" Удалена "%1" Failed to create new folder. Не удалось создать новую папку. Created "%1" Создана "%1" Cannot perform action with temporary image. Невозможно выполнить действие с временным изображением. Manage External Applications Управление внешними приложениями Zoom Out Отдалить Zoom In Приблизить Reset Zoom Сбросить масштаб Original Size Исходный размер Keep Zoom Сохранить масштаб Rotate 90 degree CCW Повернуть на 90° против часовой стрелки Rotate 90 degree CW Повернуть на 90° по часовой стрелке Flip Horizontally Отразить по горизонтали Flip Vertically Отразить по вертикали Cropping Обрезка Rotate 1 degree CCW Повернуть на 1° против часовой стрелки Rotate 1 degree CW Повернуть на 1° по часовой стрелке Colors Цвета Disable Запретить Dual Дважды Triple Трижды Dual Vertical Дважды по вертикали Quad Четырежды Move Left Сдвинуть влево Move Right Сдвинуть вправо Move Up Сдвинуть вверх Move Down Сдвинуть вниз Invert Selection Инвертировать выделение Edit Правка View Вид Sort By Упорядочить по Navigation Навигация Filter Фильтр Initializing... Инициализация... File System Файловая система <p>Image viewer and organizer</p> <p>Просмотрщик и органайзер изображений</p> Home page Домашняя страница Bug reports Сообщения об ошибках &File &Файл &Edit &Правка &Go &Переход &View &Вид &Help &Справка Can not move or copy images to this folder. Невозможно переместить или копировать изображения в эту папку. Destination folder is same as source. Папка назначения совпадает с исходной. Move "%1" to "%2"? Переместить "%1" в "%2"? Failed to move folder. Не удалось переместить папку. Failed to open folder: Не удалось открыть папку: Invalid name entered. Введено неправильное имя. Failed to rename folder. Не удалось переименовать папку. Invalid selection Неправильное выделение Error Ошибка Can not copy or move to Невозможно копировать или переместить в Delete image Удалить изображение Failed to delete image Не удалось удалить изображение No selection Нет выделения Delete images Удалить изображения Permanently delete selected images? Навсегда удалить выделенные изображения? Copy to... Копировать в... Move to... Переместить в... Copy Image Data Копировать изображение в буфер Paste Image Data Вставить изображение из буфера Hide Dock Title Bars Show Toolbar Показать панель инструментов Go Up Вверх Load Clipboard Вставить изображение из буфера Add Bookmark Добавить закладку Remove Bookmark Удалить закладку Crop to Selection Обрезать в выделение Find Duplicate Images Найти повторяющиеся изображения Lock Transformations Зафиксировать преобразования Filter by Name Фильтровать по имени Set Path Установить путь &Tools &Инструменты Image Изображение Bookmarks Закладки Tags Minimum zoom Maximum zoom Zoom Reset Сбросить масштаб Zoom Locked Масштаб зафиксирован Zoom Unlocked Масштаб разблокирован Transformations Locked Преобразования зафиксированы Transformations Unlocked Преобразования разблокированы Flipped Vertically Отражено по вертикали Unflipped Vertically Возвращено в исходное положение по вертикали Flipped Horizontally Отражено по горизонтали Unflipped Horizontally Возвращено в исходное положение по горизонтали Mirroring Disabled Зеркалирование отключено Mirroring: Dual Зеркалирование: дважды Mirroring: Triple Зеркалирование: трижды Mirroring: Dual Vertical Зеркалирование: дважды по вертикали Mirroring: Quad Зеркалирование: четырежды Can not copy or move to the same folder Невозможно копировать или переместить в одну и ту же папку Deleted Viewer Просмотрщик No images Нет изображений Failed to open file "%1", file not found. Slide show stopped Слайд-шоу остановлено Slide show started Началось слайд-шоу Move folder Переместить папку Folder moved Папка перемещена New name: Новое имя: Rename Image Переименовать изображение Delete folder Удалить папку New Sub folder Новая подпапка New folder name: Имя новой папки: Warning Внимание ProgressDialog Cancel Отмена QObject Usage: phototonic [FILE or DIRECTORY]... Использование: phototonic [ФАЙЛ или ПАПКА]... ResizeDialog Scale Image Масштабировать изображение Scale Масштабировать Cancel Отмена Original size: Первоначальный размер: Width: Ширина: Height: Высота: Units: Единицы: New size: Новый размер: Pixels Пиксели Percent Проценты Lock aspect ratio Зафиксировать соотношение сторон SettingsDialog Preferences Настройки Default quality when saving images: Качество по умолчанию при сохроанении изображений: Background color: Цвет фона: By width or height Show image file name in viewer Background image: Фоновое изображение: Add space between thumbnails: Добавить пробел между эскизами: Number of thumbnail pages to read ahead: Количество страниц с эскизами загружаемыми заранее: Delay between slides in seconds: Задержка между слайдами в секундах: OK OK Cancel Отмена Rotate image according to Exif orientation Поворачивать изображение согласно ориентации EXIF Show original size of images smaller than the thumbnail size Показывать настоящий размер изображений, которые меньше чем размер эскиза Rotate thumbnails according to Exif orientation Поворачивать эскизы согласно ориентации EXIF Thumbnails Эскизы Fit Large Images Подгонять большие изображения Disable Запретить By width and height По ширине и высоте By width По ширине By height По высоте Stretch disproportionately Вписать непропорционально Fit Small Images Подгонять маленькие изображения Exit instead of closing, when image is loaded from command line Выход вместо закрытия, когда изображение загружено из командной строки Wrap image list when reaching last or first image Закольцевать список изображений при достижении последнего или первого изображения Enable GIF animation Включить GIF-анимацию Show image file name in full screen mode Показывать полное имя изображения в полноэкранном режиме Startup folder Начальная папка Default, or specified by command line argument По умолчанию, или заданная аргументом командной строки Remember last Запомнить последнюю Specify: Задать: Delete confirmation Keyboard Shortcuts Сочетания клавиш Viewer Просмотрщик Open File Открыть файл Images Изображения Show random images Показывать случайные изображения Slide Show Слайд-шоу Swap mouse left-click and middle-click actions Поменять местами действия по левому и среднему щелчку мыши Label color: Цвет имени: General Общие Choose Startup Folder Выбрать стартовую папку ShortcutsTable Action Действие Shortcut Сочетание клавиш Delete shortcut Удалить сочетание клавиш Set shortcut Присвоить сочетание клавиш "%1" is reserved for shortcuts to external applications. "%1" зарезервировано для сочетаний клавиш для внешних приложений. "%1" is already assigned to "%2" action. «%1» уже присвоено действию «%2». ThumbView File name Имя файла Location Местоположение Format Формат Resolution Разрешение Megapixel Мегапикселей Size Размер General Общие Modified Изменён Error Ошибка %n image(s) %n изображение %n изображения %n изображений No images Нет изображений Selected %1 of%2 Выбрано %1 из%2 %n image(s) In Russian "of" changes declension of a noun after number %n изображения %n изображений %n изображений Scanned %1, displaying %2 (%3 and %4) Просмотрено %1, показано %2 (%3 и %4) %n original(s) %n оригинал %n оригинала %n оригиналов %n duplicate(s) %n копия %n копии %n копий Searching duplicate images... Поиск копий изображений... phototonic-2.1/translations/phototonic_sr.qm000066400000000000000000000653711325127642100215330ustar00rootroot00000000000000OXZw_[` [`A_w_Dy?y|!5)q(,+ H5H52zL3f5t8/Y**%!*0y+1by\GLb 'LbLb Lb]RM &N)=Nn-YNP7)Tl2FX)X FX xY%H1\Zwikn*xFDFFt(bA>[0on!cWX9 *4lQxY[[)ndCOeEj5|rIAsnNJÙ.!HȲ,6 O! 9N;C<\N8w 5]~&nSf39%3r 'fG:^QxYQxY\sRg<.SW4/eFu0oG ve"w()w 5Wr`3'CC5$BnýQ u } !& #;lu1z^ZwtR] ]TIII `IIF=IFrIKEfY646ou,lZ' : :&fR2֓]=}}P-AaB= VFW O( O CP)nMUDEIl/^$p3G~~>K]8l5t8FqFqH59on^^%B jHD XLI^(ߺInS% +#C%n69$_>eNPtTE[c_.%D_PE}n%2GmjTMF1jV_7 q7ȜGЍD ( JDJm(40(^q6 E<Ho*>%8ck-GCl6d]41BjN#Kgg2>}$OA01>"I0מ%מ46Kz=JY A]*I@ ?%@?8@:.7 gl gl lq^51 t7J3 y-T zdJG' t< &9 G.3 DJ Lt M+ #TB Ds  a3# dg= id@x p=?E p=V q%5 *# a v >#y 'd )/8 3i sP ye} yeN CU 2'_C }8J ~k ~3 =1 ʺQT I5 ص ER8 Bn  &e, ,@~ , .: A0 O PG'@ Pr R40X @CG=> Add manually AppMgmtDialog:CB0Z0 8 0@3C<5=B8 0?;8:0F8X5Application path and arguments AppMgmtDialog7015@8Choose AppMgmtDialog$7015@8 0?;8:0F8XCChoose Application AppMgmtDialog>#?@02Y0X 5:AB5@=8< 0?;8:0F8X0<0Manage External Applications AppMgmtDialog<5Name AppMgmtDialog>20 0?;8:0F8X0New Application AppMgmtDialog #@54COK AppMgmtDialog #:;>=8Remove AppMgmtDialog>3>R5=8 :0=0;8Affected Channels ColorsDialog ;020Blue ColorsDialog!25B;>AB Brightness ColorsDialog&!25B;>AB 8 :>=B@0ABBrightness and Contrast ColorsDialog0;0=A 1>X0 Color Balance ColorsDialog 1>X8Colorize ColorsDialog>X5Colors ColorsDialog>=B@0ABContrast ColorsDialog 5;5=0Green ColorsDialog8X0=A0Hue ColorsDialog(8X0=A0 8 70A8[5=>ABHue and Saturation ColorsDialog!25B;8=0 Lightness ColorsDialog530B82Negative ColorsDialog #@54COK ColorsDialog &@25=0Red ColorsDialog>2@0B8Reset ColorsDialog0A8[5=>AB Saturation ColorsDialog@53;540X... Browse...CopyMoveToDialog B:068CancelCopyMoveToDialog 7015@8 D0AF8:;C Choose FolderCopyMoveToDialog>?8@0X C... Copy to...CopyMoveToDialog5AB8=0F8X0: Destination:CopyMoveToDialog><5@8 C... Move to...CopyMoveToDialog #@54COKCopyMoveToDialog #:;>=8RemoveCopyMoveToDialog B:068Cancel CpMvDialog(>?8@0< "%1" C "%2".Copying "%1" to "%2". CpMvDialog(><5@0< "%1" C "%2".Moving "%1" to "%2". CpMvDialog>;5Bottom CropDialog 7@568Cropping CropDialog52>Left CropDialog #@54COK CropDialog>2@0B8Reset CropDialog 5A=>Right CropDialog>@5Top CropDialog5[ ?>AB>X8 already exists ImageTags">40X =>2C >7=0:C Add a new tag ImageTags B:068Cancel ImageTags#:;>=8 D8;B5@5 Clear Filters ImageTags #=5A8 8<5 >7=0:5Enter new tag name ImageTags @5H:0Error ImageTags.5CA?5;> A=8<0Z5 >7=0:5Failed to save tags to  ImageTags $8;B5@Filter ImageTags>20 >7=0:0New Tag ImageTags <5 =8X5 C=5A5=>No name entered ImageTags#:;>=8 >7=0:C Remove Tag ImageTags4#:;>=8 8701@0=C >7=0:C(5)?Remove selected tags(s)? ImageTags#:;>=8 >7=0:C Remove tag ImageTags 7=0G8Tag ImageTags 7=0:0Tag  ImageTags7=0G820Z5Tagging  ImageTags#:;>=8 >7=0:CUntag ImageTags#:;0Z0Z5 >7=0:0 Untagging  ImageTags0Yes ImageTags;81>@4 Clipboard ImageView @5H:0Error ImageViewB@5H:0 ?@8 A=8<0ZC Exif ?>40B0:0.Failed to save Exif metadata. ImageView2@5H:0 ?@8 A=8<0ZC A;8:5.Failed to save image. ImageViewt@68 Ctrl 4C3<5 ?@8B8A=CB> 8 87015@8 @538XC :>@8AB5[8 <8H.;Hold down the Ctrl key and select a region using the mouse. ImageView!;8:0 A=8<Y5=0. Image saved. ImageView !;8:5Images ImageView57 A5;5:F8X5 No selection ImageView!=8<8 A;8:C :0> Save image as ImageView!=8<0<... Saving... ImageView&5;8G8=0 A5;5:F8X5:Selection size:  ImageView>?8@0XCopyInfoView Phototonic%n A;8:0%n A;8:5%n A;8:0 %n image(s) Phototonic &#@548&Edit Phototonic &$0X;&File Phototonic&48&Go Phototonic &><>[&Help Phototonic &;0B8&Tools Phototonic&>3;54&View Phototonic:@53;540G 8 >@30=870B>@ A;8:0!

Image viewer and organizer

 PhototonicAbout Phototonic>40X :@0B8FC Add Bookmark Phototonic 0704Back Phototonic0@B8F5 Bookmarks Phototonic>;5Bottom Phototonic@8X028 3@5H:5 Bug reports PhototonicB5<>3C[5 :>?8@0B8 8;8 ?><5@8B8 C Can not copy or move to  Phototonic\5<>3C[5 :>?8@0B8 8;8 ?><5@8B8 C 8ABC D0AF8:;C'Can not copy or move to the same folder Phototonich5<>3C[5 ?><5@8B8 8;8 :>?8@0B8 A;8:5 C >2C D0AF8:;C.+Can not move or copy images to this folder. Phototonic B:068Cancel Phototonic\5<>3C[5 8725AB8 0:F8XC A0 ?@82@5<5=>< A;8:><.+Cannot perform action with temporary image. Phototonic4;0A8G=5 <8=8X0BC@=5 A;8:5Classic Thumbs Phototonic0B2>@8 A;8:C Close Image Phototonic>X5Colors Phototonic><?0:B=>Compact Phototonic>?8@0=>Copied Phototonic>?8@0XCopy Phototonic*>?8@0X ?>40B:5 A;8:5Copy Image Data Phototonic>?8@0X C... Copy to... Phototonic0?@02Y5= "%1" Created "%1" Phototonic 7@568 A5;5:F8XCCrop to Selection Phototonic 7@568Cropping Phototonic 7@568Cut Phototonic71@8H8Delete Phototonic 71@8H8 D0AF8:;C Delete folder Phototonic71@8H8 A;8:C Delete image Phototonic71@8H8 A;8:5 Delete images Phototonic71@8A0=>Deleted Phototonic71@8A0=>Deleted  PhototonicR4@548H=0 D0AF8:;0 X5 8AB0 :0> 8 ?>G5B=0.%Destination folder is same as source. PhototonicA:YCG5=>Disable Phototonic,!84@5=5 8 0;0B=5 B@0:5Docks and Toolbars Phototonic2>AB@C:>Dual Phototonic(2>AB@C:> 25@B8:0;=> Dual Vertical Phototonic C?;5 A;8:5 C %1Duplicate images in %1 Phototonic #@548Edit Phototonic6>25[0X <8=8X0BC@=5 ?@8:075Enlarge Thumbnails Phototonic.#=5A8 =>2> 8<5 70 "%1":Enter a new name for "%1": Phototonic @5H:0Error Phototonic 70R8Exit PhototonicJ5CA?5;> :>?8@0Z5 8;8 ?><5@0Z5 A;8:5.Failed to copy or move image. Phototonic@5CA?5;> ?@02Y5Z5 =>25 D0AF8:;5.Failed to create new folder. Phototonic45CA?5;> 1@8A0Z5 D0AF8:;5.Failed to delete folder. Phototonic,5CA?5;> 1@8A0Z5 A;8:5Failed to delete image Phototonic.5CA?5;> 1@8A0Z5 A;8:5.Failed to delete image. Phototonic65CA?5;> ?><5@0Z5 D0AF8:;5.Failed to move folder. Phototonic6=5CA?5;> >B20@0Z5 D0AF8:;5:Failed to open folder: Phototonic>5CA?5;> ?@58<5=>20Z5 D0AF8:;5.Failed to rename folder. Phototonic85CA?5;> ?@58<5=>20Z5 A;8:5.Failed to rename image. PhototonicR@5H:0 ?@8 ?>:@5B0ZC 5:AB5@=5 0?;8:0F8X5.%Failed to start external application. Phototonic$0X; A8AB5< File System Phototonic $8;B5@Filter Phototonic$$8;B@8@0X ?> 8<5=CFilter by Name Phototonic&@>=0R8 4C?;5 A;8:5Find Duplicate Images Phototonic@20First Phototonic$1@=8 E>@87>=B0;=>Flip Horizontally Phototonic 1@=8 25@B8:0;=>Flip Vertically Phototonic(1@=CB> E>@87>=B0;=>Flipped Horizontally Phototonic$1@=CB> 25@B8:0;=>Flipped Vertically Phototonic"$0AF8:;0 ?><5@5=0 Folder moved Phototonic 0?@54Forward Phototonic2@8:07 ?@5:> F5;>3 5:@0=0 Full Screen Phototonic48 3>@5Go Up Phototonic>G5B=0Home Phototonic >G5B=0 AB@0=8F0 Home page Phototonic !;8:0Image Phototonic&=D>@<0F8X5 > A;8F8 Image Info Phototonic&#:YCG8 ?>4-D0AF8:;5Include Sub-folders Phototonic>:@5[5<...Initializing... Phototonic 520Y0;0 ?CB0Z0: Invalid Path: Phototonic*52065[5 8<5 C=5A5=>.Invalid name entered. Phototonic$520Y0;0 A5;5:F8X0Invalid selection Phototonic&520Y0;0 A5;5:F8X0.Invalid selection. Phototonic1@=8 A5;5:F8XCInvert Selection Phototonic04@68 7C< Keep Zoom Phototonic 04Z0Last Phototonic#G8B0X :;8?1>@4Load Clipboard Phototonic.0:YCG0X B@0=AD>@<0F8X5Lock Transformations Phototonic>#?@02Y0X 5:AB5@=8< 0?;8:0F8X0<0Manage External Applications Phototonic&@5A;8:0 (>3;540;>) Mirroring Phototonic,@5A;8:020Z5 8A:YCG5=>Mirroring Disabled Phototonic,@5A;8:020Z5 42>AB@C:>Mirroring: Dual PhototonicB@5A;8:020Z5 42>AB@C:> 25@B8:0;=>Mirroring: Dual Vertical Phototonic4@5A;8:020Z5 G5B25@>AB@C:>Mirroring: Quad Phototonic,@5A;8:020Z5 B@>AB@C:>Mirroring: Triple Phototonic&><5@8 "%1" C "%2"?Move "%1" to "%2"? Phototonic><5@8 4>;5 Move Down Phototonic><5@8 ;52> Move Left Phototonic><5@8 45A=> Move Right Phototonic><5@8 3>@5Move Up Phototonic><5@8 D0AF8:;C Move folder Phototonic><5@8 C... Move to... Phototonic><5@5=>Moved Phototonic<5Name Phototonic02830F8X0 Navigation Phototonic>20 D0AF8:;0 New Folder Phototonic">20 ?>4-D0AF8:;0New Sub folder Phototonic$>2> 8<5 D0AF8:;5:New folder name: Phototonic>2> 8<5: New name: Phototonic!;545[aNext Phototonic5<0 A;8:0 No images Phototonic"<5 =8X5 C=5A5=>.No name entered. Phototonic57 A5;5:F8X5 No selection Phototonic B2>@8Open Phototonic B2>@8 ?><>[C... Open With... Phototonic&@838=0;=0 25;8G8=0 Original Size Phototonic0;5?8 >245 Paste Here Phototonic(0;5?8 ?>40B:5 A;8:5Paste Image Data Phototonic"@0X=> 871@8H8Permanently delete PhototonicD"@0X=> 71@8H8 "%1" 8 A02 A04@60X?0Permanently delete "%1" and all of its contents? Phototonic<"@0X=> 871@8H8 >401@0=5 A;8:5?#Permanently delete selected images? Phototonic>AB02:5 Preferences Phototonic @>H;0Previous Phototonic'5B25@>AB@C:>Quad Phototonic0AC<8G=0Random Phototonic#G8B0X ?>=>2>Reload Phototonic#:;>=8 :@0B8FCRemove Bookmark Phototonic#:;>Z5= "%1" Removed "%1" Phototonic@58<5=CXRename Phototonic@58<5=CX A;8:C Rename Image Phototonic>2@0B8 7C< Reset Zoom Phototonic 1@=8Reverse PhototonicB >B8@0X 1 AB5?5= AC?@>B=> :070YF8Rotate 1 degree CCW Phototonic@@>B8@0X 1 AB5?5= C A<5@C :070Y:5Rotate 1 degree CW PhototonicF >B8@0X 90 AB5?5=8 AC?@>B=> :070YF8Rotate 90 degree CCW PhototonicD >B8@0X 90 AB5?5=8 C A<5@C :070Y:5Rotate 90 degree CW Phototonic >B0F8X0 %1 Rotation %1° Phototonic !=8<8Save Phototonic!=8<8 :0>Save As Phototonic,@><5=8 25;8G8=C A;8:5 Scale Image Phototonic7=0G8 A25 Select All Phototonic>AB028 ?CB0ZCSet Path Phototonic2@8:068 A:@825=5 40B>B5:5Show Hidden Files Phototonic@8:068 =0B?8A5 Show Labels Phototonic(@8:068 0;0B=C B@0:C Show Toolbar Phototonic4#<0=Z8 <8=8X0BC@=5 ?@8:075Shrink Thumbnails Phototonic5;8G8=0Size Phototonic!;0X4 ?@8:07 Slide Show Phototonic$!;0X4 ?@8:07 ?>G5BSlide show started Phototonic.!;0X4 ?@8:07 >1CAB02Y5=Slide show stopped Phototonic0;5 8:>=5 Small Icons Phototonic!>@B8@0X ?>Sort By Phototonic>F:0AB>Squarish Phototonic*1CAB0=8 A;0X4 ?@8:07Stop Slide Show Phototonic 7=0:5Tags Phototonic @5<5Time Phototonic>@5Top Phototonic"@0=AD>@<8H8 Transform Phototonic0"@0=AD>@<0F8X5 70:YCG0=5Transformations Locked Phototonic0"@0=AD>@<0F8X5 >B:YCG0=5Transformations Unlocked Phototonic"@>AB@C:>Triple Phototonic"8?Type Phototonic,5>1@=CB> E>@87>=B0;=>Unflipped Horizontally Phototonic(5>1@=CB> 25@B8:0;=>Unflipped Vertically Phototonic >3;54View Phototonic@53;540GViewer Phototonic 06Z0Warning Phototonic0Yes Phototonic #1;868Zoom Phototonic#1;868 %1%Zoom %1% Phototonic #1;868Zoom In PhototonicC< 70:YCG0= Zoom Locked Phototonic #40Y8Zoom Out PhototonicC< 2@0[5= Zoom Reset PhototonicC< >B:YCG0= Zoom Unlocked Phototonic B:068CancelProgressDialog B:068Cancel ResizeDialog8A8=0:Height: ResizeDialog0:YCG0X ><5@Lock aspect ratio ResizeDialog>20 25;8G8=0: New size: ResizeDialog(@838=0;=0 25;8G8=0:Original size: ResizeDialog>AB>B0:Percent ResizeDialog8:A5;8Pixels ResizeDialog#25[0X/!<0Z8Scale ResizeDialog,@><5=8 25;8G8=C A;8:5 Scale Image ResizeDialog548=8F5:Units: ResizeDialog(8@8=0:Width: ResizeDialogR>40X @07<0: 87<5RC <8=8X0BC@=8E ?@8:070:Add space between thumbnails:SettingsDialog>X0 ?>7048=5:Background color:SettingsDialog">7048=A:0 A;8:0:Background image:SettingsDialog> 28A8=8 By heightSettingsDialog> H8@8=8By widthSettingsDialog(> H8@8=8 8;8 28A8=8By width or heightSettingsDialog B:068CancelSettingsDialog07015@8 ?>G5B=C D0AF8:;CChoose Startup FolderSettingsDialogL!B0=40@4=8 :20;8B5B ?@8 A=8<0ZC A;8:0:#Default quality when saving images:SettingsDialogf!B0=40@4=8, 8;8 :><0=4=>< ;8=8jom >4@5R5=8 0@3C<5=B.Default, or specified by command line argumentSettingsDialogF 07<0: 87<5RC A;0X4>20 C A5:C=40<0: Delay between slides in seconds:SettingsDialog$>B2@40 70 1@8A0Z5Delete confirmationSettingsDialogA:YCG5=>DisableSettingsDialog(#:YCG8 GIF 0=8<0F8X5Enable GIF animationSettingsDialog0?CAB8 C<5AB> 70B20@0Z0 :040 X5 CG8B0=0 A;8:0 87 :><0=4=5 ;8=8X5?Exit instead of closing, when image is loaded from command lineSettingsDialog,@8;03>48 25;8:5 A;8:5Fit Large ImagesSettingsDialog(@8;03>48 <0Z5 A;8:5Fit Small ImagesSettingsDialog?[5=8B>GeneralSettingsDialog !;8:5ImagesSettingsDialog"@0B8F5 B0AB0BC@5Keyboard ShortcutsSettingsDialogBoja natpisa: Label color:SettingsDialogj@>X AB@0=8F0 <8=8X0BC@=8E A;8:0 40 A5 CG8B0 C=0?@54:(Number of thumbnail pages to read ahead:SettingsDialog #@54COKSettingsDialogB2>@8 D0X; Open FileSettingsDialog>AB02:5 PreferencesSettingsDialog 0?0<B8 ?>A;54ZC Remember lastSettingsDialogJ >B8@0X A;8:5 ?@5<0 Exif >@8X5=B0F8X8*Rotate image according to Exif orientationSettingsDialog\ >B8@0X <8=8X0BC@=5 A;8:5 ?> Exif >@8X5=B0F8X8/Rotate thumbnails according to Exif orientationSettingsDialog<@8:068 8<5 A;8:5 C ?@53;540GCShow image file name in viewerSettingsDialog@8:068 >@838=0;=C 25;8G8=C A;8:0 :>X5 AC <0=Z5 >4 <8=8X0BC@=5 25;8G8=5G5B=0 D0AF8:;0Startup folderSettingsDialog2 072CF8 48A?@>?>@F8>=0;=>Stretch disproportionatelySettingsDialogR0<5=8 0:F8X5 ;52>3 8 A@54Z53 :;8:0 <8H5<.Swap mouse left-click and middle-click actionsSettingsDialog$8=8X0BC@=8 ?@8:07 ThumbnailsSettingsDialog@53;540GViewerSettingsDialog8#<>B0X ;8ABC A;8:0 ?@8 :@0XC1Wrap image list when reaching last or first imageSettingsDialogN"%1" X5 25[ C?>B@51Y5=> 70 "%2" 0:F8XC.("%1" is already assigned to "%2" action.ShortcutsTableViewh"%1" X5 >1@=CB> 70 ?@5G8F5 :>4 5:AB5@=8E 0?;8:0F8X0.8"%1" is reserved for shortcuts to external applications.ShortcutsTableView :F8X0ActionShortcutsTableView71@8H8 ?@5G8FCDelete shortcutShortcutsTableView>AB028 ?@5G8FC Set shortcutShortcutsTableView@5G8F5ShortcutShortcutsTableView%n A;8:0%n A;8:5%n A;8:0 %n image(s) ThumbView%n 4C?;8:0B%n 4C?;8:0B0%n 4C?;8:0B0%n duplicate(s) ThumbView%n A;8:0%n A;8:5%n A;8:0 %n image(s) ThumbView%n >@838=0;%n >@838=0;0%n >@838=0;0%n original(s) ThumbView @5H:0Error ThumbView<5 D0X;0 File name ThumbView D>@<0BFormat ThumbView#>?HB5=>General ThumbView>:0F8X0Location ThumbView530?8:A5; Megapixel ThumbView>48D8F8@0=Modified ThumbView5<0 A;8:0 No images ThumbView 57>;CF8X0 Resolution ThumbViewH!:5=8@0= %1, ?@8:07CX5< %2 (%3 8 %4)%Scanned %1, displaying %2 (%3 and %4) ThumbView*"@068< 4C?;5 A;8:5...Searching duplicate images... ThumbView"701@0=> %1 >4 %2Selected %1 of%2 ThumbView5;8G8=0Size ThumbView ) , phototonic-2.1/translations/phototonic_sr.ts000066400000000000000000002112671325127642100215410ustar00rootroot00000000000000 AppMgmtDialog Manage External Applications Управљај екстерним апликацијама Name Име Application path and arguments Путања и аргументи апликације Choose Изабери Add manually Додај ручно Remove Уклони OK Уреду Choose Application Изабери апликацију New Application Нова апликација ColorsDialog Colors Боје Reset Поврати OK Уреду Hue Нијанса Saturation Засићеност Lightness Светлина Colorize Обоји Negative Негатив Red Црвена Green Зелена Blue Плава Hue and Saturation Нијанса и засићеност Affected Channels Popravi Погођени канали Brightness Светлост Contrast Контраст Brightness and Contrast Светлост и контраст Color Balance Баланс боја CopyMoveToDialog Move to... Помери у... Copy to... Копирај у... Browse... Прегледај... Remove Уклони Cancel Откажи OK Уреду Destination: Дестинација: Choose Folder Изабери фасциклу CpMvDialog Cancel Откажи Copying "%1" to "%2". Копирам "%1" у "%2". Moving "%1" to "%2". Померам "%1" у "%2". CropDialog Cropping Изрежи Reset Поврати OK Уреду Left Лево Right Десно Top Горе Bottom Доле ImageTags Image Tags Filter Филтер Tag Означи Untag Уклони ознаку New Tag Нова ознака Remove Tag Уклони ознаку Clear Filters Уклони филтере Negate Error Грешка Failed to save tags to Неуспело снимање ознаке Tagging Означивање Untagging Уклањање ознака Add a new tag Додај нову ознаку Enter new tag name Унеси име ознаке No name entered Име није унесено Tag Ознака already exists Већ постоји Remove selected tags(s)? Уклони изабрану ознаку(е)? Remove tag Уклони ознаку Yes Да Cancel Откажи ImageView Clipboard Клиборд Selection size: Величина селекције: No selection Без селекције Hold down the Ctrl key and select a region using the mouse. Држи Ctrl дугме притиснуто и изабери регију користећи миш. Saving... Снимам... Error Грешка Failed to save image. Грешка при снимању слике. Failed to save Exif metadata. Грешка при снимању Exif података. Image saved. Слика снимљена. Save image as Сними слику као Images Слике InfoView Copy Копирај Phototonic Image Info Информације о слици Zoom Уближи Mirroring Ово треба поправити Преслика (огледало) Transform Трансформиши View Поглед Top Горе Bottom Доле Close Image Затвори слику Full Screen Приказ преко целог екрана Preferences Поставке Exit Изађи Enlarge Thumbnails Повећај минијатурне приказе Shrink Thumbnails Уманњи минијатурне приказе Cut Изрежи Copy Копирај Copy to... Копирај у... Move to... Помери у... Delete Избриши Save Сними Save As Сними као Copy Image Data Копирај податке слике Paste Image Data Налепи податке слике Rename Преименуј Select All Означи све About О Name Име Time Време Size Величина Type Тип Reverse Обрни Show Hidden Files Прикажи скривене датотеке Show Labels Прикажи натписе Small Icons Мале иконе Hide Docks Title Bar Сакриј насловну траку сидрене траке Hide Dock Title Bars Show Toolbar Прикажи алатну траку Classic Thumbs Класичне минијатурне слике Compact Компактно Squarish Коцкасто Reload Учитај поново Include Sub-folders Укључи под-фасцикле Paste Here Налепи овде New Folder Нова фасцикла Back Назад Forward Напред Go Up Иди горе Home Почетна Slide Show Слајд приказ Next Следећa Previous Прошла First Прва Last Задња Random Насумична Open Отвори Load Clipboard Учитај клипборд Open With... Отвори помоћу... Manage External Applications Управљај екстерним апликацијама Add Bookmark Додај кратицу Remove Bookmark Уклони кратицу Zoom Out Удаљи Zoom In Уближи Reset Zoom Поврати зум Original Size Оригинална величина Keep Zoom Задржи зум Rotate 90 degree CCW Ротирај 90 степени супротно казаљци Rotate 90 degree CW Ротирај 90 степени у смеру казаљке Flip Horizontally Обрни хоризонтално Flip Vertically Обрни вертикално Cropping Изрежи Crop to Selection Изрежи селекцију Scale Image Промени величину слике Rotate 1 degree CCW Ротирај 1 степен супротно казаљци Rotate 1 degree CW ротирај 1 степен у смеру казаљке Colors Боје Find Duplicate Images Пронађи дупле слике Disable Искључено Dual Двоструко Triple Троструко Dual Vertical Двоструко вертикално Quad Четвероструко Lock Transformations Закључај трансформације Move Left Помери лево Move Right Помери десно Move Up Помери горе Move Down Помери доле Invert Selection Обрни селекцију Filter by Name Филтрирај по имену Set Path Постави путању &File &Фајл &Edit &Уреди &Go &Иди &View &Поглед Sort By Сортирај по &Tools &Алати &Help &Помоћ Edit Уреди Navigation Навигација Filter Филтер Image Слика Initializing... Покрећем... File System Фајл систем Bookmarks Картице Tags Ознаке <p>Image viewer and organizer</p> Прегледач и организатор слика Home page Почетна страница Bug reports Пријави грешке Error Грешка Failed to start external application. Грешка при покретању екстерне апликације. Invalid selection. Неваљала селекција. Failed to copy or move image. Неуспело копирање или померање слике. Minimum zoom Zoom %1% Уближи %1% Maximum zoom Zoom Reset Зум враћен Zoom Locked Зум закључан Zoom Unlocked Зум откључан Transformations Locked Трансформације закључане Transformations Unlocked Трансформације откључане Rotation %1° Ротација %1° Failed to open file "%1", file not found. Flipped Vertically Обрнуто вертикално Unflipped Vertically Необрнуто вертикално Flipped Horizontally Обрнуто хоризонтално Unflipped Horizontally Необрнуто хоризонтално No selection Без селекције Mirroring Disabled Пресликавање искључено Mirroring: Dual Пресликавање двоструко Mirroring: Triple Пресликавање троструко Mirroring: Dual Vertical Пресликавање двоструко вертикално Mirroring: Quad Пресликавање четвероструко Can not copy or move to Немогуће копирати или померити у Can not copy or move to the same folder Немогуће копирати или померити у исту фасциклу Copied Копирано Moved Померено %n image(s) %n слика %n слике %n слика Permanently delete Трајно избриши Delete image Избриши слику Yes Да Cancel Откажи Deleted Избрисано Failed to delete image Неуспело брисање слике Permanently delete selected images? Трајно избриши одабране слике? Delete images Избриши слике Failed to delete image. Неуспело брисање слике. Deleted Избрисано Invalid Path: Неваљала путања: Viewer Прегледач Docks and Toolbars Сидрене и алатне траке No images Нема слика Failed to open file "%1": file not found. неуспело отварање фајла "%1": фајл није пронађен. Slide show stopped Слајд приказ обустављен Stop Slide Show Обустани слајд приказ Slide show started Слајд приказ почет Can not move or copy images to this folder. Немогуће померити или копирати слике у ову фасциклу. Destination folder is same as source. Одредишна фасцикла је иста као и почетна. Move "%1" to "%2"? Помери "%1" у "%2"? Move folder Помери фасциклу Failed to move folder. Неуспело померање фасцикле. Folder moved Фасцикла померена Failed to open folder: неуспело отварање фасцикле: Duplicate images in %1 Дупле слике у %1 New name: Ново име: Invalid name entered. Неважеће име унесено. Failed to rename folder. Неуспело преименовање фасцикле. Invalid selection Неваљала селекција Rename Image Преименуј слику Enter a new name for "%1": Унеси ново име за "%1": No name entered. Име није унесено. Failed to rename image. Неуспело преименовање слике. Permanently delete "%1" and all of its contents? Трајно Избриши "%1" и сав садржај? Delete folder Избриши фасциклу Failed to delete folder. Неуспело брисање фасцикле. Removed "%1" Уклоњен "%1" New Sub folder Нова под-фасцикла New folder name: Ново име фасцикле: Failed to create new folder. Неуспело прављење нове фасцикле. Created "%1" Направљен "%1" Warning Пажња Cannot perform action with temporary image. Немогуће извести акцију са привременом сликом. ProgressDialog Cancel Откажи QObject Usage: phototonic [FILE or DIRECTORY]... Користи овако: phototonic [ФАЈЛ или ФАСЦИКЛА]... ResizeDialog Scale Image Промени величину слике Scale Можа има болја јединствена реч Увећај/Смањи Cancel Откажи Original size: Оригинална величина: Width: Ширина: Height: Висина: Units: Јединице: New size: Нова величина: Pixels Пиксели Percent Постотак Lock aspect ratio Закључај омер SettingsDialog Preferences Поставке Fit Large Images Прилагоди велике слике Disable Искључено By width or height По ширини или висини By width По ширини By height По висини Stretch disproportionately Развуци диспропорционално Fit Small Images Прилагоди мање слике Background color: Боја позадине: Exit instead of closing, when image is loaded from command line Напусти уместо затварања када је учитана слика из командне линије Wrap image list when reaching last or first image Ово дефинитивно поправити Умотај листу слика при крају Default quality when saving images: Стандардни квалитет при снимању слика: Enable GIF animation Укључи GIF анимације Rotate image according to Exif orientation Ротирај слике према Exif оријентацији Show image file name in viewer Прикажи име слике у прегледачу Label color: Boja natpisa: Background image: Позадинска слика: Add space between thumbnails: Додај размак између минијатурних приказа: Show original size of images smaller than the thumbnail size Поправити Прикажи оригиналну величину слика које су манње од минијатурне величине Number of thumbnail pages to read ahead: Број страница минијатурних слика да се учита унапред: Rotate thumbnails according to Exif orientation Ротирај минијатурне слике по Exif оријентацији Delay between slides in seconds: Размак између слајдова у секундама: Show random images Прикажи насумичне слике Startup folder Почетна фасцикла Default, or specified by command line argument Поправити Стандардни, или командном линиjom одређени аргумент Remember last Запамти последњу Specify: Одреди: Swap mouse left-click and middle-click actions Замени акције левог и средњег клика мишем Delete confirmation Потврда за брисање Keyboard Shortcuts Кратице тастатуре OK Уреду Cancel Откажи Viewer Прегледач Thumbnails Минијатурни приказ Slide Show Слајд приказ General Опћенито Choose Startup Folder Изабери почетну фасциклу Open File Отвори фајл Images Слике ShortcutsTable Action Акција Shortcut Пречице Delete shortcut Избриши пречицу Set shortcut Постави пречицу "%1" is reserved for shortcuts to external applications. Дефинитивно поправити "%1" је обрнуто за пречице код екстерних апликација. "%1" is already assigned to "%2" action. Поправити "%1" је већ употребљено за "%2" акцију. ThumbView General Уопштено File name Име фајла Location Локација Size Величина Modified Модифициран Format формат Resolution Резолуција Megapixel Мегапиксел Error Грешка Selected %1 of%2 Изабрано %1 од %2 %n image(s) %n слика %n слике %n слика %n image(s) %n слика %n слике %n слика No images Нема слика Searching duplicate images... Тражим дупле слике... Scanned %1, displaying %2 (%3 and %4) Скениран %1, приказујем %2 (%3 и %4) %n original(s) %n оригинал %n оригинала %n оригинала %n duplicate(s) %n дупликат %n дупликата %n дупликата