]> git.sesse.net Git - kdenlive/blobdiff - src/dvdwizard.cpp
Fix issues with DVD wizard, allow to loop menu movie
[kdenlive] / src / dvdwizard.cpp
index d6228f4c514782d42ba3980dd5cb0d1a1446a4c6..ceba71c1f74ce3d555a0d56b4f46a6c580ce3369 100644 (file)
@@ -44,8 +44,8 @@ DvdWizard::DvdWizard(const QString &url, const QString &profile, QWidget *parent
         m_mkiso(NULL),
         m_burnMenu(new QMenu(this))
 {
+    setWindowTitle(i18n("DVD Wizard"));
     //setPixmap(QWizard::WatermarkPixmap, QPixmap(KStandardDirs::locate("appdata", "banner.png")));
-    setAttribute(Qt::WA_DeleteOnClose);
     m_pageVob = new DvdWizardVob(profile, this);
     m_pageVob->setTitle(i18n("Select Files For Your DVD"));
     addPage(m_pageVob);
@@ -62,24 +62,22 @@ DvdWizard::DvdWizard(const QString &url, const QString &profile, QWidget *parent
     m_pageMenu->setTitle(i18n("Create DVD Menu"));
     addPage(m_pageMenu);
 
-
-    QWizardPage *page3 = new QWizardPage;
-    page3->setTitle(i18n("DVD Image"));
-    m_iso.setupUi(page3);
-    m_iso.tmp_folder->setPath(KdenliveSettings::currenttmpfolder());
-    m_iso.iso_image->setPath(QDir::homePath() + "/untitled.iso");
-    m_iso.iso_image->setFilter("*.iso");
-    m_iso.iso_image->fileDialog()->setOperationMode(KFileDialog::Saving);
-    addPage(page3);
-
     QWizardPage *page4 = new QWizardPage;
     page4->setTitle(i18n("Creating DVD Image"));
     m_status.setupUi(page4);
     m_status.error_box->setHidden(true);
+    m_status.tmp_folder->setUrl(KUrl(KdenliveSettings::currenttmpfolder()));
+    m_status.tmp_folder->setMode(KFile::Directory | KFile::ExistingOnly);
+    m_status.iso_image->setUrl(KUrl(QDir::homePath() + "/untitled.iso"));
+    m_status.iso_image->setFilter("*.iso");
+    m_status.iso_image->setMode(KFile::File);
+    m_status.iso_image->fileDialog()->setOperationMode(KFileDialog::Saving);
+
     addPage(page4);
 
     connect(this, SIGNAL(currentIdChanged(int)), this, SLOT(slotPageChanged(int)));
-
+    connect(m_status.button_start, SIGNAL(clicked()), this, SLOT(slotGenerate()));
+    connect(m_status.button_abort, SIGNAL(clicked()), this, SLOT(slotAbort()));
     connect(m_status.button_preview, SIGNAL(clicked()), this, SLOT(slotPreview()));
 
     QString programName("k3b");
@@ -102,11 +100,24 @@ DvdWizard::DvdWizard(const QString &url, const QString &profile, QWidget *parent
     m_status.button_burn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     m_status.button_preview->setIcon(KIcon("media-playback-start"));
 
+    setButtonText(QWizard::CustomButton1, i18n("Load"));
+    setButtonText(QWizard::CustomButton2, i18n("Save"));
+    button(QWizard::CustomButton1)->setIcon(KIcon("document-open"));
+    button(QWizard::CustomButton2)->setIcon(KIcon("document-save"));
+    connect(button(QWizard::CustomButton1), SIGNAL(clicked()), this, SLOT(slotLoad()));
+    connect(button(QWizard::CustomButton2), SIGNAL(clicked()), this, SLOT(slotSave()));
+    setOption(QWizard::HaveCustomButton1, true);
+    setOption(QWizard::HaveCustomButton2, true);
+    QList<QWizard::WizardButton> layout;
+    layout << QWizard::CustomButton1 << QWizard::CustomButton2 << QWizard::Stretch << QWizard::BackButton << QWizard::NextButton << QWizard::CancelButton << QWizard::FinishButton;
+    setButtonLayout(layout);
 }
 
 DvdWizard::~DvdWizard()
 {
-    // m_menuFile.remove();
+    m_authorFile.remove();
+    m_menuFile.remove();
+    blockSignals(true);
     delete m_burnMenu;
     if (m_dvdauthor) {
         m_dvdauthor->blockSignals(true);
@@ -124,31 +135,16 @@ DvdWizard::~DvdWizard()
 void DvdWizard::slotPageChanged(int page)
 {
     //kDebug() << "// PAGE CHGD: " << page << ", ID: " << visitedPages();
-    if (page == 1) {
-        m_pageChapters->setVobFiles(m_pageVob->isPal(), m_pageVob->selectedUrls(), m_pageVob->durations());
+    if (page == 0) {
+        // Update chapters that were modified in page 1
+        m_pageChapters->stopMonitor();
+        m_pageVob->updateChapters(m_pageChapters->chaptersData());
+    } else if (page == 1) {
+        m_pageChapters->setVobFiles(m_pageVob->isPal(), m_pageVob->isWide(), m_pageVob->selectedUrls(), m_pageVob->durations(), m_pageVob->chapters());
     } else if (page == 2) {
+        m_pageChapters->stopMonitor();
         m_pageMenu->setTargets(m_pageChapters->selectedTitles(), m_pageChapters->selectedTargets());
         m_pageMenu->changeProfile(m_pageVob->isPal());
-    } else if (page == 3) {
-        //m_pageMenu->buttonsInfo();
-    } else if (page == 4) {
-        // clear job icons
-        for (int i = 0; i < m_status.job_progress->count(); i++)
-            m_status.job_progress->item(i)->setIcon(KIcon());
-        QString warnMessage;
-        if (KIO::NetAccess::exists(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), KIO::NetAccess::SourceSide, this))
-            warnMessage.append(i18n("Folder %1 already exists. Overwrite?" + '\n', m_iso.tmp_folder->url().path() + "/DVD"));
-        if (KIO::NetAccess::exists(KUrl(m_iso.iso_image->url().path()), KIO::NetAccess::SourceSide, this))
-            warnMessage.append(i18n("Image file %1 already exists. Overwrite?", m_iso.iso_image->url().path()));
-
-        if (!warnMessage.isEmpty() && KMessageBox::questionYesNo(this, warnMessage) == KMessageBox::No) {
-            back();
-        } else {
-            KIO::NetAccess::del(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
-            QTimer::singleShot(300, this, SLOT(generateDvd()));
-        }
-        m_status.button_preview->setEnabled(false);
-        m_status.button_burn->setEnabled(false);
     }
 }
 
@@ -156,6 +152,7 @@ void DvdWizard::slotPageChanged(int page)
 
 void DvdWizard::generateDvd()
 {
+    m_status.error_box->setHidden(true);
     KTemporaryFile temp1;
     temp1.setSuffix(".png");
     //temp1.setAutoRemove(false);
@@ -186,19 +183,25 @@ void DvdWizard::generateDvd()
     //temp6.setAutoRemove(false);
     temp6.open();
 
+    m_menuFile.close();
     m_menuFile.setSuffix(".mpg");
     m_menuFile.setAutoRemove(false);
     m_menuFile.open();
 
+    m_authorFile.close();
     m_authorFile.setSuffix(".xml");
     m_authorFile.setAutoRemove(false);
     m_authorFile.open();
 
     QListWidgetItem *images =  m_status.job_progress->item(0);
+    m_status.job_progress->setCurrentRow(0);
     images->setIcon(KIcon("system-run"));
     qApp->processEvents();
     QMap <QString, QRect> buttons = m_pageMenu->buttonsInfo();
     QStringList buttonsTarget;
+    m_status.error_log->clear();
+    // initialize html content
+    m_status.error_log->setText("<html></html>");
 
     if (m_pageMenu->createMenu()) {
         m_pageMenu->createButtonImages(temp1.fileName(), temp2.fileName(), temp3.fileName());
@@ -211,13 +214,14 @@ void DvdWizard::generateDvd()
         if (!m_pageMenu->menuMovie()) {
             // create menu vob file
             QListWidgetItem *vobitem =  m_status.job_progress->item(1);
+            m_status.job_progress->setCurrentRow(1);
             vobitem->setIcon(KIcon("system-run"));
             qApp->processEvents();
 
             QStringList args;
             args.append("-profile");
             if (m_pageMenu->isPalMenu()) args.append("dv_pal");
-            else  args.append("dv_ntsc");
+            else args.append("dv_ntsc");
             args.append(temp4.fileName());
             args.append("in=0");
             args.append("out=100");
@@ -236,15 +240,20 @@ void DvdWizard::generateDvd()
                     kDebug() << "/// RENDERING MENU vob crashed";
                     QByteArray result = renderbg.readAllStandardError();
                     vobitem->setIcon(KIcon("dialog-close"));
-                    m_status.error_log->setText(result);
+                    m_status.error_log->append(result);
                     m_status.error_box->setHidden(false);
+                    m_status.button_start->setEnabled(true);
+                    m_status.button_abort->setEnabled(false);
                     return;
                 }
             } else {
                 kDebug() << "/// RENDERING MENU vob timed out";
                 vobitem->setIcon(KIcon("dialog-close"));
-                m_status.error_log->setText(i18n("Rendering job timed out"));
+                m_status.error_log->append("<a name=\"result\" /><br><strong>" + i18n("Rendering job timed out"));
+                m_status.error_log->scrollToAnchor("result");
                 m_status.error_box->setHidden(false);
+                m_status.button_start->setEnabled(true);
+                m_status.button_abort->setEnabled(false);
                 return;
             }
             vobitem->setIcon(KIcon("dialog-ok"));
@@ -253,6 +262,7 @@ void DvdWizard::generateDvd()
 
         // create xml spumux file
         QListWidgetItem *spuitem =  m_status.job_progress->item(2);
+        m_status.job_progress->setCurrentRow(2);
         spuitem->setIcon(KIcon("system-run"));
         qApp->processEvents();
         QDomDocument doc;
@@ -313,22 +323,24 @@ void DvdWizard::generateDvd()
         else spumux.setStandardInputFile(temp5.fileName());
         spumux.setStandardOutputFile(m_menuFile.fileName());
         spumux.start("spumux", args);
-        spumux.setProcessChannelMode(QProcess::MergedChannels);
         if (spumux.waitForFinished()) {
-            kDebug() << QString(spumux.readAll()).simplified();
+            m_status.error_log->append(spumux.readAllStandardError());
             if (spumux.exitStatus() == QProcess::CrashExit) {
                 QByteArray result = spumux.readAllStandardError();
                 spuitem->setIcon(KIcon("dialog-close"));
-                m_status.error_log->setText(result);
+                m_status.error_log->append(result);
                 m_status.error_box->setHidden(false);
+                m_status.button_start->setEnabled(true);
                 kDebug() << "/// RENDERING SPUMUX MENU crashed";
                 return;
             }
         } else {
             kDebug() << "/// RENDERING SPUMUX MENU timed out";
             spuitem->setIcon(KIcon("dialog-close"));
-            m_status.error_log->setText(i18n("Menu job timed out"));
+            m_status.error_log->append("<a name=\"result\" /><br><strong>" + i18n("Menu job timed out"));
+            m_status.error_log->scrollToAnchor("result");
             m_status.error_box->setHidden(false);
+            m_status.button_start->setEnabled(true);
             return;
         }
 
@@ -338,13 +350,14 @@ void DvdWizard::generateDvd()
 
     // create dvdauthor xml
     QListWidgetItem *authitem =  m_status.job_progress->item(3);
+    m_status.job_progress->setCurrentRow(3);
     authitem->setIcon(KIcon("system-run"));
     qApp->processEvents();
-    KIO::NetAccess::mkdir(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
+    KIO::NetAccess::mkdir(KUrl(m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD"), this);
 
     QDomDocument dvddoc;
     QDomElement auth = dvddoc.createElement("dvdauthor");
-    auth.setAttribute("dest", m_iso.tmp_folder->url().path() + "/DVD");
+    auth.setAttribute("dest", m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD");
     dvddoc.appendChild(auth);
     QDomElement vmgm = dvddoc.createElement("vmgm");
     auth.appendChild(vmgm);
@@ -388,12 +401,26 @@ void DvdWizard::generateDvd()
         }
         QDomElement menuvob = dvddoc.createElement("vob");
         menuvob.setAttribute("file", m_menuFile.fileName());
-        menuvob.setAttribute("pause", "inf");
         pgc.appendChild(menuvob);
+
+        if (m_pageMenu->loopMovie()) {
+            QDomElement menuloop = dvddoc.createElement("post");
+            nametext = dvddoc.createTextNode("jump titleset 1 menu;");
+            menuloop.appendChild(nametext);
+            pgc.appendChild(menuloop);
+        } else menuvob.setAttribute("pause", "inf");
+
     }
 
     QDomElement titles = dvddoc.createElement("titles");
     titleset.appendChild(titles);
+    QDomElement video = dvddoc.createElement("video");
+    titles.appendChild(video);
+    if (m_pageVob->isPal()) video.setAttribute("format", "pal");
+    else video.setAttribute("format", "ntsc");
+
+    if (m_pageVob->isWide()) video.setAttribute("aspect", "16:9");
+    else video.setAttribute("aspect", "4:3");
 
     QStringList voburls = m_pageVob->selectedUrls();
 
@@ -448,24 +475,39 @@ void DvdWizard::generateDvd()
     m_creationLog.clear();
     m_dvdauthor = new QProcess(this);
     connect(m_dvdauthor, SIGNAL(finished(int , QProcess::ExitStatus)), this, SLOT(slotRenderFinished(int, QProcess::ExitStatus)));
+    connect(m_dvdauthor, SIGNAL(readyReadStandardOutput()), this, SLOT(slotShowRenderInfo()));
     m_dvdauthor->setProcessChannelMode(QProcess::MergedChannels);
     m_dvdauthor->start("dvdauthor", args);
+    m_status.button_abort->setEnabled(true);
+    button(QWizard::FinishButton)->setEnabled(false);
+}
 
+void DvdWizard::slotShowRenderInfo()
+{
+    QString log = QString(m_dvdauthor->readAll());
+    m_status.error_log->append(log);
+    m_status.error_box->setHidden(false);
 }
 
-void DvdWizard::slotRenderFinished(int /*exitCode*/, QProcess::ExitStatus status)
+void DvdWizard::slotRenderFinished(int exitCode, QProcess::ExitStatus status)
 {
     QListWidgetItem *authitem =  m_status.job_progress->item(3);
-    if (status == QProcess::CrashExit) {
-        QByteArray result = m_dvdauthor->readAllStandardError();
-        m_status.error_log->setText(result);
+    if (status == QProcess::CrashExit || exitCode != 0) {
+        QString result(m_dvdauthor->readAllStandardError());
+        result.append("<a name=\"result\" /><br><strong>");
+        result.append(i18n("DVDAuthor process crashed."));
+        m_status.error_log->append(result);
+        m_status.error_log->scrollToAnchor("result");
         m_status.error_box->setHidden(false);
         kDebug() << "DVDAuthor process crashed";
         authitem->setIcon(KIcon("dialog-close"));
         m_dvdauthor->close();
         delete m_dvdauthor;
         m_dvdauthor = NULL;
+        m_status.button_start->setEnabled(true);
+        m_status.button_abort->setEnabled(false);
         cleanup();
+        button(QWizard::FinishButton)->setEnabled(true);
         return;
     }
     m_creationLog.append(m_dvdauthor->readAllStandardError());
@@ -474,18 +516,22 @@ void DvdWizard::slotRenderFinished(int /*exitCode*/, QProcess::ExitStatus status
     m_dvdauthor = NULL;
 
     // Check if DVD structure has the necessary infos
-    if (!QFile::exists(m_iso.tmp_folder->url().path() + "/DVD/VIDEO_TS/VIDEO_TS.IFO")) {
-        m_status.error_log->setText(m_creationLog + '\n' + i18n("DVD structure broken"));
+    if (!QFile::exists(m_status.tmp_folder->url().path() + "/DVD/VIDEO_TS/VIDEO_TS.IFO")) {
+        m_status.error_log->append(m_creationLog + "<a name=\"result\" /><br /><strong>" + i18n("DVD structure broken"));
+        m_status.error_log->scrollToAnchor("result");
         m_status.error_box->setHidden(false);
         kDebug() << "DVDAuthor process crashed";
         authitem->setIcon(KIcon("dialog-close"));
+        m_status.button_start->setEnabled(true);
+        m_status.button_abort->setEnabled(false);
         cleanup();
+        button(QWizard::FinishButton)->setEnabled(true);
         return;
     }
     authitem->setIcon(KIcon("dialog-ok"));
     qApp->processEvents();
     QStringList args;
-    args << "-dvd-video" << "-v" << "-o" << m_iso.iso_image->url().path() << m_iso.tmp_folder->url().path() + "/DVD";
+    args << "-dvd-video" << "-v" << "-o" << m_status.iso_image->url().path() << m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD";
 
     if (m_mkiso) {
         m_mkiso->blockSignals(true);
@@ -495,19 +541,33 @@ void DvdWizard::slotRenderFinished(int /*exitCode*/, QProcess::ExitStatus status
     }
     m_mkiso = new QProcess(this);
     connect(m_mkiso, SIGNAL(finished(int , QProcess::ExitStatus)), this, SLOT(slotIsoFinished(int, QProcess::ExitStatus)));
+    connect(m_mkiso, SIGNAL(readyReadStandardOutput()), this, SLOT(slotShowIsoInfo()));
     m_mkiso->setProcessChannelMode(QProcess::MergedChannels);
     QListWidgetItem *isoitem =  m_status.job_progress->item(4);
+    m_status.job_progress->setCurrentRow(4);
     isoitem->setIcon(KIcon("system-run"));
-    m_mkiso->start("mkisofs", args);
+    if (!KStandardDirs::findExe("genisoimage").isEmpty()) m_mkiso->start("genisoimage", args);
+    else m_mkiso->start("mkisofs", args);
+
+}
 
+void DvdWizard::slotShowIsoInfo()
+{
+    QString log = QString(m_mkiso->readAll());
+    m_status.error_log->append(log);
+    m_status.error_box->setHidden(false);
 }
 
-void DvdWizard::slotIsoFinished(int /*exitCode*/, QProcess::ExitStatus status)
+void DvdWizard::slotIsoFinished(int exitCode, QProcess::ExitStatus status)
 {
+    button(QWizard::FinishButton)->setEnabled(true);
     QListWidgetItem *isoitem =  m_status.job_progress->item(4);
-    if (status == QProcess::CrashExit) {
-        QByteArray result = m_mkiso->readAllStandardError();
-        m_status.error_log->setText(result);
+    if (status == QProcess::CrashExit || exitCode != 0) {
+        QString result(m_mkiso->readAllStandardError());
+        result.append("<a name=\"result\" /><br /><strong>");
+        result.append(i18n("ISO creation process crashed."));
+        m_status.error_log->append(result);
+        m_status.error_log->scrollToAnchor("result");
         m_status.error_box->setHidden(false);
         m_mkiso->close();
         delete m_mkiso;
@@ -515,20 +575,25 @@ void DvdWizard::slotIsoFinished(int /*exitCode*/, QProcess::ExitStatus status)
         cleanup();
         kDebug() << "Iso process crashed";
         isoitem->setIcon(KIcon("dialog-close"));
+        m_status.button_start->setEnabled(true);
+        m_status.button_abort->setEnabled(false);
         return;
     }
 
     m_creationLog.append(m_mkiso->readAllStandardError());
     delete m_mkiso;
     m_mkiso = NULL;
+    m_status.button_start->setEnabled(true);
+    m_status.button_abort->setEnabled(false);
 
     // Check if DVD iso is ok
-    QFile iso(m_iso.iso_image->url().path());
+    QFile iso(m_status.iso_image->url().path());
     if (!iso.exists() || iso.size() == 0) {
         if (iso.exists()) {
-            KIO::NetAccess::del(m_iso.iso_image->url(), this);
+            KIO::NetAccess::del(m_status.iso_image->url(), this);
         }
-        m_status.error_log->setText(m_creationLog + '\n' + i18n("DVD ISO is broken"));
+        m_status.error_log->append(m_creationLog + "<br /><a name=\"result\" /><strong>" + i18n("DVD ISO is broken") + "</strong>");
+        m_status.error_log->scrollToAnchor("result");
         m_status.error_box->setHidden(false);
         isoitem->setIcon(KIcon("dialog-close"));
         cleanup();
@@ -536,24 +601,23 @@ void DvdWizard::slotIsoFinished(int /*exitCode*/, QProcess::ExitStatus status)
     }
 
     isoitem->setIcon(KIcon("dialog-ok"));
-    kDebug() << "ISO IMAGE " << m_iso.iso_image->url().path() << " Successfully created";
+    kDebug() << "ISO IMAGE " << m_status.iso_image->url().path() << " Successfully created";
     cleanup();
     kDebug() << m_creationLog;
 
-    m_status.error_log->setText(i18n("DVD ISO image %1 successfully created.", m_iso.iso_image->url().path()));
+    m_status.error_log->append("<a name=\"result\" /><strong>" + i18n("DVD ISO image %1 successfully created.", m_status.iso_image->url().path()) + "</strong>");
+    m_status.error_log->scrollToAnchor("result");
     m_status.button_preview->setEnabled(true);
     m_status.button_burn->setEnabled(true);
     m_status.error_box->setHidden(false);
-    //KMessageBox::information(this, i18n("DVD ISO image %1 successfully created.", m_iso.iso_image->url().path()));
+    //KMessageBox::information(this, i18n("DVD ISO image %1 successfully created.", m_status.iso_image->url().path()));
 
 }
 
 
 void DvdWizard::cleanup()
 {
-    m_authorFile.remove();
-    m_menuFile.remove();
-    KIO::NetAccess::del(KUrl(m_iso.tmp_folder->url().path() + "/DVD"), this);
+    KIO::NetAccess::del(KUrl(m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD"), this);
 }
 
 
@@ -562,7 +626,7 @@ void DvdWizard::slotPreview()
     QString programName("xine");
     QString exec = KStandardDirs::findExe(programName);
     if (exec.isEmpty()) KMessageBox::sorry(this, i18n("You need program <b>%1</b> to perform this action", programName));
-    else QProcess::startDetached(exec, QStringList() << "dvd://" + m_iso.iso_image->url().path());
+    else QProcess::startDetached(exec, QStringList() << "dvd://" + m_status.iso_image->url().path());
 }
 
 void DvdWizard::slotBurn()
@@ -570,16 +634,108 @@ void DvdWizard::slotBurn()
     QAction *action = qobject_cast<QAction *>(sender());
     QString exec = action->data().toString();
     QStringList args;
-    if (exec.endsWith("k3b")) args << "--image" << m_iso.iso_image->url().path();
-    else args << "--image=" + m_iso.iso_image->url().path();
+    if (exec.endsWith("k3b")) args << "--image" << m_status.iso_image->url().path();
+    else args << "--image=" + m_status.iso_image->url().path();
     QProcess::startDetached(exec, args);
 }
 
 
+void DvdWizard::slotGenerate()
+{
+    // clear job icons
+    if ((m_dvdauthor && m_dvdauthor->state() != QProcess::NotRunning) || (m_mkiso && m_mkiso->state() != QProcess::NotRunning)) return;
+    for (int i = 0; i < m_status.job_progress->count(); i++)
+        m_status.job_progress->item(i)->setIcon(KIcon());
+    QString warnMessage;
+    if (KIO::NetAccess::exists(KUrl(m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD"), KIO::NetAccess::SourceSide, this))
+        warnMessage.append(i18n("Folder %1 already exists. Overwrite?" + '\n', m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD"));
+    if (KIO::NetAccess::exists(KUrl(m_status.iso_image->url().path()), KIO::NetAccess::SourceSide, this))
+        warnMessage.append(i18n("Image file %1 already exists. Overwrite?", m_status.iso_image->url().path()));
+
+    if (warnMessage.isEmpty() || KMessageBox::questionYesNo(this, warnMessage) == KMessageBox::Yes) {
+        KIO::NetAccess::del(KUrl(m_status.tmp_folder->url().path(KUrl::AddTrailingSlash) + "DVD"), this);
+        QTimer::singleShot(300, this, SLOT(generateDvd()));
+        m_status.button_preview->setEnabled(false);
+        m_status.button_burn->setEnabled(false);
+        m_status.job_progress->setEnabled(true);
+        m_status.button_start->setEnabled(false);
+    }
+}
+
+void DvdWizard::slotAbort()
+{
+    // clear job icons
+    if (m_dvdauthor && m_dvdauthor->state() != QProcess::NotRunning) m_dvdauthor->terminate();
+    else if (m_mkiso && m_mkiso->state() != QProcess::NotRunning) m_mkiso->terminate();
+}
 
+void DvdWizard::slotSave()
+{
+    KUrl url = KFileDialog::getSaveUrl(KUrl("kfiledialog:///projectfolder"), "*.kdvd", this, i18n("Save DVD Project"));
+    if (url.isEmpty()) return;
+
+    if (currentId() == 0) m_pageChapters->setVobFiles(m_pageVob->isPal(), m_pageVob->isWide(), m_pageVob->selectedUrls(), m_pageVob->durations(), m_pageVob->chapters());
+
+    QDomDocument doc;
+    QDomElement dvdproject = doc.createElement("dvdproject");
+    QString profile;
+    if (m_pageVob->isPal()) profile = "dv_pal";
+    else profile = "dv_ntsc";
+    if (m_pageVob->isWide()) profile.append("_wide");
+    dvdproject.setAttribute("profile", profile);
+
+    dvdproject.setAttribute("tmp_folder", m_status.tmp_folder->url().path());
+    dvdproject.setAttribute("iso_image", m_status.iso_image->url().path());
+
+    dvdproject.setAttribute("intro_movie", m_pageVob->introMovie());
+
+    doc.appendChild(dvdproject);
+    QDomElement menu = m_pageMenu->toXml();
+    if (!menu.isNull()) dvdproject.appendChild(doc.importNode(menu, true));
+    QDomElement chaps = m_pageChapters->toXml();
+    if (!chaps.isNull()) dvdproject.appendChild(doc.importNode(chaps, true));
+
+    QFile file(url.path());
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        kWarning() << "//////  ERROR writing to file: " << url.path();
+        KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
+        return;
+    }
 
+    file.write(doc.toString().toUtf8());
+    if (file.error() != QFile::NoError) {
+        KMessageBox::error(this, i18n("Cannot write to file %1", url.path()));
+    }
+    file.close();
+}
 
 
+void DvdWizard::slotLoad()
+{
+    KUrl url = KFileDialog::getOpenUrl(KUrl("kfiledialog:///projectfolder"), "*.kdvd");
+    if (url.isEmpty()) return;
+    QDomDocument doc;
+    QFile file(url.path());
+    doc.setContent(&file, false);
+    file.close();
+    QDomElement dvdproject = doc.documentElement();
+    if (dvdproject.tagName() != "dvdproject") {
+        KMessageBox::error(this, i18n("File %1 is not a Kdenlive project file.", url.path()));
+        return;
+    }
 
+    QString profile = dvdproject.attribute("profile");
+    m_pageVob->setProfile(profile);
 
+    m_status.tmp_folder->setUrl(KUrl(dvdproject.attribute("tmp_folder")));
+    m_status.iso_image->setUrl(KUrl(dvdproject.attribute("iso_image")));
+    m_pageVob->setIntroMovie(dvdproject.attribute("intro_movie"));
 
+    QDomNodeList vobs = doc.elementsByTagName("vob");
+    m_pageVob->clear();
+    for (int i = 0; i < vobs.count(); i++) {
+        QDomElement e = vobs.at(i).toElement();
+        m_pageVob->slotAddVobFile(KUrl(e.attribute("file")), e.attribute("chapters"));
+    }
+    m_pageMenu->loadXml(dvdproject.firstChildElement("menu"));
+}