Skip to content

Commit

Permalink
Initial proof-of-concept for QML filter view and favorite filters
Browse files Browse the repository at this point in the history
  • Loading branch information
bmatherly committed Oct 25, 2014
1 parent c81880a commit f7fad66
Show file tree
Hide file tree
Showing 42 changed files with 996 additions and 498 deletions.
Binary file added icons/dark/32x32/bookmarks.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/light/32x32/bookmarks.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/oxygen/32x32/places/bookmarks.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions icons/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -181,5 +181,8 @@
<file>light/16x16/scrub_drag.png</file>
<file>oxygen/16x16/actions/target.png</file>
<file>oxygen/16x16/actions/scrub_drag.png</file>
<file>light/32x32/bookmarks.png</file>
<file>dark/32x32/bookmarks.png</file>
<file>oxygen/32x32/places/bookmarks.png</file>
</qresource>
</RCC>
198 changes: 198 additions & 0 deletions src/controllers/filtercontroller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Copyright (c) 2014 Meltytech, LLC
* Author: Brian Matherly <code@brianmatherly.com>
*
* 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 "filtercontroller.h"
#include <QQmlEngine>
#include <QDir>
#include <QDebug>
#include <QQmlComponent>
#include <QtConcurrent/QtConcurrentRun>
#include "mltcontroller.h"
#include "settings.h"
#include "qmltypes/qmlmetadata.h"
#include "qmltypes/qmlutilities.h"
#include "qmltypes/qmlfilter.h"

FilterController::FilterController(QObject* parent) : QObject(parent),
m_metadataModel(this),
m_attachedModel(this),
m_currentFilterIndex(-1)
{
// Process filters in a separate thread and add them to the model asynchronously.
connect(this, SIGNAL(newMetadataFound(QmlMetadata*)), this, SLOT(addMetadata(QmlMetadata*)), Qt::QueuedConnection);
m_future = QtConcurrent::run(this, &FilterController::loadFilterMetadata);

connect(&m_attachedModel, SIGNAL(changed()), this, SLOT(handleAttachedModelChange()));
}

void FilterController::loadFilterMetadata() {
QQmlEngine engine;
QDir dir = QmlUtilities::qmlDir();
dir.cd("filters");
foreach (QString dirName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Executable)) {
QDir subdir = dir;
subdir.cd(dirName);
subdir.setFilter(QDir::Files | QDir::NoDotAndDotDot | QDir::Readable);
subdir.setNameFilters(QStringList("meta*.qml"));
foreach (QString fileName, subdir.entryList()) {
qDebug() << "reading filter metadata" << dirName << fileName;
QQmlComponent component(&engine, subdir.absoluteFilePath(fileName));
QmlMetadata *meta = qobject_cast<QmlMetadata*>(component.create());
if (meta && (meta->isAudio() || (meta->needsGPU() == Settings.playerGPU()))) {
// Check if mlt_service is available.
if (MLT.repository()->filters()->get_data(meta->mlt_service().toLatin1().constData())) {
qDebug() << "added filter" << meta->name();
meta->loadSettings();
meta->setPath(subdir);
meta->setParent(0);
meta->moveToThread(this->thread());
emit newMetadataFound(meta);
}
} else if (!meta) {
qWarning() << component.errorString();
}
}
};
}

QmlMetadata *FilterController::metadataForService(Mlt::Service *service)
{
m_future.waitForFinished();
QmlMetadata* meta = NULL;
int rowCount = m_metadataModel.rowCount();
QString uniqueId = service->get("shotcut:filter");

// Fallback to mlt_service for legacy filters
if (uniqueId.isEmpty()) {
uniqueId = service->get("mlt_service");
}

for (int i = 0; i < rowCount; i++) {
QmlMetadata* tmpMeta = m_metadataModel.get(i);
if (tmpMeta->uniqueId() == uniqueId) {
meta = tmpMeta;
break;
}
}

return meta;
}

MetadataModel* FilterController::metadataModel()
{
return &m_metadataModel;
}

AttachedFiltersModel* FilterController::attachedModel()
{
return &m_attachedModel;
}

void FilterController::setProducer(Mlt::Producer *producer)
{
m_currentFilter.reset(NULL);
m_attachedModel.reset(producer);
}

