From e93cb83c1deb2c8130c17650da3fc7c176094d19 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Fri, 14 Aug 2009 22:04:01 +0000 Subject: [PATCH] Fix various effects related crashes (don't store effects in QList, but use QDomDocument instead) svn path=/trunk/kdenlive/; revision=3819 --- src/clipitem.cpp | 38 ++++++++-------- src/clipitem.h | 6 +-- src/customtrackview.cpp | 72 +++++++++++++++--------------- src/effectslist.cpp | 92 ++++++++++++++++++++++++++++----------- src/effectslist.h | 18 ++++++-- src/effectslistview.cpp | 2 +- src/effectslistview.h | 2 +- src/effectslistwidget.cpp | 20 ++++----- src/effectslistwidget.h | 4 +- src/effectstackedit.cpp | 52 +++++++++------------- src/effectstackedit.h | 13 ++---- src/effectstackview.cpp | 20 ++++++--- src/effectstackview.h | 2 +- src/mainwindow.cpp | 15 ++----- src/mainwindow.h | 2 +- 15 files changed, 196 insertions(+), 162 deletions(-) diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 0da8da39..58934f05 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -135,7 +135,7 @@ ClipItem *ClipItem::clone(ItemInfo info) const if (info.cropStart + (info.endPos - info.startPos) == m_cropStart + m_cropDuration) duplicate->slotSetEndThumb(m_endPix); } //kDebug() << "// CLoning clip: " << (info.cropStart + (info.endPos - info.startPos)).frames(m_fps) << ", CURRENT end: " << (cropStart() + duration()).frames(m_fps); - duplicate->setEffectList(m_effectList.clone()); + duplicate->setEffectList(m_effectList); duplicate->setVideoOnly(m_videoOnly); duplicate->setAudioOnly(m_audioOnly); //duplicate->setSpeed(m_speed); @@ -144,12 +144,12 @@ ClipItem *ClipItem::clone(ItemInfo info) const void ClipItem::setEffectList(const EffectsList effectList) { - m_effectList = effectList; + m_effectList.clone(effectList); m_effectNames = m_effectList.effectNames().join(" / "); if (!m_effectList.isEmpty()) setSelectedEffect(0); } -const EffectsList ClipItem::effectList() +const EffectsList ClipItem::effectList() const { return m_effectList; } @@ -1150,7 +1150,7 @@ void ClipItem::resizeEnd(int posx, double /*speed*/, bool updateKeyFrames) void ClipItem::checkEffectsKeyframesPos(const int previous, const int current, bool fromStart) { - for (int i = 0; i < m_effectList.size(); i++) { + for (int i = 0; i < m_effectList.count(); i++) { QDomElement effect = m_effectList.at(i); QDomNodeList params = effect.elementsByTagName("parameter"); for (int j = 0; j < params.count(); j++) { @@ -1263,7 +1263,7 @@ int ClipItem::effectsCounter() int ClipItem::effectsCount() { - return m_effectList.size(); + return m_effectList.count(); } int ClipItem::hasEffect(const QString &tag, const QString &id) const @@ -1276,10 +1276,10 @@ QStringList ClipItem::effectNames() return m_effectList.effectNames(); } -QDomElement ClipItem::effectAt(int ix) +QDomElement ClipItem::effectAt(int ix) const { - if (ix > m_effectList.count() - 1 || ix < 0) return QDomElement(); - return m_effectList.at(ix); + if (ix > m_effectList.count() - 1 || ix < 0 || m_effectList.at(ix).isNull()) return QDomElement(); + return m_effectList.at(ix).cloneNode().toElement(); } void ClipItem::setEffectAt(int ix, QDomElement effect) @@ -1303,15 +1303,10 @@ void ClipItem::setEffectAt(int ix, QDomElement effect) } } -EffectsParameterList ClipItem::addEffect(QDomElement effect, bool animate) +EffectsParameterList ClipItem::addEffect(const QDomElement effect, bool animate) { - bool needRepaint = false; - /*QDomDocument doc; - doc.appendChild(doc.importNode(effect, true)); - kDebug() << "/////// CLIP ADD EFFECT: " << doc.toString();*/ m_effectList.append(effect); - EffectsParameterList parameters; parameters.addParam("tag", effect.attribute("tag")); parameters.addParam("kdenlive_ix", effect.attribute("kdenlive_ix")); @@ -1462,7 +1457,7 @@ void ClipItem::deleteEffect(QString index) bool needRepaint = false; QString ix; - for (int i = 0; i < m_effectList.size(); ++i) { + for (int i = 0; i < m_effectList.count(); ++i) { ix = m_effectList.at(i).attribute("kdenlive_ix"); if (ix == index) { QString effectId = m_effectList.at(i).attribute("id"); @@ -1478,7 +1473,7 @@ void ClipItem::deleteEffect(QString index) m_effectList.removeAt(i); i--; } else if (ix.toInt() > index.toInt()) { - m_effectList[i].setAttribute("kdenlive_ix", ix.toInt() - 1); + m_effectList.item(i).setAttribute("kdenlive_ix", ix.toInt() - 1); } } m_effectNames = m_effectList.effectNames().join(" / "); @@ -1534,12 +1529,15 @@ GenTime ClipItem::endPos() const //virtual void ClipItem::dropEvent(QGraphicsSceneDragDropEvent * event) { - QString effects = QString(event->mimeData()->data("kdenlive/effectslist")); + const QString effects = QString(event->mimeData()->data("kdenlive/effectslist")); QDomDocument doc; doc.setContent(effects, true); - QDomElement e = doc.documentElement(); - CustomTrackView *view = (CustomTrackView *) scene()->views()[0]; - if (view) view->slotAddEffect(e, m_startPos, track()); + const QDomElement e = doc.documentElement(); + if (scene() && !scene()->views().isEmpty()) { + event->accept(); + CustomTrackView *view = (CustomTrackView *) scene()->views()[0]; + if (view) view->slotAddEffect(e, m_startPos, track()); + } } //virtual diff --git a/src/clipitem.h b/src/clipitem.h index 8d0feafd..5e69f84d 100644 --- a/src/clipitem.h +++ b/src/clipitem.h @@ -57,13 +57,13 @@ public: void setClipName(const QString &name); QDomElement xml() const; ClipItem *clone(ItemInfo info) const; - const EffectsList effectList(); + const EffectsList effectList() const; void setFadeOut(int pos); void setFadeIn(int pos); /** Give a string list of the clip's effect names */ QStringList effectNames(); /** Add an effect to the clip and return the parameters that will be passed to Mlt */ - EffectsParameterList addEffect(QDomElement effect, bool animate = true); + EffectsParameterList addEffect(const QDomElement effect, bool animate = true); /** Get the effect parameters that will be passed to Mlt */ EffectsParameterList getEffectArgs(QDomElement effect); /** Delete effect with id index */ @@ -73,7 +73,7 @@ public: /** return a unique effect id */ int effectsCounter(); /** return the xml of effect at index ix in stack */ - QDomElement effectAt(int ix); + QDomElement effectAt(int ix) const; /** Replace effect at pos ix with given value */ void setEffectAt(int ix, QDomElement effect); void flashClip(); diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 30247dbb..1bb87a2d 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -618,7 +618,6 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) } m_blockRefresh = true; - m_dragItem = NULL; m_dragGuide = NULL; bool collision = false; @@ -663,9 +662,15 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) // Find first clip, transition or group under mouse (when no guides selected) int ct = 0; AbstractGroupItem *dragGroup = NULL; + AbstractClipItem *collisionClip = NULL; + bool found = false; while (!m_dragGuide && ct < collisionList.count()) { if (collisionList.at(ct)->type() == AVWIDGET || collisionList.at(ct)->type() == TRANSITIONWIDGET) { - m_dragItem = static_cast (collisionList.at(ct)); + collisionClip = static_cast (collisionList.at(ct)); + if (collisionClip == m_dragItem) { + collisionClip = NULL; + } else m_dragItem = collisionClip; + found = true; m_dragItemInfo = m_dragItem->info(); if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET && m_dragItem->parentItem() != m_selectionGroup) { // kDebug()<<"// KLIK FOUND GRP: "<sceneBoundingRect(); @@ -675,6 +680,7 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) } ct++; } + if (!found) m_dragItem = NULL; if (m_dragItem && m_dragItem->type() == TRANSITIONWIDGET) { // update transition menu action @@ -773,7 +779,6 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) m_operationMode = SPACER; } else setCursorPos((int)(mapToScene(event->x(), 0).x())); QGraphicsView::mousePressEvent(event); - kDebug() << "END mousePress EVENT "; return; } @@ -825,16 +830,13 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) } } - if (m_dragItem->type() == AVWIDGET && !m_dragItem->isItemLocked()) emit clipItemSelected((ClipItem*) m_dragItem); - else emit clipItemSelected(NULL); - bool itemSelected = false; if (m_dragItem->isSelected()) itemSelected = true; else if (m_dragItem->parentItem() && m_dragItem->parentItem()->isSelected()) itemSelected = true; else if (dragGroup && dragGroup->isSelected()) itemSelected = true; if (event->modifiers() == Qt::ControlModifier || itemSelected == false) { - resetSelectionGroup(); if (event->modifiers() != Qt::ControlModifier) m_scene->clearSelection(); + resetSelectionGroup(); dragGroup = NULL; if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET) { //kDebug()<<"// KLIK FOUND GRP: "<sceneBoundingRect(); @@ -850,6 +852,14 @@ void CustomTrackView::mousePressEvent(QMouseEvent * event) m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1); } + if (collisionClip != NULL || m_dragItem == NULL) { + if (m_dragItem && m_dragItem->type() == AVWIDGET && !m_dragItem->isItemLocked()) { + kDebug() << "//////// CLIP ITEM SELECTED, TRANSMITTING . . . . . . ."; + ClipItem *selected = static_cast (m_dragItem); + emit clipItemSelected(selected); + } else emit clipItemSelected(NULL); + } + // If clicked item is selected, allow move if (event->modifiers() != Qt::ControlModifier && m_operationMode == NONE/* && (m_dragItem->isSelected() || (dragGroup && dragGroup->isSelected()))*/) QGraphicsView::mousePressEvent(event); @@ -1026,7 +1036,6 @@ void CustomTrackView::groupSelectedItems(bool force, bool createNewGroup) void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) { - kDebug() << "++++++++++++ DBL CLK"; if (m_dragItem && m_dragItem->hasKeyFrames()) { if (m_moveOpMode == KEYFRAME) { // user double clicked on a keyframe, open edit dialog @@ -1039,7 +1048,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) if (d.exec() == QDialog::Accepted) { int pos = m_document->timecode().getFrameCount(view.kfr_position->text()); m_dragItem->updateKeyFramePos(GenTime(pos, m_document->fps()) + m_dragItem->cropStart(), (double) view.kfr_value->value() * m_dragItem->keyFrameFactor()); - ClipItem *item = (ClipItem *)m_dragItem; + ClipItem *item = static_cast (m_dragItem); QString previous = item->keyframes(item->selectedEffectIndex()); item->updateKeyframeEffect(); QString next = item->keyframes(item->selectedEffectIndex()); @@ -1053,7 +1062,7 @@ void CustomTrackView::mouseDoubleClickEvent(QMouseEvent *event) // add keyframe GenTime keyFramePos = GenTime((int)(mapToScene(event->pos()).x()), m_document->fps()) - m_dragItem->startPos() + m_dragItem->cropStart(); m_dragItem->addKeyFrame(keyFramePos, mapToScene(event->pos()).toPoint().y()); - ClipItem * item = (ClipItem *) m_dragItem; + ClipItem * item = static_cast (m_dragItem); QString previous = item->keyframes(item->selectedEffectIndex()); item->updateKeyframeEffect(); QString next = item->keyframes(item->selectedEffectIndex()); @@ -1313,13 +1322,14 @@ void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect) if (strobe == 0) strobe = 1; doChangeClipSpeed(info, speed, 1.0, strobe, clip->baseClip()->getId()); clip->addEffect(effect); - emit clipItemSelected(clip); + if (clip->isSelected()) emit clipItemSelected(clip); return; } - if (!m_document->renderer()->mltAddEffect(track, pos, clip->addEffect(effect))) + EffectsParameterList params = clip->addEffect(effect); + if (!m_document->renderer()->mltAddEffect(track, pos, params)) emit displayMessage(i18n("Problem adding effect to clip"), ErrorMessage); - emit clipItemSelected(clip); + if (clip->isSelected()) emit clipItemSelected(clip); } else emit displayMessage(i18n("Cannot find clip to add effect"), ErrorMessage); } @@ -1405,14 +1415,14 @@ void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track) int count = 0; if (track == -1) itemList = scene()->selectedItems(); if (itemList.isEmpty()) { - ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, track); + ClipItem *clip = getClipItemAt((int) pos.frames(m_document->fps()), track); if (clip) itemList.append(clip); else emit displayMessage(i18n("Select a clip if you want to apply an effect"), ErrorMessage); } kDebug() << "// REQUESTING EFFECT ON CLIP: " << pos.frames(25) << ", TRK: " << track << "SELECTED ITEMS: " << itemList.count(); for (int i = 0; i < itemList.count(); i++) { if (itemList.at(i)->type() == AVWIDGET) { - ClipItem *item = (ClipItem *)itemList.at(i); + ClipItem *item = static_cast (itemList.at(i)); if (effect.attribute("type") == "audio") { // Don't add audio effects on video clips if (item->isVideoOnly() || (item->clipType() != AUDIO && item->clipType() != AV && item->clipType() != PLAYLIST)) { @@ -1608,8 +1618,7 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut) item->baseClip()->addReference(); m_document->updateClip(item->baseClip()->getId()); setDocumentModified(); - kDebug() << "///////// CUTTING CLIP RESULT: (" << item->startPos().frames(25) << "-" << item->endPos().frames(25) << "), DUP: (" << dup->startPos().frames(25) << "-" << dup->endPos().frames(25) << ")" << ", CUT: " << cutTime.frames(25); - kDebug() << "// CUTTING CLIP dONE"; + //kDebug() << "///////// CUTTING CLIP RESULT: (" << item->startPos().frames(25) << "-" << item->endPos().frames(25) << "), DUP: (" << dup->startPos().frames(25) << "-" << dup->endPos().frames(25) << ")" << ", CUT: " << cutTime.frames(25); } else { // uncut clip @@ -1625,9 +1634,9 @@ void CustomTrackView::cutClip(ItemInfo info, GenTime cutTime, bool cut) return; } - kDebug() << "// UNCUTTING CLIPS: ITEM 1 (" << item->startPos().frames(25) << "x" << item->endPos().frames(25) << ")"; + /*kDebug() << "// UNCUTTING CLIPS: ITEM 1 (" << item->startPos().frames(25) << "x" << item->endPos().frames(25) << ")"; kDebug() << "// UNCUTTING CLIPS: ITEM 2 (" << dup->startPos().frames(25) << "x" << dup->endPos().frames(25) << ")"; - kDebug() << "// UNCUTTING CLIPS, INFO (" << info.startPos.frames(25) << "x" << info.endPos.frames(25) << ") , CUT: " << cutTime.frames(25);; + kDebug() << "// UNCUTTING CLIPS, INFO (" << info.startPos.frames(25) << "x" << info.endPos.frames(25) << ") , CUT: " << cutTime.frames(25);;*/ //deleteClip(dup->info()); @@ -1784,7 +1793,7 @@ void CustomTrackView::deleteTransition(ItemInfo transitionInfo, int endTrack, QD void CustomTrackView::slotTransitionUpdated(Transition *tr, QDomElement old) { - kDebug() << "TRANS UPDATE, TRACKS: " << old.attribute("transition_btrack") << ", NEW: " << tr->toXML().attribute("transition_btrack"); + //kDebug() << "TRANS UPDATE, TRACKS: " << old.attribute("transition_btrack") << ", NEW: " << tr->toXML().attribute("transition_btrack"); EditTransitionCommand *command = new EditTransitionCommand(this, tr->track(), tr->startPos(), old, tr->toXML(), false); m_commandStack->push(command); setDocumentModified(); @@ -1968,7 +1977,6 @@ void CustomTrackView::addTrack(TrackInfo type, int ix) else if (clip->isVideoOnly()) prod = clip->baseClip()->videoProducer(); else prod = clip->baseClip()->producer(clipinfo.track); m_document->renderer()->mltUpdateClipProducer((int)(m_document->tracksCount() - clipinfo.track), clipinfo.startPos.frames(m_document->fps()), prod); - kDebug() << "// UPDATING CLIP TO TRACK PROD: " << clipinfo.track; } } else if (item->type() == TRANSITIONWIDGET) { Transition *tr = static_cast (item); @@ -2446,7 +2454,6 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) bool success = m_document->renderer()->mltMoveClip((int)(m_document->tracksCount() - m_dragItemInfo.track), (int)(m_document->tracksCount() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())), prod); if (success) { - kDebug() << "// get trans info"; int tracknumber = m_document->tracksCount() - item->track() - 1; bool isLocked = m_document->trackInfoAt(tracknumber).isLocked; if (isLocked) item->setItemLocked(true); @@ -2456,7 +2463,6 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) new MoveClipCommand(this, m_dragItemInfo, info, false, moveCommand); // Also move automatic transitions (on lower track) Transition *tr = getTransitionItemAtStart(m_dragItemInfo.startPos, m_dragItemInfo.track); - kDebug() << "// get trans info2"; if (tr && tr->isAutomatic()) { ItemInfo trInfo = tr->info(); ItemInfo newTrInfo = trInfo; @@ -2759,7 +2765,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) //m_document->renderer()->doRefresh(); } else if (m_operationMode == FADEIN) { // resize fade in effect - ClipItem * item = (ClipItem *) m_dragItem; + ClipItem * item = static_cast (m_dragItem); int ix = item->hasEffect("volume", "fadein"); if (ix != -1) { QDomElement oldeffect = item->effectAt(ix).cloneNode().toElement(); @@ -2798,7 +2804,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) } } else if (m_operationMode == FADEOUT) { // resize fade in effect - ClipItem * item = (ClipItem *) m_dragItem; + ClipItem * item = static_cast (m_dragItem); int ix = item->hasEffect("volume", "fadeout"); if (ix != -1) { QDomElement oldeffect = item->effectAt(ix).cloneNode().toElement(); @@ -2840,7 +2846,7 @@ void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) } } else if (m_operationMode == KEYFRAME) { // update the MLT effect - ClipItem * item = (ClipItem *) m_dragItem; + ClipItem * item = static_cast (m_dragItem); QString previous = item->keyframes(item->selectedEffectIndex()); item->updateKeyframeEffect(); QString next = item->keyframes(item->selectedEffectIndex()); @@ -3327,8 +3333,6 @@ void CustomTrackView::moveGroup(QList startClip, QList sta m_selectionGroup->moveBy(offset.frames(m_document->fps()), trackOffset *(qreal) m_tracksHeight); - kDebug() << "%% GRP NEW POS: " << m_selectionGroup->scenePos().x(); - QList children = m_selectionGroup->childItems(); // Expand groups int max = children.count(); @@ -3337,7 +3341,6 @@ void CustomTrackView::moveGroup(QList startClip, QList sta children += children.at(i)->childItems(); } } - kDebug() << "// GRP MOVE; FOUND CHILDREN:" << children.count(); for (int i = 0; i < children.count(); i++) { // re-add items in correct place @@ -3871,7 +3874,6 @@ void CustomTrackView::setScale(double scaleFactor, double verticalScale) void CustomTrackView::slotRefreshGuides() { if (KdenliveSettings::showmarkers()) { - kDebug() << "// refresh GUIDES"; for (int i = 0; i < m_guides.count(); i++) { m_guides.at(i)->update(); } @@ -3976,8 +3978,9 @@ void CustomTrackView::copyClip() } for (int i = 0; i < itemList.count(); i++) { if (itemList.at(i)->type() == AVWIDGET) { - ClipItem *dup = static_cast (itemList.at(i)); - m_copiedItems.append(dup->clone(dup->info())); + ClipItem *clip = static_cast (itemList.at(i)); + ClipItem *clone = clip->clone(clip->info()); + m_copiedItems.append(clone); } else if (itemList.at(i)->type() == TRANSITIONWIDGET) { Transition *dup = static_cast (itemList.at(i)); m_copiedItems.append(dup->clone()); @@ -4097,7 +4100,6 @@ void CustomTrackView::pasteClipEffects() return; } ClipItem *clip = static_cast < ClipItem *>(m_copiedItems.at(0)); - EffectsList effects = clip->effectList(); QUndoCommand *paste = new QUndoCommand(); paste->setText("Paste effects"); @@ -4106,8 +4108,8 @@ void CustomTrackView::pasteClipEffects() for (int i = 0; i < clips.count(); ++i) { if (clips.at(i)->type() == AVWIDGET) { ClipItem *item = static_cast < ClipItem *>(clips.at(i)); - for (int i = 0; i < clip->effectsCount(); i++) { - new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), clip->effectAt(i), true, paste); + for (int j = 0; j < clip->effectsCount(); j++) { + new AddEffectCommand(this, m_document->tracksCount() - item->track(), item->startPos(), clip->effectAt(j), true, paste); } } } diff --git a/src/effectslist.cpp b/src/effectslist.cpp index 3a64e7db..c3f1e0c2 100644 --- a/src/effectslist.cpp +++ b/src/effectslist.cpp @@ -22,9 +22,10 @@ #include -EffectsList::EffectsList() : - QList < QDomElement > () +EffectsList::EffectsList() { + m_baseElement = createElement("list"); + appendChild(m_baseElement); } EffectsList::~EffectsList() @@ -34,8 +35,9 @@ EffectsList::~EffectsList() QDomElement EffectsList::getEffectByName(const QString & name) const { QString effectName; - for (int i = 0; i < size(); ++i) { - QDomElement effect = at(i); + QDomNodeList effects = m_baseElement.childNodes(); + for (int i = 0; i < effects.count(); i++) { + QDomElement effect = effects.at(i).toElement(); QDomNode namenode = effect.elementsByTagName("name").item(0); if (!namenode.isNull()) effectName = i18n(namenode.toElement().text().toUtf8().data()); if (name == effectName) { @@ -54,10 +56,10 @@ QDomElement EffectsList::getEffectByName(const QString & name) const QDomElement EffectsList::getEffectByTag(const QString & tag, const QString & id) const { - - if (!id.isEmpty()) for (int i = 0; i < size(); ++i) { - QDomElement effect = at(i); - //kDebug() << "// SRCH EFFECT; " << id << ", LKING: " << effect.attribute("id"); + QDomNodeList effects = m_baseElement.childNodes(); + for (int i = 0; i < effects.count(); i++) { + QDomElement effect = effects.at(i).toElement(); + if (!id.isEmpty()) { if (effect.attribute("id") == id) { QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { @@ -67,10 +69,7 @@ QDomElement EffectsList::getEffectByTag(const QString & tag, const QString & id) } return effect; } - } - - if (!tag.isEmpty()) for (int i = 0; i < size(); ++i) { - QDomElement effect = at(i); + } else if (!tag.isEmpty()) { if (effect.attribute("tag") == tag) { QDomNodeList params = effect.elementsByTagName("parameter"); for (int i = 0; i < params.count(); i++) { @@ -81,14 +80,15 @@ QDomElement EffectsList::getEffectByTag(const QString & tag, const QString & id) return effect; } } - + } return QDomElement(); } int EffectsList::hasEffect(const QString & tag, const QString & id) const { - for (int i = 0; i < size(); ++i) { - QDomElement effect = at(i); + QDomNodeList effects = m_baseElement.childNodes(); + for (int i = 0; i < effects.count(); i++) { + QDomElement effect = effects.at(i).toElement(); if (!id.isEmpty()) { if (effect.attribute("id") == id) return i; } else if (!tag.isEmpty() && effect.attribute("tag") == tag) return i; @@ -99,7 +99,7 @@ int EffectsList::hasEffect(const QString & tag, const QString & id) const QStringList EffectsList::effectIdInfo(const int ix) const { QStringList info; - QDomElement effect = at(ix); + QDomElement effect = m_baseElement.childNodes().at(ix).toElement(); QDomNode namenode = effect.elementsByTagName("name").item(0); info << i18n(namenode.toElement().text().toUtf8().data()) << effect.attribute("tag") << effect.attribute("id"); return info; @@ -108,8 +108,9 @@ QStringList EffectsList::effectIdInfo(const int ix) const QStringList EffectsList::effectNames() { QStringList list; - for (int i = 0; i < size(); ++i) { - QDomElement effect = at(i); + QDomNodeList effects = m_baseElement.childNodes(); + for (int i = 0; i < effects.count(); i++) { + QDomElement effect = effects.at(i).toElement(); QDomNode namenode = effect.elementsByTagName("name").item(0); if (!namenode.isNull()) list.append(i18n(namenode.toElement().text().toUtf8().data())); } @@ -130,7 +131,7 @@ QString EffectsList::getInfo(const QString & tag, const QString & id) const QString EffectsList::getInfoFromIndex(const int ix) const { QString info; - QDomElement effect = at(ix); + QDomElement effect = m_baseElement.childNodes().at(ix).toElement(); QDomNode namenode = effect.elementsByTagName("description").item(0); if (!namenode.isNull()) info = i18n(namenode.toElement().text().toUtf8().data()); namenode = effect.elementsByTagName("author").item(0); @@ -138,6 +139,7 @@ QString EffectsList::getInfoFromIndex(const int ix) const return info; } +// static bool EffectsList::hasKeyFrames(QDomElement effect) { QDomNodeList params = effect.elementsByTagName("parameter"); @@ -148,13 +150,10 @@ bool EffectsList::hasKeyFrames(QDomElement effect) return false; } -EffectsList EffectsList::clone() const +void EffectsList::clone(const EffectsList original) { - EffectsList list; - for (int i = 0; i < size(); ++i) { - list.append(at(i).cloneNode().toElement()); - } - return list; + setContent(original.toString()); + m_baseElement = documentElement(); } // static @@ -183,3 +182,46 @@ QString EffectsList::parameter(QDomElement effect, const QString &name) return QString(); } +void EffectsList::append(QDomElement e) +{ + m_baseElement.appendChild(importNode(e, true)); +} + +int EffectsList::count() const +{ + return m_baseElement.childNodes().count(); +} + +bool EffectsList::isEmpty() const +{ + return m_baseElement.childNodes().count() == 0; +} + +const QDomElement EffectsList::at(int ix) const +{ + QDomNodeList effects = m_baseElement.childNodes(); + if (ix >= effects.count()) return QDomElement(); + return effects.at(ix).toElement(); +} + +void EffectsList::removeAt(int ix) +{ + QDomNodeList effects = m_baseElement.childNodes(); + if (ix >= effects.count()) return; + m_baseElement.removeChild(effects.at(ix)); +} + +QDomElement EffectsList::item(int ix) +{ + QDomNodeList effects = m_baseElement.childNodes(); + if (ix >= effects.count()) return QDomElement(); + return effects.at(ix).toElement(); +} + +void EffectsList::insert(int ix, QDomElement effect) +{ + QDomNodeList effects = m_baseElement.childNodes(); + if (ix >= effects.count()) m_baseElement.appendChild(effect); + else m_baseElement.insertBefore(effect, effects.at(ix)); +} + diff --git a/src/effectslist.h b/src/effectslist.h index 47ecae1e..2877738a 100644 --- a/src/effectslist.h +++ b/src/effectslist.h @@ -18,8 +18,7 @@ #ifndef EFFECTSLIST_H #define EFFECTSLIST_H -#include -#include +#include /**A List for DocClipBase objects. Use this instead of QList so as to sort lists correctly. * Also contains the ability to set a "master clip", which can be used by a number of operations where @@ -28,7 +27,7 @@ */ -class EffectsList: public QList < QDomElement > +class EffectsList: public QDomDocument { public: EffectsList(); @@ -42,10 +41,21 @@ public: QStringList effectNames(); QString getInfo(const QString & tag, const QString & id) const; QString getInfoFromIndex(const int ix) const; - EffectsList clone() const; + void clone(const EffectsList original); + void append(QDomElement e); + bool isEmpty() const; + int count() const; + const QDomElement at(int ix) const; + void removeAt(int ix); + QDomElement item(int ix); + void insert(int ix, QDomElement effect); static bool hasKeyFrames(QDomElement effect); static void setParameter(QDomElement effect, const QString &name, const QString &value); static QString parameter(QDomElement effect, const QString &name); + +private: + QDomElement m_baseElement; + }; #endif diff --git a/src/effectslistview.cpp b/src/effectslistview.cpp index ae9da5a5..0c313cf3 100644 --- a/src/effectslistview.cpp +++ b/src/effectslistview.cpp @@ -91,7 +91,7 @@ void EffectsListView::showInfoPanel() void EffectsListView::slotEffectSelected() { - QDomElement effect = m_effectsList->currentEffect().cloneNode().toElement(); + QDomElement effect = m_effectsList->currentEffect(); if (!effect.isNull()) emit addEffect(effect); } diff --git a/src/effectslistview.h b/src/effectslistview.h index f8002cd0..e95d2137 100644 --- a/src/effectslistview.h +++ b/src/effectslistview.h @@ -55,7 +55,7 @@ private slots: public slots: signals: - void addEffect(QDomElement); + void addEffect(const QDomElement); void reloadEffects(); }; diff --git a/src/effectslistwidget.cpp b/src/effectslistwidget.cpp index f9f10fec..f5ae91b8 100644 --- a/src/effectslistwidget.cpp +++ b/src/effectslistwidget.cpp @@ -93,12 +93,12 @@ void EffectsListWidget::initList() } } -QDomElement EffectsListWidget::currentEffect() +const QDomElement EffectsListWidget::currentEffect() const { return itemEffect(currentItem()); } -QDomElement EffectsListWidget::itemEffect(QListWidgetItem *item) +const QDomElement EffectsListWidget::itemEffect(QListWidgetItem *item) const { QDomElement effect; if (!item) return effect; @@ -106,13 +106,13 @@ QDomElement EffectsListWidget::itemEffect(QListWidgetItem *item) kDebug() << "// EFFECT SELECTED: " << effectInfo; switch (item->data(TypeRole).toInt()) { case 1: - effect = MainWindow::videoEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)); + effect = MainWindow::videoEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)).cloneNode().toElement(); break; case 2: - effect = MainWindow::audioEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)); + effect = MainWindow::audioEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)).cloneNode().toElement(); break; default: - effect = MainWindow::customEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)); + effect = MainWindow::customEffects.getEffectByTag(effectInfo.at(0), effectInfo.at(1)).cloneNode().toElement(); break; } return effect; @@ -165,7 +165,7 @@ void EffectsListWidget::mouseMoveEvent(QMouseEvent *event) const QList list = selectedItems(); QDomDocument doc; foreach(QListWidgetItem *item, list) { - QDomElement e = itemEffect(item); + const QDomElement e = itemEffect(item); if (!e.isNull()) doc.appendChild(doc.importNode(e, true)); } QByteArray data; @@ -175,17 +175,15 @@ void EffectsListWidget::mouseMoveEvent(QMouseEvent *event) //QPixmap pix = qVariantValue(clickItem->data(Qt::DecorationRole)); //drag->setPixmap(pix); //drag->setHotSpot(QPoint(0, 50)); - drag->start(Qt::MoveAction); + drag->start(Qt::CopyAction); } - //event->accept(); + event->accept(); } } void EffectsListWidget::dragMoveEvent(QDragMoveEvent * event) { - event->setDropAction(Qt::IgnoreAction); - //if (item) { - event->setDropAction(Qt::MoveAction); + event->setDropAction(Qt::CopyAction); if (event->mimeData()->hasText()) { event->acceptProposedAction(); } diff --git a/src/effectslistwidget.h b/src/effectslistwidget.h index 4a08845b..e2a1203c 100644 --- a/src/effectslistwidget.h +++ b/src/effectslistwidget.h @@ -33,9 +33,9 @@ class EffectsListWidget : public KListWidget public: explicit EffectsListWidget(QMenu *menu, QWidget *parent = 0); virtual ~EffectsListWidget(); - QDomElement currentEffect(); + const QDomElement currentEffect() const; QString currentInfo(); - QDomElement itemEffect(QListWidgetItem *item); + const QDomElement itemEffect(QListWidgetItem *item) const; void initList(); protected: diff --git a/src/effectstackedit.cpp b/src/effectstackedit.cpp index 31141b6c..95171d43 100644 --- a/src/effectstackedit.cpp +++ b/src/effectstackedit.cpp @@ -41,23 +41,23 @@ #include -class Boolval: public EffectStackEdit::UiItem, public Ui::Boolval_UI +class Boolval: public QWidget, public Ui::Boolval_UI { }; -class Colorval: public EffectStackEdit::UiItem, public Ui::Colorval_UI +class Colorval: public QWidget, public Ui::Colorval_UI { }; -class Constval: public EffectStackEdit::UiItem, public Ui::Constval_UI +class Constval: public QWidget, public Ui::Constval_UI { }; -class Listval: public EffectStackEdit::UiItem, public Ui::Listval_UI +class Listval: public QWidget, public Ui::Listval_UI { }; -class Wipeval: public EffectStackEdit::UiItem, public Ui::Wipeval_UI +class Wipeval: public QWidget, public Ui::Wipeval_UI { }; @@ -75,7 +75,7 @@ EffectStackEdit::EffectStackEdit(QWidget *parent) : vbox1->setSpacing(0); QScrollArea *area = new QScrollArea; - QWidget *wid = new QWidget(parent); + m_baseWidget = new QWidget(parent); area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); area->setFrameStyle(QFrame::NoFrame); @@ -83,9 +83,9 @@ EffectStackEdit::EffectStackEdit(QWidget *parent) : area->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding)); vbox1->addWidget(area); - area->setWidget(wid); + area->setWidget(m_baseWidget); area->setWidgetResizable(true); - m_vbox = new QVBoxLayout(wid); + m_vbox = new QVBoxLayout(m_baseWidget); m_vbox->setContentsMargins(0, 0, 0, 0); m_vbox->setSpacing(0); //wid->show(); @@ -128,12 +128,12 @@ void EffectStackEdit::updateParameter(const QString &name, const QString &value) void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) { - kDebug() << " + + + +DELETING EFFECT STACK"; clearAllItems(); m_params = d; m_in = in; m_out = out; if (m_params.isNull()) { + kDebug() << "// EMPTY EFFECT STACK"; return; } @@ -148,12 +148,11 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) for (int i = 0; i < namenode.count() ; i++) { - kDebug() << "in form"; QDomElement pa = namenode.item(i).toElement(); QDomNode na = pa.firstChildElement("name"); QString type = pa.attribute("type"); QString paramName = i18n(na.toElement().text().toUtf8().data()); - QWidget * toFillin = new QWidget; + QWidget * toFillin = new QWidget(m_baseWidget); QString value = pa.attribute("value").isNull() ? pa.attribute("default") : pa.attribute("value"); @@ -232,7 +231,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) m_vbox->addWidget(pl); m_valueItems[paramName+"complex"] = pl; connect(pl, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); - m_items.append(pl); } else if (type == "geometry") { Geometryval *geo = new Geometryval(m_profile, m_frameSize); geo->setupParam(pa, minFrame, maxFrame); @@ -240,7 +238,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) m_valueItems[paramName+"geometry"] = geo; connect(geo, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); connect(geo, SIGNAL(seekToPos(int)), this, SLOT(slotSeekToPos(int))); - m_items.append(geo); } else if (type == "keyframe") { // keyframe editor widget kDebug() << "min: " << m_in << ", MAX: " << m_out; @@ -251,7 +248,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) m_vbox->addWidget(geo); m_valueItems[paramName+"keyframe"] = geo; connect(geo, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); - m_items.append(geo); } else if (type == "color") { Colorval *cval = new Colorval; cval->setupUi(toFillin); @@ -275,7 +271,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) m_vbox->addWidget(posedit); m_valueItems[paramName+"position"] = posedit; connect(posedit, SIGNAL(parameterChanged()), this, SLOT(collectAllParameters())); - m_items.append(posedit); } else if (type == "wipe") { Wipeval *wpval = new Wipeval; wpval->setupUi(toFillin); @@ -337,7 +332,6 @@ void EffectStackEdit::transferParamDesc(const QDomElement d, int in, int out) } if (toFillin) { - m_items.append(toFillin); m_vbox->addWidget(toFillin); } } @@ -420,7 +414,6 @@ QString EffectStackEdit::getWipeString(wipeInfo info) void EffectStackEdit::collectAllParameters() { if (m_valueItems.isEmpty() || m_params.isNull()) return; - const QDomElement oldparam = m_params.cloneNode().toElement(); QDomElement newparam = oldparam.cloneNode().toElement(); QDomNodeList namenode = newparam.elementsByTagName("parameter"); @@ -510,7 +503,7 @@ void EffectStackEdit::collectAllParameters() void EffectStackEdit::createSliderItem(const QString& name, int val , int min, int max, const QString suffix) { - QWidget* toFillin = new QWidget; + QWidget* toFillin = new QWidget(m_baseWidget); Constval *ctval = new Constval; ctval->setupUi(toFillin); ctval->horizontalSlider->setMinimum(min); @@ -524,7 +517,6 @@ void EffectStackEdit::createSliderItem(const QString& name, int val , int min, i m_valueItems[name] = ctval; m_uiItems.append(ctval); connect(ctval->horizontalSlider, SIGNAL(valueChanged(int)) , this, SLOT(collectAllParameters())); - m_items.append(toFillin); m_vbox->addWidget(toFillin); } @@ -537,21 +529,17 @@ void EffectStackEdit::clearAllItems() { blockSignals(true); m_valueItems.clear(); - - while (!m_items.isEmpty()) { - QWidget * die = m_items.takeFirst(); + m_uiItems.clear(); + /*while (!m_items.isEmpty()) { + QWidget *die = m_items.takeFirst(); die->disconnect(); delete die; - } - - qDeleteAll(m_uiItems); - m_uiItems.clear(); - m_items.clear(); - QLayoutItem *item = m_vbox->itemAt(0); - while (item) { - m_vbox->removeItem(item); - delete item; - item = m_vbox->itemAt(0); + }*/ + //qDeleteAll(m_uiItems); + QLayoutItem *child; + while ((child = m_vbox->takeAt(0)) != 0) { + if (child->widget()) delete child->widget(); + delete child; } blockSignals(false); } diff --git a/src/effectstackedit.h b/src/effectstackedit.h index 334e4af8..f16ea1ae 100644 --- a/src/effectstackedit.h +++ b/src/effectstackedit.h @@ -50,20 +50,13 @@ public: void updateParameter(const QString &name, const QString &value); void setFrameSize(QPoint p); - class UiItem - { - public: - UiItem() {}; - ~UiItem() {}; - }; - private: void clearAllItems(); QVBoxLayout *m_vbox; - QList m_items; - QList m_uiItems; + QList m_uiItems; + QWidget *m_baseWidget; QDomElement m_params; - QMap m_valueItems; + QMap m_valueItems; void createSliderItem(const QString& name, int val , int min, int max, const QString); wipeInfo getWipeInfo(QString value); QString getWipeString(wipeInfo info); diff --git a/src/effectstackview.cpp b/src/effectstackview.cpp index 33d252b0..c16d0041 100644 --- a/src/effectstackview.cpp +++ b/src/effectstackview.cpp @@ -142,8 +142,10 @@ void EffectStackView::slotClipItemSelected(ClipItem* c, int ix) else ix = 0; } if (m_clipref == NULL) { + m_ui.effectlist->blockSignals(true); m_ui.effectlist->clear(); m_effectedit->transferParamDesc(QDomElement(), 0, 0); + m_ui.effectlist->blockSignals(false); setEnabled(false); return; } @@ -175,7 +177,15 @@ void EffectStackView::setupListView(int ix) QListWidgetItem* item; for (int i = 0; i < m_clipref->effectsCount(); i++) { - QDomElement d = m_clipref->effectAt(i); + const QDomElement d = m_clipref->effectAt(i); + if (d.isNull()) { + kDebug() << " . . . . WARNING, NULL EFFECT IN STACK!!!!!!!!!"; + continue; + } + + /*QDomDocument doc; + doc.appendChild(doc.importNode(d, true)); + kDebug() << "IMPORTED STK: " << doc.toString();*/ QDomNode namenode = d.elementsByTagName("name").item(0); if (!namenode.isNull()) { @@ -194,7 +204,7 @@ void EffectStackView::setupListView(int ix) else item->setCheckState(Qt::Checked); } } - if (m_clipref->effectsCount() == 0) { + if (m_ui.effectlist->count() == 0) { m_ui.buttonDel->setEnabled(false); m_ui.buttonSave->setEnabled(false); m_ui.buttonReset->setEnabled(false); @@ -207,10 +217,10 @@ void EffectStackView::setupListView(int ix) } m_ui.effectlist->blockSignals(false); if (m_ui.effectlist->count() == 0) m_effectedit->transferParamDesc(QDomElement(), 0, 0); - else slotItemSelectionChanged(); + else slotItemSelectionChanged(false); } -void EffectStackView::slotItemSelectionChanged() +void EffectStackView::slotItemSelectionChanged(bool update) { bool hasItem = m_ui.effectlist->currentItem(); int activeRow = m_ui.effectlist->currentRow(); @@ -219,7 +229,7 @@ void EffectStackView::slotItemSelectionChanged() if (hasItem && m_ui.effectlist->currentItem()->isSelected()) { m_effectedit->transferParamDesc(m_clipref->effectAt(activeRow), m_clipref->cropStart().frames(KdenliveSettings::project_fps()), m_clipref->cropDuration().frames(KdenliveSettings::project_fps()));//minx max frame } - if (m_clipref) m_clipref->setSelectedEffect(activeRow); + if (m_clipref && update) m_clipref->setSelectedEffect(activeRow); m_ui.buttonDel->setEnabled(hasItem); m_ui.buttonSave->setEnabled(hasItem); m_ui.buttonReset->setEnabled(hasItem && isChecked); diff --git a/src/effectstackview.h b/src/effectstackview.h index 6d517c98..5227930a 100644 --- a/src/effectstackview.h +++ b/src/effectstackview.h @@ -50,7 +50,7 @@ public slots: void slotUpdateEffectParams(const QDomElement, const QDomElement); private slots: - void slotItemSelectionChanged(); + void slotItemSelectionChanged(bool update = true); void slotItemUp(); void slotItemDown(); void slotItemDel(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c6cb29c2..6d86b82c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -355,7 +355,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, QWidget *parent connect(m_clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool))); //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors())); connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool))); - connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement))); + connect(m_effectList, SIGNAL(addEffect(const QDomElement)), this, SLOT(slotAddEffect(const QDomElement))); connect(m_effectList, SIGNAL(reloadEffects()), this, SLOT(slotReloadEffects())); m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor); @@ -596,14 +596,15 @@ void MainWindow::slotFullScreen() KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked()); } -void MainWindow::slotAddEffect(QDomElement effect, GenTime pos, int track) +void MainWindow::slotAddEffect(const QDomElement effect, GenTime pos, int track) { if (!m_activeDocument) return; if (effect.isNull()) { kDebug() << "--- ERROR, TRYING TO APPEND NULL EFFECT"; return; } - m_activeTimeline->projectView()->slotAddEffect(effect.cloneNode().toElement(), pos, track); + QDomElement effectToAdd = effect.cloneNode().toElement(); + m_activeTimeline->projectView()->slotAddEffect(effectToAdd, pos, track); } void MainWindow::slotRaiseMonitor(bool clipMonitor) @@ -838,19 +839,11 @@ void MainWindow::setupActions() collection->addAction("manage_profiles", profilesAction); connect(profilesAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProfiles())); -#if KDE_IS_VERSION(4,3,63) - KNS::standardAction(i18n("Download New Wipes..."), this, SLOT(slotGetNewLumaStuff()), actionCollection(), QString("get_new_lumas")); - - KNS::standardAction(i18n("Download New Render Profiles..."), this, SLOT(slotGetNewRenderStuff()), actionCollection(), QString("get_new_profiles")); - - KNS::standardAction(i18n("Download New Project Profiles..."), this, SLOT(slotGetNewMltProfileStuff()), actionCollection(), QString("get_new_mlt_profiles")); -#else KNS::standardAction(i18n("Download New Wipes..."), this, SLOT(slotGetNewLumaStuff()), actionCollection(), "get_new_lumas"); KNS::standardAction(i18n("Download New Render Profiles..."), this, SLOT(slotGetNewRenderStuff()), actionCollection(), "get_new_profiles"); KNS::standardAction(i18n("Download New Project Profiles..."), this, SLOT(slotGetNewMltProfileStuff()), actionCollection(), "get_new_mlt_profiles"); -#endif KAction* wizAction = new KAction(KIcon("configure"), i18n("Run Config Wizard"), this); collection->addAction("run_wizard", wizAction); diff --git a/src/mainwindow.h b/src/mainwindow.h index cf2cff91..1abc23ca 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -224,7 +224,7 @@ private slots: void slotRaiseMonitor(bool clipMonitor); void slotUpdateClip(const QString &id); void slotUpdateMousePosition(int pos); - void slotAddEffect(QDomElement effect, GenTime pos = GenTime(), int track = -1); + void slotAddEffect(const QDomElement effect, GenTime pos = GenTime(), int track = -1); void slotEditProfiles(); void slotDetectAudioDriver(); void slotEditProjectSettings(); -- 2.39.2