On Tuesday 18 November 2008 04:53:10 Alberto Villa wrote:
> great news! thanks, i'm going on, so we'll have an example on which debate
> :)

here it is
it's just a draft, as the name suggests, full of kdebug(), comments and junk 
code, but it works

it supports few things, only to show it is fast (it takes a second to scan 450 
files here, and freebsd ufs2 is slower than ext3) and it can be done 
efficiently (i think there's room for speed improvements... i've made 
something really simple):
- create a new project and add some clips, but DO NOT insert them in the 
timeline
- close the project
- rename or move those clips
- open the project and test the options (the producer is still not updated, so 
the thumbnail will be red or... ?)

what's missing?
- timeline clips refresh
- producer refresh after an automatic search (but saving an restarting 
obviously works)
- mh... slideshows? i didn't take care of them, still don't know how they work
- old broken projects (wrong paths and no hashes) result in their clips to be 
"left as placeholders"... i don't think it's safe to let the user replace a 
file manually (image instead of video, 1min file in place of 1hour file... 
dangerous?)...
- and probably there's something broken :P

what do you think?

regards
-- 
Alberto Villa <[EMAIL PROTECTED]>
diff -ur kdenlive.orig/src/docclipbase.cpp kdenlive/src/docclipbase.cpp
--- kdenlive.orig/src/docclipbase.cpp	2008-11-18 00:28:28.000000000 +0000
+++ kdenlive/src/docclipbase.cpp	2008-11-18 23:25:19.000000000 +0000
@@ -15,6 +15,8 @@
  *                                                                         *
  ***************************************************************************/
 
+#include <QCryptographicHash>
+
 #include <KDebug>
 
 #include "kdenlivesettings.h"
@@ -34,6 +36,8 @@
     }
 
     KUrl url = KUrl(xml.attribute("resource"));
