]> git.sesse.net Git - kdenlive/commitdiff
* Fix possible crash when creating new document
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 31 Jan 2009 15:03:15 +0000 (15:03 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 31 Jan 2009 15:03:15 +0000 (15:03 +0000)
* Add "Cancel" button that will abort loading when opening a project with missing clips:
http://www.kdenlive.org:80/mantis/view.php?id=622

svn path=/branches/KDE4/; revision=3012

src/clipmanager.cpp
src/clipmanager.h
src/kdenlivedoc.cpp
src/kdenlivedoc.h
src/mainwindow.cpp
src/monitormanager.cpp
src/projectlist.cpp
src/projectlist.h

index f0f3a1fc25ace03f188c3bc3156fe534121bf4af..d3b8453ac7ad944f2bf87fdf4946556a89b83a00 100644 (file)
@@ -37,6 +37,15 @@ ClipManager::~ClipManager() {
     qDeleteAll(m_clipList);
 }
 
+void ClipManager::clear() {
+    qDeleteAll(m_clipList);
+    m_clipList.clear();
+    m_clipIdCounter = 1;
+    m_folderIdCounter = 1;
+    m_folderList.clear();
+    m_audioThumbsQueue.clear();
+}
+
 void ClipManager::checkAudioThumbs() {
     if (m_audioThumbsEnabled == KdenliveSettings::audiothumbnails()) return;
     m_audioThumbsEnabled = KdenliveSettings::audiothumbnails();
index 2b224521a0941488aaa1c578a368a0c4ffcee83f..2d5f510795fb4dc8a0440a8e8fa74c511090277f 100644 (file)
@@ -74,6 +74,7 @@ Q_OBJECT public:
     void resetProducersList(QList <Mlt::Producer *> prods);
     void addFolder(const QString&, const QString&);
     void deleteFolder(const QString&);
+    void clear();
 
 public slots:
     void updatePreviewSettings();
index b88cedae952a436af71ce1ae571b14b555b65313..1e42516f67dc9f13818e9276e13934d73029a153 100644 (file)
@@ -41,7 +41,7 @@
 #include "titlewidget.h"
 #include "mainwindow.h"
 
-KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QPoint tracks, Render *render, MainWindow *parent): QObject(parent), m_render(render), m_url(url), m_projectFolder(projectFolder), m_commandStack(new QUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0), m_zoom(7), m_autosave(NULL), m_zoneStart(0), m_zoneEnd(100) {
+KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup *undoGroup, const QString &profileName, const QPoint tracks, Render *render, MainWindow *parent): QObject(parent), m_render(render), m_url(url), m_projectFolder(projectFolder), m_commandStack(new QUndoStack(undoGroup)), m_modified(false), m_documentLoadingProgress(0), m_documentLoadingStep(0.0), m_startPos(0), m_zoom(7), m_autosave(NULL), m_zoneStart(0), m_zoneEnd(100), m_abortLoading(false) {
     m_clipManager = new ClipManager(this);
     m_autoSaveTimer = new QTimer(this);
     m_autoSaveTimer->setSingleShot(true);
@@ -92,7 +92,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                     setProfilePath(profilePath);
 
                     // Build tracks
-                    QString tracks = infoXml.attribute("tracks");
+                    QString xmltracks = infoXml.attribute("tracks");
                     TrackInfo videoTrack;
                     videoTrack.type = VIDEOTRACK;
                     videoTrack.isMute = false;
@@ -102,8 +102,8 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                     audioTrack.type = AUDIOTRACK;
                     audioTrack.isMute = false;
                     audioTrack.isBlind = true;
-                    for (int i = 0; i < tracks.size(); i++) {
-                        if (tracks.data()[i] == 'v') m_tracksList.append(videoTrack);
+                    for (int i = 0; i < xmltracks.size(); i++) {
+                        if (xmltracks.data()[i] == 'v') m_tracksList.append(videoTrack);
                         else m_tracksList.append(audioTrack);
                     }
 
@@ -127,7 +127,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                     }
 
 
-                    for (int i = 0; i < infomax; i++) {
+                    for (int i = 0; i < infomax && !m_abortLoading; i++) {
                         e = infoproducers.item(i).cloneNode().toElement();
                         if (m_documentLoadingStep > 0) {
                             m_documentLoadingProgress += m_documentLoadingStep;
@@ -135,7 +135,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                             //qApp->processEvents();
                         }
                         QString prodId = e.attribute("id");
-                        if (!e.isNull() && prodId != "black" && !prodId.startsWith("slowmotion")) {
+                        if (!e.isNull() && prodId != "black" && !prodId.startsWith("slowmotion") && !m_abortLoading) {
                             e.setTagName("producer");
                             // Get MLT's original producer properties
 
@@ -151,35 +151,47 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
                             kDebug() << "// NLIVE PROD: " << prodId;
                         }
                     }
-
-                    QDomNode markers = m_document.elementsByTagName("markers").at(0);
-                    if (!markers.isNull()) {
-                        QDomNodeList markerslist = markers.childNodes();
-                        int maxchild = markerslist.count();
-                        for (int k = 0; k < maxchild; k++) {
-                            e = markerslist.at(k).toElement();
-                            if (e.tagName() == "marker") {
-                                m_clipManager->getClipById(e.attribute("id"))->addSnapMarker(GenTime(e.attribute("time").toDouble()), e.attribute("comment"));
+                    if (m_abortLoading) {
+                        //parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file."), 100);
+                        emit resetProjectList();
+                        m_startPos = 0;
+                        m_url = KUrl();
+                        m_tracksList.clear();
+                        kWarning() << "Aborted loading of: " << url.path();
+                        m_document = createEmptyDocument(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks());
+                        setProfilePath(KdenliveSettings::default_profile());
+                        m_clipManager->clear();
+                    } else {
+                        QDomNode markers = m_document.elementsByTagName("markers").at(0);
+                        if (!markers.isNull()) {
+                            QDomNodeList markerslist = markers.childNodes();
+                            int maxchild = markerslist.count();
+                            for (int k = 0; k < maxchild; k++) {
+                                e = markerslist.at(k).toElement();
+                                if (e.tagName() == "marker") {
+                                    m_clipManager->getClipById(e.attribute("id"))->addSnapMarker(GenTime(e.attribute("time").toDouble()), e.attribute("comment"));
+                                }
                             }
+                            westley.removeChild(markers);
                         }
-                        westley.removeChild(markers);
+                        m_document.removeChild(infoXmlNode);
+                        kDebug() << "Reading file: " << url.path() << ", found clips: " << producers.count();
                     }
-                    m_document.removeChild(infoXmlNode);
-
-                    kDebug() << "Reading file: " << url.path() << ", found clips: " << producers.count();
                 }
             } else {
                 parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file."), 100);
                 kWarning() << "  NO KDENLIVE INFO FOUND IN FILE: " << url.path();
-                m_document = createEmptyDocument(tracks.x(), tracks.y());
-                setProfilePath(profileName);
+                m_document = createEmptyDocument(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks());
+                m_url = KUrl();
+                setProfilePath(KdenliveSettings::default_profile());
             }
             KIO::NetAccess::removeTempFile(tmpFile);
         } else {
             KMessageBox::error(parent, KIO::NetAccess::lastErrorString());
             parent->slotGotProgressInfo(i18n("File %1 is not a Kdenlive project file."), 100);
-            m_document = createEmptyDocument(tracks.x(), tracks.y());
-            setProfilePath(profileName);
+            m_url = KUrl();
+            m_document = createEmptyDocument(KdenliveSettings::videotracks(), KdenliveSettings::audiotracks());
+            setProfilePath(KdenliveSettings::default_profile());
         }
     } else {
         m_document = createEmptyDocument(tracks.x(), tracks.y());
@@ -192,8 +204,7 @@ KdenliveDoc::KdenliveDoc(const KUrl &url, const KUrl &projectFolder, QUndoGroup
     KStandardDirs::makeDir(m_projectFolder.path() + "/thumbs/");
     KStandardDirs::makeDir(m_projectFolder.path() + "/ladspa/");
 
-    m_scenelist = m_document.toString();
-    kDebug() << "KDEnnlive document, init timecode: " << m_fps;
+    kDebug() << "KDEnlive document, init timecode: " << m_fps;
     if (m_fps == 30000.0 / 1001.0) m_timecode.setFormat(30, true);
     else m_timecode.setFormat((int) m_fps);
 
@@ -1150,10 +1161,6 @@ QDomNodeList KdenliveDoc::producersList() {
     return m_document.elementsByTagName("producer");
 }
 
-void KdenliveDoc::backupMltPlaylist() {
-    if (m_render) m_scenelist = m_render->sceneList();
-}
-
 double KdenliveDoc::projectDuration() const {
     if (m_render) return GenTime(m_render->getLength(), m_fps).ms() / 1000;
 }
@@ -1241,16 +1248,28 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem)
             const QString size = elem.attribute("file_size");
             const QString hash = elem.attribute("file_hash");
             QString newpath;
-            KMessageBox::ButtonCode action = KMessageBox::No;
+            int action = KMessageBox::No;
             if (!size.isEmpty() && !hash.isEmpty()) {
                 if (!m_searchFolder.isEmpty()) newpath = searchFileRecursively(m_searchFolder, size, hash);
-                else action = (KMessageBox::ButtonCode)KMessageBox::messageBox(kapp->activeWindow(), KMessageBox::WarningYesNo, i18n("Clip <b>%1</b><br>is invalid, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search automatically")), /*KGuiItem(i18n("Remove from project")), */KGuiItem(i18n("Keep as placeholder")));
+                else action = (KMessageBox::ButtonCode) KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip <b>%1</b><br>is invalid, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search automatically")), KGuiItem(i18n("Keep as placeholder")));
             } else {
                 if (elem.attribute("type").toInt() == SLIDESHOW) {
-                    if (KMessageBox::messageBox(kapp->activeWindow(), KMessageBox::WarningYesNo, i18n("<qt>Clip <b>%1</b><br>is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), /*KGuiItem(i18n("Remove from project")),*/ KGuiItem(i18n("Keep as placeholder"))) == KMessageBox::Yes)
+                    int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip <b>%1</b><br>is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder")));
+                    if (res == KMessageBox::Yes)
                         newpath = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///clipfolder"), kapp->activeWindow(), i18n("Looking for %1", path));
-                } else if (KMessageBox::messageBox(kapp->activeWindow(), KMessageBox::WarningYesNo, i18n("Clip <b>%1</b><br>is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), /*KGuiItem(i18n("Remove from project")),*/ KGuiItem(i18n("Keep as placeholder"))) == KMessageBox::Yes)
-                    newpath = KFileDialog::getOpenFileName(KUrl("kfiledialog:///clipfolder"), QString(), kapp->activeWindow(), i18n("Looking for %1", path));
+                    else if (res == KMessageBox::Cancel) {
+                        // Abort project loading
+                        action = KMessageBox::Cancel;
+                    }
+                } else {
+                    int res = KMessageBox::questionYesNoCancel(kapp->activeWindow(), i18n("Clip <b>%1</b><br>is invalid or missing, what do you want to do?", path), i18n("File not found"), KGuiItem(i18n("Search manually")), KGuiItem(i18n("Keep as placeholder")));
+                    if (res == KMessageBox::Yes)
+                        newpath = KFileDialog::getOpenFileName(KUrl("kfiledialog:///clipfolder"), QString(), kapp->activeWindow(), i18n("Looking for %1", path));
+                    else if (res == KMessageBox::Cancel) {
+                        // Abort project loading
+                        action = KMessageBox::Cancel;
+                    }
+                }
             }
             if (action == KMessageBox::Yes) {
                 kDebug() << "// ASKED FOR SRCH CLIP: " << clipId;
@@ -1258,6 +1277,9 @@ void KdenliveDoc::addClip(QDomElement elem, QString clipId, bool createClipItem)
                 if (!m_searchFolder.isEmpty()) {
                     newpath = searchFileRecursively(QDir(m_searchFolder), size, hash);
                 }
+            } else if (action == KMessageBox::Cancel) {
+                m_abortLoading = true;
+                return;
             }
             if (!newpath.isEmpty()) {
                 if (elem.attribute("type").toInt() == SLIDESHOW) newpath.append('/' + extension);
index 29cd402b7e6954975511f7057a12006edcbefb03..24aaea11210d8d44f35f3c69f19f514d8df8ed35 100644 (file)
@@ -56,7 +56,6 @@ Q_OBJECT public:
     int height() const;
     KUrl url() const;
     KAutoSaveFile *m_autosave;
-    void backupMltPlaylist();
     Timecode timecode() const;
     QDomDocument toXml();
     //void setRenderer(Render *render);
@@ -133,7 +132,6 @@ private:
     QDomDocument generateSceneList();
     ClipManager *m_clipManager;
     MltVideoProfile m_profile;
-    QString m_scenelist;
     QTimer *m_autoSaveTimer;
     QString m_searchFolder;
     /** tells whether current doc has been changed since last save event */
@@ -142,6 +140,7 @@ private:
     KUrl m_projectFolder;
     double m_documentLoadingStep;
     double m_documentLoadingProgress;
+    bool m_abortLoading;
     int m_zoneStart;
     int m_zoneEnd;
 
@@ -164,6 +163,7 @@ private slots:
     void slotAutoSave();
 
 signals:
+    void resetProjectList();
     void addProjectClip(DocClipBase *, bool getInfo = true);
     void signalDeleteProjectClip(const QString &);
     void updateClipDisplay(const QString&);
index ef0714647a418c35761ec5232586c0c618e4f76c..5b2878e7cef485a724b041f0999898e210f24223 100644 (file)
@@ -1519,7 +1519,6 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
     kDebug() << "///////////////////   CONNECTING DOC TO PROJECT VIEW ////////////////";
     if (m_activeDocument) {
         if (m_activeDocument == doc) return;
-        m_activeDocument->backupMltPlaylist();
         if (m_activeTimeline) {
             disconnect(m_projectMonitor, SIGNAL(renderPosition(int)), m_activeTimeline, SLOT(moveCursorPos(int)));
             disconnect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), m_activeTimeline, SLOT(slotSetZone(QPoint)));
@@ -1529,6 +1528,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
 
             disconnect(m_activeDocument, SIGNAL(guidesUpdated()), this, SLOT(slotGuidesUpdated()));
             disconnect(m_activeDocument, SIGNAL(addProjectClip(DocClipBase *, bool)), m_projectList, SLOT(slotAddClip(DocClipBase *, bool)));
+            disconnect(m_activeDocument, SIGNAL(resetProjectList()), m_projectList, SLOT(slotResetProjectList()));
             disconnect(m_activeDocument, SIGNAL(signalDeleteProjectClip(const QString &)), m_projectList, SLOT(slotDeleteClip(const QString &)));
             disconnect(m_activeDocument, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
             disconnect(m_activeDocument, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
@@ -1583,6 +1583,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
     connect(m_projectMonitor, SIGNAL(zoneUpdated(QPoint)), trackView, SLOT(slotSetZone(QPoint)));
     connect(m_projectMonitor, SIGNAL(durationChanged(int)), trackView, SLOT(setDuration(int)));
     connect(doc, SIGNAL(addProjectClip(DocClipBase *, bool)), m_projectList, SLOT(slotAddClip(DocClipBase *, bool)));
+    connect(doc, SIGNAL(resetProjectList()), m_projectList, SLOT(slotResetProjectList()));
     connect(doc, SIGNAL(signalDeleteProjectClip(const QString &)), m_projectList, SLOT(slotDeleteClip(const QString &)));
     connect(doc, SIGNAL(updateClipDisplay(const QString &)), m_projectList, SLOT(slotUpdateClip(const QString &)));
     connect(doc, SIGNAL(selectLastAddedClip(const QString &)), m_projectList, SLOT(slotSelectClip(const QString &)));
index 0800fe95a31a5b1a439cc9df3d032063b8a14d8d..00515de5fda074295e45b5db5963eb05a04d3956 100644 (file)
@@ -131,7 +131,7 @@ void MonitorManager::slotEnd() {
 
 void MonitorManager::resetProfiles(Timecode tc) {
     m_timecode = tc;
-    slotResetProfiles();
+    QTimer::singleShot(300, this, SLOT(slotResetProfiles()));
 }
 
 void MonitorManager::slotResetProfiles() {
index c9dccf7df52442a3ab57adb40add514a53e3c94b..9d284d7c94ecc6c259ab159b13f03442a6a97e17 100644 (file)
@@ -394,6 +394,14 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties) {
     listView->blockSignals(false);
 }
 
+void ProjectList::slotResetProjectList() {
+    listView->clear();
+    emit clipSelected(NULL);
+    m_thumbnailQueue.clear();
+    m_infoQueue.clear();
+    m_refreshed = false;
+}
+
 void ProjectList::requestClipInfo(const QDomElement xml, const QString id) {
     kDebug() << " PRG LIST REQUEST CLP INFO: " << id;
     m_infoQueue.insert(id, xml);
@@ -498,6 +506,7 @@ void ProjectList::slotRemoveInvalidClip(const QString &id) {
         m_doc->deleteProjectClip(ids);
     }
     if (!m_infoQueue.isEmpty()) QTimer::singleShot(300, this, SLOT(slotProcessNextClipInQueue()));
+    else listView->setEnabled(true);
 }
 
 void ProjectList::slotAddColorClip() {
@@ -578,6 +587,7 @@ void ProjectList::slotAddTitleClip() {
 void ProjectList::setDocument(KdenliveDoc *doc) {
     listView->blockSignals(true);
     listView->clear();
+    emit clipSelected(NULL);
     m_thumbnailQueue.clear();
     m_infoQueue.clear();
     m_refreshed = false;
@@ -666,7 +676,7 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
     if (item && producer) {
         listView->blockSignals(true);
         item->setProperties(properties, metadata);
-        Q_ASSERT_X( item->referencedClip(), "void ProjectList::slotReplyGetFileProperties", QString( "Item with groupName %1 does not have a clip associated" ).arg( item->groupName() ).toLatin1() );
+        Q_ASSERT_X(item->referencedClip(), "void ProjectList::slotReplyGetFileProperties", QString("Item with groupName %1 does not have a clip associated").arg(item->groupName()).toLatin1());
         item->referencedClip()->setProducer(producer);
         emit receivedClipDuration(clipId, item->clipMaxDuration());
         listView->blockSignals(false);
index f49952e2c2af319fc3c05ce684134008f290dd9e..d707faf399c4a40db4b2b426f2dc409f60294d3e 100644 (file)
@@ -130,6 +130,7 @@ public slots:
     void slotRemoveClip();
     void slotAddClip(KUrl givenUrl = KUrl(), QString group = QString());
     void slotAddFolder(const QString foldername, const QString &clipId, bool remove, bool edit = false);
+    void slotResetProjectList();
 
 private:
     ProjectListView *listView;
@@ -140,7 +141,6 @@ private:
     QToolBar *m_toolbar;
     QMenu *m_menu;
     QUndoStack *m_commandStack;
-    // mbd: I think this has died at some point: int m_clipIdCounter;
     void selectItemById(const QString &clipId);
     ProjectItem *getItemById(const QString &id);
     ProjectItem *getFolderItemById(const QString &id);