]> git.sesse.net Git - kdenlive/commitdiff
Start of the new document checker (check for missing clips,...) not fully functionnal yet
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 4 May 2009 09:50:34 +0000 (09:50 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Mon, 4 May 2009 09:50:34 +0000 (09:50 +0000)
svn path=/trunk/kdenlive/; revision=3353

src/CMakeLists.txt
src/documentchecker.cpp [new file with mode: 0644]
src/documentchecker.h [new file with mode: 0644]
src/kdenlivedoc.cpp
src/kdenlivedoc.h

index 6a5dcda6b50db4c6e76a7867ffd763d82445b1a1..fa795173f7fad3ebdabc0d07d115df5176ca5377 100644 (file)
@@ -70,6 +70,7 @@ kde4_add_ui_files(kdenlive_UI
   widgets/dvdwizardmenu_ui.ui
   widgets/dvdwizardiso_ui.ui
   widgets/dvdwizardstatus_ui.ui
+  widgets/missingclips_ui.ui
 )
  
 set(kdenlive_SRCS 
@@ -155,6 +156,7 @@ set(kdenlive_SRCS
   groupclipscommand.cpp
   splitaudiocommand.cpp
   changecliptypecommand.cpp
+  documentchecker.cpp
 )
 
 add_definitions( ${KDE4_DEFINITIONS} )
diff --git a/src/documentchecker.cpp b/src/documentchecker.cpp
new file mode 100644 (file)
index 0000000..724cdf9
--- /dev/null
@@ -0,0 +1,215 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
+ ***************************************************************************/
+
+
+#include "documentchecker.h"
+#include "kthumb.h"
+#include "definitions.h"
+
+#include <KDebug>
+#include <KGlobalSettings>
+#include <KFileItem>
+#include <KIO/NetAccess>
+#include <KFileDialog>
+#include <KApplication>
+#include <KUrlRequesterDialog>
+
+#include <QTreeWidgetItem>
+#include <QFile>
+#include <QHeaderView>
+#include <QIcon>
+#include <QPixmap>
+#include <QTimer>
+#include <QCryptographicHash>
+
+const int hashRole = Qt::UserRole;
+const int sizeRole = Qt::UserRole + 1;
+const int idRole = Qt::UserRole + 2;
+const int statusRole = Qt::UserRole + 3;
+
+DocumentChecker::DocumentChecker(QDomDocument doc, QWidget * parent) :
+        QDialog(parent), m_doc(doc)
+{
+    setFont(KGlobalSettings::toolBarFont());
+    m_view.setupUi(this);
+
+    QDomNodeList producers = m_doc.elementsByTagName("producer");
+    QDomNodeList infoproducers = m_doc.elementsByTagName("kdenlive_producer");
+
+    int clipType;
+    QDomElement e;
+    QString id;
+    QString resource;
+    QList <QDomElement> missingClips;
+    for (int i = 0; i < infoproducers.count(); i++) {
+        e = infoproducers.item(i).toElement();
+        clipType = e.attribute("type").toInt();
+        if (clipType == TEXT) continue;
+        id = e.attribute("id");
+        resource = e.attribute("resource");
+        if (clipType == SLIDESHOW) resource = KUrl(resource).directory();
+        if (!KIO::NetAccess::exists(KUrl(resource), KIO::NetAccess::SourceSide, 0)) {
+            // Missing clip found
+            missingClips.append(e);
+        }
+    }
+
+    if (missingClips.isEmpty()) QTimer::singleShot(0, this, SLOT(reject()));
+
+    for (int i = 0; i < missingClips.count(); i++) {
+        e = missingClips.at(i).toElement();
+        QString clipType;
+        switch (e.attribute("type").toInt()) {
+        case AV:
+            clipType = i18n("Video clip");
+            break;
+        case VIDEO:
+            clipType = i18n("Mute video clip");
+            break;
+        case AUDIO:
+            clipType = i18n("Audio clip");
+            break;
+        case PLAYLIST:
+            clipType = i18n("Playlist clip");
+            break;
+        case IMAGE:
+            clipType = i18n("Image clip");
+            break;
+        case SLIDESHOW:
+            clipType = i18n("Slideshow clip");
+            break;
+        default:
+            clipType = i18n("Video clip");
+        }
+        QTreeWidgetItem *item = new QTreeWidgetItem(m_view.treeWidget, QStringList() << clipType << e.attribute("resource"));
+        item->setIcon(0, KIcon("dialog-close"));
+        item->setData(0, hashRole, e.attribute("file_hash"));
+        item->setData(0, sizeRole, e.attribute("file_size"));
+        item->setData(0, idRole, e.attribute("id"));
+        item->setData(0, statusRole, '1');
+    }
+    connect(m_view.recursiveSearch, SIGNAL(pressed()), this, SLOT(slotSearchClips()));
+    connect(m_view.treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(slotEditItem(QTreeWidgetItem *, int)));
+    //adjustSize();
+}
+
+DocumentChecker::~DocumentChecker() {}
+
+void DocumentChecker::slotSearchClips()
+{
+    QString newpath = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///clipfolder"), kapp->activeWindow(), i18n("Clips folder"));
+    if (newpath.isEmpty()) return;
+    int ix = 0;
+    QTreeWidgetItem *child = m_view.treeWidget->topLevelItem(ix);
+    while (child && !child->data(0, statusRole).toString().isEmpty()) {
+        QString clipPath = searchFileRecursively(QDir(newpath), child->data(0, sizeRole).toString(), child->data(0, hashRole).toString());
+        if (!clipPath.isEmpty()) {
+            child->setText(1, clipPath);
+            child->setIcon(0, KIcon("dialog-ok"));
+            child->setData(0, statusRole, QString());
+        }
+        ix++;
+        child = m_view.treeWidget->topLevelItem(ix);
+    }
+}
+
+QString DocumentChecker::searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash) const
+{
+    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();
+    }
+    filesAndDirs = dir.entryList(QDir::Dirs | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot);
+    for (int i = 0; i < filesAndDirs.size() && foundFileName.isEmpty(); i++) {
+        foundFileName = searchFileRecursively(dir.absoluteFilePath(filesAndDirs.at(i)), matchSize, matchHash);
+        if (!foundFileName.isEmpty())
+            break;
+    }
+    return foundFileName;
+}
+
+void DocumentChecker::slotEditItem(QTreeWidgetItem *item, int)
+{
+    KUrl url = KUrlRequesterDialog::getUrl(item->text(1), this, i18n("Enter new location for file"));
+    if (url.isEmpty()) return;
+    item->setText(1, url.path());
+    if (KIO::NetAccess::exists(url, KIO::NetAccess::SourceSide, 0)) {
+        item->setIcon(0, KIcon("dialog-ok"));
+        item->setData(0, statusRole, QString());
+    }
+}
+
+// virtual
+void DocumentChecker::accept()
+{
+    QDomElement e;
+    QDomNodeList producers = m_doc.elementsByTagName("producer");
+    QDomNodeList infoproducers = m_doc.elementsByTagName("kdenlive_producer");
+    int ix = 0;
+    QTreeWidgetItem *child = m_view.treeWidget->topLevelItem(ix);
+    while (child && child->data(0, statusRole).toString().isEmpty()) {
+        QString id = child->data(0, idRole).toString();
+        for (int i = 0; i < infoproducers.count(); i++) {
+            e = infoproducers.item(i).toElement();
+            if (e.attribute("id") == id) {
+                // Fix clip
+                e.setAttribute("resource", child->text(1));
+                break;
+            }
+        }
+        for (int i = 0; i < producers.count(); i++) {
+            e = producers.item(i).toElement();
+            if (e.attribute("id") == id) {
+                // Fix clip
+                e.setAttribute("resource", child->text(1));
+                break;
+            }
+        }
+
+        ix++;
+        child = m_view.treeWidget->topLevelItem(ix);
+    }
+    QDialog::accept();
+}
+
+#include "documentchecker.moc"
+
+
diff --git a/src/documentchecker.h b/src/documentchecker.h
new file mode 100644 (file)
index 0000000..ef8e4c5
--- /dev/null
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *   Copyright (C) 2008 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
+ ***************************************************************************/
+
+
+#ifndef DOCUMENTCHECKER_H
+#define DOCUMENTCHECKER_H
+
+#include "ui_missingclips_ui.h"
+
+#include <KUrl>
+
+#include <QDir>
+#include <QPushButton>
+#include <QDomElement>
+
+
+class DocumentChecker : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit DocumentChecker(QDomDocument doc, QWidget * parent = 0);
+    ~DocumentChecker();
+    KUrl::List importFiles();
+
+private slots:
+    virtual void accept();
+    void slotSearchClips();
+    void slotEditItem(QTreeWidgetItem *item, int);
+
+protected:
+    //void wheelEvent(QWheelEvent * event);
+
+private:
+    Ui::MissingClips_UI m_view;
+    QDomDocument m_doc;
+    QString searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash) const;
+
+signals:
+    //void updateThumb();
+};
+
+
+#endif
+
index f20526e04b9228742d82b278b05d4e9ce8659ed8..eb12c9f4a183d5dc16138a1e726acc8cc7701c87 100644 (file)
@@ -26,6 +26,7 @@
 #include "clipmanager.h"
 #include "titlewidget.h"
 #include "mainwindow.h"
