]> git.sesse.net Git - kdenlive/blobdiff - src/kdenlivedoc.cpp
Remove (old) LADSPA related code.
[kdenlive] / src / kdenlivedoc.cpp
index 119c352051ee639c93825ec7e67c91fb16a60d50..f453f70dc1ccaf4db089d323f8442fa6e4b195f2 100644 (file)
@@ -52,9 +52,9 @@
 
 #include <mlt++/Mlt.h>
 
-const double DOCUMENTVERSION = 0.85;
+const double DOCUMENTVERSION = 0.87;
 
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, const QPoint tracks, Render *render, KTextEdit *notes, MainWindow *parent, KProgressDialog *progressDialog) :
+KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, QString profileName, QMap <QString, QString> properties, const QPoint tracks, Render *render, KTextEdit *notes, bool *openBackup, MainWindow *parent, KProgressDialog *progressDialog) :
     QObject(parent),
     m_autosave(NULL),
     m_url(url),
@@ -74,12 +74,39 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
     m_documentProperties["verticalzoom"] = "1";
     m_documentProperties["zonein"] = "0";
     m_documentProperties["zoneout"] = "100";
+    m_documentProperties["enableproxy"] = QString::number((int) KdenliveSettings::enableproxy());
+    m_documentProperties["proxyparams"] = KdenliveSettings::proxyparams();
+    m_documentProperties["proxyextension"] = KdenliveSettings::proxyextension();
+    m_documentProperties["generateproxy"] = QString::number((int) KdenliveSettings::generateproxy());
+    m_documentProperties["proxyminsize"] = QString::number(KdenliveSettings::proxyminsize());
+    m_documentProperties["generateimageproxy"] = QString::number((int) KdenliveSettings::generateimageproxy());
+    m_documentProperties["proxyimageminsize"] = QString::number(KdenliveSettings::proxyimageminsize());
+#if QT_VERSION >= 0x040700
+    m_documentProperties["documentid"] = QString::number(QDateTime::currentMSecsSinceEpoch());
+#else
+    QDateTime date = QDateTime::currentDateTime();
+    m_documentProperties["documentid"] = QString::number(date.toTime_t());
+#endif
+
+    // Load properties
+    QMapIterator<QString, QString> i(properties);
+    while (i.hasNext()) {
+        i.next();
+        m_documentProperties[i.key()] = i.value();
+    }
 
