Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tproject.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/sceneproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/observer.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzfolders.h"
Toshihiro Shimizu 890ddd
#include "toonz/cleanupparameters.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
#include "tfilepath_io.h"
Toshihiro Shimizu 890ddd
#include "tconvert.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qfileinfo></qfileinfo>
Toshihiro Shimizu 890ddd
#include <qdir></qdir>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <fstream></fstream>
Toshihiro Shimizu 890ddd
#include <stdlib.h></stdlib.h>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace std;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* Version-related strings added to project files, in reversed chronological order */
Toshihiro Shimizu 890ddd
const std::wstring prjSuffix[4] = {L"_otprj", L"_prj63ml", L"_prj6", L"_prj"};
Toshihiro Shimizu 890ddd
const std::wstring xmlExt = L".xml";
Toshihiro Shimizu 890ddd
const int prjSuffixCount = 4;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
/*! Default inputs folder: is used to save all scanned immage.*/
Toshihiro Shimizu 890ddd
const string
Toshihiro Shimizu 890ddd
	TProject::Inputs = "inputs",
Toshihiro Shimizu 890ddd
	/*! Default drawings folder: is used to save all tlv and pli levels.*/
Toshihiro Shimizu 890ddd
	TProject::Drawings = "drawings",
Toshihiro Shimizu 890ddd
	/*! Default scenes folder: is used to save all scenes.*/
Toshihiro Shimizu 890ddd
	TProject::Scenes = "scenes",
Toshihiro Shimizu 890ddd
	/*! Default scripts folder: is used to save all the script.*/
Toshihiro Shimizu 890ddd
	TProject::Scripts = "scripts",
Toshihiro Shimizu 890ddd
	/*! Default extras folder: is used to save all imported images and levels not pli or tlv.*/
Toshihiro Shimizu 890ddd
	TProject::Extras = "extras",
Toshihiro Shimizu 890ddd
	/*! Default outputs folder: is used to save all rendered scenes.*/
Toshihiro Shimizu 890ddd
	TProject::Outputs = "outputs",
Toshihiro Shimizu 890ddd
	/*! Default palettes folder: is used for color design (色指定)*/
Toshihiro Shimizu 890ddd
	TProject::Palettes = "palettes";
Toshihiro Shimizu 890ddd
//! Default project name
Toshihiro Shimizu 890ddd
const TFilePath
Toshihiro Shimizu 890ddd
	TProject::SandboxProjectName("sandbox");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TProjectP currentProject;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// helper functions
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath makeRelative(TFilePath ref, TFilePath fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!fp.isAbsolute())
Toshihiro Shimizu 890ddd
		return fp;
Toshihiro Shimizu 890ddd
	TFilePath dots;
