00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include <ksavefile.h>
00028 #include <kimageio.h>
00029 #include <klocale.h>
00030 #include <kurl.h>
00031 #include <kapplication.h>
00032
00033 #include <qbitmap.h>
00034 #include <qimage.h>
00035 #include <qregexp.h>
00036 #include <qpainter.h>
00037 #include <qpaintdevicemetrics.h>
00038 #include <qfile.h>
00039 #include <qregion.h>
00040
00041 #include <stdlib.h>
00042
00043 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
00044 #include <X11/extensions/shape.h>
00045 #endif
00046
00047 #include "grabber.h"
00048
00049 Grabber::Grabber(QObject *parent, const char *name)
00050 : QObject(parent, name),
00051 m_snapshot()
00052 {
00053 }
00054
00055 Grabber::~Grabber()
00056 {
00057 }
00058
00059 QPixmap Grabber::capture()
00060 {
00061 emit startCapture();
00062 emit message(i18n("Taking snapshot..."));
00063
00064 kapp->processEvents();
00065
00066 XGrabServer( qt_xdisplay());
00067 if ( Config().Capture.CaptureMode == Configuration::WindowUnderCursor )
00068 {
00069 Window root;
00070 Window child;
00071 uint mask;
00072 int rootX, rootY, winX, winY;
00073 XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
00074 &rootX, &rootY, &winX, &winY,
00075 &mask);
00076 if( child == None )
00077 child = qt_xrootwin();
00078 if( !Config().Capture.IncludeWD)
00079 {
00080 Window real_child = findRealWindow( child );
00081 if( real_child != None )
00082 child = real_child;
00083 }
00084
00085 int x, y;
00086 unsigned int w, h;
00087 unsigned int border;
00088 unsigned int depth;
00089 XGetGeometry( qt_xdisplay(), child, &root, &x, &y, &w, &h, &border, &depth );
00090 w += 2 * border;
00091 h += 2 * border;
00092
00093 Window parent;
00094 Window* children;
00095 unsigned int nchildren;
00096 if( XQueryTree( qt_xdisplay(), child, &root, &parent, &children, &nchildren ) != 0 )
00097 {
00098 if( children != NULL )
00099 XFree( children );
00100
00101 int newx, newy;
00102 Window dummy;
00103 if( XTranslateCoordinates( qt_xdisplay(), parent, qt_xrootwin(),
00104 x, y, &newx, &newy, &dummy ))
00105 {
00106 x = newx;
00107 y = newy;
00108 }
00109 }
00110
00111 m_snapshot = QPixmap::grabWindow( qt_xrootwin(), x, y, w, h );
00112
00113 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
00114
00115 if (haveXShape)
00116 {
00117 QBitmap mask(w, h);
00118
00119 int count, order;
00120 XRectangle* rects = XShapeGetRectangles(qt_xdisplay(), child,
00121 ShapeBounding, &count, &order);
00122
00123
00124
00125
00126 if (rects)
00127 {
00128
00129 QRegion contents;
00130 for (int pos = 0; pos < count; pos++)
00131 contents += QRegion(rects[pos].x, rects[pos].y,
00132 rects[pos].width, rects[pos].height);
00133 XFree(rects);
00134
00135
00136 QRegion bbox(0, 0, snapshot.width(), snapshot.height());
00137
00138 if( border > 0 )
00139 {
00140 contents.translate( border, border );
00141 contents += QRegion( 0, 0, border, h );
00142 contents += QRegion( 0, 0, w, border );
00143 contents += QRegion( 0, h - border, w, border );
00144 contents += QRegion( w - border, 0, border, h );
00145 }
00146
00147
00148 QRegion maskedAway = bbox - contents;
00149 QMemArray<QRect> maskedAwayRects = maskedAway.rects();
00150
00151
00152 QPainter p(&mask);
00153 p.fillRect(0, 0, w, h, Qt::color1);
00154 for (uint pos = 0; pos < maskedAwayRects.count(); pos++)
00155 p.fillRect(maskedAwayRects[pos], Qt::color0);
00156 p.end();
00157
00158 m_snapshot.setMask(mask);
00159 }
00160 }
00161 #endif
00162 }
00163 else
00164 {
00165 m_snapshot = QPixmap::grabWindow( qt_xrootwin() );
00166 }
00167 XUngrabServer( qt_xdisplay());
00168
00169 emit message(i18n("Snapshot taken."));
00170 emit finishCapture();
00171
00172 return m_snapshot;
00173 }
00174
00175 void Grabber::saveFiles()
00176 {
00177 emit startSave();
00178 emit message(i18n("Saving images..."));
00179
00180
00181 kapp->processEvents();
00182
00183 QString fileNameMain = Config().File.PathMain;
00184 saveMain(fileNameMain);
00185
00186 if(Config().Ftp.UseThumb)
00187 {
00188 QString fileNameThumb = Config().File.PathThumb;
00189 saveThumb(fileNameThumb);
00190 }
00191
00192 emit message(i18n("Images saved."));
00193 emit finishSave();
00194 }
00195
00196
00197 Window Grabber::findRealWindow( Window w, int depth)
00198 {
00199 if( depth > 5 )
00200 return None;
00201
00202 static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
00203 Atom type;
00204 int format;
00205 unsigned long nitems, after;
00206 unsigned char* prop;
00207
00208 if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType,
00209 &type, &format, &nitems, &after, &prop ) == Success )
00210 {
00211 if( prop != NULL )
00212 XFree( prop );
00213 if( type != None )
00214 return w;
00215 }
00216
00217 Window root, parent;
00218 Window* children;
00219 unsigned int nchildren;
00220 Window ret = None;
00221 if( XQueryTree( qt_xdisplay(), w, &root, &parent, &children, &nchildren ) != 0 )
00222 {
00223 for( unsigned int i = 0; i < nchildren && ret == None; ++i )
00224 ret = findRealWindow( children[ i ], depth + 1 );
00225 if( children != NULL )
00226 XFree( children );
00227 }
00228 return ret;
00229 }
00230
00231 void Grabber::saveMain( const QString & fileName )
00232 {
00233 QImage temp = m_snapshot.convertToImage();
00234
00235 if(Config().Capture.ScaleMode == Configuration::ScalePercent)
00236 {
00237 int scale = Config().Capture.ScaleMain;
00238 if(scale != 100)
00239 {
00240 int neww = (int)((double)m_snapshot.width() * ((double)scale / 100.0));
00241 int newh = (int)((double)m_snapshot.height() * ((double)scale / 100.0));
00242 temp = temp.scale(neww, newh, QImage::ScaleMin);
00243 }
00244 }
00245 else if(Config().Capture.ScaleMode == Configuration::ScalePixel)
00246 {
00247 int neww = Config().Capture.ScaleMain;
00248 if(neww != m_snapshot.width())
00249 {
00250 double scale = (double)neww / (double) m_snapshot.width();
00251 int newh = (int)((double)m_snapshot.height() *((double)scale));
00252 temp = temp.scale(neww, newh, QImage::ScaleMin);
00253 }
00254 }
00255
00256 if(Config().Caption.UseCaption)
00257 {
00258 QImage temp2 = drawCaption(temp);
00259
00260 if(!temp2.isNull())
00261 {
00262 temp = temp2;
00263 }
00264 else
00265 {
00266 emit message(i18n("Could not draw caption on main image."), Configuration::Debug);
00267 }
00268 }
00269
00270 saveImage(fileName, temp);
00271 }
00272
00273 void Grabber::saveThumb( const QString & fileName )
00274 {
00275 QImage temp = m_snapshot.convertToImage();
00276
00277 if(Config().Caption.UseCaption)
00278 {
00279 QImage temp2 = drawCaption(temp);
00280
00281 if(!temp2.isNull())
00282 {
00283 temp = temp2;
00284 }
00285 else
00286 {
00287 emit message(i18n("Could not draw caption on thumbnail image."), Configuration::Debug);
00288 }
00289 }
00290
00291 if(Config().Capture.ScaleMode == Configuration::ScalePercent)
00292 {
00293 int scale = Config().Capture.ScaleThumb;
00294 if(scale != 100)
00295 {
00296 int neww = (int)((double)m_snapshot.width() * ((double)scale / 100.0));
00297 int newh = (int)((double)m_snapshot.height() * ((double)scale / 100.0));
00298 temp = temp.scale(neww, newh, QImage::ScaleMin);
00299 }
00300 }
00301 else if(Config().Capture.ScaleMode == Configuration::ScalePixel)
00302 {
00303 int neww = Config().Capture.ScaleThumb;
00304 if(neww != m_snapshot.width())
00305 {
00306 double scale = (double)neww / (double) m_snapshot.width();
00307 int newh = (int)((double)m_snapshot.height() *((double)scale));
00308 temp = temp.scale(neww, newh, QImage::ScaleMin);
00309 }
00310 }
00311
00312 saveImage(fileName, temp);
00313 }
00314
00315 void Grabber::saveImage(const QString& fileName, const QImage& image)
00316 {
00317 KURL url(fileName);
00318
00319 if ( !url.isValid() )
00320 {
00321
00322 return;
00323 }
00324
00325 QString type( KImageIO::type(url.path()) );
00326 if ( type.isNull() )
00327 type = "PNG";
00328
00329 bool ok = false;
00330
00331 KSaveFile saveFile( url.path() );
00332 if ( saveFile.status() == 0 )
00333 {
00334 if ( image.save( saveFile.file(), type.latin1(), Config().Capture.PictureQuality ) )
00335 ok = saveFile.close();
00336 }
00337
00338 if ( !ok )
00339 emit message(i18n("Unable to save the image."), Configuration::Debug);
00340 }
00341
00342 QImage Grabber::drawCaption(const QImage& image)
00343 {
00344 QString text = Config().Caption.Text;
00345
00346 QPixmap pic(image);
00347 QPainter paint;
00348 paint.begin(&pic);
00349 paint.setFont(Config().Caption.Font);
00350 paint.setPen(Config().Caption.Color);
00351
00352 if(Config().Caption.CustomPos)
00353 {
00354 paint.drawText(Config().Caption.PositionX, Config().Caption.PositionY, text);
00355 }
00356 else
00357 {
00358 paint.drawText(pic.rect(), Config().Caption.Position | Qt::WordBreak, text);
00359 }
00360
00361 paint.end();
00362 return pic.convertToImage();
00363 }
00364
00365 #include "grabber.moc"