#include <KCursor>
#include <KMessageBox>
#include <KIO/NetAccess>
+#include <KFileDialog>
#include <QMouseEvent>
#include <QStylePainter>
// If mouse is at a border of the view, scroll
if (m_moveOpMode != SEEK) return;
if (mapFromScene(m_cursorPos, 0).x() < 3) {
+ if (horizontalScrollBar()->value() == 0) return;
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 2);
QTimer::singleShot(200, this, SLOT(slotCheckPositionScrolling()));
seekCursorPos(mapToScene(QPoint(-2, 0)).x());
else if (dragGroup && dragGroup->isSelected())
itemSelected = true;
- if (event->modifiers() == Qt::ControlModifier || itemSelected == false) {
+ if ((event->modifiers() == Qt::ControlModifier) || itemSelected == false) {
if (event->modifiers() != Qt::ControlModifier) {
resetSelectionGroup(false);
m_scene->clearSelection();
// A refresh seems necessary otherwise in zoomed mode, some clips disappear
viewport()->update();
- } else resetSelectionGroup();
+ } else {
+ resetSelectionGroup();
+ }
dragGroup = NULL;
if (m_dragItem->parentItem() && m_dragItem->parentItem()->type() == GROUPWIDGET) {
dragGroup = static_cast <AbstractGroupItem *>(m_dragItem->parentItem());
}
bool selected = !m_dragItem->isSelected();
- if (dragGroup)
+ /*if (dragGroup)
dragGroup->setSelected(selected);
- else
+ else*/
m_dragItem->setSelected(selected);
-
+ if (selected == false) {
+ m_dragItem = NULL;
+ }
groupSelectedItems();
- ClipItem *clip = static_cast <ClipItem *>(m_dragItem);
- updateClipTypeActions(dragGroup == NULL ? clip : NULL);
- m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
+ if (m_dragItem) {
+ ClipItem *clip = static_cast <ClipItem *>(m_dragItem);
+ updateClipTypeActions(dragGroup == NULL ? clip : NULL);
+ m_pasteEffectsAction->setEnabled(m_copiedItems.count() == 1);
+ }
+ else updateClipTypeActions(NULL);
}
if (collisionClip != NULL || m_dragItem == NULL) {
}
// If clicked item is selected, allow move
- if (event->modifiers() != Qt::ControlModifier && m_operationMode == NONE) QGraphicsView::mousePressEvent(event);
+ //if (!(event->modifiers() | Qt::ControlModifier) && m_operationMode == NONE)
+ QGraphicsView::mousePressEvent(event);
- m_clickPoint = QPoint((int)(mapToScene(event->pos()).x() - m_dragItem->startPos().frames(m_document->fps())), (int)(event->pos().y() - m_dragItem->pos().y()));
+ if (m_dragItem) {
+ m_clickPoint = QPoint((int)(mapToScene(event->pos()).x() - m_dragItem->startPos().frames(m_document->fps())), (int)(event->pos().y() - m_dragItem->pos().y()));
if (m_selectionGroup && m_dragItem->parentItem() == m_selectionGroup) {
// all other modes break the selection, so the user probably wants to move it
m_operationMode = MOVE;
}
else m_operationMode = m_dragItem->operationMode(mapToScene(event->pos()));
}
+ } else m_operationMode = NONE;
m_controlModifier = (event->modifiers() == Qt::ControlModifier);
// Update snap points
pasteInfo.startPos = GenTime(m_cursorPos, m_document->fps());
pasteInfo.endPos = pasteInfo.startPos + info.endPos;
pasteInfo.track = selectedTrack();
- if (!canBePastedTo(pasteInfo, AVWIDGET)) {
+ bool ok = canBePastedTo(pasteInfo, AVWIDGET);
+ if (!ok) {
+ // Cannot be inserted at cursor pos, insert at end of track
+ int duration = m_document->renderer()->mltTrackDuration(m_document->tracksCount() - pasteInfo.track) + 1;
+ pasteInfo.startPos = GenTime(duration, m_document->fps());
+ pasteInfo.endPos = pasteInfo.startPos + info.endPos;
+ ok = canBePastedTo(pasteInfo, AVWIDGET);
+ }
+ if (!ok) {
emit displayMessage(i18n("Cannot insert clip in timeline"), ErrorMessage);
return;
}
// Check if clips can be inserted at that position
for (int i = 0; i < ids.size(); ++i) {
- DocClipBase *clip = m_document->getBaseClip(ids.at(i));
+ QString clipData = ids.at(i);
+ DocClipBase *clip = m_document->getBaseClip(clipData.section('/', 0, 0));
if (clip == NULL) {
kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << ids.at(i);
return false;
}
ItemInfo info;
info.startPos = start;
- info.cropDuration = clip->duration();
- info.endPos = info.startPos + info.cropDuration;
+ if (clipData.contains('/')) {
+ // this is a clip zone, set in / out
+ int in = clipData.section('/', 1, 1).toInt();
+ int out = clipData.section('/', 2, 2).toInt();
+ info.cropStart = GenTime(in, m_document->fps());
+ info.cropDuration = GenTime(out - in, m_document->fps());
+ }
+ else {
+ info.cropDuration = clip->duration();
+ }
+ info.endPos = info.startPos + info.cropDuration;
info.track = track;
infoList.append(info);
- start += clip->duration();
+ start += info.cropDuration;
}
if (!canBePastedTo(infoList, AVWIDGET)) {
return true;
m_selectionGroup = new AbstractGroupItem(m_document->fps());
start = GenTime();
for (int i = 0; i < ids.size(); ++i) {
- DocClipBase *clip = m_document->getBaseClip(ids.at(i));
+ QString clipData = ids.at(i);
+ DocClipBase *clip = m_document->getBaseClip(clipData.section('/', 0, 0));
ItemInfo info;
info.startPos = start;
- info.cropDuration = clip->duration();
- info.endPos = info.startPos + info.cropDuration;
+ if (clipData.contains('/')) {
+ // this is a clip zone, set in / out
+ int in = clipData.section('/', 1, 1).toInt();
+ int out = clipData.section('/', 2, 2).toInt();
+ info.cropStart = GenTime(in, m_document->fps());
+ info.cropDuration = GenTime(out - in, m_document->fps());
+ }
+ else {
+ info.cropDuration = clip->duration();
+ }
+ info.endPos = info.startPos + info.cropDuration;
info.track = 0;
start += info.cropDuration;
offsetList.append(start);
}
}
-void CustomTrackView::slotAddGroupEffect(QDomElement effect, AbstractGroupItem *group)
+void CustomTrackView::slotAddGroupEffect(QDomElement effect, AbstractGroupItem *group, AbstractClipItem *dropTarget)
{
QList<QGraphicsItem *> itemList = group->childItems();
QUndoCommand *effectCommand = new QUndoCommand();
m_commandStack->push(effectCommand);
setDocumentModified();
} else delete effectCommand;
+ if (dropTarget) {
+ clearSelection(false);
+ m_dragItem = dropTarget;
+ m_dragItem->setSelected(true);
+ emit clipItemSelected(static_cast<ClipItem *>(dropTarget));
+ }
}
void CustomTrackView::slotAddEffect(ClipItem *clip, QDomElement effect)
clearSelection(false);
clip->setSelected(true);
m_dragItem = clip;
- emit clipItemSelected(clip);
}
+ emit clipItemSelected(clip);
break;
}
}
}
+ else {
+ for (int i = 0; i < itemList.count(); i++) {
+ if (itemList.at(i)->type() == AVWIDGET) {
+ ClipItem *clip = static_cast<ClipItem *>(itemList.at(i));
+ if (clip->isMainSelectedClip()) {
+ emit clipItemSelected(clip);
+ break;
+ }
+ }
+ }
+ }
} else delete effectCommand;
}
}
-void CustomTrackView::setCursorPos(int pos, bool seek)
+void CustomTrackView::setCursorPos(int pos)
{
if (pos != m_cursorPos) {
emit cursorMoved((int)(m_cursorPos), (int)(pos));
void CustomTrackView::mouseReleaseEvent(QMouseEvent * event)
{
if (m_moveOpMode == SEEK) m_moveOpMode = NONE;
- QGraphicsView::mouseReleaseEvent(event);
+ if (!m_controlModifier) QGraphicsView::mouseReleaseEvent(event);
setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
#if QT_VERSION >= 0x040600
if (m_dragItem) m_dragItem->setGraphicsEffect(NULL);
}
}
-void CustomTrackView::slotAddClipMarker(const QString &id, GenTime t, QString c)
+void CustomTrackView::slotAddClipMarker(const QString &id, CommentedTime newMarker, QUndoCommand *groupCommand)
{
- QString oldcomment = m_document->clipManager()->getClipById(id)->markerComment(t);
- AddMarkerCommand *command = new AddMarkerCommand(this, oldcomment, c, id, t);
- m_commandStack->push(command);
+ CommentedTime oldMarker = m_document->clipManager()->getClipById(id)->markerAt(newMarker.time());
+ if (oldMarker == CommentedTime()) {
+ oldMarker = newMarker;
+ oldMarker.setMarkerType(-1);
+ }
+ AddMarkerCommand *command = new AddMarkerCommand(this, oldMarker, newMarker, id, groupCommand);
+ if (!groupCommand) m_commandStack->push(command);
}
void CustomTrackView::slotDeleteClipMarker(const QString &comment, const QString &id, const GenTime &position)
{
- AddMarkerCommand *command = new AddMarkerCommand(this, comment, QString(), id, position);
+ CommentedTime oldmarker(position, comment);
+ CommentedTime marker = oldmarker;
+ marker.setMarkerType(-1);
+ AddMarkerCommand *command = new AddMarkerCommand(this, oldmarker, marker, id);
m_commandStack->push(command);
}
deleteMarkers->setText("Delete clip markers");
for (int i = 0; i < markers.size(); i++) {
- new AddMarkerCommand(this, markers.at(i).comment(), QString(), id, markers.at(i).time(), deleteMarkers);
+ CommentedTime oldMarker = markers.at(i);
+ CommentedTime marker = oldMarker;
+ marker.setMarkerType(-1);
+ new AddMarkerCommand(this, oldMarker, marker, id, deleteMarkers);
}
m_commandStack->push(deleteMarkers);
}
-void CustomTrackView::addMarker(const QString &id, const GenTime &pos, const QString &comment)
+void CustomTrackView::slotSaveClipMarkers(const QString &id)
+{
+ DocClipBase *base = m_document->clipManager()->getClipById(id);
+ QList < CommentedTime > markers = base->commentedSnapMarkers();
+ if (!markers.isEmpty()) {
+ // Set up categories
+ QComboBox *cbox = new QComboBox;
+ cbox->insertItem(0, i18n("All categories"));
+ for (int i = 0; i < 5; ++i) {
+ cbox->insertItem(i + 1, i18n("Category %1", i));
+ cbox->setItemData(i + 1, CommentedTime::markerColor(i), Qt::DecorationRole);
+ }
+ cbox->setCurrentIndex(0);
+ KFileDialog fd(KUrl("kfiledialog:///projectfolder"), "text/plain", this, cbox);
+ fd.setMode(KFile::File);
+ fd.setOperationMode(KFileDialog::Saving);
+ fd.exec();
+ QString url = fd.selectedFile();
+ //QString url = KFileDialog::getSaveFileName(KUrl("kfiledialog:///projectfolder"), "text/plain", this, i18n("Save markers"));
+ if (url.isEmpty()) return;
+
+ QString data;
+ int category = cbox->currentIndex() - 1;
+ for (int i = 0; i < markers.count(); i++) {
+ if (category >= 0) {
+ // Save only the markers in selected category
+ if (markers.at(i).markerType() != category) continue;
+ }
+ data.append(QString::number(markers.at(i).time().seconds()));
+ data.append("\t");
+ data.append(QString::number(markers.at(i).time().seconds()));
+ data.append("\t");
+ data.append(markers.at(i).comment());
+ data.append("\n");
+ }
+ delete cbox;
+
+ QFile file(url);
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ emit displayMessage(i18n("Cannot open file %1", url), ErrorMessage);
+ return;
+ }
+ file.write(data.toUtf8());
+ file.close();
+ }
+}
+
+void CustomTrackView::slotLoadClipMarkers(const QString &id)
+{
+ QComboBox *cbox = new QComboBox;
+ for (int i = 0; i < 5; ++i) {
+ cbox->insertItem(i, i18n("Category %1", i));
+ cbox->setItemData(i, CommentedTime::markerColor(i), Qt::DecorationRole);
+ }
+ cbox->setCurrentIndex(KdenliveSettings::default_marker_type());
+ KFileDialog fd(KUrl("kfiledialog:///projectfolder"), "text/plain", this, cbox);
+ fd.setMode(KFile::File);
+ fd.setOperationMode(KFileDialog::Opening);
+ fd.exec();
+ QString url = fd.selectedFile();
+
+ //KUrl url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///projectfolder"), "text/plain", this, i18n("Load marker file"));
+ if (url.isEmpty()) return;
+ int category = cbox->currentIndex();
+ delete cbox;
+ QFile file(url);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ emit displayMessage(i18n("Cannot open file %1", KUrl(url).fileName()), ErrorMessage);
+ return;
+ }
+ QString data = QString::fromUtf8(file.readAll());
+ file.close();
+ QStringList lines = data.split("\n", QString::SkipEmptyParts);
+ QStringList values;
+ bool ok;
+ QUndoCommand *command = new QUndoCommand();
+ command->setText("Load markers");
+ QString markerText;
+ foreach(QString line, lines) {
+ markerText.clear();
+ values = line.split("\t", QString::SkipEmptyParts);
+ double time1 = values.at(0).toDouble(&ok);
+ double time2 = -1;
+ if (!ok) continue;
+ if (values.count() >1) {
+ time2 = values.at(1).toDouble(&ok);
+ if (values.count() == 2) {
+ // Check if second value is a number or text
+ if (!ok) {
+ time2 = -1;
+ markerText = values.at(1);
+ }
+ else markerText = i18n("Marker");
+ }
+ else {
+ // We assume 3 values per line: in out name
+ if (!ok) {
+ // 2nd value is not a number, drop
+ }
+ else {
+ markerText = values.at(2);
+ }
+ }
+ }
+ if (!markerText.isEmpty()) {
+ // Marker found, add it
+ //TODO: allow user to set a marker category
+ CommentedTime marker1(GenTime(time1), markerText, category);
+ slotAddClipMarker(id, marker1, command);
+ if (time2 > 0 && time2 != time1) {
+ CommentedTime marker2(GenTime(time2), markerText, category);
+ slotAddClipMarker(id, marker2, command);
+ }
+ }
+ }
+ if (command->childCount() > 0) m_commandStack->push(command);
+ else delete command;
+}
+
+void CustomTrackView::addMarker(const QString &id, const CommentedTime marker)
{
DocClipBase *base = m_document->clipManager()->getClipById(id);
- if (!comment.isEmpty()) base->addSnapMarker(pos, comment);
- else base->deleteSnapMarker(pos);
+ if (marker.markerType() < 0) base->deleteSnapMarker(marker.time());
+ else base->addSnapMarker(marker);
emit updateClipMarkers(base);
setDocumentModified();
viewport()->update();
{
painter->setClipRect(rect);
QPen pen1 = painter->pen();
- pen1.setColor(palette().dark().color());
+ QColor lineColor = palette().dark().color();
+ lineColor.setAlpha(100);
+ pen1.setColor(lineColor);
painter->setPen(pen1);
double min = rect.left();
double max = rect.right();
QList<QGraphicsItem *> collisions = scene()->items(rect, Qt::IntersectsItemBoundingRect);
for (int i = 0; i < collisions.count(); i++) {
if (collisions.at(i)->type() == AVWIDGET) {
- return static_cast < ClipItem *>(collisions.at(i));
+ ClipItem *clip = static_cast < ClipItem *>(collisions.at(i));
+ if (!clip->isItemLocked()) return clip;
}
}
return NULL;