]> git.sesse.net Git - kdenlive/blobdiff - src/effectstack/collapsiblegroup.cpp
Use KLocalizedString (for i18n only, in kf5 it will necessary => use a script for...
[kdenlive] / src / effectstack / collapsiblegroup.cpp
index 4e7afd847b63680592549e85e87ccb66f8f73176..cd5a439fbd6e4fcf8dd3c2261a99ee8691863b14 100644 (file)
@@ -30,7 +30,7 @@
 
 #include <KDebug>
 #include <KGlobalSettings>
-#include <KLocale>
+#include <KLocalizedString>
 #include <KMessageBox>
 #include <KStandardDirs>
 #include <KFileDialog>
@@ -42,7 +42,7 @@ MyEditableLabel::MyEditableLabel(QWidget * parent):
 {
     setFrame(false);
     setReadOnly(true);
-    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
+    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
 }
 
 void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
@@ -53,17 +53,19 @@ void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e )
 }
 
 
-CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QString groupName, QWidget * parent) :
-        AbstractCollapsibleWidget(parent),
-        m_index(ix)
+CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, const EffectInfo &info, QWidget * parent) :
+        AbstractCollapsibleWidget(parent)
 {
-    setupUi(this);
+    m_info.groupIndex = ix;
     m_subWidgets = QList <CollapsibleEffect *> ();
     setFont(KGlobalSettings::smallestReadableFont());
-    QHBoxLayout *l = static_cast <QHBoxLayout *>(framegroup->layout());
+    frame->setObjectName("framegroup");
+    decoframe->setObjectName("decoframegroup");
+    QHBoxLayout *l = static_cast <QHBoxLayout *>(frame->layout());
     m_title = new MyEditableLabel(this);
-    l->insertWidget(4, m_title);
-    m_title->setText(groupName.isEmpty() ? i18n("Effect Group") : groupName);
+    l->insertWidget(2, m_title);
+    m_title->setText(info.groupName.isEmpty() ? i18n("Effect Group") : info.groupName);
+    m_info.groupName = m_title->text();
     connect(m_title, SIGNAL(editingFinished()), this, SLOT(slotRenameGroup()));
     buttonUp->setIcon(KIcon("kdenlive-up"));
     buttonUp->setToolTip(i18n("Move effect up"));
@@ -78,19 +80,23 @@ CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QStr
     m_menu->addAction(KIcon("view-refresh"), i18n("Reset Group"), this, SLOT(slotResetGroup()));
     m_menu->addAction(KIcon("document-save"), i18n("Save Group"), this, SLOT(slotSaveGroup()));
     
-    effecticon->setPixmap(KIcon("folder").pixmap(16,16));
     m_menu->addAction(KIcon("list-remove"), i18n("Ungroup"), this, SLOT(slotUnGroup()));
     setAcceptDrops(true);
     menuButton->setIcon(KIcon("kdenlive-menu"));
     menuButton->setMenu(m_menu);
     
-    enabledBox->setChecked(true);
+    enabledButton->setChecked(false);
+    enabledButton->setIcon(KIcon("visible"));
+    
+    if (info.groupIsCollapsed) {
+       slotShow(false);
+    }
 
     connect(collapseButton, SIGNAL(clicked()), this, SLOT(slotSwitch()));
-    connect(enabledBox, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool)));
+    connect(enabledButton, SIGNAL(toggled(bool)), this, SLOT(slotEnable(bool)));
     connect(buttonUp, SIGNAL(clicked()), this, SLOT(slotEffectUp()));
     connect(buttonDown, SIGNAL(clicked()), this, SLOT(slotEffectDown()));
-    connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteEffect()));
+    connect(buttonDel, SIGNAL(clicked()), this, SLOT(slotDeleteGroup()));
 
 }
 
