Index: branches/KDE/3.5/kdegraphics/kuickshow/ChangeLog =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/ChangeLog (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/ChangeLog (revision 495613) @@ -1,846 +1,873 @@ +
+Sun Jan 8 09:47:39 2006 Carsten Pfeiffer+ + * fix crash when deleting the last image without having a browser + +Sat Jan 7 23:27:32 2006 Carsten Pfeiffer + + * 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 + + * 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 + + * 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 * src/imagewindow.cpp (init): mouse-wheel can switch between images now, per request of Bill Benken * also fixed the KStdAccel::save() and close() accels not working in the image window - Sat Aug 4 03:37:50 2001 Carsten PfeifferIndex: branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.cpp =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.cpp (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.cpp (revision 495613) @@ -1,1246 +1,1379 @@ /* This file is part of the KDE project - Copyright (C) 1998-2003 Carsten Pfeiffer* 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 and another anonymous helper from #kde for testing and useful feedback. * Added patch from Adrian Schroeter to make it work with autoconf 2.5x -- Thanks! Wed Jul 11 17:19:38 2001 Carsten Pfeiffer * 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 * src/imagewindow.cpp (printImage): Grmbl. Really fixed printing. It even works now :) Tue Jul 3 3:04:18 2001 Carsten Pfeiffer * 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 * src/imagewindow.cpp: added KTempFile patch from Kevin Lo Tue May 29 15:20:34 2001 Carsten Pfeiffer * 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 * Integrated Multihead patch from Evan Edwards 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 , 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 I got a Brazilian/Portuguese translation for KuickShow Tue Jul 27 20:32:09 1999 Carsten Pfeiffer * 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 * 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 * src/kfileview.cpp (refresh): Oh well, thanks to Robert Hamberger , 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 * src/imlibwidget.cpp (loadImageInternal): Applied patch from Thorsten Scheuermann (autoscale images to screensize) - thanks! Mon Jul 5 15:27:05 1999 Carsten Pfeiffer * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * doc/en/index.html: updated documentation Wed Feb 3 22:43:32 1999 Carsten Pfeiffer * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * src/kuickshow.cpp (printImage): added preliminary support for printing Sat Sep 19 01:40:22 1998 Carsten Pfeiffer * src/imlibwidget.cpp (rotate): added rotate-routine to - doh - rotate an image Fri Sep 18 01:08:46 1998 Carsten Pfeiffer * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 + Copyright (C) 1998-2006 Carsten Pfeiffer 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include + #include "aboutwidget.h" #include "filewidget.h" #include "imdata.h" #include "imagewindow.h" #include "imlibwidget.h" #include "kuick.h" #include "kuickio.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 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() + '/' ); for ( int i = 0; i < args->count(); 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 ); show(); } else { // don't show browser, when image on commandline hide(); KStartupInfo::appStarted(); } } KuickShow::~KuickShow() { saveSettings(); if ( m_viewer ) m_viewer->close( true ); free( id ); kapp->quit(); delete kdata; } // TODO convert to use xmlui file void KuickShow::initGUI( const KURL& startDir ) { fileWidget = new FileWidget( startDir, 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 ( coll->action("sorting menu")); KActionMenu *mainActionMenu = static_cast ( 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 ( 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(); ::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 ( 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*/ ) { } void 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" ); s_viewers.append( m_viewer ); connect( m_viewer, SIGNAL( nextSlideRequested() ), this, SLOT( nextSlide() )); connect( m_viewer, SIGNAL( destroyed() ), SLOT( viewerDeleted() )); connect( m_viewer, SIGNAL( sigFocusWindow( ImageWindow *) ), this, SLOT( slotSetActiveViewer( ImageWindow * ) )); connect( m_viewer, SIGNAL( sigBadImage(const QString& ) ), this, SLOT( messageCantLoadImage(const QString &) )); connect( m_viewer, SIGNAL( requestImage( ImageWindow *, int )), this, SLOT( slotAdvanceImage( ImageWindow *, int ))); - connect( m_viewer, SIGNAL( pauseSlideShowSignal() ), + connect( m_viewer, SIGNAL( pauseSlideShowSignal() ), this, SLOT( pauseSlideShow() ) ); - connect( m_viewer, SIGNAL (deleteImage ()), - this, SLOT (slotDeleteImage ())); + 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; QString filename; KIO::NetAccess::download(fi->url(), filename, this); if ( !safeViewer->showNextImage( filename ) ) { 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().path() ); // FIXME } m_viewer = safeViewer; } // m_viewer created successfully } // isImage } -void KuickShow::slotDeleteImage() +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(" Do you really want to delete\n '%1'? ").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); + list.append (item); + + if (KMessageBox::warningContinueCancel( + parent, + i18n("Do you really want to trash\n '%1'? ").arg(item->url().pathOrURL()), + i18n("Trash File"), + KGuiItem(i18n("to trash", "&Trash"),"edittrash"), + "Kuick_trash_current_image") + != KMessageBox::Continue) + { + return; + } + + tryShowNextImage(); + fileWidget->trash(list, 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); - if (next) + + // FIXME: why is this necessary at all? Why does KDirOperator suddenly re-read the + // entire directory after a file was deleted/trashed!? + if (!m_viewer) + return; + + if (next) showImage(next, false); else - m_viewer->close(true); - fileWidget->del(list, false,false); + { + 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().path() ); 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().path())) 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 // the viewer might not be available yet. Factor this out somewhen. if ( !fileWidget ) { if ( m_delayedRepeatItem ) return; - m_delayedRepeatItem = new DelayedRepeatEvent( view, steps ); - - KURL start; - QFileInfo fi( view->filename() ); - start.setPath( fi.dirPath( true ) ); - initGUI( start ); - - // see eventFilter() for explanation and similar code - if ( fileWidget->dirLister()->isFinished() && - fileWidget->dirLister()->rootItem() ) - { - fileWidget->setCurrentItem( fi.fileName() ); - QTimer::singleShot( 0, this, SLOT( slotReplayAdvance())); - } - else - { - fileWidget->setInitialItem( fi.fileName() ); - connect( fileWidget, SIGNAL( finished() ), - SLOT( slotReplayAdvance() )); - } - + 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( filename ); if (m_slideTimer->isActive() && kdata->slideDelay) m_slideTimer->start( kdata->slideDelay ); if ( kdata->preloadImage && item_next && item_next->url().isLocalFile() ) // preload next image if ( FileWidget::isImage( item_next ) ) view->cacheImage( item_next->url().path() ); // ### } } 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( e ); if ( k ) { if ( KStdAccel::quit().contains( KKey( k ) ) ) { saveSettings(); deleteAllViewers(); ::exit(0); } else if ( KStdAccel::help().contains( KKey( k ) ) ) { appHelpActivated(); return true; } } ImageWindow *window = dynamic_cast ( 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 ) { KURL start; QFileInfo fi( m_viewer->filename() ); start.setPath( fi.dirPath( true ) ); initGUI( start ); // 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() && fileWidget->dirLister()->rootItem() ) { fileWidget->setCurrentItem( fi.fileName() ); QTimer::singleShot( 0, this, SLOT( slotReplayEvent())); } else { fileWidget->setInitialItem( fi.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( filename ); if ( kdata->preloadImage && item_next && item_next->url().isLocalFile() ) // preload next image if ( FileWidget::isImage( item_next ) ) m_viewer->cacheImage( item_next->url().path() ); // ### 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 ( e ); if ( ev->button() == LeftButton ) { if ( s_viewers.count() == 1 ) { if ( !fileWidget ) { KURL start; - QFileInfo fi( m_viewer->filename() ); + QFileInfo fi( window->filename() ); start.setPath( fi.dirPath( true ) ); initGUI( start ); } 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 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(); } QStringList images = kc->readPathListEntry( "Images shown" ); QStringList::Iterator it; for ( it = images.begin(); it != images.end(); ++it ) { KFileItem item( KFileItem::Unknown, KFileItem::Unknown, KURL::fromPathOrURL( *it ), false ); if ( item.isReadable() ) showImage( &item, true ); } if ( !s_viewers.isEmpty() ) { bool visible = kc->readBoolEntry( "Browser visible", true ); if ( !visible ) hide(); } } void KuickShow::saveProperties( KConfig *kc ) { kc->writePathEntry( "CurrentDirectory", fileWidget->url().url() ); kc->writeEntry( "Browser visible", fileWidget->isVisible() ); QStringList urls; QValueListIterator it; for ( it = s_viewers.begin(); it != s_viewers.end(); ++it ) urls.append( (*it)->filename() ); 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().url() ); fileWidget->writeConfig( kc, "Filebrowser" ); } kc->sync(); } void KuickShow::messageCantLoadImage( const QString& filename ) { m_viewer->clearFocus(); QString tmp = i18n("Unable to load the image %1.\n" "Perhaps the file format is unsupported or " "your Imlib is not installed properly.").arg(filename); KMessageBox::sorry( m_viewer, tmp, i18n("Image Error") ); } 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" ); // FIXME - 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") ); ::exit(1); } } } void KuickShow::initImlibParams( ImData *idata, ImlibInitParams *par ) { 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; } 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::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::slotReplayAdvance() +void KuickShow::replayAdvance(DelayedRepeatEvent *event) { - if ( !m_delayedRepeatItem ) - return; - - disconnect( fileWidget, SIGNAL( finished() ), - this, SLOT( slotReplayAdvance() )); - - DelayedRepeatEvent *e = m_delayedRepeatItem; - m_delayedRepeatItem = 0L; // otherwise, eventFilter aborts - // ### 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( e->viewer, e->steps ); - delete e; + slotAdvanceImage( event->viewer, *(int *) (event->data) ); +} + +void KuickShow::delayAction(DelayedRepeatEvent *event) +{ + if (m_delayedRepeatItem) + return; + + m_delayedRepeatItem = event; + + KURL start; + QFileInfo fi( event->viewer->filename() ); + start.setPath( fi.dirPath( true ) ); + initGUI( start ); + + // see eventFilter() for explanation and similar code + if ( fileWidget->dirLister()->isFinished() && + fileWidget->dirLister()->rootItem() ) + { + fileWidget->setCurrentItem( fi.fileName() ); + QTimer::singleShot( 0, this, SLOT( doReplay())); + } + else + { + fileWidget->setInitialItem( fi.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 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" Index: branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.cpp =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.cpp (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.cpp (revision 495613) @@ -1,1114 +1,1129 @@ /* This file is part of the KDE project Copyright (C) 1998-2004 Carsten Pfeiffer 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 #include #include #include #include #include #include #include #ifdef KDE_USE_FINAL #undef GrayScale #undef Color #endif #include #include #include #include #include #include #include #include #include #ifdef KDE_USE_FINAL #undef Unsorted #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "imagewindow.h" #include "kuick.h" #include "kuickdata.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() { KCursor::setAutoHideCursor( this, true, true ); KCursor::setHideCursorDelay( 1500 ); // give the image window a different WM_CLASS XClassHint hint; hint.res_name = const_cast ( kapp->name() ); hint.res_class = const_cast ( "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"), Key_Delete, + + 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" ); // -------- - KAction *pause = new KAction( i18n("Pause Slideshow"), Key_P, - this, SLOT( pauseSlideShow() ), - m_actions, "kuick_slideshow_pause" ); + 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 ); - new KAction( i18n("Reload Image"), Key_Enter, - this, SLOT( reload() ), - m_actions, "reload_image" ); + 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() - KShortcut cut( fullscreenAction->shortcut() ); - if ( cut == fullscreenAction->shortcutDefault() ) { - cut.append(KKey(Key_Return)); - fullscreenAction->setShortcut(cut); + 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::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->filename() ); 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 QString& filename ) { if ( !loadImage( filename ) ) { emit sigBadImage( filename ); return false; } else { // updateWidget( true ); // already called from loadImage() showImage(); return true; } } void ImageWindow::reload() { showNextImage( filename() ); } 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(); + 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 if ( key == Key_Right || key == Key_Down ) emit nextSlideRequested(); else if ( key == Key_Left || key == Key_Up ) emit prevSlideRequested(); // For future use... 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 ( 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 ( w > kdata->maxWidth || h > kdata->maxHeight ) { qDebug("KuickShow: scaling larger than configured maximum -> aborting" ); 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 ); 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 * ) { 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->filename() : KURL::fromPathOrURL( m_kuim->filename() ).fileName(); dlg.setSelection( selection ); dlg.setOperationMode( KFileDialog::Saving ); dlg.setCaption( i18n("Save As") ); if ( dlg.exec() == QDialog::Accepted ) { QString file = dlg.selectedFile(); if ( !file.isEmpty() ) { if ( !saveImage( file, 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")); } if ( file == m_kuim->filename() ) { 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 QString& filename, bool keepOriginalSize ) const { 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; if ( saveIm ) { Imlib_apply_modifiers_to_rgb( id, saveIm ); success = Imlib_save_image( id, saveIm, QFile::encodeName( filename ).data(), NULL ); Imlib_kill_image( id, saveIm ); } return success; } void ImageWindow::toggleFullscreen() { setFullscreen( !myIsFullscreen ); } void ImageWindow::loaded( KuickImage *kuim ) { if ( !kdata->isModsEnabled ) { 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 ); } // 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; } void ImageWindow::slotProperties() { KURL url; url.setPath( filename() ); // ### (void) new KPropertiesDialog( url, this, "props dialog", true ); } #include "imagewindow.moc" Index: branches/KDE/3.5/kdegraphics/kuickshow/src/kurlwidget.cpp =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/kurlwidget.cpp (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/kurlwidget.cpp (revision 495613) @@ -1,42 +1,42 @@ /* This file is part of the KDE project Copyright (C) 1998,1999,2000 Carsten Pfeiffer 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 #include #include #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 ); + (void) new KRun( ku, this ); } } #include "kurlwidget.moc" Index: branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.h =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.h (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/kuickshow.h (revision 495613) @@ -1,153 +1,175 @@ /* This file is part of the KDE project - Copyright (C) 1998-2003 Carsten Pfeiffer + Copyright (C) 1998-2006 Carsten Pfeiffer 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 #include #include #include #include #include #include #include #include "aboutwidget.h" class FileWidget; class ImageWindow; class ImData; class KuickConfigDialog; class KAccel; class KConfig; class KToggleAction; class AboutWidget; class KURL; class KURLComboBox; class DelayedRepeatEvent { public: DelayedRepeatEvent( ImageWindow *view, QKeyEvent *ev ) { viewer = view; event = ev; } - DelayedRepeatEvent( ImageWindow *view, int step ) { - viewer = view; - steps = step; - event = 0L; + 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 steps; + int action; + void *data; }; class KuickShow : public KMainWindow { Q_OBJECT public: KuickShow( const char *name=0 ); ~KuickShow(); virtual void show(); static QValueList 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 QString& ); void 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 slotReplayAdvance(); void slotOpenURL(); void slotSetURL( const KURL& ); void slotURLComboReturnPressed(); // void invalidateImages( const KFileItemList& items ); - void slotDeleteImage(); + 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 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; }; #endif Index: branches/KDE/3.5/kdegraphics/kuickshow/src/aboutwidget.cpp =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/aboutwidget.cpp (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/aboutwidget.cpp (revision 495613) @@ -1,95 +1,95 @@ /* This file is part of the KDE project Copyright (C) 1998-2002 Carsten Pfeiffer 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 #include #include #include #include #include #include #include "imlibwidget.h" #include "kurlwidget.h" #include "version.h" #include "aboutwidget.h" AboutWidget::AboutWidget( QWidget *parent, const char *name ) - : QVBox( parent, name ) + : QVBox( parent, name, Qt::WShowModal ) { KWin::setType( winId(), NET::Override ); - KWin::setState( winId(), NET::StaysOnTop | NET::SkipTaskbar ); + 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-2004", gBox); + 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 ( e ); if ( !m_homepage->geometry().contains( ev->pos() ) ) { - delete this; + deleteLater(); return true; } } return QVBox::eventFilter( o, e ); } #include "aboutwidget.moc" Index: branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.h =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.h (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/imagewindow.h (revision 495613) @@ -1,165 +1,168 @@ /* This file is part of the KDE project Copyright (C) 1998-2003 Carsten Pfeiffer 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 #include #include "imlibwidget.h" class QCursor; class QPopupMenu; class QRect; class QString; class QTimer; class QWidget; 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( const QString& filename ); 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 QString& filename, bool keepOriginalSize ) const; 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(); + void deleteImage(ImageWindow *viewer); + void trashImage(ImageWindow *viewer); void nextSlideRequested(); void prevSlideRequested(); 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 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 * ); 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(); signals: void pauseSlideShowSignal(); private: int desktopWidth( bool totalScreen = false ) const; int desktopHeight( bool totalScreen = false ) const; QSize maxImageSize() const; void setupActions(); void setPopupMenu(); bool myIsFullscreen; int m_numHeads; QString m_saveDirectory; KActionCollection *m_actions; static QCursor * s_handCursor; }; #endif // IMAGEWINDOW_H Index: branches/KDE/3.5/kdegraphics/kuickshow/src/version.h =================================================================== --- branches/KDE/3.5/kdegraphics/kuickshow/src/version.h (revision 495612) +++ branches/KDE/3.5/kdegraphics/kuickshow/src/version.h (revision 495613) @@ -1,3 +1,3 @@ #ifndef KUICKSHOWVERSION -#define KUICKSHOWVERSION "0.8.7" +#define KUICKSHOWVERSION "0.8.8" #endif