]> git.sesse.net Git - kdenlive/blobdiff - src/archivewidget.cpp
Cleanup document loading and make sure to read all thumbs from disk cache on opening
[kdenlive] / src / archivewidget.cpp
index a7830bedcaf9730b0b683cbf11a584e58141eb05..363781df6423abef52f85f0cde8c52e71ce24da4 100644 (file)
 #include <KGuiItem>
 #include <KIO/NetAccess>
 #include <KTar>
-
 #include <KDebug>
+#include <KApplication>
+#include <kio/directorysizejob.h>
+
 #include <QTreeWidget>
 #include <QtConcurrentRun>
 #include "projectsettings.h"
@@ -42,7 +44,9 @@ ArchiveWidget::ArchiveWidget(QString projectName, QDomDocument doc, QList <DocCl
         m_copyJob(NULL),
         m_name(projectName.section('.', 0, -2)),
         m_doc(doc),
-        m_abortArchive(false)
+        m_abortArchive(false),
+        m_extractMode(false),
+        m_extractArchive(NULL)
 {
     setAttribute(Qt::WA_DeleteOnClose);
     setupUi(this);
@@ -162,7 +166,7 @@ ArchiveWidget::ArchiveWidget(QString projectName, QDomDocument doc, QList <DocCl
             parentItem->setText(0, files_list->topLevelItem(i)->text(0) + " " + i18np("(%1 item)", "(%1 items)", items));
         }
     }
-
+    if (m_name.isEmpty()) m_name = i18n("Untitled");
     compressed_archive->setText(compressed_archive->text() + " (" + m_name + ".tar.gz)");
     project_files->setText(i18np("%1 file to archive, requires %2", "%1 files to archive, requires %2", total, KIO::convertSize(m_requestedSize)));
     buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
@@ -172,8 +176,71 @@ ArchiveWidget::ArchiveWidget(QString projectName, QDomDocument doc, QList <DocCl
     slotCheckSpace();
 }
 
+// Constructor for extract widget
+ArchiveWidget::ArchiveWidget(const KUrl &url, QWidget * parent):
+    QDialog(parent),
+    m_extractMode(true),
+    m_extractUrl(url)
+{
+    //setAttribute(Qt::WA_DeleteOnClose);
+
+    setupUi(this);
+    connect(this, SIGNAL(extractingFinished()), this, SLOT(slotExtractingFinished()));
+    connect(this, SIGNAL(showMessage(const QString &, const QString &)), this, SLOT(slotDisplayMessage(const QString &, const QString &)));
+    
+    compressed_archive->setHidden(true);
+    project_files->setHidden(true);
+    files_list->setHidden(true);
+    label->setText(i18n("Extract to"));
+    setWindowTitle(i18n("Open Archived Project"));
+    archive_url->setUrl(KUrl(QDir::homePath()));
+    buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Extract"));
+    connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartExtracting()));
+    buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
+    adjustSize();
+    m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::openArchiveForExtraction);
+}
+
+
 ArchiveWidget::~ArchiveWidget()
 {
+    if (m_extractArchive) delete m_extractArchive;
+}
+
+void ArchiveWidget::slotDisplayMessage(const QString &icon, const QString &text)
+{
+    icon_info->setPixmap(KIcon(icon).pixmap(16, 16));
+    text_info->setText(text);
+}
+
+void ArchiveWidget::openArchiveForExtraction()
+{
+    emit showMessage("system-run", i18n("Opening archive..."));
+    m_extractArchive = new KTar(m_extractUrl.path());
+    if (!m_extractArchive->isOpen() && !m_extractArchive->open( QIODevice::ReadOnly )) {
+        emit showMessage("dialog-close", i18n("Cannot open archive file:\n %1", m_extractUrl.path()));
+        groupBox->setEnabled(false);
+        return;
+    }
+
+    // Check that it is a kdenlive project archive
+    bool isProjectArchive = false;
+    QStringList files = m_extractArchive->directory()->entries();
+    for (int i = 0; i < files.count(); i++) {
+        if (files.at(i).endsWith(".kdenlive")) {
+            m_projectName = files.at(i);
+            isProjectArchive = true;
+            break;
+        }
+    }
+
+    if (!isProjectArchive) {
+        emit showMessage("dialog-close", i18n("File %1\n is not an archived Kdenlive project", m_extractUrl.path()));
+        groupBox->setEnabled(false);
+        return;
+    }
+    buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
+    emit showMessage("dialog-ok", i18n("Ready"));
 }
 
 void ArchiveWidget::done ( int r )