@@ -106,49 +112,57 @@ void CollapsibleGroup::slotUnGroup()
 
 bool CollapsibleGroup::isActive() const
 {
-    return decoframegroup->property("active").toBool();
+    return decoframe->property("active").toBool();
 }
 
 void CollapsibleGroup::setActive(bool activate)
 {
-    decoframegroup->setProperty("active", activate);
-    decoframegroup->setStyleSheet(decoframegroup->styleSheet());
+    decoframe->setProperty("active", activate);
+    decoframe->setStyleSheet(decoframe->styleSheet());
 }
 
 void CollapsibleGroup::mouseDoubleClickEvent ( QMouseEvent * event )
 {
-    if (framegroup->underMouse() && collapseButton->isEnabled()) slotSwitch();
+    if (frame->underMouse() && collapseButton->isEnabled()) slotSwitch();
     QWidget::mouseDoubleClickEvent(event);
 }
 
 
-void CollapsibleGroup::slotEnable(bool enable)
+void CollapsibleGroup::slotEnable(bool disable, bool emitInfo)
 {
-    m_title->setEnabled(enable);
-    enabledBox->blockSignals(true);
-    enabledBox->setChecked(enable);
-    enabledBox->blockSignals(false);
-    QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
-    if (vbox == NULL) return;
-    for (int i = 0; i < vbox->count(); i++) {
-       CollapsibleGroup *e = static_cast<CollapsibleGroup *>(vbox->itemAt(i)->widget());
-       if (e) e->enabledBox->setChecked(enable);// slotEnable(enable);
-    }
+    m_title->setEnabled(!disable);
+    enabledButton->blockSignals(true);
+    enabledButton->setChecked(disable);
+    enabledButton->setIcon(disable ? KIcon("novisible") : KIcon("visible"));
+    enabledButton->blockSignals(false);
+    for (int i = 0; i < m_subWidgets.count(); ++i)
+       m_subWidgets.at(i)->slotDisable(disable, emitInfo);
 }
 
-void CollapsibleGroup::slotDeleteEffect()
+void CollapsibleGroup::slotDeleteGroup()
 {
-    emit deleteGroup(groupIndex());
+    QDomDocument doc;
+    // delete effects from the last one to the first, otherwise each deletion would trigger an update
+    // in other effects's kdenlive_ix index.
+    for (int i = m_subWidgets.count() - 1; i >= 0; --i)
+        doc.appendChild(doc.importNode(m_subWidgets.at(i)->effect(), true));
+    emit deleteGroup(doc);
 }
 
 void CollapsibleGroup::slotEffectUp()
 {
-    emit changeGroupPosition(groupIndex(), true);
+    QList <int> indexes;
+    for (int i = 0; i < m_subWidgets.count(); ++i)
+        indexes << m_subWidgets.at(i)->effectIndex();
+    emit changeEffectPosition(indexes, true);
 }
 
 void CollapsibleGroup::slotEffectDown()
 {
-    emit changeGroupPosition(groupIndex(), false);
+    QList <int> indexes;
+    for (int i = 0; i < m_subWidgets.count(); ++i)
+        indexes << m_subWidgets.at(i)->effectIndex();
+    emit changeEffectPosition(indexes, false);
 }
 
 void CollapsibleGroup::slotSaveGroup()
@@ -162,9 +176,20 @@ void CollapsibleGroup::slotSaveGroup()
     QDomDocument doc = effectsData();
     QDomElement base = doc.documentElement();
     QDomNodeList effects = base.elementsByTagName("effect");
-    for (int i = 0; i < effects.count(); i++)
-        effects.at(i).toElement().removeAttribute("kdenlive_ix");
+    for (int i = 0; i < effects.count(); ++i) {
+       QDomElement eff = effects.at(i).toElement();
+        eff.removeAttribute("kdenlive_ix");
+       EffectInfo info;
+       info.fromString(eff.attribute("kdenlive_info"));
+       // Make sure all effects have the correct new group name
+       info.groupName = name;
+       // Saved effect group should have a group index of -1
+       info.groupIndex = -1;
+       eff.setAttribute("kdenlive_info", info.toString());
+
+    }
     
+    base.setAttribute("name", name);
     base.setAttribute("id", name);
     base.setAttribute("type", "custom");  
 
