You can capture video through firewire (with dvgrab), video4linux (with ffmpeg) and x11 video grabbing (with ffmpeg configured with: --enable-x11grab )
svn path=/branches/KDE4/; revision=2276
guide.cpp
editguidecommand.cpp
statusbarmessagelabel.cpp
+ regiongrabber.cpp
)
kde4_add_kcfg_files(kdenlive_SRCS GENERATE_MOC kdenlivesettings.kcfgc )
#include "mainwindow.h"
KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, MltVideoProfile profile, QUndoGroup *undoGroup, MainWindow *parent): QObject(parent), m_render(NULL), m_url(url), m_projectFolder(projectFolder), m_profile(profile), m_fps((double)profile.frame_rate_num / profile.frame_rate_den), m_width(profile.width), m_height(profile.height), m_commandStack(new KUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0) {
+ kDebug()<<"// init profile, ratnum: "<<profile.frame_rate_num<<", "<<profile.frame_rate_num<<", width: "<<profile.width;
m_clipManager = new ClipManager(this);
if (!url.isEmpty()) {
QString tmpFile;
westley.appendChild(tractor);
}
m_scenelist = m_document.toString();
- // kDebug() << "scenelist" << m_scenelist;
+ kDebug() << "KDEnnlive document, init timecode: "<<m_fps;
if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
else m_timecode.setFormat((int) m_fps);
}
m_fps = (double) m_profile.frame_rate_num / m_profile.frame_rate_den;
m_width = m_profile.width;
m_height = m_profile.height;
+ kDebug() << "KDEnnlive document, init timecode from path: "<<path<<", "<<m_fps;
if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
else m_timecode.setFormat((int) m_fps);
}
<default></default>
</entry>
+ <entry name="screengrabcapture" type="String">
+ <label>ffmpeg arguments for x11 grab capture.</label>
+ <default>-f x11grab -r 15 -s %size -i :0.0%offset</default>
+ </entry>
+
+ <entry name="screengrabencoding" type="String">
+ <label>ffmpeg arguments for x11 capture encoding.</label>
+ <default>-vcodec mpeg4</default>
+ </entry>
+
+ <entry name="screengrabextension" type="String">
+ <label>file extension for captured file.</label>
+ <default>avi</default>
+ </entry>
+
+ <entry name="fullscreengrab" type="Bool">
+ <label>Capture full screen.</label>
+ <default>false</default>
+ </entry>
+
<entry name="video4playback" type="String">
<label>ffplay arguments for video playback.</label>
<default></default>
QWidget *p4 = new QWidget;
m_configCapture.setupUi(p4);
page4 = addPage(p4, i18n("Capture"), "audio-card");
+ m_configCapture.tabWidget->setCurrentIndex(KdenliveSettings::defaultcapture());
QWidget *p5 = new QWidget;
m_configShuttle.setupUi(p5);
projectFolder = w->selectedFolder();
delete w;
}
- MltVideoProfile prof = ProfilesDialog::getVideoProfile(profileName);
+ MltVideoProfile prof;
+ if (!profileName.isEmpty()) prof = ProfilesDialog::getVideoProfile(profileName);
+ else prof = ProfilesDialog::getVideoProfile("dv_pal");
if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
KdenliveDoc *doc = new KdenliveDoc(KUrl(), projectFolder, prof, m_commandStack, this);
TrackView *trackView = new TrackView(doc, this);
#include <QToolButton>
#include <QFile>
#include <QDir>
+#include <QDesktopWidget>
#include <KDebug>
#include <KLocale>
}
void RecMonitor::slotVideoDeviceChanged(int ix) {
-
- if (ix == 1) {
- m_discAction->setEnabled(false);
- m_rewAction->setEnabled(false);
- m_fwdAction->setEnabled(false);
- m_recAction->setEnabled(true);
- m_stopAction->setEnabled(false);
- m_playAction->setEnabled(true);
- } else {
- m_discAction->setEnabled(true);
- m_recAction->setEnabled(false);
- m_stopAction->setEnabled(false);
- m_playAction->setEnabled(false);
- m_rewAction->setEnabled(false);
- m_fwdAction->setEnabled(false);
+ switch (ix) {
+ case SCREENGRAB:
+ m_discAction->setEnabled(false);
+ m_rewAction->setEnabled(false);
+ m_fwdAction->setEnabled(false);
+ m_recAction->setEnabled(true);
+ m_stopAction->setEnabled(false);
+ m_playAction->setEnabled(false);
+ break;
+ case VIDEO4LINUX:
+ m_discAction->setEnabled(false);
+ m_rewAction->setEnabled(false);
+ m_fwdAction->setEnabled(false);
+ m_recAction->setEnabled(true);
+ m_stopAction->setEnabled(false);
+ m_playAction->setEnabled(true);
+ break;
+ default: // FIREWIRE
+ m_discAction->setEnabled(true);
+ m_recAction->setEnabled(false);
+ m_stopAction->setEnabled(false);
+ m_playAction->setEnabled(false);
+ m_rewAction->setEnabled(false);
+ m_fwdAction->setEnabled(false);
+ break;
}
}
void RecMonitor::slotStopCapture() {
// stop capture
- if (ui.device_selector->currentIndex() == 0) {
+ switch (ui.device_selector->currentIndex()) {
+ case FIREWIRE:
captureProcess->write("\e", 2);
m_playAction->setIcon(m_playIcon);
m_isPlaying = false;
- } else {
- if (m_isCapturing && ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile);
+ break;
+ case VIDEO4LINUX:
captureProcess->kill();
displayProcess->kill();
- }
+ if (m_isCapturing && ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile);
+ break;
+ case SCREENGRAB:
+ captureProcess->kill();
+ if (m_isCapturing && ui.autoaddbox->isChecked()) emit addProjectClip(m_captureFile);
+ break;
+ default:
+ break;
+ }
}
void RecMonitor::slotStartCapture(bool play) {
if (captureProcess->state() != QProcess::NotRunning) {
- if (ui.device_selector->currentIndex() == 0) {
+ if (ui.device_selector->currentIndex() == FIREWIRE) {
if (m_isPlaying) {
captureProcess->write("k", 1);
//captureProcess->write("\e", 2);
m_displayArgs.clear();
m_isPlaying = false;
- if (ui.device_selector->currentIndex() == 0) {
+ switch (ui.device_selector->currentIndex()) {
+ case FIREWIRE:
m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-";
m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
- } else {
- m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << "-";
- m_displayArgs << KdenliveSettings::video4playback().simplified().split(' ') << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
- }
-
- captureProcess->setStandardOutputProcess(displayProcess);
- if (ui.device_selector->currentIndex() == 0) {
+ captureProcess->setStandardOutputProcess(displayProcess);
captureProcess->setWorkingDirectory(KdenliveSettings::capturefolder());
captureProcess->start("dvgrab", m_captureArgs);
if (play) captureProcess->write(" ", 1);
m_discAction->setEnabled(true);
- } else captureProcess->start("ffmpeg", m_captureArgs);
- displayProcess->start("ffplay", m_displayArgs);
- ui.video_frame->setText(i18n("Initialising..."));
+ break;
+ case VIDEO4LINUX:
+ m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << "-";
+ m_displayArgs << KdenliveSettings::video4playback().simplified().split(' ') << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
+ captureProcess->setStandardOutputProcess(displayProcess);
+ captureProcess->start("ffmpeg", m_captureArgs);
+ break;
+ default:
+ break;
+ }
+ if (ui.device_selector->currentIndex() != SCREENGRAB) {
+ displayProcess->start("ffplay", m_displayArgs);
+ ui.video_frame->setText(i18n("Initialising..."));
+ } else {
+ // do something when starting screen grab
+ }
}
void RecMonitor::slotRecord() {
- if (captureProcess->state() == QProcess::NotRunning && ui.device_selector->currentIndex() == 0) {
+ if (captureProcess->state() == QProcess::NotRunning && ui.device_selector->currentIndex() == FIREWIRE) {
slotStartCapture();
}
if (m_isCapturing) {
- if (ui.device_selector->currentIndex() == 0) {
+ switch (ui.device_selector->currentIndex()) {
+ case FIREWIRE:
captureProcess->write("\e", 2);
m_playAction->setIcon(m_playIcon);
m_isCapturing = false;
m_isPlaying = false;
m_recAction->setChecked(false);
- } else {
+ break;
+ case VIDEO4LINUX:
slotStopCapture();
+ m_isCapturing = false;
QTimer::singleShot(1000, this, SLOT(slotStartCapture()));
+ break;
+ case SCREENGRAB:
+ slotStopCapture();
+ m_isCapturing = false;
+ break;
}
return;
- } else if (ui.device_selector->currentIndex() == 0) {
+ } else if (ui.device_selector->currentIndex() == FIREWIRE) {
m_isCapturing = true;
captureProcess->write("c\n", 3);
return;
}
if (captureProcess->state() == QProcess::NotRunning) {
m_recAction->setChecked(true);
-
- QString path = KdenliveSettings::capturefolder() + "/capture0000.mpg";
+ QString extension = "mpg";
+ if (ui.device_selector->currentIndex() == SCREENGRAB) extension = KdenliveSettings::screengrabextension();
+ QString path = KdenliveSettings::capturefolder() + "/capture0000." + extension;
int i = 1;
while (QFile::exists(path)) {
QString num = QString::number(i).rightJustified(4, '0', false);
- path = KdenliveSettings::capturefolder() + "/capture" + num + ".mpg";
+ path = KdenliveSettings::capturefolder() + "/capture" + num + "." + extension;
i++;
}
m_captureFile = KUrl(path);
- m_isCapturing = true;
m_captureArgs.clear();
m_displayArgs.clear();
+ QString args;
- if (ui.device_selector->currentIndex() == 0) {
+ switch (ui.device_selector->currentIndex()) {
+ case FIREWIRE:
m_captureArgs << "--format" << "hdv" << "-i" << "capture" << "-";
m_displayArgs << "-f" << "mpegts" << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
- } else {
+ captureProcess->setStandardOutputProcess(displayProcess);
+ captureProcess->start("dvgrab", m_captureArgs);
+ break;
+ case VIDEO4LINUX:
m_captureArgs << KdenliveSettings::video4capture().simplified().split(' ') << "-y" << m_captureFile.path() << "-f" << KdenliveSettings::video4vencoding() << "-";
m_displayArgs << KdenliveSettings::video4playback().simplified().split(' ') << "-x" << QString::number(ui.video_frame->width()) << "-y" << QString::number(ui.video_frame->height()) << "-";
- }
+ captureProcess->setStandardOutputProcess(displayProcess);
+ captureProcess->start("ffmpeg", m_captureArgs);
+ break;
+ case SCREENGRAB:
+ if (KdenliveSettings::fullscreengrab()) {
+ const QRect rect = QApplication::desktop()->screenGeometry();
+ args = KdenliveSettings::screengrabcapture().replace("%size", QString::number(rect.width()) + "x" + QString::number(rect.height())).replace("%offset", QString());
+ kDebug()<<"// capture params: "<<args;
+ m_captureArgs << args.simplified().split(' ') <<KdenliveSettings::screengrabencoding().simplified().split(' ')<<m_captureFile.path();
+ ui.video_frame->setText(i18n("Capturing..."));
+ m_isCapturing = true;
+ captureProcess->start("ffmpeg", m_captureArgs);
+ }
+ else {
+ ui.video_frame->setText(i18n("Select region..."));
+ rgnGrab = new RegionGrabber();
+ connect( rgnGrab, SIGNAL( regionGrabbed( const QRect&) ), SLOT( slotStartGrab( const QRect & ) ) );
+ }
+ break;
+ default:
+ break;
+ }
- captureProcess->setStandardOutputProcess(displayProcess);
//ui.video_frame->setScaledContents(false);
- if (ui.device_selector->currentIndex() == 0) captureProcess->start("dvgrab", m_captureArgs);
- else captureProcess->start("ffmpeg", m_captureArgs);
- displayProcess->start("ffplay", m_displayArgs);
- ui.video_frame->setText(i18n("Initialising..."));
+ if (ui.device_selector->currentIndex() != SCREENGRAB) {
+ m_isCapturing = true;
+ displayProcess->start("ffplay", m_displayArgs);
+ ui.video_frame->setText(i18n("Initialising..."));
+ }
} else {
// stop capture
displayProcess->kill();
}
}
+void RecMonitor::slotStartGrab(const QRect &rect)
+{
+ rgnGrab->deleteLater();
+ QApplication::restoreOverrideCursor();
+ show();
+ if (rect.isNull()) return;
+ int width = rect.width();
+ int height = rect.height();
+ if (width % 2 != 0) width--;
+ if (height % 2 != 0) height--;
+ QString args = KdenliveSettings::screengrabcapture().replace("%size", QString::number(width) + "x" + QString::number(height)).replace("%offset", "+" + QString::number(rect.x()) + "," + QString::number(rect.y()));
+ kDebug()<<"// capture params: "<<args;
+ m_captureArgs << args.simplified().split(' ') <<KdenliveSettings::screengrabencoding().simplified().split(' ')<<m_captureFile.path();
+ m_isCapturing = true;
+ ui.video_frame->setText(i18n("Capturing..."));
+ captureProcess->start("ffmpeg", m_captureArgs);
+}
+
void RecMonitor::slotProcessStatus(QProcess::ProcessState status) {
if (status == QProcess::NotRunning) {
m_isCapturing = false;
m_recAction->setChecked(false);
m_stopAction->setEnabled(false);
ui.device_selector->setEnabled(true);
- ui.video_frame->setText(i18n("Not connected"));
+ /*if (captureProcess && captureProcess->exitStatus() == QProcess::CrashExit) {
+ ui.video_frame->setText(i18n("Capture crashed, please check your parameters"));
+ }
+ else*/ ui.video_frame->setText(i18n("Not connected"));
} else {
m_stopAction->setEnabled(true);
ui.device_selector->setEnabled(false);
#include "ui_recmonitor_ui.h"
#include "smallruler.h"
+#include "regiongrabber.h"
class RecMonitor : public QWidget {
Q_OBJECT
RecMonitor(QString name, QWidget *parent = 0);
QString name() const;
+enum CAPTUREDEVICE {FIREWIRE = 0, VIDEO4LINUX = 1, SCREENGRAB =2};
protected:
virtual void mousePressEvent(QMouseEvent * event);
Ui::RecMonitor_UI ui;
QString m_tmpFolder;
QString m_name;
-
+ RegionGrabber *rgnGrab;
bool m_isActive;
void slotRewind();
void slotForward();
void slotDisconnect();
+ void slotStartGrab(const QRect &rect);
public slots:
void refreshRecMonitor(bool visible);
--- /dev/null
+/*
+ * Copyright (C) 2007 Luca Gugelmann <lucag@student.ethz.ch>
+ * Adapted for Kdenlive by Jean-Baptiste Mardelle (2008) jb@kdenlive.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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 General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "regiongrabber.h"
+
+#include <QPainter>
+#include <QMouseEvent>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QToolTip>
+
+#include <klocale.h>
+#include <KWindowSystem>
+
+RegionGrabber::RegionGrabber( ) :
+ QWidget( 0 ), selection(), mouseDown( false ), newSelection( false ),
+ handleSize( 10 ), mouseOverHandle( 0 ), idleTimer(),
+ showHelp( true ), grabbing( false ),
+ TLHandle(0,0,handleSize,handleSize), TRHandle(0,0,handleSize,handleSize),
+ BLHandle(0,0,handleSize,handleSize), BRHandle(0,0,handleSize,handleSize),
+ LHandle(0,0,handleSize,handleSize), THandle(0,0,handleSize,handleSize),
+ RHandle(0,0,handleSize,handleSize), BHandle(0,0,handleSize,handleSize)
+{
+ handles << &TLHandle << &TRHandle << &BLHandle << &BRHandle
+ << &LHandle << &THandle << &RHandle << &BHandle;
+ setMouseTracking( true );
+ setWindowFlags( Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
+ int timeout = KWindowSystem::compositingActive() ? 200 : 50;
+ QTimer::singleShot( timeout, this, SLOT(init()) );
+ connect( &idleTimer, SIGNAL( timeout() ), this, SLOT( displayHelp() ) );
+ idleTimer.start( 3000 );
+}
+
+RegionGrabber::~RegionGrabber()
+{
+}
+
+void RegionGrabber::init()
+{
+ pixmap = QPixmap::grabWindow( QApplication::desktop()->winId() );
+ showFullScreen();
+ resize( pixmap.size() );
+ move(0, 0);
+ setCursor( Qt::CrossCursor );
+}
+
+void RegionGrabber::displayHelp()
+{
+ showHelp = true;
+ update();
+}
+
+void RegionGrabber::paintEvent( QPaintEvent* e )
+{
+ Q_UNUSED( e );
+ if ( grabbing ) // grabWindow() should just get the background
+ return;
+
+ QPainter painter( this );
+
+ QPalette pal(QToolTip::palette());
+ QFont font = QToolTip::font();
+
+ QColor handleColor = pal.color( QPalette::Active, QPalette::Highlight );
+ handleColor.setAlpha( 160 );
+ QColor overlayColor( 0, 0, 0, 160 );
+ QColor textColor = pal.color( QPalette::Active, QPalette::Text );
+ QColor textBackgroundColor = pal.color( QPalette::Active, QPalette::Base );
+ painter.drawPixmap(0, 0, pixmap);
+ painter.setFont(font);
+
+ QRect r = selection.normalized().adjusted( 0, 0, -1, -1 );
+ if ( !selection.isNull() )
+ {
+ QRegion grey( rect() );
+ grey = grey.subtracted( r );
+ painter.setPen( handleColor );
+ painter.setBrush( overlayColor );
+ painter.setClipRegion( grey );
+ painter.drawRect( -1, -1, rect().width() + 1, rect().height() + 1 );
+ painter.setClipRect( rect() );
+ painter.setBrush( Qt::NoBrush );
+ painter.drawRect( r );
+ }
+
+ if ( showHelp )
+ {
+ painter.setPen( textColor );
+ painter.setBrush( textBackgroundColor );
+ QString helpText = i18n( "Select a region using the mouse. To take the snapshot, press the Enter key. Press Esc to quit." );
+ QRect textRect = painter.boundingRect( rect().adjusted( 2, 2, -2, -2 ), Qt::TextWordWrap, helpText );
+ textRect.adjust( -2, -2, 4, 2 );
+ painter.drawRect( textRect );
+ textRect.moveTopLeft( QPoint( 3, 3 ) );
+ painter.drawText( textRect, helpText );
+ }
+
+ if ( selection.isNull() )
+ {
+ return;
+ }
+
+ // The grabbed region is everything which is covered by the drawn
+ // rectangles (border included). This means that there is no 0px
+ // selection, since a 0px wide rectangle will always be drawn as a line.
+ QString txt = QString( "%1x%2" ).arg( selection.width() == 0 ? 2 : selection.width() )
+ .arg( selection.height() == 0 ? 2 : selection.height() );
+ QRect textRect = painter.boundingRect( rect(), Qt::AlignLeft, txt );
+ QRect boundingRect = textRect.adjusted( -4, 0, 0, 0);
+
+ if ( textRect.width() < r.width() - 2*handleSize &&
+ textRect.height() < r.height() - 2*handleSize &&
+ ( r.width() > 100 && r.height() > 100 ) ) // center, unsuitable for small selections
+ {
+ boundingRect.moveCenter( r.center() );
+ textRect.moveCenter( r.center() );
+ }
+ else if ( r.y() - 3 > textRect.height() &&
+ r.x() + textRect.width() < rect().right() ) // on top, left aligned
+ {
+ boundingRect.moveBottomLeft( QPoint( r.x(), r.y() - 3 ) );
+ textRect.moveBottomLeft( QPoint( r.x() + 2, r.y() - 3 ) );
+ }
+ else if ( r.x() - 3 > textRect.width() ) // left, top aligned
+ {
+ boundingRect.moveTopRight( QPoint( r.x() - 3, r.y() ) );
+ textRect.moveTopRight( QPoint( r.x() - 5, r.y() ) );
+ }
+ else if ( r.bottom() + 3 + textRect.height() < rect().bottom() &&
+ r.right() > textRect.width() ) // at bottom, right aligned
+ {
+ boundingRect.moveTopRight( QPoint( r.right(), r.bottom() + 3 ) );
+ textRect.moveTopRight( QPoint( r.right() - 2, r.bottom() + 3 ) );
+ }
+ else if ( r.right() + textRect.width() + 3 < rect().width() ) // right, bottom aligned
+ {
+ boundingRect.moveBottomLeft( QPoint( r.right() + 3, r.bottom() ) );
+ textRect.moveBottomLeft( QPoint( r.right() + 5, r.bottom() ) );
+ }
+ // if the above didn't catch it, you are running on a very tiny screen...
+ painter.setPen( textColor );
+ painter.setBrush( textBackgroundColor );
+ painter.drawRect( boundingRect );
+ painter.drawText( textRect, txt );
+
+ if ( ( r.height() > handleSize*2 && r.width() > handleSize*2 )
+ || !mouseDown )
+ {
+ updateHandles();
+ painter.setPen( handleColor );
+ handleColor.setAlpha( 60 );
+ painter.setBrush( handleColor );
+ painter.drawRects( handleMask().rects() );
+ }
+}
+
+void RegionGrabber::resizeEvent( QResizeEvent* e )
+{
+ Q_UNUSED( e );
+ if ( selection.isNull() )
+ return;
+ QRect r = selection;
+ r.setTopLeft( limitPointToRect( r.topLeft(), rect() ) );
+ r.setBottomRight( limitPointToRect( r.bottomRight(), rect() ) );
+ if ( r.width() <= 1 || r.height() <= 1 ) //this just results in ugly drawing...
+ r = QRect();
+ selection = r;
+}
+
+void RegionGrabber::mousePressEvent( QMouseEvent* e )
+{
+ showHelp = false;
+ idleTimer.stop();
+ if ( e->button() == Qt::LeftButton )
+ {
+ mouseDown = true;
+ dragStartPoint = e->pos();
+ selectionBeforeDrag = selection;
+ if ( !selection.contains( e->pos() ) )
+ {
+ newSelection = true;
+ selection = QRect();
+ showHelp = true;
+ }
+ else
+ {
+ setCursor( Qt::ClosedHandCursor );
+ }
+ }
+ else if ( e->button() == Qt::RightButton )
+ {
+ newSelection = false;
+ selection = QRect();
+ setCursor( Qt::CrossCursor );
+ }
+ update();
+}
+
+void RegionGrabber::mouseMoveEvent( QMouseEvent* e )
+{
+ if ( mouseDown )
+ {
+ if ( newSelection )
+ {
+ QPoint p = e->pos();
+ QRect r = rect();
+ selection = QRect( dragStartPoint, limitPointToRect( p, r ) ).normalized();
+ }
+ else if ( mouseOverHandle == 0 ) // moving the whole selection
+ {
+ QRect r = rect().normalized(), s = selectionBeforeDrag.normalized();
+ QPoint p = s.topLeft() + e->pos() - dragStartPoint;
+ r.setBottomRight( r.bottomRight() - QPoint( s.width(), s.height() ) );
+ if ( !r.isNull() && r.isValid() )
+ selection.moveTo( limitPointToRect( p, r ) );
+ }
+ else // dragging a handle
+ {
+ QRect r = selectionBeforeDrag;
+ QPoint offset = e->pos() - dragStartPoint;
+
+ if ( mouseOverHandle == &TLHandle || mouseOverHandle == &THandle
+ || mouseOverHandle == &TRHandle ) // dragging one of the top handles
+ {
+ r.setTop( r.top() + offset.y() );
+ }
+
+ if ( mouseOverHandle == &TLHandle || mouseOverHandle == &LHandle
+ || mouseOverHandle == &BLHandle ) // dragging one of the left handles
+ {
+ r.setLeft( r.left() + offset.x() );
+ }
+
+ if ( mouseOverHandle == &BLHandle || mouseOverHandle == &BHandle
+ || mouseOverHandle == &BRHandle ) // dragging one of the bottom handles
+ {
+ r.setBottom( r.bottom() + offset.y() );
+ }
+
+ if ( mouseOverHandle == &TRHandle || mouseOverHandle == &RHandle
+ || mouseOverHandle == &BRHandle ) // dragging one of the right handles
+ {
+ r.setRight( r.right() + offset.x() );
+ }
+ r = r.normalized();
+ r.setTopLeft( limitPointToRect( r.topLeft(), rect() ) );
+ r.setBottomRight( limitPointToRect( r.bottomRight(), rect() ) );
+ selection = r;
+ }
+ update();
+ }
+ else
+ {
+ if ( selection.isNull() )
+ return;
+ bool found = false;
+ foreach( QRect* r, handles )
+ {
+ if ( r->contains( e->pos() ) )
+ {
+ mouseOverHandle = r;
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ mouseOverHandle = 0;
+ if ( selection.contains( e->pos() ) )
+ setCursor( Qt::OpenHandCursor );
+ else
+ setCursor( Qt::CrossCursor );
+ }
+ else
+ {
+ if ( mouseOverHandle == &TLHandle || mouseOverHandle == &BRHandle )
+ setCursor( Qt::SizeFDiagCursor );
+ if ( mouseOverHandle == &TRHandle || mouseOverHandle == &BLHandle )
+ setCursor( Qt::SizeBDiagCursor );
+ if ( mouseOverHandle == &LHandle || mouseOverHandle == &RHandle )
+ setCursor( Qt::SizeHorCursor );
+ if ( mouseOverHandle == &THandle || mouseOverHandle == &BHandle )
+ setCursor( Qt::SizeVerCursor );
+ }
+ }
+}
+
+void RegionGrabber::mouseReleaseEvent( QMouseEvent* e )
+{
+ mouseDown = false;
+ newSelection = false;
+ idleTimer.start();
+ if ( mouseOverHandle == 0 && selection.contains( e->pos() ) )
+ setCursor( Qt::OpenHandCursor );
+ update();
+}
+
+void RegionGrabber::mouseDoubleClickEvent( QMouseEvent* )
+{
+ grabRect();
+}
+
+void RegionGrabber::keyPressEvent( QKeyEvent* e )
+{
+ if ( e->key() == Qt::Key_Escape )
+ {
+ emit regionGrabbed( QRect() );
+ close();
+ }
+ else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
+ {
+ grabRect();
+ }
+ else
+ {
+ e->ignore();
+ }
+}
+
+void RegionGrabber::grabRect()
+{
+ QRect r = selection.normalized();
+ if ( !r.isNull() && r.isValid() )
+ {
+ grabbing = true;
+ emit regionGrabbed( r );
+ }
+ close();
+}
+
+void RegionGrabber::updateHandles()
+{
+ QRect r = selection.normalized().adjusted( 0, 0, -1, -1 );
+ int s2 = handleSize / 2;
+
+ TLHandle.moveTopLeft( r.topLeft() );
+ TRHandle.moveTopRight( r.topRight() );
+ BLHandle.moveBottomLeft( r.bottomLeft() );
+ BRHandle.moveBottomRight( r.bottomRight() );
+
+ LHandle.moveTopLeft( QPoint( r.x(), r.y() + r.height() / 2 - s2) );
+ THandle.moveTopLeft( QPoint( r.x() + r.width() / 2 - s2, r.y() ) );
+ RHandle.moveTopRight( QPoint( r.right(), r.y() + r.height() / 2 - s2 ) );
+ BHandle.moveBottomLeft( QPoint( r.x() + r.width() / 2 - s2, r.bottom() ) );
+}
+
+QRegion RegionGrabber::handleMask() const
+{
+ // note: not normalized QRects are bad here, since they will not be drawn
+ QRegion mask;
+ foreach( QRect* rect, handles ) mask += QRegion( *rect );
+ return mask;
+}
+
+QPoint RegionGrabber::limitPointToRect( const QPoint &p, const QRect &r ) const
+{
+ QPoint q;
+ q.setX( p.x() < r.x() ? r.x() : p.x() < r.right() ? p.x() : r.right() );
+ q.setY( p.y() < r.y() ? r.y() : p.y() < r.bottom() ? p.y() : r.bottom() );
+ return q;
+}
+
+#include "regiongrabber.moc"
--- /dev/null
+/*
+ * Copyright (C) 2007 Luca Gugelmann <lucag@student.ethz.ch>
+ * Adapted for Kdenlive by Jean-Baptiste Mardelle (2008) jb@kdenlive.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ * 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 General Public License for more details
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; 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 <QWidget>
+#include <QRegion>
+#include <QPoint>
+#include <QVector>
+#include <QRect>
+#include <QTimer>
+
+class QPaintEvent;
+class QResizeEvent;
+class QMouseEvent;
+
+class RegionGrabber : public QWidget
+{
+ Q_OBJECT
+public:
+ RegionGrabber();
+ ~RegionGrabber();
+
+protected slots:
+ void init();
+ void displayHelp();
+
+signals:
+ void regionGrabbed( const QRect & );
+
+protected:
+ void paintEvent( QPaintEvent* e );
+ void resizeEvent( QResizeEvent* e );
+ void mousePressEvent( QMouseEvent* e );
+ void mouseMoveEvent( QMouseEvent* e );
+ void mouseReleaseEvent( QMouseEvent* e );
+ void mouseDoubleClickEvent( QMouseEvent* );
+ void keyPressEvent( QKeyEvent* e );
+ void updateHandles();
+ QRegion handleMask() const;
+ QPoint limitPointToRect( const QPoint &p, const QRect &r ) const;
+ void grabRect();
+
+ QRect selection;
+ bool mouseDown;
+ bool newSelection;
+ const int handleSize;
+ QRect* mouseOverHandle;
+ QPoint dragStartPoint;
+ QRect selectionBeforeDrag;
+ QTimer idleTimer;
+ bool showHelp;
+ bool grabbing;
+
+ // naming convention for handles
+ // T top, B bottom, R Right, L left
+ // 2 letters: a corner
+ // 1 letter: the handle on the middle of the corresponding side
+ QRect TLHandle, TRHandle, BLHandle, BRHandle;
+ QRect LHandle, THandle, RHandle, BHandle;
+
+ QVector<QRect*> handles;
+ QPixmap pixmap;
+};
+
+#endif
<string>Video4Linux (webcam)</string>
</property>
</item>
+ <item>
+ <property name="text" >
+ <string>Screen Grab</string>
+ </property>
+ </item>
</widget>
</item>
<item row="1" column="0" colspan="2" >
<rect>
<x>0</x>
<y>0</y>
- <width>482</width>
- <height>233</height>
+ <width>486</width>
+ <height>270</height>
</rect>
</property>
<attribute name="title" >
<rect>
<x>0</x>
<y>0</y>
- <width>482</width>
- <height>233</height>
+ <width>486</width>
+ <height>270</height>
</rect>
</property>
<attribute name="title" >
</widget>
</item>
</layout>
- <zorder>kcfg_video4vdevice</zorder>
- <zorder>label_7</zorder>
- <zorder>line</zorder>
- <zorder>label_3</zorder>
- <zorder>label_5</zorder>
- <zorder>kcfg_video4vformat</zorder>
- <zorder>kcfg_video4vencoding</zorder>
- <zorder>label_14</zorder>
- <zorder>kcfg_video4aencoding</zorder>
- <zorder>kcfg_video4adevice</zorder>
- <zorder>line_2</zorder>
- <zorder>label_9</zorder>
- <zorder>label_16</zorder>
- <zorder>label_15</zorder>
- <zorder>label_13</zorder>
- <zorder>line_3</zorder>
- <zorder>label_4</zorder>
- <zorder>label_6</zorder>
- <zorder>kcfg_video4size</zorder>
- <zorder>label_11</zorder>
- <zorder>kcfg_video4rate</zorder>
- <zorder>kcfg_video4capture</zorder>
- <zorder>kcfg_video4playback</zorder>
- <zorder>label_12</zorder>
- <zorder>kcfg_video4aformat</zorder>
+ </widget>
+ <widget class="QWidget" name="tab_3" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>486</width>
+ <height>270</height>
+ </rect>
+ </property>
+ <attribute name="title" >
+ <string>Screen Grab / FFmpeg</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_4" >
+ <item row="0" column="0" >
+ <widget class="QLabel" name="label_17" >
+ <property name="text" >
+ <string>Capture params</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="KLineEdit" name="kcfg_screengrabcapture" />
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label_8" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>Encoding parameters</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="KLineEdit" name="kcfg_screengrabencoding" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QLabel" name="label_10" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Maximum" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string>File extension</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="KLineEdit" name="kcfg_screengrabextension" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="MinimumExpanding" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2" >
+ <widget class="QCheckBox" name="kcfg_fullscreengrab" >
+ <property name="text" >
+ <string>Full screen capture</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <spacer name="verticalSpacer_3" >
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0" >
+ <size>
+ <width>383</width>
+ <height>160</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</widget>
</widget>
</item>
<string>Video4Linux</string>
</property>
</item>
+ <item>
+ <property name="text" >
+ <string>Screen grab</string>
+ </property>
+ </item>
</widget>
</item>
</layout>