mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-18 18:40:06 +00:00
Merge branch 'next' of git://github.com/zinnschlag/openmw into next
This commit is contained in:
commit
e4717d7c92
@ -23,8 +23,7 @@ struct ESMData
|
|||||||
std::string author;
|
std::string author;
|
||||||
std::string description;
|
std::string description;
|
||||||
int version;
|
int version;
|
||||||
int type;
|
std::vector<ESM::Header::MasterData> masters;
|
||||||
ESM::ESMReader::MasterList masters;
|
|
||||||
|
|
||||||
std::deque<EsmTool::RecordBase *> mRecords;
|
std::deque<EsmTool::RecordBase *> mRecords;
|
||||||
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
|
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
|
||||||
@ -284,16 +283,13 @@ int load(Arguments& info)
|
|||||||
info.data.author = esm.getAuthor();
|
info.data.author = esm.getAuthor();
|
||||||
info.data.description = esm.getDesc();
|
info.data.description = esm.getDesc();
|
||||||
info.data.masters = esm.getMasters();
|
info.data.masters = esm.getMasters();
|
||||||
info.data.version = esm.getVer();
|
|
||||||
info.data.type = esm.getType();
|
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
{
|
{
|
||||||
std::cout << "Author: " << esm.getAuthor() << std::endl
|
std::cout << "Author: " << esm.getAuthor() << std::endl
|
||||||
<< "Description: " << esm.getDesc() << std::endl
|
<< "Description: " << esm.getDesc() << std::endl
|
||||||
<< "File format version: " << esm.getFVer() << std::endl
|
<< "File format version: " << esm.getFVer() << std::endl;
|
||||||
<< "Special flag: " << esm.getSpecial() << std::endl;
|
std::vector<ESM::Header::MasterData> m = esm.getMasters();
|
||||||
ESM::ESMReader::MasterList m = esm.getMasters();
|
|
||||||
if (!m.empty())
|
if (!m.empty())
|
||||||
{
|
{
|
||||||
std::cout << "Masters:" << std::endl;
|
std::cout << "Masters:" << std::endl;
|
||||||
@ -430,9 +426,9 @@ int clone(Arguments& info)
|
|||||||
esm.setAuthor(info.data.author);
|
esm.setAuthor(info.data.author);
|
||||||
esm.setDescription(info.data.description);
|
esm.setDescription(info.data.description);
|
||||||
esm.setVersion(info.data.version);
|
esm.setVersion(info.data.version);
|
||||||
esm.setType(info.data.type);
|
esm.setRecordCount (recordCount);
|
||||||
|
|
||||||
for (ESM::ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
|
for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
|
||||||
esm.addMaster(it->name, it->size);
|
esm.addMaster(it->name, it->size);
|
||||||
|
|
||||||
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
|
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
set (OPENCS_SRC main.cpp)
|
set (OPENCS_SRC main.cpp)
|
||||||
|
|
||||||
opencs_units (. editor)
|
opencs_units (. editor)
|
||||||
|
@ -113,5 +113,7 @@ int CS::Editor::run()
|
|||||||
{
|
{
|
||||||
mStartup.show();
|
mStartup.show();
|
||||||
|
|
||||||
|
QApplication::setQuitOnLastWindowClosed (true);
|
||||||
|
|
||||||
return QApplication::exec();
|
return QApplication::exec();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <QDebug>
|
||||||
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
||||||
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
||||||
{
|
{
|
||||||
@ -237,6 +237,9 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
|
|||||||
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::Document::~Document()
|
||||||
|
{}
|
||||||
|
|
||||||
QUndoStack& CSMDoc::Document::getUndoStack()
|
QUndoStack& CSMDoc::Document::getUndoStack()
|
||||||
{
|
{
|
||||||
return mUndoStack;
|
return mUndoStack;
|
||||||
@ -290,11 +293,13 @@ void CSMDoc::Document::abortOperation (int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::modificationStateChanged (bool clean)
|
void CSMDoc::Document::modificationStateChanged (bool clean)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type)
|
void CSMDoc::Document::operationDone (int type)
|
||||||
{
|
{
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
@ -308,9 +313,12 @@ void CSMDoc::Document::saving()
|
|||||||
|
|
||||||
if (mSaveCount>15)
|
if (mSaveCount>15)
|
||||||
{
|
{
|
||||||
|
//clear the stack before resetting the save state
|
||||||
|
//to avoid emitting incorrect states
|
||||||
|
mUndoStack.setClean();
|
||||||
|
|
||||||
mSaveCount = 0;
|
mSaveCount = 0;
|
||||||
mSaveTimer.stop();
|
mSaveTimer.stop();
|
||||||
mUndoStack.setClean();
|
|
||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ namespace CSMDoc
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const std::vector<boost::filesystem::path>& files, bool new_);
|
Document (const std::vector<boost::filesystem::path>& files, bool new_);
|
||||||
|
~Document();
|
||||||
|
|
||||||
QUndoStack& getUndoStack();
|
QUndoStack& getUndoStack();
|
||||||
|
|
||||||
@ -105,4 +106,4 @@ namespace CSMDoc
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,7 +56,7 @@ void CSVDoc::Operations::quitOperation (int type)
|
|||||||
|
|
||||||
mLayout->removeItem ((*iter)->getLayout());
|
mLayout->removeItem ((*iter)->getLayout());
|
||||||
|
|
||||||
delete *iter;
|
(*iter)->deleteLater();
|
||||||
mOperations.erase (iter);
|
mOperations.erase (iter);
|
||||||
|
|
||||||
if (oldCount > 1)
|
if (oldCount > 1)
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QMdiArea>
|
#include <QMdiArea>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
|
||||||
#include "../../model/doc/document.hpp"
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
@ -39,6 +40,16 @@ void CSVDoc::View::setupFileMenu()
|
|||||||
mSave = new QAction (tr ("&Save"), this);
|
mSave = new QAction (tr ("&Save"), this);
|
||||||
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
|
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
|
||||||
file->addAction (mSave);
|
file->addAction (mSave);
|
||||||
|
|
||||||
|
QAction *close = new QAction (tr ("&Close"), this);
|
||||||
|
connect (close, SIGNAL (triggered()), this, SLOT (close()));
|
||||||
|
file->addAction(close);
|
||||||
|
|
||||||
|
QAction *exit = new QAction (tr ("&Exit"), this);
|
||||||
|
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
|
||||||
|
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
|
||||||
|
|
||||||
|
file->addAction(exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::setupEditMenu()
|
void CSVDoc::View::setupEditMenu()
|
||||||
@ -117,15 +128,15 @@ void CSVDoc::View::updateActions()
|
|||||||
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
|
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent)
|
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
|
||||||
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent)
|
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
|
||||||
|
mViewTotal (totalViews)
|
||||||
{
|
{
|
||||||
setDockOptions (QMainWindow::AllowNestedDocks);
|
|
||||||
|
|
||||||
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
|
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
|
||||||
|
|
||||||
mSubViewWindow = new QMainWindow();
|
mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
|
||||||
setCentralWidget (mSubViewWindow);
|
|
||||||
|
setCentralWidget (&mSubViewWindow);
|
||||||
|
|
||||||
mOperations = new Operations;
|
mOperations = new Operations;
|
||||||
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
addDockWidget (Qt::BottomDockWidgetArea, mOperations);
|
||||||
@ -200,7 +211,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
|
|||||||
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
|
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
|
||||||
|
|
||||||
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
|
||||||
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view);
|
mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
|
||||||
|
|
||||||
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
|
||||||
SLOT (addSubView (const CSMWorld::UniversalId&)));
|
SLOT (addSubView (const CSMWorld::UniversalId&)));
|
||||||
@ -239,7 +250,12 @@ void CSVDoc::View::abortOperation (int type)
|
|||||||
updateActions();
|
updateActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDockWidget *CSVDoc::View::getOperations() const
|
CSVDoc::Operations *CSVDoc::View::getOperations() const
|
||||||
{
|
{
|
||||||
return mOperations;
|
return mOperations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::View::exit()
|
||||||
|
{
|
||||||
|
emit exitApplicationRequest (this);
|
||||||
|
}
|
||||||
|
@ -41,7 +41,8 @@ namespace CSVDoc
|
|||||||
std::vector<QAction *> mEditingActions;
|
std::vector<QAction *> mEditingActions;
|
||||||
Operations *mOperations;
|
Operations *mOperations;
|
||||||
SubViewFactoryManager mSubViewFactory;
|
SubViewFactoryManager mSubViewFactory;
|
||||||
QMainWindow* mSubViewWindow;
|
QMainWindow mSubViewWindow;
|
||||||
|
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
View (const View&);
|
View (const View&);
|
||||||
@ -65,9 +66,12 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void updateActions();
|
void updateActions();
|
||||||
|
|
||||||
|
void exitApplication();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent);
|
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
|
||||||
|
|
||||||
///< The ownership of \a document is not transferred to *this.
|
///< The ownership of \a document is not transferred to *this.
|
||||||
|
|
||||||
virtual ~View();
|
virtual ~View();
|
||||||
@ -82,7 +86,7 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void updateProgress (int current, int max, int type, int threads);
|
void updateProgress (int current, int max, int type, int threads);
|
||||||
|
|
||||||
QDockWidget *getOperations() const;
|
Operations *getOperations() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
@ -90,23 +94,28 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void loadDocumentRequest();
|
void loadDocumentRequest();
|
||||||
|
|
||||||
|
void exitApplicationRequest (CSVDoc::View *view);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void addSubView (const CSMWorld::UniversalId& id);
|
void addSubView (const CSMWorld::UniversalId& id);
|
||||||
|
|
||||||
|
void abortOperation (int type);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void newView();
|
void newView();
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
|
void exit();
|
||||||
|
|
||||||
void verify();
|
void verify();
|
||||||
|
|
||||||
void addGlobalsSubView();
|
void addGlobalsSubView();
|
||||||
|
|
||||||
void addGmstsSubView();
|
void addGmstsSubView();
|
||||||
|
|
||||||
void abortOperation (int type);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
|
|
||||||
#include "view.hpp"
|
#include "view.hpp"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QtGui/QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
void CSVDoc::ViewManager::updateIndices()
|
void CSVDoc::ViewManager::updateIndices()
|
||||||
{
|
{
|
||||||
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
|
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
|
||||||
@ -31,7 +36,7 @@ void CSVDoc::ViewManager::updateIndices()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
||||||
: mDocumentManager (documentManager)
|
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
|
||||||
{
|
{
|
||||||
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
||||||
|
|
||||||
@ -40,7 +45,6 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
|||||||
|
|
||||||
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
|
||||||
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
|
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSVDoc::ViewManager::~ViewManager()
|
CSVDoc::ViewManager::~ViewManager()
|
||||||
@ -63,9 +67,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
|||||||
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
|
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMainWindow *mainWindow = new QMainWindow;
|
View *view = new View (*this, document, countViews (document)+1);
|
||||||
|
|
||||||
View *view = new View (*this, document, countViews (document)+1, mainWindow);
|
|
||||||
|
|
||||||
mViews.push_back (view);
|
mViews.push_back (view);
|
||||||
|
|
||||||
@ -94,23 +97,143 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
|
|||||||
{
|
{
|
||||||
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
|
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
|
||||||
|
|
||||||
|
bool continueWithClose = true;
|
||||||
|
|
||||||
if (iter!=mViews.end())
|
if (iter!=mViews.end())
|
||||||
{
|
{
|
||||||
bool last = countViews (view->getDocument())<=1;
|
bool last = countViews (view->getDocument())<=1;
|
||||||
|
|
||||||
/// \todo check if save is in progress -> warn user about possible data loss
|
|
||||||
/// \todo check if document has not been saved -> return false and start close dialogue
|
|
||||||
|
|
||||||
mViews.erase (iter);
|
|
||||||
view->deleteLater();
|
|
||||||
|
|
||||||
if (last)
|
if (last)
|
||||||
mDocumentManager.removeDocument (view->getDocument());
|
continueWithClose = notifySaveOnClose (view);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
(*iter)->deleteLater();
|
||||||
|
mViews.erase (iter);
|
||||||
|
|
||||||
updateIndices();
|
updateIndices();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return continueWithClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
//notify user of saving in progress
|
||||||
|
if ( (document->getState() & CSMDoc::State_Saving) )
|
||||||
|
result = showSaveInProgressMessageBox (view);
|
||||||
|
|
||||||
|
//notify user of unsaved changes and process response
|
||||||
|
else if ( document->getState() & CSMDoc::State_Modified)
|
||||||
|
result = showModifiedDocumentMessageBox (view);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
QMessageBox messageBox;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
messageBox.setText ("The document has been modified.");
|
||||||
|
messageBox.setInformativeText ("Do you want to save your changes?");
|
||||||
|
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||||
|
messageBox.setDefaultButton (QMessageBox::Save);
|
||||||
|
|
||||||
|
bool retVal = true;
|
||||||
|
|
||||||
|
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
|
||||||
|
|
||||||
|
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
|
||||||
|
mUserWarned = true;
|
||||||
|
int response = messageBox.exec();
|
||||||
|
mUserWarned = false;
|
||||||
|
|
||||||
|
switch (response)
|
||||||
|
{
|
||||||
|
case QMessageBox::Save:
|
||||||
|
|
||||||
|
document->save();
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
retVal = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMessageBox::Discard:
|
||||||
|
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
|
||||||
|
//disconnect to prevent unintended view closures
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
retVal = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
QMessageBox messageBox;
|
||||||
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
|
messageBox.setText ("The document is currently being saved.");
|
||||||
|
messageBox.setInformativeText("Do you want to close now and abort saving, or wait until saving has completed?");
|
||||||
|
|
||||||
|
QPushButton* waitButton = messageBox.addButton (tr("Wait"), QMessageBox::YesRole);
|
||||||
|
QPushButton* closeButton = messageBox.addButton (tr("Close Now"), QMessageBox::RejectRole);
|
||||||
|
QPushButton* cancelButton = messageBox.addButton (tr("Cancel"), QMessageBox::NoRole);
|
||||||
|
|
||||||
|
messageBox.setDefaultButton (waitButton);
|
||||||
|
|
||||||
|
bool retVal = true;
|
||||||
|
|
||||||
|
//Connections shut down message box if operation ends before user makes a decision.
|
||||||
|
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
|
||||||
|
|
||||||
|
//set / clear the user warned flag to indicate whether or not the message box is currently active.
|
||||||
|
mUserWarned = true;
|
||||||
|
messageBox.exec();
|
||||||
|
mUserWarned = false;
|
||||||
|
|
||||||
|
//if closed by the warning handler, defaults to the RejectRole button (closeButton)
|
||||||
|
if (messageBox.clickedButton() == waitButton)
|
||||||
|
{
|
||||||
|
//save the View iterator for shutdown after the save operation ends
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
retVal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (messageBox.clickedButton() == closeButton)
|
||||||
|
{
|
||||||
|
//disconnect to avoid segmentation fault
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
|
||||||
|
view->abortOperation(CSMDoc::State_Saving);
|
||||||
|
mExitOnSaveStateChange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (messageBox.clickedButton() == cancelButton)
|
||||||
|
{
|
||||||
|
//abort shutdown, allow save to complete
|
||||||
|
//disconnection to prevent unintended view closures
|
||||||
|
mExitOnSaveStateChange = false;
|
||||||
|
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
|
||||||
|
retVal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
|
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
|
||||||
@ -126,3 +249,25 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
|
|||||||
if ((*iter)->getDocument()==document)
|
if ((*iter)->getDocument()==document)
|
||||||
(*iter)->updateProgress (current, max, type, threads);
|
(*iter)->updateProgress (current, max, type, threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
if ( !(state & CSMDoc::State_Saving) )
|
||||||
|
{
|
||||||
|
//if the user is being warned (message box is active), shut down the message box,
|
||||||
|
//as there is no save operation currently running
|
||||||
|
if ( mUserWarned )
|
||||||
|
emit closeMessageBox();
|
||||||
|
|
||||||
|
//otherwise, the user has closed the message box before the save operation ended.
|
||||||
|
//exit the application
|
||||||
|
else if (mExitOnSaveStateChange)
|
||||||
|
QApplication::instance()->exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
|
||||||
|
{
|
||||||
|
if (notifySaveOnClose (view))
|
||||||
|
QApplication::instance()->exit();
|
||||||
|
}
|
||||||
|
@ -27,12 +27,17 @@ namespace CSVDoc
|
|||||||
CSMDoc::DocumentManager& mDocumentManager;
|
CSMDoc::DocumentManager& mDocumentManager;
|
||||||
std::vector<View *> mViews;
|
std::vector<View *> mViews;
|
||||||
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
|
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
|
||||||
|
bool mExitOnSaveStateChange;
|
||||||
|
bool mUserWarned;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
ViewManager (const ViewManager&);
|
ViewManager (const ViewManager&);
|
||||||
ViewManager& operator= (const ViewManager&);
|
ViewManager& operator= (const ViewManager&);
|
||||||
|
|
||||||
void updateIndices();
|
void updateIndices();
|
||||||
|
bool notifySaveOnClose (View *view = 0);
|
||||||
|
bool showModifiedDocumentMessageBox (View *view);
|
||||||
|
bool showSaveInProgressMessageBox (View *view);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -54,13 +59,21 @@ namespace CSVDoc
|
|||||||
|
|
||||||
void loadDocumentRequest();
|
void loadDocumentRequest();
|
||||||
|
|
||||||
|
void closeMessageBox();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void exitApplication (CSVDoc::View *view);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void documentStateChanged (int state, CSMDoc::Document *document);
|
void documentStateChanged (int state, CSMDoc::Document *document);
|
||||||
|
|
||||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void onExitWarningHandler(int state, CSMDoc::Document* document);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,14 +27,15 @@ void ESMStore::load(ESM::ESMReader &esm)
|
|||||||
|
|
||||||
ESM::Dialogue *dialogue = 0;
|
ESM::Dialogue *dialogue = 0;
|
||||||
|
|
||||||
|
/// \todo Move this to somewhere else. ESMReader?
|
||||||
// Cache parent esX files by tracking their indices in the global list of
|
// Cache parent esX files by tracking their indices in the global list of
|
||||||
// all files/readers used by the engine. This will greaty accelerate
|
// all files/readers used by the engine. This will greaty accelerate
|
||||||
// refnumber mangling, as required for handling moved references.
|
// refnumber mangling, as required for handling moved references.
|
||||||
int index = ~0;
|
int index = ~0;
|
||||||
const ESM::ESMReader::MasterList &masters = esm.getMasters();
|
const std::vector<ESM::Header::MasterData> &masters = esm.getMasters();
|
||||||
std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
|
std::vector<ESM::ESMReader> *allPlugins = esm.getGlobalReaderList();
|
||||||
for (size_t j = 0; j < masters.size(); j++) {
|
for (size_t j = 0; j < masters.size(); j++) {
|
||||||
ESM::MasterData &mast = const_cast<ESM::MasterData&>(masters[j]);
|
ESM::Header::MasterData &mast = const_cast<ESM::Header::MasterData&>(masters[j]);
|
||||||
std::string fname = mast.name;
|
std::string fname = mast.name;
|
||||||
for (int i = 0; i < esm.getIndex(); i++) {
|
for (int i = 0; i < esm.getIndex(); i++) {
|
||||||
const std::string &candidate = allPlugins->at(i).getContext().filename;
|
const std::string &candidate = allPlugins->at(i).getContext().filename;
|
||||||
|
@ -39,7 +39,7 @@ add_component_dir (esm
|
|||||||
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
|
loadclas loadclot loadcont loadcrea loadcrec loaddial loaddoor loadench loadfact loadglob loadgmst
|
||||||
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
|
loadinfo loadingr loadland loadlevlist loadligh loadlocks loadltex loadmgef loadmisc loadnpcc
|
||||||
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
||||||
loadweap records aipackage effectlist spelllist variant variantimp
|
loadweap records aipackage effectlist spelllist variant variantimp loadtes3
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (misc
|
add_component_dir (misc
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define OPENMW_ESM_COMMON_H
|
#define OPENMW_ESM_COMMON_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include <libs/platform/stdint.h>
|
#include <libs/platform/stdint.h>
|
||||||
#include <libs/platform/string.h>
|
#include <libs/platform/string.h>
|
||||||
@ -14,24 +15,6 @@ enum Version
|
|||||||
VER_13 = 0x3fa66666
|
VER_13 = 0x3fa66666
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileType
|
|
||||||
{
|
|
||||||
FT_ESP = 0, // Plugin
|
|
||||||
FT_ESM = 1, // Master
|
|
||||||
FT_ESS = 32 // Savegame
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used to mark special files. The original ESM files are given
|
|
||||||
// special treatment in a few places, most noticably in loading and
|
|
||||||
// filtering out "dirtly" GMST entries correctly.
|
|
||||||
enum SpecialFile
|
|
||||||
{
|
|
||||||
SF_Other,
|
|
||||||
SF_Morrowind,
|
|
||||||
SF_Tribunal,
|
|
||||||
SF_Bloodmoon
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A structure used for holding fixed-length strings. In the case of
|
/* A structure used for holding fixed-length strings. In the case of
|
||||||
LEN=4, it can be more efficient to match the string as a 32 bit
|
LEN=4, it can be more efficient to match the string as a 32 bit
|
||||||
number, therefore the struct is implemented as a union with an int.
|
number, therefore the struct is implemented as a union with an int.
|
||||||
@ -41,7 +24,7 @@ union NAME_T
|
|||||||
{
|
{
|
||||||
char name[LEN];
|
char name[LEN];
|
||||||
int32_t val;
|
int32_t val;
|
||||||
|
|
||||||
bool operator==(const char *str) const
|
bool operator==(const char *str) const
|
||||||
{
|
{
|
||||||
for(int i=0; i<LEN; i++)
|
for(int i=0; i<LEN; i++)
|
||||||
@ -61,6 +44,8 @@ union NAME_T
|
|||||||
bool operator!=(int v) const { return v != val; }
|
bool operator!=(int v) const { return v != val; }
|
||||||
|
|
||||||
std::string toString() const { return std::string(name, strnlen(name, LEN)); }
|
std::string toString() const { return std::string(name, strnlen(name, LEN)); }
|
||||||
|
|
||||||
|
void assign (const std::string& value) { std::strncpy (name, value.c_str(), LEN); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NAME_T<4> NAME;
|
typedef NAME_T<4> NAME;
|
||||||
@ -70,28 +55,6 @@ typedef NAME_T<256> NAME256;
|
|||||||
|
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
/// File header data for all ES files
|
|
||||||
struct HEDRstruct
|
|
||||||
{
|
|
||||||
/* File format version. This is actually a float, the supported
|
|
||||||
versions are 1.2 and 1.3. These correspond to:
|
|
||||||
1.2 = 0x3f99999a and 1.3 = 0x3fa66666
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
int type; // 0=esp, 1=esm, 32=ess
|
|
||||||
NAME32 author; // Author's name
|
|
||||||
NAME256 desc; // File description
|
|
||||||
int records; // Number of records? Not used.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Defines another files (esm or esp) that this file depends upon.
|
|
||||||
struct MasterData
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
uint64_t size;
|
|
||||||
int index; // Position of the parent file in the global list of loaded files
|
|
||||||
};
|
|
||||||
|
|
||||||
// Data that is only present in save game files
|
// Data that is only present in save game files
|
||||||
struct SaveData
|
struct SaveData
|
||||||
{
|
{
|
||||||
@ -113,7 +76,6 @@ struct ESM_Context
|
|||||||
uint32_t leftRec, leftSub;
|
uint32_t leftRec, leftSub;
|
||||||
size_t leftFile;
|
size_t leftFile;
|
||||||
NAME recName, subName;
|
NAME recName, subName;
|
||||||
HEDRstruct header;
|
|
||||||
// When working with multiple esX files, we will generate lists of all files that
|
// When working with multiple esX files, we will generate lists of all files that
|
||||||
// actually contribute to a specific cell. Therefore, we need to store the index
|
// actually contribute to a specific cell. Therefore, we need to store the index
|
||||||
// of the file belonging to this contest. See CellStore::(list/load)refs for details.
|
// of the file belonging to this contest. See CellStore::(list/load)refs for details.
|
||||||
|
@ -15,11 +15,16 @@ ESM_Context ESMReader::getContext()
|
|||||||
return mCtx;
|
return mCtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESMReader::ESMReader(void):
|
ESMReader::ESMReader():
|
||||||
mBuffer(50*1024)
|
mBuffer(50*1024)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ESMReader::getFormat() const
|
||||||
|
{
|
||||||
|
return mHeader.mFormat;
|
||||||
|
}
|
||||||
|
|
||||||
void ESMReader::restoreContext(const ESM_Context &rc)
|
void ESMReader::restoreContext(const ESM_Context &rc)
|
||||||
{
|
{
|
||||||
// Reopen the file if necessary
|
// Reopen the file if necessary
|
||||||
@ -51,18 +56,6 @@ void ESMReader::openRaw(Ogre::DataStreamPtr _esm, const std::string &name)
|
|||||||
mEsm = _esm;
|
mEsm = _esm;
|
||||||
mCtx.filename = name;
|
mCtx.filename = name;
|
||||||
mCtx.leftFile = mEsm->size();
|
mCtx.leftFile = mEsm->size();
|
||||||
|
|
||||||
// Flag certain files for special treatment, based on the file
|
|
||||||
// name.
|
|
||||||
const char *cstr = mCtx.filename.c_str();
|
|
||||||
if (iends(cstr, "Morrowind.esm"))
|
|
||||||
mSpf = SF_Morrowind;
|
|
||||||
else if (iends(cstr, "Tribunal.esm"))
|
|
||||||
mSpf = SF_Tribunal;
|
|
||||||
else if (iends(cstr, "Bloodmoon.esm"))
|
|
||||||
mSpf = SF_Bloodmoon;
|
|
||||||
else
|
|
||||||
mSpf = SF_Other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
|
void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
|
||||||
@ -74,42 +67,7 @@ void ESMReader::open(Ogre::DataStreamPtr _esm, const std::string &name)
|
|||||||
|
|
||||||
getRecHeader();
|
getRecHeader();
|
||||||
|
|
||||||
// Get the header
|
mHeader.load (*this);
|
||||||
getHNT(mCtx.header, "HEDR", 300);
|
|
||||||
|
|
||||||
// Some mods abuse the header.version field for the version of the mod instead of the version of the file format, so we can only ignore it.
|
|
||||||
|
|
||||||
while (isNextSub("MAST"))
|
|
||||||
{
|
|
||||||
MasterData m;
|
|
||||||
m.name = getHString();
|
|
||||||
m.size = getHNLong("DATA");
|
|
||||||
mMasters.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCtx.header.type == FT_ESS)
|
|
||||||
{
|
|
||||||
// Savegame-related data
|
|
||||||
|
|
||||||
// Player position etc
|
|
||||||
getHNT(mSaveData, "GMDT", 124);
|
|
||||||
|
|
||||||
/* Image properties, five ints. Is always:
|
|
||||||
Red-mask: 0xff0000
|
|
||||||
Blue-mask: 0x00ff00
|
|
||||||
Green-mask: 0x0000ff
|
|
||||||
Alpha-mask: 0x000000
|
|
||||||
Bpp: 32
|
|
||||||
*/
|
|
||||||
getSubNameIs("SCRD");
|
|
||||||
skipHSubSize(20);
|
|
||||||
|
|
||||||
/* Savegame screenshot:
|
|
||||||
128x128 pixels * 4 bytes per pixel
|
|
||||||
*/
|
|
||||||
getSubNameIs("SCRS");
|
|
||||||
skipHSubSize(65536);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMReader::open(const std::string &file)
|
void ESMReader::open(const std::string &file)
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "esmcommon.hpp"
|
#include "esmcommon.hpp"
|
||||||
|
#include "loadtes3.hpp"
|
||||||
|
|
||||||
namespace ESM {
|
namespace ESM {
|
||||||
|
|
||||||
@ -20,15 +22,7 @@ class ESMReader
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ESMReader(void);
|
ESMReader();
|
||||||
|
|
||||||
/*************************************************************************
|
|
||||||
*
|
|
||||||
* Public type definitions
|
|
||||||
*
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
typedef std::vector<MasterData> MasterList;
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
*
|
*
|
||||||
@ -36,14 +30,12 @@ public:
|
|||||||
*
|
*
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
int getVer() const { return mCtx.header.version; }
|
int getVer() const { return mHeader.mData.version; }
|
||||||
float getFVer() const { if(mCtx.header.version == VER_12) return 1.2; else return 1.3; }
|
float getFVer() const { if(mHeader.mData.version == VER_12) return 1.2; else return 1.3; }
|
||||||
int getSpecial() const { return mSpf; }
|
const std::string getAuthor() const { return mHeader.mData.author.toString(); }
|
||||||
int getType() const { return mCtx.header.type; }
|
const std::string getDesc() const { return mHeader.mData.desc.toString(); }
|
||||||
const std::string getAuthor() const { return mCtx.header.author.toString(); }
|
const std::vector<Header::MasterData> &getMasters() const { return mHeader.mMaster; }
|
||||||
const std::string getDesc() const { return mCtx.header.desc.toString(); }
|
int getFormat() const;
|
||||||
const SaveData &getSaveData() const { return mSaveData; }
|
|
||||||
const MasterList &getMasters() const { return mMasters; }
|
|
||||||
const NAME &retSubName() const { return mCtx.subName; }
|
const NAME &retSubName() const { return mCtx.subName; }
|
||||||
uint32_t getSubSize() const { return mCtx.leftSub; }
|
uint32_t getSubSize() const { return mCtx.leftSub; }
|
||||||
|
|
||||||
@ -263,13 +255,12 @@ private:
|
|||||||
ESM_Context mCtx;
|
ESM_Context mCtx;
|
||||||
|
|
||||||
// Special file signifier (see SpecialFile enum above)
|
// Special file signifier (see SpecialFile enum above)
|
||||||
int mSpf;
|
|
||||||
|
|
||||||
// Buffer for ESM strings
|
// Buffer for ESM strings
|
||||||
std::vector<char> mBuffer;
|
std::vector<char> mBuffer;
|
||||||
|
|
||||||
SaveData mSaveData;
|
Header mHeader;
|
||||||
MasterList mMasters;
|
|
||||||
std::vector<ESMReader> *mGlobalReaderList;
|
std::vector<ESMReader> *mGlobalReaderList;
|
||||||
ToUTF8::Utf8Encoder* mEncoder;
|
ToUTF8::Utf8Encoder* mEncoder;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "esmwriter.hpp"
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <iostream>
|
||||||
|
|
||||||
bool count = true;
|
bool count = true;
|
||||||
|
|
||||||
@ -9,40 +11,40 @@ namespace ESM
|
|||||||
|
|
||||||
int ESMWriter::getVersion()
|
int ESMWriter::getVersion()
|
||||||
{
|
{
|
||||||
return m_header.version;
|
return mHeader.mData.version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setVersion(int ver)
|
void ESMWriter::setVersion(int ver)
|
||||||
{
|
{
|
||||||
m_header.version = ver;
|
mHeader.mData.version = ver;
|
||||||
}
|
|
||||||
|
|
||||||
int ESMWriter::getType()
|
|
||||||
{
|
|
||||||
return m_header.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ESMWriter::setType(int type)
|
|
||||||
{
|
|
||||||
m_header.type = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setAuthor(const std::string& auth)
|
void ESMWriter::setAuthor(const std::string& auth)
|
||||||
{
|
{
|
||||||
strncpy((char*)&m_header.author, auth.c_str(), 32);
|
mHeader.mData.author.assign (auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::setDescription(const std::string& desc)
|
void ESMWriter::setDescription(const std::string& desc)
|
||||||
{
|
{
|
||||||
strncpy((char*)&m_header.desc, desc.c_str(), 256);
|
mHeader.mData.desc.assign (desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESMWriter::setRecordCount (int count)
|
||||||
|
{
|
||||||
|
mHeader.mData.records = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESMWriter::setFormat (int format)
|
||||||
|
{
|
||||||
|
mHeader.mFormat = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::addMaster(const std::string& name, uint64_t size)
|
void ESMWriter::addMaster(const std::string& name, uint64_t size)
|
||||||
{
|
{
|
||||||
MasterData d;
|
Header::MasterData d;
|
||||||
d.name = name;
|
d.name = name;
|
||||||
d.size = size;
|
d.size = size;
|
||||||
m_masters.push_back(d);
|
mHeader.mMaster.push_back(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::save(const std::string& file)
|
void ESMWriter::save(const std::string& file)
|
||||||
@ -58,25 +60,13 @@ void ESMWriter::save(std::ostream& file)
|
|||||||
|
|
||||||
startRecord("TES3", 0);
|
startRecord("TES3", 0);
|
||||||
|
|
||||||
m_header.records = 0;
|
mHeader.save (*this);
|
||||||
writeHNT("HEDR", m_header, 300);
|
|
||||||
m_headerPos = m_stream->tellp() - (std::streampos)4;
|
|
||||||
|
|
||||||
for (std::list<MasterData>::iterator it = m_masters.begin(); it != m_masters.end(); ++it)
|
|
||||||
{
|
|
||||||
writeHNCString("MAST", it->name);
|
|
||||||
writeHNT("DATA", it->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
endRecord("TES3");
|
endRecord("TES3");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESMWriter::close()
|
void ESMWriter::close()
|
||||||
{
|
{
|
||||||
std::cout << "Writing amount of saved records (" << m_recordCount - 1 << ")" << std::endl;
|
|
||||||
m_stream->seekp(m_headerPos);
|
|
||||||
writeT<int>(m_recordCount-1);
|
|
||||||
m_stream->seekp(0, std::ios::end);
|
|
||||||
m_stream->flush();
|
m_stream->flush();
|
||||||
|
|
||||||
if (!m_records.empty())
|
if (!m_records.empty())
|
||||||
@ -86,7 +76,7 @@ void ESMWriter::close()
|
|||||||
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
|
void ESMWriter::startRecord(const std::string& name, uint32_t flags)
|
||||||
{
|
{
|
||||||
m_recordCount++;
|
m_recordCount++;
|
||||||
|
|
||||||
writeName(name);
|
writeName(name);
|
||||||
RecordData rec;
|
RecordData rec;
|
||||||
rec.name = name;
|
rec.name = name;
|
||||||
@ -109,7 +99,7 @@ void ESMWriter::startSubRecord(const std::string& name)
|
|||||||
rec.size = 0;
|
rec.size = 0;
|
||||||
writeT<int>(0); // Size goes here
|
writeT<int>(0); // Size goes here
|
||||||
m_records.push_back(rec);
|
m_records.push_back(rec);
|
||||||
|
|
||||||
assert(m_records.back().size == 0);
|
assert(m_records.back().size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +108,7 @@ void ESMWriter::endRecord(const std::string& name)
|
|||||||
RecordData rec = m_records.back();
|
RecordData rec = m_records.back();
|
||||||
assert(rec.name == name);
|
assert(rec.name == name);
|
||||||
m_records.pop_back();
|
m_records.pop_back();
|
||||||
|
|
||||||
m_stream->seekp(rec.position);
|
m_stream->seekp(rec.position);
|
||||||
|
|
||||||
count = false;
|
count = false;
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#ifndef OPENMW_ESM_WRITER_H
|
#ifndef OPENMW_ESM_WRITER_H
|
||||||
#define OPENMW_ESM_WRITER_H
|
#define OPENMW_ESM_WRITER_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iosfwd>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <assert.h>
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "esmcommon.hpp"
|
#include "esmcommon.hpp"
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include "loadtes3.hpp"
|
||||||
|
|
||||||
namespace ESM {
|
namespace ESM {
|
||||||
|
|
||||||
@ -22,11 +23,11 @@ class ESMWriter
|
|||||||
public:
|
public:
|
||||||
int getVersion();
|
int getVersion();
|
||||||
void setVersion(int ver);
|
void setVersion(int ver);
|
||||||
int getType();
|
|
||||||
void setType(int type);
|
|
||||||
void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8?
|
void setEncoder(ToUTF8::Utf8Encoder *encoding); // Write strings as UTF-8?
|
||||||
void setAuthor(const std::string& author);
|
void setAuthor(const std::string& author);
|
||||||
void setDescription(const std::string& desc);
|
void setDescription(const std::string& desc);
|
||||||
|
void setRecordCount (int count);
|
||||||
|
void setFormat (int format);
|
||||||
|
|
||||||
void addMaster(const std::string& name, uint64_t size);
|
void addMaster(const std::string& name, uint64_t size);
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ public:
|
|||||||
{
|
{
|
||||||
write((char*)&data, size);
|
write((char*)&data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startRecord(const std::string& name, uint32_t flags);
|
void startRecord(const std::string& name, uint32_t flags);
|
||||||
void startSubRecord(const std::string& name);
|
void startSubRecord(const std::string& name);
|
||||||
void endRecord(const std::string& name);
|
void endRecord(const std::string& name);
|
||||||
@ -90,14 +91,13 @@ public:
|
|||||||
void write(const char* data, size_t size);
|
void write(const char* data, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<MasterData> m_masters;
|
|
||||||
std::list<RecordData> m_records;
|
std::list<RecordData> m_records;
|
||||||
std::ostream* m_stream;
|
std::ostream* m_stream;
|
||||||
std::streampos m_headerPos;
|
std::streampos m_headerPos;
|
||||||
ToUTF8::Utf8Encoder* m_encoder;
|
ToUTF8::Utf8Encoder* m_encoder;
|
||||||
int m_recordCount;
|
int m_recordCount;
|
||||||
|
|
||||||
HEDRstruct m_header;
|
Header mHeader;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
|
|||||||
// If the most significant 8 bits are used, then this reference already exists.
|
// If the most significant 8 bits are used, then this reference already exists.
|
||||||
// In this case, do not spawn a new reference, but overwrite the old one.
|
// In this case, do not spawn a new reference, but overwrite the old one.
|
||||||
ref.mRefnum &= 0x00ffffff; // delete old plugin ID
|
ref.mRefnum &= 0x00ffffff; // delete old plugin ID
|
||||||
const ESM::ESMReader::MasterList &masters = esm.getMasters();
|
const std::vector<Header::MasterData> &masters = esm.getMasters();
|
||||||
global = masters[local-1].index + 1;
|
global = masters[local-1].index + 1;
|
||||||
ref.mRefnum |= global << 24; // insert global plugin ID
|
ref.mRefnum |= global << 24; // insert global plugin ID
|
||||||
}
|
}
|
||||||
@ -348,7 +348,7 @@ bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
|
|||||||
int local = (mref.mRefnum & 0xff000000) >> 24;
|
int local = (mref.mRefnum & 0xff000000) >> 24;
|
||||||
size_t global = esm.getIndex() + 1;
|
size_t global = esm.getIndex() + 1;
|
||||||
mref.mRefnum &= 0x00ffffff; // delete old plugin ID
|
mref.mRefnum &= 0x00ffffff; // delete old plugin ID
|
||||||
const ESM::ESMReader::MasterList &masters = esm.getMasters();
|
const std::vector<Header::MasterData> &masters = esm.getMasters();
|
||||||
global = masters[local-1].index + 1;
|
global = masters[local-1].index + 1;
|
||||||
mref.mRefnum |= global << 24; // insert global plugin ID
|
mref.mRefnum |= global << 24; // insert global plugin ID
|
||||||
|
|
||||||
|
53
components/esm/loadtes3.cpp
Normal file
53
components/esm/loadtes3.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
|
||||||
|
#include "loadtes3.hpp"
|
||||||
|
|
||||||
|
#include "esmcommon.hpp"
|
||||||
|
#include "esmreader.hpp"
|
||||||
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
|
void ESM::Header::blank()
|
||||||
|
{
|
||||||
|
mData.version = ESM::VER_13;
|
||||||
|
mData.type = 0;
|
||||||
|
mData.author.assign ("");
|
||||||
|
mData.desc.assign ("");
|
||||||
|
mData.records = 0;
|
||||||
|
mFormat = CurrentFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESM::Header::load (ESMReader &esm)
|
||||||
|
{
|
||||||
|
esm.getHNT (mData, "HEDR", 300);
|
||||||
|
|
||||||
|
if (esm.isNextSub ("FORM"))
|
||||||
|
{
|
||||||
|
esm.getHT (mFormat);
|
||||||
|
if (mFormat<0)
|
||||||
|
esm.fail ("invalid format code");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mFormat = 0;
|
||||||
|
|
||||||
|
while (esm.isNextSub ("MAST"))
|
||||||
|
{
|
||||||
|
MasterData m;
|
||||||
|
m.name = esm.getHString();
|
||||||
|
m.size = esm.getHNLong ("DATA");
|
||||||
|
mMaster.push_back (m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESM::Header::save (ESMWriter &esm)
|
||||||
|
{
|
||||||
|
esm.writeHNT ("HEDR", mData, 300);
|
||||||
|
|
||||||
|
if (mFormat>0)
|
||||||
|
esm.writeHNT ("FORM", mFormat);
|
||||||
|
|
||||||
|
for (std::vector<Header::MasterData>::iterator iter = mMaster.begin();
|
||||||
|
iter != mMaster.end(); ++iter)
|
||||||
|
{
|
||||||
|
esm.writeHNCString ("MAST", iter->name);
|
||||||
|
esm.writeHNT ("DATA", iter->size);
|
||||||
|
}
|
||||||
|
}
|
55
components/esm/loadtes3.hpp
Normal file
55
components/esm/loadtes3.hpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef COMPONENT_ESM_TES3_H
|
||||||
|
#define COMPONENT_ESM_TES3_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "esmcommon.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
/// \brief File header record
|
||||||
|
struct Header
|
||||||
|
{
|
||||||
|
static const int CurrentFormat = 0; // most recent known format
|
||||||
|
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
/* File format version. This is actually a float, the supported
|
||||||
|
versions are 1.2 and 1.3. These correspond to:
|
||||||
|
1.2 = 0x3f99999a and 1.3 = 0x3fa66666
|
||||||
|
*/
|
||||||
|
int version;
|
||||||
|
int type; // 0=esp, 1=esm, 32=ess (unused)
|
||||||
|
NAME32 author; // Author's name
|
||||||
|
NAME256 desc; // File description
|
||||||
|
int records; // Number of records? Not used.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defines another files (esm or esp) that this file depends upon.
|
||||||
|
struct MasterData
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
uint64_t size;
|
||||||
|
int index; // Position of the parent file in the global list of loaded files
|
||||||
|
};
|
||||||
|
|
||||||
|
Data mData;
|
||||||
|
int mFormat;
|
||||||
|
std::vector<MasterData> mMaster;
|
||||||
|
|
||||||
|
void blank();
|
||||||
|
|
||||||
|
void load (ESMReader &esm);
|
||||||
|
void save (ESMWriter &esm);
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,6 +1,6 @@
|
|||||||
#include <QDebug>
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ Qt::ItemFlags DataFilesModel::flags(const QModelIndex &index) const
|
|||||||
if (!file)
|
if (!file)
|
||||||
return Qt::NoItemFlags;
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
if (canBeChecked(file)) {
|
if (canBeChecked(file)) {
|
||||||
if (index.column() == 0) {
|
if (index.column() == 0) {
|
||||||
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
} else {
|
} else {
|
||||||
@ -226,7 +226,7 @@ bool lessThanEsmFile(const EsmFile *e1, const EsmFile *e2)
|
|||||||
return true;
|
return true;
|
||||||
if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm"))
|
if (!e1->fileName().endsWith(".esm") && e2->fileName().endsWith(".esm"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return e1->fileName().toLower() < e2->fileName().toLower();
|
return e1->fileName().toLower() < e2->fileName().toLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ void DataFilesModel::addFiles(const QString &path)
|
|||||||
fileReader.setEncoder(&encoder);
|
fileReader.setEncoder(&encoder);
|
||||||
fileReader.open(dir.absoluteFilePath(path).toStdString());
|
fileReader.open(dir.absoluteFilePath(path).toStdString());
|
||||||
|
|
||||||
ESM::ESMReader::MasterList mlist = fileReader.getMasters();
|
std::vector<ESM::Header::MasterData> mlist = fileReader.getMasters();
|
||||||
QStringList masters;
|
QStringList masters;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
for (unsigned int i = 0; i < mlist.size(); ++i) {
|
||||||
@ -369,10 +369,10 @@ QStringList DataFilesModel::checkedItems()
|
|||||||
QStringList DataFilesModel::checkedItemsPaths()
|
QStringList DataFilesModel::checkedItemsPaths()
|
||||||
{
|
{
|
||||||
QStringList list;
|
QStringList list;
|
||||||
|
|
||||||
QList<EsmFile *>::ConstIterator it;
|
QList<EsmFile *>::ConstIterator it;
|
||||||
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
|
QList<EsmFile *>::ConstIterator itEnd = mFiles.constEnd();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (it = mFiles.constBegin(); it != itEnd; ++it) {
|
for (it = mFiles.constBegin(); it != itEnd; ++it) {
|
||||||
EsmFile *file = item(i);
|
EsmFile *file = item(i);
|
||||||
@ -381,7 +381,7 @@ QStringList DataFilesModel::checkedItemsPaths()
|
|||||||
if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file))
|
if (mCheckStates[file->fileName()] == Qt::Checked && canBeChecked(file))
|
||||||
list << file->path();
|
list << file->path();
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user