Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slideshow #867

Merged
merged 8 commits into from May 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/commands/timelinecommands.cpp
Expand Up @@ -15,15 +15,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "dialogs/longuitask.h"
#include "timelinecommands.h"
#include "mltcontroller.h"
#include "shotcut_mlt_properties.h"
#include "settings.h"
#include <Logger.h>


#include <QMetaObject>

namespace Timeline {

Mlt::Producer* deserializeProducer(QString& xml)
{
return new Mlt::Producer(MLT.profile(), "xml-string", xml.toUtf8().constData());
}

AppendCommand::AppendCommand(MultitrackModel &model, int trackIndex, const QString &xml, QUndoCommand *parent)
: QUndoCommand(parent)
, m_model(model)
Expand All @@ -34,13 +42,27 @@ AppendCommand::AppendCommand(MultitrackModel &model, int trackIndex, const QStri
setText(QObject::tr("Append to track"));
}


void AppendCommand::redo()
{
LOG_DEBUG() << "trackIndex" << m_trackIndex;
LongUiTask longTask(QObject::tr("Append to Timeline"));
m_undoHelper.recordBeforeState();
Mlt::Producer producer(MLT.profile(), "xml-string", m_xml.toUtf8().constData());
m_model.appendClip(m_trackIndex, producer);
Mlt::Producer* producer = longTask.runAsync<Mlt::Producer*>(QObject::tr("Preparing"), deserializeProducer, m_xml);
if (producer->type() == playlist_type) {
Mlt::Playlist playlist(*producer);
int count = playlist.count();
for (int i = 0; i < count; i++) {
longTask.reportProgress(QObject::tr("Appending"), i, count);
QScopedPointer<Mlt::ClipInfo> info(playlist.clip_info(i));
Mlt::Producer clip = Mlt::Producer(info->producer);
clip.set_in_and_out(info->frame_in, info->frame_out);
m_model.appendClip(m_trackIndex, clip);
}
} else {
m_model.appendClip(m_trackIndex, *producer);
}
longTask.reportProgress(QObject::tr("Finishing"), 0, 0);
delete producer;
m_undoHelper.recordAfterState();
}

Expand Down
38 changes: 38 additions & 0 deletions src/dialogs/longuitask.cpp
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2020 Meltytech, LLC
*
* This program 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 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "longuitask.h"

#include "mainwindow.h"

LongUiTask::LongUiTask(QString title)
: QProgressDialog(title, QString(), 0, 0, &MAIN)
{
setWindowTitle(title);
setModal(true);
setWindowModality(Qt::ApplicationModal);
setMinimumDuration(2000);
setRange(0, 0);
}

void LongUiTask::reportProgress(QString text, int value, int max)
{
setLabelText(text);
setRange(0, max);
setValue(value);
QCoreApplication::processEvents();
}
50 changes: 50 additions & 0 deletions src/dialogs/longuitask.h
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 Meltytech, LLC
*
* This program 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 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef LONGUITASK_H
#define LONGUITASK_H

#include <QFuture>
#include <QProgressDialog>
#include <QtConcurrent/QtConcurrent>

class LongUiTask : public QProgressDialog
{
public:
explicit LongUiTask(QString title);

template <class Ret, class Func, class Arg>
Ret runAsync(QString text, Func&& f, Arg&& arg)
{
setLabelText(text);
setRange(0, 0);
QFuture<Ret> future = QtConcurrent::run(f, arg);
while(!future.isFinished())
{
setValue(0);
QCoreApplication::processEvents();
QThread::msleep(100);
}
return future.result();
}

void reportProgress(QString text, int value, int max);
private:

};

#endif // LONGUITASK_H
71 changes: 71 additions & 0 deletions src/dialogs/slideshowgeneratordialog.cpp
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2020 Meltytech, LLC
*
* This program 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 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "slideshowgeneratordialog.h"

#include "Logger.h"
#include "widgets/slideshowgeneratorwidget.h"

#include <MltProfile.h>
#include <MltTransition.h>

#include <QDebug>
#include <QDialogButtonBox>
#include <QVBoxLayout>

SlideshowGeneratorDialog::SlideshowGeneratorDialog(QWidget* parent, Mlt::Playlist& clips)
: QDialog(parent)
{
setWindowTitle(tr("Slideshow Generator - %1 Clips").arg(QString::number(clips.count())));

QVBoxLayout* VLayout = new QVBoxLayout(this);

m_sWidget = new SlideshowGeneratorWidget(&clips, this);
VLayout->addWidget(m_sWidget);

m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close);
VLayout->addWidget(m_buttonBox);
connect(m_buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(clicked(QAbstractButton*)));

setLayout(VLayout);
setModal(true);
layout()->setSizeConstraint(QLayout::SetFixedSize);
}

Mlt::Playlist* SlideshowGeneratorDialog::getSlideshow()
{
return m_sWidget->getSlideshow();
}

