summaryrefslogtreecommitdiffstats
path: root/kuickshow
diff options
context:
space:
mode:
Diffstat (limited to 'kuickshow')
-rw-r--r--kuickshow/AUTHORS1
-rw-r--r--kuickshow/BUGS3
-rw-r--r--kuickshow/COPYING339
-rw-r--r--kuickshow/ChangeLog921
-rw-r--r--kuickshow/Makefile.am8
-rw-r--r--kuickshow/README8
-rw-r--r--kuickshow/TODO24
-rw-r--r--kuickshow/configure.in.bot9
-rw-r--r--kuickshow/configure.in.in69
-rw-r--r--kuickshow/kuickshow.lsm18
-rw-r--r--kuickshow/kuickshow.spec69
-rw-r--r--kuickshow/misc/Makefile.am2
-rw-r--r--kuickshow/misc/im_palette.pal64
-rw-r--r--kuickshow/pics/Makefile.am7
-rw-r--r--kuickshow/pics/about.pngbin0 -> 257 bytes
-rw-r--r--kuickshow/pics/arrows.pngbin0 -> 264 bytes
-rw-r--r--kuickshow/pics/calibrate.pngbin0 -> 9161 bytes
-rw-r--r--kuickshow/pics/handcursor.pngbin0 -> 359 bytes
-rw-r--r--kuickshow/pics/imageviewer-medium.pngbin0 -> 1696 bytes
-rw-r--r--kuickshow/pics/imageviewer-small.pngbin0 -> 618 bytes
-rw-r--r--kuickshow/pics/ksslide.pngbin0 -> 246 bytes
-rw-r--r--kuickshow/pics/kuickshow-day.jpgbin0 -> 48857 bytes
-rw-r--r--kuickshow/pics/kuickshow-night.jpgbin0 -> 36800 bytes
-rw-r--r--kuickshow/pics/logo.pngbin0 -> 2904 bytes
-rw-r--r--kuickshow/src/Makefile.am31
-rw-r--r--kuickshow/src/aboutwidget.cpp95
-rw-r--r--kuickshow/src/aboutwidget.h43
-rw-r--r--kuickshow/src/defaultswidget.cpp282
-rw-r--r--kuickshow/src/defaultswidget.h73
-rw-r--r--kuickshow/src/filecache.cpp83
-rw-r--r--kuickshow/src/filecache.h47
-rw-r--r--kuickshow/src/filefinder.cpp99
-rw-r--r--kuickshow/src/filefinder.h54
-rw-r--r--kuickshow/src/filewidget.cpp464
-rw-r--r--kuickshow/src/filewidget.h98
-rw-r--r--kuickshow/src/generalwidget.cpp163
-rw-r--r--kuickshow/src/generalwidget.h62
-rw-r--r--kuickshow/src/hi16-app-kuickshow.pngbin0 -> 396 bytes
-rw-r--r--kuickshow/src/hi22-app-kuickshow.pngbin0 -> 1423 bytes
-rw-r--r--kuickshow/src/hi32-app-kuickshow.pngbin0 -> 954 bytes
-rw-r--r--kuickshow/src/imagewindow.cpp1251
-rw-r--r--kuickshow/src/imagewindow.h176
-rw-r--r--kuickshow/src/imdata.cpp92
-rw-r--r--kuickshow/src/imdata.h57
-rw-r--r--kuickshow/src/imlibwidget.cpp715
-rw-r--r--kuickshow/src/imlibwidget.h187
-rw-r--r--kuickshow/src/kuick.cpp4
-rw-r--r--kuickshow/src/kuick.h70
-rw-r--r--kuickshow/src/kuickconfigdlg.cpp99
-rw-r--r--kuickshow/src/kuickconfigdlg.h58
-rw-r--r--kuickshow/src/kuickdata.cpp177
-rw-r--r--kuickshow/src/kuickdata.h86
-rw-r--r--kuickshow/src/kuickfile.cpp194
-rw-r--r--kuickshow/src/kuickfile.h99
-rw-r--r--kuickshow/src/kuickglobals.h33
-rw-r--r--kuickshow/src/kuickimage.cpp527
-rw-r--r--kuickshow/src/kuickimage.h92
-rw-r--r--kuickshow/src/kuickshow.cpp1443
-rw-r--r--kuickshow/src/kuickshow.desktop93
-rw-r--r--kuickshow/src/kuickshow.h178
-rw-r--r--kuickshow/src/kurlwidget.cpp42
-rw-r--r--kuickshow/src/kurlwidget.h36
-rw-r--r--kuickshow/src/main.cpp66
-rw-r--r--kuickshow/src/mainwidget.cpp43
-rw-r--r--kuickshow/src/mainwidget.h47
-rw-r--r--kuickshow/src/printing.cpp338
-rw-r--r--kuickshow/src/printing.h85
-rw-r--r--kuickshow/src/slideshowwidget.cpp80
-rw-r--r--kuickshow/src/slideshowwidget.h44
-rw-r--r--kuickshow/src/version.h3
70 files changed, 9551 insertions, 0 deletions
diff --git a/kuickshow/AUTHORS b/kuickshow/AUTHORS
new file mode 100644
index 00000000..9e0745fb
--- /dev/null
+++ b/kuickshow/AUTHORS
@@ -0,0 +1 @@
+Carsten Pfeiffer <[email protected]>
diff --git a/kuickshow/BUGS b/kuickshow/BUGS
new file mode 100644
index 00000000..511b33ee
--- /dev/null
+++ b/kuickshow/BUGS
@@ -0,0 +1,3 @@
+kdelibs issues:
+- The filefinder doesn't work when using the splitted view
+- in the detailed view, the filefinder can't highlight files during typing.
diff --git a/kuickshow/COPYING b/kuickshow/COPYING
new file mode 100644
index 00000000..0b84a43f
--- /dev/null
+++ b/kuickshow/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/kuickshow/ChangeLog b/kuickshow/ChangeLog
new file mode 100644
index 00000000..55a198b2
--- /dev/null
+++ b/kuickshow/ChangeLog
@@ -0,0 +1,921 @@
+<pre>
+Fri Mar 31 02:04:21 2006 Carsten Pfeiffer <[email protected]>
+
+ * fixed one of the most long-standing bugs: non-local browsing
+ (i.e. you can browse remote directories like local ones now, flipping
+ through the images with PageUp/Down etc., including pre-loading
+ images)
+ Browsing through /media should work now, but can be improved by
+ not"downloading" from there. Framework to do this is there, though.
+
+ * also allow saving to remote URLs
+
+ * fixed image not being completely maximized when opening image in
+ fullscreen mode
+ * performance improvement
+
+ * layed groundwork for fixing #48812 and #101986
+
+ * make sure all temporary files get deleted
+
+Wed Feb 22 16:02:58 2006 Carsten Pfeiffer <[email protected]>
+
+ * make autohide-cursor finally work
+
+Wed Feb 22 02:14:24 2006 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp, imagewindow.*
+ remove nextSlideRequested() and prevSlideRequested() patch, you
+ can already navigate with PageUp/Down. The arrow-keys are used for
+ scrolling.
+
+Wed Feb 22 01:31:54 2006 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (KuickShow):
+ warn before loading >= 10 images at once from the commandline
+
+Wed Feb 22 01:03:07 2006 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (rotated):
+ auto-scale image on rotation
+
+Wed Feb 22 00:01:02 2006 Carsten Pfeiffer <[email protected]>
+
+ * add a warning messagebox when zooming to larger than
+ 4 * desktop area size. The "4*" is configurable in
+ [GeneralConfiguration]
+ MaximumZoomFactorByDesktop=4.0
+
+
+Sun Jan 8 09:47:39 2006 Carsten Pfeiffer <[email protected]>
+
+ * fix crash when deleting the last image without having a browser
+
+Sat Jan 7 23:27:32 2006 Carsten Pfeiffer <[email protected]>
+
+ * fix deleting images from image window and browser!
+
+ * support moving to trash and make that the default
+
+ * refactor delayed execution of events/actions (for when the browser window needs to
+ be loaded lazily)
+
+Sat Jan 7 22:36:25 2006 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (addAlternativeShortcut):
+ use F5 as default shortcut for "Reload image", keep Enter as alternative
+
+Sat Jan 7 22:33:30 2006 Carsten Pfeiffer <[email protected]>
+
+ * src/aboutwidget.cpp:
+ fixed crash (right-clicking on about widget)
+
+ * made the about widget not always-on-top, but a modal widget,
+ which prevents error messages from being hidden below the about
+ widget (i.e. when clicking the homepage link while being offline)
+
+Sat Aug 25 02:58:31 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (init):
+ mouse-wheel can switch between images now, per request of
+ Bill Benken <[email protected]>
+
+ * also fixed the KStdAccel::save() and close() accels not working
+ in the image window
+
+Sat Aug 4 03:37:50 2001 Carsten Pfeiffer <[email protected]>
+
+ * now completely smooth, flicker-free switching between images
+ and zooming
+
+ * Reverted again to current kde-common/admin stuff
+
+ * added quit-button to toolbar (also makes Ctrl-Q work)
+
+ * made ChangeLog readable by KHelpCenter
+
+ * commented out benchmark debug output
+
+ * added support for objprelink in the specfile
+ (copy the tarball to your rpm-dir/SOURCES and rpm -ba kuickshow.spec)
+
+ * Fixed some bugs coming from kdelibs 2.1.x vs. 2.2 handling
+ Thanks a lot to Robert Charbonneau <[email protected]>
+ and another anonymous helper from #kde for testing and useful
+ feedback.
+
+ * Added patch from Adrian Schroeter <[email protected]> to make it
+ work with autoconf 2.5x -- Thanks!
+
+Wed Jul 11 17:19:38 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/filewidget.cpp (initActions):
+ adopt to KDirOperator's contextmenu (i.e. don't add the "Properties..."
+ entry when it's already present)
+
+ * src/imagewindow.cpp:
+ show image size in the caption
+
+ * reverted to admin/* files from KuickShow 0.8 so that users of older
+ KDE versions can compile it again.
+
+ * cleaned up Imlib configure check
+
+ * made background color in viewer configurable
+
+ * added delete-action again for users of older kdelibs
+
+ * fixed some bugs in the filefinder widget
+
+Wed Jul 4 01:06:58 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (printImage):
+ Grmbl. Really fixed printing. It even works now :)
+
+Tue Jul 3 3:04:18 2001 Carsten Pfeiffer <[email protected]>
+
+ * Oups, the behavior of QPrinter::printCommand() has changed.
+ It returns a null String by default now :-O Fixed.
+
+Tue Jun 27 15:44:28 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp:
+ added KTempFile patch from Kevin Lo <[email protected]>
+
+Tue May 29 15:20:34 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (updateAccel):
+ changed accels:
+ shift-accel is now for removing brightness/contrast/gamma
+
+ removed delete action, now provided by kfile
+
+Thu Apr 19 23:16:12 2001 Carsten Pfeiffer <[email protected]>
+
+ * Integrated Multihead patch from Evan Edwards <[email protected]>
+ who was also so kind, to set up a homepage for KuickShow, as well
+ as a Sourceforge account. See kuickshow.sourceforge.net for details.
+
+ Thanks a lot, Evan!
+
+ Added handcursor from qwertz <[email protected]>, thanks a lot!
+
+ * src/imlibwidget.cpp (getKuimage):
+ hopefully fixed crash reported by Alexxx and linuxphreak:
+ reorder the kuickimage and file-lists when returning a cached image
+
+Tue Mar 13 03:16:24 2001 Carsten Pfeiffer <[email protected]>
+
+ * added lots of translations from the translation team.
+ I need to add a KAboutDialog somewhere to give them credit
+ for their excellent work!
+
+Fri Mar 9 21:50:12 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (eventFilter):
+ call our parent class' eventFilter if we don't stop the event
+ -> moving/rearranging the toolbar works :)
+
+ * caption fixes, show the url in the caption
+
+ * save the visible images on SM shutdown and restore them on restore
+
+ * src/imlibwidget.cpp:
+ don't delete this from closeEvent, WDestructiveClose does it better
+ -> sessionmanagement works
+
+ * defaultswidget.cpp:
+ fix typo found by qwertz
+
+ * add icon for delete, as suggested by Florian
+
+Thu Mar 8 13:29:17 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (mouseReleaseEvent):
+ zooming should work properly now:
+ - the window size is kept
+ - scrolling the zoomed image works correctly
+ - the rubber band sort of works (maybe even as good as in 0.6.7)
+ - respect maxWidth and maxHeight during zoom with the rubberband
+
+ added different icon for image window
+
+ * src/kuickshow.cpp
+ go into window mode when pressing space in fullscreen mode to show
+ the browser (always-on-top issue)
+
+ * src/filewidget.cpp
+ some more ensureItemVisible()
+
+ * installation/spec files fixes
+
+ * added im_palette.pal
+
+Wed Mar 7 21:25:15 2001 Carsten Pfeiffer <[email protected]>
+
+ * doc/en/index.html:
+ updated english documentation
+
+ * src/imagewindow.cpp
+ set our nice icon so that kicker can show it in the taskbar for
+ example. Thanks to Florian for the hint :)
+
+ * i18n fix (� -> degrees), and s/-90/270/, another one from Florian
+
+ * resizeOptimal(): if we don't resize because we already have the right
+ size, call centerImage()
+
+ * zooming with the mouse works again (still not completely right tho:
+ - the rubber band is missing
+ - the size/scrolling does not always match the real imagesize
+
+ * src/filewidget.cpp:
+ ensureItemVisible() in the browser when browsing with PageUp/PageDown
+
+ * src/kuickshow.cpp:
+ disable the slideshow action when a slideshow is running
+
+Wed Mar 7 01:39:34 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (readProperties):
+ clear the diroperators history stack on startup
+
+ * src/imagewindow.cpp:
+ update the accelerators when applying new configuration
+ (delete the old and create a new KAccel, setKeyDict() doesn't
+ work in our case
+
+ * use QWidget::x11Display() for later multihead support)
+
+ * general cleanup. hmm, this could be added to every entry
+ in the last days, I guess :}
+
+ * added workaround for relative paths not working in the filefinder
+ relative _files_ don't work yet, tho.
+
+ * documentation written for the upcoming 0.8pre release
+
+Mon Mar 5 13:07:59 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (init):
+ Maximize and close shortcuts, as proposed by Crocodile on IRC.
+
+ * WDestructiveClose in ImlibWidget and close(true) everywhere
+
+Mon Mar 5 00:12:45 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (slotReplayEvent):
+ going to the next/previous/... image now also works when started with
+ an image on the commandline (== no browser available)
+ Tricky thing: after creating the browser, we can't simply go on,
+ because the browser doesn't have any files at all (async listing).
+ So we save the pageUp/pageDown event and replay it when the browser
+ is ready.
+
+ * fixed Space needed to be hit twice to show the initial browser
+
+ * src/kuickshow.cpp, src/filewidget.cpp (eventFilter)
+ deleting files works from the filebrowser again, not only from the
+ image window
+
+ * Makefile.am
+ build as KLM (kdeinit-loadable-module) to speed up startup
+
+ * hah! Adding two lines makes browsing about twice as fast :)
+ Well, equally as fast as the KDE1 version at least ;) The new caching
+ system set the dirty flag wrongly at one place, so the pixmap was
+ effectively rendered twice per image.
+
+Sun Mar 4 20:33:44 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (initGUI):
+ open only one window item in toolbar is honored properly now
+ (replaced the checkbox in the configdialog)
+
+ * don't pass the KKeyEntryMap to all the image windows, this doesn't
+ work (and it also crashes after doing it a second time).
+ Thanks to Florian Hacker for the bugreport :)
+
+ * save the view properties of KDirOperator
+
+ * statusbar looks a bit better now (no fixed size entries anymore)
+
+ * src/kuickio.cpp (deleteFile):
+ deletion of directories works, now
+
+ * src/imdata.cpp, kuickdata.cpp:
+ better handling of default values
+
+Sun Mar 4 13:57:52 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (setFullscreen):
+ hack around QWidget::move() resizing us -> we just ignore that
+ resizeEvent. Gives less flicker when switching into window-mode.
+
+ * initial fullscreen mode works again as well (hacking around a kwin
+ "limitation")
+
+Sun Mar 4 10:50:23 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickconfigdlg.cpp (KuickConfigDialog):
+ Keyboard shortcuts configurable for browser and image viewer
+
+ * don't check mimetype in isImage() at the moment, people won't have
+ mimetypes for .eim and .psd probably
+
+ * removed unused EditDialog
+
+ * Added auto-hide cursor in viewer (doesn't work properly tho)
+
+Sat Mar 3 02:00:41 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (resizeOptimal):
+ Honor the window manager decoration in window mode. Now always the
+ entire window including decoration is visible, no matter how large the
+ image is.
+
+ * Fixed a scrolling bug when the window was exactly as large as the
+ desktop (only in fullscreen mode)
+
+ * don't go to the next image when cancelling a deletion of a file or
+ deletion fails
+
+ * some cleanup
+
+Thu Mar 1 03:49:11 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (showImage):
+ positioning is fixed now. Removed processEvents() after move(),
+ we don't seem to need this anymore. Actually, this was the cause
+ for bogus geometries.
+
+Thu Mar 1 02:15:49 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp, src/imlibwidget.cpp:
+ upScale/downScale mostly works. Some WindowManager positioning
+ problems are left.
+
+Tue Feb 27 23:30:11 2001 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (viewerDeleted):
+ Fixed crash when the only image on the commandline couldn't be loaded
+
+Sun Feb 25 23:22:30 2001 Carsten Pfeiffer <[email protected]>
+
+ * config-dialog works now, everything is saved, loaded and resetting
+ defaults works, too. All the layout management rewritten (was still
+ Qt 1.x style). Default Image modifications work, including the preview.
+ Only need a nice preview image now :)
+
+ * src/imlibwidget.*:
+ fixed setFlipMode()
+
+ * src/filewidget.cpp (eventFilter):
+ fixed filefinder completion on first character
+ filefinder enters directory/opens image upon return now
+
+ * added nice new calibrate.png from qwertz, thanks!
+
+Wed Jan 10 23:39:14 2001 Carsten Pfeiffer <[email protected]>
+
+ * lots of work... getting closer. Commandline handling is really
+ fixed now %-} Handles multiple files just fine. The filefinder
+ sort of works now (only the sort-order is not considered, this
+ could get hairy, I'm afraid). Added browsing actions to toolbar
+ and shortcuts. Works quite nicely.
+
+Fri Nov 3 14:32:53 2000 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (setFullscreen):
+ cool, no need to workaround kwin's auto-maximization needed,
+ setMinimumSize() does it! Thanks Matthias Ettrich!
+
+Fri Nov 3 13:23:41 2000 Carsten Pfeiffer <[email protected]>
+
+ * src/*:
+ some cleanups here and there
+ fixed commandline handling (dirs, files, absolute, relative)
+ made KURLWidget use KURLLabel (and fixed KURLLabel bugs)
+
+Fri Nov 3 01:49:57 2000 Carsten Pfeiffer <[email protected]>
+
+ * src/*: some more work on the KDE2 port/integration. Workarounds for
+ kwin's auto-maximization added. Fullscreen works. Moving images inside
+ the window works properly again. NETWM/KWin handling is better now.
+ Also better handling of non-loadable files.
+
+ Will make it a kdeinit-loadable module (KLM) for fast startup-times
+ later.
+
+ Finally using it again reminds me how fast it is compared to, erm, the
+ other viewers :)
+
+Thu Aug 31 01:48:55 2000 Carsten Pfeiffer <[email protected]>
+
+ * src/*: started reworking/rewriting the whole stuff to make it KDE2
+ ready. Now I have to pay for rewriting so much of kdelibs/kfile...
+ The good thing is: it's mostly about removing stuff from KuickShow
+ because the functionality is already in libkfile, now :)
+
+Tue Sep 28 10:35:39 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (resizeEvent):
+ ahh, fixed a seldom-happening segfault: when "preload images" was
+ turned on and kuickshow was started with an image as parameter (so that
+ the filebrowser was not shown in the beginning), it would segfault
+ in KuickShow::resizeEvent(). I even got a bugreport about such a
+ segfault a while ago, but I couldn't reproduce it and neither did the
+ reporter answer to my mail.
+ Anyway, this is fixed now.
+
+ * src/imagewindow.cpp (dragEnterEvent):
+ implemented preliminary drag/drop support from Konqueror
+
+Sat Sep 25 18:30:32 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp (saveImage):
+ (hopefully, untested) fixed bug, that an image was not saved with the
+ current size - the original size was used. Thanks for the report (and
+ for some other suggestions) go to Hugo Lopes <[email protected]>
+
+ * src/imlibwidget.cpp:
+ lots of other changes, fixes, there's no sense mentioning them all, as
+ a lot of stuff is being rewritten/restructured and many things have to
+ be fixed.
+
+Tue Sep 14 23:57:18 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imagewindow.cpp:
+ Ok, finally I took the time to restructure ImlibWidget.
+ Now there is a simple ImlibWidget, that can load and show images
+ and there is the powerful ImageWindow, that can do all the stuff, the
+ previous ImlibWidget did.
+ There is a nice object-oriented wrapper around ImlibImages named
+ KuickImage - I hated all those C-functions everywhere.
+
+ Additionally, the ImageWindow has fully configurable key-bindings.
+
+ And thanks to Vitor Fernandes <[email protected]>
+ I got a Brazilian/Portuguese translation for KuickShow
+
+Tue Jul 27 20:32:09 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (setBusyCursor):
+ loading an image from disk could take quite some time (e.g. on NFS),
+ so show a busy cursor during that operation, too.
+
+Thu Jul 22 21:26:11 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (preloadImage):
+ Argh, fixed segfault - don't free the cached image, when it is the
+ current shown image as well (imCache == im). Occured when switching
+ back and forth between two images
+
+Fri Jul 16 13:09:07 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kfileview.cpp (refresh):
+ Oh well, thanks to Robert Hamberger <[email protected]>, I
+ fixed another (hopefully last, for the next time) segfault. SIGSEGV
+ happened, when opening the about-dialog, NOT giving the focus back
+ to the filebrowser and then pressing the "show-hidden-files-button"
+ twice.
+
+ * src/kuickconfigdlg.cpp (keyPressEvent):
+ fixed bug: pressing escape in config dialog didn't reenable the
+ toolbar button to open the dialog
+
+ * src/imlibwidget.cpp (autoRender):
+ LOTS of updates, the new configuration dialog sort of works now
+ - all image manipulations can be daisychained now, just call
+ setAutoRender( false ) and call updateImage() to apply (render)
+ configuration dialog makes use of this to show the settings in an
+ example image
+ - new and nice about dialog, also based on ImlibWidget :o)
+
+
+Wed Jul 7 01:09:14 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (loadImageInternal):
+ Applied patch from Thorsten Scheuermann <[email protected]>
+ (autoscale images to screensize) - thanks!
+
+Mon Jul 5 15:27:05 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickconfigdlg.cpp (closeEvent):
+ Eieiei, introduced closeEvent() in configdialog, which just emits
+ cancelButtonPressed() - otherwise the Toolbarbutton wouldn't get
+ reenabled. Thanks to Thorsten Scheuermann for the bugreport!
+
+ * src/kuickshow.cpp (deleteFile):
+ Uh oh, I really thought there were no segfaults in 0.6.6...
+ Thanks go to Vadim Zaliva, who proved me wrong :-} Just fixed that
+ core-dump, when trying to delete a directory.
+
+Fri Jul 2 14:27:08 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (initGUI):
+ moved some code around to delay creating the filebrowser and reading
+ the directory contents. If you give a filename on the commandline as
+ parameter, kuickshow will load the filebrowser first, when you really
+ want to.
+
+ * src/imlibwidget.cpp (desktopWidth):
+ kuickhow now honors the panel and window-frame-size when displaying
+ images in window-mode - the imagesize is properly adjusted in
+ auto-shrink mode
+
+ * src/imlibwidget.cpp (showImageOriginalSize):
+ fixed bug in window-mode: displaying image with "o" (original size)
+ didn't resize the window, if necessary
+
+ * src/kuickshow.cpp (eventFilter):
+ Bugfix: when did I have that crazy idea to set the palette to black
+ in the filebrowser??? In certain cases, I got an almost completely
+ black Messagebox...
+
+ * src/kfileview.cpp (removeItem):
+ oups... segfault fixed: removing the very first item in the
+ filebrowser caused crash
+
+Sat Jun 26 22:47:05 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/fileview.cpp (changeDirDialog):
+ goto-dialog (ctrl-g) accepts ~ and replaces it with your homedirectory
+ I love ideas, that can be implemented in half a minute :o)
+
+Mon May 31 12:08:41 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (setFullscreen):
+ Save and restore the geometry when switching between fullscreen and
+ window mode. Much nicer now :o)
+
+ * src/kuickshow.cpp (showImage):
+ Honor kpanel's placement, when showing the first image. Don't just move
+ it to (0,0), but use KWM::geometry().
+
+ * src/imlibwidget.cpp (showImageOriginalSize):
+ implemented Shortcut "o" to show image in the original size. Useful when
+ autoscaling is active and you want the original size (e.g. scaled text
+ is hardly readable).
+
+Mon May 31 02:24:56 1999 Carsten Pfeiffer <[email protected]>
+
+ * updated polish translation, many thanks to Krzysztof P. Jasiutowicz
+
+ * added german documentation, many thanks to Robert Hamberger,
+ who also enlargened the TODO-list :-P
+
+Fri May 28 11:48:46 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (mouseMoveEvent, mouseReleaseEvent):
+ several cleanups (replaced bool shiftPressed with the appropriate
+ QEvent::state() & ShiftButton in the eventhandlers)
+
+ * fixed bug: Shift + MousePress + MouseRelease without moving the mouse
+ moved the image to the lower right corner
+
+ * implemented "close image on doubleclick", as suggested by Ralph
+ Bernecker. Also put Close into popupmenu.
+
+ * improved cache of preloaded image, now stores the actual rendered
+ Pixmap -> a preloaded image shows almost before you press "next image"
+ ;-) It can't get faster now. I only could cache more than one pixmap...
+ hmm, maybe later
+
+ * updated documentation
+
+Tue May 18 21:19:32 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kfileview.cpp (refresh):
+ sorting does somehow work. Some code seems to be duplicated in
+ KFileInfoContents and KDir - both offer sorting. However, both
+ don't work 100% :-/ Anyway, if you have KDE 1.1.1, sorting should
+ work, it is disabled for earlier releases, as there was a segfault
+ problem in kfile (nobody ever seemed to use KFileInfoContent's sorting,
+ so that was never realized).
+
+ * src/kfileview.cpp, src/fileview.cpp:
+ some minor fixlets: always try to highlight the last active file,
+ whenever the directory contents are updated
+
+ * src/kuickconfigdlg.cpp (several):
+ changed the two KIntLineEdits to more appropriate QSpinBoxes
+
+ * src/imlibwidget.cpp (setFullscreen, several),
+ * src/kuickshow.cpp (several)
+ FINALLY got the fullscreen/kpanel thing together
+ KDE 1.1 introduced KWM::staysOnTop, but unfortunately "on top" meant
+ "below kpanel". Since KDE 1.1.1, on top means on top :o) Even more
+ unfortunately, this revealed several problems with focus handling and
+ other widgets on top of the "top"-widget. So I used a timer, check
+ the focusevents and tell kwm when to make us the top widget, and when
+ not.
+
+ * src/imlibwidget.cpp, src/kuickshow.cpp
+ improved handling of multiple windows - always the window which last
+ had the focus will load new images
+
+ * src/kuickdata.cpp, src/kuickconfigdlg.cpp, src/kuickshow.cpp
+ configurable: open all images in one window, or open a new window
+
+Sat Apr 17 18:43:03 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (setToolbarPosition):
+ added methods to (re)store the toolbar position
+
+ * src/imlibwidget.cpp:
+ changed fullscreen code to use the current (and hopefully final) way
+ KWM does "stayOnTop"
+
+ * src/kuickdata.cpp:
+ updated file filters (Photoshop psd and bmp)
+
+ * src/kfileview.cpp:
+ changed the kdir behavior, so that the browser displays files
+ altogether at once, not incrementally. This also let me (finally,
+ yippeee :-P) highlight the last direcory, where you came from.
+ And reading directories is a bit faster now, too.
+
+Sun Feb 21 16:02:44 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (zoomImage):
+ added minimum and maximum sizes for zooming images (thanks to
+ Robert Hamberger for the idea (and for some funny emails :-P))
+
+ * src/kwm-workaround.h (keepOnTop):
+ added Matthias' workaround for "always on top"-problem in fullscreen
+ mode, which was introduced with KWM-changes just before KDE 1.1
+ ... too bad it doesn't work :-/ Gotta spend some time finding out, why
+
+ * src/kuickshow.cpp (showImage):
+ always move the first opened image-window to 0x0 (top left)
+ (thanks to Andreas Gelezun for the idea)
+
+Thu Feb 4 11:40:50 1999 Carsten Pfeiffer <[email protected]>
+
+ * doc/en/index.html:
+ updated documentation
+
+Wed Feb 3 22:43:32 1999 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (KuickShow):
+ implemented deletion of files (delete/shift-delete/popupmenu)
+
+ fixed quite a few buglets with keyboard navigation (pageUp didn't
+ halt when a directory was found). pageUp/down and the like shall only
+ select files.
+
+ worked around kwm-bug (resize doesn't work properly after
+ KWM::setDecoration( noDecoration )
+
+Tue Dec 29 16:55:11 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp, imlibwidget.cpp, kfileview.*:
+ fixed updating of directory in statusbar and filename in caption of
+ imlibwidget
+
+ fileview is prepared to support sorting and filtering
+
+ added toggle showing hidden files (accessible via toolbar)
+
+ added Home-Button in toolbar to change to home directory
+
+Wed Nov 18 15:40:46 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (mouseMoveEvent):
+
+ fixed cursor not being reset to arrorCursor, when shift-key was
+ released during resize ( == abort resizing )
+
+Wed Nov 18 15:09:36 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (saveSettings):
+
+ size of the browserwindow is now saved and restored on next start
+
+Mon Nov 9 23:16:32 1998 Carsten Pfeiffer <[email protected]>
+
+ * hopefully fixed autoconf stuff, which was broken at least on SunOS
+ Now tries to detect imlib-config and links against
+ `imlib-config --libs`. If this doesn't work, it links against
+ every graphics lib of libgif, libjpeg, libtiff and libpng, that
+ is available.
+ Another little bug is fixed, any changes (contrast/brightness/gamma)
+ were not saved when using "save as"
+
+Sat Nov 7 15:22:18 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp
+ added changing of brightness, contrast and gamma via keyboard and popup menu
+ added saving image
+ the factor, how much brightness/contrast/gamma you change with one click is
+ only editable in configfile, no dialog, yet.
+
+Sat Nov 7 12:57:48 1998 Carsten Pfeiffer <[email protected]>
+
+ * acinclude.m4 (ac_imlib_config):
+ added some configure-stuff to use `imlib-config' to determine the libs
+ to be linked against.
+
+Sun Oct 11 23:58:46 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (loadImageInternal):
+ added configuration option to not override the color palette
+ useful for 8bit displays
+
+ * src/kuickshow.cpp:
+ fixed segfault when imlib can't load image
+ (don't preload the next image, then)
+
+Wed Sep 30 19:39:15 1998 Carsten Pfeiffer <[email protected]>
+
+ * acinclude.m4, configure.in:
+ Added a configure-check for Imlib. Still incomplete (does NOT
+ check for all those other libs as libgif, libjpeg, libz, ...),
+ but at least finds libImlibs which are too old.
+
+ src/kuickshow.cpp (about):
+ about dialog is centered, now
+
+Fri Sep 25 19:32:13 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (keyPressEvent):
+ Now behavior of scrolling/zooming with mouse is fixed:
+ pressing left mousebutton and moving the mouse will move the image
+ (only if it image is larger than current window)
+
+ Pressing Shift, left mousebutton and moving the mouse will zoom into
+ the image. Releasing Shift-button before mousebutton will abort zooming
+
+Thu Sep 24 02:41:26 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (mouseReleaseEvent):
+ Ahh, finally I got "zoom inside image with mouse" working perfectly.
+ A rectangle is painted and this rectangle is zoomed and centered.
+ Not the very best solution, tho, as imlib is zooming the entire
+ image, not only the selected part... guess how long it can take for
+ bigger images.
+ Gotta find another solution later, creating a new imlib image with
+ just the selected part.
+
+Tue Sep 22 21:05:58 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (preloadImage):
+ Added preloading facility. Fills the cache with the next image, so it
+ will pop up almost instantaneously, when pressing PageUp/Down.
+ Configurable via dialog.
+
+Mon Sep 21 16:29:56 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (eventFilter):
+ Added "Enter-key", that reloads current image (so all zoom/move stuff
+ is restored to original settings).
+
+Sun Sep 20 19:04:23 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kfileview.cpp (prev):
+ whoops, fixed a segfault, when trying to get a kfileinfo of index -1.
+ I shouldn't check, whether an unsigned int is smaller than 0, which it
+ actually was. Now uses int.
+
+Sun Sep 20 13:35:00 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (closeEvent):
+ reverted to override closeEvent() and changed every occurrence of
+ close( true ) to close( false ), as closeEvent now explicitely
+ deletes itself.
+ This was due to windowmanagers close-button, which should delete widget
+
+Sun Sep 20 03:08:45 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickshow.cpp (printImage):
+ added preliminary support for printing
+
+Sat Sep 19 01:40:22 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (rotate):
+ added rotate-routine to - doh - rotate an image
+
+Fri Sep 18 01:08:46 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (scrollImage):
+ Now changes cursor when attempting to move the image with the mouse
+ Also, image can be moved now, when in window mode and window is
+ larger than desktop
+
+Thu Sep 17 17:25:11 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (setPopupMenu):
+ the fix for the popupmenu also let me finally delete it without
+ segfault :o)
+
+Thu Sep 17 13:13:09 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/kuickconfigdlg.cpp (KuickConfigDialog):
+ enlargened maxCache lineedit and changed tooltip
+
+ * src/imlibconfig.cpp
+ changed default value for maxCache from 0 to 10000 (10megs)
+
+ * src/imlibwidget.cpp (scrollImage):
+ restricted scrolling so that you can move the image only
+ if it doesn't fit onto the screen.
+ You can't move the image out of the screen anymore.
+
+ Also fixed a segfault (ugh) in viewerMenu->popup(), as it was
+ initialized in the wrong place (now in initImlib()).
+
+
+Thu Sep 17 00:11:53 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (loadImage):
+ re-enabled Imlib_destroy_image()
+ Found another value in imlib configuration struct, pixmapcachesize
+ which I wasn't aware of. Now limiting imlib's cache really works :o))
+ I'm really happy now :-) Running out of Ram and even Swap is not too
+ funny ;o)
+
+Tue Sep 15 20:28:49 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (centerImage):
+ fixed images not centering when larger than screen and in fullscreen
+ mode.
+
+
+Tue Sep 15 14:06:27 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (mouseMoveEvent):
+ scrolling the image with the mouse is now possible. Didn't expect
+ scrolling would be so smooth :o)
+ Also added a popupmenu (ImlibWidget::setPopupmenu( bool )) for
+ the basic features like zoom and flip image
+
+Mon Sep 14 16:20:30 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/fileview.cpp/.h
+ * src/kfileview.cpp/.h
+ * src/kuickshow.cpp
+ added "change directory" possibility. A dialog asks for a directory
+ and the fileview is being updated. Either accessible via the
+ popupmenu, or via Ctrl-g (goto)
+
+ * src/kuickshow.cpp (KuickShow):
+ once again optimized commandline parsing
+
+Mon Sep 14 13:24:40 1998 Carsten Pfeiffer <[email protected]>
+
+ * funny, I added lots of stuff, moved some other stuff around and
+ the result is a binary about 30k smaller than before :-D
+
+ * src/fileview.cpp (findCompletion):
+ *strike* now even filecompletion works :-) If you hit some keys
+ on your keyboard, while in the filebrowser, a small edit window pops
+ up in the bottom-right corner. Just type in the first chars of the
+ filename of the image you want to see, and it will be highlighted.
+
+ * src/kuickshow.cpp, src/imlibwidget.h/.cpp:
+ Cool. Now, I have only one ImlibData object, so I share imlib's
+ cache between all open windows. This does not only speed things
+ up quite a bit, but also reduced memory usage with multiple open
+ windows.
+ ImlibWidget therefore has a new constructor, where you can pass the
+ pointer to the ImlibData object.
+
+ * src/imlibwidget.cpp (ImlibWidget):
+ now creates an ImlibConfig object itself, when none has been given
+ in the contructor
+
+Sun Sep 13 23:28:31 1998 Carsten Pfeiffer <[email protected]>
+
+ * src/imlibwidget.cpp (renderImage):
+ Don't destroy images ( Imlib_destroy_image() ) anymore. This boosts
+ browsing a LOT. Showing cached images is almosts instantaneous now!
+ Hope there's no sideeffect on this :-}
+
+ * src/kuickshow.cpp (eventFilter):
+ space toggles show()ing and hide()ing the browser now.
+ If started with image as parameter, kuickshow doesn't show
+ the browser, hit space to show it.
+
+ * src/fileview.h (class FileView):
+ findCompletion() is now public, so that I can tell the browser
+ to highlight the file, supplied via commandline.
+
+
+History:
+--------
+- found that xemacs can create much better changelogs :o)
+- hacked a lot of goodies into KuickShow, several configuration options
+- decided to have a look at the Xlib stuff and found out, how to map
+ an Imlib image onto any QWidget - this is cool :o)
+- too bad, it was not very reliable and it was a mess, too
+- with my Xlib non-knowledge, found a way to "swallow" an Imlib image
+ onto a QWidget - imagine how happy I was :o)
+- if Kopacz got Imlib to work, I could do that, too :-P
+- end of August 98, saw Adam Kopacz' release of qiv (quick image viewer)
+ damn, this was my name (kiv, kuick image viewer) :o(
+- first tries to use Imlib to display on Qt/KDE widgets in April 98,
+ too bad, it didn't work :o(
+- first hack of kview to use a filebrowser in January
+- had the idea for such an app about December 97
+</pre>
diff --git a/kuickshow/Makefile.am b/kuickshow/Makefile.am
new file mode 100644
index 00000000..e53fd831
--- /dev/null
+++ b/kuickshow/Makefile.am
@@ -0,0 +1,8 @@
+SUBDIRS = src misc pics
+
+kuickshow-package:
+ @export CVSROOT=`cat CVS/Root`; \
+ kuickdir=$$PWD; \
+ kuickver=`cat src/version.h | grep define | cut -f3 -d' ' | sed -e 's/"//g'`; \
+ cd /tmp; \
+ cvs2dist `dirname $$kuickdir` kuickshow --remove-hidden --version $$kuickver $$kuickdir/TODO $$kuickdir/BUGS $$kuickdir/kuickshow.lsm $$kuickdir/kuickshow.spec $$kuickshow/../Makefile.cvs
diff --git a/kuickshow/README b/kuickshow/README
new file mode 100644
index 00000000..e6167514
--- /dev/null
+++ b/kuickshow/README
@@ -0,0 +1,8 @@
+KuickShow v0.8
+Carsten Pfeiffer <[email protected]>
+----------------------------------------------------------------------
+KuickShow is a very fast and comfortable imageviewer, somewhat inspired
+by ACDSee (early versions :)
+
+See http://devel-home.kde.org/~pfeiffer/kuickshow/ for updated versions,
+see ChangeLog for what has changed.
diff --git a/kuickshow/TODO b/kuickshow/TODO
new file mode 100644
index 00000000..0f75ec1c
--- /dev/null
+++ b/kuickshow/TODO
@@ -0,0 +1,24 @@
+toolbar in imageviewer
+
+- Ctrl-S = Save current, Shift-Ctrl-S = Filedialog
+
+- allow to split browser into subwindows (multiple browsers)
+- mouse-usage better (e.g. left button = next image, middle button = previous
+ image, all configurable)
+- anim-gif support (QMovie perhaps)
+- cropping images (via Imlib_clone_scaled_image & Imlib_crop_and_clone_image())
+- thumbnail view, treeview
+- menubar (same as popupmenu) (abschaltbar) (mac-mode!)
+
+- configure-dialog: offer a directory to copy files to -> one click copies to it
+- rename/delete into popupmenu of imagewindow
+
+- if image not readable -> no nagscreen, jump to next image
+- network transparency with kio
+
+- small preview in browser window
+- bookmarks?
+- generate wallpaper (background desktop image)
+- display more image information (resolution, color depth, image comments...)
+- better slideshow (randomize, pause/continue, reverse, ...)
+- what else?
diff --git a/kuickshow/configure.in.bot b/kuickshow/configure.in.bot
new file mode 100644
index 00000000..ef8aaf93
--- /dev/null
+++ b/kuickshow/configure.in.bot
@@ -0,0 +1,9 @@
+if test -z "$LIB_IMLIB"; then
+ echo ""
+ echo "You're missing Imlib 1.x. The graphics browser/viewer KuickShow"
+ echo "won't be compiled without Imlib."
+ echo "You can download it from"
+ echo "http://freshmeat.net/redir/imlib/4385/url_tgz/imlib-1.9.10.tar.gz"
+ echo ""
+ all_tests=bad
+fi
diff --git a/kuickshow/configure.in.in b/kuickshow/configure.in.in
new file mode 100644
index 00000000..fb1f0432
--- /dev/null
+++ b/kuickshow/configure.in.in
@@ -0,0 +1,69 @@
+#MIN_CONFIG
+
+#AM_INIT_AUTOMAKE(kuickshow,0.8.2)
+
+# my own additions to KDE's version
+#
+# checking for Imlib...
+
+AC_DEFUN([KDE_FIND_IMLIB_CONFIG],
+ [AC_MSG_CHECKING([for imlib-config])
+
+imlib_config_given=NO
+ac_imlib_config=""
+
+AC_ARG_WITH(imlib-config,
+AC_HELP_STRING([--with-imlib-config=DIR],[directory where "imlib-config" is located]),
+[ ac_imlib_config="$withval/imlib-config"
+ imlib_config_given=yes
+])
+
+if test "$imlib_config_given" = "yes"; then
+ if test ! -r $ac_imlib_config; then
+ AC_MSG_RESULT(wrong file specified)
+ ac_imlib_config=""
+ else
+ AC_MSG_RESULT($ac_imlib_config)
+ LIB_IMLIB=`$ac_imlib_config --libs`
+ AC_SUBST(LIB_IMLIB)
+ fi
+else
+ ac_imlib_config=`which imlib-config 2>/dev/null`
+ if test -z "$ac_imlib_config"; then
+ AC_MSG_RESULT(no)
+ else
+ dummy=`echo "$ac_imlib_config" | grep '/imlib-config'`
+ if test -z "$dummy"; then
+ AC_MSG_RESULT(no)
+ ac_imlib_config=""
+ else
+ LIB_IMLIB=`$ac_imlib_config --libs`
+ IMLIB_CFLAGS=`$ac_imlib_config --cflags`
+ imlib_config=`echo "$LIB_IMLIB" | grep lImlib`
+ if test -z "$imlib_config"; then
+ AC_MSG_RESULT(no)
+ ac_imlib_config=""
+ else
+ AC_SUBST(LIB_IMLIB)
+ AC_SUBST(IMLIB_CFLAGS)
+ AC_MSG_RESULT($ac_imlib_config)
+ fi
+ fi
+ fi
+fi
+
+])
+
+dnl #### now some kuickshow stuff ###
+dnl Check if Imlib is installed properly
+KDE_PKG_CHECK_MODULES(IMLIB, imlib >= 1.9.10,
+ LIB_IMLIB=$IMLIB_LIBS
+ AC_SUBST(LIB_IMLIB)
+,
+KDE_FIND_IMLIB_CONFIG
+)
+
+if test -z "$LIB_IMLIB"; then
+dnl AC_MSG_ERROR([You need to install Imlib 1.x, e.g. http://freshmeat.net/redir/imlib/4385/url_tgz/imlib-1.9.10.tar.gz if your distributor doesn't have a package])
+ DO_NOT_COMPILE="$DO_NOT_COMPILE kuickshow"
+fi
diff --git a/kuickshow/kuickshow.lsm b/kuickshow/kuickshow.lsm
new file mode 100644
index 00000000..4872440c
--- /dev/null
+++ b/kuickshow/kuickshow.lsm
@@ -0,0 +1,18 @@
+Begin3
+Title: KuickShow
+Version: 0.8.5
+Entered-date: August 2001
+Description: KuickShow is a very fast image viewer, that lets you easily
+ browse large galleries. A builtin filebrowser and manager
+ is also available. Usage is somewhat inspired by ACDSee.
+Keywords: KDE Qt Graphics Images Imageviewer Imlib
+Author: Carsten Pfeiffer <[email protected]>
+Maintained-by: Carsten Pfeiffer <[email protected]>
+Home-page: http://devel-home.kde.org/~pfeiffer/kuickshow/
+Alternate-site: ftp://ftp.kde.org/pub/kde/stable/apps/graphics/
+Primary-site: http://devel-home.kde.org/~pfeiffer/kuickshow/
+ xxxxxx kuickshow-0.8.5.tar.gz
+ xxx kuickshow-0.8.5.lsm
+Platform: Unix. Needs Qt >= 3.0.4, KDE (kdelibs) >= 3.0 and Imlib 1.x
+Copying-policy: GPL
+End
diff --git a/kuickshow/kuickshow.spec b/kuickshow/kuickshow.spec
new file mode 100644
index 00000000..0fcba9ea
--- /dev/null
+++ b/kuickshow/kuickshow.spec
@@ -0,0 +1,69 @@
+%define version 0.8.5
+%define release 1
+%define serial 1
+%define prefix /opt/kde3
+
+Name: kuickshow
+Summary: KuickShow -- A very fast image viewer/browser
+Version: %{version}
+Release: %{release}
+Serial: %{serial}
+Source: http://devel-home.kde.org/~pfeiffer/kuickshow/kuickshow-%{version}.tar.gz
+URL: http://devel-home.kde.org/~pfeiffer/kuickshow/
+Copyright: GPL
+Packager: Carsten Pfeiffer <[email protected]>
+Group: X11/KDE/Graphics
+BuildRoot: /tmp/kuickshow-%{version}-root
+Prefix: %{prefix}
+
+%description
+KuickShow is a very fast image viewer, that lets you easily
+browse large galleries. A builtin filebrowser and manager
+is also available. Usage is somewhat inspired by ACDSee.
+It supports many fileformats, e.g. jpeg, gif, png, psd, bmp,
+tiff, xpm, xbm, xcf, eim, ...
+
+KuickShow has a nice user interface, that allows you to browse large amounts
+of images in a short time. It can zoom, mirror, rotate images, adjust
+brightness, contrast and gamma and can do a slideshow, of course.
+It is fully configurable through dialogs.
+
+Besides that, it offers a nice filebrowser with basic filemanager capabilities
+like renaming, deleting, creating directories, ...
+
+Install with '--prefix $KDEDIR' unless you have the kde-config program.
+
+%prep
+rm -rf $RPM_BUILD_ROOT
+
+%setup -n kuickshow-%{version}
+
+%build
+PREFIX=""
+which kde-config || PREFIX=%{prefix}
+if test -z "$PREFIX"; then
+ PREFIX=`kde-config --prefix`
+fi
+
+export KDEDIR="$PREFIX"
+CXXFLAGS="$RPM_OPT_FLAGS -fno-exceptions -pipe" LDFLAGS=-s ./configure --prefix="$PREFIX" --enable-final --disable-debug
+mkdir -p $RPM_BUILD_ROOT
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+
+cd $RPM_BUILD_ROOT
+
+find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > $RPM_BUILD_DIR/file.list.%{name}
+
+find . -type f | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name}
+
+find . -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> $RPM_BUILD_DIR/file.list.%{name}
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+rm -f $RPM_BUILD_DIR/file.list.%{name}
+
+%files -f ../file.list.%{name}
+
diff --git a/kuickshow/misc/Makefile.am b/kuickshow/misc/Makefile.am
new file mode 100644
index 00000000..caea8ab1
--- /dev/null
+++ b/kuickshow/misc/Makefile.am
@@ -0,0 +1,2 @@
+pal_DATA = im_palette.pal
+paldir = $(kde_datadir)/kuickshow
diff --git a/kuickshow/misc/im_palette.pal b/kuickshow/misc/im_palette.pal
new file mode 100644
index 00000000..9a243f73
--- /dev/null
+++ b/kuickshow/misc/im_palette.pal
@@ -0,0 +1,64 @@
+0x0 0x0 0x0
+0xff 0xff 0xff
+0xff 0x0 0x0
+0xff 0xff 0x0
+0x0 0xff 0x0
+0x0 0x0 0xff
+0x0 0xff 0xff
+0x99 0x99 0x99
+0xff 0x88 0x0
+0x88 0x0 0x0
+0x0 0x88 0x88
+0x88 0x88 0x0
+0xff 0xcc 0x97
+0xbb 0xbb 0xbb
+0x9f 0x6b 0x42
+0x55 0x55 0x55
+0xdd 0xdd 0xdd
+0x77 0x77 0x77
+0x33 0x33 0x33
+0xcc 0x0 0x0
+0xff 0x44 0x0
+0xff 0xcc 0x0
+0xcc 0xcc 0x0
+0x60 0x60 0x0
+0x0 0x43 0x0
+0x0 0x7f 0x0
+0x0 0xcc 0x0
+0x0 0x44 0x44
+0x0 0x0 0x44
+0x0 0x0 0x88
+0xef 0xb1 0x7b
+0xdf 0x98 0x5f
+0xbf 0x87 0x56
+0x7f 0x57 0x26
+0x5f 0x39 0xc
+0x3f 0x1c 0x0
+0x21 0x0 0x0
+0x0 0x43 0x87
+0x2d 0x70 0xaf
+0x5a 0x9e 0xd7
+0x87 0xcc 0xff
+0xff 0xe0 0xba
+0x21 0x43 0xf
+0x3d 0x5d 0x25
+0x59 0x78 0x3a
+0x75 0x93 0x4f
+0x91 0xae 0x64
+0xad 0xc8 0x7a
+0xf0 0xa8 0xef
+0xd0 0x88 0xd0
+0xaf 0x66 0xaf
+0x8e 0x44 0x8e
+0x6d 0x22 0x6d
+0x4b 0x0 0x4b
+0xff 0xc0 0xbc
+0xff 0x93 0x91
+0xff 0x66 0x67
+0xd8 0xf2 0xbf
+0xff 0xc9 0x68
+0xff 0x96 0x67
+0xa5 0x60 0xff
+0x51 0xff 0x99
+0x3f 0xa5 0x63
+0x98 0x90 0x67
diff --git a/kuickshow/pics/Makefile.am b/kuickshow/pics/Makefile.am
new file mode 100644
index 00000000..198327f8
--- /dev/null
+++ b/kuickshow/pics/Makefile.am
@@ -0,0 +1,7 @@
+# Add all of your pixmaps here
+pics_DATA = calibrate.png kuickshow-day.jpg kuickshow-night.jpg logo.png \
+ imageviewer-medium.png imageviewer-small.png handcursor.png \
+ ksslide.png about.png
+
+# This is where it will all be installed
+picsdir = $(kde_datadir)/kuickshow/pics
diff --git a/kuickshow/pics/about.png b/kuickshow/pics/about.png
new file mode 100644
index 00000000..a5468c1d
--- /dev/null
+++ b/kuickshow/pics/about.png
Binary files differ
diff --git a/kuickshow/pics/arrows.png b/kuickshow/pics/arrows.png
new file mode 100644
index 00000000..f1d4d51c
--- /dev/null
+++ b/kuickshow/pics/arrows.png
Binary files differ
diff --git a/kuickshow/pics/calibrate.png b/kuickshow/pics/calibrate.png
new file mode 100644
index 00000000..ca5296df
--- /dev/null
+++ b/kuickshow/pics/calibrate.png
Binary files differ
diff --git a/kuickshow/pics/handcursor.png b/kuickshow/pics/handcursor.png
new file mode 100644
index 00000000..61af7bd7
--- /dev/null
+++ b/kuickshow/pics/handcursor.png
Binary files differ
diff --git a/kuickshow/pics/imageviewer-medium.png b/kuickshow/pics/imageviewer-medium.png
new file mode 100644
index 00000000..8b2ce5cb
--- /dev/null
+++ b/kuickshow/pics/imageviewer-medium.png
Binary files differ
diff --git a/kuickshow/pics/imageviewer-small.png b/kuickshow/pics/imageviewer-small.png
new file mode 100644
index 00000000..cb9dddce
--- /dev/null
+++ b/kuickshow/pics/imageviewer-small.png
Binary files differ
diff --git a/kuickshow/pics/ksslide.png b/kuickshow/pics/ksslide.png
new file mode 100644
index 00000000..b7109e14
--- /dev/null
+++ b/kuickshow/pics/ksslide.png
Binary files differ
diff --git a/kuickshow/pics/kuickshow-day.jpg b/kuickshow/pics/kuickshow-day.jpg
new file mode 100644
index 00000000..b257e429
--- /dev/null
+++ b/kuickshow/pics/kuickshow-day.jpg
Binary files differ
diff --git a/kuickshow/pics/kuickshow-night.jpg b/kuickshow/pics/kuickshow-night.jpg
new file mode 100644
index 00000000..f755c2e4
--- /dev/null
+++ b/kuickshow/pics/kuickshow-night.jpg
Binary files differ
diff --git a/kuickshow/pics/logo.png b/kuickshow/pics/logo.png
new file mode 100644
index 00000000..7e2305a4
--- /dev/null
+++ b/kuickshow/pics/logo.png
Binary files differ
diff --git a/kuickshow/src/Makefile.am b/kuickshow/src/Makefile.am
new file mode 100644
index 00000000..57c92388
--- /dev/null
+++ b/kuickshow/src/Makefile.am
@@ -0,0 +1,31 @@
+## Makefile.am for kuickshow
+
+bin_PROGRAMS =
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = kuickshow.la
+
+# set the include path for X, qt and KDE
+INCLUDES = $(all_includes)
+KDE_CXXFLAGS = $(IMLIB_CFLAGS)
+METASOURCES = AUTO
+
+kuickshow_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kuickshow_la_LIBADD = $(LIB_KDEPRINT) $(LIB_IMLIB)
+kuickshow_la_SOURCES = kuickshow.cpp \
+ aboutwidget.cpp generalwidget.cpp kuickconfigdlg.cpp main.cpp \
+ defaultswidget.cpp imagewindow.cpp kuickdata.cpp \
+ imdata.cpp filefinder.cpp kurlwidget.cpp filewidget.cpp \
+ kuick.cpp imlibwidget.cpp slideshowwidget.cpp printing.cpp \
+ kuickfile.cpp kuickimage.cpp filecache.cpp
+
+# if you "make distclean", this files get removed. If you want to remove
+# them while "make clean", use CLEANFILES
+DISTCLEANFILES = $(METASOURCES)
+
+messages:
+ $(XGETTEXT) *.cpp *.h -o $(podir)/kuickshow.pot
+
+KDE_ICON = kuickshow
+
+ # this is where the kdelnk file will go
+xdg_apps_DATA = kuickshow.desktop
diff --git a/kuickshow/src/aboutwidget.cpp b/kuickshow/src/aboutwidget.cpp
new file mode 100644
index 00000000..2ae41102
--- /dev/null
+++ b/kuickshow/src/aboutwidget.cpp
@@ -0,0 +1,95 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qdatetime.h>
+#include <qevent.h>
+#include <qglobal.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+
+#include <kwin.h>
+#include <kstandarddirs.h>
+
+#include "imlibwidget.h"
+#include "kurlwidget.h"
+#include "version.h"
+
+#include "aboutwidget.h"
+
+AboutWidget::AboutWidget( QWidget *parent, const char *name )
+ : QVBox( parent, name, Qt::WShowModal )
+{
+ KWin::setType( winId(), NET::Override );
+ KWin::setState( winId(), NET::SkipTaskbar );
+
+ setFrameStyle( WinPanel | Raised );
+
+ QGroupBox *gBox = new QGroupBox( 1, Horizontal, this);
+ gBox->setGeometry( 10, 10, width()-20, height()-20 );
+ gBox->setAlignment( AlignHCenter );
+ gBox->installEventFilter( this );
+
+ gBox->setPalette( QPalette( QColor( white ) ) );
+ gBox->setBackgroundMode( PaletteBackground );
+
+ int hour = QTime::currentTime().hour();
+ QString file;
+
+ if ( hour >= 10 && hour < 16 )
+ file = locate("appdata", "pics/kuickshow-day.jpg");
+ else
+ file = locate("appdata", "pics/kuickshow-night.jpg");
+
+ QLabel *authors = new QLabel("Kuickshow " KUICKSHOWVERSION
+ " was brought to you by", gBox);
+ authors->setAlignment( AlignCenter );
+
+ m_homepage = new KURLWidget("Carsten Pfeiffer", gBox);
+ m_homepage->setURL( "http://devel-home.kde.org/~pfeiffer/kuickshow/" );
+ m_homepage->setAlignment( AlignCenter );
+
+ QLabel *copy = new QLabel("(C) 1998-2006", gBox);
+ copy->setAlignment( AlignCenter );
+
+ ImlibWidget *im = new ImlibWidget( 0L, gBox, "KuickShow Logo" );
+ if ( im->loadImage( file ) )
+ im->setFixedSize( im->width(), im->height() );
+ else {
+ delete im;
+ im = 0L;
+ qWarning( "KuickShow: about-image not found/unreadable." );
+ }
+}
+
+AboutWidget::~AboutWidget()
+{
+}
+
+bool AboutWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::MouseButtonPress ) {
+ QMouseEvent *ev = static_cast<QMouseEvent*>( e );
+ if ( !m_homepage->geometry().contains( ev->pos() ) ) {
+ deleteLater();
+ return true;
+ }
+ }
+
+ return QVBox::eventFilter( o, e );
+}
+#include "aboutwidget.moc"
diff --git a/kuickshow/src/aboutwidget.h b/kuickshow/src/aboutwidget.h
new file mode 100644
index 00000000..b9bc79d1
--- /dev/null
+++ b/kuickshow/src/aboutwidget.h
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef ABOUTWIDGET_H
+#define ABOUTWIDGET_H
+
+#include <qevent.h>
+#include <qvbox.h>
+
+class KURLWidget;
+
+class AboutWidget : public QVBox
+{
+ Q_OBJECT
+
+public:
+ AboutWidget(QWidget *parent = 0, const char *name = 0);
+
+protected:
+ ~AboutWidget();
+ bool eventFilter( QObject*, QEvent * );
+
+private:
+ KURLWidget *m_homepage;
+
+};
+
+#endif
diff --git a/kuickshow/src/defaultswidget.cpp b/kuickshow/src/defaultswidget.cpp
new file mode 100644
index 00000000..69807251
--- /dev/null
+++ b/kuickshow/src/defaultswidget.cpp
@@ -0,0 +1,282 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qvgroupbox.h>
+
+#include <kcombobox.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+
+#include "imlibwidget.h"
+#include "defaultswidget.h"
+
+DefaultsWidget::DefaultsWidget( QWidget *parent, const char *name)
+ : QWidget( parent, name )
+{
+ imFiltered = 0L;
+
+ cbEnableMods = new QCheckBox( i18n("Apply default image modifications"), this );
+ connect( cbEnableMods, SIGNAL( toggled(bool) ), SLOT( enableWidgets(bool) ));
+
+ // create all the widgets
+
+ gbScale = new QGroupBox( i18n("Scaling"), this );
+ gbScale->setColumnLayout( 0, Qt::Horizontal );
+
+ cbDownScale = new QCheckBox( i18n("Shrink image to screen size, if larger"),
+ gbScale, "shrinktoscreen" );
+
+ cbUpScale = new QCheckBox( i18n("Scale image to screen size, if smaller, up to factor:"), gbScale, "upscale checkbox" );
+
+ sbMaxUpScaleFactor = new KIntNumInput( gbScale, "upscale factor" );
+ sbMaxUpScaleFactor->setRange( 1, 100, 1, false );
+
+ connect(cbUpScale, SIGNAL( toggled(bool)), sbMaxUpScaleFactor,
+ SLOT( setEnabled(bool) ));
+
+ // --
+
+ gbGeometry = new QGroupBox( i18n("Geometry"), this );
+ gbGeometry->setColumnLayout( 0, Qt::Horizontal );
+
+ cbFlipVertically = new QCheckBox( i18n("Flip vertically"), gbGeometry );
+
+ cbFlipHorizontally = new QCheckBox( i18n("Flip horizontally"), gbGeometry );
+
+ lbRotate = new QLabel( i18n("Rotate image:"), gbGeometry );
+
+ comboRotate = new KComboBox( gbGeometry, "rotate combobox" );
+ comboRotate->insertItem( i18n("0 Degrees") );
+ comboRotate->insertItem( i18n("90 Degrees") );
+ comboRotate->insertItem( i18n("180 Degrees") );
+ comboRotate->insertItem( i18n("270 Degrees") );
+
+ // --
+
+ gbAdjust = new QVGroupBox( i18n("Adjustments"), this );
+
+ sbBrightness = new KIntNumInput( gbAdjust, "brightness spinbox" );
+ sbBrightness->setRange( -256, 256, 1, true );
+ sbBrightness->setLabel( i18n("Brightness:"), AlignVCenter );
+
+ sbContrast = new KIntNumInput( sbBrightness, 0,gbAdjust, 10,
+ "contrast spinbox");
+ sbContrast->setRange( -256, 256, 1, true );
+ sbContrast->setLabel( i18n("Contrast:"), AlignVCenter );
+
+ sbGamma = new KIntNumInput( sbContrast, 0, gbAdjust, 10, "gamma spinbox" );
+ sbGamma->setRange( -256, 256, 1, true );
+ sbGamma->setLabel( i18n("Gamma:"), AlignVCenter );
+
+ // --
+
+ gbPreview = new QGroupBox( i18n("Preview"), this );
+ gbPreview->setAlignment( AlignCenter );
+
+ lbImOrig = new QLabel( i18n("Original"), gbPreview );
+ imOrig = new ImlibWidget( 0L, gbPreview, "original image" );
+
+ lbImFiltered = new QLabel( i18n("Modified"), gbPreview );
+ imFiltered = new ImlibWidget( 0L, imOrig->getImlibData(), gbPreview, "" );
+ connect( imFiltered, SIGNAL( destroyed() ), SLOT( slotNoImage() ));
+
+ ////
+ ////////////////
+
+
+ // layout management
+ QVBoxLayout *mainLayout = new QVBoxLayout( this, 0,
+ KDialog::spacingHint(), "main layout" );
+
+ QVBoxLayout *gbScaleLayout = new QVBoxLayout( gbScale->layout(),
+ KDialog::spacingHint());
+ QVBoxLayout *gbGeometryLayout = new QVBoxLayout(gbGeometry->layout(),
+ KDialog::spacingHint());
+ QGridLayout *gbPreviewLayout = new QGridLayout(gbPreview, 2, 3, 0,
+ KDialog::spacingHint());
+
+ QHBoxLayout *scaleLayout = new QHBoxLayout();
+ QHBoxLayout *rotateLayout = new QHBoxLayout();
+
+ mainLayout->addWidget( cbEnableMods );
+ mainLayout->addWidget( gbScale );
+ QHBoxLayout *hl = new QHBoxLayout();
+ hl->addWidget( gbGeometry );
+ hl->addWidget( gbAdjust );
+ mainLayout->addLayout( hl );
+ mainLayout->addWidget( gbPreview );
+ mainLayout->addStretch();
+
+ // --
+
+ gbScaleLayout->addWidget( cbDownScale );
+ gbScaleLayout->addLayout( scaleLayout );
+
+ scaleLayout->addWidget( cbUpScale );
+ scaleLayout->addWidget( sbMaxUpScaleFactor );
+
+ // --
+
+ gbGeometryLayout->addWidget( cbFlipVertically, 0, AlignLeft );
+ gbGeometryLayout->addWidget( cbFlipHorizontally, 0, AlignLeft );
+ gbGeometryLayout->addLayout( rotateLayout, 0 );
+
+ rotateLayout->addWidget( lbRotate, 0, AlignLeft );
+ rotateLayout->addWidget( comboRotate, 0, AlignLeft );
+
+ // --
+
+ gbPreviewLayout->setMargin( 10 );
+ gbPreviewLayout->setSpacing( KDialog::spacingHint() );
+ gbPreviewLayout->addWidget( lbImOrig, 0, 0, AlignCenter );
+ gbPreviewLayout->addWidget( imOrig, 1, 0, AlignCenter | AlignTop );
+ gbPreviewLayout->addWidget( lbImFiltered, 0, 2, AlignCenter );
+ gbPreviewLayout->addWidget( imFiltered, 1, 2, AlignCenter | AlignTop );
+
+
+ ////
+ ////////////////
+
+ // connect them all to the update slot
+ connect( cbDownScale, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbUpScale, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbFlipVertically, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( cbFlipHorizontally, SIGNAL( clicked() ), SLOT( updatePreview() ));
+ connect( sbMaxUpScaleFactor, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbBrightness, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbContrast, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+ connect( sbGamma, SIGNAL( valueChanged(int) ), SLOT( updatePreview() ));
+
+ connect( comboRotate, SIGNAL( activated(int) ), SLOT( updatePreview() ));
+
+
+ QString filename = locate( "data", "kuickshow/pics/calibrate.png" );
+ if ( !imOrig->loadImage( filename ) )
+ imOrig = 0L; // FIXME - display some errormessage!
+ if ( !imFiltered->loadImage( filename ) )
+ imFiltered = 0L; // FIXME - display some errormessage!
+
+ loadSettings( *kdata );
+
+ if ( imOrig )
+ imOrig->setFixedSize( imOrig->size() );
+ if ( imFiltered )
+ imFiltered->setFixedSize( imFiltered->size() );
+
+ mainLayout->activate();
+}
+
+
+DefaultsWidget::~DefaultsWidget()
+{
+ // those need to be deleted in the right order, as imFiltered
+ // references ImlibData from imOrig
+ delete imFiltered;
+ delete imOrig;
+}
+
+void DefaultsWidget::loadSettings( const KuickData& data )
+{
+ cbDownScale->setChecked( data.downScale );
+ cbUpScale->setChecked( data.upScale );
+ sbMaxUpScaleFactor->setValue( data.maxUpScale );
+
+ cbFlipVertically->setChecked( data.flipVertically );
+ cbFlipHorizontally->setChecked( data.flipHorizontally );
+
+ comboRotate->setCurrentItem( data.rotation );
+
+ ImData *id = data.idata;
+
+ sbBrightness->setValue( id->brightness );
+ sbContrast->setValue( id->contrast );
+ sbGamma->setValue( id->gamma );
+
+ cbEnableMods->setChecked( data.isModsEnabled );
+ enableWidgets( data.isModsEnabled );
+
+ updatePreview();
+}
+
+void DefaultsWidget::applySettings( KuickData& data )
+{
+ data.isModsEnabled = cbEnableMods->isChecked();
+
+ data.downScale = cbDownScale->isChecked();
+ data.upScale = cbUpScale->isChecked();
+ data.maxUpScale = sbMaxUpScaleFactor->value();
+
+ data.flipVertically = cbFlipVertically->isChecked();
+ data.flipHorizontally = cbFlipHorizontally->isChecked();
+
+ data.rotation = currentRotation();
+
+ ImData *id = data.idata;
+
+ id->brightness = sbBrightness->value();
+ id->contrast = sbContrast->value();
+ id->gamma = sbGamma->value();
+}
+
+void DefaultsWidget::updatePreview()
+{
+ if ( !imFiltered )
+ return;
+
+ imFiltered->setAutoRender( false );
+
+ int flipMode = cbFlipHorizontally->isChecked() ? FlipHorizontal : FlipNone;
+ flipMode |= cbFlipVertically->isChecked() ? FlipVertical : FlipNone;
+ imFiltered->setFlipMode( flipMode );
+
+ Rotation rotation = cbEnableMods->isChecked() ? currentRotation() : ROT_0;
+ imFiltered->setRotation( rotation );
+
+ imFiltered->setBrightness( sbBrightness->value() );
+ imFiltered->setContrast( sbContrast->value() );
+ imFiltered->setGamma( sbGamma->value() );
+
+ imFiltered->updateImage();
+ imFiltered->setAutoRender( true );
+}
+
+
+void DefaultsWidget::enableWidgets( bool enable )
+{
+ gbScale->setEnabled( enable );
+ sbMaxUpScaleFactor->setEnabled( enable & cbUpScale->isChecked() );
+
+ gbGeometry->setEnabled( enable );
+ gbAdjust->setEnabled( enable );
+ gbPreview->setEnabled( enable );
+ updatePreview();
+}
+
+
+Rotation DefaultsWidget::currentRotation() const
+{
+ return (Rotation) comboRotate->currentItem();
+}
+
+#include "defaultswidget.moc"
diff --git a/kuickshow/src/defaultswidget.h b/kuickshow/src/defaultswidget.h
new file mode 100644
index 00000000..3febb098
--- /dev/null
+++ b/kuickshow/src/defaultswidget.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef DEFAULTSWIDGET_H
+#define DEFAULTSWIDGET_H
+
+#include "kuickdata.h"
+
+class ImlibWidget;
+class ImData;
+
+class QCheckBox;
+class QLabel;
+
+class KComboBox;
+class KIntNumInput;
+
+class DefaultsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ DefaultsWidget( QWidget *parent, const char *name );
+ ~DefaultsWidget();
+
+ void loadSettings( const KuickData& data );
+ void applySettings( KuickData& data );
+
+private:
+ Rotation currentRotation() const;
+
+ QCheckBox *cbEnableMods;
+
+ QGroupBox *gbScale;
+ QCheckBox *cbUpScale, *cbDownScale;
+ KIntNumInput *sbMaxUpScaleFactor;
+
+ QGroupBox *gbAdjust;
+ KIntNumInput *sbBrightness, *sbContrast, *sbGamma;
+
+ QGroupBox *gbGeometry;
+ QLabel *lbRotate;
+ KComboBox *comboRotate;
+ QCheckBox *cbFlipVertically, *cbFlipHorizontally;
+
+ QGroupBox *gbPreview;
+ QLabel *lbImOrig, *lbImFiltered;
+ ImlibWidget *imOrig, *imFiltered;
+
+
+private slots:
+ void updatePreview();
+ void slotNoImage() { imFiltered = 0L; }
+ void enableWidgets( bool );
+
+};
+
+#endif
diff --git a/kuickshow/src/filecache.cpp b/kuickshow/src/filecache.cpp
new file mode 100644
index 00000000..c1c1affe
--- /dev/null
+++ b/kuickshow/src/filecache.cpp
@@ -0,0 +1,83 @@
+#include <unistd.h>
+
+#include <qstring.h>
+
+#include <kdebug.h>
+#include <kstandarddirs.h>
+#include <ktempdir.h>
+
+#include "filecache.h"
+
+FileCache * FileCache::s_self;
+
+FileCache::FileCache()
+ : m_limit( 0 ),
+ m_tempDir( 0L )
+{
+ m_files.setAutoDelete( true );
+ m_files.setMaxCost( 100 ); // good default? ### make configurable?
+}
+
+FileCache::~FileCache()
+{
+ delete m_tempDir;
+}
+
+void FileCache::shutdown()
+{
+ if ( s_self )
+ {
+ delete s_self;
+ s_self = 0L;
+ }
+}
+
+FileCache * FileCache::self()
+{
+ if ( !s_self )
+ s_self = new FileCache();
+ return s_self;
+}
+
+KuickFile * FileCache::getFile( const KURL& url )
+{
+ QString urlString = url.prettyURL();
+ KuickFile *file = m_files.find( urlString );
+ if ( !file ) {
+ file = new KuickFile( url );
+ m_files.insert( urlString, file );
+ }
+
+ return file;
+}
+
+QString FileCache::tempDir()
+{
+ if ( !m_tempDir ) {
+ m_tempDir = createTempDir();
+
+ if ( !m_tempDir ) {
+ kdWarning() << "Unable to create temporary directory for KuickShow" << endl;
+ return QString::null;
+ }
+ }
+
+ return m_tempDir->name();
+}
+
+
+KTempDir * FileCache::createTempDir()
+{
+ QString tmpName = QString::fromLatin1( KGlobal::instance()->instanceName() );
+ tmpName.append( QString::number( getpid() ) );
+ QString dirName = locateLocal( "tmp", tmpName );
+ KTempDir *dir = new KTempDir( dirName );
+ dir->setAutoDelete( true );
+ if ( dir->status() != 0L )
+ {
+ delete dir;
+ return 0L;
+ }
+
+ return dir;
+}
diff --git a/kuickshow/src/filecache.h b/kuickshow/src/filecache.h
new file mode 100644
index 00000000..16e53261
--- /dev/null
+++ b/kuickshow/src/filecache.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2006/02/20 15:06:53 gis Exp $
+**
+** Created : 2006
+**
+** Copyright (C) 2006 Carsten Pfeiffer <[email protected]>
+**
+****************************************************************************/
+
+#ifndef FILECACHE_H
+#define FILECACHE_H
+
+#include <qcache.h>
+
+#include "kuickfile.h"
+
+class KTempDir;
+
+class FileCache
+{
+public:
+ static FileCache * self();
+ static void shutdown();
+
+ KuickFile * getFile( const KURL& url );
+ void setLimit( int numFiles );
+ int getLimit() const { return m_limit; }
+
+ /**
+ * @return the temporary directory or QString::null if none available
+ */
+ QString tempDir();
+
+private:
+ static FileCache *s_self;
+ FileCache();
+ ~FileCache();
+
+ KTempDir * createTempDir();
+ QCache<KuickFile> m_files;
+
+ int m_limit;
+ KTempDir *m_tempDir;
+
+};
+
+#endif // FILECACHE_H
diff --git a/kuickshow/src/filefinder.cpp b/kuickshow/src/filefinder.cpp
new file mode 100644
index 00000000..9dda0046
--- /dev/null
+++ b/kuickshow/src/filefinder.cpp
@@ -0,0 +1,99 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qkeycode.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kcompletionbox.h>
+#include <kurlcompletion.h>
+
+#include "filefinder.h"
+
+FileFinder::FileFinder( QWidget *parent, const char *name )
+ : KLineEdit( parent, name )
+{
+ // make this widget just as large, as the font is + 8 Pixels
+ int height = fontMetrics().height() + 8;
+ setFixedSize( 150, height );
+ setFrame( true );
+
+ setHandleSignals( true ); // we want the completionbox signals
+ completionBox()->setTabHandling( true );
+
+ connect( completionBox(), SIGNAL( userCancelled(const QString&) ),
+ SLOT( hide() ));
+ connect( completionBox(), SIGNAL( activated( const QString& ) ),
+ SLOT( slotAccept( const QString& )));
+ connect( this, SIGNAL( returnPressed( const QString& )),
+ SLOT( slotAccept( const QString& ) ));
+
+ KURLCompletion *comp = new KURLCompletion();
+ comp->setReplaceHome( true );
+ comp->setReplaceEnv( true );
+ setCompletionObject( comp, false );
+ setAutoDeleteCompletionObject( true );
+ setFocusPolicy( ClickFocus );
+
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "GeneralConfiguration" );
+ setCompletionMode( (KGlobalSettings::Completion)
+ config->readNumEntry( "FileFinderCompletionMode",
+ KGlobalSettings::completionMode()));
+}
+
+FileFinder::~FileFinder()
+{
+ KConfig *config = KGlobal::config();
+ KConfigGroupSaver cs( config, "GeneralConfiguration" );
+ config->writeEntry( "FileFinderCompletionMode", completionMode() );
+}
+
+void FileFinder::focusOutEvent( QFocusEvent *e )
+{
+ if ( e->reason() != QFocusEvent::Popup )
+ hide();
+}
+
+void FileFinder::keyPressEvent( QKeyEvent *e )
+{
+ int key = e->key();
+ if ( key == Key_Escape ) {
+ hide();
+ e->accept();
+ }
+
+ else {
+ KLineEdit::keyPressEvent( e );
+ }
+}
+
+void FileFinder::hide()
+{
+ KLineEdit::hide();
+ parentWidget()->setFocus();
+}
+
+void FileFinder::slotAccept( const QString& dir )
+{
+ hide();
+ emit enterDir( dir );
+}
+
+#include "filefinder.moc"
diff --git a/kuickshow/src/filefinder.h b/kuickshow/src/filefinder.h
new file mode 100644
index 00000000..f75c69a4
--- /dev/null
+++ b/kuickshow/src/filefinder.h
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FILEFINDER_H
+#define FILEFINDER_H
+
+#include <qevent.h>
+
+#include <klineedit.h>
+
+class KURLCompletion;
+
+class FileFinder : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+ FileFinder( QWidget *parent=0, const char *name=0 );
+ ~FileFinder();
+
+ KURLCompletion *completion() {
+ return static_cast<KURLCompletion*>( completionObject() );
+ }
+
+ virtual void hide();
+
+signals:
+ void enterDir( const QString& );
+
+protected:
+ virtual void focusOutEvent( QFocusEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+
+private slots:
+ void slotAccept( const QString& );
+
+};
+
+#endif // FILEFINDER_H
diff --git a/kuickshow/src/filewidget.cpp b/kuickshow/src/filewidget.cpp
new file mode 100644
index 00000000..d4b99f0a
--- /dev/null
+++ b/kuickshow/src/filewidget.cpp
@@ -0,0 +1,464 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qkeycode.h>
+
+#include <kdeversion.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kpropertiesdialog.h>
+#include <kurlcompletion.h>
+
+#include "filefinder.h"
+#include "filewidget.h"
+#include "kuickdata.h"
+#include "kuickshow.h"
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+FileWidget::FileWidget( const KURL& url, QWidget *parent, const char *name )
+ : KDirOperator( url, parent, name ),
+ m_validCompletion( false ),
+ m_fileFinder( 0L )
+{
+ setEnableDirHighlighting( true );
+
+#if KDE_VERSION >= 310
+ setViewConfig( KGlobal::config(), "Filebrowser" );
+#endif
+ readConfig( KGlobal::config(), "Filebrowser" );
+ setView( KFile::Default );
+
+ // setOnlyDoubleClickSelectsFiles( true );
+ reloadConfiguration();
+
+ completionObject()->setCompletionMode( KGlobalSettings::CompletionAuto );
+ dirCompletionObject()->setCompletionMode( KGlobalSettings::CompletionAuto);
+
+ slotViewChanged();
+ connect( this, SIGNAL( viewChanged( KFileView * )),
+ SLOT( slotViewChanged() ));
+
+ connect( dirLister(), SIGNAL( clear() ), SLOT( slotItemsCleared() ));
+ connect( dirLister(), SIGNAL( deleteItem( KFileItem * ) ),
+ SLOT( slotItemDeleted( KFileItem *) ));
+
+ connect( this, SIGNAL( fileHighlighted( const KFileItem * )),
+ SLOT( slotHighlighted( const KFileItem * )));
+
+ connect( this, SIGNAL(urlEntered(const KURL&)),
+ SLOT( slotURLEntered( const KURL& )));
+
+ // should actually be KDirOperator's job!
+ connect( this, SIGNAL( finishedLoading() ), SLOT( slotFinishedLoading() ));
+}
+
+FileWidget::~FileWidget()
+{
+ delete m_fileFinder;
+}
+
+void FileWidget::initActions()
+{
+ int index = 0;
+ KActionCollection *coll = actionCollection();
+ KActionSeparator *sep = new KActionSeparator( coll, "kuicksep" );
+ KActionMenu *menu = static_cast<KActionMenu*>( coll->action("popupMenu") );
+
+ menu->insert( coll->action("kuick_showInOtherWindow"), index++ );
+ menu->insert( coll->action("kuick_showInSameWindow"), index++ );
+ menu->insert( coll->action("kuick_showFullscreen"), index++ );
+ menu->insert( sep, index++ );
+
+ // support for older kdelibs, remove somewhen...
+ if ( coll->action("kuick_delete") )
+ menu->insert( coll->action("kuick_delete"), 9 );
+
+ // properties dialog is now in kfile, but not at the right position,
+ // so we move it to the real bottom
+ menu->remove( coll->action( "properties" ) );
+
+ QPopupMenu *pMenu = menu->popupMenu();
+ int lastItemId = pMenu->idAt( pMenu->count() - 1 );
+ QMenuItem *mItem = pMenu->findItem( lastItemId );
+ if ( mItem && !mItem->isSeparator() )
+ menu->insert( sep );
+
+ // those at the bottom
+ menu->insert( coll->action("kuick_print") );
+ menu->insert( sep );
+ menu->insert( coll->action("properties") );
+}
+
+void FileWidget::reloadConfiguration()
+{
+ if ( kdata->fileFilter != nameFilter() ) {
+ // At first, our list must have folders
+ QStringList mimes;
+ mimes.append("inode/directory");
+
+ // Then, all the images!
+ KMimeType::List l = KMimeType::allMimeTypes();
+ for (KMimeType::List::iterator it = l.begin(); it != l.end(); ++it)
+ if ((*it)->name().startsWith( "image/" ))
+ mimes.append( (*it)->name() );
+
+ // Ok, show what we've done
+ setMimeFilter (mimes);
+ updateDir();
+ }
+}
+
+bool FileWidget::hasFiles() const
+{
+ return (numFiles() > 0);
+}
+
+void FileWidget::activatedMenu( const KFileItem *item, const QPoint& pos )
+{
+ bool image = isImage( item );
+ actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
+ actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
+ actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
+ actionCollection()->action("kuick_print")->setEnabled( image );
+ actionCollection()->action("properties")->setEnabled( item );
+
+ bool hasSelection = (item != 0L);
+ if ( actionCollection()->action("kuick_delete") )
+ actionCollection()->action("kuick_delete")->setEnabled( hasSelection );
+
+ KDirOperator::activatedMenu( item, pos );
+}
+
+void FileWidget::findCompletion( const QString& text )
+{
+ if ( text.at(0) == '/' || text.at(0) == '~' ||
+ text.find('/') != -1 ) {
+ QString t = m_fileFinder->completion()->makeCompletion( text );
+
+ if (m_fileFinder->completionMode() == KGlobalSettings::CompletionPopup ||
+ m_fileFinder->completionMode() == KGlobalSettings::CompletionPopupAuto)
+ m_fileFinder->setCompletedItems(
+ m_fileFinder->completion()->allMatches() );
+ else
+ if ( !t.isNull() )
+ m_fileFinder->setCompletedText( t );
+
+ return;
+ }
+
+ QString file = makeDirCompletion( text );
+ if ( file.isNull() )
+ file = makeCompletion( text );
+
+ m_validCompletion = !file.isNull();
+
+ if ( m_validCompletion )
+ KDirOperator::setCurrentItem( file );
+}
+
+bool FileWidget::eventFilter( QObject *o, QEvent *e )
+{
+ if ( e->type() == QEvent::KeyPress ) {
+ QKeyEvent *k = static_cast<QKeyEvent*>( e );
+
+ if ( (k->state() & (ControlButton | AltButton)) == 0 ) {
+ int key = k->key();
+ if ( actionCollection()->action("delete")->shortcut().contains( key ) )
+ {
+ k->accept();
+ KFileItem *item = getCurrentItem( false );
+ if ( item ) {
+ KFileItemList list;
+ list.append( item );
+ del( list, (k->state() & ShiftButton) == 0 );
+ }
+ return true;
+ }
+
+ const QString& text = k->text();
+ if ( !text.isEmpty() && text.unicode()->isPrint() ) {
+ k->accept();
+
+ if ( !m_fileFinder ) {
+ m_fileFinder = new FileFinder( this, "file finder" );
+ connect( m_fileFinder, SIGNAL( completion(const QString&)),
+ SLOT( findCompletion( const QString& )));
+ connect( m_fileFinder,
+ SIGNAL( enterDir( const QString& ) ),
+ SLOT( slotReturnPressed( const QString& )));
+ m_fileFinder->move( width() - m_fileFinder->width(),
+ height() - m_fileFinder->height() );
+ }
+
+ bool first = m_fileFinder->isHidden();
+
+ m_fileFinder->setText( text );
+ m_fileFinder->raise();
+ m_fileFinder->show();
+ m_fileFinder->setFocus();
+ if ( first )
+ findCompletion( text );
+
+ return true;
+ }
+ }
+
+ k->ignore();
+ }
+ return KDirOperator::eventFilter( o, e );
+}
+
+
+// KIO::NetAccess::stat() does NOT give us the right mimetype, while
+// KIO::NetAccess::mimetype() does. So we have this hacklet to tell
+// showImage that the KFileItem is really an image.
+#define IS_IMAGE 5
+#define MY_TYPE 55
+
+bool FileWidget::isImage( const KFileItem *item )
+{
+// return item && !item->isDir();
+ if ( item )
+ {
+ return item->isReadable() && item->mimetype().startsWith( "image/") ||
+ item->extraData( (void*) MY_TYPE ) == (void*) IS_IMAGE;
+ }
+ return false;
+}
+
+void FileWidget::setImage( KFileItem& item, bool enable )
+{
+ if ( enable )
+ item.setExtraData( (void*) MY_TYPE, (void*) IS_IMAGE );
+ else
+ item.removeExtraData( (void*) MY_TYPE );
+}
+
+KFileItem * FileWidget::gotoFirstImage()
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+
+ while ( it.current() ) {
+ if ( isImage( it.current() ) ) {
+ setCurrentItem( it.current() );
+ return it.current();
+ }
+ ++it;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::gotoLastImage()
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+ it.toLast();
+
+ while ( it.current() ) {
+ if ( isImage( it.current() ) ) {
+ setCurrentItem( it.current() );
+ return it.current();
+ }
+ --it;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::getNext( bool go )
+{
+ KFileItem *item = getItem( Next, true );
+ if ( item ) {
+ if ( go )
+ setCurrentItem( item );
+ return item;
+ }
+
+ return 0L;
+}
+
+KFileItem * FileWidget::getPrevious( bool go )
+{
+ KFileItem *item = getItem( Previous, true );
+ if ( item ) {
+ if ( go )
+ setCurrentItem( item );
+ return item;
+ }
+
+ return 0L;
+}
+
+// returns 0L when there is no previous/next item/image
+// this sucks! Use KFileView::currentFileItem() when implemented
+KFileItem * FileWidget::getItem( WhichItem which, bool onlyImage ) const
+{
+ KFileItemListIterator it( *(fileView()->items()) );
+
+ while ( it.current() ) { // find the iterator to the current item
+ if ( it.current()->url() == m_currentURL )
+ break;
+
+ ++it;
+ }
+
+ if ( it.current() ) {
+ switch ( which ) {
+ case Previous: {
+ --it;
+ while ( it.current() ) {
+ if ( isImage( it.current() ) || !onlyImage )
+ return it.current();
+ --it;
+ }
+ return 0L; // no previous item / image
+ }
+
+ case Next: {
+ ++it;
+ while ( it.current() ) {
+ if ( isImage( it.current() ) || !onlyImage )
+ return it.current();
+ ++it;
+ }
+ return 0L; // no further item / image
+ }
+
+ case Current:
+ default:
+ return it.current();
+ }
+ }
+
+ return 0L;
+}
+
+void FileWidget::slotViewChanged()
+{
+ fileView()->widget()->installEventFilter( this );
+}
+
+void FileWidget::slotItemsCleared()
+{
+ m_currentURL = QString::null;
+}
+
+void FileWidget::slotItemDeleted( KFileItem *item )
+{
+ KFileItem *current = getCurrentItem( false );
+ if ( item != current ) {
+ return; // all ok, we already have a new current item
+ }
+
+ KFileItem *next = getNext();
+ if ( !next )
+ next = getPrevious();
+
+ if ( next )
+ m_currentURL = next->url().url();
+}
+
+void FileWidget::slotHighlighted( const KFileItem *item )
+{
+ m_currentURL = item->url().url();
+}
+
+void FileWidget::slotReturnPressed( const QString& t )
+{
+ // we need a / at the end, otherwise replacedPath() will cut off the dir,
+ // assuming it is a filename
+ QString text = t;
+ if ( text.at( text.length()-1 ) != '/' )
+ text += '/';
+
+ if ( text.at(0) == '/' || text.at(0) == '~' ) {
+ QString dir = m_fileFinder->completion()->replacedPath( text );
+
+ KURL url;
+ url.setPath( dir );
+ setURL( url, true );
+ }
+
+ else if ( text.find('/') != (int) text.length() -1 ) { // relative path
+ QString dir = m_fileFinder->completion()->replacedPath( text );
+ KURL u( url(), dir );
+ setURL( u, true );
+ }
+
+ else if ( m_validCompletion ) {
+ KFileItem *item = getCurrentItem( true );
+
+ if ( item ) {
+ if ( item->isDir() )
+ setURL( item->url(), true );
+ else
+ emit fileSelected( item );
+ }
+ }
+}
+
+void FileWidget::setCurrentItem( const KFileItem *item )
+{
+ if ( item ) {
+ fileView()->setCurrentItem( item );
+ fileView()->ensureItemVisible( item );
+ }
+}
+
+void FileWidget::setInitialItem( const QString& filename )
+{
+ m_initialName = filename;
+}
+
+void FileWidget::slotURLEntered( const KURL& url )
+{
+ if ( m_fileFinder )
+ m_fileFinder->completion()->setDir( url.path() );
+}
+
+void FileWidget::slotFinishedLoading()
+{
+ KFileItem *current = getCurrentItem( false );
+ if ( !m_initialName.isEmpty() )
+ setCurrentItem( m_initialName );
+ else if ( !current )
+ setCurrentItem( view()->items()->getFirst() );
+
+ m_initialName = QString::null;
+ emit finished();
+}
+
+QSize FileWidget::sizeHint() const
+{
+ return QSize( 300, 300 );
+}
+
+void FileWidget::resizeEvent( QResizeEvent *e )
+{
+ KDirOperator::resizeEvent( e );
+ if ( m_fileFinder )
+ m_fileFinder->move( width() - m_fileFinder->width(),
+ height() - m_fileFinder->height() );
+}
+
+#include "filewidget.moc"
diff --git a/kuickshow/src/filewidget.h b/kuickshow/src/filewidget.h
new file mode 100644
index 00000000..a785fd85
--- /dev/null
+++ b/kuickshow/src/filewidget.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef FILEWIDGET_H
+#define FILEWIDGET_H
+
+#include <qevent.h>
+
+#include <kdiroperator.h>
+
+class FileFinder;
+class KFileItem;
+
+class FileWidget : public KDirOperator
+{
+ Q_OBJECT
+
+public:
+ enum WhichItem { Previous, Next, Current };
+
+ FileWidget( const KURL& url, QWidget *parent = 0L, const char *name = 0L );
+ ~FileWidget();
+
+ bool hasFiles() const;
+ void reloadConfiguration();
+
+ void setInitialItem( const QString& filename );
+
+ KFileItem *getCurrentItem( bool onlyImage ) const {
+ return getItem( Current, onlyImage );
+ }
+
+ void setCurrentItem( const KFileItem * );
+ void setCurrentItem( const QString& filename ) {
+ KDirOperator::setCurrentItem( filename );
+ }
+
+ KFileItem * gotoFirstImage();
+ KFileItem * gotoLastImage();
+ KFileItem * getNext( bool go=true );
+ KFileItem * getPrevious( bool go=true );
+
+
+ KFileItem *getItem( WhichItem which, bool onlyImage ) const;
+
+ static bool isImage( const KFileItem * );
+ static void setImage( KFileItem& item, bool enable );
+
+ void initActions();
+
+signals:
+ void finished();
+
+protected:
+ virtual bool eventFilter( QObject *o, QEvent * );
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void activatedMenu( const KFileItem *, const QPoint& );
+ virtual QSize sizeHint() const;
+
+private slots:
+ void slotReturnPressed( const QString& text );
+ void findCompletion( const QString& );
+ void slotViewChanged();
+
+ void slotItemsCleared();
+ void slotItemDeleted( KFileItem * );
+ void slotHighlighted( const KFileItem * );
+
+ void slotURLEntered( const KURL& url );
+ void slotFinishedLoading();
+
+private:
+ KFileView * fileView() const { return (KFileView*) view(); }
+
+ bool m_validCompletion;
+ FileFinder *m_fileFinder;
+ QString m_currentURL;
+ QString m_initialName;
+
+};
+
+
+#endif // FILEWIDGET_H
diff --git a/kuickshow/src/generalwidget.cpp b/kuickshow/src/generalwidget.cpp
new file mode 100644
index 00000000..3b718d69
--- /dev/null
+++ b/kuickshow/src/generalwidget.cpp
@@ -0,0 +1,163 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qvgroupbox.h>
+
+#include <kapplication.h>
+#include <kcolorbutton.h>
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kurllabel.h>
+
+#include "generalwidget.h"
+
+GeneralWidget::GeneralWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ QPixmap pixmap = UserIcon( "logo" );
+ KURLLabel *logo = new KURLLabel( this );
+ logo->setURL( "http://devel-home.kde.org/~pfeiffer/kuickshow/" );
+ logo->setPixmap( pixmap );
+ logo->setFixedSize( pixmap.size() );
+ logo->setTipText( i18n( "Open KuickShow Website" ) );
+ logo->setUseTips( true );
+
+ connect( logo, SIGNAL( leftClickedURL( const QString & ) ),
+ SLOT( slotURLClicked( const QString & ) ) );
+
+ layout->addWidget( logo, 0, AlignRight );
+
+ cbFullscreen = new QCheckBox( i18n("Fullscreen mode"), this, "boscreen" );
+
+ cbPreload = new QCheckBox( i18n("Preload next image"), this, "preload");
+ cbLastdir = new QCheckBox( i18n("Remember last folder"), this, "restart_lastdir");
+
+ QGridLayout *gridLayout = new QGridLayout( 2, 2 );
+ gridLayout->setSpacing( KDialog::spacingHint() );
+ QLabel *l0 = new QLabel( i18n("Background color:"), this );
+ colorButton = new KColorButton( this );
+
+ QLabel *l1 = new QLabel( i18n("Show only files with extension: "), this, "label" );
+ editFilter = new KLineEdit( this, "filteredit" );
+
+ gridLayout->addWidget( l0, 0, 0 );
+ gridLayout->addWidget( colorButton, 0, 1 );
+ gridLayout->addWidget( l1, 1, 0 );
+ gridLayout->addWidget( editFilter, 1, 1 );
+
+ layout->addWidget( cbFullscreen );
+ layout->addWidget( cbPreload );
+ layout->addWidget( cbLastdir );
+ layout->addLayout( gridLayout );
+
+ ////////////////////////////////////////////////////////////////////////
+
+ QVGroupBox *gbox2 = new QVGroupBox( i18n("Quality/Speed"),
+ this, "qualitybox" );
+ layout->addWidget( gbox2 );
+ layout->addStretch();
+
+ cbSmoothScale = new QCheckBox( i18n("Smooth scaling"), gbox2, "smoothscale" );
+ cbFastRender = new QCheckBox( i18n("Fast rendering"), gbox2, "fastrender" );
+ cbDither16bit = new QCheckBox( i18n("Dither in HiColor (15/16bit) modes"),
+ gbox2, "dither16bit" );
+
+ cbDither8bit = new QCheckBox( i18n("Dither in LowColor (<=8bit) modes"),
+ gbox2, "dither8bit" );
+
+ cbOwnPalette = new QCheckBox( i18n("Use own color palette"),
+ gbox2, "pal");
+ connect( cbOwnPalette, SIGNAL( clicked() ), this, SLOT( useOwnPalette() ) );
+
+ cbFastRemap = new QCheckBox( i18n("Fast palette remapping"), gbox2, "remap");
+
+ maxCacheSpinBox = new KIntNumInput( gbox2, "editmaxcache" );
+ maxCacheSpinBox->setLabel( i18n("Maximum cache size: "), AlignVCenter );
+ maxCacheSpinBox->setSuffix( i18n( " MB" ) );
+ maxCacheSpinBox->setSpecialValueText( i18n( "Unlimited" ) );
+ maxCacheSpinBox->setRange( 0, 400, 1 );
+
+ loadSettings( *kdata );
+ cbFullscreen->setFocus();
+}
+
+GeneralWidget::~GeneralWidget()
+{
+}
+
+void GeneralWidget::slotURLClicked( const QString & url )
+{
+ kapp->invokeBrowser( url );
+}
+
+void GeneralWidget::loadSettings( const KuickData& data )
+{
+ ImData *idata = data.idata;
+
+ colorButton->setColor( data.backgroundColor );
+ editFilter->setText( data.fileFilter );
+ cbFullscreen->setChecked( data.fullScreen );
+ cbPreload->setChecked( data.preloadImage );
+ cbLastdir->setChecked( data.startInLastDir );
+ cbFastRemap->setChecked( idata->fastRemap );
+ cbOwnPalette->setChecked( idata->ownPalette );
+ cbSmoothScale->setChecked( idata->smoothScale );
+ cbFastRender->setChecked( idata->fastRender );
+ cbDither16bit->setChecked( idata->dither16bit );
+ cbDither8bit->setChecked( idata->dither8bit );
+ maxCacheSpinBox->setValue( idata->maxCache / 1024 );
+
+ useOwnPalette(); // enable/disable remap-checkbox
+}
+
+void GeneralWidget::applySettings( KuickData& data)
+{
+ ImData *idata = data.idata;
+
+ data.backgroundColor = colorButton->color();
+ data.fileFilter = editFilter->text();
+ data.fullScreen = cbFullscreen->isChecked();
+ data.preloadImage = cbPreload->isChecked();
+ data.startInLastDir = cbLastdir->isChecked();
+
+ idata->smoothScale = cbSmoothScale->isChecked();
+ idata->fastRemap = cbFastRemap->isChecked();
+ idata->ownPalette = cbOwnPalette->isChecked();
+ idata->fastRender = cbFastRender->isChecked();
+ idata->dither16bit = cbDither16bit->isChecked();
+ idata->dither8bit = cbDither8bit->isChecked();
+
+ idata->maxCache = (uint) maxCacheSpinBox->value() * 1024;
+}
+
+void GeneralWidget::useOwnPalette()
+{
+ cbFastRemap->setEnabled( cbOwnPalette->isChecked() );
+}
+
+#include "generalwidget.moc"
diff --git a/kuickshow/src/generalwidget.h b/kuickshow/src/generalwidget.h
new file mode 100644
index 00000000..e39eef18
--- /dev/null
+++ b/kuickshow/src/generalwidget.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GENERALWIDGET_H
+#define GENERALWIDGET_H
+
+#include <qwidget.h>
+
+#include "kuickdata.h"
+
+class QCheckBox;
+class KColorButton;
+class KLineEdit;
+class KIntNumInput;
+
+
+class GeneralWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ GeneralWidget( QWidget *parent, const char *name );
+ ~GeneralWidget();
+
+ void loadSettings( const KuickData& data );
+ void applySettings( KuickData& data );
+
+private:
+ QCheckBox *cbFullscreen, *cbActiveWindow, *cbPreload, *cbLastdir;
+ QCheckBox *cbSmoothScale, *cbFastRemap, *cbFastRender;
+ QCheckBox *cbDither16bit, *cbDither8bit, *cbOwnPalette;
+
+ KLineEdit *editFilter;
+ KIntNumInput *maxCacheSpinBox;
+
+ KIntNumInput *sbMaxWidth, *sbMaxHeight;
+ KIntNumInput *sbZoomFactor;
+
+ KColorButton *colorButton;
+
+private slots:
+ void useOwnPalette();
+ void slotURLClicked( const QString & );
+
+};
+
+#endif
diff --git a/kuickshow/src/hi16-app-kuickshow.png b/kuickshow/src/hi16-app-kuickshow.png
new file mode 100644
index 00000000..9f764485
--- /dev/null
+++ b/kuickshow/src/hi16-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/hi22-app-kuickshow.png b/kuickshow/src/hi22-app-kuickshow.png
new file mode 100644
index 00000000..d8750f31
--- /dev/null
+++ b/kuickshow/src/hi22-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/hi32-app-kuickshow.png b/kuickshow/src/hi32-app-kuickshow.png
new file mode 100644
index 00000000..e70e573e
--- /dev/null
+++ b/kuickshow/src/hi32-app-kuickshow.png
Binary files differ
diff --git a/kuickshow/src/imagewindow.cpp b/kuickshow/src/imagewindow.cpp
new file mode 100644
index 00000000..c63a3c67
--- /dev/null
+++ b/kuickshow/src/imagewindow.cpp
@@ -0,0 +1,1251 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <qcheckbox.h>
+#include <qcursor.h>
+#include <qdrawutil.h>
+#include <qfileinfo.h>
+#include <qkeycode.h>
+#include <qpainter.h>
+#include <qpen.h>
+#include <qpopupmenu.h>
+
+#ifdef KDE_USE_FINAL
+#undef GrayScale
+#undef Color
+#endif
+#include <qrect.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#ifdef KDE_USE_FINAL
+#undef Unsorted
+#endif
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <kimageeffect.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprinter.h>
+#include <kpropertiesdialog.h>
+#include <kstdaccel.h>
+#include <kstdguiitem.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <ktempfile.h>
+#include <kwin.h>
+#include <netwm.h>
+#include <kurldrag.h>
+#include <kio/netaccess.h>
+
+#include "filecache.h"
+#include "imagewindow.h"
+#include "kuick.h"
+#include "kuickdata.h"
+#include "kuickfile.h"
+#include "kuickimage.h"
+#include "printing.h"
+
+
+#undef GrayScale
+
+QCursor *ImageWindow::s_handCursor = 0L;
+
+ImageWindow::ImageWindow( ImData *_idata, ImlibData *id, QWidget *parent,
+ const char *name )
+ : ImlibWidget( _idata, id, parent, name )
+{
+ init();
+}
+
+ImageWindow::ImageWindow( ImData *_idata, QWidget *parent, const char *name )
+ : ImlibWidget( _idata, parent, name )
+{
+ init();
+}
+
+ImageWindow::~ImageWindow()
+{
+}
+
+
+void ImageWindow::init()
+{
+ setFocusPolicy( QWidget::StrongFocus );
+
+ KCursor::setAutoHideCursor( this, true, true );
+ KCursor::setHideCursorDelay( 1500 );
+
+ // give the image window a different WM_CLASS
+ XClassHint hint;
+ hint.res_name = const_cast<char*>( kapp->name() );
+ hint.res_class = const_cast<char*>( "ImageWindow" );
+ XSetClassHint( x11Display(), winId(), &hint );
+
+ viewerMenu = 0L;
+ gammaMenu = 0L;
+ brightnessMenu = 0L;
+ contrastMenu = 0L;
+
+
+ m_actions = new KActionCollection( this );
+
+ if ( !s_handCursor ) {
+ QString file = locate( "appdata", "pics/handcursor.png" );
+ if ( !file.isEmpty() )
+ s_handCursor = new QCursor( file );
+ else
+ s_handCursor = new QCursor( arrowCursor );
+ }
+
+ setupActions();
+ imageCache->setMaxImages( kdata->maxCachedImages );
+
+ transWidget = 0L;
+ myIsFullscreen = false;
+
+ xpos = 0, ypos = 0;
+ m_numHeads = ScreenCount( x11Display() );
+
+ setAcceptDrops( true );
+ setBackgroundColor( kdata->backgroundColor );
+
+ static QPixmap imageIcon = UserIcon( "imageviewer-medium" );
+ static QPixmap miniImageIcon = UserIcon( "imageviewer-small" );
+ KWin::setIcons( winId(), imageIcon, miniImageIcon );
+}
+
+void ImageWindow::updateActions()
+{
+ m_actions->readShortcutSettings();
+}
+
+void ImageWindow::setupActions()
+{
+ new KAction( i18n("Show Next Image"), KStdAccel::next(),
+ this, SLOT( slotRequestNext() ),
+ m_actions, "next_image" );
+ new KAction( i18n("Show Previous Image"), KStdAccel::prior(),
+ this, SLOT( slotRequestPrevious() ),
+ m_actions, "previous_image" );
+
+ new KAction( i18n("Delete Image"), SHIFT + Key_Delete,
+ this, SLOT( imageDelete() ),
+ m_actions, "delete_image" );
+ new KAction( i18n("Move Image to Trash"), Key_Delete,
+ this, SLOT( imageTrash() ),
+ m_actions, "trash_image" );
+
+ new KAction( i18n("Zoom In"), Key_Plus,
+ this, SLOT( zoomIn() ),
+ m_actions, "zoom_in" );
+ new KAction( i18n("Zoom Out"), Key_Minus,
+ this, SLOT( zoomOut() ),
+ m_actions, "zoom_out" );
+ new KAction( i18n("Restore Original Size"), Key_O,
+ this, SLOT( showImageOriginalSize() ),
+ m_actions, "original_size" );
+ new KAction( i18n("Maximize"), Key_M,
+ this, SLOT( maximize() ),
+ m_actions, "maximize" );
+
+ new KAction( i18n("Rotate 90 Degrees"), Key_9,
+ this, SLOT( rotate90() ),
+ m_actions, "rotate90" );
+ new KAction( i18n("Rotate 180 Degrees"), Key_8,
+ this, SLOT( rotate180() ),
+ m_actions, "rotate180" );
+ new KAction( i18n("Rotate 270 Degrees"), Key_7,
+ this, SLOT( rotate270() ),
+ m_actions, "rotate270" );
+
+ new KAction( i18n("Flip Horizontally"), Key_Asterisk,
+ this, SLOT( flipHoriz() ),
+ m_actions, "flip_horicontally" );
+ new KAction( i18n("Flip Vertically"), Key_Slash,
+ this, SLOT( flipVert() ),
+ m_actions, "flip_vertically" );
+
+ new KAction( i18n("Print Image..."), KStdAccel::print(),
+ this, SLOT( printImage() ),
+ m_actions, "print_image" );
+ KStdAction::saveAs( this, SLOT( saveImage() ),
+ m_actions, "save_image_as" );
+
+ KStdAction::close( this, SLOT( close() ),
+ m_actions, "close_image" );
+ // --------
+ new KAction( i18n("More Brightness"), Key_B,
+ this, SLOT( moreBrightness() ),
+ m_actions, "more_brightness" );
+ new KAction( i18n("Less Brightness"), SHIFT + Key_B,
+ this, SLOT( lessBrightness() ),
+ m_actions, "less_brightness" );
+ new KAction( i18n("More Contrast"), Key_C,
+ this, SLOT( moreContrast() ),
+ m_actions, "more_contrast" );
+ new KAction( i18n("Less Contrast"), SHIFT + Key_C,
+ this, SLOT( lessContrast() ),
+ m_actions, "less_contrast" );
+ new KAction( i18n("More Gamma"), Key_G,
+ this, SLOT( moreGamma() ),
+ m_actions, "more_gamma" );
+ new KAction( i18n("Less Gamma"), SHIFT + Key_G,
+ this, SLOT( lessGamma() ),
+ m_actions, "less_gamma" );
+
+ // --------
+ new KAction( i18n("Scroll Up"), Key_Up,
+ this, SLOT( scrollUp() ),
+ m_actions, "scroll_up" );
+ new KAction( i18n("Scroll Down"), Key_Down,
+ this, SLOT( scrollDown() ),
+ m_actions, "scroll_down" );
+ new KAction( i18n("Scroll Left"), Key_Left,
+ this, SLOT( scrollLeft() ),
+ m_actions, "scroll_left" );
+ new KAction( i18n("Scroll Right"), Key_Right,
+ this, SLOT( scrollRight() ),
+ m_actions, "scroll_right" );
+ // --------
+ new KAction( i18n("Pause Slideshow"), Key_P,
+ this, SLOT( pauseSlideShow() ),
+ m_actions, "kuick_slideshow_pause" );
+
+ KAction *fullscreenAction = KStdAction::fullScreen(this, SLOT( toggleFullscreen() ), m_actions, 0 );
+
+ KAction *reloadAction = new KAction( i18n("Reload Image"), KStdAccel::shortcut(KStdAccel::Reload),
+ this, SLOT( reload() ),
+ m_actions, "reload_image" );
+
+ new KAction( i18n("Properties"), ALT + Key_Return,
+ this, SLOT( slotProperties() ),
+ m_actions, "properties" );
+
+ m_actions->readShortcutSettings();
+
+ // Unfortunately there is no KAction::setShortcutDefault() :-/
+ // so add Key_Return as fullscreen shortcut _after_ readShortcutSettings()
+ addAlternativeShortcut(fullscreenAction, Key_Return);
+ addAlternativeShortcut(reloadAction, Key_Enter);
+}
+
+void ImageWindow::addAlternativeShortcut(KAction *action, int key)
+{
+ KShortcut cut( action->shortcut() );
+ if (cut == action->shortcutDefault()) {
+ cut.append(KKey(key));
+ action->setShortcut(cut);
+ }
+}
+
+void ImageWindow::showWindow()
+{
+ if ( myIsFullscreen )
+ showFullScreen();
+ else
+ showNormal();
+}
+
+void ImageWindow::setFullscreen( bool enable )
+{
+ xpos = 0; ypos = 0;
+
+// if ( enable && !myIsFullscreen ) { // set Fullscreen
+// showFullScreen();
+// }
+// else if ( !enable && myIsFullscreen ) { // go into window mode
+// showNormal();
+// }
+
+ myIsFullscreen = enable;
+// centerImage(); // ### really necessary (multihead!)
+}
+
+
+void ImageWindow::updateGeometry( int imWidth, int imHeight )
+{
+// qDebug("::updateGeometry: %i, %i", imWidth, imHeight);
+ // XMoveWindow( x11Display(), win, 0, 0 );
+ XResizeWindow( x11Display(), win, imWidth, imHeight );
+
+ if ( imWidth != width() || imHeight != height() ) {
+ if ( myIsFullscreen ) {
+ centerImage();
+ }
+ else { // window mode
+ // XMoveWindow( x11Display(), win, 0, 0 );
+ resizeOptimal( imWidth, imHeight ); // also centers the image
+ }
+ }
+ else { // image size == widget size
+ xpos = 0; ypos = 0;
+ XMoveWindow( x11Display(), win, 0, 0 );
+ }
+
+ updateCursor();
+
+ QString caption = i18n( "Filename (Imagewidth x Imageheight)",
+ "%3 (%1 x %2)" );
+ caption = caption.arg( m_kuim->originalWidth() ).
+ arg( m_kuim->originalHeight() ).arg( m_kuim->url().prettyURL() );
+ setCaption( kapp->makeStdCaption( caption ) );
+}
+
+
+void ImageWindow::centerImage()
+{
+ int w, h;
+ if ( myIsFullscreen )
+ {
+ QRect desktopRect = KGlobalSettings::desktopGeometry( this );
+ w = desktopRect.width();
+ h = desktopRect.height();
+ }
+ else
+ {
+ w = width();
+ h = height();
+ }
+
+ xpos = w/2 - imageWidth()/2;
+ ypos = h/2 - imageHeight()/2;
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+
+ // Modified by Evan for his Multi-Head (2 screens)
+ // This should center on the first head
+// if ( myIsFullscreen && m_numHeads > 1 && ((m_numHeads % 2) == 0) )
+// xpos = ((width()/m_numHeads) / 2) - imageWidth()/2;
+// else
+// xpos = width()/2 - imageWidth()/2;
+
+// ypos = height()/2 - imageHeight()/2;
+// XMoveWindow( x11Display(), win, xpos, ypos );
+}
+
+
+void ImageWindow::scrollImage( int x, int y, bool restrict )
+{
+ xpos += x;
+ ypos += y;
+
+ int cwlocal = width();
+ int chlocal = height();
+
+ int iw = imageWidth();
+ int ih = imageHeight();
+
+ if ( myIsFullscreen || width() > desktopWidth() )
+ cwlocal = desktopWidth();
+
+ if ( myIsFullscreen || height() > desktopHeight() )
+ chlocal = desktopHeight();
+
+ if ( restrict ) { // don't allow scrolling in certain cases
+ if ( x != 0 ) { // restrict x-movement
+ if ( iw <= cwlocal )
+ xpos -= x; // restore previous position
+ else if ( (xpos <= 0) && (xpos + iw <= cwlocal) )
+ xpos = cwlocal - iw;
+ else if ( (xpos + iw >= cwlocal) && xpos >= 0 )
+ xpos = 0;
+ }
+
+ if ( y != 0 ) { // restrict y-movement
+ if ( ih <= chlocal )
+ ypos -= y;
+ else if ( (ypos <= 0) && (ypos + ih <= chlocal) )
+ ypos = chlocal - ih;
+ else if ( (ypos + ih >= chlocal) && ypos >= 0 )
+ ypos = 0;
+ }
+ }
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+ XClearArea( x11Display(), win, xpos, ypos, iw, ih, false );
+ showImage();
+}
+
+
+// image loading performs:
+// ---------------------
+// loadImageInternal();
+// reset image mods
+// load image from disk / get from cache
+// loaded(); // apply modifications, scale
+// render pixmap
+//
+// updateWidget();
+// XUnmapWindow();
+// XSetWindowBackgroundPixmap()
+// resize window to fit image size, center image
+// XClearWindow(); // repaint
+// XMapWindow(), XSync();
+//
+bool ImageWindow::showNextImage( const KURL& url )
+{
+ KuickFile *file = FileCache::self()->getFile( url );
+ switch ( file->waitForDownload( this ) ) {
+ case KuickFile::ERROR:
+ {
+ QString tmp = i18n("Unable to download the image from %1.").arg(url.prettyURL());
+ emit sigImageError( file, tmp );
+ return false;
+ }
+ case KuickFile::CANCELED:
+ return false; // just abort, no error message
+ default:
+ break; // go on...
+ }
+
+ return showNextImage( file );
+}
+
+bool ImageWindow::showNextImage( KuickFile *file )
+{
+ if ( !loadImage( file ) ) {
+ QString tmp = i18n("Unable to load the image %1.\n"
+ "Perhaps the file format is unsupported or "
+ "your Imlib is not installed properly.").arg(file->url().prettyURL());
+ emit sigImageError( file, tmp );
+ return false;
+ }
+
+ else {
+ // updateWidget( true ); // already called from loadImage()
+ if ( !isVisible() )
+ showWindow();
+
+ showImage();
+ return true;
+ }
+}
+
+void ImageWindow::reload()
+{
+ showNextImage( currentFile() );
+}
+
+void ImageWindow::pauseSlideShow()
+{
+ emit pauseSlideShowSignal();
+}
+
+void ImageWindow::addBrightness( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.brightness - ImlibOffset;
+ setBrightness( oldValue + (idata->brightnessFactor * (int) factor) );
+}
+
+void ImageWindow::addContrast( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.contrast - ImlibOffset;
+ setContrast( oldValue + (idata->contrastFactor * (int) factor) );
+}
+
+void ImageWindow::addGamma( int factor )
+{
+ if ( factor == 0 )
+ return;
+
+ int oldValue = mod.gamma - ImlibOffset;
+ setGamma( oldValue + (idata->gammaFactor * (int) factor) );
+}
+
+
+////////////
+////
+// slots for keyboard/popupmenu actions
+
+
+void ImageWindow::scrollUp()
+{
+ scrollImage( 0, 20 * kdata->scrollSteps );
+}
+
+void ImageWindow::scrollDown()
+{
+ scrollImage( 0, - 20 * kdata->scrollSteps );
+}
+
+void ImageWindow::scrollLeft()
+{
+ scrollImage( 20 * kdata->scrollSteps, 0 );
+}
+
+void ImageWindow::scrollRight()
+{
+ scrollImage( - 20 * kdata->scrollSteps, 0 );
+}
+
+///
+
+void ImageWindow::zoomIn()
+{
+ zoomImage( kdata->zoomSteps );
+}
+
+void ImageWindow::zoomOut()
+{
+ Q_ASSERT( kdata->zoomSteps != 0 );
+ zoomImage( 1.0 / kdata->zoomSteps );
+}
+
+///
+
+void ImageWindow::moreBrightness()
+{
+ addBrightness( kdata->brightnessSteps );
+}
+
+void ImageWindow::moreContrast()
+{
+ addContrast( kdata->contrastSteps );
+}
+
+void ImageWindow::moreGamma()
+{
+ addGamma( kdata->gammaSteps );
+}
+
+
+void ImageWindow::lessBrightness()
+{
+ addBrightness( - kdata->brightnessSteps );
+}
+
+void ImageWindow::lessContrast()
+{
+ addContrast( - kdata->contrastSteps );
+}
+
+void ImageWindow::lessGamma()
+{
+ addGamma( - kdata->gammaSteps );
+}
+
+void ImageWindow::imageDelete()
+{
+ emit deleteImage(this);
+}
+
+void ImageWindow::imageTrash()
+{
+ emit trashImage(this);
+}
+
+///
+
+
+
+
+/////////////
+////
+// event handlers
+
+void ImageWindow::wheelEvent( QWheelEvent *e )
+{
+ e->accept();
+ static const int WHEEL_DELTA = 120;
+ int delta = e->delta();
+
+ if ( delta == 0 )
+ return;
+
+ int steps = delta / WHEEL_DELTA;
+ emit requestImage( this, -steps );
+}
+
+void ImageWindow::keyPressEvent( QKeyEvent *e )
+{
+ uint key = e->key();
+
+ if ( key == Key_Shift )
+ updateCursor( ZoomCursor );
+
+ if ( key == Key_Escape || KStdAccel::close().contains( KKey( e ) ) )
+ close( true );
+ else if ( KStdAccel::save().contains( KKey( e ) ) )
+ saveImage();
+
+ else {
+ e->ignore();
+ return;
+ }
+
+ e->accept();
+}
+
+void ImageWindow::keyReleaseEvent( QKeyEvent *e )
+{
+ if ( e->state() & ShiftButton ) { // Shift-key released
+ updateCursor();
+ if ( transWidget ) {
+ delete transWidget;
+ transWidget = 0L;
+ }
+ }
+
+ e->accept();
+}
+
+void ImageWindow::mousePressEvent( QMouseEvent *e )
+{
+ xmove = e->x(); // for moving the image with the mouse
+ ymove = e->y();
+
+ xzoom = xmove; // for zooming with the mouse
+ yzoom = ymove;
+
+ xposPress = xmove;
+ yposPress = ymove;
+
+ if ( e->button() == LeftButton ) {
+ if ( e->state() & ShiftButton )
+ updateCursor( ZoomCursor );
+ else
+ updateCursor( MoveCursor );
+ }
+
+ ImlibWidget::mousePressEvent( e );
+}
+
+void ImageWindow::contextMenuEvent( QContextMenuEvent *e )
+{
+ e->accept();
+
+ if ( !viewerMenu )
+ setPopupMenu();
+
+ viewerMenu->popup( e->globalPos() );
+}
+
+void ImageWindow::updateCursor( KuickCursor cursor )
+{
+ switch ( cursor )
+ {
+ case ZoomCursor:
+ setCursor( arrowCursor ); // need a magnify-cursor
+ break;
+ case MoveCursor:
+ setCursor( *s_handCursor );
+ break;
+ case DefaultCursor:
+ default:
+ if ( isCursorHidden() )
+ return;
+
+ if ( imageWidth() > width() || imageHeight() > height() )
+ setCursor( *s_handCursor );
+ else
+ setCursor( arrowCursor );
+ break;
+ }
+}
+
+void ImageWindow::mouseMoveEvent( QMouseEvent *e )
+{
+ if ( !(e->state() & LeftButton) ) { // only handle LeftButton actions
+ return;
+ }
+
+ if ( e->state() & ShiftButton ) {
+
+ if ( !transWidget ) {
+ transWidget = new QWidget( this );
+ transWidget->setGeometry( 0, 0, width(), height() );
+ transWidget->setBackgroundMode( NoBackground );
+ }
+
+ transWidget->hide();
+ QPainter p( transWidget );
+ // really required?
+ p.eraseRect( transWidget->rect() );
+ transWidget->show();
+ qApp->processOneEvent();
+
+ int width = e->x() - xposPress;
+ int height = e->y() - yposPress;
+
+ if ( width < 0 ) {
+ width = abs( width );
+ xzoom = e->x();
+ }
+
+ if ( height < 0 ) {
+ height = abs( height );
+ yzoom = e->y();
+ }
+
+ QPen pen( Qt::white, 1, DashLine );
+ p.setPen( pen ); // for drawing white dashed line
+ p.drawRect( xzoom, yzoom, width, height );
+ p.setPen( DotLine ); // defaults to black dotted line pen
+ p.drawRect( xzoom, yzoom, width, height );
+ p.flush();
+ }
+
+ else { // move the image
+ // scrolling with mouse
+ uint xtmp = e->x();
+ uint ytmp = e->y();
+ scrollImage( xtmp - xmove, ytmp - ymove );
+ xmove = xtmp;
+ ymove = ytmp;
+ }
+}
+
+void ImageWindow::mouseReleaseEvent( QMouseEvent *e )
+{
+ updateCursor();
+
+ if ( transWidget ) {
+ // destroy the transparent widget, used for showing the rectangle (zoom)
+ delete transWidget;
+ transWidget = 0L;
+ }
+
+ // only proceed if shift-Key is still pressed
+ if ( !(e->button() == LeftButton && e->state() & ShiftButton) )
+ return;
+
+ int neww, newh, topX, topY, botX, botY;
+ float factor, factorx, factory;
+
+ // zoom into the selected area
+ uint x = e->x();
+ uint y = e->y();
+
+ if ( xposPress == x || yposPress == y )
+ return;
+
+ if ( xposPress > x ) {
+ topX = x;
+ botX = xposPress;
+ }
+ else {
+ topX = xposPress;
+ botX = x;
+ }
+
+ if ( yposPress > y ) {
+ topY = y;
+ botY = yposPress;
+ }
+ else {
+ topY = yposPress;
+ botY = y;
+ }
+
+ neww = botX - topX;
+ newh = botY - topY;
+
+ factorx = ((float) width() / (float) neww);
+ factory = ((float) height() / (float) newh);
+
+ if ( factorx < factory ) // use the smaller factor
+ factor = factorx;
+ else factor = factory;
+
+ uint w = 0; // shut up compiler!
+ uint h = 0;
+ w = (uint) ( factor * (float) imageWidth() );
+ h = (uint) ( factor * (float) imageHeight() );
+
+ if ( !canZoomTo( w, h ) )
+ return;
+
+ int xtmp = - (int) (factor * abs(xpos - topX) );
+ int ytmp = - (int) (factor * abs(ypos - topY) );
+
+ // if image has different ratio (width()/height()), center it
+ int xcenter = (width() - (int) (neww * factor)) / 2;
+ int ycenter = (height() - (int) (newh * factor)) / 2;
+
+ xtmp += xcenter;
+ ytmp += ycenter;
+
+ m_kuim->resize( w, h, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+ XResizeWindow( x11Display(), win, w, h );
+ updateWidget( false );
+
+ xpos = xtmp; ypos = ytmp;
+
+ XMoveWindow( x11Display(), win, xpos, ypos );
+ scrollImage( 1, 1, true ); // unrestricted scrolling
+}
+
+
+void ImageWindow::focusInEvent( QFocusEvent *ev )
+{
+ ImlibWidget::focusInEvent( ev );
+ emit sigFocusWindow( this );
+}
+
+
+void ImageWindow::resizeEvent( QResizeEvent *e )
+{
+ ImlibWidget::resizeEvent( e );
+
+ centerImage();
+ updateCursor();
+}
+
+
+void ImageWindow::dragEnterEvent( QDragEnterEvent *e )
+{
+ // if ( e->provides( "image/*" ) ) // can't do this right now with Imlib
+ if ( e->provides( "text/uri-list" ) )
+ e->accept();
+ else
+ e->ignore();
+}
+
+
+void ImageWindow::dropEvent( QDropEvent *e )
+{
+ // FIXME - only preliminary drop-support for now
+ KURL::List list;
+ if ( KURLDrag::decode( e, list ) && !list.isEmpty()) {
+ QString tmpFile;
+ const KURL &url = list.first();
+ if (KIO::NetAccess::download( url, tmpFile, this ) )
+ {
+ loadImage( tmpFile );
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+ updateWidget();
+ e->accept();
+ }
+ else
+ e->ignore();
+}
+
+
+////////////////////
+/////////
+// misc stuff
+
+void ImageWindow::setPopupMenu()
+{
+ viewerMenu = new QPopupMenu( this );
+
+ m_actions->action("next_image")->plug( viewerMenu );
+ m_actions->action("previous_image")->plug( viewerMenu );
+ viewerMenu->insertSeparator();
+
+ brightnessMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_brightness")->plug(brightnessMenu);
+ m_actions->action("less_brightness")->plug(brightnessMenu);
+
+ contrastMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_contrast")->plug(contrastMenu);
+ m_actions->action("less_contrast")->plug(contrastMenu);
+
+ gammaMenu = new QPopupMenu( viewerMenu );
+ m_actions->action("more_gamma")->plug(gammaMenu);
+ m_actions->action("less_gamma")->plug(gammaMenu);
+
+ m_actions->action("zoom_in")->plug( viewerMenu );
+ m_actions->action("zoom_out")->plug( viewerMenu );
+ m_actions->action("original_size")->plug( viewerMenu );
+ m_actions->action("maximize")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("rotate90")->plug( viewerMenu );
+ m_actions->action("rotate180")->plug( viewerMenu );
+ m_actions->action("rotate270")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("flip_vertically")->plug( viewerMenu );
+ m_actions->action("flip_horicontally")->plug( viewerMenu );
+ viewerMenu->insertSeparator();
+ viewerMenu->insertItem( i18n("Brightness"), brightnessMenu );
+ viewerMenu->insertItem( i18n("Contrast"), contrastMenu );
+ viewerMenu->insertItem( i18n("Gamma"), gammaMenu );
+ viewerMenu->insertSeparator();
+
+ m_actions->action("delete_image")->plug( viewerMenu );
+ m_actions->action("print_image")->plug( viewerMenu );
+ m_actions->action("save_image_as")->plug( viewerMenu );
+ m_actions->action("properties")->plug( viewerMenu );
+
+ viewerMenu->insertSeparator();
+ m_actions->action("close_image")->plug( viewerMenu );
+}
+
+void ImageWindow::printImage()
+{
+ if ( !m_kuim )
+ return;
+
+ if ( !Printing::printImage( *this, this ) )
+ {
+ KMessageBox::sorry( this, i18n("Unable to print the image."),
+ i18n("Printing Failed") );
+ }
+}
+
+void ImageWindow::saveImage()
+{
+ if ( !m_kuim )
+ return;
+
+ KuickData tmp;
+ QCheckBox *keepSize = new QCheckBox( i18n("Keep original image size"), 0L);
+ keepSize->setChecked( true );
+ KFileDialog dlg( m_saveDirectory, tmp.fileFilter, this, "filedialog", true
+#if KDE_VERSION >= 310
+ ,keepSize
+#endif
+ );
+
+ QString selection = m_saveDirectory.isEmpty() ?
+ m_kuim->url().url() :
+ m_kuim->url().fileName();
+ dlg.setOperationMode( KFileDialog::Saving );
+ dlg.setMode( KFile::File );
+ dlg.setSelection( selection );
+ dlg.setCaption( i18n("Save As") );
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ KURL url = dlg.selectedURL();
+ if ( url.isValid() )
+ {
+ if ( !saveImage( url, keepSize->isChecked() ) )
+ {
+ QString tmp = i18n("Couldn't save the file.\n"
+ "Perhaps the disk is full, or you don't "
+ "have write permission to the file.");
+ KMessageBox::sorry( this, tmp, i18n("File Saving Failed"));
+ }
+ else
+ {
+ if ( url.equals( m_kuim->url() )) {
+ Imlib_apply_modifiers_to_rgb( id, m_kuim->imlibImage() );
+ }
+ }
+ }
+ }
+
+ QString lastDir = dlg.baseURL().path(+1);
+ if ( lastDir != m_saveDirectory )
+ m_saveDirectory = lastDir;
+
+#if KDE_VERSION < 310
+ delete keepSize;
+#endif
+}
+
+bool ImageWindow::saveImage( const KURL& dest, bool keepOriginalSize )
+{
+ int w = keepOriginalSize ? m_kuim->originalWidth() : m_kuim->width();
+ int h = keepOriginalSize ? m_kuim->originalHeight() : m_kuim->height();
+ if ( m_kuim->absRotation() == ROT_90 || m_kuim->absRotation() == ROT_270 )
+ qSwap( w, h );
+
+ ImlibImage *saveIm = Imlib_clone_scaled_image( id, m_kuim->imlibImage(),
+ w, h );
+ bool success = false;
+
+ QString saveFile;
+ if ( dest.isLocalFile() )
+ saveFile = dest.path();
+ else
+ {
+ QString extension = QFileInfo( dest.fileName() ).extension();
+ if ( !extension.isEmpty() )
+ extension.prepend( '.' );
+
+ KTempFile tmpFile( QString::null, extension );
+ if ( tmpFile.status() != 0 )
+ return false;
+ tmpFile.close();
+ if ( tmpFile.status() != 0 )
+ return false;
+ saveFile = tmpFile.name();
+ }
+
+ if ( saveIm )
+ {
+ Imlib_apply_modifiers_to_rgb( id, saveIm );
+ success = Imlib_save_image( id, saveIm,
+ QFile::encodeName( saveFile ).data(),
+ NULL );
+ if ( success && !dest.isLocalFile() )
+ {
+ if ( isFullscreen() )
+ toggleFullscreen(); // otherwise upload window would block us invisibly
+ success = KIO::NetAccess::upload( saveFile, dest, const_cast<ImageWindow*>( this ) );
+ }
+
+ Imlib_kill_image( id, saveIm );
+ }
+
+ return success;
+}
+
+void ImageWindow::toggleFullscreen()
+{
+ setFullscreen( !myIsFullscreen );
+ showWindow();
+}
+
+void ImageWindow::loaded( KuickImage *kuim )
+{
+ if ( !kdata->isModsEnabled ) {
+ // ### BUG: should be "restorePreviousSize"
+ kuim->restoreOriginalSize();
+ }
+ else
+ {
+ autoRotate( kuim );
+ autoScale( kuim );
+ }
+}
+
+// upscale/downscale depending on configuration
+void ImageWindow::autoScale( KuickImage *kuim )
+{
+ int newW = kuim->originalWidth();
+ int newH = kuim->originalHeight();
+
+ QSize s = maxImageSize();
+ int mw = s.width();
+ int mh = s.height();
+
+ if ( kuim->absRotation() == ROT_90 || kuim->absRotation() == ROT_270 )
+ qSwap( newW, newH );
+
+ bool doIt = false;
+
+ if ( kdata->upScale )
+ {
+ if ( (newW < mw) && (newH < mh) )
+ {
+ doIt = true;
+
+ float ratio1, ratio2;
+ int maxUpScale = kdata->maxUpScale;
+
+ ratio1 = (float) mw / (float) newW;
+ ratio2 = (float) mh / (float) newH;
+ ratio1 = (ratio1 < ratio2) ? ratio1 : ratio2;
+ if ( maxUpScale > 0 )
+ ratio1 = (ratio1 < maxUpScale) ? ratio1 : maxUpScale;
+ newH = (int) ((float) newH * ratio1);
+ newW = (int) ((float) newW * ratio1);
+ }
+ }
+
+ if ( kdata->downScale )
+ {
+ // eventually set width and height to the best/max possible screen size
+ if ( (newW > mw) || (newH > mh) )
+ {
+ doIt = true;
+
+ if ( newW > mw )
+ {
+ float ratio = (float) newW / (float) newH;
+ newW = mw;
+ newH = (int) ((float) newW / ratio);
+ }
+
+ // the previously calculated "h" might be larger than screen
+ if ( newH > mh ) {
+ float ratio = (float) newW / (float) newH;
+ newH = mh;
+ newW = (int) ((float) newH * ratio);
+ }
+ }
+ }
+
+ if ( doIt )
+ kuim->resize( newW, newH, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+}
+
+// only called when kdata->isModsEnabled is true
+bool ImageWindow::autoRotate( KuickImage *kuim )
+{
+ if ( kdata->autoRotation && ImlibWidget::autoRotate( kuim ) )
+ return true;
+
+ else // rotation by metadata not available or not configured
+ {
+ // only apply default mods to newly loaded images
+
+ // ### actually we should have a dirty flag ("neverManuallyFlipped")
+ if ( kuim->flipMode() == FlipNone )
+ {
+ int flipMode = 0;
+ if ( kdata->flipVertically )
+ flipMode |= FlipVertical;
+ if ( kdata->flipHorizontally )
+ flipMode |= FlipHorizontal;
+
+ kuim->flipAbs( flipMode );
+ }
+
+ if ( kuim->absRotation() == ROT_0 )
+ kuim->rotateAbs( kdata->rotation );
+ }
+
+ return true;
+}
+
+int ImageWindow::desktopWidth( bool totalScreen ) const
+{
+ if ( myIsFullscreen || totalScreen )
+ {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).width();
+ } else
+ return Kuick::workArea().width();
+}
+
+
+int ImageWindow::desktopHeight( bool totalScreen ) const
+{
+ if ( myIsFullscreen || totalScreen ) {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).height();
+ } else {
+ return Kuick::workArea().height();
+ }
+}
+
+QSize ImageWindow::maxImageSize() const
+{
+ if ( myIsFullscreen ) {
+ return KGlobalSettings::desktopGeometry(topLevelWidget()).size();
+ }
+ else {
+ return Kuick::workArea().size() - Kuick::frameSize( winId() );
+ }
+}
+
+void ImageWindow::resizeOptimal( int w, int h )
+{
+ QSize s = maxImageSize();
+ int mw = s.width();
+ int mh = s.height();
+ int neww = (w >= mw) ? mw : w;
+ int newh = (h >= mh) ? mh : h;
+
+ if ( neww == width() && newh == height() )
+ centerImage();
+ else
+ resize( neww, newh ); // also centers the image
+}
+
+void ImageWindow::maximize()
+{
+ if ( !m_kuim )
+ return;
+
+ bool oldUpscale = kdata->upScale;
+ bool oldDownscale = kdata->downScale;
+
+ kdata->upScale = true;
+ kdata->downScale = true;
+
+ autoScale( m_kuim );
+ updateWidget( true );
+
+ if ( !myIsFullscreen )
+ resizeOptimal( imageWidth(), imageHeight() );
+
+ kdata->upScale = oldUpscale;
+ kdata->downScale = oldDownscale;
+}
+
+bool ImageWindow::canZoomTo( int newWidth, int newHeight )
+{
+ if ( !ImlibWidget::canZoomTo( newWidth, newHeight ) )
+ return false;
+
+ QSize desktopSize = KGlobalSettings::desktopGeometry(topLevelWidget()).size();
+
+ int desktopArea = desktopSize.width() * desktopSize.height();
+ int imageArea = newWidth * newHeight;
+
+ if ( imageArea > desktopArea * kdata->maxZoomFactor )
+ {
+ return KMessageBox::warningContinueCancel(
+ this,
+ i18n("You are about to view a very large image (%1 x %2 pixels), which can be very resource-consuming and even make your computer hang.\nDo you want to continue?")
+ .arg( newWidth ).arg( newHeight ),
+ QString::null,
+ KStdGuiItem::cont(),
+ "ImageWindow_confirm_very_large_window"
+ ) == KMessageBox::Continue;
+ }
+
+ return true;
+}
+
+void ImageWindow::rotated( KuickImage *kuim, int rotation )
+{
+ if ( !m_kuim )
+ return;
+
+ ImlibWidget::rotated( kuim, rotation );
+
+ if ( rotation == ROT_90 || rotation == ROT_270 )
+ autoScale( kuim ); // ### BUG: only autoScale when configured!
+}
+
+void ImageWindow::slotProperties()
+{
+ (void) new KPropertiesDialog( currentFile()->url(), this, "props dialog", true );
+}
+
+void ImageWindow::setBusyCursor()
+{
+ // avoid busy cursor in fullscreen mode
+ if ( !isFullscreen() )
+ ImlibWidget::setBusyCursor();
+}
+
+void ImageWindow::restoreCursor()
+{
+ // avoid busy cursor in fullscreen mode
+ if ( !isFullscreen() )
+ ImlibWidget::restoreCursor();
+}
+
+bool ImageWindow::isCursorHidden() const
+{
+ return cursor().shape() == Qt::BlankCursor;
+}
+
+#include "imagewindow.moc"
diff --git a/kuickshow/src/imagewindow.h b/kuickshow/src/imagewindow.h
new file mode 100644
index 00000000..4a823a0a
--- /dev/null
+++ b/kuickshow/src/imagewindow.h
@@ -0,0 +1,176 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMAGEWINDOW_H
+#define IMAGEWINDOW_H
+
+#include <qevent.h>
+
+#include <kaction.h>
+#include <kurl.h>
+
+#include "imlibwidget.h"
+
+class QCursor;
+class QPopupMenu;
+class QRect;
+class QString;
+class QTimer;
+class QWidget;
+
+class KuickFile;
+
+class ImageWindow : public ImlibWidget
+{
+ Q_OBJECT
+
+public:
+ ImageWindow( ImData *_idata, ImlibData *id, QWidget *parent=0,
+ const char *name=0 );
+ ImageWindow( ImData *_idata=0, QWidget *parent=0, const char *name=0 );
+
+ bool showNextImage( KuickFile * file );
+ bool showNextImage( const KURL& url );
+ void scrollImage( int, int, bool restrict=true );
+ void setFullscreen( bool );
+ bool isFullscreen() const { return myIsFullscreen; }
+
+ void addBrightness( int );
+ void addContrast( int );
+ void addGamma( int );
+
+ void updateActions();
+
+ KActionCollection * actionCollection() const { return m_actions; }
+
+ /**
+ * Resizes image to @p w, @p h, but takes into account the workarea, so
+ * it won't ever get a bigger size than the workarea.
+ */
+ void resizeOptimal( int w, int h );
+ void autoScale( KuickImage *kuim );
+ virtual bool autoRotate( KuickImage *kuim );
+
+ bool saveImage( const KURL& dest, bool keepOriginalSize );
+
+public slots:
+ void zoomIn();
+ void zoomOut();
+ void moreBrightness();
+ void lessBrightness();
+ void moreContrast();
+ void lessContrast();
+ void moreGamma();
+ void lessGamma();
+ void scrollUp();
+ void scrollDown();
+ void scrollLeft();
+ void scrollRight();
+ void printImage();
+ void toggleFullscreen();
+ void maximize();
+ void imageDelete();
+ void imageTrash();
+
+signals:
+ void sigFocusWindow( ImageWindow * );
+ // go advance images back/forth
+ void requestImage( ImageWindow *, int advance );
+ void deleteImage(ImageWindow *viewer);
+ void trashImage(ImageWindow *viewer);
+
+protected:
+ ~ImageWindow(); // deletes itself, just call close( true );
+
+ void init();
+ void centerImage();
+ void addAlternativeShortcut( KAction *action, int key );
+ virtual void updateGeometry( int imWidth, int imHeight );
+ virtual void loaded( KuickImage * );
+ virtual bool canZoomTo( int newWidth, int newHeight );
+ virtual void rotated( KuickImage *kuim, int rotation );
+
+ virtual void wheelEvent( QWheelEvent * );
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual void keyReleaseEvent( QKeyEvent * );
+ virtual void mousePressEvent( QMouseEvent * );
+ virtual void mouseReleaseEvent( QMouseEvent * );
+ virtual void mouseMoveEvent( QMouseEvent * );
+ virtual void focusInEvent( QFocusEvent * );
+ virtual void resizeEvent( QResizeEvent * );
+ virtual void dragEnterEvent( QDragEnterEvent * );
+ virtual void dropEvent( QDropEvent * );
+ virtual void contextMenuEvent( QContextMenuEvent * );
+
+ void showWindow();
+ enum KuickCursor { DefaultCursor = 0, ZoomCursor, MoveCursor };
+ void updateCursor( KuickCursor cursor = DefaultCursor );
+
+ // popupmenu entries
+ uint itemViewerZoomMax, itemViewerZoomOrig, itemViewerZoomIn;
+ uint itemViewerZoomOut, itemViewerFlipH, itemViewerProps;
+ uint itemRotate90, itemRotate180, itemRotate270;
+ uint itemViewerFlipV, itemViewerPrint;
+ uint itemViewerSave, itemViewerClose;
+ uint itemBrightnessPlus, itemBrightnessMinus;
+ uint itemContrastPlus, itemContrastMinus;
+ uint itemGammaPlus, itemGammaMinus;
+
+
+ uint xmove, ymove; // used for scrolling the image with the mouse
+ int xpos, ypos; // top left corner of the image
+ int xzoom, yzoom; // used for zooming the image with the mouse
+ uint xposPress, yposPress;
+
+
+ QPopupMenu *viewerMenu, *gammaMenu, *brightnessMenu, *contrastMenu;
+ QWidget *transWidget;
+
+
+protected slots:
+ void saveImage();
+ void slotRequestNext() { emit requestImage( this, +1 ); }
+ void slotRequestPrevious() { emit requestImage( this, -1 ); }
+ void reload();
+ void slotProperties();
+ void pauseSlideShow();
+ virtual void setBusyCursor();
+ virtual void restoreCursor();
+
+signals:
+ void pauseSlideShowSignal();
+
+private:
+ int desktopWidth( bool totalScreen = false ) const;
+ int desktopHeight( bool totalScreen = false ) const;
+ QSize maxImageSize() const;
+ void setupActions();
+ void setPopupMenu();
+ bool isCursorHidden() const;
+
+ bool myIsFullscreen;
+ int m_numHeads;
+ QString m_saveDirectory;
+
+ KActionCollection *m_actions;
+
+ static QCursor * s_handCursor;
+};
+
+
+#endif // IMAGEWINDOW_H
diff --git a/kuickshow/src/imdata.cpp b/kuickshow/src/imdata.cpp
new file mode 100644
index 00000000..a2e89283
--- /dev/null
+++ b/kuickshow/src/imdata.cpp
@@ -0,0 +1,92 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2001 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <kconfig.h>
+
+#include "imdata.h"
+
+
+ImData::ImData()
+{
+ ownPalette = true;
+ fastRemap = true;
+ fastRender = true;
+ dither16bit = false;
+ dither8bit = true;
+ smoothScale = false;
+ maxCache = 10240;
+
+ gamma = 0;
+ brightness = 0;
+ contrast = 0;
+
+ gammaFactor = 10;
+ brightnessFactor = 10;
+ contrastFactor = 10;
+}
+
+
+void ImData::load( KConfig *kc )
+{
+ ImData def;
+
+ kc->setGroup( "ImlibConfiguration" );
+
+ ownPalette = kc->readBoolEntry( "UseOwnPalette", def.ownPalette );
+ fastRemap = kc->readBoolEntry( "FastRemapping", def.fastRemap );
+ fastRender = kc->readBoolEntry( "FastRendering", def.fastRender );
+ dither16bit = kc->readBoolEntry( "Dither16Bit", def.dither16bit );
+ dither8bit = kc->readBoolEntry( "Dither8Bit", def.dither8bit );
+ smoothScale = kc->readBoolEntry( "SmoothScaling", def.smoothScale );
+
+ maxCache = kc->readNumEntry( "MaxCacheSize", 10240 );
+
+ gamma = kc->readNumEntry( "GammaDefault", 0 );
+ brightness = kc->readNumEntry( "BrightnessDefault", 0 );
+ contrast = kc->readNumEntry( "ContrastDefault", 0 );
+
+ gammaFactor = abs( kc->readNumEntry( "GammaFactor", 10 ) );
+ brightnessFactor = abs( kc->readNumEntry( "BrightnessFactor", 10 ) );
+ contrastFactor = abs( kc->readNumEntry( "ContrastFactor", 10 ) );
+}
+
+
+void ImData::save( KConfig *kc )
+{
+ kc->setGroup( "ImlibConfiguration" );
+
+ kc->writeEntry( "UseOwnPalette", ownPalette );
+ kc->writeEntry( "FastRemapping", fastRemap );
+ kc->writeEntry( "FastRendering", fastRender );
+ kc->writeEntry( "Dither16Bit", dither16bit );
+ kc->writeEntry( "Dither8Bit", dither8bit );
+ kc->writeEntry( "MaxCacheSize", maxCache );
+ kc->writeEntry( "SmoothScaling", smoothScale );
+
+ kc->writeEntry( "GammaDefault", gamma );
+ kc->writeEntry( "BrightnessDefault", brightness );
+ kc->writeEntry( "ContrastDefault", contrast );
+
+ kc->writeEntry( "GammaFactor", gammaFactor );
+ kc->writeEntry( "BrightnessFactor", brightnessFactor );
+ kc->writeEntry( "ContrastFactor", contrastFactor );
+
+ kc->sync();
+}
diff --git a/kuickshow/src/imdata.h b/kuickshow/src/imdata.h
new file mode 100644
index 00000000..c6dc6a5c
--- /dev/null
+++ b/kuickshow/src/imdata.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000,2001 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef IMBLIBCONFIG_H
+#define IMBLIBCONFIG_H
+
+class KConfig;
+class ImData
+{
+public:
+ ImData();
+ ~ImData() {};
+
+ void load( KConfig *kc );
+ void save( KConfig *kc );
+
+ // new stuff..........
+
+ int gamma;
+ int brightness;
+ int contrast;
+
+ // -----------------------
+
+ bool ownPalette :1;
+ bool fastRemap :1;
+ bool fastRender :1;
+ bool dither16bit :1;
+ bool dither8bit :1;
+ bool smoothScale :1;
+
+
+ uint gammaFactor;
+ uint brightnessFactor;
+ uint contrastFactor;
+
+ uint maxCache;
+
+};
+
+
+#endif
diff --git a/kuickshow/src/imlibwidget.cpp b/kuickshow/src/imlibwidget.cpp
new file mode 100644
index 00000000..5b5cb84b
--- /dev/null
+++ b/kuickshow/src/imlibwidget.cpp
@@ -0,0 +1,715 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "kuickdata.h"
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <qcolor.h>
+#include <qfile.h>
+#include <qglobal.h>
+#include <qimage.h>
+#include <qobject.h>
+#include <qpalette.h>
+
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kfilemetainfo.h>
+#include <kimageio.h>
+
+#include "filecache.h"
+#include "kuickfile.h"
+#include "kuickimage.h"
+#include "imlibwidget.h"
+
+const int ImlibWidget::ImlibOffset = 256;
+
+ImlibWidget::ImlibWidget( ImData *_idata, QWidget *parent, const char *name ) :
+ QWidget( parent, name, WDestructiveClose )
+{
+ idata = _idata;
+ deleteImData = false;
+ deleteImlibData = true;
+
+ if ( !idata ) { // if no imlib configuration was given, create one ourself
+ idata = new ImData;
+ deleteImData = true;
+ }
+
+ ImlibInitParams par;
+
+ // PARAMS_PALETTEOVERRIDE taken out because of segfault in imlib :o(
+ par.flags = ( PARAMS_REMAP | PARAMS_VISUALID |
+ PARAMS_FASTRENDER | PARAMS_HIQUALITY | PARAMS_DITHER |
+ PARAMS_IMAGECACHESIZE | PARAMS_PIXMAPCACHESIZE );
+
+ Visual* defaultvis = DefaultVisual(x11Display(), x11Screen());
+
+ par.paletteoverride = idata->ownPalette ? 1 : 0;
+ par.remap = idata->fastRemap ? 1 : 0;
+ par.fastrender = idata->fastRender ? 1 : 0;
+ par.hiquality = idata->dither16bit ? 1 : 0;
+ par.dither = idata->dither8bit ? 1 : 0;
+ par.visualid = defaultvis->visualid;
+ uint maxcache = idata->maxCache;
+
+ // 0 == no cache
+ par.imagecachesize = maxcache * 1024;
+ par.pixmapcachesize = maxcache * 1024;
+
+ id = Imlib_init_with_params( x11Display(), &par );
+
+ init();
+}
+
+
+ImlibWidget::ImlibWidget( ImData *_idata, ImlibData *_id, QWidget *parent,
+ const char *name )
+ : QWidget( parent, name, WDestructiveClose )
+{
+ id = _id;
+ idata = _idata;
+ deleteImData = false;
+ deleteImlibData = false;
+
+ if ( !idata ) {
+ idata = new ImData;
+ deleteImData = true;
+ }
+
+ init();
+}
+
+
+void ImlibWidget::init()
+{
+ int w = 1; // > 0 for XCreateWindow
+ int h = 1;
+ myBackgroundColor = Qt::black;
+ m_kuim = 0L;
+ m_kuickFile = 0L;
+
+ if ( !id )
+ qFatal("ImlibWidget: Imlib not initialized, aborting.");
+
+ setAutoRender( true );
+
+ setPalette( QPalette( myBackgroundColor ));
+ setBackgroundMode( PaletteBackground );
+
+ imageCache = new ImageCache( id, 4 ); // cache 4 images (FIXME?)
+ connect( imageCache, SIGNAL( sigBusy() ), SLOT( setBusyCursor() ));
+ connect( imageCache, SIGNAL( sigIdle() ), SLOT( restoreCursor() ));
+
+ win = XCreateSimpleWindow(x11Display(), winId(), 0,0,w,h,0,0,0);
+}
+
+ImlibWidget::~ImlibWidget()
+{
+ delete imageCache;
+ if ( deleteImlibData && id ) free ( id );
+ if ( win ) XDestroyWindow( x11Display(), win );
+ if ( deleteImData ) delete idata;
+}
+
+KURL ImlibWidget::url() const
+{
+ if ( m_kuickFile )
+ return m_kuickFile->url();
+
+ return KURL();
+}
+
+KuickFile * ImlibWidget::currentFile() const
+{
+ return m_kuickFile;
+}
+
+// tries to load "file" and returns the according KuickImage *
+// or 0L if unsuccessful
+// Note that the given file MUST already be downloaded prior to calling this function
+KuickImage * ImlibWidget::loadImageInternal( KuickFile * file )
+{
+ assert( file->isAvailable() );
+
+ // apply default image modifications
+ mod.brightness = idata->brightness + ImlibOffset;
+ mod.contrast = idata->contrast + ImlibOffset;
+ mod.gamma = idata->gamma + ImlibOffset;
+
+ KuickImage *kuim = imageCache->getKuimage( file, mod );
+ if ( !kuim ) {// couldn't load file, maybe corrupt or wrong format
+ kdWarning() << "ImlibWidget: can't load image " << file->url().prettyURL() << endl;
+ return 0L;
+ }
+
+ loaded( kuim ); // maybe upscale/downscale/rotate in subclasses
+
+ return kuim;
+}
+
+// overridden in subclass
+void ImlibWidget::loaded( KuickImage * )
+{
+}
+
+bool ImlibWidget::loadImage( const KURL& url )
+{
+ return loadImage( FileCache::self()->getFile( url ));
+}
+
+bool ImlibWidget::loadImage( KuickFile * file )
+{
+ if ( file->waitForDownload( this ) != KuickFile::OK)
+ return false;
+
+ KuickImage *kuim = loadImageInternal( file );
+ // FIXME - check everywhere if we have a kuim or not!
+
+ if ( kuim ) {
+ m_kuim = kuim;
+ autoUpdate( true ); // -> updateWidget() -> updateGeometry()
+ m_kuickFile = file;
+ return true;
+ }
+
+ return false;
+}
+
+
+bool ImlibWidget::cacheImage( const KURL& url )
+{
+// qDebug("cache image: %s", url.url().latin1());
+ KuickFile *file = FileCache::self()->getFile( url );
+ if ( file->isAvailable() )
+ return cacheImage( file );
+ else {
+ if ( !file->download() ) {
+ return false;
+ }
+ connect( file, SIGNAL( downloaded( KuickFile * )), SLOT( cacheImage( KuickFile * )) );
+ return true; // optimistic
+ }
+}
+
+bool ImlibWidget::cacheImage( KuickFile * file )
+{
+// qDebug("cache image: %s", file->url().url().latin1());
+ KuickImage *kuim = loadImageInternal( file );
+ if ( kuim ) {
+ kuim->renderPixmap();
+ return true;
+ }
+ return false;
+}
+
+
+void ImlibWidget::showImage()
+{
+ XMapWindow( x11Display(), win );
+ XSync( x11Display(), False );
+}
+
+
+// -256..256
+void ImlibWidget::setBrightness( int factor )
+{
+ mod.brightness = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+// -256..256
+void ImlibWidget::setContrast( int factor )
+{
+ mod.contrast = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+// -256..256
+void ImlibWidget::setGamma( int factor )
+{
+ mod.gamma = factor + ImlibOffset;
+ setImageModifier();
+
+ autoUpdate();
+}
+
+
+Rotation ImlibWidget::rotation() const
+{
+ return m_kuim ? m_kuim->absRotation() : ROT_0;
+}
+
+FlipMode ImlibWidget::flipMode() const
+{
+ return m_kuim ? m_kuim->flipMode() : FlipNone;
+}
+
+void ImlibWidget::zoomImage( float factor )
+{
+ if ( factor == 1 || factor == 0 || !m_kuim )
+ return;
+
+ int newWidth = (int) (factor * (float) m_kuim->width());
+ int newHeight = (int) (factor * (float) m_kuim->height());
+
+ if ( canZoomTo( newWidth, newHeight ) )
+ {
+ m_kuim->resize( newWidth, newHeight, idata->smoothScale ? KuickImage::SMOOTH : KuickImage::FAST );
+ autoUpdate( true );
+ }
+}
+
+bool ImlibWidget::canZoomTo( int newWidth, int newHeight )
+{
+ if ( newWidth <= 2 || newHeight <= 2 ) // minimum size for an image is 2x2 pixels
+ return false;
+
+ return true;
+}
+
+
+void ImlibWidget::showImageOriginalSize()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->restoreOriginalSize();
+ autoUpdate( true );
+
+ showImage();
+}
+
+bool ImlibWidget::autoRotate( KuickImage *kuim )
+{
+ KFileMetaInfo metadatas( kuim->file().localFile() );
+ if ( !metadatas.isValid() )
+ return false;
+
+ KFileMetaInfoItem metaitem = metadatas.item("Orientation");
+ if ( !metaitem.isValid()
+#if QT_VERSION >= 0x030100
+ || metaitem.value().isNull()
+#endif
+ )
+ return false;
+
+
+ switch ( metaitem.value().toInt() )
+ {
+ // Orientation:
+ // 1: normal
+ // 2: flipped horizontally
+ // 3: ROT 180
+ // 4: flipped vertically
+ // 5: ROT 90 -> flip horizontally
+ // 6: ROT 90
+ // 7: ROT 90 -> flip vertically
+ // 8: ROT 270
+
+ case 1:
+ default:
+ kuim->rotateAbs( ROT_0 );
+ break;
+ case 2:
+ kuim->flipAbs( FlipHorizontal );
+ break;
+ case 3:
+ kuim->rotateAbs( ROT_180 );
+ break;
+ case 4:
+ kuim->flipAbs( FlipVertical );
+ break;
+ case 5:
+ kuim->rotateAbs( ROT_90 );
+ kuim->flipAbs( FlipHorizontal );
+ break;
+ case 6:
+ kuim->rotateAbs( ROT_90 );
+ break;
+ case 7:
+ kuim->rotateAbs( ROT_90 );
+ kuim->flipAbs( FlipVertical );
+ break;
+ case 8:
+ kuim->rotateAbs( ROT_270 );
+ break;
+ }
+
+ return true;
+}
+
+
+void ImlibWidget::setRotation( Rotation rot )
+{
+ if ( m_kuim )
+ {
+ if ( m_kuim->rotateAbs( rot ) )
+ autoUpdate( true );
+ }
+}
+
+
+// slots connected to Accels and popupmenu
+void ImlibWidget::rotate90()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_90 );
+ rotated( m_kuim, ROT_90 );
+ autoUpdate( true );
+}
+
+void ImlibWidget::rotate180()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_180 );
+ rotated( m_kuim, ROT_180 );
+ autoUpdate();
+}
+
+void ImlibWidget::rotate270()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->rotate( ROT_270 );
+ rotated( m_kuim, ROT_270 );
+ autoUpdate( true );
+}
+
+
+// should this go into a subclass?
+void ImlibWidget::flipHoriz()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->flip( FlipHorizontal );
+ autoUpdate();
+}
+
+void ImlibWidget::flipVert()
+{
+ if ( !m_kuim )
+ return;
+
+ m_kuim->flip( FlipVertical );
+ autoUpdate();
+}
+// end slots
+
+
+void ImlibWidget::setFlipMode( int mode )
+{
+ if ( !m_kuim )
+ return;
+
+ if ( m_kuim->flipAbs( mode ) )
+ autoUpdate();
+}
+
+
+void ImlibWidget::updateWidget( bool geometryUpdate )
+{
+ if ( !m_kuim )
+ return;
+
+// if ( geometryUpdate )
+// XUnmapWindow( x11Display(), win );// remove the old image -> no flicker
+
+ XSetWindowBackgroundPixmap( x11Display(), win, m_kuim->pixmap() );
+
+ if ( geometryUpdate )
+ updateGeometry( m_kuim->width(), m_kuim->height() );
+
+ XClearWindow( x11Display(), win );
+
+ showImage();
+}
+
+
+// here we just use the size of m_kuim, may be overridden in subclass
+void ImlibWidget::updateGeometry( int w, int h )
+{
+ XMoveWindow( x11Display(), win, 0, 0 ); // center?
+ XResizeWindow( x11Display(), win, w, h );
+ resize( w, h );
+}
+
+
+void ImlibWidget::closeEvent( QCloseEvent *e )
+{
+ e->accept();
+ QWidget::closeEvent( e );
+}
+
+
+void ImlibWidget::setBackgroundColor( const QColor& color )
+{
+ myBackgroundColor = color;
+ setPalette( QPalette( myBackgroundColor ));
+ repaint( false); // FIXME - false? necessary at all?
+}
+
+const QColor& ImlibWidget::backgroundColor() const
+{
+ return myBackgroundColor;
+}
+
+
+void ImlibWidget::setImageModifier()
+{
+ if ( !m_kuim )
+ return;
+
+ Imlib_set_image_modifier( id, m_kuim->imlibImage(), &mod );
+ m_kuim->setDirty( true );
+}
+
+int ImlibWidget::imageWidth() const
+{
+ return m_kuim ? m_kuim->width() : 0;
+}
+
+int ImlibWidget::imageHeight() const
+{
+ return m_kuim ? m_kuim->height() : 0;
+}
+
+void ImlibWidget::setBusyCursor()
+{
+ if ( ownCursor() )
+ m_oldCursor = cursor();
+ else
+ m_oldCursor = QCursor();
+
+ setCursor( KCursor::waitCursor() );
+}
+
+void ImlibWidget::restoreCursor()
+{
+ if ( cursor().shape() == KCursor::waitCursor().shape() ) // only if nobody changed the cursor in the meantime!
+ setCursor( m_oldCursor );
+}
+
+// Reparenting a widget in Qt in fact means destroying the old X window of the widget
+// and creating a new one. And since the X window used for the Imlib image is a child
+// of this widget's X window, destroying this widget's X window would mean also
+// destroying the Imlib image X window. Therefore it needs to be temporarily reparented
+// away and reparented back to the new X window.
+// Reparenting may happen e.g. when doing the old-style (non-NETWM) fullscreen changes.
+void ImlibWidget::reparent( QWidget* parent, WFlags f, const QPoint& p, bool showIt )
+{
+ XWindowAttributes attr;
+ XGetWindowAttributes( x11Display(), win, &attr );
+ XUnmapWindow( x11Display(), win );
+ XReparentWindow( x11Display(), win, attr.root, 0, 0 );
+ QWidget::reparent( parent, f, p, showIt );
+ XReparentWindow( x11Display(), win, winId(), attr.x, attr.y );
+ if( attr.map_state != IsUnmapped )
+ XMapWindow( x11Display(), win );
+}
+
+void ImlibWidget::rotated( KuickImage *, int )
+{
+}
+
+//----------
+
+
+// uhh ugly, we have two lists to map from filename to KuickImage :-/
+ImageCache::ImageCache( ImlibData *id, int maxImages )
+{
+ myId = id;
+ idleCount = 0;
+ myMaxImages = maxImages;
+ kuickList.setAutoDelete( true );
+ fileList.clear();
+ kuickList.clear();
+}
+
+
+ImageCache::~ImageCache()
+{
+ kuickList.clear();
+ fileList.clear();
+}
+
+
+void ImageCache::setMaxImages( int maxImages )
+{
+ myMaxImages = maxImages;
+ int count = kuickList.count();
+ while ( count > myMaxImages ) {
+ kuickList.removeLast();
+ fileList.remove( fileList.fromLast() );
+ count--;
+ }
+}
+
+void ImageCache::slotBusy()
+{
+ if ( idleCount == 0 )
+ emit sigBusy();
+
+ idleCount++;
+}
+
+void ImageCache::slotIdle()
+{
+ idleCount--;
+
+ if ( idleCount == 0 )
+ emit sigIdle();
+}
+
+
+KuickImage * ImageCache::getKuimage( KuickFile * file,
+ ImlibColorModifier mod )
+{
+ if ( !file )
+ return 0L;
+
+ assert( file->isAvailable() ); // debug build
+ if ( file->waitForDownload( 0L ) != KuickFile::OK ) // and for users
+ return 0L;
+
+ KuickImage *kuim = 0L;
+ int index = fileList.findIndex( file );
+ if ( index != -1 ) {
+ if ( index == 0 )
+ kuim = kuickList.at( 0 );
+
+ // need to reorder the lists, otherwise we might delete the current
+ // image when a new one is cached and the current one is the last!
+ else {
+ kuim = kuickList.take( index );
+ kuickList.insert( 0, kuim );
+ fileList.remove( file );
+ fileList.prepend( file );
+ }
+
+ return kuim;
+ }
+
+ if ( !kuim ) {
+ slotBusy();
+
+// #ifndef NDEBUG
+// struct timeval tms1, tms2;
+// gettimeofday( &tms1, NULL );
+// #endif
+
+ ImlibImage *im = Imlib_load_image( myId,
+ QFile::encodeName( file->localFile() ).data() );
+
+// #ifndef NDEBUG
+// gettimeofday( &tms2, NULL );
+// qDebug("*** LOADING image: %s, took %ld ms", file.latin1(),
+// (tms2.tv_usec - tms1.tv_usec)/1000);
+// #endif
+
+ slotIdle();
+ if ( !im ) {
+ slotBusy();
+ im = loadImageWithQt( file->localFile() );
+ slotIdle();
+ if ( !im )
+ return 0L;
+ }
+
+ Imlib_set_image_modifier( myId, im, &mod );
+ kuim = new KuickImage( file, im, myId );
+ connect( kuim, SIGNAL( startRendering() ), SLOT( slotBusy() ));
+ connect( kuim, SIGNAL( stoppedRendering() ), SLOT( slotIdle() ));
+
+ kuickList.insert( 0, kuim );
+ fileList.prepend( file );
+ }
+
+ if ( kuickList.count() > (uint) myMaxImages ) {
+// qDebug(":::: now removing from cache: %s", (*fileList.fromLast()).latin1());
+ kuickList.removeLast();
+ fileList.remove( fileList.fromLast() );
+ }
+
+ return kuim;
+}
+
+
+// Note: the returned image's filename will not be the real filename (which it usually
+// isn't anyway, according to Imlib's sources).
+ImlibImage * ImageCache::loadImageWithQt( const QString& fileName ) const
+{
+ kdDebug() << "Trying to load " << fileName << " with KImageIO..." << endl;
+
+ KImageIO::registerFormats();
+
+ QImage image( fileName );
+ if ( image.isNull() )
+ return 0L;
+ if ( image.depth() != 32 ) {
+ image.setAlphaBuffer(false);
+ image = image.convertDepth(32);
+
+ if ( image.isNull() )
+ return 0L;
+ }
+
+ // convert to 24 bpp (discard alpha)
+ int numPixels = image.width() * image.height();
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+ uchar *newData = newImageData;
+
+ int w = image.width();
+ int h = image.height();
+
+ for (int y = 0; y < h; y++) {
+ QRgb *scanLine = reinterpret_cast<QRgb *>( image.scanLine(y) );
+ for (int x = 0; x < w; x++) {
+ const QRgb& pixel = scanLine[x];
+ *(newData++) = qRed(pixel);
+ *(newData++) = qGreen(pixel);
+ *(newData++) = qBlue(pixel);
+ }
+ }
+
+ ImlibImage *im = Imlib_create_image_from_data( myId, newImageData, NULL,
+ image.width(), image.height() );
+
+ delete[] newImageData;
+
+ return im;
+}
+
+#include "imlibwidget.moc"
diff --git a/kuickshow/src/imlibwidget.h b/kuickshow/src/imlibwidget.h
new file mode 100644
index 00000000..5f6e89e1
--- /dev/null
+++ b/kuickshow/src/imlibwidget.h
@@ -0,0 +1,187 @@
+/****************************************************************************
+** $Id$
+**
+** ImlibWidget: maps an Xlib window with Imlib's contents on a QWidget
+**
+** Created : 98
+**
+** Copyright (C) 1998-2001 by Carsten Pfeiffer. All rights reserved.
+**
+****************************************************************************/
+
+#ifndef IMLIBWIDGET_H
+#define IMLIBWIDGET_H
+
+#include <qvariant.h>
+
+#include <qcursor.h>
+#include <qevent.h>
+#include <qptrlist.h>
+#include <qtimer.h>
+#include <qwidget.h>
+
+#include <kurl.h>
+
+// #include those AFTER Qt-includes!
+#include <Imlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+// #include <X11/extensions/shape.h>
+
+#include "imdata.h"
+#include "kuickdata.h"
+
+class KuickFile;
+class KuickImage;
+
+class ImageCache : public QObject
+{
+ Q_OBJECT
+
+public:
+ ImageCache( ImlibData *id, int maxImages=1 );
+ ~ImageCache();
+
+ void setMaxImages( int maxImages );
+ int maxImages() const { return myMaxImages; }
+
+ KuickImage * getKuimage( KuickFile * file, ImlibColorModifier );
+
+private:
+ ImlibImage * loadImageWithQt( const QString& filename ) const;
+
+ int myMaxImages;
+ QValueList<KuickFile*>fileList;
+ QPtrList<KuickImage> kuickList;
+ // QPtrList<ImlibImage> imList;
+ ImlibData * myId;
+ int idleCount;
+
+private slots:
+ void slotBusy();
+ void slotIdle();
+
+signals:
+ void sigBusy();
+ void sigIdle();
+
+};
+
+
+// ------------------------------------------
+
+class QColor;
+
+class ImlibWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+
+ ImlibWidget( ImData *_idata=0, QWidget *parent=0, const char *name=0 );
+ ImlibWidget( ImData *_idata, ImlibData *id, QWidget *parent=0,
+ const char *name=0 );
+ virtual ~ImlibWidget();
+
+ KURL url() const;
+ KuickFile * currentFile() const;
+ bool loadImage( KuickFile * file );
+ bool loadImage( const KURL& url );
+ bool cacheImage(const KURL& url );
+ void zoomImage( float );
+ void setBrightness( int );
+ void setContrast( int );
+ void setGamma( int );
+ void setRotation( Rotation );
+ void setFlipMode( int mode );
+
+ int brightness() const; // ### no impl!
+ int contrast() const; // ### no impl!
+ int gamma() const; // ### no impl!
+ Rotation rotation() const;
+ FlipMode flipMode() const;
+
+ int imageWidth() const;
+ int imageHeight() const;
+
+ void setAutoRender( bool enable ) { isAutoRendering = enable;}
+ bool isAutoRenderEnabled() const { return isAutoRendering; }
+ void setMaxImageCache( int );
+ int maxImageCache() const { return myMaxImageCache; }
+ const QColor& backgroundColor() const;
+ void setBackgroundColor( const QColor& );
+
+ /**
+ * @return true if auto-rotation is not possible, e.g. because no metadata
+ * about orientation is available
+ */
+ virtual bool autoRotate( KuickImage *kuim );
+
+ ImlibData* getImlibData() const { return id; }
+
+ virtual void reparent( QWidget* parent, WFlags f, const QPoint& p, bool showIt = FALSE );
+
+public slots:
+ void rotate90();
+ void rotate270();
+ void rotate180();
+ void flipHoriz();
+ void flipVert();
+ void showImageOriginalSize();
+ inline void updateImage() { updateWidget( true ); }
+
+
+protected:
+ KuickImage * loadImageInternal( KuickFile * file );
+ void showImage();
+ void setImageModifier();
+ void rotate( int );
+ void updateWidget( bool geometryUpdate=true );
+ virtual void updateGeometry( int width, int height );
+ virtual void loaded( KuickImage * );
+ virtual bool canZoomTo( int newWidth, int newHeight );
+ virtual void rotated( KuickImage *kuim, int rotation );
+
+ void closeEvent( QCloseEvent * );
+
+ inline void autoUpdate( bool geometryUpdate=false ) {
+ if ( isAutoRendering )
+ updateWidget( geometryUpdate );
+ }
+
+ bool stillResizing, deleteImData, deleteImlibData;
+ bool imlibModifierChanged;
+
+ KuickImage *m_kuim;
+ ImageCache *imageCache;
+ ImlibData *id;
+ ImData *idata;
+ Window win;
+ ImlibColorModifier mod;
+
+ KuickFile *m_kuickFile;
+ QCursor m_oldCursor;
+
+ static const int ImlibOffset;
+
+
+private:
+ void init();
+ bool isAutoRendering;
+ int myMaxImageCache;
+ QColor myBackgroundColor;
+
+
+protected slots:
+ bool cacheImage( KuickFile *file );
+ virtual void setBusyCursor();
+ virtual void restoreCursor();
+
+
+signals:
+ void sigImageError( const KuickFile * file, const QString& );
+
+};
+
+
+#endif
diff --git a/kuickshow/src/kuick.cpp b/kuickshow/src/kuick.cpp
new file mode 100644
index 00000000..43eadb50
--- /dev/null
+++ b/kuickshow/src/kuick.cpp
@@ -0,0 +1,4 @@
+#include "kuick.h"
+
+Kuick * Kuick::s_self = 0L;
+QSize Kuick::s_frameSize;
diff --git a/kuickshow/src/kuick.h b/kuickshow/src/kuick.h
new file mode 100644
index 00000000..bc86d5d2
--- /dev/null
+++ b/kuickshow/src/kuick.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000,2001,2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKGLOBALS_H
+#define KUICKGLOBALS_H
+
+#include <qrect.h>
+#include <qsize.h>
+
+#include <kwin.h>
+#include <kwinmodule.h>
+
+class Kuick
+{
+public:
+ static QRect workArea() {
+ return self()->winModule.workArea();
+ }
+
+ static QSize frameSize( WId win = 0L ) {
+ if ( win ) {
+ KWin::WindowInfo info = KWin::windowInfo(win, NET::WMKDEFrameStrut | NET::WMGeometry);
+ int wborder = info.frameGeometry().width() - info.geometry().width();
+ int hborder = info.frameGeometry().height() - info.geometry().height();
+
+ if ( wborder || hborder ) { // we get a 0,0 border when not shown
+ s_frameSize.setWidth( wborder );
+ s_frameSize.setHeight( hborder );
+ }
+ }
+
+ if ( !s_frameSize.isValid() )
+ return QSize( 0, 0 );
+
+ return s_frameSize;
+ }
+
+ static Kuick * self() {
+ if ( !s_self ) {
+ s_self = new Kuick;
+ }
+ return s_self;
+ }
+
+ KWinModule winModule;
+
+private:
+ Kuick() {}
+ static Kuick * s_self;
+
+ static QSize s_frameSize;
+};
+
+
+#endif // KUICKGLOBALS_H
diff --git a/kuickshow/src/kuickconfigdlg.cpp b/kuickshow/src/kuickconfigdlg.cpp
new file mode 100644
index 00000000..6ece8883
--- /dev/null
+++ b/kuickshow/src/kuickconfigdlg.cpp
@@ -0,0 +1,99 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifdef index
+#undef index
+#endif
+#include "kuickconfigdlg.h"
+
+#include <qkeycode.h>
+#include <qvbox.h>
+
+#include <kaccel.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include "imagewindow.h"
+#include "defaultswidget.h"
+#include "generalwidget.h"
+#include "slideshowwidget.h"
+
+#include "kuickdata.h"
+
+
+KuickConfigDialog::KuickConfigDialog( KActionCollection *_coll, QWidget *parent,
+ const char *name, bool modal )
+ : KDialogBase( Tabbed, i18n("Configure"),
+ Help | Default | Ok | Apply | Cancel, Ok,
+ parent, name, modal )
+{
+ coll = _coll;
+ QVBox *box = addVBoxPage( i18n("&General") );
+ generalWidget = new GeneralWidget( box, "general widget" );
+
+ box = addVBoxPage( i18n("&Modifications") );
+ defaultsWidget = new DefaultsWidget( box, "defaults widget" );
+
+ box = addVBoxPage( i18n("&Slideshow") );
+ slideshowWidget = new SlideShowWidget( box, "slideshow widget" );
+
+ box = addVBoxPage( i18n("&Viewer Shortcuts") );
+
+ imageWindow = new ImageWindow(); // just to get the accel...
+ imageWindow->hide();
+
+ imageKeyChooser = new KKeyChooser( imageWindow->actionCollection(), box );
+
+ box = addVBoxPage( i18n("Bro&wser Shortcuts") );
+ browserKeyChooser = new KKeyChooser( coll, box );
+
+ connect( this, SIGNAL( defaultClicked() ), SLOT( resetDefaults() ));
+}
+
+KuickConfigDialog::~KuickConfigDialog()
+{
+ imageWindow->close( true );
+}
+
+void KuickConfigDialog::applyConfig()
+{
+ generalWidget->applySettings( *kdata );
+ defaultsWidget->applySettings( *kdata );
+ slideshowWidget->applySettings( *kdata );
+
+ imageKeyChooser->save();
+ browserKeyChooser->save();
+
+ KGlobal::config()->sync();
+}
+
+
+void KuickConfigDialog::resetDefaults()
+{
+ KuickData data;
+ generalWidget->loadSettings( data );
+ defaultsWidget->loadSettings( data );
+ slideshowWidget->loadSettings( data );
+
+ imageKeyChooser->allDefault();
+ browserKeyChooser->allDefault();
+}
+
+#include "kuickconfigdlg.moc"
diff --git a/kuickshow/src/kuickconfigdlg.h b/kuickshow/src/kuickconfigdlg.h
new file mode 100644
index 00000000..884d91dc
--- /dev/null
+++ b/kuickshow/src/kuickconfigdlg.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKCONFIGDLG_H
+#define KUICKCONFIGDLG_H
+
+#include <qevent.h>
+
+#include <kkeydialog.h>
+
+#include <kdialogbase.h>
+
+class GeneralWidget;
+class DefaultsWidget;
+class SlideShowWidget;
+class ImageWindow;
+
+class KuickConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KuickConfigDialog( KActionCollection *coll, QWidget *parent=0,
+ const char *name=0, bool modal=true);
+ ~KuickConfigDialog();
+
+ void applyConfig();
+
+private slots:
+ void resetDefaults();
+
+private:
+ DefaultsWidget *defaultsWidget;
+ GeneralWidget *generalWidget;
+ SlideShowWidget *slideshowWidget;
+ KKeyChooser *imageKeyChooser, *browserKeyChooser;
+ KActionCollection *coll;
+
+ ImageWindow *imageWindow;
+
+};
+
+#endif
diff --git a/kuickshow/src/kuickdata.cpp b/kuickshow/src/kuickdata.cpp
new file mode 100644
index 00000000..c6aa47c2
--- /dev/null
+++ b/kuickshow/src/kuickdata.cpp
@@ -0,0 +1,177 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdlib.h>
+
+#include <qcolor.h>
+#include <kconfig.h>
+#include <kglobal.h>
+
+#include "kuickdata.h"
+
+
+KuickData::KuickData()
+{
+ fileFilter = "*.jpeg *.jpg *.gif *.xpm *.ppm *.pgm *.pbm *.pnm *.png *.bmp *.psd *.eim *.tif *.tiff *.xcf";// *.mng";
+ slideDelay = 3000;
+ slideshowCycles = 1;
+ slideshowFullscreen = true;
+ slideshowStartAtFirst = true;
+
+ preloadImage = true;
+
+ isModsEnabled = true;
+ fullScreen = false;
+ autoRotation = true;
+ downScale = true;
+ upScale = false;
+ flipVertically = false;
+ flipHorizontally = false;
+
+ maxUpScale = 3;
+ rotation = ROT_0;
+
+ brightnessSteps = 1;
+ contrastSteps = 1;
+ gammaSteps = 1;
+ scrollSteps = 1;
+ zoomSteps = 1.5;
+
+ maxZoomFactor = 4.0;
+
+ maxCachedImages = 4;
+ backgroundColor = Qt::black;
+
+ startInLastDir = true;
+
+ idata = new ImData;
+}
+
+KuickData::~KuickData()
+{
+ delete idata;
+}
+
+
+void KuickData::load()
+{
+ KConfig *kc = KGlobal::config();
+
+ KuickData def;
+
+ kc->setGroup( "GeneralConfiguration" );
+ fileFilter = kc->readEntry( "FileFilter", def.fileFilter );
+ slideDelay = kc->readNumEntry( "SlideShowDelay", def.slideDelay );
+ slideshowCycles = kc->readUnsignedNumEntry( "SlideshowCycles", 1 );
+ slideshowFullscreen = kc->readBoolEntry( "SlideshowFullscreen", true );
+ slideshowStartAtFirst = kc->readBoolEntry("SlideshowStartAtFirst", true );
+
+ preloadImage = kc->readBoolEntry( "PreloadNextImage", def.preloadImage );
+
+ fullScreen = kc->readBoolEntry( "Fullscreen", def.fullScreen);
+ autoRotation = kc->readBoolEntry( "AutoRotation", def.autoRotation);
+ downScale = kc->readBoolEntry( "ShrinkToScreenSize", def.downScale );
+ upScale = kc->readBoolEntry( "ZoomToScreenSize", def.upScale );
+ flipVertically = kc->readBoolEntry( "FlipVertically", def.flipVertically );
+ flipHorizontally = kc->readBoolEntry( "FlipHorizontally",
+ def.flipHorizontally );
+ maxUpScale = kc->readNumEntry( "MaxUpscale Factor", def.maxUpScale );
+ rotation = (Rotation) kc->readNumEntry( "Rotation", def.rotation );
+
+ isModsEnabled = kc->readBoolEntry( "ApplyDefaultModifications",
+ def.isModsEnabled );
+
+ brightnessSteps = kc->readNumEntry("BrightnessStepSize",def.brightnessSteps);
+ contrastSteps = kc->readNumEntry("ContrastStepSize", def.contrastSteps);
+ gammaSteps = kc->readNumEntry("GammaStepSize", def.gammaSteps);
+ scrollSteps = kc->readNumEntry("ScrollingStepSize", def.scrollSteps);
+ zoomSteps = kc->readDoubleNumEntry("ZoomStepSize", def.zoomSteps);
+
+ maxZoomFactor = kc->readDoubleNumEntry( "MaximumZoomFactorByDesktop", def.maxZoomFactor );
+
+ maxCachedImages = kc->readUnsignedNumEntry( "MaxCachedImages",
+ def.maxCachedImages );
+ backgroundColor = kc->readColorEntry( "BackgroundColor", &Qt::black );
+
+ startInLastDir = kc->readBoolEntry( "StartInLastDir", true);
+
+ idata->load( kc );
+
+ // compatibility with KuickShow <= 0.8.3
+ switch ( rotation )
+ {
+ case 90:
+ rotation = ROT_90;
+ break;
+ case 180:
+ rotation = ROT_180;
+ break;
+ case 270:
+ rotation = ROT_270;
+ break;
+ default:
+ if ( (rotation < ROT_0) || (rotation > ROT_270) )
+ rotation = ROT_0;
+ break;
+ }
+}
+
+
+void KuickData::save()
+{
+ KConfig *kc = KGlobal::config();
+ kc->setGroup( "GeneralConfiguration" );
+
+ kc->writeEntry( "FileFilter", fileFilter );
+ kc->writeEntry( "SlideShowDelay", slideDelay );
+ kc->writeEntry( "SlideshowCycles", slideshowCycles );
+ kc->writeEntry( "SlideshowFullscreen", slideshowFullscreen );
+ kc->writeEntry( "SlideshowStartAtFirst", slideshowStartAtFirst );
+
+ kc->writeEntry( "PreloadNextImage", preloadImage );
+
+ kc->writeEntry( "Fullscreen", fullScreen );
+ kc->writeEntry( "AutoRotation", autoRotation );
+ kc->writeEntry( "ShrinkToScreenSize", downScale );
+ kc->writeEntry( "ZoomToScreenSize", upScale );
+ kc->writeEntry( "FlipVertically", flipVertically );
+ kc->writeEntry( "FlipHorizontally", flipHorizontally );
+ kc->writeEntry( "MaxUpscale Factor", maxUpScale );
+ kc->writeEntry( "Rotation", rotation );
+
+ kc->writeEntry( "ApplyDefaultModifications", isModsEnabled );
+
+
+ kc->writeEntry( "BrightnessStepSize", brightnessSteps );
+ kc->writeEntry( "ContrastStepSize", contrastSteps );
+ kc->writeEntry( "GammaStepSize", gammaSteps );
+
+ kc->writeEntry( "ScrollingStepSize", scrollSteps );
+ kc->writeEntry( "ZoomStepSize", zoomSteps );
+
+ kc->writeEntry( "MaximumZoomFactorByDesktop", maxZoomFactor );
+
+ kc->writeEntry( "MaxCachedImages", maxCachedImages );
+ kc->writeEntry( "BackgroundColor", backgroundColor );
+
+ kc->writeEntry( "StartInLastDir", startInLastDir );
+
+ idata->save( kc );
+
+ kc->sync();
+}
diff --git a/kuickshow/src/kuickdata.h b/kuickshow/src/kuickdata.h
new file mode 100644
index 00000000..d05b3e99
--- /dev/null
+++ b/kuickshow/src/kuickdata.h
@@ -0,0 +1,86 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2003 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKDATA_H
+#define KUICKDATA_H
+
+#include <qcolor.h>
+#include <qstring.h>
+
+#include "imdata.h"
+
+class KConfig;
+
+// values are also used as combobox index defaultswidget.*
+enum Rotation { ROT_0=0, ROT_90=1, ROT_180=2, ROT_270=3 };
+
+// hmm, global declaration for now
+enum FlipMode { FlipNone = 0, FlipHorizontal = 1, FlipVertical = 2 };
+
+class KuickData
+{
+public:
+ KuickData();
+ ~KuickData();
+
+ void load();
+ void save();
+
+
+ ImData *idata;
+
+ QString fileFilter;
+ uint slideDelay;
+ uint slideshowCycles;
+ bool slideshowFullscreen :1;
+ bool slideshowStartAtFirst :1;
+
+ int brightnessSteps;
+ int contrastSteps;
+ int gammaSteps;
+
+ int scrollSteps;
+ float zoomSteps;
+
+ bool startInLastDir :1;
+
+ bool preloadImage :1;
+ bool autoRotation :1;
+ bool fullScreen :1;
+
+ // default image modifications
+ bool isModsEnabled :1;
+
+ bool flipVertically :1;
+ bool flipHorizontally :1;
+ bool downScale :1;
+ bool upScale :1;
+ int maxUpScale;
+ float maxZoomFactor;
+ uint maxCachedImages;
+ Rotation rotation;
+
+ QColor backgroundColor;
+
+
+};
+
+
+extern KuickData* kdata;
+
+#endif
diff --git a/kuickshow/src/kuickfile.cpp b/kuickshow/src/kuickfile.cpp
new file mode 100644
index 00000000..1dd259d6
--- /dev/null
+++ b/kuickshow/src/kuickfile.cpp
@@ -0,0 +1,194 @@
+#include <qfile.h>
+
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include <kprogress.h>
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <ktempfile.h>
+
+#include "filecache.h"
+#include "kuickfile.h"
+
+KuickFile::KuickFile(const KURL& url)
+ : QObject(),
+ m_url( url ),
+ m_job( 0L ),
+ m_progress( 0L ),
+ m_currentProgress( 0 )
+{
+ if ( m_url.isLocalFile())
+ m_localFile = m_url.path();
+ else {
+ const KURL& mostLocal = KIO::NetAccess::mostLocalURL( m_url, 0L );
+ if ( mostLocal.isValid() && mostLocal.isLocalFile() )
+ m_localFile = mostLocal.path();
+ }
+}
+
+KuickFile::~KuickFile()
+{
+ delete m_job;
+
+ if ( hasDownloaded() )
+ QFile::remove( m_localFile );
+}
+
+QString KuickFile::localFile() const
+{
+ // Note: never call isAvailable() from here, directly or indirectly
+
+ if ( isDownloading() )
+ return QString::null;
+
+ return m_localFile;
+}
+
+bool KuickFile::hasDownloaded() const
+{
+ return !m_url.isLocalFile() && isAvailable() && m_job != 0L;
+}
+
+// ### need an API for refreshing the file?
+bool KuickFile::download()
+{
+ if ( m_url.isLocalFile() || isAvailable() )
+ return true;
+
+ if ( isDownloading() )
+ return true;
+
+ // reinitialize
+ m_localFile = QString::null;
+ m_currentProgress = 0;
+
+
+ QString ext;
+ QString fileName = m_url.fileName();
+ int extIndex = fileName.findRev('.');
+ if ( extIndex > 0 )
+ ext = fileName.mid( extIndex + 1 );
+
+ QString tempDir = FileCache::self()->tempDir();
+ KTempFile tempFile( tempDir, ext );
+ tempFile.setAutoDelete( tempDir.isNull() ); // in case there is no proper tempdir, make sure to delete those files!
+ if ( tempFile.status() != 0 )
+ return false;
+
+ tempFile.close();
+ if ( tempFile.status() != 0 )
+ return false;
+
+ KURL destURL;
+ destURL.setPath( tempFile.name() );
+
+ m_job = KIO::file_copy( m_url, destURL, -1, true, false, false ); // handling progress ourselves
+ m_job->setAutoErrorHandlingEnabled( true );
+ connect( m_job, SIGNAL( result( KIO::Job * )), SLOT( slotResult( KIO::Job * ) ));
+ connect( m_job, SIGNAL( percent( KIO::Job *, unsigned long )), SLOT( slotProgress( KIO::Job *, unsigned long ) ));
+
+ // TODO: generify background/foreground downloading?
+
+ return m_job != 0L;
+}
+
+KuickFile::DownloadStatus KuickFile::waitForDownload( QWidget *parent )
+{
+ if ( isAvailable() )
+ return OK;
+
+ if ( !isDownloading() ) {
+ if ( !download() )
+ return ERROR;
+ }
+
+ KProgressDialog *dialog = new KProgressDialog( parent );
+ dialog->setModal( true );
+ dialog->setCaption( i18n("Downloading %1...").arg( m_url.fileName() ) );
+ dialog->setLabel( i18n("Please wait while downloading\n%1").arg( m_url.prettyURL() ));
+ dialog->setAllowCancel( true );
+ dialog->setAutoClose( true );
+
+ m_progress = dialog->progressBar();
+ m_progress->setTotalSteps( 100 ); // percent
+ m_progress->setProgress( m_currentProgress );
+ dialog->exec();
+ bool canceled = dialog->wasCancelled();
+ delete dialog;
+ m_progress = 0L;
+
+ if ( canceled && m_job ) {
+ m_job->kill();
+ m_job = 0L;
+ m_currentProgress = 0;
+ }
+ // ### when aborted, remove KuickImage from FileCache?
+
+ if ( canceled )
+ return CANCELED;
+
+ if ( !isAvailable() )
+ return ERROR;
+
+ // ### use custom progress dialog with OK, SKIP, CANCEL?
+ return OK;
+}
+
+void KuickFile::slotResult( KIO::Job *job )
+{
+ if (job != m_job) { // huh?
+ return;
+ }
+
+ m_job = 0L;
+
+ if ( job->error() != 0 ) {
+ m_currentProgress = 0;
+
+ if ( job->error() != KIO::ERR_USER_CANCELED )
+ kdWarning() << "ERROR: KuickFile::slotResult: " << job->errorString() << endl;
+
+ QString canceledFile = static_cast<KIO::FileCopyJob*>(job)->destURL().path();
+ QFile::remove( canceledFile );
+ m_progress->topLevelWidget()->hide();
+ }
+ else {
+ m_localFile = static_cast<KIO::FileCopyJob*>(job)->destURL().path();
+ emit downloaded( this ); // before closing the progress dialog
+
+ if ( m_progress ) {
+ m_progress->setProgress( 100 );
+#define BUGGY_VERSION KDE_MAKE_VERSION(3,5,2)
+ if ( KDE::version() <= BUGGY_VERSION ) {
+ m_progress->topLevelWidget()->hide(); // ### workaround broken KProgressDialog
+ }
+ }
+ }
+}
+
+void KuickFile::slotProgress( KIO::Job *job, unsigned long percent )
+{
+ if (job != m_job) { // huh?
+ return;
+ }
+
+ m_currentProgress = percent;
+
+ if ( !m_progress )
+ return;
+
+ // only set 100% in slotResult. Otherwise, the progress dialog would be closed
+ // before slotResult() is called.
+ if ( percent >= 100 )
+ percent = 99;
+
+ m_progress->setProgress( (int) percent );
+}
+
+bool operator==( const KuickFile& first, const KuickFile& second ) {
+ return first.url().equals( second.url() );
+}
+
+#include "kuickfile.moc"
diff --git a/kuickshow/src/kuickfile.h b/kuickshow/src/kuickfile.h
new file mode 100644
index 00000000..957db6ee
--- /dev/null
+++ b/kuickshow/src/kuickfile.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2002/02/20 15:06:53 gis Exp $
+**
+** Created : 2006
+**
+** Copyright (C) 2006 Carsten Pfeiffer <[email protected]>
+**
+****************************************************************************/
+
+#ifndef KUICKFILE_H
+#define KUICKFILE_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <kurl.h>
+#include <kprogress.h>
+
+namespace KIO {
+ class Job;
+ class FileCopyJob;
+}
+
+class KuickFile : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum DownloadStatus
+ {
+ OK = 1,
+ CANCELED,
+ ERROR
+ };
+
+ KuickFile(const KURL& url);
+
+ /**
+ * Cleans up resources and removes any temporary file, if available.
+ */
+ ~KuickFile();
+
+ const KURL& url() const { return m_url; }
+
+
+ QString localFile() const;
+
+ bool download();
+
+ /**
+ * @return true if download is in progress
+ */
+ bool isDownloading() const { return m_job != 0L; }
+
+ /**
+ * @return true if a local file is available, that is,
+ * @ref #localFile will return a non-empty name
+ * ### HERE ADD mostlylocal thing!
+ */
+ bool isAvailable() const { return !localFile().isEmpty(); }
+
+ /**
+ * @return true if @ref #isAvailable() returns true AND @ref #url() is a remote URL,
+ * i.e. the file really has been downloaded.
+ */
+ bool hasDownloaded() const;
+
+ /**
+ * Opens a modal dialog window, blocking user interaction until the download
+ * has finished. If the file is already available, this function will return true
+ * immediately.
+ * @return true when the download has finished or false when the user aborted the dialog
+ */
+ KuickFile::DownloadStatus waitForDownload( QWidget *parent );
+
+// bool needsDownload();
+
+signals:
+ /**
+ * Signals that download has finished for that file. Will only be emitted for non-local files!
+ */
+ void downloaded( KuickFile * );
+
+private slots:
+ void slotResult( KIO::Job *job );
+ void slotProgress( KIO::Job *job, unsigned long percent );
+
+private:
+ KURL m_url;
+ QString m_localFile;
+ KIO::FileCopyJob *m_job;
+ KProgress *m_progress;
+ int m_currentProgress;
+
+};
+
+bool operator==( const KuickFile& first, const KuickFile& second );
+
+#endif // KUICKFILE_H
diff --git a/kuickshow/src/kuickglobals.h b/kuickshow/src/kuickglobals.h
new file mode 100644
index 00000000..4ea2ff3c
--- /dev/null
+++ b/kuickshow/src/kuickglobals.h
@@ -0,0 +1,33 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001,2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKGLOBALS_H
+#define KUICKGLOBALS_H
+
+#include <kwinmodule.h>
+
+class KuickGlobals
+{
+public:
+ KWinModule winModule;
+
+
+};
+
+
+#endif // KUICKGLOBALS_H
diff --git a/kuickshow/src/kuickimage.cpp b/kuickshow/src/kuickimage.cpp
new file mode 100644
index 00000000..29e5de1c
--- /dev/null
+++ b/kuickshow/src/kuickimage.cpp
@@ -0,0 +1,527 @@
+#include "kuickimage.h"
+
+KuickImage::KuickImage( const KuickFile * file, ImlibImage *im, ImlibData *id)
+ : QObject( 0L, 0L )
+{
+ myFile = file;
+ myOrigIm = 0L;
+ myIm = im;
+ myId = id;
+ myPixmap = 0L;
+ myWidth = im->rgb_width;
+ myHeight = im->rgb_height;
+ myIsDirty = true;
+
+ myOrigWidth = myWidth;
+ myOrigHeight = myHeight;
+ myRotation = ROT_0;
+ myFlipMode = FlipNone;
+}
+
+KuickImage::~KuickImage()
+{
+ if ( myPixmap )
+ Imlib_free_pixmap( myId, myPixmap );
+
+ if ( myOrigIm )
+ {
+ Imlib_destroy_image( myId, myOrigIm );
+ Imlib_kill_image( myId, myIm ); // kill scaled image (### really? analyze!)
+ }
+ else
+ Imlib_destroy_image( myId, myIm );
+}
+
+
+Pixmap& KuickImage::pixmap()
+{
+ if ( myIsDirty )
+ renderPixmap();
+
+ return myPixmap;
+}
+
+
+void KuickImage::renderPixmap()
+{
+ if ( !myIsDirty )
+ return;
+
+// qDebug("### rendering: %s", myFilename.latin1());
+
+ if ( myPixmap )
+ Imlib_free_pixmap( myId, myPixmap );
+
+ emit startRendering();
+
+// #ifndef NDEBUG
+// struct timeval tms1, tms2;
+// gettimeofday( &tms1, NULL );
+// #endif
+
+ Imlib_render( myId, myIm, myWidth, myHeight );
+ myPixmap = Imlib_move_image( myId, myIm );
+
+// #ifndef NDEBUG
+// gettimeofday( &tms2, NULL );
+// qDebug("*** rendering image: %s, took %ld ms", myFilename.latin1(),
+// (tms2.tv_usec - tms1.tv_usec)/1000);
+// #endif
+
+ emit stoppedRendering();
+
+ myIsDirty = false;
+}
+
+
+void KuickImage::rotate( Rotation rot )
+{
+ if ( rot == ROT_180 ) { // rotate 180 degrees
+ Imlib_flip_image_horizontal( myId, myIm );
+ Imlib_flip_image_vertical( myId, myIm );
+ }
+
+ else if ( rot == ROT_90 || rot == ROT_270 ) {
+ qSwap( myWidth, myHeight );
+ Imlib_rotate_image( myId, myIm, -1 );
+
+ if ( rot == ROT_90 ) // rotate 90 degrees
+ Imlib_flip_image_horizontal( myId, myIm );
+ else if ( rot == ROT_270 ) // rotate 270 degrees
+ Imlib_flip_image_vertical( myId, myIm );
+ }
+
+ myRotation = (Rotation) ((myRotation + rot) % 4);
+ myIsDirty = true;
+}
+
+
+bool KuickImage::rotateAbs( Rotation rot )
+{
+ if ( myRotation == rot )
+ return false;
+
+ int diff = rot - myRotation;
+ bool clockWise = (diff > 0);
+
+ switch( abs(diff) ) {
+ case ROT_90:
+ rotate( clockWise ? ROT_90 : ROT_270 );
+ break;
+ case ROT_180:
+ rotate( ROT_180 );
+ break;
+ case ROT_270:
+ rotate( clockWise ? ROT_270 : ROT_90 );
+ break;
+ }
+
+ return true;
+}
+
+void KuickImage::flip( FlipMode flipMode )
+{
+ if ( flipMode & FlipHorizontal )
+ Imlib_flip_image_horizontal( myId, myIm );
+ if ( flipMode & FlipVertical )
+ Imlib_flip_image_vertical( myId, myIm );
+
+ myFlipMode = (FlipMode) (myFlipMode ^ flipMode);
+ myIsDirty = true;
+}
+
+bool KuickImage::flipAbs( int mode )
+{
+ if ( myFlipMode == mode )
+ return false;
+
+ bool changed = false;
+
+ if ( ((myFlipMode & FlipHorizontal) && !(mode & FlipHorizontal)) ||
+ (!(myFlipMode & FlipHorizontal) && (mode & FlipHorizontal)) ) {
+ Imlib_flip_image_horizontal( myId, myIm );
+ changed = true;
+ }
+
+ if ( ((myFlipMode & FlipVertical) && !(mode & FlipVertical)) ||
+ (!(myFlipMode & FlipVertical) && (mode & FlipVertical)) ) {
+ Imlib_flip_image_vertical( myId, myIm );
+ changed = true;
+ }
+
+ if ( changed ) {
+ myFlipMode = (FlipMode) mode;
+ myIsDirty = true;
+ return true;
+ }
+
+ return false;
+}
+
+
+void KuickImage::restoreOriginalSize()
+{
+ if (myWidth == myOrigWidth && myHeight == myOrigHeight)
+ return;
+
+// qDebug("-- restoreOriginalSize");
+
+ if ( myOrigIm != 0L )
+ {
+ Imlib_destroy_image( myId, myIm );
+ myIm = myOrigIm;
+ myOrigIm = 0L;
+ }
+
+ myWidth = myOrigWidth;
+ myHeight = myOrigHeight;
+ myIsDirty = true;
+
+ if ( myRotation == ROT_90 || myRotation == ROT_270 )
+ qSwap( myWidth, myHeight );
+}
+
+void KuickImage::resize( int width, int height, KuickImage::ResizeMode mode )
+{
+ if ( myWidth == width && myHeight == height )
+ return;
+
+ if ( mode == KuickImage::SMOOTH )
+ {
+ if ( !smoothResize( width, height ) )
+ fastResize( width, height );
+ }
+ else
+ {
+ fastResize( width, height );
+ }
+}
+
+
+void KuickImage::fastResize( int width, int height )
+{
+// qDebug("-- fastResize: %i x %i", width, height );
+
+ // lazy resizing (only done when rendering pixmap)
+ myWidth = width;
+ myHeight = height;
+ myIsDirty = true;
+}
+
+bool KuickImage::smoothResize( int newWidth, int newHeight )
+{
+// qDebug("-- smoothResize: %i x %i", newWidth, newHeight);
+
+ QImage *image = newQImage();
+ // Note: QImage::ScaleMin seems to have a bug (off-by-one, sometimes results in width being 1 pixel too small)
+ QImage scaledImage = image->smoothScale(newWidth, newHeight, QImage::ScaleFree);
+
+ delete image;
+
+
+ ImlibImage *newIm = toImage( myId, scaledImage );
+ if ( newIm )
+ {
+ if ( myOrigIm == 0 )
+ myOrigIm = myIm;
+
+ myIm = newIm;
+ myWidth = newWidth;
+ myHeight = newHeight;
+ myIsDirty = true;
+ return true;
+ }
+
+ return false;
+}
+
+QImage * KuickImage::newQImage() const
+{
+ ImlibImage *im;
+
+// qDebug("-- newQImage");
+
+ if ( myOrigIm != 0L && myRotation == ROT_0 && myFlipMode == FlipNone )
+ {
+ // use original image if no other modifications have been applied
+ // ### use orig image always and reapply mods?
+ im = myOrigIm;
+ }
+ else
+ {
+ im = myIm;
+ }
+
+ int w = im->rgb_width;
+ int h = im->rgb_height;
+
+ QImage *image = new QImage( w, h, 32 );
+ uchar *rgb = im->rgb_data;
+ QRgb **destImageData = reinterpret_cast<QRgb**>( image->jumpTable() );
+
+
+ int byteIndex = 0;
+ int destLineIndex = 0;
+ int destByteIndex = 0;
+ for ( int pixel = 0; pixel < (w * h); pixel++ )
+ {
+ if ( pixel != 0 && (pixel % w) == 0 )
+ {
+ destLineIndex++;
+ destByteIndex = 0;
+ }
+
+ uchar r = rgb[byteIndex++];
+ uchar g = rgb[byteIndex++];
+ uchar b = rgb[byteIndex++];
+
+ QRgb rgbPixel = qRgb( r, g, b );
+ destImageData[destLineIndex][destByteIndex++] = rgbPixel;
+ }
+
+ return image;
+}
+
+ImlibImage * KuickImage::toImage( ImlibData *id, QImage& image )
+{
+ if ( image.isNull() )
+ return 0L;
+
+ if ( image.depth() != 32 )
+ {
+ image.setAlphaBuffer(false);
+ image = image.convertDepth(32);
+
+ if ( image.isNull() )
+ return 0L;
+ }
+
+ // convert to 24 bpp (discard alpha)
+ int numPixels = image.width() * image.height();
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+ uchar *newData = newImageData;
+
+ int w = image.width();
+ int h = image.height();
+
+ for (int y = 0; y < h; y++) {
+ QRgb *scanLine = reinterpret_cast<QRgb *>( image.scanLine(y) );
+ for (int x = 0; x < w; x++) {
+ const QRgb& pixel = scanLine[x];
+ *(newData++) = qRed(pixel);
+ *(newData++) = qGreen(pixel);
+ *(newData++) = qBlue(pixel);
+ }
+ }
+
+ ImlibImage *im = Imlib_create_image_from_data( id, newImageData, NULL,
+ image.width(), image.height() );
+
+ delete [] newImageData;
+
+ return im;
+}
+
+
+#if 0
+bool KuickImage::smoothResize( int newWidth, int newHeight )
+{
+ int numPixels = newWidth * newHeight;
+ const int NUM_BYTES_NEW = 3; // 24 bpp
+ uchar *newImageData = new uchar[numPixels * NUM_BYTES_NEW];
+
+ // ### endianness
+ // myIm : old image, old size
+
+
+ /////////////////////////////////////////////////
+// int w = myOrigWidth; //myViewport.width();
+ //int h = myOrigHeight; //myViewport.height();
+
+ //QImage dst(w, h, myIm->depth(), myIm->numColors(), myIm->bitOrder());
+
+ //QRgb *scanline;
+
+ int basis_ox, basis_oy, basis_xx, basis_yy;
+
+ // ### we only scale with a fixed factor for x and y anyway
+ double scalex = newWidth / (double) myOrigWidth;
+ double scaley = newHeight / (double) myOrigHeight;
+
+// basis_ox=(int) (myViewport.left() * 4096.0 / scalex);
+// basis_oy=(int) (myViewport.top() * 4096.0 / scaley);
+ basis_ox = 0;
+ basis_oy = 0;
+ basis_xx = (int) (4096.0 / scalex);
+ basis_yy = (int) (4096.0 / scaley);
+
+ //qDebug("Basis: (%d, %d), (%d, 0), (0, %d)", basis_ox, basis_oy, basis_xx, basis_yy);
+
+ int x2, y2;
+
+ int max_x2 = (myOrigWidth << 12);
+ int max_y2 = (myOrigHeight << 12);
+
+// QRgb background = idata->backgroundColor.rgb();
+
+// QRgb **imdata = (QRgb **) myIm->jumpTable();
+// QRgb *imdata = reinterpret_cast<QRgb*>( myIm->rgb_data );
+ uchar *imdata = myIm->rgb_data;
+
+
+ int y = 0;
+
+
+// for (;;) //fill the top of the target pixmap with the background color
+// {
+// y2 = basis_oy + y * basis_yy;
+//
+// if ((y2 >= 0 && (y2 >> 12) < myIm->height()) || y >= h)
+// break;
+//
+// scanline = (QRgb*) dst.scanLine(y);
+// for (int i = 0; i < w; i++)
+// *(scanline++) = background; //qRgb(0,255,0);
+// y++;
+// }
+
+ for (; y < newHeight; y++)
+ {
+// scanline = (QRgb*) dst.scanLine(y);
+
+ x2 = basis_ox;
+ y2 = basis_oy + y * basis_yy;
+
+ if (y2 >= max_y2)
+ break;
+
+ int x = 0;
+
+// while ((x2 < 0 || (x2 >> 12) >= myIm->width()) && x < w) //fill the left of the target pixmap with the background color
+// {
+// *(scanline++) = background; //qRgb(0,0,255);
+// x2 += basis_xx;
+// x++;
+// }
+
+ int top = y2 >> 12;
+ int bottom = top + 1;
+ if (bottom >= myOrigHeight)
+ bottom--;
+
+// for (; x < w; x++)
+ for (; x < newWidth; x++) // ### myOrigWidth orig
+ {
+ int left = x2 >> 12;
+ int right = left + 1;
+
+ if (right >= myOrigWidth)
+ right = myOrigWidth - 1;
+
+ unsigned int wx = x2 & 0xfff; //12 bits of precision for reasons which will become clear
+ unsigned int wy = y2 & 0xfff; //12 bits of precision
+
+ unsigned int iwx = 0xfff - wx;
+ unsigned int iwy = 0xfff - wy;
+
+ QRgb tl = 0, tr = 0, bl = 0, br = 0;
+ int ind = 0;
+ ind = (left + top * myOrigWidth) * 3;
+ tl = (imdata[ind] << 16);
+ tl |= (imdata[ind + 1] << 8);
+ tl |= (imdata[ind + 2] << 0);
+ int bar = imdata[ind + 2] << 8;
+ bar = qBlue(bar);
+
+ ind = (right + top * myOrigWidth) * 3;
+ tr = (imdata[ind] << 16);
+ tr |= (imdata[ind + 1] << 8);
+ tr |= (imdata[ind + 2] << 0);
+ bar = imdata[ind + 2] << 8;
+
+ ind = (left + bottom * myOrigWidth) * 3;
+ bl = (imdata[ind] << 16);
+ bl |= (imdata[ind + 1] << 8);
+ bl |= (imdata[ind + 2] << 0);
+ bar = imdata[ind + 2] << 8;
+
+ ind = (right + bottom * myOrigWidth) * 3;
+ br = (imdata[ind] << 16);
+ br |= (imdata[ind + 1] << 8);
+ br |= (imdata[ind + 2] << 0);
+// tl=imdata[top][left];
+// tr=imdata[top][right];
+// bl=imdata[bottom][left];
+// br=imdata[bottom][right];
+
+ /*
+ tl=getValidPixel(myIm, left, top, x, y); //these calls are expensive
+ tr=getValidPixel(myIm, right, top, x, y); //use them to debug segfaults in this function
+ bl=getValidPixel(myIm, left, bottom, x, y);
+ br=getValidPixel(myIm, right, bottom, x, y);
+ */
+
+ unsigned int r = (unsigned int) (qRed(tl) * iwx * iwy + qRed(tr) * wx* iwy + qRed(bl) * iwx * wy + qRed(br) * wx * wy); // NB 12+12+8 == 32
+ unsigned int g = (unsigned int) (qGreen(tl) * iwx * iwy + qGreen(tr) * wx * iwy + qGreen(bl) * iwx * wy + qGreen(br) * wx * wy);
+ unsigned int b = (unsigned int) (qBlue(tl) * iwx * iwy + qBlue(tr) * wx * iwy + qBlue(bl) * iwx * wy + qBlue(br) * wx * wy);
+
+ // ### endianness
+ //we're actually off by one in 255 here! (254 instead of 255)
+ int foo = r >> 24;
+ foo = g >> 24;
+ foo = b >> 24;
+ newImageData[(y * newWidth * 3) + (x * 3) + 0] = (r >> 24);
+ newImageData[(y * newWidth * 3) + (x * 3) + 1] = (g >> 24);
+ newImageData[(y * newWidth * 3) + (x * 3) + 2] = (b >> 24);
+// *(scanline++) = qRgb(r >> 24, g >> 24, b >> 24); //we're actually off by one in 255 here
+
+ x2 += basis_xx;
+
+ if (x2 > max_x2)
+ {
+ x++;
+ break;
+ }
+
+ }
+
+// while (x < w) //fill the right of each scanline with the background colour
+// {
+// *(scanline++) = background; //qRgb(255,0,0);
+// x++;
+// }
+ }
+
+// for (;;) //fill the bottom of the target pixmap with the background color
+// {
+// y2 = basis_oy + y * basis_yy;
+//
+// if (y >= h)
+// break;
+//
+// scanline = (QRgb*) dst.scanLine(y);
+// for (int i = 0; i < w; i++)
+// *(scanline++) = background; //qRgb(255,255,0);
+// y++;
+// }
+
+ // ### keep orig image somewhere but delete all scaled images!
+ ImlibImage *newIm = Imlib_create_image_from_data( myId, newImageData, NULL,
+ newWidth, newHeight );
+ delete[] newImageData;
+
+ if ( newIm )
+ {
+ myScaledIm = newIm;
+ myIsDirty = true;
+ myWidth = newWidth;
+ myHeight = newHeight;
+ }
+
+ return myIm != 0L;
+// return dst.copy();
+}
+#endif
+
+#include "kuickimage.moc"
diff --git a/kuickshow/src/kuickimage.h b/kuickshow/src/kuickimage.h
new file mode 100644
index 00000000..745facf4
--- /dev/null
+++ b/kuickshow/src/kuickimage.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+** $Id: .emacs,v 1.3 2002/02/20 15:06:53 gis Exp $
+**
+** Created : 2002
+**
+** Copyright (C) 2002 Carsten Pfeiffer <[email protected]>
+**
+****************************************************************************/
+
+#ifndef KUICKIMAGE_H
+#define KUICKIMAGE_H
+
+#include <qimage.h>
+#include <qobject.h>
+
+#include <kurl.h>
+
+#include "kuickdata.h"
+#include "kuickfile.h"
+
+// #include those AFTER Qt-includes!
+#include <Imlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+// #include <X11/extensions/shape.h>
+
+
+class KuickImage : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum ResizeMode { FAST, SMOOTH };
+
+ KuickImage( const KuickFile * file, ImlibImage *im, ImlibData *id );
+ ~KuickImage();
+
+ int width() const { return myWidth; }
+ int height() const { return myHeight; }
+ int originalWidth() const { return myOrigWidth; }
+ int originalHeight() const { return myOrigHeight; }
+
+ void resize( int width, int height, KuickImage::ResizeMode mode );
+ void restoreOriginalSize();
+ void rotate( Rotation rot );
+ bool rotateAbs( Rotation rot );
+ void flip( FlipMode flipMode );
+ bool flipAbs( int mode );
+ ImlibImage * imlibImage() const { return myIm; }
+ Pixmap& pixmap();
+ void renderPixmap();
+// const QString& filename() const { return myFilename;}
+ const KuickFile& file() const { return *myFile; }
+ const KURL& url() const { return myFile->url(); }
+
+ void setDirty( bool d ) { myIsDirty = d; }
+ bool isDirty() const { return myIsDirty; }
+ Rotation absRotation() const { return myRotation; }
+ FlipMode flipMode() const { return myFlipMode; }
+
+ static ImlibImage * toImage( ImlibData *id, QImage& image );
+
+private:
+ void fastResize( int newWidth, int newHeight );
+ bool smoothResize( int width, int height );
+ /**
+ * Note: caller must delete it!
+ */
+ QImage * newQImage() const;
+
+ const KuickFile * myFile;
+
+ int myWidth;
+ int myHeight;
+ ImlibImage * myOrigIm;
+ ImlibImage * myIm;
+ ImlibData * myId;
+ Pixmap myPixmap;
+ bool myIsDirty;
+
+ int myOrigWidth;
+ int myOrigHeight;
+ Rotation myRotation;
+ FlipMode myFlipMode;
+
+signals:
+ void startRendering();
+ void stoppedRendering();
+};
+
+
+#endif // KUICKIMAGE_H
diff --git a/kuickshow/src/kuickshow.cpp b/kuickshow/src/kuickshow.cpp
new file mode 100644
index 00000000..7e8718fb
--- /dev/null
+++ b/kuickshow/src/kuickshow.cpp
@@ -0,0 +1,1443 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <qdir.h>
+#include <qdesktopwidget.h>
+#include <qdialog.h>
+#include <qglobal.h>
+#include <qkeycode.h>
+#include <qlayout.h>
+#include <qsize.h>
+#include <qstring.h>
+
+#include <kaboutdata.h>
+#include <kaccel.h>
+#include <kaction.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kconfig.h>
+#include <kcursor.h>
+#include <kdeversion.h>
+#include <kfiledialog.h>
+#include <kfilemetainfo.h>
+#include <kglobal.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <kio/netaccess.h>
+#include <klocale.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kpopupmenu.h>
+#include <kprotocolinfo.h>
+#include <kpropertiesdialog.h>
+#include <kprotocolinfo.h>
+#include <kstatusbar.h>
+#include <kstdaction.h>
+#include <kstandarddirs.h>
+#include <kstartupinfo.h>
+#include <ktoolbar.h>
+#include <kurlcombobox.h>
+#include <kurlcompletion.h>
+#include <kurldrag.h>
+#include <kwin.h>
+#include <kstdguiitem.h>
+
+#include <kdebug.h>
+
+#include "aboutwidget.h"
+#include "filewidget.h"
+#include "filecache.h"
+#include "imdata.h"
+#include "imagewindow.h"
+#include "imlibwidget.h"
+#include "kuick.h"
+#include "kuickfile.h"
+
+#ifdef index
+#undef index
+#endif
+
+#include "kuickconfigdlg.h"
+#include "kuickdata.h"
+#include "kuickshow.h"
+#include "version.h"
+
+#ifdef KeyPress
+#undef KeyPress
+#endif
+
+KuickData* kdata;
+
+static const int URL_ITEM = 0;
+static const int META_ITEM = 1;
+
+QValueList<ImageWindow*> KuickShow::s_viewers;
+
+KuickShow::KuickShow( const char *name )
+ : KMainWindow( 0L, name ),
+ m_slideshowCycle( 1 ),
+ fileWidget( 0L ),
+ dialog( 0L ),
+ id( 0L ),
+ m_viewer( 0L ),
+ oneWindowAction( 0L ),
+ m_accel( 0L ),
+ m_delayedRepeatItem( 0L ),
+ m_slideShowStopped(false)
+{
+ aboutWidget = 0L;
+ kdata = new KuickData;
+ kdata->load();
+
+ initImlib();
+ resize( 400, 500 );
+
+ m_slideTimer = new QTimer( this );
+ connect( m_slideTimer, SIGNAL( timeout() ), SLOT( nextSlide() ));
+
+
+ KConfig *kc = KGlobal::config();
+
+ bool isDir = false; // true if we get a directory on the commandline
+
+ // parse commandline options
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ // files to display
+ // either a directory to display, an absolute path, a relative path, or a URL
+ KURL startDir;
+ startDir.setPath( QDir::currentDirPath() + '/' );
+
+ int numArgs = args->count();
+ if ( numArgs >= 10 )
+ {
+ // Even though the 1st i18n string will never be used, it needs to exist for plural handling - mhunter
+ if ( KMessageBox::warningYesNo(
+ this,
+ i18n("Do you really want to display this 1 image at the same time? This might be quite resource intensive and could overload your computer.<br>If you choose %1, only the first image will be shown.",
+ "Do you really want to display these %n images at the same time? This might be quite resource intensive and could overload your computer.<br>If you choose %1, only the first image will be shown.", numArgs).arg(KStdGuiItem::no().plainText()),
+ i18n("Display Multiple Images?"))
+ != KMessageBox::Yes )
+ {
+ numArgs = 1;
+ }
+ }
+
+ for ( int i = 0; i < numArgs; i++ ) {
+ KURL url = args->url( i );
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, url, false );
+
+ // for remote URLs, we don't know if it's a file or directory, but
+ // FileWidget::isImage() should correct in most cases.
+ // For non-local non-images, we just assume directory.
+
+ if ( FileWidget::isImage( &item ) )
+ {
+ showImage( &item, true, false, true ); // show in new window, not fullscreen-forced and move to 0,0
+// showImage( &item, true, false, false ); // show in new window, not fullscreen-forced and not moving to 0,0
+ }
+ else if ( item.isDir() )
+ {
+ startDir = url;
+ isDir = true;
+ }
+
+ // need to check remote files
+ else if ( !url.isLocalFile() )
+ {
+ KMimeType::Ptr mime = KMimeType::findByURL( url );
+ QString name = mime->name();
+ if ( name == "application/octet-stream" ) // unknown -> stat()
+ name = KIO::NetAccess::mimetype( url, this );
+
+ // text/* is a hack for bugs.kde.org-attached-images urls.
+ // The real problem here is that NetAccess::mimetype does a HTTP HEAD, which doesn't
+ // always return the right mimetype. The rest of KDE start a get() instead....
+ if ( name.startsWith( "image/" ) || name.startsWith( "text/" ) )
+ {
+ FileWidget::setImage( item, true );
+ showImage( &item, true, false, true );
+ }
+ else // assume directory, KDirLister will tell us if we can't list
+ {
+ startDir = url;
+ isDir = true;
+ }
+ }
+ // else // we don't handle local non-images
+ }
+
+ if ( (kdata->startInLastDir && args->count() == 0) || args->isSet( "lastfolder" )) {
+ kc->setGroup( "SessionSettings");
+ startDir = kc->readPathEntry( "CurrentDirectory", startDir.url() );
+ }
+
+ if ( s_viewers.isEmpty() || isDir ) {
+ initGUI( startDir );
+ if (!kapp->isRestored()) // during session management, readProperties() will show()
+ show();
+ }
+
+ else { // don't show browser, when image on commandline
+ hide();
+ KStartupInfo::appStarted();
+ }
+}
+
+
+KuickShow::~KuickShow()
+{
+ saveSettings();
+
+ if ( m_viewer )
+ m_viewer->close( true );
+
+ FileCache::shutdown();
+ free( id );
+ kapp->quit();
+
+ delete kdata;
+}
+
+// TODO convert to use xmlui file
+void KuickShow::initGUI( const KURL& startDir )
+{
+ KURL startURL( startDir );
+ if ( !KProtocolInfo::supportsListing( startURL ) )
+ startURL = KURL();
+
+ fileWidget = new FileWidget( startURL, this, "MainWidget" );
+ setFocusProxy( fileWidget );
+
+ KActionCollection *coll = fileWidget->actionCollection();
+
+ redirectDeleteAndTrashActions(coll);
+
+ connect( fileWidget, SIGNAL( fileSelected( const KFileItem * ) ),
+ this, SLOT( slotSelected( const KFileItem * ) ));
+
+ connect( fileWidget, SIGNAL( fileHighlighted( const KFileItem * )),
+ this, SLOT( slotHighlighted( const KFileItem * ) ));
+
+ connect( fileWidget, SIGNAL( urlEntered( const KURL& )),
+ this, SLOT( dirSelected( const KURL& )) );
+
+
+ fileWidget->setAcceptDrops(true);
+ connect( fileWidget, SIGNAL( dropped( const KFileItem *, QDropEvent *, const KURL::List & )),
+ this, SLOT( slotDropped( const KFileItem *, QDropEvent *, const KURL::List &)) );
+
+ // setup actions
+ KAction *open = KStdAction::open( this, SLOT( slotOpenURL() ),
+ coll, "openURL" );
+
+ KAction *print = KStdAction::print( this, SLOT( slotPrint() ),
+ coll, "kuick_print" );
+ print->setText( i18n("Print Image...") );
+
+ KAction *configure = new KAction( i18n("Configure %1...").arg( KGlobal::instance()->aboutData()->programName() ), "configure",
+ KShortcut(),
+ this, SLOT( configuration() ),
+ coll, "kuick_configure" );
+ KAction *slide = new KAction( i18n("Start Slideshow" ), "ksslide",
+ KShortcut( Key_F2 ),
+ this, SLOT( startSlideShow() ),
+ coll, "kuick_slideshow" );
+ KAction *about = new KAction( i18n( "About KuickShow" ), "about",
+ KShortcut(),
+ this, SLOT( about() ), coll, "about" );
+
+ oneWindowAction = new KToggleAction( i18n("Open Only One Image Window"),
+ "window_new",
+ KShortcut( CTRL+Key_N ), coll,
+ "kuick_one window" );
+
+ m_toggleBrowserAction = new KToggleAction( i18n("Show File Browser"), KShortcut( Key_Space ), coll, "toggleBrowser" );
+ m_toggleBrowserAction->setCheckedState(i18n("Hide File Browser"));
+ connect( m_toggleBrowserAction, SIGNAL( toggled( bool ) ),
+ SLOT( toggleBrowser() ));
+
+ KAction *showInOther = new KAction( i18n("Show Image"), KShortcut(),
+ this, SLOT( slotShowInOtherWindow() ),
+ coll, "kuick_showInOtherWindow" );
+ KAction *showInSame = new KAction( i18n("Show Image in Active Window"),
+ KShortcut(),
+ this, SLOT( slotShowInSameWindow() ),
+ coll, "kuick_showInSameWindow" );
+ KAction *showFullscreen = new KAction( i18n("Show Image in Fullscreen Mode"),
+ KShortcut(), this, SLOT( slotShowFullscreen() ),
+ coll, "kuick_showFullscreen" );
+
+ KAction *quit = KStdAction::quit( this, SLOT(slotQuit()), coll, "quit");
+
+ // remove QString::null parameter -- ellis
+ coll->readShortcutSettings( QString::null );
+ m_accel = coll->accel();
+
+ // menubar
+ KMenuBar *mBar = menuBar();
+ QPopupMenu *fileMenu = new QPopupMenu( mBar, "file" );
+ open->plug( fileMenu );
+ showInOther->plug( fileMenu );
+ showInSame->plug( fileMenu );
+ showFullscreen->plug( fileMenu );
+ fileMenu->insertSeparator();
+ slide->plug( fileMenu );
+ print->plug( fileMenu );
+ fileMenu->insertSeparator();
+ quit->plug( fileMenu );
+
+ QPopupMenu *editMenu = new QPopupMenu( mBar, "edit" );
+ coll->action("mkdir")->plug( editMenu );
+ coll->action("delete")->plug( editMenu );
+ editMenu->insertSeparator();
+ coll->action("properties")->plug( editMenu );
+
+
+ // remove the Sorting submenu (and the separator below)
+ // from the main contextmenu
+ KActionMenu *sortingMenu = static_cast<KActionMenu*>( coll->action("sorting menu"));
+ KActionMenu *mainActionMenu = static_cast<KActionMenu*>( coll->action("popupMenu"));
+ QPopupMenu *mainPopup = mainActionMenu->popupMenu();
+ int sortingIndex = mainPopup->indexOf( sortingMenu->itemId( 0 ) );
+ int separatorId = mainPopup->idAt( sortingIndex + 1 );
+ QMenuItem *separatorItem = mainPopup->findItem( separatorId );
+ if ( separatorItem && separatorItem->isSeparator() )
+ mainPopup->removeItem( separatorId );
+ mainActionMenu->remove( sortingMenu );
+
+ // add the sorting menu and a separator into the View menu
+ KActionMenu *viewActionMenu = static_cast<KActionMenu*>( coll->action("view menu"));
+ viewActionMenu->popupMenu()->insertSeparator( 0 );
+ sortingMenu->plug( viewActionMenu->popupMenu(), 0 ); // on top of the menu
+
+
+ QPopupMenu *settingsMenu = new QPopupMenu( mBar, "settings" );
+ configure->plug( settingsMenu );
+
+ mBar->insertItem( i18n("&File"), fileMenu );
+ mBar->insertItem( i18n("&Edit"), editMenu );
+ viewActionMenu->plug( mBar );
+ mBar->insertItem( i18n("&Settings"), settingsMenu );
+
+ // toolbar
+ KToolBar *tBar = toolBar();
+ tBar->setText( i18n( "Main Toolbar" ) );
+
+ coll->action("up")->plug( tBar );
+ coll->action("back")->plug( tBar );
+ coll->action("forward")->plug( tBar );
+ coll->action("home")->plug( tBar );
+ coll->action("reload")->plug( tBar );
+
+ tBar->insertSeparator();
+
+ coll->action( "short view" )->plug( tBar );
+ coll->action( "detailed view" )->plug( tBar );
+ coll->action( "preview")->plug( tBar );
+
+ tBar->insertSeparator();
+ configure->plug( tBar );
+ slide->plug( tBar );
+ tBar->insertSeparator();
+ oneWindowAction->plug( tBar );
+ print->plug( tBar );
+ tBar->insertSeparator();
+ about->plug( tBar );
+
+ QPopupMenu *help = helpMenu( QString::null, false );
+ mBar->insertItem( KStdGuiItem::help().text() , help );
+
+
+ KStatusBar* sBar = statusBar();
+ sBar->insertItem( " ", URL_ITEM, 10 );
+ sBar->insertItem( " ", META_ITEM, 2 );
+ sBar->setItemAlignment(URL_ITEM, QLabel::AlignVCenter | QLabel::AlignLeft);
+
+ fileWidget->setFocus();
+
+ KConfig *kc = KGlobal::config();
+ kc->setGroup("SessionSettings");
+ bool oneWindow = kc->readBoolEntry("OpenImagesInActiveWindow", true );
+ oneWindowAction->setChecked( oneWindow );
+
+ tBar->show();
+
+ // Address box in address tool bar
+ KToolBar *addressToolBar = toolBar( "address_bar" );
+ const int ID_ADDRESSBAR = 1;
+
+ cmbPath = new KURLComboBox( KURLComboBox::Directories,
+ true, addressToolBar, "address_combo_box" );
+ KURLCompletion *cmpl = new KURLCompletion( KURLCompletion::DirCompletion );
+ cmbPath->setCompletionObject( cmpl );
+ cmbPath->setAutoDeleteCompletionObject( true );
+
+ addressToolBar->insertWidget( ID_ADDRESSBAR, 1, cmbPath);
+ addressToolBar->setItemAutoSized( ID_ADDRESSBAR );
+
+ connect( cmbPath, SIGNAL( urlActivated( const KURL& )),
+ this, SLOT( slotSetURL( const KURL& )));
+ connect( cmbPath, SIGNAL( returnPressed()),
+ this, SLOT( slotURLComboReturnPressed()));
+
+
+ fileWidget->initActions();
+ fileWidget->clearHistory();
+ dirSelected( fileWidget->url() );
+
+ setCentralWidget( fileWidget );
+ setupGUI( KMainWindow::Save );
+
+ coll->action( "reload" )->setShortcut( KStdAccel::reload() );
+ coll->action( "short view" )->setShortcut(Key_F6);
+ coll->action( "detailed view" )->setShortcut(Key_F7);
+ coll->action( "show hidden" )->setShortcut(Key_F8);
+ coll->action( "mkdir" )->setShortcut(Key_F10);
+ coll->action( "preview" )->setShortcut(Key_F11);
+ coll->action( "separate dirs" )->setShortcut(Key_F12);
+}
+
+void KuickShow::redirectDeleteAndTrashActions(KActionCollection *coll)
+{
+ KAction *action = coll->action("delete");
+ if (action)
+ {
+ action->disconnect(fileWidget);
+ connect(action, SIGNAL(activated()), this, SLOT(slotDeleteCurrentImage()));
+ }
+
+ action = coll->action("trash");
+ if (action)
+ {
+ action->disconnect(fileWidget);
+ connect(action, SIGNAL(activated()), this, SLOT(slotTrashCurrentImage()));
+ }
+}
+
+void KuickShow::slotSetURL( const KURL& url )
+{
+ fileWidget->setURL( url, true );
+}
+
+void KuickShow::slotURLComboReturnPressed()
+{
+ KURL where = KURL::fromPathOrURL( cmbPath->currentText() );
+ slotSetURL( where );
+}
+
+void KuickShow::viewerDeleted()
+{
+ ImageWindow *viewer = (ImageWindow*) sender();
+ s_viewers.remove( viewer );
+ if ( viewer == m_viewer )
+ m_viewer = 0L;
+
+ if ( !haveBrowser() && s_viewers.isEmpty() ) {
+ saveSettings();
+ FileCache::shutdown();
+ ::exit(0);
+ }
+
+ else if ( haveBrowser() ) {
+ setActiveWindow();
+ // This setFocus() call causes problems in the combiview (always the
+ // directory view on the left gets the focus, which is not desired)
+ // fileWidget->setFocus();
+ }
+
+ if ( fileWidget )
+ // maybe a slideshow was stopped --> enable the action again
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+
+ m_slideTimer->stop();
+}
+
+
+void KuickShow::slotHighlighted( const KFileItem *fi )
+{
+ KFileItem *item = const_cast<KFileItem *>( fi );
+ statusBar()->changeItem( item->getStatusBarInfo(), URL_ITEM );
+ bool image = FileWidget::isImage( fi );
+
+ QString meta;
+ if ( image )
+ {
+ KFileMetaInfo info = item->metaInfo();
+ if ( info.isValid() )
+ {
+ meta = info.item( KFileMimeTypeInfo::Size ).string();
+ KFileMetaInfoGroup group = info.group( "Technical" );
+ if ( group.isValid() )
+ {
+ QString bpp = group.item( "BitDepth" ).string();
+ if ( !bpp.isEmpty() )
+ meta.append( ", " ).append( bpp );
+ }
+ }
+ }
+ statusBar()->changeItem( meta, META_ITEM );
+
+ fileWidget->actionCollection()->action("kuick_print")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showInSameWindow")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showInOtherWindow")->setEnabled( image );
+ fileWidget->actionCollection()->action("kuick_showFullscreen")->setEnabled( image );
+}
+
+void KuickShow::dirSelected( const KURL& url )
+{
+ if ( url.isLocalFile() )
+ setCaption( url.path() );
+ else
+ setCaption( url.prettyURL() );
+
+ cmbPath->setURL( url );
+ statusBar()->changeItem( url.prettyURL(), URL_ITEM );
+}
+
+void KuickShow::slotSelected( const KFileItem *item )
+{
+ showImage( item, !oneWindowAction->isChecked() );
+}
+
+// downloads item if necessary
+void KuickShow::showFileItem( ImageWindow * /*view*/,
+ const KFileItem * /*item*/ )
+{
+
+}
+
+bool KuickShow::showImage( const KFileItem *fi,
+ bool newWindow, bool fullscreen, bool moveToTopLeft )
+{
+ newWindow |= !m_viewer;
+ fullscreen |= (newWindow && kdata->fullScreen);
+ if ( FileWidget::isImage( fi ) ) {
+
+ if ( newWindow ) {
+ m_viewer = new ImageWindow( kdata->idata, id, 0L, "image window" );
+ m_viewer->setFullscreen( fullscreen );
+ s_viewers.append( m_viewer );
+
+ connect( m_viewer, SIGNAL( destroyed() ), SLOT( viewerDeleted() ));
+ connect( m_viewer, SIGNAL( sigFocusWindow( ImageWindow *) ),
+ this, SLOT( slotSetActiveViewer( ImageWindow * ) ));
+ connect( m_viewer, SIGNAL( sigImageError(const KuickFile *, const QString& ) ),
+ this, SLOT( messageCantLoadImage(const KuickFile *, const QString &) ));
+ connect( m_viewer, SIGNAL( requestImage( ImageWindow *, int )),
+ this, SLOT( slotAdvanceImage( ImageWindow *, int )));
+ connect( m_viewer, SIGNAL( pauseSlideShowSignal() ),
+ this, SLOT( pauseSlideShow() ) );
+ connect( m_viewer, SIGNAL (deleteImage (ImageWindow *)),
+ this, SLOT (slotDeleteCurrentImage (ImageWindow *)));
+ connect( m_viewer, SIGNAL (trashImage (ImageWindow *)),
+ this, SLOT (slotTrashCurrentImage (ImageWindow *)));
+ if ( s_viewers.count() == 1 && moveToTopLeft ) {
+ // we have to move to 0x0 before showing _and_
+ // after showing, otherwise we get some bogus geometry()
+ m_viewer->move( Kuick::workArea().topLeft() );
+ }
+
+ m_viewer->installEventFilter( this );
+ }
+
+ // for some strange reason, m_viewer sometimes changes during the
+ // next few lines of code, so as a workaround, we use safeViewer here.
+ // This happens when calling KuickShow with two or more remote-url
+ // arguments on the commandline, where the first one is loaded properly
+ // and the second isn't (e.g. because it is a pdf or something else,
+ // Imlib can't load).
+ ImageWindow *safeViewer = m_viewer;
+
+// file->waitForDownload( this );
+// QString filename;
+// KIO::NetAccess::download(fi->url(), filename, this);
+
+ if ( !safeViewer->showNextImage( fi->url() ) ) {
+ m_viewer = safeViewer;
+ safeViewer->close( true ); // couldn't load image, close window
+ }
+ else {
+// safeViewer->setFullscreen( fullscreen );
+
+ if ( newWindow ) {
+// safeViewer->show();
+
+ if ( !fullscreen && s_viewers.count() == 1 && moveToTopLeft ) {
+ // the WM might have moved us after showing -> strike back!
+ // move the first image to 0x0 workarea coord
+ safeViewer->move( Kuick::workArea().topLeft() );
+ }
+ }
+
+ if ( kdata->preloadImage && fileWidget ) {
+ KFileItem *item = 0L; // don't move cursor
+ item = fileWidget->getItem( FileWidget::Next, true );
+ if ( item )
+ safeViewer->cacheImage( item->url() );
+ }
+
+ m_viewer = safeViewer;
+ return true;
+ } // m_viewer created successfully
+ } // isImage
+
+ return false;
+}
+
+void KuickShow::slotDeleteCurrentImage()
+{
+ performDeleteCurrentImage(fileWidget);
+}
+
+void KuickShow::slotTrashCurrentImage()
+{
+ performTrashCurrentImage(fileWidget);
+}
+
+void KuickShow::slotDeleteCurrentImage(ImageWindow *viewer)
+{
+ if (!fileWidget) {
+ delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::DeleteCurrentFile, 0L));
+ return;
+ }
+ performDeleteCurrentImage(viewer);
+}
+
+void KuickShow::slotTrashCurrentImage(ImageWindow *viewer)
+{
+ if (!fileWidget) {
+ delayAction(new DelayedRepeatEvent(viewer, DelayedRepeatEvent::TrashCurrentFile, 0L));
+ return;
+ }
+ performTrashCurrentImage(viewer);
+}
+
+void KuickShow::performDeleteCurrentImage(QWidget *parent)
+{
+ assert(fileWidget != 0L);
+
+ KFileItemList list;
+ KFileItem *item = fileWidget->getCurrentItem(false);
+ list.append (item);
+
+ if (KMessageBox::warningContinueCancel(
+ parent,
+ i18n("<qt>Do you really want to delete\n <b>'%1'</b>?</qt>").arg(item->url().pathOrURL()),
+ i18n("Delete File"),
+ KStdGuiItem::del(),
+ "Kuick_delete_current_image")
+ != KMessageBox::Continue)
+ {
+ return;
+ }
+
+ tryShowNextImage();
+ fileWidget->del(list, false, false);
+}
+
+void KuickShow::performTrashCurrentImage(QWidget *parent)
+{
+ assert(fileWidget != 0L);
+
+ KFileItemList list;
+ KFileItem *item = fileWidget->getCurrentItem(false);
+ if (!item) return;
+
+ list.append (item);
+
+ if (KMessageBox::warningContinueCancel(
+ parent,
+ i18n("<qt>Do you really want to trash\n <b>'%1'</b>?</qt>").arg(item->url().pathOrURL()),
+ i18n("Trash File"),
+ KGuiItem(i18n("to trash", "&Trash"),"edittrash"),
+ "Kuick_trash_current_image")
+ != KMessageBox::Continue)
+ {
+ return;
+ }
+
+ tryShowNextImage();
+ fileWidget->trash(list, parent, false, false);
+}
+
+void KuickShow::tryShowNextImage()
+{
+ // move to next file item even if we have no viewer
+ KFileItem *next = fileWidget->getNext(true);
+ if (!next)
+ next = fileWidget->getPrevious(true);
+
+ // ### why is this necessary at all? Why does KDirOperator suddenly re-read the
+ // entire directory after a file was deleted/trashed!? (KDirNotify is the reason)
+ if (!m_viewer)
+ return;
+
+ if (next)
+ showImage(next, false);
+ else
+ {
+ if (!haveBrowser())
+ {
+ // ### when simply calling toggleBrowser(), this main window is completely messed up
+ QTimer::singleShot(0, this, SLOT(toggleBrowser()));
+ }
+ m_viewer->deleteLater();
+ }
+}
+
+void KuickShow::startSlideShow()
+{
+ KFileItem *item = kdata->slideshowStartAtFirst ?
+ fileWidget->gotoFirstImage() :
+ fileWidget->getCurrentItem(false);
+
+ if ( item ) {
+ m_slideshowCycle = 1;
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( false );
+ showImage( item, !oneWindowAction->isChecked(),
+ kdata->slideshowFullscreen );
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+ }
+}
+
+void KuickShow::pauseSlideShow()
+{
+ if(m_slideShowStopped) {
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+ m_slideShowStopped = false;
+ }
+ else {
+ m_slideTimer->stop();
+ m_slideShowStopped = true;
+ }
+}
+
+void KuickShow::nextSlide()
+{
+ if ( !m_viewer ) {
+ m_slideshowCycle = 1;
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+ return;
+ }
+
+ KFileItem *item = fileWidget->getNext( true );
+ if ( !item ) { // last image
+ if ( m_slideshowCycle < kdata->slideshowCycles
+ || kdata->slideshowCycles == 0 ) {
+ item = fileWidget->gotoFirstImage();
+ if ( item ) {
+ nextSlide( item );
+ m_slideshowCycle++;
+ return;
+ }
+ }
+
+ m_viewer->close( true );
+ fileWidget->actionCollection()->action("kuick_slideshow")->setEnabled( true );
+ return;
+ }
+
+ nextSlide( item );
+}
+
+void KuickShow::nextSlide( KFileItem *item )
+{
+ m_viewer->showNextImage( item->url() );
+ if(kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+}
+
+
+// prints the selected files in the filebrowser
+void KuickShow::slotPrint()
+{
+ const KFileItemList *items = fileWidget->selectedItems();
+ if ( !items )
+ return;
+
+ KFileItemListIterator it( *items );
+
+ // don't show the image, just print
+ ImageWindow *iw = new ImageWindow( 0, id, this, "printing image" );
+ KFileItem *item;
+ while ( (item = it.current()) ) {
+ if (FileWidget::isImage( item ) && iw->loadImage( item->url() ))
+ iw->printImage();
+ ++it;
+ }
+
+ iw->close( true );
+}
+
+void KuickShow::slotShowInOtherWindow()
+{
+ showImage( fileWidget->getCurrentItem( false ), true );
+}
+
+void KuickShow::slotShowInSameWindow()
+{
+ showImage( fileWidget->getCurrentItem( false ), false );
+}
+
+void KuickShow::slotShowFullscreen()
+{
+ showImage( fileWidget->getCurrentItem( false ), false, true );
+}
+
+void KuickShow::slotDropped( const KFileItem *, QDropEvent *, const KURL::List &urls)
+{
+ KURL::List::ConstIterator it = urls.begin();
+ for ( ; it != urls.end(); ++it )
+ {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, *it );
+ if ( FileWidget::isImage( &item ) )
+ showImage( &item, true );
+ else
+ fileWidget->setURL( *it, true );
+ }
+}
+
+// try to init the WM border as it is 0,0 when the window is not shown yet.
+void KuickShow::show()
+{
+ KMainWindow::show();
+ (void) Kuick::frameSize( winId() );
+}
+
+void KuickShow::slotAdvanceImage( ImageWindow *view, int steps )
+{
+ KFileItem *item = 0L; // to be shown
+ KFileItem *item_next = 0L; // to be cached
+
+ if ( steps == 0 )
+ return;
+
+ // the viewer might not be available yet. Factor this out somewhen.
+ if ( !fileWidget ) {
+ if ( m_delayedRepeatItem )
+ return;
+
+ delayAction(new DelayedRepeatEvent( view, DelayedRepeatEvent::AdvanceViewer, new int(steps) ));
+ return;
+ }
+
+ if ( steps > 0 ) {
+ for ( int i = 0; i < steps; i++ )
+ item = fileWidget->getNext( true );
+ item_next = fileWidget->getNext( false );
+ }
+
+ else if ( steps < 0 ) {
+ for ( int i = steps; i < 0; i++ )
+ item = fileWidget->getPrevious( true );
+ item_next = fileWidget->getPrevious( false );
+ }
+
+ if ( FileWidget::isImage( item ) ) {
+// QString filename;
+// KIO::NetAccess::download(item->url(), filename, this);
+ view->showNextImage( item->url() );
+ if (m_slideTimer->isActive() && kdata->slideDelay)
+ m_slideTimer->start( kdata->slideDelay );
+
+ if ( kdata->preloadImage && item_next ) { // preload next image
+ if ( FileWidget::isImage( item_next ) )
+ view->cacheImage( item_next->url() );
+ }
+
+ }
+}
+
+bool KuickShow::eventFilter( QObject *o, QEvent *e )
+{
+ if ( m_delayedRepeatItem ) // we probably need to install an eventFilter over
+ {
+ return true; // kapp, to make it really safe
+ }
+
+ bool ret = false;
+ int eventType = e->type();
+ QKeyEvent *k = 0L;
+ if ( eventType == QEvent::KeyPress )
+ k = static_cast<QKeyEvent *>( e );
+
+ if ( k ) {
+ if ( KStdAccel::quit().contains( KKey( k ) ) ) {
+ saveSettings();
+ deleteAllViewers();
+ FileCache::shutdown();
+ ::exit(0);
+ }
+ else if ( KStdAccel::help().contains( KKey( k ) ) ) {
+ appHelpActivated();
+ return true;
+ }
+ }
+
+
+ ImageWindow *window = dynamic_cast<ImageWindow*>( o );
+
+ if ( window ) {
+ // The XWindow used to display Imlib's image is being resized when
+ // switching images, causing enter- and leaveevents for this
+ // ImageWindow, leading to the cursor being unhidden. So we simply
+ // don't pass those events to KCursor to prevent that.
+ if ( eventType != QEvent::Leave && eventType != QEvent::Enter )
+ KCursor::autoHideEventFilter( o, e );
+
+ m_viewer = window;
+ QString img;
+ KFileItem *item = 0L; // the image to be shown
+ KFileItem *item_next = 0L; // the image to be cached
+
+ if ( k ) { // keypress
+ ret = true;
+ int key = k->key();
+
+ // Key_Shift shouldn't load the browser in nobrowser mode, it
+ // is used for zooming in the imagewindow
+ // Key_Alt shouldn't either - otherwise Alt+F4 doesn't work, the
+ // F4 gets eaten (by NetAccess' modal dialog maybe?)
+
+ if ( !fileWidget )
+ {
+ if ( key != Key_Escape && key != Key_Shift && key != Key_Alt )
+ {
+ KuickFile *file = m_viewer->currentFile();
+// QFileInfo fi( m_viewer->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( file->url().upURL() );
+
+ // the fileBrowser will list the start-directory
+ // asynchronously so we can't immediately continue. There
+ // is no current-item and no next-item (actually no item
+ // at all). So we tell the browser the initial
+ // current-item and wait for it to tell us when it's ready.
+ // Then we will replay this KeyEvent.
+ delayedRepeatEvent( m_viewer, k );
+
+ // OK, once again, we have a problem with the now async and
+ // sync KDirLister :( If the startDir is already cached by
+ // KDirLister, we won't ever get that finished() signal
+ // because it is emitted before we can connect(). So if
+ // our dirlister has a rootFileItem, we assume the
+ // directory is read already and simply call
+ // slotReplayEvent() without the need for the finished()
+ // signal.
+
+ // see slotAdvanceImage() for similar code
+ if ( fileWidget->dirLister()->isFinished() )
+ {
+ if ( fileWidget->dirLister()->rootItem() )
+ {
+ fileWidget->setCurrentItem( file->url().fileName() );
+ QTimer::singleShot( 0, this, SLOT( slotReplayEvent()));
+ }
+ else // finished, but no root-item -- probably an error, kill repeat-item!
+ {
+ abortDelayedEvent();
+ }
+ }
+ else // not finished yet
+ {
+ fileWidget->setInitialItem( file->url().fileName() );
+ connect( fileWidget, SIGNAL( finished() ),
+ SLOT( slotReplayEvent() ));
+ }
+
+ return true;
+ }
+
+ return KMainWindow::eventFilter( o, e );
+ }
+
+ // we definitely have a fileWidget here!
+
+ KKey kkey( k );
+ if ( key == Key_Home || KStdAccel::home().contains( kkey ) )
+ {
+ item = fileWidget->gotoFirstImage();
+ item_next = fileWidget->getNext( false );
+ }
+
+ else if ( key == Key_End || KStdAccel::end().contains( kkey ) )
+ {
+ item = fileWidget->gotoLastImage();
+ item_next = fileWidget->getPrevious( false );
+ }
+
+ else if ( fileWidget->actionCollection()->action("delete")->shortcut().contains( key ))
+ {
+ kdDebug() << "WOW, deletion happens here!" << endl;
+// KFileItem *cur = fileWidget->getCurrentItem( false );
+ (void) fileWidget->getCurrentItem( false );
+ item = fileWidget->getNext( false ); // don't move
+ if ( !item )
+ item = fileWidget->getPrevious( false );
+ KFileItem it( KFileItem::Unknown, KFileItem::Unknown,
+ m_viewer->url() );
+ KFileItemList list;
+ list.append( &it );
+ if ( fileWidget->del(list, window,
+ (k->state() & ShiftButton) == 0) == 0L )
+ return true; // aborted deletion
+
+ // ### check failure asynchronously and restore old item?
+ fileWidget->setCurrentItem( item );
+ }
+
+ else if ( m_toggleBrowserAction->shortcut().contains( key ) )
+ {
+ toggleBrowser();
+ return true; // don't pass keyEvent
+ }
+
+ else
+ ret = false;
+
+
+ if ( FileWidget::isImage( item ) ) {
+// QString filename;
+// KIO::NetAccess::download(item->url(), filename, this);
+ m_viewer->showNextImage( item->url() );
+
+ if ( kdata->preloadImage && item_next ) { // preload next image
+ if ( FileWidget::isImage( item_next ) )
+ m_viewer->cacheImage( item_next->url() );
+ }
+
+ ret = true; // don't pass keyEvent
+ }
+ } // keyPressEvent on ImageWindow
+
+
+ // doubleclick closes image window
+ // and shows browser when last window closed via doubleclick
+ else if ( eventType == QEvent::MouseButtonDblClick )
+ {
+ QMouseEvent *ev = static_cast<QMouseEvent*>( e );
+ if ( ev->button() == LeftButton )
+ {
+ if ( s_viewers.count() == 1 )
+ {
+ if ( !fileWidget )
+ {
+// KURL start;
+// QFileInfo fi( window->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( window->currentFile()->url().fileName() );
+ }
+ show();
+ raise();
+ }
+
+ window->close( true );
+
+ ev->accept();
+ ret = true;
+ }
+ }
+
+ } // isA ImageWindow
+
+
+ if ( ret )
+ return true;
+
+ return KMainWindow::eventFilter( o, e );
+}
+
+void KuickShow::configuration()
+{
+ if ( !m_accel ) {
+ KURL start;
+ start.setPath( QDir::homeDirPath() );
+ initGUI( KURL::fromPathOrURL( QDir::homeDirPath() ) );
+ }
+
+ dialog = new KuickConfigDialog( fileWidget->actionCollection(), 0L,
+ "dialog", false );
+ dialog->resize( 540, 510 );
+ dialog->setIcon( kapp->miniIcon() );
+
+ connect( dialog, SIGNAL( okClicked() ),
+ this, SLOT( slotConfigApplied() ) );
+ connect( dialog, SIGNAL( applyClicked() ),
+ this, SLOT( slotConfigApplied() ) );
+ connect( dialog, SIGNAL( finished() ),
+ this, SLOT( slotConfigClosed() ) );
+
+ fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( false );
+ dialog->show();
+}
+
+
+void KuickShow::slotConfigApplied()
+{
+ dialog->applyConfig();
+
+ initImlib();
+ kdata->save();
+
+ ImageWindow *viewer;
+ QValueListIterator<ImageWindow*> it = s_viewers.begin();
+ while ( it != s_viewers.end() ) {
+ viewer = *it;
+ viewer->updateActions();
+ ++it;
+ }
+
+ fileWidget->reloadConfiguration();
+}
+
+
+void KuickShow::slotConfigClosed()
+{
+ dialog->delayedDestruct();
+ fileWidget->actionCollection()->action( "kuick_configure" )->setEnabled( true );
+}
+
+void KuickShow::about()
+{
+ if ( !aboutWidget )
+ aboutWidget = new AboutWidget( 0L, "about" );
+
+ aboutWidget->adjustSize();
+
+#if KDE_VERSION >= 310
+ KDialog::centerOnScreen( aboutWidget );
+#else
+// Not fixed because it must be dead code now.
+ QDesktopWidget *desktop = QApplication::desktop();
+ int screen = desktop->screenNumber( aboutWidget );
+ if ( screen == -1 )
+ screen = desktop->primaryScreen();
+
+ QRect r = desktop->screenGeometry( screen );
+ aboutWidget->move( r.center().x() - aboutWidget->width()/2,
+ r.center().y() - aboutWidget->height()/2 );
+#endif
+
+ aboutWidget->show();
+}
+
+// ------ sessionmanagement - load / save current directory -----
+void KuickShow::readProperties( KConfig *kc )
+{
+ assert( fileWidget ); // from SM, we should always have initGUI on startup
+ QString dir = kc->readPathEntry( "CurrentDirectory" );
+ if ( !dir.isEmpty() ) {
+ fileWidget->setURL( KURL::fromPathOrURL( dir ), true );
+ fileWidget->clearHistory();
+ }
+
+ const KURL& listedURL = fileWidget->url();
+ QStringList images = kc->readPathListEntry( "Images shown" );
+ QStringList::Iterator it;
+ bool hasCurrentURL = false;
+
+ for ( it = images.begin(); it != images.end(); ++it ) {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL( *it ), false );
+ if ( item.isReadable() )
+ if ( showImage( &item, true ) ) {
+ // Set the current URL in the file widget, if possible
+ if ( !hasCurrentURL && listedURL.isParentOf( item.url() ))
+ fileWidget->setInitialItem( item.url().fileName() );
+ hasCurrentURL = true;
+ }
+ }
+
+ bool visible = kc->readBoolEntry( "Browser visible", false );
+ if ( visible || s_viewers.isEmpty() )
+ show();
+}
+
+void KuickShow::saveProperties( KConfig *kc )
+{
+ kc->writeEntry( "Browser visible", fileWidget && fileWidget->isVisible() );
+ if (fileWidget)
+ kc->writePathEntry( "CurrentDirectory", fileWidget->url().url() );
+
+ QStringList urls;
+ QValueListIterator<ImageWindow*> it;
+ for ( it = s_viewers.begin(); it != s_viewers.end(); ++it )
+ {
+ const KURL& url = (*it)->currentFile()->url();
+ if ( url.isLocalFile() )
+ urls.append( url.path() );
+ else
+ urls.append( url.prettyURL() ); // ### check if writePathEntry( prettyURL ) works!
+ }
+
+ kc->writePathEntry( "Images shown", urls );
+}
+
+// --------------------------------------------------------------
+
+void KuickShow::saveSettings()
+{
+ KConfig *kc = KGlobal::config();
+
+ kc->setGroup("SessionSettings");
+ if ( oneWindowAction )
+ kc->writeEntry( "OpenImagesInActiveWindow", oneWindowAction->isChecked() );
+
+ if ( fileWidget ) {
+ kc->writePathEntry( "CurrentDirectory", fileWidget->url().prettyURL() ); // ### was url().url()
+ fileWidget->writeConfig( kc, "Filebrowser" );
+ }
+
+ kc->sync();
+}
+
+
+void KuickShow::messageCantLoadImage( const KuickFile *, const QString& message )
+{
+ m_viewer->clearFocus();
+ KMessageBox::information( m_viewer, message, i18n("Error"), "kuick_cant_load_image" );
+}
+
+void KuickShow::initImlib()
+{
+ ImData *idata = kdata->idata;
+ ImlibInitParams par;
+ initImlibParams( idata, &par );
+
+ id = Imlib_init_with_params( x11Display(), &par );
+ if ( !id ) {
+ initImlibParams( idata, &par );
+
+ qWarning("*** KuickShow: Whoops, can't initialize imlib, trying my own palettefile now.");
+ QString paletteFile = locate( "data", "kuickshow/im_palette.pal" );
+ // ### - does the qstrdup() cure the segfault in imlib eventually?
+ char *file = qstrdup( paletteFile.local8Bit() );
+ par.palettefile = file;
+ par.flags |= PARAMS_PALETTEFILE;
+
+ qWarning("Palettefile: %s", par.palettefile );
+
+ id = Imlib_init_with_params( x11Display(), &par );
+
+ if ( !id ) {
+ QString tmp = i18n("Unable to initialize \"Imlib\".\n"
+ "Start kuickshow from the command line "
+ "and look for error messages.\n"
+ "The program will now quit.");
+ KMessageBox::error( this, tmp, i18n("Fatal Imlib Error") );
+
+ FileCache::shutdown();
+ ::exit(1);
+ }
+ }
+}
+
+
+void KuickShow::initImlibParams( ImData *idata, ImlibInitParams *par )
+{
+ par->flags = ( PARAMS_REMAP | PARAMS_VISUALID | PARAMS_SHAREDMEM | PARAMS_SHAREDPIXMAPS |
+ PARAMS_FASTRENDER | PARAMS_HIQUALITY | PARAMS_DITHER |
+ PARAMS_IMAGECACHESIZE | PARAMS_PIXMAPCACHESIZE );
+
+ Visual* defaultvis = DefaultVisual(x11Display(), x11Screen());
+
+ par->paletteoverride = idata->ownPalette ? 1 : 0;
+ par->remap = idata->fastRemap ? 1 : 0;
+ par->fastrender = idata->fastRender ? 1 : 0;
+ par->hiquality = idata->dither16bit ? 1 : 0;
+ par->dither = idata->dither8bit ? 1 : 0;
+ par->sharedmem = 1;
+ par->sharedpixmaps = 1;
+ par->visualid = defaultvis->visualid;
+ uint maxcache = idata->maxCache;
+
+ // 0 == no cache
+ par->imagecachesize = maxcache * 1024;
+ par->pixmapcachesize = maxcache * 1024;
+}
+
+bool KuickShow::haveBrowser() const
+{
+ return fileWidget && fileWidget->isVisible();
+}
+
+void KuickShow::delayedRepeatEvent( ImageWindow *w, QKeyEvent *e )
+{
+ m_delayedRepeatItem = new DelayedRepeatEvent( w, new QKeyEvent( *e ) );
+}
+
+void KuickShow::abortDelayedEvent()
+{
+ delete m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L;
+}
+
+void KuickShow::slotReplayEvent()
+{
+ disconnect( fileWidget, SIGNAL( finished() ),
+ this, SLOT( slotReplayEvent() ));
+
+ DelayedRepeatEvent *e = m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L; // otherwise, eventFilter aborts
+
+ eventFilter( e->viewer, e->event );
+ delete e;
+
+ // ### WORKAROUND for QIconView bug in Qt <= 3.0.3 at least
+ if ( fileWidget && fileWidget->view() ) {
+ QWidget *widget = fileWidget->view()->widget();
+ if ( widget->inherits( "QIconView" ) || widget->child(0, "QIconView" ) ){
+ fileWidget->setSorting( fileWidget->sorting() );
+ }
+ }
+ // --------------------------------------------------------------
+}
+
+void KuickShow::replayAdvance(DelayedRepeatEvent *event)
+{
+ // ### WORKAROUND for QIconView bug in Qt <= 3.0.3 at least
+ // Sigh. According to qt-bugs, they won't fix this bug ever. So you can't
+ // rely on sorting to be correct before the QIconView has been show()n.
+ if ( fileWidget && fileWidget->view() ) {
+ QWidget *widget = fileWidget->view()->widget();
+ if ( widget->inherits( "QIconView" ) || widget->child(0, "QIconView" ) ){
+ fileWidget->setSorting( fileWidget->sorting() );
+ }
+ }
+ // --------------------------------------------------------------
+
+ slotAdvanceImage( event->viewer, *(int *) (event->data) );
+}
+
+void KuickShow::delayAction(DelayedRepeatEvent *event)
+{
+ if (m_delayedRepeatItem)
+ return;
+
+ m_delayedRepeatItem = event;
+
+ KURL url = event->viewer->currentFile()->url();
+// QFileInfo fi( event->viewer->filename() );
+// start.setPath( fi.dirPath( true ) );
+ initGUI( url.upURL() );
+
+ // see eventFilter() for explanation and similar code
+ if ( fileWidget->dirLister()->isFinished() &&
+ fileWidget->dirLister()->rootItem() )
+ {
+ fileWidget->setCurrentItem( url.fileName() );
+ QTimer::singleShot( 0, this, SLOT( doReplay()));
+ }
+ else
+ {
+ fileWidget->setInitialItem( url.fileName() );
+ connect( fileWidget, SIGNAL( finished() ),
+ SLOT( doReplay() ));
+ }
+}
+
+void KuickShow::doReplay()
+{
+ if (!m_delayedRepeatItem)
+ return;
+
+ disconnect( fileWidget, SIGNAL( finished() ),
+ this, SLOT( doReplay() ));
+
+ switch (m_delayedRepeatItem->action)
+ {
+ case DelayedRepeatEvent::DeleteCurrentFile:
+ performDeleteCurrentImage((QWidget *) m_delayedRepeatItem->data);
+ break;
+ case DelayedRepeatEvent::TrashCurrentFile:
+ performTrashCurrentImage((QWidget *) m_delayedRepeatItem->data);
+ break;
+ case DelayedRepeatEvent::AdvanceViewer:
+ replayAdvance(m_delayedRepeatItem);
+ break;
+ default:
+ kdWarning() << "doReplay: unknown action -- ignoring: " << m_delayedRepeatItem->action << endl;
+ break;
+ }
+
+ delete m_delayedRepeatItem;
+ m_delayedRepeatItem = 0L;
+}
+
+void KuickShow::toggleBrowser()
+{
+ if ( !haveBrowser() ) {
+ if ( m_viewer && m_viewer->isFullscreen() )
+ m_viewer->setFullscreen( false );
+ fileWidget->resize( size() ); // ### somehow fileWidget isn't resized!?
+ show();
+ raise();
+ KWin::activateWindow( winId() ); // ### this should not be necessary
+// setFocus();
+ }
+ else if ( !s_viewers.isEmpty() )
+ hide();
+}
+
+void KuickShow::slotOpenURL()
+{
+ KFileDialog dlg(QString::null, kdata->fileFilter, this, "filedialog", true);
+ dlg.setMode( KFile::Files | KFile::Directory );
+ dlg.setCaption( i18n("Select Files or Folder to Open") );
+
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ KURL::List urls = dlg.selectedURLs();
+ KURL::List::ConstIterator it = urls.begin();
+ for ( ; it != urls.end(); ++it )
+ {
+ KFileItem item( KFileItem::Unknown, KFileItem::Unknown, *it );
+ if ( FileWidget::isImage( &item ) )
+ showImage( &item, true );
+ else
+ fileWidget->setURL( *it, true );
+ }
+ }
+}
+
+void KuickShow::deleteAllViewers()
+{
+ QValueListIterator<ImageWindow*> it = s_viewers.begin();
+ for ( ; it != s_viewers.end(); ++it ) {
+ (*it)->disconnect( SIGNAL( destroyed() ), this, SLOT( viewerDeleted() ));
+ (*it)->close( true );
+ }
+
+ s_viewers.clear();
+ m_viewer = 0L;
+}
+
+KActionCollection * KuickShow::actionCollection() const
+{
+ if ( fileWidget )
+ return fileWidget->actionCollection();
+
+ return KMainWindow::actionCollection();
+}
+
+#include "kuickshow.moc"
diff --git a/kuickshow/src/kuickshow.desktop b/kuickshow/src/kuickshow.desktop
new file mode 100644
index 00000000..b2e2ee37
--- /dev/null
+++ b/kuickshow/src/kuickshow.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Name=Kuickshow
+Name[af]=Vinnig-vertoon
+Name[ar]=عرض سريع
+Name[eo]=Rapidmontrilo
+Name[fr]=KuickShow
+Name[hi]=क्विक-शो
+Name[it]=KuickShow
+Name[ko]=K퀵쇼
+Name[ne]=क्विकशो
+Name[pt_BR]=KRápida Exibição
+Name[ta]=விரைவுகாட்சி
+Name[th]=ดูภาพด่วน - K
+Name[ven]=Musumbedzo wa kuick
+Name[zh_TW]=Kuickshow 快秀
+Name[zu]=I Kuickshow
+Exec=kuickshow %i %m -caption "%c" %U
+Icon=kuickshow
+Type=Application
+MimeType=image/gif;image/x-xpm;image/x-xbm;image/jpeg;image/png;image/tiff;image/x-bmp;image/x-psd;image/x-eim;image/x-portable-bitmap;image/x-portable-pixmap;image/x-portable-greymap;
+DocPath=kuickshow/index.html
+Terminal=false
+InitialPreference=6
+
+GenericName=Image Viewer
+GenericName[af]=Beeld Aansig
+GenericName[ar]=عارض صور
+GenericName[bg]=Преглед на изображения
+GenericName[br]=Gweler ar skeudennoù
+GenericName[bs]=Preglednik slika
+GenericName[ca]=Visualitzador d'imatges
+GenericName[cs]=Prohlížeč obrázků
+GenericName[cy]=Gwelydd Delweddau
+GenericName[da]=Billedfremviser
+GenericName[de]=Bildbetrachter
+GenericName[el]=Προβολέας εικόνων
+GenericName[eo]=Bildorigardilo
+GenericName[es]=Visor de imágenes
+GenericName[et]=Pildifailide näitaja
+GenericName[eu]=Irudi ikustailua
+GenericName[fa]=مشاهده‌گر تصویر
+GenericName[fi]=Kuvannäytin
+GenericName[fr]=Afficheur d'images
+GenericName[ga]=Amharcán Íomhánna
+GenericName[gl]=Visor de imaxes
+GenericName[he]=מציג תמונות
+GenericName[hi]=छवि प्रदर्शक
+GenericName[hr]=Preglednik slika
+GenericName[hu]=Képnézegető
+GenericName[is]=Myndaskoðari
+GenericName[it]=Visore di immagini
+GenericName[ja]=画像ビューア
+GenericName[kk]=Кескіндерді қарау
+GenericName[km]=កម្មវិធី​មើល​រូបភាព
+GenericName[lt]=Paveikslėlių žiūriklis
+GenericName[lv]=Attēlu Skatītājs
+GenericName[ms]=Paparan Imej
+GenericName[mt]=Werrej tal-istampi
+GenericName[nb]=Bildefremviser
+GenericName[nds]=Bildkieker
+GenericName[ne]=छवि दर्शक
+GenericName[nl]=Afbeeldingenweergaveprogramma
+GenericName[nn]=Biletvisar
+GenericName[nso]=Molebeledi wa Ponagalo
+GenericName[pa]=ਚਿੱਤਰ ਦਰਸ਼ਕ
+GenericName[pl]=Przeglądarka obrazków
+GenericName[pt]=Visualizador de Imagens
+GenericName[pt_BR]=Visualizador de Imagens
+GenericName[ro]=Vizualizor de imagini
+GenericName[ru]=Просмотр изображений
+GenericName[rw]=Mugaraza Shusho
+GenericName[se]=Govvačájeheaddji
+GenericName[sk]=Prehliadač obrázkov
+GenericName[sl]=Pregledovalnik slik
+GenericName[sr]=Приказивач слика
+GenericName[sr@Latn]=Prikazivač slika
+GenericName[sv]=Bildvisare
+GenericName[ta]=பிம்ப காட்சி
+GenericName[tg]=Намоиши тасвирот
+GenericName[th]=เครื่องมือแสดงภาพ
+GenericName[tr]=Resim Göstericisi
+GenericName[uk]=Переглядач зображень
+GenericName[uz]=Rasm koʻruvchi
+GenericName[uz@cyrillic]=Расм кўрувчи
+GenericName[ven]=Tshivhoni tsha Mutaleli
+GenericName[wa]=Håyneu d' imådjes
+GenericName[xh]=Umboniseli Womfanekiso
+GenericName[zh_CN]=图片查看程序
+GenericName[zh_HK]=圖像檢視器
+GenericName[zh_TW]=影像檢視程式
+GenericName[zu]=Umbonisi Womfanekiso
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Graphics;
diff --git a/kuickshow/src/kuickshow.h b/kuickshow/src/kuickshow.h
new file mode 100644
index 00000000..d6239b64
--- /dev/null
+++ b/kuickshow/src/kuickshow.h
@@ -0,0 +1,178 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2006 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KUICKSHOW_H
+#define KUICKSHOW_H
+
+#include <qevent.h>
+#include <qguardedptr.h>
+#include <qstring.h>
+#include <qvaluelist.h>
+
+#include <kfileitem.h>
+#include <kmainwindow.h>
+#include <kurl.h>
+
+#include <Imlib.h>
+
+#include "aboutwidget.h"
+
+class FileWidget;
+class ImageWindow;
+class ImData;
+class KuickConfigDialog;
+
+class KAccel;
+class KConfig;
+class KToggleAction;
+class AboutWidget;
+
+class KURL;
+class KURLComboBox;
+
+class KuickFile;
+
+class DelayedRepeatEvent
+{
+public:
+ DelayedRepeatEvent( ImageWindow *view, QKeyEvent *ev ) {
+ viewer = view;
+ event = ev;
+ }
+ DelayedRepeatEvent( ImageWindow *view, int action, void *data ) {
+ this->viewer = view;
+ this->action = action;
+ this->data = data;
+ this->event = 0L;
+ }
+
+ ~DelayedRepeatEvent() {
+ delete event;
+ }
+
+ enum Action
+ {
+ DeleteCurrentFile,
+ TrashCurrentFile,
+ AdvanceViewer
+ };
+
+ ImageWindow *viewer;
+ QKeyEvent *event;
+ int action;
+ void *data;
+};
+
+
+class KuickShow : public KMainWindow
+{
+ Q_OBJECT
+
+public:
+ KuickShow( const char *name=0 );
+ ~KuickShow();
+
+ virtual void show();
+ static QValueList<ImageWindow*> s_viewers;
+
+ // overridden to make KDCOPActionProxy work -- all our actions are not
+ // in the mainwindow's collection, but in the filewidget's.
+ virtual KActionCollection* actionCollection() const;
+
+
+protected:
+ virtual void readProperties( KConfig * );
+ void initImlibParams( ImData *, ImlibInitParams * );
+ void tryShowNextImage();
+
+private slots:
+ void toggleBrowser();
+ void slotQuit() { delete this; }
+ void slotPrint();
+ void slotConfigApplied();
+ void slotConfigClosed();
+ void messageCantLoadImage( const KuickFile * file, const QString& message);
+ bool showImage(const KFileItem *, bool newWindow = false,
+ bool fullscreen = false, bool moveToTopLeft = true );
+ void showFileItem( ImageWindow *, const KFileItem * );
+ void slotHighlighted( const KFileItem * );
+ void slotSelected( const KFileItem * );
+ void dirSelected( const KURL& );
+ void configuration();
+ void about();
+ void startSlideShow();
+ void pauseSlideShow();
+ void nextSlide();
+ void nextSlide( KFileItem *item );
+ void viewerDeleted();
+ void slotDropped( const KFileItem *, QDropEvent *, const KURL::List &);
+ void slotSetActiveViewer( ImageWindow *i ) { m_viewer = i; }
+ void slotAdvanceImage( ImageWindow *, int steps );
+
+ void slotShowInSameWindow();
+ void slotShowInOtherWindow();
+ void slotShowFullscreen();
+
+ void slotReplayEvent();
+ void slotOpenURL();
+ void slotSetURL( const KURL& );
+ void slotURLComboReturnPressed();
+// void invalidateImages( const KFileItemList& items );
+ void slotDeleteCurrentImage(ImageWindow *viewer);
+ void slotTrashCurrentImage(ImageWindow *viewer);
+ void slotDeleteCurrentImage();
+ void slotTrashCurrentImage();
+
+ void doReplay();
+
+private:
+ void initGUI( const KURL& startDir );
+ bool eventFilter( QObject *, QEvent * );
+ void initImlib();
+ void saveProperties( KConfig * );
+ void saveSettings();
+ bool haveBrowser() const;
+ void delayedRepeatEvent( ImageWindow *, QKeyEvent * );
+ void abortDelayedEvent();
+ void deleteAllViewers();
+ void redirectDeleteAndTrashActions(KActionCollection *coll);
+
+ void delayAction(DelayedRepeatEvent *event);
+ void replayAdvance(DelayedRepeatEvent *event);
+
+ void performDeleteCurrentImage(QWidget *parent);
+ void performTrashCurrentImage(QWidget *parent);
+
+ uint viewItem, renameItem, deleteItem, printItem;
+ uint m_slideshowCycle;
+
+ FileWidget *fileWidget;
+ KURLComboBox *cmbPath;
+ KuickConfigDialog *dialog;
+ ImlibData *id;
+ ImageWindow *m_viewer;
+ KToggleAction *oneWindowAction;
+ KAccel *m_accel;
+ DelayedRepeatEvent *m_delayedRepeatItem;
+ QTimer *m_slideTimer;
+ bool m_slideShowStopped;
+ KToggleAction *m_toggleBrowserAction;
+ QGuardedPtr<AboutWidget> aboutWidget;
+};
+
+#endif
diff --git a/kuickshow/src/kurlwidget.cpp b/kuickshow/src/kurlwidget.cpp
new file mode 100644
index 00000000..0a23fa3a
--- /dev/null
+++ b/kuickshow/src/kurlwidget.cpp
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qtooltip.h>
+
+#include <kurl.h>
+#include <krun.h>
+
+#include "kurlwidget.h"
+
+KURLWidget::KURLWidget(const QString& text, QWidget *parent, const char *name)
+ : KURLLabel( parent, name )
+{
+ setText( text );
+ connect( this, SIGNAL( leftClickedURL() ), SLOT( run() ));
+ setUseTips( true );
+}
+
+void KURLWidget::run()
+{
+ KURL ku( url() );
+ if ( ku.isValid() ) {
+ (void) new KRun( ku, this );
+ }
+}
+
+#include "kurlwidget.moc"
diff --git a/kuickshow/src/kurlwidget.h b/kuickshow/src/kurlwidget.h
new file mode 100644
index 00000000..2f35e009
--- /dev/null
+++ b/kuickshow/src/kurlwidget.h
@@ -0,0 +1,36 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999,2000 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KURLWIDGET_H
+#define KURLWIDGET_H
+
+#include <kurllabel.h>
+
+class KURLWidget : public KURLLabel
+{
+ Q_OBJECT
+
+public:
+ KURLWidget( const QString& text, QWidget *, const char *name=0 );
+
+protected slots:
+ virtual void run();
+
+};
+
+#endif
diff --git a/kuickshow/src/main.cpp b/kuickshow/src/main.cpp
new file mode 100644
index 00000000..dfb462f0
--- /dev/null
+++ b/kuickshow/src/main.cpp
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998-2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qstring.h>
+
+#include <kaboutdata.h>
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kuickshow.h"
+#include "version.h"
+
+static KCmdLineOptions options[] =
+{
+ { "lastfolder", I18N_NOOP("Start in the last visited folder, not the "
+ "current working folder."), 0 },
+ { "d", 0, 0 }, // short option for --lastdir
+ { "+[files]", I18N_NOOP("Optional image filenames/urls to show"), 0 },
+ KCmdLineLastOption
+};
+
+extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
+{
+ KAboutData about(
+ "kuickshow", I18N_NOOP( "KuickShow" ), KUICKSHOWVERSION,
+ I18N_NOOP("A fast and versatile image viewer" ),
+ KAboutData::License_GPL, "(c) 1998-2006, Carsten Pfeiffer",
+ 0 /*text*/, "http://devel-home.kde.org/~pfeiffer/" );
+
+ about.addAuthor( "Carsten Pfeiffer", 0, "[email protected]",
+ "http://devel-home.kde.org/~pfeiffer/" );
+ about.addCredit( "Rober Hamberger", 0, "[email protected]" );
+ about.addCredit( "Thorsten Scheuermann", 0, "[email protected]" );
+
+ KCmdLineArgs::init( argc, argv, &about );
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+
+ if ( app.isRestored() ) {
+ (new KuickShow())->restore( 1, false ); // don't show automatically
+ }
+ else {
+ KuickShow *k = new KuickShow( "kuickshow" );
+ app.setMainWidget( k );
+ }
+
+ return app.exec();
+}
diff --git a/kuickshow/src/mainwidget.cpp b/kuickshow/src/mainwidget.cpp
new file mode 100644
index 00000000..caa6700c
--- /dev/null
+++ b/kuickshow/src/mainwidget.cpp
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998,1999 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "fileview.h"
+#include "kuickdata.h"
+#include "mainwidget.h"
+
+
+MainWidget::MainWidget( QString startDir, QWidget *parent,
+ const char *name ) : QWidget ( parent, name )
+{
+ box = new FileView( startDir, true, (QDir::Dirs | QDir::Files),
+ this, "fileview" );
+}
+
+
+MainWidget::~MainWidget()
+{
+
+}
+
+
+// for now, no layout managers
+void MainWidget::resizeEvent( QResizeEvent * )
+{
+ box->resize( width(), height() );
+}
+#include "mainwidget.moc"
diff --git a/kuickshow/src/mainwidget.h b/kuickshow/src/mainwidget.h
new file mode 100644
index 00000000..36285dd8
--- /dev/null
+++ b/kuickshow/src/mainwidget.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MAINWIDGET_H
+#define MAINWIDGET_H
+
+#include <qevent.h>
+#include <qstring.h>
+#include <qwidget.h>
+
+class FileView;
+
+class MainWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MainWidget( QString, QWidget *parent, const char *name=0L);
+ ~MainWidget();
+
+ FileView* getFileBox() { return box; }
+
+protected:
+ virtual void resizeEvent( QResizeEvent * );
+
+private:
+ FileView *box;
+
+};
+
+
+#endif
diff --git a/kuickshow/src/printing.cpp b/kuickshow/src/printing.cpp
new file mode 100644
index 00000000..be57ca7f
--- /dev/null
+++ b/kuickshow/src/printing.cpp
@@ -0,0 +1,338 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qfont.h>
+#include <qfontmetrics.h>
+#include <qgrid.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qimage.h>
+#include <kimageeffect.h>
+#include <qpaintdevicemetrics.h>
+#include <qpainter.h>
+#include <qradiobutton.h>
+#include <qvbuttongroup.h>
+#include <qcolor.h>
+
+#include <kcombobox.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <knuminput.h>
+#include <kprinter.h>
+#include <ktempfile.h>
+
+#include "imagewindow.h"
+#include "printing.h"
+#include "version.h"
+
+bool Printing::printImage( ImageWindow& imageWin, QWidget *parent )
+{
+ QString imageURL = imageWin.url().prettyURL();
+ KPrinter printer;
+ printer.setDocName( imageURL );
+ printer.setCreator( "KuickShow-" KUICKSHOWVERSION );
+
+ KPrinter::addDialogPage( new KuickPrintDialogPage( parent, "kuick page"));
+
+ if ( printer.setup( parent, i18n("Print %1").arg(printer.docName().section('/', -1)) ) )
+ {
+ KTempFile tmpFile( QString::null, ".png" );
+ if ( tmpFile.status() == 0 )
+ {
+ tmpFile.setAutoDelete( true );
+ if ( imageWin.saveImage( tmpFile.name(), true ) )
+ return printImageWithQt( tmpFile.name(), printer,
+ imageURL );
+ }
+
+ return false;
+ }
+
+ return true; // user aborted
+}
+
+bool Printing::printImageWithQt( const QString& filename, KPrinter& printer,
+ const QString& originalFileName )
+{
+ QImage image( filename );
+ if ( image.isNull() ) {
+ kdWarning() << "Can't load image: " << filename << " for printing.\n";
+ return false;
+ }
+
+ QPainter p;
+ p.begin( &printer );
+
+ QPaintDeviceMetrics metrics( &printer );
+ p.setFont( KGlobalSettings::generalFont() );
+ QFontMetrics fm = p.fontMetrics();
+
+ int w = metrics.width();
+ int h = metrics.height();
+
+ QString t = "true";
+ QString f = "false";
+
+ // Black & white print?
+ if ( printer.option( "app-kuickshow-blackwhite" ) != f) {
+ image = image.convertDepth( 1, Qt::MonoOnly | Qt::ThresholdDither | Qt::AvoidDither );
+ }
+
+ int filenameOffset = 0;
+ bool printFilename = printer.option( "app-kuickshow-printFilename" ) != f;
+ if ( printFilename ) {
+ filenameOffset = fm.lineSpacing() + 14;
+ h -= filenameOffset; // filename goes into one line!
+ }
+
+ //
+ // shrink image to pagesize, if necessary
+ //
+ bool shrinkToFit = (printer.option( "app-kuickshow-shrinkToFit" ) != f);
+ QSize imagesize = image.size();
+ if ( shrinkToFit && (image.width() > w || image.height() > h) ) {
+ imagesize.scale( w, h, QSize::ScaleMin );
+ }
+
+
+ //
+ // align image
+ //
+ bool ok = false;
+ int alignment = printer.option("app-kuickshow-alignment").toInt( &ok );
+ if ( !ok )
+ alignment = Qt::AlignCenter; // default
+
+ int x = 0;
+ int y = 0;
+
+ // ### need a GUI for this in KuickPrintDialogPage!
+ // x - alignment
+ if ( alignment & Qt::AlignHCenter )
+ x = (w - imagesize.width())/2;
+ else if ( alignment & Qt::AlignLeft )
+ x = 0;
+ else if ( alignment & Qt::AlignRight )
+ x = w - imagesize.width();
+
+ // y - alignment
+ if ( alignment & Qt::AlignVCenter )
+ y = (h - imagesize.height())/2;
+ else if ( alignment & Qt::AlignTop )
+ y = 0;
+ else if ( alignment & Qt::AlignBottom )
+ y = h - imagesize.height();
+
+ //
+ // perform the actual drawing
+ //
+ p.drawImage( QRect( x, y, imagesize.width(), imagesize.height()), image );
+
+ if ( printFilename )
+ {
+ QString fname = minimizeString( originalFileName, fm, w );
+ if ( !fname.isEmpty() )
+ {
+ int fw = fm.width( fname );
+ int x = (w - fw)/2;
+ int y = metrics.height() - filenameOffset/2;
+ p.drawText( x, y, fname );
+ }
+ }
+
+ p.end();
+
+ return true;
+}
+
+QString Printing::minimizeString( QString text, const QFontMetrics&
+ metrics, int maxWidth )
+{
+ if ( text.length() <= 5 )
+ return QString::null; // no sense to cut that tiny little string
+
+ bool changed = false;
+ while ( metrics.width( text ) > maxWidth )
+ {
+ int mid = text.length() / 2;
+ text.remove( mid, 2 ); // remove 2 characters in the middle
+ changed = true;
+ }
+
+ if ( changed ) // add "..." in the middle
+ {
+ int mid = text.length() / 2;
+ if ( mid <= 5 ) // sanity check
+ return QString::null;
+
+ text.replace( mid - 1, 3, "..." );
+ }
+
+ return text;
+}
+
+
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+
+
+KuickPrintDialogPage::KuickPrintDialogPage( QWidget *parent, const char *name )
+ : KPrintDialogPage( parent, name )
+{
+ setTitle( i18n("Image Settings") );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setMargin( KDialog::marginHint() );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ m_addFileName = new QCheckBox( i18n("Print fi&lename below image"), this);
+ m_addFileName->setChecked( true );
+ layout->addWidget( m_addFileName );
+
+ m_blackwhite = new QCheckBox ( i18n("Print image in &black and white"), this);
+ m_blackwhite->setChecked( false );
+ layout->addWidget (m_blackwhite );
+
+ QVButtonGroup *group = new QVButtonGroup( i18n("Scaling"), this );
+ group->setRadioButtonExclusive( true );
+ layout->addWidget( group );
+ // m_shrinkToFit = new QRadioButton( i18n("Shrink image to &fit, if necessary"), group );
+ m_shrinkToFit = new QCheckBox( i18n("Shrink image to &fit, if necessary"), group );
+ m_shrinkToFit->setChecked( true );
+
+ QWidget *widget = new QWidget( group );
+ QGridLayout *grid = new QGridLayout( widget, 3, 3 );
+ grid->addColSpacing( 0, 30 );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+ grid->setColStretch( 2, 10 );
+
+ m_scale = new QRadioButton( i18n("Print e&xact size: "), widget );
+ m_scale->setEnabled( false ); // ###
+ grid->addMultiCellWidget( m_scale, 0, 0, 0, 1 );
+ group->insert( m_scale );
+ connect( m_scale, SIGNAL( toggled( bool )), SLOT( toggleScaling( bool )));
+
+ m_units = new KComboBox( false, widget, "unit combobox" );
+ grid->addWidget( m_units, 0, 2, AlignLeft );
+ m_units->insertItem( i18n("Millimeters") );
+ m_units->insertItem( i18n("Centimeters") );
+ m_units->insertItem( i18n("Inches") );
+
+ m_width = new KIntNumInput( widget, "exact width" );
+ grid->addWidget( m_width, 1, 1 );
+ m_width->setLabel( i18n("&Width:" ) );
+ m_width->setMinValue( 1 );
+
+ m_height = new KIntNumInput( widget, "exact height" );
+ grid->addWidget( m_height, 2, 1 );
+ m_height->setLabel( i18n("&Height:" ) );
+ m_height->setMinValue( 1 );
+}
+
+KuickPrintDialogPage::~KuickPrintDialogPage()
+{
+}
+
+void KuickPrintDialogPage::getOptions( QMap<QString,QString>& opts,
+ bool /*incldef*/ )
+{
+ QString t = "true";
+ QString f = "false";
+
+// ### opts["app-kuickshow-alignment"] = ;
+ opts["app-kuickshow-printFilename"] = m_addFileName->isChecked() ? t : f;
+ opts["app-kuickshow-blackwhite"] = m_blackwhite->isChecked() ? t : f;
+ opts["app-kuickshow-shrinkToFit"] = m_shrinkToFit->isChecked() ? t : f;
+ opts["app-kuickshow-scale"] = m_scale->isChecked() ? t : f;
+ opts["app-kuickshow-scale-unit"] = m_units->currentText();
+ opts["app-kuickshow-scale-width-pixels"] = QString::number( scaleWidth() );
+ opts["app-kuickshow-scale-height-pixels"] = QString::number( scaleHeight() );
+}
+
+void KuickPrintDialogPage::setOptions( const QMap<QString,QString>& opts )
+{
+ QString t = "true";
+ QString f = "false";
+
+ m_addFileName->setChecked( opts["app-kuickshow-printFilename"] != f );
+ // This sound strange, but if I copy the code on the line above, the checkbox
+ // was always checked. And this isn't the wanted behavior. So, with this works.
+ // KPrint magic ;-)
+ m_blackwhite->setChecked ( false );
+ m_shrinkToFit->setChecked( opts["app-kuickshow-shrinkToFit"] != f );
+ m_scale->setChecked( opts["app-kuickshow-scale"] == t );
+
+ m_units->setCurrentItem( opts["app-kuickshow-scale-unit"] );
+
+ bool ok;
+ int val = opts["app-kuickshow-scale-width-pixels"].toInt( &ok );
+ if ( ok )
+ setScaleWidth( val );
+ val = opts["app-kuickshow-scale-height-pixels"].toInt( &ok );
+ if ( ok )
+ setScaleHeight( val );
+
+ if ( m_scale->isChecked() == m_shrinkToFit->isChecked() )
+ m_shrinkToFit->setChecked( !m_scale->isChecked() );
+
+ // ### re-enable when implementednn
+ toggleScaling( false && m_scale->isChecked() );
+}
+
+void KuickPrintDialogPage::toggleScaling( bool enable )
+{
+ m_width->setEnabled( enable );
+ m_height->setEnabled( enable );
+ m_units->setEnabled( enable );
+}
+
+int KuickPrintDialogPage::scaleWidth() const
+{
+ return fromUnitToPixels( m_width->value() );
+}
+
+int KuickPrintDialogPage::scaleHeight() const
+{
+ return fromUnitToPixels( m_height->value() );
+}
+
+void KuickPrintDialogPage::setScaleWidth( int pixels )
+{
+ m_width->setValue( (int) pixelsToUnit( pixels ) );
+}
+
+void KuickPrintDialogPage::setScaleHeight( int pixels )
+{
+ m_width->setValue( (int) pixelsToUnit( pixels ) );
+}
+
+int KuickPrintDialogPage::fromUnitToPixels( float /*value*/ ) const
+{
+ return 1; // ###
+}
+
+float KuickPrintDialogPage::pixelsToUnit( int /*pixels*/ ) const
+{
+ return 1.0; // ###
+}
+
+#include "printing.moc"
diff --git a/kuickshow/src/printing.h b/kuickshow/src/printing.h
new file mode 100644
index 00000000..eb679f7e
--- /dev/null
+++ b/kuickshow/src/printing.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef PRINTING_H
+#define PRINTING_H
+
+#include <qfontmetrics.h>
+#include <qstring.h>
+
+#include <kdeprint/kprintdialogpage.h>
+
+class QCheckBox;
+class QRadioButton;
+class KComboBox;
+class KPrinter;
+class KIntNumInput;
+
+class ImageWindow;
+
+
+class Printing
+{
+public:
+ static bool printImage( ImageWindow& imageWin, QWidget *parent = 0L);
+ static bool printImageWithQt( const QString& filename, KPrinter& printer,
+ const QString& originalFileName );
+
+private:
+ static void addConfigPages();
+ static QString minimizeString( QString text, const QFontMetrics& metrics,
+ int maxWidth );
+
+};
+
+class KuickPrintDialogPage : public KPrintDialogPage
+{
+ Q_OBJECT
+
+public:
+ KuickPrintDialogPage( QWidget *parent = 0L, const char *name = 0 );
+ ~KuickPrintDialogPage();
+
+ virtual void getOptions(QMap<QString,QString>& opts, bool incldef = false);
+ virtual void setOptions(const QMap<QString,QString>& opts);
+
+private slots:
+ void toggleScaling( bool enable );
+
+private:
+ // return values in pixels!
+ int scaleWidth() const;
+ int scaleHeight() const;
+
+ void setScaleWidth( int pixels );
+ void setScaleHeight( int pixels );
+
+ int fromUnitToPixels( float val ) const;
+ float pixelsToUnit( int pixels ) const;
+
+ QCheckBox *m_shrinkToFit;
+ QRadioButton *m_scale;
+ KIntNumInput *m_width;
+ KIntNumInput *m_height;
+ KComboBox *m_units;
+ QCheckBox *m_addFileName;
+ QCheckBox *m_blackwhite;
+
+};
+
+#endif // PRINTING_H
diff --git a/kuickshow/src/slideshowwidget.cpp b/kuickshow/src/slideshowwidget.cpp
new file mode 100644
index 00000000..447b996e
--- /dev/null
+++ b/kuickshow/src/slideshowwidget.cpp
@@ -0,0 +1,80 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "slideshowwidget.h"
+
+
+SlideShowWidget::SlideShowWidget( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+// setTitle( i18n("Slideshow") );
+
+ QVBoxLayout *layout = new QVBoxLayout( this );
+ layout->setSpacing( KDialog::spacingHint() );
+
+ m_fullScreen = new QCheckBox( i18n("Switch to &full-screen"), this );
+ m_startWithCurrent = new QCheckBox( i18n("S&tart with current image"), this);
+
+ m_delayTime = new KIntNumInput( this, "delay time" );
+ m_delayTime->setLabel( i18n("De&lay between slides:") );
+ m_delayTime->setSuffix( i18n(" sec") );
+ m_delayTime->setRange( 0, 60 * 60 ); // 1 hour
+ m_delayTime->setSpecialValueText( i18n("Wait for key") );
+
+ m_cycles = new KIntNumInput( m_delayTime, 1, this );
+ m_cycles->setLabel( i18n("&Iterations (0 = infinite):") );
+ m_cycles->setSpecialValueText( i18n("infinite") );
+ m_cycles->setRange( 0, 500 );
+
+ layout->addWidget( m_fullScreen );
+ layout->addWidget( m_startWithCurrent );
+ layout->addWidget( m_delayTime );
+ layout->addWidget( m_cycles );
+ layout->addStretch( 1 );
+
+ loadSettings( *kdata );
+}
+
+SlideShowWidget::~SlideShowWidget()
+{
+}
+
+void SlideShowWidget::loadSettings( const KuickData& data )
+{
+ m_delayTime->setValue( data.slideDelay / 1000 );
+ m_cycles->setValue( data.slideshowCycles );
+ m_fullScreen->setChecked( data.slideshowFullscreen );
+ m_startWithCurrent->setChecked( !data.slideshowStartAtFirst );
+}
+
+void SlideShowWidget::applySettings( KuickData& data )
+{
+ data.slideDelay = m_delayTime->value() * 1000;
+ data.slideshowCycles = m_cycles->value();
+ data.slideshowFullscreen = m_fullScreen->isChecked();
+ data.slideshowStartAtFirst = !m_startWithCurrent->isChecked();
+}
+
+#include "slideshowwidget.moc"
diff --git a/kuickshow/src/slideshowwidget.h b/kuickshow/src/slideshowwidget.h
new file mode 100644
index 00000000..c651103d
--- /dev/null
+++ b/kuickshow/src/slideshowwidget.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Carsten Pfeiffer <[email protected]>
+
+ 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, version 2.
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef SLIDESHOWWIDGET_H
+#define SLIDESHOWWIDGET_H
+
+#include "kuickdata.h"
+
+class QCheckBox;
+class KIntNumInput;
+
+class SlideShowWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ SlideShowWidget( QWidget *parent, const char *name );
+ ~SlideShowWidget();
+
+ virtual void loadSettings( const KuickData& data );
+ virtual void applySettings( KuickData& data );
+
+private:
+ KIntNumInput *m_delayTime;
+ KIntNumInput *m_cycles;
+ QCheckBox *m_fullScreen;
+ QCheckBox *m_startWithCurrent;
+};
+
+#endif // SLIDESHOWWIDGET_H
diff --git a/kuickshow/src/version.h b/kuickshow/src/version.h
new file mode 100644
index 00000000..2465967f
--- /dev/null
+++ b/kuickshow/src/version.h
@@ -0,0 +1,3 @@
+#ifndef KUICKSHOWVERSION
+#define KUICKSHOWVERSION "0.8.13"
+#endif