+    *openBackup = false;
+    
     if (!url.isEmpty()) {
         QString tmpFile;
         success = KIO::NetAccess::download(url.path(), tmpFile, parent);
-        if (!success) // The file cannot be opened
-            KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
+        if (!success) {
+            // The file cannot be opened
+            if (KMessageBox::warningContinueCancel(parent, i18n("Cannot open the project file, error is:\n%1\nDo you want to open a backup file?", KIO::NetAccess::lastErrorString()), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
+                *openBackup = true;
+            }
+            //KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
+        }
         else {
             QFile file(tmpFile);
             QString errorMsg;
@@ -89,8 +116,13 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
             file.close();
             KIO::NetAccess::removeTempFile(tmpFile);
 
-            if (!success) // It is corrupted
-                KMessageBox::error(parent, errorMsg);
+            if (!success) {
+                // It is corrupted
+                if (KMessageBox::warningContinueCancel(parent, i18n("Cannot open the project file, error is:\n%1\nDo you want to open a backup file?", errorMsg), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
+                *openBackup = true;
+            }
+                //KMessageBox::error(parent, errorMsg);
+            }
             else {
                 parent->slotGotProgressInfo(i18n("Validating"), 0);
                 qApp->processEvents();
@@ -99,6 +131,9 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                 if (!success) {
                     // It is not a project file
                     parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file", m_url.path()), 100);
+                    if (KMessageBox::warningContinueCancel(parent, i18n("File %1 is not a valid project file.\nDo you want to open a backup file?", m_url.path()), i18n("Error opening file"), KGuiItem(i18n("Open Backup"))) == KMessageBox::Continue) {
+                        *openBackup = true;
+                    }
                 } else {
                     /*
                      * Validate the file against the current version (upgrade
@@ -117,6 +152,9 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                             QDomElement mlt = m_document.firstChildElement("mlt");
                             QDomElement infoXml = mlt.firstChildElement("kdenlivedoc");
 
+                            // Set profile, fps, etc for the document
+                            setProfilePath(infoXml.attribute("profile"));
+
                             // Check embedded effects
                             QDomElement customeffects = infoXml.firstChildElement("customeffects");
                             if (!customeffects.isNull() && customeffects.hasChildNodes()) {
@@ -152,12 +190,14 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                                 }
                                 mlt.removeChild(tracksinfo);
                             }
-
+                            QStringList expandedFolders;
                             QDomNodeList folders = m_document.elementsByTagName("folder");
                             for (int i = 0; i < folders.count(); i++) {
                                 e = folders.item(i).cloneNode().toElement();
+                                if (e.hasAttribute("opened")) expandedFolders.append(e.attribute("id"));
                                 m_clipManager->addFolder(e.attribute("id"), e.attribute("name"));
                             }
+                            m_documentProperties["expandedfolders"] = expandedFolders.join(";");
 
                             const int infomax = infoproducers.count();
                             QDomNodeList producers = m_document.elementsByTagName("producer");
@@ -220,7 +260,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                                 QDomNamedNodeMap props = docproperties.attributes();
                                 for (int i = 0; i < props.count(); i++)
                                     m_documentProperties.insert(props.item(i).nodeName(), props.item(i).nodeValue());
-                                setProfilePath(infoXml.attribute("profile"));
+
                                 if (validator.isModified()) setModified(true);
                                 kDebug() << "Reading file: " << url.path() << ", found clips: " << producers.count();
                             }
@@ -230,17 +270,14 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
             }
         }
     }
-
+    
     // Something went wrong, or a new file was requested: create a new project
     if (!success) {
-        m_url = KUrl();
+        m_url.clear();
         setProfilePath(profileName);
         m_document = createEmptyDocument(tracks.x(), tracks.y());
     }
 
-    // Set the video profile (empty == default)
-    KdenliveSettings::setCurrent_profile(profilePath());
-
     // Ask to create the project directory if it does not exist
     if (!QFile::exists(m_projectFolder.path())) {
         int create = KMessageBox::questionYesNo(parent, i18n("Project directory %1 does not exist. Create it?", m_projectFolder.path()));
@@ -262,7 +299,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
     // Make sure that the necessary folders exist
     KStandardDirs::makeDir(m_projectFolder.path(KUrl::AddTrailingSlash) + "titles/");
     KStandardDirs::makeDir(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/");
-    KStandardDirs::makeDir(m_projectFolder.path(KUrl::AddTrailingSlash) + "ladspa/");
+    KStandardDirs::makeDir(m_projectFolder.path(KUrl::AddTrailingSlash) + "proxy/");
 
     updateProjectFolderPlacesEntry();
 
@@ -286,7 +323,7 @@ KdenliveDoc::~KdenliveDoc()
 
 int KdenliveDoc::setSceneList()
 {
-    m_render->resetProfile(KdenliveSettings::current_profile());
+    m_render->resetProfile(KdenliveSettings::current_profile(), true);
     if (m_render->setSceneList(m_document.toString(), m_documentProperties.value("position").toInt()) == -1) {
         // INVALID MLT Consumer, something is wrong
         return -1;
@@ -311,6 +348,7 @@ QDomDocument KdenliveDoc::createEmptyDocument(int videotracks, int audiotracks)
         audioTrack.isBlind = true;
         audioTrack.isLocked = false;
         audioTrack.trackName = QString("Audio ") + QString::number(audiotracks - i);
+        audioTrack.duration = 0;
         m_tracksList.append(audioTrack);
 
     }
@@ -321,6 +359,7 @@ QDomDocument KdenliveDoc::createEmptyDocument(int videotracks, int audiotracks)
         videoTrack.isBlind = false;
         videoTrack.isLocked = false;
         videoTrack.trackName = QString("Video ") + QString::number(videotracks - i);
+        videoTrack.duration = 0;
         m_tracksList.append(videoTrack);
     }
     return createEmptyDocument(m_tracksList);
@@ -331,9 +370,9 @@ QDomDocument KdenliveDoc::createEmptyDocument(QList <TrackInfo> tracks)
     // Creating new document
     QDomDocument doc;
     QDomElement mlt = doc.createElement("mlt");
+    mlt.setAttribute("LC_NUMERIC", "");
     doc.appendChild(mlt);
-
-
+    
     // Create black producer
     // For some unknown reason, we have to build the black producer here and not in renderer.cpp, otherwise
     // the composite transitions with the black track are corrupted.
@@ -350,7 +389,7 @@ QDomDocument KdenliveDoc::createEmptyDocument(QList <TrackInfo> tracks)
 
     property = doc.createElement("property");
     property.setAttribute("name", "aspect_ratio");
-    value = doc.createTextNode(QString::number(0.0));
+    value = doc.createTextNode(QString::number(0));
     property.appendChild(value);
     blk.appendChild(property);
 
@@ -490,7 +529,7 @@ void KdenliveDoc::slotAutoSave()
             kDebug() << "ERROR; CANNOT CREATE AUTOSAVE FILE";
         }
         kDebug() << "// AUTOSAVE FILE: " << m_autosave->fileName();
-        saveSceneList(m_autosave->fileName(), m_render->sceneList());
+        saveSceneList(m_autosave->fileName(), m_render->sceneList(), QStringList(), true);
     }
 }
 
@@ -516,15 +555,26 @@ QPoint KdenliveDoc::zone() const
     return QPoint(m_documentProperties.value("zonein").toInt(), m_documentProperties.value("zoneout").toInt());
 }
 
-bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene)
+QDomDocument KdenliveDoc::xmlSceneList(const QString &scene, const QStringList expandedFolders)
 {
     QDomDocument sceneList;
     sceneList.setContent(scene, true);
     QDomElement mlt = sceneList.firstChildElement("mlt");
     if (mlt.isNull() || !mlt.hasChildNodes()) {
-        //Make sure we don't save if scenelist is corrupted
-        KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1, scene list is corrupted.", path));
-        return false;
+        //scenelist is corrupted
+        return sceneList;
+    }
+
+    // Set playlist audio volume to 100%
+    QDomElement tractor = mlt.firstChildElement("tractor");
+    if (!tractor.isNull()) {
+        QDomNodeList props = tractor.elementsByTagName("property");
+        for (int i = 0; i < props.count(); i++) {
+            if (props.at(i).toElement().attribute("name") == "meta.volume") {
+                props.at(i).firstChild().setNodeValue("1");
+                break;
+            }
+        }
     }
 
     QDomElement addedXml = sceneList.createElement("kdenlivedoc");
@@ -570,7 +620,7 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene)
     addedXml.appendChild(docproperties);
 
     QDomElement docnotes = sceneList.createElement("documentnotes");
-    QDomText value = sceneList.createTextNode(m_notesWidget->toPlainText());
+    QDomText value = sceneList.createTextNode(m_notesWidget->toHtml());
     docnotes.appendChild(value);
     addedXml.appendChild(docnotes);
 
@@ -610,6 +660,7 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene)
         QDomElement folder = sceneList.createElement("folder");
         folder.setAttribute("id", f.key());
         folder.setAttribute("name", f.value());
+        if (expandedFolders.contains(f.key())) folder.setAttribute("opened", "1");
         addedXml.appendChild(folder);
     }
 
@@ -638,8 +689,22 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene)
     addedXml.appendChild(sceneList.importNode(m_clipManager->groupsXml(), true));
 
     //wes.appendChild(doc.importNode(kdenliveData, true));
+    return sceneList;
+}
 
+bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene, const QStringList expandedFolders, bool autosave)
+{
+    QDomDocument sceneList = xmlSceneList(scene, expandedFolders);
+    if (sceneList.isNull()) {
+        //Make sure we don't save if scenelist is corrupted
+        KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1, scene list is corrupted.", path));
+        return false;
+    }
+    
+    // Backup current version
+    if (!autosave) backupLastSavedVersion(path);
     QFile file(path);
+    
     if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
         kWarning() << "//////  ERROR writing to file: " << path;
         KMessageBox::error(kapp->activeWindow(), i18n("Cannot write to file %1", path));
@@ -653,6 +718,18 @@ bool KdenliveDoc::saveSceneList(const QString &path, const QString &scene)
         return false;
     }
     file.close();
+    if (!autosave) {
+        cleanupBackupFiles();
+        QFileInfo info(file);
+        QString fileName = KUrl(path).fileName().section('.', 0, -2);   
+        fileName.append("-" + m_documentProperties.value("documentid"));
+        fileName.append(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
+        fileName.append(".kdenlive.png");
+        KUrl backupFile = m_projectFolder;
+        backupFile.addPath(".backup/");
+        backupFile.addPath(fileName);
+        emit saveTimelinePreview(backupFile.path());
+    }
     return true;
 }
 
@@ -683,7 +760,6 @@ void KdenliveDoc::setProjectFolder(KUrl url)
 void KdenliveDoc::moveProjectData(KUrl url)
 {
     QList <DocClipBase*> list = m_clipManager->documentClipList();
-    //TODO: Also move ladspa effects files
     for (int i = 0; i < list.count(); i++) {
         DocClipBase *clip = list.at(i);
         if (clip->clipType() == TEXT) {
@@ -724,7 +800,7 @@ bool KdenliveDoc::setProfilePath(QString path)
     if (path.isEmpty()) path = KdenliveSettings::default_profile();
     if (path.isEmpty()) path = "dv_pal";
     m_profile = ProfilesDialog::getVideoProfile(path);
-    bool current_fps = m_fps;
+    double current_fps = m_fps;
     if (m_profile.path.isEmpty()) {
         // Profile not found, use embedded profile
         QDomElement profileInfo = m_document.elementsByTagName("profileinfo").at(0).toElement();
@@ -776,6 +852,7 @@ bool KdenliveDoc::setProfilePath(QString path)
     m_height = m_profile.height;
     kDebug() << "Kdenlive document, init timecode from path: " << path << ",  " << m_fps;
     m_timecode.setFormat(m_fps);
+    KdenliveSettings::setCurrent_profile(m_profile.path);
     return (current_fps != m_fps);
 }
 
@@ -808,10 +885,10 @@ void KdenliveDoc::setRenderer(Render *render) {
     emit progressInfo(QString(), -1);
 }*/
 
-void KdenliveDoc::checkProjectClips()
+void KdenliveDoc::checkProjectClips(bool displayRatioChanged, bool fpsChanged)
 {
     if (m_render == NULL) return;
-    m_clipManager->resetProducersList(m_render->producersList());
+    m_clipManager->resetProducersList(m_render->producersList(), displayRatioChanged, fpsChanged);
 }
 
 Render *KdenliveDoc::renderer()
@@ -895,6 +972,7 @@ void KdenliveDoc::setUrl(KUrl url)
 
 void KdenliveDoc::setModified(bool mod)
 {
+    if (isReadOnly()) return;
     if (!m_url.isEmpty() && mod && KdenliveSettings::crashrecovery()) {
         m_autoSaveTimer->start(3000);
     }
@@ -985,7 +1063,6 @@ bool KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem)
 
     if (createClipItem) {
         emit addProjectClip(clip);
-        //qApp->processEvents();
     }
 
     return true;
@@ -1219,6 +1296,16 @@ void KdenliveDoc::switchTrackVideo(int ix, bool hide)
     m_tracksList[ix].isBlind = hide; // !m_tracksList.at(ix).isBlind;
 }
 
+int KdenliveDoc::trackDuration(int ix)
+{
+    return m_tracksList.at(ix).duration; 
+}
+
+void KdenliveDoc::setTrackDuration(int ix, int duration)
+{
+    m_tracksList[ix].duration = duration;
+}
+
 void KdenliveDoc::insertTrack(int ix, TrackInfo type)
 {
     if (ix == -1) m_tracksList << type;
@@ -1268,21 +1355,10 @@ void KdenliveDoc::cachePixmap(const QString &fileId, const QPixmap &pix) const
     pix.save(m_projectFolder.path(KUrl::AddTrailingSlash) + "thumbs/" + fileId + ".png");
 }
 
-QString KdenliveDoc::getLadspaFile() const
-{
-    int ct = 0;
-    QString counter = QString::number(ct).rightJustified(5, '0', false);
-    while (QFile::exists(m_projectFolder.path(KUrl::AddTrailingSlash) + "ladspa/" + counter + ".ladspa")) {
-        ct++;
-        counter = QString::number(ct).rightJustified(5, '0', false);
-    }
-    return m_projectFolder.path(KUrl::AddTrailingSlash) + "ladspa/" + counter + ".ladspa";
-}
-
 bool KdenliveDoc::checkDocumentClips(QDomNodeList infoproducers)
 {
     DocumentChecker d(infoproducers, m_document);
-    return (d.hasMissingClips() == false);
+    return (d.hasErrorInClips() == false);
 
     /*    int clipType;
         QDomElement e;
@@ -1351,7 +1427,7 @@ void KdenliveDoc::addTrackEffect(int ix, QDomElement effect)
         QDomElement e = params.item(i).toElement();
 
         // Check if this effect has a variable parameter
-        if (e.attribute("default").startsWith('%')) {
+        if (e.attribute("default").contains('%')) {
             double evaluatedValue = ProfilesDialog::getStringEval(m_profile, e.attribute("default"));
             e.setAttribute("default", evaluatedValue);
             if (e.hasAttribute("value") && e.attribute("value").startsWith('%')) {
@@ -1368,6 +1444,12 @@ void KdenliveDoc::addTrackEffect(int ix, QDomElement effect)
                 //break;
             }
         }
+
+        if (effect.attribute("id") == "crop") {
+            // default use_profile to 1 for clips with proxies to avoid problems when rendering
+            if (e.attribute("name") == "use_profile" && getDocumentProperty("enableproxy") == "1")
+                e.setAttribute("value", "1");
+        }
     }
 
     m_tracksList[ix].effectsList.append(effect);
@@ -1493,12 +1575,168 @@ void KdenliveDoc::updateProjectFolderPlacesEntry()
 
     // if entry does not exist yet (was not found), well, create it then
     if (!exists) {
-        KBookmark newBookmark = root.addBookmark(i18n("Project Folder"), documentLocation, "folder-favorites");
+        bookmark = root.addBookmark(i18n("Project Folder"), documentLocation, "folder-favorites");
         // Make this user selectable ?
-        newBookmark.setMetaDataItem("OnlyInApp", kdenliveName);
+        bookmark.setMetaDataItem("OnlyInApp", kdenliveName);
         bookmarkManager->emitChanged(root);
     }
 }
 
+QStringList KdenliveDoc::getExpandedFolders()
+{
+    QStringList result = m_documentProperties.value("expandedfolders").split(';');
+    // this property is only needed once when opening project, so clear it now
+    m_documentProperties.remove("expandedfolders");
+    return result;
+}
+
+// static
+double KdenliveDoc::getDisplayRatio(const QString &path)
+{
+    QFile file(path);
+    QDomDocument doc;
+    if (!file.open(QIODevice::ReadOnly)) {
+        kWarning() << "ERROR, CANNOT READ: " << path;
+        return 0;
+    }
+    if (!doc.setContent(&file)) {
+        kWarning() << "ERROR, CANNOT READ: " << path;
+        file.close();
+        return 0;
+    }
+    file.close();
+    QDomNodeList list = doc.elementsByTagName("profile");
+    if (list.isEmpty()) return 0;
+    QDomElement profile = list.at(0).toElement();
+    double den = profile.attribute("display_aspect_den").toDouble();
+    if (den > 0) return profile.attribute("display_aspect_num").toDouble() / den;
+    return 0;
+}
+
+void KdenliveDoc::backupLastSavedVersion(const QString &path)
+{
+    // Ensure backup folder exists
+    if (path.isEmpty()) return;
+    QFile file(path);
+    KUrl backupFile = m_projectFolder;
+    backupFile.addPath(".backup/");
+    KIO::NetAccess::mkdir(backupFile, kapp->activeWindow());
+    QString fileName = KUrl(path).fileName().section('.', 0, -2);
+    QFileInfo info(file);
+    fileName.append("-" + m_documentProperties.value("documentid"));
+    fileName.append(info.lastModified().toString("-yyyy-MM-dd-hh-mm"));
+    fileName.append(".kdenlive");
+    backupFile.addPath(fileName);
+
+    if (file.exists()) {
+        // delete previous backup if it was done less than 60 seconds ago
+        QFile::remove(backupFile.path());
+        if (!QFile::copy(path, backupFile.path())) {
+            KMessageBox::information(kapp->activeWindow(), i18n("Cannot create backup copy:\n%1", backupFile.path()));
+        }
+    }    
+}
+
+bool KdenliveDoc::isReadOnly() const
+{
+    return m_documentProperties.contains("readonly");
+}
+
+void KdenliveDoc::cleanupBackupFiles()
+{
+    KUrl backupFile = m_projectFolder;
+    backupFile.addPath(".backup/");
+    QDir dir(backupFile.path());
+    QString projectFile = url().fileName().section('.', 0, -2);
+    projectFile.append("-" + m_documentProperties.value("documentid"));
+    projectFile.append("-??");
+    projectFile.append("??");
+    projectFile.append("-??");
+    projectFile.append("-??");
+    projectFile.append("-??");
+    projectFile.append("-??.kdenlive");
+
+    QStringList filter;
+    backupFile.addPath(projectFile);
+    filter << projectFile;
+    dir.setNameFilters(filter);
+    QFileInfoList resultList = dir.entryInfoList(QDir::Files, QDir::Time);
+
+    QDateTime d = QDateTime::currentDateTime();
+    QStringList hourList;
+    QStringList dayList;
+    QStringList weekList;
+    QStringList oldList;
+    for (int i = 0; i < resultList.count(); i++) {
+        if (d.secsTo(resultList.at(i).lastModified()) < 3600) {
+            // files created in the last hour
+            hourList.append(resultList.at(i).absoluteFilePath());
+        }
+        else if (d.secsTo(resultList.at(i).lastModified()) < 43200) {
+            // files created in the day
+            dayList.append(resultList.at(i).absoluteFilePath());
+        }
+        else if (d.daysTo(resultList.at(i).lastModified()) < 8) {
+            // files created in the week
+            weekList.append(resultList.at(i).absoluteFilePath());
+        }
+        else {
+            // older files
+            oldList.append(resultList.at(i).absoluteFilePath());
+        }
+    }
+    if (hourList.count() > 20) {
+        int step = hourList.count() / 10;
+        for (int i = 0; i < hourList.count(); i += step) {
+            kDebug()<<"REMOVE AT: "<<i<<", COUNT: "<<hourList.count();
+            hourList.removeAt(i);
+            i--;
+        }
+    } else hourList.clear();
+    if (dayList.count() > 20) {
+        int step = dayList.count() / 10;
+        for (int i = 0; i < dayList.count(); i += step) {
+            dayList.removeAt(i);
+            i--;
+        }
+    } else dayList.clear();
+    if (weekList.count() > 20) {
+        int step = weekList.count() / 10;
+        for (int i = 0; i < weekList.count(); i += step) {
+            weekList.removeAt(i);
+            i--;
+        }
+    } else weekList.clear();
+    if (oldList.count() > 20) {
+        int step = oldList.count() / 10;
+        for (int i = 0; i < oldList.count(); i += step) {
+            oldList.removeAt(i);
+            i--;
+        }
+    } else oldList.clear();
+    
+    QString f;
+    while (hourList.count() > 0) {
+        f = hourList.takeFirst();
+        QFile::remove(f);
+        QFile::remove(f + ".png");
+    }
+    while (dayList.count() > 0) {
+        f = dayList.takeFirst();
+        QFile::remove(f);
+        QFile::remove(f + ".png");
+    }
+    while (weekList.count() > 0) {
+        f = weekList.takeFirst();
+        QFile::remove(f);
+        QFile::remove(f + ".png");
+    }
+    while (oldList.count() > 0) {
+        f = oldList.takeFirst();
+        QFile::remove(f);
+        QFile::remove(f + ".png");
+    }
+}
+
 #include "kdenlivedoc.moc"