X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Feffectstack%2Fcollapsiblegroup.cpp;h=cd5a439fbd6e4fcf8dd3c2261a99ee8691863b14;hb=56aee6aedeeed3efd10ada8fe3c229eddc01ef05;hp=de38ff5dfe5a97aa49cd7b98e50635f2f7a156bf;hpb=2e1eba4e997f5b4c2aa21345968ed0b192e788d1;p=kdenlive diff --git a/src/effectstack/collapsiblegroup.cpp b/src/effectstack/collapsiblegroup.cpp index de38ff5d..cd5a439f 100644 --- a/src/effectstack/collapsiblegroup.cpp +++ b/src/effectstack/collapsiblegroup.cpp @@ -26,11 +26,11 @@ #include #include #include - +#include #include #include -#include +#include #include #include #include @@ -42,27 +42,30 @@ MyEditableLabel::MyEditableLabel(QWidget * parent): { setFrame(false); setReadOnly(true); - setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + 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()); - QHBoxLayout *l = static_cast (framegroup->layout()); + 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")); @@ -74,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())); } @@ -105,76 +112,86 @@ 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(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)) { @@ -182,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() @@ -201,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 @@ -217,6 +236,7 @@ QWidget *CollapsibleGroup::title() const void CollapsibleGroup::addGroupEffect(CollapsibleEffect *effect) { + QMutexLocker lock(&m_mutex); QVBoxLayout *vbox = static_cast(widgetFrame->layout()); if (vbox == NULL) { vbox = new QVBoxLayout(); @@ -226,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); } @@ -237,18 +258,21 @@ 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 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(); } int CollapsibleGroup::groupIndex() const { - return m_index; + return m_info.groupIndex; } bool CollapsibleGroup::isGroup() const @@ -269,39 +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) { - 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 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; } 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 () <text()); event->setDropAction(Qt::MoveAction); event->accept(); } @@ -313,18 +380,21 @@ 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); } QList CollapsibleGroup::effects() { + QMutexLocker lock(&m_mutex); return m_subWidgets; } 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"