void FilterController::attachFilter(int metadataIndex)
{
QmlMetadata* meta = m_metadataModel.get(metadataIndex);
QmlFilter* filter = NULL;
if (meta) {
filter = new QmlFilter(m_attachedModel, *meta, -1);
m_currentFilterIndex = m_attachedModel.rowCount() - 1;
} else {
m_currentFilterIndex = -1;
}
emit currentFilterChanged(filter, meta);
m_currentFilter.reset(filter);
}

void FilterController::removeFilter(int attachedIndex)
{
QModelIndex index = m_attachedModel.index(attachedIndex);
if (index.isValid()) {
m_attachedModel.remove(index.row());
}
}

void FilterController::setCurrentFilter(int attachedIndex)
{
if( attachedIndex == m_currentFilterIndex ) {
return;
}

Mlt::Filter* mltFilter = m_attachedModel.filterForRow(attachedIndex);
QmlMetadata* meta = NULL;
QmlFilter* filter = NULL;

if (mltFilter && mltFilter->is_valid()) {
meta = metadataForService(mltFilter);
if (meta) {
filter = new QmlFilter(m_attachedModel, *meta, attachedIndex);
}
}

if (meta) {
m_currentFilterIndex = attachedIndex;
} else {
m_currentFilterIndex = -1;
}

emit currentFilterChanged(filter, meta);
m_currentFilter.reset(filter);
delete mltFilter;
}

void FilterController::setFadeInDuration(int duration)
{
/* TODO: implement this
if (m_quickObject && ui->listView->currentIndex().isValid()) {
Mlt::Filter* filter = m_model.filterForRow(ui->listView->currentIndex().row());
if (filter && filter->is_valid()
&& QString(filter->get("shotcut:filter")).startsWith("fadeIn")) {
m_quickObject->setProperty("duration", duration);
}
delete filter;
}
*/
}

void FilterController::setFadeOutDuration(int duration)
{
/* TODO: implement this
if (m_quickObject && ui->listView->currentIndex().isValid()) {
Mlt::Filter* filter = m_model.filterForRow(ui->listView->currentIndex().row());
if (filter && filter->is_valid()
&& QString(filter->get("shotcut:filter")).startsWith("fadeOut")) {
m_quickObject->setProperty("duration", duration);
}
delete filter;
}
*/
}

void FilterController::handleAttachedModelChange()
{
MLT.refreshConsumer();
}

void FilterController::addMetadata(QmlMetadata* meta)
{
m_metadataModel.add(meta);
}

67 changes: 67 additions & 0 deletions src/controllers/filtercontroller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2014 Meltytech, LLC
* Author: Brian Matherly <code@brianmatherly.com>
*
* 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 FILTERCONTROLLER_H
#define FILTERCONTROLLER_H

#include <QObject>
#include <QScopedPointer>
#include <QFuture>
#include "models/metadatamodel.h"
#include "models/attachedfiltersmodel.h"
#include "qmltypes/qmlmetadata.h"
#include "qmltypes/qmlfilter.h"

class FilterController : public QObject
{
Q_OBJECT

public:
explicit FilterController(QObject* parent = 0);
MetadataModel* metadataModel();
AttachedFiltersModel* attachedModel();

QmlMetadata* metadataForService(Mlt::Service *service);

signals:
void currentFilterChanged(QmlFilter* filter, QmlMetadata* meta);
void newMetadataFound(QmlMetadata* meta);

public slots:
void setProducer(Mlt::Producer *producer = 0);
void attachFilter(int metadataIndex);
void removeFilter(int attachedIndex);
void setCurrentFilter(int attachedIndex);
void setFadeInDuration(int duration);
void setFadeOutDuration(int duration);

private slots:
void handleAttachedModelChange();
void addMetadata(QmlMetadata*);

private:
void loadFilterMetadata();

QFuture<void> m_future;
QScopedPointer<QmlFilter> m_currentFilter;
MetadataModel m_metadataModel;
AttachedFiltersModel m_attachedModel;
int m_currentFilterIndex;
};

#endif // FILTERCONTROLLER_H

0 comments on commit f7fad66

Please sign in to comment.