X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Feffectstack%2Fcollapsiblegroup.cpp;h=c4824e9fb1f1c3b217e7805723cc8aa52fd14216;hb=c3302003093710ee247ad84c0fe2ef3c579d417f;hp=5fc3a5de7dce61fdb5a0a6484a539dd7a7e11f2e;hpb=c6257befd2f196284231e67cb87e7ca570fe526e;p=kdenlive diff --git a/src/effectstack/collapsiblegroup.cpp b/src/effectstack/collapsiblegroup.cpp index 5fc3a5de..c4824e9f 100644 --- a/src/effectstack/collapsiblegroup.cpp +++ b/src/effectstack/collapsiblegroup.cpp @@ -26,7 +26,7 @@ #include #include #include - +#include #include #include @@ -42,25 +42,30 @@ MyEditableLabel::MyEditableLabel(QWidget * parent): { setFrame(false); setReadOnly(true); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); } void MyEditableLabel::mouseDoubleClickEvent ( QMouseEvent * e ) { setReadOnly(false); selectAll(); + e->accept(); } -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 (); setFont(KGlobalSettings::smallestReadableFont()); + frame->setObjectName("framegroup"); + decoframe->setObjectName("decoframegroup"); QHBoxLayout *l = static_cast (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")); @@ -72,22 +77,26 @@ CollapsibleGroup::CollapsibleGroup(int ix, bool firstGroup, bool lastGroup, QStr if (firstGroup) buttonUp->setVisible(false); if (lastGroup) buttonDown->setVisible(false); m_menu = new QMenu; - m_menu->addAction(KIcon("view-refresh"), i18n("Reset effect"), this, SLOT(slotResetEffect())); - m_menu->addAction(KIcon("document-save"), i18n("Save effect"), this, SLOT(slotSaveEffect())); + 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())); } @@ -103,13 +112,13 @@ 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 ) @@ -119,60 +128,70 @@ void CollapsibleGroup::mouseDoubleClickEvent ( QMouseEvent * 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(widgetFrame->layout()); - if (vbox == NULL) return; - for (int i = 0; i < vbox->count(); i++) { - CollapsibleGroup *e = static_cast(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 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 indexes; + for (int i = 0; i < m_subWidgets.count(); ++i) + indexes << m_subWidgets.at(i)->effectIndex(); + emit changeEffectPosition(indexes, false); } -void CollapsibleGroup::slotSaveEffect() +void CollapsibleGroup::slotSaveGroup() { - QString name = QInputDialog::getText(this, i18n("Save Effect"), i18n("Name for saved effect: ")); + QString name = QInputDialog::getText(this, i18n("Save Group"), i18n("Name for saved group: "), QLineEdit::Normal, m_title->text()); if (name.isEmpty()) return; QString path = KStandardDirs::locateLocal("appdata", "effects/", true); path = path + name + ".xml"; if (QFile::exists(path)) if (KMessageBox::questionYesNo(this, i18n("File %1 already exists.\nDo you want to overwrite it?", path)) == KMessageBox::No) return; - /*TODO - QDomDocument doc; - QDomElement effect = m_effect.cloneNode().toElement(); - doc.appendChild(doc.importNode(effect, true)); - effect = doc.firstChild().toElement(); - effect.removeAttribute("kdenlive_ix"); - effect.setAttribute("id", name); - effect.setAttribute("type", "custom"); - QDomElement effectname = effect.firstChildElement("name"); - effect.removeChild(effectname); - effectname = doc.createElement("name"); - QDomText nametext = doc.createTextNode(name); - effectname.appendChild(nametext); - effect.insertBefore(effectname, QDomNode()); - QDomElement effectprops = effect.firstChildElement("properties"); - effectprops.setAttribute("id", name); - effectprops.setAttribute("type", "custom"); + QDomDocument doc = effectsData(); + QDomElement base = doc.documentElement(); + QDomNodeList effects = base.elementsByTagName("effect"); + 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"); QFile file(path); if (file.open(QFile::WriteOnly | QFile::Truncate)) { @@ -180,12 +199,14 @@ void CollapsibleGroup::slotSaveEffect() out << doc.toString(); } file.close(); - emit reloadEffects();*/ + emit reloadEffects(); } -void CollapsibleGroup::slotResetEffect() +void CollapsibleGroup::slotResetGroup() { - //TODO: emit resetEffect(effectIndex()); + QMutexLocker lock(&m_mutex); + for (int i = 0; i < m_subWidgets.count(); ++i) + m_subWidgets.at(i)->slotResetEffect(); } void CollapsibleGroup::slotSwitch() @@ -199,33 +220,34 @@ 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); } -void CollapsibleGroup::updateGroupIndex(int groupIndex) +QWidget *CollapsibleGroup::title() const { - /*TODO: - m_info.groupIndex = groupIndex; - m_effect.setAttribute("kdenlive_info", m_info.toString()); - emit parameterChanged(m_original_effect, m_effect, effectIndex());*/ + return m_title; } void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect) { + QMutexLocker lock(&m_mutex); QVBoxLayout *vbox = static_cast(widgetFrame->layout()); if (vbox == NULL) { vbox = new QVBoxLayout(); - vbox->setContentsMargins(10, 0, 0, 0); + vbox->setContentsMargins(0, 0, 0, 0); vbox->setSpacing(2); widgetFrame->setLayout(vbox); } effect->setGroupIndex(groupIndex()); + effect->setGroupName(m_title->text()); + effect->decoframe->setObjectName("decoframesub"); + m_subWidgets.append(effect); vbox->addWidget(effect); } @@ -236,25 +258,23 @@ QString CollapsibleGroup::infoString() const void CollapsibleGroup::removeGroup(int ix, QVBoxLayout *layout) { + QMutexLocker lock(&m_mutex); QVBoxLayout *vbox = static_cast(widgetFrame->layout()); if (vbox == NULL) return; - - for (int j = vbox->count() - 1; j >= 0; j--) { - QLayoutItem *child = vbox->takeAt(j); - CollapsibleGroup *e = static_cast(child->widget()); - layout->insertWidget(ix, e); - e->updateGroupIndex(-1); - delete child; + 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(); } int CollapsibleGroup::groupIndex() const { - return m_index; + return m_info.groupIndex; } - - bool CollapsibleGroup::isGroup() const { return true; @@ -273,7 +293,7 @@ void CollapsibleGroup::updateTimecodeFormat() void CollapsibleGroup::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("kdenlive/effectslist")) { - frame->setProperty("active", true); + frame->setProperty("target", true); frame->setStyleSheet(frame->styleSheet()); event->acceptProposedAction(); } @@ -281,13 +301,13 @@ void CollapsibleGroup::dragEnterEvent(QDragEnterEvent *event) void CollapsibleGroup::dragLeaveEvent(QDragLeaveEvent */*event*/) { - frame->setProperty("active", false); + frame->setProperty("target", false); frame->setStyleSheet(frame->styleSheet()); } void CollapsibleGroup::dropEvent(QDropEvent *event) { - frame->setProperty("active", false); + frame->setProperty("target", false); frame->setStyleSheet(frame->styleSheet()); const QString effects = QString::fromUtf8(event->mimeData()->data("kdenlive/effectslist")); //event->acceptProposedAction(); @@ -295,20 +315,60 @@ void CollapsibleGroup::dropEvent(QDropEvent *event) 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 pastedEffectIndexes; + QList 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: "<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; } - int new_index = -1; - QVBoxLayout *vbox = static_cast(widgetFrame->layout()); - if (vbox == NULL) return; - CollapsibleEffect *effect = static_cast(vbox->itemAt(vbox->count() -1)->widget()); - new_index = effect->effectIndex(); - emit moveEffect(ix, new_index, m_index); + if (m_subWidgets.isEmpty()) return; + int new_index = m_subWidgets.last()->effectIndex(); + emit moveEffect(QList () <text()); event->setDropAction(Qt::MoveAction); event->accept(); } @@ -317,17 +377,38 @@ void CollapsibleGroup::slotRenameGroup() { m_title->setReadOnly(true); if (m_title->text().isEmpty()) m_title->setText(i18n("Effect Group")); - QList effects = findChildren(); - for (int j = 0; j < effects.count(); j++) { - effects.at(j)->setGroupName(m_title->text()); + 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); } QList CollapsibleGroup::effects() { - QList result = findChildren(); - return result; + QMutexLocker lock(&m_mutex); + return m_subWidgets; +} + +QDomDocument CollapsibleGroup::effectsData() +{ + QMutexLocker lock(&m_mutex); + QDomDocument doc; + QDomElement list = doc.createElement("effectgroup"); + list.setAttribute("name", m_title->text()); + doc.appendChild(list); + for (int j = 0; j < m_subWidgets.count(); j++) { + list.appendChild(doc.importNode(m_subWidgets.at(j)->effect(), true)); + } + 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"