X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fkeyframeedit.cpp;h=ac367215b7b24a7cbb69165db0642431fc45f708;hb=1404e8f1d631c81399e0e92ffce7dfac0195fabb;hp=1e4502198b81a9b6d1abd4b8408f3929f2e0ee6c;hpb=713204e803e323a6a6e8eb2b49ab6d3d5a3b780c;p=kdenlive diff --git a/src/keyframeedit.cpp b/src/keyframeedit.cpp index 1e450219..ac367215 100644 --- a/src/keyframeedit.cpp +++ b/src/keyframeedit.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - geomeytrval.cpp - description + keyframedit.cpp - description ------------------- begin : 03 Aug 2008 copyright : (C) 2008 by Marco Gittler @@ -17,6 +17,7 @@ #include "keyframeedit.h" #include "doubleparameterwidget.h" +#include "positionedit.h" #include "kdenlivesettings.h" #include @@ -24,48 +25,65 @@ #include -KeyframeEdit::KeyframeEdit(QDomElement e, int minFrame, int maxFrame, int minVal, int maxVal, Timecode tc, int active_keyframe, QWidget* parent) : - QWidget(parent), - m_min(minFrame), - m_max(maxFrame), - m_minVal(minVal), - m_maxVal(maxVal), - m_timecode(tc), - m_previousPos(0), - m_active_keyframe(active_keyframe) +KeyframeEdit::KeyframeEdit(const QDomElement &e, int minFrame, int maxFrame, const Timecode &tc, int activeKeyframe, QWidget* parent) : + QWidget(parent), + m_min(minFrame), + m_max(maxFrame), + m_timecode(tc) { - kDebug() << " / / / /MODIFIED KFR: " << m_active_keyframe; setupUi(this); - m_params.append(e.cloneNode().toElement()); + if (m_max == -1) { + // special case: keyframe for tracks, do not allow keyframes + widgetTable->setHidden(true); + } keyframe_list->setFont(KGlobalSettings::generalFont()); - keyframe_seek->setChecked(KdenliveSettings::keyframeseek()); - connect(keyframe_seek, SIGNAL(stateChanged(int)), this, SLOT(slotSetSeeking(int))); + buttonSeek->setChecked(KdenliveSettings::keyframeseek()); + connect(buttonSeek, SIGNAL(toggled(bool)), this, SLOT(slotSetSeeking(bool))); + buttonKeyframes->setIcon(KIcon("chronometer")); button_add->setIcon(KIcon("list-add")); button_add->setToolTip(i18n("Add keyframe")); button_delete->setIcon(KIcon("list-remove")); button_delete->setToolTip(i18n("Delete keyframe")); + buttonResetKeyframe->setIcon(KIcon("edit-undo")); + buttonSeek->setIcon(KIcon("insert-link")); connect(keyframe_list, SIGNAL(itemSelectionChanged()), this, SLOT(slotAdjustKeyframeInfo())); - connect(keyframe_list, SIGNAL(cellChanged(int, int)), this, SLOT(slotGenerateParams(int, int))); - setupParam(); + connect(keyframe_list, SIGNAL(cellChanged(int,int)), this, SLOT(slotGenerateParams(int,int))); + + m_position = new PositionEdit(i18n("Position"), 0, 0, 1, tc, widgetTable); + ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 3, 0, 1, -1); + m_slidersLayout = new QGridLayout(param_sliders); + //m_slidersLayout->setSpacing(0); + + m_slidersLayout->setContentsMargins(0, 0, 0, 0); + m_slidersLayout->setVerticalSpacing(2); + keyframe_list->setSelectionBehavior(QAbstractItemView::SelectRows); + keyframe_list->setSelectionMode(QAbstractItemView::SingleSelection); + addParameter(e, activeKeyframe); keyframe_list->resizeRowsToContents(); - keyframe_list->resizeColumnsToContents(); + //keyframe_list->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); connect(button_delete, SIGNAL(clicked()), this, SLOT(slotDeleteKeyframe())); connect(button_add, SIGNAL(clicked()), this, SLOT(slotAddKeyframe())); - //connect(keyframe_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotSaveCurrentParam(QTreeWidgetItem *, int))); - connect(keyframe_pos, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframePos(int))); - //connect(keyframe_val, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); - keyframe_pos->setPageStep(1); + connect(buttonKeyframes, SIGNAL(clicked()), this, SLOT(slotKeyframeMode())); + connect(buttonResetKeyframe, SIGNAL(clicked()), this, SLOT(slotResetKeyframe())); + connect(m_position, SIGNAL(parameterChanged(int)), this, SLOT(slotAdjustKeyframePos(int))); + + //connect(keyframe_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotSaveCurrentParam(QTreeWidgetItem*,int))); + if (!keyframe_list->currentItem()) { keyframe_list->setCurrentCell(0, 0); keyframe_list->selectRow(0); } // ensure the keyframe list shows at least 3 lines keyframe_list->setMinimumHeight(QFontInfo(keyframe_list->font()).pixelSize() * 9); - /*m_delegate = new KeyItemDelegate(minVal, maxVal); - keyframe_list->setItemDelegate(m_delegate);*/ + + // Do not show keyframe table if only one keyframe exists at the beginning + if (keyframe_list->rowCount() < 2 && getPos(0) == m_min && m_max != -1) + widgetTable->setHidden(true); + else + buttonKeyframes->setHidden(true); } KeyframeEdit::~KeyframeEdit() @@ -79,27 +97,37 @@ KeyframeEdit::~KeyframeEdit() if (wid) delete wid; } - //delete m_delegate; } -void KeyframeEdit::addParameter(QDomElement e) +void KeyframeEdit::addParameter(const QDomElement &e, int activeKeyframe) { keyframe_list->blockSignals(true); m_params.append(e.cloneNode().toElement()); - QDomNode na = e.firstChildElement("name"); - QString paramName = i18n(na.toElement().text().toUtf8().data()); + + QDomElement na = e.firstChildElement("name"); + QString paramName = i18n(na.text().toUtf8().data()); + QDomElement commentElem = e.firstChildElement("comment"); + QString comment; + if (!commentElem.isNull()) + comment = i18n(commentElem.text().toUtf8().data()); + int columnId = keyframe_list->columnCount(); keyframe_list->insertColumn(columnId); keyframe_list->setHorizontalHeaderItem(columnId, new QTableWidgetItem(paramName)); DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, 0, - m_params.at(columnId).attribute("min").toInt(), m_params.at(columnId).attribute("max").toInt(), - m_params.at(columnId).attribute("default").toInt(), m_params.at(columnId).attribute("suffix"), this); - connect(doubleparam, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); + m_params.at(columnId).attribute("min").toDouble(), m_params.at(columnId).attribute("max").toDouble(), + m_params.at(columnId).attribute("default").toDouble(), comment, columnId, m_params.at(columnId).attribute("suffix"), m_params.at(columnId).attribute("decimals").toInt(), this); + connect(doubleparam, SIGNAL(valueChanged(double)), this, SLOT(slotAdjustKeyframeValue(double))); + connect(this, SIGNAL(showComments(bool)), doubleparam, SLOT(slotShowComment(bool))); + connect(doubleparam, SIGNAL(setInTimeline(int)), this, SLOT(slotUpdateVisibleParameter(int))); m_slidersLayout->addWidget(doubleparam, columnId, 0); + if (e.attribute("intimeline") == "1") { + doubleparam->setInTimelineProperty(true); + } - QStringList frames = e.attribute("keyframes").split(";", QString::SkipEmptyParts); - for (int i = 0; i < frames.count(); i++) { + QStringList frames = e.attribute("keyframes").split(';', QString::SkipEmptyParts); + for (int i = 0; i < frames.count(); ++i) { int frame = frames.at(i).section(':', 0, 0).toInt(); bool found = false; int j; @@ -119,49 +147,13 @@ void KeyframeEdit::addParameter(QDomElement e) keyframe_list->setItem(j, columnId, new QTableWidgetItem(frames.at(i).section(':', 1, 1))); keyframe_list->resizeRowToContents(j); } - } - keyframe_list->resizeColumnsToContents(); - keyframe_list->blockSignals(false); - slotAdjustKeyframeInfo(false); -} - -void KeyframeEdit::setupParam() -{ - keyframe_list->blockSignals(true); - keyframe_list->clear(); - int col = keyframe_list->columnCount(); - QDomNode na = m_params.at(0).firstChildElement("name"); - QString paramName = i18n(na.toElement().text().toUtf8().data()); - kDebug() << " INSERT COL: " << col << ", " << paramName; - keyframe_list->insertColumn(col); - keyframe_list->setHorizontalHeaderItem(col, new QTableWidgetItem(paramName)); - m_slidersLayout = new QGridLayout(param_sliders); - - DoubleParameterWidget *doubleparam = new DoubleParameterWidget(paramName, 0, - m_params.at(0).attribute("min").toInt(), m_params.at(0).attribute("max").toInt(), - m_params.at(0).attribute("default").toInt(), m_params.at(0).attribute("suffix"), this); - connect(doubleparam, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); - m_slidersLayout->addWidget(doubleparam, 0, 0); - - keyframe_list->setSelectionBehavior(QAbstractItemView::SelectRows); - keyframe_list->setSelectionMode(QAbstractItemView::SingleSelection); - - QStringList frames = m_params.at(0).attribute("keyframes").split(";", QString::SkipEmptyParts); - for (int i = 0; i < frames.count(); i++) { - keyframe_list->insertRow(i); - int currentpos = frames.at(i).section(':', 0, 0).toInt(); - keyframe_list->setVerticalHeaderItem(i, new QTableWidgetItem(getPosString(currentpos))); - keyframe_list->setItem(i, col, new QTableWidgetItem(frames.at(i).section(':', 1, 1))); - if ((m_active_keyframe > -1) && (m_active_keyframe == currentpos)) { - keyframe_list->setCurrentCell(i, 0); + if ((activeKeyframe > -1) && (activeKeyframe == frame)) { + keyframe_list->setCurrentCell(i, columnId); keyframe_list->selectRow(i); } - //item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled); } - /*QTreeWidgetItem *first = keyframe_list->topLevelItem(0); - if (first) keyframe_list->setCurrentItem(first);*/ + keyframe_list->resizeColumnsToContents(); keyframe_list->blockSignals(false); - //keyframe_list->setCurrentCell(0, 0); slotAdjustKeyframeInfo(false); button_delete->setEnabled(keyframe_list->rowCount() > 1); } @@ -177,7 +169,12 @@ void KeyframeEdit::slotDeleteKeyframe() keyframe_list->setCurrentCell(row, col); keyframe_list->selectRow(row); generateAllParams(); - button_delete->setEnabled(keyframe_list->rowCount() > 1); + + bool disable = keyframe_list->rowCount() < 2; + button_delete->setEnabled(!disable); + disable &= getPos(0) == m_min; + widgetTable->setHidden(disable); + buttonKeyframes->setHidden(!disable); } void KeyframeEdit::slotAddKeyframe() @@ -190,29 +187,33 @@ void KeyframeEdit::slotAddKeyframe() int pos1 = getPos(row); int result; - kDebug() << "// ADD KF: " << row << ", MAX: " << keyframe_list->rowCount() << ", POS: " << pos1; if (row < (keyframe_list->rowCount() - 1)) { result = pos1 + (getPos(row + 1) - pos1) / 2; newrow++; } else if (row == 0) { if (pos1 == m_min) { - result = m_max - 1; + result = m_max; newrow++; } else { result = m_min; } } else { - int pos2 = getPos(row - 1); - result = pos2 + (pos1 - pos2) / 2; + if (pos1 < m_max) { + // last keyframe selected and it is not at end of clip -> add keyframe at the end + result = m_max; + newrow++; + } else { + int pos2 = getPos(row - 1); + result = pos2 + (pos1 - pos2) / 2; + } } keyframe_list->insertRow(newrow); keyframe_list->setVerticalHeaderItem(newrow, new QTableWidgetItem(getPosString(result))); - for (int i = 0; i < keyframe_list->columnCount(); i++) + for (int i = 0; i < keyframe_list->columnCount(); ++i) keyframe_list->setItem(newrow, i, new QTableWidgetItem(keyframe_list->item(item->row(), i)->text())); keyframe_list->resizeRowsToContents(); - //keyframe_list->resizeRowToContents(newrow); slotAdjustKeyframeInfo(); keyframe_list->blockSignals(false); generateAllParams(); @@ -233,7 +234,7 @@ void KeyframeEdit::slotGenerateParams(int row, int column) int pos = getPos(row); if (pos <= m_min) pos = m_min; - if (pos > m_max) + if (m_max != -1 && pos > m_max) pos = m_max; QString val = getPosString(pos); if (val != keyframe_list->verticalHeaderItem(row)->text()) @@ -241,13 +242,14 @@ void KeyframeEdit::slotGenerateParams(int row, int column) for (int col = 0; col < keyframe_list->horizontalHeader()->count(); col++) { item = keyframe_list->item(row, col); + if (!item) continue; int v = item->text().toInt(); if (v >= m_params.at(col).attribute("max").toInt()) item->setText(m_params.at(col).attribute("max")); if (v <= m_params.at(col).attribute("min").toInt()) item->setText(m_params.at(col).attribute("min")); QString keyframes; - for (int i = 0; i < keyframe_list->rowCount(); i++) { + for (int i = 0; i < keyframe_list->rowCount(); ++i) { if (keyframe_list->item(i, col)) keyframes.append(QString::number(getPos(i)) + ':' + keyframe_list->item(i, col)->text() + ';'); } @@ -265,7 +267,7 @@ void KeyframeEdit::slotGenerateParams(int row, int column) int pos = getPos(row); if (pos <= m_min) pos = m_min; - if (pos > m_max) + if (m_max != -1 && pos > m_max) pos = m_max; /*QList duplicates = keyframe_list->findItems(val, Qt::MatchExactly, 0); duplicates.removeAll(item); @@ -285,7 +287,7 @@ void KeyframeEdit::slotGenerateParams(int row, int column) slotAdjustKeyframeInfo(false); QString keyframes; - for (int i = 0; i < keyframe_list->rowCount(); i++) { + for (int i = 0; i < keyframe_list->rowCount(); ++i) { if (keyframe_list->item(i, column)) keyframes.append(QString::number(getPos(i)) + ':' + keyframe_list->item(i, column)->text() + ';'); } @@ -297,7 +299,7 @@ void KeyframeEdit::generateAllParams() { for (int col = 0; col < keyframe_list->columnCount(); col++) { QString keyframes; - for (int i = 0; i < keyframe_list->rowCount(); i++) { + for (int i = 0; i < keyframe_list->rowCount(); ++i) { if (keyframe_list->item(i, col)) keyframes.append(QString::number(getPos(i)) + ':' + keyframe_list->item(i, col)->text() + ';'); } @@ -311,7 +313,6 @@ const QString KeyframeEdit::getValue(const QString &name) for (int col = 0; col < keyframe_list->columnCount(); col++) { QDomNode na = m_params.at(col).firstChildElement("name"); QString paramName = i18n(na.toElement().text().toUtf8().data()); - kDebug() << paramName << " == " << name; if (paramName == name) return m_params.at(col).attribute("keyframes"); } @@ -332,24 +333,25 @@ void KeyframeEdit::slotAdjustKeyframeInfo(bool seek) if (below) max = getPos(below->row()) - 1; - keyframe_pos->blockSignals(true); - keyframe_pos->setRange(min, max); - keyframe_pos->setValue(getPos(item->row())); - keyframe_pos->blockSignals(false); + m_position->blockSignals(true); + m_position->setRange(min, max, true); + m_position->setPosition(getPos(item->row())); + m_position->blockSignals(false); + for (int col = 0; col < keyframe_list->columnCount(); col++) { DoubleParameterWidget *doubleparam = static_cast (m_slidersLayout->itemAtPosition(col, 0)->widget()); if (!doubleparam) continue; doubleparam->blockSignals(true); if (keyframe_list->item(item->row(), col)) { - doubleparam->setValue(keyframe_list->item(item->row(), col)->text().toInt()); + doubleparam->setValue(keyframe_list->item(item->row(), col)->text().toDouble()); } else { kDebug() << "Null pointer exception caught: http://www.kdenlive.org/mantis/view.php?id=1771"; } doubleparam->blockSignals(false); } if (KdenliveSettings::keyframeseek() && seek) - emit seekToPos(keyframe_pos->value() - m_min); + emit seekToPos(m_position->getPosition() - m_min); } void KeyframeEdit::slotAdjustKeyframePos(int value) @@ -361,16 +363,18 @@ void KeyframeEdit::slotAdjustKeyframePos(int value) emit seekToPos(value - m_min); } -void KeyframeEdit::slotAdjustKeyframeValue(int /*value*/) +void KeyframeEdit::slotAdjustKeyframeValue(double value) { + Q_UNUSED(value) + QTableWidgetItem *item = keyframe_list->currentItem(); for (int col = 0; col < keyframe_list->columnCount(); col++) { DoubleParameterWidget *doubleparam = static_cast (m_slidersLayout->itemAtPosition(col, 0)->widget()); if (!doubleparam) continue; - int val = doubleparam->getValue(); + double val = doubleparam->getValue(); QTableWidgetItem *nitem = keyframe_list->item(item->row(), col); - if (nitem->text().toInt() != val) + if (nitem && nitem->text().toDouble() != val) nitem->setText(QString::number(val)); } //keyframe_list->item(item->row() - 1, item->column()); @@ -379,6 +383,8 @@ void KeyframeEdit::slotAdjustKeyframeValue(int /*value*/) int KeyframeEdit::getPos(int row) { + if (!keyframe_list->verticalHeaderItem(row)) + return 0; if (KdenliveSettings::frametimecode()) return keyframe_list->verticalHeaderItem(row)->text().toInt(); else @@ -393,9 +399,9 @@ QString KeyframeEdit::getPosString(int pos) return m_timecode.getTimecodeFromFrames(pos); } -void KeyframeEdit::slotSetSeeking(int state) +void KeyframeEdit::slotSetSeeking(bool seek) { - KdenliveSettings::setKeyframeseek(state == Qt::Checked); + KdenliveSettings::setKeyframeseek(seek); } void KeyframeEdit::updateTimecodeFormat() @@ -407,10 +413,70 @@ void KeyframeEdit::updateTimecodeFormat() else keyframe_list->verticalHeaderItem(row)->setText(m_timecode.getTimecodeFromFrames(pos.toInt())); } + + m_position->updateTimecodeFormat(); +} + +void KeyframeEdit::slotKeyframeMode() +{ + widgetTable->setHidden(false); + buttonKeyframes->setHidden(true); + slotAddKeyframe(); +} + +void KeyframeEdit::slotResetKeyframe() +{ + for (int col = 0; col < keyframe_list->columnCount(); ++col) { + DoubleParameterWidget *doubleparam = static_cast(m_slidersLayout->itemAtPosition(col, 0)->widget()); + if (doubleparam) + doubleparam->slotReset(); + } } -/*void KeyframeEdit::slotSaveCurrentParam(QTreeWidgetItem *item, int column) +void KeyframeEdit::slotUpdateVisibleParameter(int id, bool update) { - if (item && column == 0) m_previousPos = m_timecode.getFrameCount(item->text(0)); -}*/ + for (int i = 0; i < m_params.count(); ++i) { + m_params[i].setAttribute("intimeline", (i == id ? "1" : "0")); + } + for (int col = 0; col < keyframe_list->columnCount(); col++) { + DoubleParameterWidget *doubleparam = static_cast (m_slidersLayout->itemAtPosition(col, 0)->widget()); + if (!doubleparam) + continue; + doubleparam->setInTimelineProperty(col == id); + //kDebug()<<"// PARAM: "<columnCount(); ++col) { + QDomNode na = m_params.at(col).firstChildElement("name"); + QString paramName = i18n(na.toElement().text().toUtf8().data()); + if (paramName == name) + return m_params.at(col).attribute("intimeline") == "1"; + } + return false; +} + +void KeyframeEdit::checkVisibleParam() +{ + if (m_params.count() == 0) + return; + + foreach(const QDomElement &elem, m_params) { + if (elem.attribute("intimeline") == "1") + return; + } + + slotUpdateVisibleParameter(0); +} + +void KeyframeEdit::slotUpdateRange(int inPoint, int outPoint) +{ + m_min = inPoint; + m_max = outPoint; +} +#include "keyframeedit.moc"