compile
[kdegraphics.git] / ksnapshot / ksnapshot.cpp
blob4a39faafc1f7a643e6fd112b35869a02102fb468
1 /*
2 * Copyright (C) 1997-2008 Richard J. Moore <rich@kde.org>
3 * Copyright (C) 2000 Matthias Ettrich <ettrich@troll.no>
4 * Copyright (C) 2002 Aaron J. Seigo <aseigo@kde.org>
5 * Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
6 * Copyright (C) 2004 Bernd Brandstetter <bbrand@freenet.de>
7 * Copyright (C) 2006 Urs Wolfer <uwolfer @ kde.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
25 #include "ksnapshot.h"
27 #include <QClipboard>
28 #include <QShortcut>
29 #include <QMenu>
30 #include <QDesktopWidget>
32 #include <klocale.h>
34 #include <KDebug>
35 #include <kglobal.h>
36 #include <kicon.h>
37 #include <kimageio.h>
38 #include <kcomponentdata.h>
39 #include <kfiledialog.h>
40 #include <kmessagebox.h>
41 #include <kio/netaccess.h>
42 #include <ksavefile.h>
43 #include <kstandardshortcut.h>
44 #include <ktemporaryfile.h>
45 #include <knotification.h>
46 #include <khelpmenu.h>
47 #include <kmenu.h>
48 #include <kmimetypetrader.h>
49 #include <kopenwithdialog.h>
50 #include <krun.h>
51 #include <kstandarddirs.h>
52 #include <kstartupinfo.h>
53 #include <kvbox.h>
54 #include <qdebug.h>
56 #include "regiongrabber.h"
57 #include "windowgrabber.h"
58 #include "ui_ksnapshotwidget.h"
61 class KSnapshotWidget : public QWidget, public Ui::KSnapshotWidget
63 public:
64 KSnapshotWidget(QWidget *parent = 0)
65 : QWidget(parent)
67 setupUi(this);
68 btnNew->setIcon(KIcon("ksnapshot"));
69 btnSave->setIcon(KIcon("document-save"));
70 btnOpen->setIcon(KIcon("document-open"));
71 btnCopy->setIcon(KIcon("edit-copy"));
76 KSnapshot::KSnapshot(QWidget *parent, KSnapshotObject::CaptureMode mode )
77 : KDialog(parent), KSnapshotObject(), modified(false)
79 setCaption( "" );
80 setModal( true );
81 showButtonSeparator( true );
82 setDefaultButton( User1 );
83 setButtons(Help|User1);
84 setButtonGuiItem( User1, KStandardGuiItem::quit() );
85 grabber = new QWidget( 0, Qt::X11BypassWindowManagerHint );
86 grabber->move( -1000, -1000 );
87 grabber->installEventFilter( this );
89 KStartupInfo::appStarted();
91 KVBox *vbox = new KVBox( this );
92 vbox->setSpacing( spacingHint() );
93 setMainWidget( vbox );
95 mainWidget = new KSnapshotWidget( vbox );
97 connect( mainWidget->lblImage, SIGNAL( startDrag() ), SLOT( slotDragSnapshot() ) );
98 connect( mainWidget->btnNew, SIGNAL( clicked() ), SLOT( slotGrab() ) );
99 connect( mainWidget->btnSave, SIGNAL( clicked() ), SLOT( slotSaveAs() ) );
100 connect( mainWidget->btnCopy, SIGNAL( clicked() ), SLOT( slotCopy() ) );
101 // connect( mainWidget->btnOpen, SIGNAL( clicked() ), SLOT( slotOpen() ) );
102 connect( mainWidget->comboMode, SIGNAL( activated(int) ), SLOT( slotModeChanged(int) ) );
104 openMenu = new QMenu(this);
105 mainWidget->btnOpen->setMenu(openMenu);
106 connect(openMenu, SIGNAL(aboutToShow()),
107 this, SLOT(slotPopulateOpenMenu()));
108 connect(openMenu, SIGNAL(triggered(QAction*)),
109 this, SLOT(slotOpen(QAction*)));
111 grabber->show();
112 grabber->grabMouse( Qt::WaitCursor );
114 qDebug() << "Mode = " << mode;
115 if ( mode == KSnapshotObject::FullScreen )
116 snapshot = QPixmap::grabWindow( QApplication::desktop()->winId() );
117 else if ( mode == KSnapshotObject::CurrentScreen ) {
118 qDebug() << "Desktop Geom = " << QApplication::desktop()->geometry();
119 QDesktopWidget *desktop = QApplication::desktop();
120 int screenId = desktop->screenNumber( QCursor::pos() );
121 qDebug() << "Screenid = " << screenId;
122 QRect geom = desktop->screenGeometry( screenId );
123 qDebug() << "Geometry = " << screenId;
124 snapshot = QPixmap::grabWindow( desktop->winId(),
125 geom.x(), geom.y(), geom.width(), geom.height() );
128 else {
129 setMode( mode );
130 switch(mode)
132 case KSnapshotObject::WindowUnderCursor:
134 setIncludeDecorations( true );
135 performGrab();
136 break;
138 case KSnapshotObject::ChildWindow:
140 slotGrab();
141 break;
143 case KSnapshotObject::Region:
145 grabRegion();
146 break;
148 default:
149 break;
153 //When we use argument to take snapshot we mustn't hide it.
154 if(mode != KSnapshotObject::ChildWindow)
156 grabber->releaseMouse();
157 grabber->hide();
160 KConfigGroup conf(KGlobal::config(), "GENERAL");
161 setDelay( conf.readEntry("delay", 0) );
162 setMode( conf.readEntry("mode", 0) );
163 setIncludeDecorations(conf.readEntry("includeDecorations",true));
164 filename = KUrl( conf.readPathEntry( "filename", QDir::currentPath()+'/'+i18n("snapshot")+"1.png" ));
166 // Make sure the name is not already being used
167 while(KIO::NetAccess::exists( filename, KIO::NetAccess::DestinationSide, this )) {
168 autoincFilename();
171 connect( &grabTimer, SIGNAL( timeout() ), this, SLOT( grabTimerDone() ) );
172 connect( &updateTimer, SIGNAL( timeout() ), this, SLOT( updatePreview() ) );
173 QTimer::singleShot( 0, this, SLOT( updateCaption() ) );
175 KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::mainComponent().aboutData(), true);
176 setButtonMenu( Help, helpMenu->menu() );
177 #if 0
178 accel->insert( "QuickSave", i18n("Quick Save Snapshot &As..."),
179 i18n("Save the snapshot to the file specified by the user without showing the file dialog."),
180 Qt::CTRL+Qt::SHIFT+Qt::Key_S, this, SLOT(slotSave()));
181 accel->insert( "SaveAs", i18n("Save Snapshot &As..."),
182 i18n("Save the snapshot to the file specified by the user."),
183 Qt::CTRL+Qt::Key_A, this, SLOT(slotSaveAs()));
184 #endif
186 new QShortcut( KStandardShortcut::shortcut( KStandardShortcut::Quit ).primary(), this, SLOT(reject()));
188 new QShortcut( Qt::Key_Q, this, SLOT(slotSave()));
190 new QShortcut( KStandardShortcut::shortcut( KStandardShortcut::Copy ).primary(), mainWidget->btnCopy, SLOT(animateClick()));
192 new QShortcut( KStandardShortcut::shortcut( KStandardShortcut::Save ).primary(), mainWidget->btnSave, SLOT(animateClick()));
193 new QShortcut( Qt::Key_S, mainWidget->btnSave, SLOT(animateClick()));
195 new QShortcut( KStandardShortcut::shortcut( KStandardShortcut::New ).primary(), mainWidget->btnNew, SLOT(animateClick()) );
196 new QShortcut( Qt::Key_N, mainWidget->btnNew, SLOT(animateClick()) );
197 new QShortcut( Qt::Key_Space, mainWidget->btnNew, SLOT(animateClick()) );
199 setEscapeButton( User1 );
200 connect( this, SIGNAL( user1Clicked() ), SLOT( reject() ) );
202 mainWidget->btnNew->setFocus();
205 KSnapshot::~KSnapshot()
207 delete mainWidget;
210 void KSnapshot::resizeEvent( QResizeEvent * )
212 updateTimer.setSingleShot( true );
213 updateTimer.start( 200 );
216 void KSnapshot::slotSave()
218 if ( save(filename, this) ) {
219 modified = false;
220 autoincFilename();
221 updateCaption();
225 void KSnapshot::slotSaveAs()
227 QStringList mimetypes = KImageIO::mimeTypes( KImageIO::Writing );
228 KFileDialog dlg( filename.url(), mimetypes.join(" "), this);
230 dlg.setOperationMode( KFileDialog::Saving );
231 dlg.setCaption( i18n("Save As") );
232 dlg.setSelection( filename.url() );
234 dlg.setInlinePreviewShown(true);
236 if ( !dlg.exec() )
237 return;
239 KUrl url = dlg.selectedUrl();
240 if ( !url.isValid() )
241 return;
243 if ( save(url,this) ) {
244 filename = url;
245 modified = false;
246 autoincFilename();
247 updateCaption();
251 void KSnapshot::slotCopy()
253 QClipboard *cb = QApplication::clipboard();
254 cb->setPixmap( snapshot );
257 void KSnapshot::slotDragSnapshot()
259 QDrag *drag = new QDrag(this);
261 drag->setMimeData(new QMimeData);
262 drag->mimeData()->setImageData(snapshot);
263 drag->setPixmap(preview());
264 drag->start();
267 void KSnapshot::slotGrab()
269 hide();
271 if ( delay() ) {
272 //kDebug() << "starting timer with time of" << delay();
273 grabTimer.start( delay());
275 else {
276 if ( mode() == Region ) {
277 grabRegion();
279 else {
280 grabber->show();
281 grabber->grabMouse( Qt::CrossCursor );
286 void KSnapshot::slotOpen(const QString& application)
288 QString fileopen = KStandardDirs::locateLocal("tmp", filename.fileName());
290 if (!saveEqual(fileopen,this))
292 return;
295 KUrl::List list;
296 list.append(fileopen);
297 KRun::run(application, list, this);
300 void KSnapshot::slotOpen(QAction* action)
302 KSnapshotServiceAction* serviceAction =
303 qobject_cast<KSnapshotServiceAction*>(action);
305 if (!serviceAction)
307 return;
310 KService::Ptr service = serviceAction->service;
311 QString fileopen = KStandardDirs::locateLocal("tmp", filename.fileName());
313 if (!saveEqual(fileopen,this))
315 return;
318 KUrl::List list;
319 list.append(fileopen);
321 if (!service)
323 KOpenWithDialog dlg(list, this);
324 if (!dlg.exec())
326 return;
329 service = dlg.service();
331 if (!service && !dlg.text().isEmpty())
333 KRun::run(dlg.text(), list, this);
334 return;
338 // we have an action with a service, run it!
339 KRun::run(*service, list, this, true);
342 void KSnapshot::slotPopulateOpenMenu()
344 QList<QAction*> currentActions = openMenu->actions();
345 foreach (QAction* currentAction, currentActions)
347 openMenu->removeAction(currentAction);
348 currentAction->deleteLater();
351 KService::List services = KMimeTypeTrader::self()->query( "image/png");
352 QMap<QString, KService::Ptr> apps;
354 foreach (const KService::Ptr &service, services)
356 apps.insert(service->name(), service);
359 foreach (const KService::Ptr &service, apps)
361 QString name = service->name().replace( "&", "&&" );
362 openMenu->addAction(new KSnapshotServiceAction(service,
363 KIcon(service->icon()),
364 name, this));
367 openMenu->addSeparator();
368 KService::Ptr none;
369 openMenu->addAction(new KSnapshotServiceAction(none,
370 i18n("Other Application..."),
371 this));
374 void KSnapshot::slotRegionGrabbed( const QPixmap &pix )
376 if ( !pix.isNull() )
378 snapshot = pix;
379 updatePreview();
380 modified = true;
381 updateCaption();
384 rgnGrab->deleteLater();
385 QApplication::restoreOverrideCursor();
386 show();
389 void KSnapshot::slotWindowGrabbed( const QPixmap &pix )
391 if ( !pix.isNull() )
393 snapshot = pix;
394 updatePreview();
395 modified = true;
396 updateCaption();
399 QApplication::restoreOverrideCursor();
400 show();
403 void KSnapshot::closeEvent( QCloseEvent * e )
405 KConfigGroup conf(KGlobal::config(), "GENERAL");
406 conf.writeEntry("delay",delay());
407 conf.writeEntry("mode",mode());
408 conf.writeEntry("includeDecorations",includeDecorations());
409 KUrl url = filename;
410 url.setPass( QString::null ); //krazy:exclude=nullstrassign for old broken gcc
411 conf.writePathEntry("filename",url.url());
413 conf.sync();
414 e->accept();
417 bool KSnapshot::eventFilter( QObject* o, QEvent* e)
419 if ( o == grabber && e->type() == QEvent::MouseButtonPress ) {
420 QMouseEvent* me = (QMouseEvent*) e;
421 if ( QWidget::mouseGrabber() != grabber )
422 return false;
423 if ( me->button() == Qt::LeftButton )
424 performGrab();
426 return false;
429 void KSnapshot::updatePreview()
431 setPreview( snapshot );
434 void KSnapshot::grabRegion()
436 rgnGrab = new RegionGrabber();
437 connect( rgnGrab, SIGNAL( regionGrabbed( const QPixmap & ) ),
438 SLOT( slotRegionGrabbed( const QPixmap & ) ) );
442 void KSnapshot::grabTimerDone()
444 if ( mode() == Region ) {
445 grabRegion();
447 else {
448 performGrab();
450 KNotification::beep(i18n("The screen has been successfully grabbed."));
453 void KSnapshot::performGrab()
455 grabber->releaseMouse();
456 grabber->hide();
457 grabTimer.stop();
459 title = QString();
460 windowClass = QString();
462 if ( mode() == ChildWindow ) {
463 WindowGrabber wndGrab;
464 connect( &wndGrab, SIGNAL( windowGrabbed( const QPixmap & ) ),
465 SLOT( slotWindowGrabbed( const QPixmap & ) ) );
466 wndGrab.exec();
468 else if ( mode() == WindowUnderCursor ) {
469 snapshot = WindowGrabber::grabCurrent( includeDecorations() );
471 // If we're showing decorations anyway then we'll add the title and window
472 // class to the output image meta data.
473 if ( includeDecorations() ) {
474 title = WindowGrabber::lastWindowTitle();
475 windowClass = WindowGrabber::lastWindowClass();
478 else if ( mode() == CurrentScreen ) {
479 kDebug() << "Desktop Geom2 = " << QApplication::desktop()->geometry();
480 QDesktopWidget *desktop = QApplication::desktop();
481 int screenId = desktop->screenNumber( QCursor::pos() );
482 kDebug() << "Screenid2 = " << screenId;
483 QRect geom = desktop->screenGeometry( screenId );
484 kDebug() << "Geometry2 = " << geom;
485 snapshot = QPixmap::grabWindow( desktop->winId(),
486 geom.x(), geom.y(), geom.width(), geom.height() );
488 else {
489 snapshot = QPixmap::grabWindow( QApplication::desktop()->winId() );
491 updatePreview();
492 QApplication::restoreOverrideCursor();
493 modified = true;
494 updateCaption();
495 show();
498 void KSnapshot::setTime(int newTime)
500 setDelay(newTime);
503 int KSnapshot::timeout() const
505 return delay();
508 void KSnapshot::setURL( const QString &url )
510 changeUrl( url );
513 void KSnapshot::setGrabMode( int m )
515 setMode( m );
518 int KSnapshot::grabMode() const
520 return mode();
523 void KSnapshot::refreshCaption()
525 updateCaption();
528 void KSnapshot::updateCaption()
530 setCaption( filename.fileName(), modified );
533 void KSnapshot::slotMovePointer(int x, int y)
535 QCursor::setPos( x, y );
538 void KSnapshot::exit()
540 reject();
543 void KSnapshot::slotModeChanged( int mode )
545 switch ( mode )
547 case 0:
548 mainWidget->cbIncludeDecorations->setEnabled(false);
549 break;
550 case 1:
551 mainWidget->cbIncludeDecorations->setEnabled(true);
552 break;
553 case 2:
554 mainWidget->cbIncludeDecorations->setEnabled(false);
555 break;
556 case 3:
557 mainWidget->cbIncludeDecorations->setEnabled(false);
558 break;
559 default:
560 break;
564 void KSnapshot::setPreview( const QPixmap &pm )
566 QPixmap pmScaled = pm.scaled( previewWidth(), previewHeight(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
568 mainWidget->lblImage->setToolTip(
569 i18n( "Preview of the snapshot image (%1 x %2)" ,
570 pm.width(), pm.height() ) );
572 mainWidget->lblImage->setPreview( pmScaled );
573 mainWidget->lblImage->adjustSize();
576 void KSnapshot::setDelay( int i )
578 mainWidget->spinDelay->setValue(i);
581 void KSnapshot::setIncludeDecorations( bool b )
583 mainWidget->cbIncludeDecorations->setChecked(b);
586 void KSnapshot::setMode( int mode )
588 mainWidget->comboMode->setCurrentIndex(mode);
589 slotModeChanged(mode);
592 int KSnapshot::delay() const
594 return mainWidget->spinDelay->value();
597 bool KSnapshot::includeDecorations() const
599 return mainWidget->cbIncludeDecorations->isChecked();
602 int KSnapshot::mode() const
604 return mainWidget->comboMode->currentIndex();
607 QPixmap KSnapshot::preview()
609 return *mainWidget->lblImage->pixmap();
612 int KSnapshot::previewWidth() const
614 return mainWidget->lblImage->width();
617 int KSnapshot::previewHeight() const
619 return mainWidget->lblImage->height();
622 #include "ksnapshot.moc"