mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 04:49:54 +00:00
700d55f1fb
Implemented updating editor application from preferences menu, loading settings when editor loads, adding Record Status Display prefernce. Fixed multiple bugs, made changes to CSM(V)Settings classes to make implementing new prefrences easier. Rewrote CSMSettings::UserSettings to retain last-loaded settings. Adjusted icon position in Record Status column Capitalized status text Added delegate to referenceables table
361 lines
12 KiB
C++
361 lines
12 KiB
C++
|
|
#include "viewmanager.hpp"
|
|
|
|
#include <map>
|
|
|
|
#include <QApplication>
|
|
#include <QDesktopWidget>
|
|
|
|
#include "../../model/doc/documentmanager.hpp"
|
|
#include "../../model/doc/document.hpp"
|
|
|
|
#include "../world/util.hpp"
|
|
#include "../world/enumdelegate.hpp"
|
|
#include "../world/vartypedelegate.hpp"
|
|
#include "../world/recordstatusdelegate.hpp"
|
|
#include "../settings/usersettingsdialog.hpp"
|
|
|
|
#include "view.hpp"
|
|
|
|
#include <QMessageBox>
|
|
#include <QPushButton>
|
|
#include <QtGui/QApplication>
|
|
|
|
void CSVDoc::ViewManager::updateIndices()
|
|
{
|
|
std::map<CSMDoc::Document *, std::pair<int, int> > documents;
|
|
|
|
for (std::vector<View *>::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
|
{
|
|
std::map<CSMDoc::Document *, std::pair<int, int> >::iterator document = documents.find ((*iter)->getDocument());
|
|
|
|
if (document==documents.end())
|
|
document =
|
|
documents.insert (
|
|
std::make_pair ((*iter)->getDocument(), std::make_pair (0, countViews ((*iter)->getDocument())))).
|
|
first;
|
|
|
|
(*iter)->setIndex (document->second.first++, document->second.second);
|
|
}
|
|
}
|
|
|
|
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
|
|
: mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
|
|
{
|
|
static const char *sSpecialisations[] =
|
|
{
|
|
"Combat", "Magic", "Stealth", 0
|
|
};
|
|
|
|
static const char *sAttributes[] =
|
|
{
|
|
"Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
|
|
"Luck", 0
|
|
};
|
|
|
|
static const char *sSpellTypes[] =
|
|
{
|
|
"Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0
|
|
};
|
|
|
|
static const char *sApparatusTypes[] =
|
|
{
|
|
"Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0
|
|
};
|
|
|
|
static const char *sArmorTypes[] =
|
|
{
|
|
"Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet",
|
|
"Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0
|
|
};
|
|
|
|
static const char *sClothingTypes[] =
|
|
{
|
|
"Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring",
|
|
"Amulet", 0
|
|
};
|
|
|
|
static const char *sCreatureTypes[] =
|
|
{
|
|
"Creature", "Deadra", "Undead", "Humanoid", 0
|
|
};
|
|
|
|
static const char *sWeaponTypes[] =
|
|
{
|
|
"Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close",
|
|
"Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow",
|
|
"Bolt", 0
|
|
};
|
|
|
|
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
|
|
new CSVWorld::VarTypeDelegateFactory (ESM::VT_None, ESM::VT_String, ESM::VT_Int, ESM::VT_Float));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
|
|
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
|
|
new CSVWorld::EnumDelegateFactory (sSpecialisations));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
|
|
new CSVWorld::EnumDelegateFactory (sAttributes, true));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType,
|
|
new CSVWorld::EnumDelegateFactory (sSpellTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ApparatusType,
|
|
new CSVWorld::EnumDelegateFactory (sApparatusTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ArmorType,
|
|
new CSVWorld::EnumDelegateFactory (sArmorTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ClothingType,
|
|
new CSVWorld::EnumDelegateFactory (sClothingTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_CreatureType,
|
|
new CSVWorld::EnumDelegateFactory (sCreatureTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_WeaponType,
|
|
new CSVWorld::EnumDelegateFactory (sWeaponTypes));
|
|
|
|
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RecordState,
|
|
new CSVWorld::RecordStatusDelegateFactory() );
|
|
|
|
connect (&CSMSettings::UserSettings::instance(), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)),
|
|
this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)));
|
|
|
|
CSMSettings::UserSettings::instance().loadSettings("opencs.cfg");
|
|
}
|
|
|
|
CSVDoc::ViewManager::~ViewManager()
|
|
{
|
|
delete mDelegateFactories;
|
|
|
|
for (std::vector<View *>::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
|
delete *iter;
|
|
}
|
|
|
|
CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
|
|
{
|
|
if (countViews (document)==0)
|
|
{
|
|
// new document
|
|
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)),
|
|
this, SLOT (documentStateChanged (int, CSMDoc::Document *)));
|
|
|
|
connect (document, SIGNAL (progress (int, int, int, int, CSMDoc::Document *)),
|
|
this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
|
|
}
|
|
|
|
View *view = new View (*this, document, countViews (document)+1);
|
|
|
|
|
|
mViews.push_back (view);
|
|
|
|
view->show();
|
|
|
|
connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest()));
|
|
connect (view, SIGNAL (loadDocumentRequest ()), this, SIGNAL (loadDocumentRequest()));
|
|
|
|
updateIndices();
|
|
|
|
return view;
|
|
}
|
|
|
|
int CSVDoc::ViewManager::countViews (const CSMDoc::Document *document) const
|
|
{
|
|
int count = 0;
|
|
|
|
for (std::vector<View *>::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
|
if ((*iter)->getDocument()==document)
|
|
++count;
|
|
|
|
return count;
|
|
}
|
|
|
|
bool CSVDoc::ViewManager::closeRequest (View *view)
|
|
{
|
|
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
|
|
|
|
bool continueWithClose = true;
|
|
|
|
if (iter!=mViews.end())
|
|
{
|
|
bool last = countViews (view->getDocument())<=1;
|
|
|
|
if (last)
|
|
continueWithClose = notifySaveOnClose (view);
|
|
else
|
|
{
|
|
(*iter)->deleteLater();
|
|
mViews.erase (iter);
|
|
|
|
updateIndices();
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
for (std::vector<View *>::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
|
if ((*iter)->getDocument()==document)
|
|
(*iter)->updateDocumentState();
|
|
}
|
|
|
|
void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, CSMDoc::Document *document)
|
|
{
|
|
for (std::vector<View *>::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
|
|
if ((*iter)->getDocument()==document)
|
|
(*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();
|
|
}
|
|
|
|
void CSVDoc::ViewManager::slotUpdateEditorSetting (const QString &settingName, const QString &settingValue)
|
|
{
|
|
if (settingName == "Record Status Display")
|
|
foreach (CSVDoc::View *view, mViews)
|
|
view->updateEditorSetting (settingName, settingValue);
|
|
}
|