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),
this, SLOT( filterTypeChanged() ) );
}
void
MediaLibrary::setMediaContainer( MediaContainer* container )
{
}
void
MediaLibrary::changeEvent( QEvent *e )
{
......
......@@ -39,8 +39,6 @@ class MediaLibrary : public QWidget
public:
typedef bool (*Filter)( const Clip*, const QString& filter );
explicit MediaLibrary( QWidget *parent = 0);
void setMediaContainer( MediaContainer* container );
protected:
void dragEnterEvent( QDragEnterEvent *event );
......
......@@ -181,10 +181,12 @@ Timeline::projectLoading( Project* project )
m_tracksRuler, SLOT( update() ) );
connect( m_tracksRuler, SIGNAL( frameChanged(qint64,Vlmc::FrameChangedReason) ),
m_renderer, SLOT( rulerCursorChanged(qint64)) );
project->registerLoadSave( this );
}
void
Timeline::save( QXmlStreamWriter &project ) const
bool
Timeline::save( QXmlStreamWriter &project )
{
project.writeStartElement( "timeline" );
for ( int i = 0; i < tracksView()->m_scene->items().size(); ++i )
......@@ -209,16 +211,17 @@ Timeline::save( QXmlStreamWriter &project ) const
project.writeEndElement();
}
project.writeEndDocument();
return true;
}
void
Timeline::load( const QDomElement &root )
bool
Timeline::load(const QDomDocument& root )
{
QDomElement project = root.firstChildElement( "timeline" );
if ( project.isNull() == true )
{
vlmcCritical() << "No timeline node in the project file";
return ;
return false;
}
QDomElement elem = project.firstChildElement();
......@@ -252,4 +255,5 @@ Timeline::load( const QDomElement &root )
vlmcWarning() << "No such timeline item:" << uuid;
elem = elem.nextSiblingElement();
}
return true;
}
......@@ -24,6 +24,7 @@
#define TIMELINE_H
#include "Workflow/ClipHelper.h"
#include "Project/ILoadSave.h"
#include "vlmc.h"
#include "ui_Timeline.h"
#include "Workflow/Types.h"
......@@ -42,7 +43,7 @@ class WorkflowRenderer;
/**
* \brief Entry point of the timeline widget.
*/
class Timeline : public QWidget
class Timeline : public QWidget, public ILoadSave
{
Q_OBJECT
Q_DISABLE_COPY( Timeline )
......@@ -61,9 +62,6 @@ public:
static Timeline* getInstance() { return m_instance; }
WorkflowRenderer *renderer() { return m_renderer; }
void save( QXmlStreamWriter& project ) const;
void load( const QDomElement &root );
public slots:
/**
* \brief Asks the workflow to clear itself.
......@@ -90,7 +88,10 @@ protected:
virtual void changeEvent( QEvent *e );
private:
void initialize();
void initialize();
virtual bool save( QXmlStreamWriter& project );
virtual bool load( const QDomDocument& root );
private:
Ui::Timeline m_ui;
......
......@@ -46,13 +46,13 @@ Library::Library( Workspace *workspace )
{
}
void
Library::loadProject( const QDomElement& doc )
bool
Library::load(const QDomDocument& doc )
{
const QDomElement medias = doc.firstChildElement( "medias" );
if ( medias.isNull() == true )
return ;
return false;
//Add a virtual media, which represents all the clip.
//This avoid emitting projectLoaded(); before all the clip are actually loaded.
......@@ -73,19 +73,20 @@ Library::loadProject( const QDomElement& doc )
}
media = media.nextSiblingElement();
}
const QDomElement clips = doc.firstChildElement( "clips" );
const QDomElement clips = doc.firstChildElement( "clips" );
if ( clips.isNull() == true )
return ;
load( clips, this );
return false;
loadContainer( clips, this );
mediaLoaded( NULL );
//Mark the state as clean, as we just loaded a project. Otherwise, a media
//loading triggers a setCleanState(false) which makes sense when modifying
//project, but not here.
setCleanState(true);
return true;
}
void
Library::saveProject( QXmlStreamWriter& project )
bool
Library::save( QXmlStreamWriter& project )
{
QHash<QUuid, Clip*>::const_iterator it = m_clips.begin();
QHash<QUuid, Clip*>::const_iterator end = m_clips.end();
......@@ -98,9 +99,10 @@ Library::saveProject( QXmlStreamWriter& project )
}
project.writeEndElement();
project.writeStartElement( "clips" );
save( project );
saveContainer( project );
project.writeEndElement();
setCleanState( true );
return true;
}
void
......
......@@ -31,6 +31,7 @@
#define LIBRARY_H
#include "MediaContainer.h"
#include "Project/ILoadSave.h"
#include <QObject>
#include <QXmlStreamWriter>
......@@ -46,7 +47,7 @@ class Workspace;
* \class Library
* \brief Library Object that handles public Clips
*/
class Library : public MediaContainer
class Library : public MediaContainer, public ILoadSave
{
Q_OBJECT
Q_DISABLE_COPY( Library );
......@@ -60,22 +61,15 @@ public:
bool isInCleanState() const;
private:
void setCleanState( bool newState );
void setCleanState( bool newState );
virtual bool load( const QDomDocument& project );
virtual bool save( QXmlStreamWriter& project );
private:
QAtomicInt m_nbMediaToLoad;
bool m_cleanState;
Workspace* m_workspace;
public slots:
/**
* \brief
*/
void loadProject( const QDomElement& project );
/**
* \brief
*/
void saveProject( QXmlStreamWriter& project );
private slots:
void mediaLoaded( const Media* m );
......
......@@ -189,14 +189,14 @@ MediaContainer::count() const
}
void
MediaContainer::save( QXmlStreamWriter &project )
MediaContainer::saveContainer( QXmlStreamWriter &project ) const
{
foreach ( Clip* c, m_clips.values() )
c->save( project );
}
void
MediaContainer::load( const QDomElement &clips, MediaContainer *parentMC )
bool
MediaContainer::loadContainer( const QDomElement& clips, MediaContainer *parentMC )
{
QDomElement clip = clips.firstChildElement();
......@@ -248,8 +248,9 @@ MediaContainer::load( const QDomElement &clips, MediaContainer *parentMC )
c->setNotes( notes );
QDomElement subClips = clip.firstChildElement( "subClips" );
if ( subClips.isNull() == false )
c->getChilds()->load( subClips, this );
c->getChilds()->loadContainer( subClips, this );
}
clip = clip.nextSiblingElement();
}
return true;
}
......@@ -102,9 +102,9 @@ public:
*
* \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
......
......@@ -241,7 +241,7 @@ Clip::save( QXmlStreamWriter &project )
if ( m_childs->count() > 0 )
{
project.writeStartElement( "subClips" );
m_childs->save( project );
m_childs->saveContainer( project );
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()
{
m_settings = new Settings( QString() );
m_undoStack = new QUndoStack;
m_workflow = new MainWorkflow();
m_workflow = new MainWorkflow;
m_workspace = new Workspace( m_settings );
m_library = new Library( m_workspace );
m_workflowRenderer = new WorkflowRenderer( Backend::getBackend(), m_workflow );
......@@ -124,10 +124,10 @@ Project::load( const QString& fileName )
// Now let's start over with a clean state.
self = getInstance();
self->loadProject( fileName );
self->connectComponents();
Core::getInstance()->onProjectLoaded( self );
self->loadProject( fileName );
return true;
}
......@@ -159,10 +159,10 @@ Project::loadProject( const QString &fileName )
QString fileToLoad = checkBackupFile( fileName );
m_projectFile = new QFile( fileToLoad );
m_domDocument = new QDomDocument;
QDomDocument doc;
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();
delete m_projectFile;
......@@ -178,13 +178,8 @@ Project::loadProject( const QString &fileName )
m_isClean = false;
}
QDomElement root = m_domDocument->documentElement();
//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 );
foreach (ILoadSave* listener, m_loadSave)
listener->load( doc );
m_projectFile->close();
return true;
}
......@@ -209,6 +204,10 @@ Project::connectComponents()
//We have to wait for the library to be loaded before loading the workflow
//FIXME
//connect( Project::getInstance()->library(), SIGNAL( projectLoaded() ), this, SLOT( loadWorkflow() ) );
registerLoadSave( m_settings );
registerLoadSave( m_library );
registerLoadSave( m_workflow );
registerLoadSave( m_workflowRenderer );
}
bool
......@@ -235,6 +234,7 @@ Project::closeProject()
void
Project::save()
{
Q_ASSERT( m_projectFile != NULL );
saveProject( m_projectFile->fileName() );
}
......@@ -340,15 +340,13 @@ Project::saveProject( const QString& fileName )
project.writeStartDocument();
project.writeStartElement( "vlmc" );
Project::getInstance()->library()->saveProject( project );
Project::getInstance()->workflow()->saveProject( project );
Timeline::getInstance()->renderer()->saveProject( project );
Core::getInstance()->settings()->save( project );
Timeline::getInstance()->save( project );
foreach ( ILoadSave* listener, m_loadSave )
listener->save( project );
project.writeEndElement();
project.writeEndDocument();
//FIXME: why not m_projectFile?!
QFile projectFile( fileName );
projectFile.open( QFile::WriteOnly );
projectFile.write( projectString );
......@@ -364,6 +362,15 @@ Project::emergencyBackup()
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
Project::loadEmergencyBackup()
{
......@@ -403,20 +410,6 @@ Project::projectNameChanged( const QVariant& name )
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
Project::autoSaveRequired()
{
......
......@@ -27,6 +27,7 @@
#include <QObject>
#include "ILoadSave.h"
#include "Tools/Singleton.hpp"
class QDomDocument;
......@@ -60,6 +61,7 @@ class Project : public QObject, public Singleton<Project>
void saveAs();
bool loadEmergencyBackup();
void emergencyBackup();
bool registerLoadSave( ILoadSave* loadSave );
private:
Q_DISABLE_COPY( Project );
......@@ -96,7 +98,6 @@ class Project : public QObject, public Singleton<Project>
void cleanChanged( bool val );
void libraryCleanChanged( bool val );
void projectNameChanged( const QVariant& projectName );
void loadWorkflow();
void autoSaveRequired();
signals:
......@@ -133,10 +134,10 @@ class Project : public QObject, public Singleton<Project>
private:
QFile* m_projectFile;
QString m_projectName;
QDomDocument* m_domDocument;
bool m_isClean;
bool m_libraryCleanState;
IProjectUiCb* m_projectManagerUi;
QList<ILoadSave*> m_loadSave;
///////////////////////////////////
// Dependent components part below:
......
......@@ -368,21 +368,23 @@ WorkflowRenderer::paramsHasChanged( quint32 width, quint32 height, double fps, Q
newOutputFps != fps || newAspectRatio != aspect );
}
void
WorkflowRenderer::saveProject( QXmlStreamWriter &project ) const
bool
WorkflowRenderer::save( QXmlStreamWriter &project )
{
project.writeStartElement( "renderer" );
saveFilters( project );
project.writeEndElement();
return true;
}
void
WorkflowRenderer::loadProject( const QDomElement &project )
bool
WorkflowRenderer::load(const QDomDocument& project )
{
QDomElement renderer = project.firstChildElement( "renderer" );
if ( renderer.isNull() == true )
return ;
return false;
loadEffects( renderer );
return true;
}
/////////////////////////////////////////////////////////////////////
......
......@@ -24,6 +24,7 @@
#define WORKFLOWRENDERER_H
#include "GenericRenderer.h"
#include "Project/ILoadSave.h"
#include "Backend/ISourceRenderer.h"
#include "Workflow/MainWorkflow.h"
......@@ -41,7 +42,7 @@ class QWidget;
class QWaitCondition;
class QMutex;
class WorkflowRenderer : public GenericRenderer
class WorkflowRenderer : public GenericRenderer, public ILoadSave
{
Q_OBJECT
Q_DISABLE_COPY( WorkflowRenderer )
......@@ -131,8 +132,6 @@ class WorkflowRenderer : public GenericRenderer
*/
virtual float getFps() const;
void saveProject( QXmlStreamWriter &project ) const;
void loadProject( const QDomElement& project );
private:
/**
* \brief This is a subpart of the togglePlayPause( bool ) method
......@@ -144,6 +143,9 @@ class WorkflowRenderer : public GenericRenderer
*/
virtual void startPreview();
virtual bool save( QXmlStreamWriter &project );
virtual bool load( const QDomDocument& project );
protected:
/**
* \brief Will return a pointer to the function/static method to use
......
......@@ -80,8 +80,8 @@ Settings::setSettingsFile(const QString &settingsFile)
m_settingsFile = NULL;
}
void
Settings::save( QXmlStreamWriter& project ) const
bool
Settings::save( QXmlStreamWriter& project )
{
QReadLocker lock( &m_rwLock );
......@@ -101,23 +101,13 @@ Settings::save( QXmlStreamWriter& project ) const
project.writeEndElement();
}
project.writeEndElement();
return true;
}
bool
Settings::load()
Settings::load( const QDomDocument& document )
{
QDomDocument doc("root");
if ( m_settingsFile->open( QFile::ReadOnly ) == false )
{
vlmcWarning() << "Failed to open settings file" << m_settingsFile->fileName();
return false;
}
if ( doc.setContent( m_settingsFile ) == false )
{
vlmcWarning() << "Failed to load settings file" << m_settingsFile->fileName();
return false;
}
QDomElement element = doc.firstChildElement( "settings" );
QDomElement element = document.firstChildElement( "settings" );
if ( element.isNull() == true )
{
vlmcWarning() << "Invalid settings node";
......@@ -140,15 +130,33 @@ Settings::load()
}
s = s.nextSiblingElement();
}
m_settingsFile->close();
return true;
}
void
Settings::save() const
bool
Settings::load()
{
QDomDocument doc("root");
if ( m_settingsFile->open( QFile::ReadOnly ) == false )
{
vlmcWarning() << "Failed to open settings file" << m_settingsFile->fileName();
return false;
}
if ( doc.setContent( m_settingsFile ) == false )
{
vlmcWarning() << "Failed to load settings file" << m_settingsFile->fileName();
return false;
}
bool res = load( doc );
m_settingsFile->close();
return res;
}
bool
Settings::save()
{
if ( m_settingsFile == NULL )
return ;
return false;
QByteArray settingsContent;
QXmlStreamWriter streamWriter( &settingsContent );
streamWriter.setAutoFormatting( true );
......@@ -156,6 +164,7 @@ Settings::save() const
m_settingsFile->open( QFile::WriteOnly );
m_settingsFile->write( settingsContent );
m_settingsFile->close();
return true;
}
bool
......
......@@ -25,6 +25,7 @@
#include "Main/Core.h"
#include "Project/Project.h"
#include "Project/ILoadSave.h"
#include "SettingValue.h"
#include <QString>
......@@ -108,7 +109,7 @@ class QDomElement;
VLMC_CREATE_PROJECT_VAR( SettingValue::String, key, defaultValue, "", "", SettingValue::Private )
class Settings
class Settings : public ILoadSave
{
public:
typedef QList<SettingValue*> SettingList;
......@@ -121,10 +122,14 @@ class Settings
SettingValue* createVar( SettingValue::Type type, const QString &key, const QVariant &defaultValue, const char *name, const char *desc, SettingValue::Flags flags );
SettingList group( const QString &groupName ) const;
bool load();
void save() const;
void save( QXmlStreamWriter& project ) const;
bool save();
bool save( QXmlStreamWriter& project );
bool watchValue( const QString &key, QObject* receiver, const char *method, Qt::ConnectionType cType = Qt::AutoConnection );
void setSettingsFile( const QString& settingsFile );
private:
bool load( const QDomDocument& document );
private:
SettingMap m_settings;
mutable QReadWriteLock m_rwLock;
......
......@@ -235,12 +235,12 @@ MainWorkflow::getClipHelper( const QUuid &uuid, unsigned int trackId,
/**
* \warning The mainworkflow is expected to be already cleared by the ProjectManager
*/
void
MainWorkflow::loadProject( const QDomElement &root )
bool
MainWorkflow::load(const QDomDocument& root )
{
QDomElement project = root.firstChildElement( "workflow" );
if ( project.isNull() == true )
return ;
return false;
QDomElement elem = project.firstChildElement();
......@@ -252,14 +252,14 @@ MainWorkflow::loadProject( const QDomElement &root )
if ( ok == false )
{
vlmcWarning() << "Invalid track number in project file";
return ;
return false;
}
Workflow::TrackType type;
int utype = elem.attribute( "type" ).toInt( &ok );
if ( ok == false || (utype < 0 && utype >= Workflow::NbTrackType ) )
{
vlmcWarning() << "Invalid track type";
return ;
return false;
}
type = static_cast<Workflow::TrackType>( utype );
......@@ -287,7 +287,7 @@ MainWorkflow::loadProject( const QDomElement &root )
if ( uuid.isEmpty() == true || startFrame.isEmpty() == true )
{
vlmcWarning() << "Invalid clip node";
return ;
return false;
}
Clip* c = Project::getInstance()->library()->clip( uuid );
......@@ -304,10 +304,11 @@ MainWorkflow::loadProject( const QDomElement &root )
}
elem = elem.nextSiblingElement();
}
return true;
}
void
MainWorkflow::saveProject( QXmlStreamWriter& project ) const
bool
MainWorkflow::save( QXmlStreamWriter& project )
{
project.writeStartElement( "workflow" );
for ( unsigned int i = 0; i < Workflow::NbTrackType; ++i )
......@@ -315,6 +316,7 @@ MainWorkflow::saveProject( QXmlStreamWriter& project ) const
m_tracks[i]->save( project );
}
project.writeEndElement();
return true;
}
void
......
......@@ -26,6 +26,7 @@
#include "EffectsEngine/EffectsEngine.h"
#include <QXmlStreamWriter>
#include "Project/ILoadSave.h"
#include "Types.h"
class Clip;
......@@ -52,7 +53,7 @@ class QReadWriteLock;
/**
* \class Represent the Timeline backend.
*/
class MainWorkflow : public QObject
class MainWorkflow : public QObject, public ILoadSave
{
Q_OBJECT
......@@ -280,6 +281,9 @@ class MainWorkflow : public QObject
ClipHelper* getClipHelper( const QUuid& uuid, unsigned int trackId,
Workflow::TrackType trackType );
bool load( const QDomDocument& project );
bool save( QXmlStreamWriter& project );
private:
/// Pre-filled buffer used when there's nothing to render
Workflow::Frame *m_blackOutput;
......@@ -323,18 +327,6 @@ class MainWorkflow : public QObject
void tracksEndReached();
public slots:
/**
* \brief load a project based on a QDomElement
*
* \param project The project node to load.
*/
void loadProject( const QDomElement& project );
/**
* \brief Save the project on a XML stream.
*
* \param project The XML stream representing the project
*/
void saveProject( QXmlStreamWriter& project ) const;
/**
* \brief Clear the workflow.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment