keyframeedit.cpp
positionedit.cpp
trackdialog.cpp
+ subprojectitem.cpp
+ addclipcutcommand.cpp
)
add_definitions( ${KDE4_DEFINITIONS} )
m_selectedKeyframe(0),
m_keyframeFactor(1),
m_fps(fps)
-#if QT_VERSION >= 0x040600
- , m_closeAnimation(NULL)
+#if QT_VERSION >= 0x040600
+ , m_closeAnimation(NULL)
#endif
{
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
{
#if QT_VERSION >= 0x040600
if (m_closeAnimation) delete m_closeAnimation;
-#endif
-}
-
+#endif
+}
+
void AbstractClipItem::closeAnimation()
{
#if QT_VERSION >= 0x040600
void setItemLocked(bool locked);
bool isItemLocked() const;
void closeAnimation();
-
+
virtual OPERATIONTYPE operationMode(QPointF pos) = 0;
virtual GenTime startPos() const ;
virtual void setTrack(int track);
void drawKeyFrames(QPainter *painter, QRectF exposedRect);
int mouseOverKeyFrames(QPointF pos, double maxOffset);
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
-
+
private:
#if QT_VERSION >= 0x040600
QPropertyAnimation *m_closeAnimation;
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "addclipcutcommand.h"
+#include "projectlist.h"
+
+#include <KLocale>
+
+AddClipCutCommand::AddClipCutCommand(ProjectList *list, const QString &id, int in, int out, bool remove, QUndoCommand * parent) :
+ QUndoCommand(parent),
+ m_list(list),
+ m_id(id),
+ m_in(in),
+ m_out(out),
+ m_remove(remove)
+{
+ setText(i18n("Add clip cut"));
+}
+
+
+// virtual
+void AddClipCutCommand::undo()
+{
+ if (m_remove) m_list->addClipCut(m_id, m_in, m_out);
+ else m_list->removeClipCut(m_id, m_in, m_out);
+}
+// virtual
+void AddClipCutCommand::redo()
+{
+ if (m_remove) m_list->removeClipCut(m_id, m_in, m_out);
+ else m_list->addClipCut(m_id, m_in, m_out);
+}
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#ifndef ADDCLIPCUTCOMMAND_H
+#define ADDCLIPCUTCOMMAND_H
+
+#include <QUndoCommand>
+#include <KDebug>
+
+class ProjectList;
+
+class AddClipCutCommand : public QUndoCommand
+{
+public:
+ AddClipCutCommand(ProjectList *list, const QString &id, int in, int out, bool remove, QUndoCommand * parent = 0);
+
+ virtual void undo();
+ virtual void redo();
+
+private:
+ ProjectList *m_list;
+ QString m_id;
+ int m_in;
+ int m_out;
+ bool m_remove;
+};
+
+#endif
+
colour = colour.replace(0, 2, "#");
m_baseColor = QColor(colour.left(7));
} else if (m_clipType == AUDIO) m_baseColor = QColor(141, 215, 166);
- else m_baseColor = QColor(141, 166, 215);
+ else m_baseColor = QColor(141, 166, 215);
}
m_audioThumbCachePic.clear();
}
m_doc->commandStack()->push(command);
}
+
void ClipManager::slotAddColorClipFile(const QString name, const QString color, QString duration, const QString group, const QString &groupId)
{
QDomDocument doc;
delete item;
item = NULL;
#endif
-
+
setDocumentModified();
if (refresh) m_document->renderer()->doRefresh();
}
m_properties.insert(attributes.item(i).nodeName(), attributes.item(i).nodeValue());
}
+ if (xml.hasAttribute("cutzones")) {
+ QStringList cuts = xml.attribute("cutzones").split(";", QString::SkipEmptyParts);
+ for (int i = 0; i < cuts.count(); i++) {
+ QString z = cuts.at(i);
+ addCutZone(z.section('-', 0, 0).toInt(), z.section('-', 1, 1).toInt());
+ }
+ }
+
KUrl url = KUrl(xml.attribute("resource"));
if (!m_properties.contains("file_hash") && !url.isEmpty()) getFileHash(url.path());
if (!i.value().isEmpty()) clip.setAttribute(i.key(), i.value());
}
doc.appendChild(clip);
+ if (!m_cutZones.isEmpty()) {
+ QStringList cuts;
+ for (int i = 0; i < m_cutZones.size(); i++) {
+ cuts << QString::number(m_cutZones.at(i).x()) + "-" + QString::number(m_cutZones.at(i).y());
+ }
+ clip.setAttribute("cutzones", cuts.join(";"));
+ }
//kDebug() << "/// CLIP XML: " << doc.toString();
return doc.documentElement();
}
return m_placeHolder;
}
+void DocClipBase::addCutZone(int in, int out)
+{
+ if (!m_cutZones.contains(QPoint(in, out))) {
+ m_cutZones.append(QPoint(in, out));
+ }
+}
+
+bool DocClipBase::hasCutZone(QPoint p) const
+{
+ return m_cutZones.contains(p);
+}
+
+
+void DocClipBase::removeCutZone(int in, int out)
+{
+ m_cutZones.removeAll(QPoint(in, out));
+}
+
+void DocClipBase::updateCutZone(int oldin, int oldout, int in, int out)
+{
+ QPoint old(oldin, oldout);
+ for (int i = 0; i < m_cutZones.size(); ++i) {
+ if (m_cutZones.at(i) == old) {
+ m_cutZones.replace(i, QPoint(in, out));
+ break;
+ }
+ }
+}
+
+QList <QPoint> DocClipBase::cutZones() const
+{
+ return m_cutZones;
+}
+
bool isPlaceHolder() const;
static QString getHash(const QString &path);
+ void addCutZone(int in, int out);
+ bool hasCutZone(QPoint p) const;
+ void removeCutZone(int in, int out);
+ QList <QPoint> cutZones() const;
+ void updateCutZone(int oldin, int oldout, int in, int out);
+
private: // Private attributes
/** The number of times this clip is used in the project - the number of references to this clip
/** Wheter the clip is a placeholder (clip missing but user wants to see it) */
bool m_placeHolder;
+ QList <QPoint> m_cutZones;
+
void setAudioThumbCreated(bool isDone);
/** Holds clip infos like fps, size,... */
QMap <QString, QString> m_properties;
}
}
-
void KdenliveDoc::setNewClipResource(const QString &id, const QString &path)
{
QDomNodeList prods = m_document.elementsByTagName("producer");
void KdenliveDoc::slotAddClipList(const KUrl::List urls, const QString group, const QString &groupId)
{
m_clipManager->slotAddClipList(urls, group, groupId);
- emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
+ //emit selectLastAddedClip(QString::number(m_clipManager->lastClipId()));
setModified(true);
}
// Deselect current effect / transition
m_effectStack->slotClipItemSelected(NULL, 0);
m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
- m_clipMonitor->slotSetXml(NULL, 0);
+ m_clipMonitor->slotSetXml(NULL);
bool updateFps = m_activeDocument->setProfilePath(profile);
KdenliveSettings::setCurrent_profile(profile);
KdenliveSettings::setProject_fps(m_activeDocument->fps());
m_projectList->setDocument(doc);
m_transitionConfig->updateProjectFormat(doc->mltProfile(), doc->timecode(), doc->tracksList());
m_effectStack->updateProjectFormat(doc->mltProfile(), doc->timecode());
- connect(m_projectList, SIGNAL(clipSelected(DocClipBase *)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *)));
+ connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint)));
connect(m_projectList, SIGNAL(refreshClip()), m_clipMonitor, SLOT(refreshMonitor()));
connect(m_projectList, SIGNAL(projectModified()), doc, SLOT(setModified()));
connect(m_projectList, SIGNAL(clipNameChanged(const QString, const QString)), trackView->projectView(), SLOT(clipNameChanged(const QString, const QString)));
void MainWindow::slotUpdatePreviewSettings()
{
if (m_activeDocument) {
- m_clipMonitor->slotSetXml(NULL, 0);
+ m_clipMonitor->slotSetXml(NULL);
m_activeDocument->updatePreviewSettings();
}
}
mimeData->setData("kdenlive/clip", data);
drag->setMimeData(mimeData);
QPixmap pix = m_currentClip->thumbnail();
- kDebug() << "/ / / /CLIP DRAGGED PIXMAP: " << pix.width() << "x" << pix.height();
drag->setPixmap(pix);
drag->setHotSpot(QPoint(0, 50));
drag->start(Qt::MoveAction);
m_playAction->setIcon(m_pauseIcon);
}
-void Monitor::slotSetXml(DocClipBase *clip, const int position)
+void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position)
{
if (render == NULL) return;
activateMonitor();
- if (!clip && m_currentClip != NULL) {
+ if (clip == NULL && m_currentClip != NULL) {
m_currentClip = NULL;
render->setProducer(NULL, -1);
return;
emit blockMonitors();
}
} else if (position != -1) render->seek(GenTime(position, m_monitorManager->timecode().fps()));
+ if (!zone.isNull()) {
+ m_ruler->setZone(zone.x(), zone.y());
+ render->seek(GenTime(zone.x(), m_monitorManager->timecode().fps()));
+ }
}
void Monitor::slotOpenFile(const QString &file)
public slots:
void slotOpenFile(const QString &);
- void slotSetXml(DocClipBase *clip, const int position = -1);
+ void slotSetXml(DocClipBase *clip, QPoint zone = QPoint(), const int position = -1);
void initMonitor();
void refreshMonitor(bool visible = true);
void slotSeek(int pos);
#include "projectlist.h"
#include "projectitem.h"
+#include "subprojectitem.h"
#include "addfoldercommand.h"
#include "kdenlivesettings.h"
#include "slideshowclip.h"
#include "projectlistview.h"
#include "editclipcommand.h"
#include "editfoldercommand.h"
+#include "addclipcutcommand.h"
+
#include "ui_templateclip_ui.h"
#include <KDebug>
m_reloadAction(NULL),
m_transcodeAction(NULL),
m_doc(NULL),
- m_selectedItem(NULL),
m_refreshed(false),
m_infoQueue(),
m_thumbnailQueue()
connect(m_listView, SIGNAL(requestMenu(const QPoint &, QTreeWidgetItem *)), this, SLOT(slotContextMenu(const QPoint &, QTreeWidgetItem *)));
connect(m_listView, SIGNAL(addClip()), this, SLOT(slotAddClip()));
connect(m_listView, SIGNAL(addClip(const QList <QUrl>, const QString &, const QString &)), this, SLOT(slotAddClip(const QList <QUrl>, const QString &, const QString &)));
+ connect(m_listView, SIGNAL(addClipCut(const QString &, int, int)), this, SLOT(slotAddClipCut(const QString &, int, int)));
connect(m_listView, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotItemEdited(QTreeWidgetItem *, int)));
connect(m_listView, SIGNAL(showProperties(DocClipBase *)), this, SIGNAL(showClipProperties(DocClipBase *)));
void ProjectList::slotEditClip()
{
- ProjectItem *item = static_cast <ProjectItem*>(m_listView->currentItem());
+ ProjectItem *item;
+ if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ item = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
+ } else item = static_cast <ProjectItem*>(m_listView->currentItem());
if (!(item->flags() & Qt::ItemIsDragEnabled)) return;
if (item && !item->isGroup()) {
emit clipSelected(item->referencedClip());
void ProjectList::slotOpenClip()
{
- ProjectItem *item = static_cast <ProjectItem*>(m_listView->currentItem());
+ ProjectItem *item;
+ if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ item = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
+ } else item = static_cast <ProjectItem*>(m_listView->currentItem());
if (item && !item->isGroup()) {
if (item->clipType() == IMAGE) {
if (KdenliveSettings::defaultimageapp().isEmpty()) KMessageBox::sorry(this, i18n("Please set a default application to open images in the Settings dialog"));
QTreeWidgetItemIterator it(m_listView);
ProjectItem *item;
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ it++;
+ continue;
+ }
item = static_cast <ProjectItem *>(*it);
if (!item->isGroup() && item->numReferences() == 0) item->setSelected(true);
it++;
QStringList ids;
QStringList urls;
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ it++;
+ continue;
+ }
item = static_cast <ProjectItem *>(*it);
if (!item->isGroup() && item->numReferences() == 0) {
ids << item->clipId();
// Check that we don't use the URL in another clip
QTreeWidgetItemIterator it2(m_listView);
while (*it2) {
+ if ((*it2)->type() == QTreeWidgetItem::UserType + 1) {
+ it2++;
+ continue;
+ }
item = static_cast <ProjectItem *>(*it2);
if (item->numReferences() > 0) {
KUrl url = item->clipUrl();
else selected.append(getItemById(id));
ProjectItem *item;
for (int i = 0; i < selected.count(); i++) {
+ if (selected.at(i)->type() == QTreeWidgetItem::UserType + 1) continue;
item = static_cast <ProjectItem *>(selected.at(i));
if (item && !item->isGroup()) {
if (item->clipType() == IMAGE) {
void ProjectList::slotClipSelected()
{
if (m_listView->currentItem()) {
- ProjectItem *clip = static_cast <ProjectItem*>(m_listView->currentItem());
+ ProjectItem *clip;
+ if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ // this is a sub item, use base clip
+ clip = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
+ if (clip == NULL) kDebug() << "-----------ERROR";
+ SubProjectItem *sub = static_cast <SubProjectItem*>(m_listView->currentItem());
+ emit clipSelected(clip->referencedClip(), sub->zone());
+ return;
+ }
+ clip = static_cast <ProjectItem*>(m_listView->currentItem());
if (!clip->isGroup()) {
- m_selectedItem = clip;
emit clipSelected(clip->referencedClip());
}
m_editAction->setEnabled(true);
void ProjectList::slotItemEdited(QTreeWidgetItem *item, int column)
{
+ if (item->type() == QTreeWidgetItem::UserType + 1) {
+ // this is a sub-item
+ return;
+ }
+
ProjectItem *clip = static_cast <ProjectItem*>(item);
if (column == 2) {
if (clip->referencedClip()) {
m_reloadAction->setEnabled(enable);
m_transcodeAction->setEnabled(enable);
if (enable) {
- ProjectItem *clip = static_cast <ProjectItem*>(item);
+ ProjectItem *clip;
+ if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ clip = static_cast <ProjectItem*>(item->parent());
+ } else clip = static_cast <ProjectItem*>(item);
if (clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
m_openAction->setIcon(KIcon(KdenliveSettings::defaultimageapp()));
m_openAction->setEnabled(true);
QStringList ids;
QMap <QString, QString> folderids;
QList<QTreeWidgetItem *> selected = m_listView->selectedItems();
- ProjectItem *item;
+
+ QUndoCommand *delCommand = new QUndoCommand();
+ delCommand->setText(i18n("Delete Clip Zone"));
+
for (int i = 0; i < selected.count(); i++) {
- item = static_cast <ProjectItem *>(selected.at(i));
+ if (selected.at(i)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ SubProjectItem *sub = static_cast <SubProjectItem *>(selected.at(i));
+ ProjectItem *item = static_cast <ProjectItem *>(sub->parent());
+ new AddClipCutCommand(this, item->clipId(), sub->zone().x(), sub->zone().y(), true, delCommand);
+ continue;
+ }
+ ProjectItem *item = static_cast <ProjectItem *>(selected.at(i));
if (item->isGroup()) folderids[item->groupName()] = item->clipId();
else ids << item->clipId();
if (item->numReferences() > 0) {
}
}
}
+ if (delCommand->childCount() == 0) delete delCommand;
+ else m_commandStack->push(delCommand);
if (!ids.isEmpty()) m_doc->deleteProjectClip(ids);
if (!folderids.isEmpty()) deleteProjectFolder(folderids);
if (m_listView->topLevelItemCount() == 0) {
if (!annotation.isEmpty()) item->setText(2, annotation);
item->setText(3, QString::number(f.rating()));
}
+
+ // Add cut zones
+ QList <QPoint> cuts = clip->cutZones();
+ if (!cuts.isEmpty()) {
+ m_listView->blockSignals(true);
+ for (int i = 0; i < cuts.count(); i++) {
+ SubProjectItem *sub = new SubProjectItem(item, cuts.at(i).x(), cuts.at(i).y());
+ if (!clip->getClipHash().isEmpty()) {
+ QString cachedPixmap = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "thumbs/" + clip->getClipHash() + '#' + QString::number(cuts.at(i).x()) + ".png";
+ if (QFile::exists(cachedPixmap)) {
+ sub->setIcon(0, QPixmap(cachedPixmap));
+ }
+ }
+ }
+ m_listView->blockSignals(false);
+ }
+
if (getProperties && m_listView->isEnabled()) m_listView->blockSignals(false);
if (getProperties && !m_queueTimer.isActive()) m_queueTimer.start();
}
m_infoQueue.remove(j.key());
emit getFileProperties(dom, id, false);
}
- //if (!m_infoQueue.isEmpty() && !m_queueTimer.isActive()) m_queueTimer.start();
}
void ProjectList::slotUpdateClip(const QString &id)
ProjectItem *item;
m_listView->blockSignals(true);
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ SubProjectItem *sub = static_cast <SubProjectItem *>(*it);
+ if (sub->icon(0).isNull()) {
+ item = static_cast <ProjectItem *>((*it)->parent());
+ requestClipThumbnail(item->clipId() + '#' + QString::number(sub->zone().x()));
+ }
+ ++it;
+ continue;
+ }
item = static_cast <ProjectItem *>(*it);
if (!item->isGroup()) {
clip = item->referencedClip();
QStringList ProjectList::getGroup() const
{
QStringList result;
- ProjectItem *item = static_cast <ProjectItem*>(m_listView->currentItem());
+ ProjectItem *item = NULL;
+ if (m_listView->currentItem() && m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ // sub item selected
+ item = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
+ } else item = static_cast <ProjectItem*>(m_listView->currentItem());
if (item && !item->isGroup()) {
while (item->parent()) {
item = static_cast <ProjectItem*>(item->parent());
kDebug() << "//////////// PRO LISTÂ BUILD PRDSLIST ";
QTreeWidgetItemIterator it(m_listView);
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ ++it;
+ continue;
+ }
if (!((ProjectItem *)(*it))->isGroup())
prods.appendChild(doc.importNode(((ProjectItem *)(*it))->toXml(), true));
++it;
m_thumbnailQueue.clear();
QTreeWidgetItemIterator it(m_listView);
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ ++it;
+ continue;
+ }
if (!((ProjectItem *)(*it))->isGroup())
m_thumbnailQueue << ((ProjectItem *)(*it))->clipId();
++it;
void ProjectList::slotRefreshClipThumbnail(const QString &clipId, bool update)
{
- ProjectItem *item = getItemById(clipId);
+ QTreeWidgetItem *item = getAnyItemById(clipId);
if (item) slotRefreshClipThumbnail(item, update);
else slotProcessNextThumbnail();
}
-void ProjectList::slotRefreshClipThumbnail(ProjectItem *item, bool update)
+void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update)
{
+ if (it == NULL) return;
+ ProjectItem *item = NULL;
+ bool isSubItem = false;
+ int frame;
+ if (it->type() == QTreeWidgetItem::UserType + 1) {
+ item = static_cast <ProjectItem *>(it->parent());
+ frame = static_cast <SubProjectItem *>(it)->zone().x();
+ isSubItem = true;
+ } else {
+ item = static_cast <ProjectItem *>(it);
+ frame = item->referencedClip()->getClipThumbFrame();
+ }
+
if (item) {
DocClipBase *clip = item->referencedClip();
if (!clip) {
return;
}
QPixmap pix;
- int height = 50;
+ int height = it->sizeHint(0).height();
int width = (int)(height * m_render->dar());
if (clip->clipType() == AUDIO) pix = KIcon("audio-x-generic").pixmap(QSize(width, height));
else if (clip->clipType() == IMAGE) pix = QPixmap::fromImage(KThumb::getFrame(item->referencedClip()->producer(), 0, width, height));
- else pix = item->referencedClip()->thumbProducer()->extractImage(item->referencedClip()->getClipThumbFrame(), width, height);
+ else pix = item->referencedClip()->thumbProducer()->extractImage(frame, width, height);
+
if (!pix.isNull()) {
m_listView->blockSignals(true);
- item->setIcon(0, pix);
+ it->setIcon(0, pix);
if (m_listView->isEnabled()) m_listView->blockSignals(false);
- m_doc->cachePixmap(item->getClipHash(), pix);
+ if (!isSubItem) m_doc->cachePixmap(item->getClipHash(), pix);
+ else m_doc->cachePixmap(item->getClipHash() + '#' + QString::number(frame), pix);
}
if (update) emit projectModified();
QTimer::singleShot(30, this, SLOT(slotProcessNextThumbnail()));
int max = m_doc->clipManager()->clipsCount();
emit displayMessage(i18n("Loading clips"), (int)(100 * (max - m_infoQueue.count()) / max));
// small delay so that the app can display the progress info
+ if (item && m_infoQueue.isEmpty() && m_thumbnailQueue.isEmpty()) {
+ m_listView->setCurrentItem(item);
+ emit clipSelected(item->referencedClip());
+ }
QTimer::singleShot(30, this, SLOT(slotProcessNextClipInQueue()));
}
}
}
+QTreeWidgetItem *ProjectList::getAnyItemById(const QString &id)
+{
+ QTreeWidgetItemIterator it(m_listView);
+ QString lookId = id;
+ if (id.contains('#')) {
+ lookId = id.section('#', 0, 0);
+ }
+
+ ProjectItem *result = NULL;
+ while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ ++it;
+ continue;
+ }
+ ProjectItem *item = static_cast<ProjectItem *>(*it);
+ if (item->clipId() == lookId && item->clipType() != FOLDER) {
+ result = item;
+ break;
+ }
+ ++it;
+ }
+ if (!id.contains('#')) return result;
+ else for (int i = 0; i < result->childCount(); i++) {
+ SubProjectItem *sub = static_cast <SubProjectItem *>(result->child(i));
+ if (sub && sub->zone().x() == id.section('#', 1, 1).toInt()) {
+ return sub;
+ }
+ }
+
+ return NULL;
+}
+
+
ProjectItem *ProjectList::getItemById(const QString &id)
{
ProjectItem *item;
QTreeWidgetItemIterator it(m_listView);
while (*it) {
+ if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ ++it;
+ continue;
+ }
item = static_cast<ProjectItem *>(*it);
if (item->clipId() == id && item->clipType() != FOLDER)
return item;
QString ProjectList::currentClipUrl() const
{
- ProjectItem *item = static_cast <ProjectItem*>(m_listView->currentItem());
+ ProjectItem *item;
+ if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ item = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
+ } else item = static_cast <ProjectItem*>(m_listView->currentItem());
if (item == NULL) return QString();
return item->clipUrl().path();
}
return doc;
}
+
+void ProjectList::slotAddClipCut(const QString &id, int in, int out)
+{
+ ProjectItem *clip = getItemById(id);
+ if (clip == NULL) return;
+ if (clip->referencedClip()->hasCutZone(QPoint(in, out))) return;
+ AddClipCutCommand *command = new AddClipCutCommand(this, id, in, out, false);
+ m_commandStack->push(command);
+}
+
+void ProjectList::addClipCut(const QString &id, int in, int out)
+{
+ //m_doc->slotAddClipCut(id, in, out, groupName, groupId);
+ ProjectItem *clip = getItemById(id);
+ if (clip) {
+ DocClipBase *base = clip->referencedClip();
+ base->addCutZone(in, out);
+ m_listView->blockSignals(true);
+ SubProjectItem *sub = new SubProjectItem(clip, in, out);
+
+ QPixmap p = clip->referencedClip()->thumbProducer()->extractImage(in, (int)(sub->sizeHint(0).height() * m_render->dar()), sub->sizeHint(0).height());
+ sub->setIcon(0, p);
+ m_doc->cachePixmap(clip->getClipHash() + '#' + QString::number(in), p);
+ m_listView->blockSignals(false);
+ }
+}
+
+void ProjectList::removeClipCut(const QString &id, int in, int out)
+{
+ //m_doc->slotAddClipCut(id, in, out, groupName, groupId);
+ ProjectItem *clip = getItemById(id);
+ if (clip) {
+ DocClipBase *base = clip->referencedClip();
+ base->removeCutZone(in, out);
+ for (int i = 0; i < clip->childCount(); i++) {
+ QTreeWidgetItem *it = clip->child(i);
+ if (it->type() != QTreeWidgetItem::UserType + 1) continue;
+ SubProjectItem *sub = static_cast <SubProjectItem*>(it);
+ if (sub->zone() == QPoint(in, out)) {
+ m_listView->blockSignals(true);
+ delete it;
+ m_listView->blockSignals(false);
+ break;
+ }
+ }
+ }
+}
+
#include "projectlist.moc"
void cleanup();
void trashUnusedClips();
QList <DocClipBase*> documentClipList() const;
+ void addClipCut(const QString &id, int in, int out);
+ void removeClipCut(const QString &id, int in, int out);
public slots:
void setDocument(KdenliveDoc *doc);
void slotDeleteClip(const QString &clipId);
void slotUpdateClip(const QString &id);
void slotRefreshClipThumbnail(const QString &clipId, bool update = true);
- void slotRefreshClipThumbnail(ProjectItem *item, bool update = true);
+ void slotRefreshClipThumbnail(QTreeWidgetItem *item, bool update = true);
void slotRemoveInvalidClip(const QString &id, bool replace);
void slotSelectClip(const QString &ix);
void slotRemoveClip();
QUndoStack *m_commandStack;
void selectItemById(const QString &clipId);
ProjectItem *getItemById(const QString &id);
+ QTreeWidgetItem *getAnyItemById(const QString &id);
ProjectItem *getFolderItemById(const QString &id);
QAction *m_editAction;
QAction *m_deleteAction;
QAction *m_reloadAction;
QMenu *m_transcodeAction;
KdenliveDoc *m_doc;
- ProjectItem *m_selectedItem;
ItemDelegate *m_listViewDelegate;
bool m_refreshed;
QToolButton *m_addButton;
void slotProcessNextThumbnail();
void slotCheckForEmptyQueue();
void slotPauseMonitor();
+ void slotAddClipCut(const QString &id, int in, int out);
//void slotShowMenu(const QPoint &pos);
signals:
- void clipSelected(DocClipBase *);
+ void clipSelected(DocClipBase *, QPoint zone = QPoint());
void getFileProperties(const QDomElement, const QString &, bool);
void receivedClipDuration(const QString &);
void showClipProperties(DocClipBase *);
#include "projectlistview.h"
#include "projectitem.h"
+#include "subprojectitem.h"
#include "kdenlivesettings.h"
#include <KDebug>
// virtual
void ProjectListView::mouseDoubleClickEvent(QMouseEvent * event)
{
- ProjectItem *item = static_cast <ProjectItem *>(itemAt(event->pos()));
+ QTreeWidgetItem *it = itemAt(event->pos());
+ if (!it) return;
+ ProjectItem *item;
+ if (it->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ item = static_cast <ProjectItem *>(it->parent());
+ } else item = static_cast <ProjectItem *>(it);
if (!item) {
emit addClip();
return;
// virtual
void ProjectListView::dropEvent(QDropEvent *event)
{
- kDebug() << "//////////////// DROPPED EVENT";
+ ProjectItem *item = NULL;
+ QTreeWidgetItem *it = itemAt(event->pos());
+ if (it) {
+ if (it->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ item = static_cast <ProjectItem *>(it->parent());
+ } else item = static_cast <ProjectItem *>(it);
+ }
+
if (event->mimeData()->hasUrls()) {
- ProjectItem *item = static_cast <ProjectItem *>(itemAt(event->pos()));
QString groupName;
QString groupId;
if (item) {
event->accept();
return;
} else if (event->mimeData()->hasFormat("kdenlive/producerslist")) {
- ProjectItem *item = static_cast <ProjectItem *>(itemAt(event->pos()));
if (item) {
if (item->parent()) item = static_cast <ProjectItem *>(item->parent());
if (item->isGroup()) {
//emit addClip(event->mimeData->text());
- kDebug() << "//////////////// DROPPED RIGHT 1 ";
const QList <QTreeWidgetItem *> list = selectedItems();
ProjectItem *clone;
QString parentId = item->clipId();
} else item = NULL;
}
if (!item) {
- kDebug() << "//////////////// DROPPED ONÂ EMPTY ZONE";
// item dropped in empty zone, move it to top level
const QList <QTreeWidgetItem *> list = selectedItems();
ProjectItem *clone;
}
}
}
+ } else if (event->mimeData()->hasFormat("kdenlive/clip")) {
+ QStringList list = QString(event->mimeData()->data("kdenlive/clip")).split(';');
+ emit addClipCut(list.at(0), list.at(1).toInt(), list.at(2).toInt());
}
event->acceptProposedAction();
}
< QApplication::startDragDistance())
return;
- {
- ProjectItem *clickItem = static_cast <ProjectItem *>(itemAt(m_DragStartPosition));
+ QTreeWidgetItem *it = itemAt(m_DragStartPosition);
+ if (!it) return;
+ if (it->type() == QTreeWidgetItem::UserType + 1) {
+ // subitem
+ SubProjectItem *clickItem = static_cast <SubProjectItem *>(it);
+ if (clickItem && (clickItem->flags() & Qt::ItemIsDragEnabled)) {
+ ProjectItem *clip = static_cast <ProjectItem *>(it->parent());
+ QDrag *drag = new QDrag(this);
+ QMimeData *mimeData = new QMimeData;
+
+ QStringList list;
+ list.append(clip->clipId());
+ QPoint p = clickItem->zone();
+ list.append(QString::number(p.x()));
+ list.append(QString::number(p.y()));
+ QByteArray data;
+ data.append(list.join(";").toUtf8());
+ mimeData->setData("kdenlive/clip", data);
+ drag->setMimeData(mimeData);
+ drag->setPixmap(clickItem->icon(0).pixmap(iconSize()));
+ drag->setHotSpot(QPoint(0, 50));
+ drag->exec();
+ }
+ } else {
+ ProjectItem *clickItem = static_cast <ProjectItem *>(it);
if (clickItem && (clickItem->flags() & Qt::ItemIsDragEnabled)) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
qstrList.append("text/uri-list");
qstrList.append("text/plain");
qstrList.append("kdenlive/producerslist");
+ qstrList.append("kdenlive/clip");
return qstrList;
}
void showProperties(DocClipBase *);
void focusMonitor();
void pauseMonitor();
+ void addClipCut(const QString&, int, int);
};
#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#include "subprojectitem.h"
+#include "timecode.h"
+#include "kdenlivesettings.h"
+#include "docclipbase.h"
+
+#include <KDebug>
+#include <KLocale>
+#include <KIcon>
+
+const int DurationRole = Qt::UserRole + 1;
+
+SubProjectItem::SubProjectItem(QTreeWidgetItem * parent, int in, int out) :
+ QTreeWidgetItem(parent, QTreeWidgetItem::UserType + 1), m_in(in), m_out(out)
+{
+ setSizeHint(0, QSize(65, 30));
+ setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable);
+ QString name = Timecode::getStringTimecode(in, KdenliveSettings::project_fps());
+ setText(1, name);
+ GenTime duration = GenTime(out - in, KdenliveSettings::project_fps());
+ if (duration != GenTime()) setData(1, DurationRole, Timecode::getEasyTimecode(duration, KdenliveSettings::project_fps()));
+ //setFlags(Qt::NoItemFlags);
+ //kDebug() << "Constructed with clipId: " << m_clipId;
+}
+
+
+SubProjectItem::~SubProjectItem()
+{
+}
+
+int SubProjectItem::numReferences() const
+{
+ return 0;
+}
+
+QDomElement SubProjectItem::toXml() const
+{
+ //return m_clip->toXML();
+ return QDomElement();
+}
+
+QPoint SubProjectItem::zone() const
+{
+ QPoint z(m_in, m_out);
+ return z;
+}
+
+DocClipBase *SubProjectItem::referencedClip()
+{
+ return NULL; //m_clip;
+}
+
+
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+
+#ifndef SUBPROJECTITEM_H
+#define SUBPROJECTITEM_H
+
+#include <QTreeWidgetItem>
+#include <QTreeWidget>
+#include <QDomElement>
+
+#include <KUrl>
+
+#include "gentime.h"
+#include "definitions.h"
+
+class DocClipBase;
+
+/** \brief Represents a clip or a folder in the projecttree
+ *
+ * This class represents a clip or folder in the projecttree and in the document(?) */
+class SubProjectItem : public QTreeWidgetItem
+{
+public:
+ SubProjectItem(QTreeWidgetItem * parent, int in, int out);
+ virtual ~SubProjectItem();
+ QDomElement toXml() const;
+ int numReferences() const;
+ DocClipBase *referencedClip();
+ QPoint zone() const;
+
+private:
+ int m_in;
+ int m_out;
+};
+
+#endif
/** Return the transition type for a given name */
TRANSITIONTYPE getTransitionForName(const QString & type);
-
+
#if QT_VERSION >= 0x040600
QPropertyAnimation *m_startAnimation;
#endif