@@ -180,7 +205,7 @@ void CollapsibleGroup::slotSaveGroup()
 void CollapsibleGroup::slotResetGroup()
 {
     QMutexLocker lock(&m_mutex);
-    for (int i = 0; i < m_subWidgets.count(); i++)
+    for (int i = 0; i < m_subWidgets.count(); ++i)
         m_subWidgets.at(i)->slotResetEffect();
 }
 
@@ -195,13 +220,13 @@ void CollapsibleGroup::slotShow(bool show)
     widgetFrame->setVisible(show);
     if (show) {
         collapseButton->setArrowType(Qt::DownArrow);
-       m_info.isCollapsed = false;
+       m_info.groupIsCollapsed = false;
     }
     else {
         collapseButton->setArrowType(Qt::RightArrow);
-       m_info.isCollapsed = true;
+       m_info.groupIsCollapsed = true;
     }
-    //emit parameterChanged(m_original_effect, m_effect, effectIndex());   
+    if (!m_subWidgets.isEmpty()) m_subWidgets.at(0)->groupStateChanged(m_info.groupIsCollapsed);
 }
 
 QWidget *CollapsibleGroup::title() const
@@ -221,6 +246,7 @@ void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect)
     }
     effect->setGroupIndex(groupIndex());
     effect->setGroupName(m_title->text());
+    effect->decoframe->setObjectName("decoframesub");
     m_subWidgets.append(effect);
     vbox->addWidget(effect);
 }
@@ -235,9 +261,10 @@ void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
     QMutexLocker lock(&m_mutex);
     QVBoxLayout *vbox = static_cast<QVBoxLayout *>(widgetFrame->layout());
     if (vbox == NULL) return;
-    for (int i = m_subWidgets.count() - 1; i >= 0 ; i--) {
+    for (int i = m_subWidgets.count() - 1; i >= 0 ; --i) {
        vbox->removeWidget(m_subWidgets.at(i));
        layout->insertWidget(ix, m_subWidgets.at(i));
+       m_subWidgets.at(i)->decoframe->setObjectName("decoframe");
         m_subWidgets.at(i)->removeFromGroup();
     }
     m_subWidgets.clear();
@@ -245,7 +272,7 @@ void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout)
 
 int CollapsibleGroup::groupIndex() const
 {
-    return m_index;
+    return m_info.groupIndex;
 }
 
 bool CollapsibleGroup::isGroup() const
