From 890932ce1fb3c925b54b7e486575380f2d6e67e0 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sat, 31 Jan 2009 15:03:15 +0000 Subject: [PATCH] * Fix possible crash when creating new document * 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 | 9 +++++ src/clipmanager.h | 1 + src/kdenlivedoc.cpp | 90 ++++++++++++++++++++++++++---------------- src/kdenlivedoc.h | 4 +- src/mainwindow.cpp | 3 +- src/monitormanager.cpp | 2 +- src/projectlist.cpp | 12 +++++- src/projectlist.h | 2 +- 8 files changed, 83 insertions(+), 40 deletions(-) diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index f0f3a1fc..d3b8453a 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -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(); diff --git a/src/clipmanager.h b/src/clipmanager.h index 2b224521..2d5f5107 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -74,6 +74,7 @@ Q_OBJECT public: void resetProducersList(QList prods); void addFolder(const QString&, const QString&); void deleteFolder(const QString&); + void clear(); public slots: void updatePreviewSettings(); diff --git a/src/kdenlivedoc.cpp b/src/kdenlivedoc.cpp index b88cedae..1e42516f 100644 --- a/src/kdenlivedoc.cpp +++ b/src/kdenlivedoc.cpp @@ -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 %1
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 %1
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("Clip %1
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 %1
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 %1
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 %1
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); diff --git a/src/kdenlivedoc.h b/src/kdenlivedoc.h index 29cd402b..24aaea11 100644 --- a/src/kdenlivedoc.h +++ b/src/kdenlivedoc.h @@ -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&); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ef071464..5b2878e7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -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 &))); diff --git a/src/monitormanager.cpp b/src/monitormanager.cpp index 0800fe95..00515de5 100644 --- a/src/monitormanager.cpp +++ b/src/monitormanager.cpp @@ -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() { diff --git a/src/projectlist.cpp b/src/projectlist.cpp index c9dccf7d..9d284d7c 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -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); diff --git a/src/projectlist.h b/src/projectlist.h index f49952e2..d707faf3 100644 --- a/src/projectlist.h +++ b/src/projectlist.h @@ -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); -- 2.39.2