void SlideshowGeneratorDialog::clicked(QAbstractButton* button)
{
QDialogButtonBox::ButtonRole role = m_buttonBox->buttonRole(button);
if (role == QDialogButtonBox::AcceptRole)
{
LOG_DEBUG() << "Accept";
accept();
}
else if (role == QDialogButtonBox::RejectRole)
{
LOG_DEBUG() << "Reject";
reject();
}
else
{
LOG_DEBUG() << "Unknown role" << role;
}
}
45 changes: 45 additions & 0 deletions src/dialogs/slideshowgeneratordialog.h
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 Meltytech, LLC
*
* This program 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 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef SLIDESHOWGENERATORDIALOG_H
#define SLIDESHOWGENERATORDIALOG_H

#include <MltPlaylist.h>

#include <QDialog>

class SlideshowGeneratorWidget;
class QAbstractButton;
class QDialogButtonBox;

class SlideshowGeneratorDialog : public QDialog
{
Q_OBJECT

public:
explicit SlideshowGeneratorDialog(QWidget *parent, Mlt::Playlist& clips);
Mlt::Playlist* getSlideshow();

private slots:
void clicked(QAbstractButton* button);

private:
SlideshowGeneratorWidget* m_sWidget;
QDialogButtonBox* m_buttonBox;
};

#endif // SLIDESHOWGENERATORDIALOG_H
34 changes: 34 additions & 0 deletions src/docks/playlistdock.cpp
Expand Up @@ -19,6 +19,8 @@
#include "ui_playlistdock.h"
#include "dialogs/durationdialog.h"
#include "dialogs/filedatedialog.h"
#include "dialogs/longuitask.h"
#include "dialogs/slideshowgeneratordialog.h"
#include "mainwindow.h"
#include "settings.h"
#include "shotcut_mlt_properties.h"
Expand Down Expand Up @@ -300,6 +302,7 @@ void PlaylistDock::on_menuButton_clicked()
menu.addAction(ui->actionSelectAll);
menu.addAction(ui->actionSelectNone);
menu.addAction(ui->actionAddToTimeline);
menu.addAction(ui->actionAddToSlideshow);
menu.addSeparator();

QMenu* sortByMenu = menu.addMenu(tr("Sort"));
Expand Down Expand Up @@ -800,6 +803,37 @@ void PlaylistDock::on_actionAddToTimeline_triggered()
emit addAllTimeline(&playlist);
}

void PlaylistDock::on_actionAddToSlideshow_triggered()
{
const QModelIndexList& indexes = m_view->selectionModel()->selectedIndexes();
Mlt::Playlist playlist(MLT.profile());
foreach (auto index, indexes) {
if (index.column()) continue;
QScopedPointer<Mlt::ClipInfo> info(m_model.playlist()->clip_info(index.row()));
if (info && info->producer) {
playlist.append(*info->producer, info->frame_in, info->frame_out);
}
}
if (playlist.count() <= 0 )
{
return;
}

SlideshowGeneratorDialog dialog(this, playlist);
if (dialog.exec() == QDialog::Accepted ) {
LongUiTask longTask(QObject::tr("Generate Slideshow"));
Mlt::Playlist* slideshow = longTask.runAsync<Mlt::Playlist*>(tr("Generating"), &dialog, &SlideshowGeneratorDialog::getSlideshow);
if (slideshow)
{
if ( slideshow->count() > 0 )
{
emit addAllTimeline(slideshow);
}
delete slideshow;
}
}
}

void PlaylistDock::on_updateButton_clicked()
{
int index = MLT.producer()->get_int(kPlaylistIndexProperty);
Expand Down
2 changes: 2 additions & 0 deletions src/docks/playlistdock.h
Expand Up @@ -118,6 +118,8 @@ private slots:

void on_actionAddToTimeline_triggered();

void on_actionAddToSlideshow_triggered();

void on_updateButton_clicked();

void updateViewModeFromActions();
Expand Down
5 changes: 5 additions & 0 deletions src/docks/playlistdock.ui
Expand Up @@ -398,6 +398,11 @@ p, li { white-space: pre-wrap; }
<string>Add Selected to Timeline</string>
</property>
</action>
<action name="actionAddToSlideshow">
<property name="text">
<string>Add Selected to Slideshow</string>
</property>
</action>
<action name="actionSortByName">
<property name="text">
<string>Sort By Name</string>
Expand Down
3 changes: 2 additions & 1 deletion src/docks/timelinedock.cpp
Expand Up @@ -1187,7 +1187,8 @@ void TimelineDock::appendFromPlaylist(Mlt::Playlist *playlist)
pulseLockButtonOnTrack(trackIndex);
return;
}
m_model.appendFromPlaylist(playlist, trackIndex);
MAIN.undoStack()->push(
new Timeline::AppendCommand(m_model, trackIndex, MLT.XML(playlist)));
selectClipUnderPlayhead();
}

Expand Down