mirror of
https://github.com/SWG-Source/client-tools.git
synced 2026-01-15 22:04:32 -05:00
Merge branch 'master' of https://github.com/SWG-Source/client-tools
This commit is contained in:
@@ -17,7 +17,6 @@
|
||||
#include "ConfigGodClient.h"
|
||||
#include "FavoritesWindow.h"
|
||||
#include "GodClientData.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "MainFrame.h"
|
||||
#include "ServerCommander.h"
|
||||
@@ -268,7 +267,7 @@ void ActionsObjectTemplate::onServerObjectTemplatePathSelectionChanged(const std
|
||||
*/
|
||||
void ActionsObjectTemplate::onServerRevert()
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile || !(m_isServerEdit || m_isServerNew))
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile || !(m_isServerEdit || m_isServerNew))
|
||||
return;
|
||||
|
||||
{
|
||||
@@ -276,23 +275,10 @@ void ActionsObjectTemplate::onServerRevert()
|
||||
const std::string msg = std::string("Really revert ObjectTemplate: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getServerObjectTemplateTpfFilePath());
|
||||
sv.push_back(getServerObjectTemplateIffFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
if(!GodClientPerforce::getInstance().revertFiles(sv, false, result))
|
||||
{
|
||||
const std::string msg = "Could not revert class files: " + sv [0] + ", " + sv [1] + "\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
m_serverRefresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -304,7 +290,7 @@ void ActionsObjectTemplate::onServerRevert()
|
||||
*/
|
||||
void ActionsObjectTemplate::onServerView() const
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile)
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
@@ -314,14 +300,6 @@ void ActionsObjectTemplate::onServerView() const
|
||||
|
||||
std::string result;
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
doEditFile(local);
|
||||
}
|
||||
|
||||
@@ -333,35 +311,13 @@ void ActionsObjectTemplate::onServerView() const
|
||||
*/
|
||||
void ActionsObjectTemplate::onServerEdit()
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile)
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
std::string result;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getServerObjectTemplateTpfFilePath());
|
||||
sv.push_back(getServerObjectTemplateIffFilePath());
|
||||
|
||||
if(!GodClientPerforce::getInstance().editFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit. View Will be read-only." + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
|
||||
// TODO: missing a return here???
|
||||
}
|
||||
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(sv [0], dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_serverRefresh->doActivate();
|
||||
doEditFile(local);
|
||||
}
|
||||
@@ -378,72 +334,17 @@ void ActionsObjectTemplate::onServerNew()
|
||||
std::string actualPath = m_selectedServerPath;
|
||||
|
||||
//-- trim the filename from the path
|
||||
if(!actualPath.empty() && m_isServerFile)
|
||||
if (!actualPath.empty() && m_isServerFile)
|
||||
{
|
||||
const size_t slashpos = actualPath.rfind('/');
|
||||
|
||||
if(slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
if (slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
actualPath.clear();
|
||||
else
|
||||
actualPath = actualPath.substr(0, slashpos);
|
||||
}
|
||||
|
||||
|
||||
const char * const srcPath = NON_NULL(ConfigGodClient::getData().templateServerSourcePath);
|
||||
std::string path = GodClientPerforce::concatenateSubpath(srcPath, actualPath);
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
std::string result;
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString qselection = QFileDialog::getSaveFileName(local.c_str(), "*.tpf",&MainFrame::getInstance());
|
||||
|
||||
if(qselection == QString::null)
|
||||
return;
|
||||
|
||||
std::string selection = qselection.latin1();
|
||||
if(selection.size() < 4 || selection.substr(selection.size() - 4) != ms_objectTemplateSourceExtension)
|
||||
selection += ms_objectTemplateSourceExtension;
|
||||
|
||||
UNREF(selection);
|
||||
|
||||
//-- discover the depot path to the .class file
|
||||
size_t dsrc_pos = selection.find("\\dsrc\\");
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
dsrc_pos = selection.find("/dsrc/");
|
||||
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
{
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", "Can't translate ObjectTemplate path to Iff path."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string compiledLocalPath = selection;
|
||||
IGNORE_RETURN(compiledLocalPath.replace(dsrc_pos + 1, 4, "data"));
|
||||
IGNORE_RETURN(compiledLocalPath.replace(compiledLocalPath.size() - 6, 6, "iff"));
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(selection);
|
||||
sv.push_back(compiledLocalPath);
|
||||
|
||||
if(!GodClientPerforce::getInstance().addFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Unable to add new files to perforce.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_serverRefresh->doActivate();
|
||||
doEditFile(selection);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -476,31 +377,16 @@ void ActionsObjectTemplate::onServerReload() const
|
||||
*/
|
||||
void ActionsObjectTemplate::onServerSubmit()
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile || !(m_isServerEdit || m_isServerNew))
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile || !(m_isServerEdit || m_isServerNew))
|
||||
return;
|
||||
|
||||
const std::string classPath = ActionsObjectTemplate::convertToClassPath(m_selectedServerPath);
|
||||
const std::string msg = std::string("Really submit ObjectTemplate: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getServerObjectTemplateTpfFilePath());
|
||||
sv.push_back(getServerObjectTemplateIffFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
IGNORE_RETURN(GodClientPerforce::getInstance().revertFiles(sv, true, result));
|
||||
|
||||
if(!GodClientPerforce::getInstance().submitFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not submit file(s) to perforce! Beanhead.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
m_serverRefresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -521,22 +407,22 @@ void ActionsObjectTemplate::onServerCompile() const
|
||||
|
||||
const std::string ActionsObjectTemplate::getServerObjectTemplateTpfFilePath() const
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile)
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile)
|
||||
return "";
|
||||
|
||||
const char* const srcPath = NON_NULL(ConfigGodClient::getData().templateServerSourcePath);
|
||||
return GodClientPerforce::concatenateSubpath(srcPath, m_selectedServerPath) + ms_objectTemplateSourceExtension;
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
const std::string ActionsObjectTemplate::getServerObjectTemplateIffFilePath() const
|
||||
{
|
||||
if(m_selectedServerPath.empty() || !m_isServerFile)
|
||||
if (m_selectedServerPath.empty() || !m_isServerFile)
|
||||
return "";
|
||||
|
||||
const char* const iffPath = NON_NULL(ConfigGodClient::getData().templateServerIffPath);
|
||||
return GodClientPerforce::concatenateSubpath(iffPath, m_selectedServerPath) + ms_objectTemplateCompiledExtension;
|
||||
return iffPath;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -583,7 +469,7 @@ void ActionsObjectTemplate::onClientObjectTemplatePathSelectionChanged(const std
|
||||
*/
|
||||
void ActionsObjectTemplate::onClientRevert()
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile || !(m_isClientEdit || m_isClientNew))
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile || !(m_isClientEdit || m_isClientNew))
|
||||
return;
|
||||
|
||||
{
|
||||
@@ -591,23 +477,10 @@ void ActionsObjectTemplate::onClientRevert()
|
||||
const std::string msg = std::string("Really revert ObjectTemplate: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getClientObjectTemplateTpfFilePath());
|
||||
sv.push_back(getClientObjectTemplateIffFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
if(!GodClientPerforce::getInstance().revertFiles(sv, false, result))
|
||||
{
|
||||
const std::string msg = "Could not revert class files: " + sv [0] + ", " + sv [1] + "\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
m_clientRefresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -619,7 +492,7 @@ void ActionsObjectTemplate::onClientRevert()
|
||||
*/
|
||||
void ActionsObjectTemplate::onClientView() const
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile)
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
@@ -628,14 +501,6 @@ void ActionsObjectTemplate::onClientView() const
|
||||
|
||||
const std::string path = getClientObjectTemplateTpfFilePath();
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
doEditFile(local);
|
||||
}
|
||||
|
||||
@@ -647,32 +512,13 @@ void ActionsObjectTemplate::onClientView() const
|
||||
*/
|
||||
void ActionsObjectTemplate::onClientEdit()
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile)
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
std::string result;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getClientObjectTemplateTpfFilePath());
|
||||
sv.push_back(getClientObjectTemplateIffFilePath());
|
||||
|
||||
if(!GodClientPerforce::getInstance().editFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit. View Will be read-only.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(sv [0], dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_clientRefresh->doActivate();
|
||||
doEditFile(local);
|
||||
}
|
||||
@@ -689,72 +535,17 @@ void ActionsObjectTemplate::onClientNew()
|
||||
std::string actualPath = m_selectedClientPath;
|
||||
|
||||
//-- trim the filename from the path
|
||||
if(!actualPath.empty() && m_isClientFile)
|
||||
if (!actualPath.empty() && m_isClientFile)
|
||||
{
|
||||
const size_t slashpos = actualPath.rfind('/');
|
||||
|
||||
if(slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
if (slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
actualPath.clear();
|
||||
else
|
||||
actualPath = actualPath.substr(0, slashpos);
|
||||
}
|
||||
|
||||
|
||||
const char* const srcPath = NON_NULL(ConfigGodClient::getData().templateClientSourcePath);
|
||||
std::string path = GodClientPerforce::concatenateSubpath(srcPath, actualPath);
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
std::string result;
|
||||
|
||||
//-- map the desired ObjectTemplate classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString qselection = QFileDialog::getSaveFileName(local.c_str(), "*.tpf",&MainFrame::getInstance());
|
||||
|
||||
if(qselection == QString::null)
|
||||
return;
|
||||
|
||||
std::string selection = qselection.latin1();
|
||||
if(selection.size() < 4 || selection.substr(selection.size() - 4) != ms_objectTemplateSourceExtension)
|
||||
selection += ms_objectTemplateSourceExtension;
|
||||
|
||||
UNREF(selection);
|
||||
|
||||
//-- discover the depot path to the .class file
|
||||
size_t dsrc_pos = selection.find("\\dsrc\\");
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
dsrc_pos = selection.find("/dsrc/");
|
||||
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
{
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", "Can't translate ObjectTemplate path to Iff path."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string compiledLocalPath = selection;
|
||||
IGNORE_RETURN(compiledLocalPath.replace(dsrc_pos + 1, 4, "data"));
|
||||
IGNORE_RETURN(compiledLocalPath.replace(compiledLocalPath.size() - 6, 6, "iff"));
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(selection);
|
||||
sv.push_back(compiledLocalPath);
|
||||
|
||||
if(!GodClientPerforce::getInstance().addFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Unable to add new files to perforce.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
m_clientRefresh->doActivate();
|
||||
doEditFile(selection);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -765,31 +556,16 @@ void ActionsObjectTemplate::onClientNew()
|
||||
*/
|
||||
void ActionsObjectTemplate::onClientSubmit()
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile || !(m_isClientEdit || m_isClientNew))
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile || !(m_isClientEdit || m_isClientNew))
|
||||
return;
|
||||
|
||||
const std::string classPath = ActionsObjectTemplate::convertToClassPath(m_selectedClientPath);
|
||||
const std::string msg = std::string("Really submit ObjectTemplate: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getClientObjectTemplateTpfFilePath());
|
||||
sv.push_back(getClientObjectTemplateIffFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
IGNORE_RETURN(GodClientPerforce::getInstance().revertFiles(sv, true, result));
|
||||
|
||||
if(!GodClientPerforce::getInstance().submitFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not submit file(s) to perforce! Beanhead.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
m_clientRefresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -810,22 +586,22 @@ void ActionsObjectTemplate::onClientCompile() const
|
||||
|
||||
const std::string ActionsObjectTemplate::getClientObjectTemplateTpfFilePath() const
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile)
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile)
|
||||
return "";
|
||||
|
||||
const char * const srcPath = NON_NULL(ConfigGodClient::getData().templateClientSourcePath);
|
||||
return GodClientPerforce::concatenateSubpath(srcPath, m_selectedClientPath) + ms_objectTemplateSourceExtension;
|
||||
const char* const srcPath = NON_NULL(ConfigGodClient::getData().templateClientSourcePath);
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
const std::string ActionsObjectTemplate::getClientObjectTemplateIffFilePath() const
|
||||
{
|
||||
if(m_selectedClientPath.empty() || !m_isClientFile)
|
||||
if (m_selectedClientPath.empty() || !m_isClientFile)
|
||||
return "";
|
||||
|
||||
const char * const iffPath = NON_NULL(ConfigGodClient::getData().templateClientIffPath);
|
||||
return GodClientPerforce::concatenateSubpath(iffPath, m_selectedClientPath) + ms_objectTemplateCompiledExtension;
|
||||
const char* const iffPath = NON_NULL(ConfigGodClient::getData().templateClientIffPath);
|
||||
return iffPath;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "ActionHack.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "GodClientData.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "MainFrame.h"
|
||||
#include "ServerCommander.h"
|
||||
@@ -176,7 +175,7 @@ void ActionsScript::doEditFile(const std::string & filename) const
|
||||
*/
|
||||
void ActionsScript::onRevert()
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile || !(m_isEdit || m_isNew))
|
||||
if (m_selectedPath.empty() || !m_isFile || !(m_isEdit || m_isNew))
|
||||
return;
|
||||
|
||||
{
|
||||
@@ -184,23 +183,10 @@ void ActionsScript::onRevert()
|
||||
const std::string msg = std::string("Really revert script: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
}
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getScriptFilePath());
|
||||
sv.push_back(getClassFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
if(!GodClientPerforce::getInstance().revertFiles(sv, false, result))
|
||||
{
|
||||
const std::string msg = "Could not revert class files: " + sv [0] + ", " + sv [1] + "\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
refresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -212,7 +198,7 @@ void ActionsScript::onRevert()
|
||||
*/
|
||||
void ActionsScript::onView() const
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile)
|
||||
if (m_selectedPath.empty() || !m_isFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
@@ -222,14 +208,6 @@ void ActionsScript::onView() const
|
||||
|
||||
std::string result;
|
||||
|
||||
//-- map the desired script classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
doEditFile(local);
|
||||
}
|
||||
|
||||
@@ -241,33 +219,12 @@ void ActionsScript::onView() const
|
||||
*/
|
||||
void ActionsScript::onEdit()
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile)
|
||||
if (m_selectedPath.empty() || !m_isFile)
|
||||
return;
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getScriptFilePath());
|
||||
sv.push_back(getClassFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
if(!GodClientPerforce::getInstance().editFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit. View Will be read-only.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
//-- map the desired script classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(sv [0], dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
refresh->doActivate();
|
||||
doEditFile(local);
|
||||
}
|
||||
@@ -285,73 +242,17 @@ void ActionsScript::onNew()
|
||||
|
||||
//-- trim the filename from the path
|
||||
|
||||
if(!actualPath.empty() && m_isFile)
|
||||
if (!actualPath.empty() && m_isFile)
|
||||
{
|
||||
const size_t slashpos = actualPath.rfind('/');
|
||||
|
||||
if(slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
if (slashpos == actualPath.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
actualPath.clear();
|
||||
else
|
||||
actualPath = actualPath.substr(0, slashpos);
|
||||
}
|
||||
|
||||
|
||||
const char * const srcPath = NON_NULL(ConfigGodClient::getData().scriptSourcePath);
|
||||
std::string path = GodClientPerforce::concatenateSubpath(srcPath, actualPath);
|
||||
|
||||
std::string dummy;
|
||||
std::string local;
|
||||
|
||||
std::string result;
|
||||
|
||||
//-- map the desired script classpath to a local source directory
|
||||
if(!GodClientPerforce::getInstance().getFileMapping(path, dummy, dummy, local, result))
|
||||
{
|
||||
const std::string msg = "Can't 'where' directory. User error? Perhaps.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
const QString qselection = QFileDialog::getSaveFileName(local.c_str(), "*.script", &MainFrame::getInstance());
|
||||
|
||||
if(qselection == QString::null)
|
||||
return;
|
||||
|
||||
std::string selection = qselection.latin1();
|
||||
if(selection.size() < 7 || selection.substr(selection.size() - 7) != ".script")
|
||||
selection += ".script";
|
||||
|
||||
UNREF(selection);
|
||||
|
||||
//-- discover the depot path to the .class file
|
||||
size_t dsrc_pos = selection.find("\\dsrc\\");
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
dsrc_pos = selection.find("/dsrc/");
|
||||
|
||||
if(dsrc_pos == selection.npos) //lint !e737 implicit promotion, bug in STL with size_t and std::string::npos being of different signage
|
||||
{
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", "Can't translate script path to class path."));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string compiledLocalPath = selection;
|
||||
IGNORE_RETURN(compiledLocalPath.replace(dsrc_pos + 1, 4, "data"));
|
||||
IGNORE_RETURN(compiledLocalPath.replace(compiledLocalPath.size() - 6, 6, "class"));
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(selection);
|
||||
sv.push_back(compiledLocalPath);
|
||||
|
||||
if(!GodClientPerforce::getInstance().addFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Unable to add new files to perforce." + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
refresh->doActivate();
|
||||
doEditFile(selection);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@@ -383,31 +284,16 @@ void ActionsScript::onServerReload() const
|
||||
*/
|
||||
void ActionsScript::onSubmit()
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile || !(m_isEdit || m_isNew))
|
||||
if (m_selectedPath.empty() || !m_isFile || !(m_isEdit || m_isNew))
|
||||
return;
|
||||
|
||||
const std::string classPath = ActionsScript::convertToClasspath(m_selectedPath);
|
||||
const std::string msg = std::string("Really submit script: [") + classPath + "]?";
|
||||
const int retval = QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str(), QMessageBox::Yes, QMessageBox::No);
|
||||
|
||||
if(retval == QMessageBox::No)
|
||||
if (retval == QMessageBox::No)
|
||||
return;
|
||||
|
||||
GodClientPerforce::StringVector sv;
|
||||
sv.reserve(2);
|
||||
sv.push_back(getScriptFilePath());
|
||||
sv.push_back(getClassFilePath());
|
||||
|
||||
std::string result;
|
||||
|
||||
IGNORE_RETURN(GodClientPerforce::getInstance().revertFiles(sv, true, result));
|
||||
|
||||
if(!GodClientPerforce::getInstance().submitFiles(sv, result))
|
||||
{
|
||||
const std::string msg = "Could not submit file(s) to perforce! Beanhead.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
refresh->doActivate();
|
||||
}
|
||||
|
||||
@@ -450,22 +336,22 @@ const std::string ActionsScript::convertToClasspath(const std::string & path)
|
||||
|
||||
const std::string ActionsScript::getScriptFilePath() const
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile)
|
||||
if (m_selectedPath.empty() || !m_isFile)
|
||||
return "";
|
||||
|
||||
const char * const srcPath = NON_NULL(ConfigGodClient::getData().scriptSourcePath);
|
||||
return GodClientPerforce::concatenateSubpath(srcPath, m_selectedPath) + ".script";
|
||||
const char* const srcPath = NON_NULL(ConfigGodClient::getData().scriptSourcePath);
|
||||
return srcPath;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
const std::string ActionsScript::getClassFilePath() const
|
||||
{
|
||||
if(m_selectedPath.empty() || !m_isFile)
|
||||
if (m_selectedPath.empty() || !m_isFile)
|
||||
return "";
|
||||
|
||||
const char * const classPath = NON_NULL(ConfigGodClient::getData().scriptClassPath);
|
||||
return GodClientPerforce::concatenateSubpath(classPath, m_selectedPath) + ".class";
|
||||
const char* const classPath = NON_NULL(ConfigGodClient::getData().scriptClassPath);
|
||||
return classPath;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "FilesystemTree.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "MainFrame.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "ServerObjectData.h"
|
||||
#include <hash_set>
|
||||
#include <string>
|
||||
@@ -178,112 +177,6 @@ void BuildoutAreaSupport::getBuildoutAreaList(std::string const &sceneName, std:
|
||||
areaPath += "/datatables/buildout/";
|
||||
areaPath += sceneName;
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
// scan the datatable directory for the specified scene and update status
|
||||
std::string result;
|
||||
|
||||
AbstractFilesystemTree *afst = GodClientPerforce::getInstance().getFileTree(areaPath, "tab", result, GodClientPerforce::FileState_depot);
|
||||
if (afst)
|
||||
{
|
||||
AbstractFilesystemTree::Node const * const node = afst->getRootNode();
|
||||
if (node)
|
||||
{
|
||||
for (AbstractFilesystemTree::Node::ConstIterator i = node->begin (); i != node->end (); ++i)
|
||||
{
|
||||
std::string name((*i)->name);
|
||||
if (name.size() > 4)
|
||||
name.erase(name.size()-4, 4);
|
||||
|
||||
bool found = false;
|
||||
for (unsigned int areaIndex = 0; areaIndex < areaNames.size(); ++areaIndex)
|
||||
{
|
||||
if (areaNames[areaIndex] == name)
|
||||
{
|
||||
areaStatuses[areaIndex] = "Active";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
areaNames.push_back(name);
|
||||
areaLocations.push_back();
|
||||
areaStatuses.push_back("Inactive");
|
||||
}
|
||||
}
|
||||
}
|
||||
delete afst;
|
||||
}
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(areaPath, "tab", result, GodClientPerforce::FileState_add);
|
||||
if (afst)
|
||||
{
|
||||
AbstractFilesystemTree::Node const * const node = afst->getRootNode();
|
||||
if (node)
|
||||
{
|
||||
for (AbstractFilesystemTree::Node::ConstIterator i = node->begin (); i != node->end (); ++i)
|
||||
{
|
||||
std::string name((*i)->name);
|
||||
if (name.size() > 4)
|
||||
name.erase(name.size()-4, 4);
|
||||
|
||||
bool found = false;
|
||||
for (unsigned int areaIndex = 0; areaIndex < areaNames.size(); ++areaIndex)
|
||||
{
|
||||
if (areaNames[areaIndex] == name)
|
||||
{
|
||||
areaStatuses[areaIndex] = "New";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
areaNames.push_back(name);
|
||||
areaLocations.push_back();
|
||||
areaStatuses.push_back("New+Inactive");
|
||||
}
|
||||
}
|
||||
}
|
||||
delete afst;
|
||||
}
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(areaPath, "tab", result, GodClientPerforce::FileState_edit);
|
||||
if (afst)
|
||||
{
|
||||
AbstractFilesystemTree::Node const * const node = afst->getRootNode();
|
||||
if (node)
|
||||
{
|
||||
for (AbstractFilesystemTree::Node::ConstIterator i = node->begin (); i != node->end (); ++i)
|
||||
{
|
||||
std::string name((*i)->name);
|
||||
if (name.size() > 4)
|
||||
name.erase(name.size()-4, 4);
|
||||
|
||||
bool found = false;
|
||||
for (unsigned int areaIndex = 0; areaIndex < areaNames.size(); ++areaIndex)
|
||||
{
|
||||
if (areaNames[areaIndex] == name)
|
||||
{
|
||||
areaStatuses[areaIndex] = "Edit";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
areaNames.push_back(name);
|
||||
areaLocations.push_back();
|
||||
areaStatuses.push_back("Edit+Inactive");
|
||||
}
|
||||
}
|
||||
}
|
||||
delete afst;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FilesystemTree* fst = new FilesystemTree();
|
||||
|
||||
fst->setRootPath(areaPath);
|
||||
@@ -319,7 +212,6 @@ void BuildoutAreaSupport::getBuildoutAreaList(std::string const &sceneName, std:
|
||||
}
|
||||
|
||||
delete fst;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -330,72 +222,6 @@ bool BuildoutAreaSupport::openBuildoutFilesForEditing( const std::string &areaNa
|
||||
std::string serverTabFilename, serverIffFilename, clientTabFilename, clientIffFilename;
|
||||
getBuildoutAreaTableNames(areaName, serverTabFilename, serverIffFilename, clientTabFilename, clientIffFilename);
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
// open the files for edit, in case they already exist
|
||||
std::vector<std::string> perforceFiles;
|
||||
perforceFiles.push_back(serverTabFilename);
|
||||
perforceFiles.push_back(serverIffFilename);
|
||||
perforceFiles.push_back(clientTabFilename);
|
||||
perforceFiles.push_back(clientIffFilename);
|
||||
|
||||
std::string result;
|
||||
|
||||
//warn, and possibly abort, if anyone else has the buildout files checked out already
|
||||
std::vector<std::string> alsoOpenedBy;
|
||||
for(std::vector<std::string>::const_iterator it = perforceFiles.begin(); it != perforceFiles.end(); ++it)
|
||||
{
|
||||
bool ok = GodClientPerforce::getInstance().fileAlsoOpenedBy(*it, alsoOpenedBy, result);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
QMessageBox::critical (0, "GodClientPerforce::getInstance().fileAlsoOpenedBy error!", result.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!alsoOpenedBy.empty())
|
||||
{
|
||||
//build the warning message string
|
||||
std::string msg = "File:\n";
|
||||
msg += *it + " is also checked out by:\n";
|
||||
for(std::vector<std::string>::const_iterator it2 = alsoOpenedBy.begin(); it2 != alsoOpenedBy.end(); ++it2)
|
||||
{
|
||||
msg += *it2 + "\n";
|
||||
}
|
||||
|
||||
|
||||
if ( !Game::getSinglePlayer() )
|
||||
{
|
||||
QMessageBox::warning (0, "I can not check these files out because...", msg.c_str(), QMessageBox::Ok, 0 );
|
||||
return false;
|
||||
}
|
||||
|
||||
QMessageBox::warning (0, "Uh oh!", msg.c_str(), QMessageBox::Ok, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
preModifyBuildoutArea(serverTabFilename, serverIffFilename, clientTabFilename, clientIffFilename);
|
||||
|
||||
if ( Game::getSinglePlayer() )
|
||||
{
|
||||
if (!GodClientPerforce::getInstance().editFiles(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GodClientPerforce::getInstance().editFilesAndLock(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit and lock!\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -413,77 +239,10 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
|
||||
std::map<std::string, std::vector<std::string>> serverEventObjectMap;
|
||||
|
||||
CachedBuildoutArea const &cachedBuildoutArea = (*i).second;
|
||||
std::vector<ServerBuildoutAreaRow> const &serverRows = cachedBuildoutArea.serverRows;
|
||||
std::vector<ClientBuildoutAreaRow> const &clientRows = cachedBuildoutArea.clientRows;
|
||||
CachedBuildoutArea const& cachedBuildoutArea = (*i).second;
|
||||
std::vector<ServerBuildoutAreaRow> const& serverRows = cachedBuildoutArea.serverRows;
|
||||
std::vector<ClientBuildoutAreaRow> const& clientRows = cachedBuildoutArea.clientRows;
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
// open the files for edit, in case they already exist
|
||||
std::vector<std::string> perforceFiles;
|
||||
perforceFiles.push_back(serverTabFilename);
|
||||
perforceFiles.push_back(serverIffFilename);
|
||||
perforceFiles.push_back(clientTabFilename);
|
||||
perforceFiles.push_back(clientIffFilename);
|
||||
|
||||
std::string result;
|
||||
|
||||
//warn, and possibly abort, if anyone else has the buildout files checked out already
|
||||
std::vector<std::string> alsoOpenedBy;
|
||||
for(std::vector<std::string>::const_iterator it = perforceFiles.begin(); it != perforceFiles.end(); ++it)
|
||||
{
|
||||
bool ok = GodClientPerforce::getInstance().fileAlsoOpenedBy(*it, alsoOpenedBy, result);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
QMessageBox::critical (0, "Error", result.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if(!alsoOpenedBy.empty())
|
||||
{
|
||||
//build the warning message string
|
||||
std::string msg = "File:\n";
|
||||
msg += *it + " is also checked out by:\n";
|
||||
for(std::vector<std::string>::const_iterator it2 = alsoOpenedBy.begin(); it2 != alsoOpenedBy.end(); ++it2)
|
||||
{
|
||||
msg += *it2 + "\n";
|
||||
}
|
||||
msg += "Check out anyway?";
|
||||
switch (QMessageBox::warning (0, "Someone else has this file checked out!", msg.c_str(), QMessageBox::Yes | QMessageBox::Default, QMessageBox::No))
|
||||
{
|
||||
case QMessageBox::No:
|
||||
{
|
||||
QMessageBox::information (0, "Aborted", "Buildout save aborted.", QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preModifyBuildoutArea(serverTabFilename, serverIffFilename, clientTabFilename, clientIffFilename);
|
||||
|
||||
if ( Game::getSinglePlayer () )
|
||||
{
|
||||
if (!GodClientPerforce::getInstance().editFiles(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GodClientPerforce::getInstance().editFilesAndLock(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce edit.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write the tables
|
||||
{
|
||||
@@ -521,40 +280,40 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
{
|
||||
for (std::vector<ServerBuildoutAreaRow>::const_iterator i = serverRows.begin(); i != serverRows.end(); ++i)
|
||||
{
|
||||
ConstCharCrcString const &serverTemplateName = getServerTemplateName((*i).serverTemplateCrc);
|
||||
ConstCharCrcString const& serverTemplateName = getServerTemplateName((*i).serverTemplateCrc);
|
||||
char buf[512];
|
||||
IGNORE_RETURN(snprintf(buf, sizeof(buf)-1, "%d\t%d\t%s\t%d\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t",
|
||||
IGNORE_RETURN(_snprintf(buf, sizeof(buf) - 1, "%d\t%d\t%s\t%d\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t",
|
||||
(*i).id,
|
||||
(*i).container,
|
||||
serverTemplateName.getString(),
|
||||
(*i).cellIndex,
|
||||
(*i).position.x, (*i).position.y, (*i).position.z,
|
||||
(*i).orientation.w, (*i).orientation.x, (*i).orientation.y, (*i).orientation.z));
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
std::string::size_type index = (*i).objvars.find("eventRequired");
|
||||
|
||||
if(index != std::string::npos )
|
||||
if (index != std::string::npos)
|
||||
{
|
||||
std::string::size_type eventSubStringStart = (*i).objvars.find("|", index );
|
||||
if(eventSubStringStart == std::string::npos)
|
||||
std::string::size_type eventSubStringStart = (*i).objvars.find("|", index);
|
||||
if (eventSubStringStart == std::string::npos)
|
||||
continue; //Malformed event obj var. TODO: Warning goes here!
|
||||
|
||||
eventSubStringStart = (*i).objvars.find("|", eventSubStringStart + 1);
|
||||
|
||||
std::string::size_type eventSubStringEnd = (*i).objvars.find("|", eventSubStringStart + 1);
|
||||
|
||||
std::string eventName = (*i).objvars.substr(eventSubStringStart + 1, (eventSubStringEnd - 1) - eventSubStringStart );
|
||||
std::string eventName = (*i).objvars.substr(eventSubStringStart + 1, (eventSubStringEnd - 1) - eventSubStringStart);
|
||||
|
||||
DEBUG_WARNING(true, ("Found an Event Object! Event Name [%s]", eventName.c_str()));
|
||||
|
||||
std::vector<std::string>* eventList = NULL;
|
||||
std::map<std::string, std::vector<std::string>>::iterator eventIter = serverEventObjectMap.find(eventName);
|
||||
|
||||
if(eventIter == serverEventObjectMap.end())
|
||||
if (eventIter == serverEventObjectMap.end())
|
||||
{
|
||||
std::pair<std::map<std::string, std::vector<std::string>>::iterator, bool> insertIter;
|
||||
insertIter = serverEventObjectMap.insert(std::make_pair<std::string, std::vector<std::string>>(eventName, std::vector<std::string>()));
|
||||
if(insertIter.second)
|
||||
insertIter = serverEventObjectMap.insert(std::make_pair(eventName, std::vector<std::string>()));
|
||||
if (insertIter.second)
|
||||
eventList = &(*insertIter.first).second;
|
||||
}
|
||||
else
|
||||
@@ -567,7 +326,7 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
objectOutputString.append((*i).objvars);
|
||||
objectOutputString.append("\n", 1);
|
||||
|
||||
if(eventList)
|
||||
if (eventList)
|
||||
eventList->push_back(objectOutputString);
|
||||
|
||||
continue;
|
||||
@@ -585,9 +344,9 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
{
|
||||
for (std::vector<ClientBuildoutAreaRow>::const_iterator i = clientRows.begin(); i != clientRows.end(); ++i)
|
||||
{
|
||||
ConstCharCrcString const &sharedTemplateName = getSharedTemplateName((*i).sharedTemplateCrc);
|
||||
ConstCharCrcString const& sharedTemplateName = getSharedTemplateName((*i).sharedTemplateCrc);
|
||||
char buf[512];
|
||||
IGNORE_RETURN(snprintf(buf, sizeof(buf)-1, "%d\t%d\t%d\t%s\t%d\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%d\n",
|
||||
IGNORE_RETURN(_snprintf(buf, sizeof(buf) - 1, "%d\t%d\t%d\t%s\t%d\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%g\t%d\n",
|
||||
(*i).id,
|
||||
(*i).container,
|
||||
(*i).type,
|
||||
@@ -597,7 +356,7 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
(*i).orientation.w, (*i).orientation.x, (*i).orientation.y, (*i).orientation.z,
|
||||
(*i).radius,
|
||||
static_cast<int>((*i).portalLayoutCrc)));
|
||||
buf[sizeof(buf)-1] = '\0';
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
clientOutputFile.write(strlen(buf), buf);
|
||||
}
|
||||
}
|
||||
@@ -610,7 +369,7 @@ void BuildoutAreaSupport::saveBuildoutArea(std::string const &areaName)
|
||||
|
||||
// Write out event specific tables.
|
||||
std::map<std::string, std::vector<std::string>>::iterator beginIter = serverEventObjectMap.begin();
|
||||
for(; beginIter != serverEventObjectMap.end(); ++beginIter)
|
||||
for (; beginIter != serverEventObjectMap.end(); ++beginIter)
|
||||
{
|
||||
writeOutServerEventArea((*beginIter).first, (*beginIter).second);
|
||||
}
|
||||
@@ -1243,38 +1002,7 @@ void BuildoutAreaSupportNamespace::install()
|
||||
{
|
||||
std::string depotPath, clientPath, localPath, result;
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
|
||||
if (!GodClientPerforce::getInstance().getFileMapping(".", depotPath, clientPath, localPath, result))
|
||||
{
|
||||
WARNING(true, ("BuildoutAreaSupportNamespace::install(): %s", result.c_str()));
|
||||
IGNORE_RETURN(QMessageBox::warning(0, "Perforce Buildout Warning", result.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string prefix("//depot/swg/");
|
||||
prefix += depotPath.substr(12, depotPath.find("/", 12)-12);
|
||||
|
||||
GodClientPerforce::getInstance().getFileMapping(
|
||||
prefix + "/dsrc/sku.0/sys.server/compiled/game",
|
||||
s_serverSrcDepotPath, clientPath, s_serverSrcPath, result);
|
||||
GodClientPerforce::getInstance().getFileMapping(
|
||||
prefix + "/data/sku.0/sys.server/compiled/game",
|
||||
depotPath, clientPath, s_serverDataPath, result);
|
||||
GodClientPerforce::getInstance().getFileMapping(
|
||||
prefix + "/dsrc/sku.0/sys.client/compiled/game",
|
||||
depotPath, clientPath, s_clientSrcPath, result);
|
||||
GodClientPerforce::getInstance().getFileMapping(
|
||||
prefix + "/data/sku.0/sys.client/compiled/game",
|
||||
depotPath, clientPath, s_clientDataPath, result);
|
||||
GodClientPerforce::getInstance().getFileMapping(
|
||||
prefix + "/data/sku.0/sys.server/built/game/misc/object_template_crc_string_table.iff",
|
||||
depotPath, clientPath, localPath, result);
|
||||
s_serverTemplateCrcStringTable.load(localPath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
s_clientSrcPath = ConfigGodClient::getData().localClientSrcPath;
|
||||
s_clientDataPath = ConfigGodClient::getData().localClientDataPath;
|
||||
s_serverSrcPath = ConfigGodClient::getData().localServerSrcPath;
|
||||
@@ -1283,8 +1011,6 @@ void BuildoutAreaSupportNamespace::install()
|
||||
s_serverSrcDepotPath = "";
|
||||
|
||||
s_serverTemplateCrcStringTable.load(ConfigGodClient::getData().localServerCrcStringTable);
|
||||
}
|
||||
|
||||
|
||||
s_installed = true;
|
||||
}
|
||||
@@ -1327,13 +1053,6 @@ void BuildoutAreaSupportNamespace::preModifyBuildoutArea(std::string const &serv
|
||||
|
||||
// create the directories to contain the files as needed
|
||||
createDirectoriesForFiles(perforceFiles);
|
||||
|
||||
// open the files for edit, in case they already exist
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
std::string result;
|
||||
IGNORE_RETURN(GodClientPerforce::getInstance().editFiles(perforceFiles, result));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -1352,30 +1071,6 @@ void BuildoutAreaSupportNamespace::postModifyBuildoutArea(std::string const &ser
|
||||
writer.save(clientIffFilename.c_str());
|
||||
}
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
std::vector<std::string> perforceFiles;
|
||||
perforceFiles.push_back(serverTabFilename);
|
||||
perforceFiles.push_back(serverIffFilename);
|
||||
perforceFiles.push_back(clientTabFilename);
|
||||
perforceFiles.push_back(clientIffFilename);
|
||||
|
||||
std::string result;
|
||||
// add the files, in case they didn't already exist
|
||||
if (!GodClientPerforce::getInstance().addFiles(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce add.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
// revert unchanged
|
||||
if (!GodClientPerforce::getInstance().revertFiles(perforceFiles, true, result))
|
||||
{
|
||||
const std::string msg = "Could not revert unchanged file(s).\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -2195,13 +1890,6 @@ void BuildoutAreaSupportNamespace::writeOutServerEventArea(std::string const eve
|
||||
// create the directories to contain the files as needed
|
||||
createDirectoriesForFiles(eventFiles);
|
||||
|
||||
// open the files for edit, in case they already exist
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
std::string result;
|
||||
IGNORE_RETURN(GodClientPerforce::getInstance().editFiles(eventFiles, result));
|
||||
}
|
||||
|
||||
StdioFile serverEventOutputFile(serverTabFilename.c_str(), "w");
|
||||
|
||||
if (!serverEventOutputFile.isOpen())
|
||||
@@ -2220,7 +1908,7 @@ void BuildoutAreaSupportNamespace::writeOutServerEventArea(std::string const eve
|
||||
|
||||
// Write out the actually object info.
|
||||
std::vector<std::string>::size_type i = 0;
|
||||
for(; i < objects.size(); ++i)
|
||||
for (; i < objects.size(); ++i)
|
||||
serverEventOutputFile.write(objects[i].length(), objects[i].c_str());
|
||||
|
||||
serverEventOutputFile.close();
|
||||
@@ -2232,29 +1920,6 @@ void BuildoutAreaSupportNamespace::writeOutServerEventArea(std::string const eve
|
||||
writer.save(serverIffFilename.c_str());
|
||||
}
|
||||
|
||||
|
||||
if (ConfigGodClient::getConnectToPerforce())
|
||||
{
|
||||
std::vector<std::string> perforceFiles;
|
||||
perforceFiles.push_back(serverTabFilename);
|
||||
perforceFiles.push_back(serverIffFilename);
|
||||
|
||||
std::string result;
|
||||
// add the files, in case they didn't already exist
|
||||
if (!GodClientPerforce::getInstance().addFiles(perforceFiles, result))
|
||||
{
|
||||
const std::string msg = "Could not open file(s) for perforce add.\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
|
||||
// revert unchanged
|
||||
if (!GodClientPerforce::getInstance().revertFiles(perforceFiles, true, result))
|
||||
{
|
||||
const std::string msg = "Could not revert unchanged file(s).\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(&MainFrame::getInstance(), "Warning", msg.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "ActionsObjectTemplate.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "FileSystemTree.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "ObjectTemplateData.h"
|
||||
|
||||
@@ -149,50 +148,6 @@ void ClientTemplateListView::onRefreshList()
|
||||
|
||||
setCursor(static_cast<int>(Qt::WaitCursor));
|
||||
|
||||
if ( ConfigGodClient::getConnectToPerforce() )
|
||||
{
|
||||
|
||||
const char* const templateIffPath = NON_NULL(ConfigGodClient::getData().templateClientIffPath);
|
||||
std::string result;
|
||||
AbstractFilesystemTree* afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_depot);
|
||||
|
||||
if(!afst)
|
||||
{
|
||||
const std::string msg = "Unable to retrieve info from perforce:\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(this, "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_red);
|
||||
populateTemplateTree(0,&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_add);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_blue);
|
||||
populateTemplateTree("[NEW]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_edit);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_violet);
|
||||
populateTemplateTree("[EDIT]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
}
|
||||
else
|
||||
{
|
||||
FilesystemTree* fst = new FilesystemTree();
|
||||
|
||||
std::string path = ConfigGodClient::getData().localClientDataPath;
|
||||
@@ -209,7 +164,6 @@ void ClientTemplateListView::onRefreshList()
|
||||
}
|
||||
|
||||
delete fst;
|
||||
}
|
||||
|
||||
|
||||
unsetCursor();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "ObjectTemplateData.h"
|
||||
|
||||
#include "ConfigGodClient.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "AbstractFilesystemTree.h"
|
||||
|
||||
#include <qmessagebox.h>
|
||||
@@ -41,22 +40,14 @@ ObjectTemplateData::~ObjectTemplateData()
|
||||
|
||||
void ObjectTemplateData::repopulate()
|
||||
{
|
||||
if(m_tree)
|
||||
if (m_tree)
|
||||
{
|
||||
delete m_tree;
|
||||
m_tree = 0;
|
||||
}
|
||||
|
||||
const char * const templatePath = NON_NULL(ConfigGodClient::getData().templateServerIffPath);
|
||||
const char* const templatePath = NON_NULL(ConfigGodClient::getData().templateServerIffPath);
|
||||
std::string result;
|
||||
m_tree = GodClientPerforce::getInstance().getFileTree(templatePath, "iff", result, GodClientPerforce::FileState_depot);
|
||||
|
||||
if(!m_tree)
|
||||
{
|
||||
const std::string msg = "Unable to retrieve info from perforce:\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(0, "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "AbstractFilesystemTree.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "FilesystemTree.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "fileInterface/StdioFile.h"
|
||||
|
||||
@@ -136,49 +135,7 @@ void ScriptListView::onRefreshList()
|
||||
|
||||
setCursor(static_cast<int>(Qt::WaitCursor));
|
||||
|
||||
if ( ConfigGodClient::getConnectToPerforce() )
|
||||
{
|
||||
|
||||
const char* const classPath = NON_NULL(ConfigGodClient::getData().scriptClassPath);
|
||||
std::string result;
|
||||
AbstractFilesystemTree* afst = GodClientPerforce::getInstance().getFileTree(classPath, "class", result, GodClientPerforce::FileState_depot);
|
||||
|
||||
if(!afst)
|
||||
{
|
||||
const std::string msg = "Unable to retrieve info from perforce:\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(this, "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_green);
|
||||
poulateScriptTree(0,&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(classPath, "class", result, GodClientPerforce::FileState_add);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_red);
|
||||
poulateScriptTree("[NEW]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(classPath, "class", result, GodClientPerforce::FileState_edit);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_violet);
|
||||
poulateScriptTree("[EDIT]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
FilesystemTree* fst = new FilesystemTree();
|
||||
|
||||
@@ -194,9 +151,7 @@ void ScriptListView::onRefreshList()
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_green);
|
||||
poulateScriptTree(0,&pix,&folderPix, this, fst);
|
||||
}
|
||||
|
||||
delete fst;
|
||||
}
|
||||
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "ActionsObjectTemplate.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "FileSystemTree.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "ObjectTemplateData.h"
|
||||
|
||||
@@ -148,50 +147,6 @@ void ServerTemplateListView::onRefreshList()
|
||||
|
||||
setCursor(static_cast<int>(Qt::WaitCursor));
|
||||
|
||||
if ( ConfigGodClient::getConnectToPerforce() )
|
||||
{
|
||||
|
||||
const char* const templateIffPath = NON_NULL(ConfigGodClient::getData().templateServerIffPath);
|
||||
std::string result;
|
||||
AbstractFilesystemTree* afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_depot);
|
||||
|
||||
if(!afst)
|
||||
{
|
||||
const std::string msg = "Unable to retrieve info from perforce:\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(this, "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_blue);
|
||||
populateTemplateTree(0,&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_add);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_red);
|
||||
populateTemplateTree("[NEW]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_edit);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_violet);
|
||||
populateTemplateTree("[EDIT]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
}
|
||||
else
|
||||
{
|
||||
FilesystemTree* fst = new FilesystemTree();
|
||||
|
||||
std::string path = ConfigGodClient::getData().localServerDataPath;
|
||||
@@ -208,7 +163,6 @@ void ServerTemplateListView::onRefreshList()
|
||||
}
|
||||
|
||||
delete fst;
|
||||
}
|
||||
|
||||
|
||||
unsetCursor();
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "ActionsObjectTemplate.h"
|
||||
#include "ConfigGodClient.h"
|
||||
#include "FileSystemTree.h"
|
||||
#include "GodClientPerforce.h"
|
||||
#include "IconLoader.h"
|
||||
#include "ObjectTemplateData.h"
|
||||
|
||||
@@ -149,42 +148,6 @@ void TemplateListView::onRefreshList()
|
||||
|
||||
const char* const templateIffPath = NON_NULL(ConfigGodClient::getData().templateServerIffPath);
|
||||
std::string result;
|
||||
AbstractFilesystemTree* afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_depot);
|
||||
|
||||
if(!afst)
|
||||
{
|
||||
const std::string msg = "Unable to retrieve info from perforce:\n" + result;
|
||||
IGNORE_RETURN(QMessageBox::warning(this, "Warning", msg.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_blue);
|
||||
populateTemplateTree(0,&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_add);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_red);
|
||||
populateTemplateTree("[NEW]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
afst = GodClientPerforce::getInstance().getFileTree(templateIffPath, "iff", result, GodClientPerforce::FileState_edit);
|
||||
|
||||
{
|
||||
const QPixmap pix = IL_PIXMAP(hi16_mime_document);
|
||||
const QPixmap folderPix = IL_PIXMAP(hi16_filesys_folder_violet);
|
||||
populateTemplateTree("[EDIT]",&pix,&folderPix, this, afst);
|
||||
}
|
||||
|
||||
delete afst;
|
||||
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user