//virtual
void MyLabel::wheelEvent(QWheelEvent * event)
{
- if(event->delta() > 0) emit seek(true);
+ if (event->delta() > 0) emit seek(true);
else emit seek(false);
}
+//virtual
+void MyLabel::mousePressEvent(QMouseEvent *)
+{
+ emit switchToLive();
+}
+
//virtual
void MyLabel::paintEvent(QPaintEvent * event)
{
int pictureHeight = height();
int pictureWidth = width();
int calculatedWidth = aspect_ratio * height();
- if(calculatedWidth > width()) pictureHeight = width() / aspect_ratio;
+ if (calculatedWidth > width()) pictureHeight = width() / aspect_ratio;
else {
int calculatedHeight = width() / aspect_ratio;
- if(calculatedHeight > height()) pictureWidth = height() * aspect_ratio;
+ if (calculatedHeight > height()) pictureWidth = height() * aspect_ratio;
}
p.drawImage(QRect((width() - pictureWidth) / 2, (height() - pictureHeight) / 2, pictureWidth, pictureHeight), m_img, QRect(0, 0, m_img.width(), m_img.height()));
p.end();
}
-StopmotionWidget::StopmotionWidget(KUrl projectFolder, QWidget *parent) :
+StopmotionWidget::StopmotionWidget(KUrl projectFolder, const QList< QAction * > actions, QWidget *parent) :
QDialog(parent)
, Ui::Stopmotion_UI()
, m_projectFolder(projectFolder)
, m_sequenceFrame(0)
, m_animatedIndex(-1)
{
+ //setAttribute(Qt::WA_DeleteOnClose);
+ addActions(actions);
setupUi(this);
setWindowTitle(i18n("Stop Motion Capture"));
setFont(KGlobalSettings::toolBarFont());
live_button->setIcon(KIcon("camera-photo"));
- m_captureAction = new QAction(KIcon("media-record"), i18n("Capture frame"), this);
- m_captureAction->setShortcut(QKeySequence(Qt::Key_Space));
+
+ m_captureAction = actions.at(0);
connect(m_captureAction, SIGNAL(triggered()), this, SLOT(slotCaptureFrame()));
capture_button->setDefaultAction(m_captureAction);
+ connect(actions.at(1), SIGNAL(triggered()), this, SLOT(slotSwitchLive()));
+
preview_button->setIcon(KIcon("media-playback-start"));
capture_button->setEnabled(false);
// Build config menu
QMenu *confMenu = new QMenu;
- m_showOverlay = new QAction(KIcon("edit-paste"), i18n("Show last frame over video"), this);
- m_showOverlay->setCheckable(true);
- m_showOverlay->setChecked(false);
+ m_showOverlay = actions.at(2);
connect(m_showOverlay, SIGNAL(triggered(bool)), this, SLOT(slotShowOverlay(bool)));
confMenu->addAction(m_showOverlay);
effectsMenu->addAction(invertEffect);
effectsMenu->addAction(thresEffect);
QList <QAction *> list = effectsMenu->actions();
- for(int i = 0; i < list.count(); i++) {
+ for (int i = 0; i < list.count(); i++) {
list.at(i)->setCheckable(true);
- if(list.at(i)->data().toInt() == m_effectIndex) {
+ if (list.at(i)->data().toInt() == m_effectIndex) {
list.at(i)->setChecked(true);
}
}
connect(showThumbs, SIGNAL(triggered(bool)), this, SLOT(slotShowThumbs(bool)));
QAction *removeCurrent = new QAction(KIcon("edit-delete"), i18n("Delete current frame"), this);
- //TODO: implement frame deletion
- //connect(removeCurrent, SIGNAL(triggered()), this, SLOT(slotRemoveFrame()));
+ removeCurrent->setShortcut(Qt::Key_Delete);
+ connect(removeCurrent, SIGNAL(triggered()), this, SLOT(slotRemoveFrame()));
QAction *capInterval = new QAction(KIcon(), i18n("Set capture interval"), this);
connect(capInterval, SIGNAL(triggered()), this, SLOT(slotSetCaptureInterval()));
capture_button->setMenu(capMenu);
connect(sequence_name, SIGNAL(textChanged(const QString &)), this, SLOT(sequenceNameChanged(const QString &)));
+ connect(sequence_name, SIGNAL(currentIndexChanged(int)), live_button, SLOT(setFocus()));
+
m_layout = new QVBoxLayout;
- if(BMInterface::getBlackMagicDeviceList(capture_device, NULL)) {
+ if (BMInterface::getBlackMagicDeviceList(capture_device, NULL)) {
// Found a BlackMagic device
m_bmCapture = new BmdCaptureHandler(m_layout);
connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
}
- if(QFile::exists(KdenliveSettings::video4vdevice())) {
- if(m_bmCapture == NULL) m_bmCapture = new V4lCaptureHandler(m_layout);
- capture_device->addItem(KdenliveSettings::video4vdevice(), "v4l");
+ if (QFile::exists(KdenliveSettings::video4vdevice())) {
+#ifndef Q_WS_MAC
+ V4lCaptureHandler v4l(NULL);
+ // Video 4 Linux device detection
+ for (int i = 0; i < 10; i++) {
+ QString path = "/dev/video" + QString::number(i);
+ if (QFile::exists(path)) {
+ QStringList deviceInfo = v4l.getDeviceName(path);
+ if (!deviceInfo.isEmpty()) {
+ capture_device->addItem(deviceInfo.at(0), "v4l");
+ capture_device->setItemData(capture_device->count() - 1, path, Qt::UserRole + 1);
+ capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(1), Qt::UserRole + 2);
+ if (path == KdenliveSettings::video4vdevice()) capture_device->setCurrentIndex(capture_device->count() - 1);
+ }
+ }
+ }
+
+ /*V4lCaptureHandler v4lhandler(NULL);
+ QStringList deviceInfo = v4lhandler.getDeviceName(KdenliveSettings::video4vdevice());
+ capture_device->addItem(deviceInfo.at(0), "v4l");
+ capture_device->setItemData(capture_device->count() - 1, deviceInfo.at(3), Qt::UserRole + 1);*/
+ if (m_bmCapture == NULL) {
+ m_bmCapture = new V4lCaptureHandler(m_layout);
+ m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
+ }
+#endif
}
- connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
connect(capture_device, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateHandler()));
+ if (m_bmCapture) {
+ connect(m_bmCapture, SIGNAL(frameSaved(const QString)), this, SLOT(slotNewThumb(const QString)));
+ } else live_button->setEnabled(false);
m_frame_preview = new MyLabel(this);
connect(m_frame_preview, SIGNAL(seek(bool)), this, SLOT(slotSeekFrame(bool)));
+ connect(m_frame_preview, SIGNAL(switchToLive()), this, SLOT(slotSwitchLive()));
m_layout->addWidget(m_frame_preview);
m_frame_preview->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
video_preview->setLayout(m_layout);
button_addsequence->setEnabled(false);
connect(live_button, SIGNAL(clicked(bool)), this, SLOT(slotLive(bool)));
connect(button_addsequence, SIGNAL(clicked(bool)), this, SLOT(slotAddSequence()));
- connect(preview_button, SIGNAL(clicked(bool)), this, SLOT(slotPlayPreview()));
+ connect(preview_button, SIGNAL(clicked(bool)), this, SLOT(slotPlayPreview(bool)));
connect(frame_list, SIGNAL(currentRowChanged(int)), this, SLOT(slotShowSelectedFrame()));
+ connect(frame_list, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(slotShowSelectedFrame()));
connect(this, SIGNAL(doCreateThumbs(QImage, int)), this, SLOT(slotCreateThumbs(QImage, int)));
+ frame_list->addAction(removeCurrent);
+ frame_list->setContextMenuPolicy(Qt::ActionsContextMenu);
frame_list->setHidden(!KdenliveSettings::showstopmotionthumbs());
parseExistingSequences();
}
StopmotionWidget::~StopmotionWidget()
{
- m_bmCapture->stopPreview();
+ if (m_bmCapture)
+ m_bmCapture->stopPreview();
}
void StopmotionWidget::slotUpdateOverlayEffect(QAction *act)
{
#ifdef QIMAGEBLITZ
- if(act) m_effectIndex = act->data().toInt();
+ if (act) m_effectIndex = act->data().toInt();
KdenliveSettings::setBlitzeffect(m_effectIndex);
- if(m_showOverlay->isChecked()) slotUpdateOverlay();
+ if (m_showOverlay->isChecked()) slotUpdateOverlay();
#endif
}
void StopmotionWidget::closeEvent(QCloseEvent *e)
{
slotLive(false);
- live_button->setChecked(false);
QDialog::closeEvent(e);
}
void StopmotionWidget::slotSetCaptureInterval()
{
int interval = QInputDialog::getInteger(this, i18n("Set Capture Interval"), i18n("Interval (in seconds)"), KdenliveSettings::captureinterval(), 1);
- if(interval > 0 && interval != KdenliveSettings::captureinterval())
+ if (interval > 0 && interval != KdenliveSettings::captureinterval())
KdenliveSettings::setCaptureinterval(interval);
}
void StopmotionWidget::slotShowThumbs(bool show)
{
KdenliveSettings::setShowstopmotionthumbs(show);
- kDebug() << "SHOW THUMBS: " << show;
- if(show) {
+ if (show) {
frame_list->clear();
sequenceNameChanged(sequence_name->currentText());
} else {
void StopmotionWidget::slotIntervalCapture(bool capture)
{
- if(capture) slotCaptureFrame();
+ if (capture) slotCaptureFrame();
}
void StopmotionWidget::slotUpdateHandler()
{
QString data = capture_device->itemData(capture_device->currentIndex()).toString();
- m_bmCapture->stopPreview();
- delete m_bmCapture;
+ slotLive(false);
+ if (m_bmCapture) {
+ delete m_bmCapture;
+ }
m_layout->removeWidget(m_frame_preview);
- if(data == "v4l") {
+ if (data == "v4l") {
+#ifndef Q_WS_MAC
m_bmCapture = new V4lCaptureHandler(m_layout);
+ m_bmCapture->setDevice(capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 1).toString(), capture_device->itemData(capture_device->currentIndex(), Qt::UserRole + 2).toString());
+#endif
} else {
m_bmCapture = new BmdCaptureHandler(m_layout);
- connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
+ if (m_bmCapture) connect(m_bmCapture, SIGNAL(gotMessage(const QString &)), this, SLOT(slotGotHDMIMessage(const QString &)));
}
+ live_button->setEnabled(m_bmCapture != NULL);
m_layout->addWidget(m_frame_preview);
}
}
}
+void StopmotionWidget::slotSwitchLive()
+{
+ setUpdatesEnabled(false);
+ if (m_frame_preview->isHidden()) {
+ if (m_bmCapture) m_bmCapture->hidePreview(true);
+ m_frame_preview->setHidden(false);
+ } else {
+ m_frame_preview->setHidden(true);
+ if (m_bmCapture) m_bmCapture->hidePreview(false);
+ capture_button->setEnabled(true);
+ }
+ setUpdatesEnabled(true);
+}
+
void StopmotionWidget::slotLive(bool isOn)
{
- if(isOn) {
- m_frame_preview->setImage(QImage());
+ if (isOn && m_bmCapture) {
+ //m_frame_preview->setImage(QImage());
m_frame_preview->setHidden(true);
- m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode());
+ m_bmCapture->startPreview(KdenliveSettings::hdmi_capturedevice(), KdenliveSettings::hdmi_capturemode(), false);
capture_button->setEnabled(true);
} else {
- m_bmCapture->stopPreview();
+ if (m_bmCapture) m_bmCapture->stopPreview();
+ m_frame_preview->setHidden(false);
capture_button->setEnabled(false);
+ live_button->setChecked(false);
}
}
void StopmotionWidget::slotShowOverlay(bool isOn)
{
- if(isOn) {
- if(live_button->isChecked() && m_sequenceFrame > 0) {
+ if (isOn) {
+ if (live_button->isChecked() && m_sequenceFrame > 0) {
slotUpdateOverlay();
}
- } else {
+ } else if (m_bmCapture) {
m_bmCapture->hideOverlay();
}
}
void StopmotionWidget::slotUpdateOverlay()
{
+ if (m_bmCapture == NULL) return;
QString path = getPathForFrame(m_sequenceFrame - 1);
- if(!QFile::exists(path)) return;
+ if (!QFile::exists(path)) return;
QImage img(path);
- if(img.isNull()) {
+ if (img.isNull()) {
QTimer::singleShot(1000, this, SLOT(slotUpdateOverlay()));
return;
}
#ifdef QIMAGEBLITZ
//img = Blitz::convolveEdge(img, 0, Blitz::Low);
- switch(m_effectIndex) {
+ switch (m_effectIndex) {
case 2:
- img = Blitz::contrast(img, true);
+ img = Blitz::contrast(img, true, 6);
break;
case 3:
img = Blitz::edge(img);
Blitz::invert(img);
break;
case 6:
- img = Blitz::threshold(img, 200, Blitz::Grayscale, qRgba(255, 0, 0, 255), qRgba(0, 0, 0, 0));
+ img = Blitz::threshold(img, 120, Blitz::Grayscale, qRgba(0, 0, 0, 0), qRgba(255, 0, 0, 255));
+ //img = Blitz::flatten(img, QColor(255, 0, 0, 255), QColor(0, 0, 0, 0));
break;
default:
break;
m_filesList.clear();
m_future.waitForFinished();
frame_list->clear();
- if(name.isEmpty()) {
+ if (name.isEmpty()) {
button_addsequence->setEnabled(false);
} else {
// Check if we are editing an existing sequence
QString pattern = SlideshowClip::selectedPath(getPathForFrame(0, sequence_name->currentText()), false, QString(), &m_filesList);
m_sequenceFrame = m_filesList.isEmpty() ? 0 : SlideshowClip::getFrameNumberFromPath(m_filesList.last()) + 1;
- if(!m_filesList.isEmpty()) {
+ if (!m_filesList.isEmpty()) {
m_sequenceName = sequence_name->currentText();
connect(this, SIGNAL(doCreateThumbs(QImage, int)), this, SLOT(slotCreateThumbs(QImage, int)));
m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
void StopmotionWidget::slotCaptureFrame()
{
- if(sequence_name->currentText().isEmpty()) {
+ if (m_bmCapture == NULL) return;
+ if (sequence_name->currentText().isEmpty()) {
QString seqName = QInputDialog::getText(this, i18n("Create New Sequence"), i18n("Enter sequence name"));
- if(seqName.isEmpty()) return;
+ if (seqName.isEmpty()) return;
sequence_name->blockSignals(true);
sequence_name->setItemText(sequence_name->currentIndex(), seqName);
sequence_name->blockSignals(false);
}
- if(m_sequenceName != sequence_name->currentText()) {
+ if (m_sequenceName != sequence_name->currentText()) {
m_sequenceName = sequence_name->currentText();
m_sequenceFrame = 0;
}
//capture_button->setEnabled(false);
QString currentPath = getPathForFrame(m_sequenceFrame);
- kDebug() << "Capture FRame NB: " << m_sequenceFrame;
m_bmCapture->captureFrame(currentPath);
KNotification::event("FrameCaptured");
m_sequenceFrame++;
button_addsequence->setEnabled(true);
- if(m_intervalCapture->isChecked()) QTimer::singleShot(KdenliveSettings::captureinterval() * 1000, this, SLOT(slotCaptureFrame()));
+ if (m_intervalCapture->isChecked()) QTimer::singleShot(KdenliveSettings::captureinterval() * 1000, this, SLOT(slotCaptureFrame()));
}
void StopmotionWidget::slotNewThumb(const QString path)
{
- if(!KdenliveSettings::showstopmotionthumbs()) return;
+ if (!KdenliveSettings::showstopmotionthumbs()) return;
m_filesList.append(path);
- if(m_showOverlay->isChecked()) slotUpdateOverlay();
- if(!m_future.isRunning()) m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
+ if (m_showOverlay->isChecked()) slotUpdateOverlay();
+ if (!m_future.isRunning()) m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
}
void StopmotionWidget::slotPrepareThumbs()
{
- if(m_filesList.isEmpty()) return;
+ if (m_filesList.isEmpty()) return;
QString path = m_filesList.takeFirst();
emit doCreateThumbs(QImage(path), SlideshowClip::getFrameNumberFromPath(path));
void StopmotionWidget::slotCreateThumbs(QImage img, int ix)
{
- if(img.isNull()) {
+ if (img.isNull()) {
m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
return;
}
QListWidgetItem *item = new QListWidgetItem(icon, QString(), frame_list);
item->setToolTip(getPathForFrame(ix, sequence_name->currentText()));
item->setData(Qt::UserRole, ix);
+ frame_list->blockSignals(true);
+ frame_list->setCurrentItem(item);
+ frame_list->blockSignals(false);
m_future = QtConcurrent::run(this, &StopmotionWidget::slotPrepareThumbs);
}
QString StopmotionWidget::getPathForFrame(int ix, QString seqName)
{
- if(seqName.isEmpty()) seqName = m_sequenceName;
+ if (seqName.isEmpty()) seqName = m_sequenceName;
return m_projectFolder.path(KUrl::AddTrailingSlash) + seqName + "_" + QString::number(ix).rightJustified(4, '0', false) + ".png";
}
-void StopmotionWidget::slotShowFrame(int ix)
+void StopmotionWidget::slotShowFrame(const QString &path)
{
- if(m_sequenceFrame == 0) {
- //there are no images in sequence
- return;
- }
- if(ix < m_sequenceFrame) {
- // Show previous frame
- slotLive(false);
- live_button->setChecked(false);
- QImage img(getPathForFrame(ix));
- capture_button->setEnabled(false);
- if(!img.isNull()) {
- //m_bmCapture->showOverlay(img, false);
- m_bmCapture->hidePreview(true);
- m_frame_preview->setImage(img);
- m_frame_preview->setHidden(false);
- m_frame_preview->update();
- selectFrame(ix);
- }
+ //slotLive(false);
+ QImage img(path);
+ capture_button->setEnabled(false);
+ if (!img.isNull()) {
+ if (m_bmCapture) m_bmCapture->hidePreview(true);
+ m_frame_preview->setImage(img);
+ m_frame_preview->setHidden(false);
+ m_frame_preview->update();
}
- /*else {
- slotLive(true);
- m_frame_preview->setImage(QImage());
- m_frame_preview->setHidden(true);
- m_bmCapture->hideOverlay();
- m_bmCapture->hidePreview(false);
- capture_button->setEnabled(true);
- }*/
}
void StopmotionWidget::slotShowSelectedFrame()
{
QListWidgetItem *item = frame_list->currentItem();
- if(item) {
- int ix = item->data(Qt::UserRole).toInt();;
- //slotShowFrame(ix);
+ if (item) {
+ //int ix = item->data(Qt::UserRole).toInt();;
+ slotShowFrame(item->toolTip());
}
}
emit addOrUpdateSequence(getPathForFrame(0));
}
-void StopmotionWidget::slotPlayPreview()
+void StopmotionWidget::slotPlayPreview(bool animate)
{
- if(m_animatedIndex != -1) {
+ if (!animate) {
// stop animation
- m_animatedIndex = -1;
+ m_animationList.clear();
return;
}
- QListWidgetItem *item = frame_list->currentItem();
- if(item) {
- m_animatedIndex = item->data(Qt::UserRole).toInt();
+ if (KdenliveSettings::showstopmotionthumbs()) {
+ frame_list->setCurrentRow(0);
+ QTimer::singleShot(200, this, SLOT(slotAnimate()));
+ } else {
+ SlideshowClip::selectedPath(getPathForFrame(0, sequence_name->currentText()), false, QString(), &m_animationList);
+ slotAnimate();
}
- QTimer::singleShot(200, this, SLOT(slotAnimate()));
}
void StopmotionWidget::slotAnimate()
{
- slotShowFrame(m_animatedIndex);
- m_animatedIndex++;
- if(m_animatedIndex < m_sequenceFrame) QTimer::singleShot(200, this, SLOT(slotAnimate()));
- else m_animatedIndex = -1;
+ //slotShowFrame(m_animatedIndex);
+ if (KdenliveSettings::showstopmotionthumbs()) {
+ //TODO: loop
+ if (frame_list->currentRow() < (frame_list->count() - 1)) {
+ frame_list->setCurrentRow(frame_list->currentRow() + 1);
+ QTimer::singleShot(100, this, SLOT(slotAnimate()));
+ } else preview_button->setChecked(false);
+ } else if (!m_animationList.isEmpty()) {
+ slotShowFrame(m_animationList.takeFirst());
+ QTimer::singleShot(100, this, SLOT(slotAnimate()));
+ } else preview_button->setChecked(false);
+
}
QListWidgetItem *StopmotionWidget::getFrameFromIndex(int ix)
{
QListWidgetItem *item = NULL;
int pos = ix;
- if(ix >= frame_list->count()) {
+ if (ix >= frame_list->count()) {
pos = frame_list->count() - 1;
}
- if(ix < 0) pos = 0;
+ if (ix < 0) pos = 0;
item = frame_list->item(pos);
int value = item->data(Qt::UserRole).toInt();
- if(value == ix) return item;
- else if(value < ix) {
+ if (value == ix) return item;
+ else if (value < ix) {
pos++;
- while(pos < frame_list->count()) {
+ while (pos < frame_list->count()) {
item = frame_list->item(pos);
value = item->data(Qt::UserRole).toInt();
- if(value == ix) return item;
+ if (value == ix) return item;
pos++;
}
} else {
pos --;
- while(pos >= 0) {
+ while (pos >= 0) {
item = frame_list->item(pos);
value = item->data(Qt::UserRole).toInt();
- if(value == ix) return item;
+ if (value == ix) return item;
pos --;
}
}
{
frame_list->blockSignals(true);
QListWidgetItem *item = getFrameFromIndex(ix);
- if(!item) return;
+ if (!item) return;
frame_list->setCurrentItem(item);
frame_list->blockSignals(false);
}
void StopmotionWidget::slotSeekFrame(bool forward)
{
int ix = frame_list->currentRow();
- if(forward) {
- if(ix < frame_list->count() - 1) frame_list->setCurrentRow(ix + 1);
- } else if(ix > 0) frame_list->setCurrentRow(ix - 1);
+ if (forward) {
+ if (ix < frame_list->count() - 1) frame_list->setCurrentRow(ix + 1);
+ } else if (ix > 0) frame_list->setCurrentRow(ix - 1);
}
-
+void StopmotionWidget::slotRemoveFrame()
+{
+ if (frame_list->currentItem() == NULL) return;
+ QString path = frame_list->currentItem()->toolTip();
+ if (KMessageBox::questionYesNo(this, i18n("Delete frame %1 from disk?", path), i18n("Delete Frame")) != KMessageBox::Yes) return;
+ QFile f(path);
+ if (f.remove()) {
+ QListWidgetItem *item = frame_list->takeItem(frame_list->currentRow());
+ delete item;
+ }
+}