moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kstars / kstars / imageviewer.cpp
blob1a277ed2b96b626eb460371253c29cb3bec00763
1 /***************************************************************************
2 imageviewer.cpp - An ImageViewer for KStars
3 -------------------
4 begin : Mon Aug 27 2001
5 copyright : (C) 2001 by Thomas Kabelmann
6 email : tk78@gmx.de
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 #include <qfont.h>
20 #include <klocale.h>
21 #include <kmessagebox.h>
22 #include <kfiledialog.h>
23 #include <kstatusbar.h>
24 #include <kio/netaccess.h>
25 #include <kaction.h>
26 #include <kaccel.h>
27 #include <kdebug.h>
28 #include "imageviewer.h"
30 #include <kapplication.h>
32 ImageViewer::ImageViewer (const KURL *url, const QString &capText, QWidget *parent, const char *name)
33 : KMainWindow (parent, name), imageURL (*url), fileIsImage (false),
34 ctrl (false), key_s (false), key_q (false), downloadJob(0)
36 // toolbar can dock only on top-position and can't be minimized
37 // JH: easier to just disable its mobility
38 toolBar()->setMovingEnabled( false );
40 KAction *action = new KAction (i18n ("Close Window"), "fileclose", CTRL+Key_Q, this, SLOT (close()), actionCollection());
41 action->plug (toolBar());
42 action = new KAction (i18n ("Save Image"), "filesave", CTRL+Key_S, this, SLOT (saveFileToDisc()), actionCollection());
43 action->plug (toolBar());
45 statusBar()->insertItem( capText, 0, 1, true );
46 statusBar()->setItemAlignment( 0, AlignLeft | AlignVCenter );
47 QFont fnt = statusBar()->font();
48 fnt.setPointSize( fnt.pointSize() - 2 );
49 statusBar()->setFont( fnt );
51 if (!imageURL.isValid()) //check URL
52 kdDebug()<<"URL is malformed"<<endl;
53 setCaption (imageURL.fileName()); // the title of the window
54 loadImageFromURL();
57 ImageViewer::~ImageViewer() {
58 // check if download job is running
59 checkJob();
61 if (!file->remove()) // if the file was not complete downloaded the suffix is ".part"
63 kdDebug()<<QString("remove of %1 failed").arg(file->name())<<endl;
64 file->setName (file->name() + ".part"); // set new suffix to filename
65 kdDebug()<<QString("try to remove %1").arg( file->name())<<endl;
66 if (file->remove())
67 kdDebug()<<"file removed\n";
68 else
69 kdDebug()<<"file not removed\n";
73 void ImageViewer::paintEvent (QPaintEvent */*ev*/)
75 bitBlt (this, 0, toolBar()->height() + 1, &pix);
78 void ImageViewer::resizeEvent (QResizeEvent */*ev*/)
80 if ( !downloadJob ) // only if image is loaded
81 pix = kpix.convertToPixmap ( image.smoothScale ( size().width() , size().height() - toolBar()->height() - statusBar()->height() ) ); // convert QImage to QPixmap (fastest method)
83 update();
86 void ImageViewer::closeEvent (QCloseEvent *ev)
88 if (ev) // not if closeEvent (0) is called, because segfault
89 ev->accept(); // parent-widgets should not get this event, so it will be filtered
90 this->~ImageViewer(); // destroy the object, so the object can only allocated with operator new, not as a global/local variable
94 void ImageViewer::keyPressEvent (QKeyEvent *ev)
96 ev->accept(); //make sure key press events are captured.
97 switch (ev->key())
99 case Key_Control : ctrl = true; break;
100 case Key_Q : key_q = true; break;
101 case Key_S : key_s = true; break;
102 default : ev->ignore();
104 if (ctrl && key_q)
105 close();
106 if (ctrl && key_s)
108 ctrl = false;
109 key_s = false;
110 saveFileToDisc();
114 void ImageViewer::keyReleaseEvent (QKeyEvent *ev)
116 ev->accept();
117 switch (ev->key())
119 case Key_Control : ctrl = false; break;
120 case Key_Q : key_q = false; break;
121 case Key_S : key_s = false; break;
122 default : ev->ignore();
126 void ImageViewer::loadImageFromURL()
128 file = tempfile.file();
129 tempfile.unlink(); // we just need the name and delete the tempfile from disc; if we don't do it, a dialog will be shown
130 KURL saveURL (file->name());
131 if (!saveURL.isValid())
132 kdDebug()<<"tempfile-URL is malformed\n";
134 downloadJob = KIO::copy (imageURL, saveURL); // starts the download asynchron
135 connect (downloadJob, SIGNAL (result (KIO::Job *)), SLOT (downloadReady (KIO::Job *)));
138 void ImageViewer::downloadReady (KIO::Job *job)
140 // set downloadJob to 0, but don't delete it - the job will automatically deleted !!!
141 downloadJob = 0;
143 if ( job->error() )
145 job->showErrorDialog();
146 closeEvent (0);
147 return; // exit this function
150 file->close(); // to get the newest informations of the file and not any informations from opening of the file
152 if ( file->exists() )
154 showImage();
155 return;
157 closeEvent (0);
160 void ImageViewer::showImage()
162 if (!image.load (file->name())) // if loading failed
164 QString text = i18n ("Loading of the image %1 failed.");
165 KMessageBox::error (this, text.arg (imageURL.prettyURL() ));
166 closeEvent (0);
167 return;
169 fileIsImage = true; // we loaded the file and know now, that it is an image
171 //First, if the image is less wide than the statusBar, we have to scale it up.
172 if ( image.width() < statusBar()->width() ) {
173 image.smoothScale ( statusBar()->width() , image.height() * statusBar()->width() / image.width() );
176 QRect deskRect = kapp->desktop()->availableGeometry();
177 int w = deskRect.width(); // screen width
178 int h = deskRect.height(); // screen height
179 int h2 = image.height() + toolBar()->height() + statusBar()->height(); //height required for ImageViewer
180 if (image.width() <= w && h2 <= h)
181 resize ( image.width(), h2 );
183 //If the image is larger than screen width and/or screen height, shrink it to fit the screen
184 //while preserving the original aspect ratio
186 else if (image.width() <= w) //only the height is too large
187 resize ( int( image.width()*h/h2 ), h );
188 else if (image.height() <= h) //only the width is too large
189 resize ( w, int( h2*w/image.width() ) );
190 else { //uh-oh...both width and height are too large. which needs to be shrunk least?
191 float fx = float(w)/float(image.width());
192 float fy = float(h)/float(h2);
193 if (fx > fy) //width needs to be shrunk less, so shrink to fit in height
194 resize ( int( image.width()*fy ), h );
195 else //vice versa
196 resize ( w, int( h2*fx ) );
199 show(); // hide is default
200 // pix will be initialized in resizeEvent(), which will automatically called first time
203 void ImageViewer::saveFileToDisc()
205 KURL newURL = KFileDialog::getSaveURL(imageURL.fileName()); // save-dialog with default filename
206 if (!newURL.isEmpty())
208 QFile f (newURL.directory() + "/" + newURL.fileName());
209 if (f.exists())
211 int r=KMessageBox::warningContinueCancel(static_cast<QWidget *>(parent()),
212 i18n( "A file named \"%1\" already exists. "
213 "Overwrite it?" ).arg(newURL.fileName()),
214 i18n( "Overwrite File?" ),
215 i18n( "&Overwrite" ) );
216 if(r==KMessageBox::Cancel) return;
218 f.remove();
220 saveFile (newURL);
224 void ImageViewer::saveFile (KURL &url) {
225 // synchronous Access to prevent segfaults
226 if (!KIO::NetAccess::copy (KURL (file->name()), url, (QWidget*) 0))
228 QString text = i18n ("Saving of the image %1 failed.");
229 KMessageBox::error (this, text.arg (url.prettyURL() ));
233 void ImageViewer::close() {
234 closeEvent (0);
237 void ImageViewer::checkJob() {
238 if ( downloadJob ) { // if download job is running
239 downloadJob->kill( true ); // close job quietly, without emitting a result
240 kdDebug() << "Download job killed";
244 #include "imageviewer.moc"