1 /***************************************************************************
2 * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
21 #include "archivewidget.h"
22 #include "titlewidget.h"
25 #include <KDiskFreeSpaceInfo>
26 #include <KUrlRequester>
27 #include <KFileDialog>
28 #include <KMessageBox>
30 #include <KIO/NetAccess>
33 #include <KApplication>
35 #include <QTreeWidget>
36 #include <QtConcurrentRun>
37 #include "projectsettings.h"
40 ArchiveWidget::ArchiveWidget(QString projectName, QDomDocument doc, QList <DocClipBase*> list, QStringList luma_list, QWidget * parent) :
44 m_name(projectName.section('.', 0, -2)),
46 m_abortArchive(false),
49 setAttribute(Qt::WA_DeleteOnClose);
51 setWindowTitle(i18n("Archive Project"));
52 archive_url->setUrl(KUrl(QDir::homePath()));
53 connect(archive_url, SIGNAL(textChanged (const QString &)), this, SLOT(slotCheckSpace()));
54 connect(this, SIGNAL(archivingFinished(bool)), this, SLOT(slotArchivingFinished(bool)));
55 connect(this, SIGNAL(archiveProgress(int)), this, SLOT(slotArchivingProgress(int)));
58 QTreeWidgetItem *videos = new QTreeWidgetItem(files_list, QStringList() << i18n("Video clips"));
59 videos->setIcon(0, KIcon("video-x-generic"));
60 videos->setData(0, Qt::UserRole, "videos");
61 videos->setExpanded(false);
62 QTreeWidgetItem *sounds = new QTreeWidgetItem(files_list, QStringList() << i18n("Audio clips"));
63 sounds->setIcon(0, KIcon("audio-x-generic"));
64 sounds->setData(0, Qt::UserRole, "sounds");
65 sounds->setExpanded(false);
66 QTreeWidgetItem *images = new QTreeWidgetItem(files_list, QStringList() << i18n("Image clips"));
67 images->setIcon(0, KIcon("image-x-generic"));
68 images->setData(0, Qt::UserRole, "images");
69 images->setExpanded(false);
70 QTreeWidgetItem *slideshows = new QTreeWidgetItem(files_list, QStringList() << i18n("Slideshow clips"));
71 slideshows->setIcon(0, KIcon("image-x-generic"));
72 slideshows->setData(0, Qt::UserRole, "slideshows");
73 slideshows->setExpanded(false);
74 QTreeWidgetItem *texts = new QTreeWidgetItem(files_list, QStringList() << i18n("Text clips"));
75 texts->setIcon(0, KIcon("text-plain"));
76 texts->setData(0, Qt::UserRole, "texts");
77 texts->setExpanded(false);
78 QTreeWidgetItem *others = new QTreeWidgetItem(files_list, QStringList() << i18n("Other clips"));
79 others->setIcon(0, KIcon("unknown"));
80 others->setData(0, Qt::UserRole, "others");
81 others->setExpanded(false);
82 QTreeWidgetItem *lumas = new QTreeWidgetItem(files_list, QStringList() << i18n("Luma files"));
83 lumas->setIcon(0, KIcon("image-x-generic"));
84 lumas->setData(0, Qt::UserRole, "lumas");
85 lumas->setExpanded(false);
87 QTreeWidgetItem *proxies = new QTreeWidgetItem(files_list, QStringList() << i18n("Proxy clips"));
88 proxies->setIcon(0, KIcon("video-x-generic"));
89 proxies->setData(0, Qt::UserRole, "proxy");
90 proxies->setExpanded(false);
95 QStringList fileNames;
96 generateItems(lumas, luma_list);
98 QStringList slideUrls;
99 QStringList audioUrls;
100 QStringList videoUrls;
101 QStringList imageUrls;
102 QStringList otherUrls;
103 QStringList proxyUrls;
105 for (int i = 0; i < list.count(); i++) {
106 DocClipBase *clip = list.at(i);
107 CLIPTYPE t = clip->clipType();
108 if (t == SLIDESHOW) {
109 KUrl slideUrl = clip->fileURL();
110 //TODO: Slideshow files
111 slideUrls << slideUrl.path();
113 else if (t == IMAGE) imageUrls << clip->fileURL().path();
114 else if (t == TEXT) {
115 QStringList imagefiles = TitleWidget::extractImageList(clip->getProperty("xmldata"));
116 QStringList fonts = TitleWidget::extractFontList(clip->getProperty("xmldata"));
117 imageUrls << imagefiles;
119 } else if (t == PLAYLIST) {
120 QStringList files = ProjectSettings::extractPlaylistUrls(clip->fileURL().path());
123 else if (!clip->fileURL().isEmpty()) {
124 if (t == AUDIO) audioUrls << clip->fileURL().path();
126 videoUrls << clip->fileURL().path();
127 // Check if we have a proxy
128 QString proxy = clip->getProperty("proxy");
129 if (!proxy.isEmpty() && proxy != "-" && QFile::exists(proxy)) proxyUrls << proxy;
134 generateItems(sounds, audioUrls);
135 generateItems(videos, videoUrls);
136 generateItems(images, imageUrls);
137 generateItems(slideshows, slideUrls);
138 generateItems(others, otherUrls);
139 generateItems(proxies, proxyUrls);
141 #if QT_VERSION >= 0x040500
142 allFonts.removeDuplicates();
147 // Hide unused categories, add item count
149 for (int i = 0; i < files_list->topLevelItemCount(); i++) {
150 QTreeWidgetItem *parentItem = files_list->topLevelItem(i);
151 int items = parentItem->childCount();
153 files_list->topLevelItem(i)->setHidden(true);
156 if (parentItem->data(0, Qt::UserRole).toString() == "slideshows")
158 // Special case: slideshows contain several files
159 for (int j = 0; j < items; j++) {
160 total += parentItem->child(j)->data(0, Qt::UserRole + 1).toStringList().count();
164 parentItem->setText(0, files_list->topLevelItem(i)->text(0) + " " + i18np("(%1 item)", "(%1 items)", items));
168 compressed_archive->setText(compressed_archive->text() + " (" + m_name + ".tar.gz)");
169 project_files->setText(i18np("%1 file to archive, requires %2", "%1 files to archive, requires %2", total, KIO::convertSize(m_requestedSize)));
170 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
171 connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartArchiving()));
172 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
177 // Constructor for extract widget
178 ArchiveWidget::ArchiveWidget(const KUrl &url, QWidget * parent):
183 //setAttribute(Qt::WA_DeleteOnClose);
184 KTar archive(url.path());
185 archive.open( QIODevice::ReadOnly );
187 // Check that it is a kdenlive project archive
188 bool isProjectArchive = false;
189 QStringList files = archive.directory()->entries();
190 for (int i = 0; i < files.count(); i++) {
191 if (files.at(i).endsWith(".kdenlive")) {
192 m_projectName = files.at(i);
193 isProjectArchive = true;
199 if (!isProjectArchive) {
200 KMessageBox::sorry(kapp->activeWindow(), i18n("%1 is not an archived Kdenlive project", url.path(), i18n("Cannot open file")));
202 //HACK: find a better way to terminate the dialog
203 QTimer::singleShot(50, this, SLOT(reject()));
207 connect(this, SIGNAL(extractingFinished()), this, SLOT(slotExtractingFinished()));
209 compressed_archive->setHidden(true);
210 project_files->setHidden(true);
211 files_list->setHidden(true);
212 label->setText(i18n("Extract to"));
213 setWindowTitle(i18n("Open Archived Project"));
214 archive_url->setUrl(KUrl(QDir::homePath()));
215 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Extract"));
216 connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(slotStartExtracting()));
220 ArchiveWidget::~ArchiveWidget()
224 void ArchiveWidget::done ( int r )
226 if (closeAccepted()) QDialog::done(r);
229 void ArchiveWidget::closeEvent ( QCloseEvent * e )
232 if (closeAccepted()) e->accept();
237 bool ArchiveWidget::closeAccepted()
239 if (!m_extractMode && !archive_url->isEnabled()) {
240 // Archiving in progress, should we stop?
241 if (KMessageBox::warningContinueCancel(this, i18n("Archiving in progress, do you want to stop it?"), i18n("Stop Archiving"), KGuiItem(i18n("Stop Archiving"))) != KMessageBox::Continue) {
244 if (m_copyJob) m_copyJob->kill();
250 void ArchiveWidget::generateItems(QTreeWidgetItem *parentItem, QStringList items)
252 QStringList filesList;
255 bool isSlideshow = parentItem->data(0, Qt::UserRole).toString() == "slideshows";
256 foreach(const QString & file, items) {
257 QTreeWidgetItem *item = new QTreeWidgetItem(parentItem, QStringList() << file);
258 fileName = KUrl(file).fileName();
260 // we store each slideshow in a separate subdirectory
261 item->setData(0, Qt::UserRole, ix);
264 QDir dir(slideUrl.directory(KUrl::AppendTrailingSlash));
265 if (slideUrl.fileName().startsWith(".all.")) {
266 // mimetype slideshow (for example *.png)
269 // TODO: improve jpeg image detection with extension like jpeg, requires change in MLT image producers
270 filters << "*." + slideUrl.fileName().section('.', -1);
271 dir.setNameFilters(filters);
272 QFileInfoList resultList = dir.entryInfoList(QDir::Files);
273 QStringList slideImages;
274 for (int i = 0; i < resultList.count(); i++) {
275 m_requestedSize += resultList.at(i).size();
276 slideImages << resultList.at(i).absoluteFilePath();
278 item->setData(0, Qt::UserRole + 1, slideImages);
281 // pattern url (like clip%.3d.png)
282 QStringList result = dir.entryList(QDir::Files);
283 QString filter = slideUrl.fileName();
284 QString ext = filter.section('.', -1);
285 filter = filter.section('%', 0, -2);
286 QString regexp = "^" + filter + "\\d+\\." + ext + "$";
288 QStringList slideImages;
289 QString directory = dir.absolutePath();
290 if (!directory.endsWith('/')) directory.append('/');
291 foreach(const QString & path, result) {
292 if (rx.exactMatch(path)) {
293 m_requestedSize += QFileInfo(directory + path).size();
294 slideImages << directory + path;
297 item->setData(0, Qt::UserRole + 1, slideImages);
300 else if (filesList.contains(fileName)) {
301 // we have 2 files with same name
303 QString newFileName = fileName.section('.', 0, -2) + "_" + QString::number(ix) + "." + fileName.section('.', -1);
304 while (filesList.contains(newFileName)) {
306 newFileName = fileName.section('.', 0, -2) + "_" + QString::number(ix) + "." + fileName.section('.', -1);
308 fileName = newFileName;
309 item->setData(0, Qt::UserRole, fileName);
312 m_requestedSize += QFileInfo(file).size();
313 filesList << fileName;
318 void ArchiveWidget::slotCheckSpace()
320 KDiskFreeSpaceInfo inf = KDiskFreeSpaceInfo::freeSpaceInfo( archive_url->url().path());
321 KIO::filesize_t freeSize = inf.available();;
322 if (freeSize > m_requestedSize) {
324 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(true);
325 icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
326 text_info->setText(i18n("Available space on drive: %1", KIO::convertSize(freeSize)));
329 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
330 icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
331 text_info->setText(i18n("Not enough space on drive, free space: %1", KIO::convertSize(freeSize)));
335 bool ArchiveWidget::slotStartArchiving(bool firstPass)
337 if (firstPass && (m_copyJob || m_archiveThread.isRunning())) {
338 // archiving in progress, abort
339 if (m_copyJob) m_copyJob->kill(KJob::EmitResult);
340 m_abortArchive = true;
343 bool isArchive = compressed_archive->isChecked();
344 if (!firstPass) m_copyJob = NULL;
347 m_abortArchive = false;
348 m_duplicateFiles.clear();
349 m_replacementList.clear();
350 m_foldersList.clear();
352 icon_info->setPixmap(KIcon("system-run").pixmap(16, 16));
353 text_info->setText(i18n("Archiving..."));
355 archive_url->setEnabled(false);
356 compressed_archive->setEnabled(false);
361 QTreeWidgetItem *parentItem;
362 bool isSlideshow = false;
363 for (int i = 0; i < files_list->topLevelItemCount(); i++) {
364 parentItem = files_list->topLevelItem(i);
365 if (parentItem->childCount() > 0 && !parentItem->isDisabled()) {
366 if (parentItem->data(0, Qt::UserRole).toString() == "slideshows") {
367 KUrl slideFolder(archive_url->url().path(KUrl::AddTrailingSlash) + "slideshows");
368 if (isArchive) m_foldersList.append("slideshows");
369 else KIO::NetAccess::mkdir(slideFolder, this);
372 files_list->setCurrentItem(parentItem);
373 if (!isSlideshow) parentItem->setDisabled(true);
374 destPath = parentItem->data(0, Qt::UserRole).toString() + "/";
375 destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + destPath);
376 QTreeWidgetItem *item;
377 for (int j = 0; j < parentItem->childCount(); j++) {
378 item = parentItem->child(j);
379 // Special case: slideshows
381 if (item->isDisabled()) {
384 destPath.append(item->data(0, Qt::UserRole).toString() + "/");
385 destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + destPath);
386 QStringList srcFiles = item->data(0, Qt::UserRole + 1).toStringList();
387 for (int k = 0; k < srcFiles.count(); k++) {
388 files << KUrl(srcFiles.at(k));
390 item->setDisabled(true);
391 if (parentItem->indexOfChild(item) == parentItem->childCount() - 1) {
392 // We have processed all slideshows
393 parentItem->setDisabled(true);
397 else if (item->data(0, Qt::UserRole).isNull()) {
398 files << KUrl(item->text(0));
401 // We must rename the destination file, since another file with same name exists
402 //TODO: monitor progress
404 m_filesList.insert(item->text(0), destPath + item->data(0, Qt::UserRole).toString());
406 else m_duplicateFiles.insert(KUrl(item->text(0)), KUrl(destUrl.path(KUrl::AddTrailingSlash) + item->data(0, Qt::UserRole).toString()));
413 if (destPath.isEmpty()) {
414 if (m_duplicateFiles.isEmpty()) return false;
415 QMapIterator<KUrl, KUrl> i(m_duplicateFiles);
418 KUrl startJobSrc = i.key();
419 KUrl startJobDst = i.value();
420 m_duplicateFiles.remove(startJobSrc);
421 KIO::CopyJob *job = KIO::copyAs(startJobSrc, startJobDst, KIO::HideProgressInfo);
422 connect(job, SIGNAL(result(KJob *)), this, SLOT(slotArchivingFinished(KJob *)));
423 connect(job, SIGNAL(processedSize(KJob *, qulonglong)), this, SLOT(slotArchivingProgress(KJob *, qulonglong)));
429 m_foldersList.append(destPath);
430 for (int i = 0; i < files.count(); i++) {
431 m_filesList.insert(files.at(i).path(), destPath + files.at(i).fileName());
433 slotArchivingFinished();
435 else if (files.isEmpty()) {
436 slotStartArchiving(false);
439 KIO::NetAccess::mkdir(destUrl, this);
440 m_copyJob = KIO::copy (files, destUrl, KIO::HideProgressInfo);
441 connect(m_copyJob, SIGNAL(result(KJob *)), this, SLOT(slotArchivingFinished(KJob *)));
442 connect(m_copyJob, SIGNAL(processedSize(KJob *, qulonglong)), this, SLOT(slotArchivingProgress(KJob *, qulonglong)));
445 progressBar->setValue(0);
446 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Abort"));
451 void ArchiveWidget::slotArchivingFinished(KJob *job)
453 if (job == NULL || job->error() == 0) {
454 if (slotStartArchiving(false)) {
455 // We still have files to archive
458 else if (!compressed_archive->isChecked()) {
459 // Archiving finished
460 progressBar->setValue(100);
461 if (processProjectFile()) {
462 icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
463 text_info->setText(i18n("Project was successfully archived."));
466 icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
467 text_info->setText(i18n("There was an error processing project file"));
469 } else processProjectFile();
473 icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
474 text_info->setText(i18n("There was an error while copying the files: %1", job->errorString()));
476 if (!compressed_archive->isChecked()) {
477 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
478 archive_url->setEnabled(true);
479 compressed_archive->setEnabled(true);
480 for (int i = 0; i < files_list->topLevelItemCount(); i++) {
481 files_list->topLevelItem(i)->setDisabled(false);
482 for (int j = 0; j < files_list->topLevelItem(i)->childCount(); j++)
483 files_list->topLevelItem(i)->child(j)->setDisabled(false);
488 void ArchiveWidget::slotArchivingProgress(KJob *, qulonglong size)
490 progressBar->setValue((int) 100 * size / m_requestedSize);
494 bool ArchiveWidget::processProjectFile()
497 QTreeWidgetItem *item;
498 bool isArchive = compressed_archive->isChecked();
500 for (int i = 0; i < files_list->topLevelItemCount(); i++) {
501 QTreeWidgetItem *parentItem = files_list->topLevelItem(i);
502 if (parentItem->childCount() > 0) {
503 destUrl = KUrl(archive_url->url().path(KUrl::AddTrailingSlash) + parentItem->data(0, Qt::UserRole).toString());
504 bool isSlideshow = parentItem->data(0, Qt::UserRole).toString() == "slideshows";
505 for (int j = 0; j < parentItem->childCount(); j++) {
506 item = parentItem->child(j);
507 KUrl src(item->text(0));
510 dest = KUrl(destUrl.path(KUrl::AddTrailingSlash) + item->data(0, Qt::UserRole).toString() + "/" + src.fileName());
512 else if (item->data(0, Qt::UserRole).isNull()) {
513 dest.addPath(src.fileName());
516 dest.addPath(item->data(0, Qt::UserRole).toString());
518 m_replacementList.insert(src, dest);
523 QDomElement mlt = m_doc.documentElement();
524 QString root = mlt.attribute("root") + "/";
526 // Adjust global settings
528 if (isArchive) basePath = "$CURRENTPATH";
529 else basePath = archive_url->url().path(KUrl::RemoveTrailingSlash);
530 mlt.setAttribute("root", basePath);
531 QDomElement project = mlt.elementsByTagName("kdenlivedoc").at(0).toElement();
532 project.setAttribute("projectfolder", basePath);
534 // process kdenlive producers
535 QDomNodeList prods = mlt.elementsByTagName("kdenlive_producer");
536 for (int i = 0; i < prods.count(); i++) {
537 QDomElement e = prods.item(i).toElement();
538 if (e.isNull()) continue;
539 if (e.hasAttribute("resource")) {
540 KUrl src(e.attribute("resource"));
541 KUrl dest = m_replacementList.value(src);
542 if (!dest.isEmpty()) e.setAttribute("resource", dest.path());
544 if (e.hasAttribute("proxy") && e.attribute("proxy") != "-") {
545 KUrl src(e.attribute("proxy"));
546 KUrl dest = m_replacementList.value(src);
547 if (!dest.isEmpty()) e.setAttribute("proxy", dest.path());
551 // process mlt producers
552 prods = mlt.elementsByTagName("producer");
553 for (int i = 0; i < prods.count(); i++) {
554 QDomElement e = prods.item(i).toElement();
555 if (e.isNull()) continue;
556 QString src = EffectsList::property(e, "resource");
557 if (!src.isEmpty()) {
558 if (!src.startsWith('/')) src.prepend(root);
560 KUrl dest = m_replacementList.value(src);
561 if (!dest.isEmpty()) EffectsList::setProperty(e, "resource", dest.path());
565 // process mlt transitions (for luma files)
566 prods = mlt.elementsByTagName("transition");
568 for (int i = 0; i < prods.count(); i++) {
569 QDomElement e = prods.item(i).toElement();
570 if (e.isNull()) continue;
571 attribute = "resource";
572 QString src = EffectsList::property(e, attribute);
573 if (src.isEmpty()) attribute = "luma";
574 src = EffectsList::property(e, attribute);
575 if (!src.isEmpty()) {
576 if (!src.startsWith('/')) src.prepend(root);
578 KUrl dest = m_replacementList.value(src);
579 if (!dest.isEmpty()) EffectsList::setProperty(e, attribute, dest.path());
583 QString playList = m_doc.toString();
585 QString startString("\"");
586 startString.append(archive_url->url().path(KUrl::RemoveTrailingSlash));
587 QString endString("\"");
588 endString.append(basePath);
589 playList.replace(startString, endString);
590 startString = ">" + archive_url->url().path(KUrl::RemoveTrailingSlash);
591 endString = ">" + basePath;
592 playList.replace(startString, endString);
596 m_temp = new KTemporaryFile;
597 if (!m_temp->open()) KMessageBox::error(this, i18n("Cannot create temporary file"));
598 m_temp->write(playList.toUtf8());
600 m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::createArchive);
604 QString path = archive_url->url().path(KUrl::AddTrailingSlash) + m_name + ".kdenlive";
606 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
607 kWarning() << "////// ERROR writing to file: " << path;
608 KMessageBox::error(this, i18n("Cannot write to file %1", path));
612 file.write(m_doc.toString().toUtf8());
613 if (file.error() != QFile::NoError) {
614 KMessageBox::error(this, i18n("Cannot write to file %1", path));
622 void ArchiveWidget::createArchive()
624 QFileInfo dirInfo(archive_url->url().path());
625 QString user = dirInfo.owner();
626 QString group = dirInfo.group();
627 KTar archive(archive_url->url().path(KUrl::AddTrailingSlash) + m_name + ".tar.gz", "application/x-gzip");
628 archive.open( QIODevice::WriteOnly );
631 foreach(const QString &path, m_foldersList) {
632 archive.writeDir(path, user, group);
637 QMapIterator<QString, QString> i(m_filesList);
638 while (i.hasNext()) {
640 archive.addLocalFile(i.key(), i.value());
641 emit archiveProgress((int) 100 * ix / m_filesList.count());
646 archive.addLocalFile(m_temp->fileName(), m_name + ".kdenlive");
647 bool result = archive.close();
649 emit archivingFinished(result);
652 void ArchiveWidget::slotArchivingFinished(bool result)
655 icon_info->setPixmap(KIcon("dialog-ok").pixmap(16, 16));
656 text_info->setText(i18n("Project was successfully archived."));
659 icon_info->setPixmap(KIcon("dialog-close").pixmap(16, 16));
660 text_info->setText(i18n("There was an error processing project file"));
662 progressBar->setValue(100);
663 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Archive"));
664 archive_url->setEnabled(true);
665 compressed_archive->setEnabled(true);
666 for (int i = 0; i < files_list->topLevelItemCount(); i++) {
667 files_list->topLevelItem(i)->setDisabled(false);
668 for (int j = 0; j < files_list->topLevelItem(i)->childCount(); j++)
669 files_list->topLevelItem(i)->child(j)->setDisabled(false);
673 void ArchiveWidget::slotArchivingProgress(int p)
675 progressBar->setValue(p);
678 void ArchiveWidget::slotStartExtracting()
680 if (m_archiveThread.isRunning()) {
681 //TODO: abort extracting
684 KIO::NetAccess::mkdir(archive_url->url().path(KUrl::RemoveTrailingSlash), this);
685 icon_info->setPixmap(KIcon("system-run").pixmap(16, 16));
686 text_info->setText(i18n("Extracting..."));
687 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Abort"));
688 m_archiveThread = QtConcurrent::run(this, &ArchiveWidget::doExtracting);
691 void ArchiveWidget::doExtracting()
693 KTar archive(m_extractUrl.path());
694 archive.open( QIODevice::ReadOnly );
695 archive.directory()->copyTo(archive_url->url().path(KUrl::AddTrailingSlash));
697 emit extractingFinished();
700 QString ArchiveWidget::extractedProjectFile()
702 return archive_url->url().path(KUrl::AddTrailingSlash) + m_projectName;
705 void ArchiveWidget::slotExtractingFinished()
707 // Process project file
708 QFile file(extractedProjectFile());
710 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
714 QString playList = file.readAll();
716 if (playList.isEmpty()) {
720 playList.replace("$CURRENTPATH", archive_url->url().path(KUrl::RemoveTrailingSlash));
721 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
722 kWarning() << "////// ERROR writing to file: ";
726 file.write(playList.toUtf8());
727 if (file.error() != QFile::NoError) {
735 KMessageBox::sorry(kapp->activeWindow(), i18n("Cannot open project file %1", extractedProjectFile()), i18n("Cannot open file"));