Toshihiro Shimizu 890ddd
	for (;;) {
Toshihiro Shimizu 890ddd
		if (ref.isAncestorOf(fp)) {
Toshihiro Shimizu 890ddd
			TFilePath relativePath = dots + (fp - ref);
Toshihiro Shimizu 890ddd
			return relativePath;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (ref.isRoot())
Toshihiro Shimizu 890ddd
			return fp;
Toshihiro Shimizu 890ddd
		ref = ref.getParentDir();
Toshihiro Shimizu 890ddd
		dots = dots + "..";
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath makeAbsolute(TFilePath ref, TFilePath fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fp.isAbsolute())
Toshihiro Shimizu 890ddd
		return fp;
Toshihiro Shimizu 890ddd
	const TFilePath twoDots("..");
Toshihiro Shimizu 890ddd
	while (twoDots.isAncestorOf(fp)) {
Toshihiro Shimizu 890ddd
		TFilePath refParent = ref.getParentDir();
Toshihiro Shimizu 890ddd
		if (refParent == TFilePath())
Toshihiro Shimizu 890ddd
			break; // non dovrebbe succedere
Toshihiro Shimizu 890ddd
		ref = refParent;
Toshihiro Shimizu 890ddd
		fp = fp - twoDots;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	fp = ref + fp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::StringVar currentProjectPath("CurrentProject", "");
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns the project suffix (ie anything beyond the last '_' included)
Toshihiro Shimizu 890ddd
//! of the passed file path.
Toshihiro Shimizu 890ddd
std::wstring getProjectSuffix(const TFilePath &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::wstring &name = path.getWideName();
Toshihiro Shimizu 890ddd
	int idx = name.find_last_of(L'_');
Toshihiro Shimizu 890ddd
	if (idx == string::npos)
Toshihiro Shimizu 890ddd
		return L"";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return name.substr(idx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! In case the supplied path has an old version suffix,
Toshihiro Shimizu 890ddd
//! this function updates it to the most recent; otherwise,
Toshihiro Shimizu 890ddd
//! it is left untouched.
Toshihiro Shimizu 890ddd
TFilePath getLatestVersionProjectPath(const TFilePath &path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::wstring &suffix = getProjectSuffix(path);
Toshihiro Shimizu 890ddd
	for (int i = 1; i < prjSuffixCount; ++i)
Toshihiro Shimizu 890ddd
		if (suffix == prjSuffix[i]) {
Toshihiro Shimizu 890ddd
			const std::wstring &name = path.getWideName();
Toshihiro Shimizu 890ddd
			int pos = name.size() - suffix.size();
Toshihiro Shimizu 890ddd
			return path.withName(path.getWideName().substr(0, pos) + prjSuffix[0]);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return path;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Return project path with right suffix.
Toshihiro Shimizu 890ddd
		VERSION 6.0: _prj6.xml;
Toshihiro Shimizu 890ddd
		PRECEDENT VERSION: _prj.xml.
Toshihiro Shimizu 890ddd
		If in \b folder exists ONLY old version project path return old version path;
Toshihiro Shimizu 890ddd
		otherwise return 6.0 version project path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath searchProjectPath(TFilePath folder)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(folder.isAbsolute());
Toshihiro Shimizu 890ddd
	wstring projectName = folder.getWideName();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Search for the first available project file, starting from the most recent.
Toshihiro Shimizu 890ddd
	TFilePath projectPath;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < prjSuffixCount; ++i) {
Toshihiro Shimizu 890ddd
		projectPath = folder + TFilePath(projectName + prjSuffix[i] + xmlExt);
Toshihiro Shimizu 890ddd
		if (TFileStatus(projectPath).doesExist())
Toshihiro Shimizu 890ddd
			return projectPath;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If none exist in the folder, build the name with the most recent suffix
Toshihiro Shimizu 890ddd
	return folder + TFilePath(projectName + prjSuffix[0] + xmlExt);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool isFolderUnderVersionControl(const TFilePath &folderPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QDir dir(QString::fromStdWString(folderPath.getWideString()));
Toshihiro Shimizu 890ddd
	return dir.entryList(QDir::AllDirs | QDir::Hidden).contains(".svn");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void hideOlderProjectFiles(const TFilePath &folderPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	const std::wstring &name = folderPath.getWideName();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath path;
Toshihiro Shimizu 890ddd
	for (int i = 1; i < prjSuffixCount; ++i) {
Toshihiro Shimizu 890ddd
		path = folderPath + (name + prjSuffix[i] + xmlExt);
Toshihiro Shimizu 890ddd
		if (TFileStatus(path).doesExist())
Toshihiro Shimizu 890ddd
			TSystem::renameFile(path.withType("xml_"), path);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// TProject
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \class TProject tproject.h
Toshihiro Shimizu 890ddd
	\brief Define and handle a toonz project.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
    A toonz project is identified by a project name that matches a folder with the same name in the project root.\n
Toshihiro Shimizu 890ddd
	The project folder can contains saveral other folders. 
Toshihiro Shimizu 890ddd
	By default, five folders are created: Inputs, Drawings, Scenes, Extras and Outputs. 
Toshihiro Shimizu 890ddd
	Each of this folders can be renamed using the setFolder(string name, TFilePath path) method.
Toshihiro Shimizu 890ddd
	Usually, the \b name parameter is choosen from inputs, drawings, scenes, extras and outputs;
Toshihiro Shimizu 890ddd
	the \b path parameter contains the folder that can have a different name from them.
Toshihiro Shimizu 890ddd
	All association between names and folder are kept in a mapping.\n
Toshihiro Shimizu 890ddd
	A folder of a project can be constant or scene dependent. A constant folder is used by 
Toshihiro Shimizu 890ddd
	every scene created in the project to save or load data. A scene dependent folder is used only by the scene 
Toshihiro Shimizu 890ddd
	from wich the folder depends. A scene dependent folder contains the string "$scene" in its path. 
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. 
Toshihiro Shimizu 890ddd
	Scene path: "...\\prodA\\episode1\\scenes\\sceneA.tzn"
Toshihiro Shimizu 890ddd
	Drawings scene dependent folder: "...\\prodA\\episode1\\$scene\\drawings"
Toshihiro Shimizu 890ddd
	Drawings folder path: "...\\prodA\\episode1\\SceneA\\drawings"
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
	\n\n
Toshihiro Shimizu 890ddd
	By default, from the toonz installation, exist allways a toonz project called "sandbox".
Toshihiro Shimizu 890ddd
	\see TProjectManager, TSceneProperties.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn TFilePath TProject::getName() const
Toshihiro Shimizu 890ddd
	Returns the name of the project.
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. "prodA\\episode1"
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn TFilePath TProject::getProjectPath() const
Toshihiro Shimizu 890ddd
	Returns the path of the project. It is an absolute path.
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. "prodA\\episode1" -> "...\\prodA\\episode1\\episode1_prj.xml"
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn TFilePath TProject::getProjectFolder() const
Toshihiro Shimizu 890ddd
	Returns the project folder path. It is an absolute path.
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. "prodA\\episode1" -> "...\\prodA\\episode1\\"
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn const TSceneProperties &TProject::getSceneProperties() const
Toshihiro Shimizu 890ddd
    Returns the scene properties of the project.
Toshihiro Shimizu 890ddd
    \see TSceneProperties
Toshihiro Shimizu 890ddd
	*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn void TProject::save()
Toshihiro Shimizu 890ddd
	Saves the project.
Toshihiro Shimizu 890ddd
	Is equvalent to save(getProjectPath()).
Toshihiro Shimizu 890ddd
	The project is saved as a xml file.\n
Toshihiro Shimizu 890ddd
	Uses TProjectManager and TOStream.
Toshihiro Shimizu 890ddd
	\note Exceptions can be thrown.
Toshihiro Shimizu 890ddd
	\see TProjectManager and TOStream.
Toshihiro Shimizu 890ddd
  */
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TProject::TProject()
Toshihiro Shimizu 890ddd
	: m_name(), m_path(), m_sprop(new TSceneProperties())
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TProject::~TProject()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	delete m_sprop;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Associates the \b name to the specified \b path.
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. setFolder(TProject::Drawings, TFilePath("C:\\temp\\drawings"))
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
	Usually, the \b name parameter is choosen from inputs, drawings, scenes, extras and outputs;
Toshihiro Shimizu 890ddd
	the \b path contains the folder that can have a different name from them.
Toshihiro Shimizu 890ddd
	Every association between names and paths is contained in a mapping.
Toshihiro Shimizu 890ddd
	\note Not absolute path are thought relative to the project folder.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TProject::setFolder(string name, TFilePath path)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<string, tfilepath="">::iterator it;</string,>
Toshihiro Shimizu 890ddd
	it = m_folders.find(name);
Toshihiro Shimizu 890ddd
	if (it == m_folders.end()) {
Toshihiro Shimizu 890ddd
		m_folderNames.push_back(name);
Toshihiro Shimizu 890ddd
		m_folders[name] = path;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		it->second = path;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Create a folder named with \b name.
Toshihiro Shimizu 890ddd
	Call the setFolder(name,TFilePath(name)) method.\n
Toshihiro Shimizu 890ddd
	e.g. setFolder(TProject::Drawings) is equivalent to setFolder(TProject::Drawings, TFilePath("drawings"))\n
Toshihiro Shimizu 890ddd
	The resulting is "..\\projectFolder\\drawings"
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TProject::setFolder(string name)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	setFolder(name, TFilePath(name));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the path of the folder named with \b name.\n
Toshihiro Shimizu 890ddd
	Returns TFilePath() if there isn't a folder named with \b name.
Toshihiro Shimizu 890ddd
	\note The returned path could be a relative path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProject::getFolder(string name) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<string, tfilepath="">::const_iterator it;</string,>
Toshihiro Shimizu 890ddd
	it = m_folders.find(name);
Toshihiro Shimizu 890ddd
	if (it != m_folders.end())
Toshihiro Shimizu 890ddd
		return it->second;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return TFilePath();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the path of the Scene folder.\n
Toshihiro Shimizu 890ddd
	The Scene folder contains all the saved scene. The returned path is an absolute path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProject::getScenesPath() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath scenes = getFolder(Scenes);
Toshihiro Shimizu 890ddd
	return makeAbsolute(getProjectFolder(), scenes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the path of the folder indexed with \b index.\n
Toshihiro Shimizu 890ddd
	Returns TFilePath() if there isn't a folder indexed with \b index.
Toshihiro Shimizu 890ddd
	\note The returned path could be a relative path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProject::getFolder(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (0 <= index && index < (int)m_folderNames.size())
Toshihiro Shimizu 890ddd
		return getFolder(m_folderNames[index]);
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return TFilePath();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns true if the folder indexed with \b index isn't scene dependent.\n
Toshihiro Shimizu 890ddd
	A scene dependent folder is a folder containing "$scene" in its path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool TProject::isConstantFolder(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath fp = getFolder(index);
Toshihiro Shimizu 890ddd
	return fp.getWideString().find(L"$scene") == wstring::npos;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//! Returns the number of the folders contained in the project folder.
Toshihiro Shimizu 890ddd
int TProject::getFolderCount() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_folders.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
//! Returns the name of the folder indexed with \b index.
Toshihiro Shimizu 890ddd
string TProject::getFolderName(int index) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (0 <= index && index < (int)m_folderNames.size())
Toshihiro Shimizu 890ddd
		return m_folderNames[index];
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return "";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Returns the index of the folder named with \b folderName.\n
Toshihiro Shimizu 890ddd
	If a folder named with \b folderName doesn't exist, return -1.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int TProject::getFolderIndex(string name) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::vector<string>::const_iterator it;</string>
Toshihiro Shimizu 890ddd
	it = std::find(
Toshihiro Shimizu 890ddd
		m_folderNames.begin(),
Toshihiro Shimizu 890ddd
		m_folderNames.end(),
Toshihiro Shimizu 890ddd
		name);
Toshihiro Shimizu 890ddd
	if (it == m_folderNames.end())
Toshihiro Shimizu 890ddd
		return -1;
Toshihiro Shimizu 890ddd
	return std::distance(it, m_folderNames.begin());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns true if this project is the current project.
Toshihiro Shimizu 890ddd
	Uses \b TProjectManager.
Toshihiro Shimizu 890ddd
	\see TProjectManager
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool TProject::isCurrent() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath currentProjectPath =
Toshihiro Shimizu 890ddd
		TProjectManager::instance()->getCurrentProjectPath();
Toshihiro Shimizu 890ddd
	if (getProjectPath() == currentProjectPath)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return getLatestVersionProjectPath(currentProjectPath) ==
Toshihiro Shimizu 890ddd
			   getLatestVersionProjectPath(getProjectPath());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Set the scene properties \b sprop to the project.
Toshihiro Shimizu 890ddd
    \see TSceneProperties*/
Toshihiro Shimizu 890ddd
void TProject::setSceneProperties(const TSceneProperties &sprop)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_sprop->assign(&sprop);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the absolute path of \b fp.
Toshihiro Shimizu 890ddd
	If \b fp contains "$project", replaces it with the name of the project.
Toshihiro Shimizu 890ddd
	\note the returned path can contain "$scene"
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProject::decode(TFilePath fp) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (;;) {
Toshihiro Shimizu 890ddd
		wstring fpstr = fp.getWideString();
Toshihiro Shimizu 890ddd
		int j = fpstr.find(L"$project");
Toshihiro Shimizu 890ddd
		if (j == (int)wstring::npos)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		fpstr.replace(j, 8, getName().getWideString());
Toshihiro Shimizu 890ddd
		fp = TFilePath(fpstr);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return makeAbsolute(getProjectFolder(), fp);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TProject::setUseScenePath(string folderName, bool on)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_useScenePathFlags[folderName] = on;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TProject::getUseScenePath(string folderName) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::map<string, bool="">::const_iterator it;</string,>
Toshihiro Shimizu 890ddd
	it = m_useScenePathFlags.find(folderName);
Toshihiro Shimizu 890ddd
	return it != m_useScenePathFlags.end() ? it->second : false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the index of the folder specified in the path \b folderDir.
Toshihiro Shimizu 890ddd
	Returns -1 if \b folderDir isn't a folder of the project.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
int TProject::getFolderIndexFromPath(const TFilePath &folderDir)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath scenePath = decode(getFolder(Scenes));
Toshihiro Shimizu 890ddd
	bool sceneDependentScenePath = false;
Toshihiro Shimizu 890ddd
	if (scenePath.getName().find("$scene") != string::npos) {
Toshihiro Shimizu 890ddd
		scenePath = scenePath.getParentDir();
Toshihiro Shimizu 890ddd
		sceneDependentScenePath = true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	int folderIndex;
Toshihiro Shimizu 890ddd
	for (folderIndex = 0; folderIndex < getFolderCount(); folderIndex++)
Toshihiro Shimizu 890ddd
		if (isConstantFolder(folderIndex)) {
Toshihiro Shimizu 890ddd
			TFilePath fp = decode(getFolder(folderIndex));
Toshihiro Shimizu 890ddd
			if (fp == folderDir)
Toshihiro Shimizu 890ddd
				return folderIndex;
Toshihiro Shimizu 890ddd
		} else {
Toshihiro Shimizu 890ddd
			TFilePath fp = decode(getFolder(folderIndex));
Toshihiro Shimizu 890ddd
			wstring a = fp.getWideString();
Toshihiro Shimizu 890ddd
			wstring b = folderDir.getWideString();
Toshihiro Shimizu 890ddd
			int alen = a.length();
Toshihiro Shimizu 890ddd
			int blen = b.length();
Toshihiro Shimizu 890ddd
			int i = a.find(L"$scene");
Toshihiro Shimizu 890ddd
			assert(i != (int)wstring::npos);
Toshihiro Shimizu 890ddd
			if (i == (int)wstring::npos)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			int j = i + 1;
Toshihiro Shimizu 890ddd
			while (j < alen && isalnum(a[j]))
Toshihiro Shimizu 890ddd
				j++;
Toshihiro Shimizu 890ddd
			// a.substr(i,j-i) == "$scenexxxx"
Toshihiro Shimizu 890ddd
			int k = j + blen - alen;
Toshihiro Shimizu 890ddd
			if (!(0 <= i && i < k && k <= blen))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			assert(i < blen);
Toshihiro Shimizu 890ddd
			if (i > 0 && a.substr(0, i) != b.substr(0, i))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			if (k < blen && (j >= alen || a.substr(j) != b.substr(k)))
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			wstring v = b.substr(i, k - i);
Toshihiro Shimizu 890ddd
			TFilePath scene(v + L".tnz");
Toshihiro Shimizu 890ddd
			if (sceneDependentScenePath)
Toshihiro Shimizu 890ddd
				scene = scenePath + scene.getWideName() + scene;
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				scene = scenePath + scene;
Toshihiro Shimizu 890ddd
			if (TFileStatus(scene).doesExist())
Toshihiro Shimizu 890ddd
				return folderIndex;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	return -1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the folder's name of the specified TFilePath \b folderDir.\n
Toshihiro Shimizu 890ddd
	Returns the empty string if \b folderDir isn't a folder of the project.*/
Toshihiro Shimizu 890ddd
wstring TProject::getFolderNameFromPath(const TFilePath &folderDir)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int index = getFolderIndexFromPath(folderDir);
Toshihiro Shimizu 890ddd
	if (index < 0)
Toshihiro Shimizu 890ddd
		return L"";
Toshihiro Shimizu 890ddd
	if (getFolder(index).isAbsolute())
Toshihiro Shimizu 890ddd
		return toWideString("+" + getFolderName(index));
Toshihiro Shimizu 890ddd
	else
Toshihiro Shimizu 890ddd
		return folderDir.getWideName();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Saves the project in the specified path.
Toshihiro Shimizu 890ddd
	The TfilePath fp must be an absolute path. The project is saved as a xml file.\n 
Toshihiro Shimizu 890ddd
	Uses TProjectManager and TOStream.
Toshihiro Shimizu 890ddd
	\note Exceptions can be thrown.
Toshihiro Shimizu 890ddd
	\see TProjectManager and TOStream.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool TProject::save(const TFilePath &projectPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(isAProjectPath(projectPath));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TProjectManager *pm = TProjectManager::instance();
Toshihiro Shimizu 890ddd
	m_name = pm->projectPathToProjectName(projectPath);
Toshihiro Shimizu 890ddd
	m_path = getLatestVersionProjectPath(projectPath);
Toshihiro Shimizu 890ddd
	TFilePath projectFolder = projectPath.getParentDir();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TFileStatus(projectFolder).doesExist()) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			TSystem::mkDir(projectFolder);
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath sceneFolder = decode(getFolder(TProject::Scenes));
Toshihiro Shimizu 890ddd
	TFilePath scenesDescPath = sceneFolder + "scenes.xml";
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFileStatus fs(projectPath);
Toshihiro Shimizu 890ddd
	if (fs.doesExist() && !fs.isWritable()) {
Toshihiro Shimizu 890ddd
		throw TSystemException(projectPath, "Cannot save the project settings. The file is read-only.");
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	TFileStatus fs2(scenesDescPath);
Toshihiro Shimizu 890ddd
	if (fs2.doesExist() && !fs2.isWritable()) {
Toshihiro Shimizu 890ddd
		throw TSystemException(projectPath, "Cannot save the project settings. The scenes file is read-only.");
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TOStream os(m_path);
Toshihiro Shimizu 890ddd
	os.openChild("project");
Toshihiro Shimizu 890ddd
	os.openChild("version");
Toshihiro Shimizu 890ddd
	os << 70 << 1;   // Standard version signature:
Toshihiro Shimizu 890ddd
	os.closeChild(); //   <major *="" 10="" number="" toonz="" version="">.<major advancement="" version=""></major></major>
Toshihiro Shimizu 890ddd
	os.openChild("folders");
Toshihiro Shimizu 890ddd
	int i = 0;
Toshihiro Shimizu 890ddd
	for (i = 0; i < getFolderCount(); i++) {
Toshihiro Shimizu 890ddd
		TFilePath folderRelativePath = getFolder(i);
Toshihiro Shimizu 890ddd
		if (folderRelativePath == TFilePath())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		std::map<string, string=""> attr;</string,>
Toshihiro Shimizu 890ddd
		string folderName = getFolderName(i);
Toshihiro Shimizu 890ddd
		attr["name"] = folderName;
Toshihiro Shimizu 890ddd
		attr["path"] = toString(folderRelativePath); // escape()
Toshihiro Shimizu 890ddd
		if (getUseScenePath(folderName))
Toshihiro Shimizu 890ddd
			attr["useScenePath"] = "yes";
Toshihiro Shimizu 890ddd
		os.openCloseChild("folder", attr);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	os.closeChild();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	os.openChild("sceneProperties");
Toshihiro Shimizu 890ddd
	getSceneProperties().saveData(os);
Toshihiro Shimizu 890ddd
	os.closeChild();
Toshihiro Shimizu 890ddd
	os.closeChild();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// crea (se necessario) le directory relative ai vari folder
Toshihiro Shimizu 890ddd
	for (i = 0; i < getFolderCount(); i++)
Toshihiro Shimizu 890ddd
		if (isConstantFolder(i)) {
Toshihiro Shimizu 890ddd
			TFilePath fp = getFolder(i);
Toshihiro Shimizu 890ddd
			if (fp == TFilePath())
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			fp = decode(fp);
Toshihiro Shimizu 890ddd
			// if(!fp.isAbsolute()) fp = projectFolder + fp;
Toshihiro Shimizu 890ddd
			if (!TFileStatus(fp).doesExist()) {
Toshihiro Shimizu 890ddd
				try {
Toshihiro Shimizu 890ddd
					TSystem::mkDir(fp);
Toshihiro Shimizu 890ddd
				} catch (...) {
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	/*-- +scenes だけでなく、全てのProject Folderにscenes.xmlを生成する --*/
Toshihiro Shimizu 890ddd
	std::vector<std::string> foldernames;</std::string>
Toshihiro Shimizu 890ddd
	pm->getFolderNames(foldernames);
Toshihiro Shimizu 890ddd
	for (int f = 0; f < foldernames.size(); f++) {
Toshihiro Shimizu 890ddd
		TFilePath folderpath = decode(getFolder(foldernames.at(f)));
Toshihiro Shimizu 890ddd
		if (folderpath.isEmpty())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		TFilePath xmlPath = folderpath + "scenes.xml";
Toshihiro Shimizu 890ddd
		TFileStatus xmlfs(xmlPath);
Toshihiro Shimizu 890ddd
		if (xmlfs.doesExist() && !xmlfs.isWritable())
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFilePath relativeProjectFolder = makeRelative(folderpath, m_path.getParentDir());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TOStream os2(xmlPath);
Toshihiro Shimizu 890ddd
		std::map<string, string=""> attr;</string,>
Toshihiro Shimizu 890ddd
		attr["type"] = "projectFolder";
Toshihiro Shimizu 890ddd
		os2.openChild("parentProject", attr);
Toshihiro Shimizu 890ddd
		os2 << relativeProjectFolder;
Toshihiro Shimizu 890ddd
		os2.closeChild();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//The project has been successfully saved. In case there are other
Toshihiro Shimizu 890ddd
	//project files from older Toonz project versions, those files are
Toshihiro Shimizu 890ddd
	//renamed so that older Toonz versions can no longer 'see' it.
Toshihiro Shimizu 890ddd
	if (!isFolderUnderVersionControl(projectFolder))
Toshihiro Shimizu 890ddd
		hideOlderProjectFiles(projectFolder);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TProject::save()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return save(m_path);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Loads the project specified in \b projectPath.\n
Toshihiro Shimizu 890ddd
	\b projectPath must be an absolute path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TProject::load(const TFilePath &projectPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(isAProjectPath(projectPath));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath latestProjectPath = getLatestVersionProjectPath(projectPath);
Toshihiro Shimizu 890ddd
	TFilePath inputProjectPath = searchProjectPath(projectPath.getParentDir());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TProjectManager *pm = TProjectManager::instance();
Toshihiro Shimizu 890ddd
	m_name = pm->projectPathToProjectName(latestProjectPath);
Toshihiro Shimizu 890ddd
	m_path = latestProjectPath;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_folderNames.clear();
Toshihiro Shimizu 890ddd
	m_folders.clear();
Toshihiro Shimizu 890ddd
	m_useScenePathFlags.clear();
Toshihiro Shimizu 890ddd
	delete m_sprop;
Toshihiro Shimizu 890ddd
	m_sprop = new TSceneProperties();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Read the project
Toshihiro Shimizu 890ddd
	TIStream is(inputProjectPath);
Toshihiro Shimizu 890ddd
	if (!is)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	string tagName;
Toshihiro Shimizu 890ddd
	if (!is.matchTag(tagName) || tagName != "project")
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	while (is.matchTag(tagName)) {
Toshihiro Shimizu 890ddd
		if (tagName == "folders") {
Toshihiro Shimizu 890ddd
			while (is.matchTag(tagName)) {
Toshihiro Shimizu 890ddd
				if (tagName == "folder") {
Toshihiro Shimizu 890ddd
					string name = is.getTagAttribute("name");
Toshihiro Shimizu 890ddd
					TFilePath path(is.getTagAttribute("path"));
Toshihiro Shimizu 890ddd
					setFolder(name, path);
Toshihiro Shimizu 890ddd
					string useScenePath = is.getTagAttribute("useScenePath");
Toshihiro Shimizu 890ddd
					setUseScenePath(name, useScenePath == "yes");
Toshihiro Shimizu 890ddd
				} else
Toshihiro Shimizu 890ddd
					throw TException("expected <folder>");</folder>
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			is.matchEndTag();
Toshihiro Shimizu 890ddd
		} else if (tagName == "version") {
Toshihiro Shimizu 890ddd
			int major, minor;
Toshihiro Shimizu 890ddd
			is >> major >> minor;
Toshihiro Shimizu 890ddd
			is.setVersion(VersionNumber(major, minor));
Toshihiro Shimizu 890ddd
			is.matchEndTag();
Toshihiro Shimizu 890ddd
		} else if (tagName == "sceneProperties") {
Toshihiro Shimizu 890ddd
			TSceneProperties sprop;
Toshihiro Shimizu 890ddd
			try {
Toshihiro Shimizu 890ddd
				sprop.loadData(is, true);
Toshihiro Shimizu 890ddd
			} catch (...) {
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			setSceneProperties(sprop);
Toshihiro Shimizu 890ddd
			is.matchEndTag();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns true if the specified path is a project path.\n
Toshihiro Shimizu 890ddd
	A project path must be absolute, must be an xml file and must have the name of the 
Toshihiro Shimizu 890ddd
	parent root with either one of the version-dependent suffixes "_prj*".\n
Toshihiro Shimizu 890ddd
	\code
Toshihiro Shimizu 890ddd
	e.g. "C:\\Toonz 5.2 stuff\\projects\\prodA\\episode1\\episode1_prj.xml" is a project path.
Toshihiro Shimizu 890ddd
	\endcode
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
bool TProject::isAProjectPath(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (fp.isAbsolute() && fp.getType() == "xml") {
Toshihiro Shimizu 890ddd
		const std::wstring &fpName = fp.getWideName();
Toshihiro Shimizu 890ddd
		const std::wstring &folderName = fp.getParentDir().getWideName();
Toshihiro Shimizu 890ddd
		for (int i = 0; i < prjSuffixCount; ++i)
Toshihiro Shimizu 890ddd
			if (fpName == (folderName + prjSuffix[i]))
Toshihiro Shimizu 890ddd
				return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
class SimpleProject : public TProject {
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
  SimpleProject() : TProject(TFilePath("___simpleProject")) {    
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===================================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// TProjectManager
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \class TProjectManager tproject.h
Toshihiro Shimizu 890ddd
	\brief Manages all toonz projects. The class provides all needed method to retrieve projects paths, names 
Toshihiro Shimizu 890ddd
	and folders.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	It is possible to handle more than one project root. 
Toshihiro Shimizu 890ddd
	The class mantains a container this purpose. All the projects roots must be setted by hand in the windows 
Toshihiro Shimizu 890ddd
	registery. By default, only one project root is created when toonz is installed.\n
Toshihiro Shimizu 890ddd
	The project root container can be updated using addProjectsRoot(const TFilePath &root), addDefaultProjectsRoot()
Toshihiro Shimizu 890ddd
	methods.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	The class mantains also information about the current project. The class provides all needed method to retrieve 
Toshihiro Shimizu 890ddd
	the current project path, name and folder.
Toshihiro Shimizu 890ddd
	\see TProject
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn bool TProjectManager::isTabModeEnabled() const
Toshihiro Shimizu 890ddd
	Returns the tab mode.
Toshihiro Shimizu 890ddd
	\note the tab mode is used for Tab Application
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \fn void TProjectManager::enableTabMode(bool tabMode)
Toshihiro Shimizu 890ddd
	Set the tab mode to the passed \b tabMode.
Toshihiro Shimizu 890ddd
	\note the tab mode is used for Tab Application
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TProjectManager::TProjectManager()
Toshihiro Shimizu 890ddd
	: m_tabMode(false), m_tabKidsMode(false)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TProjectManager::~TProjectManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the instance to the TProjectManager.\n
Toshihiro Shimizu 890ddd
	If an instance doesn't exist, creates one.*/
Toshihiro Shimizu 890ddd
TProjectManager *TProjectManager::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	static TProjectManager _instance;
Toshihiro Shimizu 890ddd
	return &_instance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Adds the specified folder \b fp in the projecs roots container.\n 
Toshihiro Shimizu 890ddd
	If \b fp is already contained in the container, the method does nothing.
Toshihiro Shimizu 890ddd
	\note \b fp must be a folder and not a file path.*/
Toshihiro Shimizu 890ddd
void TProjectManager::addProjectsRoot(const TFilePath &root)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//assert(TFileStatus(root).isDirectory());
Toshihiro Shimizu 890ddd
	if (std::find(m_projectsRoots.begin(), m_projectsRoots.end(), root) == m_projectsRoots.end())
Toshihiro Shimizu 890ddd
		m_projectsRoots.push_back(root);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Adds the specified folder \b fp in the version control projecs roots container.\n 
Toshihiro Shimizu 890ddd
	If \b fp is already contained in the container, the method does nothing.
Toshihiro Shimizu 890ddd
	\note \b fp must be a folder and not a file path.*/
Toshihiro Shimizu 890ddd
void TProjectManager::addSVNProjectsRoot(const TFilePath &root)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(TFileStatus(root).isDirectory());
Toshihiro Shimizu 890ddd
	if (std::find(m_svnProjectsRoots.begin(), m_svnProjectsRoots.end(), root) == m_svnProjectsRoots.end())
Toshihiro Shimizu 890ddd
		m_svnProjectsRoots.push_back(root);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TProjectManager::addDefaultProjectsRoot()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	addProjectsRoot(TEnv::getStuffDir() + "projects");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::getCurrentProjectRoot()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath currentProjectPath = getCurrentProjectPath();
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_projectsRoots.size(); i++)
Toshihiro Shimizu 890ddd
		if (m_projectsRoots[i].isAncestorOf(currentProjectPath))
Toshihiro Shimizu 890ddd
			return m_projectsRoots[i];
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_svnProjectsRoots.size(); i++)
Toshihiro Shimizu 890ddd
		if (m_svnProjectsRoots[i].isAncestorOf(currentProjectPath))
Toshihiro Shimizu 890ddd
			return m_svnProjectsRoots[i];
Toshihiro Shimizu 890ddd
	if (m_projectsRoots.empty())
Toshihiro Shimizu 890ddd
		addDefaultProjectsRoot(); // shouldn't be necessary
Toshihiro Shimizu 890ddd
	return m_projectsRoots[0];
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the name of the specified \b projectPath.
Toshihiro Shimizu 890ddd
	\note projectPath must be an absolute path.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::projectPathToProjectName(const TFilePath &projectPath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(projectPath.isAbsolute());
Toshihiro Shimizu 890ddd
	TFilePath projectFolder = projectPath.getParentDir();
Toshihiro Shimizu 890ddd
	if (m_projectsRoots.empty())
Toshihiro Shimizu 890ddd
		addDefaultProjectsRoot();
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_projectsRoots.size(); i++) {
Toshihiro Shimizu 890ddd
		if (m_projectsRoots[i].isAncestorOf(projectFolder))
Toshihiro Shimizu 890ddd
			return projectFolder - m_projectsRoots[i];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_svnProjectsRoots.size(); i++) {
Toshihiro Shimizu 890ddd
		if (m_svnProjectsRoots[i].isAncestorOf(projectFolder))
Toshihiro Shimizu 890ddd
			return projectFolder - m_svnProjectsRoots[i];
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	// non dovrei mai arrivare qui: il progetto non sta sotto un project root
Toshihiro Shimizu 890ddd
	return projectFolder.withoutParentDir();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns an absolute path of the specified \b projectName.\n
Toshihiro Shimizu 890ddd
	\note The returned project path is allways computed used the first project root in the container.*/
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::projectNameToProjectPath(const TFilePath &projectName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!TProject::isAProjectPath(projectName));
Toshihiro Shimizu 890ddd
	assert(!projectName.isAbsolute());
Toshihiro Shimizu 890ddd
	if (m_projectsRoots.empty())
Toshihiro Shimizu 890ddd
		addDefaultProjectsRoot();
Toshihiro Shimizu 890ddd
	if (projectName == TProject::SandboxProjectName)
Toshihiro Shimizu 890ddd
		return searchProjectPath(TEnv::getStuffDir() + projectName);
Toshihiro Shimizu 890ddd
	return searchProjectPath(m_projectsRoots[0] + projectName);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the absolute path of the project file respect to the specified \b projectFolder.\n
Toshihiro Shimizu 890ddd
	\note \b projectName must be an absolute path.*/
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::projectFolderToProjectPath(const TFilePath &projectFolder)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(projectFolder.isAbsolute());
Toshihiro Shimizu 890ddd
	return searchProjectPath(projectFolder);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the absolute path of the specified \b projectName only if the project already exist.\n
Toshihiro Shimizu 890ddd
	Returns TFilePath() if a project with the specified \b projectName doesn't exsist.\n
Toshihiro Shimizu 890ddd
	\note \b projectName must be a relative path.*/
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::getProjectPathByName(const TFilePath &projectName)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(!TProject::isAProjectPath(projectName));
Toshihiro Shimizu 890ddd
	assert(!projectName.isAbsolute());
Toshihiro Shimizu 890ddd
	//TFilePath relativeProjectPath = projectName + (projectName.getName() + projectPathSuffix);
Toshihiro Shimizu 890ddd
	if (m_projectsRoots.empty())
Toshihiro Shimizu 890ddd
		addDefaultProjectsRoot();
Toshihiro Shimizu 890ddd
	if (projectName == TProject::SandboxProjectName)
Toshihiro Shimizu 890ddd
		return searchProjectPath(TEnv::getStuffDir() + projectName);
Toshihiro Shimizu 890ddd
	int i, n = (int)m_projectsRoots.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i < n; i++) {
Toshihiro Shimizu 890ddd
		TFilePath projectPath = searchProjectPath(m_projectsRoots[i] + projectName);
Toshihiro Shimizu 890ddd
		assert(TProject::isAProjectPath(projectPath));
Toshihiro Shimizu 890ddd
		if (TFileStatus(projectPath).doesExist())
Toshihiro Shimizu 890ddd
			return projectPath;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 0; i < (int)m_svnProjectsRoots.size(); i++) {
Toshihiro Shimizu 890ddd
		TFilePath projectPath = searchProjectPath(m_svnProjectsRoots[i] + projectName);
Toshihiro Shimizu 890ddd
		assert(TProject::isAProjectPath(projectPath));
Toshihiro Shimizu 890ddd
		if (TFileStatus(projectPath).doesExist())
Toshihiro Shimizu 890ddd
			return projectPath;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return TFilePath();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Gets all project folder names and put them in the passed vector \b names.
Toshihiro Shimizu 890ddd
	\note All previous data contained in \b names are lost.*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TProjectManager::getFolderNames(std::vector<string> &names)</string>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	names.clear();
Toshihiro Shimizu 890ddd
	TFilePath fp = ToonzFolder::getProfileFolder() + "project_folders.txt";
Toshihiro Shimizu 890ddd
	try {
Toshihiro Shimizu 890ddd
		Tifstream is(fp);
Toshihiro Shimizu 890ddd
		if (is)
Toshihiro Shimizu 890ddd
			for (;;) {
Toshihiro Shimizu 890ddd
				char buffer[1024];
Toshihiro Shimizu 890ddd
				is.getline(buffer, sizeof(buffer));
Toshihiro Shimizu 890ddd
				if (is.eof())
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				char *s = buffer;
Toshihiro Shimizu 890ddd
				while (*s == ' ' || *s == '\t')
Toshihiro Shimizu 890ddd
					s++; // skips blanks
Toshihiro Shimizu 890ddd
				char *t = s;
Toshihiro Shimizu 890ddd
				while (*t && *t != '\r' && *t != '\n')
Toshihiro Shimizu 890ddd
					t++; // reads up to end of line
Toshihiro Shimizu 890ddd
				while (t > s && (t[-1] == ' ' || t[-1] == '\t'))
Toshihiro Shimizu 890ddd
					t--; // remove trailing blanks
Toshihiro Shimizu 890ddd
				t[0] = '\0';
Toshihiro Shimizu 890ddd
				if (s[0])
Toshihiro Shimizu 890ddd
					names.push_back(string(s));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
	} catch (...) {
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	const string stdNames[] = {
Toshihiro Shimizu 890ddd
		TProject::Inputs, TProject::Drawings, TProject::Scenes,
Toshihiro Shimizu 890ddd
		TProject::Extras, TProject::Outputs, TProject::Scripts};
Toshihiro Shimizu 890ddd
	for (int i = 0; i < (int)tArrayCount(stdNames); i++) {
Toshihiro Shimizu 890ddd
		string name = stdNames[i];
Toshihiro Shimizu 890ddd
		// se il nome non e' gia' stato inserito lo aggiungo
Toshihiro Shimizu 890ddd
		if (std::find(names.begin(), names.end(), name) == names.end())
Toshihiro Shimizu 890ddd
			names.push_back(name);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Set the the path \b fp as current project path.\n
Toshihiro Shimizu 890ddd
	\b fp must be an absolute path.*/
Toshihiro Shimizu 890ddd
void TProjectManager::setCurrentProjectPath(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(TProject::isAProjectPath(fp));
Toshihiro Shimizu 890ddd
	currentProjectPath = toString(fp.getWideString());
Toshihiro Shimizu 890ddd
	currentProject = TProjectP();
Toshihiro Shimizu 890ddd
	notifyListeners();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the current project path.\n
Toshihiro Shimizu 890ddd
	The project path, usually, is setted in key registry. If a current project path isn't setted, 
Toshihiro Shimizu 890ddd
	TProject::SandboxProjectName is setted as current project.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::getCurrentProjectPath()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath fp(currentProjectPath);
Toshihiro Shimizu 890ddd
	if (fp == TFilePath())
Toshihiro Shimizu 890ddd
		fp = projectNameToProjectPath(TProject::SandboxProjectName);
Toshihiro Shimizu 890ddd
	if (!TProject::isAProjectPath(fp)) {
Toshihiro Shimizu 890ddd
		// in Toonz 5.1 e precedenti era un project name
Toshihiro Shimizu 890ddd
		if (!fp.isAbsolute())
Toshihiro Shimizu 890ddd
			fp = getProjectPathByName(fp);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	fp = searchProjectPath(fp.getParentDir());
Toshihiro Shimizu 890ddd
	if (!TFileStatus(fp).doesExist())
Toshihiro Shimizu 890ddd
		fp = projectNameToProjectPath(TProject::SandboxProjectName);
Toshihiro Shimizu 890ddd
	fp = getLatestVersionProjectPath(fp);
Toshihiro Shimizu 890ddd
	string s = toString(fp);
Toshihiro Shimizu 890ddd
	if (s != (string)currentProjectPath)
Toshihiro Shimizu 890ddd
		currentProjectPath = s;
Toshihiro Shimizu 890ddd
	return fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the current TProject.\n
Toshihiro Shimizu 890ddd
	If a current TProject() doesn't exist, load the project in the the current project path. 
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
TProjectP TProjectManager::getCurrentProject()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (currentProject.getPointer() == 0) {
Toshihiro Shimizu 890ddd
		TFilePath fp = getCurrentProjectPath();
Toshihiro Shimizu 890ddd
		assert(TProject::isAProjectPath(fp));
Toshihiro Shimizu 890ddd
		currentProject = new TProject();
Toshihiro Shimizu 890ddd
		currentProject->load(fp);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return currentProject;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Returns the TProjectP in which the specified \b scenePath is saved.\n
Toshihiro Shimizu 890ddd
	Returns 0 if \b scenePath isn't a valid scene, or isn't saved in a valid folder of a project root.
Toshihiro Shimizu 890ddd
	\note \b scenePath must be an absolute path.\n
Toshihiro Shimizu 890ddd
	Creates a new TProject. The caller gets ownership.*/
Toshihiro Shimizu 890ddd
TProjectP TProjectManager::loadSceneProject(const TFilePath &scenePath)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	// cerca il file scenes.xml nella stessa directory della scena
Toshihiro Shimizu 890ddd
	// oppure in una
Toshihiro Shimizu 890ddd
	// directory superiore
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath folder = scenePath.getParentDir();
Toshihiro Shimizu 890ddd
	TFilePath sceneDesc;
Toshihiro Shimizu 890ddd
	bool found = true;
Toshihiro Shimizu 890ddd
	for (;;) {
Toshihiro Shimizu 890ddd
		sceneDesc = folder + "scenes.xml";
Toshihiro Shimizu 890ddd
		if (TFileStatus(sceneDesc).doesExist())
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		if (folder.isRoot()) {
Toshihiro Shimizu 890ddd
			found = false;
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		folder = folder.getParentDir();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// legge il path (o il nome) del progetto
Toshihiro Shimizu 890ddd
	TFilePath projectPath;
Toshihiro Shimizu 890ddd
	if (found) {
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			TIStream is(sceneDesc);
Toshihiro Shimizu 890ddd
			string tagName;
Toshihiro Shimizu 890ddd
			is.matchTag(tagName);
Toshihiro Shimizu 890ddd
			string type = is.getTagAttribute("type");
Toshihiro Shimizu 890ddd
			TFilePath projectFolderPath;
Toshihiro Shimizu 890ddd
			is >> projectFolderPath;
Toshihiro Shimizu 890ddd
			if (type == "") {
Toshihiro Shimizu 890ddd
				projectFolderPath = TFilePath("..");
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
			is.matchEndTag();
Toshihiro Shimizu 890ddd
			projectPath = makeAbsolute(folder, projectFolderPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TFilePath path;
Toshihiro Shimizu 890ddd
			for (int i = 0; i < prjSuffixCount; ++i) {
Toshihiro Shimizu 890ddd
				path = projectPath + (projectPath.getWideName() + prjSuffix[i] + xmlExt);
Toshihiro Shimizu 890ddd
				if (TFileStatus(path).doesExist())
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			projectPath = path;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (projectPath == TFilePath())
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
	} else
Toshihiro Shimizu 890ddd
		projectPath = getSandboxProjectPath();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!TProject::isAProjectPath(projectPath)) {
Toshihiro Shimizu 890ddd
		// in Toonz 5.1 e precedenti era un project name
Toshihiro Shimizu 890ddd
		if (!projectPath.isAbsolute())
Toshihiro Shimizu 890ddd
			projectPath = getProjectPathByName(projectPath);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			return 0;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (!TFileStatus(projectPath).doesExist())
Toshihiro Shimizu 890ddd
		return 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TProject *project = new TProject();
Toshihiro Shimizu 890ddd
	project->load(projectPath);
Toshihiro Shimizu 890ddd
	return project;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TProjectManager::notifyListeners()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (std::set<listener *="">::iterator i =</listener>
Toshihiro Shimizu 890ddd
			 m_listeners.begin();
Toshihiro Shimizu 890ddd
		 i != m_listeners.end();
Toshihiro Shimizu 890ddd
		 ++i)
Toshihiro Shimizu 890ddd
		(*i)->onProjectSwitched();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TProjectManager::notifyProjectChanged()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (std::set<listener *="">::iterator i =</listener>
Toshihiro Shimizu 890ddd
			 m_listeners.begin();
Toshihiro Shimizu 890ddd
		 i != m_listeners.end();
Toshihiro Shimizu 890ddd
		 ++i)
Toshihiro Shimizu 890ddd
		(*i)->onProjectChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Adds \b listener to the listners container.*/
Toshihiro Shimizu 890ddd
void TProjectManager::addListener(Listener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_listeners.insert(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Removes \b listener from the listners container.*/
Toshihiro Shimizu 890ddd
void TProjectManager::removeListener(Listener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_listeners.erase(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Initializes the specified \b scene using the TSceneProperties of the current project.\n
Toshihiro Shimizu 890ddd
	\see TSceneProperties
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
void TProjectManager::initializeScene(ToonzScene *scene)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TProject *project = scene->getProject();
Toshihiro Shimizu 890ddd
	TSceneProperties *sprop = scene->getProperties();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFilePath currentProjectPath = getCurrentProjectPath();
Toshihiro Shimizu 890ddd
	project->load(currentProjectPath);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	sprop->assign(&project->getSceneProperties());
Toshihiro Shimizu 890ddd
	CleanupParameters::GlobalParameters.assign(project->getSceneProperties().getCleanupParameters());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//scene->setProject(this);
Toshihiro Shimizu 890ddd
	scene->setUntitled();
Toshihiro Shimizu 890ddd
	sprop->cloneCamerasTo(scene->getTopXsheet()->getStageObjectTree());
Toshihiro Shimizu 890ddd
	sprop->onInitialize();
Toshihiro Shimizu 890ddd
	// scene->save(scene->getScenePath());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Saves the TSceneProperties of the specified scene in the current project.*/
Toshihiro Shimizu 890ddd
void TProjectManager::saveTemplate(ToonzScene *scene)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TSceneProperties props;
Toshihiro Shimizu 890ddd
	props.assign(scene->getProperties());
Toshihiro Shimizu 890ddd
	props.cloneCamerasFrom(scene->getXsheet()->getStageObjectTree());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TProjectP currentProject = getCurrentProject();
Toshihiro Shimizu 890ddd
	currentProject->setSceneProperties(props);
Toshihiro Shimizu 890ddd
	currentProject->save();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Creates the standard project folder "sandbox" if it doesn't exist.*/
Toshihiro Shimizu 890ddd
void TProjectManager::createSandboxIfNeeded()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath path = getSandboxProjectPath();
Toshihiro Shimizu 890ddd
	if (!TFileStatus(path).doesExist()) {
Toshihiro Shimizu 890ddd
		TProjectP project = createStandardProject();
Toshihiro Shimizu 890ddd
		try {
Toshihiro Shimizu 890ddd
			project->save(path);
Toshihiro Shimizu 890ddd
		} catch (...) {
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Create a standard project.\n
Toshihiro Shimizu 890ddd
	A standard project is a project containing the standard named and constant folder.
Toshihiro Shimizu 890ddd
	\see TProject. */
Toshihiro Shimizu 890ddd
TProjectP TProjectManager::createStandardProject()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TProject *project = new TProject();
Toshihiro Shimizu 890ddd
	// set default folders (+drawings, ecc.)
Toshihiro Shimizu 890ddd
	std::vector<std::string> names;</std::string>
Toshihiro Shimizu 890ddd
	getFolderNames(names);
Toshihiro Shimizu 890ddd
	std::vector<std::string>::iterator it;</std::string>
Toshihiro Shimizu 890ddd
	for (it = names.begin(); it != names.end(); ++it)
Toshihiro Shimizu 890ddd
		project->setFolder(*it);
Toshihiro Shimizu 890ddd
	return project;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Return the absolute path of the standard folder "sandbox".
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::getSandboxProjectFolder()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return getSandboxProjectPath().getParentDir();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//! Return the absolute path of the standard project "sandbox_prj6.xml" file.
Toshihiro Shimizu 890ddd
TFilePath TProjectManager::getSandboxProjectPath()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return getProjectPathByName(TProject::SandboxProjectName);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool TProjectManager::isProject(const TFilePath &projectFolder)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFilePath projectPath = projectFolderToProjectPath(projectFolder);
Toshihiro Shimizu 890ddd
	return TFileStatus(projectPath).doesExist();
Toshihiro Shimizu 890ddd
}