X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fkeyframeedit.cpp;h=fd70c71aa110d924271994363a1de59d366344d0;hb=ad7ce4d41797792d4552ad264724f29750a858d5;hp=c46de5503bd840352a158f634bc3868fb4d9e082;hpb=c3328ce0388eae40987ed0d4ec32e4673fa6521b;p=kdenlive diff --git a/src/keyframeedit.cpp b/src/keyframeedit.cpp index c46de550..fd70c71a 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 @@ -16,54 +16,74 @@ ***************************************************************************/ #include "keyframeedit.h" +#include "doubleparameterwidget.h" +#include "positionedit.h" #include "kdenlivesettings.h" #include #include #include +#include +#include - -KeyframeEdit::KeyframeEdit(QDomElement e, int minFrame, int maxFrame, int minVal, int maxVal, Timecode tc, int active_keyframe, QWidget* parent) : +KeyframeEdit::KeyframeEdit(QDomElement e, int minFrame, int maxFrame, Timecode tc, int activeKeyframe, 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) + 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(); + m_position = new PositionEdit(i18n("Position"), 0, 0, 1, tc, widgetTable); + ((QGridLayout*)widgetTable->layout())->addWidget(m_position, 3, 0, 1, -1); + + m_showButtons = new QButtonGroup(this); + m_slidersLayout = new QGridLayout(param_sliders); + 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(buttonKeyframes, SIGNAL(clicked()), this, SLOT(slotKeyframeMode())); + connect(buttonResetKeyframe, SIGNAL(clicked()), this, SLOT(slotResetKeyframe())); + connect(m_position, SIGNAL(parameterChanged(int)), this, SLOT(slotAdjustKeyframePos(int))); + connect(m_showButtons, SIGNAL(buttonClicked(int)), this, SLOT(slotUpdateVisibleParameter(int))); + //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); + if (!keyframe_list->currentItem()) { keyframe_list->setCurrentCell(0, 0); keyframe_list->selectRow(0); } - /*m_delegate = new KeyItemDelegate(minVal, maxVal); - keyframe_list->setItemDelegate(m_delegate);*/ + // ensure the keyframe list shows at least 3 lines + keyframe_list->setMinimumHeight(QFontInfo(keyframe_list->font()).pixelSize() * 9); + + // 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() @@ -77,23 +97,40 @@ KeyframeEdit::~KeyframeEdit() if (wid) delete wid; } - //delete m_delegate; } -void KeyframeEdit::addParameter(QDomElement e) +void KeyframeEdit::addParameter(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)); - m_slidersLayout->addWidget(new QLabel(paramName), columnId, 0); - QSlider *sl = new QSlider(Qt::Horizontal, this); - sl->setRange(m_params.at(columnId).attribute("min").toInt(), m_params.at(columnId).attribute("max").toInt()); - connect(sl, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); - m_slidersLayout->addWidget(sl, columnId, 1); + + 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(), comment, m_params.at(columnId).attribute("suffix"), this); + connect(doubleparam, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); + connect(this, SIGNAL(showComments(bool)), doubleparam, SLOT(slotShowComment(bool))); + m_slidersLayout->addWidget(doubleparam, columnId, 0); + + QRadioButton *radio = new QRadioButton(this); + radio->setToolTip(i18n("Show %1 in timeline").arg(paramName)); + m_showButtons->addButton(radio, columnId); + if (e.attribute("intimeline") == "1") + radio->setChecked(true); + + QVBoxLayout *radioLayout = new QVBoxLayout; + radioLayout->addWidget(radio, 0, Qt::AlignTop); + m_slidersLayout->addLayout(radioLayout, columnId, 1); QStringList frames = e.attribute("keyframes").split(";", QString::SkipEmptyParts); for (int i = 0; i < frames.count(); i++) { @@ -116,48 +153,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; - m_slidersLayout->addWidget(new QLabel(paramName), 0, 0); - QSlider *sl = new QSlider(Qt::Horizontal, this); - sl->setRange(m_params.at(0).attribute("min").toInt(), m_params.at(0).attribute("max").toInt()); - connect(sl, SIGNAL(valueChanged(int)), this, SLOT(slotAdjustKeyframeValue(int))); - m_slidersLayout->addWidget(sl, 0, 1); - param_sliders->setLayout(m_slidersLayout); - 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); } @@ -173,7 +175,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() @@ -186,7 +193,6 @@ 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++; @@ -198,8 +204,14 @@ void KeyframeEdit::slotAddKeyframe() result = m_min; } } else { - int pos2 = getPos(row - 1); - result = pos2 + (pos1 - pos2) / 2; + if (pos1 < m_max - 1) { + // last keyframe selected and it is not at end of clip -> add keyframe at the end + result = m_max - 1; + newrow++; + } else { + int pos2 = getPos(row - 1); + result = pos2 + (pos1 - pos2) / 2; + } } keyframe_list->insertRow(newrow); @@ -208,7 +220,6 @@ void KeyframeEdit::slotAddKeyframe() 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(); @@ -229,7 +240,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()) @@ -261,7 +272,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); @@ -307,7 +318,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"); } @@ -328,20 +338,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); + m_position->setPosition(getPos(item->row())); + m_position->blockSignals(false); + for (int col = 0; col < keyframe_list->columnCount(); col++) { - QSlider *sl = static_cast (m_slidersLayout->itemAtPosition(col, 1)->widget()); - if (!sl) + DoubleParameterWidget *doubleparam = static_cast (m_slidersLayout->itemAtPosition(col, 0)->widget()); + if (!doubleparam) continue; - sl->blockSignals(true); - sl->setValue(keyframe_list->item(item->row(), col)->text().toInt()); - sl->blockSignals(false); + doubleparam->blockSignals(true); + if (keyframe_list->item(item->row(), col)) { + doubleparam->setValue(keyframe_list->item(item->row(), col)->text().toInt()); + } 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) @@ -353,16 +368,18 @@ void KeyframeEdit::slotAdjustKeyframePos(int value) emit seekToPos(value - m_min); } -void KeyframeEdit::slotAdjustKeyframeValue(int /*value*/) +void KeyframeEdit::slotAdjustKeyframeValue(int value) { + Q_UNUSED(value); + QTableWidgetItem *item = keyframe_list->currentItem(); for (int col = 0; col < keyframe_list->columnCount(); col++) { - QSlider *sl = static_cast (m_slidersLayout->itemAtPosition(col, 1)->widget()); - if (!sl) + DoubleParameterWidget *doubleparam = static_cast (m_slidersLayout->itemAtPosition(col, 0)->widget()); + if (!doubleparam) continue; - int val = sl->value(); + int val = doubleparam->getValue(); QTableWidgetItem *nitem = keyframe_list->item(item->row(), col); - if (nitem->text().toInt() != val) + if (nitem && nitem->text().toInt() != val) nitem->setText(QString::number(val)); } //keyframe_list->item(item->row() - 1, item->column()); @@ -385,14 +402,72 @@ QString KeyframeEdit::getPosString(int pos) return m_timecode.getTimecodeFromFrames(pos); } -void KeyframeEdit::slotSetSeeking(int state) +void KeyframeEdit::slotSetSeeking(bool seek) +{ + KdenliveSettings::setKeyframeseek(seek); +} + +void KeyframeEdit::updateTimecodeFormat() +{ + for (int row = 0; row < keyframe_list->rowCount(); ++row) { + QString pos = keyframe_list->verticalHeaderItem(row)->text(); + if (KdenliveSettings::frametimecode()) + keyframe_list->verticalHeaderItem(row)->setText(QString::number(m_timecode.getFrameCount(pos))); + 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() { - KdenliveSettings::setKeyframeseek(state == Qt::Checked); + 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::slotUpdateVisibleParameter(int id, bool update) +{ + for (int i = 0; i < m_params.count(); ++i) + m_params[i].setAttribute("intimeline", (i == id ? "1" : "0")); + if (update) emit parameterChanged(); +} -/*void KeyframeEdit::slotSaveCurrentParam(QTreeWidgetItem *item, int column) +bool KeyframeEdit::isVisibleParam(const QString& name) { - if (item && column == 0) m_previousPos = m_timecode.getFrameCount(item->text(0)); -}*/ + 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()); + if (paramName == name) + return m_params.at(col).attribute("intimeline") == "1"; + } + return false; +} + +void KeyframeEdit::checkVisibleParam() +{ + if (m_params.count() == 0) + return; + + foreach(QDomElement elem, m_params) { + if (elem.attribute("intimeline") == "1") + return; + } + + slotUpdateVisibleParameter(0, false); + QRadioButton *radio = static_cast(m_slidersLayout->itemAtPosition(0, 1)->widget()); + if (radio) + radio->setChecked(true); +} +#include "keyframeedit.moc"