Exemplo n.º 1
0
void	CDocument::LoadFromURL( const std::string& inURL, std::function<void(CDocument*)> inCompletionBlock )
{
	if( mLoaded )
	{
		inCompletionBlock( this );
		return;
	}
	
	mLoadCompletionBlocks.push_back( inCompletionBlock );
	
	if( mLoading )	// We'll call you, too, once we have finished loading.
		return;
	
	mLoading = true;
	
	size_t			slashOffset = inURL.rfind( '/' );
	if( slashOffset == std::string::npos )
		slashOffset = 0;
	mURL = inURL.substr(0,slashOffset);
	mMediaCache.SetURL( mURL );
	slashOffset = mURL.rfind( '/' );
	if( slashOffset == std::string::npos )
		slashOffset = 0;
	mName = mURL.substr(slashOffset+1,std::string::npos);
	slashOffset = mName.rfind( '.' );
	if( slashOffset == std::string::npos )
		slashOffset = 0;
	mName = mName.substr(0,slashOffset);
	
	CURLRequest		request( inURL );
	CURLConnection::SendRequestWithCompletionHandler( request, [inURL,this](CURLResponse inResponse, const char* inData, size_t inDataLength)
	{
		if( inURL.find("file://") != 0 )	// Not a local file?
			SetWriteProtected(true);		// Can't write changes to it to disk.
		
		CAutoreleasePool			pool;
		tinyxml2::XMLDocument		document;
		
		if( tinyxml2::XML_SUCCESS == document.Parse( inData, inDataLength ) )
		{
			//document.Print();
			
			tinyxml2::XMLElement	*	root = document.RootElement();
			
			// Load read/written version numbers so we can conditionally react to them:
			mCreatedByVersion.clear();
			CTinyXMLUtils::GetStringNamed( root, "createdByVersion", mCreatedByVersion );
			mLastCompactedVersion.clear();
			CTinyXMLUtils::GetStringNamed( root, "lastCompactedVersion", mLastCompactedVersion );
			mFirstEditedVersion.clear();
			CTinyXMLUtils::GetStringNamed( root, "firstEditedVersion", mFirstEditedVersion );
			mLastEditedVersion.clear();
			CTinyXMLUtils::GetStringNamed( root, "lastEditedVersion", mLastEditedVersion );
			
			mUserLevel = CTinyXMLUtils::GetIntNamed( root, "userLevel", 5 );
			mPrivateAccess = CTinyXMLUtils::GetBoolNamed( root, "privateAccess", false );
			mCantPeek = CTinyXMLUtils::GetBoolNamed( root, "cantPeek", false );

			mMediaCache.LoadStandardResources();
			
			// Load media table of this document so others can access it: (ICONs, PICTs, CURSs and SNDs)
			// Load style table so others can access it:
			mMediaCache.LoadMediaTableFromElementAsBuiltIn( root, false );	// Load media from this stack.
			
			LoadUserPropertiesFromElement( root );

			mScript.clear();
			CTinyXMLUtils::GetStringNamed( root, "script", mScript );
			
			// Load stacks:
			tinyxml2::XMLElement	*	currStackElem = root->FirstChildElement( "stack" );
			
			while( currStackElem )
			{
				std::string		fileName( currStackElem->Attribute("file") );
				std::string		stackURL = mURL;
				if( stackURL[stackURL.length()-1] != '/' )
					stackURL.append( 1, '/' );
				stackURL.append( fileName );
				ObjectID		stackID = CTinyXMLUtils::GetLongLongAttributeNamed( currStackElem, "id" );
				const char*		theName = currStackElem->Attribute("name");
				const char*		theThumbnail = currStackElem->Attribute("thumbnail");
				
				CStack	*	theStack = NewStackWithURLIDNameForDocument( stackURL, stackID, (theName ? theName : ""), fileName, this );
				theStack->Autorelease();
				mStacks.push_back( theStack );
				
				if( theThumbnail )
					theStack->SetThumbnailName( theThumbnail );
				
				currStackElem = currStackElem->NextSiblingElement( "stack" );
			}

			// Load menus:
			tinyxml2::XMLElement	*	currMenuElem = root->FirstChildElement( "menu" );
			
			while( currMenuElem )
			{
				NewMenuWithElement( currMenuElem, EMenuDontMarkChanged );
				
				currMenuElem = currMenuElem->NextSiblingElement( "menu" );
			}
		}
		
		mChangeCount = 0;
		
		CallAllCompletionBlocks();
	} );
}