From: Jean-Baptiste Mardelle Date: Mon, 4 May 2009 09:50:34 +0000 (+0000) Subject: Start of the new document checker (check for missing clips,...) not fully functionnal yet X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=0618f3f840f5aff08f66f8b76e5377bd5c41e217;p=kdenlive Start of the new document checker (check for missing clips,...) not fully functionnal yet svn path=/trunk/kdenlive/; revision=3353 --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a5dcda6..fa795173 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 index 00000000..724cdf98 --- /dev/null +++ b/src/documentchecker.cpp @@ -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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +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 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 index 00000000..ef8e4c51 --- /dev/null +++ b/src/documentchecker.h @@ -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 + +#include +#include +#include + + +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 + diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index f20526e0..eb12c9f4 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -26,6 +26,7 @@ #include "clipmanager.h" #include "titlewidget.h" #include "mainwindow.h" +#include "documentchecker.h" #include "kdenlive-config.h" #include @@ -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" diff --git a/src/kdenlivedoc.h b/src/kdenlivedoc.h index 3b2d8ea3..01f103d5 100644 --- a/src/kdenlivedoc.h +++ b/src/kdenlivedoc.h @@ -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);