X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=inline;f=src%2Farchivewidget.cpp;h=db2b9e8db2c6d033c1db1f17a42db70beb343ad0;hb=72afb974a98c4ecde0a892c5ed35519d63a576d2;hp=16a8243c1db43613d8384053178836963817411d;hpb=93720831f547d37e5075262008c6af6e5a32aaf5;p=kdenlive diff --git a/src/archivewidget.cpp b/src/archivewidget.cpp index 16a8243c..db2b9e8d 100644 --- a/src/archivewidget.cpp +++ b/src/archivewidget.cpp @@ -28,23 +28,33 @@ #include #include #include - +#include #include +#include +#include + #include +#include #include "projectsettings.h" -ArchiveWidget::ArchiveWidget(QDomDocument doc, QList list, QStringList luma_list, QWidget * parent) : +ArchiveWidget::ArchiveWidget(QString projectName, QDomDocument doc, QList list, QStringList luma_list, QWidget * parent) : QDialog(parent), m_requestedSize(0), m_copyJob(NULL), - m_doc(doc) + m_name(projectName.section('.', 0, -2)), + m_doc(doc), + m_abortArchive(false), + m_extractMode(false), + m_extractArchive(NULL) { setAttribute(Qt::WA_DeleteOnClose); setupUi(this); setWindowTitle(i18n("Archive Project")); archive_url->setUrl(KUrl(QDir::homePath())); connect(archive_url, SIGNAL(textChanged (const QString &)), this, SLOT(slotCheckSpace())); + connect(this, SIGNAL(archivingFinished(bool)), this, SLOT(slotArchivingFinished(bool))); + connect(this, SIGNAL(archiveProgress(int)), this, SLOT(slotArchivingProgress(int))); // Setup categories QTreeWidgetItem *videos = new QTreeWidgetItem(files_list, QStringList() << i18n("Video clips")); @@ -130,9 +140,7 @@ ArchiveWidget::ArchiveWidget(QDomDocument doc, QList list, QStrin generateItems(others, otherUrls); generateItems(proxies, proxyUrls); -#if QT_VERSION >= 0x040500 allFonts.removeDuplicates(); -#endif //TODO: fonts @@ -156,7 +164,8 @@ ArchiveWidget::ArchiveWidget(QDomDocument doc, QList list, QStrin 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")); connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartArchiving())); @@ -165,8 +174,71 @@ ArchiveWidget::ArchiveWidget(QDomDocument doc, QList list, QStrin 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 ) @@ -184,7 +256,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; @@ -270,44 +342,54 @@ 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))); } } bool ArchiveWidget::slotStartArchiving(bool firstPass) { - if (firstPass && m_copyJob) { + if (firstPass && (m_copyJob || m_archiveThread.isRunning())) { // archiving in progress, abort - m_copyJob->kill(KJob::EmitResult); + if (m_copyJob) m_copyJob->kill(KJob::EmitResult); + m_abortArchive = true; return true; } + bool isArchive = compressed_archive->isChecked(); if (!firstPass) m_copyJob = NULL; else { //starting archiving + m_abortArchive = false; m_duplicateFiles.clear(); m_replacementList.clear(); + m_foldersList.clear(); + m_filesList.clear(); + slotDisplayMessage("system-run", i18n("Archiving...")); + repaint(); archive_url->setEnabled(false); + compressed_archive->setEnabled(false); } KUrl::List files; KUrl destUrl; + QString destPath; QTreeWidgetItem *parentItem; bool isSlideshow = false; for (int i = 0; i < files_list->topLevelItemCount(); i++) { parentItem = files_list->topLevelItem(i); if (parentItem->childCount() > 0 && !parentItem->isDisabled()) { if (parentItem->data(0, Qt::UserRole).toString() == "slideshows") { - KIO::NetAccess::mkdir(KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + "slideshows"), this); + KUrl slideFolder(archive_url->url().path(KUrl::AddTrailingSlash) + "slideshows"); + if (isArchive) m_foldersList.append("slideshows"); + else KIO::NetAccess::mkdir(slideFolder, this); isSlideshow = true; } files_list->setCurrentItem(parentItem); if (!isSlideshow) parentItem->setDisabled(true); - destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + parentItem->data(0, Qt::UserRole).toString()); + destPath = parentItem->data(0, Qt::UserRole).toString() + "/"; + destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + destPath); QTreeWidgetItem *item; for (int j = 0; j < parentItem->childCount(); j++) { item = parentItem->child(j); @@ -316,7 +398,8 @@ bool ArchiveWidget::slotStartArchiving(bool firstPass) if (item->isDisabled()) { continue; } - destUrl = KUrl(destUrl.path(KUrl::AddTrailingSlash) + item->data(0, Qt::UserRole).toString() + "/"); + destPath.append(item->data(0, Qt::UserRole).toString() + "/"); + destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + destPath); QStringList srcFiles = item->data(0, Qt::UserRole + 1).toStringList(); for (int k = 0; k < srcFiles.count(); k++) { files << KUrl(srcFiles.at(k)); @@ -334,14 +417,17 @@ bool ArchiveWidget::slotStartArchiving(bool firstPass) else { // We must rename the destination file, since another file with same name exists //TODO: monitor progress - m_duplicateFiles.insert(KUrl(item->text(0)), KUrl(destUrl.path(KUrl::AddTrailingSlash) + item->data(0, Qt::UserRole).toString())); + if (isArchive) { + m_filesList.insert(item->text(0), destPath + item->data(0, Qt::UserRole).toString()); + } + else m_duplicateFiles.insert(KUrl(item->text(0)), KUrl(destUrl.path(KUrl::AddTrailingSlash) + item->data(0, Qt::UserRole).toString())); } } break; } } - if (destUrl.isEmpty()) { + if (destPath.isEmpty()) { if (m_duplicateFiles.isEmpty()) return false; QMapIterator i(m_duplicateFiles); if (i.hasNext()) { @@ -356,12 +442,22 @@ bool ArchiveWidget::slotStartArchiving(bool firstPass) return true; } - if (files.isEmpty()) slotStartArchiving(false); - KIO::NetAccess::mkdir(destUrl, this); - m_copyJob = KIO::copy (files, destUrl, KIO::HideProgressInfo); - connect(m_copyJob, SIGNAL(result(KJob *)), this, SLOT(slotArchivingFinished(KJob *))); - connect(m_copyJob, SIGNAL(processedSize(KJob *, qulonglong)), this, SLOT(slotArchivingProgress(KJob *, qulonglong))); - + if (isArchive) { + m_foldersList.append(destPath); + for (int i = 0; i < files.count(); i++) { + m_filesList.insert(files.at(i).path(), destPath + files.at(i).fileName()); + } + slotArchivingFinished(); + } + else if (files.isEmpty()) { + slotStartArchiving(false); + } + else { + KIO::NetAccess::mkdir(destUrl, this); + m_copyJob = KIO::copy (files, destUrl, KIO::HideProgressInfo); + connect(m_copyJob, SIGNAL(result(KJob *)), this, SLOT(slotArchivingFinished(KJob *))); + connect(m_copyJob, SIGNAL(processedSize(KJob *, qulonglong)), this, SLOT(slotArchivingProgress(KJob *, qulonglong))); + } if (firstPass) { progressBar->setValue(0); buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Abort")); @@ -371,36 +467,35 @@ bool ArchiveWidget::slotStartArchiving(bool firstPass) void ArchiveWidget::slotArchivingFinished(KJob *job) { - if (job->error() == 0) { + if (job == NULL || job->error() == 0) { if (slotStartArchiving(false)) { // We still have files to archive return; } - else { + else if (!compressed_archive->isChecked()) { // 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())); } - buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive")); - archive_url->setEnabled(true); - for (int i = 0; i < files_list->topLevelItemCount(); i++) { - files_list->topLevelItem(i)->setDisabled(false); - for (int j = 0; j < files_list->topLevelItem(i)->childCount(); j++) - files_list->topLevelItem(i)->child(j)->setDisabled(false); - + if (!compressed_archive->isChecked()) { + buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive")); + archive_url->setEnabled(true); + compressed_archive->setEnabled(true); + for (int i = 0; i < files_list->topLevelItemCount(); i++) { + files_list->topLevelItem(i)->setDisabled(false); + for (int j = 0; j < files_list->topLevelItem(i)->childCount(); j++) + files_list->topLevelItem(i)->child(j)->setDisabled(false); + } } } @@ -414,6 +509,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) { @@ -433,15 +530,22 @@ bool ArchiveWidget::processProjectFile() dest.addPath(item->data(0, Qt::UserRole).toString()); } m_replacementList.insert(src, dest); - kDebug()<<"___ PROCESS ITEM :"<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(); @@ -490,7 +594,28 @@ bool ArchiveWidget::processProjectFile() } } - QString path = archive_url->url().path(KUrl::AddTrailingSlash) + "project.kdenlive"; + 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(playList.toUtf8()); + m_temp->close(); + m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::createArchive); + return true; + } + + QString path = archive_url->url().path(KUrl::AddTrailingSlash) + m_name + ".kdenlive"; QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { kWarning() << "////// ERROR writing to file: " << path; @@ -508,3 +633,140 @@ bool ArchiveWidget::processProjectFile() return true; } +void ArchiveWidget::createArchive() +{ + QFileInfo dirInfo(archive_url->url().path()); + QString user = dirInfo.owner(); + QString group = dirInfo.group(); + KTar archive(archive_url->url().path(KUrl::AddTrailingSlash) + m_name + ".tar.gz", "application/x-gzip"); + archive.open( QIODevice::WriteOnly ); + + // Create folders + foreach(const QString &path, m_foldersList) { + archive.writeDir(path, user, group); + } + + // Add files + int ix = 0; + QMapIterator i(m_filesList); + while (i.hasNext()) { + i.next(); + archive.addLocalFile(i.key(), i.value()); + emit archiveProgress((int) 100 * ix / m_filesList.count()); + ix++; + } + + // Add project file + archive.addLocalFile(m_temp->fileName(), m_name + ".kdenlive"); + bool result = archive.close(); + delete m_temp; + emit archivingFinished(result); +} + +void ArchiveWidget::slotArchivingFinished(bool result) +{ + if (result) { + slotDisplayMessage("dialog-ok", i18n("Project was successfully archived.")); + } + else { + slotDisplayMessage("dialog-close", i18n("There was an error processing project file")); + } + progressBar->setValue(100); + buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive")); + archive_url->setEnabled(true); + compressed_archive->setEnabled(true); + for (int i = 0; i < files_list->topLevelItemCount(); i++) { + files_list->topLevelItem(i)->setDisabled(false); + for (int j = 0; j < files_list->topLevelItem(i)->childCount(); j++) + files_list->topLevelItem(i)->child(j)->setDisabled(false); + } +} + +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 (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(); +}