+    if (!xml.attribute("resource").isEmpty())
+        setProperty("resource", xml.attribute("resource")); // resetting resource to calculate hash
     int out = xml.attribute("out").toInt();
     if (out != 0) {
         setDuration(GenTime(out, KdenliveSettings::project_fps()));
@@ -519,8 +523,30 @@
 
 void DocClipBase::setProperty(const QString &key, const QString &value) {
     m_properties.insert(key, value);
-    if (key == "resource") m_thumbProd->updateClipUrl(KUrl(value));
-    else if (key == "out") setDuration(GenTime(value.toInt(), KdenliveSettings::project_fps()));
+    if (key == "resource") {
+        //m_thumbProd->updateClipUrl(KUrl(value)); -> this crashes...
+        QFile file(value);
+        if (file.open(QIODevice::ReadOnly)) { // write size and hash only if resource points to a file
+            QByteArray fileData;
+            QByteArray fileHash;
+    	    kDebug() << "SETTING HASH of" << value;
+            m_properties.insert("file_size", QString::number(file.size()));
+        	/*
+        	 * 1 MB = 1 second per 450 files (or faster)
+        	 * 10 MB = 9 seconds per 450 files (or faster)
+        	 */
+            if (file.size() > 1000000*2) {
+                fileData = file.read(1000000);
+                if (file.seek(file.size() - 1000000))
+                    fileData.append(file.readAll());
+            } else
+                fileData = file.readAll();
+            file.close();
+            fileHash = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
+            m_properties.insert("file_hash", QString(fileHash.toHex()));
+            kDebug() << file.fileName() << file.size() << fileHash.toHex();
+        }
+    } else if (key == "out") setDuration(GenTime(value.toInt(), KdenliveSettings::project_fps()));
     //else if (key == "transparency") m_clipProducer->set("transparency", value.toInt());
     else if (key == "colour") {
         char *tmp = (char *) qstrdup(value.toUtf8().data());
diff -ur kdenlive.orig/src/projectlist.cpp kdenlive/src/projectlist.cpp
--- kdenlive.orig/src/projectlist.cpp	2008-11-18 00:28:25.000000000 +0000
+++ kdenlive/src/projectlist.cpp	2008-11-18 23:12:37.000000000 +0000
@@ -24,6 +24,8 @@
 #include <QIcon>
 #include <QDialog>
 #include <QtGui>
+#include <QDir>
+#include <QCryptographicHash>
 
 #include <KDebug>
 #include <KAction>
@@ -441,15 +443,73 @@
 
 void ProjectList::slotRemoveInvalidClip(const QString &id) {
     ProjectItem *item = getItemById(id);
+    KMessageBox::ButtonCode action;
+    QString path = item->referencedClip()->fileURL().path();
     if (item) {
-        QString path = item->referencedClip()->fileURL().path();
-        if (!path.isEmpty()) KMessageBox::sorry(this, i18n("<qt>Clip <b>%1</b><br>is invalid, will be removed from project.", path));
+        if (!path.isEmpty()) //KMessageBox::sorry(this, i18n("<qt>Clip <b>%1</b><br>is invalid, will be removed from project.", path));
+            action = (KMessageBox::ButtonCode)KMessageBox::messageBox(this, KMessageBox::WarningYesNoCancel, i18n("<qt>Clip <b>%1</b><br>is invalid, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search automatically")), KGuiItem(i18n("Remove from project")), KGuiItem(i18n("Keep as placeholder")));  
+    } else
+        action = KMessageBox::No; // then remove
+    if (action == KMessageBox::Yes) { // search
+        QString foundFileName;
+        if (!item->referencedClip()->getProperty("file_size").isEmpty() &&
+            !item->referencedClip()->getProperty("file_hash").isEmpty()) { // both hash and file size were registered
+            KUrl rootDirUrl = KFileDialog::getExistingDirectoryUrl(KUrl("kfiledialog:///clipfolder"), this);
+    	    if (!rootDirUrl.path().isEmpty()) { 
+    	        QDir *rootDir = new QDir(rootDirUrl.path());
+    	        foundFileName = searchFileRecursively(rootDir, item->referencedClip()->getProperty("file_size"), item->referencedClip()->getProperty("file_hash"));
+    	    }
+        }
+    	if (foundFileName.isEmpty())
+    	    KMessageBox::sorry(this, i18n("<qt>Cannot find a match for clip<br><b>%1</b>,<br>leaving in project as a placeholder.", path));
+    	else {
+    	    QMap <QString, QString> properties;
+    	    properties["resource"] = foundFileName;
+    	    kDebug() << "CLIP ID:" << item->referencedClip()->getId() << "--- setting 'resource' to" << foundFileName;
+    	    slotUpdateClipProperties(item->referencedClip()->getId(), properties);
+    	}
+    } else if (action == KMessageBox::No) { // remove
+        QList <QString> ids;
+        ids << id;
+        m_doc->deleteProjectClip(ids);
+    } // else keep it (last choice to be automatically bound to ESC)
+    if (!m_infoQueue.isEmpty()) QTimer::singleShot(300, this, SLOT(slotProcessNextClipInQueue()));
+}
 
+QString ProjectList::searchFileRecursively(const QDir *dir, const QString matchSize, const QString matchHash) {
+	QString foundFileName;
+	QByteArray fileData;
+	QByteArray fileHash;
+    QStringList filesAndDirs = dir->entryList(QDir::Files | QDir::Readable);
+    for (int i = 0; i < filesAndDirs.size() && foundFileName.isEmpty(); i++) {
+        QFile file(dir->absoluteFilePath(filesAndDirs.at(i)));
+        if (file.open(QIODevice::ReadOnly)) {
+            if (QString::number(file.size()) == matchSize) { 
+                /*
+        	    * 1 MB = 1 second per 450 files (or faster)
+        	    * 10 MB = 9 seconds per 450 files (or faster)
+                */
+                if (file.size() > 1000000*2) {
+                    fileData = file.read(1000000);
+                    if (file.seek(file.size() - 1000000))
+                        fileData.append(file.readAll());
+                } else
+                    fileData = file.readAll();
+                file.close();
+                fileHash = QCryptographicHash::hash(fileData, QCryptographicHash::Md5);
+                if (QString(fileHash.toHex()) == matchHash)
+                    return file.fileName();
+            }
+        }
+        kDebug() << filesAndDirs.at(i) << file.size() << fileHash.toHex();
     }
-    QList <QString> ids;
-    ids << id;
-    m_doc->deleteProjectClip(ids);
-    if (!m_infoQueue.isEmpty()) QTimer::singleShot(300, this, SLOT(slotProcessNextClipInQueue()));
+    filesAndDirs = dir->entryList(QDir::Dirs | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot);
+    for (int i = 0; i < filesAndDirs.size() && foundFileName.isEmpty(); i++) {
+  	    foundFileName = searchFileRecursively(new QDir(dir->absoluteFilePath(filesAndDirs.at(i))), matchSize, matchHash);
+        if (!foundFileName.isEmpty())
+            break;
+    }
+    return foundFileName; 
 }
 
 void ProjectList::slotAddColorClip() {
diff -ur kdenlive.orig/src/projectlist.h kdenlive/src/projectlist.h
--- kdenlive.orig/src/projectlist.h	2008-11-18 00:28:28.000000000 +0000
+++ kdenlive/src/projectlist.h	2008-11-18 17:04:19.000000000 +0000
@@ -43,6 +43,7 @@
 class Render;
 class KdenliveDoc;
 class DocClipBase;
+class QDir;
 
 const int NameRole = Qt::UserRole;
 const int DurationRole = NameRole + 1;
@@ -109,6 +110,7 @@
     void setRenderer(Render *projectRender);
     void slotUpdateClipProperties(const QString &id, QMap <QString, QString> properties);
     void updateAllClips();
+    QString searchFileRecursively(const QDir *dir, const QString matchSize, const QString matchHash);
     QByteArray headerInfo();
     void setHeaderInfo(const QByteArray &state);
 
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Kdenlive-devel mailing list
Kdenlive-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kdenlive-devel

Reply via email to