@@ -191,7 +258,7 @@ void ArchiveWidget::closeEvent ( QCloseEvent * e )
 
 bool ArchiveWidget::closeAccepted()
 {
-    if (!archive_url->isEnabled()) {
+    if (!m_extractMode && !archive_url->isEnabled()) {
         // Archiving in progress, should we stop?
         if (KMessageBox::warningContinueCancel(this, i18n("Archiving in progress, do you want to stop it?"), i18n("Stop Archiving"), KGuiItem(i18n("Stop Archiving"))) != KMessageBox::Continue) {
             return false;
@@ -277,13 +344,11 @@ void ArchiveWidget::slotCheckSpace()
     if (freeSize > m_requestedSize) {
         // everything is ok
         buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
-        icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
-        text_info->setText(i18n("Available space on drive: %1", KIO::convertSize(freeSize)));
+        slotDisplayMessage("dialog-ok", i18n("Available space on drive: %1", KIO::convertSize(freeSize)));
     }
     else {
         buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
-        icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
-        text_info->setText(i18n("Not enough space on drive, free space: %1", KIO::convertSize(freeSize)));
+        slotDisplayMessage("dialog-close", i18n("Not enough space on drive, free space: %1", KIO::convertSize(freeSize)));
     }
 }
 
@@ -304,8 +369,7 @@ bool ArchiveWidget::slotStartArchiving(bool firstPass)
         m_replacementList.clear();
         m_foldersList.clear();
         m_filesList.clear();
-        icon_info->setPixmap(KIcon("system-run").pixmap(16, 16));
-        text_info->setText(i18n("Archiving..."));
+        slotDisplayMessage("system-run", i18n("Archiving..."));
         repaint();
         archive_url->setEnabled(false);
         compressed_archive->setEnabled(false);
@@ -414,19 +478,16 @@ void ArchiveWidget::slotArchivingFinished(KJob *job)
             // Archiving finished
             progressBar->setValue(100);
             if (processProjectFile()) {
-                icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
-                text_info->setText(i18n("Project was successfully archived."));
+                slotDisplayMessage("dialog-ok", i18n("Project was successfully archived."));
             }
             else {
-                icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
-                text_info->setText(i18n("There was an error processing project file"));
+                slotDisplayMessage("dialog-close", i18n("There was an error processing project file"));
             }
         } else processProjectFile();
     }
     else {
         m_copyJob = NULL;
-        icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
-        text_info->setText(i18n("There was an error while copying the files: %1", job->errorString()));
+        slotDisplayMessage("dialog-close", i18n("There was an error while copying the files: %1", job->errorString()));
     }
     if (!compressed_archive->isChecked()) {
         buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
@@ -450,6 +511,8 @@ bool ArchiveWidget::processProjectFile()
 {
     KUrl destUrl;
     QTreeWidgetItem *item;
+    bool isArchive = compressed_archive->isChecked();
+
     for (int i = 0; i < files_list->topLevelItemCount(); i++) {
         QTreeWidgetItem *parentItem = files_list->topLevelItem(i);
         if (parentItem->childCount() > 0) {
@@ -473,10 +536,18 @@ bool ArchiveWidget::processProjectFile()
         }
     }
     
-    // process kdenlive producers           
     QDomElement mlt = m_doc.documentElement();
     QString root = mlt.attribute("root") + "/";
-    mlt.setAttribute("root", archive_url->url().path(KUrl::RemoveTrailingSlash));
+
+    // Adjust global settings
+    QString basePath;
+    if (isArchive) basePath = "$CURRENTPATH";
+    else basePath = archive_url->url().path(KUrl::RemoveTrailingSlash);
+    mlt.setAttribute("root", basePath);
+    QDomElement project = mlt.firstChildElement("kdenlivedoc");
+    project.setAttribute("projectfolder", basePath);
+
+    // process kdenlive producers
     QDomNodeList prods = mlt.elementsByTagName("kdenlive_producer");
     for (int i = 0; i < prods.count(); i++) {
         QDomElement e = prods.item(i).toElement();
@@ -525,11 +596,22 @@ bool ArchiveWidget::processProjectFile()
         }
     }
 
-    bool isArchive = compressed_archive->isChecked();
+    QString playList = m_doc.toString();
+    if (isArchive) {
+        QString startString("\"");
+        startString.append(archive_url->url().path(KUrl::RemoveTrailingSlash));
+        QString endString("\"");
+        endString.append(basePath);
+        playList.replace(startString, endString);
+        startString = ">" + archive_url->url().path(KUrl::RemoveTrailingSlash);
+        endString = ">" + basePath;
+        playList.replace(startString, endString);
+    }
+
     if (isArchive) {
         m_temp = new KTemporaryFile;
         if (!m_temp->open()) KMessageBox::error(this, i18n("Cannot create temporary file"));
-        m_temp->write(m_doc.toString().toUtf8());
+        m_temp->write(playList.toUtf8());
         m_temp->close();
         m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::createArchive);
         return true;
@@ -586,12 +668,10 @@ void ArchiveWidget::createArchive()
 void ArchiveWidget::slotArchivingFinished(bool result)
 {
     if (result) {
-        icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
-        text_info->setText(i18n("Project was successfully archived."));
+        slotDisplayMessage("dialog-ok", i18n("Project was successfully archived."));
     }
     else {
-        icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
-        text_info->setText(i18n("There was an error processing project file"));
+        slotDisplayMessage("dialog-close", i18n("There was an error processing project file"));
     }
     progressBar->setValue(100);
     buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
@@ -608,3 +688,87 @@ void ArchiveWidget::slotArchivingProgress(int p)
 {
     progressBar->setValue(p);
 }
+
+void ArchiveWidget::slotStartExtracting()
+{
+    if (m_archiveThread.isRunning()) {
+        //TODO: abort extracting
+        return;
+    }
+    QFileInfo f(m_extractUrl.path());
+    m_requestedSize = f.size();
+    KIO::NetAccess::mkdir(archive_url->url().path(KUrl::RemoveTrailingSlash), this);
+    slotDisplayMessage("system-run", i18n("Extracting..."));
+    buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Abort"));
+    m_progressTimer = new QTimer;
+    m_progressTimer->setInterval(800);
+    m_progressTimer->setSingleShot(false);
+    connect(m_progressTimer, SIGNAL(timeout()), this, SLOT(slotExtractProgress()));
+    m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::doExtracting);
+    m_progressTimer->start();
+}
+
+void ArchiveWidget::slotExtractProgress()
+{
+    KIO::DirectorySizeJob *job = KIO::directorySize(archive_url->url());
+    connect(job, SIGNAL(result(KJob*)), this, SLOT(slotGotProgress(KJob*)));
+}
+
+void ArchiveWidget::slotGotProgress(KJob* job)
+{
+    if (!job->error()) {
+        KIO::DirectorySizeJob *j = static_cast <KIO::DirectorySizeJob *>(job);
+        progressBar->setValue((int) 100 * j->totalSize() / m_requestedSize);
+    }
+    job->deleteLater();
+}
+
+void ArchiveWidget::doExtracting()
+{
+    m_extractArchive->directory()->copyTo(archive_url->url().path(KUrl::AddTrailingSlash));
+    m_extractArchive->close();
+    emit extractingFinished();    
+}
+
+QString ArchiveWidget::extractedProjectFile()
+{
+    return archive_url->url().path(KUrl::AddTrailingSlash) + m_projectName;
+}
+
+void ArchiveWidget::slotExtractingFinished()
+{
+    m_progressTimer->stop();
+    delete m_progressTimer;
+    // Process project file
+    QFile file(extractedProjectFile());
+    bool error = false;
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+        error = true;
+    }
+    else {
+        QString playList = file.readAll();
+        file.close();
+        if (playList.isEmpty()) {
+            error = true;
+        }
+        else {
+            playList.replace("$CURRENTPATH", archive_url->url().path(KUrl::RemoveTrailingSlash));
+            if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+                kWarning() << "//////  ERROR writing to file: ";
+                error = true;
+            }
+            else {
+                file.write(playList.toUtf8());
+                if (file.error() != QFile::NoError) {
+                    error = true;
+                }
+                file.close();
+            }
+        }
+    }
+    if (error) {
+        KMessageBox::sorry(kapp->activeWindow(), i18n("Cannot open project file %1", extractedProjectFile()), i18n("Cannot open file"));
+        reject();
+    }
+    else accept();
+}