]> git.sesse.net Git - kdenlive/blobdiff - src/projectlist.cpp
Get ready for typewriter effect in titles
[kdenlive] / src / projectlist.cpp
index 5247e978cdcc04a208957d58e9fbeb7f374b3b84..eade2f3d265b52a6e3fb292ff724560df6f51152 100644 (file)
@@ -83,6 +83,8 @@ ProjectList::ProjectList(QWidget *parent) :
     KTreeWidgetSearchLine *searchView = new KTreeWidgetSearchLine(this);
     m_toolbar = new QToolBar("projectToolBar", this);
     m_toolbar->addWidget(searchView);
+    int s = style()->pixelMetric(QStyle::PM_SmallIconSize);
+    m_toolbar->setIconSize(QSize(s, s));
     searchView->setTreeWidget(m_listView);
 
     m_addButton = new QToolButton(m_toolbar);
@@ -130,6 +132,11 @@ ProjectList::~ProjectList()
     delete m_listViewDelegate;
 }
 
+void ProjectList::focusTree() const
+{
+    m_listView->setFocus();
+}
+
 void ProjectList::setupMenu(QMenu *addMenu, QAction *defaultAction)
 {
     QList <QAction *> actions = addMenu->actions();
@@ -196,11 +203,12 @@ void ProjectList::setHeaderInfo(const QByteArray &state)
 void ProjectList::slotEditClip()
 {
     ProjectItem *item;
-    if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+    if (!m_listView->currentItem() || m_listView->currentItem()->type() == PROJECTFOLDERTYPE) return;
+    if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
         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()) {
+    if (item) {
         emit clipSelected(item->referencedClip());
         emit showClipProperties(item->referencedClip());
     }
@@ -209,10 +217,11 @@ void ProjectList::slotEditClip()
 void ProjectList::slotOpenClip()
 {
     ProjectItem *item;
+    if (!m_listView->currentItem() || m_listView->currentItem()->type() == PROJECTFOLDERTYPE) return;
     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) {
         if (item->clipType() == IMAGE) {
             if (KdenliveSettings::defaultimageapp().isEmpty()) KMessageBox::sorry(this, i18n("Please set a default application to open images in the Settings dialog"));
             else QProcess::startDetached(KdenliveSettings::defaultimageapp(), QStringList() << item->clipUrl().path());
@@ -230,12 +239,12 @@ void ProjectList::cleanup()
     QTreeWidgetItemIterator it(m_listView);
     ProjectItem *item;
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             it++;
             continue;
         }
         item = static_cast <ProjectItem *>(*it);
-        if (!item->isGroup() && item->numReferences() == 0) item->setSelected(true);
+        if (item->numReferences() == 0) item->setSelected(true);
         it++;
     }
     slotRemoveClip();
@@ -248,23 +257,23 @@ void ProjectList::trashUnusedClips()
     QStringList ids;
     QStringList urls;
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             it++;
             continue;
         }
         item = static_cast <ProjectItem *>(*it);
-        if (!item->isGroup() && item->numReferences() == 0) {
+        if (item->numReferences() == 0) {
             ids << item->clipId();
             KUrl url = item->clipUrl();
-            if (!url.isEmpty()) urls << url.path();
+            if (!url.isEmpty() && !urls.contains(url.path())) urls << url.path();
         }
         it++;
     }
-    urls.removeDuplicates();
+
     // Check that we don't use the URL in another clip
     QTreeWidgetItemIterator it2(m_listView);
     while (*it2) {
-        if ((*it2)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it2)->type() != PROJECTCLIPTYPE) {
             it2++;
             continue;
         }
@@ -289,9 +298,9 @@ void ProjectList::slotReloadClip(const QString &id)
     else selected.append(getItemById(id));
     ProjectItem *item;
     for (int i = 0; i < selected.count(); i++) {
-        if (selected.at(i)->type() == QTreeWidgetItem::UserType + 1) continue;
+        if (selected.at(i)->type() != PROJECTCLIPTYPE) continue;
         item = static_cast <ProjectItem *>(selected.at(i));
-        if (item && !item->isGroup()) {
+        if (item) {
             if (item->clipType() == IMAGE) {
                 item->referencedClip()->producer()->set("force_reload", 1);
             } else if (item->clipType() == TEXT) {
@@ -307,36 +316,43 @@ void ProjectList::slotReloadClip(const QString &id)
 void ProjectList::setRenderer(Render *projectRender)
 {
     m_render = projectRender;
-    m_listView->setIconSize(QSize(40 * m_render->dar(), 40));
+    m_listView->setIconSize(QSize((ProjectItem::itemDefaultHeight() - 2) * m_render->dar(), ProjectItem::itemDefaultHeight() - 2));
 }
 
 void ProjectList::slotClipSelected()
 {
     if (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()) {
+        if (m_listView->currentItem()->type() == PROJECTFOLDERTYPE) {
+            emit clipSelected(NULL);
+            m_editAction->setEnabled(false);
+            m_deleteAction->setEnabled(true);
+            m_openAction->setEnabled(false);
+            m_reloadAction->setEnabled(false);
+            m_transcodeAction->setEnabled(false);
+        } else {
+            ProjectItem *clip;
+            if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
+                // 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());
             emit clipSelected(clip->referencedClip());
+            m_editAction->setEnabled(true);
+            m_deleteAction->setEnabled(true);
+            m_reloadAction->setEnabled(true);
+            m_transcodeAction->setEnabled(true);
+            if (clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
+                m_openAction->setIcon(KIcon(KdenliveSettings::defaultimageapp()));
+                m_openAction->setEnabled(true);
+            } else if (clip->clipType() == AUDIO && !KdenliveSettings::defaultaudioapp().isEmpty()) {
+                m_openAction->setIcon(KIcon(KdenliveSettings::defaultaudioapp()));
+                m_openAction->setEnabled(true);
+            } else m_openAction->setEnabled(false);
         }
-        m_editAction->setEnabled(true);
-        m_deleteAction->setEnabled(true);
-        m_reloadAction->setEnabled(true);
-        m_transcodeAction->setEnabled(true);
-        if (clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
-            m_openAction->setIcon(KIcon(KdenliveSettings::defaultimageapp()));
-            m_openAction->setEnabled(true);
-        } else if (clip->clipType() == AUDIO && !KdenliveSettings::defaultaudioapp().isEmpty()) {
-            m_openAction->setIcon(KIcon(KdenliveSettings::defaultaudioapp()));
-            m_openAction->setEnabled(true);
-        } else m_openAction->setEnabled(false);
     } else {
         emit clipSelected(NULL);
         m_editAction->setEnabled(false);
@@ -369,17 +385,17 @@ void ProjectList::slotUpdateClipProperties(const QString &id, QMap <QString, QSt
 void ProjectList::slotUpdateClipProperties(ProjectItem *clip, QMap <QString, QString> properties)
 {
     if (!clip) return;
-    if (!clip->isGroup()) clip->setProperties(properties);
+    clip->setProperties(properties);
     if (properties.contains("name")) {
         m_listView->blockSignals(true);
-        clip->setText(1, properties.value("name"));
+        clip->setText(0, properties.value("name"));
         m_listView->blockSignals(false);
         emit clipNameChanged(clip->clipId(), properties.value("name"));
     }
     if (properties.contains("description")) {
         CLIPTYPE type = clip->clipType();
         m_listView->blockSignals(true);
-        clip->setText(2, properties.value("description"));
+        clip->setText(1, properties.value("description"));
         m_listView->blockSignals(false);
         if (KdenliveSettings::activate_nepomuk() && (type == AUDIO || type == VIDEO || type == AV || type == IMAGE || type == PLAYLIST)) {
             // Use Nepomuk system to store clip description
@@ -392,51 +408,53 @@ void ProjectList::slotUpdateClipProperties(ProjectItem *clip, QMap <QString, QSt
 
 void ProjectList::slotItemEdited(QTreeWidgetItem *item, int column)
 {
-    if (item->type() == QTreeWidgetItem::UserType + 1) {
+    if (item->type() == PROJECTSUBCLIPTYPE) {
         // this is a sub-item
         return;
     }
+    if (item->type() == PROJECTFOLDERTYPE) {
+        if (column != 0) return;
+        FolderProjectItem *folder = static_cast <FolderProjectItem*>(item);
+        editFolder(item->text(0), folder->groupName(), folder->clipId());
+        folder->setGroupName(item->text(0));
+        m_doc->clipManager()->addFolder(folder->clipId(), item->text(0));
+        const int children = item->childCount();
+        for (int i = 0; i < children; i++) {
+            ProjectItem *child = static_cast <ProjectItem *>(item->child(i));
+            child->setProperty("groupname", item->text(0));
+        }
+        return;
+    }
 
     ProjectItem *clip = static_cast <ProjectItem*>(item);
-    if (column == 2) {
+    if (column == 1) {
         if (clip->referencedClip()) {
             QMap <QString, QString> oldprops;
             QMap <QString, QString> newprops;
             oldprops["description"] = clip->referencedClip()->getProperty("description");
-            newprops["description"] = item->text(2);
+            newprops["description"] = item->text(1);
 
             if (clip->clipType() == TEXT) {
                 // This is a text template clip, update the image
                 /*oldprops.insert("xmldata", clip->referencedClip()->getProperty("xmldata"));
                 newprops.insert("xmldata", generateTemplateXml(clip->referencedClip()->getProperty("xmltemplate"), item->text(2)).toString());*/
                 oldprops.insert("templatetext", clip->referencedClip()->getProperty("templatetext"));
-                newprops.insert("templatetext", item->text(2));
+                newprops.insert("templatetext", item->text(1));
             }
             slotUpdateClipProperties(clip->clipId(), newprops);
             EditClipCommand *command = new EditClipCommand(this, clip->clipId(), oldprops, newprops, false);
             m_commandStack->push(command);
         }
-    } else if (column == 1) {
-        if (clip->isGroup()) {
-            editFolder(item->text(1), clip->groupName(), clip->clipId());
-            clip->setGroupName(item->text(1));
-            m_doc->clipManager()->addFolder(clip->clipId(), item->text(1));
-            const int children = item->childCount();
-            for (int i = 0; i < children; i++) {
-                ProjectItem *child = static_cast <ProjectItem *>(item->child(i));
-                child->setProperty("groupname", item->text(1));
-            }
-        } else {
-            if (clip->referencedClip()) {
-                QMap <QString, QString> oldprops;
-                QMap <QString, QString> newprops;
-                oldprops["name"] = clip->referencedClip()->getProperty("name");
-                newprops["name"] = item->text(1);
-                slotUpdateClipProperties(clip, newprops);
-                emit projectModified();
-                EditClipCommand *command = new EditClipCommand(this, clip->clipId(), oldprops, newprops, false);
-                m_commandStack->push(command);
-            }
+    } else if (column == 0) {
+        if (clip->referencedClip()) {
+            QMap <QString, QString> oldprops;
+            QMap <QString, QString> newprops;
+            oldprops["name"] = clip->referencedClip()->getProperty("name");
+            newprops["name"] = item->text(0);
+            slotUpdateClipProperties(clip, newprops);
+            emit projectModified();
+            EditClipCommand *command = new EditClipCommand(this, clip->clipId(), oldprops, newprops, false);
+            m_commandStack->push(command);
         }
     }
 }
@@ -452,14 +470,14 @@ void ProjectList::slotContextMenu(const QPoint &pos, QTreeWidgetItem *item)
     m_reloadAction->setEnabled(enable);
     m_transcodeAction->setEnabled(enable);
     if (enable) {
-        ProjectItem *clip;
-        if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+        ProjectItem *clip = NULL;
+        if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
             clip = static_cast <ProjectItem*>(item->parent());
-        } else clip = static_cast <ProjectItem*>(item);
-        if (clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
+        } else if (m_listView->currentItem()->type() == PROJECTCLIPTYPE) clip = static_cast <ProjectItem*>(item);
+        if (clip && clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
             m_openAction->setIcon(KIcon(KdenliveSettings::defaultimageapp()));
             m_openAction->setEnabled(true);
-        } else if (clip->clipType() == AUDIO && !KdenliveSettings::defaultaudioapp().isEmpty()) {
+        } else if (clip && clip->clipType() == AUDIO && !KdenliveSettings::defaultaudioapp().isEmpty()) {
             m_openAction->setIcon(KIcon(KdenliveSettings::defaultaudioapp()));
             m_openAction->setEnabled(true);
         } else m_openAction->setEnabled(false);
@@ -478,25 +496,32 @@ void ProjectList::slotRemoveClip()
     delCommand->setText(i18n("Delete Clip Zone"));
 
     for (int i = 0; i < selected.count(); i++) {
-        if (selected.at(i)->type() == QTreeWidgetItem::UserType + 1) {
+        if (selected.at(i)->type() == PROJECTSUBCLIPTYPE) {
             // 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 (KMessageBox::questionYesNo(this, i18np("Delete clip <b>%2</b>?<br>This will also remove the clip in timeline", "Delete clip <b>%2</b>?<br>This will also remove its %1 clips in timeline", item->numReferences(), item->names().at(1)), i18n("Delete Clip")) != KMessageBox::Yes) return;
-        } else if (item->isGroup() && item->childCount() > 0) {
-            int children = item->childCount();
-            if (KMessageBox::questionYesNo(this, i18np("Delete folder <b>%2</b>?<br>This will also remove the clip in that folder", "Delete folder <b>%2</b>?<br>This will also remove the %1 clips in that folder",  children, item->names().at(1)), i18n("Delete Folder")) != KMessageBox::Yes) return;
+
+        if (selected.at(i)->type() == PROJECTFOLDERTYPE) {
+            // folder
+            FolderProjectItem *folder = static_cast <FolderProjectItem *>(selected.at(i));
+            folderids[folder->groupName()] = folder->clipId();
+            int children = folder->childCount();
+
+            if (children > 0 && KMessageBox::questionYesNo(this, i18np("Delete folder <b>%2</b>?<br>This will also remove the clip in that folder", "Delete folder <b>%2</b>?<br>This will also remove the %1 clips in that folder",  children, folder->text(1)), i18n("Delete Folder")) != KMessageBox::Yes) return;
             for (int i = 0; i < children; ++i) {
-                ProjectItem *child = static_cast <ProjectItem *>(item->child(i));
+                ProjectItem *child = static_cast <ProjectItem *>(folder->child(i));
                 ids << child->clipId();
             }
+            continue;
+        }
+
+        ProjectItem *item = static_cast <ProjectItem *>(selected.at(i));
+        ids << item->clipId();
+        if (item->numReferences() > 0) {
+            if (KMessageBox::questionYesNo(this, i18np("Delete clip <b>%2</b>?<br>This will also remove the clip in timeline", "Delete clip <b>%2</b>?<br>This will also remove its %1 clips in timeline", item->numReferences(), item->names().at(1)), i18n("Delete Clip")) != KMessageBox::Yes) return;
         }
     }
     if (delCommand->childCount() == 0) delete delCommand;
@@ -550,14 +575,14 @@ void ProjectList::slotAddFolder()
 void ProjectList::slotAddFolder(const QString foldername, const QString &clipId, bool remove, bool edit)
 {
     if (remove) {
-        ProjectItem *item = getFolderItemById(clipId);
+        FolderProjectItem *item = getFolderItemById(clipId);
         if (item) {
             m_doc->clipManager()->deleteFolder(clipId);
             delete item;
         }
     } else {
         if (edit) {
-            ProjectItem *item = getFolderItemById(clipId);
+            FolderProjectItem *item = getFolderItemById(clipId);
             if (item) {
                 m_listView->blockSignals(true);
                 item->setGroupName(foldername);
@@ -571,13 +596,14 @@ void ProjectList::slotAddFolder(const QString foldername, const QString &clipId,
             }
         } else {
             QStringList text;
-            text << QString() << foldername;
+            text << foldername;
             m_listView->blockSignals(true);
-            m_listView->setCurrentItem(new ProjectItem(m_listView, text, clipId));
+            m_listView->setCurrentItem(new FolderProjectItem(m_listView, text, clipId));
             m_doc->clipManager()->addFolder(clipId, foldername);
             m_listView->blockSignals(false);
         }
     }
+    m_doc->setModified(true);
 }
 
 
@@ -592,7 +618,6 @@ void ProjectList::deleteProjectFolder(QMap <QString, QString> map)
         new AddFolderCommand(this, i.key(), i.value(), false, delCommand);
     }
     m_commandStack->push(delCommand);
-    m_doc->setModified(true);
 }
 
 void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
@@ -610,14 +635,14 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
     const QString parent = clip->getProperty("groupid");
     ProjectItem *item = NULL;
     if (!parent.isEmpty()) {
-        ProjectItem *parentitem = getFolderItemById(parent);
+        FolderProjectItem *parentitem = getFolderItemById(parent);
         if (!parentitem) {
             QStringList text;
             QString groupName = clip->getProperty("groupname");
             //kDebug() << "Adding clip to new group: " << groupName;
             if (groupName.isEmpty()) groupName = i18n("Folder");
-            text << QString() << groupName;
-            parentitem = new ProjectItem(m_listView, text, parent);
+            text << groupName;
+            parentitem = new FolderProjectItem(m_listView, text, parent);
         } else {
             //kDebug() << "Adding clip to existing group: " << parentitem->groupName();
         }
@@ -637,14 +662,13 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
         // if file has Nepomuk comment, use it
         Nepomuk::Resource f(url.path());
         QString annotation = f.description();
-        if (!annotation.isEmpty()) item->setText(2, annotation);
-        item->setText(3, QString::number(f.rating()));
+        if (!annotation.isEmpty()) item->setText(1, annotation);
+        item->setText(2, 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()) {
@@ -654,7 +678,6 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
                 }
             }
         }
-        m_listView->blockSignals(false);
     }
 
     if (getProperties && m_listView->isEnabled()) m_listView->blockSignals(false);
@@ -710,7 +733,7 @@ void ProjectList::updateAllClips()
     ProjectItem *item;
     m_listView->blockSignals(true);
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() == PROJECTSUBCLIPTYPE) {
             // subitem
             SubProjectItem *sub = static_cast <SubProjectItem *>(*it);
             if (sub->icon(0).isNull()) {
@@ -719,25 +742,27 @@ void ProjectList::updateAllClips()
             }
             ++it;
             continue;
+        } else if ((*it)->type() == PROJECTFOLDERTYPE) {
+            // folder
+            ++it;
+            continue;
         }
         item = static_cast <ProjectItem *>(*it);
-        if (!item->isGroup()) {
-            clip = item->referencedClip();
-            if (item->referencedClip()->producer() == NULL) {
-                if (clip->isPlaceHolder() == false) {
-                    requestClipInfo(clip->toXML(), clip->getId());
-                } else item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
-            } else {
-                if (item->icon(0).isNull()) {
-                    requestClipThumbnail(clip->getId());
-                }
-                if (item->data(1, DurationRole).toString().isEmpty()) {
-                    item->changeDuration(item->referencedClip()->producer()->get_playtime());
-                }
+        clip = item->referencedClip();
+        if (item->referencedClip()->producer() == NULL) {
+            if (clip->isPlaceHolder() == false) {
+                requestClipInfo(clip->toXML(), clip->getId());
+            } else item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
+        } else {
+            if (item->icon(0).isNull()) {
+                requestClipThumbnail(clip->getId());
+            }
+            if (item->data(0, DurationRole).toString().isEmpty()) {
+                item->changeDuration(item->referencedClip()->producer()->get_playtime());
             }
-            item->setData(1, UsageRole, QString::number(item->numReferences()));
-            //qApp->processEvents();
         }
+        item->setData(1, UsageRole, QString::number(item->numReferences()));
+        //qApp->processEvents();
         ++it;
     }
     qApp->processEvents();
@@ -875,20 +900,15 @@ void ProjectList::slotAddTitleTemplateClip()
 QStringList ProjectList::getGroup() const
 {
     QStringList result;
-    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());
-            if (item->isGroup()) break;
-        }
+    QTreeWidgetItem *item = m_listView->currentItem();
+    while (item && item->type() != PROJECTFOLDERTYPE) {
+        item = item->parent();
     }
-    if (item && item->isGroup()) {
-        result << item->groupName();
-        result << item->clipId();
+
+    if (item) {
+        FolderProjectItem *folder = static_cast <FolderProjectItem *>(item);
+        result << folder->groupName();
+        result << folder->clipId();
     } else result << QString() << QString();
     return result;
 }
@@ -911,7 +931,7 @@ void ProjectList::setDocument(KdenliveDoc *doc)
     QMapIterator<QString, QString> f(flist);
     while (f.hasNext()) {
         f.next();
-        (void) new ProjectItem(m_listView, QStringList() << QString() << f.value(), f.key());
+        (void) new FolderProjectItem(m_listView, QStringList() << f.value(), f.key());
     }
 
     QList <DocClipBase*> list = doc->clipManager()->documentClipList();
@@ -939,13 +959,12 @@ QDomElement ProjectList::producersList()
     kDebug() << "////////////  PRO LISTĀ BUILD PRDSLIST ";
     QTreeWidgetItemIterator it(m_listView);
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             // subitem
             ++it;
             continue;
         }
-        if (!((ProjectItem *)(*it))->isGroup())
-            prods.appendChild(doc.importNode(((ProjectItem *)(*it))->toXml(), true));
+        prods.appendChild(doc.importNode(((ProjectItem *)(*it))->toXml(), true));
         ++it;
     }
     return prods;
@@ -968,13 +987,12 @@ void ProjectList::reloadClipThumbnails()
     m_thumbnailQueue.clear();
     QTreeWidgetItemIterator it(m_listView);
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             // subitem
             ++it;
             continue;
         }
-        if (!((ProjectItem *)(*it))->isGroup())
-            m_thumbnailQueue << ((ProjectItem *)(*it))->clipId();
+        m_thumbnailQueue << ((ProjectItem *)(*it))->clipId();
         ++it;
     }
     QTimer::singleShot(300, this, SLOT(slotProcessNextThumbnail()));
@@ -997,7 +1015,7 @@ void ProjectList::slotProcessNextThumbnail()
     }
     if (m_thumbnailQueue.count() > 1) {
         int max = m_doc->clipManager()->clipsCount();
-        emit displayMessage(i18n("Loading thumbnails"), (int)(100 * (max - m_thumbnailQueue.count()) / max));
+        emit displayMessage(i18n("Loading thumbnails"), (int)(100 *(max - m_thumbnailQueue.count()) / max));
     }
     slotRefreshClipThumbnail(m_thumbnailQueue.takeFirst(), false);
 }
@@ -1015,7 +1033,8 @@ void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update)
     ProjectItem *item = NULL;
     bool isSubItem = false;
     int frame;
-    if (it->type() == QTreeWidgetItem::UserType + 1) {
+    if (it->type() == PROJECTFOLDERTYPE) return;
+    if (it->type() == PROJECTSUBCLIPTYPE) {
         item = static_cast <ProjectItem *>(it->parent());
         frame = static_cast <SubProjectItem *>(it)->zone().x();
         isSubItem = true;
@@ -1055,7 +1074,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
     if (item && producer) {
         m_listView->blockSignals(true);
         item->setProperties(properties, metadata);
-        Q_ASSERT_X(item->referencedClip(), "void ProjectList::slotReplyGetFileProperties", QString("Item with groupName %1 does not have a clip associated").arg(item->groupName()).toLatin1());
+        //Q_ASSERT_X(item->referencedClip(), "void ProjectList::slotReplyGetFileProperties", QString("Item with groupName %1 does not have a clip associated").arg(item->groupName()).toLatin1());
         item->referencedClip()->setProducer(producer, replace);
         //emit receivedClipDuration(clipId);
         if (m_listView->isEnabled() && replace) {
@@ -1074,7 +1093,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
         }
     } else kDebug() << "////////  COULD NOT FIND CLIP TO UPDATE PRPS...";
     int max = m_doc->clipManager()->clipsCount();
-    emit displayMessage(i18n("Loading clips"), (int)(100 * (max - m_infoQueue.count()) / max));
+    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);
@@ -1104,19 +1123,19 @@ QTreeWidgetItem *ProjectList::getAnyItemById(const QString &id)
 
     ProjectItem *result = NULL;
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             // subitem
             ++it;
             continue;
         }
         ProjectItem *item = static_cast<ProjectItem *>(*it);
-        if (item->clipId() == lookId && item->clipType() != FOLDER) {
+        if (item->clipId() == lookId) {
             result = item;
             break;
         }
         ++it;
     }
-    if (!id.contains('#')) return result;
+    if (result == NULL || !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()) {
@@ -1133,27 +1152,28 @@ ProjectItem *ProjectList::getItemById(const QString &id)
     ProjectItem *item;
     QTreeWidgetItemIterator it(m_listView);
     while (*it) {
-        if ((*it)->type() == QTreeWidgetItem::UserType + 1) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
             // subitem
             ++it;
             continue;
         }
         item = static_cast<ProjectItem *>(*it);
-        if (item->clipId() == id && item->clipType() != FOLDER)
+        if (item->clipId() == id)
             return item;
         ++it;
     }
     return NULL;
 }
 
-ProjectItem *ProjectList::getFolderItemById(const QString &id)
+FolderProjectItem *ProjectList::getFolderItemById(const QString &id)
 {
-    ProjectItem *item;
+    FolderProjectItem *item;
     QTreeWidgetItemIterator it(m_listView);
     while (*it) {
-        item = static_cast<ProjectItem *>(*it);
-        if (item->clipId() == id && item->clipType() == FOLDER)
+        if ((*it)->type() == PROJECTFOLDERTYPE) {
+            item = static_cast<FolderProjectItem *>(*it);
             return item;
+        }
         ++it;
     }
     return NULL;
@@ -1182,7 +1202,8 @@ void ProjectList::slotSelectClip(const QString &ix)
 QString ProjectList::currentClipUrl() const
 {
     ProjectItem *item;
-    if (m_listView->currentItem()->type() == QTreeWidgetItem::UserType + 1) {
+    if (!m_listView->currentItem() || m_listView->currentItem()->type() == PROJECTFOLDERTYPE) return QString();
+    if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
         // subitem
         item = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
     } else item = static_cast <ProjectItem*>(m_listView->currentItem());
@@ -1237,7 +1258,6 @@ void ProjectList::slotAddClipCut(const QString &id, int in, int out)
 
 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();
@@ -1245,7 +1265,7 @@ void ProjectList::addClipCut(const QString &id, int in, int 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());
+        QPixmap p = clip->referencedClip()->thumbProducer()->extractImage(in, (int)(sub->sizeHint(0).height()  * m_render->dar()), sub->sizeHint(0).height() - 2);
         sub->setIcon(0, p);
         m_doc->cachePixmap(clip->getClipHash() + '#' + QString::number(in), p);
         m_listView->blockSignals(false);
@@ -1254,14 +1274,13 @@ void ProjectList::addClipCut(const QString &id, int in, int out)
 
 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;
+            if (it->type() != PROJECTSUBCLIPTYPE) continue;
             SubProjectItem *sub = static_cast <SubProjectItem*>(it);
             if (sub->zone() == QPoint(in, out)) {
                 m_listView->blockSignals(true);