Logo Search packages:      
Sourcecode: kdenlive version File versions

playlist.cpp

/***************************************************************************
                          playlist  -  description
                             -------------------
    begin                : Fri Jul 27 2007
    copyright            : (C) 2007 by Jean-Baptiste Mardelle
    email                : 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <klocale.h>
#include <klineedit.h>
#include <kdebug.h>
#include <kurlrequesterdlg.h>
#include <kurlrequester.h>
#include <kfiledialog.h>
#include <kmessagebox.h>
#include <kcommand.h>

#include <qlayout.h>
#include <qlistview.h>
#include <qiconview.h>
#include <qlabel.h>

#include "playlist.h"
#include "avlistviewitem.h"
#include "kselectclipcommand.h"
#include "kaddrefclipcommand.h"
#include "aviconviewitem.h"
#include "westleylistviewitem.h"
#include "kdenlivedoc.h"
#include "docclipref.h"
#include "docclipavfile.h"
#include "loadprojectnativefilter.h"



namespace Gui {

    PlayList::PlayList(QListView *m_listView, QIconView *m_iconView, bool iconView, QWidget * parent, const char *name): KDialogBase(  KDialogBase::Swallow, i18n("Fix Broken Playlists"), KDialogBase::User1 | KDialogBase::User2 | KDialogBase::Close , KDialogBase::Close, parent, name, true) {
      QWidget *page = new QWidget( this );
      setMainWidget(page);
      setButtonText(KDialogBase::User1, i18n("Fix All"));
      setButtonText(KDialogBase::User2, i18n("Fix Selected"));
      QGridLayout *grid = new QGridLayout(page, 2, 2);
      grid->setSpacing(5);
      QLabel *lab = new QLabel(i18n("Following broken url were found: "), page);    
      grid->addWidget(lab, 0, 0);
      m_broken_list = new KListView(page);
      m_broken_list->addColumn(i18n("Broken Playlists"));
      m_broken_list->setResizeMode(QListView::LastColumn);
      m_broken_list->setRootIsDecorated(true);
      grid->addWidget(m_broken_list, 1, 0);
      setMinimumWidth(400);

      if (!iconView) {
        QListViewItemIterator it( m_listView );
        while ( it.current() ) {
          BaseListViewItem::ITEMTYPE type = ((BaseListViewItem *) it.current())->getType();
            if (type == BaseListViewItem::PLAYLISTITEM) {
            if (((WestleyListViewItem *) it.current())->isBroken()) {
                const AVListViewItem *avitem = static_cast < AVListViewItem * >(*it);
                QStringList urls = avitem->clip()->referencedClip()->toDocClipAVFile()->brokenPlayList();
                if (!urls.isEmpty()) {
                    KListViewItem *item = new KListViewItem(m_broken_list, avitem->clip()->fileURL().path());
                    for ( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it )
                      (void) new KListViewItem(item, (*it));
                }
            }
          }
            ++it;
        }
      }
      else {
          for ( QIconViewItem *item = m_iconView->firstItem(); item; item = item->nextItem() )
          {
                  const AVIconViewItem *avitem = static_cast < AVIconViewItem * >(item);
                if (avitem && avitem->clip() && avitem->clip()->clipType() == DocClipBase::PLAYLIST) {
                QStringList urls = avitem->clip()->referencedClip()->toDocClipAVFile()->brokenPlayList();
                if (!urls.isEmpty()) {
                    KListViewItem *item = new KListViewItem(m_broken_list, avitem->clip()->fileURL().path());
                    for ( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it )
                        (void) new KListViewItem(item, (*it));
                }
                  }
            }
      }

      connect(this, SIGNAL(user1Clicked ()), this, SLOT(slotFixAllLists()));
      connect(this, SIGNAL(user2Clicked ()), this, SLOT(slotFixLists()));

      adjustSize();
    }

    PlayList::~PlayList() {
      delete m_broken_list;
    }

    void PlayList::slotFixAllLists() {
      if (!m_broken_list->currentItem()) return;
      replaceDialog = new FixPlayList_UI(this);
      replaceDialog->old_path->setText(KURL(m_broken_list->firstChild()->firstChild()->text(0)).directory());
      replaceDialog->new_path->fileDialog()->setMode(KFile::Directory);
      replaceDialog->buttonOk->setEnabled(false);
      replaceDialog->setMinimumWidth(400);
      replaceDialog->adjustSize();
      connect(replaceDialog->preview_button, SIGNAL(clicked ()), this, SLOT(slotPreviewFix()));
      if (replaceDialog->exec() == QDialog::Accepted) {
            if (KMessageBox::questionYesNo(this, i18n("<qt>This will definitely modify all broken playlists.\nAre you sure you want to do this ?")) == KMessageBox::Yes)
            slotDoFix( replaceDialog->old_path->text(), replaceDialog->new_path->url());
      }
      delete replaceDialog;
    }

    void PlayList::slotPreviewFix() {
          if (!m_broken_list->currentItem()) return;
          replaceDialog->preview_list->clear();
          QString oldPath = replaceDialog->old_path->text();
          QString newPath = replaceDialog->new_path->url();
          QListViewItem *item = m_broken_list->firstChild();
          while (item) {
            // Parse all broken playlist and simulate new path
            QDomDocument doc;
            QFile file(item->text(0));
            doc.setContent(&file, false);
            file.close();
            QDomElement documentElement = doc.documentElement();
            if (documentElement.tagName() != "westley") {
                kdWarning() << "KdenliveDoc::loadFromXML() document element has unknown tagName : " << documentElement.tagName() << endl;
            }

            QDomNode kdenlivedoc = documentElement.elementsByTagName("kdenlivedoc").item(0);
            QDomNode n;
            if (!kdenlivedoc.isNull()) n = kdenlivedoc.firstChild();
            else n = documentElement.firstChild();
            QDomElement e;
            while (!n.isNull()) {
                e = n.toElement();
                if (!e.isNull() && e.tagName() == "producer") {
                  QString prodUrl = e.attribute("resource", QString::null);
                  if (!prodUrl.isEmpty()) {
                      (void) new KListViewItem(replaceDialog->preview_list, prodUrl, prodUrl.replace(oldPath, newPath));
                      //e.setAttribute("resource", newPath);
                  }
                }
                n = n.nextSibling();
            }
            item = item->nextSibling();
          }
          replaceDialog->buttonOk->setEnabled(true);
    }

    void PlayList::slotFixLists() {
          if (!m_broken_list->currentItem()) return;
          QString brokenPath;
          QString fileUrl;
          if (m_broken_list->currentItem()->childCount() == 0) {
            fileUrl = m_broken_list->currentItem()->parent()->text(0);
              brokenPath = m_broken_list->currentItem()->text(0);
          }
          else {
            fileUrl = m_broken_list->currentItem()->text(0);
            brokenPath = m_broken_list->currentItem()->firstChild()->text(0);
          }
          KURLRequesterDlg *getUrl = new KURLRequesterDlg(KURL(brokenPath).directory(), i18n("Please give new path for\n") + brokenPath, this, "new_path");
          getUrl->fileDialog()->setMode(KFile::Directory);
          getUrl->exec();
          KURL newUrl = getUrl->selectedURL ();
          delete getUrl;
          QString oldPath = KURL(brokenPath).directory();
          QString newPath = newUrl.path();
          if (!newUrl.isEmpty() && KMessageBox::questionYesNo(this, i18n("<qt>This will modify playlist:<br> <b>%1</b><br><br>Replacing %2 with<br>%3</qt>").arg(fileUrl).arg(oldPath).arg(newPath)) == KMessageBox::Yes) {
            fixPlayListClip(fileUrl, brokenPath, newPath + "/" + KURL(brokenPath).fileName());
            emit signalFixed();
          }

    }

    void PlayList::fixPlayListClip(QString fileUrl, QString oldPath, QString newPath, bool partialReplace) {
      QDomDocument doc;
      QFile file(fileUrl);
      doc.setContent(&file, false);
      file.close();
      QDomElement documentElement = doc.documentElement();
      if (documentElement.tagName() != "westley") {
      kdWarning() << "KdenliveDoc::loadFromXML() document element has unknown tagName : " << documentElement.tagName() << endl;
      }

      QDomNode kdenlivedoc = documentElement.elementsByTagName("kdenlivedoc").item(0);
      QDomNode n;
      if (!kdenlivedoc.isNull()) n = kdenlivedoc.firstChild();
      else n = documentElement.firstChild();
      QDomElement e;
      bool fixed = false;

      while (!n.isNull()) {
          e = n.toElement();
          if (!e.isNull() && e.tagName() == "producer") {
                QString prodUrl = e.attribute("resource", QString::null);
                if (!partialReplace) {
                  if (prodUrl == oldPath) {
                      e.setAttribute("resource", newPath);
                      fixed = true;
                    }
                }
                else {
                  e.setAttribute("resource", prodUrl.replace(oldPath, newPath));
                }
          }
          n = n.nextSibling();
      }
      if (fixed || partialReplace) {
          QCString save = doc.toString().utf8();
          if ( file.open( IO_WriteOnly ) ) {
              file.writeBlock(save, save.length());
            file.close();
            if (!partialReplace) {
                  QListViewItem *fixed = m_broken_list->findItem(oldPath, 0);
                  if (fixed->parent()->childCount() == 1) m_broken_list->takeItem(fixed->parent());
                  else m_broken_list->takeItem(fixed);
            }
          }
          else KMessageBox::sorry(this, i18n("Unable to write to the file:\n%1").arg(fileUrl));
      }
    }


    void PlayList::slotDoFix(QString oldPath, QString newPath) {
      QListViewItem *item = m_broken_list->firstChild();
      while (item) {
          // Parse all broken playlist and fix paths
          fixPlayListClip(item->text(0), oldPath, newPath, true);
          item = item->nextSibling();
      }
      emit signalFixed();
    }

    // static
    void PlayList::saveDescription(QString path, QString description) {
      QDomDocument doc;
      QFile file(path);
      doc.setContent(&file, false);
      file.close();
      QDomElement documentElement = doc.documentElement();
      if (documentElement.tagName() != "westley") {
          kdWarning() << "KdenliveDoc::loadFromXML() document element has unknown tagName : " << documentElement.tagName() << endl;
          return;
      }
      documentElement.setAttribute("title", description);
      
      QCString save = doc.toString().utf8();
      if ( file.open( IO_WriteOnly ) ) {
              file.writeBlock(save, save.length());
            file.close();
      }
    }

    // static
    void PlayList::explodePlaylist(DocClipRef *clip, KdenliveApp *app) {
      QDomDocument doc;
      QFile file(clip->fileURL().path());
      doc.setContent(&file, false);
      file.close();
      int track = clip->trackNum();
      GenTime startTime = clip->trackStart();
      QDomElement documentElement = doc.documentElement();
      if (documentElement.tagName() != "westley") {
          kdWarning() << "KdenliveDoc::loadFromXML() document element has unknown tagName : " << documentElement.tagName() << endl;
          return;
      }

      KURL::List producersList;
      int tracksCount = 0;

      QDomNode kdenlivedoc = documentElement.elementsByTagName("kdenlivedoc").item(0);
      QDomNode n, node;
      QDomElement e, entry;

      QString documentCopy = doc.toString();

      if (!kdenlivedoc.isNull()) n = kdenlivedoc.firstChild();
      else n = documentElement.firstChild();

      while (!n.isNull()) {
          e = n.toElement();
          if (!e.isNull()) {
            if (e.tagName() == "producer") {
                QString producerId = e.attribute("id", QString::number(-1));
                int newId  = app->getDocument()->clipManager().requestIdNumber();
                e.setAttribute("id", QString::number(newId));
                documentCopy.replace(" producer=\"" + producerId + "\"", " producer=\"" + QString::number(newId) + "\"", false);
                documentCopy.replace(" producer=" + producerId + " ", " producer=" + QString::number(newId) + " ", false);
                LoadProjectNativeFilter::addToDocument(i18n("Clips"), e, app->getDocument());
            }
          }
          n = n.nextSibling();
      }
      if (!kdenlivedoc.isNull() || tracksCount == 0) {
          // it is a kdenlive document, parse for tracks
          kdenlivedoc = documentElement.elementsByTagName("multitrack").item(0);
          if (!kdenlivedoc.isNull()) n = kdenlivedoc.firstChild();
          while (!n.isNull()) {
            e = n.toElement();
            if (!e.isNull()) {
                if (e.tagName() == "playlist") tracksCount++;
            }
            n = n.nextSibling();
          }
      }
      app->slotDeleteSelected();

      // use the document copy with updated ids
      doc.setContent(documentCopy, false);
      documentElement = doc.documentElement();
      kdenlivedoc = documentElement.elementsByTagName("kdenlivedoc").item(0);

      if (!kdenlivedoc.isNull()) n = kdenlivedoc.firstChild();
      else n = documentElement.firstChild();

      while (!n.isNull()) {
          e = n.toElement();
          if (!e.isNull()) {
            if (e.tagName() == "playlist") {
                tracksCount++;
                node = n.firstChild();
                while (!node.isNull()) {
                  entry = node.toElement();
                  if (entry.tagName() == "entry") {
                      QString id = entry.attribute("producer", QString::null);
                      DocClipBase *baseClip = app->getDocument()->clipManager().findClipById(entry.attribute("producer", QString::number(-1)).toInt());
                      if (baseClip) {
                        GenTime insertTime = GenTime(entry.attribute("in", QString::number(0)).toInt(), KdenliveSettings::defaultfps());
                        GenTime endTime = GenTime(entry.attribute("out", QString::number(0)).toInt(), KdenliveSettings::defaultfps()) - insertTime;
                        DocClipRef *clip = new DocClipRef(baseClip);
                        DocClipRefList selectedClip;
                        selectedClip.append(clip);
                        if (app->getDocument()->projectClip().canAddClipsToTracks(selectedClip, track, startTime)) {
                            kdDebug()<<"/ / /ADDING CLIP TO TRACK: "<<track<<endl;
                            //clip->setParentTrack(app->getDocument()->track(track), track);
                            clip->moveTrackStart(startTime);
                            app->getDocument()->track(track)->addClip(clip, false);
                            clip->setCropStartTime(insertTime);
                            clip->setCropDuration(endTime);
                            clip->setParentTrack(app->getDocument()->track(track), track);
                            baseClip->addReference();
                            startTime+=endTime;
                            KMacroCommand *macroCommand = new KMacroCommand(i18n("Paste"));
                            macroCommand->addCommand(Command::KSelectClipCommand::selectNone(app->getDocument()));
                            macroCommand->addCommand(new Command::KSelectClipCommand(app->getDocument(), clip, true));
                            app->addCommand(macroCommand, true);

                            app->addCommand(new Command::KAddRefClipCommand(*(app->getDocument()), clip, true), false);

                        }

                      }
                  }
                  node = node.nextSibling();
                }
            }
          }
          n = n.nextSibling();
      }
      app->getDocument()->track(track)->checkTrackLength();
      app->getDocument()->generateProducersList();
      app->getDocument()->activateSceneListGeneration(true);

    }

}

Generated by  Doxygen 1.6.0   Back to index