Commit 66ab7390 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Refactoring step 1 part 2:

New Bin widget handling project clips.
Added JobManager to handle clip jobs
Cleanup loading of clips in a project
Start deprecating DocClipBase, currently causing many crashes in timeline
Many features (thumbnails, clip jobs, speed effect, markers, ... )are
broken but should be fixable without too much trouble.
parent 79269e39
......@@ -75,6 +75,7 @@ add_subdirectory(titler)
add_subdirectory(utils)
add_subdirectory(onmonitoritems/rotoscoping)
add_subdirectory(mltcontroller)
add_subdirectory(bin)
list(APPEND kdenlive_SRCS
colortools.cpp
......
set(kdenlive_SRCS
${kdenlive_SRCS}
bin/bin.cpp
bin/projectitemmodel.cpp
bin/abstractprojectitem.cpp
bin/projectclip.cpp
bin/projectfolder.cpp
bin/projectsortproxymodel.cpp
PARENT_SCOPE
)
\ No newline at end of file
/*
Copyright (C) 2012 Till Theato <root@ttill.de>
Copyright (C) 2014 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
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 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 "abstractprojectitem.h"
#include "bin.h"
#include <QDomElement>
#include <QVariant>
#include <QPainter>
#include <QDebug>
AbstractProjectItem::AbstractProjectItem(const QString &id, AbstractProjectItem* parent) :
QObject()
, m_parent(NULL)
, m_id(id)
, m_isCurrent(false)
, m_jobProgress(0)
, m_jobType(AbstractClipJob::NOJOBTYPE)
{
setParent(parent);
}
AbstractProjectItem::AbstractProjectItem(const QDomElement& description, AbstractProjectItem* parent) :
QObject()
, m_parent(NULL)
, m_id(description.attribute("id"))
, m_isCurrent(false)
, m_jobProgress(0)
, m_jobType(AbstractClipJob::NOJOBTYPE)
{
setParent(parent);
}
AbstractProjectItem::~AbstractProjectItem()
{
}
bool AbstractProjectItem::operator==(const AbstractProjectItem* projectItem) const
{
// FIXME: only works for folders
bool equal = static_cast<const QList* const>(this) == static_cast<const QList* const>(projectItem);
equal &= m_parent == projectItem->parent();
return equal;
}
AbstractProjectItem* AbstractProjectItem::parent() const
{
return m_parent;
}
const QString &AbstractProjectItem::clipId() const
{
return m_id;
}
void AbstractProjectItem::setParent(AbstractProjectItem* parent)
{
if (m_parent != parent) {
if (m_parent) {
m_parent->removeChild(this);
}
// Check if we are trying to delete the item
if (m_isCurrent && parent == NULL) {
/*if (bin()) {
bin()->setCurrentItem(NULL);
}*/
}
m_parent = parent;
QObject::setParent(m_parent);
}
if (m_parent && !m_parent->contains(this)) {
m_parent->addChild(this);
}
}
Bin* AbstractProjectItem::bin()
{
if (m_parent) {
return m_parent->bin();
}
return NULL;
}
QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
{
QPixmap pix(source.width(), source.height());
pix.fill(Qt::transparent);
QPainter p(&pix);
p.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
path.addRoundedRect(0.5, 0.5, pix.width() - 1, pix.height() - 1, 4, 4);
p.setClipPath(path);
p.drawPixmap(0, 0, source);
p.end();
return pix;
}
void AbstractProjectItem::finishInsert(AbstractProjectItem* parent)
{
/*if (m_parent && !m_parent->contains(this)) {
m_parent->addChild(this);
}*/
//bin()->emitItemReady(this);
}
void AbstractProjectItem::addChild(AbstractProjectItem* child)
{
if (child && !contains(child)) {
bin()->emitAboutToAddItem(child);
append(child);
bin()->emitItemAdded(this);
}
}
void AbstractProjectItem::removeChild(AbstractProjectItem* child)
{
if (child && contains(child)) {
bin()->emitAboutToRemoveItem(child);
removeAll(child);
bin()->emitItemRemoved(child);
}
}
int AbstractProjectItem::index() const
{
if (m_parent) {
return m_parent->indexOf(const_cast<AbstractProjectItem*>(this));
}
return 0;
}
QVariant AbstractProjectItem::data(DataType type) const
{
QVariant data;
switch (type) {
case DataName:
data = QVariant(m_name);
break;
case DataDescription:
data = QVariant(m_description);
break;
case DataThumbnail:
data = QVariant(m_thumbnail);
break;
case DataDuration:
data = QVariant(m_duration);
break;
case JobType:
data = QVariant(m_jobType);
break;
case JobProgress:
data = QVariant(m_jobProgress);
break;
case JobMessage:
data = QVariant(m_jobMessage);
break;
default:
break;
}
return data;
}
int AbstractProjectItem::supportedDataCount() const
{
return 1;
}
QString AbstractProjectItem::name() const
{
return m_name;
}
void AbstractProjectItem::setName(const QString& name)
{
m_name = name;
}
QString AbstractProjectItem::description() const
{
return m_description;
}
void AbstractProjectItem::setDescription(const QString& description)
{
m_description = description;
}
void AbstractProjectItem::setCurrent(bool current, bool notify)
{
if (m_isCurrent != current)
{
m_isCurrent = current;
if (!notify)
return;
/*if (current) {
bin()->setCurrentItem(this);
} else {
bin()->setCurrentItem(NULL);
}*/
}
}
void AbstractProjectItem::setZone(const QPoint &/*zone*/)
{
}
QPoint AbstractProjectItem::zone() const
{
return QPoint();
}
/*
Copyright (C) 2012 Till Theato <root@ttill.de>
Copyright (C) 2014 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
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 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 ABSTRACTPROJECTITEM_H
#define ABSTRACTPROJECTITEM_H
#include "project/jobs/abstractclipjob.h"
#include <QObject>
#include <QPixmap>
#include <QUrl>
class ProjectClip;
class Bin;
class QDomElement;
class QDomDocument;
/**
* @class AbstractProjectItem
* @brief Base class for all project items (clips, folders, ...).
*
* Project items are stored in a tree like structure ...
*/
class AbstractProjectItem : public QObject, public QList<AbstractProjectItem *>
{
Q_OBJECT
public:
/**
* @brief Constructor.
* @param parent parent this item should be added to
*/
AbstractProjectItem(const QString &id, AbstractProjectItem *parent = 0);
/**
* @brief Creates a project item upon project load.
* @param description element for this item.
* @param parent parent this item should be added to
*
* We try to read the attributes "name" and "description"
*/
AbstractProjectItem(const QDomElement &description, AbstractProjectItem* parent = 0);
virtual ~AbstractProjectItem();
bool operator==(const AbstractProjectItem *projectItem) const;
/** @brief Returns a pointer to the parent item (or NULL). */
AbstractProjectItem *parent() const;
/** @brief Removes the item from its current parent and adds it as a child to @param parent. */
virtual void setParent(AbstractProjectItem *parent);
void finishInsert(AbstractProjectItem* parent);
/**
* @brief Adds a new child item and notifies the bin model about it (before and after).
* @param child project item which should be added as a child
*
* This function is called by setParent.
*/
virtual void addChild(AbstractProjectItem *child);
/**
* @brief Removes a child item and notifies the bin model about it (before and after).
* @param child project which sould be removed from the child list
*
* This function is called when a child's parent is changed through setParent
*/
virtual void removeChild(AbstractProjectItem *child);
/** @brief Returns a pointer to the bin model this item is child of (through its parent item). */
virtual Bin *bin();
/** @brief Returns the index this item has in its parent's child list. */
int index() const;
/** @brief Used to search for a clip with a specific id. */
virtual ProjectClip *clip(const QString &id) = 0;
virtual ProjectClip *clipAt(int ix) = 0;
/** @brief Returns the clip's id. */
const QString &clipId() const;
virtual void setZone(const QPoint &zone);
virtual QPoint zone() const;
enum DataType {
DataName = 0,
DataDescription,
DataDate,
DataThumbnail,
DataDuration,
JobType = Qt::UserRole + 1,
JobProgress,
JobMessage
};
/** @brief Returns the data that describes this item.
* @param type type of data to return
*
* This function is necessary for interaction with ProjectItemModel.
*/
virtual QVariant data(DataType type) const;
/**
* @brief Returns the amount of different types of data this item supports.
*
* This base class supports only DataName and DataDescription, so the return value is always 2.
* This function is necessary for interaction with ProjectItemModel.
*/
virtual int supportedDataCount() const;
/** @brief Returns the (displayable) name of this item. */
QString name() const;
/** @brief Sets a new (displayable) name. */
virtual void setName(const QString &name);
/** @brief Returns the (displayable) description of this item. */
QString description() const;
/** @brief Sets a new description. */
virtual void setDescription(const QString &description);
/** @brief Flags this item as being current (or not) and notifies the bin model about it. */
virtual void setCurrent(bool current, bool notify = true);
virtual QDomElement toXml(QDomDocument &document) = 0;
signals:
void childAdded(AbstractProjectItem *child);
void aboutToRemoveChild(AbstractProjectItem *child);
protected:
AbstractProjectItem *m_parent;
QString m_name;
QString m_description;
QPixmap m_thumbnail;
QString m_duration;
QPoint m_zone;
QString m_id;
AbstractClipJob::JOBTYPE m_jobType;
int m_jobProgress;
QString m_jobMessage;
/** @brief Returns a rounded border pixmap from the @param source pixmap. */
QPixmap roundedPixmap(const QPixmap &source);
private:
bool m_isCurrent;
};
#endif
This diff is collapsed.
/*
Copyright (C) 2012 Till Theato <root@ttill.de>
Copyright (C) 2014 Jean-Baptiste Mardelle <jb@kdenlive.org>
This file is part of Kdenlive. See www.kdenlive.org.
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 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
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 KDENLIVE_BIN_H
#define KDENLIVE_BIN_H
#include "abstractprojectitem.h"
#include <QWidget>
#include <QApplication>
#include <QStyledItemDelegate>
#include <QPainter>
#include <QDomElement>
#include <QSortFilterProxyModel>
class KdenliveDoc;
class QSplitter;
class KToolBar;
class QMenu;
class ProjectItemModel;
class ProjectClip;
class ProjectFolder;
class AbstractProjectItem;
class Monitor;
class QItemSelectionModel;
class ProjectSortProxyModel;
class JobManager;
namespace Mlt {
class Producer;
};
/**
* @class BinItemDelegate
* @brief This class is responsible for drawing items in the QTreeView.
*/
class BinItemDelegate: public QStyledItemDelegate
{
public:
BinItemDelegate(QObject* parent = 0): QStyledItemDelegate(parent) {
}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSize hint = QStyledItemDelegate::sizeHint(option, index);
return QSize(hint.width(), qMax(option.fontMetrics.lineSpacing() * 2 + 4, hint.height()));
QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
QString line1 = index.data(Qt::DisplayRole).toString();
QString line2 = index.data(Qt::UserRole).toString();
int textW = qMax(option.fontMetrics.width(line1), option.fontMetrics.width(line2));
QSize iconSize = icon.actualSize(option.decorationSize);
return QSize(qMax(textW, iconSize.width()) + 4, option.fontMetrics.lineSpacing() * 2 + 4);
}
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
if (index.column() == 0 && !index.data().isNull()) {
QRect r1 = option.rect;
painter->save();
painter->setClipRect(r1);
QStyleOptionViewItemV4 opt(option);
initStyleOption(&opt, index);
QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
QRect r = QStyle::alignedRect(opt.direction, Qt::AlignVCenter | Qt::AlignLeft,
opt.decorationSize, r1);
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
if (option.state & QStyle::State_Selected) {
painter->setPen(option.palette.highlightedText().color());
}
// Draw thumbnail
opt.icon.paint(painter, r);
int decoWidth = r.width() + 2 * textMargin;
QFont font = painter->font();
font.setBold(true);
painter->setFont(font);
int mid = (int)((r1.height() / 2));
r1.adjust(decoWidth, 0, 0, -mid);
QRect r2 = option.rect;
r2.adjust(decoWidth, mid, 0, 0);
QRectF bounding;
painter->drawText(r1, Qt::AlignLeft | Qt::AlignTop, index.data().toString(), &bounding);
font.setBold(false);
painter->setFont(font);
QString subText = index.data(Qt::UserRole).toString();
//int usage = index.data(UsageRole).toInt();
//if (usage != 0) subText.append(QString(" (%1)").arg(usage));
//if (option.state & (QStyle::State_Selected)) painter->setPen(option.palette.color(QPalette::Mid));
r2.adjust(0, bounding.bottom() - r2.top(), 0, 0);
QColor subTextColor = painter->pen().color();
subTextColor.setAlphaF(.5);
painter->setPen(subTextColor);
painter->drawText(r2, Qt::AlignLeft | Qt::AlignTop , subText, &bounding);
int jobProgress = index.data(AbstractProjectItem::JobProgress).toInt();
if (jobProgress != 0 && jobProgress != JobDone && jobProgress != JobAborted) {
if (jobProgress != JobCrashed) {
// Draw job progress bar
QColor color = option.palette.alternateBase().color();
painter->setPen(Qt::NoPen);
color.setAlpha(180);
painter->setBrush(QBrush(color));
QRect progress(r1.x() + 1, opt.rect.bottom() - 12, r1.width() / 2, 8);
painter->drawRect(progress);
painter->setBrush(option.palette.text());
if (jobProgress > 0) {
progress.adjust(1, 1, 0, -1);
progress.setWidth((progress.width() - 4) * jobProgress / 100);
painter->drawRect(progress);
} else if (jobProgress == JobWaiting) {
// Draw kind of a pause icon
progress.adjust(1, 1, 0, -1);
progress.setWidth(2);
painter->drawRect(progress);
progress.moveLeft(progress.right() + 2);
painter->drawRect(progress);
}
} else if (jobProgress == JobCrashed) {
QString jobText = index.data(AbstractProjectItem::JobMessage).toString();
if (!jobText.isEmpty()) {
QRectF txtBounding = painter->boundingRect(r2, Qt::AlignRight | Qt::AlignVCenter, " " + jobText + " ");
painter->setPen(Qt::NoPen);
painter->setBrush(option.palette.highlight());
painter->drawRoundedRect(txtBounding, 2, 2);
painter->setPen(option.palette.highlightedText().color());
painter->drawText(txtBounding, Qt::AlignCenter, jobText);
}
}
}
painter->restore();
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
};
/**
* @class EventEater
* @brief Filter mouse clicks in the Item View.
*/
class EventEater : public QObject
{
Q_OBJECT
public:
EventEater(QObject *parent = 0);