@@ -266,40 +293,82 @@ void CollapsibleGroup::updateTimecodeFormat()
 void CollapsibleGroup::dragEnterEvent(QDragEnterEvent *event)
 {
     if (event->mimeData()->hasFormat("kdenlive/effectslist")) {
-       framegroup->setProperty("active", true);
-       framegroup->setStyleSheet(framegroup->styleSheet());
+       frame->setProperty("target", true);
+       frame->setStyleSheet(frame->styleSheet());
        event->acceptProposedAction();
     }
 }
 
 void CollapsibleGroup::dragLeaveEvent(QDragLeaveEvent */*event*/)
 {
-    framegroup->setProperty("active", false);
-    framegroup->setStyleSheet(framegroup->styleSheet());
+    frame->setProperty("target", false);
+    frame->setStyleSheet(frame->styleSheet());
 }
 
 void CollapsibleGroup::dropEvent(QDropEvent *event)
 {
-    QMutexLocker lock(&m_mutex);
-    framegroup->setProperty("active", false);
-    framegroup->setStyleSheet(framegroup->styleSheet());
+    frame->setProperty("target", false);
+    frame->setStyleSheet(frame->styleSheet());
     const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist"));
     //event->acceptProposedAction();
     QDomDocument doc;
     doc.setContent(effects, true);
     QDomElement e = doc.documentElement();
     int ix = e.attribute("kdenlive_ix").toInt();
-    if (ix == 0) {
+    if (ix == 0 || e.tagName() == "effectgroup") {
+       if (e.tagName() == "effectgroup") {
+           // dropped a group on another group
+           QDomNodeList pastedEffects = e.elementsByTagName("effect");
+           if (pastedEffects.isEmpty() || m_subWidgets.isEmpty()) {
+               // Buggy groups, should not happen
+               event->ignore();
+               return;
+           }
+           QList <int> pastedEffectIndexes;
+           QList <int> currentEffectIndexes;
+           EffectInfo pasteInfo;
+           pasteInfo.fromString(pastedEffects.at(0).toElement().attribute("kdenlive_info"));
+           if (pasteInfo.groupIndex == -1) {
+               // Group dropped from effects list, add effect
+               e.setAttribute("kdenlive_ix", m_subWidgets.last()->effectIndex());
+               emit addEffect(e);
+               event->setDropAction(Qt::CopyAction);
+               event->accept();
+               return;
+           }
+           // Moving group
+           for (int i = 0; i < pastedEffects.count(); ++i) {
+               pastedEffectIndexes << pastedEffects.at(i).toElement().attribute("kdenlive_ix").toInt();
+           }
+           for (int i = 0; i < m_subWidgets.count(); ++i) {
+               currentEffectIndexes << m_subWidgets.at(i)->effectIndex();
+           }
+           kDebug()<<"PASTING: "<<pastedEffectIndexes<<" TO "<<currentEffectIndexes;
+           if (pastedEffectIndexes.at(0) < currentEffectIndexes.at(0)) {
+               // Pasting group after current one:
+               emit moveEffect(pastedEffectIndexes, currentEffectIndexes.last(), pasteInfo.groupIndex, pasteInfo.groupName);
+           }
+           else {
+               // Group moved before current one
+               emit moveEffect(pastedEffectIndexes, currentEffectIndexes.first(), pasteInfo.groupIndex, pasteInfo.groupName);
+           }
+           event->setDropAction(Qt::MoveAction);
+           event->accept();
+           return;
+       }
        // effect dropped from effects list, add it
-       e.setAttribute("kdenlive_ix", ix);
+       e.setAttribute("kdenlive_info", m_info.toString());
+       if (!m_subWidgets.isEmpty()) {
+           e.setAttribute("kdenlive_ix", m_subWidgets.at(0)->effectIndex());
+       }
+       emit addEffect(e);
        event->setDropAction(Qt::CopyAction);
        event->accept();
-       emit addEffect(e);
        return;
     }
     if (m_subWidgets.isEmpty()) return;
-    int new_index = m_subWidgets.at(m_subWidgets.count() - 1)->effectIndex();
-    emit moveEffect(ix, new_index, m_index, m_title->text());
+    int new_index = m_subWidgets.last()->effectIndex();
+    emit moveEffect(QList <int> () <<ix, new_index, m_info.groupIndex, m_title->text());
     event->setDropAction(Qt::MoveAction);
     event->accept();
 }
@@ -311,6 +380,7 @@ void CollapsibleGroup::slotRenameGroup()
     for (int j = 0; j < m_subWidgets.count(); j++) {
        m_subWidgets.at(j)->setGroupName(m_title->text());
     }
+    m_info.groupName = m_title->text();
     emit groupRenamed(this);
 }
 
@@ -324,7 +394,7 @@ QDomDocument CollapsibleGroup::effectsData()
 {
     QMutexLocker lock(&m_mutex);
     QDomDocument doc;
-    QDomElement list = doc.createElement("list");
+    QDomElement list = doc.createElement("effectgroup");
     list.setAttribute("name", m_title->text());
     doc.appendChild(list);
     for (int j = 0; j < m_subWidgets.count(); j++) {
@@ -333,3 +403,12 @@ QDomDocument CollapsibleGroup::effectsData()
     return doc;
 }
 
+void CollapsibleGroup::adjustEffects()
+{
+    for (int i = 0; i < m_subWidgets.count(); ++i) {
+       m_subWidgets.at(i)->adjustButtons(i, m_subWidgets.count());
+    }
+}
+
+
+#include "collapsiblegroup.moc"