+#include "documentchecker.h"
 #include "kdenlive-config.h"
 
 #include <KDebug>
@@ -133,7 +134,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                         }
                         westley.removeChild(tracksinfo);
                     }
-
+                    checkDocumentClips();
                     QDomNodeList producers = m_document.elementsByTagName("producer");
                     QDomNodeList infoproducers = m_document.elementsByTagName("kdenlive_producer");
                     const int max = producers.count();
@@ -1679,5 +1680,12 @@ QString KdenliveDoc::getLadspaFile() const
     return m_projectFolder.path() + "/ladspa/" + counter + ".ladspa";
 }
 
+void KdenliveDoc::checkDocumentClips()
+{
+    DocumentChecker d(m_document);
+    d.exec();
+}
+
+
 #include "kdenlivedoc.moc"
 
index 3b2d8ea3214ab209de7576cdc7b0ab3ad12bd620..01f103d58f4d640ea6c054a0350a673e5b34f105 100644 (file)
@@ -149,6 +149,7 @@ private:
     void setNewClipResource(const QString &id, const QString &path);
     QString searchFileRecursively(const QDir &dir, const QString &matchSize, const QString &matchHash) const;
     void moveProjectData(KUrl url);
+    void checkDocumentClips();
 
 public slots:
     void slotCreateTextClip(QString group, const QString &groupId);