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"
30 #include <QDesktopWidget>
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>
48 #include <kmimetypetrader.h>
49 #include <kopenwithdialog.h>
51 #include <kstandarddirs.h>
52 #include <kstartupinfo.h>
56 #include "regiongrabber.h"
57 #include "windowgrabber.h"
58 #include "ui_ksnapshotwidget.h"
61 class KSnapshotWidget
: public QWidget
, public Ui::KSnapshotWidget
64 KSnapshotWidget(QWidget
*parent
= 0)
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)
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
*)));
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() );
132 case KSnapshotObject::WindowUnderCursor
:
134 setIncludeDecorations( true );
138 case KSnapshotObject::ChildWindow
:
143 case KSnapshotObject::Region
:
153 //When we use argument to take snapshot we mustn't hide it.
154 if(mode
!= KSnapshotObject::ChildWindow
)
156 grabber
->releaseMouse();
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 )) {
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() );
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()));
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()
210 void KSnapshot::resizeEvent( QResizeEvent
* )
212 updateTimer
.setSingleShot( true );
213 updateTimer
.start( 200 );
216 void KSnapshot::slotSave()
218 if ( save(filename
, this) ) {
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);
239 KUrl url
= dlg
.selectedUrl();
240 if ( !url
.isValid() )
243 if ( save(url
,this) ) {
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());
267 void KSnapshot::slotGrab()
272 //kDebug() << "starting timer with time of" << delay();
273 grabTimer
.start( delay());
276 if ( mode() == Region
) {
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))
296 list
.append(fileopen
);
297 KRun::run(application
, list
, this);
300 void KSnapshot::slotOpen(QAction
* action
)
302 KSnapshotServiceAction
* serviceAction
=
303 qobject_cast
<KSnapshotServiceAction
*>(action
);
310 KService::Ptr service
= serviceAction
->service
;
311 QString fileopen
= KStandardDirs::locateLocal("tmp", filename
.fileName());
313 if (!saveEqual(fileopen
,this))
319 list
.append(fileopen
);
323 KOpenWithDialog
dlg(list
, this);
329 service
= dlg
.service();
331 if (!service
&& !dlg
.text().isEmpty())
333 KRun::run(dlg
.text(), list
, this);
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()),
367 openMenu
->addSeparator();
369 openMenu
->addAction(new KSnapshotServiceAction(none
,
370 i18n("Other Application..."),
374 void KSnapshot::slotRegionGrabbed( const QPixmap
&pix
)
384 rgnGrab
->deleteLater();
385 QApplication::restoreOverrideCursor();
389 void KSnapshot::slotWindowGrabbed( const QPixmap
&pix
)
399 QApplication::restoreOverrideCursor();
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());
410 url
.setPass( QString::null
); //krazy:exclude=nullstrassign for old broken gcc
411 conf
.writePathEntry("filename",url
.url());
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
)
423 if ( me
->button() == Qt::LeftButton
)
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
) {
450 KNotification::beep(i18n("The screen has been successfully grabbed."));
453 void KSnapshot::performGrab()
455 grabber
->releaseMouse();
460 windowClass
= QString();
462 if ( mode() == ChildWindow
) {
463 WindowGrabber wndGrab
;
464 connect( &wndGrab
, SIGNAL( windowGrabbed( const QPixmap
& ) ),
465 SLOT( slotWindowGrabbed( const QPixmap
& ) ) );
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() );
489 snapshot
= QPixmap::grabWindow( QApplication::desktop()->winId() );
492 QApplication::restoreOverrideCursor();
498 void KSnapshot::setTime(int newTime
)
503 int KSnapshot::timeout() const
508 void KSnapshot::setURL( const QString
&url
)
513 void KSnapshot::setGrabMode( int m
)
518 int KSnapshot::grabMode() const
523 void KSnapshot::refreshCaption()
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()
543 void KSnapshot::slotModeChanged( int mode
)
548 mainWidget
->cbIncludeDecorations
->setEnabled(false);
551 mainWidget
->cbIncludeDecorations
->setEnabled(true);
554 mainWidget
->cbIncludeDecorations
->setEnabled(false);
557 mainWidget
->cbIncludeDecorations
->setEnabled(false);
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"