]> git.sesse.net Git - kdenlive/blobdiff - src/projectlist.cpp
First step for implementation of proxy editing (for testing purpose only)
[kdenlive] / src / projectlist.cpp
index 18562312f62821e09ddc82d3d787e8be209bf200..b2837a206950e25ffc1cd7b044bc69ccc319871e 100644 (file)
@@ -48,6 +48,7 @@
 #include <KMessageBox>
 #include <KIO/NetAccess>
 #include <KFileItem>
+#include <KApplication>
 #ifdef NEPOMUK
 #include <nepomuk/global.h>
 #include <nepomuk/resourcemanager.h>
@@ -68,8 +69,6 @@ ProjectList::ProjectList(QWidget *parent) :
     m_render(NULL),
     m_fps(-1),
     m_commandStack(NULL),
-    m_editAction(NULL),
-    m_deleteAction(NULL),
     m_openAction(NULL),
     m_reloadAction(NULL),
     m_transcodeAction(NULL),
@@ -78,27 +77,39 @@ ProjectList::ProjectList(QWidget *parent) :
     m_infoQueue(),
     m_thumbnailQueue()
 {
-
-    m_listView = new ProjectListView(this);;
     QVBoxLayout *layout = new QVBoxLayout;
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setSpacing(0);
 
     // setup toolbar
-    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);
+    QFrame *frame = new QFrame;
+    frame->setFrameStyle(QFrame::NoFrame);
+    QHBoxLayout *box = new QHBoxLayout;
+    KTreeWidgetSearchLine *searchView = new KTreeWidgetSearchLine;
+
+    box->addWidget(searchView);
+    //int s = style()->pixelMetric(QStyle::PM_SmallIconSize);
+    //m_toolbar->setIconSize(QSize(s, s));
 
-    m_addButton = new QToolButton(m_toolbar);
+    m_addButton = new QToolButton;
     m_addButton->setPopupMode(QToolButton::MenuButtonPopup);
-    m_toolbar->addWidget(m_addButton);
+    m_addButton->setAutoRaise(true);
+    box->addWidget(m_addButton);
+
+    m_editButton = new QToolButton;
+    m_editButton->setAutoRaise(true);
+    box->addWidget(m_editButton);
+
+    m_deleteButton = new QToolButton;
+    m_deleteButton->setAutoRaise(true);
+    box->addWidget(m_deleteButton);
+    frame->setLayout(box);
+    layout->addWidget(frame);
 
-    layout->addWidget(m_toolbar);
+    m_listView = new ProjectListView;
     layout->addWidget(m_listView);
     setLayout(layout);
+    searchView->setTreeWidget(m_listView);
 
     m_queueTimer.setInterval(100);
     connect(&m_queueTimer, SIGNAL(timeout()), this, SLOT(slotProcessNextClipInQueue()));
