Fix subtitle model used start time as index - caused issues if a subtitle if...

Fix subtitle model used start time as index - caused issues if a subtitle if moved after another one. Add start/end position control in subtitle widget
parent 380315e3
......@@ -284,40 +284,30 @@ GenTime SubtitleModel::stringtoTime(QString &str)
return pos;
}
void SubtitleModel::addSubtitle(int id, GenTime start, GenTime end, const QString str, bool temporary)
bool SubtitleModel::addSubtitle(int id, GenTime start, GenTime end, const QString str, bool temporary)
{
if (start.frames(pCore->getCurrentFps()) < 0 || end.frames(pCore->getCurrentFps()) < 0) {
qDebug()<<"Time error: is negative";
return;
return false;
}
if (start.frames(pCore->getCurrentFps()) > end.frames(pCore->getCurrentFps())) {
qDebug()<<"Time error: start should be less than end";
return;
return false;
}
//Q_ASSERT(model->m_subtitleList.count(start)==0); //returns warning if sub at start time position already exists ,i.e. count !=0
if (m_subtitleList[start].first == str) {
// Don't allow 2 subtitles at same start pos
if (m_subtitleList.count(start) > 0) {
qDebug()<<"already present in model"<<"string :"<<m_subtitleList[start].first<<" start time "<<start.frames(pCore->getCurrentFps())<<"end time : "<< m_subtitleList[start].second.frames(pCore->getCurrentFps());
return;
return false;
}
/*if (model->m_subtitleList.count(start) > 0) {
qDebug()<<"Start time already in model";
editSubtitle(start, str, end);
return;
}*/
auto it= m_subtitleList.lower_bound(start); // returns the key and its value *just* greater than start.
//Q_ASSERT(it->first < model->m_subtitleList.end()->second.second); // returns warning if added subtitle start time is less than last subtitle's end time
int insertRow= static_cast<int>(m_subtitleList.size());//converts the returned unsigned size() to signed int
/* For adding it in the middle of the list */
if (it != m_subtitleList.end()) { // check if the subtitle greater than added subtitle is not the same as the last one
insertRow = static_cast<int>(std::distance(m_subtitleList.begin(), it));
}
beginInsertRows(QModelIndex(), insertRow, insertRow);
int row = m_timeline->m_allSubtitles.size();
beginInsertRows(QModelIndex(), row, row);
m_subtitleList[start] = {str, end};
m_timeline->registerSubtitle(id, start, temporary);
endInsertRows();
addSnapPoint(start);
addSnapPoint(end);
qDebug()<<"Added to model";
return true;
}
QHash<int, QByteArray> SubtitleModel::roleNames() const
......@@ -338,25 +328,24 @@ QVariant SubtitleModel::data(const QModelIndex& index, int role) const
if (index.row() < 0 || index.row() >= static_cast<int>(m_subtitleList.size()) || !index.isValid()) {
return QVariant();
}
auto it = m_subtitleList.begin();
std::advance(it, index.row());
auto subInfo = m_timeline->getSubtitleIdFromIndex(index.row());
switch (role) {
case Qt::DisplayRole:
case Qt::EditRole:
case SubtitleRole:
return it->second.first;
case IdRole:
return getIdForStartPos(it->first);
case StartPosRole:
return it->first.seconds();
case EndPosRole:
return it->second.second.seconds();
case StartFrameRole:
return it->first.frames(pCore->getCurrentFps());
case EndFrameRole:
return it->second.second.frames(pCore->getCurrentFps());
case SelectedRole:
return m_selected.contains(getIdForStartPos(it->first));
case Qt::DisplayRole:
case Qt::EditRole:
case SubtitleRole:
return m_subtitleList.at(subInfo.second).first;
case IdRole:
return subInfo.first;
case StartPosRole:
return subInfo.second.seconds();
case EndPosRole:
return m_subtitleList.at(subInfo.second).second.seconds();
case StartFrameRole:
return subInfo.second.frames(pCore->getCurrentFps());
case EndFrameRole:
return m_subtitleList.at(subInfo.second).second.frames(pCore->getCurrentFps());
case SelectedRole:
return m_selected.contains(subInfo.first);
}
return QVariant();
}
......@@ -468,20 +457,19 @@ bool SubtitleModel::cutSubtitle(int position, Fun &undo, Fun &redo)
if (res) {
int id = TimelineModel::getNextId();
Fun local_redo = [this, id, pos, end, text]() {
addSubtitle(id, pos, end, text);
return true;
return addSubtitle(id, pos, end, text);
};
Fun local_undo = [this, id]() {
removeSubtitle(id);
return true;
};
local_redo();
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
} else {
undo();
if (local_redo()) {
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
}
}
}
undo();
return false;
}
......@@ -493,7 +481,6 @@ void SubtitleModel::registerSnap(const std::weak_ptr<SnapInterface> &snapModel)
m_regSnaps.push_back(snapModel);
// we now add the already existing subtitles to the snap
for (const auto &subtitle : m_subtitleList) {
qDebug() << " REGISTERING SUBTITLE: " << subtitle.first.frames(pCore->getCurrentFps());
ptr->addPoint(subtitle.first.frames(pCore->getCurrentFps()));
}
} else {
......@@ -535,9 +522,10 @@ void SubtitleModel::editEndPos(GenTime startPos, GenTime newEndPos, bool refresh
//is not present in model only
return;
}
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
m_subtitleList[startPos].second = newEndPos;
// Trigger update of the qml view
int id = getIdForStartPos(startPos);
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), {EndFrameRole});
if (refreshModel) {
emit modelChanged();
......@@ -545,6 +533,20 @@ void SubtitleModel::editEndPos(GenTime startPos, GenTime newEndPos, bool refresh
qDebug()<<startPos.frames(pCore->getCurrentFps())<<m_subtitleList[startPos].second.frames(pCore->getCurrentFps());
}
bool SubtitleModel::requestResize(int id, int size, bool right)
{
Fun undo = []() { return true; };
Fun redo = []() { return true; };
bool res = requestResize(id, size, right, undo, redo, true);
if (res) {
pCore->pushUndo(undo, redo, i18n("Resize subtitle"));
return true;
} else {
undo();
return false;
}
}
bool SubtitleModel::requestResize(int id, int size, bool right, Fun &undo, Fun &redo, bool logUndo)
{
Q_ASSERT(m_timeline->m_allSubtitles.find( id ) != m_timeline->m_allSubtitles.end());
......@@ -554,44 +556,63 @@ bool SubtitleModel::requestResize(int id, int size, bool right, Fun &undo, Fun &
Fun reverse = []() { return true; };
if (right) {
GenTime newEndPos = startPos + GenTime(size, pCore->getCurrentFps());
operation = [this, startPos, endPos, newEndPos, logUndo]() {
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
operation = [this, id, startPos, endPos, newEndPos, logUndo]() {
m_subtitleList[startPos].second = newEndPos;
removeSnapPoint(endPos);
addSnapPoint(newEndPos);
// Trigger update of the qml view
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), {EndFrameRole});
if (logUndo) {
emit modelChanged();
if (endPos > newEndPos) {
pCore->refreshProjectRange({newEndPos.frames(pCore->getCurrentFps()), endPos.frames(pCore->getCurrentFps())});
} else {
pCore->refreshProjectRange({endPos.frames(pCore->getCurrentFps()), newEndPos.frames(pCore->getCurrentFps())});
}
}
return true;
};
reverse = [this, startPos, endPos, newEndPos, logUndo]() {
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
reverse = [this, id, startPos, endPos, newEndPos, logUndo]() {
m_subtitleList[startPos].second = endPos;
removeSnapPoint(newEndPos);
addSnapPoint(endPos);
// Trigger update of the qml view
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), {EndFrameRole});
if (logUndo) {
emit modelChanged();
if (endPos > newEndPos) {
pCore->refreshProjectRange({newEndPos.frames(pCore->getCurrentFps()), endPos.frames(pCore->getCurrentFps())});
} else {
pCore->refreshProjectRange({endPos.frames(pCore->getCurrentFps()), newEndPos.frames(pCore->getCurrentFps())});
}
}
return true;
};
} else {
GenTime newStartPos = endPos - GenTime(size, pCore->getCurrentFps());
if (m_subtitleList.count(newStartPos) > 0) {
// There already is another subtitle at this position, abort
return false;
}
const QString text = m_subtitleList.at(startPos).first;
operation = [this, id, startPos, newStartPos, endPos, text, logUndo]() {
m_timeline->m_allSubtitles[id] = newStartPos;
m_subtitleList.erase(startPos);
m_subtitleList[newStartPos] = {text, endPos};
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(newStartPos)));
// Trigger update of the qml view
removeSnapPoint(startPos);
addSnapPoint(newStartPos);
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), {StartFrameRole});
if (logUndo) {
emit modelChanged();
if (startPos > newStartPos) {
pCore->refreshProjectRange({newStartPos.frames(pCore->getCurrentFps()), startPos.frames(pCore->getCurrentFps())});
} else {
pCore->refreshProjectRange({startPos.frames(pCore->getCurrentFps()), newStartPos.frames(pCore->getCurrentFps())});
}
}
return true;
};
......@@ -601,11 +622,16 @@ bool SubtitleModel::requestResize(int id, int size, bool right, Fun &undo, Fun &
m_subtitleList[startPos] = {text, endPos};
removeSnapPoint(newStartPos);
addSnapPoint(startPos);
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
// Trigger update of the qml view
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), {StartFrameRole});
if (logUndo) {
emit modelChanged();
if (startPos > newStartPos) {
pCore->refreshProjectRange({newStartPos.frames(pCore->getCurrentFps()), startPos.frames(pCore->getCurrentFps())});
} else {
pCore->refreshProjectRange({startPos.frames(pCore->getCurrentFps()), newStartPos.frames(pCore->getCurrentFps())});
}
}
return true;
};
......@@ -626,10 +652,11 @@ void SubtitleModel::editSubtitle(GenTime startPos, QString newSubtitleText, GenT
return;
}
qDebug()<<"Editing existing subtitle in model";
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
m_subtitleList[startPos].first = newSubtitleText ;
m_subtitleList[startPos].second = endPos;
int id = getIdForStartPos(startPos);
qDebug()<<startPos.frames(pCore->getCurrentFps())<<m_subtitleList[startPos].first<<m_subtitleList[startPos].second.frames(pCore->getCurrentFps());
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), QVector<int>() << SubtitleRole);
emit modelChanged();
return;
......@@ -648,7 +675,7 @@ bool SubtitleModel::removeSubtitle(int id, bool temporary)
return false;
}
GenTime end = m_subtitleList.at(start).second;
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(start)));
int row = m_timeline->getSubtitleIndex(id);
m_timeline->deregisterSubtitle(id, temporary);
beginRemoveRows(QModelIndex(), row, row);
m_subtitleList.erase(start);
......@@ -666,17 +693,23 @@ void SubtitleModel::removeAllSubtitles()
}
}
void SubtitleModel::moveSubtitle(GenTime oldPos, GenTime newPos, bool updateModel, bool updateView)
bool SubtitleModel::moveSubtitle(int subId, GenTime newPos, bool updateModel, bool updateView)
{
qDebug()<<"Moving Subtitle";
if (m_subtitleList.count(oldPos) <= 0) {
//is not present in model only
return;
if (m_timeline->m_allSubtitles.count(subId) == 0) {
return false;
}
GenTime oldPos = m_timeline->m_allSubtitles.at(subId);
if (m_subtitleList.count(oldPos) <= 0 || m_subtitleList.count(newPos) > 0) {
//is not present in model, or already another one at new position
qDebug()<<"==== MOVE FAILED";
return false;
}
QString subtitleText = m_subtitleList[oldPos].first ;
removeSnapPoint(oldPos);
removeSnapPoint(m_subtitleList[oldPos].second);
GenTime endPos = m_subtitleList[oldPos].second + (newPos - oldPos);
GenTime duration = m_subtitleList[oldPos].second - oldPos;
GenTime endPos = newPos + duration;
int id = getIdForStartPos(oldPos);
m_timeline->m_allSubtitles[id] = newPos;
m_subtitleList.erase(oldPos);
......@@ -685,11 +718,17 @@ void SubtitleModel::moveSubtitle(GenTime oldPos, GenTime newPos, bool updateMode
addSnapPoint(endPos);
if (updateView) {
updateSub(id, {StartFrameRole, EndFrameRole});
if (oldPos < newPos) {
pCore->refreshProjectRange({oldPos.frames(pCore->getCurrentFps()), endPos.frames(pCore->getCurrentFps())});
} else {
pCore->refreshProjectRange({newPos.frames(pCore->getCurrentFps()), (oldPos + duration).frames(pCore->getCurrentFps())});
}
}
if (updateModel) {
// Trigger update of the subtitle file
emit modelChanged();
}
return true;
}
int SubtitleModel::getIdForStartPos(GenTime startTime) const
......@@ -858,21 +897,13 @@ void SubtitleModel::jsontoSubtitle(const QString &data, QString updatedFileName)
void SubtitleModel::updateSub(int id, QVector <int> roles)
{
GenTime startPos = m_timeline->m_allSubtitles.at(id);
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
// Trigger update of the qml view
qDebug()<<"=== UPDATING ROLE FOR ROW: "<<row;
int row = m_timeline->getSubtitleIndex(id);
emit dataChanged(index(row), index(row), roles);
}
int SubtitleModel::getRowForId(int id) const
{
if (m_timeline->m_allSubtitles.find( id ) == m_timeline->m_allSubtitles.end()) {
return -1;
}
GenTime startPos = m_timeline->m_allSubtitles.at(id);
int row = static_cast<int>(std::distance(m_subtitleList.begin(), m_subtitleList.find(startPos)));
return row;
return m_timeline->getSubtitleIndex(id);
}
int SubtitleModel::getSubtitlePlaytime(int id) const
......@@ -888,7 +919,6 @@ void SubtitleModel::setSelected(int id, bool select)
} else {
m_selected.removeAll(id);
}
qDebug()<<"=== SELECTING: "<<id<<"="<<select;
updateSub(id, {SelectedRole});
}
......
......@@ -55,7 +55,7 @@ public:
enum { SubtitleRole = Qt::UserRole + 1, StartPosRole, EndPosRole, StartFrameRole, EndFrameRole, IdRole, SelectedRole };
/** @brief Function that parses through a subtitle file */
void addSubtitle(int id, GenTime start,GenTime end, const QString str, bool temporary = false);
bool addSubtitle(int id, GenTime start,GenTime end, const QString str, bool temporary = false);
/** @brief Converts string of time to GenTime */
GenTime stringtoTime(QString &str);
/** @brief Return model data item according to the role passed */
......@@ -80,6 +80,7 @@ public:
@param pos defines the new position of the end time
*/
void editEndPos(GenTime startPos, GenTime newEndPos, bool refreshModel = true);
bool requestResize(int id, int size, bool right);
bool requestResize(int id, int size, bool right, Fun &undo, Fun &redo, bool logUndo);
/** @brief Edit subtitle , i.e. text and/or end time
......@@ -99,10 +100,10 @@ public:
void updateSub(int id, QVector <int> roles);
/** @brief Move an existing subtitle
@param oldPos is original start position of subtitle
@param subId is the subtitle's ID
@param newPos is new start position of subtitle
*/
void moveSubtitle(GenTime oldPos, GenTime newPos, bool updateModel, bool updateView);
bool moveSubtitle(int subId, GenTime newPos, bool updateModel, bool updateView);
/** @brief Function that imports a subtitle file */
void importSubtitle(const QString filePath, int offset = 0, bool externalImport = false);
......
......@@ -188,6 +188,12 @@ void Core::initGUI(const QUrl &Url, const QString &clipsToLoad)
connect(m_mixerWidget, &MixerManager::updateRecVolume, m_capture.get(), &MediaCapture::setAudioVolume);
m_monitorManager = new MonitorManager(this);
connect(m_monitorManager, &MonitorManager::cleanMixer, m_mixerWidget, &MixerManager::clearMixers);
connect(m_subtitleWidget, &SubtitleEdit::addSubtitle, [this]() {
if (m_guiConstructed && m_mainWindow->getCurrentTimeline()->controller()) {
m_mainWindow->getCurrentTimeline()->controller()->addSubtitle();
}
});
// Producer queue, creating MLT::Producers on request
/*
m_producerQueue = new ProducerQueue(m_binController);
......
......@@ -133,7 +133,7 @@ void ClipCreationDialog::createColorClip(KdenliveDoc *doc, const QString &parent
dia->setWindowTitle(i18n("Color Clip"));
dia_ui.clip_name->setText(i18n("Color Clip"));
QScopedPointer<TimecodeDisplay> t(new TimecodeDisplay(doc->timecode()));
QScopedPointer<TimecodeDisplay> t(new TimecodeDisplay(doc->timecode(), dia.get()));
t->setValue(KdenliveSettings::color_duration());
dia_ui.clip_durationBox->addWidget(t.data());
dia_ui.clip_color->setColor(KdenliveSettings::colorclipcolor());
......
......@@ -25,6 +25,7 @@
#include "core.h"
#include "kdenlivesettings.h"
#include "timecodedisplay.h"
#include "klocalizedstring.h"
#include "QTextEdit"
......@@ -59,16 +60,48 @@ SubtitleEdit::SubtitleEdit(QWidget *parent)
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setupUi(this);
buttonApply->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply")));
buttonAdd->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
auto *keyFilter = new ShiftEnterFilter(this);
subText->installEventFilter(keyFilter);
connect(keyFilter, &ShiftEnterFilter::triggerUpdate, this, &SubtitleEdit::updateSubtitle);
connect(subText, &QPlainTextEdit::textChanged, [this]() {
buttonApply->setEnabled(true);
});
m_position = new TimecodeDisplay(pCore->timecode(), this);
m_endPosition = new TimecodeDisplay(pCore->timecode(), this);
m_duration = new TimecodeDisplay(pCore->timecode(), this);
m_position->setEnabled(false);
m_endPosition->setEnabled(false);
m_duration->setEnabled(false);
position_box->addWidget(m_position);
end_box->addWidget(m_endPosition);
duration_box->addWidget(m_duration);
connect(m_position, &TimecodeDisplay::timeCodeEditingFinished, [this] (int value) {
if (buttonApply->isEnabled()) {
updateSubtitle();
}
GenTime duration = m_endPos - GenTime(value, pCore->getCurrentFps());
m_model->requestResize(m_activeSub, duration.frames(pCore->getCurrentFps()), false);
});
connect(m_endPosition, &TimecodeDisplay::timeCodeEditingFinished, [this] (int value) {
if (buttonApply->isEnabled()) {
updateSubtitle();
}
GenTime duration = GenTime(value, pCore->getCurrentFps()) - m_startPos;
m_model->requestResize(m_activeSub, duration.frames(pCore->getCurrentFps()), true);
});
connect(m_duration, &TimecodeDisplay::timeCodeEditingFinished, [this] (int value) {
if (buttonApply->isEnabled()) {
updateSubtitle();
}
m_model->requestResize(m_activeSub, value, true);
});
connect(buttonAdd, &QToolButton::clicked, this, &SubtitleEdit::addSubtitle);
connect(buttonApply, &QToolButton::clicked, this, &SubtitleEdit::updateSubtitle);
connect(buttonPrev, &QToolButton::clicked, this, &SubtitleEdit::goToPrevious);
connect(buttonNext, &QToolButton::clicked, this, &SubtitleEdit::goToNext);
sub_list->setVisible(false);
}
void SubtitleEdit::setModel(std::shared_ptr<SubtitleModel> model)
......@@ -82,8 +115,10 @@ void SubtitleEdit::setModel(std::shared_ptr<SubtitleModel> model)
subText->clear();
} else {
connect(m_model.get(), &SubtitleModel::dataChanged, [this](const QModelIndex &start, const QModelIndex &, const QVector <int>&roles) {
if (m_activeSub > -1 && start.row() == m_model->getRowForId(m_activeSub) && roles.contains(SubtitleModel::SubtitleRole)) {
setActiveSubtitle(m_activeSub);
if (m_activeSub > -1 && start.row() == m_model->getRowForId(m_activeSub)) {
if (roles.contains(SubtitleModel::SubtitleRole) || roles.contains(SubtitleModel::StartFrameRole) || roles.contains(SubtitleModel::EndFrameRole)) {
setActiveSubtitle(m_activeSub);
}
}
});
}
......@@ -103,10 +138,25 @@ void SubtitleEdit::setActiveSubtitle(int id)
subText->setEnabled(true);
buttonApply->setEnabled(false);
QSignalBlocker bk(subText);
m_position->setEnabled(true);
m_endPosition->setEnabled(true);
m_duration->setEnabled(true);
/*QSignalBlocker bk2(m_position);
QSignalBlocker bk3(m_endPosition);
QSignalBlocker bk4(m_duration);*/
subText->setPlainText(m_model->getText(id));
m_startPos = m_model->getStartPosForId(id);
GenTime duration = GenTime(m_model->getSubtitlePlaytime(id), pCore->getCurrentFps());
m_endPos = m_startPos + duration;
m_position->setValue(m_startPos);
m_endPosition->setValue(m_endPos);
m_duration->setValue(duration);
} else {
subText->setEnabled(false);
buttonApply->setEnabled(false);
m_position->setEnabled(false);
m_endPosition->setEnabled(false);
m_duration->setEnabled(false);
QSignalBlocker bk(subText);
subText->clear();
}
......
......@@ -28,6 +28,7 @@
class SubtitleModel;
class TimecodeDisplay;
class ShiftEnterFilter : public QObject
{
......@@ -66,7 +67,14 @@ private slots:
private:
std::shared_ptr<SubtitleModel> m_model;
int m_activeSub;
TimecodeDisplay *m_position;
TimecodeDisplay *m_endPosition;
TimecodeDisplay *m_duration;
GenTime m_startPos;
GenTime m_endPos;
signals:
void addSubtitle();
};
#endif
......@@ -144,7 +144,11 @@ void TimecodeDisplay::mouseReleaseEvent(QMouseEvent *e)
void TimecodeDisplay::wheelEvent(QWheelEvent *e)
{
QAbstractSpinBox::wheelEvent(e);
clearFocus();
if (hasFocus()) {
clearFocus();
} else {
slotEditingFinished();
}
}
void TimecodeDisplay::enterEvent(QEvent *e)
......
......@@ -1089,16 +1089,11 @@ bool TimelineModel::requestSubtitleMove(int clipId, int position, bool updateVie
QWriteLocker locker(&m_lock);
GenTime oldPos = m_allSubtitles.at(clipId);
GenTime newPos(position, pCore->getCurrentFps());
int min = qMin(oldPos.frames(pCore->getCurrentFps()), newPos.frames(pCore->getCurrentFps()));
Fun local_redo = [this, oldPos, newPos, min, logUndo, updateView]() {
m_subtitleModel->moveSubtitle(oldPos, newPos, logUndo, updateView);
//pCore->refreshProjectRange({min, oldStartFrame + duration});
return true;
Fun local_redo = [this, clipId, newPos, logUndo, updateView]() {
return m_subtitleModel->moveSubtitle(clipId, newPos, logUndo, updateView);
};
Fun local_undo = [this, oldPos, newPos, min, logUndo, updateView]() {
m_subtitleModel->moveSubtitle(newPos, oldPos, logUndo, updateView);
//pCore->refreshProjectRange({min, oldStartFrame + duration});
return true;
Fun local_undo = [this, oldPos, clipId, logUndo, updateView]() {
return m_subtitleModel->moveSubtitle(clipId, oldPos, logUndo, updateView);
};
bool res = local_redo();
if (res) {
......@@ -1174,6 +1169,7 @@ int TimelineModel::suggestSubtitleMove(int subId, int position, int cursorPositi
if (currentPos == position) {
return position;
}
int newPos = position;
if (snapDistance > 0) {
std::vector<int> ignored_pts;
// For snapping, we must ignore all in/outs of the clips of the group being moved
......@@ -1201,11 +1197,13 @@ int TimelineModel::suggestSubtitleMove(int subId, int position, int cursorPositi
int snapped = getBestSnapPos(currentPos, position - currentPos, ignored_pts, cursorPosition, snapDistance);
qDebug() << "Starting suggestion " << position << currentPos << "snapped to " << snapped << ", SND: "<<snapDistance;
if (snapped >= 0) {
position = snapped;
newPos = snapped;
}
}
//m_subtitleModel->moveSubtitle(GenTime(currentPos, pCore->getCurrentFps()), GenTime(position, pCore->getCurrentFps()));
requestSubtitleMove(subId, position, true, false);
if (requestSubtitleMove(subId, newPos, true, false)) {
return newPos;
}
return position;
}
......@@ -2241,13 +2239,13 @@ bool TimelineModel::requestGroupMove(int itemId, int groupId, int delta_track, i
GenTime deltaTime(delta_pos, pCore->getCurrentFps());
redo_subs = [this, deltaTime, sorted_subtitles, finalMove, updateView]() {
for (auto &item : sorted_subtitles) {
m_subtitleModel->moveSubtitle(item.second, item.second + deltaTime, finalMove, updateView);
m_subtitleModel->moveSubtitle(item.first, item.second + deltaTime, finalMove, updateView);
}
return true;
};
undo_subs = [this, deltaTime, sorted_subtitles, finalMove, updateView]() {
undo_subs = [this, sorted_subtitles, finalMove, updateView]() {
for (auto &item : sorted_subtitles) {
m_subtitleModel->moveSubtitle(item.second + deltaTime, item.second, finalMove, updateView);
m_subtitleModel->moveSubtitle(item.first, item.second, finalMove, updateView);
}
return true;
};
......@@ -3635,7 +3633,7 @@ void TimelineModel::registerClip(const std::shared_ptr<ClipModel> &clip, bool re
void TimelineModel::registerSubtitle(int id, GenTime startTime, bool temporary)
{
Q_ASSERT(m_allSubtitles.count(id) == 0);
m_allSubtitles[id] = startTime;
m_allSubtitles.emplace(id, startTime);
if (!temporary) {
m_groups->createGroupItem(id);
}
......@@ -5206,3 +5204,22 @@ void TimelineModel::setSubModel(std::shared_ptr<SubtitleModel> model)
m_subtitleModel = std::move(model);
m_subtitleModel->registerSnap(std::static_pointer_cast<SnapInterface>(m_snaps));
}
int TimelineModel::getSubtitleIndex(int subId) const
{
if (m_allSubtitles.count(subId) == 0) {
return -1;
}
auto it = m_allSubtitles.find(subId);
return std::distance( m_allSubtitles.begin(), it);
}