Added: Implemented bnp_manager_plugin add and delete files

--HG--
branch : branch-bnp-manager-plugin
This commit is contained in:
Krolock 2012-01-11 20:54:54 +01:00
parent e61e79eee3
commit ba66f5e070
4 changed files with 306 additions and 19 deletions

View file

@ -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

View file

@ -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,10 +77,28 @@ 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
@ -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

View file

@ -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;
@ -198,6 +262,10 @@ void BNPManagerWindow::unpackFiles()
tr(m_DataPath.toStdString().c_str()),
QFileDialog::ShowDirsOnly
| QFileDialog::DontResolveSymlinks);
// If anything went wrong or the user pressed "cancel"
if ( dir.isEmpty() )
return;
if (myBNPFileHandle.unpack(dir.toStdString(),selectedrows))
{

View file

@ -101,11 +101,11 @@ private:
/**
* Read plugin settings and set the window accordingly
*/
void readSettings();
void readSettings();
/**
* Write plugin settings
*/
*/
void writeSettings();
/**
@ -136,8 +136,7 @@ private:
BnpFileListDialog *m_BnpFileListDialog;
QString m_DataPath;
BNPFileHandle *m_BNPFileHandle;
QString m_openedBNPFile;
}; /* class BNPManagerWindow */