@@ -132,7 +143,6 @@ ProjectList::ProjectList(QWidget *parent) :
 ProjectList::~ProjectList()
 {
     delete m_menu;
-    delete m_toolbar;
     m_listView->blockSignals(true);
     m_listView->clear();
     delete m_listViewDelegate;
@@ -148,13 +158,11 @@ void ProjectList::setupMenu(QMenu *addMenu, QAction *defaultAction)
     QList <QAction *> actions = addMenu->actions();
     for (int i = 0; i < actions.count(); i++) {
         if (actions.at(i)->data().toString() == "clip_properties") {
-            m_editAction = actions.at(i);
-            m_toolbar->addAction(m_editAction);
+            m_editButton->setDefaultAction(actions.at(i));
             actions.removeAt(i);
             i--;
         } else if (actions.at(i)->data().toString() == "delete_clip") {
-            m_deleteAction = actions.at(i);
-            m_toolbar->addAction(m_deleteAction);
+            m_deleteButton->setDefaultAction(actions.at(i));
             actions.removeAt(i);
             i--;
         } else if (actions.at(i)->data().toString() == "edit_clip") {
@@ -194,10 +202,10 @@ void ProjectList::setupGeneratorMenu(QMenu *addMenu, QMenu *transcodeMenu, QMenu
     m_menu->addAction(m_reloadAction);
     m_menu->addMenu(inTimelineMenu);
     inTimelineMenu->setEnabled(false);
-    m_menu->addAction(m_editAction);
+    m_menu->addAction(m_editButton->defaultAction());
     m_menu->addAction(m_openAction);
-    m_menu->addAction(m_deleteAction);
-    m_menu->insertSeparator(m_deleteAction);
+    m_menu->addAction(m_deleteButton->defaultAction());
+    m_menu->insertSeparator(m_deleteButton->defaultAction());
 }
 
 
@@ -241,12 +249,16 @@ void ProjectList::editClipSelection(QList<QTreeWidgetItem *> list)
     // Gather all common properties
     QMap <QString, QString> commonproperties;
     QList <DocClipBase *> clipList;
-    commonproperties.insert("force_aspect_ratio", "-");
+    commonproperties.insert("force_aspect_num", "-");
+    commonproperties.insert("force_aspect_den", "-");
     commonproperties.insert("force_fps", "-");
     commonproperties.insert("force_progressive", "-");
+    commonproperties.insert("force_tff", "-");
     commonproperties.insert("threads", "-");
     commonproperties.insert("video_index", "-");
     commonproperties.insert("audio_index", "-");
+    commonproperties.insert("force_colorspace", "-");
+    commonproperties.insert("full_luma", "-");
 
     bool allowDurationChange = true;
     int commonDuration = -1;
@@ -312,13 +324,13 @@ void ProjectList::slotOpenClip()
     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"));
+                KMessageBox::sorry(kapp->activeWindow(), i18n("Please set a default application to open images in the Settings dialog"));
             else
                 QProcess::startDetached(KdenliveSettings::defaultimageapp(), QStringList() << item->clipUrl().path());
         }
         if (item->clipType() == AUDIO) {
             if (KdenliveSettings::defaultaudioapp().isEmpty())
-                KMessageBox::sorry(this, i18n("Please set a default application to open audio files in the Settings dialog"));
+                KMessageBox::sorry(kapp->activeWindow(), i18n("Please set a default application to open audio files in the Settings dialog"));
             else
                 QProcess::startDetached(KdenliveSettings::defaultaudioapp(), QStringList() << item->clipUrl().path());
         }
@@ -402,18 +414,28 @@ void ProjectList::slotReloadClip(const QString &id)
         }
         item = static_cast <ProjectItem *>(selected.at(i));
         if (item) {
-            if (item->clipType() == TEXT) {
+            CLIPTYPE t = item->clipType();
+            if (t == TEXT) {
                 if (!item->referencedClip()->getProperty("xmltemplate").isEmpty())
                     regenerateTemplate(item);
-            } else if (item->clipType() != COLOR && item->clipType() != SLIDESHOW && item->referencedClip() &&  item->referencedClip()->checkHash() == false) {
+            } else if (t != COLOR && t != SLIDESHOW && item->referencedClip() &&  item->referencedClip()->checkHash() == false) {
                 item->referencedClip()->setPlaceHolder(true);
                 item->setProperty("file_hash", QString());
-            } else if (item->clipType() == IMAGE) {
+            } else if (t == IMAGE) {
                 item->referencedClip()->producer()->set("force_reload", 1);
             }
-            //requestClipInfo(item->toXml(), item->clipId(), true);
-            // Clear the file_hash value, which will cause a complete reload of the clip
-            emit getFileProperties(item->toXml(), item->clipId(), m_listView->iconSize().height(), true);
+
+            QDomElement e = item->toXml();
+            // Make sure we get the correct producer length if it was adjusted in timeline
+            if (t == COLOR || t == IMAGE || t == SLIDESHOW || t == TEXT) {
+                int length = QString(item->referencedClip()->producerProperty("length")).toInt();
+                if (length > 0 && !e.hasAttribute("length")) {
+                    e.setAttribute("length", length);
+                    e.setAttribute("out", length - 1);
+                }
+            }
+            
+            emit getFileProperties(e, item->clipId(), m_listView->iconSize().height(), true);
         }
     }
 }
