Commit f7bf7548 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Refactor project saving & load using a ILoadSave interface

parent 0d3a62a4
...@@ -57,12 +57,6 @@ MediaLibrary::MediaLibrary(QWidget *parent) : QWidget(parent), ...@@ -57,12 +57,6 @@ MediaLibrary::MediaLibrary(QWidget *parent) : QWidget(parent),
this, SLOT( filterTypeChanged() ) ); this, SLOT( filterTypeChanged() ) );
} }
void
MediaLibrary::setMediaContainer( MediaContainer* container )
{
}
void void
MediaLibrary::changeEvent( QEvent *e ) MediaLibrary::changeEvent( QEvent *e )
{ {
......
...@@ -39,8 +39,6 @@ class MediaLibrary : public QWidget ...@@ -39,8 +39,6 @@ class MediaLibrary : public QWidget
public: public:
typedef bool (*Filter)( const Clip*, const QString& filter ); typedef bool (*Filter)( const Clip*, const QString& filter );
explicit MediaLibrary( QWidget *parent = 0); explicit MediaLibrary( QWidget *parent = 0);
void setMediaContainer( MediaContainer* container );
protected: protected:
void dragEnterEvent( QDragEnterEvent *event ); void dragEnterEvent( QDragEnterEvent *event );
......
...@@ -181,10 +181,12 @@ Timeline::projectLoading( Project* project ) ...@@ -181,10 +181,12 @@ Timeline::projectLoading( Project* project )
m_tracksRuler, SLOT( update() ) ); m_tracksRuler, SLOT( update() ) );
connect( m_tracksRuler, SIGNAL( frameChanged(qint64,Vlmc::FrameChangedReason) ), connect( m_tracksRuler, SIGNAL( frameChanged(qint64,Vlmc::FrameChangedReason) ),
m_renderer, SLOT( rulerCursorChanged(qint64)) ); m_renderer, SLOT( rulerCursorChanged(qint64)) );
project->registerLoadSave( this );
} }
void bool
Timeline::save( QXmlStreamWriter &project ) const Timeline::save( QXmlStreamWriter &project )
{ {
project.writeStartElement( "timeline" ); project.writeStartElement( "timeline" );
for ( int i = 0; i < tracksView()->m_scene->items().size(); ++i ) for ( int i = 0; i < tracksView()->m_scene->items().size(); ++i )
...@@ -209,16 +211,17 @@ Timeline::save( QXmlStreamWriter &project ) const ...@@ -209,16 +211,17 @@ Timeline::save( QXmlStreamWriter &project ) const
project.writeEndElement(); project.writeEndElement();
} }
project.writeEndDocument(); project.writeEndDocument();
return true;
} }
void bool
Timeline::load( const QDomElement &root ) Timeline::load(const QDomDocument& root )
{ {
QDomElement project = root.firstChildElement( "timeline" ); QDomElement project = root.firstChildElement( "timeline" );
if ( project.isNull() == true ) if ( project.isNull() == true )
{ {
vlmcCritical() << "No timeline node in the project file"; vlmcCritical() << "No timeline node in the project file";
return ; return false;
} }
QDomElement elem = project.firstChildElement(); QDomElement elem = project.firstChildElement();
...@@ -252,4 +255,5 @@ Timeline::load( const QDomElement &root ) ...@@ -252,4 +255,5 @@ Timeline::load( const QDomElement &root )
vlmcWarning() << "No such timeline item:" << uuid; vlmcWarning() << "No such timeline item:" << uuid;
elem = elem.nextSiblingElement(); elem = elem.nextSiblingElement();
} }
return true;
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define TIMELINE_H #define TIMELINE_H
#include "Workflow/ClipHelper.h" #include "Workflow/ClipHelper.h"
#include "Project/ILoadSave.h"
#include "vlmc.h" #include "vlmc.h"
#include "ui_Timeline.h" #include "ui_Timeline.h"
#include "Workflow/Types.h" #include "Workflow/Types.h"
...@@ -42,7 +43,7 @@ class WorkflowRenderer; ...@@ -42,7 +43,7 @@ class WorkflowRenderer;
/** /**
* \brief Entry point of the timeline widget. * \brief Entry point of the timeline widget.
*/ */
class Timeline : public QWidget class Timeline : public QWidget, public ILoadSave
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY( Timeline ) Q_DISABLE_COPY( Timeline )
...@@ -61,9 +62,6 @@ public: ...@@ -61,9 +62,6 @@ public:
static Timeline* getInstance() { return m_instance; } static Timeline* getInstance() { return m_instance; }
WorkflowRenderer *renderer() { return m_renderer; } WorkflowRenderer *renderer() { return m_renderer; }
void save( QXmlStreamWriter& project ) const;
void load( const QDomElement &root );
public slots: public slots:
/** /**
* \brief Asks the workflow to clear itself. * \brief Asks the workflow to clear itself.
...@@ -91,6 +89,9 @@ protected: ...@@ -91,6 +89,9 @@ protected:
private: private:
void initialize(); void initialize();
virtual bool save( QXmlStreamWriter& project );
virtual bool load( const QDomDocument& root );
private: private:
Ui::Timeline m_ui; Ui::Timeline m_ui;
......
...@@ -46,13 +46,13 @@ Library::Library( Workspace *workspace ) ...@@ -46,13 +46,13 @@ Library::Library( Workspace *workspace )
{ {
} }
void bool
Library::loadProject( const QDomElement& doc ) Library::load(const QDomDocument& doc )
{ {
const QDomElement medias = doc.firstChildElement( "medias" ); const QDomElement medias = doc.firstChildElement( "medias" );
if ( medias.isNull() == true ) if ( medias.isNull() == true )
return ; return false;
//Add a virtual media, which represents all the clip. //Add a virtual media, which represents all the clip.
//This avoid emitting projectLoaded(); before all the clip are actually loaded. //This avoid emitting projectLoaded(); before all the clip are actually loaded.
...@@ -75,17 +75,18 @@ Library::loadProject( const QDomElement& doc ) ...@@ -75,17 +75,18 @@ Library::loadProject( const QDomElement& doc )
} }
const QDomElement clips = doc.firstChildElement( "clips" ); const QDomElement clips = doc.firstChildElement( "clips" );
if ( clips.isNull() == true ) if ( clips.isNull() == true )
return ; return false;
load( clips, this ); loadContainer( clips, this );
mediaLoaded( NULL ); mediaLoaded( NULL );
//Mark the state as clean, as we just loaded a project. Otherwise, a media //Mark the state as clean, as we just loaded a project. Otherwise, a media
//loading triggers a setCleanState(false) which makes sense when modifying //loading triggers a setCleanState(false) which makes sense when modifying
//project, but not here. //project, but not here.
setCleanState(true); setCleanState(true);
return true;
} }
void bool
Library::saveProject( QXmlStreamWriter& project ) Library::save( QXmlStreamWriter& project )
{ {
QHash<QUuid, Clip*>::const_iterator it = m_clips.begin(); QHash<QUuid, Clip*>::const_iterator it = m_clips.begin();
QHash<QUuid, Clip*>::const_iterator end = m_clips.end(); QHash<QUuid, Clip*>::const_iterator end = m_clips.end();
...@@ -98,9 +99,10 @@ Library::saveProject( QXmlStreamWriter& project ) ...@@ -98,9 +99,10 @@ Library::saveProject( QXmlStreamWriter& project )
} }
project.writeEndElement(); project.writeEndElement();
project.writeStartElement( "clips" ); project.writeStartElement( "clips" );
save( project ); saveContainer( project );
project.writeEndElement(); project.writeEndElement();
setCleanState( true ); setCleanState( true );
return true;
} }
void void
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define LIBRARY_H #define LIBRARY_H
#include "MediaContainer.h" #include "MediaContainer.h"
#include "Project/ILoadSave.h"
#include <QObject> #include <QObject>
#include <QXmlStreamWriter> #include <QXmlStreamWriter>
...@@ -46,7 +47,7 @@ class Workspace; ...@@ -46,7 +47,7 @@ class Workspace;
* \class Library * \class Library
* \brief Library Object that handles public Clips * \brief Library Object that handles public Clips
*/ */
class Library : public MediaContainer class Library : public MediaContainer, public ILoadSave
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY( Library ); Q_DISABLE_COPY( Library );
...@@ -61,21 +62,14 @@ public: ...@@ -61,21 +62,14 @@ public:
private: private:
void setCleanState( bool newState ); void setCleanState( bool newState );
virtual bool load( const QDomDocument& project );
virtual bool save( QXmlStreamWriter& project );
private: private:
QAtomicInt m_nbMediaToLoad; QAtomicInt m_nbMediaToLoad;
bool m_cleanState; bool m_cleanState;
Workspace* m_workspace; Workspace* m_workspace;
public slots:
/**
* \brief
*/
void loadProject( const QDomElement& project );
/**
* \brief
*/
void saveProject( QXmlStreamWriter& project );
private slots: private slots:
void mediaLoaded( const Media* m ); void mediaLoaded( const Media* m );
......
...@@ -189,14 +189,14 @@ MediaContainer::count() const ...@@ -189,14 +189,14 @@ MediaContainer::count() const
} }
void void
MediaContainer::save( QXmlStreamWriter &project ) MediaContainer::saveContainer( QXmlStreamWriter &project ) const
{ {
foreach ( Clip* c, m_clips.values() ) foreach ( Clip* c, m_clips.values() )
c->save( project ); c->save( project );
} }
void bool
MediaContainer::load( const QDomElement &clips, MediaContainer *parentMC ) MediaContainer::loadContainer( const QDomElement& clips, MediaContainer *parentMC )
{ {
QDomElement clip = clips.firstChildElement(); QDomElement clip = clips.firstChildElement();
...@@ -248,8 +248,9 @@ MediaContainer::load( const QDomElement &clips, MediaContainer *parentMC ) ...@@ -248,8 +248,9 @@ MediaContainer::load( const QDomElement &clips, MediaContainer *parentMC )
c->setNotes( notes ); c->setNotes( notes );
QDomElement subClips = clip.firstChildElement( "subClips" ); QDomElement subClips = clip.firstChildElement( "subClips" );
if ( subClips.isNull() == false ) if ( subClips.isNull() == false )
c->getChilds()->load( subClips, this ); c->getChilds()->loadContainer( subClips, this );
} }
clip = clip.nextSiblingElement(); clip = clip.nextSiblingElement();
} }
return true;
} }
...@@ -102,9 +102,9 @@ public: ...@@ -102,9 +102,9 @@ public:
* *
* \param project The QXmlStreamWriter to write into. * \param project The QXmlStreamWriter to write into.
*/ */
void save( QXmlStreamWriter& project ); void saveContainer( QXmlStreamWriter& project ) const;
void load( const QDomElement& root, MediaContainer *parent ); bool loadContainer( const QDomElement& clips, MediaContainer *parent );
/** /**
* \return All the loaded Clip * \return All the loaded Clip
......
...@@ -241,7 +241,7 @@ Clip::save( QXmlStreamWriter &project ) ...@@ -241,7 +241,7 @@ Clip::save( QXmlStreamWriter &project )
if ( m_childs->count() > 0 ) if ( m_childs->count() > 0 )
{ {
project.writeStartElement( "subClips" ); project.writeStartElement( "subClips" );
m_childs->save( project ); m_childs->saveContainer( project );
project.writeEndElement(); project.writeEndElement();
} }
project.writeEndElement(); project.writeEndElement();
......
/*****************************************************************************
* ILoadSave.h: Defines the basic interaction for a component that wishes to
* load or save its state to a project
*****************************************************************************
* Copyright (C) 2008-2014 VideoLAN
*
* Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef ILOADSAVE_H
#define ILOADSAVE_H
class QDomDocument;
class QXmlStreamWriter;
class ILoadSave
{
public:
virtual ~ILoadSave() {}
virtual bool load( const QDomDocument& project ) = 0;
virtual bool save( QXmlStreamWriter& project ) = 0;
};
#endif // ILOADSAVE_H
...@@ -54,7 +54,7 @@ Project::Project() ...@@ -54,7 +54,7 @@ Project::Project()
{ {
m_settings = new Settings( QString() ); m_settings = new Settings( QString() );
m_undoStack = new QUndoStack; m_undoStack = new QUndoStack;
m_workflow = new MainWorkflow(); m_workflow = new MainWorkflow;
m_workspace = new Workspace( m_settings ); m_workspace = new Workspace( m_settings );
m_library = new Library( m_workspace ); m_library = new Library( m_workspace );
m_workflowRenderer = new WorkflowRenderer( Backend::getBackend(), m_workflow ); m_workflowRenderer = new WorkflowRenderer( Backend::getBackend(), m_workflow );
...@@ -124,10 +124,10 @@ Project::load( const QString& fileName ) ...@@ -124,10 +124,10 @@ Project::load( const QString& fileName )
// Now let's start over with a clean state. // Now let's start over with a clean state.
self = getInstance(); self = getInstance();
self->loadProject( fileName );
self->connectComponents(); self->connectComponents();
Core::getInstance()->onProjectLoaded( self ); Core::getInstance()->onProjectLoaded( self );
self->loadProject( fileName );
return true; return true;
} }
...@@ -159,10 +159,10 @@ Project::loadProject( const QString &fileName ) ...@@ -159,10 +159,10 @@ Project::loadProject( const QString &fileName )
QString fileToLoad = checkBackupFile( fileName ); QString fileToLoad = checkBackupFile( fileName );
m_projectFile = new QFile( fileToLoad ); m_projectFile = new QFile( fileToLoad );
m_domDocument = new QDomDocument; QDomDocument doc;
if ( m_projectFile->open( QFile::ReadOnly ) == false || if ( m_projectFile->open( QFile::ReadOnly ) == false ||
m_domDocument->setContent( m_projectFile ) == false ) doc.setContent( m_projectFile ) == false )
{ {
vlmcCritical() << "Can't open project file" << m_projectFile->errorString(); vlmcCritical() << "Can't open project file" << m_projectFile->errorString();
delete m_projectFile; delete m_projectFile;
...@@ -178,13 +178,8 @@ Project::loadProject( const QString &fileName ) ...@@ -178,13 +178,8 @@ Project::loadProject( const QString &fileName )
m_isClean = false; m_isClean = false;
} }
QDomElement root = m_domDocument->documentElement(); foreach (ILoadSave* listener, m_loadSave)
listener->load( doc );
//Load settings first, as it contains some informations about the workspace.
Project::getInstance()->settings()->setSettingsFile( fileName );
Project::getInstance()->settings()->load();
Timeline::getInstance()->renderer()->loadProject( root );
Project::getInstance()->library()->loadProject( root );
m_projectFile->close(); m_projectFile->close();
return true; return true;
} }
...@@ -209,6 +204,10 @@ Project::connectComponents() ...@@ -209,6 +204,10 @@ Project::connectComponents()
//We have to wait for the library to be loaded before loading the workflow //We have to wait for the library to be loaded before loading the workflow
//FIXME //FIXME
//connect( Project::getInstance()->library(), SIGNAL( projectLoaded() ), this, SLOT( loadWorkflow() ) ); //connect( Project::getInstance()->library(), SIGNAL( projectLoaded() ), this, SLOT( loadWorkflow() ) );
registerLoadSave( m_settings );
registerLoadSave( m_library );
registerLoadSave( m_workflow );
registerLoadSave( m_workflowRenderer );
} }
bool bool
...@@ -235,6 +234,7 @@ Project::closeProject() ...@@ -235,6 +234,7 @@ Project::closeProject()
void void
Project::save() Project::save()
{ {
Q_ASSERT( m_projectFile != NULL );
saveProject( m_projectFile->fileName() ); saveProject( m_projectFile->fileName() );
} }
...@@ -340,15 +340,13 @@ Project::saveProject( const QString& fileName ) ...@@ -340,15 +340,13 @@ Project::saveProject( const QString& fileName )
project.writeStartDocument(); project.writeStartDocument();
project.writeStartElement( "vlmc" ); project.writeStartElement( "vlmc" );
Project::getInstance()->library()->saveProject( project ); foreach ( ILoadSave* listener, m_loadSave )
Project::getInstance()->workflow()->saveProject( project ); listener->save( project );
Timeline::getInstance()->renderer()->saveProject( project );
Core::getInstance()->settings()->save( project );
Timeline::getInstance()->save( project );
project.writeEndElement(); project.writeEndElement();
project.writeEndDocument(); project.writeEndDocument();
//FIXME: why not m_projectFile?!
QFile projectFile( fileName ); QFile projectFile( fileName );
projectFile.open( QFile::WriteOnly ); projectFile.open( QFile::WriteOnly );
projectFile.write( projectString ); projectFile.write( projectString );
...@@ -364,6 +362,15 @@ Project::emergencyBackup() ...@@ -364,6 +362,15 @@ Project::emergencyBackup()
Core::getInstance()->settings()->setValue( "private/EmergencyBackup", name ); Core::getInstance()->settings()->setValue( "private/EmergencyBackup", name );
} }
bool
Project::registerLoadSave( ILoadSave* loadSave )
{
if ( m_projectFile != NULL )
return false;
m_loadSave.append( loadSave );
return true;
}
bool bool
Project::loadEmergencyBackup() Project::loadEmergencyBackup()
{ {
...@@ -403,20 +410,6 @@ Project::projectNameChanged( const QVariant& name ) ...@@ -403,20 +410,6 @@ Project::projectNameChanged( const QVariant& name )
emit projectUpdated( m_projectName ); emit projectUpdated( m_projectName );
} }
void
Project::loadWorkflow()
{
QDomElement root = m_domDocument->documentElement();
Project::getInstance()->workflow()->loadProject( root );
//FIXME: This was a no-op after a previous refactoring.
// loadTimeline( root );
emit projectLoaded( name(), m_projectFile->fileName() );
delete m_domDocument;
}
void void
Project::autoSaveRequired() Project::autoSaveRequired()
{ {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <QObject> #include <QObject>
#include "ILoadSave.h"
#include "Tools/Singleton.hpp" #include "Tools/Singleton.hpp"
class QDomDocument; class QDomDocument;
...@@ -60,6 +61,7 @@ class Project : public QObject, public Singleton<Project> ...@@ -60,6 +61,7 @@ class Project : public QObject, public Singleton<Project>
void saveAs(); void saveAs();
bool loadEmergencyBackup(); bool loadEmergencyBackup();
void emergencyBackup(); void emergencyBackup();
bool registerLoadSave( ILoadSave* loadSave );
private: private:
Q_DISABLE_COPY( Project ); Q_DISABLE_COPY( Project );
...@@ -96,7 +98,6 @@ class Project : public QObject, public Singleton<Project> ...@@ -96,7 +98,6 @@ class Project : public QObject, public Singleton<Project>
void cleanChanged( bool val ); void cleanChanged( bool val );
void libraryCleanChanged( bool val ); void libraryCleanChanged( bool val );
void projectNameChanged( const QVariant& projectName ); void projectNameChanged( const QVariant& projectName );
void loadWorkflow();
void autoSaveRequired(); void autoSaveRequired();
signals: signals:
...@@ -133,10 +134,10 @@ class Project : public QObject, public Singleton<Project> ...@@ -133,10 +134,10 @@ class Project : public QObject, public Singleton<Project>
private: private:
QFile* m_projectFile; QFile* m_projectFile;
QString m_projectName; QString m_projectName;
QDomDocument* m_domDocument;
bool m_isClean; bool m_isClean;
bool m_libraryCleanState; bool m_libraryCleanState;
IProjectUiCb* m_projectManagerUi; IProjectUiCb* m_projectManagerUi;
QList<ILoadSave*> m_loadSave;
/////////////////////////////////// ///////////////////////////////////
// Dependent components part below: // Dependent components part below:
......
...@@ -368,21 +368,23 @@ WorkflowRenderer::paramsHasChanged( quint32 width, quint32 height, double fps, Q ...@@ -368,21 +368,23 @@ WorkflowRenderer::paramsHasChanged( quint32 width, quint32 height, double fps, Q
newOutputFps != fps || newAspectRatio != aspect ); newOutputFps != fps || newAspectRatio != aspect );
} }
void bool
WorkflowRenderer::saveProject( QXmlStreamWriter &project ) const WorkflowRenderer::save( QXmlStreamWriter &project )
{ {
project.writeStartElement( "renderer" ); project.writeStartElement( "renderer" );
saveFilters( project ); saveFilters( project );
project.writeEndElement(); project.writeEndElement();
return true;
} }
void bool
WorkflowRenderer::loadProject( const QDomElement &project ) WorkflowRenderer::load(const QDomDocument& project )
{ {
QDomElement renderer = project.firstChildElement( "renderer" ); QDomElement renderer = project.firstChildElement( "renderer" );
if ( renderer.isNull() == true ) if ( renderer.isNull() == true )
return ; return false;
loadEffects( renderer ); loadEffects( renderer );
return true;
} }
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#define WORKFLOWRENDERER_H #define WORKFLOWRENDERER_H
#include "GenericRenderer.h" #include "GenericRenderer.h"
#include "Project/ILoadSave.h"
#include "Backend/ISourceRenderer.h" #include "Backend/ISourceRenderer.h"
#include "Workflow/MainWorkflow.h" #include "Workflow/MainWorkflow.h"
...@@ -41,7 +42,7 @@ class QWidget; ...@@ -41,7 +42,7 @@ class QWidget;
class QWaitCondition; class QWaitCondition;
class QMutex; class QMutex;
class WorkflowRenderer : public GenericRenderer class WorkflowRenderer : public GenericRenderer, public ILoadSave
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY( WorkflowRenderer ) Q_DISABLE_COPY( WorkflowRenderer )
...@@ -131,8 +132,6 @@ class WorkflowRenderer : public GenericRenderer ...@@ -131,8 +132,6 @@ class WorkflowRenderer : public GenericRenderer
*/ */
virtual float getFps() const; virtual float getFps() const;
void saveProject( QXmlStreamWriter &project ) const;
void loadProject( const QDomElement& project );
private: private:
/** /**
* \brief This is a subpart of the togglePlayPause( bool ) method * \brief This is a subpart of the togglePlayPause( bool ) method
...@@ -144,6 +143,9 @@ class WorkflowRenderer : public GenericRenderer ...@@ -144,6 +143,9 @@ class WorkflowRenderer : public GenericRenderer
*/ */
virtual void startPreview(); virtual void startPreview();
virtual bool save( QXmlStreamWriter &project );
virtual bool load( const QDomDocument& project );
protected: protected:
/** /**
* \brief Will return a pointer to the function/static method to use * \brief Will return a pointer to the function/static method to use
......
...@@ -80,8 +80,8 @@ Settings::setSettingsFile(const QString &settingsFile) ...@@ -80,8 +80,8 @@ Settings::setSettingsFile(const QString &settingsFile)
m_settingsFile = NULL; m_settingsFile = NULL;
} }
void bool
Settings::save( QXmlStreamWriter& project ) const Settings::save( QXmlStreamWriter& project )
{ {
QReadLocker lock( &m_rwLock ); QReadLocker lock( &m_rwLock );
...@@ -101,23 +101,13 @@ Settings::save( QXmlStreamWriter& project ) const ...@@ -101,23 +101,13 @@ Settings::save( QXmlStreamWriter& project ) const
project.writeEndElement(); project.writeEndElement();
} }
project.writeEndElement(); project.writeEndElement();
return true;
} }
bool bool
Settings::load() Settings::load( const QDomDocument& document )