diff options
Diffstat (limited to 'ksnapshot')
-rw-r--r-- | ksnapshot/Makefile.am | 21 | ||||
-rw-r--r-- | ksnapshot/README | 29 | ||||
-rw-r--r-- | ksnapshot/configure.in.in | 6 | ||||
-rw-r--r-- | ksnapshot/hi16-app-ksnapshot.png | bin | 0 -> 852 bytes | |||
-rw-r--r-- | ksnapshot/hi22-app-ksnapshot.png | bin | 0 -> 1328 bytes | |||
-rw-r--r-- | ksnapshot/hi32-app-ksnapshot.png | bin | 0 -> 2056 bytes | |||
-rw-r--r-- | ksnapshot/hi48-app-ksnapshot.png | bin | 0 -> 3530 bytes | |||
-rw-r--r-- | ksnapshot/hisc-app-ksnapshot.svgz | bin | 0 -> 5445 bytes | |||
-rw-r--r-- | ksnapshot/ksnapshot.cpp | 510 | ||||
-rw-r--r-- | ksnapshot/ksnapshot.desktop | 92 | ||||
-rw-r--r-- | ksnapshot/ksnapshot.h | 150 | ||||
-rw-r--r-- | ksnapshot/ksnapshotiface.h | 65 | ||||
-rw-r--r-- | ksnapshot/ksnapshotwidget.ui | 361 | ||||
-rw-r--r-- | ksnapshot/ksnapshotwidget.ui.h | 138 | ||||
-rw-r--r-- | ksnapshot/main.cpp | 77 | ||||
-rw-r--r-- | ksnapshot/regiongrabber.cpp | 177 | ||||
-rw-r--r-- | ksnapshot/regiongrabber.h | 70 | ||||
-rw-r--r-- | ksnapshot/uninstall.desktop | 2 | ||||
-rw-r--r-- | ksnapshot/windowgrabber.cpp | 353 | ||||
-rw-r--r-- | ksnapshot/windowgrabber.h | 59 |
20 files changed, 2110 insertions, 0 deletions
diff --git a/ksnapshot/Makefile.am b/ksnapshot/Makefile.am new file mode 100644 index 00000000..a9dae435 --- /dev/null +++ b/ksnapshot/Makefile.am @@ -0,0 +1,21 @@ +bin_PROGRAMS= ksnapshot + +INCLUDES = -DKSNAPVERSION="\"0.7\"" $(all_includes) + +ksnapshot_LDFLAGS = $(all_libraries) $(KDE_RPATH) +ksnapshot_LDADD = $(LIB_KDEPRINT) + +ksnapshot_SOURCES = ksnapshotiface.skel main.cpp ksnapshot.cpp \ + regiongrabber.cpp windowgrabber.cpp ksnapshotwidget.ui + +ksnapshot_METASOURCES = AUTO + +xdg_apps_DATA = ksnapshot.desktop + +KDE_ICON = ksnapshot + +EXTRA_DIST = $(xdg_apps_DATA) + +messages: rc.cpp + $(XGETTEXT) rc.cpp *.cpp -o $(podir)/ksnapshot.pot + diff --git a/ksnapshot/README b/ksnapshot/README new file mode 100644 index 00000000..0aa0b121 --- /dev/null +++ b/ksnapshot/README @@ -0,0 +1,29 @@ + KSnapshot Release Notes + ======================= + +KSnapshot is intended to be an easy to use program for making +screenshots. I can be bound to the Print Screen" key, as the program +takes a snapshot of the desktop on startup (before it displays it +window), so it's a simple way of of making snapshots. + +Currently Implemented features: + +- Mini Preview image +- Adjustable time delay. +- Auto hides it own window when grabbing. +- Grabs desktop or specific windows +- Save to various formats +- Auto increment filename + + +The original KSnapshot was implemented by Richard Moore (rich@kde.org) +for KDE1. Shortly before KDE2 I rewrote most of it to bring it a bit +closer to KDE2' higher standards. + +This version is still not good, but I wanted something that doesn't +break translations and is still comfortable to old ksnapshot users. + +Use Pixie if you want more functionality. + +Matthias ( ettrich@kde.org) + diff --git a/ksnapshot/configure.in.in b/ksnapshot/configure.in.in new file mode 100644 index 00000000..56c82023 --- /dev/null +++ b/ksnapshot/configure.in.in @@ -0,0 +1,6 @@ +dnl Check for the X shaped windows extension - test taken from kdebase/kwin/clients/keramik +KDE_CHECK_HEADERS(X11/extensions/shape.h,,, +[ +#include <X11/Xlib.h> +#include <X11/Xutil.h> +]) diff --git a/ksnapshot/hi16-app-ksnapshot.png b/ksnapshot/hi16-app-ksnapshot.png Binary files differnew file mode 100644 index 00000000..79743e82 --- /dev/null +++ b/ksnapshot/hi16-app-ksnapshot.png diff --git a/ksnapshot/hi22-app-ksnapshot.png b/ksnapshot/hi22-app-ksnapshot.png Binary files differnew file mode 100644 index 00000000..446af476 --- /dev/null +++ b/ksnapshot/hi22-app-ksnapshot.png diff --git a/ksnapshot/hi32-app-ksnapshot.png b/ksnapshot/hi32-app-ksnapshot.png Binary files differnew file mode 100644 index 00000000..4619ae8d --- /dev/null +++ b/ksnapshot/hi32-app-ksnapshot.png diff --git a/ksnapshot/hi48-app-ksnapshot.png b/ksnapshot/hi48-app-ksnapshot.png Binary files differnew file mode 100644 index 00000000..f962f5a0 --- /dev/null +++ b/ksnapshot/hi48-app-ksnapshot.png diff --git a/ksnapshot/hisc-app-ksnapshot.svgz b/ksnapshot/hisc-app-ksnapshot.svgz Binary files differnew file mode 100644 index 00000000..22f4e3fb --- /dev/null +++ b/ksnapshot/hisc-app-ksnapshot.svgz diff --git a/ksnapshot/ksnapshot.cpp b/ksnapshot/ksnapshot.cpp new file mode 100644 index 00000000..a0e1d06f --- /dev/null +++ b/ksnapshot/ksnapshot.cpp @@ -0,0 +1,510 @@ +/* + * KSnapshot + * + * (c) Richard J. Moore 1997-2002 + * (c) Matthias Ettrich 2000 + * (c) Aaron J. Seigo 2002 + * (c) Nadeem Hasan 2003 + * (c) Bernd Brandstetter 2004 + * + * Released under the LGPL see file LICENSE for details. + */ + + +#include <klocale.h> +#include <kimageio.h> +#include <kfiledialog.h> +#include <kimagefilepreview.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <kapplication.h> +#include <kprinter.h> +#include <kio/netaccess.h> +#include <ksavefile.h> +#include <ktempfile.h> + +#include <qbitmap.h> +#include <qdragobject.h> +#include <qimage.h> +#include <qclipboard.h> +#include <qvbox.h> + +#include <kaccel.h> +#include <knotifyclient.h> +#include <khelpmenu.h> +#include <kpopupmenu.h> +#include <kpushbutton.h> +#include <kstartupinfo.h> + +#include <qcursor.h> +#include <qregexp.h> +#include <qpainter.h> +#include <qpaintdevicemetrics.h> +#include <qwhatsthis.h> + +#include <stdlib.h> + +#include "ksnapshot.h" +#include "regiongrabber.h" +#include "windowgrabber.h" +#include "ksnapshotwidget.h" + +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +#include <config.h> + +#include <kglobal.h> + +#define kApp KApplication::kApplication() + +KSnapshot::KSnapshot(QWidget *parent, const char *name, bool grabCurrent) + : DCOPObject("interface"), + KDialogBase(parent, name, true, QString::null, Help|User1, User1, + true, KStdGuiItem::quit() ) +{ + grabber = new QWidget( 0, 0, WStyle_Customize | WX11BypassWM ); + grabber->move( -1000, -1000 ); + grabber->installEventFilter( this ); + + KStartupInfo::appStarted(); + + QVBox *vbox = makeVBoxMainWidget(); + mainWidget = new KSnapshotWidget( vbox, "mainWidget" ); + + connect(mainWidget, SIGNAL(startImageDrag()), SLOT(slotDragSnapshot())); + + connect( mainWidget, SIGNAL( newClicked() ), SLOT( slotGrab() ) ); + connect( mainWidget, SIGNAL( saveClicked() ), SLOT( slotSaveAs() ) ); + connect( mainWidget, SIGNAL( printClicked() ), SLOT( slotPrint() ) ); + connect( mainWidget, SIGNAL( copyClicked() ), SLOT( slotCopy() ) ); + + grabber->show(); + grabber->grabMouse( waitCursor ); + + if ( !grabCurrent ) + snapshot = QPixmap::grabWindow( qt_xrootwin() ); + else { + mainWidget->setMode( WindowUnderCursor ); + mainWidget->setIncludeDecorations( true ); + performGrab(); + } + + updatePreview(); + grabber->releaseMouse(); + grabber->hide(); + + KConfig *conf=KGlobal::config(); + conf->setGroup("GENERAL"); + mainWidget->setDelay(conf->readNumEntry("delay",0)); + mainWidget->setMode( conf->readNumEntry( "mode", 0 ) ); + mainWidget->setIncludeDecorations(conf->readBoolEntry("includeDecorations",true)); + filename = KURL::fromPathOrURL( conf->readPathEntry( "filename", QDir::currentDirPath()+"/"+i18n("snapshot")+"1.png" )); + + // Make sure the name is not already being used + while(KIO::NetAccess::exists( filename, false, this )) { + autoincFilename(); + } + + connect( &grabTimer, SIGNAL( timeout() ), this, SLOT( grabTimerDone() ) ); + connect( &updateTimer, SIGNAL( timeout() ), this, SLOT( updatePreview() ) ); + QTimer::singleShot( 0, this, SLOT( updateCaption() ) ); + + KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::instance()->aboutData(), false); + + QPushButton *helpButton = actionButton( Help ); + helpButton->setPopup(helpMenu->menu()); + + KAccel* accel = new KAccel(this); + accel->insert(KStdAccel::Quit, kapp, SLOT(quit())); + accel->insert( "QuickSave", i18n("Quick Save Snapshot &As..."), + i18n("Save the snapshot to the file specified by the user without showing the file dialog."), + CTRL+SHIFT+Key_S, this, SLOT(slotSave())); + accel->insert(KStdAccel::Save, this, SLOT(slotSaveAs())); +// accel->insert(KShortcut(CTRL+Key_A), this, SLOT(slotSaveAs())); + accel->insert( "SaveAs", i18n("Save Snapshot &As..."), + i18n("Save the snapshot to the file specified by the user."), + CTRL+Key_A, this, SLOT(slotSaveAs())); + accel->insert(KStdAccel::Print, this, SLOT(slotPrint())); + accel->insert(KStdAccel::New, this, SLOT(slotGrab())); + accel->insert(KStdAccel::Copy, this, SLOT(slotCopy())); + + accel->insert( "Quit2", Key_Q, this, SLOT(slotSave())); + accel->insert( "Save2", Key_S, this, SLOT(slotSaveAs())); + accel->insert( "Print2", Key_P, this, SLOT(slotPrint())); + accel->insert( "New2", Key_N, this, SLOT(slotGrab())); + accel->insert( "New3", Key_Space, this, SLOT(slotGrab())); + + setEscapeButton( User1 ); + connect( this, SIGNAL( user1Clicked() ), SLOT( reject() ) ); + + mainWidget->btnNew->setFocus(); +} + +KSnapshot::~KSnapshot() +{ +} + +void KSnapshot::resizeEvent( QResizeEvent *event) +{ + if( !updateTimer.isActive() ) + updateTimer.start(200, true); + else + updateTimer.changeInterval(200); +} + +bool KSnapshot::save( const QString &filename ) +{ + return save( KURL::fromPathOrURL( filename )); +} + +bool KSnapshot::save( const KURL& url ) +{ + if ( KIO::NetAccess::exists( url, false, this ) ) { + const QString title = i18n( "File Exists" ); + const QString text = i18n( "<qt>Do you really want to overwrite <b>%1</b>?</qt>" ).arg(url.prettyURL()); + if (KMessageBox::Continue != KMessageBox::warningContinueCancel( this, text, title, i18n("Overwrite") ) ) + { + return false; + } + } + + QString type( KImageIO::type(url.path()) ); + if ( type.isNull() ) + type = "PNG"; + + bool ok = false; + + if ( url.isLocalFile() ) { + KSaveFile saveFile( url.path() ); + if ( saveFile.status() == 0 ) { + if ( snapshot.save( saveFile.file(), type.latin1() ) ) + ok = saveFile.close(); + } + } + else { + KTempFile tmpFile; + tmpFile.setAutoDelete( true ); + if ( tmpFile.status() == 0 ) { + if ( snapshot.save( tmpFile.file(), type.latin1() ) ) { + if ( tmpFile.close() ) + ok = KIO::NetAccess::upload( tmpFile.name(), url, this ); + } + } + } + + QApplication::restoreOverrideCursor(); + if ( !ok ) { + kdWarning() << "KSnapshot was unable to save the snapshot" << endl; + + QString caption = i18n("Unable to save image"); + QString text = i18n("KSnapshot was unable to save the image to\n%1.") + .arg(url.prettyURL()); + KMessageBox::error(this, text, caption); + } + + return ok; +} + +void KSnapshot::slotSave() +{ + if ( save(filename) ) { + modified = false; + autoincFilename(); + } +} + +void KSnapshot::slotSaveAs() +{ + QStringList mimetypes = KImageIO::mimeTypes( KImageIO::Writing ); + KFileDialog dlg( filename.url(), mimetypes.join(" "), this, "filedialog", true); + + dlg.setOperationMode( KFileDialog::Saving ); + dlg.setCaption( i18n("Save As") ); + + KImageFilePreview *ip = new KImageFilePreview( &dlg ); + dlg.setPreviewWidget( ip ); + + if ( !dlg.exec() ) + return; + + KURL url = dlg.selectedURL(); + if ( !url.isValid() ) + return; + + if ( save(url) ) { + filename = url; + modified = false; + autoincFilename(); + } +} + +void KSnapshot::slotCopy() +{ + QClipboard *cb = QApplication::clipboard(); + cb->setPixmap( snapshot ); +} + +void KSnapshot::slotDragSnapshot() +{ + QDragObject *drobj = new QImageDrag(snapshot.convertToImage(), this); + drobj->setPixmap(mainWidget->preview()); + drobj->dragCopy(); +} + +void KSnapshot::slotGrab() +{ + hide(); + + if ( mainWidget->delay() && mainWidget->mode() != Region ) + grabTimer.start( mainWidget->delay() * 1000, true ); + else { + if ( mainWidget->mode() == Region ) { + rgnGrab = new RegionGrabber(); + connect( rgnGrab, SIGNAL( regionGrabbed( const QPixmap & ) ), + SLOT( slotRegionGrabbed( const QPixmap & ) ) ); + } + else { + grabber->show(); + grabber->grabMouse( crossCursor ); + } + } +} + +void KSnapshot::slotPrint() +{ + KPrinter printer; + if (snapshot.width() > snapshot.height()) + printer.setOrientation(KPrinter::Landscape); + else + printer.setOrientation(KPrinter::Portrait); + + qApp->processEvents(); + + if (printer.setup(this, i18n("Print Screenshot"))) + { + qApp->processEvents(); + + QPainter painter(&printer); + QPaintDeviceMetrics metrics(painter.device()); + + float w = snapshot.width(); + float dw = w - metrics.width(); + float h = snapshot.height(); + float dh = h - metrics.height(); + bool scale = false; + + if ( (dw > 0.0) || (dh > 0.0) ) + scale = true; + + if ( scale ) { + + QImage img = snapshot.convertToImage(); + qApp->processEvents(); + + float newh, neww; + if ( dw > dh ) { + neww = w-dw; + newh = neww/w*h; + } + else { + newh = h-dh; + neww = newh/h*w; + } + + img = img.smoothScale( int(neww), int(newh), QImage::ScaleMin ); + qApp->processEvents(); + + int x = (metrics.width()-img.width())/2; + int y = (metrics.height()-img.height())/2; + + painter.drawImage( x, y, img); + } + else { + int x = (metrics.width()-snapshot.width())/2; + int y = (metrics.height()-snapshot.height())/2; + painter.drawPixmap( x, y, snapshot ); + } + } + + qApp->processEvents(); +} + +void KSnapshot::slotRegionGrabbed( const QPixmap &pix ) +{ + if ( !pix.isNull() ) + { + snapshot = pix; + updatePreview(); + modified = true; + updateCaption(); + } + + delete rgnGrab; + QApplication::restoreOverrideCursor(); + show(); +} + +void KSnapshot::slotWindowGrabbed( const QPixmap &pix ) +{ + if ( !pix.isNull() ) + { + snapshot = pix; + updatePreview(); + modified = true; + updateCaption(); + } + + QApplication::restoreOverrideCursor(); + show(); +} + +void KSnapshot::closeEvent( QCloseEvent * e ) +{ + KConfig *conf=KGlobal::config(); + conf->setGroup("GENERAL"); + conf->writeEntry("delay",mainWidget->delay()); + conf->writeEntry("mode",mainWidget->mode()); + conf->writeEntry("includeDecorations",mainWidget->includeDecorations()); + KURL url = filename; + url.setPass( QString::null ); + conf->writePathEntry("filename",url.url()); + e->accept(); +} + +bool KSnapshot::eventFilter( QObject* o, QEvent* e) +{ + if ( o == grabber && e->type() == QEvent::MouseButtonPress ) { + QMouseEvent* me = (QMouseEvent*) e; + if ( QWidget::mouseGrabber() != grabber ) + return false; + if ( me->button() == LeftButton ) + performGrab(); + } + return false; +} + +void KSnapshot::autoincFilename() +{ + // Extract the filename from the path + QString name= filename.fileName(); + + // If the name contains a number then increment it + QRegExp numSearch("[0-9]+"); + + // Does it have a number? + int start = numSearch.search(name); + if (start != -1) { + // It has a number, increment it + int len = numSearch.matchedLength(); + QString numAsStr= name.mid(start, len); + QString number = QString::number(numAsStr.toInt() + 1); + number = number.rightJustify( len, '0'); + name.replace(start, len, number ); + } + else { + // no number + start = name.findRev('.'); + if (start != -1) { + // has a . somewhere, e.g. it has an extension + name.insert(start, '1'); + } + else { + // no extension, just tack it on to the end + name += '1'; + } + } + + //Rebuild the path + KURL newURL = filename; + newURL.setFileName( name ); + setURL( newURL.url() ); +} + +void KSnapshot::updatePreview() +{ + mainWidget->setPreview( snapshot ); +} + +void KSnapshot::grabTimerDone() +{ + if ( mainWidget->mode() == Region ) { + rgnGrab = new RegionGrabber(); + connect( rgnGrab, SIGNAL( regionGrabbed( const QPixmap & ) ), + SLOT( slotRegionGrabbed( const QPixmap & ) ) ); + } + else { + performGrab(); + } + KNotifyClient::beep(i18n("The screen has been successfully grabbed.")); +} + +void KSnapshot::performGrab() +{ + grabber->releaseMouse(); + grabber->hide(); + grabTimer.stop(); + if ( mainWidget->mode() == ChildWindow ) { + WindowGrabber wndGrab; + connect( &wndGrab, SIGNAL( windowGrabbed( const QPixmap & ) ), + SLOT( slotWindowGrabbed( const QPixmap & ) ) ); + wndGrab.exec(); + } + else if ( mainWidget->mode() == WindowUnderCursor ) { + snapshot = WindowGrabber::grabCurrent( mainWidget->includeDecorations() ); + } + else { + snapshot = QPixmap::grabWindow( qt_xrootwin() ); + } + updatePreview(); + QApplication::restoreOverrideCursor(); + modified = true; + updateCaption(); + show(); +} + +void KSnapshot::setTime(int newTime) +{ + mainWidget->setDelay(newTime); +} + +int KSnapshot::timeout() +{ + return mainWidget->delay(); +} + +void KSnapshot::setURL( const QString &url ) +{ + KURL newURL = KURL::fromPathOrURL( url ); + if ( newURL == filename ) + return; + + filename = newURL; + updateCaption(); +} + +void KSnapshot::setGrabMode( int m ) +{ + mainWidget->setMode( m ); +} + +int KSnapshot::grabMode() +{ + return mainWidget->mode(); +} + +void KSnapshot::updateCaption() +{ + setCaption( kApp->makeStdCaption( filename.fileName(), true, modified ) ); +} + +void KSnapshot::slotMovePointer(int x, int y) +{ + QCursor::setPos( x, y ); +} + +void KSnapshot::exit() +{ + reject(); +} +#include "ksnapshot.moc" diff --git a/ksnapshot/ksnapshot.desktop b/ksnapshot/ksnapshot.desktop new file mode 100644 index 00000000..311a2199 --- /dev/null +++ b/ksnapshot/ksnapshot.desktop @@ -0,0 +1,92 @@ +[Desktop Entry] +GenericName=Screen Capture Program +GenericName[af]=Skerm Vang Program +GenericName[ar]=برنامج تصوير الشاشة +GenericName[bg]=Снимки на екрана +GenericName[bs]=Program za "hvatanje" slike +GenericName[ca]=Programa de captura de pantalla +GenericName[cs]=Snímač obrazovky +GenericName[cy]=Rhaglen Cipio'r Sgrîn +GenericName[da]=Program til øjebliksbilleder +GenericName[de]=Bildschirmphotos +GenericName[el]=Πρόγραμμα σύλληψης οθόνης +GenericName[eo]=Ekranfota programo +GenericName[es]=Capturador de pantalla +GenericName[et]=Töölaua pildistamine +GenericName[eu]=Pantailari argazkiak ateratzeko programa +GenericName[fa]=برنامۀ گیراندازی پرده +GenericName[fi]=Ruudunkaappausohjelma +GenericName[fr]=Logiciel de capture d'écran +GenericName[ga]=Clár gabhála scáileáin +GenericName[gl]=Progama para facer capturas de pantalla +GenericName[he]=תוכנית לצילום המסך +GenericName[hi]=स्क्रीन केप्चर प्रोग्राम +GenericName[hr]=Program za snimanje zaslona +GenericName[hu]=Képlopó +GenericName[is]=Forrit sem grípur skjámyndir +GenericName[it]=Scatta foto allo schermo +GenericName[ja]=スクリーンキャプチャプログラム +GenericName[kk]=Экраннан түсіріп алу бағдарламасы +GenericName[km]=កម្មវិធីចាប់យកអេក្រង់ +GenericName[lt]=Ekrano kopijos programa +GenericName[lv]=Ekrāna Sagrābšanas Programma +GenericName[ms]=Program Cekupan Skrin +GenericName[mt]=Programm biex tieħu "ritratt" tal-iskrin +GenericName[nb]=Skjermdumpprogram +GenericName[nds]=Schirmfotos opnehmen +GenericName[ne]=पर्दा समात्ने कार्यक्रम +GenericName[nl]=Schermafdrukprogramma +GenericName[nn]=Program for skjermbilete +GenericName[nso]=Lenaneo lago Apesa Pontsho +GenericName[pl]=Program do zrzutów ekranu +GenericName[pt]=Programa de Captura do Ecrã +GenericName[pt_BR]=Programa de Captura de Tela +GenericName[ro]=Program de captură de ecran +GenericName[ru]=Создание снимков экрана +GenericName[rw]=Porogaramu Gufata Mugaragaza +GenericName[se]=Šearbmagovvenprográmma +GenericName[sk]=Zachytenie obrazovky +GenericName[sl]=Program za zajem zaslona +GenericName[sr]=Програм за снимање екрана +GenericName[sr@Latn]=Program za snimanje ekrana +GenericName[sv]=Ta en skärmdump +GenericName[ta]=திரை கைப்பற்றும் நிரலி +GenericName[tg]=Эҷоди суратҳои экран +GenericName[th]=โปรแกรมจับภาพหน้าจอ +GenericName[tr]=Ekran Yakalama Programı +GenericName[uk]=Захоплювач екрана +GenericName[uz]=Skrinshot olish dasturi +GenericName[uz@cyrillic]=Скриншот олиш дастури +GenericName[ven]=Mbekanya mushumo ino gavha tshikirini +GenericName[wa]=Programe po fé des waitroûlêyes +GenericName[xh]=Iinkcazelo Ezigcina Ikhusi +GenericName[zh_CN]=屏幕截图程序 +GenericName[zh_HK]=螢幕擷取程式 +GenericName[zh_TW]=畫面擷取程式 +GenericName[zu]=Iprogremu Yokubamba Isikrini +Name=KSnapshot +Name[af]=K-kiekie +Name[cy]=KCipluniau +Name[eo]=Ekranfotilo +Name[fr]=KSnapShot +Name[hi]=के-स्नेपशॉट +Name[lv]=KSnapšots +Name[ne]=केडीई स्न्यापसट +Name[pl]=Zrzuty ekranu +Name[sv]=Ksnapshot +Name[ta]=கேதிரையை நகலெடுத்தல் +Name[th]=จับภาพ - K +Name[ven]=Tshinepe tsha K +Name[wa]=KWaitroûlêye +Name[zh_TW]=KSnapshot 快照 +Name[zu]=KEsincane isithombe +MimeType= +Exec=ksnapshot -caption "%c" %i %m +Icon=ksnapshot +Path= +Type=Application +Terminal=false +DocPath=ksnapshot/index.html +X-KDE-StartupNotify=true +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Graphics; diff --git a/ksnapshot/ksnapshot.h b/ksnapshot/ksnapshot.h new file mode 100644 index 00000000..486c0a1b --- /dev/null +++ b/ksnapshot/ksnapshot.h @@ -0,0 +1,150 @@ +// -*- c++ -*- + +#ifndef KSNAPSHOT_H +#define KSNAPSHOT_H +#include "ksnapshotiface.h" + +#include <qbitmap.h> +#include <qcursor.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qstyle.h> +#include <qtimer.h> + +#include <dcopclient.h> +#include <kglobalsettings.h> +#include <kdialogbase.h> +#include <kurl.h> + +class RegionGrabber; +class KSnapshotWidget; + +class KSnapshotPreview : public QLabel +{ + Q_OBJECT + + public: + KSnapshotPreview(QWidget *parent, const char *name = 0) + : QLabel(parent, name) + { + setAlignment(AlignHCenter | AlignVCenter); + setCursor(QCursor(Qt::PointingHandCursor)); + } + virtual ~KSnapshotPreview() {} + + void setPixmap(const QPixmap& pm) + { + // if this looks convoluted, that's because it is. drawing a PE_SizeGrip + // does unexpected things when painting directly onto the pixmap + QPixmap pixmap(pm); + QPixmap handle(15, 15); + QBitmap mask(15, 15, true); + + { + QPainter p(&mask); + style().drawPrimitive(QStyle::PE_SizeGrip, &p, QRect(0, 0, 15, 15), palette().active()); + p.end(); + handle.setMask(mask); + } + + { + QPainter p(&handle); + style().drawPrimitive(QStyle::PE_SizeGrip, &p, QRect(0, 0, 15, 15), palette().active()); + p.end(); + } + + QRect rect(pixmap.width() - 16, pixmap.height() - 16, 15, 15); + QPainter p(&pixmap); + p.drawPixmap(rect, handle); + p.end(); + QLabel::setPixmap(pixmap); + } + + signals: + void startDrag(); + + protected: + void mousePressEvent(QMouseEvent * e) + { + mClickPt = e->pos(); + } + + void mouseMoveEvent(QMouseEvent * e) + { + if (mClickPt != QPoint(0, 0) && + (e->pos() - mClickPt).manhattanLength() > KGlobalSettings::dndEventDelay()) + { + mClickPt = QPoint(0, 0); + emit startDrag(); + } + } + + void mouseReleaseEvent(QMouseEvent * /*e*/) + { + mClickPt = QPoint(0, 0); + } + + QPoint mClickPt; +}; + +class KSnapshot : public KDialogBase, virtual public KSnapshotIface +{ + Q_OBJECT + +public: + KSnapshot(QWidget *parent= 0, const char *name= 0, bool grabCurrent=false); + ~KSnapshot(); + + enum CaptureMode { FullScreen=0, WindowUnderCursor=1, Region=2, ChildWindow=3 }; + + bool save( const QString &filename ); + QString url() const { return filename.url(); } + +protected slots: + void slotGrab(); + void slotSave(); + void slotSaveAs(); + void slotCopy(); + void slotPrint(); + void slotMovePointer( int x, int y ); + + void setTime(int newTime); + void setURL(const QString &newURL); + void setGrabMode( int m ); + void exit(); + +protected: + void reject() { close(); } + + virtual void closeEvent( QCloseEvent * e ); + void resizeEvent(QResizeEvent*); + bool eventFilter( QObject*, QEvent* ); + +private slots: + void grabTimerDone(); + void slotDragSnapshot(); + void updateCaption(); + void updatePreview(); + void slotRegionGrabbed( const QPixmap & ); + void slotWindowGrabbed( const QPixmap & ); + +private: + bool save( const KURL& url ); + void performGrab(); + void autoincFilename(); + int grabMode(); + int timeout(); + + QPixmap snapshot; + QTimer grabTimer; + QTimer updateTimer; + QWidget* grabber; + KURL filename; + KSnapshotWidget *mainWidget; + RegionGrabber *rgnGrab; + bool modified; +}; + +#endif // KSNAPSHOT_H + diff --git a/ksnapshot/ksnapshotiface.h b/ksnapshot/ksnapshotiface.h new file mode 100644 index 00000000..6b1f3477 --- /dev/null +++ b/ksnapshot/ksnapshotiface.h @@ -0,0 +1,65 @@ +/** KSnapshot DCOP interface + File: ksnapshotiface.h + Date: January 12, 2001 + Author: Ian Geiser <geiseri@linuxppc.com> + Comments: + This is an addition to the existing KSnapshot code + that will allow other applications to access internal + public member functions via dcop. +**/ + +#ifndef __KS_IFACE_H +#define __KS_IFACE_H + +#include <dcopobject.h> + +class KSnapshotIface : virtual public DCOPObject +{ + K_DCOP + k_dcop: + /** the current filename (as a URL) that will + be used to save to */ + virtual QString url() const = 0; + + /** Grab an image **/ + virtual void slotGrab() = 0; + + /** Prints the image. */ + virtual void slotPrint() = 0; + + /** Saves the image **/ + virtual void slotSave() = 0; + + /** Save the image to the specified filename */ + virtual bool save(const QString &filename) = 0; + + /** Saves image as **/ + virtual void slotSaveAs() = 0; + + /** Copy the snapshot to the clipboard. **/ + virtual void slotCopy() = 0; + + /** Set the timeout value */ + virtual void setTime(int newTime) = 0; + + /** Get the current timeout value */ + virtual int timeout() = 0; + + /** Set the URL to the file to save **/ + virtual void setURL(const QString &newURL) = 0; + + /** Set the ability to grab the entire screen, just the window + containing the mouse, or a region */ + virtual void setGrabMode(int grab) = 0; + + /** Return the current grab mode */ + virtual int grabMode() = 0; + + /** Move the mouse pointer. */ + virtual void slotMovePointer( int x, int y ) = 0; + + /** Exit KSnapshot **/ + virtual void exit() = 0; +}; + +#endif diff --git a/ksnapshot/ksnapshotwidget.ui b/ksnapshot/ksnapshotwidget.ui new file mode 100644 index 00000000..88efce1a --- /dev/null +++ b/ksnapshot/ksnapshotwidget.ui @@ -0,0 +1,361 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KSnapshotWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KSnapshotWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>356</width> + <height>226</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="KSnapshotPreview" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>lblImage</cstring> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>130</height> + </size> + </property> + <property name="whatsThis" stdset="0"> + <string>This is a preview of the current snapshot. + +The image can be dragged to another application or document to copy the full screenshot there. Try it with the Konqueror file manager. + +You can also copy the image to the clipboard by pressing Ctrl+C.</string> + </property> + </widget> + <widget class="Line" row="1" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QSpinBox" row="3" column="1"> + <property name="name"> + <cstring>spinDelay</cstring> + </property> + <property name="suffix"> + <string> sec</string> + </property> + <property name="specialValueText"> + <string>No delay</string> + </property> + <property name="toolTip" stdset="0"> + <string>Snapshot delay in seconds</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +This is the number of seconds to wait after clicking the <i>New Snapshot</i> button before taking the snapshot. +<p> +This is very useful for getting windows, menus and other items on the screen set up just the way you want. +<p> +If <i>no delay</i> is set, the program will wait for a mouse click before taking a snapshot. +</p> +</qt></string> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>lblDelay</cstring> + </property> + <property name="text"> + <string>Snapshot &delay:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>spinDelay</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Cap&ture mode:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>comboMode</cstring> + </property> + </widget> + <spacer row="3" column="2" rowspan="1" colspan="2"> + <property name="name"> + <cstring>Spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>156</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>cbIncludeDecorations</cstring> + </property> + <property name="text"> + <string>Include &window decorations</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="whatsThis" stdset="0"> + <string>When enabled, snapshot of a window will also include the window decorations</string> + </property> + </widget> + <widget class="QComboBox" row="2" column="1" rowspan="1" colspan="3"> + <item> + <property name="text"> + <string>Full Screen</string> + </property> + </item> + <item> + <property name="text"> + <string>Window Under Cursor</string> + </property> + </item> + <item> + <property name="text"> + <string>Region</string> + </property> + </item> + <item> + <property name="text"> + <string>Section of Window</string> + </property> + </item> + <property name="name"> + <cstring>comboMode</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string><qt>Using this menu, you can select from the four following snapshot modes: +<p> +<b>Full Screen</b> - captures the entire desktop.<br> +<b>Window Under Cursor</b> - captures only the window (or menu) that is under the mouse cursor when the snapshot is taken.<br> +<b>Region</b> - captures only the region of the desktop that you specify. When taking a new snapshot in this mode you will be able to select any area of the screen by clicking and dragging the mouse.</p> +<b>Section of Window</b> - captures only a section of the window. When taking a new snapshot in this mode you will be able to select any child window by moving the mouse over it.</p></qt></string> + </property> + </widget> + <widget class="QLayoutWidget" row="0" column="3"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnNew</cstring> + </property> + <property name="text"> + <string>&New Snapshot</string> + </property> + <property name="iconSet"> + <iconset>"ksnapshot", 32</iconset> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to take a new snapshot.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnSave</cstring> + </property> + <property name="text"> + <string>&Save As...</string> + </property> + <property name="iconSet"> + <iconset>"filesave"</iconset> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to save the current snapshot. To quickly save the snapshot without showing the file dialog, press Ctrl+Shift+S. The filename is automatically incremented after each save.</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnCopy</cstring> + </property> + <property name="text"> + <string>&Copy to Clipboard</string> + </property> + <property name="iconSet"> + <iconset>"editcopy"</iconset> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to copy the current snapshot to the clipboard.</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnPrint</cstring> + </property> + <property name="text"> + <string>&Print...</string> + </property> + <property name="iconSet"> + <iconset>"fileprint"</iconset> + </property> + <property name="whatsThis" stdset="0"> + <string>Click this button to print the current screenshot.</string> + </property> + </widget> + </vbox> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KSnapshotPreview</class> + <header location="local">ksnapshot.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <signal>startDrag()</signal> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="660">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000025b49444154789cb595bf4b1b6118c73f962bbc070e115af006210107f52fa8b18b071dbb445ca48bb8199c544a8b53b153092e3ad9d8ad53c962390a2da6507227441207e10296be190a774330070af74202760889899e3f22f50bc7ddfb72efe7799eef7bcf7b0305bbc06d9a4a4e9d5f9e2bd885819bd63cba0ff4a6f9eec800e7fffbd2da01fed81ff1a48d52014213b715d22b3d060d853cdce1d587d65407ec491b79b8d31fb02d0d2ea7d2012b15007422f6ab2f6f04a0ae82bbcb3f3939416882e02ca07454c2dab5086a01c9e749e2237174a1230605524ab29fb2e47fe431c652c8a3cf57c1ddca6e67f16b3ef62f1be7c0616e768ecdad4d8686860008c31067df415625beef475610095e7dbddaf3865db4d9dade223d9fc6adb8acbd5ba37c502608028488dee84830407c344e7a298daee90c3f1d263196400c0adc631773da64617e81dcd71caaaeb0be5977032f2e2d32f37206f385090de0319dbb528ae4641273da647c7c1c599591e06b3b2f24243c0d5b830678358ff03444fe9658df2dc2d390443c81eff5e1b1b56b613c3198189d20168b213481e77b88b868d95171c9ede6281f96b18bf6ddc1fe5f1fafe6513fabb7364783bdfc1efaa08e5b7129154b4c3e9b24359ba21ed4717e3a77b3423515eeb18bac4a6455a29a0a73da445624a56209236eb43eb326a497d29119477bac4179bf8c936f65a2ce14c6b0c1f2ea32ebefd7498c24b08b362b6f57709cabd9f65aa1c72e464d088280cc4686cc462672615b6d1b841ebb06dc50085a3d6f8ca56e845d96d06304f56a34f8e264533d3ddf979a5dcf0f75d0dffa6bbaaf1e0cfc0ff3922877348d5d5a0000000049454e44ae426082</data> + </image> +</images> +<connections> + <connection> + <sender>comboMode</sender> + <signal>activated(int)</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotModeChanged(int)</slot> + </connection> + <connection> + <sender>btnNew</sender> + <signal>clicked()</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotNewClicked()</slot> + </connection> + <connection> + <sender>btnPrint</sender> + <signal>clicked()</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotPrintClicked()</slot> + </connection> + <connection> + <sender>btnSave</sender> + <signal>clicked()</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotSaveClicked()</slot> + </connection> + <connection> + <sender>btnCopy</sender> + <signal>clicked()</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotCopyClicked()</slot> + </connection> + <connection> + <sender>lblImage</sender> + <signal>startDrag()</signal> + <receiver>KSnapshotWidget</receiver> + <slot>slotStartDrag()</slot> + </connection> +</connections> +<tabstops> + <tabstop>btnNew</tabstop> + <tabstop>btnSave</tabstop> + <tabstop>btnCopy</tabstop> + <tabstop>btnPrint</tabstop> + <tabstop>comboMode</tabstop> + <tabstop>spinDelay</tabstop> + <tabstop>cbIncludeDecorations</tabstop> +</tabstops> +<includes> + <include location="global" impldecl="in implementation">kdialog.h</include> + <include location="global" impldecl="in implementation">kiconloader.h</include> + <include location="global" impldecl="in implementation">kglobalsettings.h</include> + <include location="local" impldecl="in implementation">ksnapshotwidget.ui.h</include> +</includes> +<signals> + <signal>newClicked()</signal> + <signal>saveClicked()</signal> + <signal>copyClicked()</signal> + <signal>printClicked()</signal> + <signal>startImageDrag()</signal> +</signals> +<slots> + <slot access="protected" specifier="non virtual">slotModeChanged( int mode )</slot> + <slot access="protected" specifier="non virtual">slotNewClicked()</slot> + <slot access="protected" specifier="non virtual">slotSaveClicked()</slot> + <slot access="protected" specifier="non virtual">slotCopyClicked()</slot> + <slot access="protected" specifier="non virtual">slotPrintClicked()</slot> + <slot access="protected" specifier="non virtual">slotStartDrag()</slot> + <slot specifier="non virtual" returnType="int">previewWidth()</slot> + <slot specifier="non virtual" returnType="int">previewHeight()</slot> +</slots> +<functions> + <function specifier="non virtual">setPreview( const QPixmap & pm )</function> + <function specifier="non virtual">setDelay( int i )</function> + <function specifier="non virtual">setIncludeDecorations( bool b )</function> + <function specifier="non virtual">setMode( int mode )</function> + <function specifier="non virtual" returnType="int">delay()</function> + <function specifier="non virtual" returnType="bool">includeDecorations()</function> + <function specifier="non virtual" returnType="int">mode()</function> + <function specifier="non virtual" returnType="QPixmap">preview()</function> +</functions> +<pixmapfunction>SmallIconSet</pixmapfunction> +<layoutdefaults spacing="6" margin="11"/> +<layoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/> +<includehints> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/ksnapshot/ksnapshotwidget.ui.h b/ksnapshot/ksnapshotwidget.ui.h new file mode 100644 index 00000000..d7e757f5 --- /dev/null +++ b/ksnapshot/ksnapshotwidget.ui.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + + +void KSnapshotWidget::slotModeChanged( int mode ) +{ + switch ( mode ) + { + case 0: + cbIncludeDecorations->setEnabled(false); + break; + case 1: + cbIncludeDecorations->setEnabled(true); + break; + case 2: + cbIncludeDecorations->setEnabled(false); + break; + case 3: + cbIncludeDecorations->setEnabled(false); + break; + default: + break; + } + + spinDelay->setEnabled(mode != 2); +} + + +void KSnapshotWidget::setPreview( const QPixmap &pm ) +{ + QImage img = pm.convertToImage(); + double r1 = ( ( double ) pm.height() ) / pm.width(); + if ( r1 * previewWidth() < previewHeight() ) + img = img.smoothScale( previewWidth(), + int( previewWidth() * r1 ), + QImage::ScaleMin ); + else + img = img.smoothScale( ( int ) ( ( ( double )previewHeight() ) / r1 ), + previewHeight(), QImage::ScaleMin ); + + QToolTip::remove( lblImage ); + QToolTip::add( lblImage, + QString( "Preview of the snapshot image (%1 x %2)" ) + .arg( pm.width() ).arg( pm.height() ) ); + + lblImage->setPixmap( img ); + lblImage->adjustSize(); +} + + +void KSnapshotWidget::setDelay( int i ) +{ + spinDelay->setValue(i); +} + + +void KSnapshotWidget::setIncludeDecorations( bool b ) +{ + cbIncludeDecorations->setChecked(b); +} + + +void KSnapshotWidget::setMode( int mode ) +{ + comboMode->setCurrentItem(mode); + slotModeChanged(mode); +} + + +int KSnapshotWidget::delay() +{ + return spinDelay->value(); +} + + +bool KSnapshotWidget::includeDecorations() +{ + return cbIncludeDecorations->isChecked(); +} + + +int KSnapshotWidget::mode() +{ + return comboMode->currentItem(); +} + + +void KSnapshotWidget::slotNewClicked() +{ + emit newClicked(); +} + + +void KSnapshotWidget::slotSaveClicked() +{ + emit saveClicked(); +} + + +void KSnapshotWidget::slotPrintClicked() +{ + emit printClicked(); +} + + +void KSnapshotWidget::slotStartDrag() +{ + emit startImageDrag(); +} + + +QPixmap KSnapshotWidget::preview() +{ + return *lblImage->pixmap(); +} + + +int KSnapshotWidget::previewWidth() +{ + return lblImage->width(); +} + + +int KSnapshotWidget::previewHeight() +{ + return lblImage->height(); +} + +void KSnapshotWidget::slotCopyClicked() +{ + emit copyClicked(); +} diff --git a/ksnapshot/main.cpp b/ksnapshot/main.cpp new file mode 100644 index 00000000..f3e397e2 --- /dev/null +++ b/ksnapshot/main.cpp @@ -0,0 +1,77 @@ +/* + (c) Richard J. Moore 1997-2002 + (c) Matthias Ettrich 2000 + (c) Aaron J. Seigo 2002-2004 + (c) Nadeem Hasan 2003 + (c) Waldo Bastian 1999-2002 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or ( at your option ) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kapplication.h> +#include <kimageio.h> +#include <klocale.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kiconloader.h> + +#include "ksnapshot.h" + +static const char description[] = + I18N_NOOP("KDE Screenshot Utility"); + +static KCmdLineOptions options[] = +{ + { "c", 0, 0 }, + { "current", I18N_NOOP("Captures the window under the mouse on startup (instead of the desktop)"), 0 }, + { 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + KAboutData aboutData( "ksnapshot", I18N_NOOP("KSnapshot"), + KSNAPVERSION, description, KAboutData::License_GPL, + "(c) 1997-2004, Richard J. Moore,\n(c) 2000, Matthias Ettrich,\n(c) 2002-2003 Aaron J. Seigo"); + aboutData.addAuthor("Richard J. Moore",0, "rich@kde.org"); + aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org"); + aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@kde.org"); + aboutData.addCredit( "Nadeem Hasan", I18N_NOOP("Region Grabbing\nReworked GUI"), + "nhasan@kde.org" ); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + KApplication app; + + KImageIO::registerFormats(); + + // Create top level window + KSnapshot *toplevel; + + if ( args->isSet( "current" ) ) + toplevel = new KSnapshot( 0, 0, true ); + else + toplevel = new KSnapshot(); + + args->clear(); + app.dcopClient()->setDefaultObject( toplevel->objId() ); + toplevel->setCaption( app.makeStdCaption("") ); + app.setMainWidget(toplevel); + toplevel->show(); + return app.exec(); +} + diff --git a/ksnapshot/regiongrabber.cpp b/ksnapshot/regiongrabber.cpp new file mode 100644 index 00000000..c1d8ed98 --- /dev/null +++ b/ksnapshot/regiongrabber.cpp @@ -0,0 +1,177 @@ +/* + Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or ( at your option ) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "regiongrabber.h" + +#include <qapplication.h> +#include <qpainter.h> +#include <qpalette.h> +#include <qstyle.h> +#include <qtimer.h> +#include <qtooltip.h> + +#include <kglobalsettings.h> + +SizeTip::SizeTip( QWidget *parent, const char *name ) + : QLabel( parent, name, WStyle_Customize | WX11BypassWM | + WStyle_StaysOnTop | WStyle_NoBorder | WStyle_Tool ) +{ + setMargin( 2 ); + setIndent( 0 ); + setFrameStyle( QFrame::Plain | QFrame::Box ); + + setPalette( QToolTip::palette() ); +} + +void SizeTip::setTip( const QRect &rect ) +{ + QString tip = QString( "%1x%2" ).arg( rect.width() ) + .arg( rect.height() ); + + setText( tip ); + adjustSize(); + + positionTip( rect ); +} + +void SizeTip::positionTip( const QRect &rect ) +{ + QRect tipRect = geometry(); + tipRect.moveTopLeft( QPoint( 0, 0 ) ); + + if ( rect.intersects( tipRect ) ) + { + QRect deskR = KGlobalSettings::desktopGeometry( QPoint( 0, 0 ) ); + + tipRect.moveCenter( QPoint( deskR.width()/2, deskR.height()/2 ) ); + if ( !rect.contains( tipRect, true ) && rect.intersects( tipRect ) ) + tipRect.moveBottomRight( geometry().bottomRight() ); + } + + move( tipRect.topLeft() ); +} + +RegionGrabber::RegionGrabber() + : QWidget( 0, 0, WStyle_Customize | WX11BypassWM ), + mouseDown( false ), sizeTip( 0L ) +{ + sizeTip = new SizeTip( ( QWidget * )0L ); + + tipTimer = new QTimer( this ); + connect( tipTimer, SIGNAL( timeout() ), SLOT( updateSizeTip() ) ); + + QTimer::singleShot( 200, this, SLOT( initGrabber() ) ); +} + +RegionGrabber::~RegionGrabber() +{ + delete sizeTip; +} + +void RegionGrabber::initGrabber() +{ + pixmap = QPixmap::grabWindow( qt_xrootwin() ); + setPaletteBackgroundPixmap( pixmap ); + + QDesktopWidget desktopWidget; + QRect desktopSize; + if ( desktopWidget.isVirtualDesktop() ) + desktopSize = desktopWidget.geometry(); + else + desktopSize = desktopWidget.screenGeometry( qt_xrootwin() ); + + setGeometry( desktopSize ); + showFullScreen(); + + QApplication::setOverrideCursor( crossCursor ); +} + +void RegionGrabber::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == LeftButton ) + { + mouseDown = true; + grabRect = QRect( e->pos(), e->pos() ); + } +} + +void RegionGrabber::mouseMoveEvent( QMouseEvent *e ) +{ + if ( mouseDown ) + { + sizeTip->hide(); + tipTimer->start( 250, true ); + + drawRubber(); + grabRect.setBottomRight( e->pos() ); + drawRubber(); + } +} + +void RegionGrabber::mouseReleaseEvent( QMouseEvent *e ) +{ + mouseDown = false; + drawRubber(); + sizeTip->hide(); + + grabRect.setBottomRight( e->pos() ); + grabRect = grabRect.normalize(); + + QPixmap region = QPixmap::grabWindow( winId(), grabRect.x(), grabRect.y(), + grabRect.width(), grabRect.height() ); + + QApplication::restoreOverrideCursor(); + + emit regionGrabbed( region ); +} + +void RegionGrabber::keyPressEvent( QKeyEvent *e ) +{ + if ( e->key() == Key_Escape ) + { + QApplication::restoreOverrideCursor(); + emit regionGrabbed( QPixmap() ); + } + else + e->ignore(); +} + +void RegionGrabber::updateSizeTip() +{ + QRect rect = grabRect.normalize(); + + sizeTip->setTip( rect ); + sizeTip->show(); +} + +void RegionGrabber::drawRubber() +{ + QPainter p; + p.begin( this ); + p.setRasterOp( NotROP ); + p.setPen( QPen( color0, 1 ) ); + p.setBrush( NoBrush ); + + style().drawPrimitive( QStyle::PE_FocusRect, &p, grabRect, colorGroup(), + QStyle::Style_Default, QStyleOption( colorGroup().base() ) ); + + p.end(); +} + +#include "regiongrabber.moc" diff --git a/ksnapshot/regiongrabber.h b/ksnapshot/regiongrabber.h new file mode 100644 index 00000000..ee9a8238 --- /dev/null +++ b/ksnapshot/regiongrabber.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or ( at your option ) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef REGIONGRABBER_H +#define REGIONGRABBER_H + +#include <qlabel.h> +#include <qpixmap.h> + +class QTimer; + +class SizeTip : public QLabel +{ + public: + SizeTip( QWidget *parent, const char *name=0 ); + ~SizeTip() {} + + void setTip( const QRect &rect ); + void positionTip( const QRect &rect ); +}; + +class RegionGrabber : public QWidget +{ + Q_OBJECT + + public: + RegionGrabber(); + ~RegionGrabber(); + + protected slots: + void initGrabber(); + void updateSizeTip(); + + signals: + void regionGrabbed( const QPixmap & ); + + protected: + void mousePressEvent( QMouseEvent *e ); + void mouseReleaseEvent( QMouseEvent *e ); + void mouseMoveEvent( QMouseEvent *e ); + void keyPressEvent( QKeyEvent *e ); + + void drawRubber(); + + bool mouseDown; + QRect grabRect; + QPixmap pixmap; + + SizeTip *sizeTip; + QTimer *tipTimer; +}; + +#endif // REGIONGRABBER_H + diff --git a/ksnapshot/uninstall.desktop b/ksnapshot/uninstall.desktop new file mode 100644 index 00000000..e1e3e173 --- /dev/null +++ b/ksnapshot/uninstall.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/ksnapshot/windowgrabber.cpp b/ksnapshot/windowgrabber.cpp new file mode 100644 index 00000000..036764b1 --- /dev/null +++ b/ksnapshot/windowgrabber.cpp @@ -0,0 +1,353 @@ +/* + Copyright (C) 2004 Bernd Brandstetter <bbrand@freenet.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or ( at your option ) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "windowgrabber.h" +#include <qbitmap.h> +#include <qpainter.h> +#include <qptrlist.h> +#include <algorithm> + +#include <config.h> + +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H +#include <X11/extensions/shape.h> +#endif + + +static +const int minSize = 8; + +static +bool operator< ( const QRect& r1, const QRect& r2 ) +{ + return r1.width() * r1.height() < r2.width() * r2.height(); +} + +// Recursively iterates over the window w and its children, thereby building +// a tree of window descriptors. Windows in non-viewable state or with height +// or width smaller than minSize will be ignored. +static +void getWindowsRecursive( std::vector<QRect>& windows, Window w, + int rx = 0, int ry = 0, int depth = 0 ) +{ + XWindowAttributes atts; + XGetWindowAttributes( qt_xdisplay(), w, &atts ); + if ( atts.map_state == IsViewable && + atts.width >= minSize && atts.height >= minSize ) { + int x = 0, y = 0; + if ( depth ) { + x = atts.x + rx; + y = atts.y + ry; + } + + QRect r( x, y, atts.width, atts.height ); + if ( std::find( windows.begin(), windows.end(), r ) == windows.end() ) { + windows.push_back( r ); + } + + Window root, parent; + Window* children; + unsigned int nchildren; + + if( XQueryTree( qt_xdisplay(), w, &root, &parent, &children, &nchildren ) != 0 ) { + for( unsigned int i = 0; i < nchildren; ++i ) { + getWindowsRecursive( windows, children[ i ], x, y, depth + 1 ); + } + if( children != NULL ) + XFree( children ); + } + } + if ( depth == 0 ) + std::sort( windows.begin(), windows.end() ); +} + +static +Window findRealWindow( Window w, int depth = 0 ) +{ + if( depth > 5 ) + return None; + static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False ); + Atom type; + int format; + unsigned long nitems, after; + unsigned char* prop; + if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType, + &type, &format, &nitems, &after, &prop ) == Success ) { + if( prop != NULL ) + XFree( prop ); + if( type != None ) + return w; + } + Window root, parent; + Window* children; + unsigned int nchildren; + Window ret = None; + if( XQueryTree( qt_xdisplay(), w, &root, &parent, &children, &nchildren ) != 0 ) { + for( unsigned int i = 0; + i < nchildren && ret == None; + ++i ) + ret = findRealWindow( children[ i ], depth + 1 ); + if( children != NULL ) + XFree( children ); + } + return ret; +} + +static +Window windowUnderCursor( bool includeDecorations = true ) +{ + Window root; + Window child; + uint mask; + int rootX, rootY, winX, winY; + XGrabServer( qt_xdisplay() ); + XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child, + &rootX, &rootY, &winX, &winY, &mask ); + if( child == None ) + child = qt_xrootwin(); + if( !includeDecorations ) { + Window real_child = findRealWindow( child ); + if( real_child != None ) // test just in case + child = real_child; + } + return child; +} + +static +QPixmap grabWindow( Window child, int x, int y, uint w, uint h, uint border ) +{ + QPixmap pm( QPixmap::grabWindow( qt_xrootwin(), x, y, w, h ) ); + +#ifdef HAVE_X11_EXTENSIONS_SHAPE_H + int tmp1, tmp2; + //Check whether the extension is available + if ( XShapeQueryExtension( qt_xdisplay(), &tmp1, &tmp2 ) ) { + QBitmap mask( w, h ); + //As the first step, get the mask from XShape. + int count, order; + XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), child, + ShapeBounding, &count, &order ); + //The ShapeBounding region is the outermost shape of the window; + //ShapeBounding - ShapeClipping is defined to be the border. + //Since the border area is part of the window, we use bounding + // to limit our work region + if (rects) { + //Create a QRegion from the rectangles describing the bounding mask. + QRegion contents; + for ( int pos = 0; pos < count; pos++ ) + contents += QRegion( rects[pos].x, rects[pos].y, + rects[pos].width, rects[pos].height ); + XFree( rects ); + + //Create the bounding box. + QRegion bbox( 0, 0, w, h ); + + if( border > 0 ) { + contents.translate( border, border ); + contents += QRegion( 0, 0, border, h ); + contents += QRegion( 0, 0, w, border ); + contents += QRegion( 0, h - border, w, border ); + contents += QRegion( w - border, 0, border, h ); + } + + //Get the masked away area. + QRegion maskedAway = bbox - contents; + QMemArray<QRect> maskedAwayRects = maskedAway.rects(); + + //Construct a bitmap mask from the rectangles + QPainter p(&mask); + p.fillRect(0, 0, w, h, Qt::color1); + for (uint pos = 0; pos < maskedAwayRects.count(); pos++) + p.fillRect(maskedAwayRects[pos], Qt::color0); + p.end(); + + pm.setMask(mask); + } + } +#endif + + return pm; +} + +WindowGrabber::WindowGrabber() +: QDialog( 0, 0, true, Qt::WStyle_Customize | Qt::WStyle_NoBorder | + Qt::WStyle_StaysOnTop | Qt::WX11BypassWM ), + current( -1 ), yPos( -1 ) +{ + Window root; + int y, x; + uint w, h, border, depth; + XGrabServer( qt_xdisplay() ); + Window child = windowUnderCursor(); + XGetGeometry( qt_xdisplay(), child, &root, &x, &y, &w, &h, &border, &depth ); + QPixmap pm( grabWindow( child, x, y, w, h, border ) ); + getWindowsRecursive( windows, child ); + XUngrabServer( qt_xdisplay() ); + + setPaletteBackgroundPixmap( pm ); + setFixedSize( pm.size() ); + setMouseTracking( true ); + setGeometry( x, y, w, h ); +} + +WindowGrabber::~WindowGrabber() +{ +} + +QPixmap WindowGrabber::grabCurrent( bool includeDecorations ) +{ + Window root; + int y, x; + uint w, h, border, depth; + XGrabServer( qt_xdisplay() ); + Window child = windowUnderCursor( includeDecorations ); + XGetGeometry( qt_xdisplay(), child, &root, &x, &y, &w, &h, &border, &depth ); + Window parent; + Window* children; + unsigned int nchildren; + if( XQueryTree( qt_xdisplay(), child, &root, &parent, + &children, &nchildren ) != 0 ) { + if( children != NULL ) + XFree( children ); + int newx, newy; + Window dummy; + if( XTranslateCoordinates( qt_xdisplay(), parent, qt_xrootwin(), + x, y, &newx, &newy, &dummy )) { + x = newx; + y = newy; + } + } + QPixmap pm( grabWindow( child, x, y, w, h, border ) ); + XUngrabServer( qt_xdisplay() ); + return pm; +} + +void WindowGrabber::mousePressEvent( QMouseEvent *e ) +{ + if ( e->button() == QMouseEvent::RightButton ) + yPos = e->globalY(); + else { + QPixmap pm; + if ( current ) { + QRect r( windows[ current ] ); + int w = r.width(); + int h = r.height(); + pm.resize( w, h ); + copyBlt( &pm, 0, 0, paletteBackgroundPixmap(), r.x(), r.y(), w, h ); + } + emit windowGrabbed( pm ); + accept(); + } +} + +void WindowGrabber::mouseReleaseEvent( QMouseEvent *e ) +{ + if ( e->button() == QMouseEvent::RightButton ) + yPos = -1; +} + +static +const int minDistance = 10; + +void WindowGrabber::mouseMoveEvent( QMouseEvent *e ) +{ + if ( yPos == -1 ) { + int w = windowIndex( e->pos() ); + if ( w != -1 && w != current ) { + current = w; + drawBorder(); + } + } + else { + int y = e->globalY(); + if ( y > yPos + minDistance ) { + decreaseScope( e->pos() ); + yPos = y; + } + else if ( y < yPos - minDistance ) { + increaseScope( e->pos() ); + yPos = y; + } + } +} + +void WindowGrabber::wheelEvent( QWheelEvent *e ) +{ + if ( e->delta() > 0 ) + increaseScope( e->pos() ); + else if ( e->delta() < 0 ) + decreaseScope( e->pos() ); + else + e->ignore(); +} + +// Increases the scope to the next-bigger window containing the mouse pointer. +// This method is activated by either rotating the mouse wheel forwards or by +// dragging the mouse forwards while keeping the right mouse button pressed. +void WindowGrabber::increaseScope( const QPoint &pos ) +{ + for ( uint i = current + 1; i < windows.size(); i++ ) { + if ( windows[ i ].contains( pos ) ) { + current = i; + break; + } + } + drawBorder(); +} + +// Decreases the scope to the next-smaller window containing the mosue pointer. +// This method is activated by either rotating the mouse wheel backwards or by +// dragging the mouse backwards while keeping the right mouse button pressed. +void WindowGrabber::decreaseScope( const QPoint &pos ) +{ + for ( int i = current - 1; i >= 0; i-- ) { + if ( windows[ i ].contains( pos ) ) { + current = i; + break; + } + } + drawBorder(); +} + +// Searches and returns the index of the first (=smallest) window +// containing the mouse pointer. +int WindowGrabber::windowIndex( const QPoint &pos ) const +{ + for ( uint i = 0; i < windows.size(); i++ ) { + if ( windows[ i ].contains( pos ) ) + return i; + } + return -1; +} + +// Draws a border around the (child) window currently containing the pointer +void WindowGrabber::drawBorder() +{ + repaint(); + + if ( current >= 0 ) { + QPainter p; + p.begin( this ); + p.setPen( QPen( Qt::red, 3 ) ); + p.drawRect( windows[ current ] ); + p.end(); + } +} + +#include "windowgrabber.moc" diff --git a/ksnapshot/windowgrabber.h b/ksnapshot/windowgrabber.h new file mode 100644 index 00000000..43598576 --- /dev/null +++ b/ksnapshot/windowgrabber.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2004 Bernd Brandstetter <bbrand@freenet.de> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or ( at your option ) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this library; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef WINDOWGRABBER_H +#define WINDOWGRABBER_H + +#include <qdialog.h> +#include <qpixmap.h> +#include <vector> +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +class WindowGrabber : public QDialog +{ + Q_OBJECT + +public: + WindowGrabber(); + ~WindowGrabber(); + + static QPixmap grabCurrent( bool includeDecorations = true ); + +signals: + void windowGrabbed( const QPixmap & ); + +protected: + void mousePressEvent( QMouseEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void wheelEvent( QWheelEvent * ); + +private: + void drawBorder(); + void increaseScope( const QPoint & ); + void decreaseScope( const QPoint & ); + int windowIndex( const QPoint & ) const; + std::vector<QRect> windows; + int current; + int yPos; +}; + + +#endif // WINDOWGRABBER_H |