Added: Implemented bnp_manager_plugin add and delete files
--HG-- branch : branch-bnp-manager-plugin
This commit is contained in:
parent
e61e79eee3
commit
ba66f5e070
4 changed files with 306 additions and 19 deletions
|
@ -33,6 +33,12 @@ using namespace std;
|
|||
namespace BNPManager
|
||||
{
|
||||
|
||||
PackedFile::PackedFile()
|
||||
{
|
||||
m_size = 0;
|
||||
m_pos = 0;
|
||||
}
|
||||
|
||||
NLMISC_SAFE_SINGLETON_IMPL(BNPFileHandle);
|
||||
|
||||
BNPFileHandle::BNPFileHandle()
|
||||
|
@ -58,7 +64,7 @@ void BNPFileHandle::releaseInstance()
|
|||
// ***************************************************************************
|
||||
bool BNPFileHandle::unpack(const string &dirName, const vector<string>& fileList)
|
||||
{
|
||||
FILE *bnp = fopen (m_activeBNPFile.c_str(), "rb");
|
||||
FILE *bnp = fopen (m_openedBNPFile.c_str(), "rb");
|
||||
FILE *out;
|
||||
if (bnp == NULL)
|
||||
return false;
|
||||
|
@ -97,13 +103,13 @@ bool BNPFileHandle::unpack(const string &dirName, const vector<string>& fileList
|
|||
}
|
||||
// ***************************************************************************
|
||||
// Read the header from a big file
|
||||
bool BNPFileHandle::readHeader(const std::string &filename)
|
||||
bool BNPFileHandle::readHeader(const std::string &filePath)
|
||||
{
|
||||
m_packedFiles.clear();
|
||||
|
||||
m_activeBNPFile = filename;
|
||||
m_openedBNPFile = filePath;
|
||||
|
||||
FILE *f = fopen (filename.c_str(), "rb");
|
||||
FILE *f = fopen (filePath.c_str(), "rb");
|
||||
if (f == NULL)
|
||||
{
|
||||
nlwarning("Could not open file!");
|
||||
|
@ -111,7 +117,7 @@ bool BNPFileHandle::readHeader(const std::string &filename)
|
|||
}
|
||||
|
||||
nlfseek64 (f, 0, SEEK_END);
|
||||
uint32 nFileSize=CFile::getFileSize (filename );
|
||||
uint32 nFileSize=CFile::getFileSize (filePath );
|
||||
nlfseek64 (f, nFileSize-sizeof(uint32), SEEK_SET);
|
||||
|
||||
uint32 nOffsetFromBegining;
|
||||
|
@ -162,6 +168,7 @@ bool BNPFileHandle::readHeader(const std::string &filename)
|
|||
sName[nStringSize] = 0;
|
||||
PackedFile tmpPackedFile;
|
||||
tmpPackedFile.m_name = sName;
|
||||
tmpPackedFile.m_path = m_openedBNPFile;
|
||||
if (fread (&tmpPackedFile.m_size, sizeof(uint32), 1, f) != 1)
|
||||
{
|
||||
nlwarning("Error reading packed file size!");
|
||||
|
@ -196,9 +203,186 @@ void BNPFileHandle::list(TPackedFilesList& FileList)
|
|||
tmpFile.m_name = it->m_name;
|
||||
tmpFile.m_pos = it->m_pos;
|
||||
tmpFile.m_size = it->m_size;
|
||||
tmpFile.m_path = it->m_path;
|
||||
FileList.push_back(tmpFile);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// ***************************************************************************
|
||||
bool BNPFileHandle::writeHeader( const std::string &filePath, uint32 offset )
|
||||
{
|
||||
FILE *f = fopen (filePath.c_str(), "ab");
|
||||
if (f == NULL) return false;
|
||||
|
||||
uint32 nNbFile = (uint32)m_packedFiles.size();
|
||||
if (fwrite (&nNbFile, sizeof(uint32), 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < nNbFile; ++i)
|
||||
{
|
||||
uint8 nStringSize = (uint8)m_packedFiles[i].m_name.size();
|
||||
if (fwrite (&nStringSize, 1, 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fwrite (m_packedFiles[i].m_name.c_str(), 1, nStringSize, f) != nStringSize)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fwrite (&m_packedFiles[i].m_size, sizeof(uint32), 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fwrite (&m_packedFiles[i].m_pos, sizeof(uint32), 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fwrite (&offset, sizeof(uint32), 1, f) != 1)
|
||||
{
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
return true;
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPFileHandle::fileNames(std::vector<std::string> &fileNames)
|
||||
{
|
||||
TPackedFilesList::iterator it = m_packedFiles.begin();
|
||||
while (it != m_packedFiles.end() )
|
||||
{
|
||||
fileNames.push_back(it->m_name);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPFileHandle::addFiles( const vector<string> &filePathes)
|
||||
{
|
||||
uint32 OffsetFromBegining = 0;
|
||||
|
||||
// create packed files and add them to the private vector
|
||||
vector<string>::const_iterator it_vec = filePathes.begin();
|
||||
while (it_vec != filePathes.end() )
|
||||
{
|
||||
PackedFile tmpFile;
|
||||
tmpFile.m_name = CFile::getFilename (*it_vec);
|
||||
// Leave position to 0 and set the value during the new bnp file is creating
|
||||
// We need the position only for the header at the end
|
||||
tmpFile.m_pos = 0;
|
||||
tmpFile.m_size = CFile::getFileSize(*it_vec);
|
||||
tmpFile.m_path = *it_vec;
|
||||
m_packedFiles.push_back( tmpFile );
|
||||
|
||||
it_vec++;
|
||||
}
|
||||
|
||||
// sort packed files alphabetic
|
||||
std::sort ( m_packedFiles.begin(), m_packedFiles.end(), compare );
|
||||
|
||||
// create a new temporary bnp file with extension *.tmp
|
||||
TPackedFilesList::iterator it_packed = m_packedFiles.begin();
|
||||
while (it_packed != m_packedFiles.end() )
|
||||
{
|
||||
append(m_openedBNPFile + ".tmp", *it_packed);
|
||||
// Set now the new offset for the new header
|
||||
it_packed->m_pos = OffsetFromBegining;
|
||||
OffsetFromBegining += it_packed->m_size;
|
||||
|
||||
it_packed++;
|
||||
}
|
||||
|
||||
writeHeader(m_openedBNPFile + ".tmp", OffsetFromBegining);
|
||||
|
||||
CFile::deleteFile( m_openedBNPFile );
|
||||
string src = m_openedBNPFile + ".tmp";
|
||||
CFile::moveFile( m_openedBNPFile.c_str(), src.c_str() );
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPFileHandle::deleteFiles( const vector<string>& fileNames)
|
||||
{
|
||||
vector<string>::const_iterator it_vec;
|
||||
TPackedFilesList::iterator it_packed;
|
||||
uint32 OffsetFromBegining = 0;
|
||||
string tmpFile = m_openedBNPFile + ".tmp";
|
||||
|
||||
// create a new temporary bnp file with extension *.tmp
|
||||
it_packed = m_packedFiles.begin();
|
||||
while (it_packed != m_packedFiles.end() )
|
||||
{
|
||||
// check each packed file if it should be deleted
|
||||
it_vec = find (fileNames.begin(), fileNames.end(), it_packed->m_name );
|
||||
if ( it_vec != fileNames.end() )
|
||||
{
|
||||
nlinfo("Deleting file %s.", it_packed->m_name.c_str() );
|
||||
it_packed = m_packedFiles.erase(it_packed);
|
||||
}
|
||||
else
|
||||
{
|
||||
append(tmpFile, *it_packed);
|
||||
// Set now the new offset for the new header
|
||||
it_packed->m_pos = OffsetFromBegining;
|
||||
OffsetFromBegining += it_packed->m_size;
|
||||
|
||||
it_packed++;
|
||||
}
|
||||
}
|
||||
nldebug("Writing header...");
|
||||
|
||||
writeHeader(tmpFile, OffsetFromBegining);
|
||||
|
||||
CFile::deleteFile( m_openedBNPFile );
|
||||
string src = m_openedBNPFile + ".tmp";
|
||||
CFile::moveFile( m_openedBNPFile.c_str(), src.c_str() );
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPFileHandle::append(const string &destination, const PackedFile &source)
|
||||
{
|
||||
// check if the file exists and create one if not
|
||||
if ( !CFile::fileExists(destination) )
|
||||
CFile::createEmptyFile( destination );
|
||||
|
||||
FILE *bnpfile = fopen(destination.c_str(), "ab");
|
||||
FILE *packedfile = fopen(source.m_path.c_str(), "rb");
|
||||
if (bnpfile == NULL) return;
|
||||
if (packedfile == NULL) { fclose(bnpfile); return; }
|
||||
|
||||
uint8 *ptr = new uint8[source.m_size];
|
||||
|
||||
// check if the source is a bnp file.
|
||||
if ( nlstricmp( CFile::getExtension(source.m_path), "bnp" ) == 0 )
|
||||
{
|
||||
// Jump to the file position inside the bnp
|
||||
nlfseek64(packedfile, source.m_pos, SEEK_SET);
|
||||
}
|
||||
// Read the source
|
||||
if (fread (ptr, source.m_size, 1, packedfile) != 1)
|
||||
nlwarning("%s read error", source.m_path.c_str());
|
||||
|
||||
// Append the data to the destination
|
||||
if (fwrite (ptr, source.m_size, 1, bnpfile) != 1)
|
||||
nlwarning("%s write error", destination.c_str());
|
||||
|
||||
delete [] ptr;
|
||||
|
||||
fclose(packedfile);
|
||||
fclose(bnpfile);
|
||||
}
|
||||
// ***************************************************************************
|
||||
bool BNPFileHandle::compare(const PackedFile &left, const PackedFile &right)
|
||||
{
|
||||
return nlstricmp (left.m_name.c_str(), right.m_name.c_str()) < 0;
|
||||
}
|
||||
} // namespace BNPManager
|
|
@ -32,9 +32,11 @@ namespace BNPManager
|
|||
|
||||
struct PackedFile
|
||||
{
|
||||
PackedFile();
|
||||
std::string m_name;
|
||||
uint32 m_size;
|
||||
uint32 m_pos;
|
||||
std::string m_path;
|
||||
};
|
||||
|
||||
typedef std::vector<PackedFile> TPackedFilesList;
|
||||
|
@ -64,7 +66,9 @@ public:
|
|||
* Read the header from the bnp file and create a filelist
|
||||
* \param filename (consisting the whole path)
|
||||
*/
|
||||
bool readHeader (const std::string &filename);
|
||||
bool readHeader (const std::string &filePath);
|
||||
|
||||
bool writeHeader (const std::string &filePath, uint32 offset);
|
||||
|
||||
/**
|
||||
* Append the header to a created bnp file
|
||||
|
@ -73,11 +77,29 @@ public:
|
|||
void appendHeader (const std::string &filename) {};
|
||||
|
||||
/**
|
||||
* Create a list of all packed files inside the bnp file
|
||||
* \param reference to the list, which has to be filled
|
||||
* Create a vector of all packed files inside the bnp file
|
||||
* \param reference to the vector, which has to be filled
|
||||
*/
|
||||
void list (TPackedFilesList& FileList);
|
||||
|
||||
/**
|
||||
* Create a vector of all file names inside the bnp file
|
||||
* \param reference to the vector, which has to be filled
|
||||
*/
|
||||
void fileNames( std::vector<std::string>& fileNames );
|
||||
|
||||
/**
|
||||
* Add files to the current aktive bnp file
|
||||
* \param vector of file pathes to add
|
||||
*/
|
||||
void addFiles( const std::vector<std::string>& filePathes );
|
||||
|
||||
/**
|
||||
* Delete files from the current aktive bnp file
|
||||
* \param vector of files names
|
||||
*/
|
||||
void deleteFiles (const std::vector<std::string>& fileNames);
|
||||
|
||||
/**
|
||||
* Unpack the selected packed files into user defined dir
|
||||
* \param directory path, where the files should be unpacked
|
||||
|
@ -85,19 +107,33 @@ public:
|
|||
*/
|
||||
bool unpack (const std::string &dirName, const std::vector<std::string>& fileList);
|
||||
|
||||
/**
|
||||
* Compares two filenames
|
||||
* \param left: left packed file
|
||||
* \param right: right packed file
|
||||
* \return: TODO
|
||||
*/
|
||||
static bool compare(const PackedFile &left, const PackedFile &right);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Append one file to an existing bnp file
|
||||
* \param destination: the active bnp file to append the file
|
||||
* \param source: the source file to pack
|
||||
*/
|
||||
void append( const std::string& destination, const PackedFile& source );
|
||||
|
||||
TPackedFilesList m_packedFiles;
|
||||
|
||||
// currently opened and displayed bnp file
|
||||
std::string m_activeBNPFile;
|
||||
std::string m_openedBNPFile;
|
||||
|
||||
// offset where the header of the bnp file begins
|
||||
uint32 m_offsetFromBeginning;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
// NeL includes
|
||||
#include <nel/misc/debug.h>
|
||||
#include <nel/misc/path.h>
|
||||
|
||||
// Qt includes
|
||||
#include <QDebug>
|
||||
|
@ -153,9 +154,11 @@ void BNPManagerWindow::open()
|
|||
fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open BNP file"), tr(m_DataPath.toStdString().c_str()), tr("BNP Files (*.bnp)"));
|
||||
|
||||
// check if there is a filename
|
||||
// Check if filename is empty
|
||||
if (fileName.isNull())
|
||||
return;
|
||||
|
||||
m_openedBNPFile = fileName;
|
||||
loadFile(fileName);
|
||||
}
|
||||
// ***************************************************************************
|
||||
|
@ -166,12 +169,73 @@ void BNPManagerWindow::close()
|
|||
// ***************************************************************************
|
||||
void BNPManagerWindow::addFiles()
|
||||
{
|
||||
//TODO
|
||||
// reference to the BNPFileHandle singletone instance
|
||||
BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance();
|
||||
|
||||
// vector of all current packed filenames
|
||||
vector<string> currentFiles;
|
||||
|
||||
// vector of files to add
|
||||
vector<string> addFiles;
|
||||
|
||||
// open a file dialog and to add files
|
||||
QStringList FileList;
|
||||
|
||||
FileList = QFileDialog::getOpenFileNames(this,tr("Add Files..."),
|
||||
QDir::currentPath(), tr("All Files (*.*)") );
|
||||
|
||||
// get all current filenames from the opened bnp file
|
||||
myBNPFileHandle.fileNames(currentFiles);
|
||||
|
||||
QStringList::iterator it_list = FileList.begin();
|
||||
while (it_list != FileList.end() )
|
||||
{
|
||||
string fileName = CFile::getFilename (it_list->toStdString() );
|
||||
if ( std::find(currentFiles.begin(), currentFiles.end(), fileName ) != currentFiles.end() )
|
||||
{
|
||||
// Ask the user if he wants to override the existing file
|
||||
// atm only warn the user and do not override
|
||||
QMessageBox::warning(this, tr("BNP Manager"),
|
||||
tr("File is already in the list!"),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
addFiles.push_back( it_list->toStdString() );
|
||||
// log it
|
||||
nlinfo("Add file %s", fileName.c_str() );
|
||||
}
|
||||
it_list++;
|
||||
}
|
||||
|
||||
if ( !addFiles.empty() )
|
||||
{
|
||||
myBNPFileHandle.addFiles( addFiles );
|
||||
}
|
||||
loadFile(m_openedBNPFile);
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPManagerWindow::deleteFiles()
|
||||
{
|
||||
//TODO
|
||||
QFileDialog filedialog(this);
|
||||
BNPFileHandle& myBNPFileHandle = BNPFileHandle::getInstance();
|
||||
vector<string> selectedRows;
|
||||
|
||||
m_BnpFileListDialog->getSelections(selectedRows);
|
||||
|
||||
// Check if files were selected. If not, inform the user.
|
||||
if (selectedRows.empty())
|
||||
{
|
||||
QMessageBox::information(this, tr("BNP Manager"),
|
||||
tr("No files selected!"),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
myBNPFileHandle.deleteFiles(selectedRows);
|
||||
loadFile(m_openedBNPFile);
|
||||
}
|
||||
// ***************************************************************************
|
||||
void BNPManagerWindow::unpackFiles()
|
||||
|
@ -188,7 +252,7 @@ void BNPManagerWindow::unpackFiles()
|
|||
if (selectedrows.empty())
|
||||
{
|
||||
QMessageBox::information(this, tr("BNP Manager"),
|
||||
tr("No files were selected to unpack!"),
|
||||
tr("No files selected!"),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
|
@ -199,6 +263,10 @@ void BNPManagerWindow::unpackFiles()
|
|||
QFileDialog::ShowDirsOnly
|
||||
| QFileDialog::DontResolveSymlinks);
|
||||
|
||||
// If anything went wrong or the user pressed "cancel"
|
||||
if ( dir.isEmpty() )
|
||||
return;
|
||||
|
||||
if (myBNPFileHandle.unpack(dir.toStdString(),selectedrows))
|
||||
{
|
||||
QMessageBox::information(this, tr("BNP Manager"),
|
||||
|
|
|
@ -136,8 +136,7 @@ private:
|
|||
BnpFileListDialog *m_BnpFileListDialog;
|
||||
|
||||
QString m_DataPath;
|
||||
|
||||
BNPFileHandle *m_BNPFileHandle;
|
||||
QString m_openedBNPFile;
|
||||
|
||||
}; /* class BNPManagerWindow */
|
||||
|
||||
|
|
Loading…
Reference in a new issue