<commit_before>//
//  FileSystem.cpp
//  Chilli Source
//
//  Created by Scott Downie on 07/07/2011.
//  Copyright 2011 Tag Games. All rights reserved.
//

#include <ChilliSource/Core/File/FileSystem.h>
#include <ChilliSource/Core/String/StringUtils.h>
#include <ChilliSource/Core/Cryptographic/HashMD5.h>
#include <ChilliSource/Core/Cryptographic/HashCRC32.h>

#ifdef CS_TARGETPLATFORM_IOS
#include <ChilliSource/Backend/Platform/iOS/Core/File/FileSystem.h>
#endif

#ifdef CS_TARGETPLATFORM_ANDROID
#include <ChilliSource/Backend/Platform/Android/Core/File/FileSystem.h>
#endif

#ifdef CS_TARGETPLATFORM_WINDOWS
#include <ChilliSource/Backend/Platform/Windows/Core/File/FileSystem.h>
#endif

#include <algorithm>

namespace ChilliSource
{
    namespace Core
    {
        namespace
        {
            const std::string k_defaultPackageDLCDirectory = "DLC/";
        }
        CS_DEFINE_NAMEDTYPE(FileSystem);

        std::string FileSystem::s_resourceDirectory[3];
        f32 FileSystem::s_assetsDensity = 1.0f;

        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDeviceResourceDirectory()
        {
            return s_resourceDirectory[0];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDefaultDeviceResourceDirectory()
        {
            return s_resourceDirectory[1];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDefaultResourceDirectory()
        {
            return s_resourceDirectory[2];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        void FileSystem::SetResourceDirectories(const std::string& in_deviceDirectory, const std::string& in_defaultDeviceDirectory, const std::string& in_defaultDirectory, f32 in_assetsDensity)
        {
            s_resourceDirectory[0] = in_deviceDirectory;
            if (!in_deviceDirectory.empty())
                s_resourceDirectory[0] += "/";
            s_resourceDirectory[1] = in_defaultDeviceDirectory;
            if (!in_defaultDeviceDirectory.empty())
                s_resourceDirectory[1] += "/";
            s_resourceDirectory[2] = in_defaultDirectory;
            if (!in_defaultDirectory.empty())
                s_resourceDirectory[2] += "/";

            s_assetsDensity = in_assetsDensity;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        f32 FileSystem::GetDeviceResourcesDensity()
        {
            return s_assetsDensity;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        FileSystemUPtr FileSystem::Create()
        {
#ifdef CS_TARGETPLATFORM_IOS
            return FileSystemUPtr(new iOS::FileSystem());
#endif
#ifdef CS_TARGETPLATFORM_ANDROID
            return FileSystemUPtr(new Android::FileSystem());
#endif
#ifdef CS_TARGETPLATFORM_WINDOWS
            return FileSystemUPtr(new Windows::FileSystem());
#endif
            return nullptr;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        FileSystem::FileSystem()
            : m_packageDLCPath(k_defaultPackageDLCDirectory)
        {
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::ReadFile(StorageLocation in_storageLocation, const std::string& in_directory, std::string& out_contents) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_read);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->GetAll(out_contents);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::WriteFile(StorageLocation in_storageLocation, const std::string& in_directory, const std::string& in_contents) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_writeBinary);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->Write(in_contents);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::WriteFile(StorageLocation in_storageLocation, const std::string& in_directory, const s8* in_data, u32 in_dataSize) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_writeBinary);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->Write(in_data, (s32)in_dataSize);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::vector<std::string> FileSystem::GetFilePathsWithExtension(StorageLocation in_storageLocation, const std::string& in_directoryPath,  bool in_recursive, const std::string& in_extension) const
        {
            std::vector<std::string> filePaths = GetFilePaths(in_storageLocation, in_directoryPath, in_recursive);

            auto it = std::remove_if(filePaths.begin(), filePaths.end(), [&in_extension] (const std::string& in_path)
            {
                return (Core::StringUtils::EndsWith(in_path, "." + in_extension, true) == false);
            });

            filePaths.resize(it - filePaths.begin());

            return filePaths;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::vector<std::string> FileSystem::GetFilePathsWithFileName(StorageLocation in_storageLocation, const std::string& in_directoryPath,  bool in_recursive, const std::string& in_fileName) const
        {
            std::vector<std::string> filePaths = GetFilePaths(in_storageLocation, in_directoryPath, in_recursive);

            auto it = std::remove_if(filePaths.begin(), filePaths.end(), [&in_fileName] (const std::string& in_path)
            {
                return (Core::StringUtils::EndsWith(in_path, in_fileName, true) == false);
            });

            filePaths.resize(it - filePaths.begin());

            return filePaths;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        void FileSystem::SetPackageDLCPath(const std::string& in_directoryPath)
        {
            m_packageDLCPath = StringUtils::StandardisePath(in_directoryPath);
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		const std::string& FileSystem::GetPackageDLCPath() const
		{
			return m_packageDLCPath;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::string FileSystem::GetFileChecksumMD5(StorageLocation in_storageLocation, const std::string& in_filePath) const
        {
            const u32 k_chunkSize = 256;
            s8 data[k_chunkSize];

            HashMD5::MD5 hash;
            s32 size = k_chunkSize;

            FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filePath, FileMode::k_readBinary);

            if(!file->IsOpen() || file->IsBad())
            {
                return "";
            }

            while(size != 0)
            {
                size = file->ReadSome(data, k_chunkSize);
                hash.update(data, size);
            }

            hash.finalize();
            return hash.binarydigest();
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::string FileSystem::GetDirectoryChecksumMD5(StorageLocation in_storageLocation, const std::string& in_directoryPath) const
		{
        	std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directoryPath, true);

			//get a hash for each of the files.
            std::vector<std::string> hashes;
			for (const std::string& filename : filenames)
			{
                std::string fileHash = GetFileChecksumMD5(in_storageLocation, in_directoryPath + filename);
                std::string pathHash = HashMD5::GenerateBinaryHashCode(filename.c_str(), filename.length());
                hashes.push_back(fileHash);
                hashes.push_back(pathHash);
			}

			//sort the list so that ordering of
            std::sort(hashes.begin(), hashes.end());

			//build this into a hashable string
			std::string hashableDirectoryContents;
			for (const std::string& hash : hashes)
			{
				hashableDirectoryContents += hash;
			}

			//return the hash of this as the output
            std::string strOutput = 0;
			if (hashableDirectoryContents.length() > 0)
            {
				strOutput = HashMD5::GenerateBinaryHashCode(hashableDirectoryContents.c_str(), hashableDirectoryContents.length());
            }

			return strOutput;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetFileChecksumCRC32(StorageLocation in_storageLocation, const std::string& in_filePath) const
		{
			u32 output = 0;

			//open the file
			FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filePath, FileMode::k_readBinary);
			if (file != nullptr && file->IsOpen() == true && file->IsBad() == false)
			{
				//get the length of the file
				file->SeekG(0, SeekDir::k_end);
				s32 length = file->TellG();
				file->SeekG(0, SeekDir::k_beginning);

				//read contents of file
				s8* contents = new s8[length];
				file->Read(contents, length);

				//get the hash
				output = HashCRC32::GenerateHashCode(contents, length);
				CS_SAFEDELETE_ARRAY(contents);
			}
			return output;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetDirectoryChecksumCRC32(StorageLocation in_storageLocation, const std::string& in_directoryPath) const
		{
			std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directoryPath, true);

			//get a hash for each of the files.
            std::vector<u32> hashes;
			for (const std::string& filename : filenames)
			{
				u32 fileHash = GetFileChecksumCRC32(in_storageLocation, in_directoryPath + filename);
				u32 pathHash = HashCRC32::GenerateHashCode(filename.c_str(), filename.length());
				hashes.push_back(fileHash);
				hashes.push_back(pathHash);
			}

			//sort the list so that ordering of
			std::sort(hashes.begin(), hashes.end());

			//build this into a hashable string
			std::string hashableDirectoryContents;
			for (const u32& hash : hashes)
			{
				hashableDirectoryContents += ToString(hash);
			}

			//return the hash of this as the output
			u32 output = 0;
			if (hashableDirectoryContents.length() > 0)
				output = HashCRC32::GenerateHashCode(hashableDirectoryContents.c_str(), hashableDirectoryContents.length());
			return output;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetFileSize(StorageLocation in_storageLocation, const std::string& in_filepath) const
		{
			//open the file
			FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filepath, FileMode::k_readBinary);
			if (file->IsOpen() == true && file->IsBad() == false)
			{
				//get the length of the file
				file->SeekG(0, SeekDir::k_end);
				s32 dwLength = file->TellG();
				file->Close();
				return dwLength;
			}

			return 0;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetDirectorySize(StorageLocation in_storageLocation, const std::string& in_directory) const
		{
			std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directory, true);

            u32 totalSize = 0;
			for (const std::string& filename : filenames)
			{
				totalSize += GetFileSize(in_storageLocation, in_directory + "/" + filename);
			}

			return totalSize;
		}
        //-------------------------------------------------------
        //-------------------------------------------------------
        bool FileSystem::IsStorageLocationWritable(StorageLocation in_storageLocation) const
        {
            switch (in_storageLocation)
            {
                case StorageLocation::k_saveData:
                case StorageLocation::k_cache:
                case StorageLocation::k_DLC:
                case StorageLocation::k_root:
                    return true;
                default:
                    return false;
            }
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        const std::string* FileSystem::GetResourceDirectories() const
        {
            return s_resourceDirectory;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::IsWriteMode(Core::FileMode in_fileMode) const
        {
            switch (in_fileMode)
            {
                case Core::FileMode::k_write:
                case Core::FileMode::k_writeAppend:
                case Core::FileMode::k_writeAtEnd:
                case Core::FileMode::k_writeBinary:
                case Core::FileMode::k_writeBinaryAppend:
                case Core::FileMode::k_writeBinaryAtEnd:
                case Core::FileMode::k_writeBinaryTruncate:
                case Core::FileMode::k_writeTruncate:
                    return true;
                default:
                    return false;
            }
        }
    }
}
<commit_msg>Minor change.<commit_after>//
//  FileSystem.cpp
//  Chilli Source
//
//  Created by Scott Downie on 07/07/2011.
//  Copyright 2011 Tag Games. All rights reserved.
//

#include <ChilliSource/Core/File/FileSystem.h>

#include <ChilliSource/Core/Cryptographic/HashMD5.h>
#include <ChilliSource/Core/Cryptographic/HashCRC32.h>
#include <ChilliSource/Core/String/StringUtils.h>

#ifdef CS_TARGETPLATFORM_IOS
#include <ChilliSource/Backend/Platform/iOS/Core/File/FileSystem.h>
#endif

#ifdef CS_TARGETPLATFORM_ANDROID
#include <ChilliSource/Backend/Platform/Android/Core/File/FileSystem.h>
#endif

#ifdef CS_TARGETPLATFORM_WINDOWS
#include <ChilliSource/Backend/Platform/Windows/Core/File/FileSystem.h>
#endif

#include <algorithm>

namespace ChilliSource
{
    namespace Core
    {
        namespace
        {
            const std::string k_defaultPackageDLCDirectory = "DLC/";
        }
        CS_DEFINE_NAMEDTYPE(FileSystem);

        std::string FileSystem::s_resourceDirectory[3];
        f32 FileSystem::s_assetsDensity = 1.0f;

        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDeviceResourceDirectory()
        {
            return s_resourceDirectory[0];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDefaultDeviceResourceDirectory()
        {
            return s_resourceDirectory[1];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        const std::string& FileSystem::GetDefaultResourceDirectory()
        {
            return s_resourceDirectory[2];
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        void FileSystem::SetResourceDirectories(const std::string& in_deviceDirectory, const std::string& in_defaultDeviceDirectory, const std::string& in_defaultDirectory, f32 in_assetsDensity)
        {
            s_resourceDirectory[0] = in_deviceDirectory;
            if (!in_deviceDirectory.empty())
                s_resourceDirectory[0] += "/";
            s_resourceDirectory[1] = in_defaultDeviceDirectory;
            if (!in_defaultDeviceDirectory.empty())
                s_resourceDirectory[1] += "/";
            s_resourceDirectory[2] = in_defaultDirectory;
            if (!in_defaultDirectory.empty())
                s_resourceDirectory[2] += "/";

            s_assetsDensity = in_assetsDensity;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        f32 FileSystem::GetDeviceResourcesDensity()
        {
            return s_assetsDensity;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        FileSystemUPtr FileSystem::Create()
        {
#ifdef CS_TARGETPLATFORM_IOS
            return FileSystemUPtr(new iOS::FileSystem());
#endif
#ifdef CS_TARGETPLATFORM_ANDROID
            return FileSystemUPtr(new Android::FileSystem());
#endif
#ifdef CS_TARGETPLATFORM_WINDOWS
            return FileSystemUPtr(new Windows::FileSystem());
#endif
            return nullptr;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        FileSystem::FileSystem()
            : m_packageDLCPath(k_defaultPackageDLCDirectory)
        {
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::ReadFile(StorageLocation in_storageLocation, const std::string& in_directory, std::string& out_contents) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_read);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->GetAll(out_contents);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::WriteFile(StorageLocation in_storageLocation, const std::string& in_directory, const std::string& in_contents) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_writeBinary);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->Write(in_contents);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::WriteFile(StorageLocation in_storageLocation, const std::string& in_directory, const s8* in_data, u32 in_dataSize) const
        {
            Core::FileStreamUPtr fileStream = CreateFileStream(in_storageLocation, in_directory, Core::FileMode::k_writeBinary);

            if (fileStream.get() == nullptr || fileStream->IsOpen() == false || fileStream->IsBad() == true)
            {
                return false;
            }

            fileStream->Write(in_data, (s32)in_dataSize);
            fileStream->Close();

            return true;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::vector<std::string> FileSystem::GetFilePathsWithExtension(StorageLocation in_storageLocation, const std::string& in_directoryPath,  bool in_recursive, const std::string& in_extension) const
        {
            std::vector<std::string> filePaths = GetFilePaths(in_storageLocation, in_directoryPath, in_recursive);

            auto it = std::remove_if(filePaths.begin(), filePaths.end(), [&in_extension] (const std::string& in_path)
            {
                return (Core::StringUtils::EndsWith(in_path, "." + in_extension, true) == false);
            });

            filePaths.resize(it - filePaths.begin());

            return filePaths;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::vector<std::string> FileSystem::GetFilePathsWithFileName(StorageLocation in_storageLocation, const std::string& in_directoryPath,  bool in_recursive, const std::string& in_fileName) const
        {
            std::vector<std::string> filePaths = GetFilePaths(in_storageLocation, in_directoryPath, in_recursive);

            auto it = std::remove_if(filePaths.begin(), filePaths.end(), [&in_fileName] (const std::string& in_path)
            {
                return (Core::StringUtils::EndsWith(in_path, in_fileName, true) == false);
            });

            filePaths.resize(it - filePaths.begin());

            return filePaths;
        }
        //-------------------------------------------------------
        //-------------------------------------------------------
        void FileSystem::SetPackageDLCPath(const std::string& in_directoryPath)
        {
            m_packageDLCPath = StringUtils::StandardisePath(in_directoryPath);
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		const std::string& FileSystem::GetPackageDLCPath() const
		{
			return m_packageDLCPath;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::string FileSystem::GetFileChecksumMD5(StorageLocation in_storageLocation, const std::string& in_filePath) const
        {
            const u32 k_chunkSize = 256;
            s8 data[k_chunkSize];

            HashMD5::MD5 hash;
            s32 size = k_chunkSize;

            FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filePath, FileMode::k_readBinary);

            if(!file->IsOpen() || file->IsBad())
            {
                return "";
            }

            while(size != 0)
            {
                size = file->ReadSome(data, k_chunkSize);
                hash.update(data, size);
            }

            hash.finalize();
            return hash.binarydigest();
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        std::string FileSystem::GetDirectoryChecksumMD5(StorageLocation in_storageLocation, const std::string& in_directoryPath) const
		{
        	std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directoryPath, true);

			//get a hash for each of the files.
            std::vector<std::string> hashes;
			for (const std::string& filename : filenames)
			{
                std::string fileHash = GetFileChecksumMD5(in_storageLocation, in_directoryPath + filename);
                std::string pathHash = HashMD5::GenerateBinaryHashCode(filename.c_str(), filename.length());
                hashes.push_back(fileHash);
                hashes.push_back(pathHash);
			}

			//sort the list so that ordering of
            std::sort(hashes.begin(), hashes.end());

			//build this into a hashable string
			std::string hashableDirectoryContents;
			for (const std::string& hash : hashes)
			{
				hashableDirectoryContents += hash;
			}

			//return the hash of this as the output
            std::string strOutput = 0;
			if (hashableDirectoryContents.length() > 0)
            {
				strOutput = HashMD5::GenerateBinaryHashCode(hashableDirectoryContents.c_str(), hashableDirectoryContents.length());
            }

			return strOutput;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetFileChecksumCRC32(StorageLocation in_storageLocation, const std::string& in_filePath) const
		{
			u32 output = 0;

			//open the file
			FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filePath, FileMode::k_readBinary);
			if (file != nullptr && file->IsOpen() == true && file->IsBad() == false)
			{
				//get the length of the file
				file->SeekG(0, SeekDir::k_end);
				s32 length = file->TellG();
				file->SeekG(0, SeekDir::k_beginning);

				//read contents of file
				s8* contents = new s8[length];
				file->Read(contents, length);

				//get the hash
				output = HashCRC32::GenerateHashCode(contents, length);
				CS_SAFEDELETE_ARRAY(contents);
			}
			return output;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetDirectoryChecksumCRC32(StorageLocation in_storageLocation, const std::string& in_directoryPath) const
		{
			std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directoryPath, true);

			//get a hash for each of the files.
            std::vector<u32> hashes;
			for (const std::string& filename : filenames)
			{
				u32 fileHash = GetFileChecksumCRC32(in_storageLocation, in_directoryPath + filename);
				u32 pathHash = HashCRC32::GenerateHashCode(filename.c_str(), filename.length());
				hashes.push_back(fileHash);
				hashes.push_back(pathHash);
			}

			//sort the list so that ordering of
			std::sort(hashes.begin(), hashes.end());

			//build this into a hashable string
			std::string hashableDirectoryContents;
			for (const u32& hash : hashes)
			{
				hashableDirectoryContents += ToString(hash);
			}

			//return the hash of this as the output
			u32 output = 0;
			if (hashableDirectoryContents.length() > 0)
				output = HashCRC32::GenerateHashCode(hashableDirectoryContents.c_str(), hashableDirectoryContents.length());
			return output;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetFileSize(StorageLocation in_storageLocation, const std::string& in_filepath) const
		{
			//open the file
			FileStreamUPtr file = CreateFileStream(in_storageLocation, in_filepath, FileMode::k_readBinary);
			if (file->IsOpen() == true && file->IsBad() == false)
			{
				//get the length of the file
				file->SeekG(0, SeekDir::k_end);
				s32 dwLength = file->TellG();
				file->Close();
				return dwLength;
			}

			return 0;
		}
        //--------------------------------------------------------------
        //--------------------------------------------------------------
		u32 FileSystem::GetDirectorySize(StorageLocation in_storageLocation, const std::string& in_directory) const
		{
			std::vector<std::string> filenames = GetFilePaths(in_storageLocation, in_directory, true);

            u32 totalSize = 0;
			for (const std::string& filename : filenames)
			{
				totalSize += GetFileSize(in_storageLocation, in_directory + "/" + filename);
			}

			return totalSize;
		}
        //-------------------------------------------------------
        //-------------------------------------------------------
        bool FileSystem::IsStorageLocationWritable(StorageLocation in_storageLocation) const
        {
            switch (in_storageLocation)
            {
                case StorageLocation::k_saveData:
                case StorageLocation::k_cache:
                case StorageLocation::k_DLC:
                case StorageLocation::k_root:
                    return true;
                default:
                    return false;
            }
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        const std::string* FileSystem::GetResourceDirectories() const
        {
            return s_resourceDirectory;
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        bool FileSystem::IsWriteMode(Core::FileMode in_fileMode) const
        {
            switch (in_fileMode)
            {
                case Core::FileMode::k_write:
                case Core::FileMode::k_writeAppend:
                case Core::FileMode::k_writeAtEnd:
                case Core::FileMode::k_writeBinary:
                case Core::FileMode::k_writeBinaryAppend:
                case Core::FileMode::k_writeBinaryAtEnd:
                case Core::FileMode::k_writeBinaryTruncate:
                case Core::FileMode::k_writeTruncate:
                    return true;
                default:
                    return false;
            }
        }
    }
}
<|endoftext|>


<commit_before>
#include "../../Flare.h"
#include "FlareEULAMenu.h"
#include "../Components/FlareButton.h"
#include "../../Game/FlareGame.h"
#include "../../Game/FlareSaveGame.h"
#include "../../Player/FlareMenuPawn.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareEULAMenu"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareEULAMenu::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	int32 Width = 1.75 * Theme.ContentWidth;
	int32 TextWidth = Width - Theme.ContentPadding.Left - Theme.ContentPadding.Right;

	// Build structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	[
		SNew(SVerticalBox)

		// Title
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		.Padding(Theme.ContentPadding)
		[
			SNew(SHorizontalBox)

			// Icon
			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				SNew(SImage).Image(FFlareStyleSet::GetImage("HeliumRain"))
			]

			// Title
			+ SHorizontalBox::Slot()
			.VAlign(VAlign_Center)
			.Padding(Theme.ContentPadding)
			[
				SNew(STextBlock)
				.Text(LOCTEXT("DONT-TRANSLATE-EULA", "END-USER LICENCE AGREEMENT"))
				.TextStyle(&Theme.SpecialTitleFont)
			]
		]

		// Main
		+ SVerticalBox::Slot()
		.HAlign(HAlign_Center)
		.Padding(Theme.ContentPadding)
		[
			SNew(SBox)
			.WidthOverride(Width)
			.HAlign(HAlign_Fill)
			[
				SNew(SVerticalBox)

				// Separator
				+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FMargin(0, 20))
				[
					SNew(SImage).Image(&Theme.SeparatorBrush)
				]

				// Text
				+ SVerticalBox::Slot()
				[
					SNew(SScrollBox)
					.Style(&Theme.ScrollBoxStyle)
					.ScrollBarStyle(&Theme.ScrollBarStyle)

					// TODO GWENN : replace [Licensor] by company name
					+ SScrollBox::Slot()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("DONT-TRANSLATE-EULA-Text", "Helium Rain includes the Unreal Engine code and other code, materials, and information " \
							"(the 'Epic Materials') from Epic Games, Inc. ('Epic'). All Epic Materials are provided on an 'as is' and 'as available' basis, " \
							"'with all faults' and without warranty of any kind.  [Licensor], Epic, and Epic's affiliates disclaim all warranties, conditions, common law duties, " \
							"and representations (express, implied, oral, and written) with respect to the Epic Materials, including without limitation all express, " \
							"implied, and statutory warranties and conditions of any kind, such as title, non-interference with your enjoyment, authority, non-infringement, " \
							"merchantability, fitness or suitability for any purpose (whether or not Epic knows or has reason to know of any such purpose), system integration, " \
							"accuracy or completeness, results, reasonable care, workmanlike effort, lack of negligence, and lack of viruses, whether alleged to arise under law, " \
							"by reason of custom or usage in the trade, or by course of dealing. \n\n" \
							"Without limiting the generality of the foregoing, [Licensor], Epic, and Epic's affiliates make no warranty that \n" \
							"    (1) any of the Epic Materials will operate properly, including as integrated in Helium Rain, \n" \
							"    (2) that the Epic Materials will meet your requirements, \n" \
							"    (3) that the operation of the Epic Materials will be uninterrupted, bug free, or error free in any or all circumstances, \n" \
							"    (4) that any defects in the Epic Materials can or will be corrected, \n" \
							"    (5) that the Epic Materials are or will be in compliance with a platform manufacturer's rules or requirements, or \n" \
							"    (6) that a platform manufacturer has approved or will approve Helium Rain, or will not revoke approval of Helium Rain for any or no reason. \n\n" \
							"Any warranty against infringement that may be provided in Section 2-312 of the Uniform Commercial Code or in any other comparable statute is expressly disclaimed " \
							"by [Licensor] and Epic. [Licensor], Epic, and Epic's affiliates do not guarantee continuous, error-free, virus-free, or secure operation of or access to the " \
							"Epic Materials. \n\n" \
							"This paragraph will apply to the maximum extent permitted by applicable law. To the maximum extent permitted by applicable law, neither[Licensor], " \
							"Epic, Epic's licensors, nor its or their affiliates, nor any of[Licensor]'s or Epic's service providers, shall be liable in any way for loss or damage of any kind " \
							"resulting from the use or inability to use the Epic Materials or otherwise in connection with this[Agreement], including but not limited to loss of goodwill, " \
							"work stoppage, computer failure, or malfunction, or any and all other commercial damages or losses. In no event will [Licensor], Epic, Epic's licensors, " \
							"nor its or their affiliates, nor any of[Licensor]'s or Epic's service providers be liable for any loss of profits or any indirect, incidental, consequential, " \
							"special, punitive, or exemplary damages, or any other damages arising out of or in connection with this[Agreement] or the Epic Materials, or the delay or inability " \
							"to use or lack of functionality of the Epic Materials, even in the event of[Licensor]'s, Epic's, or Epic's affiliates' fault, tort(including negligence), " \
							"strict liability, indemnity, product liability, breach of contract, breach of warranty, or otherwise and even if[Licensor], Epic or Epic's affiliates " \
							"have been advised of the possibility of such damages. \n\n" \
							"These limitations and exclusions regarding damages apply even if any remedy fails to provide adequate " \
							"compensation. Because some states or jurisdictions do not allow the exclusion or the limitation of liability for consequential or incidental damages, " \
							"in such states or jurisdictions, the liability of[Licensor], Epic, Epic's licensors, its and their affiliates, and any of[Licensor]'s or Epic's service " \
							"providers shall be limited to the full extent permitted by law.")) // FString neded here
						.WrapTextAt(TextWidth)
						.TextStyle(&Theme.NameFont)
					]
				]
			]
		]

		// Back
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Bottom)
		[
			SNew(SFlareButton)
			.Transparent(true)
			.Width(3)
			.Text(LOCTEXT("Back", "Back"))
			.OnClicked(this, &SFlareEULAMenu::OnMainMenu)
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareEULAMenu::Setup()
{
	SetEnabled(false);
	SetVisibility(EVisibility::Collapsed);
}

void SFlareEULAMenu::Enter()
{
	FLOG("SFlareEULAMenu::Enter");
	SetEnabled(true);
	SetVisibility(EVisibility::Visible);
}

void SFlareEULAMenu::Exit()
{
	SetEnabled(false);
	SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareEULAMenu::OnMainMenu()
{
	MenuManager->OpenMenu(EFlareMenu::MENU_Main);
}

#undef LOCTEXT_NAMESPACE

<commit_msg>Fix build on linux<commit_after>
#include "../../Flare.h"
#include "FlareEULAMenu.h"
#include "../Components/FlareButton.h"
#include "../../Game/FlareGame.h"
#include "../../Game/FlareSaveGame.h"
#include "../../Player/FlareMenuPawn.h"
#include "../../Player/FlareMenuManager.h"
#include "../../Player/FlarePlayerController.h"

#define LOCTEXT_NAMESPACE "FlareEULAMenu"

/*----------------------------------------------------
	Construct
----------------------------------------------------*/

void SFlareEULAMenu::Construct(const FArguments& InArgs)
{
	// Data
	MenuManager = InArgs._MenuManager;
	const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme();
	int32 Width = 1.75 * Theme.ContentWidth;
	int32 TextWidth = Width - Theme.ContentPadding.Left - Theme.ContentPadding.Right;

	// Build structure
	ChildSlot
	.HAlign(HAlign_Fill)
	.VAlign(VAlign_Fill)
	[
		SNew(SVerticalBox)

		// Title
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Center)
		.Padding(Theme.ContentPadding)
		[
			SNew(SHorizontalBox)

			// Icon
			+ SHorizontalBox::Slot()
			.AutoWidth()
			[
				SNew(SImage).Image(FFlareStyleSet::GetImage("HeliumRain"))
			]

			// Title
			+ SHorizontalBox::Slot()
			.VAlign(VAlign_Center)
			.Padding(Theme.ContentPadding)
			[
				SNew(STextBlock)
				.Text(LOCTEXT("DONT-TRANSLATE-EULA", "END-USER LICENCE AGREEMENT"))
				.TextStyle(&Theme.SpecialTitleFont)
			]
		]

		// Main
		+ SVerticalBox::Slot()
		.HAlign(HAlign_Center)
		.Padding(Theme.ContentPadding)
		[
			SNew(SBox)
			.WidthOverride(Width)
			.HAlign(HAlign_Fill)
			[
				SNew(SVerticalBox)

				// Separator
				+ SVerticalBox::Slot()
				.AutoHeight()
				.Padding(FMargin(0, 20))
				[
					SNew(SImage).Image(&Theme.SeparatorBrush)
				]

				// Text
				+ SVerticalBox::Slot()
				[
					SNew(SScrollBox)
					.Style(&Theme.ScrollBoxStyle)
					.ScrollBarStyle(&Theme.ScrollBarStyle)

					// TODO GWENN : replace [Licensor] by company name
					+ SScrollBox::Slot()
					[
						SNew(STextBlock)
						.Text(LOCTEXT("DONT-TRANSLATE-EULA-Text", "Helium Rain includes the Unreal® Engine code and other code, materials, and information " \
							"(the 'Epic Materials') from Epic Games, Inc. ('Epic'). All Epic Materials are provided on an 'as is' and 'as available' basis, " \
							"'with all faults' and without warranty of any kind.  [Licensor], Epic, and Epic's affiliates disclaim all warranties, conditions, common law duties, " \
							"and representations (express, implied, oral, and written) with respect to the Epic Materials, including without limitation all express, " \
							"implied, and statutory warranties and conditions of any kind, such as title, non-interference with your enjoyment, authority, non-infringement, " \
							"merchantability, fitness or suitability for any purpose (whether or not Epic knows or has reason to know of any such purpose), system integration, " \
							"accuracy or completeness, results, reasonable care, workmanlike effort, lack of negligence, and lack of viruses, whether alleged to arise under law, " \
							"by reason of custom or usage in the trade, or by course of dealing. \n\n" \
							"Without limiting the generality of the foregoing, [Licensor], Epic, and Epic's affiliates make no warranty that \n" \
							"    (1) any of the Epic Materials will operate properly, including as integrated in Helium Rain, \n" \
							"    (2) that the Epic Materials will meet your requirements, \n" \
							"    (3) that the operation of the Epic Materials will be uninterrupted, bug free, or error free in any or all circumstances, \n" \
							"    (4) that any defects in the Epic Materials can or will be corrected, \n" \
							"    (5) that the Epic Materials are or will be in compliance with a platform manufacturer's rules or requirements, or \n" \
							"    (6) that a platform manufacturer has approved or will approve Helium Rain, or will not revoke approval of Helium Rain for any or no reason. \n\n" \
							"Any warranty against infringement that may be provided in Section 2-312 of the Uniform Commercial Code or in any other comparable statute is expressly disclaimed " \
							"by [Licensor] and Epic. [Licensor], Epic, and Epic's affiliates do not guarantee continuous, error-free, virus-free, or secure operation of or access to the " \
							"Epic Materials. \n\n" \
							"This paragraph will apply to the maximum extent permitted by applicable law. To the maximum extent permitted by applicable law, neither[Licensor], " \
							"Epic, Epic's licensors, nor its or their affiliates, nor any of[Licensor]'s or Epic's service providers, shall be liable in any way for loss or damage of any kind " \
							"resulting from the use or inability to use the Epic Materials or otherwise in connection with this[Agreement], including but not limited to loss of goodwill, " \
							"work stoppage, computer failure, or malfunction, or any and all other commercial damages or losses. In no event will [Licensor], Epic, Epic's licensors, " \
							"nor its or their affiliates, nor any of[Licensor]'s or Epic's service providers be liable for any loss of profits or any indirect, incidental, consequential, " \
							"special, punitive, or exemplary damages, or any other damages arising out of or in connection with this[Agreement] or the Epic Materials, or the delay or inability " \
							"to use or lack of functionality of the Epic Materials, even in the event of[Licensor]'s, Epic's, or Epic's affiliates' fault, tort(including negligence), " \
							"strict liability, indemnity, product liability, breach of contract, breach of warranty, or otherwise and even if[Licensor], Epic or Epic's affiliates " \
							"have been advised of the possibility of such damages. \n\n" \
							"These limitations and exclusions regarding damages apply even if any remedy fails to provide adequate " \
							"compensation. Because some states or jurisdictions do not allow the exclusion or the limitation of liability for consequential or incidental damages, " \
							"in such states or jurisdictions, the liability of[Licensor], Epic, Epic's licensors, its and their affiliates, and any of[Licensor]'s or Epic's service " \
							"providers shall be limited to the full extent permitted by law.")) // FString neded here
						.WrapTextAt(TextWidth)
						.TextStyle(&Theme.NameFont)
					]
				]
			]
		]

		// Back
		+ SVerticalBox::Slot()
		.AutoHeight()
		.HAlign(HAlign_Left)
		.VAlign(VAlign_Bottom)
		[
			SNew(SFlareButton)
			.Transparent(true)
			.Width(3)
			.Text(LOCTEXT("Back", "Back"))
			.OnClicked(this, &SFlareEULAMenu::OnMainMenu)
		]
	];
}

/*----------------------------------------------------
	Interaction
----------------------------------------------------*/

void SFlareEULAMenu::Setup()
{
	SetEnabled(false);
	SetVisibility(EVisibility::Collapsed);
}

void SFlareEULAMenu::Enter()
{
	FLOG("SFlareEULAMenu::Enter");
	SetEnabled(true);
	SetVisibility(EVisibility::Visible);
}

void SFlareEULAMenu::Exit()
{
	SetEnabled(false);
	SetVisibility(EVisibility::Collapsed);
}

/*----------------------------------------------------
	Callbacks
----------------------------------------------------*/

void SFlareEULAMenu::OnMainMenu()
{
	MenuManager->OpenMenu(EFlareMenu::MENU_Main);
}

#undef LOCTEXT_NAMESPACE

<|endoftext|>


<commit_before>//
// Copyright (c) 2017-2020 the rbfx project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <Urho3D/IO/FileSystem.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Resource/ResourceEvents.h>
#include <IconFontCppHeaders/IconsFontAwesome5.h>
#include <Toolbox/SystemUI/Widgets.h>
#include "BaseResourceTab.h"

namespace Urho3D
{

BaseResourceTab::BaseResourceTab(Context* context)
    : Tab(context)
{
    onTabContextMenu_.Subscribe(this, &BaseResourceTab::OnRenderContextMenu);

    SubscribeToEvent(E_RESOURCERENAMED, [&](StringHash, VariantMap& args) {
        using namespace ResourceRenamed;

        auto nameFrom = args[P_FROM].GetString();
        if (resourceName_ == nameFrom)
            SetResourceName(args[P_TO].GetString());
    });
    SubscribeToEvent(this, E_DOCUMENTMODIFIEDREQUEST, [this](StringHash, VariantMap&)
    {
        if (!modified_)
        {
            undo_->Add<UndoModifiedState>(this, true);
            modified_ = true;
        }
    });
    SubscribeToEvent(E_DOCUMENTMODIFIED, [this](StringHash, VariantMap& args) { modified_ = args[DocumentModified::P_MODIFIED].GetBool(); });
}

bool BaseResourceTab::LoadResource(const ea::string& resourcePath)
{
    if (!Tab::LoadResource(resourcePath))
        return false;

    if (resourcePath.empty())
        return false;

    if (IsModified())
    {
        pendingLoadResource_ = resourcePath;
        return false;
    }

    SetResourceName(resourcePath);
    modified_ = false;

    return true;
}

bool BaseResourceTab::SaveResource()
{
    if (!Tab::SaveResource())
        return false;

    if (resourceName_.empty())
        return false;

    // Mark tab as not modified.
    if (modified_)
    {
        undo_->Add<UndoModifiedState>(this, false);
        modified_ = false;
    }

    return true;
}

void BaseResourceTab::OnSaveUISettings(ImGuiTextBuffer* buf)
{
    Tab::OnSaveUISettings(buf);
    if (!resourceName_.empty())
        buf->appendf("Path=%s\n", resourceName_.c_str());
}

const char* BaseResourceTab::OnLoadUISettings(const char* name, const char* line)
{
    line = Tab::OnLoadUISettings(name, line);
    char path[1024];
    if (int scanned = sscanf(line, "Path=%s\n", path))
    {
        LoadResource(path);
        line += scanned;
    }
    return line;
}

void BaseResourceTab::SetResourceName(const ea::string& resourceName)
{
    resourceName_ = resourceName;
    if (!isUtility_)
        SetTitle(GetFileName(resourceName_));
}

void BaseResourceTab::Close()
{
    auto cache = GetSubsystem<ResourceCache>();
    cache->ReleaseResource(GetResourceType(), GetResourceName(), true);
    modified_ = false;
    resourceName_.clear();
}

bool BaseResourceTab::RenderWindowContent()
{
    if (wasOpen_ && !ui::IsPopupOpen("Save?"))
    {
        if ((!open_ && IsModified()) || !pendingLoadResource_.empty())
        {
            ui::OpenPopup("Save?");
            open_ = true;
        }
    }

    bool noCancel = true;
    if (ui::BeginPopupModal("Save?", &noCancel, ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_Popup))
    {
        // Warn when closing a tab that was modified.
        if (!pendingLoadResource_.empty())
        {
            ui::Text(
                "Resource '%s' was modified. Would you like to save it before opening '%s'?",
                GetFileNameAndExtension(resourceName_).c_str(),
                GetFileNameAndExtension(pendingLoadResource_).c_str());

            bool save = ui::Button(ICON_FA_SAVE " Save & Open");
            ui::SameLine();
            bool open = save || ui::Button(ICON_FA_EXCLAMATION_TRIANGLE " Close & Open");

            if (save)
                SaveResource();

            if (open)
            {
                LoadResource(pendingLoadResource_);
                pendingLoadResource_.clear();
                ui::CloseCurrentPopup();
            }
        }
        else
        {
            ui::Text("Resource '%s' was modified. Would you like to save it before closing?",
                GetFileNameAndExtension(resourceName_).c_str());

            bool save = ui::Button(ICON_FA_SAVE " Save & Close");
            ui::SameLine();
            bool close = ui::Button(ICON_FA_EXCLAMATION_TRIANGLE " Close without saving");
            ui::SetHelpTooltip("Can not be undone!", KEY_UNKNOWN);

            if (save)
                SaveResource();

            if (save || close)
            {
                open_ = false;
                ui::CloseCurrentPopup();
            }
        }
        ui::SameLine();
        if (ui::Button(ICON_FA_TIMES " Cancel"))
        {
            pendingLoadResource_.clear();
            ui::CloseCurrentPopup();
        }
        ui::EndPopup();
    }
    else if (!pendingLoadResource_.empty())
    {
        // Click outside of popup.
        pendingLoadResource_.clear();
    }

    if (wasOpen_ && !open_)
        Close();

    return true;
}

void BaseResourceTab::OnRenderContextMenu()
{
    if (ui::MenuItem("Save"))
        SaveResource();

    ui::Separator();

    if (ui::MenuItem("Close"))
        open_ = false;
}

}
<commit_msg>Editor: Fix "Close & Open" option when scene is modified but we do not want to save.<commit_after>//
// Copyright (c) 2017-2020 the rbfx project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <Urho3D/IO/FileSystem.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Resource/ResourceEvents.h>
#include <IconFontCppHeaders/IconsFontAwesome5.h>
#include <Toolbox/SystemUI/Widgets.h>
#include "BaseResourceTab.h"

namespace Urho3D
{

BaseResourceTab::BaseResourceTab(Context* context)
    : Tab(context)
{
    onTabContextMenu_.Subscribe(this, &BaseResourceTab::OnRenderContextMenu);

    SubscribeToEvent(E_RESOURCERENAMED, [&](StringHash, VariantMap& args) {
        using namespace ResourceRenamed;

        auto nameFrom = args[P_FROM].GetString();
        if (resourceName_ == nameFrom)
            SetResourceName(args[P_TO].GetString());
    });
    SubscribeToEvent(this, E_DOCUMENTMODIFIEDREQUEST, [this](StringHash, VariantMap&)
    {
        if (!modified_)
        {
            undo_->Add<UndoModifiedState>(this, true);
            modified_ = true;
        }
    });
    SubscribeToEvent(E_DOCUMENTMODIFIED, [this](StringHash, VariantMap& args) { modified_ = args[DocumentModified::P_MODIFIED].GetBool(); });
}

bool BaseResourceTab::LoadResource(const ea::string& resourcePath)
{
    if (!Tab::LoadResource(resourcePath))
        return false;

    if (resourcePath.empty())
        return false;

    if (IsModified() && pendingLoadResource_.empty())
    {
        pendingLoadResource_ = resourcePath;
        return false;
    }

    SetResourceName(resourcePath);
    modified_ = false;

    return true;
}

bool BaseResourceTab::SaveResource()
{
    if (!Tab::SaveResource())
        return false;

    if (resourceName_.empty())
        return false;

    // Mark tab as not modified.
    if (modified_)
    {
        undo_->Add<UndoModifiedState>(this, false);
        modified_ = false;
    }

    return true;
}

void BaseResourceTab::OnSaveUISettings(ImGuiTextBuffer* buf)
{
    Tab::OnSaveUISettings(buf);
    if (!resourceName_.empty())
        buf->appendf("Path=%s\n", resourceName_.c_str());
}

const char* BaseResourceTab::OnLoadUISettings(const char* name, const char* line)
{
    line = Tab::OnLoadUISettings(name, line);
    char path[1024];
    if (int scanned = sscanf(line, "Path=%s\n", path))
    {
        LoadResource(path);
        line += scanned;
    }
    return line;
}

void BaseResourceTab::SetResourceName(const ea::string& resourceName)
{
    resourceName_ = resourceName;
    if (!isUtility_)
        SetTitle(GetFileName(resourceName_));
}

void BaseResourceTab::Close()
{
    auto cache = GetSubsystem<ResourceCache>();
    cache->ReleaseResource(GetResourceType(), GetResourceName(), true);
    modified_ = false;
    resourceName_.clear();
}

bool BaseResourceTab::RenderWindowContent()
{
    if (wasOpen_ && !ui::IsPopupOpen("Save?"))
    {
        if ((!open_ && IsModified()) || !pendingLoadResource_.empty())
        {
            ui::OpenPopup("Save?");
            open_ = true;
        }
    }

    bool noCancel = true;
    if (ui::BeginPopupModal("Save?", &noCancel, ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_Popup))
    {
        // Warn when closing a tab that was modified.
        if (!pendingLoadResource_.empty())
        {
            ui::Text(
                "Resource '%s' was modified. Would you like to save it before opening '%s'?",
                GetFileNameAndExtension(resourceName_).c_str(),
                GetFileNameAndExtension(pendingLoadResource_).c_str());

            bool save = ui::Button(ICON_FA_SAVE " Save & Open");
            ui::SameLine();
            bool open = save || ui::Button(ICON_FA_EXCLAMATION_TRIANGLE " Close & Open");

            if (save)
                SaveResource();

            if (open)
            {
                LoadResource(pendingLoadResource_);
                pendingLoadResource_.clear();
                ui::CloseCurrentPopup();
            }
        }
        else
        {
            ui::Text("Resource '%s' was modified. Would you like to save it before closing?",
                GetFileNameAndExtension(resourceName_).c_str());

            bool save = ui::Button(ICON_FA_SAVE " Save & Close");
            ui::SameLine();
            bool close = ui::Button(ICON_FA_EXCLAMATION_TRIANGLE " Close without saving");
            ui::SetHelpTooltip("Can not be undone!", KEY_UNKNOWN);

            if (save)
                SaveResource();

            if (save || close)
            {
                open_ = false;
                ui::CloseCurrentPopup();
            }
        }
        ui::SameLine();
        if (ui::Button(ICON_FA_TIMES " Cancel"))
        {
            pendingLoadResource_.clear();
            ui::CloseCurrentPopup();
        }
        ui::EndPopup();
    }
    else if (!pendingLoadResource_.empty())
    {
        // Click outside of popup.
        pendingLoadResource_.clear();
    }

    if (wasOpen_ && !open_)
        Close();

    return true;
}

void BaseResourceTab::OnRenderContextMenu()
{
    if (ui::MenuItem("Save"))
        SaveResource();

    ui::Separator();

    if (ui::MenuItem("Close"))
        open_ = false;
}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qbluetoothserviceinfo.h"
#include "qbluetoothserviceinfo_p.h"

#include "bluez/manager_p.h"
#include "bluez/service_p.h"

#include <QtCore/QXmlStreamWriter>

QTBLUETOOTH_BEGIN_NAMESPACE

static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
{
    const QString unsignedFormat(QLatin1String("0x%1"));

    switch (attribute.type()) {
    case QMetaType::Void:
        stream->writeEmptyElement(QLatin1String("nil"));
        break;
    case QMetaType::UChar:
        stream->writeEmptyElement(QLatin1String("uint8"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint8>(), 2, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::UShort:
        stream->writeEmptyElement(QLatin1String("uint16"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint16>(), 4, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::UInt:
        stream->writeEmptyElement(QLatin1String("uint32"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint32>(), 8, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Char:
        stream->writeEmptyElement(QLatin1String("int8"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<uchar>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Short:
        stream->writeEmptyElement(QLatin1String("int16"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<qint16>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Int:
        stream->writeEmptyElement(QLatin1String("int32"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<qint32>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::QString:
        stream->writeEmptyElement(QLatin1String("text"));
        if (/* require hex encoding */ false) {
            stream->writeAttribute(QLatin1String("value"), QString::fromLatin1(
                                       attribute.value<QString>().toUtf8().toHex().constData()));
            stream->writeAttribute(QLatin1String("encoding"), QLatin1String("hex"));
        } else {
            stream->writeAttribute(QLatin1String("value"), attribute.value<QString>());
            stream->writeAttribute(QLatin1String("encoding"), QLatin1String("normal"));
        }
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QMetaType::Bool:
        stream->writeEmptyElement(QLatin1String("boolean"));
        if (attribute.value<bool>())
            stream->writeAttribute(QLatin1String("value"), QLatin1String("true"));
        else
            stream->writeAttribute(QLatin1String("value"), QLatin1String("false"));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QMetaType::QUrl:
        stream->writeEmptyElement(QLatin1String("url"));
        stream->writeAttribute(QLatin1String("value"), attribute.value<QUrl>().toString());
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QVariant::UserType:
        if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
            stream->writeEmptyElement(QLatin1String("uuid"));

            QBluetoothUuid uuid = attribute.value<QBluetoothUuid>();
            switch (uuid.minimumSize()) {
            case 0:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0')));
                break;
            case 2:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(uuid.toUInt16(), 4, 16,
                                                          QLatin1Char('0')));
                break;
            case 4:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(uuid.toUInt32(), 8, 16,
                                                          QLatin1Char('0')));
                break;
            case 16:
                stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36));
                break;
            default:
                stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36));
            }
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
            stream->writeStartElement(QLatin1String("sequence"));
            const QBluetoothServiceInfo::Sequence *sequence =
                    static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data());
            foreach (const QVariant &v, *sequence)
                writeAttribute(stream, v);
            stream->writeEndElement();
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
            const QBluetoothServiceInfo::Alternative *alternative =
                    static_cast<const QBluetoothServiceInfo::Alternative *>(attribute.data());
            foreach (const QVariant &v, *alternative)
                writeAttribute(stream, v);
            stream->writeEndElement();
        }
        break;
            default:
        qDebug() << "Unknown variant type", attribute.userType();
    }
}

QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate()
:   service(0), serviceRecord(0), registered(false)
{
}

QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
{
}

bool QBluetoothServiceInfoPrivate::unregisterService() const
{
    if (!registered)
        return false;

    if (!ensureSdpConnection())
        return false;

    QDBusPendingReply<> reply = service->RemoveRecord(d->serviceRecord);
    reply.waitForFinished();
    if (reply.isError())
        return false;

    serviceRecord = 0;

    registered = false;
    return true;
}

void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const
{
    Q_UNUSED(attributeId);
    Q_UNUSED(value);

    registerService();
}

void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const
{
    Q_UNUSED(attributeId);

    registerService();
}

bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const
{
    if (service)
        return true;

    OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"),
                                     QDBusConnection::systemBus());

    QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(QLatin1String("any"));
    reply.waitForFinished();
    if (reply.isError())
        return false;

    service = new OrgBluezServiceInterface(QLatin1String("org.bluez"), reply.value().path(),
                                           QDBusConnection::systemBus());

    return true;
}

bool QBluetoothServiceInfoPrivate::registerService() const
{
    if (!ensureSdpConnection()) {
        qDebug() << "SDP not connected. Cannot register";
        return false;
    }

    QString xmlServiceRecord;

    QXmlStreamWriter stream(&xmlServiceRecord);
    stream.setAutoFormatting(true);

    stream.writeStartDocument(QLatin1String("1.0"));

    stream.writeStartElement(QLatin1String("record"));

    const QString unsignedFormat(QLatin1String("0x%1"));

    QMap<quint16, QVariant>::ConstIterator i = attributes.constBegin();
    while (i != attributes.constEnd()) {
        stream.writeStartElement(QLatin1String("attribute"));
        stream.writeAttribute(QLatin1String("id"), unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0')));
        writeAttribute(&stream, i.value());
        stream.writeEndElement();

        ++i;
    }

    stream.writeEndElement();

    stream.writeEndDocument();

//    qDebug() << xmlServiceRecord;

    if (!registered) {
        QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord);
        reply.waitForFinished();
        if (reply.isError()) {
            qDebug() << "AddRecord returned error" << reply.error();
            return false;
        }

        serviceRecord = reply.value();
    } else {
        QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord);
        reply.waitForFinished();
        if (reply.isError()) {
            qDebug() << "UpdateRecord returned error" << reply.error();
            return false;
        }
    }

    registered = true;
    return true;
}

QTBLUETOOTH_END_NAMESPACE
<commit_msg>fix compile<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qbluetoothserviceinfo.h"
#include "qbluetoothserviceinfo_p.h"

#include "bluez/manager_p.h"
#include "bluez/service_p.h"

#include <QtCore/QXmlStreamWriter>

QTBLUETOOTH_BEGIN_NAMESPACE

static void writeAttribute(QXmlStreamWriter *stream, const QVariant &attribute)
{
    const QString unsignedFormat(QLatin1String("0x%1"));

    switch (attribute.type()) {
    case QMetaType::Void:
        stream->writeEmptyElement(QLatin1String("nil"));
        break;
    case QMetaType::UChar:
        stream->writeEmptyElement(QLatin1String("uint8"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint8>(), 2, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::UShort:
        stream->writeEmptyElement(QLatin1String("uint16"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint16>(), 4, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::UInt:
        stream->writeEmptyElement(QLatin1String("uint32"));
        stream->writeAttribute(QLatin1String("value"),
                               unsignedFormat.arg(attribute.value<quint32>(), 8, 16,
                                                  QLatin1Char('0')));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Char:
        stream->writeEmptyElement(QLatin1String("int8"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<uchar>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Short:
        stream->writeEmptyElement(QLatin1String("int16"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<qint16>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::Int:
        stream->writeEmptyElement(QLatin1String("int32"));
        stream->writeAttribute(QLatin1String("value"),
                               QString::number(attribute.value<qint32>(), 16));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
    case QMetaType::QString:
        stream->writeEmptyElement(QLatin1String("text"));
        if (/* require hex encoding */ false) {
            stream->writeAttribute(QLatin1String("value"), QString::fromLatin1(
                                       attribute.value<QString>().toUtf8().toHex().constData()));
            stream->writeAttribute(QLatin1String("encoding"), QLatin1String("hex"));
        } else {
            stream->writeAttribute(QLatin1String("value"), attribute.value<QString>());
            stream->writeAttribute(QLatin1String("encoding"), QLatin1String("normal"));
        }
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QMetaType::Bool:
        stream->writeEmptyElement(QLatin1String("boolean"));
        if (attribute.value<bool>())
            stream->writeAttribute(QLatin1String("value"), QLatin1String("true"));
        else
            stream->writeAttribute(QLatin1String("value"), QLatin1String("false"));
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QMetaType::QUrl:
        stream->writeEmptyElement(QLatin1String("url"));
        stream->writeAttribute(QLatin1String("value"), attribute.value<QUrl>().toString());
        //stream->writeAttribute(QLatin1String("name"), foo);
        break;
            case QVariant::UserType:
        if (attribute.userType() == qMetaTypeId<QBluetoothUuid>()) {
            stream->writeEmptyElement(QLatin1String("uuid"));

            QBluetoothUuid uuid = attribute.value<QBluetoothUuid>();
            switch (uuid.minimumSize()) {
            case 0:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(quint16(0), 4, 16, QLatin1Char('0')));
                break;
            case 2:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(uuid.toUInt16(), 4, 16,
                                                          QLatin1Char('0')));
                break;
            case 4:
                stream->writeAttribute(QLatin1String("value"),
                                       unsignedFormat.arg(uuid.toUInt32(), 8, 16,
                                                          QLatin1Char('0')));
                break;
            case 16:
                stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36));
                break;
            default:
                stream->writeAttribute(QLatin1String("value"), uuid.toString().mid(1, 36));
            }
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Sequence>()) {
            stream->writeStartElement(QLatin1String("sequence"));
            const QBluetoothServiceInfo::Sequence *sequence =
                    static_cast<const QBluetoothServiceInfo::Sequence *>(attribute.data());
            foreach (const QVariant &v, *sequence)
                writeAttribute(stream, v);
            stream->writeEndElement();
        } else if (attribute.userType() == qMetaTypeId<QBluetoothServiceInfo::Alternative>()) {
            const QBluetoothServiceInfo::Alternative *alternative =
                    static_cast<const QBluetoothServiceInfo::Alternative *>(attribute.data());
            foreach (const QVariant &v, *alternative)
                writeAttribute(stream, v);
            stream->writeEndElement();
        }
        break;
            default:
        qDebug() << "Unknown variant type", attribute.userType();
    }
}

QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate()
:   service(0), serviceRecord(0), registered(false)
{
}

QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
{
}

bool QBluetoothServiceInfoPrivate::unregisterService() const
{
    if (!registered)
        return false;

    if (!ensureSdpConnection())
        return false;

    QDBusPendingReply<> reply = service->RemoveRecord(serviceRecord);
    reply.waitForFinished();
    if (reply.isError())
        return false;

    serviceRecord = 0;

    registered = false;
    return true;
}

void QBluetoothServiceInfoPrivate::setRegisteredAttribute(quint16 attributeId, const QVariant &value) const
{
    Q_UNUSED(attributeId);
    Q_UNUSED(value);

    registerService();
}

void QBluetoothServiceInfoPrivate::removeRegisteredAttribute(quint16 attributeId) const
{
    Q_UNUSED(attributeId);

    registerService();
}

bool QBluetoothServiceInfoPrivate::ensureSdpConnection() const
{
    if (service)
        return true;

    OrgBluezManagerInterface manager(QLatin1String("org.bluez"), QLatin1String("/"),
                                     QDBusConnection::systemBus());

    QDBusPendingReply<QDBusObjectPath> reply = manager.FindAdapter(QLatin1String("any"));
    reply.waitForFinished();
    if (reply.isError())
        return false;

    service = new OrgBluezServiceInterface(QLatin1String("org.bluez"), reply.value().path(),
                                           QDBusConnection::systemBus());

    return true;
}

bool QBluetoothServiceInfoPrivate::registerService() const
{
    if (!ensureSdpConnection()) {
        qDebug() << "SDP not connected. Cannot register";
        return false;
    }

    QString xmlServiceRecord;

    QXmlStreamWriter stream(&xmlServiceRecord);
    stream.setAutoFormatting(true);

    stream.writeStartDocument(QLatin1String("1.0"));

    stream.writeStartElement(QLatin1String("record"));

    const QString unsignedFormat(QLatin1String("0x%1"));

    QMap<quint16, QVariant>::ConstIterator i = attributes.constBegin();
    while (i != attributes.constEnd()) {
        stream.writeStartElement(QLatin1String("attribute"));
        stream.writeAttribute(QLatin1String("id"), unsignedFormat.arg(i.key(), 4, 16, QLatin1Char('0')));
        writeAttribute(&stream, i.value());
        stream.writeEndElement();

        ++i;
    }

    stream.writeEndElement();

    stream.writeEndDocument();

//    qDebug() << xmlServiceRecord;

    if (!registered) {
        QDBusPendingReply<uint> reply = service->AddRecord(xmlServiceRecord);
        reply.waitForFinished();
        if (reply.isError()) {
            qDebug() << "AddRecord returned error" << reply.error();
            return false;
        }

        serviceRecord = reply.value();
    } else {
        QDBusPendingReply<> reply = service->UpdateRecord(serviceRecord, xmlServiceRecord);
        reply.waitForFinished();
        if (reply.isError()) {
            qDebug() << "UpdateRecord returned error" << reply.error();
            return false;
        }
    }

    registered = true;
    return true;
}

QTBLUETOOTH_END_NAMESPACE
<|endoftext|>


<commit_before>//
//  Frustum.cpp
//  G3MiOSSDK
//
//  Created by Agustín Trujillo Pino on 15/07/12.
//  Copyright (c) 2012 Universidad de Las Palmas. All rights reserved.
//

#include "Frustum.hpp"
#include "Box.hpp"

Frustum::Frustum (const FrustumData& data):
_ltn(Vector3D(data._left, data._top, -data._znear)),
_rtn(Vector3D(data._right, data._top, -data._znear)),
_lbn(Vector3D(data._left, data._bottom, -data._znear)),
_rbn(Vector3D(data._right, data._bottom, -data._znear)),
_ltf(Vector3D(data._zfar/data._znear*data._left,  data._zfar/data._znear*data._top,     -data._zfar)),
_rtf(Vector3D(data._zfar/data._znear*data._right, data._zfar/data._znear*data._top,     -data._zfar)),
_lbf(Vector3D(data._zfar/data._znear*data._left,  data._zfar/data._znear*data._bottom,  -data._zfar)),
_rbf(Vector3D(data._zfar/data._znear*data._right, data._zfar/data._znear*data._bottom,  -data._zfar)),
_leftPlane(Plane(Vector3D(0, 0, 0),
                 Vector3D(data._left, data._top, -data._znear),
                 Vector3D(data._left, data._bottom, -data._znear))),
_bottomPlane(Plane(Vector3D(0, 0, 0),
                   Vector3D(data._left, data._bottom, -data._znear),
                   Vector3D(data._right, data._bottom, -data._znear))),
_rightPlane(Plane(Vector3D(0, 0, 0),
                  Vector3D(data._right, data._bottom, -data._znear),
                  Vector3D(data._right, data._top, -data._znear))),
_topPlane(Plane(Vector3D(0, 0, 0),
                Vector3D(data._right, data._top, -data._znear),
                Vector3D(data._left, data._top, -data._znear))),
_nearPlane(Plane(Vector3D(0, 0, 1), data._znear)),
_farPlane(Plane(Vector3D(0, 0, -1), -data._zfar)),
_extent(NULL)
{
}

bool Frustum::contains(const Vector3D& point) const {
  if (_leftPlane.signedDistance(point)   > 0) return false;
  if (_rightPlane.signedDistance(point)  > 0) return false;
  if (_bottomPlane.signedDistance(point) > 0) return false;
  if (_topPlane.signedDistance(point)    > 0) return false;
  if (_nearPlane.signedDistance(point)   > 0) return false;
  if (_farPlane.signedDistance(point)    > 0) return false;
  return true;
}

bool Frustum::touchesWithBox(const Box *box) const
{
  bool outside;

  // test first if frustum extent intersect with box
  if (!getExtent()->touchesBox(box)) return false;

  // create an array with the 8 corners of the box
  const Vector3D min = box->getLower();
  const Vector3D max = box->getUpper();
  Vector3D corners[8] = {
    Vector3D(min.x(), min.y(), min.z()),
    Vector3D(min.x(), min.y(), max.z()),
    Vector3D(min.x(), max.y(), min.z()),
    Vector3D(min.x(), max.y(), max.z()),
    Vector3D(max.x(), min.y(), min.z()),
    Vector3D(max.x(), min.y(), max.z()),
    Vector3D(max.x(), max.y(), min.z()),
    Vector3D(max.x(), max.y(), max.z())
  };

//  std::vector<Vector3D> corners = box->getCorners();

  int __ASK_agustin;
  /* http://www.flipcode.com/archives/Frustum_Culling.shtml */

  // test with left plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_leftPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with bottom plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_bottomPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with right plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_rightPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with top plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_topPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with near plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_nearPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with far plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_farPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  return true;
}

Extent* Frustum::computeExtent()
{
  double minx=1e10, miny=1e10, minz=1e10;
  double maxx=-1e10, maxy=-1e10, maxz=-1e10;

  if (_ltn.x()<minx) minx=_ltn.x();     if (_ltn.x()>maxx) maxx=_ltn.x();
  if (_ltn.y()<miny) miny=_ltn.y();     if (_ltn.y()>maxy) maxy=_ltn.y();
  if (_ltn.z()<minz) minz=_ltn.z();     if (_ltn.z()>maxz) maxz=_ltn.z();

  if (_rtn.x()<minx) minx=_rtn.x();     if (_rtn.x()>maxx) maxx=_rtn.x();
  if (_rtn.y()<miny) miny=_rtn.y();     if (_rtn.y()>maxy) maxy=_rtn.y();
  if (_rtn.z()<minz) minz=_rtn.z();     if (_rtn.z()>maxz) maxz=_rtn.z();

  if (_lbn.x()<minx) minx=_lbn.x();     if (_lbn.x()>maxx) maxx=_lbn.x();
  if (_lbn.y()<miny) miny=_lbn.y();     if (_lbn.y()>maxy) maxy=_lbn.y();
  if (_lbn.z()<minz) minz=_lbn.z();     if (_lbn.z()>maxz) maxz=_lbn.z();

  if (_rbn.x()<minx) minx=_rbn.x();     if (_rbn.x()>maxx) maxx=_rbn.x();
  if (_rbn.y()<miny) miny=_rbn.y();     if (_rbn.y()>maxy) maxy=_rbn.y();
  if (_rbn.z()<minz) minz=_rbn.z();     if (_rbn.z()>maxz) maxz=_rbn.z();

  if (_ltf.x()<minx) minx=_ltn.x();     if (_ltn.x()>maxx) maxx=_ltn.x();
  if (_ltf.y()<miny) miny=_ltn.y();     if (_ltn.y()>maxy) maxy=_ltn.y();
  if (_ltf.z()<minz) minz=_ltn.z();     if (_ltn.z()>maxz) maxz=_ltn.z();

  if (_rtf.x()<minx) minx=_rtf.x();     if (_rtf.x()>maxx) maxx=_rtf.x();
  if (_rtf.y()<miny) miny=_rtf.y();     if (_rtf.y()>maxy) maxy=_rtf.y();
  if (_rtf.z()<minz) minz=_rtf.z();     if (_rtf.z()>maxz) maxz=_rtf.z();

  if (_lbf.x()<minx) minx=_lbf.x();     if (_lbf.x()>maxx) maxx=_lbf.x();
  if (_lbf.y()<miny) miny=_lbf.y();     if (_lbf.y()>maxy) maxy=_lbf.y();
  if (_lbf.z()<minz) minz=_lbf.z();     if (_lbf.z()>maxz) maxz=_lbf.z();

  if (_rbf.x()<minx) minx=_rbf.x();     if (_rbf.x()>maxx) maxx=_rbf.x();
  if (_rbf.y()<miny) miny=_rbf.y();     if (_rbf.y()>maxy) maxy=_rbf.y();
  if (_rbf.z()<minz) minz=_rbf.z();     if (_rbf.z()>maxz) maxz=_rbf.z();

  return new Box(Vector3D(minx, miny, minz), Vector3D(maxx, maxy, maxz));
}

<commit_msg>solved bug in Frustum::computeExtent<commit_after>//
//  Frustum.cpp
//  G3MiOSSDK
//
//  Created by Agustín Trujillo Pino on 15/07/12.
//  Copyright (c) 2012 Universidad de Las Palmas. All rights reserved.
//

#include "Frustum.hpp"
#include "Box.hpp"

Frustum::Frustum (const FrustumData& data):
_ltn(Vector3D(data._left, data._top, -data._znear)),
_rtn(Vector3D(data._right, data._top, -data._znear)),
_lbn(Vector3D(data._left, data._bottom, -data._znear)),
_rbn(Vector3D(data._right, data._bottom, -data._znear)),
_ltf(Vector3D(data._zfar/data._znear*data._left,  data._zfar/data._znear*data._top,     -data._zfar)),
_rtf(Vector3D(data._zfar/data._znear*data._right, data._zfar/data._znear*data._top,     -data._zfar)),
_lbf(Vector3D(data._zfar/data._znear*data._left,  data._zfar/data._znear*data._bottom,  -data._zfar)),
_rbf(Vector3D(data._zfar/data._znear*data._right, data._zfar/data._znear*data._bottom,  -data._zfar)),
_leftPlane(Plane(Vector3D(0, 0, 0),
                 Vector3D(data._left, data._top, -data._znear),
                 Vector3D(data._left, data._bottom, -data._znear))),
_bottomPlane(Plane(Vector3D(0, 0, 0),
                   Vector3D(data._left, data._bottom, -data._znear),
                   Vector3D(data._right, data._bottom, -data._znear))),
_rightPlane(Plane(Vector3D(0, 0, 0),
                  Vector3D(data._right, data._bottom, -data._znear),
                  Vector3D(data._right, data._top, -data._znear))),
_topPlane(Plane(Vector3D(0, 0, 0),
                Vector3D(data._right, data._top, -data._znear),
                Vector3D(data._left, data._top, -data._znear))),
_nearPlane(Plane(Vector3D(0, 0, 1), data._znear)),
_farPlane(Plane(Vector3D(0, 0, -1), -data._zfar)),
_extent(NULL)
{
}

bool Frustum::contains(const Vector3D& point) const {
  if (_leftPlane.signedDistance(point)   > 0) return false;
  if (_rightPlane.signedDistance(point)  > 0) return false;
  if (_bottomPlane.signedDistance(point) > 0) return false;
  if (_topPlane.signedDistance(point)    > 0) return false;
  if (_nearPlane.signedDistance(point)   > 0) return false;
  if (_farPlane.signedDistance(point)    > 0) return false;
  return true;
}

bool Frustum::touchesWithBox(const Box *box) const
{
  bool outside;

  // test first if frustum extent intersect with box
  if (!getExtent()->touchesBox(box)) return false;

  // create an array with the 8 corners of the box
  const Vector3D min = box->getLower();
  const Vector3D max = box->getUpper();
  Vector3D corners[8] = {
    Vector3D(min.x(), min.y(), min.z()),
    Vector3D(min.x(), min.y(), max.z()),
    Vector3D(min.x(), max.y(), min.z()),
    Vector3D(min.x(), max.y(), max.z()),
    Vector3D(max.x(), min.y(), min.z()),
    Vector3D(max.x(), min.y(), max.z()),
    Vector3D(max.x(), max.y(), min.z()),
    Vector3D(max.x(), max.y(), max.z())
  };

//  std::vector<Vector3D> corners = box->getCorners();

  int __ASK_agustin;
  /* http://www.flipcode.com/archives/Frustum_Culling.shtml */

  // test with left plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_leftPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with bottom plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_bottomPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with right plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_rightPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with top plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_topPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with near plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_nearPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  // test with far plane
  outside = true;
  for (int i=0; i<8; i++)
    if (_farPlane.signedDistance(corners[i])<0) {
      outside = false;
      break;
    }
  if (outside) return false;

  return true;
}

Extent* Frustum::computeExtent()
{
  double minx=1e10, miny=1e10, minz=1e10;
  double maxx=-1e10, maxy=-1e10, maxz=-1e10;

  if (_ltn.x()<minx) minx=_ltn.x();     if (_ltn.x()>maxx) maxx=_ltn.x();
  if (_ltn.y()<miny) miny=_ltn.y();     if (_ltn.y()>maxy) maxy=_ltn.y();
  if (_ltn.z()<minz) minz=_ltn.z();     if (_ltn.z()>maxz) maxz=_ltn.z();

  if (_rtn.x()<minx) minx=_rtn.x();     if (_rtn.x()>maxx) maxx=_rtn.x();
  if (_rtn.y()<miny) miny=_rtn.y();     if (_rtn.y()>maxy) maxy=_rtn.y();
  if (_rtn.z()<minz) minz=_rtn.z();     if (_rtn.z()>maxz) maxz=_rtn.z();

  if (_lbn.x()<minx) minx=_lbn.x();     if (_lbn.x()>maxx) maxx=_lbn.x();
  if (_lbn.y()<miny) miny=_lbn.y();     if (_lbn.y()>maxy) maxy=_lbn.y();
  if (_lbn.z()<minz) minz=_lbn.z();     if (_lbn.z()>maxz) maxz=_lbn.z();

  if (_rbn.x()<minx) minx=_rbn.x();     if (_rbn.x()>maxx) maxx=_rbn.x();
  if (_rbn.y()<miny) miny=_rbn.y();     if (_rbn.y()>maxy) maxy=_rbn.y();
  if (_rbn.z()<minz) minz=_rbn.z();     if (_rbn.z()>maxz) maxz=_rbn.z();

  if (_ltf.x()<minx) minx=_ltf.x();     if (_ltn.x()>maxx) maxx=_ltf.x();
  if (_ltf.y()<miny) miny=_ltf.y();     if (_ltn.y()>maxy) maxy=_ltf.y();
  if (_ltf.z()<minz) minz=_ltf.z();     if (_ltn.z()>maxz) maxz=_ltf.z();

  if (_rtf.x()<minx) minx=_rtf.x();     if (_rtf.x()>maxx) maxx=_rtf.x();
  if (_rtf.y()<miny) miny=_rtf.y();     if (_rtf.y()>maxy) maxy=_rtf.y();
  if (_rtf.z()<minz) minz=_rtf.z();     if (_rtf.z()>maxz) maxz=_rtf.z();

  if (_lbf.x()<minx) minx=_lbf.x();     if (_lbf.x()>maxx) maxx=_lbf.x();
  if (_lbf.y()<miny) miny=_lbf.y();     if (_lbf.y()>maxy) maxy=_lbf.y();
  if (_lbf.z()<minz) minz=_lbf.z();     if (_lbf.z()>maxz) maxz=_lbf.z();

  if (_rbf.x()<minx) minx=_rbf.x();     if (_rbf.x()>maxx) maxx=_rbf.x();
  if (_rbf.y()<miny) miny=_rbf.y();     if (_rbf.y()>maxy) maxy=_rbf.y();
  if (_rbf.z()<minz) minz=_rbf.z();     if (_rbf.z()>maxz) maxz=_rbf.z();

  return new Box(Vector3D(minx, miny, minz), Vector3D(maxx, maxy, maxz));
}

<|endoftext|>