@@ -497,8 +519,8 @@ void ProjectList::slotClipSelected()
     if (m_listView->currentItem()) {
         if (m_listView->currentItem()->type() == PROJECTFOLDERTYPE) {
             emit clipSelected(NULL);
-            m_editAction->setEnabled(false);
-            m_deleteAction->setEnabled(true);
+            m_editButton->defaultAction()->setEnabled(false);
+            m_deleteButton->defaultAction()->setEnabled(true);
             m_openAction->setEnabled(false);
             m_reloadAction->setEnabled(false);
             m_transcodeAction->setEnabled(false);
@@ -506,7 +528,7 @@ void ProjectList::slotClipSelected()
             ProjectItem *clip;
             if (m_listView->currentItem()->type() == PROJECTSUBCLIPTYPE) {
                 // this is a sub item, use base clip
-                m_deleteAction->setEnabled(true);
+                m_deleteButton->defaultAction()->setEnabled(true);
                 clip = static_cast <ProjectItem*>(m_listView->currentItem()->parent());
                 if (clip == NULL) kDebug() << "-----------ERROR";
                 SubProjectItem *sub = static_cast <SubProjectItem*>(m_listView->currentItem());
@@ -517,8 +539,8 @@ void ProjectList::slotClipSelected()
             clip = static_cast <ProjectItem*>(m_listView->currentItem());
             if (clip)
                 emit clipSelected(clip->referencedClip());
-            m_editAction->setEnabled(true);
-            m_deleteAction->setEnabled(true);
+            m_editButton->defaultAction()->setEnabled(true);
+            m_deleteButton->defaultAction()->setEnabled(true);
             m_reloadAction->setEnabled(true);
             m_transcodeAction->setEnabled(true);
             if (clip && clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
@@ -537,8 +559,8 @@ void ProjectList::slotClipSelected()
         }
     } else {
         emit clipSelected(NULL);
-        m_editAction->setEnabled(false);
-        m_deleteAction->setEnabled(false);
+        m_editButton->defaultAction()->setEnabled(false);
+        m_deleteButton->defaultAction()->setEnabled(false);
         m_openAction->setEnabled(false);
         m_reloadAction->setEnabled(false);
         m_transcodeAction->setEnabled(false);
@@ -579,11 +601,17 @@ void ProjectList::slotUpdateClipProperties(const QString &id, QMap <QString, QSt
     ProjectItem *item = getItemById(id);
     if (item) {
         slotUpdateClipProperties(item, properties);
-        if (properties.contains("out") || properties.contains("force_fps")) {
+        if (properties.contains("out") || properties.contains("force_fps") || properties.contains("resource")) {
             slotReloadClip(id);
-        } else if (properties.contains("colour") || properties.contains("resource") || properties.contains("xmldata") || properties.contains("force_aspect_ratio") || properties.contains("templatetext")) {
+        } else if (properties.contains("colour") ||
+                   properties.contains("xmldata") ||
+                   properties.contains("force_aspect_num") ||
+                   properties.contains("force_aspect_den") ||
+                   properties.contains("templatetext")) {
             slotRefreshClipThumbnail(item);
             emit refreshClip();
+        } else if (properties.contains("full_luma") || properties.contains("force_colorspace")) {
+            emit refreshClip();
         }
     }
 }
@@ -680,8 +708,8 @@ void ProjectList::slotItemEdited(QTreeWidgetItem *item, int column)
 void ProjectList::slotContextMenu(const QPoint &pos, QTreeWidgetItem *item)
 {
     bool enable = item ? true : false;
-    m_editAction->setEnabled(enable);
-    m_deleteAction->setEnabled(enable);
+    m_editButton->defaultAction()->setEnabled(enable);
+    m_deleteButton->defaultAction()->setEnabled(enable);
     m_reloadAction->setEnabled(enable);
     m_transcodeAction->setEnabled(enable);
     if (enable) {
@@ -724,7 +752,6 @@ void ProjectList::slotRemoveClip()
 
     QUndoCommand *delCommand = new QUndoCommand();
     delCommand->setText(i18n("Delete Clip Zone"));
-
     for (int i = 0; i < selected.count(); i++) {
         if (selected.at(i)->type() == PROJECTSUBCLIPTYPE) {
             // subitem
@@ -737,7 +764,7 @@ void ProjectList::slotRemoveClip()
             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)
+            if (children > 0 && KMessageBox::questionYesNo(kapp->activeWindow(), 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 *>(folder->child(i));
@@ -746,11 +773,13 @@ void ProjectList::slotRemoveClip()
         } else {
             ProjectItem *item = static_cast <ProjectItem *>(selected.at(i));
             ids << item->clipId();
-            if (item->numReferences() > 0 && 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)
+            if (item->numReferences() > 0 && KMessageBox::questionYesNo(kapp->activeWindow(), 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"), KStandardGuiItem::yes(), KStandardGuiItem::no(), "DeleteAll") == KMessageBox::No) {
+                KMessageBox::enableMessage("DeleteAll");
                 return;
+            }
         }
     }
-
+    KMessageBox::enableMessage("DeleteAll");
     if (delCommand->childCount() == 0)
         delete delCommand;
     else
@@ -761,14 +790,14 @@ void ProjectList::slotRemoveClip()
 void ProjectList::updateButtons() const
 {
     if (m_listView->topLevelItemCount() == 0) {
-        m_deleteAction->setEnabled(false);
+        m_deleteButton->defaultAction()->setEnabled(false);
     } else {
-        m_deleteAction->setEnabled(true);
+        m_deleteButton->defaultAction()->setEnabled(true);
         if (!m_listView->currentItem())
             m_listView->setCurrentItem(m_listView->topLevelItem(0));
         QTreeWidgetItem *item = m_listView->currentItem();
         if (item && item->type() == PROJECTCLIPTYPE) {
-            m_editAction->setEnabled(true);
+            m_editButton->defaultAction()->setEnabled(true);
             m_openAction->setEnabled(true);
             m_reloadAction->setEnabled(true);
             m_transcodeAction->setEnabled(true);
@@ -776,7 +805,7 @@ void ProjectList::updateButtons() const
         }
     }
 
-    m_editAction->setEnabled(false);
+    m_editButton->defaultAction()->setEnabled(false);
     m_openAction->setEnabled(false);
     m_reloadAction->setEnabled(false);
     m_transcodeAction->setEnabled(false);
@@ -884,16 +913,7 @@ void ProjectList::deleteProjectFolder(QMap <QString, QString> map)
 void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
 {
     m_listView->setEnabled(false);
-    if (getProperties) {
-        m_listView->blockSignals(true);
-        m_refreshed = false;
-        // remove file_hash so that we load all properties for the clip
-        QDomElement e = clip->toXML().cloneNode().toElement();
-        e.removeAttribute("file_hash");
-        m_infoQueue.insert(clip->getId(), e);
-        //m_render->getFileProperties(clip->toXML(), clip->getId(), true);
-    }
-    clip->askForAudioThumbs();
+    if (getProperties) m_listView->blockSignals(true);
     const QString parent = clip->getProperty("groupid");
     ProjectItem *item = NULL;
     if (!parent.isEmpty()) {
@@ -912,8 +932,40 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
     }
     if (item == NULL)
         item = new ProjectItem(m_listView, clip);
+    if (item->data(0, DurationRole).isNull()) item->setData(0, DurationRole, i18n("Loading"));
+    if (getProperties) {
+        m_listView->blockSignals(true);
+        m_refreshed = false;
+        
+        // Proxy clips
+        CLIPTYPE t = clip->clipType();
+        if ((t == VIDEO || t == AV || t == UNKNOWN) && KdenliveSettings::enableproxy()) {
+            if (clip->getProperty("proxy").isEmpty()) {
+                connect(clip, SIGNAL(proxyReady(const QString, bool)), this, SLOT(slotGotProxy(const QString, bool)));
+                item->setProxyStatus(1);
+                clip->generateProxy(m_doc->projectFolder());
+            }
+            else {
+                // Proxy clip already created
+                item->setProxyStatus(2);
+                QDomElement e = clip->toXML().cloneNode().toElement();
+                e.removeAttribute("file_hash");
+                m_infoQueue.insert(clip->getId(), e);
+                
+            }
+        }
+        else {
+            // We don't use proxies
+            // remove file_hash so that we load all properties for the clip
+            QDomElement e = clip->toXML().cloneNode().toElement();
+            e.removeAttribute("file_hash");
+            m_infoQueue.insert(clip->getId(), e);
+        }
+        //m_render->getFileProperties(clip->toXML(), clip->getId(), true);
+    }
+    clip->askForAudioThumbs();
+    
     KUrl url = clip->fileURL();
-
     if (getProperties == false && !clip->getClipHash().isEmpty()) {
         QString cachedPixmap = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "thumbs/" + clip->getClipHash() + ".png";
         if (QFile::exists(cachedPixmap)) {
@@ -953,10 +1005,30 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
         if (getProperties)
             m_listView->blockSignals(false);
     }
+    
     if (getProperties && !m_queueTimer.isActive())
         slotProcessNextClipInQueue();
 }
 
+void ProjectList::slotGotProxy(const QString id, bool success)
+{
+    ProjectItem *item = getItemById(id);
+    if (item) {
+        disconnect(m_listView, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotItemEdited(QTreeWidgetItem *, int)));
+        if (success) {
+            // Proxy clip successfully created
+            item->setProxyStatus(2);
+            QDomElement e = item->referencedClip()->toXML().cloneNode().toElement();  
+            e.removeAttribute("file_hash");
+            m_infoQueue.insert(id, e);
+            if (!m_queueTimer.isActive()) slotProcessNextClipInQueue();
+        }
+        else item->setProxyStatus(0);
+        connect(m_listView, SIGNAL(itemChanged(QTreeWidgetItem *, int)), this, SLOT(slotItemEdited(QTreeWidgetItem *, int)));
+        update();
+    }
+}
+
 void ProjectList::slotResetProjectList()
 {
     m_listView->clear();
@@ -1054,8 +1126,8 @@ QString ProjectList::getExtensions()
 {
     // Build list of mime types
     QStringList mimeTypes = QStringList() << "application/x-kdenlive" << "application/x-kdenlivetitle" << "video/mlt-playlist" << "text/plain"
-                            << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "video/mp4" << "video/quicktime"
-                            << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "application/ogg" << "application/mxf"
+                            << "video/x-flv" << "application/vnd.rn-realmedia" << "video/x-dv" << "video/dv" << "video/x-msvideo" << "video/x-matroska" << "video/mpeg" << "video/ogg" << "video/x-ms-wmv" << "video/mp4" << "video/quicktime" << "video/webm"
+                            << "audio/x-flac" << "audio/x-matroska" << "audio/mp4" << "audio/mpeg" << "audio/x-mp3" << "audio/ogg" << "audio/x-wav" << "application/ogg" << "application/mxf" << "application/x-shockwave-flash"
                             << "image/gif" << "image/jpeg" << "image/png" << "image/x-tga" << "image/x-bmp" << "image/svg+xml" << "image/tiff" << "image/x-xcf" << "image/x-xcf-gimp" << "image/x-vnd.adobe.photoshop" << "image/x-pcx" << "image/x-exr";
 
     QString allExtensions;
@@ -1080,7 +1152,7 @@ void ProjectList::slotAddClip(const QList <QUrl> givenList, const QString &group
         const QString dialogFilter = allExtensions + ' ' + QLatin1Char('|') + i18n("All Supported Files") + "\n* " + QLatin1Char('|') + i18n("All Files");
         QCheckBox *b = new QCheckBox(i18n("Import image sequence"));
         b->setChecked(KdenliveSettings::autoimagesequence());
-        KFileDialog *d = new KFileDialog(KUrl("kfiledialog:///clipfolder"), dialogFilter, this, b);
+        KFileDialog *d = new KFileDialog(KUrl("kfiledialog:///clipfolder"), dialogFilter, kapp->activeWindow(), b);
         d->setOperationMode(KFileDialog::Opening);
         d->setMode(KFile::Files);
         d->exec();
@@ -1092,9 +1164,10 @@ void ProjectList::slotAddClip(const QList <QUrl> givenList, const QString &group
             if (fileName.at(fileName.size() - 1).isDigit()) {
                 KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
                 if (item.mimetype().startsWith("image")) {
-                    int count = 0;
                     // import as sequence if we found more than one image in the sequence
-                    QString pattern = SlideshowClip::selectedPath(url.path(), false, QString(), &count);
+                    QStringList list;
+                    QString pattern = SlideshowClip::selectedPath(url.path(), false, QString(), &list);
+                    int count = list.count();
                     if (count > 1) {
                         delete d;
                         QStringList groupInfo = getGroup();
@@ -1148,8 +1221,8 @@ void ProjectList::slotRemoveInvalidClip(const QString &id, bool replace)
         if (item->referencedClip()->isPlaceHolder()) replace = false;
         if (!path.isEmpty()) {
             if (replace)
-                KMessageBox::sorry(this, i18n("Clip <b>%1</b><br />is invalid, will be removed from project.", path));
-            else if (KMessageBox::questionYesNo(this, i18n("Clip <b>%1</b><br />is missing or invalid. Remove it from project?", path), i18n("Invalid clip")) == KMessageBox::Yes)
+                KMessageBox::sorry(kapp->activeWindow(), i18n("Clip <b>%1</b><br />is invalid, will be removed from project.", path));
+            else if (KMessageBox::questionYesNo(kapp->activeWindow(), i18n("Clip <b>%1</b><br />is missing or invalid. Remove it from project?", path), i18n("Invalid clip")) == KMessageBox::Yes)
                 replace = true;
         }
         if (replace)
@@ -1230,7 +1303,7 @@ void ProjectList::slotAddTitleTemplateClip()
 
     if (!templateFiles.isEmpty())
         dia_ui.buttonBox->button(QDialogButtonBox::Ok)->setFocus();
-    dia_ui.template_list->fileDialog()->setFilter("*.kdenlivetitle");
+    dia_ui.template_list->fileDialog()->setFilter("application/x-kdenlivetitle");
     //warning: setting base directory doesn't work??
     KUrl startDir(path);
     dia_ui.template_list->fileDialog()->setUrl(startDir);
@@ -1286,7 +1359,6 @@ void ProjectList::setDocument(KdenliveDoc *doc)
         slotAddClip(list.at(i), false);
 
     m_listView->blockSignals(false);
-    m_toolbar->setEnabled(true);
     connect(m_doc->clipManager(), SIGNAL(reloadClip(const QString &)), this, SLOT(slotReloadClip(const QString &)));
     connect(m_doc->clipManager(), SIGNAL(modifiedClip(const QString &)), this, SLOT(slotModifiedClip(const QString &)));
     connect(m_doc->clipManager(), SIGNAL(missingClip(const QString &)), this, SLOT(slotMissingClip(const QString &)));
@@ -1337,7 +1409,6 @@ void ProjectList::slotCheckForEmptyQueue()
 
 void ProjectList::reloadClipThumbnails()
 {
-    kDebug() << "//////////////  RELOAD CLIPS THUMBNAILS!!!";
     m_thumbnailQueue.clear();
     QTreeWidgetItemIterator it(m_listView);
     while (*it) {
@@ -1427,7 +1498,8 @@ void ProjectList::slotRefreshClipThumbnail(QTreeWidgetItem *it, bool update)
         }
         if (update)
             emit projectModified();
-        QTimer::singleShot(30, this, SLOT(slotProcessNextThumbnail()));
+
+        slotProcessNextThumbnail();
     }
 }
 
@@ -1443,7 +1515,6 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
             item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
             toReload = clipId;
         }
-        //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);
         item->referencedClip()->askForAudioThumbs();
         if (!replace && item->data(0, Qt::DecorationRole).isNull())
@@ -1451,7 +1522,6 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
         if (!toReload.isEmpty())
             item->slotSetToolTip();
 
-        //emit receivedClipDuration(clipId);
         if (m_listView->isEnabled() && replace) {
             // update clip in clip monitor
             emit clipSelected(NULL);
@@ -1470,66 +1540,85 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
             requestClipThumbnail(clipId);
         }*/
     } else kDebug() << "////////  COULD NOT FIND CLIP TO UPDATE PRPS...";
-    int max = m_doc->clipManager()->clipsCount();
     if (item && m_infoQueue.isEmpty() && m_thumbnailQueue.isEmpty()) {
         m_listView->setCurrentItem(item);
-        bool displayClipInMonitor = true;
+        bool updatedProfile = false;
         if (item->parent()) {
             if (item->parent()->type() == PROJECTFOLDERTYPE)
                 static_cast <FolderProjectItem *>(item->parent())->switchIcon();
         } else if (KdenliveSettings::checkfirstprojectclip() &&  m_listView->topLevelItemCount() == 1) {
             // this is the first clip loaded in project, check if we want to adjust project settings to the clip
-            int width = properties.value("frame_size").section('x', 0, 0).toInt();
-            int height = properties.value("frame_size").section('x', -1).toInt();
-            double fps = properties.value("fps").toDouble();
-            double par = properties.value("aspect_ratio").toDouble();
-            if (item->clipType() == IMAGE || item->clipType() == AV || item->clipType() == VIDEO) {
-                if (ProfilesDialog::matchProfile(width, height, fps, par, item->clipType() == IMAGE, m_doc->mltProfile()) == false) {
-                    // get a list of compatible profiles
-                    QMap <QString, QString> suggestedProfiles = ProfilesDialog::getProfilesFromProperties(width, height, fps, par, item->clipType() == IMAGE);
-                    if (!suggestedProfiles.isEmpty()) {
-                        KDialog *dialog = new KDialog(this);
-                        dialog->setCaption(i18n("Change project profile"));
-                        dialog->setButtons(KDialog::Ok | KDialog::Cancel);
-
-                        QWidget container;
-                        QVBoxLayout *l = new QVBoxLayout;
-                        QLabel *label = new QLabel(i18n("Your clip does not match current project's profile.\nDo you want to change the project profile?\n\nThe following profiles match the clip (size: %1, fps: %2)", properties.value("frame_size"), fps));
-                        l->addWidget(label);
-                        QListWidget *list = new QListWidget;
-                        list->setAlternatingRowColors(true);
-                        QMapIterator<QString, QString> i(suggestedProfiles);
-                        while (i.hasNext()) {
-                            i.next();
-                            QListWidgetItem *item = new QListWidgetItem(i.value(), list);
-                            item->setData(Qt::UserRole, i.key());
-                            item->setToolTip(i.key());
-                        }
-                        list->setCurrentRow(0);
-                        l->addWidget(list);
-                        container.setLayout(l);
-                        dialog->setButtonText(KDialog::Ok, i18n("Update profile"));
-                        dialog->setMainWidget(&container);
-                        if (dialog->exec() == QDialog::Accepted) {
-                            //Change project profile
-                            displayClipInMonitor = false;
-                            if (list->currentItem())
-                                emit updateProfile(list->currentItem()->data(Qt::UserRole).toString());
-                        }
-                        delete list;
-                        delete label;
-                    } else KMessageBox::information(this, i18n("Your clip does not match current project's profile.\nNo existing profile found to match the clip's properties.\nClip size: %1\nFps: %2\n", properties.value("frame_size"), fps));
-                }
-            }
+            updatedProfile = adjustProjectProfileToItem(item);
         }
-        if (displayClipInMonitor) emit clipSelected(item->referencedClip());
+        if (updatedProfile == false) emit clipSelected(item->referencedClip());
     } else {
+        int max = m_doc->clipManager()->clipsCount();
         emit displayMessage(i18n("Loading clips"), (int)(100 *(max - m_infoQueue.count()) / max));
     }
     if (!toReload.isEmpty())
         emit clipNeedsReload(toReload, true);
-    // small delay so that the app can display the progress info
-    QTimer::singleShot(30, this, SLOT(slotProcessNextClipInQueue()));
+
+    qApp->processEvents();
+    slotProcessNextClipInQueue();
+}
+
+bool ProjectList::adjustProjectProfileToItem(ProjectItem *item)
+{
+    if (item == NULL) {
+        if (m_listView->currentItem() && m_listView->currentItem()->type() != PROJECTFOLDERTYPE)
+            item = static_cast <ProjectItem*>(m_listView->currentItem());
+    }
+    if (item == NULL || item->referencedClip() == NULL) {
+        KMessageBox::information(kapp->activeWindow(), i18n("Cannot find profile from current clip"));
+        return false;
+    }
+    bool profileUpdated = false;
+    QString size = item->referencedClip()->getProperty("frame_size");
+    int width = size.section('x', 0, 0).toInt();
+    int height = size.section('x', -1).toInt();
+    double fps = item->referencedClip()->getProperty("fps").toDouble();
+    double par = item->referencedClip()->getProperty("aspect_ratio").toDouble();
+    if (item->clipType() == IMAGE || item->clipType() == AV || item->clipType() == VIDEO) {
+        if (ProfilesDialog::matchProfile(width, height, fps, par, item->clipType() == IMAGE, m_doc->mltProfile()) == false) {
+            // get a list of compatible profiles
+            QMap <QString, QString> suggestedProfiles = ProfilesDialog::getProfilesFromProperties(width, height, fps, par, item->clipType() == IMAGE);
+            if (!suggestedProfiles.isEmpty()) {
+                KDialog *dialog = new KDialog(this);
+                dialog->setCaption(i18n("Change project profile"));
+                dialog->setButtons(KDialog::Ok | KDialog::Cancel);
+
+                QWidget container;
+                QVBoxLayout *l = new QVBoxLayout;
+                QLabel *label = new QLabel(i18n("Your clip does not match current project's profile.\nDo you want to change the project profile?\n\nThe following profiles match the clip (size: %1, fps: %2)", size, fps));
+                l->addWidget(label);
+                QListWidget *list = new QListWidget;
+                list->setAlternatingRowColors(true);
+                QMapIterator<QString, QString> i(suggestedProfiles);
+                while (i.hasNext()) {
+                    i.next();
+                    QListWidgetItem *item = new QListWidgetItem(i.value(), list);
+                    item->setData(Qt::UserRole, i.key());
+                    item->setToolTip(i.key());
+                }
+                list->setCurrentRow(0);
+                l->addWidget(list);
+                container.setLayout(l);
+                dialog->setButtonText(KDialog::Ok, i18n("Update profile"));
+                dialog->setMainWidget(&container);
+                if (dialog->exec() == QDialog::Accepted) {
+                    //Change project profile
+                    profileUpdated = true;
+                    if (list->currentItem())
+                        emit updateProfile(list->currentItem()->data(Qt::UserRole).toString());
+                }
+                delete list;
+                delete label;
+            } else if (fps > 0) {
+                KMessageBox::information(kapp->activeWindow(), i18n("Your clip does not match current project's profile.\nNo existing profile found to match the clip's properties.\nClip size: %1\nFps: %2\n", size, fps));
+            }
+        }
+    }
+    return profileUpdated;
 }
 
 void ProjectList::slotReplyGetImage(const QString &clipId, const QPixmap &pix)
@@ -1618,8 +1707,8 @@ void ProjectList::slotSelectClip(const QString &ix)
     if (clip) {
         m_listView->setCurrentItem(clip);
         m_listView->scrollToItem(clip);
-        m_editAction->setEnabled(true);
-        m_deleteAction->setEnabled(true);
+        m_editButton->defaultAction()->setEnabled(true);
+        m_deleteButton->defaultAction()->setEnabled(true);
         m_reloadAction->setEnabled(true);
         m_transcodeAction->setEnabled(true);
         if (clip->clipType() == IMAGE && !KdenliveSettings::defaultimageapp().isEmpty()) {
@@ -1811,4 +1900,56 @@ void ProjectList::slotForceProcessing(const QString &id)
     }
 }
 
+void ProjectList::slotAddOrUpdateSequence(const QString frameName)
+{
+    QString fileName = KUrl(frameName).fileName().section('_', 0, -2);
+    QStringList list;
+    QString pattern = SlideshowClip::selectedPath(frameName, false, QString(), &list);
+    int count = list.count();
+    if (count > 1) {
+        const QList <DocClipBase *> existing = m_doc->clipManager()->getClipByResource(pattern);
+        if (!existing.isEmpty()) {
+            // Sequence already exists, update
+            QString id = existing.at(0)->getId();
+            //ProjectItem *item = getItemById(id);
+            QMap <QString, QString> oldprops;
+            QMap <QString, QString> newprops;
+            int ttl = existing.at(0)->getProperty("ttl").toInt();
+            oldprops["out"] = existing.at(0)->getProperty("out");
+            newprops["out"] = QString::number(ttl * count - 1);
+            slotUpdateClipProperties(id, newprops);
+            EditClipCommand *command = new EditClipCommand(this, id, oldprops, newprops, false);
+            m_commandStack->push(command);
+        } else {
+            // Create sequence
+            QStringList groupInfo = getGroup();
+            m_doc->slotCreateSlideshowClipFile(fileName, pattern, count, m_timecode.reformatSeparators(KdenliveSettings::sequence_duration()),
+                                               false, false, false,
+                                               m_timecode.getTimecodeFromFrames(int(ceil(m_timecode.fps()))), QString(), 0,
+                                               QString(), groupInfo.at(0), groupInfo.at(1));
+        }
+    } else emit displayMessage(i18n("Sequence not found"), -2);
+}
+
+QMap <QString, QString> ProjectList::getProxies()
+{
+    QMap <QString, QString> list;
+    ProjectItem *item;
+    QTreeWidgetItemIterator it(m_listView);
+    while (*it) {
+        if ((*it)->type() != PROJECTCLIPTYPE) {
+            // subitem
+            ++it;
+            continue;
+        }
+        item = static_cast<ProjectItem *>(*it);
+        if (item && item->referencedClip() != NULL) {
+            QString proxy = item->referencedClip()->getProperty("proxy");
+            if (!proxy.isEmpty()) list.insert(proxy, item->clipUrl().path());
+        }
+        ++it;
+    }
+    return list;
+}
+
 #include "projectlist.moc"