return m_effectList.at(ix);
}
-void ClipItem::setEffectAt(int ix, QDomElement effect)
+bool ClipItem::setEffectAt(int ix, QDomElement effect)
{
if (ix < 0 || ix > (m_effectList.count() - 1) || effect.isNull()) {
kDebug() << "Invalid effect index: " << ix;
- return;
+ return false;
}
//kDebug() << "CHange EFFECT AT: " << ix << ", CURR: " << m_effectList.at(ix).attribute("tag") << ", NEW: " << effect.attribute("tag");
effect.setAttribute("kdenlive_ix", ix + 1);
r.setHeight(20);
update(r);
}
+ return true;
}
EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool /*animate*/)
/** @brief Replaces an effect.
* @param ix The effect's index in effectlist
* @param effect The new effect */
- void setEffectAt(int ix, QDomElement effect);
+ bool setEffectAt(int ix, QDomElement effect);
void flashClip();
void addTransition(Transition*);
if (strobe == 0) strobe = 1;
doChangeClipSpeed(clip->info(), clip->speedIndependantInfo(), speed, clip->speed(), strobe, clip->baseClip()->getId());
}
- clip->setEffectAt(ix, effect);
- if (ix == clip->selectedEffectIndex()) {
- clip->setSelectedEffect(ix);
- if (!triggeredByUser)
- emit clipItemSelected(clip, ix);
- }
+ if (clip->setEffectAt(ix, effect)) {
+ if (ix == clip->selectedEffectIndex()) {
+ clip->setSelectedEffect(ix);
+ if (!triggeredByUser)
+ emit clipItemSelected(clip, ix);
+ }
+ } else emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
return;
}
clip->setFadeOut(pos);
}
}
+ bool success = true;
+ if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - clip->track(), clip->startPos(), effectParams)) success = false;
- if (!m_document->renderer()->mltEditEffect(m_document->tracksCount() - clip->track(), clip->startPos(), effectParams))
- emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
-
- clip->setEffectAt(ix, effect);
- if (ix == clip->selectedEffectIndex()) {
- clip->setSelectedEffect(ix);
- if (!triggeredByUser)
- emit clipItemSelected(clip, ix);
- }
+ if (success && clip->setEffectAt(ix, effect)) {
+ if (ix == clip->selectedEffectIndex()) {
+ clip->setSelectedEffect(ix);
+ if (!triggeredByUser)
+ emit clipItemSelected(clip, ix);
+ }
+ }
+ else emit displayMessage(i18n("Problem editing effect"), ErrorMessage);
}
else emit displayMessage(i18n("Cannot find clip to update effect"), ErrorMessage);
setDocumentModified();
{
if (pos < GenTime()) {
// Moving track effect
+ if (newPos > m_document->getTrackEffects(m_document->tracksCount() - track - 1).count()) {
+ newPos = m_document->getTrackEffects(m_document->tracksCount() - track - 1).count();
+ }
QDomElement act = m_document->getTrackEffect(m_document->tracksCount() - track - 1, newPos - 1);
QDomElement before = m_document->getTrackEffect(m_document->tracksCount() - track - 1, oldPos - 1);
return;
}
ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()), m_document->tracksCount() - track);
+ if (newPos > clip->effectsCount()) {
+ newPos = clip->effectsCount();
+ }
if (clip && !clip->effectAt(newPos - 1).isNull() && !clip->effectAt(oldPos - 1).isNull()) {
QDomElement act = clip->effectAt(newPos - 1);
QDomElement before = clip->effectAt(oldPos - 1);
if (clip) command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), oldeffect, effect, ix, true);
else command = new EditEffectCommand(this, m_document->tracksCount() - track, GenTime(-1), oldeffect, effect, ix, true);
m_commandStack->push(command);
- kDebug()<<"// UPDATE EFFECT, "<<EffectsList::property(effect, "kdenlive_ix")<<" / "<<EffectsList::property(effect, "kdenlive_group");
+ kDebug()<<"// UPDATE EFFECT, "<<EffectsList::property(effect, "kdenlive_ix")<<" / "<<EffectsList::property(effect, "kdenlive_info");
}
void CustomTrackView::slotUpdateClipRegion(ClipItem *clip, int ix, QString region)
parameters.addParam("tag", effect.attribute("tag"));
if (effect.hasAttribute("region")) parameters.addParam("region", effect.attribute("region"));
parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix"));
+ parameters.addParam("kdenlive_info", effect.attribute("kdenlive_info"));
parameters.addParam("id", effect.attribute("id"));
if (effect.hasAttribute("src")) parameters.addParam("src", effect.attribute("src"));
if (effect.hasAttribute("disable")) parameters.addParam("disable", effect.attribute("disable"));
}
};
+/**)
+ * @class EffectInfo
+ * @brief A class holding some meta info for effects widgets, like state (collapsed or not, ...)
+ * @author Jean-Baptiste Mardelle
+ */
+
+class EffectInfo
+{
+public:
+ EffectInfo() {isCollapsed = false; groupIndex = -1;}
+ bool isCollapsed;
+ int groupIndex;
+ QString groupName;
+ QString toString() const {
+ QStringList data;
+ data << QString::number(isCollapsed) << QString::number(groupIndex) << groupName;
+ return data.join("/");
+ }
+ void fromString(QString value) {
+ if (value.isEmpty()) return;
+ QStringList data = value.split("/");
+ isCollapsed = data.at(0).toInt();
+ if (data.count() > 1) groupIndex = data.at(1).toInt();
+ if (data.count() > 2) groupName = data.at(2);
+ }
+};
class EffectParameter
{
m_original_effect(original_effect),
m_lastEffect(lastEffect),
m_isGroup(isGroup),
- m_active(false)
+ m_active(false),
+ m_index(ix)
{
//setMouseTracking(true);
setupUi(this);
+ m_info.fromString(effect.attribute("kdenlive_info"));
frame->setBackgroundRole(QPalette::Midlight);
frame->setAutoFillBackground(true);
setFont(KGlobalSettings::smallestReadableFont());
void CollapsibleEffect::slotDeleteEffect()
{
- emit deleteEffect(m_effect, m_paramWidget->index());
+ if (!m_isGroup) emit deleteEffect(m_effect, m_paramWidget->index());
}
void CollapsibleEffect::slotEffectUp()
{
- emit changeEffectPosition(m_paramWidget->index(), true);
+ if (!m_isGroup) emit changeEffectPosition(m_paramWidget->index(), true);
}
void CollapsibleEffect::slotEffectDown()
{
- emit changeEffectPosition(m_paramWidget->index(), false);
+ if (!m_isGroup) emit changeEffectPosition(m_paramWidget->index(), false);
}
void CollapsibleEffect::slotSaveEffect()
widgetFrame->setVisible(show);
if (show) {
collapseButton->setArrowType(Qt::DownArrow);
- m_original_effect.removeAttribute("k_collapsed");
+ m_info.isCollapsed = false;
}
else {
collapseButton->setArrowType(Qt::RightArrow);
- m_original_effect.setAttribute("k_collapsed", 1);
+ m_info.isCollapsed = true;
}
+ m_effect.setAttribute("kdenlive_info", m_info.toString());
+ emit parameterChanged(m_original_effect, m_effect, m_index);
+
+}
+
+void CollapsibleEffect::setGroupIndex(int ix)
+{
+ m_info.groupIndex = ix;
}
void CollapsibleEffect::addGroupEffect(CollapsibleEffect *effect)
vbox->setSpacing(2);
widgetFrame->setLayout(vbox);
}
+ effect->setGroupIndex(groupIndex());
vbox->addWidget(effect);
}
int CollapsibleEffect::index() const
{
- if (m_paramWidget) return m_paramWidget->index();
- return 0;
+ return m_index;
+}
+
+int CollapsibleEffect::groupIndex() const
+{
+ if (m_isGroup) return m_index;
+ return -1;
}
int CollapsibleEffect::effectIndex() const
widgetFrame->setVisible(false);
}
}
- if (collapseButton->isEnabled()) slotShow(!m_effect.hasAttribute("k_collapsed"));
+ if (collapseButton->isEnabled() && m_info.isCollapsed) {
+ widgetFrame->setVisible(false);
+ collapseButton->setArrowType(Qt::RightArrow);
+
+ }
connect (m_paramWidget, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)), this, SIGNAL(parameterChanged(const QDomElement, const QDomElement, int)));
connect(m_paramWidget, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)));
doc.setContent(effects, true);
const QDomElement e = doc.documentElement();
int ix = e.attribute("kdenlive_ix").toInt();
- emit moveEffect(ix, this);
+ int last_index = -1;
+ if (m_isGroup) {
+ QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
+ if (vbox == NULL) return;
+ CollapsibleEffect *e = static_cast<CollapsibleEffect *>(vbox->itemAt(vbox->count() -1)->widget());
+ last_index = e->effectIndex();
+ }
+ emit moveEffect(ix, this, last_index);
event->setDropAction(Qt::MoveAction);
event->accept();
}
QDomElement effect() const;
void addGroupEffect(CollapsibleEffect *effect);
int index() const;
+ int groupIndex() const;
int effectIndex() const;
+ void setGroupIndex(int ix);
public slots:
void slotSyncEffectsPos(int pos);
bool m_active;
QMenu *m_menu;
QPoint m_clickPoint;
+ int m_index;
+ EffectInfo m_info;
protected:
virtual void mouseDoubleClickEvent ( QMouseEvent * event );
void resetEffect(int ix);
/** @brief Ask for creation of a group. */
void createGroup(int ix);
- void moveEffect(int ix, CollapsibleEffect*);
+ void moveEffect(int ix, CollapsibleEffect *group, int lastEffectIndex);
};
{
m_effectMetaInfo.trackMode = false;
m_effectMetaInfo.monitor = monitor;
+ m_effects = QList <CollapsibleEffect*>();
m_ui.setupUi(this);
setFont(KGlobalSettings::smallestReadableFont());
}
CollapsibleEffect *group = NULL;
- QString groupName = EffectsList::property(d, "kdenlive_group");
- if (!groupName.isEmpty()) {
- kDebug()<<"// CREATING EWFFECT GRP: "<<groupName;
- group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), groupName.toInt(), &m_effectMetaInfo, false, true, m_ui.container->widget());
- connect(group, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
- vbox1->addWidget(group);
+ EffectInfo effectInfo;
+ effectInfo.fromString(d.attribute("kdenlive_info"));
+ if (effectInfo.groupIndex >= 0) {
+ for (int j = 0; j < vbox1->count(); j++) {
+ CollapsibleEffect *gp = static_cast<CollapsibleEffect *>(vbox1->itemAt(j)->widget());
+ if (gp->groupIndex() == effectInfo.groupIndex) {
+ group = gp;
+ break;
+ }
+ }
+
+ if (group == NULL) {
+ group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), effectInfo.groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget());
+ if (!effectInfo.groupName.isEmpty()) group->title->setText(effectInfo.groupName);
+ connect(group, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int)));
+ vbox1->addWidget(group);
+ }
+ if (effectInfo.groupIndex >= m_groupIndex) m_groupIndex = effectInfo.groupIndex + 1;
}
/*QDomDocument doc;
connect(currentEffect, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
connect(currentEffect, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int)));
connect(currentEffect, SIGNAL(createGroup(int)), this , SLOT(slotCreateGroup(int)));
- connect(currentEffect, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
+ connect(currentEffect, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int)));
//ui.title->setPixmap(icon.pixmap(QSize(12, 12)));
}
if (m_draggedEffect) {
QMouseEvent *me = static_cast<QMouseEvent *>(e);
if (me->button() == Qt::LeftButton && (m_draggedEffect->frame->underMouse() || m_draggedEffect->title->underMouse()))
- m_clickPoint = me->pos();
+ m_clickPoint = me->globalPos();
else {
m_clickPoint = QPoint();
m_draggedEffect = NULL;
}
if (e->type() == QEvent::MouseMove) {
if (qobject_cast<CollapsibleEffect*>(o)) {
- CollapsibleEffect *effect = qobject_cast<CollapsibleEffect*>(o);
QMouseEvent *me = static_cast<QMouseEvent *>(e);
if (me->buttons() != Qt::LeftButton) {
e->accept();
void EffectStackView2::mouseMoveEvent(QMouseEvent * event)
{
- if (m_draggedEffect && (event->buttons() & Qt::LeftButton) && (m_clickPoint != QPoint()) && ((event->pos() - m_clickPoint).manhattanLength() >= QApplication::startDragDistance()))
+ if (m_draggedEffect && (event->buttons() & Qt::LeftButton) && (m_clickPoint != QPoint()) && ((event->globalPos() - m_clickPoint).manhattanLength() >= QApplication::startDragDistance())) {
+ kDebug()<<"DRAGG: "<<event->pos()<<"/"<<m_clickPoint;
startDrag();
+ }
}
void EffectStackView2::mouseReleaseEvent(QMouseEvent * event)
void EffectStackView2::slotDeleteEffect(const QDomElement effect, int index)
{
-
if (m_effectMetaInfo.trackMode)
emit removeEffect(NULL, m_trackindex, effect);
else
QDomElement oldeffect = m_currentEffectList.at(ix);
QDomElement neweffect = oldeffect.cloneNode().toElement();
QString groupName = QString::number(m_groupIndex);
- m_groupIndex++;
- EffectsList::setProperty(neweffect, "kdenlive_group", groupName);
+ EffectInfo effectinfo;
+ effectinfo.fromString(oldeffect.attribute("kdenlive_info"));
+ effectinfo.groupIndex = m_groupIndex;
+ neweffect.setAttribute("kdenlive_info", effectinfo.toString());
ItemInfo info;
if (m_effectMetaInfo.trackMode) {
int groupPos = l->indexOf(m_effects.at(ix));
CollapsibleEffect *group = new CollapsibleEffect(QDomElement(), QDomElement(), ItemInfo(), m_groupIndex, &m_effectMetaInfo, false, true, m_ui.container->widget());
- connect(group, SIGNAL(moveEffect(int, CollapsibleEffect*)), this , SLOT(slotMoveEffectToGroup(int, CollapsibleEffect*)));
+ m_groupIndex++;
+ connect(group, SIGNAL(moveEffect(int,CollapsibleEffect*,int)), this , SLOT(slotMoveEffectToGroup(int,CollapsibleEffect*,int)));
CollapsibleEffect *w = static_cast<CollapsibleEffect*>(l->takeAt(groupPos)->widget());
l->insertWidget(groupPos, group);
group->addGroupEffect(w);
}
-void EffectStackView2::slotMoveEffectToGroup(int ix, CollapsibleEffect* group)
+void EffectStackView2::slotMoveEffectToGroup(int ix, CollapsibleEffect* group, int lastEffectIndex)
{
QVBoxLayout *l = static_cast<QVBoxLayout *>(m_ui.container->widget()->layout());
CollapsibleEffect *effectToMove = getEffectByIndex(ix);
if (effectToMove == NULL) return;
l->removeWidget(effectToMove);
group->addGroupEffect(effectToMove);
+
+ QDomElement oldeffect = m_currentEffectList.at(effectToMove->index());
+ QDomElement neweffect = oldeffect.cloneNode().toElement();
+
+ EffectInfo effectinfo;
+ effectinfo.fromString(oldeffect.attribute("kdenlive_info"));
+ effectinfo.groupIndex = group->index();
+ neweffect.setAttribute("kdenlive_info", effectinfo.toString());
+
+ ItemInfo info;
+ if (m_effectMetaInfo.trackMode) {
+ info.track = m_trackInfo.type;
+ info.cropDuration = GenTime(m_trackInfo.duration, KdenliveSettings::project_fps());
+ info.cropStart = GenTime(0);
+ info.startPos = GenTime(-1);
+ info.track = 0;
+ emit updateEffect(NULL, m_trackindex, oldeffect, neweffect, effectToMove->index());
+ } else {
+ emit updateEffect(m_clipref, -1, oldeffect, neweffect, effectToMove->index());
+ }
+
+ if (effectToMove->effectIndex() == lastEffectIndex) return;
+ // Update effect index with new position
+ if (m_effectMetaInfo.trackMode) {
+ emit changeEffectPosition(NULL, m_trackindex, effectToMove->effectIndex(), lastEffectIndex + 1);
+ }
+ else {
+ emit changeEffectPosition(m_clipref, -1, effectToMove->effectIndex(), lastEffectIndex + 1);
+ }
}
+
#include "effectstackview2.moc"
/** @brief Create a group containing effect with ix index. */
void slotCreateGroup(int ix);
- /** @brief Move an effect into a group. */
- void slotMoveEffectToGroup(int, CollapsibleEffect*);
+ /** @brief Move an effect into a group.
+ ** @param ix the index of effect to move in stack layout
+ ** @param group the effect group where the effect is moved
+ ** @param lastEffectIndex the last effect index in the group, effect will be inserted after that index
+ */
+ void slotMoveEffectToGroup(int ix, CollapsibleEffect *group, int lastEffectIndex);
signals:
// add effect to clip
QString effecttag;
QString effectid;
+ QString effectinfo;
QString effectindex = QString::number(effectNb);
// Get effect tag & index
for (QDomNode n3 = effect.firstChild(); !n3.isNull(); n3 = n3.nextSibling()) {
effecttag = effectparam.text();
} else if (effectparam.attribute("name") == "kdenlive_id") {
effectid = effectparam.text();
+ } else if (effectparam.attribute("name") == "kdenlive_info") {
+ effectinfo = effectparam.text();
} else if (effectparam.attribute("name") == "disable" && effectparam.text().toInt() == 1) {
// Fix effects index
disableeffect = true;
} else {
QDomElement currenteffect = clipeffect.cloneNode().toElement();
currenteffect.setAttribute("kdenlive_ix", effectindex);
+ currenteffect.setAttribute("kdenlive_info", effectinfo);
QDomNodeList clipeffectparams = currenteffect.childNodes();
if (MainWindow::videoEffects.hasKeyFrames(currenteffect)) {