Commit 128d2982 authored by Nicolas Carion's avatar Nicolas Carion
Browse files

Start reorganizing Bin. May break things.

Most salient changes:
- Effect logic is being mostly deprecated. It now uses the effectstackmodel
- Direct access to profiles are being removed. They should be accessed through pCore
- Producers are wrapped in shared_ptr
- The coupling with the Monitor is being reduced. Ideally, there should only be a
signal telling which Producer to display.
- The bin hierarchy is melted into the abstractTreeModel framework. Fusion is done but
there are still duplicate logic
- ProjectClip now inherits ClipController
parent 3297ef4a
......@@ -26,7 +26,7 @@
AbstractTreeModel::AbstractTreeModel(QObject *parent)
: QAbstractItemModel(parent)
{
rootItem = new TreeItem(QList<QVariant>());
rootItem = new TreeItem(QList<QVariant>(), this);
}
AbstractTreeModel::~AbstractTreeModel()
......@@ -126,3 +126,32 @@ int AbstractTreeModel::rowCount(const QModelIndex &parent) const
return parentItem->childCount();
}
QModelIndex AbstractTreeModel::getIndexFromItem(TreeItem *item) const
{
if (item == rootItem) {
return QModelIndex();
}
return index(item->row(), 0, getIndexFromItem(item->parentItem()));
}
void AbstractTreeModel::notifyRowAboutToAppend(TreeItem *item)
{
auto index = getIndexFromItem(item);
beginInsertRows(index, item->childCount(), item->childCount());
}
void AbstractTreeModel::notifyRowAppended()
{
endInsertRows();
}
void AbstractTreeModel::notifyRowAboutToDelete(TreeItem *item, int row)
{
auto index = getIndexFromItem(item);
beginRemoveRows(index, row, row);
}
void AbstractTreeModel::notifyRowDeleted()
{
endRemoveRows();
}
......@@ -35,6 +35,29 @@ public:
explicit AbstractTreeModel(QObject *parent = nullptr);
virtual ~AbstractTreeModel();
/* @brief Given an item from the hierarchy, construct the corresponding ModelIndex */
QModelIndex getIndexFromItem(TreeItem *item) const;
/* @brief Send the appropriate notification related to a row that we are appending
@param item is the parent item to which row is appended
*/
void notifyRowAboutToAppend(TreeItem *item);
/* @brief Send the appropriate notification related to a row that we have appended
*/
void notifyRowAppended();
/* @brief Send the appropriate notification related to a row that we are deleting
@param item is the parent of the row being deleted
@param row is the index of the row being deleted
*/
void notifyRowAboutToDelete(TreeItem *item, int row);
/* @brief Send the appropriate notification related to a row that we have appended
@param item is the item to which row are appended
*/
void notifyRowDeleted();
QVariant data(const QModelIndex &index, int role) const override;
//This is reimplemented to prevent selection of the categories
Qt::ItemFlags flags(const QModelIndex &index) const override;
......
......@@ -20,12 +20,14 @@
***************************************************************************/
#include "treeitem.hpp"
#include "abstracttreemodel.hpp"
TreeItem::TreeItem(const QList<QVariant> &data, TreeItem *parent)
TreeItem::TreeItem(const QList<QVariant> &data, AbstractTreeModel* model, TreeItem *parent)
{
m_parentItem = parent;
m_itemData = data;
m_depth = 0;
m_model = model;
}
TreeItem::~TreeItem()
......@@ -35,19 +37,44 @@ TreeItem::~TreeItem()
TreeItem* TreeItem::appendChild(const QList<QVariant> &data)
{
TreeItem *child = new TreeItem(data, this);
m_model->notifyRowAboutToAppend(this);
TreeItem *child = new TreeItem(data, m_model, this);
child->m_depth = m_depth + 1;
m_childItems.append(child);
m_model->notifyRowAppended();
return child;
}
void TreeItem::appendChild(TreeItem *child)
{
m_model->notifyRowAboutToAppend(this);
child->m_depth = m_depth + 1;
child->m_parentItem = this;
m_childItems.append(child);
m_model->notifyRowAppended();
}
TreeItem *TreeItem::child(int row)
void TreeItem::removeChild(TreeItem *child)
{
m_model->notifyRowAboutToDelete(this, child->row());
bool success = m_childItems.removeAll(child);
Q_ASSERT(success);
child->m_depth = 0;
child->m_parentItem = nullptr;
m_model->notifyRowDeleted();
}
void TreeItem::changeParent(TreeItem *newParent)
{
if (m_parentItem) {
m_parentItem->removeChild(this);
}
if (newParent) {
newParent->appendChild(this);
}
}
TreeItem *TreeItem::child(int row) const
{
return m_childItems.value(row);
}
......@@ -77,7 +104,7 @@ int TreeItem::row() const
if (m_parentItem)
return m_parentItem->m_childItems.indexOf(const_cast<TreeItem*>(this));
return 0;
return -1;
}
int TreeItem::depth() const
......
......@@ -29,15 +29,17 @@
/* @brief This class is a generic class to represent items of a tree-like model
*/
class AbstractTreeModel;
class TreeItem
{
public:
/* @brief Construct a TreeItem
@param data List of data elements (columns) of the created item
@param model Pointer to the model to which this elem belongs to
@param parentItem address of the parent if the child is not orphan
*/
explicit TreeItem(const QList<QVariant> &data, TreeItem *parentItem = nullptr);
~TreeItem();
explicit TreeItem(const QList<QVariant> &data, AbstractTreeModel* model, TreeItem *parentItem = nullptr);
virtual ~TreeItem();
/* @brief Creates a child of the current item
@param data: List of data elements (columns) to init the child with.
......@@ -49,10 +51,19 @@ public:
*/
void appendChild(TreeItem *child);
/* @brief Remove given child from children list. The parent of the child is updated
accordingly
*/
void removeChild(TreeItem *child);
/* @brief Change the parent of the current item. Structures are modified accordingly
*/
void changeParent(TreeItem *newParent);
/* @brief Retrieves a child of the current item
@param row is the index of the child to retrieve
*/
TreeItem *child(int row);
TreeItem *child(int row) const;
/* @brief Return the number of children */
int childCount() const;
......@@ -66,6 +77,7 @@ public:
QVariant data(int column) const;
/* @brief Return the index of current item amongst father's children
Returns -1 on error (eg: no parent set)
*/
int row() const;
......@@ -76,10 +88,12 @@ public:
/* @brief Return the depth of the current item*/
int depth() const;
private:
protected:
QList<TreeItem*> m_childItems;
QList<QVariant> m_itemData;
TreeItem *m_parentItem;
AbstractTreeModel *m_model;
int m_depth;
};
......
......@@ -21,15 +21,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "abstractprojectitem.h"
#include "projectitemmodel.h"
#include "bin.h"
#include <QDomElement>
#include <QVariant>
#include <QPainter>
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, AbstractProjectItem *parent) :
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, ProjectItemModel* model, AbstractProjectItem *parent) :
QObject()
, m_parent(parent)
, TreeItem(QList<QVariant>(), static_cast<AbstractTreeModel*>(model), (TreeItem*)parent)
, m_id(id)
, m_usage(0)
, m_clipStatus(StatusReady)
......@@ -40,9 +41,9 @@ AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QString &id
{
}
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description, AbstractProjectItem *parent) :
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description,ProjectItemModel* model, AbstractProjectItem *parent) :
QObject()
, m_parent(parent)
, TreeItem(QList<QVariant>(), static_cast<AbstractTreeModel*>(model), (TreeItem*)parent)
, m_id(description.attribute(QStringLiteral("id")))
, m_usage(0)
, m_clipStatus(StatusReady)
......@@ -55,30 +56,25 @@ AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement
AbstractProjectItem::~AbstractProjectItem()
{
while (!isEmpty()) {
AbstractProjectItem *child = takeFirst();
removeChild(child);
delete child;
}
}
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();
bool equal = this->m_childItems == projectItem->m_childItems;
equal &= m_parentItem == projectItem->m_parentItem;
return equal;
}
AbstractProjectItem *AbstractProjectItem::parent() const
{
return m_parent;
return static_cast<AbstractProjectItem*>(m_parentItem);
}
void AbstractProjectItem::setRefCount(uint count)
{
m_usage = count;
bin()->emitItemUpdated(this);
static_cast<ProjectItemModel*>(m_model)->bin()->emitItemUpdated(this);
}
uint AbstractProjectItem::refCount() const
......@@ -89,13 +85,13 @@ uint AbstractProjectItem::refCount() const
void AbstractProjectItem::addRef()
{
m_usage++;
bin()->emitItemUpdated(this);
static_cast<ProjectItemModel*>(m_model)->bin()->emitItemUpdated(this);
}
void AbstractProjectItem::removeRef()
{
m_usage--;
bin()->emitItemUpdated(this);
static_cast<ProjectItemModel*>(m_model)->bin()->emitItemUpdated(this);
}
const QString &AbstractProjectItem::clipId() const
......@@ -103,29 +99,6 @@ const QString &AbstractProjectItem::clipId() const
return m_id;
}
void AbstractProjectItem::setParent(AbstractProjectItem *parent)
{
if (m_parent != parent) {
if (m_parent) {
m_parent->removeChild(this);
}
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 nullptr;
}
QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
{
QPixmap pix(source.width(), source.height());
......@@ -140,31 +113,7 @@ QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
return pix;
}
void AbstractProjectItem::addChild(AbstractProjectItem *child)
{
if (child && !contains(child)) {
bin()->emitAboutToAddItem(child);
append(child);
bin()->emitItemAdded(child);
}
}
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;
}
AbstractProjectItem::PROJECTITEMTYPE AbstractProjectItem::itemType() const
{
......@@ -265,3 +214,14 @@ AbstractProjectItem::CLIPSTATUS AbstractProjectItem::clipStatus() const
return m_clipStatus;
}
AbstractProjectItem *AbstractProjectItem::getEnclosingFolder(bool strict) const
{
if (!strict && itemType() == AbstractProjectItem::FolderItem) {
return const_cast<AbstractProjectItem*>(this);
}
if (m_parentItem) {
return static_cast<AbstractProjectItem*>(m_parentItem)->getEnclosingFolder(false);
}
return nullptr;
}
......@@ -23,10 +23,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef ABSTRACTPROJECTITEM_H
#define ABSTRACTPROJECTITEM_H
#include "abstractmodel/treeitem.hpp"
#include "project/jobs/abstractclipjob.h"
#include <QObject>
#include <QPixmap>
#include <QDateTime>
class ProjectClip;
......@@ -34,6 +34,7 @@ class ProjectFolder;
class Bin;
class QDomElement;
class QDomDocument;
class ProjectItemModel;
/**
* @class AbstractProjectItem
......@@ -42,7 +43,7 @@ class QDomDocument;
* Project items are stored in a tree like structure ...
*/
class AbstractProjectItem : public QObject, public QList<AbstractProjectItem *>
class AbstractProjectItem : public QObject, public TreeItem
{
Q_OBJECT
......@@ -59,15 +60,16 @@ public:
* @brief Constructor.
* @param parent parent this item should be added to
*/
AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, AbstractProjectItem *parent = nullptr);
AbstractProjectItem(PROJECTITEMTYPE type, const QString &id, ProjectItemModel *model, AbstractProjectItem *parent = nullptr);
/**
* @brief Creates a project item upon project load.
* @param description element for this item.
* @param model pointer to the model this item is added to.
* @param parent parent this item should be added to
*
* We try to read the attributes "name" and "description"
*/
AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description, AbstractProjectItem *parent = nullptr);
AbstractProjectItem(PROJECTITEMTYPE type, const QDomElement &description, ProjectItemModel *model, AbstractProjectItem *parent = nullptr);
virtual ~AbstractProjectItem();
bool operator==(const AbstractProjectItem *projectItem) const;
......@@ -93,10 +95,8 @@ public:
*/
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. */
//TODO : this is redudant with TreeItem::row()
int index() const;
/** @brief Returns the type of this item (folder, clip, subclip, etc). */
......@@ -196,12 +196,16 @@ public:
virtual QString getToolTip() const = 0;
virtual bool rename(const QString &name, int column) = 0;
/* Returns a ptr to the enclosing dir, and nullptr if none is found.
@param strict if set to false, the enclosing dir of a dir is itself, otherwise we try to find a "true" parent
*/
AbstractProjectItem *getEnclosingFolder(bool strict = false) const;
signals:
void childAdded(AbstractProjectItem *child);
void aboutToRemoveChild(AbstractProjectItem *child);
protected:
AbstractProjectItem *m_parent;
QString m_name;
QString m_description;
QIcon m_thumbnail;
......
This diff is collapsed.
......@@ -26,6 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "abstractprojectitem.h"
#include "timecode.h"
#include "effects/effectstack/model/effectstackmodel.hpp"
#include <KMessageWidget>
#include <QWidget>
......@@ -183,9 +185,6 @@ public:
/** @brief Sets the document for the bin and initialize some stuff */
void setDocument(KdenliveDoc *project);
/** @brief Returns the root folder, which is the parent for all items in the view */
ProjectFolder *rootFolder();
/** @brief Create a clip item from its xml description */
void createClip(const QDomElement &xml);
......@@ -226,11 +225,6 @@ public:
/** @brief Current producer has changed, refresh monitor and timeline*/
void refreshClip(const QString &id);
/** @brief Some stuff used to notify the Item Model */
void emitAboutToAddItem(AbstractProjectItem *item);
void emitItemAdded(AbstractProjectItem *item);
void emitAboutToRemoveItem(AbstractProjectItem *item);
void emitItemRemoved(AbstractProjectItem *item);
void setupMenu(QMenu *addMenu, QAction *defaultAction, const QHash<QString, QAction *> &actions);
/** @brief The source file was modified, we will reload it soon, disable item in the meantime */
......@@ -295,16 +289,8 @@ public:
void deleteClipMarker(const QString &comment, const QString &id, const GenTime &position);
/** @brief Delete all markers from @param id clip. */
void deleteAllClipMarkers(const QString &id);
/** @brief Remove an effect from a bin clip. */
void removeEffect(const QString &id, const QDomElement &effect);
void moveEffect(const QString &id, const QList<int> &oldPos, const QList<int> &newPos);
/** @brief Add an effect to a bin clip. */
void addEffect(const QString &id, QDomElement &effect);
/** @brief Update a bin clip effect. */
void updateEffect(const QString &id, QDomElement &effect, int ix, bool refreshStackWidget);
void changeEffectState(const QString &id, const QList<int> &indexes, bool disable, bool refreshStack);
/** @brief Edit an effect settings to a bin clip. */
void editMasterEffect(ClipController *ctl);
void editMasterEffect(AbstractProjectItem *clip);
/** @brief An effect setting was changed, update stack if displayed. */
void updateMasterEffect(ClipController *ctl);
/** @brief Display a message about an operation in status bar. */
......@@ -371,8 +357,6 @@ private slots:
void slotItemDropped(const QStringList &ids, const QModelIndex &parent);
void slotItemDropped(const QList<QUrl> &urls, const QModelIndex &parent);
void slotEffectDropped(const QString &effect, const QModelIndex &parent);
void slotUpdateEffect(QString id, QDomElement oldEffect, QDomElement newEffect, int ix, bool refreshStack = false);
void slotChangeEffectState(QString id, const QList<int> &indexes, bool disable);
void slotItemEdited(const QModelIndex &, const QModelIndex &, const QVector<int> &);
void slotAddUrl(const QString &url, int folderId, const QMap<QString, QString> &data = QMap<QString, QString>());
void slotAddUrl(const QString &url, const QMap<QString, QString> &data = QMap<QString, QString>());
......@@ -444,8 +428,6 @@ public slots:
void slotSaveClipMarkers(const QString &id);
void slotDuplicateClip();
void slotLocateClip();
void slotDeleteEffect(const QString &id, QDomElement effect);
void slotMoveEffect(const QString &id, const QList<int> &currentPos, int newPos);
/** @brief Request audio thumbnail for clip with id */
void slotCreateAudioThumb(const QString &id);
/** @brief Abort audio thumbnail for clip with id */
......@@ -456,8 +438,8 @@ public slots:
/** @brief Pass some important properties to timeline track producers. */
void updateTimelineProducers(const QString &id, const QMap<QString, QString> &passProperties);
/** @brief Add effect to active Bin clip (used when double clicking an effect in list). */
void slotEffectDropped(QString id, QDomElement);
/** @brief Request current frame from project monitor.
void slotEffectDropped(QString id, const QString& effectID);
/** @brief Request current frame from project monitor.
* @param clipId is the id of a clip we want to hide from screenshot
* @param request true to start capture process, false to end it. It is necessary to emit a false after image is received
**/
......@@ -482,7 +464,6 @@ protected:
private:
ProjectItemModel *m_itemModel;
QAbstractItemView *m_itemView;
ProjectFolder *m_rootFolder;
/** @brief An "Up" item that is inserted in bin when using icon view so that user can navigate up */
ProjectFolderUp *m_folderUp;
BinItemDelegate *m_binTreeViewDelegate;
......@@ -565,9 +546,11 @@ signals:
/** @brief Trigger timecode format refresh where needed. */
void refreshTimeCode();
/** @brief Request display of effect stack for a Bin clip. */
void masterClipSelected(ClipController *, Monitor *);
/** @brief Request updating of the effect stack if currently displayed. */
void masterClipUpdated(ClipController *, Monitor *);
void requestShowEffectStack(std::shared_ptr<EffectStackModel>);
/** @brief Request that the current effect stack is hidden */
void requestHideEffectStack();
/** @brief Request that the given clip is displayed in the clip monitor */
void requestClipShow(ProjectClip*);
void displayBinMessage(const QString &, KMessageWidget::MessageType);
void displayMessage(const QString &, int, MessageType);
void requesteInvalidRemoval(const QString &, const QString &, const QString &);
......
......@@ -116,117 +116,6 @@ void RenameBinFolderCommand::redo()
m_bin->renameFolder(m_clipId, m_newName);
}
AddBinEffectCommand::AddBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &effect, QUndoCommand *parent) :
QUndoCommand(parent),
m_bin(bin),
m_clipId(clipId),
m_effect(effect)
{
setText(i18n("Add Bin Effect"));
}
// virtual
void AddBinEffectCommand::undo()
{
m_bin->removeEffect(m_clipId, m_effect);
}
// virtual
void AddBinEffectCommand::redo()
{
m_bin->addEffect(m_clipId, m_effect);
}
RemoveBinEffectCommand::RemoveBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &effect, QUndoCommand *parent) :
QUndoCommand(parent),
m_bin(bin),
m_clipId(clipId),
m_effect(effect)
{
setText(i18n("Remove Bin Effect"));
}
// virtual
void RemoveBinEffectCommand::undo()
{
m_bin->addEffect(m_clipId, m_effect);
}
// virtual
void RemoveBinEffectCommand::redo()
{
m_bin->removeEffect(m_clipId, m_effect);
}
UpdateBinEffectCommand::UpdateBinEffectCommand(Bin *bin, const QString &clipId, QDomElement &oldEffect, QDomElement &newEffect, int ix, bool refreshStack, QUndoCommand *parent) :
QUndoCommand(parent),
m_bin(bin),
m_clipId(clipId),
m_oldEffect(oldEffect),
m_newEffect(newEffect),
m_ix(ix),
m_refreshStack(refreshStack)
{
setText(i18n("Edit Bin Effect"));
}
// virtual
void UpdateBinEffectCommand::undo()
{
m_bin->updateEffect(m_clipId, m_oldEffect, m_ix, m_refreshStack);
}
// virtual
void UpdateBinEffectCommand::redo()